Пример #1
0
END_TEST

START_TEST (indexed_many_zeroes) {
/*
    According to the draft a large number of zero values MUST be treated as a
    decoding error.

    This test sends a considerable number of zeroes as an index header field.
*/
    ret_t                 ret;
    chula_buffer_t        raw;
    hpack_header_parser_t parser;
    hpack_header_field_t  field;
    unsigned int          consumed = 0;

    char data[256];

    data[0] = 0xFF;
    memset(data+1, 0x80, sizeof(data)-1);
    data[sizeof(data)-1] |= 1;

    hpack_header_parser_init (&parser);
    hpack_header_field_init (&field);
    chula_buffer_fake_str (&raw, data);

    ret = hpack_header_parser_field (&parser, &raw, 0, &field, &consumed);
    ck_assert (ret != ret_ok);
    ck_assert (consumed == 0);

    hpack_header_parser_mrproper (&parser);
}
Пример #2
0
END_TEST

START_TEST (_set_max_no_table_evict_all) {
    ret_t                 ret;
    hpack_header_table_t *table;
    hpack_header_field_t  field;
    hpack_set_t           evicted;

    ret = hpack_header_table_new (&table);
    ch_assert (ret == ret_ok);

    hpack_header_field_init (&field);

    chula_buffer_add_str (&field.name,  "custom-key");
    chula_buffer_add_str (&field.value, "custom-header");

    for (int i=0; i<10; ++i) {
        ret = hpack_header_table_add (table, &field, evicted);
        ch_assert (ret_ok == ret);

        ch_assert (hpack_set_is_empty(evicted));
    }

    ret = hpack_header_table_set_max (table, 0, evicted);
    ch_assert (ret == ret_ok);

    hpack_set_is_full(evicted);

    ch_assert (table->max_data == 0);
    check_table_empty (table);

    hpack_header_field_mrproper (&field);
    hpack_header_table_free (table);
}
Пример #3
0
END_TEST

START_TEST (indexed_big_value) {
/*
    This test tries to break the header field parsing by sending an index header
    field too big to be hold by a signed integer (works with 32bit and 64bit
    machines). Since it's too big, and given the algorith of the VLQ it gets
    transformed into a negative number if this has not been taken into account.

    As a negative number it would pass many of the test conditions for sizes.
*/
    ret_t                 ret;
    chula_buffer_t        raw;
    hpack_header_parser_t parser;
    hpack_header_field_t  field;
    unsigned int          consumed = 0;

    const char *data64 = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF";
    const char *data32 = "\xFF\xFF\xFF\xFF\xFF\x0A";

    hpack_header_parser_init (&parser);
    hpack_header_field_init (&field);
    chula_buffer_fake_str (&raw, sizeof(int)>32?data64:data32);

    ret = hpack_header_parser_field (&parser, &raw, 0, &field, &consumed);
    ck_assert (ret != ret_ok);
    ck_assert (consumed == 0);

    hpack_header_parser_mrproper (&parser);
}
Пример #4
0
END_TEST

START_TEST (literal_wo_index) {
    ret_t                 ret;
    chula_buffer_t        raw;
    hpack_header_parser_t parser;
    hpack_header_field_t  field;
    unsigned int          consumed = 0;
/*
   44                                      | == Literal not indexed ==
                                           |   Indexed name (idx = 4) :path
   0c                                      | Literal value (len = 12)
   2f73 616d 706c 652f 7061 7468           |   /sample/path
*/

    hpack_header_parser_init (&parser);
    hpack_header_field_init  (&field);
    chula_buffer_fake_str (&raw, "\x44\x0c\x2f\x73\x61\x6d\x70\x6c\x65\x2f\x70\x61\x74\x68");

    ret = hpack_header_parser_field (&parser, &raw, 0, &field, &consumed);
    ck_assert (ret == ret_ok);
    ck_assert (consumed == raw.len);
    ck_assert_str_eq (field.name.buf, ":path");
    ck_assert_str_eq (field.value.buf, "/sample/path");

    hpack_header_parser_mrproper (&parser);
}
Пример #5
0
END_TEST


