Пример #1
0
void h2o_socket_ssl_server_handshake(h2o_socket_t *sock, SSL_CTX *ssl_ctx, h2o_socket_cb handshake_cb)
{
    static BIO_METHOD bio_methods = {BIO_TYPE_FD, "h2o_socket", write_bio, read_bio, puts_bio,
                                     NULL,        ctrl_bio,     new_bio,   free_bio, NULL};

    BIO *bio;

    sock->ssl = h2o_mem_alloc(sizeof(*sock->ssl));
    memset(sock->ssl, 0, offsetof(struct st_h2o_socket_ssl_t, output.pool));

    /* setup the buffers; sock->input should be empty, sock->ssl->input.encrypted should contain the initial input, if any */
    h2o_buffer_init(&sock->ssl->input.encrypted, &h2o_socket_buffer_prototype);
    if (sock->input->size != 0) {
        h2o_buffer_t *tmp = sock->input;
        sock->input = sock->ssl->input.encrypted;
        sock->ssl->input.encrypted = tmp;
    }

    h2o_mem_init_pool(&sock->ssl->output.pool);
    bio = BIO_new(&bio_methods);
    bio->ptr = sock;
    bio->init = 1;
    sock->ssl->ssl = SSL_new(ssl_ctx);
    SSL_set_bio(sock->ssl->ssl, bio, bio);

    sock->ssl->handshake.cb = handshake_cb;
    proceed_handshake(sock, 0);
}
Пример #2
0
void h2o_socket_ssl_handshake(h2o_socket_t *sock, SSL_CTX *ssl_ctx, const char *server_name, h2o_socket_cb handshake_cb)
{
    sock->ssl = h2o_mem_alloc(sizeof(*sock->ssl));
    memset(sock->ssl, 0, offsetof(struct st_h2o_socket_ssl_t, output.pool));

    /* setup the buffers; sock->input should be empty, sock->ssl->input.encrypted should contain the initial input, if any */
    h2o_buffer_init(&sock->ssl->input.encrypted, &h2o_socket_buffer_prototype);
    if (sock->input->size != 0) {
        h2o_buffer_t *tmp = sock->input;
        sock->input = sock->ssl->input.encrypted;
        sock->ssl->input.encrypted = tmp;
    }

    h2o_mem_init_pool(&sock->ssl->output.pool);
    create_ssl(sock, ssl_ctx);

    sock->ssl->handshake.cb = handshake_cb;
    if (server_name == NULL) {
        /* is server */
        if (SSL_CTX_sess_get_get_cb(ssl_ctx) != NULL)
            sock->ssl->handshake.server.async_resumption.state = ASYNC_RESUMPTION_STATE_RECORD;
        if (sock->ssl->input.encrypted->size != 0)
            proceed_handshake(sock, 0);
        else
            h2o_socket_read_start(sock, proceed_handshake);
    } else {
        sock->ssl->handshake.client.server_name = h2o_strdup(NULL, server_name, SIZE_MAX).base;
        SSL_set_tlsext_host_name(sock->ssl->ssl, sock->ssl->handshake.client.server_name);
        proceed_handshake(sock, 0);
    }
}
Пример #3
0
void h2o_socket_ssl_server_handshake(h2o_socket_t *sock, SSL_CTX *ssl_ctx, h2o_socket_cb handshake_cb)
{
    static BIO_METHOD bio_methods = {
        BIO_TYPE_FD,
        "h2o_socket",
        write_bio,
        read_bio,
        puts_bio,
        NULL,
        ctrl_bio,
        new_bio,
        free_bio,
        NULL
    };

    BIO *bio;

    sock->ssl = h2o_mem_alloc(sizeof(*sock->ssl));
    memset(sock->ssl, 0, offsetof(struct st_h2o_socket_ssl_t, output.pool));
    h2o_buffer_init(&sock->ssl->input.encrypted, &h2o_socket_buffer_prototype);
    h2o_mem_init_pool(&sock->ssl->output.pool);
    bio = BIO_new(&bio_methods);
    bio->ptr = sock;
    bio->init = 1;
    sock->ssl->ssl = SSL_new(ssl_ctx);
    SSL_set_bio(sock->ssl->ssl, bio, bio);

    sock->ssl->handshake.cb = handshake_cb;
    proceed_handshake(sock, 0);
}
Пример #4
0
static void test_extract_push_path_from_link_header(void)
{
    h2o_mem_pool_t pool;
    h2o_iovec_t path;
    h2o_iovec_t base_authority = {H2O_STRLIT("basehost")}, base_path = {H2O_STRLIT("/basepath/")};
#define BASE &H2O_URL_SCHEME_HTTP, &base_authority, &base_path
    h2o_mem_init_pool(&pool);

    path = h2o_extract_push_path_from_link_header(&pool, H2O_STRLIT("<http://basehost/otherpath>; rel=preload"), BASE);
    ok(h2o_memis(path.base, path.len, H2O_STRLIT("/otherpath")));
    path = h2o_extract_push_path_from_link_header(&pool, H2O_STRLIT("</otherpath>; rel=preload"), BASE);
    ok(h2o_memis(path.base, path.len, H2O_STRLIT("/otherpath")));
    path = h2o_extract_push_path_from_link_header(&pool, H2O_STRLIT("<otherpath>; rel=preload"), BASE);
    ok(h2o_memis(path.base, path.len, H2O_STRLIT("/basepath/otherpath")));
    path = h2o_extract_push_path_from_link_header(&pool, H2O_STRLIT("<../otherpath>; rel=preload"), BASE);
    ok(h2o_memis(path.base, path.len, H2O_STRLIT("/otherpath")));
    path = h2o_extract_push_path_from_link_header(&pool, H2O_STRLIT("<http:otherpath>; rel=preload"), BASE);
    ok(h2o_memis(path.base, path.len, H2O_STRLIT("/basepath/otherpath")));

    path = h2o_extract_push_path_from_link_header(&pool, H2O_STRLIT("<../otherpath>; rel=author"), BASE);
    ok(path.base == NULL);
    ok(path.len == 0);
    path = h2o_extract_push_path_from_link_header(&pool, H2O_STRLIT("<http://basehost:81/otherpath>; rel=preload"), BASE);
    ok(path.base == NULL);
    ok(path.len == 0);
    path = h2o_extract_push_path_from_link_header(&pool, H2O_STRLIT("<https://basehost/otherpath>; rel=preload"), BASE);
    ok(path.base == NULL);
    ok(path.len == 0);
    path = h2o_extract_push_path_from_link_header(&pool, H2O_STRLIT("<https:otherpath>; rel=preload"), BASE);
    ok(path.base == NULL);
    ok(path.len == 0);

    h2o_mem_clear_pool(&pool);
#undef BASE
}
Пример #5
0
void h2o_socket_ssl_handshake(h2o_socket_t *sock, SSL_CTX *ssl_ctx, const char *server_name, h2o_socket_cb handshake_cb)
{
    sock->ssl = h2o_mem_alloc(sizeof(*sock->ssl));
    memset(sock->ssl, 0, offsetof(struct st_h2o_socket_ssl_t, output.pool));

    /* setup the buffers; sock->input should be empty, sock->ssl->input.encrypted should contain the initial input, if any */
    h2o_buffer_init(&sock->ssl->input.encrypted, &h2o_socket_buffer_prototype);
    if (sock->input->size != 0) {
        h2o_buffer_t *tmp = sock->input;
        sock->input = sock->ssl->input.encrypted;
        sock->ssl->input.encrypted = tmp;
    }

    h2o_mem_init_pool(&sock->ssl->output.pool);
    create_ssl(sock, ssl_ctx);

    sock->ssl->handshake.cb = handshake_cb;
    if (server_name == NULL) {
        /* is server */
        if (SSL_CTX_sess_get_get_cb(ssl_ctx) != NULL)
            sock->ssl->handshake.server.async_resumption.state = ASYNC_RESUMPTION_STATE_RECORD;
        if (sock->ssl->input.encrypted->size != 0)
            proceed_handshake(sock, 0);
        else
            h2o_socket_read_start(sock, proceed_handshake);
    } else {
        h2o_cache_t *session_cache = h2o_socket_ssl_get_session_cache(ssl_ctx);
        if (session_cache != NULL) {
            struct sockaddr_storage sa;
            int32_t port;
            if (h2o_socket_getpeername(sock, (struct sockaddr *)&sa) != 0 &&
                (port = h2o_socket_getport((struct sockaddr *)&sa)) != -1) {
                /* session cache is available */
                h2o_iovec_t session_cache_key;
                session_cache_key.base = h2o_mem_alloc(strlen(server_name) + sizeof(":" H2O_UINT16_LONGEST_STR));
                session_cache_key.len = sprintf(session_cache_key.base, "%s:%" PRIu16, server_name, (uint16_t)port);
                sock->ssl->handshake.client.session_cache = session_cache;
                sock->ssl->handshake.client.session_cache_key = session_cache_key;
                sock->ssl->handshake.client.session_cache_key_hash =
                    h2o_cache_calchash(session_cache_key.base, session_cache_key.len);

                /* fetch from session cache */
                h2o_cache_ref_t *cacheref = h2o_cache_fetch(session_cache, h2o_now(h2o_socket_get_loop(sock)),
                                                            sock->ssl->handshake.client.session_cache_key,
                                                            sock->ssl->handshake.client.session_cache_key_hash);
                if (cacheref != NULL) {
                    SSL_set_session(sock->ssl->ssl, (SSL_SESSION *)cacheref->value.base);
                    h2o_cache_release(session_cache, cacheref);
                }
            }
        }
        sock->ssl->handshake.client.server_name = h2o_strdup(NULL, server_name, SIZE_MAX).base;
        SSL_set_tlsext_host_name(sock->ssl->ssl, sock->ssl->handshake.client.server_name);
        proceed_handshake(sock, 0);
    }
}
Пример #6
0
static void test_resolve(void)
{
    h2o_mem_pool_t pool;
    h2o_url_t base, relative, resolved;
    h2o_iovec_t final;
    int ret;

    h2o_mem_init_pool(&pool);

    ret = h2o_url_parse("http://example.com/dir/index.html", SIZE_MAX, &base);
    ok(ret == 0);

    ret = h2o_url_parse_relative("../assets/jquery.js", SIZE_MAX, &relative);
    ok(ret == 0);
    final = h2o_url_resolve(&pool, &base, &relative, &resolved);
Пример #7
0
static void test_decode_base64(void)
{
    h2o_mem_pool_t pool;
    char buf[256];

    h2o_mem_init_pool(&pool);

    h2o_iovec_t src = {H2O_STRLIT("The quick brown fox jumps over the lazy dog.")}, decoded;
    h2o_base64_encode(buf, (const uint8_t *)src.base, src.len, 1);
    ok(strcmp(buf, "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4") == 0);
    decoded = h2o_decode_base64url(&pool, buf, strlen(buf));
    ok(src.len == decoded.len);
    ok(strcmp(decoded.base, src.base) == 0);

    h2o_mem_clear_pool(&pool);
}
Пример #8
0
static void test_htmlescape(void)
{
    h2o_mem_pool_t pool;
    h2o_mem_init_pool(&pool);

#define TEST(src, expected)                                                                                                        \
    do {                                                                                                                           \
        h2o_iovec_t escaped = h2o_htmlescape(&pool, H2O_STRLIT(src));                                                              \
        ok(h2o_memis(escaped.base, escaped.len, H2O_STRLIT(expected)));                                                            \
    } while (0)

    TEST("hello world", "hello world");
    TEST("x < y", "x &lt; y");
    TEST("\0\"&'<>", "\0&quot;&amp;&#39;&lt;&gt;");

#undef TEST

    h2o_mem_clear_pool(&pool);
}
Пример #9
0
static void test_uri_escape(void)
{
    h2o_mem_pool_t pool;
    h2o_mem_init_pool(&pool);

#define TEST(src, preserve, expected)                                                                                              \
    do {                                                                                                                           \
        h2o_iovec_t escaped = h2o_uri_escape(&pool, H2O_STRLIT(src), preserve);                                                    \
        ok(h2o_memis(escaped.base, escaped.len, H2O_STRLIT(expected)));                                                            \
    } while (0)

    TEST("abc", NULL, "abc");
    TEST("a/c", NULL, "a%2Fc");
    TEST("a/c", "/", "a/c");
    TEST("\xe3\x81\x82", NULL, "%E3%81%82");
    TEST("a\0!", NULL, "a%00!");
    TEST("a/\0!", "/", "a/%00!");

#undef TEST

    h2o_mem_clear_pool(&pool);
}
Пример #10
0
void h2o_init_request(h2o_req_t *req, h2o_conn_t *conn, h2o_req_t *src)
{
    /* clear all memory (expect memory pool, since it is large) */
    memset(req, 0, offsetof(h2o_req_t, pool));

    /* init memory pool (before others, since it may be used) */
    h2o_mem_init_pool(&req->pool);

    /* init properties that should be initialized to non-zero */
    req->conn = conn;
    req->_timeout_entry.cb = deferred_proceed_cb;
    req->res.content_length = SIZE_MAX;

    if (src != NULL) {
#define COPY(buf) do { \
    req->buf.base = h2o_mem_alloc_pool(&req->pool, src->buf.len); \
    memcpy(req->buf.base, src->buf.base, src->buf.len); \
    req->buf.len = src->buf.len; \
} while (0)
        COPY(authority);
        COPY(method);
        COPY(path);
        COPY(scheme);
        req->version = src->version;
        h2o_vector_reserve(&req->pool, (h2o_vector_t*)&req->headers, sizeof(h2o_header_t), src->headers.size);
        memcpy(req->headers.entries, src->headers.entries, sizeof(req->headers.entries[0]) * src->headers.size);
        req->headers.size = src->headers.size;
        req->entity = src->entity;
        req->http1_is_persistent = src->http1_is_persistent;
        if (src->upgrade.base != NULL) {
            COPY(upgrade);
        } else {
            req->upgrade.base = NULL;
            req->upgrade.len = 0;
        }
#undef COPY
    }
}
Пример #11
0
static void test_normalize_path(void)
{
    h2o_mem_pool_t pool;

    h2o_mem_init_pool(&pool);

    size_t q;
    h2o_iovec_t b = h2o_url_normalize_path(&pool, H2O_STRLIT("/"), &q);
    ok(b.len == 1);
    ok(memcmp(b.base, H2O_STRLIT("/")) == 0);
    ok(q == SIZE_MAX);

    b = h2o_url_normalize_path(&pool, H2O_STRLIT("/abc"), &q);
    ok(b.len == 4);
    ok(memcmp(b.base, H2O_STRLIT("/abc")) == 0);
    ok(q == SIZE_MAX);

    b = h2o_url_normalize_path(&pool, H2O_STRLIT("/abc"), &q);
    ok(b.len == 4);
    ok(memcmp(b.base, H2O_STRLIT("/abc")) == 0);
    ok(q == SIZE_MAX);

    b = h2o_url_normalize_path(&pool, H2O_STRLIT("/abc/../def"), &q);
    ok(b.len == 4);
    ok(memcmp(b.base, H2O_STRLIT("/def")) == 0);
    ok(q == SIZE_MAX);

    b = h2o_url_normalize_path(&pool, H2O_STRLIT("/abc/../../def"), &q);
    ok(b.len == 4);
    ok(memcmp(b.base, H2O_STRLIT("/def")) == 0);
    ok(q == SIZE_MAX);

    b = h2o_url_normalize_path(&pool, H2O_STRLIT("/abc/./def"), &q);
    ok(b.len == 8);
    ok(memcmp(b.base, H2O_STRLIT("/abc/def")) == 0);
    ok(q == SIZE_MAX);

    b = h2o_url_normalize_path(&pool, H2O_STRLIT("/abc/def/.."), &q);
    ok(b.len == 5);
    ok(memcmp(b.base, H2O_STRLIT("/abc/")) == 0);
    ok(q == SIZE_MAX);

    b = h2o_url_normalize_path(&pool, H2O_STRLIT("/abc/def/."), &q);
    ok(b.len == 9);
    ok(memcmp(b.base, H2O_STRLIT("/abc/def/")) == 0);
    ok(q == SIZE_MAX);

    b = h2o_url_normalize_path(&pool, H2O_STRLIT("/abc?xx"), &q);
    ok(b.len == 4);
    ok(memcmp(b.base, H2O_STRLIT("/abc")) == 0);
    ok(q == 4);

    b = h2o_url_normalize_path(&pool, H2O_STRLIT("/abc/../def?xx"), &q);
    ok(b.len == 4);
    ok(memcmp(b.base, H2O_STRLIT("/def")) == 0);
    ok(q == 11);

    b = h2o_url_normalize_path(&pool, H2O_STRLIT("/a%62c"), &q);
    ok(b.len == 4);
    ok(memcmp(b.base, H2O_STRLIT("/abc")) == 0);
    ok(q == SIZE_MAX);

    b = h2o_url_normalize_path(&pool, H2O_STRLIT("/a%6"), &q);
    ok(b.len == 4);
    ok(memcmp(b.base, H2O_STRLIT("/a%6")) == 0);
    ok(q == SIZE_MAX);

    b = h2o_url_normalize_path(&pool, H2O_STRLIT("/a%6?"), &q);
    ok(b.len == 4);
    ok(memcmp(b.base, H2O_STRLIT("/a%6")) == 0);
    ok(q == 4);

    h2o_mem_clear_pool(&pool);
}
Пример #12
0
static void test_extract_push_path_from_link_header(void)
{
    h2o_mem_pool_t pool;
    h2o_iovec_t base_path = {H2O_STRLIT("/basepath/")}, input_authority = {H2O_STRLIT("basehost")},
                other_authority = {H2O_STRLIT("otherhost")};
    h2o_mem_init_pool(&pool);

#define DO_CHECK(_base_scheme, _base_authority, _input, _filtered_expected, ...)                                                   \
    do {                                                                                                                           \
        h2o_iovec_t input = h2o_iovec_init(_input, strlen(_input)), filtered;                                                      \
        struct expected_t expected[] = {__VA_ARGS__, {NULL}}, *e = expected;                                                       \
        h2o_extract_push_path_from_link_header(&pool, input.base, input.len, base_path, &H2O_URL_SCHEME_HTTP, input_authority,     \
                                               _base_scheme, _base_authority, check_path, &e, &filtered);                          \
        ok(e->path == NULL);                                                                                                       \
        if (_filtered_expected != NULL) {                                                                                          \
            ok(h2o_memis(filtered.base, filtered.len, _filtered_expected, strlen(_filtered_expected)));                            \
        } else {                                                                                                                   \
            ok(h2o_memis(filtered.base, filtered.len, input.base, input.len));                                                     \
        }                                                                                                                          \
    } while (0)

    // basic tests
    DO_CHECK(NULL, NULL, "<http://basehost/otherpath>; rel=preload", NULL, {"/otherpath"});
    DO_CHECK(NULL, NULL, "</otherpath>; rel=preload", NULL, {"/otherpath"});
    DO_CHECK(NULL, NULL, "<otherpath>; rel=preload", NULL, {"/basepath/otherpath"});
    DO_CHECK(NULL, NULL, "<../otherpath>; rel=preload", NULL, {"/otherpath"});
    DO_CHECK(NULL, NULL, "<http:otherpath>; rel=preload", NULL, {"/basepath/otherpath"});

    // negative filters
    DO_CHECK(NULL, NULL, "<../otherpath>; rel=author", NULL, {NULL});
    DO_CHECK(NULL, NULL, "<http://basehost:81/otherpath>; rel=preload", NULL, {NULL});
    DO_CHECK(NULL, NULL, "<https://basehost/otherpath>; rel=preload", NULL, {NULL});
    DO_CHECK(NULL, NULL, "<https:otherpath>; rel=preload", NULL, {NULL});

    // scheme and authority
    DO_CHECK(&H2O_URL_SCHEME_HTTPS, &input_authority, "</otherpath>; rel=preload", NULL, {NULL});
    DO_CHECK(&H2O_URL_SCHEME_HTTP, &input_authority, "</otherpath>; rel=preload", NULL, {"/otherpath"});
    DO_CHECK(&H2O_URL_SCHEME_HTTP, &other_authority, "<http://basehost/otherpath>; rel=preload", NULL, {"/otherpath"});

    // attributes
    DO_CHECK(NULL, NULL, "<http:otherpath>; rel=preload; nopush", NULL, {NULL});
    DO_CHECK(NULL, NULL, "<http:otherpath>; rel=preload; x-http2-push-only", "", {"/basepath/otherpath"});
    DO_CHECK(NULL, NULL, "<http:otherpath>; rel=preload; critical", NULL, {"/basepath/otherpath", 1});

    // multiple entries
    DO_CHECK(&H2O_URL_SCHEME_HTTP, &input_authority, "</firstpath>; rel=preload, </secondpath>; rel=preload", NULL, {"/firstpath"},
             {"/secondpath"});
    DO_CHECK(&H2O_URL_SCHEME_HTTP, &input_authority, "</firstpath>; rel=preload; nopush, </secondpath>; rel=preload", NULL,
             {"/secondpath"});
    DO_CHECK(&H2O_URL_SCHEME_HTTP, &input_authority,
             "</firstpath>; rel=preload; nopush, </secondpath>; nopush; rel=preload; </thirdpath>", NULL, {NULL});
    DO_CHECK(&H2O_URL_SCHEME_HTTP, &input_authority, "</firstpath>; rel=preload; nopush, <secondpath>; rel=notpreload", NULL,
             {NULL});
    DO_CHECK(&H2O_URL_SCHEME_HTTP, &input_authority,
             "</firstpath>; rel=preload, </secondpath>; rel=preload; nopush, </thirdpath>; rel=preload", NULL, {"/firstpath"},
             {"/thirdpath"});
    DO_CHECK(&H2O_URL_SCHEME_HTTP, &input_authority, "hogefoo", NULL, {NULL});
    DO_CHECK(&H2O_URL_SCHEME_HTTP, &input_authority,
             "</111>; rel=preload, </222>; rel=preload; nopush, </333>; rel=preload; x-http2-push-only, </444>; rel=preload",
             "</111>; rel=preload, </222>; rel=preload; nopush, </444>; rel=preload", {"/111"}, {"/333"}, {"/444"});

    h2o_mem_clear_pool(&pool);

#undef DO_CHECK
}
Пример #13
0
static void test_extract_push_path_from_link_header(void)
{
    h2o_mem_pool_t pool;
    h2o_iovec_vector_t paths;
    h2o_iovec_t path;
    h2o_iovec_t base_path = {H2O_STRLIT("/basepath/")}, input_authority = {H2O_STRLIT("basehost")},
                other_authority = {H2O_STRLIT("otherhost")};
#define INPUT base_path, &H2O_URL_SCHEME_HTTP, input_authority
    h2o_mem_init_pool(&pool);

    paths =
        h2o_extract_push_path_from_link_header(&pool, H2O_STRLIT("<http://basehost/otherpath>; rel=preload"), INPUT, NULL, NULL);
    ok(paths.size == 1);
    path = paths.entries[0];
    ok(h2o_memis(path.base, path.len, H2O_STRLIT("/otherpath")));

    paths = h2o_extract_push_path_from_link_header(&pool, H2O_STRLIT("</otherpath>; rel=preload"), INPUT, NULL, NULL);
    ok(paths.size == 1);
    path = paths.entries[0];
    ok(h2o_memis(path.base, path.len, H2O_STRLIT("/otherpath")));

    paths = h2o_extract_push_path_from_link_header(&pool, H2O_STRLIT("<otherpath>; rel=preload"), INPUT, NULL, NULL);
    ok(paths.size == 1);
    path = paths.entries[0];
    ok(h2o_memis(path.base, path.len, H2O_STRLIT("/basepath/otherpath")));

    paths = h2o_extract_push_path_from_link_header(&pool, H2O_STRLIT("<../otherpath>; rel=preload"), INPUT, NULL, NULL);
    ok(paths.size == 1);
    path = paths.entries[0];
    ok(h2o_memis(path.base, path.len, H2O_STRLIT("/otherpath")));

    paths = h2o_extract_push_path_from_link_header(&pool, H2O_STRLIT("<http:otherpath>; rel=preload"), INPUT, NULL, NULL);
    ok(paths.size == 1);
    path = paths.entries[0];
    ok(h2o_memis(path.base, path.len, H2O_STRLIT("/basepath/otherpath")));

    paths = h2o_extract_push_path_from_link_header(&pool, H2O_STRLIT("<../otherpath>; rel=author"), INPUT, NULL, NULL);
    ok(paths.size == 0);
    paths =
        h2o_extract_push_path_from_link_header(&pool, H2O_STRLIT("<http://basehost:81/otherpath>; rel=preload"), INPUT, NULL, NULL);
    ok(paths.size == 0);
    paths =
        h2o_extract_push_path_from_link_header(&pool, H2O_STRLIT("<https://basehost/otherpath>; rel=preload"), INPUT, NULL, NULL);
    ok(paths.size == 0);
    paths = h2o_extract_push_path_from_link_header(&pool, H2O_STRLIT("<https:otherpath>; rel=preload"), INPUT, NULL, NULL);
    ok(paths.size == 0);

    paths = h2o_extract_push_path_from_link_header(&pool, H2O_STRLIT("</otherpath>; rel=preload"), INPUT, &H2O_URL_SCHEME_HTTPS,
                                                   &input_authority);
    ok(paths.size == 0);
    paths = h2o_extract_push_path_from_link_header(&pool, H2O_STRLIT("</otherpath>; rel=preload"), INPUT, &H2O_URL_SCHEME_HTTP,
                                                   &input_authority);
    ok(paths.size == 1);
    path = paths.entries[0];
    ok(h2o_memis(path.base, path.len, H2O_STRLIT("/otherpath")));

    paths = h2o_extract_push_path_from_link_header(&pool, H2O_STRLIT("</otherpath>; rel=preload"), INPUT, &H2O_URL_SCHEME_HTTP,
                                                   &other_authority);
    ok(paths.entries == 0);

    paths = h2o_extract_push_path_from_link_header(&pool, H2O_STRLIT("<http://basehost/otherpath>; rel=preload"), INPUT,
                                                   &H2O_URL_SCHEME_HTTP, &other_authority);
    ok(paths.size == 1);
    path = paths.entries[0];
    ok(h2o_memis(path.base, path.len, H2O_STRLIT("/otherpath")));

    paths = h2o_extract_push_path_from_link_header(&pool, H2O_STRLIT("<http:otherpath>; rel=preload; nopush"), INPUT, NULL, NULL);
    ok(paths.entries == 0);

    paths = h2o_extract_push_path_from_link_header(&pool, H2O_STRLIT("</firstpath>; rel=preload, </secondpath>; rel=preload"),
                                                   INPUT, &H2O_URL_SCHEME_HTTP, &input_authority);
    ok(paths.size == 2);
    path = paths.entries[0];
    ok(h2o_memis(path.base, path.len, H2O_STRLIT("/firstpath")));
    path = paths.entries[1];
    ok(h2o_memis(path.base, path.len, H2O_STRLIT("/secondpath")));

    paths =
        h2o_extract_push_path_from_link_header(&pool, H2O_STRLIT("</firstpath>; rel=preload; nopush, </secondpath>; rel=preload"),
                                               INPUT, &H2O_URL_SCHEME_HTTP, &input_authority);
    ok(paths.size == 1);
    path = paths.entries[0];
    ok(h2o_memis(path.base, path.len, H2O_STRLIT("/secondpath")));

    paths = h2o_extract_push_path_from_link_header(
        &pool, H2O_STRLIT("</firstpath>; rel=preload; nopush, </secondpath>; nopush; rel=preload; </thirdpath>"), INPUT,
        &H2O_URL_SCHEME_HTTP, &input_authority);
    ok(paths.size == 0);

    paths =
        h2o_extract_push_path_from_link_header(&pool, H2O_STRLIT("</firstpath>; rel=preload; nopush, <secondpath>; rel=notpreload"),
                                               INPUT, &H2O_URL_SCHEME_HTTP, &input_authority);
    ok(paths.size == 0);

    paths = h2o_extract_push_path_from_link_header(
        &pool, H2O_STRLIT("</firstpath>; rel=preload, </secondpath>; rel=preload; nopush, </thirdpath>; rel=preload"), INPUT,
        &H2O_URL_SCHEME_HTTP, &input_authority);
    ok(paths.size == 2);
    path = paths.entries[0];
    ok(h2o_memis(path.base, path.len, H2O_STRLIT("/firstpath")));
    path = paths.entries[1];
    ok(h2o_memis(path.base, path.len, H2O_STRLIT("/thirdpath")));

    h2o_mem_clear_pool(&pool);
#undef INPUT
}
Пример #14
0
static void test_request(h2o_iovec_t first_req, h2o_iovec_t second_req, h2o_iovec_t third_req)
{
    h2o_hpack_header_table_t header_table;
    h2o_req_t req;
    h2o_iovec_t in;
    int r, allow_psuedo;

    memset(&header_table, 0, sizeof(header_table));
    header_table.hpack_capacity = 4096;

    memset(&req, 0, sizeof(req));
    h2o_mem_init_pool(&req.pool);
    allow_psuedo = 1;
    in = first_req;
    r = h2o_hpack_parse_headers(&req, &header_table, &allow_psuedo, (const uint8_t*)in.base, in.len);
    ok(r == 0);
    ok(allow_psuedo == 1);
    ok(req.authority.len == 15);
    ok(memcmp(req.authority.base, H2O_STRLIT("www.example.com")) == 0);
    ok(req.method.len == 3);
    ok(memcmp(req.method.base, H2O_STRLIT("GET")) == 0);
    ok(req.path.len == 1);
    ok(memcmp(req.path.base, H2O_STRLIT("/")) == 0);
    ok(req.scheme.len == 4);
    ok(memcmp(req.scheme.base, H2O_STRLIT("http")) == 0);
    ok(req.headers.size == 0);

    h2o_mem_clear_pool(&req.pool);

    memset(&req, 0, sizeof(req));
    h2o_mem_init_pool(&req.pool);
    allow_psuedo = 1;
    in = second_req;
    r = h2o_hpack_parse_headers(&req, &header_table, &allow_psuedo, (const uint8_t*)in.base, in.len);
    ok(r == 0);
    ok(allow_psuedo == 0);
    ok(req.authority.len == 15);
    ok(memcmp(req.authority.base, H2O_STRLIT("www.example.com")) == 0);
    ok(req.method.len == 3);
    ok(memcmp(req.method.base, H2O_STRLIT("GET")) == 0);
    ok(req.path.len == 1);
    ok(memcmp(req.path.base, H2O_STRLIT("/")) == 0);
    ok(req.scheme.len == 4);
    ok(memcmp(req.scheme.base, H2O_STRLIT("http")) == 0);
    ok(req.headers.size == 1);
    ok(h2o_lcstris(req.headers.entries[0].name->base, req.headers.entries[0].name->len, H2O_STRLIT("cache-control")));
    ok(h2o_lcstris(req.headers.entries[0].value.base, req.headers.entries[0].value.len, H2O_STRLIT("no-cache")));

    h2o_mem_clear_pool(&req.pool);

    memset(&req, 0, sizeof(req));
    h2o_mem_init_pool(&req.pool);
    allow_psuedo = 1;
    in = third_req;
    r = h2o_hpack_parse_headers(&req, &header_table, &allow_psuedo, (const uint8_t*)in.base, in.len);
    ok(r == 0);
    ok(allow_psuedo == 0);
    ok(req.authority.len == 15);
    ok(memcmp(req.authority.base, H2O_STRLIT("www.example.com")) == 0);
    ok(req.method.len == 3);
    ok(memcmp(req.method.base, H2O_STRLIT("GET")) == 0);
    ok(req.path.len == 11);
    ok(memcmp(req.path.base, H2O_STRLIT("/index.html")) == 0);
    ok(req.scheme.len == 5);
    ok(memcmp(req.scheme.base, H2O_STRLIT("https")) == 0);
    ok(req.headers.size == 1);
    ok(h2o_lcstris(req.headers.entries[0].name->base, req.headers.entries[0].name->len, H2O_STRLIT("custom-key")));
    ok(h2o_lcstris(req.headers.entries[0].value.base, req.headers.entries[0].value.len, H2O_STRLIT("custom-value")));

    h2o_hpack_dispose_header_table(&header_table);
    h2o_mem_clear_pool(&req.pool);
}
Пример #15
0
void test_lib__http2__hpack(void)
{
    h2o_mem_pool_t pool;
    h2o_mem_init_pool(&pool);

    note("decode_int");
    {
        h2o_iovec_t in;
        const uint8_t *p;
        int32_t out;
#define TEST(input, output) \
    in = h2o_iovec_init(H2O_STRLIT(input)); \
    p = (const uint8_t*)in.base; \
    out = decode_int(&p, p + in.len, 7); \
    ok(out == output); \
    ok(p == (const uint8_t*)in.base + in.len);
        TEST("\x00", 0);
        TEST("\x03", 3);
        TEST("\x81", 1);
        TEST("\x7f\x00", 127);
        TEST("\x7f\x01", 128);
        TEST("\x7f\x7f", 254);
        TEST("\x7f\x81\x00", 128);
        TEST("\x7f\x80\x01", 255);
        TEST("\x7f\xff\xff\xff\x7f", 0xfffffff + 127);
        /* failures */
        TEST("", -1);
        TEST("\x7f", -1);
        TEST("\x7f\xff", -1);
        TEST("\x7f\xff\xff\xff\xff", -1);
#undef TEST
    }

    note("decode_huffman");
    {
        h2o_iovec_t huffcode = { H2O_STRLIT("\xf1\xe3\xc2\xe5\xf2\x3a\x6b\xa0\xab\x90\xf4\xff") };
        h2o_iovec_t *decoded = decode_huffman(&pool, (const uint8_t*)huffcode.base, huffcode.len);
        ok(decoded->len == sizeof("www.example.com") -1);
        ok(strcmp(decoded->base, "www.example.com") == 0);
    }
    h2o_mem_clear_pool(&pool);

    note("decode_header (literal header field with indexing)");
    {
        struct st_h2o_decode_header_result_t result;
        h2o_hpack_header_table_t header_table;
        h2o_iovec_t in;
        int r;

        memset(&header_table, 0, sizeof(header_table));
        header_table.hpack_capacity = 4096;
        in = h2o_iovec_init(H2O_STRLIT("\x40\x0a\x63\x75\x73\x74\x6f\x6d\x2d\x6b\x65\x79\x0d\x63\x75\x73\x74\x6f\x6d\x2d\x68\x65\x61\x64\x65\x72"));
        const uint8_t *p = (const uint8_t*)in.base;
        r = decode_header(&pool, &result, &header_table, &p, p + in.len);
        ok(r == 0);
        ok(result.name->len == 10);
        ok(strcmp(result.name->base, "custom-key") == 0);
        ok(result.value->len == 13);
        ok(strcmp(result.value->base, "custom-header") == 0);
        ok(header_table.hpack_size == 55);
    }
    h2o_mem_clear_pool(&pool);

    note("decode_header (literal header field without indexing)");
    {
        struct st_h2o_decode_header_result_t result;
        h2o_hpack_header_table_t header_table;
        h2o_iovec_t in;
        int r;

        memset(&header_table, 0, sizeof(header_table));
        header_table.hpack_capacity = 4096;
        in = h2o_iovec_init(H2O_STRLIT("\x04\x0c\x2f\x73\x61\x6d\x70\x6c\x65\x2f\x70\x61\x74\x68"));
        const uint8_t *p = (const uint8_t*)in.base;
        r = decode_header(&pool, &result, &header_table, &p, p + in.len);
        ok(r == 0);
        ok(result.name == &H2O_TOKEN_PATH->buf);
        ok(result.value->len == 12);
        ok(strcmp(result.value->base, "/sample/path") == 0);
        ok(header_table.hpack_size == 0);
    }
    h2o_mem_clear_pool(&pool);

    note("decode_header (literal header field never indexed)");
    {
        struct st_h2o_decode_header_result_t result;
        h2o_hpack_header_table_t header_table;
        h2o_iovec_t in;
        int r;

        memset(&header_table, 0, sizeof(header_table));
        header_table.hpack_capacity = 4096;
        in = h2o_iovec_init(H2O_STRLIT("\x10\x08\x70\x61\x73\x73\x77\x6f\x72\x64\x06\x73\x65\x63\x72\x65\x74"));
        const uint8_t *p = (const uint8_t*)in.base;
        r = decode_header(&pool, &result, &header_table, &p, p + in.len);
        ok(r == 0);
        ok(result.name->len == 8);
        ok(strcmp(result.name->base, "password") == 0);
        ok(result.value->len == 6);
        ok(strcmp(result.value->base, "secret") == 0);
        ok(header_table.hpack_size == 0);
    }
    h2o_mem_clear_pool(&pool);

    note("decode_header (indexed header field)");
    {
        struct st_h2o_decode_header_result_t result;
        h2o_hpack_header_table_t header_table;
        h2o_iovec_t in;
        int r;

        memset(&header_table, 0, sizeof(header_table));
        header_table.hpack_capacity = 4096;
        in = h2o_iovec_init(H2O_STRLIT("\x82"));
        const uint8_t *p = (const uint8_t*)in.base;
        r = decode_header(&pool, &result, &header_table, &p, p + in.len);
        ok(r == 0);
        ok(result.name == &H2O_TOKEN_METHOD->buf);
        ok(result.value->len == 3);
        ok(strcmp(result.value->base, "GET") == 0);
        ok(header_table.hpack_size == 0);
    }
    h2o_mem_clear_pool(&pool);

    note("request examples without huffman coding");
    test_request(
        h2o_iovec_init(H2O_STRLIT("\x82\x86\x84\x41\x0f\x77\x77\x77\x2e\x65\x78\x61\x6d\x70\x6c\x65\x2e\x63\x6f\x6d")),
        h2o_iovec_init(H2O_STRLIT("\x82\x86\x84\xbe\x58\x08\x6e\x6f\x2d\x63\x61\x63\x68\x65")),
        h2o_iovec_init(H2O_STRLIT("\x82\x87\x85\xbf\x40\x0a\x63\x75\x73\x74\x6f\x6d\x2d\x6b\x65\x79\x0c\x63\x75\x73\x74\x6f\x6d\x2d\x76\x61\x6c\x75\x65")));

    note("request examples with huffman coding");
    test_request(
        h2o_iovec_init(H2O_STRLIT("\x82\x86\x84\x41\x8c\xf1\xe3\xc2\xe5\xf2\x3a\x6b\xa0\xab\x90\xf4\xff")),
        h2o_iovec_init(H2O_STRLIT("\x82\x86\x84\xbe\x58\x86\xa8\xeb\x10\x64\x9c\xbf")),
        h2o_iovec_init(H2O_STRLIT("\x82\x87\x85\xbf\x40\x88\x25\xa8\x49\xe9\x5b\xa9\x7d\x7f\x89\x25\xa8\x49\xe9\x5b\xb8\xe8\xb4\xbf")));

    note("encode_huffman");
    {
        h2o_iovec_t huffcode = { H2O_STRLIT("\xf1\xe3\xc2\xe5\xf2\x3a\x6b\xa0\xab\x90\xf4\xff") };
        char buf[sizeof("www.example.com")];
        size_t l = encode_huffman((uint8_t*)buf, (uint8_t*)H2O_STRLIT("www.example.com"));
        ok(l == huffcode.len);
        ok(memcmp(buf, huffcode.base, huffcode.len) == 0);
    }

    note("response examples with huffmann coding");
    {
        h2o_hpack_header_table_t header_table;
        h2o_res_t res;

        memset(&header_table, 0, sizeof(header_table));
        header_table.hpack_capacity = 256;

        memset(&res, 0, sizeof(res));
        res.status = 302;
        res.reason = "Found";
        h2o_add_header(&pool, &res.headers, H2O_TOKEN_CACHE_CONTROL, H2O_STRLIT("private"));
        h2o_add_header(&pool, &res.headers, H2O_TOKEN_DATE, H2O_STRLIT("Mon, 21 Oct 2013 20:13:21 GMT"));
        h2o_add_header(&pool, &res.headers, H2O_TOKEN_LOCATION, H2O_STRLIT("https://www.example.com"));
        check_flatten(&header_table, &res,
            H2O_STRLIT("\x08\x03\x33\x30\x32\x58\x85\xae\xc3\x77\x1a\x4b\x61\x96\xd0\x7a\xbe\x94\x10\x54\xd4\x44\xa8\x20\x05\x95\x04\x0b\x81\x66\xe0\x82\xa6\x2d\x1b\xff\x6e\x91\x9d\x29\xad\x17\x18\x63\xc7\x8f\x0b\x97\xc8\xe9\xae\x82\xae\x43\xd3"));

        memset(&res, 0, sizeof(res));
        res.status = 307;
        res.reason = "Temporary Redirect";
        h2o_add_header(&pool, &res.headers, H2O_TOKEN_CACHE_CONTROL, H2O_STRLIT("private"));
        h2o_add_header(&pool, &res.headers, H2O_TOKEN_DATE, H2O_STRLIT("Mon, 21 Oct 2013 20:13:21 GMT"));
        h2o_add_header(&pool, &res.headers, H2O_TOKEN_LOCATION, H2O_STRLIT("https://www.example.com"));
        check_flatten(&header_table, &res,
            H2O_STRLIT("\x08\x03\x33\x30\x37\xc0\xbf\xbe"));
#if 0
        h2o_iovec_init(H2O_STRLIT("\x48\x03\x33\x30\x37\xc1\xc0\xbf")),
        h2o_iovec_init(H2O_STRLIT("\x88\xc1\x61\x1d\x4d\x6f\x6e\x2c\x20\x32\x31\x20\x4f\x63\x74\x20\x32\x30\x31\x33\x20\x32\x30\x3a\x31\x33\x3a\x32\x32\x20\x47\x4d\x54\xc0\x5a\x04\x67\x7a\x69\x70\x77\x38\x66\x6f\x6f\x3d\x41\x53\x44\x4a\x4b\x48\x51\x4b\x42\x5a\x58\x4f\x51\x57\x45\x4f\x50\x49\x55\x41\x58\x51\x57\x45\x4f\x49\x55\x3b\x20\x6d\x61\x78\x2d\x61\x67\x65\x3d\x33\x36\x30\x30\x3b\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x31")));
#endif
    }

    h2o_mem_clear_pool(&pool);
}