hostconnect now divides the timeout with no. of addresses. If a connection

attempt times out, it goes on to the next. Unless each timeout would be
<5s. Added php_any_addr() that fills out the any address for IPv6 and IPv4.
This commit is contained in:
Stig Venaas 2002-01-06 22:45:43 +00:00
parent b9355b9a11
commit a6ec8d37e6
2 changed files with 52 additions and 13 deletions

View file

@ -130,30 +130,31 @@ static void php_network_freeaddresses(struct sockaddr **sal)
/* }}} */
/* {{{ php_network_getaddresses
* Returns number of addresses, 0 for none/error
*/
static int php_network_getaddresses(const char *host, struct sockaddr ***sal)
{
struct sockaddr **sap;
int n;
if (host == NULL) {
return -1;
return 0;
}
{
#ifdef HAVE_GETADDRINFO
struct addrinfo hints, *res, *sai;
int n;
memset(&hints, '\0', sizeof(hints));
hints.ai_family = AF_UNSPEC;
if ((n = getaddrinfo(host, NULL, &hints, &res))) {
php_error(E_WARNING, "php_network_getaddresses: getaddrinfo failed: %s", PHP_GAI_STRERROR(n));
return -1;
return 0;
}
sai = res;
for (n=2; (sai = sai->ai_next) != NULL; n++);
*sal = emalloc(n * sizeof(*sal));
for (n = 1; (sai = sai->ai_next) != NULL; n++);
*sal = emalloc((n + 1) * sizeof(*sal));
sai = res;
sap = *sal;
do {
@ -184,7 +185,7 @@ static int php_network_getaddresses(const char *host, struct sockaddr ***sal)
host_info = gethostbyname(host);
if (host_info == NULL) {
php_error(E_WARNING, "php_network_getaddresses: gethostbyname failed");
return -1;
return 0;
}
in = *((struct in_addr *) host_info->h_addr);
}
@ -195,10 +196,11 @@ static int php_network_getaddresses(const char *host, struct sockaddr ***sal)
(*sap)->sa_family = AF_INET;
((struct sockaddr_in *)*sap)->sin_addr = in;
sap++;
n = 1;
#endif
}
*sap = NULL;
return 0;
return n;
}
/* }}} */
@ -286,18 +288,23 @@ ok:
*/
int php_hostconnect(const char *host, unsigned short port, int socktype, int timeout)
{
int s;
int n, repeatto, s;
struct sockaddr **sal, **psal;
struct timeval timeoutval;
if (php_network_getaddresses(host, &sal))
n = php_network_getaddresses(host, &sal);
if (n == 0)
return -1;
if (timeout) {
timeoutval.tv_sec = timeout;
timeoutval.tv_usec = 0;
/* is this a good idea? 5s? */
repeatto = timeout / n > 5;
if (repeatto) {
timeout /= n;
}
timeoutval.tv_sec = timeout;
timeoutval.tv_usec = 0;
psal = sal;
while (*sal != NULL) {
s = socket((*sal)->sa_family, socktype, 0);
@ -334,6 +341,10 @@ int php_hostconnect(const char *host, unsigned short port, int socktype, int tim
close (s);
}
sal++;
if (repeatto) {
timeoutval.tv_sec = timeout;
timeoutval.tv_usec = 0;
}
}
php_network_freeaddresses(psal);
php_error(E_WARNING, "php_hostconnect: connect failed");
@ -345,6 +356,33 @@ int php_hostconnect(const char *host, unsigned short port, int socktype, int tim
}
/* }}} */
/* {{{ php_any_addr
* Fills the any (wildcard) address into php_sockaddr_storage
*/
void php_any_addr(int family, php_sockaddr_storage *addr, unsigned short port)
{
memset(addr, 0, sizeof(php_sockaddr_storage));
switch (family) {
#ifdef HAVE_IPV6
case AF_INET6: {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) addr;
sin6->sin6_family = AF_INET6;
sin6->sin6_port = htons(port);
sin6->sin6_addr = in6addr_any;
break;
}
#endif
case AF_INET: {
struct sockaddr_in *sin = (struct sockaddr_in *) addr;
sin->sin_family = AF_INET;
sin->sin_port = htons(port);
sin->sin_addr.s_addr = INADDR_ANY;
break;
}
}
}
/* }}} */
/*
* Local variables:
* tab-width: 8

View file

@ -53,6 +53,7 @@ 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);
void php_any_addr(int family, php_sockaddr_storage *addr, unsigned short port);
#endif /* _PHP_NETWORK_H */