Alien-cares
view release on metacpan or search on metacpan
libcares/ares_process.c view on Meta::CPAN
}
/* For each trip through the entire server list, double the channel's
* assigned timeout, avoiding overflow. If channel->timeout is negative,
* leave it as-is, even though that should be impossible here.
*/
timeplus = channel->timeout;
{
/* How many times do we want to double it? Presume sane values here. */
const int shift = query->try_count / channel->nservers;
/* Is there enough room to shift timeplus left that many times?
*
* To find out, confirm that all of the bits we'll shift away are zero.
* Stop considering a shift if we get to the point where we could shift
* a 1 into the sign bit (i.e. when shift is within two of the bit
* count).
*
* This has the side benefit of leaving negative numbers unchanged.
*/
if(shift <= (int)(sizeof(int) * CHAR_BIT - 1)
&& (timeplus >> (sizeof(int) * CHAR_BIT - 1 - shift)) == 0)
{
timeplus <<= shift;
}
}
query->timeout = *now;
timeadd(&query->timeout, timeplus);
/* Keep track of queries bucketed by timeout, so we can process
* timeout events quickly.
*/
ares__remove_from_list(&(query->queries_by_timeout));
ares__insert_in_list(
&(query->queries_by_timeout),
&(channel->queries_by_timeout[query->timeout.tv_sec %
ARES_TIMEOUT_TABLE_SIZE]));
/* Keep track of queries bucketed by server, so we can process server
* errors quickly.
*/
ares__remove_from_list(&(query->queries_to_server));
ares__insert_in_list(&(query->queries_to_server),
&(server->queries_to_server));
}
/*
* setsocknonblock sets the given socket to either blocking or non-blocking
* mode based on the 'nonblock' boolean argument. This function is highly
* portable.
*/
static int setsocknonblock(ares_socket_t sockfd, /* operate on this */
int nonblock /* TRUE or FALSE */)
{
#if defined(USE_BLOCKING_SOCKETS)
return 0; /* returns success */
#elif defined(HAVE_FCNTL_O_NONBLOCK)
/* most recent unix versions */
int flags;
flags = fcntl(sockfd, F_GETFL, 0);
if (FALSE != nonblock)
return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
else
return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK)); /* LCOV_EXCL_LINE */
#elif defined(HAVE_IOCTL_FIONBIO)
/* older unix versions */
int flags = nonblock ? 1 : 0;
return ioctl(sockfd, FIONBIO, &flags);
#elif defined(HAVE_IOCTLSOCKET_FIONBIO)
#ifdef WATT32
char flags = nonblock ? 1 : 0;
#else
/* Windows */
unsigned long flags = nonblock ? 1UL : 0UL;
#endif
return ioctlsocket(sockfd, FIONBIO, &flags);
#elif defined(HAVE_IOCTLSOCKET_CAMEL_FIONBIO)
/* Amiga */
long flags = nonblock ? 1L : 0L;
return IoctlSocket(sockfd, FIONBIO, flags);
#elif defined(HAVE_SETSOCKOPT_SO_NONBLOCK)
/* BeOS */
long b = nonblock ? 1L : 0L;
return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
#else
# error "no non-blocking method was found/used/set"
#endif
}
static int configure_socket(ares_socket_t s, int family, ares_channel channel)
{
ares_sockaddr local;
/* do not set options for user-managed sockets */
if (channel->sock_funcs)
return 0;
(void)setsocknonblock(s, TRUE);
#if defined(FD_CLOEXEC) && !defined(MSDOS)
/* Configure the socket fd as close-on-exec. */
if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1)
return -1; /* LCOV_EXCL_LINE */
#endif
/* Set the socket's send and receive buffer sizes. */
if ((channel->socket_send_buffer_size > 0) &&
setsockopt(s, SOL_SOCKET, SO_SNDBUF,
(void *)&channel->socket_send_buffer_size,
sizeof(channel->socket_send_buffer_size)) == -1)
return -1;
if ((channel->socket_receive_buffer_size > 0) &&
setsockopt(s, SOL_SOCKET, SO_RCVBUF,
(void *)&channel->socket_receive_buffer_size,
sizeof(channel->socket_receive_buffer_size)) == -1)
return -1;
#ifdef SO_BINDTODEVICE
( run in 0.909 second using v1.01-cache-2.11-cpan-39bf76dae61 )