[PATCH 6/7] wininet: Change the HTTP code to not assume that the connection will be closed at the end of every request.

Robert Shearman rob at codeweavers.com
Thu Jan 4 12:23:17 CST 2007


---
  dlls/wininet/http.c     |   59 
+++++++++++++++++++++++++++++++++++++++++++++++
  dlls/wininet/internet.c |   23 ++++++++++++++----
  dlls/wininet/internet.h |    4 +++
  3 files changed, 81 insertions(+), 5 deletions(-)
-------------- next part --------------
diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c
index 7fa0566..b98a3df 100644
--- a/dlls/wininet/http.c
+++ b/dlls/wininet/http.c
@@ -6,6 +6,7 @@
  * Copyright 2002 TransGaming Technologies Inc.
  * Copyright 2004 Mike McCormack for CodeWeavers
  * Copyright 2005 Aric Stewart for CodeWeavers
+ * Copyright 2006 Robert Shearman for CodeWeavers
  *
  * Ulrich Czekalla
  * David Hammerton
@@ -69,6 +70,7 @@ static const WCHAR g_szUserAgent[] = {'U
 static const WCHAR szHost[] = { 'H','o','s','t',0 };
 static const WCHAR szProxy_Authorization[] = { 'P','r','o','x','y','-','A','u','t','h','o','r','i','z','a','t','i','o','n',0 };
 static const WCHAR szStatus[] = { 'S','t','a','t','u','s',0 };
+static const WCHAR szKeepAlive[] = {'K','e','e','p','-','A','l','i','v','e',0};
 
 #define MAXHOSTNAME 100
 #define MAX_FIELD_VALUE_LEN 256
@@ -525,6 +527,20 @@ BOOL WINAPI HttpAddRequestHeadersA(HINTE
     return r;
 }
 
+/* read any content returned by the server so that the connection can be
+ * resued */
+static void HTTP_DrainContent(LPWININETHTTPREQW lpwhr)
+{
+    DWORD bytes_read;
+    do
+    {
+        char buffer[2048];
+        if (!INTERNET_ReadFile(&lpwhr->hdr, buffer, sizeof(buffer), &bytes_read,
+                               TRUE, FALSE))
+            return;
+    } while (bytes_read);
+}
+
 /***********************************************************************
  *           HttpEndRequestA (WININET.@)
  *
@@ -639,6 +655,9 @@ BOOL WINAPI HttpEndRequestW(HINTERNET hR
                              &lpwhr->dwContentLength,&dwBufferSize,NULL))
         lpwhr->dwContentLength = -1;
 
+    if (lpwhr->dwContentLength == 0)
+        HTTP_FinishedReading(lpwhr);
+
     if(!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT))
     {
         DWORD dwCode,dwCodeLength=sizeof(DWORD);
@@ -653,6 +672,7 @@ BOOL WINAPI HttpEndRequestW(HINTERNET hR
                 /* redirects are always GETs */
                 HeapFree(GetProcessHeap(),0,lpwhr->lpszVerb);
 	            lpwhr->lpszVerb = WININET_strdupW(szGET);
+                HTTP_DrainContent(lpwhr);
                 rc = HTTP_HandleRedirect(lpwhr, szNewLocation);
                 if (rc)
                     rc = HTTP_HttpSendRequestW(lpwhr, NULL, 0, NULL, 0, 0, TRUE);
@@ -2260,6 +2280,10 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWINI
         char *ascii_req;
 
         loop_next = FALSE;
+
+        /* like native, just in case the caller forgot to call InternetReadFile
+         * for all the data */
+        HTTP_DrainContent(lpwhr);
         lpwhr->dwContentRead = 0;
 
         if (TRACE_ON(wininet))
@@ -2340,6 +2364,9 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWINI
                                      &lpwhr->dwContentLength,&dwBufferSize,NULL))
                 lpwhr->dwContentLength = -1;
 
+            if (lpwhr->dwContentLength == 0)
+                HTTP_FinishedReading(lpwhr);
+
             if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT) && bSuccess)
             {
                 DWORD dwCode,dwCodeLength=sizeof(DWORD);
@@ -2349,6 +2376,7 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWINI
                     (dwCode==HTTP_STATUS_REDIRECT || dwCode==HTTP_STATUS_MOVED) &&
                     HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_LOCATION,szNewLocation,&dwBufferSize,NULL))
                 {
+                    HTTP_DrainContent(lpwhr);
                     INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
                                           INTERNET_STATUS_REDIRECT, szNewLocation,
                                           dwBufferSize);
@@ -2505,6 +2533,12 @@ static BOOL HTTP_OpenConnection(LPWININE
         goto lend;
     }
 
+    if (NETCON_connected(&lpwhr->netConnection))
+    {
+        bSuccess = TRUE;
+        goto lend;
+    }
+
     lpwhs = lpwhr->lpHttpSession;
 
     hIC = lpwhs->lpAppInfo;
