diff --git a/doc/programmers-guide.rst b/doc/programmers-guide.rst index c67c09a3..94c72e98 100644 --- a/doc/programmers-guide.rst +++ b/doc/programmers-guide.rst @@ -20,17 +20,15 @@ nghttp2 callback functions directly or indirectly. It will lead to the crash. You can submit requests or frames in the callbacks then call these functions outside the callbacks. -Currently, `nghttp2_session_send()` and `nghttp2_session_mem_send()` -do not send client connection preface -(:macro:`NGHTTP2_CLIENT_CONNECTION_PREFACE`). The applications are -responsible to send it before sending any HTTP/2 frames using these -functions if :type:`nghttp2_session` is configured as client. -Similarly, `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` -do not consume client connection preface unless -`nghttp2_option_set_recv_client_preface()` is used with nonzero option -value. The applications are responsible to receive it before calling -these functions if :type:`nghttp2_session` is configured as server and -`nghttp2_option_set_recv_client_preface()` is not used. +`nghttp2_session_send()` and `nghttp2_session_mem_send()` send first +24 bytes of client magic string (MAGIC) +(:macro:`NGHTTP2_CLIENT_MAGIC`) on client configuration. The +applications are responsible to send SETTINGS frame as part of +connection preface using `nghttp2_submit_settings()`. Similarly, +`nghttp2_session_recv()` and `nghttp2_session_mem_recv()` consume +MAGIC on server configuration unless +`nghttp2_option_set_no_recv_client_magic()` is used with nonzero +option value. .. _http-messaging: diff --git a/doc/sources/tutorial-client.rst b/doc/sources/tutorial-client.rst index 0d168991..ceaa14c8 100644 --- a/doc/sources/tutorial-client.rst +++ b/doc/sources/tutorial-client.rst @@ -184,9 +184,9 @@ its bufferevent, so it closes underlying connection as well. It also calls `nghttp2_session_del()` to delete nghttp2 session object. We begin HTTP/2 communication by sending client connection preface, -which is 24 bytes magic byte sequence -(:macro:`NGHTTP2_CLIENT_CONNECTION_PREFACE`) and SETTINGS frame. The -transmission of client connection header is done in +which is 24 bytes magic byte string (:macro:`NGHTTP2_CLIENT_MAGIC`) +followed by SETTINGS frame. First 24 bytes magic string is +automatically sent by nghttp2 library. We send SETTINGS frame in ``send_client_connection_header()``:: static void send_client_connection_header(http2_session_data *session_data) { @@ -194,8 +194,7 @@ transmission of client connection header is done in {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}}; int rv; - bufferevent_write(session_data->bev, NGHTTP2_CLIENT_CONNECTION_PREFACE, - NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN); + /* client 24 bytes magic string will be sent by nghttp2 library */ rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE, iv, ARRLEN(iv)); if (rv != 0) { diff --git a/doc/sources/tutorial-server.rst b/doc/sources/tutorial-server.rst index 12347ef6..8f5b5833 100644 --- a/doc/sources/tutorial-server.rst +++ b/doc/sources/tutorial-server.rst @@ -194,15 +194,8 @@ We initialize a nghttp2 session object which is done in ``initialize_nghttp2_session()``:: static void initialize_nghttp2_session(http2_session_data *session_data) { - nghttp2_option *option; nghttp2_session_callbacks *callbacks; - nghttp2_option_new(&option); - - /* Tells nghttp2_session object that it handles client connection - preface */ - nghttp2_option_set_recv_client_preface(option, 1); - nghttp2_session_callbacks_new(&callbacks); nghttp2_session_callbacks_set_send_callback(callbacks, send_callback); @@ -219,20 +212,15 @@ We initialize a nghttp2 session object which is done in nghttp2_session_callbacks_set_on_begin_headers_callback( callbacks, on_begin_headers_callback); - nghttp2_session_server_new2(&session_data->session, callbacks, session_data, - option); + nghttp2_session_server_new(&session_data->session, callbacks, session_data); nghttp2_session_callbacks_del(callbacks); - nghttp2_option_del(option); } Since we are creating a server and uses options, the nghttp2 session object is created using `nghttp2_session_server_new2()` function. We registers five callbacks for nghttp2 session object. We'll talk about -these callbacks later. Our server only speaks HTTP/2. In this case, -we use `nghttp2_option_set_recv_client_preface()` to make -:type:`nghttp2_session` object handle client connection preface, which -saves some lines of application code. +these callbacks later. After initialization of the nghttp2 session object, we are going to send a server connection header in ``send_server_connection_header()``:: diff --git a/examples/client.c b/examples/client.c index 314efb34..b202df18 100644 --- a/examples/client.c +++ b/examples/client.c @@ -528,14 +528,6 @@ static void fetch_uri(const struct URI *uri) { connection.ssl = ssl; connection.want_io = IO_NONE; - /* Send connection header in blocking I/O mode */ - rv = SSL_write(ssl, NGHTTP2_CLIENT_CONNECTION_PREFACE, - NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN); - if (rv <= 0) { - dief("SSL_write failed: could not send connection preface", - ERR_error_string(ERR_get_error(), NULL)); - } - /* Here make file descriptor non-block */ make_non_block(fd); set_tcp_nodelay(fd); diff --git a/examples/libevent-client.c b/examples/libevent-client.c index 98c194a6..c970629b 100644 --- a/examples/libevent-client.c +++ b/examples/libevent-client.c @@ -345,8 +345,7 @@ static void send_client_connection_header(http2_session_data *session_data) { {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}}; int rv; - bufferevent_write(session_data->bev, NGHTTP2_CLIENT_CONNECTION_PREFACE, - NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN); + /* client 24 bytes magic string will be sent by nghttp2 library */ rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE, iv, ARRLEN(iv)); if (rv != 0) { diff --git a/lib/includes/nghttp2/nghttp2.h b/lib/includes/nghttp2/nghttp2.h index e80049b7..969726f4 100644 --- a/lib/includes/nghttp2/nghttp2.h +++ b/lib/includes/nghttp2/nghttp2.h @@ -194,32 +194,17 @@ typedef struct { /** * @macro * - * The client connection preface. + * The client magic string, which is the first 24 bytes byte string of + * client connection preface. */ -#define NGHTTP2_CLIENT_CONNECTION_PREFACE "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" +#define NGHTTP2_CLIENT_MAGIC "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" /** * @macro * - * The length of :macro:`NGHTTP2_CLIENT_CONNECTION_PREFACE`. + * The length of :macro:`NGHTTP2_CLIENT_MAGIC`. */ -#define NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN 24 - -/** - * @macro - * - * The client connection header. This macro is obsoleted by - * NGHTTP2_CLIENT_CONNECTION_PREFACE. - */ -#define NGHTTP2_CLIENT_CONNECTION_HEADER NGHTTP2_CLIENT_CONNECTION_PREFACE - -/** - * @macro - * - * The length of :macro:`NGHTTP2_CLIENT_CONNECTION_HEADER`. - */ -#define NGHTTP2_CLIENT_CONNECTION_HEADER_LEN \ - NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN +#define NGHTTP2_CLIENT_MAGIC_LEN 24 /** * @enum @@ -397,10 +382,10 @@ typedef enum { */ NGHTTP2_ERR_CALLBACK_FAILURE = -902, /** - * Invalid connection preface was received and further processing is - * not possible. + * Invalid client magic (see :macro:`NGHTTP2_CLIENT_MAGIC`) was + * received and further processing is not possible. */ - NGHTTP2_ERR_BAD_PREFACE = -903 + NGHTTP2_ERR_BAD_CLIENT_MAGIC = -903 } nghttp2_error; /** @@ -1975,25 +1960,22 @@ nghttp2_option_set_peer_max_concurrent_streams(nghttp2_option *option, * @function * * By default, nghttp2 library, if configured as server, requires - * first 24 bytes of client connection preface. In most cases, this - * will simplify the implementation of server. But sometimes erver - * may want to detect the application protocol based on first few - * bytes on clear text communication. + * first 24 bytes of client magic byte string (MAGIC). In most cases, + * this will simplify the implementation of server. But sometimes + * server may want to detect the application protocol based on first + * few bytes on clear text communication. * * If this option is used with nonzero |val|, nghttp2 library does not - * handle first 24 bytes client connection preface. It still checks - * following SETTINGS frame. This means that applications should deal - * with 24 bytes connection preface by themselves. + * handle MAGIC. It still checks following SETTINGS frame. This + * means that applications should deal with MAGIC by themselves. * - * If this option is not used or used with zero value, if client - * connection preface does not match the one - * (:macro:`NGHTTP2_CLIENT_CONNECTION_PREFACE`) in the HTTP/2 - * specification, `nghttp2_session_recv()` and - * `nghttp2_session_mem_recv()` will return error - * :enum:`NGHTTP2_ERR_BAD_PREFACE`, which is fatal error. + * If this option is not used or used with zero value, if MAGIC does + * not match :macro:`NGHTTP2_CLIENT_MAGIC`, `nghttp2_session_recv()` + * and `nghttp2_session_mem_recv()` will return error + * :enum:`NGHTTP2_ERR_BAD_CLIENT_MAGIC`, which is fatal error. */ NGHTTP2_EXTERN void -nghttp2_option_set_no_recv_client_preface(nghttp2_option *option, int val); +nghttp2_option_set_no_recv_client_magic(nghttp2_option *option, int val); /** * @function @@ -2310,10 +2292,10 @@ NGHTTP2_EXTERN ssize_t nghttp2_session_mem_send(nghttp2_session *session, * Out of memory. * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` * The callback function failed. - * :enum:`NGHTTP2_ERR_BAD_PREFACE` - * Invalid client preface was detected. This error only returns + * :enum:`NGHTTP2_ERR_BAD_CLIENT_MAGIC` + * Invalid client magic was detected. This error only returns * when |session| was configured as server and - * `nghttp2_option_set_no_recv_client_preface()` is not used with + * `nghttp2_option_set_no_recv_client_magic()` is not used with * nonzero value. */ NGHTTP2_EXTERN int nghttp2_session_recv(nghttp2_session *session); @@ -2346,10 +2328,10 @@ NGHTTP2_EXTERN int nghttp2_session_recv(nghttp2_session *session); * Out of memory. * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` * The callback function failed. - * :enum:`NGHTTP2_ERR_BAD_PREFACE` - * Invalid client preface was detected. This error only returns + * :enum:`NGHTTP2_ERR_BAD_CLIENT_MAGIC` + * Invalid client magic was detected. This error only returns * when |session| was configured as server and - * `nghttp2_option_set_no_recv_client_preface()` is not used with + * `nghttp2_option_set_no_recv_client_magic()` is not used with * nonzero value. */ NGHTTP2_EXTERN ssize_t nghttp2_session_mem_recv(nghttp2_session *session, diff --git a/lib/nghttp2_helper.c b/lib/nghttp2_helper.c index 5883f72c..15f329cc 100644 --- a/lib/nghttp2_helper.c +++ b/lib/nghttp2_helper.c @@ -307,8 +307,8 @@ const char *nghttp2_strerror(int error_code) { return "Out of memory"; case NGHTTP2_ERR_CALLBACK_FAILURE: return "The user callback function failed"; - case NGHTTP2_ERR_BAD_PREFACE: - return "Received bad connection preface"; + case NGHTTP2_ERR_BAD_CLIENT_MAGIC: + return "Received bad clinet magic byte string"; default: return "Unknown error code"; } diff --git a/lib/nghttp2_option.c b/lib/nghttp2_option.c index cf9bae02..a45b5e0e 100644 --- a/lib/nghttp2_option.c +++ b/lib/nghttp2_option.c @@ -47,10 +47,9 @@ void nghttp2_option_set_peer_max_concurrent_streams(nghttp2_option *option, option->peer_max_concurrent_streams = val; } -void nghttp2_option_set_no_recv_client_preface(nghttp2_option *option, - int val) { - option->opt_set_mask |= NGHTTP2_OPT_NO_RECV_CLIENT_PREFACE; - option->no_recv_client_preface = val; +void nghttp2_option_set_no_recv_client_magic(nghttp2_option *option, int val) { + option->opt_set_mask |= NGHTTP2_OPT_NO_RECV_CLIENT_MAGIC; + option->no_recv_client_magic = val; } void nghttp2_option_set_no_http_messaging(nghttp2_option *option, int val) { diff --git a/lib/nghttp2_option.h b/lib/nghttp2_option.h index f35339ab..2e56ff07 100644 --- a/lib/nghttp2_option.h +++ b/lib/nghttp2_option.h @@ -57,7 +57,7 @@ typedef enum { * SETTINGS_MAX_CONCURRENT_STREAMS from the remote endpoint. */ NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS = 1 << 1, - NGHTTP2_OPT_NO_RECV_CLIENT_PREFACE = 1 << 2, + NGHTTP2_OPT_NO_RECV_CLIENT_MAGIC = 1 << 2, NGHTTP2_OPT_NO_HTTP_MESSAGING = 1 << 3, } nghttp2_option_flag; @@ -79,9 +79,9 @@ struct nghttp2_option { */ uint8_t no_auto_window_update; /** - * NGHTTP2_OPT_NO_RECV_CLIENT_PREFACE + * NGHTTP2_OPT_NO_RECV_CLIENT_MAGIC */ - uint8_t no_recv_client_preface; + uint8_t no_recv_client_magic; /** * NGHTTP2_OPT_NO_HTTP_MESSAGING */ diff --git a/lib/nghttp2_session.c b/lib/nghttp2_session.c index bbb9aaa3..15d0f02c 100644 --- a/lib/nghttp2_session.c +++ b/lib/nghttp2_session.c @@ -314,9 +314,9 @@ static void active_outbound_item_reset(nghttp2_active_outbound_item *aob, aob->state = NGHTTP2_OB_POP_ITEM; } -/* This global variable exists for tests where we want to disable this - check. */ -int nghttp2_enable_strict_connection_preface_check = 1; +/* The global variable for tests where we want to disable strict + preface handling. */ +int nghttp2_enable_strict_preface = 1; static int session_new(nghttp2_session **session_ptr, const nghttp2_session_callbacks *callbacks, @@ -417,10 +417,10 @@ static int session_new(nghttp2_session **session_ptr, option->peer_max_concurrent_streams; } - if ((option->opt_set_mask & NGHTTP2_OPT_NO_RECV_CLIENT_PREFACE) && - option->no_recv_client_preface) { + if ((option->opt_set_mask & NGHTTP2_OPT_NO_RECV_CLIENT_MAGIC) && + option->no_recv_client_magic) { - (*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_RECV_CLIENT_PREFACE; + (*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_RECV_CLIENT_MAGIC; } if ((option->opt_set_mask & NGHTTP2_OPT_NO_HTTP_MESSAGING) && @@ -435,17 +435,23 @@ static int session_new(nghttp2_session **session_ptr, session_inbound_frame_reset(*session_ptr); - if (nghttp2_enable_strict_connection_preface_check) { + if (nghttp2_enable_strict_preface) { nghttp2_inbound_frame *iframe = &(*session_ptr)->iframe; if (server && - ((*session_ptr)->opt_flags & NGHTTP2_OPTMASK_NO_RECV_CLIENT_PREFACE) == + ((*session_ptr)->opt_flags & NGHTTP2_OPTMASK_NO_RECV_CLIENT_MAGIC) == 0) { - iframe->state = NGHTTP2_IB_READ_CLIENT_PREFACE; - iframe->payloadleft = NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN; + iframe->state = NGHTTP2_IB_READ_CLIENT_MAGIC; + iframe->payloadleft = NGHTTP2_CLIENT_MAGIC_LEN; } else { iframe->state = NGHTTP2_IB_READ_FIRST_SETTINGS; } + + if (!server) { + (*session_ptr)->aob.state = NGHTTP2_OB_SEND_CLIENT_MAGIC; + nghttp2_bufs_add(&(*session_ptr)->aob.framebufs, NGHTTP2_CLIENT_MAGIC, + NGHTTP2_CLIENT_MAGIC_LEN); + } } return 0; @@ -2979,6 +2985,25 @@ static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session, break; } + case NGHTTP2_OB_SEND_CLIENT_MAGIC: { + size_t datalen; + nghttp2_buf *buf; + + buf = &framebufs->cur->buf; + + if (buf->pos == buf->last) { + DEBUGF(fprintf(stderr, "send: end transmission of client magic\n")); + active_outbound_item_reset(aob, mem); + break; + } + + *data_ptr = buf->pos; + datalen = nghttp2_buf_len(buf); + + buf->pos += datalen; + + return datalen; + } } } } @@ -2993,14 +3018,16 @@ ssize_t nghttp2_session_mem_send(nghttp2_session *session, return len; } - /* We have to call session_after_frame_sent1 here to handle stream - closure upon transmission of frames. Otherwise, END_STREAM may - be reached to client before we call nghttp2_session_mem_send - again and we may get exceeding number of incoming streams. */ - rv = session_after_frame_sent1(session); - if (rv < 0) { - assert(nghttp2_is_fatal(rv)); - return (ssize_t)rv; + if (session->aob.item) { + /* We have to call session_after_frame_sent1 here to handle stream + closure upon transmission of frames. Otherwise, END_STREAM may + be reached to client before we call nghttp2_session_mem_send + again and we may get exceeding number of incoming streams. */ + rv = session_after_frame_sent1(session); + if (rv < 0) { + assert(nghttp2_is_fatal(rv)); + return (ssize_t)rv; + } } return len; @@ -4907,14 +4934,13 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, for (;;) { switch (iframe->state) { - case NGHTTP2_IB_READ_CLIENT_PREFACE: + case NGHTTP2_IB_READ_CLIENT_MAGIC: readlen = nghttp2_min(inlen, iframe->payloadleft); - if (memcmp(NGHTTP2_CLIENT_CONNECTION_PREFACE + - NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN - + if (memcmp(NGHTTP2_CLIENT_MAGIC + NGHTTP2_CLIENT_MAGIC_LEN - iframe->payloadleft, in, readlen) != 0) { - return NGHTTP2_ERR_BAD_PREFACE; + return NGHTTP2_ERR_BAD_CLIENT_MAGIC; } iframe->payloadleft -= readlen; diff --git a/lib/nghttp2_session.h b/lib/nghttp2_session.h index ea532262..9d14c8ee 100644 --- a/lib/nghttp2_session.h +++ b/lib/nghttp2_session.h @@ -46,14 +46,15 @@ */ typedef enum { NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE = 1 << 0, - NGHTTP2_OPTMASK_NO_RECV_CLIENT_PREFACE = 1 << 1, + NGHTTP2_OPTMASK_NO_RECV_CLIENT_MAGIC = 1 << 1, NGHTTP2_OPTMASK_NO_HTTP_MESSAGING = 1 << 2, } nghttp2_optmask; typedef enum { NGHTTP2_OB_POP_ITEM, NGHTTP2_OB_SEND_DATA, - NGHTTP2_OB_SEND_NO_COPY + NGHTTP2_OB_SEND_NO_COPY, + NGHTTP2_OB_SEND_CLIENT_MAGIC } nghttp2_outbound_state; typedef struct { @@ -69,7 +70,7 @@ typedef struct { /* Internal state when receiving incoming frame */ typedef enum { /* Receiving frame header */ - NGHTTP2_IB_READ_CLIENT_PREFACE, + NGHTTP2_IB_READ_CLIENT_MAGIC, NGHTTP2_IB_READ_FIRST_SETTINGS, NGHTTP2_IB_READ_HEAD, NGHTTP2_IB_READ_NBYTE, diff --git a/python/nghttp2.pyx b/python/nghttp2.pyx index 10b12759..c6b9b66c 100644 --- a/python/nghttp2.pyx +++ b/python/nghttp2.pyx @@ -1477,8 +1477,6 @@ if asyncio: cnghttp2.NGHTTP2_PROTO_VERSION_ID: self.transport.abort() - # Send preamble - self.transport.write(cnghttp2.NGHTTP2_CLIENT_CONNECTION_PREFACE) self.http2 = _HTTP2ClientSessionCore(self.transport) # Clear pending requests diff --git a/src/HttpServer.cc b/src/HttpServer.cc index 1aa2aea7..b9bb557f 100644 --- a/src/HttpServer.cc +++ b/src/HttpServer.cc @@ -431,7 +431,7 @@ int Http2Handler::read_clear() { rv = nghttp2_session_mem_recv(session_, buf.data(), nread); if (rv < 0) { - if (rv != NGHTTP2_ERR_BAD_PREFACE) { + if (rv != NGHTTP2_ERR_BAD_CLIENT_MAGIC) { std::cerr << "nghttp2_session_mem_recv() returned error: " << nghttp2_strerror(rv) << std::endl; } @@ -558,7 +558,7 @@ int Http2Handler::read_tls() { rv = nghttp2_session_mem_recv(session_, buf.data(), nread); if (rv < 0) { - if (rv != NGHTTP2_ERR_BAD_PREFACE) { + if (rv != NGHTTP2_ERR_BAD_CLIENT_MAGIC) { std::cerr << "nghttp2_session_mem_recv() returned error: " << nghttp2_strerror(rv) << std::endl; } diff --git a/src/asio_client_session_impl.cc b/src/asio_client_session_impl.cc index 844b1957..e705105d 100644 --- a/src/asio_client_session_impl.cc +++ b/src/asio_client_session_impl.cc @@ -75,10 +75,6 @@ void session_impl::connected(tcp::resolver::iterator endpoint_it) { socket().set_option(boost::asio::ip::tcp::no_delay(true)); - std::copy_n(NGHTTP2_CLIENT_CONNECTION_PREFACE, - NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN, std::begin(wb_)); - wblen_ = NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN; - do_write(); do_read(); diff --git a/src/h2load_http2_session.cc b/src/h2load_http2_session.cc index bc658380..0f0ef0f6 100644 --- a/src/h2load_http2_session.cc +++ b/src/h2load_http2_session.cc @@ -202,12 +202,6 @@ void Http2Session::on_connect() { extra_connection_window); } - auto &wb = client_->wb; - assert(wb.wleft() >= NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN); - - wb.write(NGHTTP2_CLIENT_CONNECTION_PREFACE, - NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN); - client_->signal_write(); } diff --git a/src/nghttp.cc b/src/nghttp.cc index fa57a99e..34f84820 100644 --- a/src/nghttp.cc +++ b/src/nghttp.cc @@ -962,9 +962,6 @@ int HttpClient::connection_made() { request_done(stream_user_data); } } - // Send connection header here - wb.write(NGHTTP2_CLIENT_CONNECTION_PREFACE, - NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN); // If upgrade succeeds, the SETTINGS value sent with // HTTP2-Settings header field has already been submitted to // session object. diff --git a/src/shrpx.cc b/src/shrpx.cc index 4b64ce39..8904ce13 100644 --- a/src/shrpx.cc +++ b/src/shrpx.cc @@ -904,7 +904,7 @@ void fill_default_config() { nghttp2_option_new(&mod_config()->http2_option); nghttp2_option_set_no_auto_window_update(get_config()->http2_option, 1); - nghttp2_option_set_no_recv_client_preface(get_config()->http2_option, 1); + nghttp2_option_set_no_recv_client_magic(get_config()->http2_option, 1); nghttp2_option_new(&mod_config()->http2_client_option); nghttp2_option_set_no_auto_window_update(get_config()->http2_client_option, diff --git a/src/shrpx_client_handler.cc b/src/shrpx_client_handler.cc index c8065bb4..58d9eb74 100644 --- a/src/shrpx_client_handler.cc +++ b/src/shrpx_client_handler.cc @@ -279,8 +279,7 @@ int ClientHandler::upstream_write() { int ClientHandler::upstream_http2_connhd_read() { auto nread = std::min(left_connhd_len_, rb_.rleft()); - if (memcmp(NGHTTP2_CLIENT_CONNECTION_PREFACE + - NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN - left_connhd_len_, + if (memcmp(NGHTTP2_CLIENT_MAGIC + NGHTTP2_CLIENT_MAGIC_LEN - left_connhd_len_, rb_.pos, nread) != 0) { // There is no downgrade path here. Just drop the connection. if (LOG_ENABLED(INFO)) { @@ -309,8 +308,7 @@ int ClientHandler::upstream_http2_connhd_read() { int ClientHandler::upstream_http1_connhd_read() { auto nread = std::min(left_connhd_len_, rb_.rleft()); - if (memcmp(NGHTTP2_CLIENT_CONNECTION_PREFACE + - NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN - left_connhd_len_, + if (memcmp(NGHTTP2_CLIENT_MAGIC + NGHTTP2_CLIENT_MAGIC_LEN - left_connhd_len_, rb_.pos, nread) != 0) { if (LOG_ENABLED(INFO)) { CLOG(INFO, this) << "This is HTTP/1.1 connection, " @@ -318,7 +316,7 @@ int ClientHandler::upstream_http1_connhd_read() { } // Reset header length for later HTTP/2 upgrade - left_connhd_len_ = NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN; + left_connhd_len_ = NGHTTP2_CLIENT_MAGIC_LEN; on_read_ = &ClientHandler::upstream_read; on_write_ = &ClientHandler::upstream_write; @@ -362,7 +360,7 @@ ClientHandler::ClientHandler(Worker *worker, int fd, SSL *ssl, get_config()->read_burst, writecb, readcb, timeoutcb, this), ipaddr_(ipaddr), port_(port), worker_(worker), http2session_(worker_->next_http2_session()), - left_connhd_len_(NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN), + left_connhd_len_(NGHTTP2_CLIENT_MAGIC_LEN), should_close_after_write_(false) { ++worker_->get_worker_stat()->num_connections; diff --git a/src/shrpx_http2_session.cc b/src/shrpx_http2_session.cc index a73c91c5..5fc5f7e3 100644 --- a/src/shrpx_http2_session.cc +++ b/src/shrpx_http2_session.cc @@ -1278,13 +1278,6 @@ int Http2Session::connection_made() { } } - auto nwrite = wb_.write(NGHTTP2_CLIENT_CONNECTION_PREFACE, - NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN); - if (nwrite != NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN) { - SSLOG(FATAL, this) << "buffer is too small to send connection preface"; - return -1; - } - auto must_terminate = !get_config()->downstream_no_tls && !ssl::check_http2_requirement(conn_.tls.ssl); diff --git a/src/shrpx_http2_upstream.cc b/src/shrpx_http2_upstream.cc index 64af8afa..121db248 100644 --- a/src/shrpx_http2_upstream.cc +++ b/src/shrpx_http2_upstream.cc @@ -769,7 +769,7 @@ int Http2Upstream::on_read() { if (rb->rleft()) { rv = nghttp2_session_mem_recv(session_, rb->pos, rb->rleft()); if (rv < 0) { - if (rv != NGHTTP2_ERR_BAD_PREFACE) { + if (rv != NGHTTP2_ERR_BAD_CLIENT_MAGIC) { ULOG(ERROR, this) << "nghttp2_session_recv() returned error: " << nghttp2_strerror(rv); } diff --git a/tests/main.c b/tests/main.c index 9b9e8e63..396c0081 100644 --- a/tests/main.c +++ b/tests/main.c @@ -41,7 +41,7 @@ #include "nghttp2_helper_test.h" #include "nghttp2_buf_test.h" -extern int nghttp2_enable_strict_connection_preface_check; +extern int nghttp2_enable_strict_preface; static int init_suite1(void) { return 0; } @@ -51,7 +51,7 @@ int main(int argc _U_, char *argv[] _U_) { CU_pSuite pSuite = NULL; unsigned int num_tests_failed; - nghttp2_enable_strict_connection_preface_check = 0; + nghttp2_enable_strict_preface = 0; /* initialize the CUnit test registry */ if (CUE_SUCCESS != CU_initialize_registry()) @@ -250,8 +250,8 @@ int main(int argc _U_, char *argv[] _U_) { test_nghttp2_session_graceful_shutdown) || !CU_add_test(pSuite, "session_on_header_temporal_failure", test_nghttp2_session_on_header_temporal_failure) || - !CU_add_test(pSuite, "session_recv_client_preface", - test_nghttp2_session_recv_client_preface) || + !CU_add_test(pSuite, "session_recv_client_magic", + test_nghttp2_session_recv_client_magic) || !CU_add_test(pSuite, "session_delete_data_item", test_nghttp2_session_delete_data_item) || !CU_add_test(pSuite, "session_open_idle_stream", diff --git a/tests/nghttp2_session_test.c b/tests/nghttp2_session_test.c index 4e77019b..8721eeae 100644 --- a/tests/nghttp2_session_test.c +++ b/tests/nghttp2_session_test.c @@ -36,7 +36,7 @@ #include "nghttp2_test_helper.h" #include "nghttp2_priority_spec.h" -extern int nghttp2_enable_strict_connection_preface_check; +extern int nghttp2_enable_strict_preface; #define OB_CTRL(ITEM) nghttp2_outbound_item_get_ctrl_frame(ITEM) #define OB_CTRL_TYPE(ITEM) nghttp2_outbound_item_get_ctrl_frame_type(ITEM) @@ -6722,27 +6722,25 @@ void test_nghttp2_session_on_header_temporal_failure(void) { nghttp2_session_del(session); } -void test_nghttp2_session_recv_client_preface(void) { +void test_nghttp2_session_recv_client_magic(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; ssize_t rv; nghttp2_frame ping_frame; uint8_t buf[16]; - /* enable global nghttp2_enable_strict_connection_preface_check - here */ - nghttp2_enable_strict_connection_preface_check = 1; + /* enable global nghttp2_enable_strict_preface here */ + nghttp2_enable_strict_preface = 1; memset(&callbacks, 0, sizeof(callbacks)); /* Check success case */ nghttp2_session_server_new(&session, &callbacks, NULL); - rv = nghttp2_session_mem_recv( - session, (const uint8_t *)NGHTTP2_CLIENT_CONNECTION_PREFACE, - NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN); + rv = nghttp2_session_mem_recv(session, (const uint8_t *)NGHTTP2_CLIENT_MAGIC, + NGHTTP2_CLIENT_MAGIC_LEN); - CU_ASSERT(rv == NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN); + CU_ASSERT(rv == NGHTTP2_CLIENT_MAGIC_LEN); CU_ASSERT(NGHTTP2_IB_READ_FIRST_SETTINGS == session->iframe.state); /* Receiving PING is error because we want SETTINGS. */ @@ -6762,24 +6760,22 @@ void test_nghttp2_session_recv_client_preface(void) { /* Check bad case */ nghttp2_session_server_new(&session, &callbacks, NULL); - /* Feed preface with one byte less */ - rv = nghttp2_session_mem_recv( - session, (const uint8_t *)NGHTTP2_CLIENT_CONNECTION_PREFACE, - NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN - 1); + /* Feed magic with one byte less */ + rv = nghttp2_session_mem_recv(session, (const uint8_t *)NGHTTP2_CLIENT_MAGIC, + NGHTTP2_CLIENT_MAGIC_LEN - 1); - CU_ASSERT(rv == NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN - 1); - CU_ASSERT(NGHTTP2_IB_READ_CLIENT_PREFACE == session->iframe.state); + CU_ASSERT(rv == NGHTTP2_CLIENT_MAGIC_LEN - 1); + CU_ASSERT(NGHTTP2_IB_READ_CLIENT_MAGIC == session->iframe.state); CU_ASSERT(1 == session->iframe.payloadleft); rv = nghttp2_session_mem_recv(session, (const uint8_t *)"\0", 1); - CU_ASSERT(NGHTTP2_ERR_BAD_PREFACE == rv); + CU_ASSERT(NGHTTP2_ERR_BAD_CLIENT_MAGIC == rv); nghttp2_session_del(session); - /* disable global nghttp2_enable_strict_connection_preface_check - here */ - nghttp2_enable_strict_connection_preface_check = 0; + /* disable global nghttp2_enable_strict_preface here */ + nghttp2_enable_strict_preface = 0; } void test_nghttp2_session_delete_data_item(void) { diff --git a/tests/nghttp2_session_test.h b/tests/nghttp2_session_test.h index b6fe967d..406cfb78 100644 --- a/tests/nghttp2_session_test.h +++ b/tests/nghttp2_session_test.h @@ -118,7 +118,7 @@ void test_nghttp2_session_detach_idle_stream(void); void test_nghttp2_session_large_dep_tree(void); void test_nghttp2_session_graceful_shutdown(void); void test_nghttp2_session_on_header_temporal_failure(void); -void test_nghttp2_session_recv_client_preface(void); +void test_nghttp2_session_recv_client_magic(void); void test_nghttp2_session_delete_data_item(void); void test_nghttp2_session_open_idle_stream(void); void test_nghttp2_session_cancel_reserved_remote(void);