Module: wine Branch: master Commit: c0e1dda04cce1192d477a831ece4b9e2c22353e9 URL: http://source.winehq.org/git/wine.git/?a=commit;h=c0e1dda04cce1192d477a831ec...
Author: Hans Leidekker hans@codeweavers.com Date: Wed Sep 18 13:40:24 2013 +0200
wininet: Don't assume that end of chunk means end of stream.
---
dlls/wininet/http.c | 26 ++++++++++++++++++-------- dlls/wininet/tests/http.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 8 deletions(-)
diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c index 1832b4f..2d11040 100644 --- a/dlls/wininet/http.c +++ b/dlls/wininet/http.c @@ -400,6 +400,7 @@ typedef struct { DWORD buf_size; DWORD buf_pos; DWORD chunk_size; + BOOL end_of_data; } chunked_stream_t;
static inline void destroy_data_stream(data_stream_t *stream) @@ -2697,6 +2698,8 @@ static DWORD read_more_chunked_data(chunked_stream_t *stream, http_request_t *re DWORD res; int len;
+ assert(!stream->end_of_data); + if (stream->buf_pos) { /* move existing data to the start of the buffer */ @@ -2744,10 +2747,14 @@ static DWORD discard_chunked_eol(chunked_stream_t *stream, http_request_t *req) /* read the size of the next chunk (the read section must be held) */ static DWORD start_next_chunk(chunked_stream_t *stream, http_request_t *req) { - /* TODOO */ DWORD chunk_size = 0, res;
- if(stream->chunk_size != ~0u && (res = discard_chunked_eol(stream, req)) != ERROR_SUCCESS) + assert(!stream->chunk_size || stream->chunk_size == ~0u); + + if (stream->end_of_data) return ERROR_NO_MORE_FILES; + + /* read terminator for the previous chunk */ + if(!stream->chunk_size && (res = discard_chunked_eol(stream, req)) != ERROR_SUCCESS) return res;
for (;;) @@ -2764,6 +2771,8 @@ static DWORD start_next_chunk(chunked_stream_t *stream, http_request_t *req) stream->chunk_size = chunk_size; if (req->contentLength == ~0u) req->contentLength = chunk_size; else req->contentLength += chunk_size; + + if (!chunk_size) stream->end_of_data = TRUE; return discard_chunked_eol(stream, req); } remove_chunked_data(stream, 1); @@ -2786,7 +2795,7 @@ static DWORD chunked_get_avail_data(data_stream_t *stream, http_request_t *req) static BOOL chunked_end_of_data(data_stream_t *stream, http_request_t *req) { chunked_stream_t *chunked_stream = (chunked_stream_t*)stream; - return !chunked_stream->chunk_size; + return chunked_stream->end_of_data; }
static DWORD chunked_read(data_stream_t *stream, http_request_t *req, BYTE *buf, DWORD size, @@ -2795,13 +2804,13 @@ static DWORD chunked_read(data_stream_t *stream, http_request_t *req, BYTE *buf, chunked_stream_t *chunked_stream = (chunked_stream_t*)stream; DWORD read_bytes = 0, ret_read = 0, res = ERROR_SUCCESS;
- if(chunked_stream->chunk_size == ~0u) { + if(!chunked_stream->chunk_size || chunked_stream->chunk_size == ~0u) { res = start_next_chunk(chunked_stream, req); if(res != ERROR_SUCCESS) return res; }
- while(size && chunked_stream->chunk_size) { + while(size && chunked_stream->chunk_size && !chunked_stream->end_of_data) { if(chunked_stream->buf_size) { read_bytes = min(size, min(chunked_stream->buf_size, chunked_stream->chunk_size));
@@ -2835,7 +2844,7 @@ static DWORD chunked_read(data_stream_t *stream, http_request_t *req, BYTE *buf, chunked_stream->chunk_size -= read_bytes; size -= read_bytes; ret_read += read_bytes; - if(!chunked_stream->chunk_size) { + if(size && !chunked_stream->chunk_size) { assert(read_mode != READMODE_NOBLOCK); res = start_next_chunk(chunked_stream, req); if(res != ERROR_SUCCESS) @@ -2855,8 +2864,8 @@ static BOOL chunked_drain_content(data_stream_t *stream, http_request_t *req) { chunked_stream_t *chunked_stream = (chunked_stream_t*)stream;
- /* FIXME: we can do better */ - return !chunked_stream->chunk_size; + remove_chunked_data(chunked_stream, chunked_stream->buf_size); + return chunked_stream->end_of_data; }
static void chunked_destroy(data_stream_t *stream) @@ -2905,6 +2914,7 @@ static DWORD set_content_length(http_request_t *request) chunked_stream->data_stream.vtbl = &chunked_stream_vtbl; chunked_stream->buf_size = chunked_stream->buf_pos = 0; chunked_stream->chunk_size = ~0u; + chunked_stream->end_of_data = FALSE;
if(request->read_size) { memcpy(chunked_stream->buf, request->read_buf+request->read_pos, request->read_size); diff --git a/dlls/wininet/tests/http.c b/dlls/wininet/tests/http.c index bf57223..2526681 100644 --- a/dlls/wininet/tests/http.c +++ b/dlls/wininet/tests/http.c @@ -4777,8 +4777,37 @@ static const struct notification async_send_request_ex_resolve_failure_test[] = { internet_close_handle, INTERNET_STATUS_HANDLE_CLOSING, 0, } };
+static const struct notification async_send_request_ex_chunked_test[] = +{ + { internet_connect, INTERNET_STATUS_HANDLE_CREATED }, + { http_open_request, INTERNET_STATUS_HANDLE_CREATED }, + { http_send_request_ex, INTERNET_STATUS_DETECTING_PROXY, 1, 0, 1 }, + { http_send_request_ex, INTERNET_STATUS_COOKIE_SENT, 1, 0, 1 }, + { http_send_request_ex, INTERNET_STATUS_RESOLVING_NAME, 1, 0, 1 }, + { http_send_request_ex, INTERNET_STATUS_NAME_RESOLVED, 1, 0, 1 }, + { http_send_request_ex, INTERNET_STATUS_CONNECTING_TO_SERVER, 1 }, + { http_send_request_ex, INTERNET_STATUS_CONNECTED_TO_SERVER, 1 }, + { http_send_request_ex, INTERNET_STATUS_SENDING_REQUEST, 1 }, + { http_send_request_ex, INTERNET_STATUS_REQUEST_SENT, 1 }, + { http_send_request_ex, INTERNET_STATUS_REQUEST_COMPLETE, 1 }, + { http_end_request, INTERNET_STATUS_RECEIVING_RESPONSE, 1 }, + { http_end_request, INTERNET_STATUS_RESPONSE_RECEIVED, 1 }, + { http_end_request, INTERNET_STATUS_REQUEST_COMPLETE, 1 }, + { internet_close_handle, INTERNET_STATUS_CLOSING_CONNECTION }, + { internet_close_handle, INTERNET_STATUS_CONNECTION_CLOSED }, + { internet_close_handle, INTERNET_STATUS_HANDLE_CLOSING }, + { internet_close_handle, INTERNET_STATUS_HANDLE_CLOSING } +}; + static const struct notification_data notification_data[] = { { + async_send_request_ex_chunked_test, + sizeof(async_send_request_ex_chunked_test)/sizeof(async_send_request_ex_chunked_test[0]), + "GET", + "test.winehq.org", + "tests/data.php" + }, + { async_send_request_ex_test, sizeof(async_send_request_ex_test)/sizeof(async_send_request_ex_test[0]), "POST", @@ -5100,6 +5129,7 @@ START_TEST(http) test_async_HttpSendRequestEx(¬ification_data[0]); test_async_HttpSendRequestEx(¬ification_data[1]); test_async_HttpSendRequestEx(¬ification_data[2]); + test_async_HttpSendRequestEx(¬ification_data[3]); InternetOpenRequest_test(); test_http_cache(); InternetOpenUrlA_test();