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;
}
Exemple #2
0
int amqp_destroy_connection(amqp_connection_state_t state) {
  int s = state->sockfd;

  empty_amqp_pool(&state->frame_pool);
  empty_amqp_pool(&state->decoding_pool);
  free(state->outbound_buffer.bytes);
  free(state->sock_inbound_buffer.bytes);
  free(state);

  if (s >= 0 && amqp_socket_close(s) < 0)
    return -amqp_socket_error();
  else
    return 0;
}
static int wait_frame_inner(amqp_connection_state_t state,
			    amqp_frame_t *decoded_frame)
{
  while (1) {
    int res;

    while (amqp_data_in_buffer(state)) {
      amqp_bytes_t buffer;
      buffer.len = state->sock_inbound_limit - state->sock_inbound_offset;
      buffer.bytes = ((char *) state->sock_inbound_buffer.bytes) + state->sock_inbound_offset;

      res = amqp_handle_input(state, buffer, decoded_frame);
      if (res < 0)
	return res;

      state->sock_inbound_offset += res;

      if (decoded_frame->frame_type != 0)
	/* Complete frame was read. Return it. */
	return 0;

      /* Incomplete or ignored frame. Keep processing input. */
      assert(res != 0);
    }

    res = recv(state->sockfd, state->sock_inbound_buffer.bytes,
		  state->sock_inbound_buffer.len, 0);
    if (res <= 0) {
      if (res == 0)
	return -ERROR_CONNECTION_CLOSED;
      else
	return -amqp_socket_error();
    }

    state->sock_inbound_limit = res;
    state->sock_inbound_offset = 0;
  }
}
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 #5
0
int amqp_send_frame(amqp_connection_state_t state,
		    const amqp_frame_t *frame)
{
  void *out_frame = state->outbound_buffer.bytes;
  int res;

  amqp_e8(out_frame, 0, frame->frame_type);
  amqp_e16(out_frame, 1, frame->channel);

  if (frame->frame_type == AMQP_FRAME_BODY) {
    /* For a body frame, rather than copying data around, we use
       writev to compose the frame */
    struct iovec iov[3];
    uint8_t frame_end_byte = AMQP_FRAME_END;
    const amqp_bytes_t *body = &frame->payload.body_fragment;

    amqp_e32(out_frame, 3, body->len);

    iov[0].iov_base = out_frame;
    iov[0].iov_len = HEADER_SIZE;
    iov[1].iov_base = body->bytes;
    iov[1].iov_len = body->len;
    iov[2].iov_base = &frame_end_byte;
    iov[2].iov_len = FOOTER_SIZE;

    res = amqp_socket_writev(state->sockfd, iov, 3);
  }
  else {
    size_t out_frame_len;
    amqp_bytes_t encoded;

    switch (frame->frame_type) {
    case AMQP_FRAME_METHOD:
      amqp_e32(out_frame, HEADER_SIZE, frame->payload.method.id);

      encoded.bytes = amqp_offset(out_frame, HEADER_SIZE + 4);
      encoded.len = state->outbound_buffer.len - HEADER_SIZE - 4 - FOOTER_SIZE;

      res = amqp_encode_method(frame->payload.method.id,
                               frame->payload.method.decoded, encoded);
      if (res < 0)
        return res;

      out_frame_len = res + 4;
      break;

    case AMQP_FRAME_HEADER:
      amqp_e16(out_frame, HEADER_SIZE, frame->payload.properties.class_id);
      amqp_e16(out_frame, HEADER_SIZE+2, 0); /* "weight" */
      amqp_e64(out_frame, HEADER_SIZE+4, frame->payload.properties.body_size);

      encoded.bytes = amqp_offset(out_frame, HEADER_SIZE + 12);
      encoded.len = state->outbound_buffer.len - HEADER_SIZE - 12 - FOOTER_SIZE;

      res = amqp_encode_properties(frame->payload.properties.class_id,
                                   frame->payload.properties.decoded, encoded);
      if (res < 0)
        return res;

      out_frame_len = res + 12;
      break;

    case AMQP_FRAME_HEARTBEAT:
      out_frame_len = 0;
      break;

    default:
      abort();
    }

    amqp_e32(out_frame, 3, out_frame_len);
    amqp_e8(out_frame, out_frame_len + HEADER_SIZE, AMQP_FRAME_END);
    res = send(state->sockfd, out_frame,
               out_frame_len + HEADER_SIZE + FOOTER_SIZE, 0);
  }

  if (res < 0)
    return -amqp_socket_error();
  else
    return 0;
}
Exemple #6
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;
}