@@ -2942,6 +2976,31 @@ static VOID HTTP_CloseConnection(LPWININ
 
 
 /***********************************************************************
+ *           HTTP_FinishedReading (internal)
+ *
+ * Called when all content from server has been read by client.
+ *
+ */
+BOOL HTTP_FinishedReading(LPWININETHTTPREQW lpwhr)
+{
+    WCHAR szConnectionResponse[20];
+    DWORD dwBufferSize = sizeof(szConnectionResponse)/sizeof(szConnectionResponse[0]);
+
+    TRACE("\n");
+
+    if (!HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_CONNECTION, szConnectionResponse,
+                             &dwBufferSize, NULL) ||
+        strcmpiW(szConnectionResponse, szKeepAlive))
+    {
+        HTTP_CloseConnection(lpwhr);
+    }
+
+    /* FIXME: store data in the URL cache here */
+
+    return TRUE;
+}
+
+/***********************************************************************
  *           HTTP_CloseHTTPRequestHandle (internal)
  *
  * Deallocate request handle
diff --git a/dlls/wininet/internet.c b/dlls/wininet/internet.c
index b41c714..aadac29 100644
--- a/dlls/wininet/internet.c
+++ b/dlls/wininet/internet.c
@@ -1710,9 +1710,9 @@ BOOL WINAPI InternetWriteFile(HINTERNET 
 }
 
 
-static BOOL INTERNET_ReadFile(LPWININETHANDLEHEADER lpwh, LPVOID lpBuffer,
-                              DWORD dwNumOfBytesToRead, LPDWORD pdwNumOfBytesRead,
-                              BOOL bWait, BOOL bSendCompletionStatus)
+BOOL INTERNET_ReadFile(LPWININETHANDLEHEADER lpwh, LPVOID lpBuffer,
+                       DWORD dwNumOfBytesToRead, LPDWORD pdwNumOfBytesRead,
+                       BOOL bWait, BOOL bSendCompletionStatus)
 {
     BOOL retval = FALSE;
     int nSocket = -1;
@@ -1724,18 +1724,31 @@ static BOOL INTERNET_ReadFile(LPWININETH
     {
         case WH_HHTTPREQ:
             lpwhr = (LPWININETHTTPREQW)lpwh;
+
             if (!NETCON_recv(&lpwhr->netConnection, lpBuffer,
                              min(dwNumOfBytesToRead, lpwhr->dwContentLength - lpwhr->dwContentRead),
                              bWait ? MSG_WAITALL : 0, &bytes_read))
             {
+
+                if (((lpwhr->dwContentLength != -1) &&
+                     (lpwhr->dwContentRead != lpwhr->dwContentLength)))
+                    ERR("not all data received %d/%d\n", lpwhr->dwContentRead,
+                        lpwhr->dwContentLength);
+
+                /* always returns TRUE, even if the network layer returns an
+                 * error */
                 *pdwNumOfBytesRead = 0;
-                retval = TRUE; /* Under windows, it seems to return 0 even if nothing was read... */
+                HTTP_FinishedReading(lpwhr);
+                retval = TRUE;
             }
             else
             {
                 lpwhr->dwContentRead += bytes_read;
                 *pdwNumOfBytesRead = bytes_read;
-                retval = TRUE;
+                if (!bytes_read)
+                    retval = HTTP_FinishedReading(lpwhr);
+                else
+                    retval = TRUE;
             }
             break;
 
diff --git a/dlls/wininet/internet.h b/dlls/wininet/internet.h
index d409ebf..06de851 100644
--- a/dlls/wininet/internet.h
+++ b/dlls/wininet/internet.h
@@ -407,6 +407,9 @@ DWORD INTERNET_GetLastError(void);
 BOOL INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest);
 LPSTR INTERNET_GetResponseBuffer(void);
 LPSTR INTERNET_GetNextLine(INT nSocket, LPDWORD dwLen);
+BOOL INTERNET_ReadFile(LPWININETHANDLEHEADER lpwh, LPVOID lpBuffer,
+                       DWORD dwNumOfBytesToRead, LPDWORD pdwNumOfBytesRead,
+                       BOOL bWait, BOOL bSendCompletionStatus);
 
 BOOLAPI FTP_FtpPutFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszLocalFile,
     LPCWSTR lpszNewRemoteFile, DWORD dwFlags, DWORD dwContext);
@@ -434,6 +437,7 @@ INTERNETAPI HINTERNET WINAPI HTTP_HttpOp
 	LPCWSTR lpszVerb, LPCWSTR lpszObjectName, LPCWSTR lpszVersion,
 	LPCWSTR lpszReferrer , LPCWSTR *lpszAcceptTypes,
 	DWORD dwFlags, DWORD dwContext);
+BOOL HTTP_FinishedReading(LPWININETHTTPREQW lpwhr);
 
 VOID SendAsyncCallback(LPWININETHANDLEHEADER hdr, DWORD dwContext,
                        DWORD dwInternetStatus, LPVOID lpvStatusInfo,


More information about the wine-patches mailing list