summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLars-Dominik Braun <lars@6xq.net>2013-08-08 17:35:33 +0200
committerLars-Dominik Braun <lars@6xq.net>2013-08-08 20:28:57 +0200
commitf1ddd582ba5c314202fbed98d7aa491b06b2dee2 (patch)
tree44fe9d26d77c8f18ea8b1732923ea32cb079f252 /src
parentee2e73cd7b5a1de68c8316e916c4ef3a88302bed (diff)
downloadpianobar-f1ddd582ba5c314202fbed98d7aa491b06b2dee2.tar.gz
pianobar-f1ddd582ba5c314202fbed98d7aa491b06b2dee2.tar.bz2
pianobar-f1ddd582ba5c314202fbed98d7aa491b06b2dee2.zip
waitress: Try all addresses returned by getaddrinfo
Fixes issue #384.
Diffstat (limited to 'src')
-rw-r--r--src/libwaitress/waitress.c83
1 files changed, 51 insertions, 32 deletions
diff --git a/src/libwaitress/waitress.c b/src/libwaitress/waitress.c
index 771c54f..800b9d0 100644
--- a/src/libwaitress/waitress.c
+++ b/src/libwaitress/waitress.c
@@ -770,8 +770,8 @@ static WaitressReturn_t WaitressTlsVerify (const WaitressHandle_t *waith) {
/* Connect to server
*/
static WaitressReturn_t WaitressConnect (WaitressHandle_t *waith) {
- struct addrinfo hints, *res;
- int pollres;
+ WaitressReturn_t ret;
+ struct addrinfo hints, *gares;
memset (&hints, 0, sizeof hints);
@@ -781,47 +781,66 @@ static WaitressReturn_t WaitressConnect (WaitressHandle_t *waith) {
/* Use proxy? */
if (WaitressProxyEnabled (waith)) {
if (getaddrinfo (waith->proxy.host,
- WaitressDefaultPort (&waith->proxy), &hints, &res) != 0) {
+ WaitressDefaultPort (&waith->proxy), &hints, &gares) != 0) {
return WAITRESS_RET_GETADDR_ERR;
}
} else {
if (getaddrinfo (waith->url.host,
- WaitressDefaultPort (&waith->url), &hints, &res) != 0) {
+ WaitressDefaultPort (&waith->url), &hints, &gares) != 0) {
return WAITRESS_RET_GETADDR_ERR;
}
}
- if ((waith->request.sockfd = socket (res->ai_family, res->ai_socktype,
- res->ai_protocol)) == -1) {
- freeaddrinfo (res);
- return WAITRESS_RET_SOCK_ERR;
- }
-
- /* we need shorter timeouts for connect() */
- fcntl (waith->request.sockfd, F_SETFL, O_NONBLOCK);
+ /* try all addresses */
+ for (struct addrinfo *gacurr = gares; gacurr != NULL;
+ gacurr = gacurr->ai_next) {
+ int sock = -1;
- /* increase socket receive buffer */
- const int sockopt = 256*1024;
- setsockopt (waith->request.sockfd, SOL_SOCKET, SO_RCVBUF, &sockopt,
- sizeof (sockopt));
+ ret = WAITRESS_RET_OK;
- /* non-blocking connect will return immediately */
- connect (waith->request.sockfd, res->ai_addr, res->ai_addrlen);
-
- pollres = WaitressPollLoop (waith->request.sockfd, POLLOUT,
- waith->timeout);
- freeaddrinfo (res);
- if (pollres == 0) {
- return WAITRESS_RET_TIMEOUT;
- } else if (pollres == -1) {
- return WAITRESS_RET_ERR;
+ if ((sock = socket (gacurr->ai_family, gacurr->ai_socktype,
+ gacurr->ai_protocol)) == -1) {
+ ret = WAITRESS_RET_SOCK_ERR;
+ } else {
+ int pollres;
+
+ /* we need shorter timeouts for connect() */
+ fcntl (sock, F_SETFL, O_NONBLOCK);
+
+ /* increase socket receive buffer */
+ const int sockopt = 256*1024;
+ setsockopt (sock, SOL_SOCKET, SO_RCVBUF, &sockopt,
+ sizeof (sockopt));
+
+ /* non-blocking connect will return immediately */
+ connect (sock, gacurr->ai_addr, gacurr->ai_addrlen);
+
+ pollres = WaitressPollLoop (sock, POLLOUT, waith->timeout);
+ if (pollres == 0) {
+ ret = WAITRESS_RET_TIMEOUT;
+ } else if (pollres == -1) {
+ ret = WAITRESS_RET_ERR;
+ } else {
+ /* check connect () return value */
+ socklen_t pollresSize = sizeof (pollres);
+ getsockopt (sock, SOL_SOCKET, SO_ERROR, &pollres,
+ &pollresSize);
+ if (pollres != 0) {
+ ret = WAITRESS_RET_CONNECT_REFUSED;
+ } else {
+ /* this one is working */
+ waith->request.sockfd = sock;
+ break;
+ }
+ }
+ close (sock);
+ }
}
- /* check connect () return value */
- socklen_t pollresSize = sizeof (pollres);
- getsockopt (waith->request.sockfd, SOL_SOCKET, SO_ERROR, &pollres,
- &pollresSize);
- if (pollres != 0) {
- return WAITRESS_RET_CONNECT_REFUSED;
+
+ freeaddrinfo (gares);
+ /* could not connect to any of the addresses */
+ if (ret != WAITRESS_RET_OK) {
+ return ret;
}
if (waith->url.tls) {