Flesh our packing/unpacking
This commit is contained in:
parent
2a0cf7c8d8
commit
fbc1e17f7b
|
@ -763,6 +763,71 @@ int nghttp2_frame_unpack_altsvc_payload2(nghttp2_extension *frame,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_frame_pack_origin(nghttp2_bufs *bufs, nghttp2_extension *frame) {
|
||||
int rv;
|
||||
nghttp2_buf *buf;
|
||||
nghttp2_ext_origin *origin_frame;
|
||||
|
||||
origin_frame = frame->payload;
|
||||
|
||||
buf = &bufs->head->buf;
|
||||
|
||||
assert(nghttp2_buf_avail(buf) >= 2 + origin_frame->origin_len);
|
||||
|
||||
buf->pos -= NGHTTP2_FRAME_HDLEN;
|
||||
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
|
||||
|
||||
nghttp2_put_uint16be(buf->last, (uint16_t)origin_frame->origin_len);
|
||||
buf->last += 2;
|
||||
|
||||
rv = nghttp2_bufs_add(bufs, origin_frame->origin, origin_frame->origin_len);
|
||||
|
||||
assert(rv == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_origin_payload(nghttp2_extension *frame,
|
||||
size_t origin_len, uint8_t *payload,
|
||||
size_t payloadlen) {
|
||||
nghttp2_ext_origin *origin_frame;
|
||||
uint8_t *p;
|
||||
|
||||
origin_frame = frame->payload;
|
||||
p = payload;
|
||||
|
||||
origin_frame->origin = p;
|
||||
|
||||
p += origin_len;
|
||||
|
||||
origin_frame->origin_len = origin_len;
|
||||
}
|
||||
|
||||
int nghttp2_frame_unpack_origin_payload2(nghttp2_extension *frame,
|
||||
const uint8_t *payload,
|
||||
size_t payloadlen, nghttp2_mem *mem) {
|
||||
uint8_t *buf;
|
||||
size_t origin_len;
|
||||
|
||||
if (payloadlen < 2) {
|
||||
return NGHTTP2_FRAME_SIZE_ERROR;
|
||||
}
|
||||
|
||||
origin_len = nghttp2_get_uint16(payload);
|
||||
|
||||
buf = nghttp2_mem_malloc(mem, payloadlen - 2);
|
||||
if (!buf) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
nghttp2_cpymem(buf, payload + 2, payloadlen - 2);
|
||||
|
||||
nghttp2_frame_unpack_origin_payload(frame, origin_len, buf, payloadlen - 2);
|
||||
|
||||
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;
|
||||
|
|
|
@ -393,6 +393,45 @@ 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 always succeeds and returns 0.
|
||||
*/
|
||||
int nghttp2_frame_pack_origin(nghttp2_bufs *bufs, nghttp2_extension *ext);
|
||||
|
||||
/*
|
||||
* Unpacks ORIGIN wire format into |frame|. The |payload| of
|
||||
* |payloadlen| bytes contains frame payload. This function assumes
|
||||
* that frame->payload points to the nghttp2_ext_origin object.
|
||||
*
|
||||
* This function always succeeds and returns 0.
|
||||
*/
|
||||
void nghttp2_frame_unpack_origin_payload(nghttp2_extension *frame,
|
||||
size_t origin_len, uint8_t *payload,
|
||||
size_t payloadlen);
|
||||
|
||||
/*
|
||||
* Unpacks ORIGIN wire format into |frame|. This function only exists
|
||||
* for unit test. After allocating buffer for fields, this function
|
||||
* internally calls nghttp2_frame_unpack_origin_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_payload2(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
|
||||
|
|
|
@ -1745,6 +1745,29 @@ static int session_predicate_altsvc_send(nghttp2_session *session,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int session_predicate_origin_send(nghttp2_session *session,
|
||||
int32_t stream_id) {
|
||||
nghttp2_stream *stream;
|
||||
|
||||
if (session_is_closing(session)) {
|
||||
return NGHTTP2_ERR_SESSION_CLOSING;
|
||||
}
|
||||
|
||||
if (stream_id != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
stream = nghttp2_session_get_stream(session, stream_id);
|
||||
if (stream == NULL) {
|
||||
return NGHTTP2_ERR_STREAM_CLOSED;
|
||||
}
|
||||
if (stream->state == NGHTTP2_STREAM_CLOSING) {
|
||||
return NGHTTP2_ERR_STREAM_CLOSING;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Take into account settings max frame size and both connection-level
|
||||
flow control here */
|
||||
static ssize_t
|
||||
|
@ -2275,6 +2298,15 @@ 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, frame->hd.stream_id);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nghttp2_frame_pack_origin(&session->aob.framebufs, &frame->ext);
|
||||
|
||||
return 0;
|
||||
default:
|
||||
/* Unreachable here */
|
||||
|
@ -4833,6 +4865,46 @@ static int session_process_altsvc_frame(nghttp2_session *session) {
|
|||
return nghttp2_session_on_altsvc_received(session, frame);
|
||||
}
|
||||
|
||||
int nghttp2_session_on_origin_received(nghttp2_session *session,
|
||||
nghttp2_frame *frame) {
|
||||
nghttp2_ext_origin *origin_frame;
|
||||
nghttp2_stream *stream;
|
||||
|
||||
origin_frame = frame->ext.payload;
|
||||
|
||||
/* session->server case has been excluded */
|
||||
|
||||
if (frame->hd.stream_id == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
|
||||
if (!stream) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stream->state == NGHTTP2_STREAM_CLOSING) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return session_call_on_frame_received(session, frame);
|
||||
}
|
||||
|
||||
static int session_process_origin_frame(nghttp2_session *session) {
|
||||
nghttp2_inbound_frame *iframe = &session->iframe;
|
||||
nghttp2_frame *frame = &iframe->frame;
|
||||
|
||||
nghttp2_frame_unpack_origin_payload(
|
||||
&frame->ext, nghttp2_get_uint16(iframe->sbuf.pos), iframe->lbuf.pos,
|
||||
nghttp2_buf_len(&iframe->lbuf));
|
||||
|
||||
/* nghttp2_frame_unpack_altsvc_payload steals buffer from
|
||||
iframe->lbuf */
|
||||
nghttp2_buf_wrap_init(&iframe->lbuf, NULL, 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;
|
||||
|
@ -6031,6 +6103,37 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||
|
||||
break;
|
||||
}
|
||||
case NGHTTP2_ORIGIN: {
|
||||
size_t origin_len;
|
||||
|
||||
origin_len = nghttp2_get_uint16(iframe->sbuf.pos);
|
||||
|
||||
DEBUGF("recv: origin_len=%zu\n", origin_len);
|
||||
|
||||
if (2 + origin_len > iframe->payloadleft) {
|
||||
busy = 1;
|
||||
iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (iframe->frame.hd.length > 2) {
|
||||
iframe->raw_lbuf =
|
||||
nghttp2_mem_malloc(mem, iframe->frame.hd.length - 2);
|
||||
|
||||
if (iframe->raw_lbuf == NULL) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
nghttp2_buf_wrap_init(&iframe->lbuf, iframe->raw_lbuf,
|
||||
iframe->frame.hd.length);
|
||||
}
|
||||
|
||||
busy = 1;
|
||||
|
||||
iframe->state = NGHTTP2_IB_READ_ORIGIN_PAYLOAD;
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* This is unknown frame */
|
||||
session_inbound_frame_reset(session);
|
||||
|
@ -6584,6 +6687,36 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
session_inbound_frame_reset(session);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -122,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;
|
||||
|
||||
|
@ -738,7 +739,7 @@ int nghttp2_session_on_window_update_received(nghttp2_session *session,
|
|||
nghttp2_frame *frame);
|
||||
|
||||
/*
|
||||
* Called when ALTSVC is recieved, assuming |frame| is properly
|
||||
* Called when ALTSVC is received, assuming |frame| is properly
|
||||
* initialized.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
|
@ -750,6 +751,19 @@ int nghttp2_session_on_window_update_received(nghttp2_session *session,
|
|||
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.
|
||||
|
|
Loading…
Reference in New Issue