wininet: Change the HTTP code to not assume that the connection will be closed at the end of every request.

This commit is contained in:
Rob Shearman 2007-01-04 18:23:17 +00:00 committed by Alexandre Julliard
parent f0163ae7d6
commit 272954bd81
3 changed files with 81 additions and 5 deletions

View File

@ -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','s','e','r','-','A','g','e','n','t',0}
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(HINTERNET hHttpRequest,
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 hRequest,
&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 hRequest,
/* 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(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders,
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(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders,
&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(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders,
(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(LPWININETHTTPREQW lpwhr)
goto lend;
}
if (NETCON_connected(&lpwhr->netConnection))
{
bSuccess = TRUE;
goto lend;
}
lpwhs = lpwhr->lpHttpSession;
hIC = lpwhs->lpAppInfo;
@ -2941,6 +2975,31 @@ static VOID HTTP_CloseConnection(LPWININETHTTPREQW lpwhr)
}
/***********************************************************************
* 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)
*

View File

@ -1684,7 +1684,7 @@ BOOL WINAPI InternetWriteFile(HINTERNET hFile, LPCVOID lpBuffer ,
}
static BOOL INTERNET_ReadFile(LPWININETHANDLEHEADER lpwh, LPVOID lpBuffer,
BOOL INTERNET_ReadFile(LPWININETHANDLEHEADER lpwh, LPVOID lpBuffer,
DWORD dwNumOfBytesToRead, LPDWORD pdwNumOfBytesRead,
BOOL bWait, BOOL bSendCompletionStatus)
{
@ -1698,17 +1698,30 @@ static BOOL INTERNET_ReadFile(LPWININETHANDLEHEADER lpwh, LPVOID lpBuffer,
{
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;
if (!bytes_read)
retval = HTTP_FinishedReading(lpwhr);
else
retval = TRUE;
}
break;

View File

@ -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_HttpOpenRequestW(LPWININETHTTPSESSIONW lpwhs,
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,