summaryrefslogtreecommitdiff
path: root/main/network.c
diff options
context:
space:
mode:
authorWez Furlong <wez@php.net>2001-05-05 18:36:22 +0000
committerWez Furlong <wez@php.net>2001-05-05 18:36:22 +0000
commit3ffb8e3800db8733d1bba602200a51a47985c17a (patch)
treece32f12f4ea0cb0ff9aa30bf8a744f5b09062c67 /main/network.c
parentd5763bbdcbb6323aa99392145399deb6f58ec3aa (diff)
downloadphp-git-3ffb8e3800db8733d1bba602200a51a47985c17a.tar.gz
Nuke buffering from php_streams, move connect_nonb() from fsock.c to network.c
and rename to php_connect_nonb(). Use php_connect_nonb() instead of connect() in php_hostconnect() -> timeouts should now work in php_hostconnect(). sock streams abstraction now uses php_sockbuf as the "abstract" pointer.
Diffstat (limited to 'main/network.c')
-rw-r--r--main/network.c128
1 files changed, 108 insertions, 20 deletions
diff --git a/main/network.c b/main/network.c
index 6d1822ad01..b71225dfa0 100644
--- a/main/network.c
+++ b/main/network.c
@@ -185,6 +185,83 @@ static int php_network_getaddresses(const char *host, struct sockaddr ***sal)
return 0;
}
+/* {{{ php_connect_nonb */
+PHPAPI int php_connect_nonb(int sockfd,
+ struct sockaddr *addr,
+ socklen_t addrlen,
+ struct timeval *timeout)
+{
+ /* probably won't work on Win32, someone else might try it (read: fix it ;) */
+
+#if (!defined(__BEOS__) && !defined(PHP_WIN32)) && (defined(O_NONBLOCK) || defined(O_NDELAY))
+
+#ifndef O_NONBLOCK
+#define O_NONBLOCK O_NDELAY
+#endif
+
+ int flags;
+ int n;
+ int error = 0;
+ socklen_t len;
+ int ret = 0;
+ fd_set rset;
+ fd_set wset;
+
+ if (timeout == NULL) {
+ /* blocking mode */
+ return connect(sockfd, addr, addrlen);
+ }
+
+ flags = fcntl(sockfd, F_GETFL, 0);
+ fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
+
+ if ((n = connect(sockfd, addr, addrlen)) < 0) {
+ if (errno != EINPROGRESS) {
+ return -1;
+ }
+ }
+
+ if (n == 0) {
+ goto ok;
+ }
+
+ FD_ZERO(&rset);
+ FD_SET(sockfd, &rset);
+
+ wset = rset;
+
+ if ((n = select(sockfd + 1, &rset, &wset, NULL, timeout)) == 0) {
+ error = ETIMEDOUT;
+ }
+
+ if(FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {
+ len = sizeof(error);
+ /*
+ BSD-derived systems set errno correctly
+ Solaris returns -1 from getsockopt in case of error
+ */
+ if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
+ ret = -1;
+ }
+ } else {
+ /* whoops: sockfd has disappeared */
+ ret = -1;
+ }
+
+ok:
+ fcntl(sockfd, F_SETFL, flags);
+
+ if(error) {
+ errno = error;
+ ret = -1;
+ }
+ return ret;
+#else /* !defined(PHP_WIN32) && ... */
+ return connect(sockfd, addr, addrlen);
+#endif
+}
+/* }}} */
+
/*
* Creates a socket of type socktype and connects to the given host and
* port, returns the created socket on success, else returns -1.
@@ -194,38 +271,48 @@ int php_hostconnect(char *host, unsigned short port, int socktype, int timeout)
{
int s;
struct sockaddr **sal, **psal;
-
+ struct timeval timeoutval;
+
if (php_network_getaddresses(host, &sal))
return -1;
+ if (timeout) {
+ timeoutval.tv_sec = timeout;
+ timeoutval.tv_usec = 0;
+ }
+
psal = sal;
while (*sal != NULL) {
s = socket((*sal)->sa_family, socktype, 0);
if (s != SOCK_ERR) {
switch ((*sal)->sa_family) {
#if defined( HAVE_GETADDRINFO ) && defined( HAVE_IPV6 )
- case AF_INET6: {
- struct sockaddr_in6 *sa =
- (struct sockaddr_in6 *)*sal;
-
- sa->sin6_family = (*sal)->sa_family;
- sa->sin6_port = htons(port);
- if (connect(s, (struct sockaddr *) sa,
- sizeof(*sa)) != SOCK_CONN_ERR)
- goto ok;
- } break;
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sa =
+ (struct sockaddr_in6 *)*sal;
+
+ sa->sin6_family = (*sal)->sa_family;
+ sa->sin6_port = htons(port);
+ if (php_connect_nonb(s, (struct sockaddr *) sa,
+ sizeof(*sa), timeout ? &timeoutval : NULL) != SOCK_CONN_ERR)
+ goto ok;
+ }
+ break;
#endif
- case AF_INET: {
- struct sockaddr_in *sa =
- (struct sockaddr_in *)*sal;
+ case AF_INET:
+ {
+ struct sockaddr_in *sa =
+ (struct sockaddr_in *)*sal;
- sa->sin_family = (*sal)->sa_family;
- sa->sin_port = htons(port);
- if (connect(s, (struct sockaddr *) sa,
- sizeof(*sa)) != SOCK_CONN_ERR)
- goto ok;
+ sa->sin_family = (*sal)->sa_family;
+ sa->sin_port = htons(port);
+ if (php_connect_nonb(s, (struct sockaddr *) sa,
+ sizeof(*sa), timeout ? &timeoutval : NULL) != SOCK_CONN_ERR)
+ goto ok;
- } break;
+ }
+ break;
}
close (s);
}
@@ -245,4 +332,5 @@ int php_hostconnect(char *host, unsigned short port, int socktype, int timeout)
* tab-width: 8
* c-basic-offset: 8
* End:
+ * vim: ts=4 sw=4 tw=78
*/