Hans Leidekker : wininet: Implement the connect timeout.

Alexandre Julliard julliard at winehq.org
Mon Jan 16 13:01:29 CST 2012


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

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Fri Jan 13 15:15:04 2012 +0100

wininet: Implement the connect timeout.

---

 dlls/wininet/http.c          |    4 +++-
 dlls/wininet/internet.h      |    4 +++-
 dlls/wininet/netconnection.c |   32 +++++++++++++++++++++++++++++++-
 3 files changed, 37 insertions(+), 3 deletions(-)

diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c
index 8fc01fe..e645d86 100644
--- a/dlls/wininet/http.c
+++ b/dlls/wininet/http.c
@@ -3048,6 +3048,7 @@ static DWORD HTTP_HttpOpenRequestW(http_session_t *session,
 
     request->netconn_stream.data_stream.vtbl = &netconn_stream_vtbl;
     request->data_stream = &request->netconn_stream.data_stream;
+    request->connect_timeout = session->connect_timeout;
 
     InitializeCriticalSection( &request->read_section );
     request->read_section.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": http_request_t.read_section");
@@ -4597,7 +4598,7 @@ static DWORD open_http_connection(http_request_t *request, BOOL *reusing)
                           server->addr_str,
                           strlen(server->addr_str)+1);
 
-    res = create_netconn(is_https, server, request->security_flags, &netconn);
+    res = create_netconn(is_https, server, request->security_flags, request->connect_timeout, &netconn);
     server_release(server);
     if(res != ERROR_SUCCESS) {
         ERR("create_netconn failed: %u\n", res);
@@ -5541,6 +5542,7 @@ DWORD HTTP_Connect(appinfo_t *hIC, LPCWSTR lpszServerName,
         session->password = heap_strdupW(lpszPassword);
     session->serverPort = serverPort;
     session->hostPort = serverPort;
+    session->connect_timeout = INFINITE;
 
     /* Don't send a handle created callback if this handle was created with InternetOpenUrl */
     if (!(session->hdr.dwInternalFlags & INET_OPENURL))
diff --git a/dlls/wininet/internet.h b/dlls/wininet/internet.h
index a7af629..41af08c 100644
--- a/dlls/wininet/internet.h
+++ b/dlls/wininet/internet.h
@@ -265,6 +265,7 @@ typedef struct
     LPWSTR  password;
     INTERNET_PORT hostPort; /* the final destination port of the request */
     INTERNET_PORT serverPort; /* the port of the server we directly connect to */
+    DWORD connect_timeout;
 } http_session_t;
 
 #define HDR_ISREQUEST		0x0001
@@ -305,6 +306,7 @@ typedef struct
     LPWSTR rawHeaders;
     netconn_t *netconn;
     DWORD security_flags;
+    DWORD connect_timeout;
     LPWSTR version;
     LPWSTR statusText;
     DWORD bytesToWrite;
@@ -515,7 +517,7 @@ VOID INTERNET_SendCallback(object_header_t *hdr, DWORD_PTR dwContext,
                            DWORD dwStatusInfoLength) DECLSPEC_HIDDEN;
 BOOL INTERNET_FindProxyForProtocol(LPCWSTR szProxy, LPCWSTR proto, WCHAR *foundProxy, DWORD *foundProxyLen) DECLSPEC_HIDDEN;
 
-DWORD create_netconn(BOOL,server_t*,DWORD,netconn_t**) DECLSPEC_HIDDEN;
+DWORD create_netconn(BOOL, server_t *, DWORD, DWORD, netconn_t **) DECLSPEC_HIDDEN;
 void free_netconn(netconn_t*) DECLSPEC_HIDDEN;
 void NETCON_unload(void) DECLSPEC_HIDDEN;
 DWORD NETCON_secure_connect(netconn_t *connection, LPWSTR hostname) DECLSPEC_HIDDEN;
diff --git a/dlls/wininet/netconnection.c b/dlls/wininet/netconnection.c
index bf93301..8273c73 100644
--- a/dlls/wininet/netconnection.c
+++ b/dlls/wininet/netconnection.c
@@ -497,7 +497,7 @@ static DWORD init_openssl(void)
 #endif
 }
 
-DWORD create_netconn(BOOL useSSL, server_t *server, DWORD security_flags, netconn_t **ret)
+DWORD create_netconn(BOOL useSSL, server_t *server, DWORD security_flags, DWORD timeout, netconn_t **ret)
 {
     netconn_t *netconn;
     int result, flag;
@@ -526,9 +526,39 @@ DWORD create_netconn(BOOL useSSL, server_t *server, DWORD security_flags, netcon
     assert(server->addr_len);
     result = netconn->socketFD = socket(server->addr.ss_family, SOCK_STREAM, 0);
     if(result != -1) {
+        flag = 1;
+        ioctlsocket(netconn->socketFD, FIONBIO, &flag);
         result = connect(netconn->socketFD, (struct sockaddr*)&server->addr, server->addr_len);
         if(result == -1)
+        {
+            if (sock_get_error(errno) == WSAEINPROGRESS) {
+                struct pollfd pfd;
+                int res;
+
+                pfd.fd = netconn->socketFD;
+                pfd.events = POLLOUT;
+                res = poll(&pfd, 1, timeout);
+                if (!res)
+                {
+                    closesocket(netconn->socketFD);
+                    heap_free(netconn);
+                    return ERROR_INTERNET_CANNOT_CONNECT;
+                }
+                else if (res > 0)
+                {
+                    int err;
+                    socklen_t len = sizeof(err);
+                    if (!getsockopt(netconn->socketFD, SOL_SOCKET, SO_ERROR, &err, &len) && !err)
+                        result = 0;
+                }
+            }
+        }
+        if(result == -1)
             closesocket(netconn->socketFD);
+        else {
+            flag = 0;
+            ioctlsocket(netconn->socketFD, FIONBIO, &flag);
+        }
     }
     if(result == -1) {
         heap_free(netconn);




More information about the wine-cvs mailing list