mirror of
https://github.com/nghttp2/nghttp2.git
synced 2025-12-08 19:18:53 +08:00
nghttp2_sesson_mem_recv: Process incoming data in streaming fashion
Now incoming data is processed in very small buffer (up to 8 bytes) using state machine. GOAWAY debug data can get to 16K - 1, and we don't have callback for it. Since we don't want to buffer that amount of data just for debugging, we currently discard it. This change also makes parse_error callback not function. It probably be removed from API.
This commit is contained in:
@@ -270,6 +270,25 @@ int nghttp2_frame_unpack_headers_without_nv(nghttp2_headers *frame,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
|
||||
const uint8_t *payload,
|
||||
size_t payloadlen)
|
||||
{
|
||||
/* TODO Return error if header continuation is used for now */
|
||||
if((frame->hd.flags & NGHTTP2_FLAG_END_HEADERS) == 0) {
|
||||
return NGHTTP2_ERR_PROTO;
|
||||
}
|
||||
if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
|
||||
assert(payloadlen == 4);
|
||||
frame->pri = nghttp2_get_uint32(payload) & NGHTTP2_PRIORITY_MASK;
|
||||
} else {
|
||||
frame->pri = NGHTTP2_PRI_DEFAULT;
|
||||
}
|
||||
frame->nva = NULL;
|
||||
frame->nvlen = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t nghttp2_frame_pack_priority(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
nghttp2_priority *frame)
|
||||
{
|
||||
@@ -295,7 +314,13 @@ int nghttp2_frame_unpack_priority(nghttp2_priority *frame,
|
||||
nghttp2_frame_unpack_frame_hd(&frame->hd, head);
|
||||
frame->pri = nghttp2_get_uint32(payload) & NGHTTP2_PRIORITY_MASK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame,
|
||||
const uint8_t *payload,
|
||||
size_t payloadlen)
|
||||
{
|
||||
frame->pri = nghttp2_get_uint32(payload) & NGHTTP2_PRIORITY_MASK;
|
||||
}
|
||||
|
||||
ssize_t nghttp2_frame_pack_rst_stream(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
@@ -325,6 +350,13 @@ int nghttp2_frame_unpack_rst_stream(nghttp2_rst_stream *frame,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame,
|
||||
const uint8_t *payload,
|
||||
size_t payloadlen)
|
||||
{
|
||||
frame->error_code = nghttp2_get_uint32(payload);
|
||||
}
|
||||
|
||||
ssize_t nghttp2_frame_pack_settings(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
nghttp2_settings *frame)
|
||||
{
|
||||
@@ -371,6 +403,29 @@ int nghttp2_frame_unpack_settings(nghttp2_settings *frame,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_frame_unpack_settings_payload2(nghttp2_settings *frame,
|
||||
nghttp2_settings_entry *iv,
|
||||
size_t niv)
|
||||
{
|
||||
size_t payloadlen = niv * sizeof(nghttp2_settings_entry);
|
||||
|
||||
frame->iv = malloc(payloadlen);
|
||||
if(frame->iv == NULL) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
memcpy(frame->iv, iv, payloadlen);
|
||||
frame->niv = niv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_settings_entry(nghttp2_settings_entry *iv,
|
||||
const uint8_t *payload)
|
||||
{
|
||||
iv->settings_id = nghttp2_get_uint32(&payload[0]) &
|
||||
NGHTTP2_SETTINGS_ID_MASK;
|
||||
iv->value = nghttp2_get_uint32(&payload[4]);
|
||||
}
|
||||
|
||||
int nghttp2_frame_unpack_settings_payload(nghttp2_settings_entry **iv_ptr,
|
||||
size_t *niv_ptr,
|
||||
const uint8_t *payload,
|
||||
@@ -384,9 +439,7 @@ int nghttp2_frame_unpack_settings_payload(nghttp2_settings_entry **iv_ptr,
|
||||
}
|
||||
for(i = 0; i < *niv_ptr; ++i) {
|
||||
size_t off = i*8;
|
||||
(*iv_ptr)[i].settings_id = nghttp2_get_uint32(&payload[off]) &
|
||||
NGHTTP2_SETTINGS_ID_MASK;
|
||||
(*iv_ptr)[i].value = nghttp2_get_uint32(&payload[4+off]);
|
||||
nghttp2_frame_unpack_settings_entry(&(*iv_ptr)[i], &payload[off]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -440,6 +493,21 @@ int nghttp2_frame_unpack_push_promise_without_nv(nghttp2_push_promise *frame,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
|
||||
const uint8_t *payload,
|
||||
size_t payloadlen)
|
||||
{
|
||||
/* TODO Return error if header continuation is used for now */
|
||||
if((frame->hd.flags & NGHTTP2_FLAG_END_PUSH_PROMISE) == 0) {
|
||||
return NGHTTP2_ERR_PROTO;
|
||||
}
|
||||
frame->promised_stream_id = nghttp2_get_uint32(payload) &
|
||||
NGHTTP2_STREAM_ID_MASK;
|
||||
frame->nva = NULL;
|
||||
frame->nvlen = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t nghttp2_frame_pack_ping(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
nghttp2_ping *frame)
|
||||
{
|
||||
@@ -467,6 +535,12 @@ int nghttp2_frame_unpack_ping(nghttp2_ping *frame,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame,
|
||||
const uint8_t *payload,
|
||||
size_t payloadlen)
|
||||
{
|
||||
memcpy(frame->opaque_data, payload, sizeof(frame->opaque_data));
|
||||
}
|
||||
|
||||
ssize_t nghttp2_frame_pack_goaway(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
nghttp2_goaway *frame)
|
||||
@@ -508,6 +582,17 @@ int nghttp2_frame_unpack_goaway(nghttp2_goaway *frame,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_goaway_payload(nghttp2_goaway *frame,
|
||||
const uint8_t *payload,
|
||||
size_t payloadlen)
|
||||
{
|
||||
frame->last_stream_id = nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
|
||||
frame->error_code = nghttp2_get_uint32(payload+4);
|
||||
/* TODO Currently we don't buffer debug data */
|
||||
frame->opaque_data = NULL;
|
||||
frame->opaque_data_len = 0;
|
||||
}
|
||||
|
||||
ssize_t nghttp2_frame_pack_window_update(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
nghttp2_window_update *frame)
|
||||
{
|
||||
@@ -537,6 +622,14 @@ int nghttp2_frame_unpack_window_update(nghttp2_window_update *frame,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
|
||||
const uint8_t *payload,
|
||||
size_t payloadlen)
|
||||
{
|
||||
frame->window_size_increment = nghttp2_get_uint32(payload) &
|
||||
NGHTTP2_WINDOW_SIZE_INCREMENT_MASK;
|
||||
}
|
||||
|
||||
nghttp2_settings_entry* nghttp2_frame_iv_copy(const nghttp2_settings_entry *iv,
|
||||
size_t niv)
|
||||
{
|
||||
|
||||
@@ -161,6 +161,10 @@ int nghttp2_frame_unpack_headers_without_nv(nghttp2_headers *frame,
|
||||
const uint8_t *payload,
|
||||
size_t payloadlen);
|
||||
|
||||
int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
|
||||
const uint8_t *payload,
|
||||
size_t payloadlen);
|
||||
|
||||
/*
|
||||
* Packs PRIORITY frame |frame| in wire format and store it in
|
||||
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
|
||||
@@ -189,6 +193,10 @@ int nghttp2_frame_unpack_priority(nghttp2_priority *frame,
|
||||
const uint8_t *head, size_t headlen,
|
||||
const uint8_t *payload, size_t payloadlen);
|
||||
|
||||
void nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame,
|
||||
const uint8_t *payload,
|
||||
size_t payloadlen);
|
||||
|
||||
/*
|
||||
* Packs RST_STREAM frame |frame| in wire frame format and store it in
|
||||
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
|
||||
@@ -218,6 +226,10 @@ int nghttp2_frame_unpack_rst_stream(nghttp2_rst_stream *frame,
|
||||
const uint8_t *head, size_t headlen,
|
||||
const uint8_t *payload, size_t payloadlen);
|
||||
|
||||
void nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame,
|
||||
const uint8_t *payload,
|
||||
size_t payloadlen);
|
||||
|
||||
/*
|
||||
* Packs SETTINGS frame |frame| in wire format and store it in
|
||||
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
|
||||
@@ -259,6 +271,13 @@ int nghttp2_frame_unpack_settings(nghttp2_settings *frame,
|
||||
const uint8_t *payload, size_t payloadlen);
|
||||
|
||||
|
||||
void nghttp2_frame_unpack_settings_entry(nghttp2_settings_entry *iv,
|
||||
const uint8_t *payload);
|
||||
|
||||
int nghttp2_frame_unpack_settings_payload2(nghttp2_settings *frame,
|
||||
nghttp2_settings_entry *iv,
|
||||
size_t niv);
|
||||
|
||||
/*
|
||||
* Unpacks SETTINGS payload into |*iv_ptr|. The number of entries are
|
||||
* assigned to the |*niv_ptr|. This function allocates enough memory
|
||||
@@ -347,6 +366,10 @@ int nghttp2_frame_unpack_push_promise_without_nv(nghttp2_push_promise *frame,
|
||||
const uint8_t *payload,
|
||||
size_t payloadlen);
|
||||
|
||||
int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
|
||||
const uint8_t *payload,
|
||||
size_t payloadlen);
|
||||
|
||||
/*
|
||||
* Packs PING frame |frame| in wire format and store it in
|
||||
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
|
||||
@@ -375,6 +398,10 @@ int nghttp2_frame_unpack_ping(nghttp2_ping *frame,
|
||||
const uint8_t *head, size_t headlen,
|
||||
const uint8_t *payload, size_t payloadlen);
|
||||
|
||||
void nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame,
|
||||
const uint8_t *payload,
|
||||
size_t payloadlen);
|
||||
|
||||
/*
|
||||
* Packs GOAWAY frame |frame | in wire format and store it in
|
||||
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
|
||||
@@ -405,6 +432,10 @@ int nghttp2_frame_unpack_goaway(nghttp2_goaway *frame,
|
||||
const uint8_t *head, size_t headlen,
|
||||
const uint8_t *payload, size_t payloadlen);
|
||||
|
||||
void nghttp2_frame_unpack_goaway_payload(nghttp2_goaway *frame,
|
||||
const uint8_t *payload,
|
||||
size_t payloadlen);
|
||||
|
||||
/*
|
||||
* Packs WINDOW_UPDATE frame |frame| in wire frame format and store it
|
||||
* in |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
|
||||
@@ -434,6 +465,10 @@ int nghttp2_frame_unpack_window_update(nghttp2_window_update *frame,
|
||||
const uint8_t *payload,
|
||||
size_t payloadlen);
|
||||
|
||||
void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
|
||||
const uint8_t *payload,
|
||||
size_t payloadlen);
|
||||
|
||||
/*
|
||||
* Initializes HEADERS frame |frame| with given values. |frame| takes
|
||||
* ownership of |nva|, so caller must not free it. If |stream_id| is
|
||||
|
||||
@@ -45,7 +45,9 @@ typedef int (*nghttp2_compar)(const void *lhs, const void *rhs);
|
||||
inclusive. */
|
||||
typedef enum {
|
||||
NGHTTP2_ERR_CREDENTIAL_PENDING = -101,
|
||||
NGHTTP2_ERR_BUFFER_ERROR = - 102
|
||||
NGHTTP2_ERR_BUFFER_ERROR = -102,
|
||||
NGHTTP2_ERR_IGN_HEADER_BLOCK = -103,
|
||||
NGHTTP2_ERR_IGN_PAYLOAD = -104,
|
||||
} nghttp2_internal_error;
|
||||
|
||||
#endif /* NGHTTP2_INT_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -37,6 +37,7 @@
|
||||
#include "nghttp2_stream.h"
|
||||
#include "nghttp2_buffer.h"
|
||||
#include "nghttp2_outbound_item.h"
|
||||
#include "nghttp2_int.h"
|
||||
|
||||
/*
|
||||
* Option flags.
|
||||
@@ -72,39 +73,36 @@ typedef struct {
|
||||
/* Internal state when receiving incoming frame */
|
||||
typedef enum {
|
||||
/* Receiving frame header */
|
||||
NGHTTP2_RECV_HEAD,
|
||||
/* Receiving frame payload (comes after length field) */
|
||||
NGHTTP2_RECV_PAYLOAD,
|
||||
/* Receiving frame payload, but the received bytes are discarded. */
|
||||
NGHTTP2_RECV_PAYLOAD_IGN
|
||||
NGHTTP2_IB_READ_HEAD,
|
||||
NGHTTP2_IB_READ_NBYTE,
|
||||
NGHTTP2_IB_READ_HEADER_BLOCK,
|
||||
NGHTTP2_IB_IGN_HEADER_BLOCK,
|
||||
NGHTTP2_IB_IGN_PAYLOAD,
|
||||
NGHTTP2_IB_FRAME_SIZE_ERROR,
|
||||
NGHTTP2_IB_READ_SETTINGS,
|
||||
NGHTTP2_IB_READ_GOAWAY_DEBUG,
|
||||
NGHTTP2_IB_READ_DATA,
|
||||
NGHTTP2_IB_IGN_DATA
|
||||
} nghttp2_inbound_state;
|
||||
|
||||
typedef struct {
|
||||
nghttp2_frame frame;
|
||||
/* Payload for non-DATA frames. */
|
||||
uint8_t *buf;
|
||||
/* How many bytes are filled in headbuf */
|
||||
size_t headbufoff;
|
||||
/* Capacity of buf */
|
||||
size_t bufmax;
|
||||
/* For frames without name/value header block, this is how many
|
||||
bytes are going to filled in buf. For frames with the block, buf
|
||||
only contains bytes that come before ther block, but this value
|
||||
includes the length of the block. buflen <= bufmax must be
|
||||
fulfilled. */
|
||||
size_t buflen;
|
||||
/* length in Length field */
|
||||
size_t payloadlen;
|
||||
/* How many bytes are received for this frame. off <= payloadlen
|
||||
must be fulfilled. */
|
||||
size_t off;
|
||||
/* How many bytes are decompressed inside |buf|. This is used for
|
||||
header decompression. */
|
||||
size_t inflate_offset;
|
||||
/* The received SETTINGS entry. The protocol says that we only cares
|
||||
about the defined settings ID. If unknown ID is received, it is
|
||||
subject to connection error */
|
||||
nghttp2_settings_entry iv[5];
|
||||
/* The number of entry filled in |iv| */
|
||||
size_t niv;
|
||||
/* How many bytes we still need to receive in the |buf| */
|
||||
size_t left;
|
||||
/* How many bytes we still need to receive for current frame */
|
||||
size_t payloadleft;
|
||||
nghttp2_inbound_state state;
|
||||
/* Error code */
|
||||
/* TODO, remove this. Error code */
|
||||
int error_code;
|
||||
uint8_t headbuf[NGHTTP2_FRAME_HEAD_LENGTH];
|
||||
uint8_t buf[8];
|
||||
/* How many bytes have been written to |buf| */
|
||||
uint8_t buflen;
|
||||
} nghttp2_inbound_frame;
|
||||
|
||||
typedef enum {
|
||||
@@ -131,9 +129,6 @@ struct nghttp2_session {
|
||||
/* Sequence number of outbound frame to maintain the order of
|
||||
enqueue if priority is equal. */
|
||||
int64_t next_seq;
|
||||
/* Buffer used to store inflated name/value pairs in wire format
|
||||
temporarily on pack/unpack. */
|
||||
uint8_t *nvbuf;
|
||||
void *user_data;
|
||||
/* In-flight SETTINGS values. NULL does not necessarily mean there
|
||||
is no in-flight SETTINGS. */
|
||||
@@ -358,6 +353,15 @@ int nghttp2_session_close_stream_if_shut_rdwr(nghttp2_session *session,
|
||||
nghttp2_stream *stream);
|
||||
|
||||
|
||||
int nghttp2_session_end_request_headers_received(nghttp2_session *session,
|
||||
nghttp2_frame *frame);
|
||||
|
||||
int nghttp2_session_end_response_headers_received(nghttp2_session *session,
|
||||
nghttp2_frame *frame);
|
||||
|
||||
int nghttp2_session_end_headers_received(nghttp2_session *session,
|
||||
nghttp2_frame *frame);
|
||||
|
||||
int nghttp2_session_on_request_headers_received(nghttp2_session *session,
|
||||
nghttp2_frame *frame);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user