diff options
-rw-r--r-- | common/sys/net.c | 41 | ||||
-rw-r--r-- | include/cmsys.h | 1 |
2 files changed, 41 insertions, 1 deletions
diff --git a/common/sys/net.c b/common/sys/net.c index 3e65a697..8166ed1d 100644 --- a/common/sys/net.c +++ b/common/sys/net.c @@ -7,6 +7,7 @@ #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> +#include <fcntl.h> #include <ctype.h> #include <assert.h> #include <errno.h> @@ -129,6 +130,11 @@ int tobind(const char * addr) int toconnect(const char *addr) { + return toconnectex(addr, -1); +} + +int toconnectex(const char *addr, int timeout) +{ int sock; assert(addr && *addr); @@ -152,12 +158,20 @@ int toconnect(const char *addr) else { char buf[64], *port; struct sockaddr_in serv_name; + int oflags = 0; if( (sock = socket(PF_INET, SOCK_STREAM, 0)) < 0 ){ perror("socket"); return -1; } + if (timeout > 0) + { + // set to non-block to allow timeout + oflags = fcntl(sock, F_GETFL, NULL); + fcntl(sock, F_SETFL, oflags | O_NONBLOCK); + } + strlcpy(buf, addr, sizeof(buf)); if ( (port = strchr(buf, ':')) != NULL) *port++ = '\0'; @@ -172,10 +186,35 @@ int toconnect(const char *addr) serv_name.sin_port = htons(atoi(port)); serv_name.sin_family = AF_INET; - if( connect(sock, (struct sockaddr*)&serv_name, sizeof(serv_name)) < 0 ){ + while ( connect(sock, (struct sockaddr*)&serv_name, sizeof(serv_name)) < 0 ) + { + if (errno == EINPROGRESS) + { + struct timeval tv = {0}; + fd_set myset; + + assert(timeout > 0); + tv.tv_sec = timeout; // set timeout here + FD_ZERO(&myset); + FD_SET(sock, &myset); + + if (select(sock+1, NULL, &myset, NULL, &tv) > 0) + { + // success + break; + } + } + + // various failure close(sock); return -1; } + + if (timeout > 0) + { + // restore flags + fcntl(sock, F_SETFL, oflags); + } } return sock; diff --git a/include/cmsys.h b/include/cmsys.h index ae7f6347..4574f74b 100644 --- a/include/cmsys.h +++ b/include/cmsys.h @@ -78,6 +78,7 @@ extern uint32_t ipstr2int(const char *ip); extern int tobind (const char *addr); extern int tobindex (const char *addr, int qlen, int (*setsock)(int), int do_listen); extern int toconnect(const char *addr); +extern int toconnectex(const char *addr, int timeout); extern int toread (int fd, void *buf, int len); extern int towrite (int fd, const void *buf, int len); extern int send_remote_fd(int tunnel, int fd); |