Jacek Caban : wininet: Rewrite InternetReadFileEx for http protocol to make use of non-blocking reads.
Alexandre Julliard
julliard at winehq.org
Fri Mar 10 16:51:43 CST 2017
Module: wine
Branch: master
Commit: 08808747b2e2aa590a5c8dc0d85c2882b098c460
URL: http://source.winehq.org/git/wine.git/?a=commit;h=08808747b2e2aa590a5c8dc0d85c2882b098c460
Author: Jacek Caban <jacek at 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 at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at 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 );
More information about the wine-cvs
mailing list