Browse Source

@Impelemented timeout functionality, and fixed error handling of fsockopen() on win32

Also fixed error handling on unix (micropatch)

Closes Bug #14740
experimental/new_apache_hooks
Jason Greene 24 years ago
parent
commit
c6a36d585b
  1. 30
      ext/standard/fsock.c
  2. 79
      main/network.c
  3. 5
      main/php_network.h

30
ext/standard/fsock.c

@ -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;
}

79
main/network.c

@ -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:

5
main/php_network.h

@ -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);

Loading…
Cancel
Save