int php_amqp_set_resource_write_timeout(amqp_connection_resource *resource, double timeout TSRMLS_DC) { assert(timeout >= 0.0); #ifdef PHP_WIN32 DWORD write_timeout; if (timeout == 0.) { write_timeout = 0; } else { write_timeout = (int) (max(timeout * 1.e+3 - .5e+3, 1.)); } #else struct timeval write_timeout; write_timeout.tv_sec = (int) floor(timeout); write_timeout.tv_usec = (int) ((timeout - floor(timeout)) * 1.e+6); #endif if (0 != setsockopt(amqp_get_sockfd(resource->connection_state), SOL_SOCKET, SO_SNDTIMEO, (char *)&write_timeout, sizeof(write_timeout))) { zend_throw_exception(amqp_connection_exception_class_entry, "Socket error: cannot setsockopt SO_SNDTIMEO", 0 TSRMLS_CC); return 0; } return 1; }
/* Socket-related functions */ int php_amqp_set_resource_read_timeout(amqp_connection_resource *resource, double timeout TSRMLS_DC) { assert(timeout >= 0.0); #ifdef PHP_WIN32 DWORD read_timeout; /* In Windows, setsockopt with SO_RCVTIMEO sets actual timeout to a value that's 500ms greater than specified value. Also, it's not possible to set timeout to any value below 500ms. Zero timeout works like it should, however. */ if (timeout == 0.) { read_timeout = 0; } else { read_timeout = (int) (max(connection->read_timeout * 1.e+3 - .5e+3, 1.)); } #else struct timeval read_timeout; read_timeout.tv_sec = (int) floor(timeout); read_timeout.tv_usec = (int) ((timeout - floor(timeout)) * 1.e+6); #endif if (0 != setsockopt(amqp_get_sockfd(resource->connection_state), SOL_SOCKET, SO_RCVTIMEO, (char *)&read_timeout, sizeof(read_timeout))) { zend_throw_exception(amqp_connection_exception_class_entry, "Socket error: cannot setsockopt SO_RCVTIMEO", 0 TSRMLS_CC); return 0; } return 1; }
/* * Functions */ static void camqp_close_connection (camqp_config_t *conf) /* {{{ */ { int sockfd; if ((conf == NULL) || (conf->connection == NULL)) return; sockfd = amqp_get_sockfd (conf->connection); amqp_channel_close (conf->connection, CAMQP_CHANNEL, AMQP_REPLY_SUCCESS); amqp_connection_close (conf->connection, AMQP_REPLY_SUCCESS); amqp_destroy_connection (conf->connection); close (sockfd); conf->connection = NULL; } /* }}} void camqp_close_connection */
int recv_message(uint8_t **body, size_t *len) { int head_len = get_message_header_pb_len(); amqp_connection_state_t *conn = lc_bus_get_connection(); int fd = amqp_get_sockfd(*conn); int max_fd = fd + 1; fd_set fds; amqp_envelope_t envelope; amqp_frame_t frame; amqp_message_t message; char buf[RECV_BUFSIZE] = {0}; int buf_len; Header__Header *p_head = 0; FD_ZERO(&fds); FD_SET(fd, &fds); if (select(max_fd, &fds, 0, 0, 0) > 0) { buf_len = lc_bus_consume_message(conn, 0, &envelope, &frame, &message, buf, sizeof(buf)); } else { return -1; } if (buf_len < head_len) { return -1; } p_head = header__header__unpack(0, head_len, (uint8_t *)buf); if (!p_head || head_len + p_head->length != buf_len) { return -1; } *body = calloc(1, p_head->length); if (!*body) { return -1; } memcpy(*body, buf + head_len, p_head->length); *len = p_head->length; header__header__free_unpacked(p_head, 0); return 0; }
static amqp_connection_state_t setup_amqp_connection() { amqp_connection_state_t connection = amqp_new_connection(); amqp_socket_t *socket = amqp_tcp_socket_new(connection); #ifdef FIX_SIG_PIPE // why doesn't librabbitmq do this, eh? int sockfd = amqp_get_sockfd(connection); int one = 1; // setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(one)); #endif int status = amqp_socket_open(socket, rabbit_host, rabbit_port); assert_x(!status, "Opening RabbitMQ socket", __FILE__, __LINE__); die_on_amqp_error(amqp_login(connection, "/", 0, OUR_FRAME_MAX, 0, AMQP_SASL_METHOD_PLAIN, "guest", "guest"), "Logging in to RabbitMQ"); amqp_channel_open(connection, 1); die_on_amqp_error(amqp_get_rpc_reply(connection), "Opening AMQP channel"); return connection; }
bool ChannelImpl::GetNextFrameFromBroker(amqp_frame_t& frame, boost::chrono::microseconds timeout) { int socketno = amqp_get_sockfd(m_connection); start: // Possibly set a timeout on receiving if (timeout != boost::chrono::microseconds::max() && !amqp_frames_enqueued(m_connection) && !amqp_data_in_buffer(m_connection)) { struct timeval tv_timeout; memset(&tv_timeout, 0, sizeof(tv_timeout)); // boost::chrono::seconds.count() returns boost::int_atleast64_t, // long can be 32 or 64 bit depending on the platform/arch // unless the timeout is something absurd cast to long will be ok, but // lets guard against the case where someone does something silly assert(boost::chrono::duration_cast<boost::chrono::seconds>(timeout).count() < static_cast<boost::chrono::seconds::rep>(std::numeric_limits<long>::max())); tv_timeout.tv_sec = static_cast<long>(boost::chrono::duration_cast<boost::chrono::seconds>(timeout).count()); tv_timeout.tv_usec = static_cast<long>((timeout - boost::chrono::seconds(tv_timeout.tv_sec)).count()); fd_set fds; FD_ZERO(&fds); FD_SET(static_cast<unsigned int>(socketno), &fds); int select_return = select(socketno + 1, &fds, NULL, &fds, &tv_timeout); if (select_return == 0) // If it times out, return { return false; } else if (select_return == -1) { // If its an interupted system call just try again if (errno == EINTR) { goto start; } else { std::string error_string("error calling select on socket: "); #ifdef HAVE_STRERROR_S const int BUFFER_LENGTH = 256; char error_string_buffer[BUFFER_LENGTH] = {0}; strerror_s(error_string_buffer, errno); error_string += error_string_buffer; #elif defined(HAVE_STRERROR_R) const int BUFFER_LENGTH = 256; char error_string_buffer[BUFFER_LENGTH] = {0}; strerror_r(errno, error_string_buffer, BUFFER_LENGTH); error_string += error_string_buffer; #else error_string += strerror(errno); #endif throw std::runtime_error(error_string.c_str()); } } } CheckForError(amqp_simple_wait_frame(m_connection, &frame)); return true; }
int Channel::GetSocketFD() const { return amqp_get_sockfd(m_impl->m_connection); }