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:
Tatsuhiro Tsujikawa 2014-06-09 23:16:54 +09:00
parent 317b8baa4f
commit dacc9b2f1c
11 changed files with 267 additions and 148 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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