Author: akhaldi
Date: Sun Sep 24 11:17:43 2017
New Revision: 75944
URL:
http://svn.reactos.org/svn/reactos?rev=75944&view=rev
Log:
[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.
Modified:
trunk/reactos/dll/win32/winhttp/CMakeLists.txt
trunk/reactos/dll/win32/winhttp/inet_ntop.c
trunk/reactos/dll/win32/winhttp/main.c
trunk/reactos/dll/win32/winhttp/net.c
trunk/reactos/dll/win32/winhttp/request.c
trunk/reactos/dll/win32/winhttp/session.c
trunk/reactos/dll/win32/winhttp/winhttp_private.h
trunk/reactos/media/doc/README.WINE
Modified: trunk/reactos/dll/win32/winhttp/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/CMakeLis…
==============================================================================
--- trunk/reactos/dll/win32/winhttp/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/winhttp/CMakeLists.txt [iso-8859-1] Sun Sep 24 11:17:43 2017
@@ -1,3 +1,6 @@
+
+remove_definitions(-D_WIN32_WINNT=0x502)
+add_definitions(-D_WIN32_WINNT=0x600)
add_definitions(
-D__WINESRC__
@@ -27,7 +30,7 @@
set_module_type(winhttp win32dll)
target_link_libraries(winhttp uuid wine)
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_pch(winhttp winhttp_private.h SOURCE)
add_cd_file(TARGET winhttp DESTINATION reactos/system32 FOR all)
Modified: trunk/reactos/dll/win32/winhttp/inet_ntop.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/inet_nto…
==============================================================================
--- trunk/reactos/dll/win32/winhttp/inet_ntop.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/winhttp/inet_ntop.c [iso-8859-1] Sun Sep 24 11:17:43 2017
@@ -51,16 +51,18 @@
* author:
* 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:
- return (inet_ntop4(src, dst, size));
+ return (inet_ntop4(pAddr, pStringBuf, StringBufSize));
#ifdef INET6
case AF_INET6:
- return (inet_ntop6(src, dst, size));
+ return (inet_ntop6(pAddr, pStringBuf, StringBufSize));
#endif
default:
WSASetLastError(WSAEAFNOSUPPORT);
Modified: trunk/reactos/dll/win32/winhttp/main.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/main.c?r…
==============================================================================
--- trunk/reactos/dll/win32/winhttp/main.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/winhttp/main.c [iso-8859-1] Sun Sep 24 11:17:43 2017
@@ -21,7 +21,7 @@
#include <rpcproxy.h>
#include <httprequest.h>
-static HINSTANCE instance;
+HINSTANCE winhttp_instance;
/******************************************************************
* DllMain (winhttp.@)
@@ -31,7 +31,7 @@
switch(fdwReason)
{
case DLL_PROCESS_ATTACH:
- instance = hInstDLL;
+ winhttp_instance = hInstDLL;
DisableThreadLibraryCalls(hInstDLL);
break;
case DLL_PROCESS_DETACH:
@@ -158,7 +158,7 @@
*/
HRESULT WINAPI DllRegisterServer(void)
{
- return __wine_register_resources( instance );
+ return __wine_register_resources( winhttp_instance );
}
/***********************************************************************
@@ -166,5 +166,5 @@
*/
HRESULT WINAPI DllUnregisterServer(void)
{
- return __wine_unregister_resources( instance );
+ return __wine_unregister_resources( winhttp_instance );
}
Modified: trunk/reactos/dll/win32/winhttp/net.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/net.c?re…
==============================================================================
--- trunk/reactos/dll/win32/winhttp/net.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/winhttp/net.c [iso-8859-1] Sun Sep 24 11:17:43 2017
@@ -298,13 +298,6 @@
#endif
-BOOL netconn_init( netconn_t *conn )
-{
- memset(conn, 0, sizeof(*conn));
- conn->socket = -1;
- return TRUE;
-}
-
void netconn_unload( void )
{
if(cred_handle_initialized)
@@ -319,56 +312,38 @@
#endif
}
-BOOL netconn_connected( netconn_t *conn )
-{
- 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 *netconn_create( hostdata_t *host, const struct sockaddr_storage *sockaddr, int
timeout )
+{
+ netconn_t *conn;
+ unsigned int addr_len;
BOOL ret = FALSE;
int res;
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)
{
state = 1;
@@ -378,7 +353,7 @@
for (;;)
{
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 );
if (res == WSAEWOULDBLOCK || res == WSAEINPROGRESS)
@@ -436,11 +411,35 @@
{
WARN("unable to connect to host (%d)\n", res);
set_last_error( res );
- }
- return ret;
-}
-
-BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname )
+ netconn_close( conn );
+ return NULL;
+ }
+ return conn;
+}
+
+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}};
SecBufferDesc out_desc = {SECBUFFER_VERSION, 1, &out_buf}, in_desc =
{SECBUFFER_VERSION, 2, in_bufs};
@@ -540,7 +539,7 @@
status = QueryContextAttributesW(&ctx, SECPKG_ATTR_REMOTE_CERT_CONTEXT,
(void*)&cert);
if(status == SEC_E_OK) {
- res = netconn_verify_cert(cert, hostname, conn->security_flags);
+ res = netconn_verify_cert(cert, hostname, security_flags);
CertFreeCertificateContext(cert);
if(res != ERROR_SUCCESS) {
WARN("cert verify failed: %u\n", res);
@@ -605,7 +604,6 @@
BOOL netconn_send( netconn_t *conn, const void *msg, size_t len, int *sent )
{
- if (!netconn_connected( conn )) return FALSE;
if (conn->secure)
{
const BYTE *ptr = msg;
@@ -729,7 +727,6 @@
BOOL netconn_recv( netconn_t *conn, void *buf, size_t len, int flags, int *recvd )
{
*recvd = 0;
- if (!netconn_connected( conn )) return FALSE;
if (!len) return TRUE;
if (conn->secure)
@@ -786,13 +783,7 @@
ULONG netconn_query_data_available( netconn_t *conn )
{
- if(!netconn_connected(conn))
- return 0;
-
- if(conn->secure)
- return conn->peek_len;
-
- return 0;
+ return conn->secure ? conn->peek_len : 0;
}
DWORD netconn_set_timeout( netconn_t *netconn, BOOL send, int value )
@@ -811,7 +802,37 @@
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;
#ifdef HAVE_GETADDRINFO
@@ -845,13 +866,6 @@
}
}
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 );
/* Copy port */
switch (res->ai_family)
@@ -877,13 +891,6 @@
LeaveCriticalSection( &cs_gethostbyname );
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) );
memcpy( &sin->sin_addr, he->h_addr, he->h_length );
sin->sin_family = he->h_addrtype;
@@ -896,19 +903,18 @@
struct resolve_args
{
- const WCHAR *hostname;
- INTERNET_PORT port;
- struct sockaddr *sa;
- socklen_t *sa_len;
+ const WCHAR *hostname;
+ INTERNET_PORT port;
+ struct sockaddr_storage *sa;
};
static DWORD CALLBACK resolve_proc( LPVOID arg )
{
struct resolve_args *ra = arg;
- return resolve_hostname( ra->hostname, ra->port, ra->sa, ra->sa_len );
-}
-
-BOOL netconn_resolve( WCHAR *hostname, INTERNET_PORT port, struct sockaddr *sa, socklen_t
*sa_len, int timeout )
+ return resolve_hostname( ra->hostname, ra->port, ra->sa );
+}
+
+BOOL netconn_resolve( WCHAR *hostname, INTERNET_PORT port, struct sockaddr_storage *sa,
int timeout )
{
DWORD ret;
@@ -921,7 +927,6 @@
ra.hostname = hostname;
ra.port = port;
ra.sa = sa;
- ra.sa_len = sa_len;
thread = CreateThread( NULL, 0, resolve_proc, &ra, 0, NULL );
if (!thread) return FALSE;
@@ -931,7 +936,7 @@
else ret = ERROR_WINHTTP_TIMEOUT;
CloseHandle( thread );
}
- else ret = resolve_hostname( hostname, port, sa, sa_len );
+ else ret = resolve_hostname( hostname, port, sa );
if (ret)
{
Modified: trunk/reactos/dll/win32/winhttp/request.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/request.…
==============================================================================
--- trunk/reactos/dll/win32/winhttp/request.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/winhttp/request.c [iso-8859-1] Sun Sep 24 11:17:43 2017
@@ -31,6 +31,8 @@
#include <httprequestid.h>
#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_charset[] =
{'A','c','c','e','p','t','-','C','h','a','r','s','e','t',
0};
@@ -540,7 +542,7 @@
static const WCHAR http[] = { 'h','t','t','p',0
};
static const WCHAR https[] = {
'h','t','t','p','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;
len = strlenW( scheme ) + strlenW( request->connect->hostname );
@@ -945,7 +947,7 @@
{
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 );
if (ret)
ret = read_reply( request );
@@ -959,12 +961,12 @@
#define INET6_ADDRSTRLEN 46
#endif
-static WCHAR *addr_to_str( struct sockaddr *addr )
+static WCHAR *addr_to_str( struct sockaddr_storage *addr )
{
char buf[INET6_ADDRSTRLEN];
void *src;
- switch (addr->sa_family)
+ switch (addr->ss_family)
{
case AF_INET:
src = &((struct sockaddr_in *)addr)->sin_addr;
@@ -973,79 +975,258 @@
src = &((struct sockaddr_in6 *)addr)->sin6_addr;
break;
default:
- WARN("unsupported address family %d\n", addr->sa_family);
+ WARN("unsupported address family %d\n", addr->ss_family);
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 );
}
+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 )
{
+ BOOL is_secure = request->hdr.flags & WINHTTP_FLAG_SECURE;
+ hostdata_t *host = NULL, *iter;
+ netconn_t *netconn = NULL;
connect_t *connect;
WCHAR *addressW = NULL;
INTERNET_PORT port;
- socklen_t slen;
- struct sockaddr *saddr;
DWORD len;
- if (netconn_connected( &request->netconn )) goto done;
+ if (request->netconn) goto done;
connect = request->connect;
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)
{
- len = strlenW( connect->servername ) + 1;
- send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME,
connect->servername, len );
-
- if (!netconn_resolve( connect->servername, port, saddr, &slen,
request->resolve_timeout )) return FALSE;
+ len = strlenW( host->hostname ) + 1;
+ send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME,
host->hostname, len );
+
+ if (!netconn_resolve( host->hostname, port, &connect->sockaddr,
request->resolve_timeout ))
+ {
+ release_host( host );
+ return FALSE;
+ }
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;
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_create( &request->netconn, saddr->sa_family, SOCK_STREAM, 0
))
- {
- heap_free( addressW );
- 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 ))
+
+ if (!netconn)
+ {
+ if (!addressW && !(addressW = addr_to_str( &connect->sockaddr )))
+ {
+ 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 );
+ netconn_close( netconn );
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:
request->read_pos = request->read_size = 0;
@@ -1058,10 +1239,11 @@
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
);
- netconn_close( &request->netconn );
+ netconn_close( request->netconn );
+ request->netconn = NULL;
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, 0, 0
);
}
@@ -1127,7 +1309,7 @@
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 );
if (notify) send_callback( &request->hdr,
WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED, &len, sizeof(len) );
@@ -1229,6 +1411,8 @@
WCHAR connection[20];
DWORD size = sizeof(connection);
+ if (!request->netconn) return;
+
if (request->hdr.disable_flags & WINHTTP_DISABLE_KEEP_ALIVE) close = TRUE;
else if (query_headers( request, WINHTTP_QUERY_CONNECTION, NULL, connection,
&size, NULL ) ||
query_headers( request, WINHTTP_QUERY_PROXY_CONNECTION, NULL, connection,
&size, NULL ))
@@ -1236,7 +1420,14 @@
if (!strcmpiW( connection, closeW )) 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 */
@@ -1291,13 +1482,20 @@
/* read any content returned by the server so that the connection can be reused */
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];
refill_buffer( request, FALSE );
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 @@
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 );
if (!ret) goto end;
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_len = optional_len;
len += optional_len;
@@ -2145,7 +2343,7 @@
WCHAR *versionW, *status_textW, *raw_headers;
WCHAR status_codeW[4]; /* sizeof("nnn") */
- if (!netconn_connected( &request->netconn )) return FALSE;
+ if (!request->netconn) return FALSE;
do
{
@@ -2331,11 +2529,11 @@
connect->hostport = port;
if (!(ret = set_server_for_hostname( connect, hostname, port ))) goto end;
- netconn_close( &request->netconn );
- if (!(ret = netconn_init( &request->netconn ))) goto end;
+ netconn_close( request->netconn );
+ request->netconn = NULL;
+ request->content_length = request->content_read = 0;
request->read_pos = request->read_size = 0;
- request->read_chunked = FALSE;
- request->read_chunked_eof = FALSE;
+ request->read_chunked = request->read_chunked_eof = FALSE;
}
else heap_free( hostname );
@@ -2483,14 +2681,14 @@
if (end_of_read_data( request )) goto done;
count = get_available_data( request );
- if (!request->read_chunked)
- count += netconn_query_data_available( &request->netconn );
+ if (!request->read_chunked && request->netconn)
+ count += netconn_query_data_available( request->netconn );
if (!count)
{
refill_buffer( request, async );
count = get_available_data( request );
- if (!request->read_chunked)
- count += netconn_query_data_available( &request->netconn );
+ if (!request->read_chunked && request->netconn)
+ count += netconn_query_data_available( request->netconn );
}
done:
@@ -2603,7 +2801,7 @@
BOOL ret;
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)
{
Modified: trunk/reactos/dll/win32/winhttp/session.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/session.…
==============================================================================
--- trunk/reactos/dll/win32/winhttp/session.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/winhttp/session.c [iso-8859-1] Sun Sep 24 11:17:43 2017
@@ -685,7 +685,7 @@
{
case WINHTTP_OPTION_SECURITY_FLAGS:
{
- DWORD flags;
+ DWORD flags = 0;
int bits;
if (!buffer || *buflen < sizeof(flags))
@@ -697,14 +697,17 @@
flags = 0;
if (hdr->flags & WINHTTP_FLAG_SECURE) flags |= SECURITY_FLAG_SECURE;
- flags |= request->netconn.security_flags;
- bits = netconn_get_cipher_strength( &request->netconn );
- if (bits >= 128)
- flags |= SECURITY_FLAG_STRENGTH_STRONG;
- else if (bits >= 56)
- flags |= SECURITY_FLAG_STRENGTH_MEDIUM;
- else
- flags |= SECURITY_FLAG_STRENGTH_WEAK;
+ flags |= request->security_flags;
+ if (request->netconn)
+ {
+ bits = netconn_get_cipher_strength( request->netconn );
+ if (bits >= 128)
+ flags |= SECURITY_FLAG_STRENGTH_STRONG;
+ else if (bits >= 56)
+ flags |= SECURITY_FLAG_STRENGTH_MEDIUM;
+ else
+ flags |= SECURITY_FLAG_STRENGTH_WEAK;
+ }
*(DWORD *)buffer = flags;
*buflen = sizeof(flags);
return TRUE;
@@ -720,7 +723,7 @@
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;
*buflen = sizeof(cert);
return TRUE;
@@ -739,7 +742,7 @@
set_last_error( ERROR_INSUFFICIENT_BUFFER );
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->ftStart = cert->pCertInfo->NotBefore;
@@ -754,7 +757,7 @@
else
ci->lpszSignatureAlgName = 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 );
*buflen = sizeof(*ci);
@@ -769,7 +772,7 @@
return FALSE;
}
- *(DWORD *)buffer = netconn_get_cipher_strength( &request->netconn );
+ *(DWORD *)buffer = request->netconn ? netconn_get_cipher_strength(
request->netconn ) : 0;
*buflen = sizeof(DWORD);
return TRUE;
}
@@ -786,12 +789,12 @@
set_last_error( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
- if (!netconn_connected( &request->netconn ))
+ if (!request->netconn)
{
set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_STATE );
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( remote, &info->RemoteAddress )) return FALSE;
info->cbSize = sizeof(*info);
@@ -927,7 +930,7 @@
set_last_error( ERROR_INVALID_PARAMETER );
return FALSE;
}
- request->netconn.security_flags = flags;
+ request->security_flags = flags;
return TRUE;
}
case WINHTTP_OPTION_RESOLVE_TIMEOUT:
@@ -1064,7 +1067,6 @@
request->connect = connect;
list_add_head( &connect->hdr.children, &request->hdr.entry );
- if (!netconn_init( &request->netconn )) goto end;
request->resolve_timeout = connect->session->resolve_timeout;
request->connect_timeout = connect->session->connect_timeout;
request->send_timeout = connect->session->send_timeout;
@@ -2047,10 +2049,10 @@
if (receive < 0) receive = 0;
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, FALSE, receive )) ret
= FALSE;
+ if (netconn_set_timeout( request->netconn, TRUE, send )) ret = FALSE;
+ if (netconn_set_timeout( request->netconn, FALSE, receive )) ret =
FALSE;
}
break;
Modified: trunk/reactos/dll/win32/winhttp/winhttp_private.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/winhttp_…
==============================================================================
--- trunk/reactos/dll/win32/winhttp/winhttp_private.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/winhttp/winhttp_private.h [iso-8859-1] Sun Sep 24 11:17:43
2017
@@ -111,6 +111,15 @@
WCHAR *path;
} cookie_t;
+typedef struct {
+ struct list entry;
+ LONG ref;
+ WCHAR *hostname;
+ INTERNET_PORT port;
+ BOOL secure;
+ struct list connections;
+} hostdata_t;
+
typedef struct
{
object_header_t hdr;
@@ -144,8 +153,12 @@
typedef struct
{
+ struct list entry;
int socket;
+ struct sockaddr_storage sockaddr;
BOOL secure; /* SSL active on connection? */
+ hostdata_t *host;
+ ULONGLONG keep_until;
CtxtHandle ssl_ctx;
SecPkgContext_StreamSizes ssl_sizes;
char *ssl_buf;
@@ -154,7 +167,6 @@
char *peek_msg;
char *peek_msg_mem;
size_t peek_len;
- DWORD security_flags;
} netconn_t;
typedef struct
@@ -206,7 +218,8 @@
LPWSTR raw_headers;
void *optional;
DWORD optional_len;
- netconn_t netconn;
+ netconn_t *netconn;
+ DWORD security_flags;
int resolve_timeout;
int connect_timeout;
int send_timeout;
@@ -295,17 +308,15 @@
void close_connection( request_t * ) DECLSPEC_HIDDEN;
BOOL netconn_close( netconn_t * ) DECLSPEC_HIDDEN;
-BOOL netconn_connect( netconn_t *, const struct sockaddr *, unsigned int, 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;
+netconn_t *netconn_create( hostdata_t *, const struct sockaddr_storage *, int )
DECLSPEC_HIDDEN;
void netconn_unload( void ) 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_resolve( WCHAR *, INTERNET_PORT, struct sockaddr *, socklen_t *, int )
DECLSPEC_HIDDEN;
-BOOL netconn_secure_connect( netconn_t *, WCHAR * ) DECLSPEC_HIDDEN;
+BOOL netconn_resolve( WCHAR *, INTERNET_PORT, struct sockaddr_storage *, int )
DECLSPEC_HIDDEN;
+BOOL netconn_secure_connect( netconn_t *, WCHAR *, DWORD ) DECLSPEC_HIDDEN;
BOOL netconn_send( netconn_t *, const void *, size_t, 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;
int netconn_get_cipher_strength( netconn_t * ) DECLSPEC_HIDDEN;
@@ -315,6 +326,8 @@
void delete_domain( domain_t * ) DECLSPEC_HIDDEN;
BOOL set_server_for_hostname( connect_t *, LPCWSTR, INTERNET_PORT ) 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;
@@ -395,4 +408,6 @@
return dst;
}
+extern HINSTANCE winhttp_instance DECLSPEC_HIDDEN;
+
#endif /* _WINE_WINHTTP_PRIVATE_H_ */
Modified: trunk/reactos/media/doc/README.WINE
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/media/doc/README.WINE?rev=…
==============================================================================
--- trunk/reactos/media/doc/README.WINE [iso-8859-1] (original)
+++ trunk/reactos/media/doc/README.WINE [iso-8859-1] Sun Sep 24 11:17:43 2017
@@ -200,7 +200,7 @@
reactos/dll/win32/windowscodecsext # Synced to WineStaging-2.9
reactos/dll/win32/winemp3.acm # Synced to WineStaging-2.16
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/winmm # Forked at Wine-20050628
reactos/dll/win32/winmm/midimap # Forked at Wine-20050628