Always accept SPDY/3 style name/value pairs from spdylay_submit_* and
translate them into SPDY/2 as needed.
This commit is contained in:
parent
7d9a7b3069
commit
00abfc8dd3
|
@ -563,24 +563,7 @@ void* spdylay_session_get_stream_user_data(spdylay_session *session,
|
|||
* the lowest priority is 3. If the |session| is initialized with the
|
||||
* version SPDYLAY_PROTO_SPDY3, the lowest priority is 7.
|
||||
*
|
||||
* If |session| is initialized with the version SPDYLAY_PROTO_SPDY2,
|
||||
* |nv| must include following name/value pairs:
|
||||
*
|
||||
* "method"
|
||||
* HTTP method (e.g., "GET", "POST", "HEAD", etc)
|
||||
* "scheme"
|
||||
* URI scheme (e.g., "https")
|
||||
* "url"
|
||||
* Absolute path and parameters of this request (e.g., "/foo",
|
||||
* "/foo;bar;haz?h=j&y=123")
|
||||
* "version"
|
||||
* HTTP version (e.g., "HTTP/1.1")
|
||||
*
|
||||
* The "host" name/value pair (this is the same as the HTTP "Host"
|
||||
* header field) is also required by some hosts.
|
||||
*
|
||||
* If |session| is initialized with the version SPDYLAY_PROTO_SPDY3,
|
||||
* |nv| must include following name/value pairs:
|
||||
* The |nv| must include following name/value pairs:
|
||||
*
|
||||
* ":method"
|
||||
* HTTP method (e.g., "GET", "POST", "HEAD", etc)
|
||||
|
@ -596,6 +579,10 @@ void* spdylay_session_get_stream_user_data(spdylay_session *session,
|
|||
* "example.org:443"). This is the same as the HTTP "Host" header
|
||||
* field.
|
||||
*
|
||||
* If the |session| is initialized with the version
|
||||
* SPDYLAY_PROTO_SPDY2, the above names are translated to "method",
|
||||
* "scheme", "url", "version" and "host" respectively.
|
||||
*
|
||||
* This function creates copies of all name/value pairs in |nv|. It
|
||||
* also lower-cases all names in |nv|.
|
||||
*
|
||||
|
@ -637,22 +624,17 @@ int spdylay_submit_request(spdylay_session *session, uint8_t pri,
|
|||
* Submits SYN_REPLY frame and optionally one or more DATA frames
|
||||
* against stream |stream_id|.
|
||||
*
|
||||
* If |session| is initialized with the version SPDYLAY_PROTO_SPDY2,
|
||||
* |nv| must include following name/value pairs:
|
||||
*
|
||||
* "status"
|
||||
* HTTP status code (e.g., "200" or "200 OK")
|
||||
* "version"
|
||||
* HTTP response version (e.g., "HTTP/1.1")
|
||||
*
|
||||
* If |session| is initialized with the version SPDYLAY_PROTO_SPDY3,
|
||||
* |nv| must include following name/value pairs:
|
||||
* The |nv| must include following name/value pairs:
|
||||
*
|
||||
* ":status"
|
||||
* HTTP status code (e.g., "200" or "200 OK")
|
||||
* ":version"
|
||||
* HTTP response version (e.g., "HTTP/1.1")
|
||||
*
|
||||
* If the |session| is initialized with the version
|
||||
* SPDYLAY_PROTO_SPDY2, the above names are translated to "status" and
|
||||
* "version" respectively.
|
||||
*
|
||||
* This function creates copies of all name/value pairs in |nv|. It
|
||||
* also lower-cases all names in |nv|.
|
||||
*
|
||||
|
|
|
@ -376,6 +376,43 @@ char** spdylay_frame_nv_norm_copy(const char **nv)
|
|||
return nv_copy;
|
||||
}
|
||||
|
||||
/* Table to translate SPDY/3 header names to SPDY/2. */
|
||||
static char *spdylay_nv_3to2[] = {
|
||||
":host", "host",
|
||||
":method", "method",
|
||||
":path", "url",
|
||||
":scheme", "scheme",
|
||||
":status", "status",
|
||||
":version", "version",
|
||||
NULL
|
||||
};
|
||||
|
||||
void spdylay_frame_nv_3to2(char **nv)
|
||||
{
|
||||
int i, j;
|
||||
for(i = 0; nv[i]; i += 2) {
|
||||
for(j = 0; spdylay_nv_3to2[j]; j += 2) {
|
||||
if(strcmp(nv[i], spdylay_nv_3to2[j]) == 0) {
|
||||
nv[i] = spdylay_nv_3to2[j+1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void spdylay_frame_nv_2to3(char **nv)
|
||||
{
|
||||
int i, j;
|
||||
for(i = 0; nv[i]; i += 2) {
|
||||
for(j = 0; spdylay_nv_3to2[j]; j += 2) {
|
||||
if(strcmp(nv[i], spdylay_nv_3to2[j+1]) == 0) {
|
||||
nv[i] = spdylay_nv_3to2[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void spdylay_frame_syn_stream_init(spdylay_syn_stream *frame,
|
||||
uint16_t version, uint8_t flags,
|
||||
int32_t stream_id, int32_t assoc_stream_id,
|
||||
|
|
|
@ -595,6 +595,16 @@ void spdylay_frame_nv_downcase(char **nv);
|
|||
*/
|
||||
char** spdylay_frame_nv_norm_copy(const char **nv);
|
||||
|
||||
/*
|
||||
* Translates the |nv| in SPDY/3 header names into SPDY/2.
|
||||
*/
|
||||
void spdylay_frame_nv_3to2(char **nv);
|
||||
|
||||
/*
|
||||
* Translates the |nv| in SPDY/2 header names into SPDY/3.
|
||||
*/
|
||||
void spdylay_frame_nv_2to3(char **nv);
|
||||
|
||||
/*
|
||||
* Makes copy of |iv| and return the copy. The |niv| is the number of
|
||||
* entries in |iv|. This function returns the pointer to the copy if
|
||||
|
|
|
@ -552,12 +552,18 @@ static ssize_t spdylay_session_prep_frame(spdylay_session *session,
|
|||
stream_id = session->next_stream_id;
|
||||
item->frame->syn_stream.stream_id = stream_id;
|
||||
session->next_stream_id += 2;
|
||||
if(session->version == SPDYLAY_PROTO_SPDY2) {
|
||||
spdylay_frame_nv_3to2(item->frame->syn_stream.nv);
|
||||
}
|
||||
framebuflen = spdylay_frame_pack_syn_stream(&session->aob.framebuf,
|
||||
&session->aob.framebufmax,
|
||||
&session->nvbuf,
|
||||
&session->nvbuflen,
|
||||
&item->frame->syn_stream,
|
||||
&session->hd_deflater);
|
||||
if(session->version == SPDYLAY_PROTO_SPDY2) {
|
||||
spdylay_frame_nv_2to3(item->frame->syn_stream.nv);
|
||||
}
|
||||
if(framebuflen < 0) {
|
||||
return framebuflen;
|
||||
}
|
||||
|
@ -576,12 +582,18 @@ static ssize_t spdylay_session_prep_frame(spdylay_session *session,
|
|||
item->frame->syn_reply.stream_id)) {
|
||||
return SPDYLAY_ERR_INVALID_FRAME;
|
||||
}
|
||||
if(session->version == SPDYLAY_PROTO_SPDY2) {
|
||||
spdylay_frame_nv_3to2(item->frame->syn_reply.nv);
|
||||
}
|
||||
framebuflen = spdylay_frame_pack_syn_reply(&session->aob.framebuf,
|
||||
&session->aob.framebufmax,
|
||||
&session->nvbuf,
|
||||
&session->nvbuflen,
|
||||
&item->frame->syn_reply,
|
||||
&session->hd_deflater);
|
||||
if(session->version == SPDYLAY_PROTO_SPDY2) {
|
||||
spdylay_frame_nv_2to3(item->frame->syn_reply.nv);
|
||||
}
|
||||
if(framebuflen < 0) {
|
||||
return framebuflen;
|
||||
}
|
||||
|
@ -620,12 +632,18 @@ static ssize_t spdylay_session_prep_frame(spdylay_session *session,
|
|||
item->frame->headers.stream_id)) {
|
||||
return SPDYLAY_ERR_INVALID_FRAME;
|
||||
}
|
||||
if(session->version == SPDYLAY_PROTO_SPDY2) {
|
||||
spdylay_frame_nv_3to2(item->frame->headers.nv);
|
||||
}
|
||||
framebuflen = spdylay_frame_pack_headers(&session->aob.framebuf,
|
||||
&session->aob.framebufmax,
|
||||
&session->nvbuf,
|
||||
&session->nvbuflen,
|
||||
&item->frame->headers,
|
||||
&session->hd_deflater);
|
||||
if(session->version == SPDYLAY_PROTO_SPDY2) {
|
||||
spdylay_frame_nv_2to3(item->frame->headers.nv);
|
||||
}
|
||||
if(framebuflen < 0) {
|
||||
return framebuflen;
|
||||
}
|
||||
|
|
|
@ -170,6 +170,8 @@ int main(int argc, char* argv[])
|
|||
test_spdylay_frame_nv_downcase) ||
|
||||
!CU_add_test(pSuite, "frame_pack_nv_duplicate_keys",
|
||||
test_spdylay_frame_pack_nv_duplicate_keys) ||
|
||||
!CU_add_test(pSuite, "frame_nv_2to3", test_spdylay_frame_nv_2to3) ||
|
||||
!CU_add_test(pSuite, "frame_nv_3to2", test_spdylay_frame_nv_3to2) ||
|
||||
!CU_add_test(pSuite, "stream_add_pushed_stream",
|
||||
test_spdylay_stream_add_pushed_stream)) {
|
||||
CU_cleanup_registry();
|
||||
|
|
|
@ -526,3 +526,53 @@ void test_spdylay_frame_nv_downcase()
|
|||
CU_ASSERT(0 == strcmp("1000000007", nv[3]));
|
||||
spdylay_frame_nv_del(nv);
|
||||
}
|
||||
|
||||
void test_spdylay_frame_nv_2to3()
|
||||
{
|
||||
const char *nv_src[] = {
|
||||
"host", "localhost",
|
||||
"method", "GET",
|
||||
"url", "/",
|
||||
"accept", "*/*",
|
||||
"scheme", "https",
|
||||
"status", "200 OK",
|
||||
"version", "HTTP/1.1",
|
||||
NULL
|
||||
};
|
||||
char **nv;
|
||||
nv = spdylay_frame_nv_copy(nv_src);
|
||||
spdylay_frame_nv_2to3(nv);
|
||||
CU_ASSERT(0 == strcmp(":host", nv[0]));
|
||||
CU_ASSERT(0 == strcmp(":method", nv[2]));
|
||||
CU_ASSERT(0 == strcmp(":path", nv[4]));
|
||||
CU_ASSERT(0 == strcmp("accept", nv[6]));
|
||||
CU_ASSERT(0 == strcmp(":scheme", nv[8]));
|
||||
CU_ASSERT(0 == strcmp(":status", nv[10]));
|
||||
CU_ASSERT(0 == strcmp(":version", nv[12]));
|
||||
spdylay_frame_nv_del(nv);
|
||||
}
|
||||
|
||||
void test_spdylay_frame_nv_3to2()
|
||||
{
|
||||
const char *nv_src[] = {
|
||||
":host", "localhost",
|
||||
":method", "GET",
|
||||
":path", "/",
|
||||
"accept", "*/*",
|
||||
":scheme", "https",
|
||||
":status", "200 OK",
|
||||
":version", "HTTP/1.1",
|
||||
NULL
|
||||
};
|
||||
char **nv;
|
||||
nv = spdylay_frame_nv_copy(nv_src);
|
||||
spdylay_frame_nv_3to2(nv);
|
||||
CU_ASSERT(0 == strcmp("host", nv[0]));
|
||||
CU_ASSERT(0 == strcmp("method", nv[2]));
|
||||
CU_ASSERT(0 == strcmp("url", nv[4]));
|
||||
CU_ASSERT(0 == strcmp("accept", nv[6]));
|
||||
CU_ASSERT(0 == strcmp("scheme", nv[8]));
|
||||
CU_ASSERT(0 == strcmp("status", nv[10]));
|
||||
CU_ASSERT(0 == strcmp("version", nv[12]));
|
||||
spdylay_frame_nv_del(nv);
|
||||
}
|
||||
|
|
|
@ -43,5 +43,7 @@ void test_spdylay_frame_pack_window_update();
|
|||
void test_spdylay_frame_pack_settings();
|
||||
void test_spdylay_frame_nv_sort();
|
||||
void test_spdylay_frame_nv_downcase();
|
||||
void test_spdylay_frame_nv_2to3();
|
||||
void test_spdylay_frame_nv_3to2();
|
||||
|
||||
#endif /* SPDYLAY_FRAME_TEST_H */
|
||||
|
|
|
@ -579,21 +579,36 @@ void test_spdylay_submit_response_with_null_data_read_callback()
|
|||
{
|
||||
spdylay_session *session;
|
||||
spdylay_session_callbacks callbacks;
|
||||
const char *nv[] = { "Version", "HTTP/1.1", NULL };
|
||||
accumulator acc;
|
||||
const char *nv[] = { ":Version", "HTTP/1.1", NULL };
|
||||
spdylay_data_provider data_prd = {{-1}, NULL};
|
||||
spdylay_outbound_item *item;
|
||||
my_user_data ud;
|
||||
spdylay_frame frame;
|
||||
|
||||
acc.length = 0;
|
||||
ud.acc = &acc;
|
||||
memset(&callbacks, 0, sizeof(callbacks));
|
||||
callbacks.send_callback = null_send_callback;
|
||||
callbacks.send_callback = accumulator_send_callback;
|
||||
CU_ASSERT(0 == spdylay_session_server_new(&session, SPDYLAY_PROTO_SPDY2,
|
||||
&callbacks, NULL));
|
||||
&callbacks, &ud));
|
||||
spdylay_session_open_stream(session, 1, SPDYLAY_CTRL_FLAG_FIN, 3,
|
||||
SPDYLAY_STREAM_OPENING, NULL);
|
||||
CU_ASSERT(0 == spdylay_submit_response(session, 1, nv, &data_prd));
|
||||
item = spdylay_session_get_next_ob_item(session);
|
||||
CU_ASSERT(0 == strcmp("version", item->frame->syn_reply.nv[0]));
|
||||
CU_ASSERT(0 == strcmp(":version", item->frame->syn_reply.nv[0]));
|
||||
CU_ASSERT(item->frame->syn_reply.hd.flags & SPDYLAY_CTRL_FLAG_FIN);
|
||||
|
||||
CU_ASSERT(0 == spdylay_session_send(session));
|
||||
CU_ASSERT(0 == spdylay_frame_unpack_syn_reply(&frame.syn_reply,
|
||||
&session->inflatebuf,
|
||||
&session->nvbuf,
|
||||
&session->nvbuflen,
|
||||
&acc.buf[0], SPDYLAY_HEAD_LEN,
|
||||
&acc.buf[SPDYLAY_HEAD_LEN],
|
||||
acc.length-SPDYLAY_HEAD_LEN,
|
||||
&session->hd_inflater));
|
||||
CU_ASSERT(0 == strcmp("version", frame.syn_reply.nv[0]));
|
||||
spdylay_session_del(session);
|
||||
}
|
||||
|
||||
|
@ -627,23 +642,36 @@ void test_spdylay_submit_request_with_data()
|
|||
void test_spdylay_submit_request_with_null_data_read_callback()
|
||||
{
|
||||
spdylay_session *session;
|
||||
spdylay_session_callbacks callbacks = {
|
||||
null_send_callback,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
const char *nv[] = { "Version", "HTTP/1.1", NULL };
|
||||
spdylay_session_callbacks callbacks;
|
||||
accumulator acc;
|
||||
const char *nv[] = { ":Version", "HTTP/1.1", NULL };
|
||||
spdylay_data_provider data_prd = {{-1}, NULL};
|
||||
spdylay_outbound_item *item;
|
||||
my_user_data ud;
|
||||
spdylay_frame frame;
|
||||
|
||||
acc.length = 0;
|
||||
ud.acc = &acc;
|
||||
memset(&callbacks, 0, sizeof(spdylay_session_callbacks));
|
||||
callbacks.send_callback = accumulator_send_callback;
|
||||
CU_ASSERT(0 == spdylay_session_client_new(&session, SPDYLAY_PROTO_SPDY2,
|
||||
&callbacks, NULL));
|
||||
&callbacks, &ud));
|
||||
CU_ASSERT(0 == spdylay_submit_request(session, 3, nv, &data_prd, NULL));
|
||||
item = spdylay_session_get_next_ob_item(session);
|
||||
CU_ASSERT(0 == strcmp("version", item->frame->syn_stream.nv[0]));
|
||||
CU_ASSERT(0 == strcmp(":version", item->frame->syn_stream.nv[0]));
|
||||
CU_ASSERT(item->frame->syn_stream.hd.flags & SPDYLAY_CTRL_FLAG_FIN);
|
||||
|
||||
CU_ASSERT(0 == spdylay_session_send(session));
|
||||
CU_ASSERT(0 == spdylay_frame_unpack_syn_stream(&frame.syn_stream,
|
||||
&session->inflatebuf,
|
||||
&session->nvbuf,
|
||||
&session->nvbuflen,
|
||||
&acc.buf[0], SPDYLAY_HEAD_LEN,
|
||||
&acc.buf[SPDYLAY_HEAD_LEN],
|
||||
acc.length-SPDYLAY_HEAD_LEN,
|
||||
&session->hd_inflater));
|
||||
CU_ASSERT(0 == strcmp("version", frame.syn_stream.nv[0]));
|
||||
|
||||
spdylay_session_del(session);
|
||||
}
|
||||
|
||||
|
@ -724,20 +752,24 @@ void test_spdylay_submit_headers()
|
|||
{
|
||||
spdylay_session *session;
|
||||
spdylay_session_callbacks callbacks;
|
||||
const char *nv[] = { "version", "HTTP/1.1", NULL };
|
||||
const char *nv[] = { ":Version", "HTTP/1.1", NULL };
|
||||
my_user_data ud;
|
||||
spdylay_outbound_item *item;
|
||||
spdylay_stream *stream;
|
||||
accumulator acc;
|
||||
spdylay_frame frame;
|
||||
|
||||
acc.length = 0;
|
||||
ud.acc = &acc;
|
||||
memset(&callbacks, 0, sizeof(spdylay_session_callbacks));
|
||||
callbacks.send_callback = null_send_callback;
|
||||
callbacks.send_callback = accumulator_send_callback;
|
||||
callbacks.on_ctrl_send_callback = on_ctrl_send_callback;
|
||||
|
||||
CU_ASSERT(0 == spdylay_session_client_new(&session, SPDYLAY_PROTO_SPDY2,
|
||||
&callbacks, &ud));
|
||||
CU_ASSERT(0 == spdylay_submit_headers(session, SPDYLAY_CTRL_FLAG_FIN, 1, nv));
|
||||
item = spdylay_session_get_next_ob_item(session);
|
||||
CU_ASSERT(0 == strcmp("version", item->frame->headers.nv[0]));
|
||||
CU_ASSERT(0 == strcmp(":version", item->frame->headers.nv[0]));
|
||||
CU_ASSERT(SPDYLAY_CTRL_FLAG_FIN == item->frame->headers.hd.flags);
|
||||
|
||||
ud.ctrl_send_cb_called = 0;
|
||||
|
@ -754,6 +786,16 @@ void test_spdylay_submit_headers()
|
|||
CU_ASSERT(SPDYLAY_HEADERS == ud.sent_frame_type);
|
||||
CU_ASSERT(stream->shut_flags & SPDYLAY_SHUT_WR);
|
||||
|
||||
CU_ASSERT(0 == spdylay_frame_unpack_headers(&frame.headers,
|
||||
&session->inflatebuf,
|
||||
&session->nvbuf,
|
||||
&session->nvbuflen,
|
||||
&acc.buf[0], SPDYLAY_HEAD_LEN,
|
||||
&acc.buf[SPDYLAY_HEAD_LEN],
|
||||
acc.length-SPDYLAY_HEAD_LEN,
|
||||
&session->hd_inflater));
|
||||
CU_ASSERT(0 == strcmp("version", frame.headers.nv[0]));
|
||||
|
||||
spdylay_session_del(session);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue