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;
}
Ejemplo n.º 2
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;
}