Changed behaviour of spdylay_select_next_protocol()
We use following algorithm to select protocol: 1. If server's list contains "spdy/2", this function selects "spdy/2" and returns 1. The following steps are not taken. 2. If server's list contains "http/1.1", this function selects "http/1.1" and returns 0. The following step is not taken. 3. This function selects "spdy/2" and returns -1. (So called non-overlap case).
This commit is contained in:
parent
c07f780e52
commit
b8700259fd
|
@ -461,10 +461,35 @@ int spdylay_submit_ping(spdylay_session *session);
|
||||||
int spdylay_submit_goaway(spdylay_session *session);
|
int spdylay_submit_goaway(spdylay_session *session);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A helper function for dealing with NPN. This function always
|
* A helper function for dealing with NPN in client side.
|
||||||
* selects "spdy/2" protocol. NPN draft permits that client can
|
* |in| contains server's protocol in preferable order.
|
||||||
* select any protocol even if server does not advertise it at the
|
* The format of |in| is length-prefixed and not null-terminated.
|
||||||
* time of this writing:
|
* For example, "spdy/2" are "http/1.1" stored in |in| like this:
|
||||||
|
*
|
||||||
|
* in[0] = 6
|
||||||
|
* in[1..6] = "spdy/2"
|
||||||
|
* in[7] = 8
|
||||||
|
* in[8..15] = "http/1.1"
|
||||||
|
* inlen = 16
|
||||||
|
*
|
||||||
|
* The selection algorithm is as follows:
|
||||||
|
*
|
||||||
|
* 1. If server's list contains "spdy/2", this function selects
|
||||||
|
* "spdy/2" and returns 1. The following steps are not taken.
|
||||||
|
*
|
||||||
|
* 2. If server's list contains "http/1.1", this function selects
|
||||||
|
* "http/1.1" and returns 0. The following step is not taken.
|
||||||
|
*
|
||||||
|
* 3. This function selects "spdy/2" and returns -1. (So called
|
||||||
|
* non-overlap case).
|
||||||
|
*
|
||||||
|
* When spdylay supports updated version of SPDY in the future, this
|
||||||
|
* function may select updated protocol and application code which
|
||||||
|
* relies on spdylay for SPDY stuff needs not be modified.
|
||||||
|
*
|
||||||
|
* For rationale of step 3, NPN draft permits that client can select
|
||||||
|
* any protocol even if server does not advertise it at the time of
|
||||||
|
* this writing:
|
||||||
*
|
*
|
||||||
* It's expected that a client will have a list of protocols that it
|
* It's expected that a client will have a list of protocols that it
|
||||||
* supports, in preference order, and will only select a protocol if
|
* supports, in preference order, and will only select a protocol if
|
||||||
|
@ -481,9 +506,6 @@ int spdylay_submit_goaway(spdylay_session *session);
|
||||||
* Selecting "spdy/2" means that "spdy/2" is written into |*out| and
|
* Selecting "spdy/2" means that "spdy/2" is written into |*out| and
|
||||||
* length of "spdy/2" (which is 6) is assigned to |*outlen|.
|
* length of "spdy/2" (which is 6) is assigned to |*outlen|.
|
||||||
*
|
*
|
||||||
* This function returns 0 if server advertised "spdy/2" and it is
|
|
||||||
* selected, or -1.
|
|
||||||
*
|
|
||||||
* To use this method you should do something like:
|
* To use this method you should do something like:
|
||||||
*
|
*
|
||||||
* static int select_next_proto_cb(SSL* ssl,
|
* static int select_next_proto_cb(SSL* ssl,
|
||||||
|
@ -491,7 +513,7 @@ int spdylay_submit_goaway(spdylay_session *session);
|
||||||
* const unsigned char *in, unsigned int inlen,
|
* const unsigned char *in, unsigned int inlen,
|
||||||
* void *arg)
|
* void *arg)
|
||||||
* {
|
* {
|
||||||
* if (spdylay_select_next_protocol(out, outlen, in, inlen) == 0) {
|
* if (spdylay_select_next_protocol(out, outlen, in, inlen) == 1) {
|
||||||
* ((MyType*)arg)->spdy = 1;
|
* ((MyType*)arg)->spdy = 1;
|
||||||
* }
|
* }
|
||||||
* return SSL_TLSEXT_ERR_OK;
|
* return SSL_TLSEXT_ERR_OK;
|
||||||
|
|
|
@ -29,13 +29,27 @@
|
||||||
int spdylay_select_next_protocol(unsigned char **out, unsigned char *outlen,
|
int spdylay_select_next_protocol(unsigned char **out, unsigned char *outlen,
|
||||||
const unsigned char *in, unsigned int inlen)
|
const unsigned char *in, unsigned int inlen)
|
||||||
{
|
{
|
||||||
|
int http_selected = 0;
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
|
/* For non-overlap case */
|
||||||
*out = (unsigned char*)"spdy/2";
|
*out = (unsigned char*)"spdy/2";
|
||||||
*outlen = 6;
|
*outlen = 6;
|
||||||
for(; i < inlen; i += in[i]+1) {
|
for(; i < inlen; i += in[i]+1) {
|
||||||
if(in[i] == 6 && memcmp(&in[i+1], "spdy/2", in[i]) == 0) {
|
if(in[i] == 6 && memcmp(&in[i+1], "spdy/2", in[i]) == 0) {
|
||||||
return 0;
|
*out = &in[i+1];
|
||||||
|
*outlen = in[i];
|
||||||
|
return 1;
|
||||||
|
} else if(in[i] == 8 && memcmp(&in[i+1], "http/1.1", in[i]) == 0) {
|
||||||
|
http_selected = 1;
|
||||||
|
*out = &in[i+1];
|
||||||
|
*outlen = in[i];
|
||||||
|
/* Go through to the next iteration, because "spdy/2" may be
|
||||||
|
there */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
if(http_selected) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,19 +30,34 @@
|
||||||
static void spdy2()
|
static void spdy2()
|
||||||
{
|
{
|
||||||
const unsigned char spdy[] = {
|
const unsigned char spdy[] = {
|
||||||
8, 'h', 't', 't', 'p', '/', '1', '.', '0',
|
8, 'h', 't', 't', 'p', '/', '1', '.', '1',
|
||||||
6, 's', 'p', 'd', 'y', '/', '2',
|
6, 's', 'p', 'd', 'y', '/', '2',
|
||||||
6, 's', 'p', 'd', 'y', '/', '3'
|
6, 's', 'p', 'd', 'y', '/', '3'
|
||||||
};
|
};
|
||||||
unsigned char outlen;
|
unsigned char outlen;
|
||||||
unsigned char* out;
|
unsigned char* out;
|
||||||
CU_ASSERT(0 == spdylay_select_next_protocol(&out, &outlen,
|
CU_ASSERT(1 == spdylay_select_next_protocol(&out, &outlen,
|
||||||
spdy, sizeof(spdy)));
|
spdy, sizeof(spdy)));
|
||||||
CU_ASSERT(6 == outlen);
|
CU_ASSERT(6 == outlen);
|
||||||
CU_ASSERT(memcmp("spdy/2", out, outlen) == 0);
|
CU_ASSERT(memcmp("spdy/2", out, outlen) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void spdy4()
|
static void http11()
|
||||||
|
{
|
||||||
|
const unsigned char spdy[] = {
|
||||||
|
6, 's', 'p', 'd', 'y', '/', '4',
|
||||||
|
8, 's', 'p', 'd', 'y', '/', '2', '.', '1',
|
||||||
|
8, 'h', 't', 't', 'p', '/', '1', '.', '1',
|
||||||
|
};
|
||||||
|
unsigned char outlen;
|
||||||
|
unsigned char* out;
|
||||||
|
CU_ASSERT(0 == spdylay_select_next_protocol(&out, &outlen,
|
||||||
|
spdy, sizeof(spdy)));
|
||||||
|
CU_ASSERT(8 == outlen);
|
||||||
|
CU_ASSERT(memcmp("http/1.1", out, outlen) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void no_overlap()
|
||||||
{
|
{
|
||||||
const unsigned char spdy[] = {
|
const unsigned char spdy[] = {
|
||||||
6, 's', 'p', 'd', 'y', '/', '4',
|
6, 's', 'p', 'd', 'y', '/', '4',
|
||||||
|
@ -60,5 +75,6 @@ static void spdy4()
|
||||||
void test_spdylay_npn()
|
void test_spdylay_npn()
|
||||||
{
|
{
|
||||||
spdy2();
|
spdy2();
|
||||||
spdy4();
|
http11();
|
||||||
|
no_overlap();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue