From 2ff3d97b2ef1c935ee596a3702292ebd84675705 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sat, 8 Feb 2014 17:46:21 +0900 Subject: [PATCH] Add nghttp2_frame_add_pad to deal with adding pads --- lib/nghttp2_frame.c | 39 ++++++++++++++++++++++++ lib/nghttp2_frame.h | 31 +++++++++++++++++++ lib/nghttp2_session.c | 69 +++++++++++++++++++------------------------ 3 files changed, 101 insertions(+), 38 deletions(-) diff --git a/lib/nghttp2_frame.c b/lib/nghttp2_frame.c index b0b29b47..be1fc177 100644 --- a/lib/nghttp2_frame.c +++ b/lib/nghttp2_frame.c @@ -647,3 +647,42 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv) } 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; +} diff --git a/lib/nghttp2_frame.h b/lib/nghttp2_frame.h index 79e4b089..b9224fd4 100644 --- a/lib/nghttp2_frame.h +++ b/lib/nghttp2_frame.h @@ -492,4 +492,35 @@ void nghttp2_nv_array_del(nghttp2_nv *nva); */ 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 */ diff --git a/lib/nghttp2_session.c b/lib/nghttp2_session.c index 3cdc1b97..2b518a7e 100644 --- a/lib/nghttp2_session.c +++ b/lib/nghttp2_session.c @@ -4019,23 +4019,27 @@ ssize_t nghttp2_session_pack_data(nghttp2_session *session, for padding. Based on the padding length, we adjust the starting offset of frame data. The starting offset is assigned into |*bufoff_ptr|. */ - size_t headoff = 2; - size_t dataoff = NGHTTP2_FRAME_HEAD_LENGTH + headoff; - ssize_t framelen = dataoff + datamax; - ssize_t r; + size_t payloadoff = NGHTTP2_FRAME_HEAD_LENGTH + 2; + ssize_t framelen = payloadoff + datamax; + ssize_t rv; int eof_flags; uint8_t flags; - r = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, framelen); - if(r != 0) { - return r; + ssize_t payloadlen; + + rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, framelen); + if(rv != 0) { + return rv; } eof_flags = 0; - r = frame->data_prd.read_callback - (session, frame->hd.stream_id, (*buf_ptr) + dataoff, datamax, + payloadlen = frame->data_prd.read_callback + (session, frame->hd.stream_id, (*buf_ptr) + payloadoff, datamax, &eof_flags, &frame->data_prd.source, session->user_data); - if(r == NGHTTP2_ERR_DEFERRED || r == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - return r; - } else if(r < 0 || datamax < (size_t)r) { + + if(payloadlen == NGHTTP2_ERR_DEFERRED || + payloadlen == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { + return payloadlen; + } + if(payloadlen < 0 || datamax < (size_t)payloadlen) { /* This is the error code when callback is failed. */ return NGHTTP2_ERR_CALLBACK_FAILURE; } @@ -4046,37 +4050,27 @@ ssize_t nghttp2_session_pack_data(nghttp2_session *session, flags = 0; if((session->opt_flags & NGHTTP2_OPTMASK_NO_DATA_PADDING) == 0 && - r > 0 && (size_t)r < datamax) { - const size_t align = session->data_pad_alignment; - size_t nextlen = nghttp2_min((r + align - 1) / align * align, datamax); - size_t padlen = nextlen - r; - size_t trail_padlen = 0; - if(padlen > 257) { - 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; + payloadlen > 0 && (size_t)payloadlen < datamax) { + rv = nghttp2_frame_add_pad(buf_ptr, buflen_ptr, bufoff_ptr, + &flags, payloadlen, datamax, + session->data_pad_alignment); + if(rv < 0) { + return rv; } - frame->padlen = padlen; - memset((*buf_ptr) + dataoff + r, 0, trail_padlen); - frame->hd.length = nextlen; + frame->padlen = rv; + frame->hd.length = payloadlen + rv; } else { + *bufoff_ptr = 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 the correct flags */ frame->hd.flags |= flags; - memset(*buf_ptr + headoff, 0, NGHTTP2_FRAME_HEAD_LENGTH); - nghttp2_put_uint16be(&(*buf_ptr)[headoff], frame->hd.length); + memset(*buf_ptr + *bufoff_ptr, 0, NGHTTP2_FRAME_HEAD_LENGTH); + nghttp2_put_uint16be(&(*buf_ptr)[*bufoff_ptr], frame->hd.length); if(eof_flags) { frame->eof = 1; @@ -4084,11 +4078,10 @@ ssize_t nghttp2_session_pack_data(nghttp2_session *session, flags |= NGHTTP2_FLAG_END_STREAM; } } - (*buf_ptr)[headoff + 3] = flags; - nghttp2_put_uint32be(&(*buf_ptr)[headoff + 4], frame->hd.stream_id); - *bufoff_ptr = headoff; + (*buf_ptr)[*bufoff_ptr + 3] = flags; + nghttp2_put_uint32be(&(*buf_ptr)[*bufoff_ptr + 4], frame->hd.stream_id); - 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,