mirror of https://github.com/nodejs/node.git
deps: update nghttp3 to 1.10.1
This commit is contained in:
parent
3b111eb3f5
commit
5da29ecec4
|
@ -2106,7 +2106,7 @@ NGHTTP3_EXTERN int nghttp3_conn_bind_qpack_streams(nghttp3_conn *conn,
|
||||||
* control credit (both stream and connection) of underlying QUIC
|
* control credit (both stream and connection) of underlying QUIC
|
||||||
* connection by that amount. It does not include the amount of data
|
* connection by that amount. It does not include the amount of data
|
||||||
* carried by DATA frame which contains application data (excluding
|
* carried by DATA frame which contains application data (excluding
|
||||||
* any control or QPACK unidirectional streams) . See
|
* any control or QPACK unidirectional streams). See
|
||||||
* :type:`nghttp3_recv_data` to handle those bytes. If |fin| is
|
* :type:`nghttp3_recv_data` to handle those bytes. If |fin| is
|
||||||
* nonzero, this is the last data from remote endpoint in this stream.
|
* nonzero, this is the last data from remote endpoint in this stream.
|
||||||
*
|
*
|
||||||
|
@ -2480,8 +2480,6 @@ typedef struct nghttp3_data_reader {
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
* negative error codes:
|
* negative error codes:
|
||||||
*
|
*
|
||||||
* :macro:`NGHTTP3_ERR_INVALID_ARGUMENT`
|
|
||||||
* |stream_id| identifies unidirectional stream.
|
|
||||||
* :macro:`NGHTTP3_ERR_CONN_CLOSING`
|
* :macro:`NGHTTP3_ERR_CONN_CLOSING`
|
||||||
* Connection is shutting down, and no new stream is allowed.
|
* Connection is shutting down, and no new stream is allowed.
|
||||||
* :macro:`NGHTTP3_ERR_STREAM_IN_USE`
|
* :macro:`NGHTTP3_ERR_STREAM_IN_USE`
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
*
|
*
|
||||||
* Version number of the nghttp3 library release.
|
* Version number of the nghttp3 library release.
|
||||||
*/
|
*/
|
||||||
#define NGHTTP3_VERSION "1.6.0"
|
#define NGHTTP3_VERSION "1.10.1"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @macro
|
* @macro
|
||||||
|
@ -41,6 +41,6 @@
|
||||||
* number, 8 bits for minor and 8 bits for patch. Version 1.2.3
|
* number, 8 bits for minor and 8 bits for patch. Version 1.2.3
|
||||||
* becomes 0x010203.
|
* becomes 0x010203.
|
||||||
*/
|
*/
|
||||||
#define NGHTTP3_VERSION_NUM 0x010600
|
#define NGHTTP3_VERSION_NUM 0x010a01
|
||||||
|
|
||||||
#endif /* !defined(NGHTTP3_VERSION_H) */
|
#endif /* !defined(NGHTTP3_VERSION_H) */
|
||||||
|
|
|
@ -50,6 +50,10 @@ size_t nghttp3_buf_cap(const nghttp3_buf *buf) {
|
||||||
return (size_t)(buf->end - buf->begin);
|
return (size_t)(buf->end - buf->begin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t nghttp3_buf_offset(const nghttp3_buf *buf) {
|
||||||
|
return (size_t)(buf->pos - buf->begin);
|
||||||
|
}
|
||||||
|
|
||||||
void nghttp3_buf_reset(nghttp3_buf *buf) { buf->pos = buf->last = buf->begin; }
|
void nghttp3_buf_reset(nghttp3_buf *buf) { buf->pos = buf->last = buf->begin; }
|
||||||
|
|
||||||
int nghttp3_buf_reserve(nghttp3_buf *buf, size_t size, const nghttp3_mem *mem) {
|
int nghttp3_buf_reserve(nghttp3_buf *buf, size_t size, const nghttp3_mem *mem) {
|
||||||
|
@ -87,4 +91,12 @@ void nghttp3_typed_buf_init(nghttp3_typed_buf *tbuf, const nghttp3_buf *buf,
|
||||||
nghttp3_buf_type type) {
|
nghttp3_buf_type type) {
|
||||||
tbuf->buf = *buf;
|
tbuf->buf = *buf;
|
||||||
tbuf->type = type;
|
tbuf->type = type;
|
||||||
|
tbuf->buf.begin = tbuf->buf.pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nghttp3_typed_buf_shared_init(nghttp3_typed_buf *tbuf,
|
||||||
|
const nghttp3_buf *chunk) {
|
||||||
|
tbuf->buf = *chunk;
|
||||||
|
tbuf->type = NGHTTP3_BUF_TYPE_SHARED;
|
||||||
|
tbuf->buf.begin = tbuf->buf.pos = tbuf->buf.last;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,12 @@ void nghttp3_buf_wrap_init(nghttp3_buf *buf, uint8_t *src, size_t len);
|
||||||
*/
|
*/
|
||||||
size_t nghttp3_buf_cap(const nghttp3_buf *buf);
|
size_t nghttp3_buf_cap(const nghttp3_buf *buf);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* nghttp3_buf_offset returns the distance from tbuf->begin to
|
||||||
|
* tbuf->pos. In other words, it returns buf->pos - buf->begin.
|
||||||
|
*/
|
||||||
|
size_t nghttp3_buf_offset(const nghttp3_buf *buf);
|
||||||
|
|
||||||
int nghttp3_buf_reserve(nghttp3_buf *buf, size_t size, const nghttp3_mem *mem);
|
int nghttp3_buf_reserve(nghttp3_buf *buf, size_t size, const nghttp3_mem *mem);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -69,6 +75,13 @@ typedef struct nghttp3_typed_buf {
|
||||||
void nghttp3_typed_buf_init(nghttp3_typed_buf *tbuf, const nghttp3_buf *buf,
|
void nghttp3_typed_buf_init(nghttp3_typed_buf *tbuf, const nghttp3_buf *buf,
|
||||||
nghttp3_buf_type type);
|
nghttp3_buf_type type);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* nghttp3_typed_buf_shared_init initializes |tbuf| of type
|
||||||
|
* NGHTTP3_BUF_TYPE_SHARED.
|
||||||
|
*/
|
||||||
|
void nghttp3_typed_buf_shared_init(nghttp3_typed_buf *tbuf,
|
||||||
|
const nghttp3_buf *chunk);
|
||||||
|
|
||||||
void nghttp3_typed_buf_free(nghttp3_typed_buf *tbuf);
|
void nghttp3_typed_buf_free(nghttp3_typed_buf *tbuf);
|
||||||
|
|
||||||
#endif /* !defined(NGHTTP3_BUF_H) */
|
#endif /* !defined(NGHTTP3_BUF_H) */
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
dynamic table capacity that QPACK encoder is willing to use. */
|
dynamic table capacity that QPACK encoder is willing to use. */
|
||||||
#define NGHTTP3_QPACK_ENCODER_MAX_DTABLE_CAPACITY 4096
|
#define NGHTTP3_QPACK_ENCODER_MAX_DTABLE_CAPACITY 4096
|
||||||
|
|
||||||
nghttp3_objalloc_def(chunk, nghttp3_chunk, oplent);
|
nghttp3_objalloc_def(chunk, nghttp3_chunk, oplent)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* conn_remote_stream_uni returns nonzero if |stream_id| is remote
|
* conn_remote_stream_uni returns nonzero if |stream_id| is remote
|
||||||
|
@ -233,12 +233,16 @@ static int conn_new(nghttp3_conn **pconn, int server, int callbacks_version,
|
||||||
const nghttp3_callbacks *callbacks, int settings_version,
|
const nghttp3_callbacks *callbacks, int settings_version,
|
||||||
const nghttp3_settings *settings, const nghttp3_mem *mem,
|
const nghttp3_settings *settings, const nghttp3_mem *mem,
|
||||||
void *user_data) {
|
void *user_data) {
|
||||||
int rv;
|
|
||||||
nghttp3_conn *conn;
|
nghttp3_conn *conn;
|
||||||
size_t i;
|
size_t i;
|
||||||
(void)callbacks_version;
|
(void)callbacks_version;
|
||||||
(void)settings_version;
|
(void)settings_version;
|
||||||
|
|
||||||
|
assert(settings->max_field_section_size <= NGHTTP3_VARINT_MAX);
|
||||||
|
assert(settings->qpack_max_dtable_capacity <= NGHTTP3_VARINT_MAX);
|
||||||
|
assert(settings->qpack_encoder_max_dtable_capacity <= NGHTTP3_VARINT_MAX);
|
||||||
|
assert(settings->qpack_blocked_streams <= NGHTTP3_VARINT_MAX);
|
||||||
|
|
||||||
if (mem == NULL) {
|
if (mem == NULL) {
|
||||||
mem = nghttp3_mem_default();
|
mem = nghttp3_mem_default();
|
||||||
}
|
}
|
||||||
|
@ -254,18 +258,11 @@ static int conn_new(nghttp3_conn **pconn, int server, int callbacks_version,
|
||||||
|
|
||||||
nghttp3_map_init(&conn->streams, mem);
|
nghttp3_map_init(&conn->streams, mem);
|
||||||
|
|
||||||
rv =
|
nghttp3_qpack_decoder_init(&conn->qdec, settings->qpack_max_dtable_capacity,
|
||||||
nghttp3_qpack_decoder_init(&conn->qdec, settings->qpack_max_dtable_capacity,
|
settings->qpack_blocked_streams, mem);
|
||||||
settings->qpack_blocked_streams, mem);
|
|
||||||
if (rv != 0) {
|
|
||||||
goto qdec_init_fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = nghttp3_qpack_encoder_init(
|
nghttp3_qpack_encoder_init(&conn->qenc,
|
||||||
&conn->qenc, settings->qpack_encoder_max_dtable_capacity, mem);
|
settings->qpack_encoder_max_dtable_capacity, mem);
|
||||||
if (rv != 0) {
|
|
||||||
goto qenc_init_fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
nghttp3_pq_init(&conn->qpack_blocked_streams, ricnt_less, mem);
|
nghttp3_pq_init(&conn->qpack_blocked_streams, ricnt_less, mem);
|
||||||
|
|
||||||
|
@ -291,16 +288,6 @@ static int conn_new(nghttp3_conn **pconn, int server, int callbacks_version,
|
||||||
*pconn = conn;
|
*pconn = conn;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
qenc_init_fail:
|
|
||||||
nghttp3_qpack_decoder_free(&conn->qdec);
|
|
||||||
qdec_init_fail:
|
|
||||||
nghttp3_map_free(&conn->streams);
|
|
||||||
nghttp3_objalloc_free(&conn->stream_objalloc);
|
|
||||||
nghttp3_objalloc_free(&conn->out_chunk_objalloc);
|
|
||||||
nghttp3_mem_free(mem, conn);
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int nghttp3_conn_client_new_versioned(nghttp3_conn **pconn,
|
int nghttp3_conn_client_new_versioned(nghttp3_conn **pconn,
|
||||||
|
@ -399,6 +386,9 @@ nghttp3_ssize nghttp3_conn_read_stream(nghttp3_conn *conn, int64_t stream_id,
|
||||||
size_t bidi_nproc;
|
size_t bidi_nproc;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
|
assert(stream_id >= 0);
|
||||||
|
assert(stream_id <= (int64_t)NGHTTP3_MAX_VARINT);
|
||||||
|
|
||||||
stream = nghttp3_conn_find_stream(conn, stream_id);
|
stream = nghttp3_conn_find_stream(conn, stream_id);
|
||||||
if (stream == NULL) {
|
if (stream == NULL) {
|
||||||
/* TODO Assert idtr */
|
/* TODO Assert idtr */
|
||||||
|
@ -434,6 +424,10 @@ nghttp3_ssize nghttp3_conn_read_stream(nghttp3_conn *conn, int64_t stream_id,
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (!nghttp3_client_stream_uni(stream_id)) {
|
||||||
|
/* server does not expect to receive new server initiated
|
||||||
|
bidirectional or unidirectional stream from client. */
|
||||||
|
return NGHTTP3_ERR_H3_STREAM_CREATION_ERROR;
|
||||||
} else {
|
} else {
|
||||||
/* unidirectional stream */
|
/* unidirectional stream */
|
||||||
if (srclen == 0 && fin) {
|
if (srclen == 0 && fin) {
|
||||||
|
@ -448,7 +442,7 @@ nghttp3_ssize nghttp3_conn_read_stream(nghttp3_conn *conn, int64_t stream_id,
|
||||||
|
|
||||||
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_INITIAL;
|
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_INITIAL;
|
||||||
stream->tx.hstate = NGHTTP3_HTTP_STATE_REQ_INITIAL;
|
stream->tx.hstate = NGHTTP3_HTTP_STATE_REQ_INITIAL;
|
||||||
} else if (nghttp3_stream_uni(stream_id)) {
|
} else if (nghttp3_server_stream_uni(stream_id)) {
|
||||||
if (srclen == 0 && fin) {
|
if (srclen == 0 && fin) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -461,17 +455,16 @@ nghttp3_ssize nghttp3_conn_read_stream(nghttp3_conn *conn, int64_t stream_id,
|
||||||
stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_INITIAL;
|
stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_INITIAL;
|
||||||
stream->tx.hstate = NGHTTP3_HTTP_STATE_RESP_INITIAL;
|
stream->tx.hstate = NGHTTP3_HTTP_STATE_RESP_INITIAL;
|
||||||
} else {
|
} else {
|
||||||
/* client doesn't expect to receive new bidirectional stream
|
/* client doesn't expect to receive new bidirectional stream or
|
||||||
from server. */
|
client initiated unidirectional stream from server. */
|
||||||
return NGHTTP3_ERR_H3_STREAM_CREATION_ERROR;
|
return NGHTTP3_ERR_H3_STREAM_CREATION_ERROR;
|
||||||
}
|
}
|
||||||
} else if (conn->server) {
|
} else if (conn->server) {
|
||||||
if (nghttp3_client_stream_bidi(stream_id)) {
|
assert(nghttp3_client_stream_bidi(stream_id) ||
|
||||||
if (stream->rx.hstate == NGHTTP3_HTTP_STATE_NONE) {
|
nghttp3_client_stream_uni(stream_id));
|
||||||
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_INITIAL;
|
} else {
|
||||||
stream->tx.hstate = NGHTTP3_HTTP_STATE_REQ_INITIAL;
|
assert(nghttp3_client_stream_bidi(stream_id) ||
|
||||||
}
|
nghttp3_server_stream_uni(stream_id));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (srclen == 0 && !fin) {
|
if (srclen == 0 && !fin) {
|
||||||
|
@ -608,6 +601,9 @@ nghttp3_ssize nghttp3_conn_read_uni(nghttp3_conn *conn, nghttp3_stream *stream,
|
||||||
break;
|
break;
|
||||||
case NGHTTP3_STREAM_TYPE_UNKNOWN:
|
case NGHTTP3_STREAM_TYPE_UNKNOWN:
|
||||||
nconsumed = (nghttp3_ssize)srclen;
|
nconsumed = (nghttp3_ssize)srclen;
|
||||||
|
if (fin) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
rv = conn_call_stop_sending(conn, stream, NGHTTP3_H3_STREAM_CREATION_ERROR);
|
rv = conn_call_stop_sending(conn, stream, NGHTTP3_H3_STREAM_CREATION_ERROR);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
|
@ -665,7 +661,7 @@ nghttp3_ssize nghttp3_conn_read_control(nghttp3_conn *conn,
|
||||||
nghttp3_varint_read_state_reset(rvint);
|
nghttp3_varint_read_state_reset(rvint);
|
||||||
rstate->state = NGHTTP3_CTRL_STREAM_STATE_FRAME_LENGTH;
|
rstate->state = NGHTTP3_CTRL_STREAM_STATE_FRAME_LENGTH;
|
||||||
if (p == end) {
|
if (p == end) {
|
||||||
break;
|
return (nghttp3_ssize)nconsumed;
|
||||||
}
|
}
|
||||||
/* Fall through */
|
/* Fall through */
|
||||||
case NGHTTP3_CTRL_STREAM_STATE_FRAME_LENGTH:
|
case NGHTTP3_CTRL_STREAM_STATE_FRAME_LENGTH:
|
||||||
|
@ -973,6 +969,10 @@ nghttp3_ssize nghttp3_conn_read_control(nghttp3_conn *conn,
|
||||||
|
|
||||||
rstate->state = NGHTTP3_CTRL_STREAM_STATE_PRIORITY_UPDATE;
|
rstate->state = NGHTTP3_CTRL_STREAM_STATE_PRIORITY_UPDATE;
|
||||||
|
|
||||||
|
if (p == end) {
|
||||||
|
return (nghttp3_ssize)nconsumed;
|
||||||
|
}
|
||||||
|
|
||||||
/* Fall through */
|
/* Fall through */
|
||||||
case NGHTTP3_CTRL_STREAM_STATE_PRIORITY_UPDATE:
|
case NGHTTP3_CTRL_STREAM_STATE_PRIORITY_UPDATE:
|
||||||
/* We need to buffer Priority Field Value because it might be
|
/* We need to buffer Priority Field Value because it might be
|
||||||
|
@ -1792,6 +1792,8 @@ conn_on_priority_update_stream(nghttp3_conn *conn,
|
||||||
|
|
||||||
stream->node.pri = fr->pri;
|
stream->node.pri = fr->pri;
|
||||||
stream->flags |= NGHTTP3_STREAM_FLAG_PRIORITY_UPDATE_RECVED;
|
stream->flags |= NGHTTP3_STREAM_FLAG_PRIORITY_UPDATE_RECVED;
|
||||||
|
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_INITIAL;
|
||||||
|
stream->tx.hstate = NGHTTP3_HTTP_STATE_REQ_INITIAL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1836,7 +1838,7 @@ int nghttp3_conn_create_stream(nghttp3_conn *conn, nghttp3_stream **pstream,
|
||||||
nghttp3_stream *stream;
|
nghttp3_stream *stream;
|
||||||
int rv;
|
int rv;
|
||||||
nghttp3_stream_callbacks callbacks = {
|
nghttp3_stream_callbacks callbacks = {
|
||||||
conn_stream_acked_data,
|
.acked_data = conn_stream_acked_data,
|
||||||
};
|
};
|
||||||
|
|
||||||
rv = nghttp3_stream_new(&stream, stream_id, &callbacks,
|
rv = nghttp3_stream_new(&stream, stream_id, &callbacks,
|
||||||
|
@ -1874,6 +1876,8 @@ int nghttp3_conn_bind_control_stream(nghttp3_conn *conn, int64_t stream_id) {
|
||||||
nghttp3_frame_entry frent;
|
nghttp3_frame_entry frent;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
|
assert(stream_id >= 0);
|
||||||
|
assert(stream_id <= (int64_t)NGHTTP3_MAX_VARINT);
|
||||||
assert(!conn->server || nghttp3_server_stream_uni(stream_id));
|
assert(!conn->server || nghttp3_server_stream_uni(stream_id));
|
||||||
assert(conn->server || nghttp3_client_stream_uni(stream_id));
|
assert(conn->server || nghttp3_client_stream_uni(stream_id));
|
||||||
|
|
||||||
|
@ -1906,6 +1910,10 @@ int nghttp3_conn_bind_qpack_streams(nghttp3_conn *conn, int64_t qenc_stream_id,
|
||||||
nghttp3_stream *stream;
|
nghttp3_stream *stream;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
|
assert(qenc_stream_id >= 0);
|
||||||
|
assert(qenc_stream_id <= (int64_t)NGHTTP3_MAX_VARINT);
|
||||||
|
assert(qdec_stream_id >= 0);
|
||||||
|
assert(qdec_stream_id <= (int64_t)NGHTTP3_MAX_VARINT);
|
||||||
assert(!conn->server || nghttp3_server_stream_uni(qenc_stream_id));
|
assert(!conn->server || nghttp3_server_stream_uni(qenc_stream_id));
|
||||||
assert(!conn->server || nghttp3_server_stream_uni(qdec_stream_id));
|
assert(!conn->server || nghttp3_server_stream_uni(qdec_stream_id));
|
||||||
assert(conn->server || nghttp3_client_stream_uni(qenc_stream_id));
|
assert(conn->server || nghttp3_client_stream_uni(qenc_stream_id));
|
||||||
|
@ -2194,13 +2202,11 @@ int nghttp3_conn_submit_request(nghttp3_conn *conn, int64_t stream_id,
|
||||||
assert(!conn->server);
|
assert(!conn->server);
|
||||||
assert(conn->tx.qenc);
|
assert(conn->tx.qenc);
|
||||||
|
|
||||||
|
assert(stream_id >= 0);
|
||||||
|
assert(stream_id <= (int64_t)NGHTTP3_MAX_VARINT);
|
||||||
assert(nghttp3_client_stream_bidi(stream_id));
|
assert(nghttp3_client_stream_bidi(stream_id));
|
||||||
|
|
||||||
/* TODO Should we check that stream_id is client stream_id? */
|
|
||||||
/* TODO Check GOAWAY last stream ID */
|
/* TODO Check GOAWAY last stream ID */
|
||||||
if (nghttp3_stream_uni(stream_id)) {
|
|
||||||
return NGHTTP3_ERR_INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (conn->flags & NGHTTP3_CONN_FLAG_GOAWAY_RECVED) {
|
if (conn->flags & NGHTTP3_CONN_FLAG_GOAWAY_RECVED) {
|
||||||
return NGHTTP3_ERR_CONN_CLOSING;
|
return NGHTTP3_ERR_CONN_CLOSING;
|
||||||
|
@ -2454,6 +2460,9 @@ int nghttp3_conn_close_stream(nghttp3_conn *conn, int64_t stream_id,
|
||||||
int nghttp3_conn_shutdown_stream_read(nghttp3_conn *conn, int64_t stream_id) {
|
int nghttp3_conn_shutdown_stream_read(nghttp3_conn *conn, int64_t stream_id) {
|
||||||
nghttp3_stream *stream;
|
nghttp3_stream *stream;
|
||||||
|
|
||||||
|
assert(stream_id >= 0);
|
||||||
|
assert(stream_id <= (int64_t)NGHTTP3_MAX_VARINT);
|
||||||
|
|
||||||
if (!nghttp3_client_stream_bidi(stream_id)) {
|
if (!nghttp3_client_stream_bidi(stream_id)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2515,6 +2524,9 @@ uint64_t nghttp3_conn_get_frame_payload_left(nghttp3_conn *conn,
|
||||||
nghttp3_stream *stream;
|
nghttp3_stream *stream;
|
||||||
int uni = 0;
|
int uni = 0;
|
||||||
|
|
||||||
|
assert(stream_id >= 0);
|
||||||
|
assert(stream_id <= (int64_t)NGHTTP3_MAX_VARINT);
|
||||||
|
|
||||||
if (!nghttp3_client_stream_bidi(stream_id)) {
|
if (!nghttp3_client_stream_bidi(stream_id)) {
|
||||||
uni = conn_remote_stream_uni(conn, stream_id);
|
uni = conn_remote_stream_uni(conn, stream_id);
|
||||||
if (!uni) {
|
if (!uni) {
|
||||||
|
@ -2542,6 +2554,8 @@ int nghttp3_conn_get_stream_priority_versioned(nghttp3_conn *conn,
|
||||||
(void)pri_version;
|
(void)pri_version;
|
||||||
|
|
||||||
assert(conn->server);
|
assert(conn->server);
|
||||||
|
assert(stream_id >= 0);
|
||||||
|
assert(stream_id <= (int64_t)NGHTTP3_MAX_VARINT);
|
||||||
|
|
||||||
if (!nghttp3_client_stream_bidi(stream_id)) {
|
if (!nghttp3_client_stream_bidi(stream_id)) {
|
||||||
return NGHTTP3_ERR_INVALID_ARGUMENT;
|
return NGHTTP3_ERR_INVALID_ARGUMENT;
|
||||||
|
@ -2566,6 +2580,8 @@ int nghttp3_conn_set_client_stream_priority(nghttp3_conn *conn,
|
||||||
uint8_t *buf = NULL;
|
uint8_t *buf = NULL;
|
||||||
|
|
||||||
assert(!conn->server);
|
assert(!conn->server);
|
||||||
|
assert(stream_id >= 0);
|
||||||
|
assert(stream_id <= (int64_t)NGHTTP3_MAX_VARINT);
|
||||||
|
|
||||||
if (!nghttp3_client_stream_bidi(stream_id)) {
|
if (!nghttp3_client_stream_bidi(stream_id)) {
|
||||||
return NGHTTP3_ERR_INVALID_ARGUMENT;
|
return NGHTTP3_ERR_INVALID_ARGUMENT;
|
||||||
|
@ -2603,6 +2619,8 @@ int nghttp3_conn_set_server_stream_priority_versioned(nghttp3_conn *conn,
|
||||||
assert(conn->server);
|
assert(conn->server);
|
||||||
assert(pri->urgency < NGHTTP3_URGENCY_LEVELS);
|
assert(pri->urgency < NGHTTP3_URGENCY_LEVELS);
|
||||||
assert(pri->inc == 0 || pri->inc == 1);
|
assert(pri->inc == 0 || pri->inc == 1);
|
||||||
|
assert(stream_id >= 0);
|
||||||
|
assert(stream_id <= (int64_t)NGHTTP3_MAX_VARINT);
|
||||||
|
|
||||||
if (!nghttp3_client_stream_bidi(stream_id)) {
|
if (!nghttp3_client_stream_bidi(stream_id)) {
|
||||||
return NGHTTP3_ERR_INVALID_ARGUMENT;
|
return NGHTTP3_ERR_INVALID_ARGUMENT;
|
||||||
|
|
|
@ -76,7 +76,7 @@ typedef struct nghttp3_chunk {
|
||||||
nghttp3_opl_entry oplent;
|
nghttp3_opl_entry oplent;
|
||||||
} nghttp3_chunk;
|
} nghttp3_chunk;
|
||||||
|
|
||||||
nghttp3_objalloc_decl(chunk, nghttp3_chunk, oplent);
|
nghttp3_objalloc_decl(chunk, nghttp3_chunk, oplent)
|
||||||
|
|
||||||
struct nghttp3_conn {
|
struct nghttp3_conn {
|
||||||
nghttp3_objalloc out_chunk_objalloc;
|
nghttp3_objalloc out_chunk_objalloc;
|
||||||
|
|
|
@ -66,8 +66,6 @@ const uint8_t *nghttp3_get_varint(int64_t *dest, const uint8_t *p) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t nghttp3_get_varint_fb(const uint8_t *p) { return *p & 0x3f; }
|
|
||||||
|
|
||||||
size_t nghttp3_get_varintlen(const uint8_t *p) {
|
size_t nghttp3_get_varintlen(const uint8_t *p) {
|
||||||
return (size_t)(1u << (*p >> 6));
|
return (size_t)(1u << (*p >> 6));
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,12 +135,6 @@ STIN uint16_t ntohs(uint16_t netshort) {
|
||||||
*/
|
*/
|
||||||
const uint8_t *nghttp3_get_varint(int64_t *dest, const uint8_t *p);
|
const uint8_t *nghttp3_get_varint(int64_t *dest, const uint8_t *p);
|
||||||
|
|
||||||
/*
|
|
||||||
* nghttp3_get_varint_fb reads first byte of encoded variable-length
|
|
||||||
* integer from |p|.
|
|
||||||
*/
|
|
||||||
int64_t nghttp3_get_varint_fb(const uint8_t *p);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* nghttp3_get_varintlen returns the required number of bytes to read
|
* nghttp3_get_varintlen returns the required number of bytes to read
|
||||||
* variable-length integer starting at |p|.
|
* variable-length integer starting at |p|.
|
||||||
|
|
|
@ -29,14 +29,16 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
void nghttp3_gaptr_init(nghttp3_gaptr *gaptr, const nghttp3_mem *mem) {
|
void nghttp3_gaptr_init(nghttp3_gaptr *gaptr, const nghttp3_mem *mem) {
|
||||||
nghttp3_ksl_init(&gaptr->gap, nghttp3_ksl_range_compar, sizeof(nghttp3_range),
|
nghttp3_ksl_init(&gaptr->gap, nghttp3_ksl_range_compar,
|
||||||
mem);
|
nghttp3_ksl_range_search, sizeof(nghttp3_range), mem);
|
||||||
|
|
||||||
gaptr->mem = mem;
|
gaptr->mem = mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gaptr_gap_init(nghttp3_gaptr *gaptr) {
|
static int gaptr_gap_init(nghttp3_gaptr *gaptr) {
|
||||||
nghttp3_range range = {0, UINT64_MAX};
|
nghttp3_range range = {
|
||||||
|
.end = UINT64_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
return nghttp3_ksl_insert(&gaptr->gap, NULL, &range, NULL);
|
return nghttp3_ksl_insert(&gaptr->gap, NULL, &range, NULL);
|
||||||
}
|
}
|
||||||
|
@ -52,7 +54,11 @@ void nghttp3_gaptr_free(nghttp3_gaptr *gaptr) {
|
||||||
int nghttp3_gaptr_push(nghttp3_gaptr *gaptr, uint64_t offset,
|
int nghttp3_gaptr_push(nghttp3_gaptr *gaptr, uint64_t offset,
|
||||||
uint64_t datalen) {
|
uint64_t datalen) {
|
||||||
int rv;
|
int rv;
|
||||||
nghttp3_range k, m, l, r, q = {offset, offset + datalen};
|
nghttp3_range k, m, l, r;
|
||||||
|
nghttp3_range q = {
|
||||||
|
.begin = offset,
|
||||||
|
.end = offset + datalen,
|
||||||
|
};
|
||||||
nghttp3_ksl_it it;
|
nghttp3_ksl_it it;
|
||||||
|
|
||||||
if (nghttp3_ksl_len(&gaptr->gap) == 0) {
|
if (nghttp3_ksl_len(&gaptr->gap) == 0) {
|
||||||
|
@ -62,8 +68,8 @@ int nghttp3_gaptr_push(nghttp3_gaptr *gaptr, uint64_t offset,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
it = nghttp3_ksl_lower_bound_compar(&gaptr->gap, &q,
|
it = nghttp3_ksl_lower_bound_search(&gaptr->gap, &q,
|
||||||
nghttp3_ksl_range_exclusive_compar);
|
nghttp3_ksl_range_exclusive_search);
|
||||||
|
|
||||||
for (; !nghttp3_ksl_it_end(&it);) {
|
for (; !nghttp3_ksl_it_end(&it);) {
|
||||||
k = *(nghttp3_range *)nghttp3_ksl_it_key(&it);
|
k = *(nghttp3_range *)nghttp3_ksl_it_key(&it);
|
||||||
|
@ -112,7 +118,10 @@ uint64_t nghttp3_gaptr_first_gap_offset(nghttp3_gaptr *gaptr) {
|
||||||
|
|
||||||
nghttp3_range nghttp3_gaptr_get_first_gap_after(nghttp3_gaptr *gaptr,
|
nghttp3_range nghttp3_gaptr_get_first_gap_after(nghttp3_gaptr *gaptr,
|
||||||
uint64_t offset) {
|
uint64_t offset) {
|
||||||
nghttp3_range q = {offset, offset + 1};
|
nghttp3_range q = {
|
||||||
|
.begin = offset,
|
||||||
|
.end = offset + 1,
|
||||||
|
};
|
||||||
nghttp3_ksl_it it;
|
nghttp3_ksl_it it;
|
||||||
|
|
||||||
if (nghttp3_ksl_len(&gaptr->gap) == 0) {
|
if (nghttp3_ksl_len(&gaptr->gap) == 0) {
|
||||||
|
@ -120,8 +129,8 @@ nghttp3_range nghttp3_gaptr_get_first_gap_after(nghttp3_gaptr *gaptr,
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
it = nghttp3_ksl_lower_bound_compar(&gaptr->gap, &q,
|
it = nghttp3_ksl_lower_bound_search(&gaptr->gap, &q,
|
||||||
nghttp3_ksl_range_exclusive_compar);
|
nghttp3_ksl_range_exclusive_search);
|
||||||
|
|
||||||
assert(!nghttp3_ksl_it_end(&it));
|
assert(!nghttp3_ksl_it_end(&it));
|
||||||
|
|
||||||
|
@ -130,7 +139,10 @@ nghttp3_range nghttp3_gaptr_get_first_gap_after(nghttp3_gaptr *gaptr,
|
||||||
|
|
||||||
int nghttp3_gaptr_is_pushed(nghttp3_gaptr *gaptr, uint64_t offset,
|
int nghttp3_gaptr_is_pushed(nghttp3_gaptr *gaptr, uint64_t offset,
|
||||||
uint64_t datalen) {
|
uint64_t datalen) {
|
||||||
nghttp3_range q = {offset, offset + datalen};
|
nghttp3_range q = {
|
||||||
|
.begin = offset,
|
||||||
|
.end = offset + datalen,
|
||||||
|
};
|
||||||
nghttp3_ksl_it it;
|
nghttp3_ksl_it it;
|
||||||
nghttp3_range m;
|
nghttp3_range m;
|
||||||
|
|
||||||
|
@ -138,8 +150,11 @@ int nghttp3_gaptr_is_pushed(nghttp3_gaptr *gaptr, uint64_t offset,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
it = nghttp3_ksl_lower_bound_compar(&gaptr->gap, &q,
|
it = nghttp3_ksl_lower_bound_search(&gaptr->gap, &q,
|
||||||
nghttp3_ksl_range_exclusive_compar);
|
nghttp3_ksl_range_exclusive_search);
|
||||||
|
|
||||||
|
assert(!nghttp3_ksl_it_end(&it));
|
||||||
|
|
||||||
m = nghttp3_range_intersect(&q, (nghttp3_range *)nghttp3_ksl_it_key(&it));
|
m = nghttp3_range_intersect(&q, (nghttp3_range *)nghttp3_ksl_it_key(&it));
|
||||||
|
|
||||||
return nghttp3_range_len(&m) == 0;
|
return nghttp3_range_len(&m) == 0;
|
||||||
|
|
|
@ -69,11 +69,11 @@ static int64_t parse_uint(const uint8_t *s, size_t len) {
|
||||||
}
|
}
|
||||||
for (i = 0; i < len; ++i) {
|
for (i = 0; i < len; ++i) {
|
||||||
if ('0' <= s[i] && s[i] <= '9') {
|
if ('0' <= s[i] && s[i] <= '9') {
|
||||||
if (n > INT64_MAX / 10) {
|
if (n > (int64_t)NGHTTP3_MAX_VARINT / 10) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
n *= 10;
|
n *= 10;
|
||||||
if (n > INT64_MAX - (s[i] - '0')) {
|
if (n > (int64_t)NGHTTP3_MAX_VARINT - (s[i] - '0')) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
n += s[i] - '0';
|
n += s[i] - '0';
|
||||||
|
@ -124,17 +124,17 @@ static int is_ws(uint8_t c) {
|
||||||
int nghttp3_http_parse_priority(nghttp3_pri *dest, const uint8_t *value,
|
int nghttp3_http_parse_priority(nghttp3_pri *dest, const uint8_t *value,
|
||||||
size_t valuelen) {
|
size_t valuelen) {
|
||||||
nghttp3_pri pri = *dest;
|
nghttp3_pri pri = *dest;
|
||||||
sf_parser sfp;
|
sfparse_parser sfp;
|
||||||
sf_vec key;
|
sfparse_vec key;
|
||||||
sf_value val;
|
sfparse_value val;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
sf_parser_init(&sfp, value, valuelen);
|
sfparse_parser_init(&sfp, value, valuelen);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
rv = sf_parser_dict(&sfp, &key, &val);
|
rv = sfparse_parser_dict(&sfp, &key, &val);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
if (rv == SF_ERR_EOF) {
|
if (rv == SFPARSE_ERR_EOF) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ int nghttp3_http_parse_priority(nghttp3_pri *dest, const uint8_t *value,
|
||||||
|
|
||||||
switch (key.base[0]) {
|
switch (key.base[0]) {
|
||||||
case 'i':
|
case 'i':
|
||||||
if (val.type != SF_TYPE_BOOLEAN) {
|
if (val.type != SFPARSE_TYPE_BOOLEAN) {
|
||||||
return NGHTTP3_ERR_INVALID_ARGUMENT;
|
return NGHTTP3_ERR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,7 +155,8 @@ int nghttp3_http_parse_priority(nghttp3_pri *dest, const uint8_t *value,
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
if (val.type != SF_TYPE_INTEGER || val.integer < NGHTTP3_URGENCY_HIGH ||
|
if (val.type != SFPARSE_TYPE_INTEGER ||
|
||||||
|
val.integer < NGHTTP3_URGENCY_HIGH ||
|
||||||
NGHTTP3_URGENCY_LOW < val.integer) {
|
NGHTTP3_URGENCY_LOW < val.integer) {
|
||||||
return NGHTTP3_ERR_INVALID_ARGUMENT;
|
return NGHTTP3_ERR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
@ -197,7 +198,7 @@ static char VALID_AUTHORITY_CHARS[] = {
|
||||||
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
||||||
1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
|
1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
|
||||||
0 /* < */, 1 /* = */, 0 /* > */, 0 /* ? */,
|
0 /* < */, 1 /* = */, 0 /* > */, 0 /* ? */,
|
||||||
1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
|
0 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
|
||||||
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
|
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
|
||||||
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
|
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
|
||||||
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
||||||
|
@ -548,6 +549,9 @@ static int http_request_on_header(nghttp3_http_state *http,
|
||||||
break;
|
break;
|
||||||
case NGHTTP3_QPACK_TOKEN_PRIORITY:
|
case NGHTTP3_QPACK_TOKEN_PRIORITY:
|
||||||
if (!nghttp3_check_header_value(nv->value->base, nv->value->len)) {
|
if (!nghttp3_check_header_value(nv->value->base, nv->value->len)) {
|
||||||
|
http->flags &= ~NGHTTP3_HTTP_FLAG_PRIORITY;
|
||||||
|
http->flags |= NGHTTP3_HTTP_FLAG_BAD_PRIORITY;
|
||||||
|
|
||||||
return NGHTTP3_ERR_REMOVE_HTTP_HEADER;
|
return NGHTTP3_ERR_REMOVE_HTTP_HEADER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -991,7 +995,11 @@ int nghttp3_check_header_value(const uint8_t *value, size_t len) {
|
||||||
case 0:
|
case 0:
|
||||||
return 1;
|
return 1;
|
||||||
case 1:
|
case 1:
|
||||||
return !is_ws(*value);
|
if (is_ws(*value)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (is_ws(*value) || is_ws(*(value + len - 1))) {
|
if (is_ws(*value) || is_ws(*(value + len - 1))) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -34,9 +34,9 @@
|
||||||
#include "nghttp3_mem.h"
|
#include "nghttp3_mem.h"
|
||||||
#include "nghttp3_range.h"
|
#include "nghttp3_range.h"
|
||||||
|
|
||||||
static nghttp3_ksl_blk null_blk = {{{NULL, NULL, 0, 0, {0}}}};
|
static nghttp3_ksl_blk null_blk;
|
||||||
|
|
||||||
nghttp3_objalloc_def(ksl_blk, nghttp3_ksl_blk, oplent);
|
nghttp3_objalloc_def(ksl_blk, nghttp3_ksl_blk, oplent)
|
||||||
|
|
||||||
static size_t ksl_nodelen(size_t keylen) {
|
static size_t ksl_nodelen(size_t keylen) {
|
||||||
assert(keylen >= sizeof(uint64_t));
|
assert(keylen >= sizeof(uint64_t));
|
||||||
|
@ -59,7 +59,8 @@ static void ksl_node_set_key(nghttp3_ksl *ksl, nghttp3_ksl_node *node,
|
||||||
}
|
}
|
||||||
|
|
||||||
void nghttp3_ksl_init(nghttp3_ksl *ksl, nghttp3_ksl_compar compar,
|
void nghttp3_ksl_init(nghttp3_ksl *ksl, nghttp3_ksl_compar compar,
|
||||||
size_t keylen, const nghttp3_mem *mem) {
|
nghttp3_ksl_search search, size_t keylen,
|
||||||
|
const nghttp3_mem *mem) {
|
||||||
size_t nodelen = ksl_nodelen(keylen);
|
size_t nodelen = ksl_nodelen(keylen);
|
||||||
|
|
||||||
nghttp3_objalloc_init(&ksl->blkalloc,
|
nghttp3_objalloc_init(&ksl->blkalloc,
|
||||||
|
@ -68,6 +69,7 @@ void nghttp3_ksl_init(nghttp3_ksl *ksl, nghttp3_ksl_compar compar,
|
||||||
ksl->head = NULL;
|
ksl->head = NULL;
|
||||||
ksl->front = ksl->back = NULL;
|
ksl->front = ksl->back = NULL;
|
||||||
ksl->compar = compar;
|
ksl->compar = compar;
|
||||||
|
ksl->search = search;
|
||||||
ksl->n = 0;
|
ksl->n = 0;
|
||||||
ksl->keylen = keylen;
|
ksl->keylen = keylen;
|
||||||
ksl->nodelen = nodelen;
|
ksl->nodelen = nodelen;
|
||||||
|
@ -274,20 +276,6 @@ static void ksl_insert_node(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk, size_t i,
|
||||||
++blk->n;
|
++blk->n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t ksl_search(const nghttp3_ksl *ksl, nghttp3_ksl_blk *blk,
|
|
||||||
const nghttp3_ksl_key *key,
|
|
||||||
nghttp3_ksl_compar compar) {
|
|
||||||
size_t i;
|
|
||||||
nghttp3_ksl_node *node;
|
|
||||||
|
|
||||||
for (i = 0, node = (nghttp3_ksl_node *)(void *)blk->nodes;
|
|
||||||
i < blk->n && compar((nghttp3_ksl_key *)node->key, key);
|
|
||||||
++i, node = (nghttp3_ksl_node *)(void *)((uint8_t *)node + ksl->nodelen))
|
|
||||||
;
|
|
||||||
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nghttp3_ksl_insert(nghttp3_ksl *ksl, nghttp3_ksl_it *it,
|
int nghttp3_ksl_insert(nghttp3_ksl *ksl, nghttp3_ksl_it *it,
|
||||||
const nghttp3_ksl_key *key, void *data) {
|
const nghttp3_ksl_key *key, void *data) {
|
||||||
nghttp3_ksl_blk *blk;
|
nghttp3_ksl_blk *blk;
|
||||||
|
@ -312,7 +300,7 @@ int nghttp3_ksl_insert(nghttp3_ksl *ksl, nghttp3_ksl_it *it,
|
||||||
blk = ksl->head;
|
blk = ksl->head;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
i = ksl_search(ksl, blk, key, ksl->compar);
|
i = ksl->search(ksl, blk, key);
|
||||||
|
|
||||||
if (blk->leaf) {
|
if (blk->leaf) {
|
||||||
if (i < blk->n &&
|
if (i < blk->n &&
|
||||||
|
@ -571,7 +559,7 @@ int nghttp3_ksl_remove(nghttp3_ksl *ksl, nghttp3_ksl_it *it,
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
i = ksl_search(ksl, blk, key, ksl->compar);
|
i = ksl->search(ksl, blk, key);
|
||||||
|
|
||||||
if (i == blk->n) {
|
if (i == blk->n) {
|
||||||
if (it) {
|
if (it) {
|
||||||
|
@ -642,12 +630,12 @@ int nghttp3_ksl_remove(nghttp3_ksl *ksl, nghttp3_ksl_it *it,
|
||||||
|
|
||||||
nghttp3_ksl_it nghttp3_ksl_lower_bound(const nghttp3_ksl *ksl,
|
nghttp3_ksl_it nghttp3_ksl_lower_bound(const nghttp3_ksl *ksl,
|
||||||
const nghttp3_ksl_key *key) {
|
const nghttp3_ksl_key *key) {
|
||||||
return nghttp3_ksl_lower_bound_compar(ksl, key, ksl->compar);
|
return nghttp3_ksl_lower_bound_search(ksl, key, ksl->search);
|
||||||
}
|
}
|
||||||
|
|
||||||
nghttp3_ksl_it nghttp3_ksl_lower_bound_compar(const nghttp3_ksl *ksl,
|
nghttp3_ksl_it nghttp3_ksl_lower_bound_search(const nghttp3_ksl *ksl,
|
||||||
const nghttp3_ksl_key *key,
|
const nghttp3_ksl_key *key,
|
||||||
nghttp3_ksl_compar compar) {
|
nghttp3_ksl_search search) {
|
||||||
nghttp3_ksl_blk *blk = ksl->head;
|
nghttp3_ksl_blk *blk = ksl->head;
|
||||||
nghttp3_ksl_it it;
|
nghttp3_ksl_it it;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
@ -658,7 +646,7 @@ nghttp3_ksl_it nghttp3_ksl_lower_bound_compar(const nghttp3_ksl *ksl,
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
i = ksl_search(ksl, blk, key, compar);
|
i = search(ksl, blk, key);
|
||||||
|
|
||||||
if (blk->leaf) {
|
if (blk->leaf) {
|
||||||
if (i == blk->n && blk->next) {
|
if (i == blk->n && blk->next) {
|
||||||
|
@ -702,7 +690,7 @@ void nghttp3_ksl_update_key(nghttp3_ksl *ksl, const nghttp3_ksl_key *old_key,
|
||||||
assert(ksl->head);
|
assert(ksl->head);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
i = ksl_search(ksl, blk, old_key, ksl->compar);
|
i = ksl->search(ksl, blk, old_key);
|
||||||
|
|
||||||
assert(i < blk->n);
|
assert(i < blk->n);
|
||||||
node = nghttp3_ksl_nth_node(ksl, blk, i);
|
node = nghttp3_ksl_nth_node(ksl, blk, i);
|
||||||
|
@ -825,9 +813,50 @@ int nghttp3_ksl_range_compar(const nghttp3_ksl_key *lhs,
|
||||||
return a->begin < b->begin;
|
return a->begin < b->begin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nghttp3_ksl_search_def(range, nghttp3_ksl_range_compar)
|
||||||
|
|
||||||
|
size_t nghttp3_ksl_range_search(const nghttp3_ksl *ksl, nghttp3_ksl_blk *blk,
|
||||||
|
const nghttp3_ksl_key *key) {
|
||||||
|
return ksl_range_search(ksl, blk, key);
|
||||||
|
}
|
||||||
|
|
||||||
int nghttp3_ksl_range_exclusive_compar(const nghttp3_ksl_key *lhs,
|
int nghttp3_ksl_range_exclusive_compar(const nghttp3_ksl_key *lhs,
|
||||||
const nghttp3_ksl_key *rhs) {
|
const nghttp3_ksl_key *rhs) {
|
||||||
const nghttp3_range *a = lhs, *b = rhs;
|
const nghttp3_range *a = lhs, *b = rhs;
|
||||||
return a->begin < b->begin && !(nghttp3_max_uint64(a->begin, b->begin) <
|
return a->begin < b->begin && !(nghttp3_max_uint64(a->begin, b->begin) <
|
||||||
nghttp3_min_uint64(a->end, b->end));
|
nghttp3_min_uint64(a->end, b->end));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nghttp3_ksl_search_def(range_exclusive, nghttp3_ksl_range_exclusive_compar)
|
||||||
|
|
||||||
|
size_t nghttp3_ksl_range_exclusive_search(const nghttp3_ksl *ksl,
|
||||||
|
nghttp3_ksl_blk *blk,
|
||||||
|
const nghttp3_ksl_key *key) {
|
||||||
|
return ksl_range_exclusive_search(ksl, blk, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
int nghttp3_ksl_uint64_less(const nghttp3_ksl_key *lhs,
|
||||||
|
const nghttp3_ksl_key *rhs) {
|
||||||
|
return *(uint64_t *)lhs < *(uint64_t *)rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
nghttp3_ksl_search_def(uint64_less, nghttp3_ksl_uint64_less)
|
||||||
|
|
||||||
|
size_t nghttp3_ksl_uint64_less_search(const nghttp3_ksl *ksl,
|
||||||
|
nghttp3_ksl_blk *blk,
|
||||||
|
const nghttp3_ksl_key *key) {
|
||||||
|
return ksl_uint64_less_search(ksl, blk, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
int nghttp3_ksl_int64_greater(const nghttp3_ksl_key *lhs,
|
||||||
|
const nghttp3_ksl_key *rhs) {
|
||||||
|
return *(int64_t *)lhs > *(int64_t *)rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
nghttp3_ksl_search_def(int64_greater, nghttp3_ksl_int64_greater)
|
||||||
|
|
||||||
|
size_t nghttp3_ksl_int64_greater_search(const nghttp3_ksl *ksl,
|
||||||
|
nghttp3_ksl_blk *blk,
|
||||||
|
const nghttp3_ksl_key *key) {
|
||||||
|
return ksl_int64_greater_search(ksl, blk, key);
|
||||||
|
}
|
||||||
|
|
|
@ -104,7 +104,7 @@ struct nghttp3_ksl_blk {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
nghttp3_objalloc_decl(ksl_blk, nghttp3_ksl_blk, oplent);
|
nghttp3_objalloc_decl(ksl_blk, nghttp3_ksl_blk, oplent)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* nghttp3_ksl_compar is a function type which returns nonzero if key
|
* nghttp3_ksl_compar is a function type which returns nonzero if key
|
||||||
|
@ -115,6 +115,35 @@ typedef int (*nghttp3_ksl_compar)(const nghttp3_ksl_key *lhs,
|
||||||
|
|
||||||
typedef struct nghttp3_ksl nghttp3_ksl;
|
typedef struct nghttp3_ksl nghttp3_ksl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* nghttp3_ksl_search is a function to search for the first element in
|
||||||
|
* |blk|->nodes which is not ordered before |key|. It returns the
|
||||||
|
* index of such element. It returns |blk|->n if there is no such
|
||||||
|
* element.
|
||||||
|
*/
|
||||||
|
typedef size_t (*nghttp3_ksl_search)(const nghttp3_ksl *ksl,
|
||||||
|
nghttp3_ksl_blk *blk,
|
||||||
|
const nghttp3_ksl_key *key);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* nghttp3_ksl_search_def is a macro to implement nghttp3_ksl_search
|
||||||
|
* with COMPAR which is supposed to be nghttp3_ksl_compar.
|
||||||
|
*/
|
||||||
|
#define nghttp3_ksl_search_def(NAME, COMPAR) \
|
||||||
|
static size_t ksl_##NAME##_search(const nghttp3_ksl *ksl, \
|
||||||
|
nghttp3_ksl_blk *blk, \
|
||||||
|
const nghttp3_ksl_key *key) { \
|
||||||
|
size_t i; \
|
||||||
|
nghttp3_ksl_node *node; \
|
||||||
|
\
|
||||||
|
for (i = 0, node = (nghttp3_ksl_node *)(void *)blk->nodes; \
|
||||||
|
i < blk->n && COMPAR((nghttp3_ksl_key *)node->key, key); ++i, \
|
||||||
|
node = (nghttp3_ksl_node *)(void *)((uint8_t *)node + ksl->nodelen)) \
|
||||||
|
; \
|
||||||
|
\
|
||||||
|
return i; \
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct nghttp3_ksl_it nghttp3_ksl_it;
|
typedef struct nghttp3_ksl_it nghttp3_ksl_it;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -138,6 +167,7 @@ struct nghttp3_ksl {
|
||||||
/* back points to the last leaf block. */
|
/* back points to the last leaf block. */
|
||||||
nghttp3_ksl_blk *back;
|
nghttp3_ksl_blk *back;
|
||||||
nghttp3_ksl_compar compar;
|
nghttp3_ksl_compar compar;
|
||||||
|
nghttp3_ksl_search search;
|
||||||
/* n is the number of elements stored. */
|
/* n is the number of elements stored. */
|
||||||
size_t n;
|
size_t n;
|
||||||
/* keylen is the size of key */
|
/* keylen is the size of key */
|
||||||
|
@ -149,11 +179,13 @@ struct nghttp3_ksl {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* nghttp3_ksl_init initializes |ksl|. |compar| specifies compare
|
* nghttp3_ksl_init initializes |ksl|. |compar| specifies compare
|
||||||
* function. |keylen| is the length of key and must be at least
|
* function. |search| is a search function which must use |compar|.
|
||||||
|
* |keylen| is the length of key and must be at least
|
||||||
* sizeof(uint64_t).
|
* sizeof(uint64_t).
|
||||||
*/
|
*/
|
||||||
void nghttp3_ksl_init(nghttp3_ksl *ksl, nghttp3_ksl_compar compar,
|
void nghttp3_ksl_init(nghttp3_ksl *ksl, nghttp3_ksl_compar compar,
|
||||||
size_t keylen, const nghttp3_mem *mem);
|
nghttp3_ksl_search search, size_t keylen,
|
||||||
|
const nghttp3_mem *mem);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* nghttp3_ksl_free frees resources allocated for |ksl|. If |ksl| is
|
* nghttp3_ksl_free frees resources allocated for |ksl|. If |ksl| is
|
||||||
|
@ -218,12 +250,12 @@ nghttp3_ksl_it nghttp3_ksl_lower_bound(const nghttp3_ksl *ksl,
|
||||||
const nghttp3_ksl_key *key);
|
const nghttp3_ksl_key *key);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* nghttp3_ksl_lower_bound_compar works like nghttp3_ksl_lower_bound,
|
* nghttp3_ksl_lower_bound_search works like nghttp3_ksl_lower_bound,
|
||||||
* but it takes custom function |compar| to do lower bound search.
|
* but it takes custom function |search| to do lower bound search.
|
||||||
*/
|
*/
|
||||||
nghttp3_ksl_it nghttp3_ksl_lower_bound_compar(const nghttp3_ksl *ksl,
|
nghttp3_ksl_it nghttp3_ksl_lower_bound_search(const nghttp3_ksl *ksl,
|
||||||
const nghttp3_ksl_key *key,
|
const nghttp3_ksl_key *key,
|
||||||
nghttp3_ksl_compar compar);
|
nghttp3_ksl_search search);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* nghttp3_ksl_update_key replaces the key of nodes which has
|
* nghttp3_ksl_update_key replaces the key of nodes which has
|
||||||
|
@ -330,22 +362,69 @@ int nghttp3_ksl_it_begin(const nghttp3_ksl_it *it);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* nghttp3_ksl_range_compar is an implementation of
|
* nghttp3_ksl_range_compar is an implementation of
|
||||||
* nghttp3_ksl_compar. lhs->ptr and rhs->ptr must point to
|
* nghttp3_ksl_compar. |lhs| and |rhs| must point to nghttp3_range
|
||||||
* nghttp3_range object and the function returns nonzero if (const
|
* object, and the function returns nonzero if ((const nghttp3_range
|
||||||
* nghttp3_range *)(lhs->ptr)->begin < (const nghttp3_range
|
* *)lhs)->begin < ((const nghttp3_range *)rhs)->begin.
|
||||||
* *)(rhs->ptr)->begin.
|
|
||||||
*/
|
*/
|
||||||
int nghttp3_ksl_range_compar(const nghttp3_ksl_key *lhs,
|
int nghttp3_ksl_range_compar(const nghttp3_ksl_key *lhs,
|
||||||
const nghttp3_ksl_key *rhs);
|
const nghttp3_ksl_key *rhs);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* nghttp3_ksl_range_search is an implementation of nghttp3_ksl_search
|
||||||
|
* that uses nghttp3_ksl_range_compar.
|
||||||
|
*/
|
||||||
|
size_t nghttp3_ksl_range_search(const nghttp3_ksl *ksl, nghttp3_ksl_blk *blk,
|
||||||
|
const nghttp3_ksl_key *key);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* nghttp3_ksl_range_exclusive_compar is an implementation of
|
* nghttp3_ksl_range_exclusive_compar is an implementation of
|
||||||
* nghttp3_ksl_compar. lhs->ptr and rhs->ptr must point to
|
* nghttp3_ksl_compar. |lhs| and |rhs| must point to nghttp3_range
|
||||||
* nghttp3_range object and the function returns nonzero if (const
|
* object, and the function returns nonzero if ((const nghttp3_range
|
||||||
* nghttp3_range *)(lhs->ptr)->begin < (const nghttp3_range
|
* *)lhs)->begin < ((const nghttp3_range *)rhs)->begin, and the 2
|
||||||
* *)(rhs->ptr)->begin and the 2 ranges do not intersect.
|
* ranges do not intersect.
|
||||||
*/
|
*/
|
||||||
int nghttp3_ksl_range_exclusive_compar(const nghttp3_ksl_key *lhs,
|
int nghttp3_ksl_range_exclusive_compar(const nghttp3_ksl_key *lhs,
|
||||||
const nghttp3_ksl_key *rhs);
|
const nghttp3_ksl_key *rhs);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* nghttp3_ksl_range_exclusive_search is an implementation of
|
||||||
|
* nghttp3_ksl_search that uses nghttp3_ksl_range_exclusive_compar.
|
||||||
|
*/
|
||||||
|
size_t nghttp3_ksl_range_exclusive_search(const nghttp3_ksl *ksl,
|
||||||
|
nghttp3_ksl_blk *blk,
|
||||||
|
const nghttp3_ksl_key *key);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* nghttp3_ksl_uint64_less is an implementation of nghttp3_ksl_compar.
|
||||||
|
* |lhs| and |rhs| must point to uint64_t objects, and the function
|
||||||
|
* returns nonzero if *(uint64_t *)|lhs| < *(uint64_t *)|rhs|.
|
||||||
|
*/
|
||||||
|
int nghttp3_ksl_uint64_less(const nghttp3_ksl_key *lhs,
|
||||||
|
const nghttp3_ksl_key *rhs);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* nghttp3_ksl_uint64_less_search is an implementation of
|
||||||
|
* nghttp3_ksl_search that uses nghttp3_ksl_uint64_less.
|
||||||
|
*/
|
||||||
|
size_t nghttp3_ksl_uint64_less_search(const nghttp3_ksl *ksl,
|
||||||
|
nghttp3_ksl_blk *blk,
|
||||||
|
const nghttp3_ksl_key *key);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* nghttp3_ksl_int64_greater is an implementation of
|
||||||
|
* nghttp3_ksl_compar. |lhs| and |rhs| must point to int64_t objects,
|
||||||
|
* and the function returns nonzero if *(int64_t *)|lhs| > *(int64_t
|
||||||
|
* *)|rhs|.
|
||||||
|
*/
|
||||||
|
int nghttp3_ksl_int64_greater(const nghttp3_ksl_key *lhs,
|
||||||
|
const nghttp3_ksl_key *rhs);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* nghttp3_ksl_int64_greater_search is an implementation of
|
||||||
|
* nghttp3_ksl_search that uses nghttp3_ksl_int64_greater.
|
||||||
|
*/
|
||||||
|
size_t nghttp3_ksl_int64_greater_search(const nghttp3_ksl *ksl,
|
||||||
|
nghttp3_ksl_blk *blk,
|
||||||
|
const nghttp3_ksl_key *key);
|
||||||
|
|
||||||
#endif /* !defined(NGHTTP3_KSL_H) */
|
#endif /* !defined(NGHTTP3_KSL_H) */
|
||||||
|
|
|
@ -48,27 +48,27 @@
|
||||||
#define nghttp3_max_def(SUFFIX, T) \
|
#define nghttp3_max_def(SUFFIX, T) \
|
||||||
static inline T nghttp3_max_##SUFFIX(T a, T b) { return a < b ? b : a; }
|
static inline T nghttp3_max_##SUFFIX(T a, T b) { return a < b ? b : a; }
|
||||||
|
|
||||||
nghttp3_max_def(int8, int8_t);
|
nghttp3_max_def(int8, int8_t)
|
||||||
nghttp3_max_def(int16, int16_t);
|
nghttp3_max_def(int16, int16_t)
|
||||||
nghttp3_max_def(int32, int32_t);
|
nghttp3_max_def(int32, int32_t)
|
||||||
nghttp3_max_def(int64, int64_t);
|
nghttp3_max_def(int64, int64_t)
|
||||||
nghttp3_max_def(uint8, uint8_t);
|
nghttp3_max_def(uint8, uint8_t)
|
||||||
nghttp3_max_def(uint16, uint16_t);
|
nghttp3_max_def(uint16, uint16_t)
|
||||||
nghttp3_max_def(uint32, uint32_t);
|
nghttp3_max_def(uint32, uint32_t)
|
||||||
nghttp3_max_def(uint64, uint64_t);
|
nghttp3_max_def(uint64, uint64_t)
|
||||||
nghttp3_max_def(size, size_t);
|
nghttp3_max_def(size, size_t)
|
||||||
|
|
||||||
#define nghttp3_min_def(SUFFIX, T) \
|
#define nghttp3_min_def(SUFFIX, T) \
|
||||||
static inline T nghttp3_min_##SUFFIX(T a, T b) { return a < b ? a : b; }
|
static inline T nghttp3_min_##SUFFIX(T a, T b) { return a < b ? a : b; }
|
||||||
|
|
||||||
nghttp3_min_def(int8, int8_t);
|
nghttp3_min_def(int8, int8_t)
|
||||||
nghttp3_min_def(int16, int16_t);
|
nghttp3_min_def(int16, int16_t)
|
||||||
nghttp3_min_def(int32, int32_t);
|
nghttp3_min_def(int32, int32_t)
|
||||||
nghttp3_min_def(int64, int64_t);
|
nghttp3_min_def(int64, int64_t)
|
||||||
nghttp3_min_def(uint8, uint8_t);
|
nghttp3_min_def(uint8, uint8_t)
|
||||||
nghttp3_min_def(uint16, uint16_t);
|
nghttp3_min_def(uint16, uint16_t)
|
||||||
nghttp3_min_def(uint32, uint32_t);
|
nghttp3_min_def(uint32, uint32_t)
|
||||||
nghttp3_min_def(uint64, uint64_t);
|
nghttp3_min_def(uint64, uint64_t)
|
||||||
nghttp3_min_def(size, size_t);
|
nghttp3_min_def(size, size_t)
|
||||||
|
|
||||||
#endif /* !defined(NGHTTP3_MACRO_H) */
|
#endif /* !defined(NGHTTP3_MACRO_H) */
|
||||||
|
|
|
@ -120,7 +120,11 @@ void nghttp3_map_print_distance(const nghttp3_map *map) {
|
||||||
static int insert(nghttp3_map_bucket *table, size_t hashbits,
|
static int insert(nghttp3_map_bucket *table, size_t hashbits,
|
||||||
nghttp3_map_key_type key, void *data) {
|
nghttp3_map_key_type key, void *data) {
|
||||||
size_t idx = hash(key, hashbits);
|
size_t idx = hash(key, hashbits);
|
||||||
nghttp3_map_bucket b = {0, key, data}, *bkt;
|
nghttp3_map_bucket b = {
|
||||||
|
.key = key,
|
||||||
|
.data = data,
|
||||||
|
};
|
||||||
|
nghttp3_map_bucket *bkt;
|
||||||
size_t mask = (1u << hashbits) - 1;
|
size_t mask = (1u << hashbits) - 1;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
|
@ -164,20 +164,4 @@ int nghttp3_pq_empty(const nghttp3_pq *pq) { return pq->length == 0; }
|
||||||
|
|
||||||
size_t nghttp3_pq_size(const nghttp3_pq *pq) { return pq->length; }
|
size_t nghttp3_pq_size(const nghttp3_pq *pq) { return pq->length; }
|
||||||
|
|
||||||
int nghttp3_pq_each(const nghttp3_pq *pq, nghttp3_pq_item_cb fun, void *arg) {
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if (pq->length == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < pq->length; ++i) {
|
|
||||||
if ((*fun)(pq->q[i], arg)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void nghttp3_pq_clear(nghttp3_pq *pq) { pq->length = 0; }
|
void nghttp3_pq_clear(nghttp3_pq *pq) { pq->length = 0; }
|
||||||
|
|
|
@ -112,17 +112,6 @@ int nghttp3_pq_empty(const nghttp3_pq *pq);
|
||||||
*/
|
*/
|
||||||
size_t nghttp3_pq_size(const nghttp3_pq *pq);
|
size_t nghttp3_pq_size(const nghttp3_pq *pq);
|
||||||
|
|
||||||
typedef int (*nghttp3_pq_item_cb)(nghttp3_pq_entry *item, void *arg);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* nghttp3_pq_each applies |fun| to each item in |pq|. The |arg| is
|
|
||||||
* passed as arg parameter to callback function. This function must
|
|
||||||
* not change the ordering key. If the return value from callback is
|
|
||||||
* nonzero, this function returns 1 immediately without iterating
|
|
||||||
* remaining items. Otherwise this function returns 0.
|
|
||||||
*/
|
|
||||||
int nghttp3_pq_each(const nghttp3_pq *pq, nghttp3_pq_item_cb fun, void *arg);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* nghttp3_pq_remove removes |item| from |pq|. |pq| must contain
|
* nghttp3_pq_remove removes |item| from |pq|. |pq| must contain
|
||||||
* |item| otherwise the behavior is undefined.
|
* |item| otherwise the behavior is undefined.
|
||||||
|
|
|
@ -41,7 +41,12 @@
|
||||||
#define NGHTTP3_QPACK_MAX_QPACK_STREAMS 2000
|
#define NGHTTP3_QPACK_MAX_QPACK_STREAMS 2000
|
||||||
|
|
||||||
/* Make scalar initialization form of nghttp3_qpack_static_entry */
|
/* Make scalar initialization form of nghttp3_qpack_static_entry */
|
||||||
#define MAKE_STATIC_ENT(I, T, H) {I, T, H}
|
#define MAKE_STATIC_ENT(I, T, H) \
|
||||||
|
{ \
|
||||||
|
.absidx = I, \
|
||||||
|
.token = T, \
|
||||||
|
.hash = H, \
|
||||||
|
}
|
||||||
|
|
||||||
/* Generated by mkstatichdtbl.py */
|
/* Generated by mkstatichdtbl.py */
|
||||||
static nghttp3_qpack_static_entry token_stable[] = {
|
static nghttp3_qpack_static_entry token_stable[] = {
|
||||||
|
@ -166,9 +171,19 @@ static nghttp3_qpack_static_entry token_stable[] = {
|
||||||
/* Make scalar initialization form of nghttp3_qpack_static_entry */
|
/* Make scalar initialization form of nghttp3_qpack_static_entry */
|
||||||
#define MAKE_STATIC_HD(N, V, T) \
|
#define MAKE_STATIC_HD(N, V, T) \
|
||||||
{ \
|
{ \
|
||||||
{NULL, (uint8_t *)(N), sizeof((N)) - 1, -1}, \
|
.name = \
|
||||||
{NULL, (uint8_t *)(V), sizeof((V)) - 1, -1}, \
|
{ \
|
||||||
T, \
|
.base = (uint8_t *)(N), \
|
||||||
|
.len = sizeof((N)) - 1, \
|
||||||
|
.ref = -1, \
|
||||||
|
}, \
|
||||||
|
.value = \
|
||||||
|
{ \
|
||||||
|
.base = (uint8_t *)(V), \
|
||||||
|
.len = sizeof((V)) - 1, \
|
||||||
|
.ref = -1, \
|
||||||
|
}, \
|
||||||
|
.token = T, \
|
||||||
}
|
}
|
||||||
|
|
||||||
static nghttp3_qpack_static_header stable[] = {
|
static nghttp3_qpack_static_header stable[] = {
|
||||||
|
@ -828,29 +843,12 @@ static void encoder_qpack_map_find(nghttp3_qpack_encoder *encoder,
|
||||||
* ctx->max_dtable_capacity and it is initialized to 0.
|
* ctx->max_dtable_capacity and it is initialized to 0.
|
||||||
* |hard_max_dtable_capacity| is the upper bound of
|
* |hard_max_dtable_capacity| is the upper bound of
|
||||||
* ctx->max_dtable_capacity.
|
* ctx->max_dtable_capacity.
|
||||||
*
|
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
|
||||||
* negative error codes:
|
|
||||||
*
|
|
||||||
* NGHTTP3_ERR_NOMEM
|
|
||||||
* Out of memory.
|
|
||||||
*/
|
*/
|
||||||
static int qpack_context_init(nghttp3_qpack_context *ctx,
|
static void qpack_context_init(nghttp3_qpack_context *ctx,
|
||||||
size_t hard_max_dtable_capacity,
|
size_t hard_max_dtable_capacity,
|
||||||
size_t max_blocked_streams,
|
size_t max_blocked_streams,
|
||||||
const nghttp3_mem *mem) {
|
const nghttp3_mem *mem) {
|
||||||
int rv;
|
nghttp3_ringbuf_init(&ctx->dtable, 0, sizeof(nghttp3_qpack_entry *), mem);
|
||||||
size_t len = 4096 / NGHTTP3_QPACK_ENTRY_OVERHEAD;
|
|
||||||
size_t len2;
|
|
||||||
|
|
||||||
for (len2 = 1; len2 < len; len2 <<= 1)
|
|
||||||
;
|
|
||||||
|
|
||||||
rv = nghttp3_ringbuf_init(&ctx->dtable, len2, sizeof(nghttp3_qpack_entry *),
|
|
||||||
mem);
|
|
||||||
if (rv != 0) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->mem = mem;
|
ctx->mem = mem;
|
||||||
ctx->dtable_size = 0;
|
ctx->dtable_size = 0;
|
||||||
|
@ -860,8 +858,6 @@ static int qpack_context_init(nghttp3_qpack_context *ctx,
|
||||||
ctx->max_blocked_streams = max_blocked_streams;
|
ctx->max_blocked_streams = max_blocked_streams;
|
||||||
ctx->next_absidx = 0;
|
ctx->next_absidx = 0;
|
||||||
ctx->bad = 0;
|
ctx->bad = 0;
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qpack_context_free(nghttp3_qpack_context *ctx) {
|
static void qpack_context_free(nghttp3_qpack_context *ctx) {
|
||||||
|
@ -898,19 +894,17 @@ static int max_cnt_greater(const nghttp3_ksl_key *lhs,
|
||||||
return a->max_cnt > b->max_cnt || (a->max_cnt == b->max_cnt && a->id < b->id);
|
return a->max_cnt > b->max_cnt || (a->max_cnt == b->max_cnt && a->id < b->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
int nghttp3_qpack_encoder_init(nghttp3_qpack_encoder *encoder,
|
nghttp3_ksl_search_def(max_cnt_greater, max_cnt_greater)
|
||||||
size_t hard_max_dtable_capacity,
|
|
||||||
const nghttp3_mem *mem) {
|
|
||||||
int rv;
|
|
||||||
|
|
||||||
rv = qpack_context_init(&encoder->ctx, hard_max_dtable_capacity, 0, mem);
|
void nghttp3_qpack_encoder_init(nghttp3_qpack_encoder *encoder,
|
||||||
if (rv != 0) {
|
size_t hard_max_dtable_capacity,
|
||||||
return rv;
|
const nghttp3_mem *mem) {
|
||||||
}
|
qpack_context_init(&encoder->ctx, hard_max_dtable_capacity, 0, mem);
|
||||||
|
|
||||||
nghttp3_map_init(&encoder->streams, mem);
|
nghttp3_map_init(&encoder->streams, mem);
|
||||||
|
|
||||||
nghttp3_ksl_init(&encoder->blocked_streams, max_cnt_greater,
|
nghttp3_ksl_init(&encoder->blocked_streams, max_cnt_greater,
|
||||||
|
ksl_max_cnt_greater_search,
|
||||||
sizeof(nghttp3_blocked_streams_key), mem);
|
sizeof(nghttp3_blocked_streams_key), mem);
|
||||||
|
|
||||||
qpack_map_init(&encoder->dtable_map);
|
qpack_map_init(&encoder->dtable_map);
|
||||||
|
@ -925,8 +919,6 @@ int nghttp3_qpack_encoder_init(nghttp3_qpack_encoder *encoder,
|
||||||
encoder->flags = NGHTTP3_QPACK_ENCODER_FLAG_NONE;
|
encoder->flags = NGHTTP3_QPACK_ENCODER_FLAG_NONE;
|
||||||
|
|
||||||
nghttp3_qpack_read_state_reset(&encoder->rstate);
|
nghttp3_qpack_read_state_reset(&encoder->rstate);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int map_stream_free(void *data, void *ptr) {
|
static int map_stream_free(void *data, void *ptr) {
|
||||||
|
@ -1149,6 +1141,9 @@ int nghttp3_qpack_encoder_encode(nghttp3_qpack_encoder *encoder,
|
||||||
int blocked_stream;
|
int blocked_stream;
|
||||||
nghttp3_qpack_stream *stream;
|
nghttp3_qpack_stream *stream;
|
||||||
|
|
||||||
|
assert(stream_id >= 0);
|
||||||
|
assert(stream_id <= (int64_t)NGHTTP3_MAX_VARINT);
|
||||||
|
|
||||||
if (encoder->ctx.bad) {
|
if (encoder->ctx.bad) {
|
||||||
return NGHTTP3_ERR_QPACK_FATAL;
|
return NGHTTP3_ERR_QPACK_FATAL;
|
||||||
}
|
}
|
||||||
|
@ -1444,7 +1439,14 @@ int nghttp3_qpack_encoder_encode_nv(nghttp3_qpack_encoder *encoder,
|
||||||
uint32_t hash = 0;
|
uint32_t hash = 0;
|
||||||
int32_t token;
|
int32_t token;
|
||||||
nghttp3_qpack_indexing_mode indexing_mode;
|
nghttp3_qpack_indexing_mode indexing_mode;
|
||||||
nghttp3_qpack_lookup_result sres = {-1, 0, -1}, dres = {-1, 0, -1};
|
nghttp3_qpack_lookup_result sres = {
|
||||||
|
.index = -1,
|
||||||
|
.pb_index = -1,
|
||||||
|
};
|
||||||
|
nghttp3_qpack_lookup_result dres = {
|
||||||
|
.index = -1,
|
||||||
|
.pb_index = -1,
|
||||||
|
};
|
||||||
nghttp3_qpack_entry *new_ent = NULL;
|
nghttp3_qpack_entry *new_ent = NULL;
|
||||||
int static_entry;
|
int static_entry;
|
||||||
int just_index = 0;
|
int just_index = 0;
|
||||||
|
@ -1608,8 +1610,10 @@ int nghttp3_qpack_encoder_encode_nv(nghttp3_qpack_encoder *encoder,
|
||||||
nghttp3_qpack_lookup_result
|
nghttp3_qpack_lookup_result
|
||||||
nghttp3_qpack_lookup_stable(const nghttp3_nv *nv, int32_t token,
|
nghttp3_qpack_lookup_stable(const nghttp3_nv *nv, int32_t token,
|
||||||
nghttp3_qpack_indexing_mode indexing_mode) {
|
nghttp3_qpack_indexing_mode indexing_mode) {
|
||||||
nghttp3_qpack_lookup_result res = {(nghttp3_ssize)token_stable[token].absidx,
|
nghttp3_qpack_lookup_result res = {
|
||||||
0, -1};
|
.index = (nghttp3_ssize)token_stable[token].absidx,
|
||||||
|
.pb_index = -1,
|
||||||
|
};
|
||||||
nghttp3_qpack_static_entry *ent;
|
nghttp3_qpack_static_entry *ent;
|
||||||
nghttp3_qpack_static_header *hdr;
|
nghttp3_qpack_static_header *hdr;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
@ -1639,7 +1643,10 @@ nghttp3_qpack_lookup_result nghttp3_qpack_encoder_lookup_dtable(
|
||||||
nghttp3_qpack_encoder *encoder, const nghttp3_nv *nv, int32_t token,
|
nghttp3_qpack_encoder *encoder, const nghttp3_nv *nv, int32_t token,
|
||||||
uint32_t hash, nghttp3_qpack_indexing_mode indexing_mode, uint64_t krcnt,
|
uint32_t hash, nghttp3_qpack_indexing_mode indexing_mode, uint64_t krcnt,
|
||||||
int allow_blocking) {
|
int allow_blocking) {
|
||||||
nghttp3_qpack_lookup_result res = {-1, 0, -1};
|
nghttp3_qpack_lookup_result res = {
|
||||||
|
.index = -1,
|
||||||
|
.pb_index = -1,
|
||||||
|
};
|
||||||
int exact_match = 0;
|
int exact_match = 0;
|
||||||
nghttp3_qpack_entry *match, *pb_match;
|
nghttp3_qpack_entry *match, *pb_match;
|
||||||
|
|
||||||
|
@ -1694,7 +1701,6 @@ static int ref_max_cnt_greater(const nghttp3_pq_entry *lhsx,
|
||||||
|
|
||||||
int nghttp3_qpack_stream_new(nghttp3_qpack_stream **pstream, int64_t stream_id,
|
int nghttp3_qpack_stream_new(nghttp3_qpack_stream **pstream, int64_t stream_id,
|
||||||
const nghttp3_mem *mem) {
|
const nghttp3_mem *mem) {
|
||||||
int rv;
|
|
||||||
nghttp3_qpack_stream *stream;
|
nghttp3_qpack_stream *stream;
|
||||||
|
|
||||||
stream = nghttp3_mem_malloc(mem, sizeof(nghttp3_qpack_stream));
|
stream = nghttp3_mem_malloc(mem, sizeof(nghttp3_qpack_stream));
|
||||||
|
@ -1702,12 +1708,8 @@ int nghttp3_qpack_stream_new(nghttp3_qpack_stream **pstream, int64_t stream_id,
|
||||||
return NGHTTP3_ERR_NOMEM;
|
return NGHTTP3_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = nghttp3_ringbuf_init(&stream->refs, 4,
|
nghttp3_ringbuf_init(&stream->refs, 0,
|
||||||
sizeof(nghttp3_qpack_header_block_ref *), mem);
|
sizeof(nghttp3_qpack_header_block_ref *), mem);
|
||||||
if (rv != 0) {
|
|
||||||
nghttp3_mem_free(mem, stream);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
nghttp3_pq_init(&stream->max_cnts, ref_max_cnt_greater, mem);
|
nghttp3_pq_init(&stream->max_cnts, ref_max_cnt_greater, mem);
|
||||||
|
|
||||||
|
@ -1759,17 +1761,23 @@ int nghttp3_qpack_stream_add_ref(nghttp3_qpack_stream *stream,
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
if (nghttp3_ringbuf_full(&stream->refs)) {
|
if (nghttp3_ringbuf_full(&stream->refs)) {
|
||||||
rv = nghttp3_ringbuf_reserve(&stream->refs,
|
rv = nghttp3_ringbuf_reserve(
|
||||||
nghttp3_ringbuf_len(&stream->refs) * 2);
|
&stream->refs,
|
||||||
|
nghttp3_max_size(4, nghttp3_ringbuf_len(&stream->refs) * 2));
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rv = nghttp3_pq_push(&stream->max_cnts, &ref->max_cnts_pe);
|
||||||
|
if (rv != 0) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
dest = nghttp3_ringbuf_push_back(&stream->refs);
|
dest = nghttp3_ringbuf_push_back(&stream->refs);
|
||||||
*dest = ref;
|
*dest = ref;
|
||||||
|
|
||||||
return nghttp3_pq_push(&stream->max_cnts, &ref->max_cnts_pe);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nghttp3_qpack_stream_pop_ref(nghttp3_qpack_stream *stream) {
|
void nghttp3_qpack_stream_pop_ref(nghttp3_qpack_stream *stream) {
|
||||||
|
@ -1834,7 +1842,7 @@ static int qpack_encoder_write_indexed_name(nghttp3_qpack_encoder *encoder,
|
||||||
int h = 0;
|
int h = 0;
|
||||||
|
|
||||||
hlen = nghttp3_qpack_huffman_encode_count(nv->value, nv->valuelen);
|
hlen = nghttp3_qpack_huffman_encode_count(nv->value, nv->valuelen);
|
||||||
if (hlen * 4 < nv->valuelen * 3) {
|
if (hlen < nv->valuelen) {
|
||||||
h = 1;
|
h = 1;
|
||||||
len += nghttp3_qpack_put_varint_len(hlen, 7) + hlen;
|
len += nghttp3_qpack_put_varint_len(hlen, 7) + hlen;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1925,7 +1933,7 @@ static int qpack_encoder_write_literal(nghttp3_qpack_encoder *encoder,
|
||||||
int nh = 0, vh = 0;
|
int nh = 0, vh = 0;
|
||||||
|
|
||||||
nhlen = nghttp3_qpack_huffman_encode_count(nv->name, nv->namelen);
|
nhlen = nghttp3_qpack_huffman_encode_count(nv->name, nv->namelen);
|
||||||
if (nhlen * 4 < nv->namelen * 3) {
|
if (nhlen < nv->namelen) {
|
||||||
nh = 1;
|
nh = 1;
|
||||||
len = nghttp3_qpack_put_varint_len(nhlen, prefix) + nhlen;
|
len = nghttp3_qpack_put_varint_len(nhlen, prefix) + nhlen;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1933,7 +1941,7 @@ static int qpack_encoder_write_literal(nghttp3_qpack_encoder *encoder,
|
||||||
}
|
}
|
||||||
|
|
||||||
vhlen = nghttp3_qpack_huffman_encode_count(nv->value, nv->valuelen);
|
vhlen = nghttp3_qpack_huffman_encode_count(nv->value, nv->valuelen);
|
||||||
if (vhlen * 4 < nv->valuelen * 3) {
|
if (vhlen < nv->valuelen) {
|
||||||
vh = 1;
|
vh = 1;
|
||||||
len += nghttp3_qpack_put_varint_len(vhlen, 7) + vhlen;
|
len += nghttp3_qpack_put_varint_len(vhlen, 7) + vhlen;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2083,8 +2091,9 @@ int nghttp3_qpack_context_dtable_add(nghttp3_qpack_context *ctx,
|
||||||
hash);
|
hash);
|
||||||
|
|
||||||
if (nghttp3_ringbuf_full(&ctx->dtable)) {
|
if (nghttp3_ringbuf_full(&ctx->dtable)) {
|
||||||
rv = nghttp3_ringbuf_reserve(&ctx->dtable,
|
rv = nghttp3_ringbuf_reserve(
|
||||||
nghttp3_ringbuf_len(&ctx->dtable) * 2);
|
&ctx->dtable,
|
||||||
|
nghttp3_max_size(128, nghttp3_ringbuf_len(&ctx->dtable) * 2));
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -2259,10 +2268,11 @@ void nghttp3_qpack_entry_free(nghttp3_qpack_entry *ent) {
|
||||||
int nghttp3_qpack_encoder_block_stream(nghttp3_qpack_encoder *encoder,
|
int nghttp3_qpack_encoder_block_stream(nghttp3_qpack_encoder *encoder,
|
||||||
nghttp3_qpack_stream *stream) {
|
nghttp3_qpack_stream *stream) {
|
||||||
nghttp3_blocked_streams_key bsk = {
|
nghttp3_blocked_streams_key bsk = {
|
||||||
nghttp3_struct_of(nghttp3_pq_top(&stream->max_cnts),
|
.max_cnt = nghttp3_struct_of(nghttp3_pq_top(&stream->max_cnts),
|
||||||
nghttp3_qpack_header_block_ref, max_cnts_pe)
|
nghttp3_qpack_header_block_ref, max_cnts_pe)
|
||||||
->max_cnt,
|
->max_cnt,
|
||||||
(uint64_t)stream->stream_id};
|
.id = (uint64_t)stream->stream_id,
|
||||||
|
};
|
||||||
|
|
||||||
return nghttp3_ksl_insert(&encoder->blocked_streams, NULL, &bsk, stream);
|
return nghttp3_ksl_insert(&encoder->blocked_streams, NULL, &bsk, stream);
|
||||||
}
|
}
|
||||||
|
@ -2270,10 +2280,11 @@ int nghttp3_qpack_encoder_block_stream(nghttp3_qpack_encoder *encoder,
|
||||||
void nghttp3_qpack_encoder_unblock_stream(nghttp3_qpack_encoder *encoder,
|
void nghttp3_qpack_encoder_unblock_stream(nghttp3_qpack_encoder *encoder,
|
||||||
nghttp3_qpack_stream *stream) {
|
nghttp3_qpack_stream *stream) {
|
||||||
nghttp3_blocked_streams_key bsk = {
|
nghttp3_blocked_streams_key bsk = {
|
||||||
nghttp3_struct_of(nghttp3_pq_top(&stream->max_cnts),
|
.max_cnt = nghttp3_struct_of(nghttp3_pq_top(&stream->max_cnts),
|
||||||
nghttp3_qpack_header_block_ref, max_cnts_pe)
|
nghttp3_qpack_header_block_ref, max_cnts_pe)
|
||||||
->max_cnt,
|
->max_cnt,
|
||||||
(uint64_t)stream->stream_id};
|
.id = (uint64_t)stream->stream_id,
|
||||||
|
};
|
||||||
nghttp3_ksl_it it;
|
nghttp3_ksl_it it;
|
||||||
|
|
||||||
/* This is purely debugging purpose only */
|
/* This is purely debugging purpose only */
|
||||||
|
@ -2287,7 +2298,9 @@ void nghttp3_qpack_encoder_unblock_stream(nghttp3_qpack_encoder *encoder,
|
||||||
|
|
||||||
void nghttp3_qpack_encoder_unblock(nghttp3_qpack_encoder *encoder,
|
void nghttp3_qpack_encoder_unblock(nghttp3_qpack_encoder *encoder,
|
||||||
uint64_t max_cnt) {
|
uint64_t max_cnt) {
|
||||||
nghttp3_blocked_streams_key bsk = {max_cnt, 0};
|
nghttp3_blocked_streams_key bsk = {
|
||||||
|
.max_cnt = max_cnt,
|
||||||
|
};
|
||||||
nghttp3_ksl_it it;
|
nghttp3_ksl_it it;
|
||||||
|
|
||||||
it = nghttp3_ksl_lower_bound(&encoder->blocked_streams, &bsk);
|
it = nghttp3_ksl_lower_bound(&encoder->blocked_streams, &bsk);
|
||||||
|
@ -2667,17 +2680,12 @@ void nghttp3_qpack_read_state_reset(nghttp3_qpack_read_state *rstate) {
|
||||||
rstate->huffman_encoded = 0;
|
rstate->huffman_encoded = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nghttp3_qpack_decoder_init(nghttp3_qpack_decoder *decoder,
|
void nghttp3_qpack_decoder_init(nghttp3_qpack_decoder *decoder,
|
||||||
size_t hard_max_dtable_capacity,
|
size_t hard_max_dtable_capacity,
|
||||||
size_t max_blocked_streams,
|
size_t max_blocked_streams,
|
||||||
const nghttp3_mem *mem) {
|
const nghttp3_mem *mem) {
|
||||||
int rv;
|
qpack_context_init(&decoder->ctx, hard_max_dtable_capacity,
|
||||||
|
max_blocked_streams, mem);
|
||||||
rv = qpack_context_init(&decoder->ctx, hard_max_dtable_capacity,
|
|
||||||
max_blocked_streams, mem);
|
|
||||||
if (rv != 0) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
decoder->state = NGHTTP3_QPACK_ES_STATE_OPCODE;
|
decoder->state = NGHTTP3_QPACK_ES_STATE_OPCODE;
|
||||||
decoder->opcode = 0;
|
decoder->opcode = 0;
|
||||||
|
@ -2687,8 +2695,6 @@ int nghttp3_qpack_decoder_init(nghttp3_qpack_decoder *decoder,
|
||||||
|
|
||||||
nghttp3_qpack_read_state_reset(&decoder->rstate);
|
nghttp3_qpack_read_state_reset(&decoder->rstate);
|
||||||
nghttp3_buf_init(&decoder->dbuf);
|
nghttp3_buf_init(&decoder->dbuf);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nghttp3_qpack_decoder_free(nghttp3_qpack_decoder *decoder) {
|
void nghttp3_qpack_decoder_free(nghttp3_qpack_decoder *decoder) {
|
||||||
|
@ -3171,6 +3177,7 @@ int nghttp3_qpack_decoder_dtable_static_add(nghttp3_qpack_decoder *decoder) {
|
||||||
rv = nghttp3_qpack_context_dtable_add(&decoder->ctx, &qnv, NULL, 0);
|
rv = nghttp3_qpack_context_dtable_add(&decoder->ctx, &qnv, NULL, 0);
|
||||||
|
|
||||||
nghttp3_rcbuf_decref(qnv.value);
|
nghttp3_rcbuf_decref(qnv.value);
|
||||||
|
decoder->rstate.value = NULL;
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -3197,6 +3204,7 @@ int nghttp3_qpack_decoder_dtable_dynamic_add(nghttp3_qpack_decoder *decoder) {
|
||||||
rv = nghttp3_qpack_context_dtable_add(&decoder->ctx, &qnv, NULL, 0);
|
rv = nghttp3_qpack_context_dtable_add(&decoder->ctx, &qnv, NULL, 0);
|
||||||
|
|
||||||
nghttp3_rcbuf_decref(qnv.value);
|
nghttp3_rcbuf_decref(qnv.value);
|
||||||
|
decoder->rstate.value = NULL;
|
||||||
nghttp3_rcbuf_decref(qnv.name);
|
nghttp3_rcbuf_decref(qnv.name);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -3250,7 +3258,9 @@ int nghttp3_qpack_decoder_dtable_literal_add(nghttp3_qpack_decoder *decoder) {
|
||||||
rv = nghttp3_qpack_context_dtable_add(&decoder->ctx, &qnv, NULL, 0);
|
rv = nghttp3_qpack_context_dtable_add(&decoder->ctx, &qnv, NULL, 0);
|
||||||
|
|
||||||
nghttp3_rcbuf_decref(qnv.value);
|
nghttp3_rcbuf_decref(qnv.value);
|
||||||
|
decoder->rstate.value = NULL;
|
||||||
nghttp3_rcbuf_decref(qnv.name);
|
nghttp3_rcbuf_decref(qnv.name);
|
||||||
|
decoder->rstate.name = NULL;
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -3818,6 +3828,9 @@ int nghttp3_qpack_decoder_cancel_stream(nghttp3_qpack_decoder *decoder,
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
|
assert(stream_id >= 0);
|
||||||
|
assert(stream_id <= (int64_t)NGHTTP3_MAX_VARINT);
|
||||||
|
|
||||||
if (qpack_decoder_dbuf_overflow(decoder)) {
|
if (qpack_decoder_dbuf_overflow(decoder)) {
|
||||||
return NGHTTP3_ERR_QPACK_FATAL;
|
return NGHTTP3_ERR_QPACK_FATAL;
|
||||||
}
|
}
|
||||||
|
@ -4062,7 +4075,6 @@ void nghttp3_qpack_decoder_emit_literal(nghttp3_qpack_decoder *decoder,
|
||||||
int nghttp3_qpack_encoder_new(nghttp3_qpack_encoder **pencoder,
|
int nghttp3_qpack_encoder_new(nghttp3_qpack_encoder **pencoder,
|
||||||
size_t hard_max_dtable_capacity,
|
size_t hard_max_dtable_capacity,
|
||||||
const nghttp3_mem *mem) {
|
const nghttp3_mem *mem) {
|
||||||
int rv;
|
|
||||||
nghttp3_qpack_encoder *p;
|
nghttp3_qpack_encoder *p;
|
||||||
|
|
||||||
p = nghttp3_mem_malloc(mem, sizeof(nghttp3_qpack_encoder));
|
p = nghttp3_mem_malloc(mem, sizeof(nghttp3_qpack_encoder));
|
||||||
|
@ -4070,10 +4082,7 @@ int nghttp3_qpack_encoder_new(nghttp3_qpack_encoder **pencoder,
|
||||||
return NGHTTP3_ERR_NOMEM;
|
return NGHTTP3_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = nghttp3_qpack_encoder_init(p, hard_max_dtable_capacity, mem);
|
nghttp3_qpack_encoder_init(p, hard_max_dtable_capacity, mem);
|
||||||
if (rv != 0) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
*pencoder = p;
|
*pencoder = p;
|
||||||
|
|
||||||
|
@ -4098,6 +4107,9 @@ int nghttp3_qpack_stream_context_new(nghttp3_qpack_stream_context **psctx,
|
||||||
const nghttp3_mem *mem) {
|
const nghttp3_mem *mem) {
|
||||||
nghttp3_qpack_stream_context *p;
|
nghttp3_qpack_stream_context *p;
|
||||||
|
|
||||||
|
assert(stream_id >= 0);
|
||||||
|
assert(stream_id <= (int64_t)NGHTTP3_MAX_VARINT);
|
||||||
|
|
||||||
p = nghttp3_mem_malloc(mem, sizeof(nghttp3_qpack_stream_context));
|
p = nghttp3_mem_malloc(mem, sizeof(nghttp3_qpack_stream_context));
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
return NGHTTP3_ERR_NOMEM;
|
return NGHTTP3_ERR_NOMEM;
|
||||||
|
@ -4127,7 +4139,6 @@ int nghttp3_qpack_decoder_new(nghttp3_qpack_decoder **pdecoder,
|
||||||
size_t hard_max_dtable_capacity,
|
size_t hard_max_dtable_capacity,
|
||||||
size_t max_blocked_streams,
|
size_t max_blocked_streams,
|
||||||
const nghttp3_mem *mem) {
|
const nghttp3_mem *mem) {
|
||||||
int rv;
|
|
||||||
nghttp3_qpack_decoder *p;
|
nghttp3_qpack_decoder *p;
|
||||||
|
|
||||||
p = nghttp3_mem_malloc(mem, sizeof(nghttp3_qpack_decoder));
|
p = nghttp3_mem_malloc(mem, sizeof(nghttp3_qpack_decoder));
|
||||||
|
@ -4135,11 +4146,8 @@ int nghttp3_qpack_decoder_new(nghttp3_qpack_decoder **pdecoder,
|
||||||
return NGHTTP3_ERR_NOMEM;
|
return NGHTTP3_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = nghttp3_qpack_decoder_init(p, hard_max_dtable_capacity,
|
nghttp3_qpack_decoder_init(p, hard_max_dtable_capacity, max_blocked_streams,
|
||||||
max_blocked_streams, mem);
|
mem);
|
||||||
if (rv != 0) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
*pdecoder = p;
|
*pdecoder = p;
|
||||||
|
|
||||||
|
|
|
@ -270,16 +270,10 @@ struct nghttp3_qpack_encoder {
|
||||||
* nghttp3_qpack_encoder_init initializes |encoder|.
|
* nghttp3_qpack_encoder_init initializes |encoder|.
|
||||||
* |hard_max_dtable_capacity| is the upper bound of the dynamic table
|
* |hard_max_dtable_capacity| is the upper bound of the dynamic table
|
||||||
* capacity. |mem| is a memory allocator.
|
* capacity. |mem| is a memory allocator.
|
||||||
*
|
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
|
||||||
* negative error codes:
|
|
||||||
*
|
|
||||||
* NGHTTP3_ERR_NOMEM
|
|
||||||
* Out of memory.
|
|
||||||
*/
|
*/
|
||||||
int nghttp3_qpack_encoder_init(nghttp3_qpack_encoder *encoder,
|
void nghttp3_qpack_encoder_init(nghttp3_qpack_encoder *encoder,
|
||||||
size_t hard_max_dtable_capacity,
|
size_t hard_max_dtable_capacity,
|
||||||
const nghttp3_mem *mem);
|
const nghttp3_mem *mem);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* nghttp3_qpack_encoder_free frees memory allocated for |encoder|.
|
* nghttp3_qpack_encoder_free frees memory allocated for |encoder|.
|
||||||
|
@ -800,17 +794,11 @@ struct nghttp3_qpack_decoder {
|
||||||
* |hard_max_dtable_capacity| is the upper bound of the dynamic table
|
* |hard_max_dtable_capacity| is the upper bound of the dynamic table
|
||||||
* capacity. |max_blocked_streams| is the maximum number of stream
|
* capacity. |max_blocked_streams| is the maximum number of stream
|
||||||
* which can be blocked. |mem| is a memory allocator.
|
* which can be blocked. |mem| is a memory allocator.
|
||||||
*
|
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
|
||||||
* negative error codes:
|
|
||||||
*
|
|
||||||
* NGHTTP3_ERR_NOMEM
|
|
||||||
* Out of memory.
|
|
||||||
*/
|
*/
|
||||||
int nghttp3_qpack_decoder_init(nghttp3_qpack_decoder *decoder,
|
void nghttp3_qpack_decoder_init(nghttp3_qpack_decoder *decoder,
|
||||||
size_t hard_max_dtable_capacity,
|
size_t hard_max_dtable_capacity,
|
||||||
size_t max_blocked_streams,
|
size_t max_blocked_streams,
|
||||||
const nghttp3_mem *mem);
|
const nghttp3_mem *mem);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* nghttp3_qpack_decoder_free frees memory allocated for |decoder|.
|
* nghttp3_qpack_decoder_free frees memory allocated for |decoder|.
|
||||||
|
|
|
@ -88,7 +88,9 @@ nghttp3_qpack_huffman_decode(nghttp3_qpack_huffman_decode_context *ctx,
|
||||||
int fin) {
|
int fin) {
|
||||||
uint8_t *p = dest;
|
uint8_t *p = dest;
|
||||||
const uint8_t *end = src + srclen;
|
const uint8_t *end = src + srclen;
|
||||||
nghttp3_qpack_huffman_decode_node node = {ctx->fstate, 0};
|
nghttp3_qpack_huffman_decode_node node = {
|
||||||
|
.fstate = ctx->fstate,
|
||||||
|
};
|
||||||
const nghttp3_qpack_huffman_decode_node *t = &node;
|
const nghttp3_qpack_huffman_decode_node *t = &node;
|
||||||
uint8_t c;
|
uint8_t c;
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ void nghttp3_range_init(nghttp3_range *r, uint64_t begin, uint64_t end) {
|
||||||
|
|
||||||
nghttp3_range nghttp3_range_intersect(const nghttp3_range *a,
|
nghttp3_range nghttp3_range_intersect(const nghttp3_range *a,
|
||||||
const nghttp3_range *b) {
|
const nghttp3_range *b) {
|
||||||
nghttp3_range r = {0, 0};
|
nghttp3_range r = {0};
|
||||||
uint64_t begin = nghttp3_max_uint64(a->begin, b->begin);
|
uint64_t begin = nghttp3_max_uint64(a->begin, b->begin);
|
||||||
uint64_t end = nghttp3_min_uint64(a->end, b->end);
|
uint64_t end = nghttp3_min_uint64(a->end, b->end);
|
||||||
|
|
||||||
|
|
|
@ -33,18 +33,21 @@
|
||||||
|
|
||||||
#include "nghttp3_macro.h"
|
#include "nghttp3_macro.h"
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
static int ispow2(size_t n) {
|
static int ispow2(size_t n) {
|
||||||
#if defined(_MSC_VER) && !defined(__clang__) && \
|
# if defined(DISABLE_POPCNT) || \
|
||||||
(defined(_M_ARM) || (defined(_M_ARM64) && _MSC_VER < 1941))
|
(defined(_MSC_VER) && !defined(__clang__) && \
|
||||||
|
(defined(_M_ARM) || (defined(_M_ARM64) && _MSC_VER < 1941)))
|
||||||
return n && !(n & (n - 1));
|
return n && !(n & (n - 1));
|
||||||
#elif defined(WIN32)
|
# elif defined(WIN32)
|
||||||
return 1 == __popcnt((unsigned int)n);
|
return 1 == __popcnt((unsigned int)n);
|
||||||
#else /* !((defined(_MSC_VER) && !defined(__clang__) && (defined(_M_ARM) || \
|
# else /* !((defined(_MSC_VER) && !defined(__clang__) && (defined(_M_ARM) || \
|
||||||
(defined(_M_ARM64) && _MSC_VER < 1941))) || defined(WIN32)) */
|
(defined(_M_ARM64) && _MSC_VER < 1941))) || defined(WIN32)) */
|
||||||
return 1 == __builtin_popcount((unsigned int)n);
|
return 1 == __builtin_popcount((unsigned int)n);
|
||||||
#endif /* !((defined(_MSC_VER) && !defined(__clang__) && (defined(_M_ARM) || \
|
# endif /* !((defined(_MSC_VER) && !defined(__clang__) && (defined(_M_ARM) || \
|
||||||
(defined(_M_ARM64) && _MSC_VER < 1941))) || defined(WIN32)) */
|
(defined(_M_ARM64) && _MSC_VER < 1941))) || defined(WIN32)) */
|
||||||
}
|
}
|
||||||
|
#endif /* !defined(NDEBUG) */
|
||||||
|
|
||||||
int nghttp3_ringbuf_init(nghttp3_ringbuf *rb, size_t nmemb, size_t size,
|
int nghttp3_ringbuf_init(nghttp3_ringbuf *rb, size_t nmemb, size_t size,
|
||||||
const nghttp3_mem *mem) {
|
const nghttp3_mem *mem) {
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
/* NGHTTP3_MIN_RBLEN is the minimum length of nghttp3_ringbuf */
|
/* NGHTTP3_MIN_RBLEN is the minimum length of nghttp3_ringbuf */
|
||||||
#define NGHTTP3_MIN_RBLEN 4
|
#define NGHTTP3_MIN_RBLEN 4
|
||||||
|
|
||||||
nghttp3_objalloc_def(stream, nghttp3_stream, oplent);
|
nghttp3_objalloc_def(stream, nghttp3_stream, oplent)
|
||||||
|
|
||||||
int nghttp3_stream_new(nghttp3_stream **pstream, int64_t stream_id,
|
int nghttp3_stream_new(nghttp3_stream **pstream, int64_t stream_id,
|
||||||
const nghttp3_stream_callbacks *callbacks,
|
const nghttp3_stream_callbacks *callbacks,
|
||||||
|
@ -181,42 +181,45 @@ void nghttp3_stream_read_state_reset(nghttp3_stream_read_state *rstate) {
|
||||||
nghttp3_ssize nghttp3_read_varint(nghttp3_varint_read_state *rvint,
|
nghttp3_ssize nghttp3_read_varint(nghttp3_varint_read_state *rvint,
|
||||||
const uint8_t *begin, const uint8_t *end,
|
const uint8_t *begin, const uint8_t *end,
|
||||||
int fin) {
|
int fin) {
|
||||||
const uint8_t *orig_begin = begin;
|
size_t len, vlen;
|
||||||
size_t len;
|
uint8_t *p;
|
||||||
|
|
||||||
assert(begin != end);
|
assert(begin != end);
|
||||||
|
|
||||||
if (rvint->left == 0) {
|
if (rvint->left == 0) {
|
||||||
assert(rvint->acc == 0);
|
assert(rvint->acc == 0);
|
||||||
|
|
||||||
len = nghttp3_get_varintlen(begin);
|
vlen = nghttp3_get_varintlen(begin);
|
||||||
if (len <= (size_t)(end - begin)) {
|
len = nghttp3_min_size(vlen, (size_t)(end - begin));
|
||||||
|
if (vlen <= len) {
|
||||||
nghttp3_get_varint(&rvint->acc, begin);
|
nghttp3_get_varint(&rvint->acc, begin);
|
||||||
return (nghttp3_ssize)len;
|
return (nghttp3_ssize)vlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fin) {
|
if (fin) {
|
||||||
return NGHTTP3_ERR_INVALID_ARGUMENT;
|
return NGHTTP3_ERR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
rvint->acc = nghttp3_get_varint_fb(begin++);
|
p = (uint8_t *)&rvint->acc + (sizeof(rvint->acc) - vlen);
|
||||||
rvint->left = len - 1;
|
memcpy(p, begin, len);
|
||||||
|
*p &= 0x3f;
|
||||||
|
rvint->left = vlen - len;
|
||||||
|
|
||||||
|
return (nghttp3_ssize)len;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = nghttp3_min_size(rvint->left, (size_t)(end - begin));
|
len = nghttp3_min_size(rvint->left, (size_t)(end - begin));
|
||||||
end = begin + len;
|
p = (uint8_t *)&rvint->acc + (sizeof(rvint->acc) - rvint->left);
|
||||||
|
memcpy(p, begin, len);
|
||||||
for (; begin != end;) {
|
|
||||||
rvint->acc = (rvint->acc << 8) + *begin++;
|
|
||||||
}
|
|
||||||
|
|
||||||
rvint->left -= len;
|
rvint->left -= len;
|
||||||
|
|
||||||
if (fin && rvint->left) {
|
if (rvint->left == 0) {
|
||||||
|
rvint->acc = (int64_t)nghttp3_ntohl64((uint64_t)rvint->acc);
|
||||||
|
} else if (fin) {
|
||||||
return NGHTTP3_ERR_INVALID_ARGUMENT;
|
return NGHTTP3_ERR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (nghttp3_ssize)(begin - orig_begin);
|
return (nghttp3_ssize)len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nghttp3_stream_frq_add(nghttp3_stream *stream,
|
int nghttp3_stream_frq_add(nghttp3_stream *stream,
|
||||||
|
@ -301,12 +304,6 @@ int nghttp3_stream_fill_outq(nghttp3_stream *stream) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void typed_buf_shared_init(nghttp3_typed_buf *tbuf,
|
|
||||||
const nghttp3_buf *chunk) {
|
|
||||||
nghttp3_typed_buf_init(tbuf, chunk, NGHTTP3_BUF_TYPE_SHARED);
|
|
||||||
tbuf->buf.pos = tbuf->buf.last;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nghttp3_stream_write_stream_type(nghttp3_stream *stream) {
|
int nghttp3_stream_write_stream_type(nghttp3_stream *stream) {
|
||||||
size_t len = nghttp3_put_varintlen((int64_t)stream->type);
|
size_t len = nghttp3_put_varintlen((int64_t)stream->type);
|
||||||
nghttp3_buf *chunk;
|
nghttp3_buf *chunk;
|
||||||
|
@ -319,7 +316,7 @@ int nghttp3_stream_write_stream_type(nghttp3_stream *stream) {
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk = nghttp3_stream_get_chunk(stream);
|
chunk = nghttp3_stream_get_chunk(stream);
|
||||||
typed_buf_shared_init(&tbuf, chunk);
|
nghttp3_typed_buf_shared_init(&tbuf, chunk);
|
||||||
|
|
||||||
chunk->last = nghttp3_put_varint(chunk->last, (int64_t)stream->type);
|
chunk->last = nghttp3_put_varint(chunk->last, (int64_t)stream->type);
|
||||||
tbuf.buf.last = chunk->last;
|
tbuf.buf.last = chunk->last;
|
||||||
|
@ -336,12 +333,19 @@ int nghttp3_stream_write_settings(nghttp3_stream *stream,
|
||||||
struct {
|
struct {
|
||||||
nghttp3_frame_settings settings;
|
nghttp3_frame_settings settings;
|
||||||
nghttp3_settings_entry iv[15];
|
nghttp3_settings_entry iv[15];
|
||||||
} fr;
|
} fr = {
|
||||||
|
.settings =
|
||||||
|
{
|
||||||
|
.hd =
|
||||||
|
{
|
||||||
|
.type = NGHTTP3_FRAME_SETTINGS,
|
||||||
|
},
|
||||||
|
.niv = 3,
|
||||||
|
},
|
||||||
|
};
|
||||||
nghttp3_settings_entry *iv;
|
nghttp3_settings_entry *iv;
|
||||||
nghttp3_settings *local_settings = frent->aux.settings.local_settings;
|
nghttp3_settings *local_settings = frent->aux.settings.local_settings;
|
||||||
|
|
||||||
fr.settings.hd.type = NGHTTP3_FRAME_SETTINGS;
|
|
||||||
fr.settings.niv = 3;
|
|
||||||
iv = &fr.settings.iv[0];
|
iv = &fr.settings.iv[0];
|
||||||
|
|
||||||
iv[0].id = NGHTTP3_SETTINGS_ID_MAX_FIELD_SECTION_SIZE;
|
iv[0].id = NGHTTP3_SETTINGS_ID_MAX_FIELD_SECTION_SIZE;
|
||||||
|
@ -373,7 +377,7 @@ int nghttp3_stream_write_settings(nghttp3_stream *stream,
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk = nghttp3_stream_get_chunk(stream);
|
chunk = nghttp3_stream_get_chunk(stream);
|
||||||
typed_buf_shared_init(&tbuf, chunk);
|
nghttp3_typed_buf_shared_init(&tbuf, chunk);
|
||||||
|
|
||||||
chunk->last = nghttp3_frame_write_settings(chunk->last, &fr.settings);
|
chunk->last = nghttp3_frame_write_settings(chunk->last, &fr.settings);
|
||||||
|
|
||||||
|
@ -398,7 +402,7 @@ int nghttp3_stream_write_goaway(nghttp3_stream *stream,
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk = nghttp3_stream_get_chunk(stream);
|
chunk = nghttp3_stream_get_chunk(stream);
|
||||||
typed_buf_shared_init(&tbuf, chunk);
|
nghttp3_typed_buf_shared_init(&tbuf, chunk);
|
||||||
|
|
||||||
chunk->last = nghttp3_frame_write_goaway(chunk->last, fr);
|
chunk->last = nghttp3_frame_write_goaway(chunk->last, fr);
|
||||||
|
|
||||||
|
@ -423,7 +427,7 @@ int nghttp3_stream_write_priority_update(nghttp3_stream *stream,
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk = nghttp3_stream_get_chunk(stream);
|
chunk = nghttp3_stream_get_chunk(stream);
|
||||||
typed_buf_shared_init(&tbuf, chunk);
|
nghttp3_typed_buf_shared_init(&tbuf, chunk);
|
||||||
|
|
||||||
chunk->last = nghttp3_frame_write_priority_update(chunk->last, fr);
|
chunk->last = nghttp3_frame_write_priority_update(chunk->last, fr);
|
||||||
|
|
||||||
|
@ -464,7 +468,7 @@ int nghttp3_stream_write_header_block(nghttp3_stream *stream,
|
||||||
rv = nghttp3_qpack_encoder_encode(qenc, &pbuf, rbuf, ebuf, stream->node.id,
|
rv = nghttp3_qpack_encoder_encode(qenc, &pbuf, rbuf, ebuf, stream->node.id,
|
||||||
nva, nvlen);
|
nva, nvlen);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
goto fail;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
pbuflen = nghttp3_buf_len(&pbuf);
|
pbuflen = nghttp3_buf_len(&pbuf);
|
||||||
|
@ -482,11 +486,11 @@ int nghttp3_stream_write_header_block(nghttp3_stream *stream,
|
||||||
|
|
||||||
rv = nghttp3_stream_ensure_chunk(stream, len);
|
rv = nghttp3_stream_ensure_chunk(stream, len);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
goto fail;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk = nghttp3_stream_get_chunk(stream);
|
chunk = nghttp3_stream_get_chunk(stream);
|
||||||
typed_buf_shared_init(&tbuf, chunk);
|
nghttp3_typed_buf_shared_init(&tbuf, chunk);
|
||||||
|
|
||||||
chunk->last = nghttp3_frame_write_hd(chunk->last, &hd);
|
chunk->last = nghttp3_frame_write_hd(chunk->last, &hd);
|
||||||
|
|
||||||
|
@ -498,13 +502,13 @@ int nghttp3_stream_write_header_block(nghttp3_stream *stream,
|
||||||
|
|
||||||
rv = nghttp3_stream_outq_add(stream, &tbuf);
|
rv = nghttp3_stream_outq_add(stream, &tbuf);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
goto fail;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
nghttp3_typed_buf_init(&tbuf, rbuf, NGHTTP3_BUF_TYPE_PRIVATE);
|
nghttp3_typed_buf_init(&tbuf, rbuf, NGHTTP3_BUF_TYPE_PRIVATE);
|
||||||
rv = nghttp3_stream_outq_add(stream, &tbuf);
|
rv = nghttp3_stream_outq_add(stream, &tbuf);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
goto fail;
|
return rv;
|
||||||
}
|
}
|
||||||
nghttp3_buf_init(rbuf);
|
nghttp3_buf_init(rbuf);
|
||||||
} else if (rbuflen) {
|
} else if (rbuflen) {
|
||||||
|
@ -513,7 +517,7 @@ int nghttp3_stream_write_header_block(nghttp3_stream *stream,
|
||||||
|
|
||||||
rv = nghttp3_stream_outq_add(stream, &tbuf);
|
rv = nghttp3_stream_outq_add(stream, &tbuf);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
goto fail;
|
return rv;
|
||||||
}
|
}
|
||||||
nghttp3_buf_reset(rbuf);
|
nghttp3_buf_reset(rbuf);
|
||||||
}
|
}
|
||||||
|
@ -532,18 +536,18 @@ int nghttp3_stream_write_header_block(nghttp3_stream *stream,
|
||||||
|
|
||||||
rv = nghttp3_stream_ensure_chunk(qenc_stream, ebuflen);
|
rv = nghttp3_stream_ensure_chunk(qenc_stream, ebuflen);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
goto fail;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk = nghttp3_stream_get_chunk(qenc_stream);
|
chunk = nghttp3_stream_get_chunk(qenc_stream);
|
||||||
typed_buf_shared_init(&tbuf, chunk);
|
nghttp3_typed_buf_shared_init(&tbuf, chunk);
|
||||||
|
|
||||||
chunk->last = nghttp3_cpymem(chunk->last, ebuf->pos, ebuflen);
|
chunk->last = nghttp3_cpymem(chunk->last, ebuf->pos, ebuflen);
|
||||||
tbuf.buf.last = chunk->last;
|
tbuf.buf.last = chunk->last;
|
||||||
|
|
||||||
rv = nghttp3_stream_outq_add(qenc_stream, &tbuf);
|
rv = nghttp3_stream_outq_add(qenc_stream, &tbuf);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
goto fail;
|
return rv;
|
||||||
}
|
}
|
||||||
nghttp3_buf_reset(ebuf);
|
nghttp3_buf_reset(ebuf);
|
||||||
}
|
}
|
||||||
|
@ -553,10 +557,6 @@ int nghttp3_stream_write_header_block(nghttp3_stream *stream,
|
||||||
assert(0 == nghttp3_buf_len(ebuf));
|
assert(0 == nghttp3_buf_len(ebuf));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int nghttp3_stream_write_data(nghttp3_stream *stream, int *peof,
|
int nghttp3_stream_write_data(nghttp3_stream *stream, int *peof,
|
||||||
|
@ -635,7 +635,7 @@ int nghttp3_stream_write_data(nghttp3_stream *stream, int *peof,
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk = nghttp3_stream_get_chunk(stream);
|
chunk = nghttp3_stream_get_chunk(stream);
|
||||||
typed_buf_shared_init(&tbuf, chunk);
|
nghttp3_typed_buf_shared_init(&tbuf, chunk);
|
||||||
|
|
||||||
chunk->last = nghttp3_frame_write_hd(chunk->last, &hd);
|
chunk->last = nghttp3_frame_write_hd(chunk->last, &hd);
|
||||||
|
|
||||||
|
@ -690,7 +690,7 @@ int nghttp3_stream_write_qpack_decoder_stream(nghttp3_stream *stream) {
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk = nghttp3_stream_get_chunk(stream);
|
chunk = nghttp3_stream_get_chunk(stream);
|
||||||
typed_buf_shared_init(&tbuf, chunk);
|
nghttp3_typed_buf_shared_init(&tbuf, chunk);
|
||||||
|
|
||||||
nghttp3_qpack_decoder_write_decoder(qdec, chunk);
|
nghttp3_qpack_decoder_write_decoder(qdec, chunk);
|
||||||
|
|
||||||
|
@ -717,17 +717,16 @@ int nghttp3_stream_outq_add(nghttp3_stream *stream,
|
||||||
if (len) {
|
if (len) {
|
||||||
dest = nghttp3_ringbuf_get(outq, len - 1);
|
dest = nghttp3_ringbuf_get(outq, len - 1);
|
||||||
if (dest->type == tbuf->type && dest->type == NGHTTP3_BUF_TYPE_SHARED &&
|
if (dest->type == tbuf->type && dest->type == NGHTTP3_BUF_TYPE_SHARED &&
|
||||||
dest->buf.begin == tbuf->buf.begin && dest->buf.last == tbuf->buf.pos) {
|
dest->buf.end == tbuf->buf.end && dest->buf.last == tbuf->buf.pos) {
|
||||||
/* If we have already written last entry, adjust outq_idx and
|
/* If we have already written last entry, adjust outq_idx and
|
||||||
offset so that this entry is eligible to send. */
|
offset so that this entry is eligible to send. */
|
||||||
if (len == stream->outq_idx) {
|
if (len == stream->outq_idx) {
|
||||||
--stream->outq_idx;
|
--stream->outq_idx;
|
||||||
stream->outq_offset = nghttp3_buf_len(&dest->buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dest->buf.last = tbuf->buf.last;
|
dest->buf.last = tbuf->buf.last;
|
||||||
/* TODO Is this required? */
|
|
||||||
dest->buf.end = tbuf->buf.end;
|
assert(dest->buf.end == tbuf->buf.end);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -817,34 +816,24 @@ size_t nghttp3_stream_writev(nghttp3_stream *stream, int *pfin,
|
||||||
nghttp3_ringbuf *outq = &stream->outq;
|
nghttp3_ringbuf *outq = &stream->outq;
|
||||||
size_t len = nghttp3_ringbuf_len(outq);
|
size_t len = nghttp3_ringbuf_len(outq);
|
||||||
size_t i = stream->outq_idx;
|
size_t i = stream->outq_idx;
|
||||||
uint64_t offset = stream->outq_offset;
|
|
||||||
size_t buflen;
|
size_t buflen;
|
||||||
nghttp3_vec *vbegin = vec, *vend = vec + veccnt;
|
nghttp3_vec *vbegin = vec, *vend = vec + veccnt;
|
||||||
nghttp3_typed_buf *tbuf;
|
nghttp3_typed_buf *tbuf;
|
||||||
|
|
||||||
assert(veccnt > 0);
|
assert(veccnt > 0);
|
||||||
|
|
||||||
if (i < len) {
|
for (; i < len && vec != vend; ++i) {
|
||||||
tbuf = nghttp3_ringbuf_get(outq, i);
|
tbuf = nghttp3_ringbuf_get(outq, i);
|
||||||
buflen = nghttp3_buf_len(&tbuf->buf);
|
buflen = nghttp3_buf_len(&tbuf->buf);
|
||||||
|
|
||||||
if (offset < buflen) {
|
if (buflen == 0) {
|
||||||
vec->base = tbuf->buf.pos + offset;
|
continue;
|
||||||
vec->len = (size_t)(buflen - offset);
|
|
||||||
++vec;
|
|
||||||
} else {
|
|
||||||
/* This is the only case that satisfies offset >= buflen */
|
|
||||||
assert(0 == offset);
|
|
||||||
assert(0 == buflen);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
++i;
|
vec->base = tbuf->buf.pos;
|
||||||
|
vec->len = buflen;
|
||||||
|
|
||||||
for (; i < len && vec != vend; ++i, ++vec) {
|
++vec;
|
||||||
tbuf = nghttp3_ringbuf_get(outq, i);
|
|
||||||
vec->base = tbuf->buf.pos;
|
|
||||||
vec->len = nghttp3_buf_len(&tbuf->buf);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO Rework this if we have finished implementing HTTP
|
/* TODO Rework this if we have finished implementing HTTP
|
||||||
|
@ -859,26 +848,27 @@ void nghttp3_stream_add_outq_offset(nghttp3_stream *stream, size_t n) {
|
||||||
nghttp3_ringbuf *outq = &stream->outq;
|
nghttp3_ringbuf *outq = &stream->outq;
|
||||||
size_t i;
|
size_t i;
|
||||||
size_t len = nghttp3_ringbuf_len(outq);
|
size_t len = nghttp3_ringbuf_len(outq);
|
||||||
uint64_t offset = stream->outq_offset + n;
|
|
||||||
size_t buflen;
|
size_t buflen;
|
||||||
nghttp3_typed_buf *tbuf;
|
nghttp3_typed_buf *tbuf;
|
||||||
|
|
||||||
|
stream->unsent_bytes -= n;
|
||||||
|
|
||||||
for (i = stream->outq_idx; i < len; ++i) {
|
for (i = stream->outq_idx; i < len; ++i) {
|
||||||
tbuf = nghttp3_ringbuf_get(outq, i);
|
tbuf = nghttp3_ringbuf_get(outq, i);
|
||||||
buflen = nghttp3_buf_len(&tbuf->buf);
|
buflen = nghttp3_buf_len(&tbuf->buf);
|
||||||
if (offset >= buflen) {
|
if (n < buflen) {
|
||||||
offset -= buflen;
|
tbuf->buf.pos += n;
|
||||||
continue;
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
tbuf->buf.pos = tbuf->buf.last;
|
||||||
|
n -= buflen;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(i < len || offset == 0);
|
assert(i < len || n == 0);
|
||||||
|
|
||||||
stream->unsent_bytes -= n;
|
|
||||||
stream->outq_idx = i;
|
stream->outq_idx = i;
|
||||||
stream->outq_offset = offset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int nghttp3_stream_outq_write_done(nghttp3_stream *stream) {
|
int nghttp3_stream_outq_write_done(nghttp3_stream *stream) {
|
||||||
|
@ -904,7 +894,6 @@ static void stream_pop_outq_entry(nghttp3_stream *stream,
|
||||||
|
|
||||||
chunk = nghttp3_ringbuf_get(chunks, 0);
|
chunk = nghttp3_ringbuf_get(chunks, 0);
|
||||||
|
|
||||||
assert(chunk->begin == tbuf->buf.begin);
|
|
||||||
assert(chunk->end == tbuf->buf.end);
|
assert(chunk->end == tbuf->buf.end);
|
||||||
|
|
||||||
if (chunk->last == tbuf->buf.last) {
|
if (chunk->last == tbuf->buf.last) {
|
||||||
|
@ -927,14 +916,13 @@ static void stream_pop_outq_entry(nghttp3_stream *stream,
|
||||||
int nghttp3_stream_update_ack_offset(nghttp3_stream *stream, uint64_t offset) {
|
int nghttp3_stream_update_ack_offset(nghttp3_stream *stream, uint64_t offset) {
|
||||||
nghttp3_ringbuf *outq = &stream->outq;
|
nghttp3_ringbuf *outq = &stream->outq;
|
||||||
size_t buflen;
|
size_t buflen;
|
||||||
size_t npopped = 0;
|
|
||||||
uint64_t nack;
|
uint64_t nack;
|
||||||
nghttp3_typed_buf *tbuf;
|
nghttp3_typed_buf *tbuf;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
for (; nghttp3_ringbuf_len(outq);) {
|
for (; nghttp3_ringbuf_len(outq);) {
|
||||||
tbuf = nghttp3_ringbuf_get(outq, 0);
|
tbuf = nghttp3_ringbuf_get(outq, 0);
|
||||||
buflen = nghttp3_buf_len(&tbuf->buf);
|
buflen = (size_t)(tbuf->buf.last - tbuf->buf.begin);
|
||||||
|
|
||||||
/* For NGHTTP3_BUF_TYPE_ALIEN, we never add 0 length buffer. */
|
/* For NGHTTP3_BUF_TYPE_ALIEN, we never add 0 length buffer. */
|
||||||
if (tbuf->type == NGHTTP3_BUF_TYPE_ALIEN && stream->ack_offset < offset &&
|
if (tbuf->type == NGHTTP3_BUF_TYPE_ALIEN && stream->ack_offset < offset &&
|
||||||
|
@ -949,17 +937,13 @@ int nghttp3_stream_update_ack_offset(nghttp3_stream *stream, uint64_t offset) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset >= stream->ack_base + buflen) {
|
if (stream->outq_idx > 0 && offset >= stream->ack_base + buflen) {
|
||||||
stream_pop_outq_entry(stream, tbuf);
|
stream_pop_outq_entry(stream, tbuf);
|
||||||
|
|
||||||
stream->ack_base += buflen;
|
stream->ack_base += buflen;
|
||||||
stream->ack_offset = stream->ack_base;
|
stream->ack_offset = stream->ack_base;
|
||||||
++npopped;
|
|
||||||
|
|
||||||
if (stream->outq_idx + 1 == npopped) {
|
--stream->outq_idx;
|
||||||
stream->outq_offset = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -967,13 +951,6 @@ int nghttp3_stream_update_ack_offset(nghttp3_stream *stream, uint64_t offset) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(stream->outq_idx + 1 >= npopped);
|
|
||||||
if (stream->outq_idx >= npopped) {
|
|
||||||
stream->outq_idx -= npopped;
|
|
||||||
} else {
|
|
||||||
stream->outq_idx = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
stream->ack_offset = offset;
|
stream->ack_offset = offset;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1045,19 +1022,17 @@ int nghttp3_stream_transit_rx_http_state(nghttp3_stream *stream,
|
||||||
|
|
||||||
switch (stream->rx.hstate) {
|
switch (stream->rx.hstate) {
|
||||||
case NGHTTP3_HTTP_STATE_NONE:
|
case NGHTTP3_HTTP_STATE_NONE:
|
||||||
return NGHTTP3_ERR_H3_INTERNAL_ERROR;
|
nghttp3_unreachable();
|
||||||
case NGHTTP3_HTTP_STATE_REQ_INITIAL:
|
case NGHTTP3_HTTP_STATE_REQ_INITIAL:
|
||||||
switch (event) {
|
if (event != NGHTTP3_HTTP_EVENT_HEADERS_BEGIN) {
|
||||||
case NGHTTP3_HTTP_EVENT_HEADERS_BEGIN:
|
|
||||||
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_HEADERS_BEGIN;
|
|
||||||
return 0;
|
|
||||||
default:
|
|
||||||
return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
|
return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_HEADERS_BEGIN;
|
||||||
|
|
||||||
|
return 0;
|
||||||
case NGHTTP3_HTTP_STATE_REQ_HEADERS_BEGIN:
|
case NGHTTP3_HTTP_STATE_REQ_HEADERS_BEGIN:
|
||||||
if (event != NGHTTP3_HTTP_EVENT_HEADERS_END) {
|
assert(NGHTTP3_HTTP_EVENT_HEADERS_END == event);
|
||||||
return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
|
|
||||||
}
|
|
||||||
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_HEADERS_END;
|
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_HEADERS_END;
|
||||||
return 0;
|
return 0;
|
||||||
case NGHTTP3_HTTP_STATE_REQ_HEADERS_END:
|
case NGHTTP3_HTTP_STATE_REQ_HEADERS_END:
|
||||||
|
@ -1080,12 +1055,10 @@ int nghttp3_stream_transit_rx_http_state(nghttp3_stream *stream,
|
||||||
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_END;
|
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_END;
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
|
nghttp3_unreachable();
|
||||||
}
|
}
|
||||||
case NGHTTP3_HTTP_STATE_REQ_DATA_BEGIN:
|
case NGHTTP3_HTTP_STATE_REQ_DATA_BEGIN:
|
||||||
if (event != NGHTTP3_HTTP_EVENT_DATA_END) {
|
assert(NGHTTP3_HTTP_EVENT_DATA_END == event);
|
||||||
return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
|
|
||||||
}
|
|
||||||
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_DATA_END;
|
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_DATA_END;
|
||||||
return 0;
|
return 0;
|
||||||
case NGHTTP3_HTTP_STATE_REQ_DATA_END:
|
case NGHTTP3_HTTP_STATE_REQ_DATA_END:
|
||||||
|
@ -1108,12 +1081,10 @@ int nghttp3_stream_transit_rx_http_state(nghttp3_stream *stream,
|
||||||
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_END;
|
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_END;
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
|
nghttp3_unreachable();
|
||||||
}
|
}
|
||||||
case NGHTTP3_HTTP_STATE_REQ_TRAILERS_BEGIN:
|
case NGHTTP3_HTTP_STATE_REQ_TRAILERS_BEGIN:
|
||||||
if (event != NGHTTP3_HTTP_EVENT_HEADERS_END) {
|
assert(NGHTTP3_HTTP_EVENT_HEADERS_END == event);
|
||||||
return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
|
|
||||||
}
|
|
||||||
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_TRAILERS_END;
|
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_TRAILERS_END;
|
||||||
return 0;
|
return 0;
|
||||||
case NGHTTP3_HTTP_STATE_REQ_TRAILERS_END:
|
case NGHTTP3_HTTP_STATE_REQ_TRAILERS_END:
|
||||||
|
@ -1129,7 +1100,7 @@ int nghttp3_stream_transit_rx_http_state(nghttp3_stream *stream,
|
||||||
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_END;
|
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_END;
|
||||||
return 0;
|
return 0;
|
||||||
case NGHTTP3_HTTP_STATE_REQ_END:
|
case NGHTTP3_HTTP_STATE_REQ_END:
|
||||||
return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
|
return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
|
||||||
case NGHTTP3_HTTP_STATE_RESP_INITIAL:
|
case NGHTTP3_HTTP_STATE_RESP_INITIAL:
|
||||||
if (event != NGHTTP3_HTTP_EVENT_HEADERS_BEGIN) {
|
if (event != NGHTTP3_HTTP_EVENT_HEADERS_BEGIN) {
|
||||||
return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
|
return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
|
||||||
|
@ -1137,9 +1108,7 @@ int nghttp3_stream_transit_rx_http_state(nghttp3_stream *stream,
|
||||||
stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_HEADERS_BEGIN;
|
stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_HEADERS_BEGIN;
|
||||||
return 0;
|
return 0;
|
||||||
case NGHTTP3_HTTP_STATE_RESP_HEADERS_BEGIN:
|
case NGHTTP3_HTTP_STATE_RESP_HEADERS_BEGIN:
|
||||||
if (event != NGHTTP3_HTTP_EVENT_HEADERS_END) {
|
assert(NGHTTP3_HTTP_EVENT_HEADERS_END == event);
|
||||||
return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
|
|
||||||
}
|
|
||||||
stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_HEADERS_END;
|
stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_HEADERS_END;
|
||||||
return 0;
|
return 0;
|
||||||
case NGHTTP3_HTTP_STATE_RESP_HEADERS_END:
|
case NGHTTP3_HTTP_STATE_RESP_HEADERS_END:
|
||||||
|
@ -1169,12 +1138,10 @@ int nghttp3_stream_transit_rx_http_state(nghttp3_stream *stream,
|
||||||
stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_END;
|
stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_END;
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
|
nghttp3_unreachable();
|
||||||
}
|
}
|
||||||
case NGHTTP3_HTTP_STATE_RESP_DATA_BEGIN:
|
case NGHTTP3_HTTP_STATE_RESP_DATA_BEGIN:
|
||||||
if (event != NGHTTP3_HTTP_EVENT_DATA_END) {
|
assert(NGHTTP3_HTTP_EVENT_DATA_END == event);
|
||||||
return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
|
|
||||||
}
|
|
||||||
stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_DATA_END;
|
stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_DATA_END;
|
||||||
return 0;
|
return 0;
|
||||||
case NGHTTP3_HTTP_STATE_RESP_DATA_END:
|
case NGHTTP3_HTTP_STATE_RESP_DATA_END:
|
||||||
|
@ -1197,17 +1164,15 @@ int nghttp3_stream_transit_rx_http_state(nghttp3_stream *stream,
|
||||||
stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_END;
|
stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_END;
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
|
nghttp3_unreachable();
|
||||||
}
|
}
|
||||||
case NGHTTP3_HTTP_STATE_RESP_TRAILERS_BEGIN:
|
case NGHTTP3_HTTP_STATE_RESP_TRAILERS_BEGIN:
|
||||||
if (event != NGHTTP3_HTTP_EVENT_HEADERS_END) {
|
assert(NGHTTP3_HTTP_EVENT_HEADERS_END == event);
|
||||||
return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
|
|
||||||
}
|
|
||||||
stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_TRAILERS_END;
|
stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_TRAILERS_END;
|
||||||
return 0;
|
return 0;
|
||||||
case NGHTTP3_HTTP_STATE_RESP_TRAILERS_END:
|
case NGHTTP3_HTTP_STATE_RESP_TRAILERS_END:
|
||||||
if (event != NGHTTP3_HTTP_EVENT_MSG_END) {
|
if (event != NGHTTP3_HTTP_EVENT_MSG_END) {
|
||||||
return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
|
return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
|
||||||
}
|
}
|
||||||
rv = nghttp3_http_on_remote_end_stream(stream);
|
rv = nghttp3_http_on_remote_end_stream(stream);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
|
@ -1216,7 +1181,7 @@ int nghttp3_stream_transit_rx_http_state(nghttp3_stream *stream,
|
||||||
stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_END;
|
stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_END;
|
||||||
return 0;
|
return 0;
|
||||||
case NGHTTP3_HTTP_STATE_RESP_END:
|
case NGHTTP3_HTTP_STATE_RESP_END:
|
||||||
return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
|
return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
|
||||||
default:
|
default:
|
||||||
nghttp3_unreachable();
|
nghttp3_unreachable();
|
||||||
}
|
}
|
||||||
|
|
|
@ -223,9 +223,6 @@ struct nghttp3_stream {
|
||||||
uint64_t unsent_bytes;
|
uint64_t unsent_bytes;
|
||||||
/* outq_idx is an index into outq where next write is made. */
|
/* outq_idx is an index into outq where next write is made. */
|
||||||
size_t outq_idx;
|
size_t outq_idx;
|
||||||
/* outq_offset is write offset relative to the element at outq_idx
|
|
||||||
in outq. */
|
|
||||||
uint64_t outq_offset;
|
|
||||||
/* ack_base is the number of bytes acknowledged by a remote
|
/* ack_base is the number of bytes acknowledged by a remote
|
||||||
endpoint where the first element in outq is positioned at. */
|
endpoint where the first element in outq is positioned at. */
|
||||||
uint64_t ack_base;
|
uint64_t ack_base;
|
||||||
|
@ -255,7 +252,7 @@ struct nghttp3_stream {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
nghttp3_objalloc_decl(stream, nghttp3_stream, oplent);
|
nghttp3_objalloc_decl(stream, nghttp3_stream, oplent)
|
||||||
|
|
||||||
typedef struct nghttp3_frame_entry {
|
typedef struct nghttp3_frame_entry {
|
||||||
nghttp3_frame fr;
|
nghttp3_frame fr;
|
||||||
|
|
|
@ -28,8 +28,11 @@
|
||||||
|
|
||||||
#include <nghttp3/nghttp3.h>
|
#include <nghttp3/nghttp3.h>
|
||||||
|
|
||||||
static nghttp3_info version = {NGHTTP3_VERSION_AGE, NGHTTP3_VERSION_NUM,
|
static nghttp3_info version = {
|
||||||
NGHTTP3_VERSION};
|
.age = NGHTTP3_VERSION_AGE,
|
||||||
|
.version_num = NGHTTP3_VERSION_NUM,
|
||||||
|
.version_str = NGHTTP3_VERSION,
|
||||||
|
};
|
||||||
|
|
||||||
const nghttp3_info *nghttp3_version(int least_version) {
|
const nghttp3_info *nghttp3_version(int least_version) {
|
||||||
if (least_version > NGHTTP3_VERSION_NUM) {
|
if (least_version > NGHTTP3_VERSION_NUM) {
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -31,90 +31,90 @@
|
||||||
libcurl) */
|
libcurl) */
|
||||||
#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
|
#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
|
||||||
# define WIN32
|
# define WIN32
|
||||||
#endif
|
#endif /* (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif /* defined(__cplusplus) */
|
||||||
|
|
||||||
#if defined(_MSC_VER) && (_MSC_VER < 1800)
|
#if defined(_MSC_VER) && (_MSC_VER < 1800)
|
||||||
/* MSVC < 2013 does not have inttypes.h because it is not C99
|
/* MSVC < 2013 does not have inttypes.h because it is not C99
|
||||||
compliant. See compiler macros and version number in
|
compliant. See compiler macros and version number in
|
||||||
https://sourceforge.net/p/predef/wiki/Compilers/ */
|
https://sourceforge.net/p/predef/wiki/Compilers/ */
|
||||||
# include <stdint.h>
|
# include <stdint.h>
|
||||||
#else /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */
|
#else /* !(defined(_MSC_VER) && (_MSC_VER < 1800)) */
|
||||||
# include <inttypes.h>
|
# include <inttypes.h>
|
||||||
#endif /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */
|
#endif /* !(defined(_MSC_VER) && (_MSC_VER < 1800)) */
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @enum
|
* @enum
|
||||||
*
|
*
|
||||||
* :type:`sf_type` defines value type.
|
* :type:`sfparse_type` defines value type.
|
||||||
*/
|
*/
|
||||||
typedef enum sf_type {
|
typedef enum sfparse_type {
|
||||||
/**
|
/**
|
||||||
* :enum:`SF_TYPE_BOOLEAN` indicates boolean type.
|
* :enum:`SFPARSE_TYPE_BOOLEAN` indicates boolean type.
|
||||||
*/
|
*/
|
||||||
SF_TYPE_BOOLEAN,
|
SFPARSE_TYPE_BOOLEAN,
|
||||||
/**
|
/**
|
||||||
* :enum:`SF_TYPE_INTEGER` indicates integer type.
|
* :enum:`SFPARSE_TYPE_INTEGER` indicates integer type.
|
||||||
*/
|
*/
|
||||||
SF_TYPE_INTEGER,
|
SFPARSE_TYPE_INTEGER,
|
||||||
/**
|
/**
|
||||||
* :enum:`SF_TYPE_DECIMAL` indicates decimal type.
|
* :enum:`SFPARSE_TYPE_DECIMAL` indicates decimal type.
|
||||||
*/
|
*/
|
||||||
SF_TYPE_DECIMAL,
|
SFPARSE_TYPE_DECIMAL,
|
||||||
/**
|
/**
|
||||||
* :enum:`SF_TYPE_STRING` indicates string type.
|
* :enum:`SFPARSE_TYPE_STRING` indicates string type.
|
||||||
*/
|
*/
|
||||||
SF_TYPE_STRING,
|
SFPARSE_TYPE_STRING,
|
||||||
/**
|
/**
|
||||||
* :enum:`SF_TYPE_TOKEN` indicates token type.
|
* :enum:`SFPARSE_TYPE_TOKEN` indicates token type.
|
||||||
*/
|
*/
|
||||||
SF_TYPE_TOKEN,
|
SFPARSE_TYPE_TOKEN,
|
||||||
/**
|
/**
|
||||||
* :enum:`SF_TYPE_BYTESEQ` indicates byte sequence type.
|
* :enum:`SFPARSE_TYPE_BYTESEQ` indicates byte sequence type.
|
||||||
*/
|
*/
|
||||||
SF_TYPE_BYTESEQ,
|
SFPARSE_TYPE_BYTESEQ,
|
||||||
/**
|
/**
|
||||||
* :enum:`SF_TYPE_INNER_LIST` indicates inner list type.
|
* :enum:`SFPARSE_TYPE_INNER_LIST` indicates inner list type.
|
||||||
*/
|
*/
|
||||||
SF_TYPE_INNER_LIST,
|
SFPARSE_TYPE_INNER_LIST,
|
||||||
/**
|
/**
|
||||||
* :enum:`SF_TYPE_DATE` indicates date type.
|
* :enum:`SFPARSE_TYPE_DATE` indicates date type.
|
||||||
*/
|
*/
|
||||||
SF_TYPE_DATE,
|
SFPARSE_TYPE_DATE,
|
||||||
/**
|
/**
|
||||||
* :enum:`SF_TYPE_DISPSTRING` indicates display string type.
|
* :enum:`SFPARSE_TYPE_DISPSTRING` indicates display string type.
|
||||||
*/
|
*/
|
||||||
SF_TYPE_DISPSTRING
|
SFPARSE_TYPE_DISPSTRING
|
||||||
} sf_type;
|
} sfparse_type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @macro
|
* @macro
|
||||||
*
|
*
|
||||||
* :macro:`SF_ERR_PARSE_ERROR` indicates fatal parse error has
|
* :macro:`SFPARSE_ERR_PARSE` indicates fatal parse error has
|
||||||
* occurred, and it is not possible to continue the processing.
|
* occurred, and it is not possible to continue the processing.
|
||||||
*/
|
*/
|
||||||
#define SF_ERR_PARSE_ERROR -1
|
#define SFPARSE_ERR_PARSE -1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @macro
|
* @macro
|
||||||
*
|
*
|
||||||
* :macro:`SF_ERR_EOF` indicates that there is nothing left to read.
|
* :macro:`SFPARSE_ERR_EOF` indicates that there is nothing left to
|
||||||
* The context of this error varies depending on the function that
|
* read. The context of this error varies depending on the function
|
||||||
* returns this error code.
|
* that returns this error code.
|
||||||
*/
|
*/
|
||||||
#define SF_ERR_EOF -2
|
#define SFPARSE_ERR_EOF -2
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @struct
|
* @struct
|
||||||
*
|
*
|
||||||
* :type:`sf_vec` stores sequence of bytes.
|
* :type:`sfparse_vec` stores sequence of bytes.
|
||||||
*/
|
*/
|
||||||
typedef struct sf_vec {
|
typedef struct sfparse_vec {
|
||||||
/**
|
/**
|
||||||
* :member:`base` points to the beginning of the sequence of bytes.
|
* :member:`base` points to the beginning of the sequence of bytes.
|
||||||
*/
|
*/
|
||||||
|
@ -123,29 +123,29 @@ typedef struct sf_vec {
|
||||||
* :member:`len` is the number of bytes contained in this sequence.
|
* :member:`len` is the number of bytes contained in this sequence.
|
||||||
*/
|
*/
|
||||||
size_t len;
|
size_t len;
|
||||||
} sf_vec;
|
} sfparse_vec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @macro
|
* @macro
|
||||||
*
|
*
|
||||||
* :macro:`SF_VALUE_FLAG_NONE` indicates no flag set.
|
* :macro:`SFPARSE_VALUE_FLAG_NONE` indicates no flag set.
|
||||||
*/
|
*/
|
||||||
#define SF_VALUE_FLAG_NONE 0x0u
|
#define SFPARSE_VALUE_FLAG_NONE 0x0u
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @macro
|
* @macro
|
||||||
*
|
*
|
||||||
* :macro:`SF_VALUE_FLAG_ESCAPED_STRING` indicates that a string
|
* :macro:`SFPARSE_VALUE_FLAG_ESCAPED_STRING` indicates that a string
|
||||||
* contains escaped character(s).
|
* contains escaped character(s).
|
||||||
*/
|
*/
|
||||||
#define SF_VALUE_FLAG_ESCAPED_STRING 0x1u
|
#define SFPARSE_VALUE_FLAG_ESCAPED_STRING 0x1u
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @struct
|
* @struct
|
||||||
*
|
*
|
||||||
* :type:`sf_decimal` contains decimal value.
|
* :type:`sfparse_decimal` contains decimal value.
|
||||||
*/
|
*/
|
||||||
typedef struct sf_decimal {
|
typedef struct sfparse_decimal {
|
||||||
/**
|
/**
|
||||||
* :member:`numer` contains numerator of the decimal value.
|
* :member:`numer` contains numerator of the decimal value.
|
||||||
*/
|
*/
|
||||||
|
@ -154,275 +154,289 @@ typedef struct sf_decimal {
|
||||||
* :member:`denom` contains denominator of the decimal value.
|
* :member:`denom` contains denominator of the decimal value.
|
||||||
*/
|
*/
|
||||||
int64_t denom;
|
int64_t denom;
|
||||||
} sf_decimal;
|
} sfparse_decimal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @struct
|
* @struct
|
||||||
*
|
*
|
||||||
* :type:`sf_value` stores a Structured Field item. For Inner List,
|
* :type:`sfparse_value` stores a Structured Field item. For Inner
|
||||||
* only type is set to :enum:`sf_type.SF_TYPE_INNER_LIST`. In order
|
* List, only type is set to
|
||||||
* to read the items contained in an inner list, call
|
* :enum:`sfparse_type.SFPARSE_TYPE_INNER_LIST`. In order to read the
|
||||||
* `sf_parser_inner_list`.
|
* items contained in an inner list, call `sfparse_parser_inner_list`.
|
||||||
*/
|
*/
|
||||||
typedef struct sf_value {
|
typedef struct sfparse_value {
|
||||||
/**
|
/**
|
||||||
* :member:`type` is the type of the value contained in this
|
* :member:`type` is the type of the value contained in this
|
||||||
* particular object.
|
* particular object.
|
||||||
*/
|
*/
|
||||||
sf_type type;
|
sfparse_type type;
|
||||||
/**
|
/**
|
||||||
* :member:`flags` is bitwise OR of one or more of
|
* :member:`flags` is bitwise OR of one or more of
|
||||||
* :macro:`SF_VALUE_FLAG_* <SF_VALUE_FLAG_NONE>`.
|
* :macro:`SFPARSE_VALUE_FLAG_* <SFPARSE_VALUE_FLAG_NONE>`.
|
||||||
*/
|
*/
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
/**
|
/**
|
||||||
* @anonunion_start
|
* @anonunion_start
|
||||||
*
|
*
|
||||||
* @sf_value_value
|
* @sfparse_value_value
|
||||||
*/
|
*/
|
||||||
union {
|
union {
|
||||||
/**
|
/**
|
||||||
* :member:`boolean` contains boolean value if :member:`type` ==
|
* :member:`boolean` contains boolean value if :member:`type` ==
|
||||||
* :enum:`sf_type.SF_TYPE_BOOLEAN`. 1 indicates true, and 0
|
* :enum:`sfparse_type.SFPARSE_TYPE_BOOLEAN`. 1 indicates true,
|
||||||
* indicates false.
|
* and 0 indicates false.
|
||||||
*/
|
*/
|
||||||
int boolean;
|
int boolean;
|
||||||
/**
|
/**
|
||||||
* :member:`integer` contains integer value if :member:`type` is
|
* :member:`integer` contains integer value if :member:`type` is
|
||||||
* either :enum:`sf_type.SF_TYPE_INTEGER` or
|
* either :enum:`sfparse_type.SFPARSE_TYPE_INTEGER` or
|
||||||
* :enum:`sf_type.SF_TYPE_DATE`.
|
* :enum:`sfparse_type.SFPARSE_TYPE_DATE`.
|
||||||
*/
|
*/
|
||||||
int64_t integer;
|
int64_t integer;
|
||||||
/**
|
/**
|
||||||
* :member:`decimal` contains decimal value if :member:`type` ==
|
* :member:`decimal` contains decimal value if :member:`type` ==
|
||||||
* :enum:`sf_type.SF_TYPE_DECIMAL`.
|
* :enum:`sfparse_type.SFPARSE_TYPE_DECIMAL`.
|
||||||
*/
|
*/
|
||||||
sf_decimal decimal;
|
sfparse_decimal decimal;
|
||||||
/**
|
/**
|
||||||
* :member:`vec` contains sequence of bytes if :member:`type` is
|
* :member:`vec` contains sequence of bytes if :member:`type` is
|
||||||
* either :enum:`sf_type.SF_TYPE_STRING`,
|
* either :enum:`sfparse_type.SFPARSE_TYPE_STRING`,
|
||||||
* :enum:`sf_type.SF_TYPE_TOKEN`, :enum:`sf_type.SF_TYPE_BYTESEQ`,
|
* :enum:`sfparse_type.SFPARSE_TYPE_TOKEN`,
|
||||||
* or :enum:`sf_type.SF_TYPE_DISPSTRING`.
|
* :enum:`sfparse_type.SFPARSE_TYPE_BYTESEQ`, or
|
||||||
|
* :enum:`sfparse_type.SFPARSE_TYPE_DISPSTRING`.
|
||||||
*
|
*
|
||||||
* For :enum:`sf_type.SF_TYPE_STRING`, this field contains one or
|
* For :enum:`sfparse_type.SFPARSE_TYPE_STRING`, this field
|
||||||
* more escaped characters if :member:`flags` has
|
* contains one or more escaped characters if :member:`flags` has
|
||||||
* :macro:`SF_VALUE_FLAG_ESCAPED_STRING` set. To unescape the
|
* :macro:`SFPARSE_VALUE_FLAG_ESCAPED_STRING` set. To unescape
|
||||||
* string, use `sf_unescape`.
|
* the string, use `sfparse_unescape`.
|
||||||
*
|
*
|
||||||
* For :enum:`sf_type.SF_TYPE_BYTESEQ`, this field contains base64
|
* For :enum:`sfparse_type.SFPARSE_TYPE_BYTESEQ`, this field
|
||||||
* encoded string. To decode this byte string, use
|
* contains base64 encoded string. To decode this byte string,
|
||||||
* `sf_base64decode`.
|
* use `sfparse_base64decode`.
|
||||||
*
|
*
|
||||||
* For :enum:`sf_type.SF_TYPE_DISPSTRING`, this field may contain
|
* For :enum:`sfparse_type.SFPARSE_TYPE_DISPSTRING`, this field
|
||||||
* percent-encoded UTF-8 byte sequences. To decode it, use
|
* may contain percent-encoded UTF-8 byte sequences. To decode
|
||||||
* `sf_pctdecode`.
|
* it, use `sfparse_pctdecode`.
|
||||||
*
|
*
|
||||||
* If :member:`vec.len <sf_vec.len>` == 0, :member:`vec.base
|
* If :member:`vec.len <sfparse_vec.len>` == 0, :member:`vec.base
|
||||||
* <sf_vec.base>` is guaranteed to be NULL.
|
* <sfparse_vec.base>` is guaranteed to be NULL.
|
||||||
*/
|
*/
|
||||||
sf_vec vec;
|
sfparse_vec vec;
|
||||||
/**
|
/**
|
||||||
* @anonunion_end
|
* @anonunion_end
|
||||||
*/
|
*/
|
||||||
};
|
};
|
||||||
} sf_value;
|
} sfparse_value;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @struct
|
* @struct
|
||||||
*
|
*
|
||||||
* :type:`sf_parser` is the Structured Field Values parser. Use
|
* :type:`sfparse_parser` is the Structured Field Values parser. Use
|
||||||
* `sf_parser_init` to initialize it.
|
* `sfparse_parser_init` to initialize it.
|
||||||
*/
|
*/
|
||||||
typedef struct sf_parser {
|
typedef struct sfparse_parser {
|
||||||
/* all fields are private */
|
/* all fields are private */
|
||||||
const uint8_t *pos;
|
const uint8_t *pos;
|
||||||
const uint8_t *end;
|
const uint8_t *end;
|
||||||
uint32_t state;
|
uint32_t state;
|
||||||
} sf_parser;
|
} sfparse_parser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
* `sf_parser_init` initializes |sfp| with the given buffer pointed by
|
* `sfparse_parser_init` initializes |sfp| with the given data encoded
|
||||||
* |data| of length |datalen|.
|
* in Structured Field Values pointed by |data| of length |datalen|.
|
||||||
*/
|
*/
|
||||||
void sf_parser_init(sf_parser *sfp, const uint8_t *data, size_t datalen);
|
void sfparse_parser_init(sfparse_parser *sfp, const uint8_t *data,
|
||||||
|
size_t datalen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
* `sf_parser_param` reads a parameter. If this function returns 0,
|
* `sfparse_parser_param` reads a parameter. If this function returns
|
||||||
* it stores parameter key and value in |dest_key| and |dest_value|
|
* 0, it stores parameter key and value in |dest_key| and |dest_value|
|
||||||
* respectively, if they are not NULL.
|
* respectively, if they are not NULL.
|
||||||
*
|
*
|
||||||
* This function does no effort to find duplicated keys. Same key may
|
* This function does no effort to find duplicated keys. Same key may
|
||||||
* be reported more than once.
|
* be reported more than once.
|
||||||
*
|
*
|
||||||
* Caller should keep calling this function until it returns negative
|
* Caller should keep calling this function until it returns negative
|
||||||
* error code. If it returns :macro:`SF_ERR_EOF`, all parameters have
|
* error code. If it returns :macro:`SFPARSE_ERR_EOF`, all parameters
|
||||||
* read, and caller can continue to read rest of the values. If it
|
* have read, and caller can continue to read rest of the values. If
|
||||||
* returns :macro:`SF_ERR_PARSE_ERROR`, it encountered fatal error
|
* it returns :macro:`SFPARSE_ERR_PARSE`, it encountered fatal error
|
||||||
* while parsing field value.
|
* while parsing field value.
|
||||||
*/
|
*/
|
||||||
int sf_parser_param(sf_parser *sfp, sf_vec *dest_key, sf_value *dest_value);
|
int sfparse_parser_param(sfparse_parser *sfp, sfparse_vec *dest_key,
|
||||||
|
sfparse_value *dest_value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
* `sf_parser_dict` reads the next dictionary key and value pair. If
|
* `sfparse_parser_dict` reads the next dictionary key and value pair.
|
||||||
* this function returns 0, it stores the key and value in |dest_key|
|
* If this function returns 0, it stores the key and value in
|
||||||
* and |dest_value| respectively, if they are not NULL.
|
* |dest_key| and |dest_value| respectively, if they are not NULL.
|
||||||
*
|
*
|
||||||
* Caller can optionally read parameters attached to the pair by
|
* Caller can optionally read parameters attached to the pair by
|
||||||
* calling `sf_parser_param`.
|
* calling `sfparse_parser_param`.
|
||||||
*
|
*
|
||||||
* This function does no effort to find duplicated keys. Same key may
|
* This function does no effort to find duplicated keys. Same key may
|
||||||
* be reported more than once.
|
* be reported more than once.
|
||||||
*
|
*
|
||||||
* Caller should keep calling this function until it returns negative
|
* Caller should keep calling this function until it returns negative
|
||||||
* error code. If it returns :macro:`SF_ERR_EOF`, all key and value
|
* error code. If it returns :macro:`SFPARSE_ERR_EOF`, all key and
|
||||||
* pairs have been read, and there is nothing left to read.
|
* value pairs have been read, and there is nothing left to read.
|
||||||
*
|
*
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
* negative error codes:
|
* negative error codes:
|
||||||
*
|
*
|
||||||
* :macro:`SF_ERR_EOF`
|
* :macro:`SFPARSE_ERR_EOF`
|
||||||
* All values in the dictionary have read.
|
* All values in the dictionary have read.
|
||||||
* :macro:`SF_ERR_PARSE_ERROR`
|
* :macro:`SFPARSE_ERR_PARSE`
|
||||||
* It encountered fatal error while parsing field value.
|
* It encountered fatal error while parsing field value.
|
||||||
*/
|
*/
|
||||||
int sf_parser_dict(sf_parser *sfp, sf_vec *dest_key, sf_value *dest_value);
|
int sfparse_parser_dict(sfparse_parser *sfp, sfparse_vec *dest_key,
|
||||||
|
sfparse_value *dest_value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
* `sf_parser_list` reads the next list item. If this function
|
* `sfparse_parser_list` reads the next list item. If this function
|
||||||
* returns 0, it stores the item in |dest| if it is not NULL.
|
* returns 0, it stores the item in |dest| if it is not NULL.
|
||||||
*
|
*
|
||||||
* Caller can optionally read parameters attached to the item by
|
* Caller can optionally read parameters attached to the item by
|
||||||
* calling `sf_parser_param`.
|
* calling `sfparse_parser_param`.
|
||||||
*
|
*
|
||||||
* Caller should keep calling this function until it returns negative
|
* Caller should keep calling this function until it returns negative
|
||||||
* error code. If it returns :macro:`SF_ERR_EOF`, all values in the
|
* error code. If it returns :macro:`SFPARSE_ERR_EOF`, all values in
|
||||||
* list have been read, and there is nothing left to read.
|
* the list have been read, and there is nothing left to read.
|
||||||
*
|
*
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
* negative error codes:
|
* negative error codes:
|
||||||
*
|
*
|
||||||
* :macro:`SF_ERR_EOF`
|
* :macro:`SFPARSE_ERR_EOF`
|
||||||
* All values in the list have read.
|
* All values in the list have read.
|
||||||
* :macro:`SF_ERR_PARSE_ERROR`
|
* :macro:`SFPARSE_ERR_PARSE`
|
||||||
* It encountered fatal error while parsing field value.
|
* It encountered fatal error while parsing field value.
|
||||||
*/
|
*/
|
||||||
int sf_parser_list(sf_parser *sfp, sf_value *dest);
|
int sfparse_parser_list(sfparse_parser *sfp, sfparse_value *dest);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
* `sf_parser_item` reads a single item. If this function returns 0,
|
* `sfparse_parser_item` reads a single item. If this function
|
||||||
* it stores the item in |dest| if it is not NULL.
|
* returns 0, it stores the item in |dest| if it is not NULL.
|
||||||
*
|
*
|
||||||
* This function is only used for the field value that consists of a
|
* This function is only used for the field value that consists of a
|
||||||
* single item.
|
* single item.
|
||||||
*
|
*
|
||||||
* Caller can optionally read parameters attached to the item by
|
* Caller can optionally read parameters attached to the item by
|
||||||
* calling `sf_parser_param`.
|
* calling `sfparse_parser_param`.
|
||||||
*
|
*
|
||||||
* Caller should call this function again to make sure that there is
|
* Caller should call this function again to make sure that there is
|
||||||
* nothing left to read. If this 2nd function call returns
|
* nothing left to read. If this 2nd function call returns
|
||||||
* :macro:`SF_ERR_EOF`, all data have been processed successfully.
|
* :macro:`SFPARSE_ERR_EOF`, all data have been processed
|
||||||
|
* successfully.
|
||||||
*
|
*
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
* negative error codes:
|
* negative error codes:
|
||||||
*
|
*
|
||||||
* :macro:`SF_ERR_EOF`
|
* :macro:`SFPARSE_ERR_EOF`
|
||||||
* There is nothing left to read.
|
* There is nothing left to read.
|
||||||
* :macro:`SF_ERR_PARSE_ERROR`
|
* :macro:`SFPARSE_ERR_PARSE`
|
||||||
* It encountered fatal error while parsing field value.
|
* It encountered fatal error while parsing field value.
|
||||||
*/
|
*/
|
||||||
int sf_parser_item(sf_parser *sfp, sf_value *dest);
|
int sfparse_parser_item(sfparse_parser *sfp, sfparse_value *dest);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
* `sf_parser_inner_list` reads the next inner list item. If this
|
* `sfparse_parser_inner_list` reads the next inner list item. If
|
||||||
* function returns 0, it stores the item in |dest| if it is not NULL.
|
* this function returns 0, it stores the item in |dest| if it is not
|
||||||
|
* NULL.
|
||||||
*
|
*
|
||||||
* Caller can optionally read parameters attached to the item by
|
* Caller can optionally read parameters attached to the item by
|
||||||
* calling `sf_parser_param`.
|
* calling `sfparse_parser_param`.
|
||||||
*
|
*
|
||||||
* Caller should keep calling this function until it returns negative
|
* Caller should keep calling this function until it returns negative
|
||||||
* error code. If it returns :macro:`SF_ERR_EOF`, all values in this
|
* error code. If it returns :macro:`SFPARSE_ERR_EOF`, all values in
|
||||||
* inner list have been read, and caller can optionally read
|
* this inner list have been read, and caller can optionally read
|
||||||
* parameters attached to this inner list by calling
|
* parameters attached to this inner list by calling
|
||||||
* `sf_parser_param`. Then caller can continue to read rest of the
|
* `sfparse_parser_param`. Then caller can continue to read rest of
|
||||||
* values.
|
* the values.
|
||||||
*
|
*
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
* negative error codes:
|
* negative error codes:
|
||||||
*
|
*
|
||||||
* :macro:`SF_ERR_EOF`
|
* :macro:`SFPARSE_ERR_EOF`
|
||||||
* All values in the inner list have read.
|
* All values in the inner list have read.
|
||||||
* :macro:`SF_ERR_PARSE_ERROR`
|
* :macro:`SFPARSE_ERR_PARSE`
|
||||||
* It encountered fatal error while parsing field value.
|
* It encountered fatal error while parsing field value.
|
||||||
*/
|
*/
|
||||||
int sf_parser_inner_list(sf_parser *sfp, sf_value *dest);
|
int sfparse_parser_inner_list(sfparse_parser *sfp, sfparse_value *dest);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
* `sf_unescape` copies |src| to |dest| by removing escapes (``\``).
|
* `sfparse_unescape` copies |src| to |dest| by removing escapes
|
||||||
* |src| should be the pointer to :member:`sf_value.vec` of type
|
* (``\``). |src| should be the pointer to
|
||||||
* :enum:`sf_type.SF_TYPE_STRING` produced by either `sf_parser_dict`,
|
* :member:`sfparse_value.vec` of type
|
||||||
* `sf_parser_list`, `sf_parser_inner_list`, `sf_parser_item`, or
|
* :enum:`sfparse_type.SFPARSE_TYPE_STRING` produced by either
|
||||||
* `sf_parser_param`, otherwise the behavior is undefined.
|
* `sfparse_parser_dict`, `sfparse_parser_list`,
|
||||||
|
* `sfparse_parser_inner_list`, `sfparse_parser_item`, or
|
||||||
|
* `sfparse_parser_param`, otherwise the behavior is undefined.
|
||||||
*
|
*
|
||||||
* :member:`dest->base <sf_vec.base>` must point to the buffer that
|
* :member:`dest->base <sfparse_vec.base>` must point to the buffer
|
||||||
* has sufficient space to store the unescaped string.
|
* that has sufficient space to store the unescaped string. The
|
||||||
|
* memory areas pointed by :member:`dest->base <sfparse_vec.base>` and
|
||||||
|
* :member:`src->base <sfparse_vec.base>` must not overlap.
|
||||||
*
|
*
|
||||||
* This function sets the length of unescaped string to
|
* This function sets the length of unescaped string to
|
||||||
* :member:`dest->len <sf_vec.len>`.
|
* :member:`dest->len <sfparse_vec.len>`.
|
||||||
*/
|
*/
|
||||||
void sf_unescape(sf_vec *dest, const sf_vec *src);
|
void sfparse_unescape(sfparse_vec *dest, const sfparse_vec *src);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
* `sf_base64decode` decodes Base64 encoded string |src| and writes
|
* `sfparse_base64decode` decodes Base64 encoded string |src| and
|
||||||
|
* writes the result into |dest|. |src| should be the pointer to
|
||||||
|
* :member:`sfparse_value.vec` of type
|
||||||
|
* :enum:`sfparse_type.SFPARSE_TYPE_BYTESEQ` produced by either
|
||||||
|
* `sfparse_parser_dict`, `sfparse_parser_list`,
|
||||||
|
* `sfparse_parser_inner_list`, `sfparse_parser_item`, or
|
||||||
|
* `sfparse_parser_param`, otherwise the behavior is undefined.
|
||||||
|
*
|
||||||
|
* :member:`dest->base <sfparse_vec.base>` must point to the buffer
|
||||||
|
* that has sufficient space to store the decoded byte string.
|
||||||
|
*
|
||||||
|
* This function sets the length of decoded byte string to
|
||||||
|
* :member:`dest->len <sfparse_vec.len>`.
|
||||||
|
*/
|
||||||
|
void sfparse_base64decode(sfparse_vec *dest, const sfparse_vec *src);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* `sfparse_pctdecode` decodes percent-encoded string |src| and writes
|
||||||
* the result into |dest|. |src| should be the pointer to
|
* the result into |dest|. |src| should be the pointer to
|
||||||
* :member:`sf_value.vec` of type :enum:`sf_type.SF_TYPE_BYTESEQ`
|
* :member:`sfparse_value.vec` of type
|
||||||
* produced by either `sf_parser_dict`, `sf_parser_list`,
|
* :enum:`sfparse_type.SFPARSE_TYPE_DISPSTRING` produced by either
|
||||||
* `sf_parser_inner_list`, `sf_parser_item`, or `sf_parser_param`,
|
* `sfparse_parser_dict`, `sfparse_parser_list`,
|
||||||
* otherwise the behavior is undefined.
|
* `sfparse_parser_inner_list`, `sfparse_parser_item`, or
|
||||||
|
* `sfparse_parser_param`, otherwise the behavior is undefined.
|
||||||
*
|
*
|
||||||
* :member:`dest->base <sf_vec.base>` must point to the buffer that
|
* :member:`dest->base <sfparse_vec.base>` must point to the buffer
|
||||||
* has sufficient space to store the decoded byte string.
|
* that has sufficient space to store the decoded byte string. The
|
||||||
|
* memory areas pointed by :member:`dest->base <sfparse_vec.base>` and
|
||||||
|
* :member:`src->base <sfparse_vec.base>` must not overlap.
|
||||||
*
|
*
|
||||||
* This function sets the length of decoded byte string to
|
* This function sets the length of decoded byte string to
|
||||||
* :member:`dest->len <sf_vec.len>`.
|
* :member:`dest->len <sfparse_vec.len>`.
|
||||||
*/
|
*/
|
||||||
void sf_base64decode(sf_vec *dest, const sf_vec *src);
|
void sfparse_pctdecode(sfparse_vec *dest, const sfparse_vec *src);
|
||||||
|
|
||||||
/**
|
|
||||||
* @function
|
|
||||||
*
|
|
||||||
* `sf_pctdecode` decodes percent-encoded string |src| and writes the
|
|
||||||
* result into |dest|. |src| should be the pointer to
|
|
||||||
* :member:`sf_value.vec` of type :enum:`sf_type.SF_TYPE_DISPSTRING`
|
|
||||||
* produced by either `sf_parser_dict`, `sf_parser_list`,
|
|
||||||
* `sf_parser_inner_list`, `sf_parser_item`, or `sf_parser_param`,
|
|
||||||
* otherwise the behavior is undefined.
|
|
||||||
*
|
|
||||||
* :member:`dest->base <sf_vec.base>` must point to the buffer that
|
|
||||||
* has sufficient space to store the decoded byte string.
|
|
||||||
*
|
|
||||||
* This function sets the length of decoded byte string to
|
|
||||||
* :member:`dest->len <sf_vec.len>`.
|
|
||||||
*/
|
|
||||||
void sf_pctdecode(sf_vec *dest, const sf_vec *src);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* defined(__cplusplus) */
|
||||||
|
|
||||||
#endif /* SFPARSE_H */
|
#endif /* !defined(SFPARSE_H) */
|
||||||
|
|
Loading…
Reference in New Issue