Пример #1
0
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;
    }
  }
}
Пример #2
0
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 */
  }
}
Пример #3
0
Файл: lpd.c Проект: apple/cups
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);
}
Пример #4
0
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;
  }