Jacek Caban : winhttp: Introduce global connected hosts store and keep reference to host in netconn_t.

Alexandre Julliard julliard at winehq.org
Tue Jul 18 13:58:54 CDT 2017


Module: wine
Branch: master
Commit: e0e8a3ff77466b66880df30cbf0fe3619a9ba880
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=e0e8a3ff77466b66880df30cbf0fe3619a9ba880

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Tue Jul 18 00:25:10 2017 +0200

winhttp: Introduce global connected hosts store and keep reference to host in netconn_t.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/winhttp/net.c             |  4 +-
 dlls/winhttp/request.c         | 88 +++++++++++++++++++++++++++++++++++++++---
 dlls/winhttp/winhttp_private.h | 13 ++++++-
 3 files changed, 97 insertions(+), 8 deletions(-)

diff --git a/dlls/winhttp/net.c b/dlls/winhttp/net.c
index 32d3624..c57d3af 100644
--- a/dlls/winhttp/net.c
+++ b/dlls/winhttp/net.c
@@ -299,7 +299,7 @@ void netconn_unload( void )
 #endif
 }
 
-netconn_t *netconn_create( const struct sockaddr_storage *sockaddr, int timeout )
+netconn_t *netconn_create( host_t *host, const struct sockaddr_storage *sockaddr, int timeout )
 {
     netconn_t *conn;
     unsigned int addr_len;
@@ -309,6 +309,7 @@ netconn_t *netconn_create( const struct sockaddr_storage *sockaddr, int timeout
 
     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)
     {
@@ -398,6 +399,7 @@ BOOL netconn_close( netconn_t *conn )
         DeleteSecurityContext(&conn->ssl_ctx);
     }
     res = closesocket( conn->socket );
+    release_host( conn->host );
     heap_free(conn);
     if (res == -1)
     {
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c
index 5afc768..97e4ce0 100644
--- a/dlls/winhttp/request.c
+++ b/dlls/winhttp/request.c
@@ -991,8 +991,34 @@ static WCHAR *addr_to_str( struct sockaddr_storage *addr )
     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( host_t *host )
+{
+    LONG ref;
+
+    EnterCriticalSection( &connection_pool_cs );
+    if (!(ref = --host->ref)) list_remove( &host->entry );
+    LeaveCriticalSection( &connection_pool_cs );
+    if (ref) return;
+
+    heap_free( host->hostname );
+    heap_free( host );
+}
+
 static BOOL open_connection( request_t *request )
 {
+    BOOL is_secure = request->hdr.flags & WINHTTP_FLAG_SECURE;
+    host_t *host = NULL, *iter;
     netconn_t *netconn;
     connect_t *connect;
     WCHAR *addressW = NULL;
@@ -1004,25 +1030,74 @@ static BOOL open_connection( request_t *request )
     connect = request->connect;
     port = connect->serverport ? connect->serverport : (request->hdr.flags & WINHTTP_FLAG_SECURE ? 443 : 80);
 
+    EnterCriticalSection( &connection_pool_cs );
+
+    LIST_FOR_EACH_ENTRY( iter, &connection_pool, host_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) ))) return FALSE;
+        host->ref = 1;
+        host->secure = is_secure;
+        host->port = port;
+        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;
+
     if (!connect->resolved)
     {
-        len = strlenW( connect->servername ) + 1;
-        send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, connect->servername, len );
+        len = strlenW( host->hostname ) + 1;
+        send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, host->hostname, len );
 
-        if (!netconn_resolve( connect->servername, port, &connect->sockaddr, request->resolve_timeout )) return FALSE;
+        if (!netconn_resolve( host->hostname, port, &connect->sockaddr, request->resolve_timeout ))
+        {
+            release_host( host );
+            return FALSE;
+        }
         connect->resolved = TRUE;
 
-        if (!(addressW = addr_to_str( &connect->sockaddr ))) 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( &connect->sockaddr ))) return FALSE;
+
+    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( &connect->sockaddr, request->connect_timeout )))
+    netconn = netconn_create( host, &connect->sockaddr, request->connect_timeout );
+    if (!netconn)
     {
+        release_host( host );
         heap_free( addressW );
         return FALSE;
     }
@@ -1036,6 +1111,7 @@ static BOOL open_connection( request_t *request )
             if (!secure_proxy_connect( request ))
             {
                 heap_free( addressW );
+                netconn_close( netconn );
                 return FALSE;
             }
         }
diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h
index 611dc43..2b171bf 100644
--- a/dlls/winhttp/winhttp_private.h
+++ b/dlls/winhttp/winhttp_private.h
@@ -96,6 +96,14 @@ typedef struct
     WCHAR *path;
 } cookie_t;
 
+typedef struct {
+    struct list entry;
+    LONG ref;
+    WCHAR *hostname;
+    INTERNET_PORT port;
+    BOOL secure;
+} host_t;
+
 typedef struct
 {
     object_header_t hdr;
@@ -132,6 +140,7 @@ typedef struct
     int socket;
     struct sockaddr_storage sockaddr;
     BOOL secure; /* SSL active on connection? */
+    host_t *host;
     CtxtHandle ssl_ctx;
     SecPkgContext_StreamSizes ssl_sizes;
     char *ssl_buf;
@@ -283,7 +292,7 @@ void send_callback( object_header_t *, DWORD, LPVOID, DWORD ) DECLSPEC_HIDDEN;
 void close_connection( request_t * ) DECLSPEC_HIDDEN;
 
 BOOL netconn_close( netconn_t * ) DECLSPEC_HIDDEN;
-netconn_t *netconn_create( const struct sockaddr_storage *, int ) DECLSPEC_HIDDEN;
+netconn_t *netconn_create( host_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;
@@ -301,6 +310,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( host_t *host ) DECLSPEC_HIDDEN;
+
 extern HRESULT WinHttpRequest_create( void ** ) DECLSPEC_HIDDEN;
 void release_typelib( void ) DECLSPEC_HIDDEN;
 




More information about the wine-cvs mailing list