Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/VLC/modules/access/http/   (VLC Media Plyer ©)  Datei vom 23.9.2026 mit Größe 8 kB image not shown  

Quelle  h2conn_test.c   Sprache: C

 

/*****************************************************************************
 * h2conn_test.c: HTTP/2 connection tests
 *****************************************************************************
 * Copyright (C) 2015 Rémi Denis-Courmont
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/


#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#undef NDEBUG

#include <assert.h>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif

#include <vlc_common.h>
#include <vlc_block.h>
#include <vlc_tls.h>
#include "h2frame.h"
#include "conn.h"
#include "message.h"

#if defined(PF_UNIX) && !defined(PF_LOCAL)
#    define PF_LOCAL PF_UNIX
#endif

const char vlc_module_name[] = "test_h2conn";

static struct vlc_http_conn *conn;
static struct vlc_tls *external_tls;

static void conn_send(struct vlc_h2_frame *f)
{
    assert(f != NULL);

    size_t len = vlc_h2_frame_size(f);
    ssize_t val = vlc_tls_Write(external_tls, f->data, len);
    assert((size_t)val == len);
    free(f);
}

enum {
    DATA, HEADERS, PRIORITY, RST_STREAM, SETTINGS, PUSH_PROMISE, PING, GOAWAY,
    WINDOW_UPDATE, CONTINUATION,
};

static void conn_expect(uint_fast8_t wanted)
{
    size_t len;
    ssize_t val;
    uint8_t hdr[9];
    uint8_t got;

    do {
        val = vlc_tls_Read(external_tls, hdr, 9, true);
        assert(val == 9);
        assert(hdr[0] == 0);

        /* Check type. We do not currently validate WINDOW_UPDATE. */
        got = hdr[3];
        assert(wanted == got || WINDOW_UPDATE == got);

        len = (hdr[1] << 8) | hdr[2];
        if (len > 0)
        {
            char buf[len];

            val = vlc_tls_Read(external_tls, buf, len, true);
            assert(val == (ssize_t)len);
        }
    }
    while (got != wanted);
}

static void conn_create(void)
{
    ssize_t val;
    vlc_tls_t *tlsv[2];
    char hello[24];

    if (vlc_tls_SocketPair(PF_LOCAL, 0, tlsv))
        assert(!"socketpair");

    external_tls = tlsv[0];

    conn = vlc_h2_conn_create(NULL, tlsv[1]);
    assert(conn != NULL);
    conn_send(vlc_h2_frame_settings());

    val = vlc_tls_Read(external_tls, hello, 24, true);
    assert(val == 24);
    assert(!memcmp(hello, "PRI * HTTP/2.0\r\n", 16));
    conn_expect(SETTINGS);
    conn_expect(SETTINGS);
}

static void conn_destroy(void)
{
    vlc_tls_Shutdown(external_tls, false);
    vlc_http_conn_release(conn);
    vlc_tls_SessionDelete(external_tls);
}

static struct vlc_http_stream *stream_open(bool has_data)
{
    const char *verb = has_data ? "POST" : "GET";
    struct vlc_http_msg *m = vlc_http_req_create(verb, "https",
                                                 "www.example.com", "/");
    assert(m != NULL);

    struct vlc_http_stream *s = vlc_http_stream_open(conn, m, has_data);
    vlc_http_msg_destroy(m);
    return s;
}

static void stream_reply(uint_fast32_t id, bool nodata)
{
    struct vlc_http_msg *m = vlc_http_resp_create(200);
    assert(m != NULL);
    vlc_http_msg_add_agent(m, "VLC-h2-tester");

    conn_send(vlc_http_msg_h2_frame(m, id, nodata));
    vlc_http_msg_destroy(m);
}

static void stream_continuation(uint_fast32_t id)
{
    const char *h[][2] = {
        { ":status", "100" },
    };

    conn_send(vlc_h2_frame_headers(id, VLC_H2_DEFAULT_MAX_FRAME, false, 1, h));
}

static void stream_data(uint_fast32_t id, const char *str, bool eos)
{
    conn_send(vlc_h2_frame_data(id, str, strlen(str), eos));
}

/* TODO: check messages coming from the connection under test */

