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; }
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; }