From: Michael Sweet Date: Mon, 2 May 2016 17:03:47 +0000 (-0400) Subject: Stagger connect calls by 100ms to avoid "confusing" printers and/or the network X-Git-Tag: v2.2b1~41 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6fb588e01a8b77bf34b015cba8337427310dd16c;p=thirdparty%2Fcups.git Stagger connect calls by 100ms to avoid "confusing" printers and/or the network stack. Add a socket-static target for testing. --- diff --git a/backend/Makefile b/backend/Makefile index a4017bf77e..ae08947fb9 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -1,7 +1,7 @@ # # Backend makefile 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 @@ -86,7 +86,7 @@ unittests: $(UNITTESTS) # clean: - $(RM) $(OBJS) $(TARGETS) $(UNITTESTS) $(LIBOBJS) http https ipps mdns + $(RM) $(OBJS) $(TARGETS) $(UNITTESTS) $(LIBOBJS) http https ipps mdns socket-static # @@ -293,6 +293,12 @@ socket: socket.o ../cups/$(LIBCUPS) libbackend.a echo Linking $@... $(CC) $(LDFLAGS) -o socket socket.o libbackend.a $(LIBS) +socket-static: socket.o ../cups/$(LIBCUPSSTATIC) libbackend.a + echo Linking $@... + $(CC) $(LDFLAGS) -o socket-static socket.o libbackend.a \ + ../cups/$(LIBCUPSSTATIC) $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) \ + $(COMMONLIBS) $(LIBZ) + # # usb diff --git a/cups/http-addrlist.c b/cups/http-addrlist.c index c68b629ddb..90965457e4 100644 --- a/cups/http-addrlist.c +++ b/cups/http-addrlist.c @@ -1,7 +1,7 @@ /* * 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 @@ -62,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 */ @@ -81,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 */ @@ -104,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) { @@ -117,116 +120,121 @@ 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... + */ - val = 1; - setsockopt(fds[nfds], SOL_SOCKET, SO_REUSEADDR, CUPS_SOCAST &val, sizeof(val)); + continue; + } + + /* + * 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]); + 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) @@ -251,22 +259,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); @@ -284,20 +292,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]); @@ -305,9 +313,14 @@ httpAddrConnect2( return (addrlist); } - } #endif /* O_NONBLOCK */ + if (addrlist) + remaining -= 100; + else + remaining -= 250; + } + while (nfds > 0) { nfds --;