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