Browse Source

fix connection is_closed handling (never close raw_out, never close con->out.source->out)

personal/stbuehler/wip
Stefan Bühler 9 years ago
parent
commit
7a01f69b89
  1. 17
      src/main/connection.c
  2. 1
      src/main/filter_chunked.c
  3. 8
      src/main/response.c
  4. 10
      src/main/stream_http_response.c

17
src/main/connection.c

@ -364,6 +364,7 @@ static void _connection_http_out_cb(liStream *stream, liStreamEvent event) {
/* handle below */
break;
case LI_STREAM_CONNECTED_SOURCE:
/* also handle data immediately */
break;
case LI_STREAM_DISCONNECTED_SOURCE:
if (!con->out_has_all_data) li_connection_error(con);
@ -385,6 +386,8 @@ static void _connection_http_out_cb(liStream *stream, liStreamEvent event) {
out = (NULL != stream->source) ? stream->source->out : NULL;
/* keep raw_out->is_closed = FALSE for keep-alive requests; instead set con->out_has_all_data = TRUE */
if (LI_CON_STATE_HANDLE_MAINVR <= con->state) {
if (NULL == stream->source) {
if (LI_CON_STATE_HANDLE_MAINVR == con->state) {
@ -403,18 +406,22 @@ static void _connection_http_out_cb(liStream *stream, liStreamEvent event) {
if (!con->out_has_all_data && !raw_out->is_closed && NULL != out) {
if (vr->response.transfer_encoding & LI_HTTP_TRANSFER_ENCODING_CHUNKED) {
li_filter_chunked_encode(vr, raw_out, out);
raw_out->is_closed = FALSE;
} else {
li_chunkqueue_steal_all(raw_out, out);
}
if (out->is_closed) {
con->out_has_all_data = TRUE;
}
if (raw_out->is_closed || NULL == out || out->is_closed) {
con->out_has_all_data = TRUE;
raw_out->is_closed = FALSE;
}
if (con->out_has_all_data) {
if (con->state < LI_CON_STATE_WRITE) con->state = LI_CON_STATE_WRITE;
if (NULL != out) {
out = NULL;
li_stream_disconnect(stream);
con->state = LI_CON_STATE_WRITE;
}
con->info.out_queue_length = raw_out->length;
}
con->info.out_queue_length = raw_out->length;
}
li_stream_notify(stream);

1
src/main/filter_chunked.c

@ -188,7 +188,6 @@ liHandlerResult li_filter_chunked_decode(liVRequest *vr, liChunkQueue *out, liCh
leave:
if (res == LI_HANDLER_ERROR) {
out->is_closed = TRUE;
in->is_closed = TRUE;
li_chunkqueue_skip_all(in);
state->parse_state = 20;
}

8
src/main/response.c

@ -53,8 +53,8 @@ void li_response_send_headers(liVRequest *vr, liChunkQueue *raw_out, liChunkQueu
vr->response.http_status == 205 ||
vr->response.http_status == 304) {
/* They never have a content-body/length */
li_chunkqueue_reset(response_body);
response_body->is_closed = TRUE;
li_chunkqueue_skip_all(response_body);
raw_out->is_closed = TRUE;
} else if (response_complete) {
if (vr->request.http_method != LI_HTTP_METHOD_HEAD || response_body->length > 0) {
/* do not send content-length: 0 if backend already skipped content generation for HEAD */
@ -74,8 +74,8 @@ void li_response_send_headers(liVRequest *vr, liChunkQueue *raw_out, liChunkQueu
if (vr->request.http_method == LI_HTTP_METHOD_HEAD) {
/* content-length is set, but no body */
li_chunkqueue_reset(response_body);
response_body->is_closed = TRUE;
li_chunkqueue_skip_all(response_body);
raw_out->is_closed = TRUE;
}
/* Status line */

10
src/main/stream_http_response.c

@ -10,7 +10,7 @@ struct liStreamHttpResponse {
gboolean response_headers_finished;
};
static void stream_http_respone_data(liStreamHttpResponse* shr) {
static void stream_http_response_data(liStreamHttpResponse* shr) {
if (NULL == shr->stream.source) return;
if (!shr->response_headers_finished) {
@ -24,7 +24,7 @@ static void stream_http_respone_data(liStreamHttpResponse* shr) {
li_vrequest_error(shr->vr);
return;
case LI_HANDLER_WAIT_FOR_EVENT:
if (shr->stream.source == NULL || shr->stream.source->out->is_closed) {
if (shr->stream.source->out->is_closed) {
VR_ERROR(shr->vr, "%s", "Parsing response header failed (eos)");
li_vrequest_error(shr->vr);
}
@ -48,13 +48,15 @@ static void stream_http_response_cb(liStream *stream, liStreamEvent event) {
switch (event) {
case LI_STREAM_NEW_DATA:
stream_http_respone_data(shr);
stream_http_response_data(shr);
break;
case LI_STREAM_DISCONNECTED_DEST:
shr->vr = NULL;
li_stream_disconnect(stream);
break;
case LI_STREAM_DISCONNECTED_SOURCE:
if (NULL != stream->dest && !stream->out->is_closed) {
shr->vr = NULL;
if (!stream->out->is_closed) {
/* "abort" */
li_stream_disconnect_dest(stream);
}

Loading…
Cancel
Save