/*
- * "$Id$"
- *
* HTTP address list routines for CUPS.
*
- * Copyright 2007-2014 by Apple Inc.
+ * Copyright 2007-2016 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
/*
* 'httpAddrConnect()' - Connect to any of the addresses in the list.
*
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
*/
http_addrlist_t * /* O - Connected address or NULL on failure */
* 'httpAddrConnect2()' - Connect to any of the addresses in the list with a
* timeout and optional cancel.
*
- * @since CUPS 1.7/OS X 10.9@
+ * @since CUPS 1.7/macOS 10.9@
*/
http_addrlist_t * /* O - Connected address or NULL on failure */
{
int val; /* Socket option value */
#ifdef O_NONBLOCK
- socklen_t len; /* Length of value */
- http_addr_t peer; /* Peer address */
int flags, /* Socket flags */
remaining; /* Remaining timeout */
int i, /* Looping var */
# endif /* HAVE_POLL */
#endif /* O_NONBLOCK */
#ifdef DEBUG
+ socklen_t len; /* Length of value */
+ http_addr_t peer; /* Peer address */
char temp[256]; /* Temporary address string */
#endif /* DEBUG */
* Loop through each address until we connect or run out of addresses...
*/
- for (nfds = 0; addrlist && nfds < (int)(sizeof(fds) / sizeof(fds[0])); addrlist = addrlist->next)
+ nfds = 0;
+ remaining = msec;
+
+ while (remaining > 0)
{
if (cancel && *cancel)
{
return (NULL);
}
- /*
- * Create the socket...
- */
-
- DEBUG_printf(("2httpAddrConnect2: Trying %s:%d...", httpAddrString(&(addrlist->addr), temp, sizeof(temp)), httpAddrPort(&(addrlist->addr))));
-
- if ((fds[nfds] = (int)socket(httpAddrFamily(&(addrlist->addr)), SOCK_STREAM, 0)) < 0)
+ if (addrlist && nfds < (int)(sizeof(fds) / sizeof(fds[0])))
{
/*
- * Don't abort yet, as this could just be an issue with the local
- * system not being configured with IPv4/IPv6/domain socket enabled...
+ * Create the socket...
*/
- continue;
- }
+ DEBUG_printf(("2httpAddrConnect2: Trying %s:%d...", httpAddrString(&(addrlist->addr), temp, sizeof(temp)), httpAddrPort(&(addrlist->addr))));
- /*
- * Set options...
- */
+ if ((fds[nfds] = (int)socket(httpAddrFamily(&(addrlist->addr)), SOCK_STREAM, 0)) < 0)
+ {
+ /*
+ * Don't abort yet, as this could just be an issue with the local
+ * system not being configured with IPv4/IPv6/domain socket enabled.
+ *
+ * Just skip this address...
+ */
+
+ addrlist = addrlist->next;
+ continue;
+ }
- val = 1;
- setsockopt(fds[nfds], SOL_SOCKET, SO_REUSEADDR, CUPS_SOCAST &val, sizeof(val));
+ /*
+ * Set options...
+ */
+
+ val = 1;
+ setsockopt(fds[nfds], SOL_SOCKET, SO_REUSEADDR, CUPS_SOCAST &val, sizeof(val));
#ifdef SO_REUSEPORT
- val = 1;
- setsockopt(fds[nfds], SOL_SOCKET, SO_REUSEPORT, CUPS_SOCAST &val, sizeof(val));
+ val = 1;
+ setsockopt(fds[nfds], SOL_SOCKET, SO_REUSEPORT, CUPS_SOCAST &val, sizeof(val));
#endif /* SO_REUSEPORT */
#ifdef SO_NOSIGPIPE
- val = 1;
- setsockopt(fds[nfds], SOL_SOCKET, SO_NOSIGPIPE, CUPS_SOCAST &val, sizeof(val));
+ val = 1;
+ setsockopt(fds[nfds], SOL_SOCKET, SO_NOSIGPIPE, CUPS_SOCAST &val, sizeof(val));
#endif /* SO_NOSIGPIPE */
- /*
- * Using TCP_NODELAY improves responsiveness, especially on systems
- * with a slow loopback interface...
- */
+ /*
+ * Using TCP_NODELAY improves responsiveness, especially on systems
+ * with a slow loopback interface...
+ */
- val = 1;
- setsockopt(fds[nfds], IPPROTO_TCP, TCP_NODELAY, CUPS_SOCAST &val, sizeof(val));
+ val = 1;
+ setsockopt(fds[nfds], IPPROTO_TCP, TCP_NODELAY, CUPS_SOCAST &val, sizeof(val));
#ifdef FD_CLOEXEC
- /*
- * Close this socket when starting another process...
- */
+ /*
+ * Close this socket when starting another process...
+ */
- fcntl(fds[nfds], F_SETFD, FD_CLOEXEC);
+ fcntl(fds[nfds], F_SETFD, FD_CLOEXEC);
#endif /* FD_CLOEXEC */
#ifdef O_NONBLOCK
- /*
- * Do an asynchronous connect by setting the socket non-blocking...
- */
+ /*
+ * Do an asynchronous connect by setting the socket non-blocking...
+ */
- DEBUG_printf(("httpAddrConnect2: Setting non-blocking connect()"));
+ DEBUG_printf(("httpAddrConnect2: Setting non-blocking connect()"));
- flags = fcntl(fds[nfds], F_GETFL, 0);
- fcntl(fds[nfds], F_SETFL, flags | O_NONBLOCK);
+ flags = fcntl(fds[nfds], F_GETFL, 0);
+ fcntl(fds[nfds], F_SETFL, flags | O_NONBLOCK);
#endif /* O_NONBLOCK */
- /*
- * Then connect...
- */
+ /*
+ * Then connect...
+ */
- if (!connect(fds[nfds], &(addrlist->addr.addr), (socklen_t)httpAddrLength(&(addrlist->addr))))
- {
- DEBUG_printf(("1httpAddrConnect2: Connected to %s:%d...", httpAddrString(&(addrlist->addr), temp, sizeof(temp)), httpAddrPort(&(addrlist->addr))));
+ if (!connect(fds[nfds], &(addrlist->addr.addr), (socklen_t)httpAddrLength(&(addrlist->addr))))
+ {
+ DEBUG_printf(("1httpAddrConnect2: Connected to %s:%d...", httpAddrString(&(addrlist->addr), temp, sizeof(temp)), httpAddrPort(&(addrlist->addr))));
#ifdef O_NONBLOCK
- fcntl(fds[nfds], F_SETFL, flags);
+ fcntl(fds[nfds], F_SETFL, flags);
#endif /* O_NONBLOCK */
- *sock = fds[nfds];
+ *sock = fds[nfds];
- while (nfds > 0)
- {
- nfds --;
- httpAddrClose(NULL, fds[nfds]);
- }
+ while (nfds > 0)
+ {
+ nfds --;
+ httpAddrClose(NULL, fds[nfds]);
+ }
- return (addrlist);
- }
+ return (addrlist);
+ }
#ifdef WIN32
- if (WSAGetLastError() != WSAEINPROGRESS && WSAGetLastError() != WSAEWOULDBLOCK)
+ if (WSAGetLastError() != WSAEINPROGRESS && WSAGetLastError() != WSAEWOULDBLOCK)
#else
- if (errno != EINPROGRESS && errno != EWOULDBLOCK)
+ if (errno != EINPROGRESS && errno != EWOULDBLOCK)
#endif /* WIN32 */
- {
- DEBUG_printf(("1httpAddrConnect2: Unable to connect to %s:%d: %s", httpAddrString(&(addrlist->addr), temp, sizeof(temp)), httpAddrPort(&(addrlist->addr)), strerror(errno)));
- httpAddrClose(NULL, fds[nfds]);
- continue;
- }
+ {
+ DEBUG_printf(("1httpAddrConnect2: Unable to connect to %s:%d: %s", httpAddrString(&(addrlist->addr), temp, sizeof(temp)), httpAddrPort(&(addrlist->addr)), strerror(errno)));
+ httpAddrClose(NULL, fds[nfds]);
+ addrlist = addrlist->next;
+ continue;
+ }
- fcntl(fds[nfds], F_SETFL, flags);
+ fcntl(fds[nfds], F_SETFL, flags);
#ifndef HAVE_POLL
- if (fds[nfds] > max_fd)
- max_fd = fds[nfds];
+ if (fds[nfds] > max_fd)
+ max_fd = fds[nfds];
#endif /* !HAVE_POLL */
- addrs[nfds] = addrlist;
- nfds ++;
- }
+ addrs[nfds] = addrlist;
+ nfds ++;
+ addrlist = addrlist->next;
+ }
+
+ /*
+ * See if we can connect to any of the addresses so far...
+ */
#ifdef O_NONBLOCK
- DEBUG_puts("1httpAddrConnect2: Finishing async connect()");
+ DEBUG_puts("1httpAddrConnect2: Finishing async connect()");
- for (remaining = msec; remaining > 0; remaining -= 250)
- {
do
{
if (cancel && *cancel)
# ifdef HAVE_POLL
for (i = 0; i < nfds; i ++)
{
- pfds[i].fd = fds[i];
- pfds[i].events = POLLIN | POLLOUT;
+ pfds[i].fd = fds[i];
+ pfds[i].events = POLLIN | POLLOUT;
}
- result = poll(pfds, (nfds_t)nfds, remaining > 250 ? 250 : remaining);
+ result = poll(pfds, (nfds_t)nfds, addrlist ? 100 : remaining > 250 ? 250 : remaining);
DEBUG_printf(("1httpAddrConnect2: poll() returned %d (%d)", result, errno));
# else
FD_ZERO(&input_set);
for (i = 0; i < nfds; i ++)
- FD_SET(fds[i], &input_set);
+ FD_SET(fds[i], &input_set);
output_set = input_set;
timeout.tv_sec = 0;
- timeout.tv_usec = (remaining > 250 ? 250 : remaining) * 1000;
+ timeout.tv_usec = (addrlist ? 100 : remaining > 250 ? 250 : remaining) * 1000;
result = select(max_fd + 1, &input_set, &output_set, NULL, &timeout);
for (i = 0; i < nfds; i ++)
{
# ifdef HAVE_POLL
- DEBUG_printf(("pfds[%d].revents=%x\n", i, pfds[i].revents));
- if (pfds[i].revents)
+ DEBUG_printf(("pfds[%d].revents=%x\n", i, pfds[i].revents));
+ if (pfds[i].revents)
# else
- if (FD_ISSET(fds[i], &input))
+ if (FD_ISSET(fds[i], &input))
# endif /* HAVE_POLL */
- {
- *sock = fds[i];
+ {
+ *sock = fds[i];
+ addrlist = addrs[i];
+
+# ifdef DEBUG
len = sizeof(peer);
if (!getpeername(fds[i], (struct sockaddr *)&peer, &len))
- {
DEBUG_printf(("1httpAddrConnect2: Connected to %s:%d...", httpAddrString(&peer, temp, sizeof(temp)), httpAddrPort(&peer)));
-
- addrlist = addrs[i];
- }
+# endif /* DEBUG */
}
else
httpAddrClose(NULL, fds[i]);
return (addrlist);
}
- }
#endif /* O_NONBLOCK */
+ if (addrlist)
+ remaining -= 100;
+ else
+ remaining -= 250;
+ }
+
while (nfds > 0)
{
nfds --;
/*
* 'httpAddrCopyList()' - Copy an address list.
*
- * @since CUPS 1.7/OS X 10.9@
+ * @since CUPS 1.7/macOS 10.9@
*/
http_addrlist_t * /* O - New address list or @code NULL@ on error */
/*
* 'httpAddrFreeList()' - Free an address list.
*
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
*/
void
/*
* 'httpAddrGetList()' - Get a list of addresses for a hostname.
*
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
*/
http_addrlist_t * /* O - List of addresses or NULL */
return (first);
}
-
-
-/*
- * End of "$Id$".
- */