void cupsdStopListening(void) { cupsd_listener_t *lis; /* Current listening socket */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStopListening: closing all listen sockets."); cupsdPauseListening(); for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); lis; lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) { if (lis->fd != -1) { #ifdef HAVE_LAUNCH_H httpAddrClose(NULL, lis->fd); #else httpAddrClose(&(lis->address), lis->fd); #endif /* HAVE_LAUNCH */ lis->fd = -1; } } }
void cupsdStopListening(void) { cupsd_listener_t *lis; /* Current listening socket */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStopListening: closing all listen sockets."); cupsdPauseListening(); for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); lis; lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) { #if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) if (!lis->on_demand && lis->fd != -1) { httpAddrClose(&(lis->address), lis->fd); lis->fd = -1; } #else if (lis->fd != -1) { httpAddrClose(&(lis->address), lis->fd); lis->fd = -1; } #endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ } }
static int /* O - Socket or -1 on error */ cups_rresvport(int *port, /* IO - Port number to bind to */ int family) /* I - Address family */ { http_addr_t addr; /* Socket address */ int fd; /* Socket file descriptor */ /* * Try to create an IPv4 socket... */ if ((fd = socket(family, SOCK_STREAM, 0)) < 0) return (-1); /* * Initialize the address buffer... */ memset(&addr, 0, sizeof(addr)); addr.addr.sa_family = (sa_family_t)family; /* * Try to bind the socket to a reserved port... */ while (*port > 511) { /* * Set the port number... */ _httpAddrSetPort(&addr, *port); /* * Try binding the port to the socket; return if all is OK... */ if (!bind(fd, (struct sockaddr *)&addr, (socklen_t)httpAddrLength(&addr))) return (fd); /* * Stop if we have any error other than "address already in use"... */ if (errno != EADDRINUSE) { httpAddrClose(NULL, fd); return (-1); } /* * Try the next port... */ (*port)--; } /* * Wasn't able to bind to a reserved port, so close the socket and return * -1... */ #ifdef WIN32 closesocket(fd); #else close(fd); #endif /* WIN32 */ return (-1); }
http_addrlist_t * /* O - Connected address or NULL on failure */ httpAddrConnect2( http_addrlist_t *addrlist, /* I - List of potential addresses */ int *sock, /* O - Socket */ int msec, /* I - Timeout in milliseconds */ int *cancel) /* I - Pointer to "cancel" variable */ { int val; /* Socket option value */ #ifndef WIN32 int flags; /* Socket flags */ #endif /* !WIN32 */ int remaining; /* Remaining timeout */ int i, /* Looping var */ nfds, /* Number of file descriptors */ fds[100], /* Socket file descriptors */ result; /* Result from select() or poll() */ http_addrlist_t *addrs[100]; /* Addresses */ #ifndef HAVE_POLL int max_fd = -1; /* Highest file descriptor */ #endif /* !HAVE_POLL */ #ifdef O_NONBLOCK # ifdef HAVE_POLL struct pollfd pfds[100]; /* Polled file descriptors */ # else fd_set input_set, /* select() input set */ output_set, /* select() output set */ error_set; /* select() error set */ struct timeval timeout; /* Timeout */ # 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 */ DEBUG_printf(("httpAddrConnect2(addrlist=%p, sock=%p, msec=%d, cancel=%p)", (void *)addrlist, (void *)sock, msec, (void *)cancel)); if (!sock) { errno = EINVAL; _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0); return (NULL); } if (cancel && *cancel) return (NULL); if (msec <= 0) msec = INT_MAX; /* * Loop through each address until we connect or run out of addresses... */ nfds = 0; remaining = msec; while (remaining > 0) { if (cancel && *cancel) { while (nfds > 0) { nfds --; httpAddrClose(NULL, fds[nfds]); } return (NULL); } if (addrlist && nfds < (int)(sizeof(fds) / sizeof(fds[0]))) { /* * 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) { /* * 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; } /* * 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)); #endif /* SO_REUSEPORT */ #ifdef SO_NOSIGPIPE 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... */ val = 1; setsockopt(fds[nfds], IPPROTO_TCP, TCP_NODELAY, CUPS_SOCAST &val, sizeof(val)); #ifdef FD_CLOEXEC /* * Close this socket when starting another process... */ fcntl(fds[nfds], F_SETFD, FD_CLOEXEC); #endif /* FD_CLOEXEC */ #ifdef O_NONBLOCK /* * Do an asynchronous connect by setting the socket non-blocking... */ DEBUG_printf(("httpAddrConnect2: Setting non-blocking connect()")); flags = fcntl(fds[nfds], F_GETFL, 0); fcntl(fds[nfds], F_SETFL, flags | O_NONBLOCK); #endif /* O_NONBLOCK */ /* * 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)))); #ifdef O_NONBLOCK fcntl(fds[nfds], F_SETFL, flags); #endif /* O_NONBLOCK */ *sock = fds[nfds]; while (nfds > 0) { nfds --; httpAddrClose(NULL, fds[nfds]); } return (addrlist); } #ifdef WIN32 if (WSAGetLastError() != WSAEINPROGRESS && WSAGetLastError() != WSAEWOULDBLOCK) #else 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]); addrlist = addrlist->next; continue; } #ifndef WIN32 fcntl(fds[nfds], F_SETFL, flags); #endif /* !WIN32 */ #ifndef HAVE_POLL if (fds[nfds] > max_fd) max_fd = fds[nfds]; #endif /* !HAVE_POLL */ addrs[nfds] = addrlist; nfds ++; addrlist = addrlist->next; } if (!addrlist && nfds == 0) break; /* * See if we can connect to any of the addresses so far... */ #ifdef O_NONBLOCK DEBUG_puts("1httpAddrConnect2: Finishing async connect()"); do { if (cancel && *cancel) { /* * Close this socket and return... */ DEBUG_puts("1httpAddrConnect2: Canceled connect()"); while (nfds > 0) { nfds --; httpAddrClose(NULL, fds[nfds]); } *sock = -1; return (NULL); } # ifdef HAVE_POLL for (i = 0; i < nfds; i ++) { pfds[i].fd = fds[i]; pfds[i].events = POLLIN | POLLOUT; } 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); output_set = input_set; error_set = input_set; timeout.tv_sec = 0; timeout.tv_usec = (addrlist ? 100 : remaining > 250 ? 250 : remaining) * 1000; result = select(max_fd + 1, &input_set, &output_set, &error_set, &timeout); DEBUG_printf(("1httpAddrConnect2: select() returned %d (%d)", result, errno)); # endif /* HAVE_POLL */ } # ifdef WIN32 while (result < 0 && (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEWOULDBLOCK)); # else while (result < 0 && (errno == EINTR || errno == EAGAIN)); # endif /* WIN32 */ if (result > 0) { http_addrlist_t *connaddr = NULL; /* Connected address, if any */ for (i = 0; i < nfds; i ++) { # ifdef HAVE_POLL DEBUG_printf(("pfds[%d].revents=%x\n", i, pfds[i].revents)); if (pfds[i].revents && !(pfds[i].revents & (POLLERR | POLLHUP))) # else if (FD_ISSET(fds[i], &input_set) && !FD_ISSET(fds[i], &error_set)) # endif /* HAVE_POLL */ { *sock = fds[i]; connaddr = 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))); # endif /* DEBUG */ } # ifdef HAVE_POLL else if (pfds[i].revents & (POLLERR | POLLHUP)) # else else if (FD_ISSET(fds[i], &error_set)) # endif /* HAVE_POLL */ { /* * Error on socket, remove from the "pool"... */ httpAddrClose(NULL, fds[i]); nfds --; if (i < nfds) { memmove(fds + i, fds + i + 1, (size_t)(nfds - i) * (sizeof(fds[0]))); memmove(addrs + i, addrs + i + 1, (size_t)(nfds - i) * (sizeof(addrs[0]))); } i --; } } if (connaddr) return (connaddr); } #endif /* O_NONBLOCK */ if (addrlist) remaining -= 100; else remaining -= 250; }