Commit 61366214 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Back in the mists of time, the SocketWizards were so happy to get

any connections at all, that they didn't even consider that maybe
connect(2) should have a timeout argument.

Add TCP_connect() which addresses this shortcoming, using what I
belive is a widely supported workaround.

Not to POSIX: please fix.



git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@2641 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 9636296d
......@@ -46,5 +46,8 @@ void TCP_myname(int sock, char *abuf, unsigned alen, char *pbuf, unsigned plen);
int TCP_filter_http(int sock);
void TCP_blocking(int sock);
void TCP_nonblocking(int sock);
#ifdef SOL_SOCKET
int TCP_connect(int s, const struct sockaddr *name, socklen_t namelen, int msec);
#endif
#define TRUST_ME(ptr) ((void*)(uintptr_t)(ptr))
......@@ -39,6 +39,7 @@
#include <errno.h>
#include <sys/ioctl.h>
#include <netdb.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
......@@ -138,3 +139,55 @@ TCP_nonblocking(int sock)
i = 1;
AZ(ioctl(sock, FIONBIO, &i));
}
/*--------------------------------------------------------------------
* On TCP a connect(2) can block for a looong time, and we don't want that.
* Unfortunately, the SocketWizards back in those days were happy to wait
* any amount of time for a connection, so the connect(2) syscall does not
* take an argument for patience.
*
* There is a little used work-around, and we employ it at our peril.
*
*/
int
TCP_connect(int s, const struct sockaddr *name, socklen_t namelen, int msec)
{
int i, k;
socklen_t l;
struct pollfd fds[1];
assert(s >= 0);
/* Set the socket non-blocking */
TCP_nonblocking(s);
/* Attempt the connect */
i = connect(s, name, namelen);
if (i == 0 || errno != EINPROGRESS)
return (i);
/* Exercise our patience, polling for write */
fds[0].fd = s;
fds[0].events = POLLWRNORM;
fds[0].revents = 0;
i = poll(fds, 1, msec);
if (i == 0) {
/* Timeout, close and give up */
errno = ETIMEDOUT;
return (-1);
}
/* Find out if we got a connection */
l = sizeof k;
AZ(getsockopt(s, SOL_SOCKET, SO_ERROR, &k, &l));
/* An error means no connection established */
errno = k;
if (k)
return (-1);
TCP_blocking(s);
return (0);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment