X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fuhttpd.git;a=blobdiff_plain;f=client.c;h=408a8132b1645c03207faec7cf0fe5771be9463d;hp=b673153edab48490ada82fd15e3f28c6dd6865bb;hb=a5138de52dc022aaec26948055da676851613086;hpb=2bef561c890f275ce3b785e6abdb3eda28c96aa8 diff --git a/client.c b/client.c index b673153..408a813 100644 --- a/client.c +++ b/client.c @@ -261,15 +261,16 @@ static bool client_data_cb(struct client *cl, char *buf, int len) return false; while (len) { + int offset = 0; char *sep; - r->content_length -= cur_len; consumed += cur_len; buf += cur_len; len -= cur_len; cur_len = min(r->content_length, len); if (cur_len) { + r->content_length -= cur_len; if (d->data_send) d->data_send(cl, buf, cur_len); continue; @@ -278,28 +279,44 @@ static bool client_data_cb(struct client *cl, char *buf, int len) if (!r->transfer_chunked) break; - sep = strstr(buf, "\r\n"); + if (r->transfer_chunked > 1) + offset = 2; + + sep = strstr(buf + offset, "\r\n"); if (!sep) break; *sep = 0; cur_len = sep + 2 - buf; - r->content_length = strtoul(buf, &sep, 16); + r->content_length = strtoul(buf + offset, &sep, 16); + r->transfer_chunked++; /* invalid chunk length */ if (sep && *sep) - return false; + goto abort; /* empty chunk == eof */ - if (!r->content_length) { + if (!r->content_length) r->transfer_chunked = false; - continue; - } + + continue; + +abort: + consumed = len; + r->content_length = 0; + r->transfer_chunked = 0; + break; } ustream_consume(cl->us, consumed); - return r->content_length || r->transfer_chunked; + if (!r->content_length && !r->transfer_chunked) { + if (cl->dispatch.data_done) + cl->dispatch.data_done(cl); + + cl->state = CLIENT_STATE_DONE; + } + return false; } static bool client_header_cb(struct client *cl, char *buf, int len) @@ -345,8 +362,6 @@ static void client_read_cb(struct client *cl) if (!read_cbs[cl->state](cl, str, len)) { if (len == us->r.buffer_len) uh_header_error(cl, 413, "Request Entity Too Large"); - if (cl->dispatch.data_done) - cl->dispatch.data_done(cl); break; } } while(1); @@ -354,6 +369,7 @@ static void client_read_cb(struct client *cl) static void client_close(struct client *cl) { + n_clients--; uh_dispatch_done(cl); uloop_timeout_cancel(&cl->timeout); ustream_free(&cl->sfd.stream);