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:
parent
ebf214c8fc
commit
d0c27d5229
|
@ -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:
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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()``::
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue