deps: update to nghttp2 1.33.0

Refs: https://github.com/nghttp2/nghttp2/releases/tag/v1.33.0

PR-URL: https://github.com/nodejs/node/pull/22649
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
This commit is contained in:
Anna Henningsen 2018-09-02 12:00:41 +02:00 committed by Daniel Bevenius
parent b4f5cdc6c4
commit e007166009
30 changed files with 599 additions and 78 deletions

View File

@ -28,7 +28,7 @@
/* Define WIN32 when build target is Win32 API (borrowed from
libcurl) */
#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
#define WIN32
# define WIN32
#endif
#ifdef __cplusplus
@ -40,9 +40,9 @@ extern "C" {
/* MSVC < 2013 does not have inttypes.h because it is not C99
compliant. See compiler macros and version number in
https://sourceforge.net/p/predef/wiki/Compilers/ */
#include <stdint.h>
# include <stdint.h>
#else /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */
#include <inttypes.h>
# include <inttypes.h>
#endif /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */
#include <sys/types.h>
#include <stdarg.h>
@ -50,20 +50,20 @@ extern "C" {
#include <nghttp2/nghttp2ver.h>
#ifdef NGHTTP2_STATICLIB
#define NGHTTP2_EXTERN
# define NGHTTP2_EXTERN
#elif defined(WIN32)
#ifdef BUILDING_NGHTTP2
#define NGHTTP2_EXTERN __declspec(dllexport)
#else /* !BUILDING_NGHTTP2 */
#define NGHTTP2_EXTERN __declspec(dllimport)
#endif /* !BUILDING_NGHTTP2 */
#else /* !defined(WIN32) */
#ifdef BUILDING_NGHTTP2
#define NGHTTP2_EXTERN __attribute__((visibility("default")))
#else /* !BUILDING_NGHTTP2 */
#define NGHTTP2_EXTERN
#endif /* !BUILDING_NGHTTP2 */
#endif /* !defined(WIN32) */
# ifdef BUILDING_NGHTTP2
# define NGHTTP2_EXTERN __declspec(dllexport)
# else /* !BUILDING_NGHTTP2 */
# define NGHTTP2_EXTERN __declspec(dllimport)
# endif /* !BUILDING_NGHTTP2 */
#else /* !defined(WIN32) */
# ifdef BUILDING_NGHTTP2
# define NGHTTP2_EXTERN __attribute__((visibility("default")))
# else /* !BUILDING_NGHTTP2 */
# define NGHTTP2_EXTERN
# endif /* !BUILDING_NGHTTP2 */
#endif /* !defined(WIN32) */
/**
* @macro
@ -611,7 +611,12 @@ typedef enum {
* The ALTSVC frame, which is defined in `RFC 7383
* <https://tools.ietf.org/html/rfc7838#section-4>`_.
*/
NGHTTP2_ALTSVC = 0x0a
NGHTTP2_ALTSVC = 0x0a,
/**
* The ORIGIN frame, which is defined by `RFC 8336
* <https://tools.ietf.org/html/rfc8336>`_.
*/
NGHTTP2_ORIGIN = 0x0c
} nghttp2_frame_type;
/**
@ -2473,15 +2478,15 @@ nghttp2_option_set_no_auto_window_update(nghttp2_option *option, int val);
*
* This option sets the SETTINGS_MAX_CONCURRENT_STREAMS value of
* remote endpoint as if it is received in SETTINGS frame. Without
* specifying this option, before the local endpoint receives
* SETTINGS_MAX_CONCURRENT_STREAMS in SETTINGS frame from remote
* endpoint, SETTINGS_MAX_CONCURRENT_STREAMS is unlimited. This may
* cause problem if local endpoint submits lots of requests initially
* and sending them at once to the remote peer may lead to the
* rejection of some requests. Specifying this option to the sensible
* value, say 100, may avoid this kind of issue. This value will be
* overwritten if the local endpoint receives
* SETTINGS_MAX_CONCURRENT_STREAMS from the remote endpoint.
* specifying this option, the maximum number of outgoing concurrent
* streams is initially limited to 100 to avoid issues when the local
* endpoint submits lots of requests before receiving initial SETTINGS
* frame from the remote endpoint, since sending them at once to the
* remote endpoint could lead to rejection of some of the requests.
* This value will be overwritten when the local endpoint receives
* initial SETTINGS frame from the remote endpoint, either to the
* value advertised in SETTINGS_MAX_CONCURRENT_STREAMS or to the
* default value (unlimited) if none was advertised.
*/
NGHTTP2_EXTERN void
nghttp2_option_set_peer_max_concurrent_streams(nghttp2_option *option,
@ -3797,10 +3802,13 @@ nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec);
* .. warning::
*
* This function returns assigned stream ID if it succeeds. But
* that stream is not opened yet. The application must not submit
* that stream is not created yet. The application must not submit
* frame to that stream ID before
* :type:`nghttp2_before_frame_send_callback` is called for this
* frame.
* frame. This means `nghttp2_session_get_stream_user_data()` does
* not work before the callback. But
* `nghttp2_session_set_stream_user_data()` handles this situation
* specially, and it can set data to a stream during this period.
*
*/
NGHTTP2_EXTERN int32_t nghttp2_submit_request(
@ -4516,8 +4524,7 @@ typedef struct {
* Submits ALTSVC frame.
*
* ALTSVC frame is a non-critical extension to HTTP/2, and defined in
* is defined in `RFC 7383
* <https://tools.ietf.org/html/rfc7838#section-4>`_.
* `RFC 7383 <https://tools.ietf.org/html/rfc7838#section-4>`_.
*
* The |flags| is currently ignored and should be
* :enum:`NGHTTP2_FLAG_NONE`.
@ -4551,6 +4558,81 @@ NGHTTP2_EXTERN int nghttp2_submit_altsvc(nghttp2_session *session,
const uint8_t *field_value,
size_t field_value_len);
/**
* @struct
*
* The single entry of an origin.
*/
typedef struct {
/**
* The pointer to origin. No validation is made against this field
* by the library. This is not necessarily NULL-terminated.
*/
uint8_t *origin;
/**
* The length of the |origin|.
*/
size_t origin_len;
} nghttp2_origin_entry;
/**
* @struct
*
* The payload of ORIGIN frame. ORIGIN frame is a non-critical
* extension to HTTP/2 and defined by `RFC 8336
* <https://tools.ietf.org/html/rfc8336>`_.
*
* If this frame is received, and
* `nghttp2_option_set_user_recv_extension_type()` is not set, and
* `nghttp2_option_set_builtin_recv_extension_type()` is set for
* :enum:`NGHTTP2_ORIGIN`, ``nghttp2_extension.payload`` will point to
* this struct.
*
* It has the following members:
*/
typedef struct {
/**
* The number of origins contained in |ov|.
*/
size_t nov;
/**
* The pointer to the array of origins contained in ORIGIN frame.
*/
nghttp2_origin_entry *ov;
} nghttp2_ext_origin;
/**
* @function
*
* Submits ORIGIN frame.
*
* ORIGIN frame is a non-critical extension to HTTP/2 and defined by
* `RFC 8336 <https://tools.ietf.org/html/rfc8336>`_.
*
* The |flags| is currently ignored and should be
* :enum:`NGHTTP2_FLAG_NONE`.
*
* The |ov| points to the array of origins. The |nov| specifies the
* number of origins included in |ov|. This function creates copies
* of all elements in |ov|.
*
* The ORIGIN frame is only usable by a server. If this function is
* invoked with client side session, this function returns
* :enum:`NGHTTP2_ERR_INVALID_STATE`.
*
* :enum:`NGHTTP2_ERR_NOMEM`
* Out of memory
* :enum:`NGHTTP2_ERR_INVALID_STATE`
* The function is called from client side session.
* :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
* There are too many origins, or an origin is too large to fit
* into a default frame payload.
*/
NGHTTP2_EXTERN int nghttp2_submit_origin(nghttp2_session *session,
uint8_t flags,
const nghttp2_origin_entry *ov,
size_t nov);
/**
* @function
*

View File

@ -29,7 +29,7 @@
* @macro
* Version number of the nghttp2 library release
*/
#define NGHTTP2_VERSION "1.32.0"
#define NGHTTP2_VERSION "1.33.0"
/**
* @macro
@ -37,6 +37,6 @@
* release. This is a 24 bit number with 8 bits for major number, 8 bits
* for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
*/
#define NGHTTP2_VERSION_NUM 0x012000
#define NGHTTP2_VERSION_NUM 0x012100
#endif /* NGHTTP2VER_H */

View File

@ -26,7 +26,7 @@
#define NGHTTP2_BUF_H
#ifdef HAVE_CONFIG_H
#include <config.h>
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>

View File

@ -26,7 +26,7 @@
#define NGHTTP2_CALLBACKS_H
#ifdef HAVE_CONFIG_H
#include <config.h>
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>

View File

@ -26,18 +26,18 @@
#define NGHTTP2_DEBUG_H
#ifdef HAVE_CONFIG_H
#include <config.h>
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>
#ifdef DEBUGBUILD
#define DEBUGF(...) nghttp2_debug_vprintf(__VA_ARGS__)
# define DEBUGF(...) nghttp2_debug_vprintf(__VA_ARGS__)
void nghttp2_debug_vprintf(const char *format, ...);
#else
#define DEBUGF(...) \
do { \
} while (0)
# define DEBUGF(...) \
do { \
} while (0)
#endif
#endif /* NGHTTP2_DEBUG_H */

View File

@ -223,6 +223,36 @@ void nghttp2_frame_altsvc_free(nghttp2_extension *frame, nghttp2_mem *mem) {
nghttp2_mem_free(mem, altsvc->origin);
}
void nghttp2_frame_origin_init(nghttp2_extension *frame,
nghttp2_origin_entry *ov, size_t nov) {
nghttp2_ext_origin *origin;
size_t payloadlen = 0;
size_t i;
for (i = 0; i < nov; ++i) {
payloadlen += 2 + ov[i].origin_len;
}
nghttp2_frame_hd_init(&frame->hd, payloadlen, NGHTTP2_ORIGIN,
NGHTTP2_FLAG_NONE, 0);
origin = frame->payload;
origin->ov = ov;
origin->nov = nov;
}
void nghttp2_frame_origin_free(nghttp2_extension *frame, nghttp2_mem *mem) {
nghttp2_ext_origin *origin;
origin = frame->payload;
if (origin == NULL) {
return;
}
/* We use the same buffer for all resources pointed by the field of
origin directly or indirectly. */
nghttp2_mem_free(mem, origin->ov);
}
size_t nghttp2_frame_priority_len(uint8_t flags) {
if (flags & NGHTTP2_FLAG_PRIORITY) {
return NGHTTP2_PRIORITY_SPECLEN;
@ -746,6 +776,106 @@ int nghttp2_frame_unpack_altsvc_payload2(nghttp2_extension *frame,
return 0;
}
int nghttp2_frame_pack_origin(nghttp2_bufs *bufs, nghttp2_extension *frame) {
nghttp2_buf *buf;
nghttp2_ext_origin *origin;
nghttp2_origin_entry *orig;
size_t i;
origin = frame->payload;
buf = &bufs->head->buf;
if (nghttp2_buf_avail(buf) < frame->hd.length) {
return NGHTTP2_ERR_FRAME_SIZE_ERROR;
}
buf->pos -= NGHTTP2_FRAME_HDLEN;
nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
for (i = 0; i < origin->nov; ++i) {
orig = &origin->ov[i];
nghttp2_put_uint16be(buf->last, (uint16_t)orig->origin_len);
buf->last += 2;
buf->last = nghttp2_cpymem(buf->last, orig->origin, orig->origin_len);
}
assert(nghttp2_buf_len(buf) == NGHTTP2_FRAME_HDLEN + frame->hd.length);
return 0;
}
int nghttp2_frame_unpack_origin_payload(nghttp2_extension *frame,
const uint8_t *payload,
size_t payloadlen, nghttp2_mem *mem) {
nghttp2_ext_origin *origin;
const uint8_t *p, *end;
uint8_t *dst;
size_t originlen;
nghttp2_origin_entry *ov;
size_t nov = 0;
size_t len = 0;
origin = frame->payload;
p = payload;
end = p + payloadlen;
for (; p != end;) {
if (end - p < 2) {
return NGHTTP2_ERR_FRAME_SIZE_ERROR;
}
originlen = nghttp2_get_uint16(p);
p += 2;
if (originlen == 0) {
continue;
}
if (originlen > (size_t)(end - p)) {
return NGHTTP2_ERR_FRAME_SIZE_ERROR;
}
p += originlen;
/* 1 for terminal NULL */
len += originlen + 1;
++nov;
}
if (nov == 0) {
origin->ov = NULL;
origin->nov = 0;
return 0;
}
len += nov * sizeof(nghttp2_origin_entry);
ov = nghttp2_mem_malloc(mem, len);
if (ov == NULL) {
return NGHTTP2_ERR_NOMEM;
}
origin->ov = ov;
origin->nov = nov;
dst = (uint8_t *)ov + nov * sizeof(nghttp2_origin_entry);
p = payload;
for (; p != end;) {
originlen = nghttp2_get_uint16(p);
p += 2;
if (originlen == 0) {
continue;
}
ov->origin = dst;
ov->origin_len = originlen;
dst = nghttp2_cpymem(dst, p, originlen);
*dst++ = '\0';
p += originlen;
++ov;
}
return 0;
}
nghttp2_settings_entry *nghttp2_frame_iv_copy(const nghttp2_settings_entry *iv,
size_t niv, nghttp2_mem *mem) {
nghttp2_settings_entry *iv_copy;

View File

@ -26,7 +26,7 @@
#define NGHTTP2_FRAME_H
#ifdef HAVE_CONFIG_H
#include <config.h>
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>
@ -72,6 +72,7 @@
/* Union of extension frame payload */
typedef union {
nghttp2_ext_altsvc altsvc;
nghttp2_ext_origin origin;
} nghttp2_ext_frame_payload;
void nghttp2_frame_pack_frame_hd(uint8_t *buf, const nghttp2_frame_hd *hd);
@ -392,6 +393,36 @@ int nghttp2_frame_unpack_altsvc_payload2(nghttp2_extension *frame,
const uint8_t *payload,
size_t payloadlen, nghttp2_mem *mem);
/*
* Packs ORIGIN frame |frame| in wire frame format and store it in
* |bufs|.
*
* The caller must make sure that nghttp2_bufs_reset(bufs) is called
* before calling this function.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_FRAME_SIZE_ERROR
* The length of the frame is too large.
*/
int nghttp2_frame_pack_origin(nghttp2_bufs *bufs, nghttp2_extension *ext);
/*
* Unpacks ORIGIN wire format into |frame|. The |payload| of length
* |payloadlen| contains the frame payload.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
* NGHTTP2_ERR_FRAME_SIZE_ERROR
* The payload is too small.
*/
int nghttp2_frame_unpack_origin_payload(nghttp2_extension *frame,
const uint8_t *payload,
size_t payloadlen, nghttp2_mem *mem);
/*
* Initializes HEADERS frame |frame| with given values. |frame| takes
* ownership of |nva|, so caller must not free it. If |stream_id| is
@ -489,6 +520,24 @@ void nghttp2_frame_altsvc_init(nghttp2_extension *frame, int32_t stream_id,
*/
void nghttp2_frame_altsvc_free(nghttp2_extension *frame, nghttp2_mem *mem);
/*
* Initializes ORIGIN frame |frame| with given values. This function
* assumes that frame->payload points to nghttp2_ext_origin object.
* Also |ov| and the memory pointed by the field of its elements are
* allocated in single buffer, starting with |ov|. On success, this
* function takes ownership of |ov|, so caller must not free it.
*/
void nghttp2_frame_origin_init(nghttp2_extension *frame,
nghttp2_origin_entry *ov, size_t nov);
/*
* Frees up resources under |frame|. This function does not free
* nghttp2_ext_origin object pointed by frame->payload. This function
* only frees nghttp2_ext_origin.ov. Therefore, other fields must be
* allocated in the same buffer with ov.
*/
void nghttp2_frame_origin_free(nghttp2_extension *frame, nghttp2_mem *mem);
/*
* Returns the number of padding bytes after payload. The total
* padding length is given in the |padlen|. The returned value does

View File

@ -26,7 +26,7 @@
#define NGHTTP2_HD_H
#ifdef HAVE_CONFIG_H
#include <config.h>
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>

View File

@ -26,7 +26,7 @@
#define NGHTTP2_HD_HUFFMAN_H
#ifdef HAVE_CONFIG_H
#include <config.h>
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>

View File

@ -26,7 +26,7 @@
#define NGHTTP2_HELPER_H
#ifdef HAVE_CONFIG_H
#include <config.h>
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <string.h>

View File

@ -26,7 +26,7 @@
#define NGHTTP2_HTTP_H
#ifdef HAVE_CONFIG_H
#include <config.h>
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>

View File

@ -26,7 +26,7 @@
#define NGHTTP2_INT_H
#ifdef HAVE_CONFIG_H
#include <config.h>
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>

View File

@ -26,7 +26,7 @@
#define NGHTTP2_MAP_H
#ifdef HAVE_CONFIG_H
#include <config.h>
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>

View File

@ -26,7 +26,7 @@
#define NGHTTP2_MEM_H
#ifdef HAVE_CONFIG_H
#include <config.h>
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>

View File

@ -26,15 +26,15 @@
#define NGHTTP2_NET_H
#ifdef HAVE_CONFIG_H
#include <config.h>
# include <config.h>
#endif /* HAVE_CONFIG_H */
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
# include <arpa/inet.h>
#endif /* HAVE_ARPA_INET_H */
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
# include <netinet/in.h>
#endif /* HAVE_NETINET_IN_H */
#include <nghttp2/nghttp2.h>
@ -44,11 +44,11 @@
define inline functions for those function so that we don't have
dependeny on that lib. */
#ifdef _MSC_VER
#define STIN static __inline
#else
#define STIN static inline
#endif
# ifdef _MSC_VER
# define STIN static __inline
# else
# define STIN static inline
# endif
STIN uint32_t htonl(uint32_t hostlong) {
uint32_t res;

View File

@ -26,7 +26,7 @@
#define NGHTTP2_NPN_H
#ifdef HAVE_CONFIG_H
#include <config.h>
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>

View File

@ -86,6 +86,10 @@ void nghttp2_option_set_builtin_recv_extension_type(nghttp2_option *option,
option->opt_set_mask |= NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES;
option->builtin_recv_ext_types |= NGHTTP2_TYPEMASK_ALTSVC;
return;
case NGHTTP2_ORIGIN:
option->opt_set_mask |= NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES;
option->builtin_recv_ext_types |= NGHTTP2_TYPEMASK_ORIGIN;
return;
default:
return;
}

View File

@ -26,7 +26,7 @@
#define NGHTTP2_OPTION_H
#ifdef HAVE_CONFIG_H
#include <config.h>
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>

View File

@ -86,6 +86,9 @@ void nghttp2_outbound_item_free(nghttp2_outbound_item *item, nghttp2_mem *mem) {
case NGHTTP2_ALTSVC:
nghttp2_frame_altsvc_free(&frame->ext, mem);
break;
case NGHTTP2_ORIGIN:
nghttp2_frame_origin_free(&frame->ext, mem);
break;
default:
assert(0);
break;

View File

@ -26,7 +26,7 @@
#define NGHTTP2_OUTBOUND_ITEM_H
#ifdef HAVE_CONFIG_H
#include <config.h>
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>

View File

@ -26,7 +26,7 @@
#define NGHTTP2_PQ_H
#ifdef HAVE_CONFIG_H
#include <config.h>
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>

View File

@ -26,7 +26,7 @@
#define NGHTTP2_PRIORITY_SPEC_H
#ifdef HAVE_CONFIG_H
#include <config.h>
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>

View File

@ -26,7 +26,7 @@
#define NGHTTP2_QUEUE_H
#ifdef HAVE_CONFIG_H
#include "config.h"
# include "config.h"
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>

View File

@ -26,7 +26,7 @@
#define NGHTTP2_RCBUF_H
#ifdef HAVE_CONFIG_H
#include <config.h>
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>

View File

@ -348,6 +348,12 @@ static void session_inbound_frame_reset(nghttp2_session *session) {
}
nghttp2_frame_altsvc_free(&iframe->frame.ext, mem);
break;
case NGHTTP2_ORIGIN:
if ((session->builtin_recv_ext_types & NGHTTP2_TYPEMASK_ORIGIN) == 0) {
break;
}
nghttp2_frame_origin_free(&iframe->frame.ext, mem);
break;
}
}
@ -1749,6 +1755,13 @@ static int session_predicate_altsvc_send(nghttp2_session *session,
return 0;
}
static int session_predicate_origin_send(nghttp2_session *session) {
if (session_is_closing(session)) {
return NGHTTP2_ERR_SESSION_CLOSING;
}
return 0;
}
/* Take into account settings max frame size and both connection-level
flow control here */
static ssize_t
@ -2280,6 +2293,18 @@ static int session_prep_frame(nghttp2_session *session,
nghttp2_frame_pack_altsvc(&session->aob.framebufs, &frame->ext);
return 0;
case NGHTTP2_ORIGIN:
rv = session_predicate_origin_send(session);
if (rv != 0) {
return rv;
}
rv = nghttp2_frame_pack_origin(&session->aob.framebufs, &frame->ext);
if (rv != 0) {
return rv;
}
return 0;
default:
/* Unreachable here */
@ -4385,6 +4410,12 @@ int nghttp2_session_on_settings_received(nghttp2_session *session,
return session_call_on_frame_received(session, frame);
}
if (!session->remote_settings_received) {
session->remote_settings.max_concurrent_streams =
NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS;
session->remote_settings_received = 1;
}
for (i = 0; i < frame->settings.niv; ++i) {
nghttp2_settings_entry *entry = &frame->settings.iv[i];
@ -4821,6 +4852,11 @@ int nghttp2_session_on_altsvc_received(nghttp2_session *session,
return session_call_on_frame_received(session, frame);
}
int nghttp2_session_on_origin_received(nghttp2_session *session,
nghttp2_frame *frame) {
return session_call_on_frame_received(session, frame);
}
static int session_process_altsvc_frame(nghttp2_session *session) {
nghttp2_inbound_frame *iframe = &session->iframe;
nghttp2_frame *frame = &iframe->frame;
@ -4836,6 +4872,25 @@ static int session_process_altsvc_frame(nghttp2_session *session) {
return nghttp2_session_on_altsvc_received(session, frame);
}
static int session_process_origin_frame(nghttp2_session *session) {
nghttp2_inbound_frame *iframe = &session->iframe;
nghttp2_frame *frame = &iframe->frame;
nghttp2_mem *mem = &session->mem;
int rv;
rv = nghttp2_frame_unpack_origin_payload(&frame->ext, iframe->lbuf.pos,
nghttp2_buf_len(&iframe->lbuf), mem);
if (rv != 0) {
if (nghttp2_is_fatal(rv)) {
return rv;
}
/* Ignore ORIGIN frame which cannot be parsed. */
return 0;
}
return nghttp2_session_on_origin_received(session, frame);
}
static int session_process_extension_frame(nghttp2_session *session) {
int rv;
nghttp2_inbound_frame *iframe = &session->iframe;
@ -5746,6 +5801,42 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
iframe->state = NGHTTP2_IB_READ_NBYTE;
inbound_frame_set_mark(iframe, 2);
break;
case NGHTTP2_ORIGIN:
if (!(session->builtin_recv_ext_types & NGHTTP2_TYPEMASK_ORIGIN)) {
busy = 1;
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
break;
}
DEBUGF("recv: ORIGIN\n");
iframe->frame.ext.payload = &iframe->ext_frame_payload.origin;
if (session->server || iframe->frame.hd.stream_id ||
(iframe->frame.hd.flags & 0xf0)) {
busy = 1;
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
break;
}
iframe->frame.hd.flags = NGHTTP2_FLAG_NONE;
if (iframe->payloadleft) {
iframe->raw_lbuf = nghttp2_mem_malloc(mem, iframe->payloadleft);
if (iframe->raw_lbuf == NULL) {
return NGHTTP2_ERR_NOMEM;
}
nghttp2_buf_wrap_init(&iframe->lbuf, iframe->raw_lbuf,
iframe->payloadleft);
} else {
busy = 1;
}
iframe->state = NGHTTP2_IB_READ_ORIGIN_PAYLOAD;
break;
default:
busy = 1;
@ -6583,7 +6674,6 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
DEBUGF("recv: [IB_READ_ALTSVC_PAYLOAD]\n");
readlen = inbound_frame_payload_readlen(iframe, in, last);
if (readlen > 0) {
iframe->lbuf.last = nghttp2_cpymem(iframe->lbuf.last, in, readlen);
@ -6601,11 +6691,44 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
}
rv = session_process_altsvc_frame(session);
if (nghttp2_is_fatal(rv)) {
return rv;
}
session_inbound_frame_reset(session);
break;
case NGHTTP2_IB_READ_ORIGIN_PAYLOAD:
DEBUGF("recv: [IB_READ_ORIGIN_PAYLOAD]\n");
readlen = inbound_frame_payload_readlen(iframe, in, last);
if (readlen > 0) {
iframe->lbuf.last = nghttp2_cpymem(iframe->lbuf.last, in, readlen);
iframe->payloadleft -= readlen;
in += readlen;
}
DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen,
iframe->payloadleft);
if (iframe->payloadleft) {
assert(nghttp2_buf_avail(&iframe->lbuf) > 0);
break;
}
rv = session_process_origin_frame(session);
if (nghttp2_is_fatal(rv)) {
return rv;
}
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (ssize_t)inlen;
}
session_inbound_frame_reset(session);
break;
@ -7085,12 +7208,42 @@ int nghttp2_session_set_stream_user_data(nghttp2_session *session,
int32_t stream_id,
void *stream_user_data) {
nghttp2_stream *stream;
nghttp2_frame *frame;
nghttp2_outbound_item *item;
stream = nghttp2_session_get_stream(session, stream_id);
if (!stream) {
if (stream) {
stream->stream_user_data = stream_user_data;
return 0;
}
if (session->server || !nghttp2_session_is_my_stream_id(session, stream_id) ||
!nghttp2_outbound_queue_top(&session->ob_syn)) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
stream->stream_user_data = stream_user_data;
return 0;
frame = &nghttp2_outbound_queue_top(&session->ob_syn)->frame;
assert(frame->hd.type == NGHTTP2_HEADERS);
if (frame->hd.stream_id > stream_id ||
(uint32_t)stream_id >= session->next_stream_id) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
for (item = session->ob_syn.head; item; item = item->qnext) {
if (item->frame.hd.stream_id < stream_id) {
continue;
}
if (item->frame.hd.stream_id > stream_id) {
break;
}
item->aux_data.headers.stream_user_data = stream_user_data;
return 0;
}
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
int nghttp2_session_resume_data(nghttp2_session *session, int32_t stream_id) {

View File

@ -26,7 +26,7 @@
#define NGHTTP2_SESSION_H
#ifdef HAVE_CONFIG_H
#include <config.h>
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>
@ -61,7 +61,8 @@ typedef enum {
*/
typedef enum {
NGHTTP2_TYPEMASK_NONE = 0,
NGHTTP2_TYPEMASK_ALTSVC = 1 << 0
NGHTTP2_TYPEMASK_ALTSVC = 1 << 0,
NGHTTP2_TYPEMASK_ORIGIN = 1 << 1
} nghttp2_typemask;
typedef enum {
@ -121,6 +122,7 @@ typedef enum {
NGHTTP2_IB_IGN_DATA,
NGHTTP2_IB_IGN_ALL,
NGHTTP2_IB_READ_ALTSVC_PAYLOAD,
NGHTTP2_IB_READ_ORIGIN_PAYLOAD,
NGHTTP2_IB_READ_EXTENSION_PAYLOAD
} nghttp2_inbound_state;
@ -301,8 +303,10 @@ struct nghttp2_session {
increased/decreased by submitting WINDOW_UPDATE. See
nghttp2_submit_window_update(). */
int32_t local_window_size;
/* Settings value received from the remote endpoint. We just use ID
as index. The index = 0 is unused. */
/* This flag is used to indicate that the local endpoint received initial
SETTINGS frame from the remote endpoint. */
uint8_t remote_settings_received;
/* Settings value received from the remote endpoint. */
nghttp2_settings_storage remote_settings;
/* Settings value of the local endpoint. */
nghttp2_settings_storage local_settings;
@ -698,7 +702,7 @@ int nghttp2_session_on_push_promise_received(nghttp2_session *session,
* NGHTTP2_ERR_NOMEM
* Out of memory.
* NGHTTP2_ERR_CALLBACK_FAILURE
* The callback function failed.
* The callback function failed.
* NGHTTP2_ERR_FLOODED
* There are too many items in outbound queue, and this is most
* likely caused by misbehaviour of peer.
@ -716,7 +720,7 @@ int nghttp2_session_on_ping_received(nghttp2_session *session,
* NGHTTP2_ERR_NOMEM
* Out of memory.
* NGHTTP2_ERR_CALLBACK_FAILURE
* The callback function failed.
* The callback function failed.
*/
int nghttp2_session_on_goaway_received(nghttp2_session *session,
nghttp2_frame *frame);
@ -731,7 +735,7 @@ int nghttp2_session_on_goaway_received(nghttp2_session *session,
* NGHTTP2_ERR_NOMEM
* Out of memory.
* NGHTTP2_ERR_CALLBACK_FAILURE
* The callback function failed.
* The callback function failed.
*/
int nghttp2_session_on_window_update_received(nghttp2_session *session,
nghttp2_frame *frame);
@ -744,11 +748,24 @@ int nghttp2_session_on_window_update_received(nghttp2_session *session,
* negative error codes:
*
* NGHTTP2_ERR_CALLBACK_FAILURE
* The callback function failed.
* The callback function failed.
*/
int nghttp2_session_on_altsvc_received(nghttp2_session *session,
nghttp2_frame *frame);
/*
* Called when ORIGIN is received, assuming |frame| is properly
* initialized.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_CALLBACK_FAILURE
* The callback function failed.
*/
int nghttp2_session_on_origin_received(nghttp2_session *session,
nghttp2_frame *frame);
/*
* Called when DATA is received, assuming |frame| is properly
* initialized.
@ -759,7 +776,7 @@ int nghttp2_session_on_altsvc_received(nghttp2_session *session,
* NGHTTP2_ERR_NOMEM
* Out of memory.
* NGHTTP2_ERR_CALLBACK_FAILURE
* The callback function failed.
* The callback function failed.
*/
int nghttp2_session_on_data_received(nghttp2_session *session,
nghttp2_frame *frame);

View File

@ -26,7 +26,7 @@
#define NGHTTP2_STREAM_H
#ifdef HAVE_CONFIG_H
#include <config.h>
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>

View File

@ -571,6 +571,89 @@ fail_item_malloc:
return rv;
}
int nghttp2_submit_origin(nghttp2_session *session, uint8_t flags,
const nghttp2_origin_entry *ov, size_t nov) {
nghttp2_mem *mem;
uint8_t *p;
nghttp2_outbound_item *item;
nghttp2_frame *frame;
nghttp2_ext_origin *origin;
nghttp2_origin_entry *ov_copy;
size_t len = 0;
size_t i;
int rv;
(void)flags;
mem = &session->mem;
if (!session->server) {
return NGHTTP2_ERR_INVALID_STATE;
}
if (nov) {
for (i = 0; i < nov; ++i) {
len += ov[i].origin_len;
}
if (2 * nov + len > NGHTTP2_MAX_PAYLOADLEN) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
/* The last nov is added for terminal NULL character. */
ov_copy =
nghttp2_mem_malloc(mem, nov * sizeof(nghttp2_origin_entry) + len + nov);
if (ov_copy == NULL) {
return NGHTTP2_ERR_NOMEM;
}
p = (uint8_t *)ov_copy + nov * sizeof(nghttp2_origin_entry);
for (i = 0; i < nov; ++i) {
ov_copy[i].origin = p;
ov_copy[i].origin_len = ov[i].origin_len;
p = nghttp2_cpymem(p, ov[i].origin, ov[i].origin_len);
*p++ = '\0';
}
assert((size_t)(p - (uint8_t *)ov_copy) ==
nov * sizeof(nghttp2_origin_entry) + len + nov);
} else {
ov_copy = NULL;
}
item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
if (item == NULL) {
rv = NGHTTP2_ERR_NOMEM;
goto fail_item_malloc;
}
nghttp2_outbound_item_init(item);
item->aux_data.ext.builtin = 1;
origin = &item->ext_frame_payload.origin;
frame = &item->frame;
frame->ext.payload = origin;
nghttp2_frame_origin_init(&frame->ext, ov_copy, nov);
rv = nghttp2_session_add_item(session, item);
if (rv != 0) {
nghttp2_frame_origin_free(&frame->ext, mem);
nghttp2_mem_free(mem, item);
return rv;
}
return 0;
fail_item_malloc:
free(ov_copy);
return rv;
}
static uint8_t set_request_flags(const nghttp2_priority_spec *pri_spec,
const nghttp2_data_provider *data_prd) {
uint8_t flags = NGHTTP2_FLAG_NONE;

View File

@ -26,7 +26,7 @@
#define NGHTTP2_SUBMIT_H
#ifdef HAVE_CONFIG_H
#include <config.h>
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>

View File

@ -23,7 +23,7 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>