diff options
author | Alan Antonuk <alan.antonuk@gmail.com> | 2012-06-18 16:31:22 -0700 |
---|---|---|
committer | Alan Antonuk <alan.antonuk@gmail.com> | 2012-06-18 16:31:22 -0700 |
commit | 83c5c6a20b912460980e8f2da1b86e8e49df0694 (patch) | |
tree | 55bbb695a0075a3fdb1d0be6a0b9b4f4d3e14417 | |
parent | 5e2f6de43bb1f9e501e88bccb98ba84876f2129c (diff) | |
parent | 1a70fb073880b2c262c001a7d8a297b55593caaf (diff) | |
download | rabbitmq-c-github-ask-83c5c6a20b912460980e8f2da1b86e8e49df0694.tar.gz |
Merge pull request #26 from alanxz/ipv6_support
IPv6 Support
-rw-r--r-- | librabbitmq/amqp_socket.c | 81 | ||||
-rw-r--r-- | librabbitmq/win32/socket.h | 1 |
2 files changed, 55 insertions, 27 deletions
diff --git a/librabbitmq/amqp_socket.c b/librabbitmq/amqp_socket.c index 2034f17..604e32d 100644 --- a/librabbitmq/amqp_socket.c +++ b/librabbitmq/amqp_socket.c @@ -45,44 +45,71 @@ int amqp_open_socket(char const *hostname, int portnumber) { - int sockfd, res; - struct sockaddr_in addr; - struct hostent *he; - int one = 1; /* used as a buffer by setsockopt below */ + struct addrinfo hint; + struct addrinfo *address_list; + struct addrinfo *addr; + char portnumber_string[33]; + int sockfd = -1; + int last_error = 0; + int one = 1; /* for setsockopt */ - res = amqp_socket_init(); - if (res) - return res; + if (0 != (last_error = amqp_socket_init())) + return last_error; - he = gethostbyname(hostname); - if (he == NULL) - return -ERROR_GETHOSTBYNAME_FAILED; + memset(&hint, 0, sizeof(hint)); + hint.ai_family = PF_UNSPEC; /* PF_INET or PF_INET6 */ + hint.ai_socktype = SOCK_STREAM; + hint.ai_protocol = IPPROTO_TCP; - addr.sin_family = AF_INET; - addr.sin_port = htons(portnumber); - addr.sin_addr.s_addr = * (uint32_t *) he->h_addr_list[0]; + (void)sprintf(portnumber_string, "%d", portnumber); - sockfd = socket(PF_INET, SOCK_STREAM, 0); - if (sockfd == -1) - return -amqp_socket_error(); + last_error = getaddrinfo(hostname, portnumber_string, &hint, &address_list); -#ifdef DISABLE_SIGPIPE_WITH_SETSOCKOPT - if (0 != amqp_socket_setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &one, - sizeof(one))) + if (last_error != 0) { - return -amqp_socket_error(); + return -ERROR_GETHOSTBYNAME_FAILED; } -#endif - if (amqp_socket_setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &one, - sizeof(one)) < 0 - || connect(sockfd, (struct sockaddr *) &addr, sizeof(addr)) < 0) + for (addr = address_list; addr; addr = addr->ai_next) { - res = -amqp_socket_error(); - amqp_socket_close(sockfd); - return res; + /* + This cast is to squash warnings on Win64, see: + http://stackoverflow.com/questions/1953639/is-it-safe-to-cast-socket-to-int-under-win64 + */ + sockfd = (int)socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); + if (-1 == sockfd) + { + last_error = -amqp_socket_error(); + continue; + } +#if DISABLE_SIGPIPE_WITH_SETSOCKOPT + if (0 != amqp_socket_setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(one))) + { + last_error = -amqp_socket_error(); + amqp_socket_close(sockfd); + continue; + } +#endif /* DISABLE_SIGPIPE_WITH_SETSOCKOPT */ + if (0 != amqp_socket_setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)) + || 0 != connect(sockfd, addr->ai_addr, addr->ai_addrlen)) + { + last_error = -amqp_socket_error(); + amqp_socket_close(sockfd); + continue; + } + else + { + last_error = 0; + break; + } } + freeaddrinfo(address_list); + if (last_error != 0) + { + return last_error; + } + return sockfd; } diff --git a/librabbitmq/win32/socket.h b/librabbitmq/win32/socket.h index 3b9c452..bfd717c 100644 --- a/librabbitmq/win32/socket.h +++ b/librabbitmq/win32/socket.h @@ -34,6 +34,7 @@ */ #include <winsock2.h> +#include <WS2tcpip.h> /* same as WSABUF */ struct iovec { |