wininet: Don't assume that end of chunk means end of stream.
This commit is contained in:
parent
b4ab43b3de
commit
c0e1dda04c
|
@ -400,6 +400,7 @@ typedef struct {
|
||||||
DWORD buf_size;
|
DWORD buf_size;
|
||||||
DWORD buf_pos;
|
DWORD buf_pos;
|
||||||
DWORD chunk_size;
|
DWORD chunk_size;
|
||||||
|
BOOL end_of_data;
|
||||||
} chunked_stream_t;
|
} chunked_stream_t;
|
||||||
|
|
||||||
static inline void destroy_data_stream(data_stream_t *stream)
|
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;
|
DWORD res;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
assert(!stream->end_of_data);
|
||||||
|
|
||||||
if (stream->buf_pos)
|
if (stream->buf_pos)
|
||||||
{
|
{
|
||||||
/* move existing data to the start of the buffer */
|
/* 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) */
|
/* 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)
|
static DWORD start_next_chunk(chunked_stream_t *stream, http_request_t *req)
|
||||||
{
|
{
|
||||||
/* TODOO */
|
|
||||||
DWORD chunk_size = 0, res;
|
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;
|
return res;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
|
@ -2764,6 +2771,8 @@ static DWORD start_next_chunk(chunked_stream_t *stream, http_request_t *req)
|
||||||
stream->chunk_size = chunk_size;
|
stream->chunk_size = chunk_size;
|
||||||
if (req->contentLength == ~0u) req->contentLength = chunk_size;
|
if (req->contentLength == ~0u) req->contentLength = chunk_size;
|
||||||
else req->contentLength += chunk_size;
|
else req->contentLength += chunk_size;
|
||||||
|
|
||||||
|
if (!chunk_size) stream->end_of_data = TRUE;
|
||||||
return discard_chunked_eol(stream, req);
|
return discard_chunked_eol(stream, req);
|
||||||
}
|
}
|
||||||
remove_chunked_data(stream, 1);
|
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)
|
static BOOL chunked_end_of_data(data_stream_t *stream, http_request_t *req)
|
||||||
{
|
{
|
||||||
chunked_stream_t *chunked_stream = (chunked_stream_t*)stream;
|
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,
|
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;
|
chunked_stream_t *chunked_stream = (chunked_stream_t*)stream;
|
||||||
DWORD read_bytes = 0, ret_read = 0, res = ERROR_SUCCESS;
|
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);
|
res = start_next_chunk(chunked_stream, req);
|
||||||
if(res != ERROR_SUCCESS)
|
if(res != ERROR_SUCCESS)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
while(size && chunked_stream->chunk_size) {
|
while(size && chunked_stream->chunk_size && !chunked_stream->end_of_data) {
|
||||||
if(chunked_stream->buf_size) {
|
if(chunked_stream->buf_size) {
|
||||||
read_bytes = min(size, min(chunked_stream->buf_size, chunked_stream->chunk_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;
|
chunked_stream->chunk_size -= read_bytes;
|
||||||
size -= read_bytes;
|
size -= read_bytes;
|
||||||
ret_read += read_bytes;
|
ret_read += read_bytes;
|
||||||
if(!chunked_stream->chunk_size) {
|
if(size && !chunked_stream->chunk_size) {
|
||||||
assert(read_mode != READMODE_NOBLOCK);
|
assert(read_mode != READMODE_NOBLOCK);
|
||||||
res = start_next_chunk(chunked_stream, req);
|
res = start_next_chunk(chunked_stream, req);
|
||||||
if(res != ERROR_SUCCESS)
|
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;
|
chunked_stream_t *chunked_stream = (chunked_stream_t*)stream;
|
||||||
|
|
||||||
/* FIXME: we can do better */
|
remove_chunked_data(chunked_stream, chunked_stream->buf_size);
|
||||||
return !chunked_stream->chunk_size;
|
return chunked_stream->end_of_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void chunked_destroy(data_stream_t *stream)
|
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->data_stream.vtbl = &chunked_stream_vtbl;
|
||||||
chunked_stream->buf_size = chunked_stream->buf_pos = 0;
|
chunked_stream->buf_size = chunked_stream->buf_pos = 0;
|
||||||
chunked_stream->chunk_size = ~0u;
|
chunked_stream->chunk_size = ~0u;
|
||||||
|
chunked_stream->end_of_data = FALSE;
|
||||||
|
|
||||||
if(request->read_size) {
|
if(request->read_size) {
|
||||||
memcpy(chunked_stream->buf, request->read_buf+request->read_pos, request->read_size);
|
memcpy(chunked_stream->buf, request->read_buf+request->read_pos, request->read_size);
|
||||||
|
|
|
@ -4777,7 +4777,36 @@ static const struct notification async_send_request_ex_resolve_failure_test[] =
|
||||||
{ internet_close_handle, INTERNET_STATUS_HANDLE_CLOSING, 0, }
|
{ 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[] = {
|
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,
|
async_send_request_ex_test,
|
||||||
sizeof(async_send_request_ex_test)/sizeof(async_send_request_ex_test[0]),
|
sizeof(async_send_request_ex_test)/sizeof(async_send_request_ex_test[0]),
|
||||||
|
@ -5100,6 +5129,7 @@ START_TEST(http)
|
||||||
test_async_HttpSendRequestEx(¬ification_data[0]);
|
test_async_HttpSendRequestEx(¬ification_data[0]);
|
||||||
test_async_HttpSendRequestEx(¬ification_data[1]);
|
test_async_HttpSendRequestEx(¬ification_data[1]);
|
||||||
test_async_HttpSendRequestEx(¬ification_data[2]);
|
test_async_HttpSendRequestEx(¬ification_data[2]);
|
||||||
|
test_async_HttpSendRequestEx(¬ification_data[3]);
|
||||||
InternetOpenRequest_test();
|
InternetOpenRequest_test();
|
||||||
test_http_cache();
|
test_http_cache();
|
||||||
InternetOpenUrlA_test();
|
InternetOpenUrlA_test();
|
||||||
|
|
Loading…
Reference in New Issue