summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWez Furlong <wez@php.net>2002-12-22 13:58:41 +0000
committerWez Furlong <wez@php.net>2002-12-22 13:58:41 +0000
commit17384705d3be9cc92867ce0f8d9ef02805a2f830 (patch)
tree67b5f70f0eed800a00084b84a422f93725dcad14
parent5e489050e18781ebebabe664edc91108f29a7cd2 (diff)
downloadphp-git-17384705d3be9cc92867ce0f8d9ef02805a2f830.tar.gz
MFH:
A Simple fix for Bug #12360 (fsockopen timeout doesn't work). Analysis: On systems with HAVE_GETADDRINFO and IPV6 support, php_hostconnect would attempt to connect to each possible address that matched the requested IP. If the remote host:port combination are dropping packets this would cause the first connection to timeout (after waiting for the full timeout duration). PHP would then attempt the second address and wait the full duration again. Solution: If the first connection attempt times out, abort the connection loop.
-rw-r--r--main/network.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/main/network.c b/main/network.c
index 97b6c57f2d..10b5097ede 100644
--- a/main/network.c
+++ b/main/network.c
@@ -100,9 +100,11 @@ int inet_aton(const char *, struct in_addr *);
#ifdef PHP_WIN32
# define SOCK_ERR INVALID_SOCKET
# define SOCK_CONN_ERR SOCKET_ERROR
+# define PHP_TIMEOUT_ERROR_VALUE WSAETIMEDOUT
#else
# define SOCK_ERR -1
# define SOCK_CONN_ERR -1
+# define PHP_TIMEOUT_ERROR_VALUE ETIMEDOUT
#endif
#ifdef HAVE_GETADDRINFO
@@ -266,6 +268,7 @@ PHPAPI int php_connect_nonb(int sockfd,
int ret = 0;
fd_set rset;
fd_set wset;
+ fd_set eset;
if (timeout == NULL) {
/* blocking mode */
@@ -286,11 +289,13 @@ PHPAPI int php_connect_nonb(int sockfd,
}
FD_ZERO(&rset);
+ FD_ZERO(&eset);
FD_SET(sockfd, &rset);
+ FD_SET(sockfd, &eset);
wset = rset;
- if ((n = select(sockfd + 1, &rset, &wset, NULL, timeout)) == 0) {
+ if ((n = select(sockfd + 1, &rset, &wset, &eset, timeout)) == 0) {
error = ETIMEDOUT;
}
@@ -400,9 +405,7 @@ int php_hostconnect(const char *host, unsigned short port, int socktype, struct
struct sockaddr **sal, **psal;
struct timeval individual_timeout;
int set_timeout = 0;
-#ifdef PHP_WIN32
int err;
-#endif
n = php_network_getaddresses(host, &sal TSRMLS_CC);
@@ -463,10 +466,19 @@ int php_hostconnect(const char *host, unsigned short port, int socktype, struct
#ifdef PHP_WIN32
/* Preserve the last error */
err = WSAGetLastError();
+#else
+ err = errno;
#endif
close (s);
}
sal++;
+
+ if (err == PHP_TIMEOUT_ERROR_VALUE) {
+ /* if the first attempt timed out, it's highly likely
+ * that any subsequent attempts will do so also */
+ break;
+ }
+
}
php_network_freeaddresses(psal);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "php_hostconnect: connect failed");