void nghttp2_frame_pack_frame_hd(uint8_t *buf, const nghttp2_frame_hd *hd) { nghttp2_put_uint32be(&buf[0], (uint32_t)(hd->length << 8)); buf[3] = hd->type; buf[4] = hd->flags; nghttp2_put_uint32be(&buf[5], (uint32_t)hd->stream_id); /* ignore hd->reserved for now */ }
size_t nghttp2_frame_pack_settings_payload(uint8_t *buf, nghttp2_settings_entry *iv, size_t niv) { size_t i; for(i = 0; i < niv; ++i, buf += 8) { nghttp2_put_uint32be(buf, iv[i].settings_id); nghttp2_put_uint32be(buf + 4, iv[i].value); } return 8 * niv; }
ssize_t nghttp2_frame_pack_goaway(uint8_t **buf_ptr, size_t *buflen_ptr, nghttp2_goaway *frame) { ssize_t framelen = NGHTTP2_FRAME_HEAD_LENGTH + frame->hd.length; int rv; rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, framelen); if(rv != 0) { return rv; } memset(*buf_ptr, 0, framelen); nghttp2_frame_pack_frame_hd(*buf_ptr, &frame->hd); nghttp2_put_uint32be(&(*buf_ptr)[8], frame->last_stream_id); nghttp2_put_uint32be(&(*buf_ptr)[12], frame->error_code); memcpy(&(*buf_ptr)[16], frame->opaque_data, frame->opaque_data_len); return framelen; }
void nghttp2_frame_pack_frame_hd(uint8_t* buf, const nghttp2_frame_hd *hd) { nghttp2_put_uint16be(&buf[0], hd->length); buf[2]= hd->type; buf[3] = hd->flags; nghttp2_put_uint32be(&buf[4], hd->stream_id); }
ssize_t nghttp2_frame_pack_push_promise(uint8_t **buf_ptr, size_t *buflen_ptr, nghttp2_push_promise *frame, nghttp2_hd_context *deflater) { ssize_t framelen; size_t nv_offset = NGHTTP2_FRAME_HEAD_LENGTH + 4; ssize_t rv; rv = nghttp2_hd_deflate_hd(deflater, buf_ptr, buflen_ptr, nv_offset, frame->nva, frame->nvlen); if(rv < 0) { return rv; } framelen = rv + nv_offset; frame->hd.length = framelen - NGHTTP2_FRAME_HEAD_LENGTH; /* If frame->nvlen == 0, *buflen_ptr may be smaller than nv_offset */ rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, nv_offset); if(rv < 0) { return rv; } memset(*buf_ptr, 0, nv_offset); /* pack ctrl header after length is determined */ nghttp2_frame_pack_frame_hd(*buf_ptr, &frame->hd); nghttp2_put_uint32be(&(*buf_ptr)[8], frame->promised_stream_id); return framelen; }
ssize_t nghttp2_frame_pack_headers(uint8_t **buf_ptr, size_t *buflen_ptr, nghttp2_headers *frame, nghttp2_hd_context *deflater) { ssize_t framelen; size_t nv_offset = headers_nv_offset(frame); ssize_t rv; rv = nghttp2_hd_deflate_hd(deflater, buf_ptr, buflen_ptr, nv_offset, frame->nva, frame->nvlen); if(rv < 0) { return rv; } framelen = rv + nv_offset; frame->hd.length = framelen - NGHTTP2_FRAME_HEAD_LENGTH; /* If frame->nvlen == 0, *buflen_ptr may be smaller than nv_offset */ rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, nv_offset); if(rv < 0) { return rv; } memset(*buf_ptr, 0, nv_offset); /* pack ctrl header after length is determined */ nghttp2_frame_pack_frame_hd(*buf_ptr, &frame->hd); if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY) { nghttp2_put_uint32be(&(*buf_ptr)[8], frame->pri); } return framelen; }
size_t nghttp2_frame_pack_settings_payload(uint8_t *buf, const nghttp2_settings_entry *iv, size_t niv) { size_t i; for(i = 0; i < niv; ++i, buf += NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH) { buf[0] = iv[i].settings_id; nghttp2_put_uint32be(buf + 1, iv[i].value); } return NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH * niv; }
ssize_t nghttp2_frame_pack_window_update(uint8_t **buf_ptr, size_t *buflen_ptr, nghttp2_window_update *frame) { ssize_t framelen = NGHTTP2_FRAME_HEAD_LENGTH + 4; int rv; rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, framelen); if(rv != 0) { return rv; } memset(*buf_ptr, 0, framelen); nghttp2_frame_pack_frame_hd(*buf_ptr, &frame->hd); nghttp2_put_uint32be(&(*buf_ptr)[8], frame->window_size_increment); return framelen; }
ssize_t nghttp2_frame_pack_rst_stream(uint8_t **buf_ptr, size_t *buflen_ptr, nghttp2_rst_stream *frame) { ssize_t framelen = NGHTTP2_FRAME_HEAD_LENGTH + 4; int rv; rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, framelen); if(rv != 0) { return rv; } memset(*buf_ptr, 0, framelen); nghttp2_frame_pack_frame_hd(*buf_ptr, &frame->hd); nghttp2_put_uint32be(&(*buf_ptr)[8], frame->error_code); return framelen; }
ssize_t nghttp2_frame_pack_priority(uint8_t **buf_ptr, size_t *buflen_ptr, nghttp2_priority *frame) { ssize_t framelen= NGHTTP2_FRAME_HEAD_LENGTH + 4; int r; r = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, framelen); if(r != 0) { return r; } memset(*buf_ptr, 0, framelen); nghttp2_frame_pack_frame_hd(*buf_ptr, &frame->hd); nghttp2_put_uint32be(&(*buf_ptr)[8], frame->pri); return framelen; }
ssize_t nghttp2_frame_pack_headers(uint8_t **buf_ptr, size_t *buflen_ptr, size_t *bufoff_ptr, nghttp2_headers *frame, nghttp2_hd_deflater *deflater) { size_t payloadoff = NGHTTP2_FRAME_HEAD_LENGTH + 2; size_t nv_offset = payloadoff + nghttp2_frame_headers_payload_nv_offset(frame); ssize_t rv; size_t payloadlen; rv = nghttp2_hd_deflate_hd(deflater, buf_ptr, buflen_ptr, nv_offset, frame->nva, frame->nvlen); if(rv < 0) { return rv; } payloadlen = nghttp2_frame_headers_payload_nv_offset(frame) + rv; *bufoff_ptr = 2; frame->padlen = 0; frame->hd.length = payloadlen; /* If frame->nvlen == 0, *buflen_ptr may be smaller than nv_offset */ rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, nv_offset); if(rv < 0) { return rv; } memset(*buf_ptr + *bufoff_ptr, 0, NGHTTP2_FRAME_HEAD_LENGTH); /* pack ctrl header after length is determined */ if(NGHTTP2_MAX_FRAME_LENGTH < payloadlen) { /* Needs CONTINUATION */ nghttp2_frame_hd hd = frame->hd; hd.flags &= ~NGHTTP2_FLAG_END_HEADERS; hd.length = NGHTTP2_MAX_FRAME_LENGTH; nghttp2_frame_pack_frame_hd(*buf_ptr + *bufoff_ptr, &hd); } else { nghttp2_frame_pack_frame_hd(*buf_ptr + *bufoff_ptr, &frame->hd); } if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY) { nghttp2_put_uint32be(&(*buf_ptr)[payloadoff], frame->pri); } return *bufoff_ptr + NGHTTP2_FRAME_HEAD_LENGTH + frame->hd.length; }
void test_nghttp2_frame_pack_altsvc(void) { nghttp2_extension frame, oframe; nghttp2_ext_altsvc altsvc, oaltsvc; nghttp2_bufs bufs; nghttp2_buf *buf; size_t protocol_id_len, host_len, origin_len; uint8_t *protocol_id, *host, *origin; uint8_t *data; size_t datalen; int rv; size_t payloadlen; protocol_id_len = strlen("h2"); host_len = strlen("h2.example.org"); origin_len = strlen("www.example.org"); datalen = protocol_id_len + host_len + origin_len; data = malloc(datalen); memcpy(data, "h2", protocol_id_len); protocol_id = data; memcpy(data + protocol_id_len, "h2.example.org", host_len); host = data + protocol_id_len; memcpy(data + protocol_id_len + host_len, "http://www.example.org", origin_len); origin = data + protocol_id_len + host_len; 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); rv = nghttp2_frame_pack_altsvc(&bufs, &frame); CU_ASSERT(0 == rv); 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_EXT_ALTSVC, NGHTTP2_FLAG_NONE, 1000000007, &oframe.hd); CU_ASSERT(1u << 31 == oaltsvc.max_age); CU_ASSERT(4000 == oaltsvc.port); 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 == oaltsvc.host_len); CU_ASSERT(memcmp(host, oaltsvc.host, host_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; CU_ASSERT(buf->pos - buf->begin == 1); /* Check no origin case */ payloadlen = NGHTTP2_ALTSVC_MINLEN + protocol_id_len + host_len; nghttp2_put_uint32be(buf->pos, (uint32_t)((payloadlen << 8) + buf->pos[3])); oframe.payload = &oaltsvc; CU_ASSERT(0 == nghttp2_frame_unpack_altsvc_payload (&oframe, buf->pos + NGHTTP2_FRAME_HDLEN, NGHTTP2_ALTSVC_FIXED_PARTLEN, buf->pos + NGHTTP2_FRAME_HDLEN + NGHTTP2_ALTSVC_FIXED_PARTLEN, payloadlen - NGHTTP2_ALTSVC_FIXED_PARTLEN)); 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_uint32be(buf->pos, (uint32_t)((payloadlen << 8) + buf->pos[3])); oframe.payload = &oaltsvc; CU_ASSERT(NGHTTP2_ERR_FRAME_SIZE_ERROR == nghttp2_frame_unpack_altsvc_payload (&oframe, buf->pos + NGHTTP2_FRAME_HDLEN, NGHTTP2_ALTSVC_FIXED_PARTLEN, 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_uint32be(buf->pos, (uint32_t)((payloadlen << 8) + buf->pos[3])); 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, buf->pos + NGHTTP2_FRAME_HDLEN, NGHTTP2_ALTSVC_FIXED_PARTLEN, buf->pos + NGHTTP2_FRAME_HDLEN + NGHTTP2_ALTSVC_FIXED_PARTLEN, payloadlen - NGHTTP2_ALTSVC_FIXED_PARTLEN)); 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_uint32be(buf->pos, (uint32_t)((payloadlen << 8) + buf->pos[3])); oframe.payload = &oaltsvc; CU_ASSERT(NGHTTP2_ERR_FRAME_SIZE_ERROR == nghttp2_frame_unpack_altsvc_payload (&oframe, buf->pos + NGHTTP2_FRAME_HDLEN, NGHTTP2_ALTSVC_FIXED_PARTLEN, 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); }