Browse Source

Add a generic socket connect function from url and port paramters

master
Con Kolivas 11 years ago
parent
commit
e9e62442e7
  1. 2
      configure.ac
  2. 75
      src/libckpool.c
  3. 2
      src/libckpool.h

2
configure.ac

@ -35,7 +35,7 @@ AC_CHECK_HEADERS(stdio.h stdlib.h fcntl.h sys/time.h unistd.h)
AC_CHECK_HEADERS(ctype.h errno.h byteswap.h string.h time.h) AC_CHECK_HEADERS(ctype.h errno.h byteswap.h string.h time.h)
AC_CHECK_HEADERS(endian.h sys/endian.h arpa/inet.h syslog.h) AC_CHECK_HEADERS(endian.h sys/endian.h arpa/inet.h syslog.h)
AC_CHECK_HEADERS(alloca.h pthread.h stdio.h math.h) AC_CHECK_HEADERS(alloca.h pthread.h stdio.h math.h)
AC_CHECK_HEADERS(sys/types.h sys/socket.h) AC_CHECK_HEADERS(sys/types.h sys/socket.h netdb.h)
AC_CHECK_HEADERS(stdint.h netinet/in.h netinet/tcp.h) AC_CHECK_HEADERS(stdint.h netinet/in.h netinet/tcp.h)
PTHREAD_LIBS="-lpthread" PTHREAD_LIBS="-lpthread"

75
src/libckpool.c

@ -11,6 +11,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <netdb.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <netinet/in.h> #include <netinet/in.h>
@ -313,6 +314,80 @@ void block_socket(int fd)
fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
} }
int connect_socket(char *url, char *port)
{
struct addrinfo servinfobase, *servinfo, hints, *p;
int sockd = -1;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
servinfo = &servinfobase;
if (getaddrinfo(url, port, &hints, &servinfo) != 0) {
LOGWARNING("Failed to resolve (?wrong URL) %s:%s", url, port);
goto out;
}
for (p = servinfo; p != NULL; p = p->ai_next) {
sockd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (sockd == -1) {
LOGDEBUG("Failed socket");
continue;
}
/* Iterate non blocking over entries returned by getaddrinfo
* to cope with round robin DNS entries, finding the first one
* we can connect to quickly. */
noblock_socket(sockd);
if (connect(sockd, p->ai_addr, p->ai_addrlen) == -1) {
struct timeval tv_timeout = {1, 0};
int selret;
fd_set rw;
if (!sock_connecting()) {
close(sockd);
LOGDEBUG("Failed sock connect");
continue;
}
retry:
FD_ZERO(&rw);
FD_SET(sockd, &rw);
selret = select(sockd + 1, NULL, &rw, NULL, &tv_timeout);
if (selret > 0 && FD_ISSET(sockd, &rw)) {
socklen_t len;
int err, n;
len = sizeof(err);
n = getsockopt(sockd, SOL_SOCKET, SO_ERROR, (void *)&err, &len);
if (!n && !err) {
LOGDEBUG("Succeeded delayed connect");
block_socket(sockd);
break;
}
}
if (selret < 0 && interrupted())
goto retry;
close(sockd);
sockd = -1;
LOGDEBUG("Select timeout/failed connect");
continue;
}
LOGDEBUG("Succeeded immediate connect");
if (sockd >= 0)
block_socket(sockd);
break;
}
if (p == NULL) {
LOGNOTICE("Failed to connect to %s:%s", url, port);
sockd = -1;
}
freeaddrinfo(servinfo);
out:
return sockd;
}
/* Align a size_t to 4 byte boundaries for fussy arches */ /* Align a size_t to 4 byte boundaries for fussy arches */
void align_len(size_t *len) void align_len(size_t *len)
{ {

2
src/libckpool.h

@ -137,7 +137,7 @@ bool extract_sockaddr(char *url, char **sockaddr_url, char **sockaddr_port);
void keep_sockalive(int fd); void keep_sockalive(int fd);
void noblock_socket(int fd); void noblock_socket(int fd);
void block_socket(int fd); void block_socket(int fd);
bool sock_connecting(void); int connect_socket(char *url, char *port);
void align_len(size_t *len); void align_len(size_t *len);
void __bin2hex(uchar *s, const uchar *p, size_t len); void __bin2hex(uchar *s, const uchar *p, size_t len);

Loading…
Cancel
Save