START_TEST (_add_doesnt_fit) {
    ret_t                  ret;
    hpack_header_table_t  *table;
    hpack_set_t            evicted_set;
    hpack_header_field_t   field;

    ret = hpack_header_table_new (&table);
    ch_assert (ret == ret_ok);

    hpack_header_field_init (&field);
    ret = chula_buffer_ensure_size (&field.name, (size_t) (table->max_data/2));
    ch_assert (ret_ok == ret);

    ret = chula_buffer_ensure_size (&field.value, (size_t) (table->max_data/2));
    ch_assert (ret_ok == ret);

    for (unsigned int i=0; i<field.name.len; ++i) {
        ret = chula_buffer_add_char (&field.name, '0' + (i%10));
        ch_assert (ret_ok == ret);
        ret = chula_buffer_add_char (&field.value, '9' - (i%10));
        ch_assert (ret_ok == ret);
    }

    ret = hpack_header_table_add (table, &field, evicted_set);
    ch_assert (ret_ok == ret);

    hpack_set_is_full (evicted_set);

    /* Clean up */
    hpack_header_field_mrproper (&field);
    hpack_header_table_free (table);
}
Пример #6
0
END_TEST

START_TEST (literal_w_index_false_len) {
/*
    This test tries to break the header field parsing by sending string
    literals with a string length field too big to be hold by a signed integer
    (works with 32bit and 64bit machines). Since it's too big, and given the
    algorith of the VLQ it gets transformed into a negative number if this has
    not been taken into account.

    As a negative number it would pass many of the test conditions for sizes.

    For a 32 bits machine:
   00                                      | == Literal indexed ==
   ffff ffff ff0a                          |   Literal name (len = 2952790270). Since it's bigger than INT_MAX (2147483647) it results in a negative number.
   6375 7374 6f6d 2d6b 6579                | custom-key
   0d                                      |   Literal value (len = 13)
   6375 7374 6f6d 2d68 6561 6465 72        | custom-header


    For a 64 bits machine:
   00                                      | == Literal indexed ==
   ffff ffff ffff ffff ffff                |   Literal name (len = 9223372036854776062). Since it's bigger than INT_MAX (9223372036854775807) it results in a negative number
   6375 7374 6f6d 2d6b 6579                | custom-key
   0d                                      |   Literal value (len = 13)
   6375 7374 6f6d 2d68 6561 6465 72        | custom-header

*/
    ret_t                 ret;
    chula_buffer_t        raw;
    hpack_header_parser_t parser;
    hpack_header_field_t  field;
    unsigned int          consumed = 0;

    const char *data64 = "\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\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 char *data32 = "\x00\xFF\xFF\xFF\xFF\xFF\x0A\x63\x75\x73\x74\x6f\x6d\x2d\x6b\x65\x79\0d\x63\x75\x73\x74\x6f\x6d\x2d\x68\x65\x61\x64\x65\x72";

    hpack_header_parser_init (&parser);
    hpack_header_field_init  (&field);
    chula_buffer_fake_str (&raw, sizeof(int)>32?data64:data32);

    ret = hpack_header_parser_field (&parser, &raw, 0, &field, &consumed);
    ck_assert (ret != ret_ok);
    ck_assert (consumed == 0);

    hpack_header_parser_mrproper (&parser);
}
Пример #7
0
END_TEST

START_TEST (indexed) {
    ret_t                 ret;
    chula_buffer_t        raw;
    hpack_header_parser_t parser;
    hpack_header_field_t  field;
    unsigned int          consumed = 0;

    hpack_header_parser_init (&parser);
    hpack_header_field_init (&field);
    chula_buffer_fake_str (&raw, "\x82");

    ret = hpack_header_parser_field (&parser, &raw, 0, &field, &consumed);
    ck_assert (ret == ret_ok);
    ck_assert (consumed == raw.len);
    ck_assert_str_eq (field.name.buf, ":method");
    ck_assert_str_eq (field.value.buf, "GET");

    hpack_header_parser_mrproper (&parser);
}
Пример #8
0
END_TEST

//
//START_TEST (_add_multi_evac) {
//END_TEST
//

