]> granicus.if.org Git - php/commitdiff
@Impelemented timeout functionality, and fixed error handling of fsockopen() on win32
authorJason Greene <jason@php.net>
Tue, 11 Jun 2002 03:55:28 +0000 (03:55 +0000)
committerJason Greene <jason@php.net>
Tue, 11 Jun 2002 03:55:28 +0000 (03:55 +0000)
Also fixed error handling on unix (micropatch)

Closes Bug #14740

ext/standard/fsock.c
main/network.c
main/php_network.h

index 9d90788298352bbf17de6f1a6e8195f5bdadc800..7b57267e2d48d170c3883f4cf6b2852f3161ffe8 100644 (file)
@@ -121,6 +121,7 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
        char *host;
        int host_len;
        int port = -1;
+       int err;
        zval *zerrno = NULL, *zerrstr = NULL;
        double timeout = 60;
        unsigned long conv;
@@ -152,7 +153,7 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
                zval_dtor(zerrno);
                ZVAL_LONG(zerrno, 0);
        }
-       if (zerrstr)    {
+       if (zerrstr) {
                zval_dtor(zerrstr);
                ZVAL_STRING(zerrno, "", 1);
        }
@@ -192,6 +193,10 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
                else
 #endif
                stream = php_stream_sock_open_host(host, (unsigned short)port, socktype, (int)timeout, persistent);
+#ifdef PHP_WIN32
+               /* Preserve error */
+               err = WSAGetLastError();
+#endif
 
                if (stream == NULL) {
                        zend_error(E_WARNING, "%s(): unable to connect to %s:%d", 
@@ -227,15 +232,32 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
        efree(hashkey);
        
        if (stream == NULL)     {
-               if (zerrno)     {
+               if (zerrno) {
                        zval_dtor(zerrno);
+#ifndef PHP_WIN32
                        ZVAL_LONG(zerrno, errno);
+#else
+                       ZVAL_LONG(zerrno, err);
+#endif
                }
-               if (zerrstr)    {
+#ifndef PHP_WIN32
+               if (zerrstr) {
                        zval_dtor(zerrstr);
-                       ZVAL_STRING(zerrno, strerror(errno), 1);
+                       ZVAL_STRING(zerrstr, strerror(errno), 1);
                }
+#else
+               if (zerrstr) {
+                       char *buf;
 
+                       if (! FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, 
+                                       Z_LVAL_P(zerrno), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&buf, 0, NULL)) {
+                               RETURN_FALSE;
+                       }
+
+                       ZVAL_STRING(zerrstr, buf, 1);
+                       LocalFree(buf);
+               }
+#endif
                RETURN_FALSE;
        }
                
index 54b3cb089234811a09b274b7b9a86195db32b276..4022601feb388c144988e4267df52a329acbc6d7 100644 (file)
@@ -289,11 +289,78 @@ ok:
        }
        return ret;
 #else /* !defined(PHP_WIN32) && ... */
+#ifdef PHP_WIN32
+       return php_connect_nonb_win32((SOCKET) sockfd, addr, addrlen, timeout);
+#endif
        return connect(sockfd, addr, addrlen);
 #endif
 }
 /* }}} */
 
+#ifdef PHP_WIN32
+/* {{{ php_connect_nonb_win32 */
+PHPAPI int php_connect_nonb_win32(SOCKET sockfd,
+                                               const struct sockaddr *addr,
+                                               socklen_t addrlen,
+                                               struct timeval *timeout)
+{
+       int error = 0, error_len, ret;
+       u_long non_block = TRUE, block = FALSE;
+
+       fd_set rset, wset;
+
+       if (timeout == NULL)    {
+               /* blocking mode */
+               return connect(sockfd, addr, addrlen);
+       }
+       
+       /* Set the socket to be non-blocking */
+       ioctlsocket(sockfd, FIONBIO, &non_block);
+
+       if (connect(sockfd, addr, addrlen) == SOCKET_ERROR) {
+               if (WSAGetLastError() != WSAEWOULDBLOCK) {
+                       return SOCKET_ERROR;
+               }
+       }
+
+       FD_ZERO(&rset);
+       FD_SET(sockfd, &rset);
+
+       FD_ZERO(&wset);
+       FD_SET(sockfd, &wset);
+
+       if ((ret = select(sockfd + 1, &rset, &wset, NULL, timeout)) == 0) {
+               WSASetLastError(WSAETIMEDOUT);
+               return SOCKET_ERROR;
+       }
+
+       if (ret == SOCKET_ERROR) {
+               return SOCKET_ERROR;
+       }
+
+       if(FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {
+               error_len = sizeof(error);
+               if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char *) &error, &error_len) == SOCKET_ERROR) {
+                       return SOCKET_ERROR;
+               }
+       } else {
+               /* whoops: sockfd has disappeared */
+               return SOCKET_ERROR;
+       }
+
+       /* Set the socket back to blocking */
+       ioctlsocket(sockfd, FIONBIO, &block);
+
+       if (error) { 
+               WSASetLastError(error);
+               return SOCKET_ERROR;
+       }
+
+       return 0;
+}
+/* }}} */
+#endif
+
 /* {{{ php_hostconnect
  * Creates a socket of type socktype and connects to the given host and
  * port, returns the created socket on success, else returns -1.
@@ -301,7 +368,7 @@ ok:
  */
 int php_hostconnect(const char *host, unsigned short port, int socktype, int timeout)
 {      
-       int n, repeatto, s;
+       int n, repeatto, s, err;
        struct sockaddr **sal, **psal;
        struct timeval timeoutval;
        
@@ -351,6 +418,10 @@ int php_hostconnect(const char *host, unsigned short port, int socktype, int tim
                                        } 
                                        break;
                        }
+#ifdef PHP_WIN32
+                       /* Preserve the last error */
+                       err = WSAGetLastError();
+#endif
                        close (s);
                }
                sal++;
@@ -361,6 +432,12 @@ int php_hostconnect(const char *host, unsigned short port, int socktype, int tim
        }
        php_network_freeaddresses(psal);
        php_error(E_WARNING, "php_hostconnect: connect failed");
+
+#ifdef PHP_WIN32
+       /* Restore the last error */
+       WSASetLastError(err);
+#endif 
+
        return -1;
 
  ok:
index 37e0a1add572ac647af0ea64022028dbd665ae22..8e67f7ead848fd7e506a3c6ea2ef8482b21ac814 100644 (file)
@@ -87,6 +87,11 @@ typedef struct {
 
 int php_hostconnect(const char *host, unsigned short port, int socktype, int timeout);
 PHPAPI int php_connect_nonb(int sockfd, const struct sockaddr *addr, socklen_t addrlen, struct timeval *timeout);
+
+#ifdef PHP_WIN32
+PHPAPI int php_connect_nonb_win32(SOCKET sockfd, const struct sockaddr *addr, socklen_t addrlen, struct timeval *timeout);
+#endif
+
 void php_any_addr(int family, php_sockaddr_storage *addr, unsigned short port);
 int php_sockaddr_size(php_sockaddr_storage *addr);