Send 24 bytes client magic byte string by library

Previously nghttp2_session_send() and nghttp2_session_mem_send() did
not send 24 bytes client magic byte string (MAGIC).  We made
nghttp2_session_recv() and nghttp2_session_mem_recv() process MAGIC by
default, so it is natural to make library send MAGIC as well.  This
commit makes nghttp2_session_send() and nghttp2_session_mem_send()
send MAGIC.  This commit also replace "connection preface" with
"client magic", since we call MAGIC as "connection preface" but it is
just a part of connection preface.  NGHTTP2_CLIENT_CONNECTION_PREFACE
macro was replaced with NGHTTP2_CLIENT_MAGIC.  The already deprecated
NGHTTP2_CLIENT_CONNECTION_HEADER macro was removed permanently.
nghttp2_option_set_no_recv_client_preface() was renamed as
nghttp2_option_set_no_recv_client_magic().  NGHTTP2_ERR_BAD_PREFACE
was renamed as NGHTTP2_ERR_BAD_CLIENT_MAGIC.
This commit is contained in:
Tatsuhiro Tsujikawa 2015-04-05 22:35:40 +09:00
parent ebf214c8fc
commit d0c27d5229
23 changed files with 129 additions and 173 deletions

View File

@ -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:

View File

@ -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) {

View File

@ -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()``::

View File

@ -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);

View File

@ -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) {

View File

@ -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,

View File

@ -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";
}

View File

@ -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) {

View File

@ -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
*/

View File

@ -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,6 +3018,7 @@ ssize_t nghttp2_session_mem_send(nghttp2_session *session,
return len;
}
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
@ -3002,6 +3028,7 @@ ssize_t nghttp2_session_mem_send(nghttp2_session *session,
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;

View File

@ -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,

View File

@ -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

View File

@ -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;
}

View File

@ -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();

View File

@ -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();
}

View File

@ -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.

View File

@ -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,

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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",

View File

@ -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) {

View File

@ -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);