Module: wine Branch: master Commit: 272954bd815338292a3f2c8dc916437838fa3afd URL: http://source.winehq.org/git/wine.git/?a=commit;h=272954bd815338292a3f2c8dc9...
Author: Rob Shearman rob@codeweavers.com Date: Thu Jan 4 18:23:17 2007 +0000
wininet: Change the HTTP code to not assume that the connection will be closed at the end of every request.
---
dlls/wininet/http.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++ dlls/wininet/internet.c | 23 ++++++++++++++---- dlls/wininet/internet.h | 4 +++ 3 files changed, 81 insertions(+), 5 deletions(-)
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 a7568d4..e064ac1 100644 --- a/dlls/wininet/internet.c +++ b/dlls/wininet/internet.c @@ -1684,9 +1684,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; @@ -1698,18 +1698,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 4af22ea..438654b 100644 --- a/dlls/wininet/internet.h +++ b/dlls/wininet/internet.h @@ -404,6 +404,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); @@ -431,6 +434,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,