CURLcode Curl_http2_setup(struct connectdata *conn) { CURLcode result; struct http_conn *httpc = &conn->proto.httpc; if(conn->handler->flags & PROTOPT_SSL) conn->handler = &Curl_handler_http2_ssl; else conn->handler = &Curl_handler_http2; result = Curl_http2_init(conn); if(result) return result; infof(conn->data, "Using HTTP2\n"); httpc->bodystarted = false; httpc->error_code = NGHTTP2_NO_ERROR; httpc->closed = false; httpc->header_recvbuf = Curl_add_buffer_init(); httpc->nread_header_recvbuf = 0; httpc->data = NULL; httpc->datalen = 0; httpc->upload_left = 0; httpc->upload_mem = NULL; httpc->upload_len = 0; httpc->stream_id = -1; httpc->status_code = -1; conn->httpversion = 20; return CURLE_OK; }
/* * Append headers to ask for a HTTP1.1 to HTTP2 upgrade. */ CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req, struct connectdata *conn) { CURLcode result; ssize_t binlen; char *base64; size_t blen; struct SingleRequest *k = &conn->data->req; uint8_t *binsettings = conn->proto.httpc.binsettings; result = Curl_http2_init(conn); if(result) return result; result = Curl_http2_setup(conn); if(result) return result; /* As long as we have a fixed set of settings, we don't have to dynamically * figure out the base64 strings since it'll always be the same. However, * the settings will likely not be fixed every time in the future. */ /* this returns number of bytes it wrote */ binlen = nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN, settings, sizeof(settings)/sizeof(settings[0])); if(!binlen) { failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload"); return CURLE_FAILED_INIT; } conn->proto.httpc.binlen = binlen; result = Curl_base64url_encode(conn->data, (const char *)binsettings, binlen, &base64, &blen); if(result) return result; result = Curl_add_bufferf(req, "Connection: Upgrade, HTTP2-Settings\r\n" "Upgrade: %s\r\n" "HTTP2-Settings: %s\r\n", NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, base64); Curl_safefree(base64); k->upgr101 = UPGR101_REQUESTED; return result; }
CURLcode Curl_http2_setup(struct connectdata *conn) { CURLcode result; struct http_conn *httpc = &conn->proto.httpc; struct HTTP *stream = conn->data->req.protop; stream->stream_id = -1; if(!stream->header_recvbuf) stream->header_recvbuf = Curl_add_buffer_init(); if((conn->handler == &Curl_handler_http2_ssl) || (conn->handler == &Curl_handler_http2)) return CURLE_OK; /* already done */ if(conn->handler->flags & PROTOPT_SSL) conn->handler = &Curl_handler_http2_ssl; else conn->handler = &Curl_handler_http2; result = Curl_http2_init(conn); if(result) return result; infof(conn->data, "Using HTTP2, server supports multi-use\n"); stream->upload_left = 0; stream->upload_mem = NULL; stream->upload_len = 0; httpc->inbuflen = 0; httpc->nread_inbuf = 0; httpc->pause_stream_id = 0; conn->bits.multiplex = TRUE; /* at least potentially multiplexed */ conn->httpversion = 20; conn->bundle->multiuse = BUNDLE_MULTIPLEX; infof(conn->data, "Connection state changed (HTTP/2 confirmed)\n"); Curl_multi_connchanged(conn->data->multi); /* switch on TCP_NODELAY as we need to send off packets without delay for maximum throughput */ Curl_tcpnodelay(conn, conn->sock[FIRSTSOCKET]); return CURLE_OK; }