Commit 2ff3d97b authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa

Add nghttp2_frame_add_pad to deal with adding pads

parent 748f6e65
...@@ -647,3 +647,42 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv) ...@@ -647,3 +647,42 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv)
} }
return 1; return 1;
} }
ssize_t nghttp2_frame_add_pad(uint8_t **buf_ptr, size_t *buflen_ptr,
size_t *bufoff_ptr,
uint8_t *flags_ptr,
size_t payloadlen,
size_t payloadmax,
size_t align)
{
int rv;
size_t nextlen = nghttp2_min((payloadlen + align - 1) / align * align,
payloadmax);
size_t padlen = nextlen - payloadlen;
size_t trail_padlen = 0;
size_t headoff = 2;
size_t trail_padoff = headoff + NGHTTP2_FRAME_HEAD_LENGTH + payloadlen;
if(padlen > 257) {
headoff = 0;
trail_padlen = padlen - 2;
*flags_ptr |= NGHTTP2_FLAG_PAD_HIGH | NGHTTP2_FLAG_PAD_LOW;
(*buf_ptr)[NGHTTP2_FRAME_HEAD_LENGTH] = trail_padlen >> 8;
(*buf_ptr)[NGHTTP2_FRAME_HEAD_LENGTH + 1] = trail_padlen & 0xff;
} else if(padlen > 0) {
headoff = 1;
trail_padlen = padlen - 1;
*flags_ptr |= NGHTTP2_FLAG_PAD_LOW;
(*buf_ptr)[NGHTTP2_FRAME_HEAD_LENGTH + 1] = trail_padlen;
}
rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr,
trail_padoff + trail_padlen);
if(rv != 0) {
return rv;
}
memset((*buf_ptr) + trail_padoff, 0, trail_padlen);
*bufoff_ptr = headoff;
return padlen;
}
...@@ -492,4 +492,35 @@ void nghttp2_nv_array_del(nghttp2_nv *nva); ...@@ -492,4 +492,35 @@ void nghttp2_nv_array_del(nghttp2_nv *nva);
*/ */
int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv); int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv);
/*
* Add padding to the payload in the |*buf_ptr| of length
* |*buflen_ptr|. The payload length is given in |payloadlen|. The
* payload must start at offset NGHTTP2_FRAME_HEAD_LENGTH + 2 from
* |*buf_ptr| to account for PAD_HIGH and PAD_LOW. The maximum payload
* allowed is given in the |payloadmax|. The padding will not be made
* more than |payloadmax|. The padding alignment is given in the
* |align|.
*
* The |*flags_ptr| is updated to include NGHTTP2_FLAG_PAD_LOW and
* NGHTTP2_FLAG_PAD_HIGH based on the padding length. The
* |*bufoff_ptr| will have the offset starting the frame header in
* |*buf_ptr|.
*
* The |*buf_ptr| and |*buflen_ptr| may be extended to include padding
* bytes.
*
* This function returns the number of padding added to the payload
* including PAD_HIGH and PAD_LOW if it succeeds, or one of the
* following negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
ssize_t nghttp2_frame_add_pad(uint8_t **buf_ptr, size_t *buflen_ptr,
size_t *bufoff_ptr,
uint8_t *flags_ptr,
size_t payloadlen,
size_t payloadmax,
size_t align);
#endif /* NGHTTP2_FRAME_H */ #endif /* NGHTTP2_FRAME_H */
...@@ -4019,23 +4019,27 @@ ssize_t nghttp2_session_pack_data(nghttp2_session *session, ...@@ -4019,23 +4019,27 @@ ssize_t nghttp2_session_pack_data(nghttp2_session *session,
for padding. Based on the padding length, we adjust the starting for padding. Based on the padding length, we adjust the starting
offset of frame data. The starting offset is assigned into offset of frame data. The starting offset is assigned into
|*bufoff_ptr|. */ |*bufoff_ptr|. */
size_t headoff = 2; size_t payloadoff = NGHTTP2_FRAME_HEAD_LENGTH + 2;
size_t dataoff = NGHTTP2_FRAME_HEAD_LENGTH + headoff; ssize_t framelen = payloadoff + datamax;
ssize_t framelen = dataoff + datamax; ssize_t rv;
ssize_t r;
int eof_flags; int eof_flags;
uint8_t flags; uint8_t flags;
r = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, framelen); ssize_t payloadlen;
if(r != 0) {
return r; rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, framelen);
if(rv != 0) {
return rv;
} }
eof_flags = 0; eof_flags = 0;
r = frame->data_prd.read_callback payloadlen = frame->data_prd.read_callback
(session, frame->hd.stream_id, (*buf_ptr) + dataoff, datamax, (session, frame->hd.stream_id, (*buf_ptr) + payloadoff, datamax,
&eof_flags, &frame->data_prd.source, session->user_data); &eof_flags, &frame->data_prd.source, session->user_data);
if(r == NGHTTP2_ERR_DEFERRED || r == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
return r; if(payloadlen == NGHTTP2_ERR_DEFERRED ||
} else if(r < 0 || datamax < (size_t)r) { payloadlen == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
return payloadlen;
}
if(payloadlen < 0 || datamax < (size_t)payloadlen) {
/* This is the error code when callback is failed. */ /* This is the error code when callback is failed. */
return NGHTTP2_ERR_CALLBACK_FAILURE; return NGHTTP2_ERR_CALLBACK_FAILURE;
} }
...@@ -4046,37 +4050,27 @@ ssize_t nghttp2_session_pack_data(nghttp2_session *session, ...@@ -4046,37 +4050,27 @@ ssize_t nghttp2_session_pack_data(nghttp2_session *session,
flags = 0; flags = 0;
if((session->opt_flags & NGHTTP2_OPTMASK_NO_DATA_PADDING) == 0 && if((session->opt_flags & NGHTTP2_OPTMASK_NO_DATA_PADDING) == 0 &&
r > 0 && (size_t)r < datamax) { payloadlen > 0 && (size_t)payloadlen < datamax) {
const size_t align = session->data_pad_alignment; rv = nghttp2_frame_add_pad(buf_ptr, buflen_ptr, bufoff_ptr,
size_t nextlen = nghttp2_min((r + align - 1) / align * align, datamax); &flags, payloadlen, datamax,
size_t padlen = nextlen - r; session->data_pad_alignment);
size_t trail_padlen = 0; if(rv < 0) {
if(padlen > 257) { return rv;
headoff = 0;
trail_padlen = padlen - 2;
flags |= NGHTTP2_FLAG_PAD_HIGH | NGHTTP2_FLAG_PAD_LOW;
(*buf_ptr)[NGHTTP2_FRAME_HEAD_LENGTH] = trail_padlen >> 8;
(*buf_ptr)[NGHTTP2_FRAME_HEAD_LENGTH + 1] = trail_padlen & 0xff;
} else if(padlen > 0) {
headoff = 1;
trail_padlen = padlen - 1;
flags |= NGHTTP2_FLAG_PAD_LOW;
(*buf_ptr)[NGHTTP2_FRAME_HEAD_LENGTH + 1] = trail_padlen;
} }
frame->padlen = padlen; frame->padlen = rv;
memset((*buf_ptr) + dataoff + r, 0, trail_padlen); frame->hd.length = payloadlen + rv;
frame->hd.length = nextlen;
} else { } else {
*bufoff_ptr = 0;
frame->padlen = 0; frame->padlen = 0;
frame->hd.length = r; frame->hd.length = payloadlen;
} }
/* Set PAD flags so that we can supply frame to the callback with /* Set PAD flags so that we can supply frame to the callback with
the correct flags */ the correct flags */
frame->hd.flags |= flags; frame->hd.flags |= flags;
memset(*buf_ptr + headoff, 0, NGHTTP2_FRAME_HEAD_LENGTH); memset(*buf_ptr + *bufoff_ptr, 0, NGHTTP2_FRAME_HEAD_LENGTH);
nghttp2_put_uint16be(&(*buf_ptr)[headoff], frame->hd.length); nghttp2_put_uint16be(&(*buf_ptr)[*bufoff_ptr], frame->hd.length);
if(eof_flags) { if(eof_flags) {
frame->eof = 1; frame->eof = 1;
...@@ -4084,11 +4078,10 @@ ssize_t nghttp2_session_pack_data(nghttp2_session *session, ...@@ -4084,11 +4078,10 @@ ssize_t nghttp2_session_pack_data(nghttp2_session *session,
flags |= NGHTTP2_FLAG_END_STREAM; flags |= NGHTTP2_FLAG_END_STREAM;
} }
} }
(*buf_ptr)[headoff + 3] = flags; (*buf_ptr)[*bufoff_ptr + 3] = flags;
nghttp2_put_uint32be(&(*buf_ptr)[headoff + 4], frame->hd.stream_id); nghttp2_put_uint32be(&(*buf_ptr)[*bufoff_ptr + 4], frame->hd.stream_id);
*bufoff_ptr = headoff;
return frame->hd.length + NGHTTP2_FRAME_HEAD_LENGTH + headoff; return frame->hd.length + NGHTTP2_FRAME_HEAD_LENGTH + *bufoff_ptr;
} }
void* nghttp2_session_get_stream_user_data(nghttp2_session *session, void* nghttp2_session_get_stream_user_data(nghttp2_session *session,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment