aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2013-09-12 13:51:04 +0200
committerDaniel Stenberg <daniel@haxx.se>2014-01-29 10:24:05 +0100
commit8d3608f2ad29bb65ce0926a45b46ff29902c279f (patch)
tree1d9ddec9546056b9ad7d6d94b545e0492c7ebe95 /lib
parent8bcf677a30cc1559b635c0eca7dd29ac2ab5f4bb (diff)
http2: handle 101 responses and switch to HTTP2
Diffstat (limited to 'lib')
-rw-r--r--lib/http.c25
-rw-r--r--lib/http2.c36
-rw-r--r--lib/http2.h2
-rw-r--r--lib/urldata.h9
4 files changed, 67 insertions, 5 deletions
diff --git a/lib/http.c b/lib/http.c
index da03a44c5..8df0105a1 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -2872,10 +2872,27 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
k->header = TRUE;
k->headerline = 0; /* restart the header line counter */
- /* if we did wait for this do enable write now! */
- if(k->exp100) {
- k->exp100 = EXP100_SEND_DATA;
- k->keepon |= KEEP_SEND;
+ /* "A user agent MAY ignore unexpected 1xx status responses." */
+ switch(k->httpcode) {
+ case 100:
+ /* if we did wait for this do enable write now! */
+ if(k->exp100) {
+ k->exp100 = EXP100_SEND_DATA;
+ k->keepon |= KEEP_SEND;
+ }
+ break;
+ case 101:
+ /* Switching Protocols */
+ if(k->upgr101 == UPGR101_REQUESTED) {
+ infof(data, "Received 101\n");
+ k->upgr101 = UPGR101_RECEIVED;
+
+ /* switch to http2 now */
+ Curl_http2_switched(conn);
+ }
+ break;
+ default:
+ break;
}
}
else {
diff --git a/lib/http2.c b/lib/http2.c
index b876436e1..f15cb1700 100644
--- a/lib/http2.c
+++ b/lib/http2.c
@@ -38,6 +38,32 @@
#include "memdebug.h"
/*
+ * HTTP2 handler interface. This isn't added to the general list of protocols
+ * but will be used at run-time when the protocol is dynamically switched from
+ * HTTP to HTTP2.
+ */
+const struct Curl_handler Curl_handler_http2 = {
+ "HTTP2", /* scheme */
+ ZERO_NULL, /* setup_connection */
+ ZERO_NULL, /* do_it */
+ ZERO_NULL , /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_HTTP, /* defport */
+ 0, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+
+
+/*
* Store nghttp2 version info in this buffer, Prefix with a space. Return
* total length written.
*/
@@ -138,6 +164,7 @@ CURLcode Curl_http2_request(Curl_send_buffer *req,
ssize_t binlen;
char *base64;
size_t blen;
+ struct SingleRequest *k = &conn->data->req;
if(!conn->proto.httpc.h2) {
/* The nghttp2 session is not yet setup, do it */
@@ -176,7 +203,16 @@ CURLcode Curl_http2_request(Curl_send_buffer *req,
NGHTTP2_PROTO_VERSION_ID, base64);
free(base64);
+ k->upgr101 = UPGR101_REQUESTED;
+
return result;
}
+void Curl_http2_switched(struct connectdata *conn)
+{
+ /* we are switched! */
+ conn->handler = &Curl_handler_http2;
+ infof(conn->data, "We have switched to HTTP2\n");
+}
+
#endif
diff --git a/lib/http2.h b/lib/http2.h
index 09b91d112..ffe16820e 100644
--- a/lib/http2.h
+++ b/lib/http2.h
@@ -34,8 +34,10 @@ int Curl_http2_ver(char *p, size_t len);
CURLcode Curl_http2_request(Curl_send_buffer *req,
struct connectdata *conn);
+void Curl_http2_switched(struct connectdata *conn);
#else /* USE_NGHTTP2 */
#define Curl_http2_request(x,y) CURLE_OK
+#define Curl_http2_switched(x)
#endif
#endif /* HEADER_CURL_HTTP2_H */
diff --git a/lib/urldata.h b/lib/urldata.h
index a00894e5c..7cb685707 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -580,7 +580,6 @@ struct Curl_async {
typedef CURLcode (*Curl_do_more_func)(struct connectdata *, int *);
typedef CURLcode (*Curl_done_func)(struct connectdata *, CURLcode, bool);
-
enum expect100 {
EXP100_SEND_DATA, /* enough waiting, just send the body now */
EXP100_AWAITING_CONTINUE, /* waiting for the 100 Continue header */
@@ -589,6 +588,13 @@ enum expect100 {
EXP100_FAILED /* used on 417 Expectation Failed */
};
+enum upgrade101 {
+ UPGR101_INIT, /* default state */
+ UPGR101_REQUESTED, /* upgrade requested */
+ UPGR101_RECEIVED, /* response received */
+ UPGR101_WORKING /* talking upgraded protocol */
+};
+
/*
* Request specific data in the easy handle (SessionHandle). Previously,
* these members were on the connectdata struct but since a conn struct may
@@ -639,6 +645,7 @@ struct SingleRequest {
'RTSP/1.? XXX' line */
struct timeval start100; /* time stamp to wait for the 100 code from */
enum expect100 exp100; /* expect 100 continue state */
+ enum upgrade101 upgr101; /* 101 upgrade state */
int auto_decoding; /* What content encoding. sec 3.5, RFC2616. */