X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=cups%2Fhttp-addrlist.c;h=a8237eb034ac182a452a11b81dede77fd4f5704d;hb=8072030b3c862315c367c73663b27f0427325919;hp=9f5cad56d99f8d356a15846a540fcf9b2a46c695;hpb=807315e64e0867fb7cea00b35ba4454691e844e2;p=thirdparty%2Fcups.git diff --git a/cups/http-addrlist.c b/cups/http-addrlist.c index 9f5cad56d..a8237eb03 100644 --- a/cups/http-addrlist.c +++ b/cups/http-addrlist.c @@ -1,9 +1,7 @@ /* - * "$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 @@ -34,7 +32,7 @@ /* * '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 */ @@ -52,7 +50,7 @@ httpAddrConnect( * '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 */ @@ -64,8 +62,6 @@ httpAddrConnect2( { 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 */ @@ -83,6 +79,8 @@ httpAddrConnect2( # 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 */ @@ -106,7 +104,10 @@ httpAddrConnect2( * 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) { @@ -119,116 +120,125 @@ httpAddrConnect2( 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) @@ -253,22 +263,22 @@ httpAddrConnect2( # 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); @@ -286,20 +296,20 @@ httpAddrConnect2( 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]); @@ -307,9 +317,14 @@ httpAddrConnect2( return (addrlist); } - } #endif /* O_NONBLOCK */ + if (addrlist) + remaining -= 100; + else + remaining -= 250; + } + while (nfds > 0) { nfds --; @@ -329,7 +344,7 @@ httpAddrConnect2( /* * '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 */ @@ -378,7 +393,7 @@ httpAddrCopyList( /* * 'httpAddrFreeList()' - Free an address list. * - * @since CUPS 1.2/OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ void @@ -406,7 +421,7 @@ httpAddrFreeList( /* * '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 */ @@ -888,8 +903,3 @@ httpAddrGetList(const char *hostname, /* I - Hostname, IP address, or NULL for p return (first); } - - -/* - * End of "$Id$". - */