From d0cd3628521bcbdc7ee18994071412ae641dae76 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sun, 5 Feb 2012 21:48:20 +0900 Subject: [PATCH] Changed spdylay_select_next_protocol behaviour It now always select "spdy/2" as a next protocol regardless whether or not the server advertises it. The NPN draft allows this. Returning integer version number is not flexible because the selected protcol is just a string. The function now returns 0 if the server advertised spdy/2, or -1. --- examples/spdylay_ssl.cc | 3 +-- lib/includes/spdylay/spdylay.h | 29 +++++++++++++++++++++++++---- lib/spdylay_npn.c | 7 +++---- tests/spdylay_npn_test.c | 8 ++++---- 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/examples/spdylay_ssl.cc b/examples/spdylay_ssl.cc index 8ae73087..f6c1b06b 100644 --- a/examples/spdylay_ssl.cc +++ b/examples/spdylay_ssl.cc @@ -360,8 +360,7 @@ int select_next_proto_cb(SSL* ssl, } } if(spdylay_select_next_protocol(out, outlen, in, inlen) == -1) { - std::cerr << "Invalid protocol: " - << std::string((const char*)*out, (size_t)*outlen) << std::endl; + std::cerr << "Server did not advertise spdy/2 protocol." << std::endl; abort(); } if(ssl_debug) { diff --git a/lib/includes/spdylay/spdylay.h b/lib/includes/spdylay/spdylay.h index 7b74c331..5d37308d 100644 --- a/lib/includes/spdylay/spdylay.h +++ b/lib/includes/spdylay/spdylay.h @@ -435,16 +435,37 @@ int spdylay_submit_ping(spdylay_session *session); int spdylay_submit_goaway(spdylay_session *session); /* - * A helper function for dealing with NPN. This function returns the - * version of spdy that was negotiated, or -1. To use this method you - * should do something like: + * A helper function for dealing with NPN. This function always + * selects "spdy/2" protocol. 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 + * supports, in preference order, and will only select a protocol if + * the server supports it. In that case, the client SHOULD select + * the first protocol advertised by the server that it also + * supports. In the event that the client doesn't support any of + * server's protocols, or the server doesn't advertise any, it + * SHOULD select the first protocol that it supports. + * + * There are cases where the client knows that a server supports an + * unadvertised protocol. In these cases the client should simply + * select that protocol. + * + * Selecting "spdy/2" means that "spdy/2" is written into |*out| and + * 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: * * static int select_next_proto_cb(SSL* ssl, * unsigned char **out, unsigned char *outlen, * const unsigned char *in, unsigned int inlen, * void *arg) * { - * if (spdylay_select_next_protocol(out, outlen, in, inlen) > 0) { + * if (spdylay_select_next_protocol(out, outlen, in, inlen) == 0) { * ((MyType*)arg)->spdy = 1; * } * return SSL_TLSEXT_ERR_OK; diff --git a/lib/spdylay_npn.c b/lib/spdylay_npn.c index 28158bfd..bf5c52cd 100644 --- a/lib/spdylay_npn.c +++ b/lib/spdylay_npn.c @@ -30,12 +30,11 @@ int spdylay_select_next_protocol(unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen) { unsigned int i = 0; + *out = (unsigned char*)"spdy/2"; + *outlen = 6; for(; i < inlen; i += in[i]+1) { - /* Always assign to *out so that the last one is picked. */ - *out = (unsigned char*)in+i+1; - *outlen = in[i]; if(in[i] == 6 && memcmp(&in[i+1], "spdy/2", in[i]) == 0) { - return 2; + return 0; } } return -1; diff --git a/tests/spdylay_npn_test.c b/tests/spdylay_npn_test.c index 1a358a37..8b2420fe 100644 --- a/tests/spdylay_npn_test.c +++ b/tests/spdylay_npn_test.c @@ -36,10 +36,10 @@ static void spdy2() }; unsigned char outlen; unsigned char* out; - CU_ASSERT(2 == spdylay_select_next_protocol(&out, &outlen, + CU_ASSERT(0 == spdylay_select_next_protocol(&out, &outlen, spdy, sizeof(spdy))); CU_ASSERT(6 == outlen); - CU_ASSERT(memcmp("spdy/2", out, 6) == 0); + CU_ASSERT(memcmp("spdy/2", out, outlen) == 0); } static void spdy4() @@ -53,8 +53,8 @@ static void spdy4() unsigned char* out; CU_ASSERT(-1 == spdylay_select_next_protocol(&out, &outlen, spdy, sizeof(spdy))); - CU_ASSERT(8 == outlen); - CU_ASSERT(memcmp("http/1.0", out, outlen) == 0); + CU_ASSERT(6 == outlen); + CU_ASSERT(memcmp("spdy/2", out, outlen) == 0); } void test_spdylay_npn()