START_TEST (field_get_len) {
    ret_t                ret;
    uint64_t             len;
    hpack_header_field_t field;

    ret = hpack_header_field_init (&field);
    ch_assert (ret == ret_ok);

    len = 1234;
    ret = hpack_header_field_get_size (&field, &len);
    ch_assert (ret == ret_ok);
    ch_assert (len == 0);

    /* (s =  55) custom-key: custom-header */
    chula_buffer_add_str (&field.name,  "custom-key");
    chula_buffer_add_str (&field.value, "custom-header");
    ret = hpack_header_field_get_size (&field, &len);
    ch_assert (ret == ret_ok);
    ch_assert (len == 55);

    /* (s =  42) :method: GET */
    hpack_header_field_clean (&field);
    chula_buffer_add_str (&field.name,  ":method");
    chula_buffer_add_str (&field.value, "GET");
    ret = hpack_header_field_get_size (&field, &len);
    ch_assert (ret == ret_ok);
    ch_assert (len == 42);

    ret = hpack_header_field_mrproper (&field);
    ch_assert (ret == ret_ok);
}
Пример #9
0
END_TEST

START_TEST (request1) {
    ret_t                 ret;
    chula_buffer_t        raw;
    hpack_header_parser_t parser;
    hpack_header_field_t  field;
    unsigned int          offset   = 0;
    unsigned int          consumed = 0;

/*
   82                                      | == Indexed - Add ==
                                           |   idx = 2
                                           | -> :method: GET
   87                                      | == Indexed - Add ==
                                           |   idx = 7
                                           | -> :scheme: http
   86                                      | == Indexed - Add ==
                                           |   idx = 6
                                           | -> :path: /
   04                                      | == Literal indexed ==
                                           |   Indexed name (idx = 4)
                                           |     :authority
   0f                                      |   Literal value (len = 15)
   7777 772e 6578 616d 706c 652e 636f 6d   | www.example.com
                                           | -> :authority: www.example.com
*/

    chula_buffer_fake_str (&raw, "\x82\x87\x86\x04\x0f\x77\x77\x77\x2e\x65\x78\x61\x6d\x70\x6c\x65\x2e\x63\x6f\x6d");
    hpack_header_field_init (&field);
    hpack_header_parser_init (&parser);

    chula_print_repr (chula, buffer, &raw);

    /* 82 - :method: GET */
    ret = hpack_header_parser_field (&parser, &raw, offset, &field, &consumed);
    ck_assert (ret == ret_ok);
    ck_assert (consumed == 1);
    ck_assert_str_eq (field.name.buf, ":method");
    ck_assert_str_eq (field.value.buf, "GET");
    chula_print_repr (hpack, header_field, &field);

    offset += consumed;
    ck_assert (offset == 1);
    memset (&field, 0, sizeof(field));

    /* 87 - :scheme: http */
    ret = hpack_header_parser_field (&parser, &raw, offset, &field, &consumed);
    ck_assert (ret == ret_ok);
    ck_assert (consumed == 1);
    ck_assert_str_eq (field.name.buf, ":scheme");
    ck_assert_str_eq (field.value.buf, "http");
    chula_print_repr (hpack, header_field, &field);

    offset += consumed;
    ck_assert (offset == 2);
    memset (&field, 0, sizeof(field));

    /* 86 - :path: / */
    ret = hpack_header_parser_field (&parser, &raw, offset, &field, &consumed);
    ck_assert (ret == ret_ok);
    ck_assert (consumed == 1);
    ck_assert_str_eq (field.name.buf, ":path");
    ck_assert_str_eq (field.value.buf, "/");
    chula_print_repr (hpack, header_field, &field);

    offset += consumed;
    ck_assert (offset == 3);
    memset (&field, 0, sizeof(field));

    /* 04 - :authority: www.example.com */
    ret = hpack_header_parser_field (&parser, &raw, offset, &field, &consumed);
    ck_assert (ret == ret_ok);
    ck_assert (consumed == 17);
    ck_assert_str_eq (field.name.buf, ":authority");
    ck_assert_str_eq (field.value.buf, "www.example.com");
    chula_print_repr (hpack, header_field, &field);

    hpack_header_parser_mrproper (&parser);
}
Пример #10
0
END_TEST

