mirror of
https://github.com/reactos/reactos.git
synced 2025-05-10 20:27:45 +00:00
[WINHTTP] Sync with Wine Staging 2.16. CORE-13762
d0813b7 winhttp: Avoid returning while holding a lock (Coverity). 5a61913 winhttp: Rename host_t to hostdata_t. 2a99f0e winhttp: Periodically free outdated connections. 5226865 winhttp: Cache and reuse persistent HTTP connections. e0e8a3f winhttp: Introduce global connected hosts store and keep reference to host in netconn_t. d1d65c9 winhttp: Merge netconn_create and netconn_connect implementations. 3e60241 winhttp: Store socked address in netconn_t. e129023 winhttp: Pass socket address as sockaddr_storage to netconn_connect. c2f464d winhttp: Get rid of no longer needed netconn_init. 8c9df5b winhttp: Use notification flags to explicitly mark notifications that should signal an event. c502629 winhttp: Allocate netconn_t separately from request_t. c06104c winhttp: Store security_flags in request_t instead of netconn_t. f2bb206 winhttp: Reset content length when a redirect creates a new connection. 0923897 winhttp: Only read as much data as advertized when draining content. svn path=/trunk/; revision=75944
This commit is contained in:
parent
9b95d548ca
commit
9048599788
8 changed files with 414 additions and 189 deletions
|
@ -1,4 +1,7 @@
|
||||||
|
|
||||||
|
remove_definitions(-D_WIN32_WINNT=0x502)
|
||||||
|
add_definitions(-D_WIN32_WINNT=0x600)
|
||||||
|
|
||||||
add_definitions(
|
add_definitions(
|
||||||
-D__WINESRC__
|
-D__WINESRC__
|
||||||
-D_WINE)
|
-D_WINE)
|
||||||
|
@ -27,7 +30,7 @@ add_library(winhttp SHARED
|
||||||
set_module_type(winhttp win32dll)
|
set_module_type(winhttp win32dll)
|
||||||
target_link_libraries(winhttp uuid wine)
|
target_link_libraries(winhttp uuid wine)
|
||||||
add_delay_importlibs(winhttp oleaut32 ole32 crypt32 secur32)
|
add_delay_importlibs(winhttp oleaut32 ole32 crypt32 secur32)
|
||||||
add_importlibs(winhttp user32 advapi32 ws2_32 jsproxy msvcrt kernel32 ntdll)
|
add_importlibs(winhttp user32 advapi32 ws2_32 jsproxy kernel32_vista msvcrt kernel32 ntdll)
|
||||||
add_dependencies(winhttp stdole2)
|
add_dependencies(winhttp stdole2)
|
||||||
add_pch(winhttp winhttp_private.h SOURCE)
|
add_pch(winhttp winhttp_private.h SOURCE)
|
||||||
add_cd_file(TARGET winhttp DESTINATION reactos/system32 FOR all)
|
add_cd_file(TARGET winhttp DESTINATION reactos/system32 FOR all)
|
||||||
|
|
|
@ -51,16 +51,18 @@ static const char *inet_ntop6(const u_char *src, char *dst, size_t size);
|
||||||
* author:
|
* author:
|
||||||
* Paul Vixie, 1996.
|
* Paul Vixie, 1996.
|
||||||
*/
|
*/
|
||||||
const char *
|
|
||||||
inet_ntop(int af, const void *src, char *dst, size_t size)
|
PCSTR
|
||||||
|
WSAAPI
|
||||||
|
inet_ntop(INT Family, PVOID pAddr, PSTR pStringBuf, size_t StringBufSize)
|
||||||
{
|
{
|
||||||
|
|
||||||
switch (af) {
|
switch (Family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
return (inet_ntop4(src, dst, size));
|
return (inet_ntop4(pAddr, pStringBuf, StringBufSize));
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
return (inet_ntop6(src, dst, size));
|
return (inet_ntop6(pAddr, pStringBuf, StringBufSize));
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
WSASetLastError(WSAEAFNOSUPPORT);
|
WSASetLastError(WSAEAFNOSUPPORT);
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include <rpcproxy.h>
|
#include <rpcproxy.h>
|
||||||
#include <httprequest.h>
|
#include <httprequest.h>
|
||||||
|
|
||||||
static HINSTANCE instance;
|
HINSTANCE winhttp_instance;
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
* DllMain (winhttp.@)
|
* DllMain (winhttp.@)
|
||||||
|
@ -31,7 +31,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
|
||||||
switch(fdwReason)
|
switch(fdwReason)
|
||||||
{
|
{
|
||||||
case DLL_PROCESS_ATTACH:
|
case DLL_PROCESS_ATTACH:
|
||||||
instance = hInstDLL;
|
winhttp_instance = hInstDLL;
|
||||||
DisableThreadLibraryCalls(hInstDLL);
|
DisableThreadLibraryCalls(hInstDLL);
|
||||||
break;
|
break;
|
||||||
case DLL_PROCESS_DETACH:
|
case DLL_PROCESS_DETACH:
|
||||||
|
@ -158,7 +158,7 @@ HRESULT WINAPI DllCanUnloadNow(void)
|
||||||
*/
|
*/
|
||||||
HRESULT WINAPI DllRegisterServer(void)
|
HRESULT WINAPI DllRegisterServer(void)
|
||||||
{
|
{
|
||||||
return __wine_register_resources( instance );
|
return __wine_register_resources( winhttp_instance );
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -166,5 +166,5 @@ HRESULT WINAPI DllRegisterServer(void)
|
||||||
*/
|
*/
|
||||||
HRESULT WINAPI DllUnregisterServer(void)
|
HRESULT WINAPI DllUnregisterServer(void)
|
||||||
{
|
{
|
||||||
return __wine_unregister_resources( instance );
|
return __wine_unregister_resources( winhttp_instance );
|
||||||
}
|
}
|
||||||
|
|
|
@ -298,13 +298,6 @@ BOOL netconn_init_winsock()
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
BOOL netconn_init( netconn_t *conn )
|
|
||||||
{
|
|
||||||
memset(conn, 0, sizeof(*conn));
|
|
||||||
conn->socket = -1;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void netconn_unload( void )
|
void netconn_unload( void )
|
||||||
{
|
{
|
||||||
if(cred_handle_initialized)
|
if(cred_handle_initialized)
|
||||||
|
@ -319,56 +312,38 @@ void netconn_unload( void )
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL netconn_connected( netconn_t *conn )
|
netconn_t *netconn_create( hostdata_t *host, const struct sockaddr_storage *sockaddr, int timeout )
|
||||||
{
|
|
||||||
return (conn->socket != -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL netconn_create( netconn_t *conn, int domain, int type, int protocol )
|
|
||||||
{
|
|
||||||
if ((conn->socket = socket( domain, type, protocol )) == -1)
|
|
||||||
{
|
|
||||||
WARN("unable to create socket (%s)\n", strerror(errno));
|
|
||||||
set_last_error( sock_get_error( errno ) );
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL netconn_close( netconn_t *conn )
|
|
||||||
{
|
|
||||||
int res;
|
|
||||||
|
|
||||||
if (conn->secure)
|
|
||||||
{
|
|
||||||
heap_free( conn->peek_msg_mem );
|
|
||||||
conn->peek_msg_mem = NULL;
|
|
||||||
conn->peek_msg = NULL;
|
|
||||||
conn->peek_len = 0;
|
|
||||||
heap_free(conn->ssl_buf);
|
|
||||||
conn->ssl_buf = NULL;
|
|
||||||
heap_free(conn->extra_buf);
|
|
||||||
conn->extra_buf = NULL;
|
|
||||||
conn->extra_len = 0;
|
|
||||||
DeleteSecurityContext(&conn->ssl_ctx);
|
|
||||||
conn->secure = FALSE;
|
|
||||||
}
|
|
||||||
res = closesocket( conn->socket );
|
|
||||||
conn->socket = -1;
|
|
||||||
if (res == -1)
|
|
||||||
{
|
|
||||||
set_last_error( sock_get_error( errno ) );
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL netconn_connect( netconn_t *conn, const struct sockaddr *sockaddr, unsigned int addr_len, int timeout )
|
|
||||||
{
|
{
|
||||||
|
netconn_t *conn;
|
||||||
|
unsigned int addr_len;
|
||||||
BOOL ret = FALSE;
|
BOOL ret = FALSE;
|
||||||
int res;
|
int res;
|
||||||
ULONG state;
|
ULONG state;
|
||||||
|
|
||||||
|
conn = heap_alloc_zero(sizeof(*conn));
|
||||||
|
if (!conn) return NULL;
|
||||||
|
conn->host = host;
|
||||||
|
conn->sockaddr = *sockaddr;
|
||||||
|
if ((conn->socket = socket( sockaddr->ss_family, SOCK_STREAM, 0 )) == -1)
|
||||||
|
{
|
||||||
|
WARN("unable to create socket (%s)\n", strerror(errno));
|
||||||
|
set_last_error( sock_get_error( errno ) );
|
||||||
|
heap_free(conn);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (conn->sockaddr.ss_family)
|
||||||
|
{
|
||||||
|
case AF_INET:
|
||||||
|
addr_len = sizeof(struct sockaddr_in);
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
addr_len = sizeof(struct sockaddr_in6);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
if (timeout > 0)
|
if (timeout > 0)
|
||||||
{
|
{
|
||||||
state = 1;
|
state = 1;
|
||||||
|
@ -378,7 +353,7 @@ BOOL netconn_connect( netconn_t *conn, const struct sockaddr *sockaddr, unsigned
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
res = 0;
|
res = 0;
|
||||||
if (connect( conn->socket, sockaddr, addr_len ) < 0)
|
if (connect( conn->socket, (const struct sockaddr *)&conn->sockaddr, addr_len ) < 0)
|
||||||
{
|
{
|
||||||
res = sock_get_error( errno );
|
res = sock_get_error( errno );
|
||||||
if (res == WSAEWOULDBLOCK || res == WSAEINPROGRESS)
|
if (res == WSAEWOULDBLOCK || res == WSAEINPROGRESS)
|
||||||
|
@ -436,11 +411,35 @@ BOOL netconn_connect( netconn_t *conn, const struct sockaddr *sockaddr, unsigned
|
||||||
{
|
{
|
||||||
WARN("unable to connect to host (%d)\n", res);
|
WARN("unable to connect to host (%d)\n", res);
|
||||||
set_last_error( res );
|
set_last_error( res );
|
||||||
|
netconn_close( conn );
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
return ret;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname )
|
BOOL netconn_close( netconn_t *conn )
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (conn->secure)
|
||||||
|
{
|
||||||
|
heap_free( conn->peek_msg_mem );
|
||||||
|
heap_free(conn->ssl_buf);
|
||||||
|
heap_free(conn->extra_buf);
|
||||||
|
DeleteSecurityContext(&conn->ssl_ctx);
|
||||||
|
}
|
||||||
|
res = closesocket( conn->socket );
|
||||||
|
release_host( conn->host );
|
||||||
|
heap_free(conn);
|
||||||
|
if (res == -1)
|
||||||
|
{
|
||||||
|
set_last_error( sock_get_error( errno ) );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname, DWORD security_flags )
|
||||||
{
|
{
|
||||||
SecBuffer out_buf = {0, SECBUFFER_TOKEN, NULL}, in_bufs[2] = {{0, SECBUFFER_TOKEN}, {0, SECBUFFER_EMPTY}};
|
SecBuffer out_buf = {0, SECBUFFER_TOKEN, NULL}, in_bufs[2] = {{0, SECBUFFER_TOKEN}, {0, SECBUFFER_EMPTY}};
|
||||||
SecBufferDesc out_desc = {SECBUFFER_VERSION, 1, &out_buf}, in_desc = {SECBUFFER_VERSION, 2, in_bufs};
|
SecBufferDesc out_desc = {SECBUFFER_VERSION, 1, &out_buf}, in_desc = {SECBUFFER_VERSION, 2, in_bufs};
|
||||||
|
@ -540,7 +539,7 @@ BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname )
|
||||||
|
|
||||||
status = QueryContextAttributesW(&ctx, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&cert);
|
status = QueryContextAttributesW(&ctx, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&cert);
|
||||||
if(status == SEC_E_OK) {
|
if(status == SEC_E_OK) {
|
||||||
res = netconn_verify_cert(cert, hostname, conn->security_flags);
|
res = netconn_verify_cert(cert, hostname, security_flags);
|
||||||
CertFreeCertificateContext(cert);
|
CertFreeCertificateContext(cert);
|
||||||
if(res != ERROR_SUCCESS) {
|
if(res != ERROR_SUCCESS) {
|
||||||
WARN("cert verify failed: %u\n", res);
|
WARN("cert verify failed: %u\n", res);
|
||||||
|
@ -605,7 +604,6 @@ static BOOL send_ssl_chunk(netconn_t *conn, const void *msg, size_t size)
|
||||||
|
|
||||||
BOOL netconn_send( netconn_t *conn, const void *msg, size_t len, int *sent )
|
BOOL netconn_send( netconn_t *conn, const void *msg, size_t len, int *sent )
|
||||||
{
|
{
|
||||||
if (!netconn_connected( conn )) return FALSE;
|
|
||||||
if (conn->secure)
|
if (conn->secure)
|
||||||
{
|
{
|
||||||
const BYTE *ptr = msg;
|
const BYTE *ptr = msg;
|
||||||
|
@ -729,7 +727,6 @@ static BOOL read_ssl_chunk(netconn_t *conn, void *buf, SIZE_T buf_size, SIZE_T *
|
||||||
BOOL netconn_recv( netconn_t *conn, void *buf, size_t len, int flags, int *recvd )
|
BOOL netconn_recv( netconn_t *conn, void *buf, size_t len, int flags, int *recvd )
|
||||||
{
|
{
|
||||||
*recvd = 0;
|
*recvd = 0;
|
||||||
if (!netconn_connected( conn )) return FALSE;
|
|
||||||
if (!len) return TRUE;
|
if (!len) return TRUE;
|
||||||
|
|
||||||
if (conn->secure)
|
if (conn->secure)
|
||||||
|
@ -786,13 +783,7 @@ BOOL netconn_recv( netconn_t *conn, void *buf, size_t len, int flags, int *recvd
|
||||||
|
|
||||||
ULONG netconn_query_data_available( netconn_t *conn )
|
ULONG netconn_query_data_available( netconn_t *conn )
|
||||||
{
|
{
|
||||||
if(!netconn_connected(conn))
|
return conn->secure ? conn->peek_len : 0;
|
||||||
return 0;
|
|
||||||
|
|
||||||
if(conn->secure)
|
|
||||||
return conn->peek_len;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD netconn_set_timeout( netconn_t *netconn, BOOL send, int value )
|
DWORD netconn_set_timeout( netconn_t *netconn, BOOL send, int value )
|
||||||
|
@ -811,7 +802,37 @@ DWORD netconn_set_timeout( netconn_t *netconn, BOOL send, int value )
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWORD resolve_hostname( const WCHAR *hostnameW, INTERNET_PORT port, struct sockaddr *sa, socklen_t *sa_len )
|
BOOL netconn_is_alive( netconn_t *netconn )
|
||||||
|
{
|
||||||
|
#ifdef MSG_DONTWAIT
|
||||||
|
ssize_t len;
|
||||||
|
BYTE b;
|
||||||
|
|
||||||
|
len = recv( netconn->socket, &b, 1, MSG_PEEK | MSG_DONTWAIT );
|
||||||
|
return len == 1 || (len == -1 && errno == EWOULDBLOCK);
|
||||||
|
#elif defined(__MINGW32__) || defined(_MSC_VER)
|
||||||
|
ULONG mode;
|
||||||
|
int len;
|
||||||
|
char b;
|
||||||
|
|
||||||
|
mode = 1;
|
||||||
|
if(!ioctlsocket(netconn->socket, FIONBIO, &mode))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
len = recv(netconn->socket, &b, 1, MSG_PEEK);
|
||||||
|
|
||||||
|
mode = 0;
|
||||||
|
if(!ioctlsocket(netconn->socket, FIONBIO, &mode))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return len == 1 || (len == -1 && WSAGetLastError() == WSAEWOULDBLOCK);
|
||||||
|
#else
|
||||||
|
FIXME("not supported on this platform\n");
|
||||||
|
return TRUE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD resolve_hostname( const WCHAR *hostnameW, INTERNET_PORT port, struct sockaddr_storage *sa )
|
||||||
{
|
{
|
||||||
char *hostname;
|
char *hostname;
|
||||||
#ifdef HAVE_GETADDRINFO
|
#ifdef HAVE_GETADDRINFO
|
||||||
|
@ -845,13 +866,6 @@ static DWORD resolve_hostname( const WCHAR *hostnameW, INTERNET_PORT port, struc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
heap_free( hostname );
|
heap_free( hostname );
|
||||||
if (*sa_len < res->ai_addrlen)
|
|
||||||
{
|
|
||||||
WARN("address too small\n");
|
|
||||||
freeaddrinfo( res );
|
|
||||||
return ERROR_WINHTTP_NAME_NOT_RESOLVED;
|
|
||||||
}
|
|
||||||
*sa_len = res->ai_addrlen;
|
|
||||||
memcpy( sa, res->ai_addr, res->ai_addrlen );
|
memcpy( sa, res->ai_addr, res->ai_addrlen );
|
||||||
/* Copy port */
|
/* Copy port */
|
||||||
switch (res->ai_family)
|
switch (res->ai_family)
|
||||||
|
@ -877,13 +891,6 @@ static DWORD resolve_hostname( const WCHAR *hostnameW, INTERNET_PORT port, struc
|
||||||
LeaveCriticalSection( &cs_gethostbyname );
|
LeaveCriticalSection( &cs_gethostbyname );
|
||||||
return ERROR_WINHTTP_NAME_NOT_RESOLVED;
|
return ERROR_WINHTTP_NAME_NOT_RESOLVED;
|
||||||
}
|
}
|
||||||
if (*sa_len < sizeof(struct sockaddr_in))
|
|
||||||
{
|
|
||||||
WARN("address too small\n");
|
|
||||||
LeaveCriticalSection( &cs_gethostbyname );
|
|
||||||
return ERROR_WINHTTP_NAME_NOT_RESOLVED;
|
|
||||||
}
|
|
||||||
*sa_len = sizeof(struct sockaddr_in);
|
|
||||||
memset( sa, 0, sizeof(struct sockaddr_in) );
|
memset( sa, 0, sizeof(struct sockaddr_in) );
|
||||||
memcpy( &sin->sin_addr, he->h_addr, he->h_length );
|
memcpy( &sin->sin_addr, he->h_addr, he->h_length );
|
||||||
sin->sin_family = he->h_addrtype;
|
sin->sin_family = he->h_addrtype;
|
||||||
|
@ -896,19 +903,18 @@ static DWORD resolve_hostname( const WCHAR *hostnameW, INTERNET_PORT port, struc
|
||||||
|
|
||||||
struct resolve_args
|
struct resolve_args
|
||||||
{
|
{
|
||||||
const WCHAR *hostname;
|
const WCHAR *hostname;
|
||||||
INTERNET_PORT port;
|
INTERNET_PORT port;
|
||||||
struct sockaddr *sa;
|
struct sockaddr_storage *sa;
|
||||||
socklen_t *sa_len;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static DWORD CALLBACK resolve_proc( LPVOID arg )
|
static DWORD CALLBACK resolve_proc( LPVOID arg )
|
||||||
{
|
{
|
||||||
struct resolve_args *ra = arg;
|
struct resolve_args *ra = arg;
|
||||||
return resolve_hostname( ra->hostname, ra->port, ra->sa, ra->sa_len );
|
return resolve_hostname( ra->hostname, ra->port, ra->sa );
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL netconn_resolve( WCHAR *hostname, INTERNET_PORT port, struct sockaddr *sa, socklen_t *sa_len, int timeout )
|
BOOL netconn_resolve( WCHAR *hostname, INTERNET_PORT port, struct sockaddr_storage *sa, int timeout )
|
||||||
{
|
{
|
||||||
DWORD ret;
|
DWORD ret;
|
||||||
|
|
||||||
|
@ -921,7 +927,6 @@ BOOL netconn_resolve( WCHAR *hostname, INTERNET_PORT port, struct sockaddr *sa,
|
||||||
ra.hostname = hostname;
|
ra.hostname = hostname;
|
||||||
ra.port = port;
|
ra.port = port;
|
||||||
ra.sa = sa;
|
ra.sa = sa;
|
||||||
ra.sa_len = sa_len;
|
|
||||||
|
|
||||||
thread = CreateThread( NULL, 0, resolve_proc, &ra, 0, NULL );
|
thread = CreateThread( NULL, 0, resolve_proc, &ra, 0, NULL );
|
||||||
if (!thread) return FALSE;
|
if (!thread) return FALSE;
|
||||||
|
@ -931,7 +936,7 @@ BOOL netconn_resolve( WCHAR *hostname, INTERNET_PORT port, struct sockaddr *sa,
|
||||||
else ret = ERROR_WINHTTP_TIMEOUT;
|
else ret = ERROR_WINHTTP_TIMEOUT;
|
||||||
CloseHandle( thread );
|
CloseHandle( thread );
|
||||||
}
|
}
|
||||||
else ret = resolve_hostname( hostname, port, sa, sa_len );
|
else ret = resolve_hostname( hostname, port, sa );
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
|
|
||||||
#include "inet_ntop.c"
|
#include "inet_ntop.c"
|
||||||
|
|
||||||
|
#define DEFAULT_KEEP_ALIVE_TIMEOUT 30000
|
||||||
|
|
||||||
static const WCHAR attr_accept[] = {'A','c','c','e','p','t',0};
|
static const WCHAR attr_accept[] = {'A','c','c','e','p','t',0};
|
||||||
static const WCHAR attr_accept_charset[] = {'A','c','c','e','p','t','-','C','h','a','r','s','e','t', 0};
|
static const WCHAR attr_accept_charset[] = {'A','c','c','e','p','t','-','C','h','a','r','s','e','t', 0};
|
||||||
static const WCHAR attr_accept_encoding[] = {'A','c','c','e','p','t','-','E','n','c','o','d','i','n','g',0};
|
static const WCHAR attr_accept_encoding[] = {'A','c','c','e','p','t','-','E','n','c','o','d','i','n','g',0};
|
||||||
|
@ -540,7 +542,7 @@ static WCHAR *build_request_path( request_t *request )
|
||||||
static const WCHAR http[] = { 'h','t','t','p',0 };
|
static const WCHAR http[] = { 'h','t','t','p',0 };
|
||||||
static const WCHAR https[] = { 'h','t','t','p','s',0 };
|
static const WCHAR https[] = { 'h','t','t','p','s',0 };
|
||||||
static const WCHAR fmt[] = { '%','s',':','/','/','%','s',0 };
|
static const WCHAR fmt[] = { '%','s',':','/','/','%','s',0 };
|
||||||
LPCWSTR scheme = request->netconn.secure ? https : http;
|
LPCWSTR scheme = (request->netconn ? request->netconn->secure : (request->hdr.flags & WINHTTP_FLAG_SECURE)) ? https : http;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
len = strlenW( scheme ) + strlenW( request->connect->hostname );
|
len = strlenW( scheme ) + strlenW( request->connect->hostname );
|
||||||
|
@ -945,7 +947,7 @@ static BOOL secure_proxy_connect( request_t *request )
|
||||||
{
|
{
|
||||||
int len = strlen( req_ascii ), bytes_sent;
|
int len = strlen( req_ascii ), bytes_sent;
|
||||||
|
|
||||||
ret = netconn_send( &request->netconn, req_ascii, len, &bytes_sent );
|
ret = netconn_send( request->netconn, req_ascii, len, &bytes_sent );
|
||||||
heap_free( req_ascii );
|
heap_free( req_ascii );
|
||||||
if (ret)
|
if (ret)
|
||||||
ret = read_reply( request );
|
ret = read_reply( request );
|
||||||
|
@ -959,12 +961,12 @@ static BOOL secure_proxy_connect( request_t *request )
|
||||||
#define INET6_ADDRSTRLEN 46
|
#define INET6_ADDRSTRLEN 46
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static WCHAR *addr_to_str( struct sockaddr *addr )
|
static WCHAR *addr_to_str( struct sockaddr_storage *addr )
|
||||||
{
|
{
|
||||||
char buf[INET6_ADDRSTRLEN];
|
char buf[INET6_ADDRSTRLEN];
|
||||||
void *src;
|
void *src;
|
||||||
|
|
||||||
switch (addr->sa_family)
|
switch (addr->ss_family)
|
||||||
{
|
{
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
src = &((struct sockaddr_in *)addr)->sin_addr;
|
src = &((struct sockaddr_in *)addr)->sin_addr;
|
||||||
|
@ -973,79 +975,258 @@ static WCHAR *addr_to_str( struct sockaddr *addr )
|
||||||
src = &((struct sockaddr_in6 *)addr)->sin6_addr;
|
src = &((struct sockaddr_in6 *)addr)->sin6_addr;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
WARN("unsupported address family %d\n", addr->sa_family);
|
WARN("unsupported address family %d\n", addr->ss_family);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!inet_ntop( addr->sa_family, src, buf, sizeof(buf) )) return NULL;
|
if (!inet_ntop( addr->ss_family, src, buf, sizeof(buf) )) return NULL;
|
||||||
return strdupAW( buf );
|
return strdupAW( buf );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CRITICAL_SECTION connection_pool_cs;
|
||||||
|
static CRITICAL_SECTION_DEBUG connection_pool_debug =
|
||||||
|
{
|
||||||
|
0, 0, &connection_pool_cs,
|
||||||
|
{ &connection_pool_debug.ProcessLocksList, &connection_pool_debug.ProcessLocksList },
|
||||||
|
0, 0, { (DWORD_PTR)(__FILE__ ": connection_pool_cs") }
|
||||||
|
};
|
||||||
|
static CRITICAL_SECTION connection_pool_cs = { &connection_pool_debug, -1, 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
static struct list connection_pool = LIST_INIT( connection_pool );
|
||||||
|
|
||||||
|
void release_host( hostdata_t *host )
|
||||||
|
{
|
||||||
|
LONG ref;
|
||||||
|
|
||||||
|
EnterCriticalSection( &connection_pool_cs );
|
||||||
|
if (!(ref = --host->ref)) list_remove( &host->entry );
|
||||||
|
LeaveCriticalSection( &connection_pool_cs );
|
||||||
|
if (ref) return;
|
||||||
|
|
||||||
|
assert( list_empty( &host->connections ) );
|
||||||
|
heap_free( host->hostname );
|
||||||
|
heap_free( host );
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL connection_collector_running;
|
||||||
|
|
||||||
|
static DWORD WINAPI connection_collector(void *arg)
|
||||||
|
{
|
||||||
|
unsigned int remaining_connections;
|
||||||
|
netconn_t *netconn, *next_netconn;
|
||||||
|
hostdata_t *host, *next_host;
|
||||||
|
ULONGLONG now;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* FIXME: Use more sophisticated method */
|
||||||
|
Sleep(5000);
|
||||||
|
remaining_connections = 0;
|
||||||
|
now = GetTickCount64();
|
||||||
|
|
||||||
|
EnterCriticalSection(&connection_pool_cs);
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY_SAFE(host, next_host, &connection_pool, hostdata_t, entry)
|
||||||
|
{
|
||||||
|
LIST_FOR_EACH_ENTRY_SAFE(netconn, next_netconn, &host->connections, netconn_t, entry)
|
||||||
|
{
|
||||||
|
if (netconn->keep_until < now)
|
||||||
|
{
|
||||||
|
TRACE("freeing %p\n", netconn);
|
||||||
|
list_remove(&netconn->entry);
|
||||||
|
netconn_close(netconn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
remaining_connections++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!remaining_connections) connection_collector_running = FALSE;
|
||||||
|
|
||||||
|
LeaveCriticalSection(&connection_pool_cs);
|
||||||
|
} while(remaining_connections);
|
||||||
|
|
||||||
|
FreeLibraryAndExitThread( winhttp_instance, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cache_connection( netconn_t *netconn )
|
||||||
|
{
|
||||||
|
TRACE( "caching connection %p\n", netconn );
|
||||||
|
|
||||||
|
EnterCriticalSection( &connection_pool_cs );
|
||||||
|
|
||||||
|
netconn->keep_until = GetTickCount64() + DEFAULT_KEEP_ALIVE_TIMEOUT;
|
||||||
|
list_add_head( &netconn->host->connections, &netconn->entry );
|
||||||
|
|
||||||
|
if (!connection_collector_running)
|
||||||
|
{
|
||||||
|
HMODULE module;
|
||||||
|
HANDLE thread;
|
||||||
|
|
||||||
|
GetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (const WCHAR*)winhttp_instance, &module );
|
||||||
|
|
||||||
|
thread = CreateThread(NULL, 0, connection_collector, NULL, 0, NULL);
|
||||||
|
if (thread)
|
||||||
|
{
|
||||||
|
CloseHandle( thread );
|
||||||
|
connection_collector_running = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FreeLibrary( winhttp_instance );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LeaveCriticalSection( &connection_pool_cs );
|
||||||
|
}
|
||||||
|
|
||||||
static BOOL open_connection( request_t *request )
|
static BOOL open_connection( request_t *request )
|
||||||
{
|
{
|
||||||
|
BOOL is_secure = request->hdr.flags & WINHTTP_FLAG_SECURE;
|
||||||
|
hostdata_t *host = NULL, *iter;
|
||||||
|
netconn_t *netconn = NULL;
|
||||||
connect_t *connect;
|
connect_t *connect;
|
||||||
WCHAR *addressW = NULL;
|
WCHAR *addressW = NULL;
|
||||||
INTERNET_PORT port;
|
INTERNET_PORT port;
|
||||||
socklen_t slen;
|
|
||||||
struct sockaddr *saddr;
|
|
||||||
DWORD len;
|
DWORD len;
|
||||||
|
|
||||||
if (netconn_connected( &request->netconn )) goto done;
|
if (request->netconn) goto done;
|
||||||
|
|
||||||
connect = request->connect;
|
connect = request->connect;
|
||||||
port = connect->serverport ? connect->serverport : (request->hdr.flags & WINHTTP_FLAG_SECURE ? 443 : 80);
|
port = connect->serverport ? connect->serverport : (request->hdr.flags & WINHTTP_FLAG_SECURE ? 443 : 80);
|
||||||
saddr = (struct sockaddr *)&connect->sockaddr;
|
|
||||||
slen = sizeof(struct sockaddr);
|
EnterCriticalSection( &connection_pool_cs );
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY( iter, &connection_pool, hostdata_t, entry )
|
||||||
|
{
|
||||||
|
if (iter->port == port && !strcmpW( connect->servername, iter->hostname ) && !is_secure == !iter->secure)
|
||||||
|
{
|
||||||
|
host = iter;
|
||||||
|
host->ref++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!host)
|
||||||
|
{
|
||||||
|
if ((host = heap_alloc( sizeof(*host) )))
|
||||||
|
{
|
||||||
|
host->ref = 1;
|
||||||
|
host->secure = is_secure;
|
||||||
|
host->port = port;
|
||||||
|
list_init( &host->connections );
|
||||||
|
if ((host->hostname = strdupW( connect->servername )))
|
||||||
|
{
|
||||||
|
list_add_head( &connection_pool, &host->entry );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
heap_free( host );
|
||||||
|
host = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LeaveCriticalSection( &connection_pool_cs );
|
||||||
|
|
||||||
|
if (!host) return FALSE;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
EnterCriticalSection( &connection_pool_cs );
|
||||||
|
if (!list_empty( &host->connections ))
|
||||||
|
{
|
||||||
|
netconn = LIST_ENTRY( list_head( &host->connections ), netconn_t, entry );
|
||||||
|
list_remove( &netconn->entry );
|
||||||
|
}
|
||||||
|
LeaveCriticalSection( &connection_pool_cs );
|
||||||
|
if (!netconn) break;
|
||||||
|
|
||||||
|
if (netconn_is_alive( netconn )) break;
|
||||||
|
TRACE("connection %p no longer alive, closing\n", netconn);
|
||||||
|
netconn_close( netconn );
|
||||||
|
netconn = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!connect->resolved && netconn)
|
||||||
|
{
|
||||||
|
connect->sockaddr = netconn->sockaddr;
|
||||||
|
connect->resolved = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
if (!connect->resolved)
|
if (!connect->resolved)
|
||||||
{
|
{
|
||||||
len = strlenW( connect->servername ) + 1;
|
len = strlenW( host->hostname ) + 1;
|
||||||
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, connect->servername, len );
|
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, host->hostname, len );
|
||||||
|
|
||||||
if (!netconn_resolve( connect->servername, port, saddr, &slen, request->resolve_timeout )) return FALSE;
|
if (!netconn_resolve( host->hostname, port, &connect->sockaddr, request->resolve_timeout ))
|
||||||
|
{
|
||||||
|
release_host( host );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
connect->resolved = TRUE;
|
connect->resolved = TRUE;
|
||||||
|
|
||||||
if (!(addressW = addr_to_str( saddr ))) return FALSE;
|
if (!(addressW = addr_to_str( &connect->sockaddr )))
|
||||||
|
{
|
||||||
|
release_host( host );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
len = strlenW( addressW ) + 1;
|
len = strlenW( addressW ) + 1;
|
||||||
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED, addressW, len );
|
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED, addressW, len );
|
||||||
}
|
}
|
||||||
if (!addressW && !(addressW = addr_to_str( saddr ))) return FALSE;
|
|
||||||
TRACE("connecting to %s:%u\n", debugstr_w(addressW), port);
|
|
||||||
|
|
||||||
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER, addressW, 0 );
|
if (!netconn)
|
||||||
|
|
||||||
if (!netconn_create( &request->netconn, saddr->sa_family, SOCK_STREAM, 0 ))
|
|
||||||
{
|
{
|
||||||
heap_free( addressW );
|
if (!addressW && !(addressW = addr_to_str( &connect->sockaddr )))
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
netconn_set_timeout( &request->netconn, TRUE, request->send_timeout );
|
|
||||||
netconn_set_timeout( &request->netconn, FALSE, request->recv_timeout );
|
|
||||||
if (!netconn_connect( &request->netconn, saddr, slen, request->connect_timeout ))
|
|
||||||
{
|
|
||||||
netconn_close( &request->netconn );
|
|
||||||
heap_free( addressW );
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (request->hdr.flags & WINHTTP_FLAG_SECURE)
|
|
||||||
{
|
|
||||||
if (connect->session->proxy_server &&
|
|
||||||
strcmpiW( connect->hostname, connect->servername ))
|
|
||||||
{
|
{
|
||||||
if (!secure_proxy_connect( request ))
|
release_host( host );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("connecting to %s:%u\n", debugstr_w(addressW), port);
|
||||||
|
|
||||||
|
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER, addressW, 0 );
|
||||||
|
|
||||||
|
if (!(netconn = netconn_create( host, &connect->sockaddr, request->connect_timeout )))
|
||||||
|
{
|
||||||
|
heap_free( addressW );
|
||||||
|
release_host( host );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
netconn_set_timeout( netconn, TRUE, request->send_timeout );
|
||||||
|
netconn_set_timeout( netconn, FALSE, request->recv_timeout );
|
||||||
|
if (is_secure)
|
||||||
|
{
|
||||||
|
if (connect->session->proxy_server &&
|
||||||
|
strcmpiW( connect->hostname, connect->servername ))
|
||||||
|
{
|
||||||
|
if (!secure_proxy_connect( request ))
|
||||||
|
{
|
||||||
|
heap_free( addressW );
|
||||||
|
netconn_close( netconn );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!netconn_secure_connect( netconn, connect->hostname, request->security_flags ))
|
||||||
{
|
{
|
||||||
heap_free( addressW );
|
heap_free( addressW );
|
||||||
|
netconn_close( netconn );
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!netconn_secure_connect( &request->netconn, connect->hostname ))
|
|
||||||
{
|
|
||||||
netconn_close( &request->netconn );
|
|
||||||
heap_free( addressW );
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, addressW, strlenW(addressW) + 1 );
|
request->netconn = netconn;
|
||||||
|
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, addressW, strlenW(addressW) + 1 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TRACE("using connection %p\n", netconn);
|
||||||
|
|
||||||
|
netconn_set_timeout( netconn, TRUE, request->send_timeout );
|
||||||
|
netconn_set_timeout( netconn, FALSE, request->recv_timeout );
|
||||||
|
request->netconn = netconn;
|
||||||
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
request->read_pos = request->read_size = 0;
|
request->read_pos = request->read_size = 0;
|
||||||
|
@ -1058,10 +1239,11 @@ done:
|
||||||
|
|
||||||
void close_connection( request_t *request )
|
void close_connection( request_t *request )
|
||||||
{
|
{
|
||||||
if (!netconn_connected( &request->netconn )) return;
|
if (!request->netconn) return;
|
||||||
|
|
||||||
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, 0, 0 );
|
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, 0, 0 );
|
||||||
netconn_close( &request->netconn );
|
netconn_close( request->netconn );
|
||||||
|
request->netconn = NULL;
|
||||||
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, 0, 0 );
|
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, 0, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1127,7 +1309,7 @@ static BOOL read_more_data( request_t *request, int maxlen, BOOL notify )
|
||||||
|
|
||||||
if (notify) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE, NULL, 0 );
|
if (notify) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE, NULL, 0 );
|
||||||
|
|
||||||
ret = netconn_recv( &request->netconn, request->read_buf + request->read_size,
|
ret = netconn_recv( request->netconn, request->read_buf + request->read_size,
|
||||||
maxlen - request->read_size, 0, &len );
|
maxlen - request->read_size, 0, &len );
|
||||||
|
|
||||||
if (notify) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED, &len, sizeof(len) );
|
if (notify) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED, &len, sizeof(len) );
|
||||||
|
@ -1229,6 +1411,8 @@ static void finished_reading( request_t *request )
|
||||||
WCHAR connection[20];
|
WCHAR connection[20];
|
||||||
DWORD size = sizeof(connection);
|
DWORD size = sizeof(connection);
|
||||||
|
|
||||||
|
if (!request->netconn) return;
|
||||||
|
|
||||||
if (request->hdr.disable_flags & WINHTTP_DISABLE_KEEP_ALIVE) close = TRUE;
|
if (request->hdr.disable_flags & WINHTTP_DISABLE_KEEP_ALIVE) close = TRUE;
|
||||||
else if (query_headers( request, WINHTTP_QUERY_CONNECTION, NULL, connection, &size, NULL ) ||
|
else if (query_headers( request, WINHTTP_QUERY_CONNECTION, NULL, connection, &size, NULL ) ||
|
||||||
query_headers( request, WINHTTP_QUERY_PROXY_CONNECTION, NULL, connection, &size, NULL ))
|
query_headers( request, WINHTTP_QUERY_PROXY_CONNECTION, NULL, connection, &size, NULL ))
|
||||||
|
@ -1236,7 +1420,14 @@ static void finished_reading( request_t *request )
|
||||||
if (!strcmpiW( connection, closeW )) close = TRUE;
|
if (!strcmpiW( connection, closeW )) close = TRUE;
|
||||||
}
|
}
|
||||||
else if (!strcmpW( request->version, http1_0 )) close = TRUE;
|
else if (!strcmpW( request->version, http1_0 )) close = TRUE;
|
||||||
if (close) close_connection( request );
|
if (close)
|
||||||
|
{
|
||||||
|
close_connection( request );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cache_connection( request->netconn );
|
||||||
|
request->netconn = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return the size of data available to be read immediately */
|
/* return the size of data available to be read immediately */
|
||||||
|
@ -1291,13 +1482,20 @@ done:
|
||||||
/* read any content returned by the server so that the connection can be reused */
|
/* read any content returned by the server so that the connection can be reused */
|
||||||
static void drain_content( request_t *request )
|
static void drain_content( request_t *request )
|
||||||
{
|
{
|
||||||
DWORD bytes_read;
|
DWORD size, bytes_read, bytes_total = 0, bytes_left = request->content_length - request->content_read;
|
||||||
char buffer[2048];
|
char buffer[2048];
|
||||||
|
|
||||||
refill_buffer( request, FALSE );
|
refill_buffer( request, FALSE );
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if (!read_data( request, buffer, sizeof(buffer), &bytes_read, FALSE ) || !bytes_read) return;
|
if (request->read_chunked) size = sizeof(buffer);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (bytes_total >= bytes_left) return;
|
||||||
|
size = min( sizeof(buffer), bytes_left - bytes_total );
|
||||||
|
}
|
||||||
|
if (!read_data( request, buffer, size, &bytes_read, FALSE ) || !bytes_read) return;
|
||||||
|
bytes_total += bytes_read;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1362,13 +1560,13 @@ static BOOL send_request( request_t *request, LPCWSTR headers, DWORD headers_len
|
||||||
|
|
||||||
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST, NULL, 0 );
|
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST, NULL, 0 );
|
||||||
|
|
||||||
ret = netconn_send( &request->netconn, req_ascii, len, &bytes_sent );
|
ret = netconn_send( request->netconn, req_ascii, len, &bytes_sent );
|
||||||
heap_free( req_ascii );
|
heap_free( req_ascii );
|
||||||
if (!ret) goto end;
|
if (!ret) goto end;
|
||||||
|
|
||||||
if (optional_len)
|
if (optional_len)
|
||||||
{
|
{
|
||||||
if (!netconn_send( &request->netconn, optional, optional_len, &bytes_sent )) goto end;
|
if (!netconn_send( request->netconn, optional, optional_len, &bytes_sent )) goto end;
|
||||||
request->optional = optional;
|
request->optional = optional;
|
||||||
request->optional_len = optional_len;
|
request->optional_len = optional_len;
|
||||||
len += optional_len;
|
len += optional_len;
|
||||||
|
@ -2145,7 +2343,7 @@ static BOOL read_reply( request_t *request )
|
||||||
WCHAR *versionW, *status_textW, *raw_headers;
|
WCHAR *versionW, *status_textW, *raw_headers;
|
||||||
WCHAR status_codeW[4]; /* sizeof("nnn") */
|
WCHAR status_codeW[4]; /* sizeof("nnn") */
|
||||||
|
|
||||||
if (!netconn_connected( &request->netconn )) return FALSE;
|
if (!request->netconn) return FALSE;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -2331,11 +2529,11 @@ static BOOL handle_redirect( request_t *request, DWORD status )
|
||||||
connect->hostport = port;
|
connect->hostport = port;
|
||||||
if (!(ret = set_server_for_hostname( connect, hostname, port ))) goto end;
|
if (!(ret = set_server_for_hostname( connect, hostname, port ))) goto end;
|
||||||
|
|
||||||
netconn_close( &request->netconn );
|
netconn_close( request->netconn );
|
||||||
if (!(ret = netconn_init( &request->netconn ))) goto end;
|
request->netconn = NULL;
|
||||||
|
request->content_length = request->content_read = 0;
|
||||||
request->read_pos = request->read_size = 0;
|
request->read_pos = request->read_size = 0;
|
||||||
request->read_chunked = FALSE;
|
request->read_chunked = request->read_chunked_eof = FALSE;
|
||||||
request->read_chunked_eof = FALSE;
|
|
||||||
}
|
}
|
||||||
else heap_free( hostname );
|
else heap_free( hostname );
|
||||||
|
|
||||||
|
@ -2483,14 +2681,14 @@ static BOOL query_data_available( request_t *request, DWORD *available, BOOL asy
|
||||||
if (end_of_read_data( request )) goto done;
|
if (end_of_read_data( request )) goto done;
|
||||||
|
|
||||||
count = get_available_data( request );
|
count = get_available_data( request );
|
||||||
if (!request->read_chunked)
|
if (!request->read_chunked && request->netconn)
|
||||||
count += netconn_query_data_available( &request->netconn );
|
count += netconn_query_data_available( request->netconn );
|
||||||
if (!count)
|
if (!count)
|
||||||
{
|
{
|
||||||
refill_buffer( request, async );
|
refill_buffer( request, async );
|
||||||
count = get_available_data( request );
|
count = get_available_data( request );
|
||||||
if (!request->read_chunked)
|
if (!request->read_chunked && request->netconn)
|
||||||
count += netconn_query_data_available( &request->netconn );
|
count += netconn_query_data_available( request->netconn );
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
@ -2603,7 +2801,7 @@ static BOOL write_data( request_t *request, LPCVOID buffer, DWORD to_write, LPDW
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
int num_bytes;
|
int num_bytes;
|
||||||
|
|
||||||
ret = netconn_send( &request->netconn, buffer, to_write, &num_bytes );
|
ret = netconn_send( request->netconn, buffer, to_write, &num_bytes );
|
||||||
|
|
||||||
if (async)
|
if (async)
|
||||||
{
|
{
|
||||||
|
|
|
@ -685,7 +685,7 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf
|
||||||
{
|
{
|
||||||
case WINHTTP_OPTION_SECURITY_FLAGS:
|
case WINHTTP_OPTION_SECURITY_FLAGS:
|
||||||
{
|
{
|
||||||
DWORD flags;
|
DWORD flags = 0;
|
||||||
int bits;
|
int bits;
|
||||||
|
|
||||||
if (!buffer || *buflen < sizeof(flags))
|
if (!buffer || *buflen < sizeof(flags))
|
||||||
|
@ -697,14 +697,17 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf
|
||||||
|
|
||||||
flags = 0;
|
flags = 0;
|
||||||
if (hdr->flags & WINHTTP_FLAG_SECURE) flags |= SECURITY_FLAG_SECURE;
|
if (hdr->flags & WINHTTP_FLAG_SECURE) flags |= SECURITY_FLAG_SECURE;
|
||||||
flags |= request->netconn.security_flags;
|
flags |= request->security_flags;
|
||||||
bits = netconn_get_cipher_strength( &request->netconn );
|
if (request->netconn)
|
||||||
if (bits >= 128)
|
{
|
||||||
flags |= SECURITY_FLAG_STRENGTH_STRONG;
|
bits = netconn_get_cipher_strength( request->netconn );
|
||||||
else if (bits >= 56)
|
if (bits >= 128)
|
||||||
flags |= SECURITY_FLAG_STRENGTH_MEDIUM;
|
flags |= SECURITY_FLAG_STRENGTH_STRONG;
|
||||||
else
|
else if (bits >= 56)
|
||||||
flags |= SECURITY_FLAG_STRENGTH_WEAK;
|
flags |= SECURITY_FLAG_STRENGTH_MEDIUM;
|
||||||
|
else
|
||||||
|
flags |= SECURITY_FLAG_STRENGTH_WEAK;
|
||||||
|
}
|
||||||
*(DWORD *)buffer = flags;
|
*(DWORD *)buffer = flags;
|
||||||
*buflen = sizeof(flags);
|
*buflen = sizeof(flags);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -720,7 +723,7 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(cert = netconn_get_certificate( &request->netconn ))) return FALSE;
|
if (!request->netconn || !(cert = netconn_get_certificate( request->netconn ))) return FALSE;
|
||||||
*(CERT_CONTEXT **)buffer = (CERT_CONTEXT *)cert;
|
*(CERT_CONTEXT **)buffer = (CERT_CONTEXT *)cert;
|
||||||
*buflen = sizeof(cert);
|
*buflen = sizeof(cert);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -739,7 +742,7 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf
|
||||||
set_last_error( ERROR_INSUFFICIENT_BUFFER );
|
set_last_error( ERROR_INSUFFICIENT_BUFFER );
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (!(cert = netconn_get_certificate( &request->netconn ))) return FALSE;
|
if (!request->netconn || !(cert = netconn_get_certificate( request->netconn ))) return FALSE;
|
||||||
|
|
||||||
ci->ftExpiry = cert->pCertInfo->NotAfter;
|
ci->ftExpiry = cert->pCertInfo->NotAfter;
|
||||||
ci->ftStart = cert->pCertInfo->NotBefore;
|
ci->ftStart = cert->pCertInfo->NotBefore;
|
||||||
|
@ -754,7 +757,7 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf
|
||||||
else
|
else
|
||||||
ci->lpszSignatureAlgName = NULL;
|
ci->lpszSignatureAlgName = NULL;
|
||||||
ci->lpszEncryptionAlgName = NULL;
|
ci->lpszEncryptionAlgName = NULL;
|
||||||
ci->dwKeySize = netconn_get_cipher_strength( &request->netconn );
|
ci->dwKeySize = request->netconn ? netconn_get_cipher_strength( request->netconn ) : 0;
|
||||||
|
|
||||||
CertFreeCertificateContext( cert );
|
CertFreeCertificateContext( cert );
|
||||||
*buflen = sizeof(*ci);
|
*buflen = sizeof(*ci);
|
||||||
|
@ -769,7 +772,7 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
*(DWORD *)buffer = netconn_get_cipher_strength( &request->netconn );
|
*(DWORD *)buffer = request->netconn ? netconn_get_cipher_strength( request->netconn ) : 0;
|
||||||
*buflen = sizeof(DWORD);
|
*buflen = sizeof(DWORD);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -786,12 +789,12 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf
|
||||||
set_last_error( ERROR_INSUFFICIENT_BUFFER );
|
set_last_error( ERROR_INSUFFICIENT_BUFFER );
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (!netconn_connected( &request->netconn ))
|
if (!request->netconn)
|
||||||
{
|
{
|
||||||
set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_STATE );
|
set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_STATE );
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (getsockname( request->netconn.socket, &local, &len )) return FALSE;
|
if (getsockname( request->netconn->socket, &local, &len )) return FALSE;
|
||||||
if (!convert_sockaddr( &local, &info->LocalAddress )) return FALSE;
|
if (!convert_sockaddr( &local, &info->LocalAddress )) return FALSE;
|
||||||
if (!convert_sockaddr( remote, &info->RemoteAddress )) return FALSE;
|
if (!convert_sockaddr( remote, &info->RemoteAddress )) return FALSE;
|
||||||
info->cbSize = sizeof(*info);
|
info->cbSize = sizeof(*info);
|
||||||
|
@ -927,7 +930,7 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffe
|
||||||
set_last_error( ERROR_INVALID_PARAMETER );
|
set_last_error( ERROR_INVALID_PARAMETER );
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
request->netconn.security_flags = flags;
|
request->security_flags = flags;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
case WINHTTP_OPTION_RESOLVE_TIMEOUT:
|
case WINHTTP_OPTION_RESOLVE_TIMEOUT:
|
||||||
|
@ -1064,7 +1067,6 @@ HINTERNET WINAPI WinHttpOpenRequest( HINTERNET hconnect, LPCWSTR verb, LPCWSTR o
|
||||||
request->connect = connect;
|
request->connect = connect;
|
||||||
list_add_head( &connect->hdr.children, &request->hdr.entry );
|
list_add_head( &connect->hdr.children, &request->hdr.entry );
|
||||||
|
|
||||||
if (!netconn_init( &request->netconn )) goto end;
|
|
||||||
request->resolve_timeout = connect->session->resolve_timeout;
|
request->resolve_timeout = connect->session->resolve_timeout;
|
||||||
request->connect_timeout = connect->session->connect_timeout;
|
request->connect_timeout = connect->session->connect_timeout;
|
||||||
request->send_timeout = connect->session->send_timeout;
|
request->send_timeout = connect->session->send_timeout;
|
||||||
|
@ -2047,10 +2049,10 @@ BOOL WINAPI WinHttpSetTimeouts( HINTERNET handle, int resolve, int connect, int
|
||||||
if (receive < 0) receive = 0;
|
if (receive < 0) receive = 0;
|
||||||
request->recv_timeout = receive;
|
request->recv_timeout = receive;
|
||||||
|
|
||||||
if (netconn_connected( &request->netconn ))
|
if (request->netconn)
|
||||||
{
|
{
|
||||||
if (netconn_set_timeout( &request->netconn, TRUE, send )) ret = FALSE;
|
if (netconn_set_timeout( request->netconn, TRUE, send )) ret = FALSE;
|
||||||
if (netconn_set_timeout( &request->netconn, FALSE, receive )) ret = FALSE;
|
if (netconn_set_timeout( request->netconn, FALSE, receive )) ret = FALSE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -111,6 +111,15 @@ typedef struct
|
||||||
WCHAR *path;
|
WCHAR *path;
|
||||||
} cookie_t;
|
} cookie_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct list entry;
|
||||||
|
LONG ref;
|
||||||
|
WCHAR *hostname;
|
||||||
|
INTERNET_PORT port;
|
||||||
|
BOOL secure;
|
||||||
|
struct list connections;
|
||||||
|
} hostdata_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
object_header_t hdr;
|
object_header_t hdr;
|
||||||
|
@ -144,8 +153,12 @@ typedef struct
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
struct list entry;
|
||||||
int socket;
|
int socket;
|
||||||
|
struct sockaddr_storage sockaddr;
|
||||||
BOOL secure; /* SSL active on connection? */
|
BOOL secure; /* SSL active on connection? */
|
||||||
|
hostdata_t *host;
|
||||||
|
ULONGLONG keep_until;
|
||||||
CtxtHandle ssl_ctx;
|
CtxtHandle ssl_ctx;
|
||||||
SecPkgContext_StreamSizes ssl_sizes;
|
SecPkgContext_StreamSizes ssl_sizes;
|
||||||
char *ssl_buf;
|
char *ssl_buf;
|
||||||
|
@ -154,7 +167,6 @@ typedef struct
|
||||||
char *peek_msg;
|
char *peek_msg;
|
||||||
char *peek_msg_mem;
|
char *peek_msg_mem;
|
||||||
size_t peek_len;
|
size_t peek_len;
|
||||||
DWORD security_flags;
|
|
||||||
} netconn_t;
|
} netconn_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -206,7 +218,8 @@ typedef struct
|
||||||
LPWSTR raw_headers;
|
LPWSTR raw_headers;
|
||||||
void *optional;
|
void *optional;
|
||||||
DWORD optional_len;
|
DWORD optional_len;
|
||||||
netconn_t netconn;
|
netconn_t *netconn;
|
||||||
|
DWORD security_flags;
|
||||||
int resolve_timeout;
|
int resolve_timeout;
|
||||||
int connect_timeout;
|
int connect_timeout;
|
||||||
int send_timeout;
|
int send_timeout;
|
||||||
|
@ -295,17 +308,15 @@ void send_callback( object_header_t *, DWORD, LPVOID, DWORD ) DECLSPEC_HIDDEN;
|
||||||
void close_connection( request_t * ) DECLSPEC_HIDDEN;
|
void close_connection( request_t * ) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
BOOL netconn_close( netconn_t * ) DECLSPEC_HIDDEN;
|
BOOL netconn_close( netconn_t * ) DECLSPEC_HIDDEN;
|
||||||
BOOL netconn_connect( netconn_t *, const struct sockaddr *, unsigned int, int ) DECLSPEC_HIDDEN;
|
netconn_t *netconn_create( hostdata_t *, const struct sockaddr_storage *, int ) DECLSPEC_HIDDEN;
|
||||||
BOOL netconn_connected( netconn_t * ) DECLSPEC_HIDDEN;
|
|
||||||
BOOL netconn_create( netconn_t *, int, int, int ) DECLSPEC_HIDDEN;
|
|
||||||
BOOL netconn_init( netconn_t * ) DECLSPEC_HIDDEN;
|
|
||||||
void netconn_unload( void ) DECLSPEC_HIDDEN;
|
void netconn_unload( void ) DECLSPEC_HIDDEN;
|
||||||
ULONG netconn_query_data_available( netconn_t * ) DECLSPEC_HIDDEN;
|
ULONG netconn_query_data_available( netconn_t * ) DECLSPEC_HIDDEN;
|
||||||
BOOL netconn_recv( netconn_t *, void *, size_t, int, int * ) DECLSPEC_HIDDEN;
|
BOOL netconn_recv( netconn_t *, void *, size_t, int, int * ) DECLSPEC_HIDDEN;
|
||||||
BOOL netconn_resolve( WCHAR *, INTERNET_PORT, struct sockaddr *, socklen_t *, int ) DECLSPEC_HIDDEN;
|
BOOL netconn_resolve( WCHAR *, INTERNET_PORT, struct sockaddr_storage *, int ) DECLSPEC_HIDDEN;
|
||||||
BOOL netconn_secure_connect( netconn_t *, WCHAR * ) DECLSPEC_HIDDEN;
|
BOOL netconn_secure_connect( netconn_t *, WCHAR *, DWORD ) DECLSPEC_HIDDEN;
|
||||||
BOOL netconn_send( netconn_t *, const void *, size_t, int * ) DECLSPEC_HIDDEN;
|
BOOL netconn_send( netconn_t *, const void *, size_t, int * ) DECLSPEC_HIDDEN;
|
||||||
DWORD netconn_set_timeout( netconn_t *, BOOL, int ) DECLSPEC_HIDDEN;
|
DWORD netconn_set_timeout( netconn_t *, BOOL, int ) DECLSPEC_HIDDEN;
|
||||||
|
BOOL netconn_is_alive( netconn_t * ) DECLSPEC_HIDDEN;
|
||||||
const void *netconn_get_certificate( netconn_t * ) DECLSPEC_HIDDEN;
|
const void *netconn_get_certificate( netconn_t * ) DECLSPEC_HIDDEN;
|
||||||
int netconn_get_cipher_strength( netconn_t * ) DECLSPEC_HIDDEN;
|
int netconn_get_cipher_strength( netconn_t * ) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
@ -316,6 +327,8 @@ void delete_domain( domain_t * ) DECLSPEC_HIDDEN;
|
||||||
BOOL set_server_for_hostname( connect_t *, LPCWSTR, INTERNET_PORT ) DECLSPEC_HIDDEN;
|
BOOL set_server_for_hostname( connect_t *, LPCWSTR, INTERNET_PORT ) DECLSPEC_HIDDEN;
|
||||||
void destroy_authinfo( struct authinfo * ) DECLSPEC_HIDDEN;
|
void destroy_authinfo( struct authinfo * ) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
void release_host( hostdata_t *host ) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
BOOL process_header( request_t *request, LPCWSTR field, LPCWSTR value, DWORD flags, BOOL request_only ) DECLSPEC_HIDDEN;
|
BOOL process_header( request_t *request, LPCWSTR field, LPCWSTR value, DWORD flags, BOOL request_only ) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
extern HRESULT WinHttpRequest_create( void ** ) DECLSPEC_HIDDEN;
|
extern HRESULT WinHttpRequest_create( void ** ) DECLSPEC_HIDDEN;
|
||||||
|
@ -395,4 +408,6 @@ static inline char *strdupWA_sized( const WCHAR *src, DWORD size )
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern HINSTANCE winhttp_instance DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
#endif /* _WINE_WINHTTP_PRIVATE_H_ */
|
#endif /* _WINE_WINHTTP_PRIVATE_H_ */
|
||||||
|
|
|
@ -200,7 +200,7 @@ reactos/dll/win32/windowscodecs # Synced to WineStaging-2.9
|
||||||
reactos/dll/win32/windowscodecsext # Synced to WineStaging-2.9
|
reactos/dll/win32/windowscodecsext # Synced to WineStaging-2.9
|
||||||
reactos/dll/win32/winemp3.acm # Synced to WineStaging-2.16
|
reactos/dll/win32/winemp3.acm # Synced to WineStaging-2.16
|
||||||
reactos/dll/win32/wing32 # Synced to WineStaging-2.9
|
reactos/dll/win32/wing32 # Synced to WineStaging-2.9
|
||||||
reactos/dll/win32/winhttp # Synced to WineStaging-2.9
|
reactos/dll/win32/winhttp # Synced to WineStaging-2.16
|
||||||
reactos/dll/win32/wininet # Synced to WineStaging-2.9
|
reactos/dll/win32/wininet # Synced to WineStaging-2.9
|
||||||
reactos/dll/win32/winmm # Forked at Wine-20050628
|
reactos/dll/win32/winmm # Forked at Wine-20050628
|
||||||
reactos/dll/win32/winmm/midimap # Forked at Wine-20050628
|
reactos/dll/win32/winmm/midimap # Forked at Wine-20050628
|
||||||
|
|
Loading…
Reference in a new issue