Module: wine Branch: master Commit: 08808747b2e2aa590a5c8dc0d85c2882b098c460 URL: http://source.winehq.org/git/wine.git/?a=commit;h=08808747b2e2aa590a5c8dc0d8...
Author: Jacek Caban jacek@codeweavers.com Date: Thu Mar 9 18:19:50 2017 +0100
wininet: Rewrite InternetReadFileEx for http protocol to make use of non-blocking reads.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/wininet/http.c | 100 ++++++++++++++++++++++------------------------ dlls/wininet/tests/http.c | 10 ----- 2 files changed, 48 insertions(+), 62 deletions(-)
diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c index 4109849..c9119f3 100644 --- a/dlls/wininet/http.c +++ b/dlls/wininet/http.c @@ -3166,77 +3166,73 @@ static DWORD async_read(http_request_t *req, void *buf, DWORD size, DWORD read_p static DWORD HTTPREQ_ReadFileEx(object_header_t *hdr, void *buf, DWORD size, DWORD *ret_read, DWORD flags, DWORD_PTR context) { - http_request_t *req = (http_request_t*)hdr; - DWORD res, read, cread, error = ERROR_SUCCESS; + DWORD res = ERROR_SUCCESS, read = 0, cread, error = ERROR_SUCCESS; + BOOL allow_blocking, notify_received = FALSE;
TRACE("(%p %p %u %x)\n", req, buf, size, flags);
if (flags & ~(IRF_ASYNC|IRF_NO_WAIT)) FIXME("these dwFlags aren't implemented: 0x%x\n", flags & ~(IRF_ASYNC|IRF_NO_WAIT));
- INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0); + allow_blocking = !(req->session->appInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC); + + if(allow_blocking || TryEnterCriticalSection(&req->read_section)) { + if(allow_blocking) + EnterCriticalSection(&req->read_section); + if(hdr->dwError == ERROR_SUCCESS) + hdr->dwError = INTERNET_HANDLE_IN_USE; + else if(hdr->dwError == INTERNET_HANDLE_IN_USE) + hdr->dwError = ERROR_INTERNET_INTERNAL_ERROR; + + if(req->read_size) { + read = min(size, req->read_size); + memcpy(buf, req->read_buf + req->read_pos, read); + req->read_size -= read; + req->read_pos += read; + }
- if (req->session->appInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC) - { - if (TryEnterCriticalSection( &req->read_section )) - { - if (get_avail_data(req) || end_of_read_data(req)) - { - res = HTTPREQ_Read(req, buf, size, &read, BLOCKING_DISALLOW); - LeaveCriticalSection( &req->read_section ); - goto done; + if(read < size && (!read || !(flags & IRF_NO_WAIT)) && !end_of_read_data(req)) { + LeaveCriticalSection(&req->read_section); + INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0); + EnterCriticalSection( &req->read_section ); + notify_received = TRUE; + + while(read < size) { + res = HTTPREQ_Read(req, (char*)buf+read, size-read, &cread, + allow_blocking ? BLOCKING_ALLOW : BLOCKING_DISALLOW); + read += cread; + if (res != ERROR_SUCCESS || !cread) + break; } - LeaveCriticalSection( &req->read_section ); }
- if(flags & IRF_NO_WAIT) - return async_read(req, NULL, 0, 0, 0); - return async_read(req, buf, size, 0, ret_read); - } - - read = 0; - - EnterCriticalSection( &req->read_section ); - if(hdr->dwError == ERROR_SUCCESS) - hdr->dwError = INTERNET_HANDLE_IN_USE; - else if(hdr->dwError == INTERNET_HANDLE_IN_USE) - hdr->dwError = ERROR_INTERNET_INTERNAL_ERROR; - - while(1) { - res = HTTPREQ_Read(req, (char*)buf+read, size-read, &cread, BLOCKING_ALLOW); - if(res != ERROR_SUCCESS) - break; - - read += cread; - if(read == size || end_of_read_data(req)) - break; + if(hdr->dwError == INTERNET_HANDLE_IN_USE) + hdr->dwError = ERROR_SUCCESS; + else + error = hdr->dwError;
LeaveCriticalSection( &req->read_section ); - - INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED, - &cread, sizeof(cread)); - INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, - INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0); - - EnterCriticalSection( &req->read_section ); + }else { + res = WSAEWOULDBLOCK; }
- if(hdr->dwError == INTERNET_HANDLE_IN_USE) - hdr->dwError = ERROR_SUCCESS; - else - error = hdr->dwError; - - LeaveCriticalSection( &req->read_section ); + if(res == WSAEWOULDBLOCK) { + if(!(flags & IRF_NO_WAIT)) + return async_read(req, buf, size, read, ret_read); + if(!read) + return async_read(req, NULL, 0, 0, NULL); + res = ERROR_SUCCESS; + }
-done: *ret_read = read; - if (res == ERROR_SUCCESS) { + if (res != ERROR_SUCCESS) + return res; + + if(notify_received) INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED, &read, sizeof(read)); - } - - return res==ERROR_SUCCESS ? error : res; + return error; }
static DWORD HTTPREQ_WriteFile(object_header_t *hdr, const void *buffer, DWORD size, DWORD *written) diff --git a/dlls/wininet/tests/http.c b/dlls/wininet/tests/http.c index 6df30fa..48adee6 100644 --- a/dlls/wininet/tests/http.c +++ b/dlls/wininet/tests/http.c @@ -1111,16 +1111,9 @@ static void InternetReadFileExA_test(int flags) inetbuffers.lpvBuffer = NULL; inetbuffers.dwOffsetHigh = 1234; inetbuffers.dwOffsetLow = 5678; - SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE); - SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED); rc = InternetReadFileExA(hor, &inetbuffers, 0, 0xdeadcafe); ok(rc, "InternetReadFileEx failed with error %u\n", GetLastError()); trace("read %i bytes\n", inetbuffers.dwBufferLength); - todo_wine - { - CHECK_NOT_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE); - CHECK_NOT_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED); - }
rc = InternetReadFileExA(NULL, &inetbuffers, 0, 0xdeadcafe); ok(!rc && (GetLastError() == ERROR_INVALID_HANDLE), @@ -1167,10 +1160,8 @@ static void InternetReadFileExA_test(int flags) CHECK_NOT_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE); if (inetbuffers.dwBufferLength) { - todo_wine { CHECK_NOT_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE); CHECK_NOT_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED); - } } else { @@ -4463,7 +4454,6 @@ static void test_async_read(int port) if (!ib.dwBufferLength) break; }
- todo_wine ok( pending_reads == 1, "expected 1 pending read, got %u\n", pending_reads ); ok( !strcmp(buffer, page1), "unexpected buffer content\n" ); close_async_handle( ses, hCompleteEvent, 2 );