START_TEST (_add_some_evacs) {
    ret_t                  ret;
    hpack_header_table_t  *table;
    hpack_set_t            evicted_set;

    hpack_header_field_t   fields[6];
    hpack_header_field_t   field;

    uint64_t               size;
    uint16_t               max_size;

    ret = hpack_header_table_new (&table);
    ch_assert (ret == ret_ok);

    for (int i=0; i<6; i++) {
        hpack_header_field_init (&fields[i]);
        chula_buffer_add_va  (&fields[i].name, "%c-%d", 'a'+i, i);
        chula_buffer_add_va (&fields[i].value, "foobar-%d", i);
    }

    ret = hpack_header_field_get_size (&fields[0], &size);
    ch_assert (ret == ret_ok);

    max_size = (uint16_t) size * 4.5;

    ret = hpack_header_table_set_max (table, max_size, evicted_set);
    ch_assert (ret == ret_ok);

    for (int i=0; i<6; i++) {
        ret = hpack_header_table_add (table, &fields[i], evicted_set);
        ch_assert (ret_ok == ret);

        if (i < 4) {
            ch_assert (hpack_set_is_empty (evicted_set));

        } else {
            /* Since only 4 items fit, whenever we add more we lose the oldest one, that is the fifth element */
            ch_assert (hpack_header_table_set_exists (table, evicted_set, 5));
        }
    }

    ch_assert (table->num_headers == 4);

    /* Make sure relevant contents are in there */
    hpack_header_field_init (&field);
    for (int i=1; i<5; ++i) {
        bool is_static;

        ret = hpack_header_table_get (table, i, false, &field, &is_static);
        ch_assert (ret == ret_ok);
        ch_assert_str_eq (field.name.buf, fields[6-i].name.buf);
        ch_assert_str_eq (field.value.buf, fields[6-i].value.buf);
        ch_assert (field.flags.rep == fields[6-i].flags.rep);
        ch_assert (field.flags.name == fields[6-i].flags.name);
        ch_assert (field.flags.value == fields[6-i].flags.value);
        hpack_header_field_clean (&field);
    }

    /* Check that table's contents are OK*/
    ch_assert (table->used_data == size * 4);
    ch_assert (table->headers_offsets.head == 2);
    ch_assert (table->headers_offsets.head == table->headers_offsets.tail - 4);

    /* Calculate the size of each field in table->headers_data */
    size -= HPACK_HEADER_ENTRY_OVERHEAD - sizeof(hpack_header_table_field_info_t);
    ch_assert (table->headers_data.head == size * 2);
    ch_assert (table->headers_data.head == table->headers_data.tail - (size * 4));

    /* Clean up */
    hpack_header_field_mrproper (&field);
    for (int i=0; i<6; ++i) {
        hpack_header_field_mrproper (&fields[i]);
    }

    hpack_header_table_free (table);
}
Пример #11
0
END_TEST


START_TEST (_add_fits) {
    ret_t                  ret;
    hpack_header_table_t  *table;
    hpack_set_t            evicted_set;

    hpack_header_field_t   fields[6];
    hpack_header_field_t   field;

    uint64_t               size;
    uint16_t               real_size;

    ret = hpack_header_table_new (&table);
    ch_assert (ret == ret_ok);

    for (int i=0; i<6; i++) {
        hpack_header_field_init (&fields[i]);
        chula_buffer_add_va  (&fields[i].name, "%c-%d", 'a'+i, i);
        chula_buffer_add_va (&fields[i].value, "foobar-%d", i);
    }

    ret = hpack_header_field_get_size (&fields[0], &size);
    ch_assert (ret == ret_ok);
    real_size = fields[0].name.len + fields[0].value.len + sizeof(hpack_header_table_field_info_t);

    for (int i=0; i<6; i++) {
        ret = hpack_header_table_add (table, &fields[i], evicted_set);
        ch_assert (ret_ok == ret);

        /* Confirm that there's been no evictions */
        ch_assert (hpack_set_is_empty (evicted_set));

        /* Confirm that the number of headers in the table is OK */
        ch_assert (i+1 == table->num_headers);

        /* Confirm that the "used data" is correct */
        ch_assert ((i+1) * size == table->used_data);

        /* Confirm that the offset head is in place */
        ch_assert (0 == table->headers_offsets.head);

        /* Confirm that the offsets tail is ok */
        ch_assert (i+1 == table->headers_offsets.tail);

        /* Confirm that the data head is in place */
        ch_assert (0 == table->headers_data.head);

        /* Confirm that the data tail is ok */
        ch_assert ((i+1) * real_size == table->headers_data.tail);

        /* Confirm that the offset reference is correct */
        ch_assert (table->headers_offsets.buffer[i] == i * real_size);
    }

    ch_assert (table->num_headers == 6);

    /* Check that returned fields are OK */
    hpack_header_field_init (&field);
    for (int i=1; i<7; ++i) {
        bool is_static;
        ret = hpack_header_table_get (table, i, false, &field, &is_static);
        ch_assert (ret == ret_ok);

        ch_assert (field.flags.rep == fields[6-i].flags.rep);
        ch_assert (field.flags.name == fields[6-i].flags.name);
        ch_assert (field.flags.value == fields[6-i].flags.value);
        ch_assert_str_eq (field.name.buf, fields[6-i].name.buf);
        ch_assert_str_eq (field.value.buf, fields[6-i].value.buf);

        hpack_header_field_clean (&field);
    }

    /* Check that table's contents are OK*/
    ret = hpack_header_field_get_size (&fields[0], &size);
    ch_assert (ret == ret_ok);

    ch_assert (table->used_data == 6 * size);
    ch_assert (table->headers_offsets.head == 0);
    ch_assert (table->headers_offsets.head + 6 == table->headers_offsets.tail);

    /* Calculate the size of each field in table->headers_data */
    size -= HPACK_HEADER_ENTRY_OVERHEAD - sizeof(hpack_header_table_field_info_t);
    ch_assert (table->headers_data.head == 0);
    ch_assert (table->headers_data.head == table->headers_data.tail - (size *6));

    /* Clean up */
    hpack_header_field_mrproper (&field);
    for (int i=0; i<6; ++i) {
        hpack_header_field_mrproper (&fields[i]);
    }
    hpack_header_table_free (table);
}
Пример #12
0
END_TEST

