Separate extension frames from core frames
ALTSVC and BLOCKED frames are now extension frames. To add new extension frame without modifying nghttp2_frame union, which causes so name bump, we separated extension frames from core frames. nghttp2_frame includes generic nghttp2_extension. The payload member of nghttp2_extension will point to the structure of extension frame payload. The frame types of extension frames are defined in nghttp2_ext_frame_type.
This commit is contained in:
parent
317b8baa4f
commit
dacc9b2f1c
|
@ -396,7 +396,8 @@ typedef struct {
|
|||
|
||||
/**
|
||||
* @enum
|
||||
* The control frame types in HTTP/2.
|
||||
*
|
||||
* The frame types in HTTP/2 specification.
|
||||
*/
|
||||
typedef enum {
|
||||
/**
|
||||
|
@ -438,17 +439,28 @@ typedef enum {
|
|||
/**
|
||||
* The CONTINUATION frame.
|
||||
*/
|
||||
NGHTTP2_CONTINUATION = 0x09,
|
||||
/**
|
||||
* The ALTSVC frame.
|
||||
*/
|
||||
NGHTTP2_ALTSVC = 0x0a,
|
||||
/**
|
||||
* The BLOCKED frame.
|
||||
*/
|
||||
NGHTTP2_BLOCKED = 0x0b
|
||||
NGHTTP2_CONTINUATION = 0x09
|
||||
} nghttp2_frame_type;
|
||||
|
||||
/**
|
||||
* @enum
|
||||
*
|
||||
* The extension frame types.
|
||||
*
|
||||
* TODO: The assigned frame types were carried from draft-12, and now
|
||||
* actually TBD.
|
||||
*/
|
||||
typedef enum {
|
||||
/**
|
||||
* The ALTSVC extension frame.
|
||||
*/
|
||||
NGHTTP2_EXT_ALTSVC = 0x0a,
|
||||
/**
|
||||
* The BLOCKED extension frame.
|
||||
*/
|
||||
NGHTTP2_EXT_BLOCKED = 0x0b
|
||||
} nghttp2_ext_frame_type;
|
||||
|
||||
/**
|
||||
* @enum
|
||||
*
|
||||
|
@ -938,16 +950,30 @@ typedef struct {
|
|||
int32_t window_size_increment;
|
||||
} nghttp2_window_update;
|
||||
|
||||
/**
|
||||
* @struct
|
||||
*
|
||||
* The ALTSVC frame. It has following members:
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* The frame header.
|
||||
*/
|
||||
nghttp2_frame_hd hd;
|
||||
/**
|
||||
* The pointer to extension payload. The exact pointer type is
|
||||
* determined by hd.type.
|
||||
*
|
||||
* If hd.type == :enum:`NGHTTP2_EXT_ALTSVC`, it is a pointer to
|
||||
* :type:`nghttp2_ext_altsvc`.
|
||||
*
|
||||
* If hd.type == :enum:`NGHTTP2_EXT_BLOCKED`, it points to ``NULL``,
|
||||
* since BLOCKED extension frame has no payload.
|
||||
*/
|
||||
void *payload;
|
||||
} nghttp2_extension;
|
||||
|
||||
/**
|
||||
* @struct
|
||||
*
|
||||
* The ALTSVC extension frame payload. It has following members:
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* Protocol ID
|
||||
*/
|
||||
|
@ -980,19 +1006,7 @@ typedef struct {
|
|||
* Port
|
||||
*/
|
||||
uint16_t port;
|
||||
} nghttp2_altsvc;
|
||||
|
||||
/**
|
||||
* @struct
|
||||
*
|
||||
* The BLOCKED frame. It has following members:
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* The frame header.
|
||||
*/
|
||||
nghttp2_frame_hd hd;
|
||||
} nghttp2_blocked;
|
||||
} nghttp2_ext_altsvc;
|
||||
|
||||
/**
|
||||
* @union
|
||||
|
@ -1043,13 +1057,9 @@ typedef union {
|
|||
*/
|
||||
nghttp2_window_update window_update;
|
||||
/**
|
||||
* The ALTSVC frame.
|
||||
* The extension frame.
|
||||
*/
|
||||
nghttp2_altsvc altsvc;
|
||||
/**
|
||||
* The BLOCKED frame.
|
||||
*/
|
||||
nghttp2_blocked blocked;
|
||||
nghttp2_extension ext;
|
||||
} nghttp2_frame;
|
||||
|
||||
/**
|
||||
|
|
|
@ -186,7 +186,7 @@ void nghttp2_frame_window_update_init(nghttp2_window_update *frame,
|
|||
void nghttp2_frame_window_update_free(nghttp2_window_update *frame)
|
||||
{}
|
||||
|
||||
void nghttp2_frame_altsvc_init(nghttp2_altsvc *frame, int32_t stream_id,
|
||||
void nghttp2_frame_altsvc_init(nghttp2_extension *frame, int32_t stream_id,
|
||||
uint32_t max_age,
|
||||
uint16_t port,
|
||||
uint8_t *protocol_id,
|
||||
|
@ -195,34 +195,45 @@ void nghttp2_frame_altsvc_init(nghttp2_altsvc *frame, int32_t stream_id,
|
|||
uint8_t *origin, size_t origin_len)
|
||||
{
|
||||
size_t payloadlen;
|
||||
nghttp2_ext_altsvc *altsvc;
|
||||
|
||||
altsvc = frame->payload;
|
||||
|
||||
payloadlen = NGHTTP2_ALTSVC_MINLEN + protocol_id_len + host_len + origin_len;
|
||||
|
||||
frame_set_hd(&frame->hd, payloadlen, NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE,
|
||||
frame_set_hd(&frame->hd, payloadlen, NGHTTP2_EXT_ALTSVC, NGHTTP2_FLAG_NONE,
|
||||
stream_id);
|
||||
|
||||
frame->max_age = max_age;
|
||||
frame->port = port;
|
||||
frame->protocol_id = protocol_id;
|
||||
frame->protocol_id_len = protocol_id_len;
|
||||
frame->host = host;
|
||||
frame->host_len = host_len;
|
||||
frame->origin = origin;
|
||||
frame->origin_len = origin_len;
|
||||
altsvc->max_age = max_age;
|
||||
altsvc->port = port;
|
||||
altsvc->protocol_id = protocol_id;
|
||||
altsvc->protocol_id_len = protocol_id_len;
|
||||
altsvc->host = host;
|
||||
altsvc->host_len = host_len;
|
||||
altsvc->origin = origin;
|
||||
altsvc->origin_len = origin_len;
|
||||
}
|
||||
|
||||
void nghttp2_frame_altsvc_free(nghttp2_altsvc *frame)
|
||||
void nghttp2_frame_altsvc_free(nghttp2_extension *frame)
|
||||
{
|
||||
free(frame->protocol_id);
|
||||
nghttp2_ext_altsvc *altsvc;
|
||||
|
||||
altsvc = frame->payload;
|
||||
|
||||
if(altsvc == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
void nghttp2_frame_blocked_init(nghttp2_blocked *frame, int32_t stream_id)
|
||||
free(altsvc->protocol_id);
|
||||
}
|
||||
|
||||
void nghttp2_frame_blocked_init(nghttp2_extension *frame, int32_t stream_id)
|
||||
{
|
||||
frame_set_hd(&frame->hd, 0, NGHTTP2_BLOCKED, NGHTTP2_FLAG_NONE,
|
||||
frame_set_hd(&frame->hd, 0, NGHTTP2_EXT_BLOCKED, NGHTTP2_FLAG_NONE,
|
||||
stream_id);
|
||||
}
|
||||
|
||||
void nghttp2_frame_blocked_free(nghttp2_blocked *frame)
|
||||
void nghttp2_frame_blocked_free(nghttp2_extension *frame)
|
||||
{}
|
||||
|
||||
void nghttp2_frame_data_init(nghttp2_data *frame, nghttp2_private_data *pdata)
|
||||
|
@ -757,44 +768,47 @@ void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
|
|||
NGHTTP2_WINDOW_SIZE_INCREMENT_MASK;
|
||||
}
|
||||
|
||||
int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_altsvc *frame)
|
||||
int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *frame)
|
||||
{
|
||||
int rv;
|
||||
nghttp2_buf *buf;
|
||||
nghttp2_ext_altsvc *altsvc;
|
||||
|
||||
assert(bufs->head == bufs->cur);
|
||||
|
||||
altsvc = frame->payload;
|
||||
|
||||
buf = &bufs->head->buf;
|
||||
|
||||
buf->pos -= NGHTTP2_FRAME_HDLEN;
|
||||
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
|
||||
|
||||
nghttp2_put_uint32be(buf->last, frame->max_age);
|
||||
nghttp2_put_uint32be(buf->last, altsvc->max_age);
|
||||
buf->last += 4;
|
||||
|
||||
nghttp2_put_uint16be(buf->last, frame->port);
|
||||
nghttp2_put_uint16be(buf->last, altsvc->port);
|
||||
buf->last += 2;
|
||||
|
||||
buf->last[0] = frame->protocol_id_len;
|
||||
buf->last[0] = altsvc->protocol_id_len;
|
||||
++buf->last;
|
||||
|
||||
rv = nghttp2_bufs_add(bufs, frame->protocol_id, frame->protocol_id_len);
|
||||
rv = nghttp2_bufs_add(bufs, altsvc->protocol_id, altsvc->protocol_id_len);
|
||||
if(rv != 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rv = nghttp2_bufs_addb(bufs, frame->host_len);
|
||||
rv = nghttp2_bufs_addb(bufs, altsvc->host_len);
|
||||
if(rv != 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rv = nghttp2_bufs_add(bufs, frame->host, frame->host_len);
|
||||
rv = nghttp2_bufs_add(bufs, altsvc->host, altsvc->host_len);
|
||||
if(rv != 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rv = nghttp2_bufs_add(bufs, frame->origin, frame->origin_len);
|
||||
rv = nghttp2_bufs_add(bufs, altsvc->origin, altsvc->origin_len);
|
||||
if(rv != 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
@ -810,50 +824,53 @@ int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_altsvc *frame)
|
|||
return rv;
|
||||
}
|
||||
|
||||
int nghttp2_frame_unpack_altsvc_payload(nghttp2_altsvc *frame,
|
||||
int nghttp2_frame_unpack_altsvc_payload(nghttp2_extension *frame,
|
||||
const uint8_t *payload,
|
||||
size_t payloadlen,
|
||||
uint8_t *var_gift_payload,
|
||||
size_t var_gift_payloadlen)
|
||||
{
|
||||
nghttp2_buf buf;
|
||||
nghttp2_ext_altsvc *altsvc;
|
||||
|
||||
frame->max_age = nghttp2_get_uint32(payload);
|
||||
altsvc = frame->payload;
|
||||
|
||||
altsvc->max_age = nghttp2_get_uint32(payload);
|
||||
payload += 4;
|
||||
|
||||
frame->port = nghttp2_get_uint16(payload);
|
||||
altsvc->port = nghttp2_get_uint16(payload);
|
||||
payload += 2;
|
||||
|
||||
frame->protocol_id_len = *payload;
|
||||
altsvc->protocol_id_len = *payload;
|
||||
|
||||
nghttp2_buf_wrap_init(&buf, var_gift_payload, var_gift_payloadlen);
|
||||
buf.last += var_gift_payloadlen;
|
||||
|
||||
/* 1 for Host-Len */
|
||||
if(nghttp2_buf_len(&buf) < 1 + (ssize_t)frame->protocol_id_len) {
|
||||
if(nghttp2_buf_len(&buf) < 1 + (ssize_t)altsvc->protocol_id_len) {
|
||||
return NGHTTP2_ERR_FRAME_SIZE_ERROR;
|
||||
}
|
||||
|
||||
frame->protocol_id = buf.pos;
|
||||
buf.pos += frame->protocol_id_len;
|
||||
altsvc->protocol_id = buf.pos;
|
||||
buf.pos += altsvc->protocol_id_len;
|
||||
|
||||
frame->host_len = *buf.pos;
|
||||
altsvc->host_len = *buf.pos;
|
||||
++buf.pos;
|
||||
|
||||
if(nghttp2_buf_len(&buf) < (ssize_t)frame->host_len) {
|
||||
if(nghttp2_buf_len(&buf) < (ssize_t)altsvc->host_len) {
|
||||
return NGHTTP2_ERR_FRAME_SIZE_ERROR;
|
||||
}
|
||||
|
||||
frame->host = buf.pos;
|
||||
buf.pos += frame->host_len;
|
||||
altsvc->host = buf.pos;
|
||||
buf.pos += altsvc->host_len;
|
||||
|
||||
frame->origin = buf.pos;
|
||||
frame->origin_len = nghttp2_buf_len(&buf);
|
||||
altsvc->origin = buf.pos;
|
||||
altsvc->origin_len = nghttp2_buf_len(&buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_frame_pack_blocked(nghttp2_bufs *bufs, nghttp2_blocked *frame)
|
||||
int nghttp2_frame_pack_blocked(nghttp2_bufs *bufs, nghttp2_extension *frame)
|
||||
{
|
||||
nghttp2_buf *buf;
|
||||
|
||||
|
|
|
@ -66,11 +66,10 @@
|
|||
Max-Age, Port and Proto-Len. */
|
||||
#define NGHTTP2_ALTSVC_FIXED_PARTLEN 7
|
||||
|
||||
/* Minimum length of ALTSVC frame. NGHTTP2_ALTSVC_FIXED_PARTLEN +
|
||||
Host-Len. */
|
||||
/* Minimum length of ALTSVC extension frame payload.
|
||||
NGHTTP2_ALTSVC_FIXED_PARTLEN + Host-Len. */
|
||||
#define NGHTTP2_ALTSVC_MINLEN 8
|
||||
|
||||
|
||||
/* Category of frames. */
|
||||
typedef enum {
|
||||
/* non-DATA frame */
|
||||
|
@ -79,6 +78,11 @@ typedef enum {
|
|||
NGHTTP2_CAT_DATA
|
||||
} nghttp2_frame_category;
|
||||
|
||||
/* Union of extension frame payload */
|
||||
typedef union {
|
||||
nghttp2_ext_altsvc altsvc;
|
||||
} nghttp2_ext_frame_payload;
|
||||
|
||||
/**
|
||||
* @struct
|
||||
*
|
||||
|
@ -402,6 +406,9 @@ void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
|
|||
* The caller must make sure that nghttp2_bufs_reset(bufs) is called
|
||||
* before calling this function.
|
||||
*
|
||||
* The caller must make sure that frame->payload points to
|
||||
* nghttp2_ext_altsvc object.
|
||||
*
|
||||
* This function returns 0 if it succeeds or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
|
@ -410,7 +417,7 @@ void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
|
|||
* NGHTTP2_ERR_FRAME_SIZE_ERROR
|
||||
* The length of the frame is too large.
|
||||
*/
|
||||
int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_altsvc *frame);
|
||||
int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *frame);
|
||||
|
||||
|
||||
/*
|
||||
|
@ -421,13 +428,16 @@ int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_altsvc *frame);
|
|||
* and then |frame|. The |var_gift_payloadlen| must be freed by
|
||||
* nghttp2_frame_altsvc_free().
|
||||
*
|
||||
* The caller must make sure that frame->payload points to
|
||||
* nghttp2_ext_altsvc object.
|
||||
*
|
||||
* This function returns 0 if it succeeds or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_FRAME_SIZE_ERROR
|
||||
* The |var_gift_payload| does not contain required data.
|
||||
*/
|
||||
int nghttp2_frame_unpack_altsvc_payload(nghttp2_altsvc *frame,
|
||||
int nghttp2_frame_unpack_altsvc_payload(nghttp2_extension *frame,
|
||||
const uint8_t *payload,
|
||||
size_t payloadlen,
|
||||
uint8_t *var_gift_payload,
|
||||
|
@ -441,7 +451,7 @@ int nghttp2_frame_unpack_altsvc_payload(nghttp2_altsvc *frame,
|
|||
*
|
||||
* This function always returns 0.
|
||||
*/
|
||||
int nghttp2_frame_pack_blocked(nghttp2_bufs *bufs, nghttp2_blocked *frame);
|
||||
int nghttp2_frame_pack_blocked(nghttp2_bufs *bufs, nghttp2_extension *frame);
|
||||
|
||||
/*
|
||||
* Initializes HEADERS frame |frame| with given values. |frame| takes
|
||||
|
@ -524,7 +534,7 @@ void nghttp2_frame_window_update_free(nghttp2_window_update *frame);
|
|||
|protocol_id_len| == 0 and |host_len| + |origin_len| > 0. If
|
||||
|protocol_id_len|, |host_len| and |origin_len| are all zero,
|
||||
|protocol_id| can be NULL. */
|
||||
void nghttp2_frame_altsvc_init(nghttp2_altsvc *frame, int32_t stream_id,
|
||||
void nghttp2_frame_altsvc_init(nghttp2_extension *frame, int32_t stream_id,
|
||||
uint32_t max_age,
|
||||
uint16_t port,
|
||||
uint8_t *protocol_id,
|
||||
|
@ -532,11 +542,15 @@ void nghttp2_frame_altsvc_init(nghttp2_altsvc *frame, int32_t stream_id,
|
|||
uint8_t *host, size_t host_len,
|
||||
uint8_t *origin, size_t origin_len);
|
||||
|
||||
void nghttp2_frame_altsvc_free(nghttp2_altsvc *frame);
|
||||
/*
|
||||
* Frees resources used by |frame|. This function does not free
|
||||
* frame->payload itself.
|
||||
*/
|
||||
void nghttp2_frame_altsvc_free(nghttp2_extension *frame);
|
||||
|
||||
void nghttp2_frame_blocked_init(nghttp2_blocked *frame, int32_t stream_id);
|
||||
void nghttp2_frame_blocked_init(nghttp2_extension *frame, int32_t stream_id);
|
||||
|
||||
void nghttp2_frame_blocked_free(nghttp2_blocked *frame);
|
||||
void nghttp2_frame_blocked_free(nghttp2_extension *frame);
|
||||
|
||||
void nghttp2_frame_data_init(nghttp2_data *frame, nghttp2_private_data *pdata);
|
||||
|
||||
|
|
|
@ -62,8 +62,9 @@ void nghttp2_outbound_item_free(nghttp2_outbound_item *item)
|
|||
case NGHTTP2_WINDOW_UPDATE:
|
||||
nghttp2_frame_window_update_free(&frame->window_update);
|
||||
break;
|
||||
case NGHTTP2_ALTSVC:
|
||||
nghttp2_frame_altsvc_free(&frame->altsvc);
|
||||
case NGHTTP2_EXT_ALTSVC:
|
||||
nghttp2_frame_altsvc_free(&frame->ext);
|
||||
free(frame->ext.payload);
|
||||
break;
|
||||
}
|
||||
} else if(item->frame_cat == NGHTTP2_CAT_DATA) {
|
||||
|
|
|
@ -230,14 +230,16 @@ static void session_inbound_frame_reset(nghttp2_session *session)
|
|||
case NGHTTP2_WINDOW_UPDATE:
|
||||
nghttp2_frame_window_update_free(&iframe->frame.window_update);
|
||||
break;
|
||||
case NGHTTP2_ALTSVC:
|
||||
nghttp2_frame_altsvc_free(&iframe->frame.altsvc);
|
||||
case NGHTTP2_EXT_ALTSVC:
|
||||
nghttp2_frame_altsvc_free(&iframe->frame.ext);
|
||||
break;
|
||||
case NGHTTP2_BLOCKED:
|
||||
nghttp2_frame_blocked_free(&iframe->frame.blocked);
|
||||
case NGHTTP2_EXT_BLOCKED:
|
||||
nghttp2_frame_blocked_free(&iframe->frame.ext);
|
||||
break;
|
||||
}
|
||||
|
||||
memset(&iframe->frame, 0, sizeof(nghttp2_frame));
|
||||
memset(&iframe->ext_frame_payload, 0, sizeof(nghttp2_ext_frame_payload));
|
||||
|
||||
iframe->state = NGHTTP2_IB_READ_HEAD;
|
||||
|
||||
|
@ -1504,12 +1506,14 @@ static int session_add_blocked(nghttp2_session *session, int32_t stream_id)
|
|||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
nghttp2_frame_blocked_init(&frame->blocked, stream_id);
|
||||
frame->ext.payload = NULL;
|
||||
|
||||
nghttp2_frame_blocked_init(&frame->ext, stream_id);
|
||||
|
||||
rv = nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, NULL);
|
||||
|
||||
if(rv != 0) {
|
||||
nghttp2_frame_blocked_free(&frame->blocked);
|
||||
nghttp2_frame_blocked_free(&frame->ext);
|
||||
free(frame);
|
||||
|
||||
return rv;
|
||||
|
@ -1751,28 +1755,28 @@ static int session_prep_frame(nghttp2_session *session,
|
|||
return framerv;
|
||||
}
|
||||
break;
|
||||
case NGHTTP2_ALTSVC:
|
||||
case NGHTTP2_EXT_ALTSVC:
|
||||
rv = session_predicate_altsvc_send(session, frame->hd.stream_id);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
framerv = nghttp2_frame_pack_altsvc(&session->aob.framebufs,
|
||||
&frame->altsvc);
|
||||
&frame->ext);
|
||||
|
||||
if(framerv < 0) {
|
||||
return framerv;
|
||||
}
|
||||
|
||||
break;
|
||||
case NGHTTP2_BLOCKED:
|
||||
case NGHTTP2_EXT_BLOCKED:
|
||||
rv = session_predicate_blocked_send(session, frame->hd.stream_id);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
framerv = nghttp2_frame_pack_blocked(&session->aob.framebufs,
|
||||
&frame->blocked);
|
||||
&frame->ext);
|
||||
|
||||
if(framerv < 0) {
|
||||
return framerv;
|
||||
|
@ -3650,7 +3654,9 @@ static int session_process_altsvc_frame(nghttp2_session *session)
|
|||
nghttp2_frame *frame = &iframe->frame;
|
||||
int rv;
|
||||
|
||||
rv = nghttp2_frame_unpack_altsvc_payload(&frame->altsvc,
|
||||
frame->ext.payload = &iframe->ext_frame_payload;
|
||||
|
||||
rv = nghttp2_frame_unpack_altsvc_payload(&frame->ext,
|
||||
iframe->sbuf.pos,
|
||||
nghttp2_buf_len(&iframe->sbuf),
|
||||
iframe->lbuf.pos,
|
||||
|
@ -3677,6 +3683,8 @@ static int session_process_blocked_frame(nghttp2_session *session)
|
|||
nghttp2_inbound_frame *iframe = &session->iframe;
|
||||
nghttp2_frame *frame = &iframe->frame;
|
||||
|
||||
frame->ext.payload = NULL;
|
||||
|
||||
return nghttp2_session_on_blocked_received(session, frame);
|
||||
}
|
||||
|
||||
|
@ -4463,7 +4471,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
|
|||
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
|
||||
|
||||
break;
|
||||
case NGHTTP2_ALTSVC:
|
||||
case NGHTTP2_EXT_ALTSVC:
|
||||
DEBUGF(fprintf(stderr, "recv: ALTSVC\n"));
|
||||
|
||||
iframe->frame.hd.flags = NGHTTP2_FLAG_NONE;
|
||||
|
@ -4494,7 +4502,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
|
|||
inbound_frame_set_mark(iframe, NGHTTP2_ALTSVC_FIXED_PARTLEN);
|
||||
|
||||
break;
|
||||
case NGHTTP2_BLOCKED:
|
||||
case NGHTTP2_EXT_BLOCKED:
|
||||
DEBUGF(fprintf(stderr, "recv: BLOCKED\n"));
|
||||
|
||||
iframe->frame.hd.flags = NGHTTP2_FLAG_NONE;
|
||||
|
@ -4694,7 +4702,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
|
|||
session_inbound_frame_reset(session);
|
||||
|
||||
break;
|
||||
case NGHTTP2_ALTSVC: {
|
||||
case NGHTTP2_EXT_ALTSVC: {
|
||||
size_t varlen;
|
||||
|
||||
varlen = iframe->frame.hd.length - NGHTTP2_ALTSVC_FIXED_PARTLEN;
|
||||
|
|
|
@ -83,6 +83,9 @@ typedef enum {
|
|||
|
||||
typedef struct {
|
||||
nghttp2_frame frame;
|
||||
/* Storage for extension frame payload. frame->ext.payload points
|
||||
to this structure to avoid frequent memory allocation. */
|
||||
nghttp2_ext_frame_payload ext_frame_payload;
|
||||
/* The received SETTINGS entry. The protocol says that we only cares
|
||||
about the defined settings ID. If unknown ID is received, it is
|
||||
subject to connection error */
|
||||
|
|
|
@ -379,6 +379,7 @@ int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags,
|
|||
size_t varlen;
|
||||
uint8_t *var, *varp;
|
||||
nghttp2_frame *frame;
|
||||
nghttp2_ext_altsvc *altsvc;
|
||||
uint8_t *copy_protocol_id, *copy_host, *copy_origin;
|
||||
|
||||
if(!session->server) {
|
||||
|
@ -392,6 +393,14 @@ int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags,
|
|||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
altsvc = malloc(sizeof(nghttp2_ext_altsvc));
|
||||
|
||||
if(altsvc == NULL) {
|
||||
rv = NGHTTP2_ERR_NOMEM;
|
||||
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if(varlen == 0) {
|
||||
var = NULL;
|
||||
copy_protocol_id = NULL;
|
||||
|
@ -401,7 +410,9 @@ int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags,
|
|||
var = malloc(varlen);
|
||||
|
||||
if(var == NULL) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
rv = NGHTTP2_ERR_NOMEM;
|
||||
|
||||
goto var_alloc_fail;
|
||||
}
|
||||
|
||||
varp = var;
|
||||
|
@ -424,25 +435,37 @@ int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags,
|
|||
frame = malloc(sizeof(nghttp2_frame));
|
||||
|
||||
if(frame == NULL) {
|
||||
free(var);
|
||||
rv = NGHTTP2_ERR_NOMEM;
|
||||
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
goto frame_alloc_fail;
|
||||
}
|
||||
|
||||
nghttp2_frame_altsvc_init(&frame->altsvc, stream_id, max_age, port,
|
||||
frame->ext.payload = altsvc;
|
||||
|
||||
nghttp2_frame_altsvc_init(&frame->ext, stream_id, max_age, port,
|
||||
copy_protocol_id, protocol_id_len,
|
||||
copy_host, host_len, copy_origin, origin_len);
|
||||
|
||||
rv = nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, NULL);
|
||||
|
||||
if(rv != 0) {
|
||||
nghttp2_frame_altsvc_free(&frame->altsvc);
|
||||
nghttp2_frame_altsvc_free(&frame->ext);
|
||||
free(frame);
|
||||
free(altsvc);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
frame_alloc_fail:
|
||||
free(var);
|
||||
|
||||
var_alloc_fail:
|
||||
free(altsvc);
|
||||
|
||||
fail:
|
||||
return rv;
|
||||
}
|
||||
|
||||
static uint8_t set_request_flags(const nghttp2_priority_spec *pri_spec,
|
||||
|
|
|
@ -127,9 +127,9 @@ const char* strframetype(uint8_t type)
|
|||
return "GOAWAY";
|
||||
case NGHTTP2_WINDOW_UPDATE:
|
||||
return "WINDOW_UPDATE";
|
||||
case NGHTTP2_ALTSVC:
|
||||
case NGHTTP2_EXT_ALTSVC:
|
||||
return "ALTSVC";
|
||||
case NGHTTP2_BLOCKED:
|
||||
case NGHTTP2_EXT_BLOCKED:
|
||||
return "BLOCKED";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
|
@ -427,25 +427,34 @@ void print_frame(print_type ptype, const nghttp2_frame *frame)
|
|||
fprintf(outfile, "(window_size_increment=%d)\n",
|
||||
frame->window_update.window_size_increment);
|
||||
break;
|
||||
case NGHTTP2_ALTSVC:
|
||||
case NGHTTP2_EXT_ALTSVC: {
|
||||
print_frame_attr_indent();
|
||||
|
||||
auto altsvc = static_cast<const nghttp2_ext_altsvc*>(frame->ext.payload);
|
||||
|
||||
fprintf(outfile, "(max-age=%u, port=%u, protocol_id=",
|
||||
frame->altsvc.max_age, frame->altsvc.port);
|
||||
if(frame->altsvc.protocol_id_len) {
|
||||
fwrite(frame->altsvc.protocol_id, frame->altsvc.protocol_id_len, 1,
|
||||
outfile);
|
||||
altsvc->max_age, altsvc->port);
|
||||
|
||||
if(altsvc->protocol_id_len) {
|
||||
fwrite(altsvc->protocol_id, altsvc->protocol_id_len, 1, outfile);
|
||||
}
|
||||
|
||||
fprintf(outfile, ", host=");
|
||||
if(frame->altsvc.host_len) {
|
||||
fwrite(frame->altsvc.host, frame->altsvc.host_len, 1, outfile);
|
||||
|
||||
if(altsvc->host_len) {
|
||||
fwrite(altsvc->host, altsvc->host_len, 1, outfile);
|
||||
}
|
||||
|
||||
fprintf(outfile, ", origin=");
|
||||
if(frame->altsvc.origin_len) {
|
||||
fwrite(frame->altsvc.origin, frame->altsvc.origin_len, 1, outfile);
|
||||
|
||||
if(altsvc->origin_len) {
|
||||
fwrite(altsvc->origin, altsvc->origin_len, 1, outfile);
|
||||
}
|
||||
|
||||
fprintf(outfile, ")\n");
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -435,7 +435,8 @@ void test_nghttp2_frame_pack_window_update(void)
|
|||
|
||||
void test_nghttp2_frame_pack_altsvc(void)
|
||||
{
|
||||
nghttp2_altsvc frame, oframe;
|
||||
nghttp2_extension frame, oframe;
|
||||
nghttp2_ext_altsvc altsvc, oaltsvc;
|
||||
nghttp2_bufs bufs;
|
||||
nghttp2_buf *buf;
|
||||
size_t protocol_id_len, host_len, origin_len;
|
||||
|
@ -464,6 +465,8 @@ void test_nghttp2_frame_pack_altsvc(void)
|
|||
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
frame.payload = &altsvc;
|
||||
|
||||
nghttp2_frame_altsvc_init(&frame, 1000000007, 1u << 31, 4000,
|
||||
protocol_id, protocol_id_len,
|
||||
host, host_len, origin, origin_len);
|
||||
|
@ -475,27 +478,30 @@ void test_nghttp2_frame_pack_altsvc(void)
|
|||
CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + NGHTTP2_ALTSVC_MINLEN + datalen) ==
|
||||
nghttp2_bufs_len(&bufs));
|
||||
|
||||
oframe.payload = &oaltsvc;
|
||||
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &bufs));
|
||||
|
||||
check_frame_header(NGHTTP2_ALTSVC_MINLEN + datalen,
|
||||
NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE,
|
||||
NGHTTP2_EXT_ALTSVC, NGHTTP2_FLAG_NONE,
|
||||
1000000007, &oframe.hd);
|
||||
CU_ASSERT(1u << 31 == oframe.max_age);
|
||||
CU_ASSERT(4000 == oframe.port);
|
||||
CU_ASSERT(1u << 31 == oaltsvc.max_age);
|
||||
CU_ASSERT(4000 == oaltsvc.port);
|
||||
|
||||
CU_ASSERT(protocol_id_len == oframe.protocol_id_len);
|
||||
CU_ASSERT(memcmp(protocol_id, oframe.protocol_id, protocol_id_len) == 0);
|
||||
CU_ASSERT(protocol_id_len == oaltsvc.protocol_id_len);
|
||||
CU_ASSERT(memcmp(protocol_id, oaltsvc.protocol_id, protocol_id_len) == 0);
|
||||
|
||||
CU_ASSERT(host_len == oframe.host_len);
|
||||
CU_ASSERT(memcmp(host, oframe.host, host_len) == 0);
|
||||
CU_ASSERT(host_len == oaltsvc.host_len);
|
||||
CU_ASSERT(memcmp(host, oaltsvc.host, host_len) == 0);
|
||||
|
||||
CU_ASSERT(origin_len == oframe.origin_len);
|
||||
CU_ASSERT(memcmp(origin, oframe.origin, origin_len) == 0);
|
||||
CU_ASSERT(origin_len == oaltsvc.origin_len);
|
||||
CU_ASSERT(memcmp(origin, oaltsvc.origin, origin_len) == 0);
|
||||
|
||||
nghttp2_frame_altsvc_free(&oframe);
|
||||
nghttp2_frame_altsvc_free(&frame);
|
||||
|
||||
memset(&oframe, 0, sizeof(oframe));
|
||||
memset(&oaltsvc, 0, sizeof(oaltsvc));
|
||||
|
||||
buf = &bufs.head->buf;
|
||||
|
||||
|
@ -506,6 +512,8 @@ void test_nghttp2_frame_pack_altsvc(void)
|
|||
payloadlen = NGHTTP2_ALTSVC_MINLEN + protocol_id_len + host_len;
|
||||
nghttp2_put_uint16be(buf->pos, payloadlen);
|
||||
|
||||
oframe.payload = &oaltsvc;
|
||||
|
||||
CU_ASSERT(0 ==
|
||||
nghttp2_frame_unpack_altsvc_payload
|
||||
(&oframe,
|
||||
|
@ -514,13 +522,19 @@ void test_nghttp2_frame_pack_altsvc(void)
|
|||
buf->pos + NGHTTP2_FRAME_HDLEN + NGHTTP2_ALTSVC_FIXED_PARTLEN,
|
||||
payloadlen - NGHTTP2_ALTSVC_FIXED_PARTLEN));
|
||||
|
||||
CU_ASSERT(host_len == oframe.host_len);
|
||||
CU_ASSERT(0 == oframe.origin_len);
|
||||
CU_ASSERT(protocol_id_len == oaltsvc.protocol_id_len);
|
||||
CU_ASSERT(host_len == oaltsvc.host_len);
|
||||
CU_ASSERT(0 == oaltsvc.origin_len);
|
||||
|
||||
memset(&oframe, 0, sizeof(oframe));
|
||||
memset(&oaltsvc, 0, sizeof(oaltsvc));
|
||||
|
||||
/* Check insufficient payload length for host */
|
||||
payloadlen = NGHTTP2_ALTSVC_MINLEN + protocol_id_len + host_len - 1;
|
||||
nghttp2_put_uint16be(buf->pos, payloadlen);
|
||||
|
||||
oframe.payload = &oaltsvc;
|
||||
|
||||
CU_ASSERT(NGHTTP2_ERR_FRAME_SIZE_ERROR ==
|
||||
nghttp2_frame_unpack_altsvc_payload
|
||||
(&oframe,
|
||||
|
@ -529,12 +543,17 @@ void test_nghttp2_frame_pack_altsvc(void)
|
|||
buf->pos + NGHTTP2_FRAME_HDLEN + NGHTTP2_ALTSVC_FIXED_PARTLEN,
|
||||
payloadlen - NGHTTP2_ALTSVC_FIXED_PARTLEN));
|
||||
|
||||
memset(&oframe, 0, sizeof(oframe));
|
||||
memset(&oaltsvc, 0, sizeof(oaltsvc));
|
||||
|
||||
/* Check no host case */
|
||||
payloadlen = NGHTTP2_ALTSVC_MINLEN + protocol_id_len;
|
||||
nghttp2_put_uint16be(buf->pos, payloadlen);
|
||||
buf->pos[NGHTTP2_FRAME_HDLEN + NGHTTP2_ALTSVC_FIXED_PARTLEN
|
||||
+ protocol_id_len] = 0;
|
||||
|
||||
oframe.payload = &oaltsvc;
|
||||
|
||||
CU_ASSERT(0 ==
|
||||
nghttp2_frame_unpack_altsvc_payload
|
||||
(&oframe,
|
||||
|
@ -543,13 +562,19 @@ void test_nghttp2_frame_pack_altsvc(void)
|
|||
buf->pos + NGHTTP2_FRAME_HDLEN + NGHTTP2_ALTSVC_FIXED_PARTLEN,
|
||||
payloadlen - NGHTTP2_ALTSVC_FIXED_PARTLEN));
|
||||
|
||||
CU_ASSERT(0 == oframe.host_len);
|
||||
CU_ASSERT(0 == oframe.origin_len);
|
||||
CU_ASSERT(protocol_id_len == oaltsvc.protocol_id_len);
|
||||
CU_ASSERT(0 == oaltsvc.host_len);
|
||||
CU_ASSERT(0 == oaltsvc.origin_len);
|
||||
|
||||
memset(&oframe, 0, sizeof(oframe));
|
||||
memset(&oaltsvc, 0, sizeof(oaltsvc));
|
||||
|
||||
/* Check missing Host-Len */
|
||||
payloadlen = NGHTTP2_ALTSVC_FIXED_PARTLEN + protocol_id_len;
|
||||
nghttp2_put_uint16be(buf->pos, payloadlen);
|
||||
|
||||
oframe.payload = &oaltsvc;
|
||||
|
||||
CU_ASSERT(NGHTTP2_ERR_FRAME_SIZE_ERROR ==
|
||||
nghttp2_frame_unpack_altsvc_payload
|
||||
(&oframe,
|
||||
|
@ -558,6 +583,9 @@ void test_nghttp2_frame_pack_altsvc(void)
|
|||
buf->pos + NGHTTP2_FRAME_HDLEN + NGHTTP2_ALTSVC_FIXED_PARTLEN,
|
||||
payloadlen - NGHTTP2_ALTSVC_FIXED_PARTLEN));
|
||||
|
||||
memset(&oframe, 0, sizeof(oframe));
|
||||
memset(&oaltsvc, 0, sizeof(oaltsvc));
|
||||
|
||||
nghttp2_bufs_free(&bufs);
|
||||
}
|
||||
|
||||
|
|
|
@ -57,11 +57,11 @@ typedef struct {
|
|||
accumulator *acc;
|
||||
scripted_data_feed *df;
|
||||
int frame_recv_cb_called, invalid_frame_recv_cb_called;
|
||||
nghttp2_frame_type recv_frame_type;
|
||||
uint8_t recv_frame_type;
|
||||
int frame_send_cb_called;
|
||||
nghttp2_frame_type sent_frame_type;
|
||||
uint8_t sent_frame_type;
|
||||
int frame_not_send_cb_called;
|
||||
nghttp2_frame_type not_sent_frame_type;
|
||||
uint8_t not_sent_frame_type;
|
||||
int not_sent_error;
|
||||
int stream_close_cb_called;
|
||||
size_t data_source_length;
|
||||
|
@ -1055,6 +1055,7 @@ void test_nghttp2_session_recv_altsvc(void)
|
|||
nghttp2_session *session;
|
||||
nghttp2_session_callbacks callbacks;
|
||||
nghttp2_frame frame;
|
||||
nghttp2_ext_altsvc altsvc;
|
||||
size_t protocol_id_len, host_len, origin_len;
|
||||
uint8_t *protocol_id, *host, *origin;
|
||||
uint8_t *data;
|
||||
|
@ -1087,16 +1088,18 @@ void test_nghttp2_session_recv_altsvc(void)
|
|||
"http://www.example.org", origin_len);
|
||||
origin = data + protocol_id_len + host_len;
|
||||
|
||||
nghttp2_frame_altsvc_init(&frame.altsvc, 1000000007, 1u << 31, 4000,
|
||||
frame.ext.payload = &altsvc;
|
||||
|
||||
nghttp2_frame_altsvc_init(&frame.ext, 1000000007, 1u << 31, 4000,
|
||||
protocol_id, protocol_id_len,
|
||||
host, host_len, origin, origin_len);
|
||||
|
||||
rv = nghttp2_frame_pack_altsvc(&bufs, &frame.altsvc);
|
||||
rv = nghttp2_frame_pack_altsvc(&bufs, &frame.ext);
|
||||
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
|
||||
|
||||
nghttp2_frame_altsvc_free(&frame.altsvc);
|
||||
nghttp2_frame_altsvc_free(&frame.ext);
|
||||
|
||||
buf = &bufs.head->buf;
|
||||
assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
|
||||
|
@ -1124,7 +1127,7 @@ void test_nghttp2_session_recv_altsvc(void)
|
|||
|
||||
CU_ASSERT(rv == nghttp2_buf_len(buf));
|
||||
CU_ASSERT(1 == ud.frame_recv_cb_called);
|
||||
CU_ASSERT(NGHTTP2_ALTSVC == ud.recv_frame_type);
|
||||
CU_ASSERT(NGHTTP2_EXT_ALTSVC == ud.recv_frame_type);
|
||||
|
||||
/* premature payload */
|
||||
nghttp2_put_uint16be(buf->pos, 8);
|
||||
|
@ -3529,6 +3532,7 @@ void test_nghttp2_submit_altsvc(void)
|
|||
const char host[] = "localhost";
|
||||
const char origin[] = "http://localhost/";
|
||||
nghttp2_frame *frame;
|
||||
nghttp2_ext_altsvc *altsvc;
|
||||
nghttp2_outbound_item *item;
|
||||
my_user_data ud;
|
||||
|
||||
|
@ -3564,28 +3568,30 @@ void test_nghttp2_submit_altsvc(void)
|
|||
|
||||
frame = OB_CTRL(item);
|
||||
|
||||
CU_ASSERT(NGHTTP2_ALTSVC == frame->hd.type);
|
||||
CU_ASSERT(NGHTTP2_EXT_ALTSVC == frame->hd.type);
|
||||
CU_ASSERT(9 == frame->hd.stream_id);
|
||||
|
||||
CU_ASSERT(12345 == frame->altsvc.max_age);
|
||||
CU_ASSERT(3000 == frame->altsvc.port);
|
||||
altsvc = frame->ext.payload;
|
||||
|
||||
CU_ASSERT(strlen(protocol_id) == frame->altsvc.protocol_id_len);
|
||||
CU_ASSERT(strlen(host) == frame->altsvc.host_len);
|
||||
CU_ASSERT(strlen(origin) == frame->altsvc.origin_len);
|
||||
CU_ASSERT(12345 == altsvc->max_age);
|
||||
CU_ASSERT(3000 == altsvc->port);
|
||||
|
||||
CU_ASSERT(0 == memcmp(protocol_id, frame->altsvc.protocol_id,
|
||||
frame->altsvc.protocol_id_len));
|
||||
CU_ASSERT(0 == memcmp(host, frame->altsvc.host, frame->altsvc.host_len));
|
||||
CU_ASSERT(0 == memcmp(origin, frame->altsvc.origin,
|
||||
frame->altsvc.origin_len));
|
||||
CU_ASSERT(strlen(protocol_id) == altsvc->protocol_id_len);
|
||||
CU_ASSERT(strlen(host) == altsvc->host_len);
|
||||
CU_ASSERT(strlen(origin) == altsvc->origin_len);
|
||||
|
||||
CU_ASSERT(0 == memcmp(protocol_id, altsvc->protocol_id,
|
||||
altsvc->protocol_id_len));
|
||||
CU_ASSERT(0 == memcmp(host, altsvc->host, altsvc->host_len));
|
||||
CU_ASSERT(0 == memcmp(origin, altsvc->origin,
|
||||
altsvc->origin_len));
|
||||
|
||||
ud.frame_send_cb_called = 0;
|
||||
|
||||
CU_ASSERT(0 == nghttp2_session_send(session));
|
||||
|
||||
CU_ASSERT(1 == ud.frame_send_cb_called);
|
||||
CU_ASSERT(NGHTTP2_ALTSVC == ud.sent_frame_type);
|
||||
CU_ASSERT(NGHTTP2_EXT_ALTSVC == ud.sent_frame_type);
|
||||
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ int unpack_frame(nghttp2_frame *frame, const uint8_t *in, size_t len)
|
|||
nghttp2_frame_unpack_window_update_payload
|
||||
(&frame->window_update, payload, payloadlen);
|
||||
break;
|
||||
case NGHTTP2_ALTSVC:
|
||||
case NGHTTP2_EXT_ALTSVC:
|
||||
gift_payloadlen = payloadlen - NGHTTP2_ALTSVC_FIXED_PARTLEN;
|
||||
gift_payload = malloc(gift_payloadlen);
|
||||
|
||||
|
@ -95,7 +95,7 @@ int unpack_frame(nghttp2_frame *frame, const uint8_t *in, size_t len)
|
|||
|
||||
payloadlen -= NGHTTP2_ALTSVC_FIXED_PARTLEN;
|
||||
|
||||
rv = nghttp2_frame_unpack_altsvc_payload(&frame->altsvc,
|
||||
rv = nghttp2_frame_unpack_altsvc_payload(&frame->ext,
|
||||
payload, payloadlen,
|
||||
gift_payload, gift_payloadlen);
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue