int amqp_timer_update(amqp_timer_t *timer, struct timeval *timeout) { if (0 == timer->current_timestamp) { timer->current_timestamp = amqp_get_monotonic_timestamp(); if (0 == timer->current_timestamp) { return AMQP_STATUS_TIMER_FAILURE; } timer->timeout_timestamp = timer->current_timestamp + (uint64_t)timeout->tv_sec * AMQP_NS_PER_S + (uint64_t)timeout->tv_usec * AMQP_NS_PER_US; } else { timer->current_timestamp = amqp_get_monotonic_timestamp(); if (0 == timer->current_timestamp) { return AMQP_STATUS_TIMER_FAILURE; } } if (timer->current_timestamp > timer->timeout_timestamp) { return AMQP_STATUS_TIMEOUT; } timer->ns_until_next_timeout = timer->timeout_timestamp - timer->current_timestamp; memset(&timer->tv, 0, sizeof(struct timeval)); timer->tv.tv_sec = (__darwin_time_t)(timer->ns_until_next_timeout / AMQP_NS_PER_S); timer->tv.tv_usec = (timer->ns_until_next_timeout % AMQP_NS_PER_S) / AMQP_NS_PER_US; return AMQP_STATUS_OK; }
int amqp_tune_connection(amqp_connection_state_t state, int channel_max, int frame_max, int heartbeat) { void *newbuf; ENFORCE_STATE(state, CONNECTION_STATE_IDLE); state->channel_max = channel_max; state->frame_max = frame_max; state->heartbeat = heartbeat; if (amqp_heartbeat_enabled(state)) { uint64_t current_time = amqp_get_monotonic_timestamp(); if (0 == current_time) { return AMQP_STATUS_TIMER_FAILURE; } state->next_send_heartbeat = amqp_calc_next_send_heartbeat(state, current_time); state->next_recv_heartbeat = amqp_calc_next_recv_heartbeat(state, current_time); } state->outbound_buffer.len = frame_max; newbuf = realloc(state->outbound_buffer.bytes, frame_max); if (newbuf == NULL) { return AMQP_STATUS_NO_MEMORY; } state->outbound_buffer.bytes = newbuf; return AMQP_STATUS_OK; }
int amqp_time_ms_until(amqp_time_t time) { uint64_t now_ns; uint64_t delta_ns; int left_ms; if (UINT64_MAX == time.time_point_ns) { return -1; } if (0 == time.time_point_ns) { return 0; } now_ns = amqp_get_monotonic_timestamp(); if (0 == now_ns) { return AMQP_STATUS_TIMER_FAILURE; } if (now_ns >= time.time_point_ns) { return 0; } delta_ns = time.time_point_ns - now_ns; left_ms = (int)(delta_ns / AMQP_NS_PER_MS); return left_ms; }
int amqp_time_from_now(amqp_time_t *time, struct timeval *timeout) { uint64_t now_ns; uint64_t delta_ns; assert(NULL != time); if (NULL == timeout) { *time = amqp_time_infinite(); return AMQP_STATUS_OK; } if (0 == timeout->tv_sec && 0 == timeout->tv_usec) { *time = amqp_time_immediate(); return AMQP_STATUS_OK; } if (timeout->tv_sec < 0 || timeout->tv_usec < 0) { return AMQP_STATUS_INVALID_PARAMETER; } delta_ns = (uint64_t)timeout->tv_sec * AMQP_NS_PER_S + (uint64_t)timeout->tv_usec * AMQP_NS_PER_US; now_ns = amqp_get_monotonic_timestamp(); if (0 == now_ns) { return AMQP_STATUS_TIMER_FAILURE; } time->time_point_ns = now_ns + delta_ns; if (now_ns > time->time_point_ns || delta_ns > time->time_point_ns) { return AMQP_STATUS_INVALID_PARAMETER; } return AMQP_STATUS_OK; }
int amqp_time_has_past(amqp_time_t time) { uint64_t now_ns; if (UINT64_MAX == time.time_point_ns) { return AMQP_STATUS_OK; } now_ns = amqp_get_monotonic_timestamp(); if (0 == now_ns) { return AMQP_STATUS_TIMER_FAILURE; } if (now_ns > time.time_point_ns) { return AMQP_STATUS_TIMEOUT; } return AMQP_STATUS_OK; }
int amqp_time_s_from_now(amqp_time_t *time, int seconds) { uint64_t now_ns; uint64_t delta_ns; assert(NULL != time); if (0 >= seconds) { *time = amqp_time_infinite(); return AMQP_STATUS_OK; } now_ns = amqp_get_monotonic_timestamp(); if (0 == now_ns) { return AMQP_STATUS_TIMER_FAILURE; } delta_ns = (uint64_t)seconds * AMQP_NS_PER_S; time->time_point_ns = now_ns + delta_ns; if (now_ns > time->time_point_ns || delta_ns > time->time_point_ns) { return AMQP_STATUS_INVALID_PARAMETER; } return AMQP_STATUS_OK; }
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->socket, 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: return AMQP_STATUS_INVALID_PARAMETER; } amqp_e32(out_frame, 3, out_frame_len); amqp_e8(out_frame, out_frame_len + HEADER_SIZE, AMQP_FRAME_END); res = amqp_socket_send(state->socket, out_frame, out_frame_len + HEADER_SIZE + FOOTER_SIZE); } if (state->heartbeat > 0) { uint64_t current_time = amqp_get_monotonic_timestamp(); if (0 == current_time) { return AMQP_STATUS_TIMER_FAILURE; } state->next_send_heartbeat = amqp_calc_next_send_heartbeat(state, current_time); } return res; }