START_TEST (_set_max_no_table_evict_some) {
    ret_t                 ret;
    hpack_header_table_t *table;
    hpack_header_field_t  field;
    hpack_set_t           evicted;
    uint64_t              size;
    uint16_t              used_bytes;
    uint16_t              max_size;
    hpack_set_iterator_t  iter;

    ret = hpack_header_table_new (&table);
    ch_assert (ret == ret_ok);

    hpack_header_field_init (&field);

    chula_buffer_add_str (&field.name,  "custom-key");
    chula_buffer_add_str (&field.value, "custom-header");

    for (int i=0; i<10; ++i) {
        ret = hpack_header_table_add (table, &field, evicted);
        ch_assert (ret_ok == ret);

        /* Confirm that there's been no evictions */
        ch_assert (hpack_set_is_empty (evicted));

        /* Confirm that the number of headers in the table is OK */
        ch_assert (i+1 == table->num_headers);

        /* Confirm that the "used data" is correct */
        ch_assert ((i+1) * (23+32) == table->used_data);

        /* Confirm that the offset head is in place */
        ch_assert (0 == table->headers_offsets.head);

        /* Confirm that the offsets tail is ok */
        ch_assert (i+1 == table->headers_offsets.tail);

        /* Confirm that the data head is in place */
        ch_assert (0 == table->headers_data.head);

        /* Confirm that the data tail is ok */
        ch_assert ((i+1) * (23+sizeof(hpack_header_table_field_info_t)) == table->headers_data.tail);

        /* Confirm that the offset reference is correct */
        ch_assert (table->headers_offsets.buffer[i] == i * (23+sizeof(hpack_header_table_field_info_t)));
    }

    /* We'll leave only space for 3 and 1/2 elements */
    ret = hpack_header_field_get_size (&field, &size);
    ch_assert (ret == ret_ok);

    used_bytes = (uint16_t) size * 3;
    max_size = (uint16_t) size * 3.5;

    ret = hpack_header_table_set_max (table, max_size, evicted);
    ch_assert (ret == ret_ok);

    hpack_header_table_iter_init (&iter, evicted);

    for (int i=0; i<8; ++i) {
        int e = hpack_header_table_iter_next (table, &iter);
        ch_assert (e == (i==7?-1:10-i));
    }

    ch_assert (table->max_data == max_size);
    ch_assert (table->num_headers == 3);

    ch_assert (table->used_data == used_bytes);
    ch_assert (table->headers_offsets.head == 7);
    ch_assert (table->headers_offsets.head == table->headers_offsets.tail - 3);

    /* Calculate the size of each field in table->headers_data */
    size -= HPACK_HEADER_ENTRY_OVERHEAD - sizeof(hpack_header_table_field_info_t);
    ch_assert (table->headers_data.head == size * 7);
    ch_assert (table->headers_data.head == table->headers_data.tail - (size * 3));

    hpack_header_field_mrproper (&field);
    hpack_header_table_free (table);
}