int amqp_open_socket(char const *hostname,
		     int portnumber)
{
  int sockfd, res;
  struct sockaddr_in addr;
  struct hostent *he;
  int one = 1; /* used as a buffer by setsockopt below */

  res = amqp_socket_init();
  if (res)
    return res;

  he = gethostbyname(hostname);
  if (he == NULL)
    return -ERROR_GETHOSTBYNAME_FAILED;

  addr.sin_family = AF_INET;
  addr.sin_port = htons(portnumber);
  addr.sin_addr.s_addr = * (uint32_t *) he->h_addr_list[0];

  sockfd = socket(PF_INET, SOCK_STREAM, 0);
  if (sockfd == -1)
    return -amqp_socket_error();

  if (amqp_socket_setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &one,
			     sizeof(one)) < 0
      || connect(sockfd, (struct sockaddr *) &addr, sizeof(addr)) < 0)
  {
    res = -amqp_socket_error();
    amqp_socket_close(sockfd);
    return res;
  }

  return sockfd;
}
int amqp_open_socket(char const *hostname,
		     int portnumber)
{
  struct addrinfo hint;
  struct addrinfo *address_list;
  struct addrinfo *addr;
  char portnumber_string[33];
  int sockfd = -1;
  int last_error = 0;
  int one = 1; /* for setsockopt */

  if (0 != (last_error = amqp_socket_init()))
    return last_error;

  memset(&hint, 0, sizeof(hint));
  hint.ai_family = PF_UNSPEC; /* PF_INET or PF_INET6 */
  hint.ai_socktype = SOCK_STREAM;
  hint.ai_protocol = IPPROTO_TCP;

  (void)sprintf(portnumber_string, "%d", portnumber);

  last_error = getaddrinfo(hostname, portnumber_string, &hint, &address_list);

  if (last_error != 0)
  {
    return -ERROR_GETHOSTBYNAME_FAILED;
  }

  for (addr = address_list; addr; addr = addr->ai_next)
  {
    /*
      This cast is to squash warnings on Win64, see:
      http://stackoverflow.com/questions/1953639/is-it-safe-to-cast-socket-to-int-under-win64
    */
    sockfd = (int)socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
    if (-1 == sockfd)
    {
      last_error = -amqp_socket_error();
      continue;
    }

    /*
      Set SO_RCVTIMEO and SO_SNDTIMEO on socket
    */
    struct timeval timeout;      
    timeout.tv_sec = 2;
    timeout.tv_usec = 0;

    if (0 != amqp_socket_setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) )
    {
      last_error = -amqp_socket_error();
      amqp_socket_close(sockfd);
      continue;
    }
    
    if (0 != amqp_socket_setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) )
    {
      last_error = -amqp_socket_error();
      amqp_socket_close(sockfd);
      continue;
    }

#ifdef DISABLE_SIGPIPE_WITH_SETSOCKOPT
    if (0 != amqp_socket_setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(one)))
    {
      last_error = -amqp_socket_error();
      amqp_socket_close(sockfd);
      continue;
    }
#endif /* DISABLE_SIGPIPE_WITH_SETSOCKOPT */
    if (0 != amqp_socket_setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one))
        || 0 != connect(sockfd, addr->ai_addr, addr->ai_addrlen))
    {
      last_error = -amqp_socket_error();
      amqp_socket_close(sockfd);
      continue;
    }
    else
    {
      last_error = 0;
      break;
    }
  }

  freeaddrinfo(address_list);
  if (last_error != 0)
  {
    return last_error;
  }
  
  return sockfd;
}
Exemple #3
0
int amqp_open_socket(char const *hostname,
		     int portnumber, int timeout)
{
  int sockfd, res;
  struct sockaddr_in addr;
  struct hostent *he;
  int one = 1; /* used as a buffer by setsockopt below */
  int orig_flags;

  res = amqp_socket_init();
  if (res)
    return res;

  he = gethostbyname(hostname);
  if (he == NULL)
    return -ERROR_GETHOSTBYNAME_FAILED;

  addr.sin_family = AF_INET;
  addr.sin_port = htons(portnumber);
  addr.sin_addr.s_addr = * (uint32_t *) he->h_addr_list[0];

  sockfd = socket(PF_INET, SOCK_STREAM, 0);
  if (sockfd == -1)
    return -amqp_socket_error();

  if (timeout > 0) {
	  orig_flags = fcntl(sockfd, F_GETFL,0);
	  res = fcntl(sockfd, F_SETFL, orig_flags | O_NONBLOCK);
	  if (res != 0) {
		  amqp_socket_close(sockfd);
		  return res;
	  }
  }

  if (amqp_socket_setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)) < 0)
  {
    res = -amqp_socket_error();
    amqp_socket_close(sockfd);
    return res;
  }

  if (timeout <= 0) {
	 if (connect(sockfd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
		 res = -amqp_socket_error();
		 amqp_socket_close(sockfd);
		 return res;
	 }
	 return sockfd;
  } else {
	  int err = 0;
		
	  while (1) {
		res = connect(sockfd, (struct sockaddr *) &addr, sizeof(addr));
		
		if (res == 0) {
			/* success! */
			break;
		}

		switch(errno) {
			case EALREADY:
			case EINPROGRESS:
			{
				res = _amqp_poll(sockfd, POLLOUT|POLLIN|POLLHUP|POLLERR, timeout, &err);
				if (res == AMQP_POLL_SUCCESS) {
					/* try again */
					continue;
				}

				/* timeout exceeded or an error occured */
				amqp_socket_close(sockfd);
				goto out_loop;
			}
			case EINTR:
				continue;
			default:
				res = errno;
				amqp_socket_close(sockfd);
				goto out_loop;
		}
	  }

out_loop:

	  if (res == AMQP_POLL_TIMEOUT) {
		  amqp_socket_close(sockfd);
		  return -ERROR_CONNECTION_TIMED_OUT;
	  } else if (res == AMQP_POLL_FAILURE) {
		  amqp_socket_close(sockfd);
		  return -err | ERROR_CATEGORY_OS;
	  }
  }

  if (timeout > 0) {
	  int fd_flags;

	  fd_flags = fcntl(sockfd, F_GETFL,0);
	  res = fcntl(sockfd, F_SETFL, orig_flags);
	  if (res != 0) {
		  amqp_socket_close(sockfd);
		  return res;
	  }
  }
  return sockfd;
}