Commit 43b23068 authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa

Introduce NGHTTP2_NV_FLAG_NO_COPY_NAME and NGHTTP2_NV_FLAG_NO_COPY_VALUE

parent cb73fa1d
......@@ -430,7 +430,19 @@ typedef enum {
* Header Field never Indexed" representation must be used in HPACK
* encoding). Other implementation calls this bit as "sensitive".
*/
NGHTTP2_NV_FLAG_NO_INDEX = 0x01
NGHTTP2_NV_FLAG_NO_INDEX = 0x01,
/**
* This flag is set solely by application. If this flag is set, the
* library does not make a copy of header field name. This could
* improve performance.
*/
NGHTTP2_NV_FLAG_NO_COPY_NAME = 0x02,
/**
* This flag is set solely by application. If this flag is set, the
* library does not make a copy of header field value. This could
* improve performance.
*/
NGHTTP2_NV_FLAG_NO_COPY_VALUE = 0x04
} nghttp2_nv_flag;
/**
......@@ -442,17 +454,27 @@ typedef struct {
/**
* The |name| byte string. If this struct is presented from library
* (e.g., :type:`nghttp2_on_frame_recv_callback`), |name| is
* guaranteed to be NULL-terminated. When application is
* constructing this struct, |name| is not required to be
* guaranteed to be NULL-terminated. For some callbacks
* (:type:`nghttp2_before_frame_send_callback`,
* :type:`nghttp2_on_frame_send_callback`, and
* :type:`nghttp2_on_frame_not_send_callback`), it may not be
* NULL-terminated if header field is passed from application with
* the flag :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME`). When application
* is constructing this struct, |name| is not required to be
* NULL-terminated.
*/
uint8_t *name;
/**
* The |value| byte string. If this struct is presented from
* library (e.g., :type:`nghttp2_on_frame_recv_callback`), |value|
* is guaranteed to be NULL-terminated. When application is
* constructing this struct, |value| is not required to be
* NULL-terminated.
* is guaranteed to be NULL-terminated. For some callbacks
* (:type:`nghttp2_before_frame_send_callback`,
* :type:`nghttp2_on_frame_send_callback`, and
* :type:`nghttp2_on_frame_not_send_callback`), it may not be
* NULL-terminated if header field is passed from application with
* the flag :enum:`NGHTTP2_NV_FLAG_NO_COPY_VALUE`). When
* application is constructing this struct, |value| is not required
* to be NULL-terminated.
*/
uint8_t *value;
/**
......@@ -2960,7 +2982,15 @@ nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec);
*
* This function creates copies of all name/value pairs in |nva|. It
* also lower-cases all names in |nva|. The order of elements in
* |nva| is preserved.
* |nva| is preserved. For header fields with
* :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME` and
* :enum:`NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, header field name
* and value are not copied respectively. With
* :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME`, application is responsible to
* pass header field name in lowercase. The application should
* maintain the references to them until
* :type:`nghttp2_on_frame_send_callback` or
* :type:`nghttp2_on_frame_not_send_callback` is called.
*
* HTTP/2 specification has requirement about header fields in the
* request HEADERS. See the specification for more details.
......@@ -3016,7 +3046,15 @@ NGHTTP2_EXTERN int32_t
*
* This function creates copies of all name/value pairs in |nva|. It
* also lower-cases all names in |nva|. The order of elements in
* |nva| is preserved.
* |nva| is preserved. For header fields with
* :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME` and
* :enum:`NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, header field name
* and value are not copied respectively. With
* :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME`, application is responsible to
* pass header field name in lowercase. The application should
* maintain the references to them until
* :type:`nghttp2_on_frame_send_callback` or
* :type:`nghttp2_on_frame_not_send_callback` is called.
*
* HTTP/2 specification has requirement about header fields in the
* response HEADERS. See the specification for more details.
......@@ -3073,7 +3111,15 @@ nghttp2_submit_response(nghttp2_session *session, int32_t stream_id,
*
* This function creates copies of all name/value pairs in |nva|. It
* also lower-cases all names in |nva|. The order of elements in
* |nva| is preserved.
* |nva| is preserved. For header fields with
* :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME` and
* :enum:`NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, header field name
* and value are not copied respectively. With
* :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME`, application is responsible to
* pass header field name in lowercase. The application should
* maintain the references to them until
* :type:`nghttp2_on_frame_send_callback` or
* :type:`nghttp2_on_frame_not_send_callback` is called.
*
* For server, trailer must be followed by response HEADERS or
* response DATA. The library does not check that response HEADERS
......@@ -3149,7 +3195,15 @@ NGHTTP2_EXTERN int nghttp2_submit_trailer(nghttp2_session *session,
*
* This function creates copies of all name/value pairs in |nva|. It
* also lower-cases all names in |nva|. The order of elements in
* |nva| is preserved.
* |nva| is preserved. For header fields with
* :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME` and
* :enum:`NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, header field name
* and value are not copied respectively. With
* :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME`, application is responsible to
* pass header field name in lowercase. The application should
* maintain the references to them until
* :type:`nghttp2_on_frame_send_callback` or
* :type:`nghttp2_on_frame_not_send_callback` is called.
*
* The |stream_user_data| is a pointer to an arbitrary data which is
* associated to the stream this frame will open. Therefore it is
......@@ -3347,7 +3401,15 @@ NGHTTP2_EXTERN int nghttp2_submit_settings(nghttp2_session *session,
*
* This function creates copies of all name/value pairs in |nva|. It
* also lower-cases all names in |nva|. The order of elements in
* |nva| is preserved.
* |nva| is preserved. For header fields with
* :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME` and
* :enum:`NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, header field name
* and value are not copied respectively. With
* :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME`, application is responsible to
* pass header field name in lowercase. The application should
* maintain the references to them until
* :type:`nghttp2_on_frame_send_callback` or
* :type:`nghttp2_on_frame_not_send_callback` is called.
*
* The |promised_stream_user_data| is a pointer to an arbitrary data
* which is associated to the promised stream this frame will open and
......
......@@ -741,21 +741,26 @@ void nghttp2_nv_array_sort(nghttp2_nv *nva, size_t nvlen) {
int nghttp2_nv_array_copy(nghttp2_nv **nva_ptr, const nghttp2_nv *nva,
size_t nvlen, nghttp2_mem *mem) {
size_t i;
uint8_t *data;
uint8_t *data = NULL;
size_t buflen = 0;
nghttp2_nv *p;
for (i = 0; i < nvlen; ++i) {
/* + 2 for null-termination */
buflen += nva[i].namelen + nva[i].valuelen + 2;
}
if (nvlen == 0) {
*nva_ptr = NULL;
return 0;
}
for (i = 0; i < nvlen; ++i) {
/* + 1 for null-termination */
if ((nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_NAME) == 0) {
buflen += nva[i].namelen + 1;
}
if ((nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_VALUE) == 0) {
buflen += nva[i].valuelen + 1;
}
}
buflen += sizeof(nghttp2_nv) * nvlen;
*nva_ptr = nghttp2_mem_malloc(mem, buflen);
......@@ -765,22 +770,37 @@ int nghttp2_nv_array_copy(nghttp2_nv **nva_ptr, const nghttp2_nv *nva,
}
p = *nva_ptr;
data = (uint8_t *)(*nva_ptr) + sizeof(nghttp2_nv) * nvlen;
if (buflen > sizeof(nghttp2_nv) * nvlen) {
data = (uint8_t *)(*nva_ptr) + sizeof(nghttp2_nv) * nvlen;
}
for (i = 0; i < nvlen; ++i) {
p->flags = nva[i].flags;
memcpy(data, nva[i].name, nva[i].namelen);
p->name = data;
p->namelen = nva[i].namelen;
data[p->namelen] = '\0';
nghttp2_downcase(p->name, p->namelen);
data += nva[i].namelen + 1;
memcpy(data, nva[i].value, nva[i].valuelen);
p->value = data;
p->valuelen = nva[i].valuelen;
data[p->valuelen] = '\0';
data += nva[i].valuelen + 1;
if (nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_NAME) {
p->name = nva[i].name;
p->namelen = nva[i].namelen;
} else {
memcpy(data, nva[i].name, nva[i].namelen);
p->name = data;
p->namelen = nva[i].namelen;
data[p->namelen] = '\0';
nghttp2_downcase(p->name, p->namelen);
data += nva[i].namelen + 1;
}
if (nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_VALUE) {
p->value = nva[i].value;
p->valuelen = nva[i].valuelen;
} else {
memcpy(data, nva[i].value, nva[i].valuelen);
p->value = data;
p->valuelen = nva[i].valuelen;
data[p->valuelen] = '\0';
data += nva[i].valuelen + 1;
}
++p;
}
return 0;
......
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