diff options
Diffstat (limited to 'ares/ares_process.c')
-rw-r--r-- | ares/ares_process.c | 94 |
1 files changed, 71 insertions, 23 deletions
diff --git a/ares/ares_process.c b/ares/ares_process.c index 15d372642..a1e16af28 100644 --- a/ares/ares_process.c +++ b/ares/ares_process.c @@ -466,13 +466,76 @@ void ares__send_query(ares_channel channel, struct query *query, time_t now) } } -static int open_tcp_socket(ares_channel channel, struct server_state *server) +/* + * nonblock() set the given socket to either blocking or non-blocking mode + * based on the 'nonblock' boolean argument. This function is highly portable. + */ +static int nonblock(ares_socket_t sockfd, /* operate on this */ + int nonblock /* TRUE or FALSE */) { -#if defined(WIN32) - u_long flags; -#else +#undef SETBLOCK +#define SETBLOCK 0 +#ifdef HAVE_O_NONBLOCK + /* most recent unix versions */ + int flags; + + flags = fcntl(sockfd, F_GETFL, 0); + if (TRUE == nonblock) + return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); + else + return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK)); +#undef SETBLOCK +#define SETBLOCK 1 +#endif + +#if defined(HAVE_FIONBIO) && (SETBLOCK == 0) + /* older unix versions */ int flags; + + flags = nonblock; + return ioctl(sockfd, FIONBIO, &flags); +#undef SETBLOCK +#define SETBLOCK 2 +#endif + +#if defined(HAVE_IOCTLSOCKET) && (SETBLOCK == 0) + /* Windows? */ + unsigned long flags; + flags = nonblock; + + return ioctlsocket(sockfd, FIONBIO, &flags); +#undef SETBLOCK +#define SETBLOCK 3 +#endif + +#if defined(HAVE_IOCTLSOCKET_CASE) && (SETBLOCK == 0) + /* presumably for Amiga */ + return IoctlSocket(sockfd, FIONBIO, (long)nonblock); +#undef SETBLOCK +#define SETBLOCK 4 +#endif + +#if defined(HAVE_SO_NONBLOCK) && (SETBLOCK == 0) + /* BeOS */ + long b = nonblock ? 1 : 0; + return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b)); +#undef SETBLOCK +#define SETBLOCK 5 +#endif + +#ifdef HAVE_DISABLED_NONBLOCKING + return 0; /* returns success */ +#undef SETBLOCK +#define SETBLOCK 6 +#endif + +#if (SETBLOCK == 0) +#error "no non-blocking method was found/used/set" #endif +} + +static int open_tcp_socket(ares_channel channel, struct server_state *server) +{ ares_socket_t s; struct sockaddr_in sockin; @@ -482,25 +545,7 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server) return -1; /* Set the socket non-blocking. */ - -#if defined(WIN32) || defined(WATT32) - flags = 1; - ioctlsocket(s, FIONBIO, &flags); -#else - flags = fcntl(s, F_GETFL, 0); - - if (flags == -1) - { - closesocket(s); - return -1; - } - flags |= O_NONBLOCK; - if (fcntl(s, F_SETFL, flags) == -1) - { - closesocket(s); - return -1; - } -#endif + nonblock(s, TRUE); /* Connect to the server. */ memset(&sockin, 0, sizeof(sockin)); @@ -531,6 +576,9 @@ static int open_udp_socket(ares_channel channel, struct server_state *server) if (s == ARES_SOCKET_BAD) return -1; + /* Set the socket non-blocking. */ + nonblock(s, TRUE); + /* Connect to the server. */ memset(&sockin, 0, sizeof(sockin)); sockin.sin_family = AF_INET; |