int main(void)
{
    struct vlc_http_stream *s, *s2;
    struct vlc_http_msg *m;
    block_t *b;
    uint_fast32_t sid = -1; /* Second guessed stream IDs :-/ */

    conn_create();
    conn_destroy();

    conn_create();
    conn_send(vlc_h2_frame_ping(42));
    conn_expect(PING);

    /* Test rejected stream */
    sid += 2;
    s = stream_open(false);
    assert(s != NULL);
    conn_expect(HEADERS);
    conn_send(vlc_h2_frame_rst_stream(sid, VLC_H2_REFUSED_STREAM));
    m = vlc_http_stream_read_headers(s);
    assert(m == NULL);
    b = vlc_http_stream_read(s);
    assert(b == vlc_http_error);
    vlc_http_stream_close(s, false);
    conn_expect(RST_STREAM);

    /* Test accepted stream */
    sid += 2;
    s = stream_open(false);
    assert(s != NULL);
    stream_reply(sid, false);
    m = vlc_http_msg_get_initial(s);
    assert(m != NULL);
    vlc_http_msg_destroy(m);

    stream_data(3, "Hello ", false); /* late data */
    stream_data(3, "world!", true);

    conn_expect(HEADERS);
    conn_expect(RST_STREAM);
    conn_expect(RST_STREAM);
    conn_expect(RST_STREAM);

    /* Test continuation then accepted stream */
    sid += 2;
    s = stream_open(false);
    assert(s != NULL);
    stream_continuation(sid);
    m = vlc_http_msg_get_initial(s);
    assert(m != NULL);
    assert(vlc_http_msg_get_status(m) == 100);
    stream_reply(sid, false);
    m = vlc_http_msg_iterate(m);
    assert(m != NULL);
    stream_data(sid, "Hello ", false);
    stream_data(sid, "world!", true);
    stream_data(sid, "Stray message", false); /* data after EOS */
    b = vlc_http_msg_read(m);
    assert(b != NULL);
    block_Release(b);
    b = vlc_http_msg_read(m);
    assert(b != NULL);
    block_Release(b);
    b = vlc_http_msg_read(m);
    assert(b == NULL);
    vlc_http_msg_destroy(m);

    conn_expect(HEADERS);
    conn_expect(RST_STREAM);
    conn_expect(RST_STREAM);

    /* Test accepted stream after continuation */
    sid += 2;
    s = stream_open(false);
    assert(s != NULL);
    stream_continuation(sid);
    stream_reply(sid, true);
    sid += 2;
    s2 = stream_open(false); /* 2nd stream to enforce test timing/ordering */
    assert(s2 != NULL);
    stream_reply(sid, true);
    m = vlc_http_msg_get_initial(s2);
    assert(m != NULL);
    vlc_http_msg_destroy(m);
    m = vlc_http_msg_get_initial(s);
    assert(m != NULL);
    assert(vlc_http_msg_get_status(m) == 200);
    b = vlc_http_msg_read(m);
    assert(b == NULL);
    vlc_http_msg_destroy(m);

    conn_expect(HEADERS);
    conn_expect(HEADERS);
    conn_expect(RST_STREAM);
    conn_expect(RST_STREAM);

    /* Test stream with request payload */
    sid += 2;
    s = stream_open(true);
    assert(s != NULL);
    stream_continuation(sid);
    m = vlc_http_msg_get_initial(s);
    assert(m != NULL);
    b = block_Alloc(12);
    assert(b != NULL);
    memcpy(b->p_buffer, "Hello world!", 12);
    assert(vlc_http_msg_write(m, b, false) == 0);
    assert(vlc_http_msg_write(m, NULL, true) == 0);
    stream_reply(sid, false);
    m = vlc_http_msg_iterate(m);
    assert(m != NULL);
    vlc_http_msg_destroy(m);

    conn_expect(HEADERS);
    conn_expect(DATA);
    conn_expect(DATA);
    conn_expect(RST_STREAM);

    /* Test nonexistent stream reset */
    conn_send(vlc_h2_frame_rst_stream(sid + 100, VLC_H2_REFUSED_STREAM));

    /* Test multiple streams in non-LIFO order */
    sid += 2;
    s = stream_open(false);
    assert(s != NULL);
    sid += 2;
    s2 = stream_open(false);
    assert(s2 != NULL);
    stream_reply(sid, false);
    stream_reply(sid - 2, true);
    stream_data(sid, "Discarded", false); /* not read data */
    m = vlc_http_msg_get_initial(s);
    assert(m != NULL);
    vlc_http_msg_destroy(m);
    m = vlc_http_msg_get_initial(s2);
    assert(m != NULL);
    vlc_http_msg_destroy(m);

    conn_expect(HEADERS);
    conn_expect(HEADERS);
    conn_expect(RST_STREAM);
    conn_expect(RST_STREAM);
    /* might or might not seen one or two extra RST_STREAM now */

    /* Test graceful connection termination */
    sid += 2;
    s = stream_open(false);
    assert(s != NULL);
    conn_send(vlc_h2_frame_goaway(sid - 2, VLC_H2_NO_ERROR));
    m = vlc_http_stream_read_headers(s);
    assert(m == NULL);

    /* Test stream after connection shut down */
    assert(stream_open(false) == NULL);

    /* Test releasing connection before stream */
    conn_destroy();
    vlc_http_stream_close(s, false);

    return 0;
}

Messung
CHZG
849610093

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.