예제 #1
0
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;
}
예제 #3
0
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;
}
예제 #4
0
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;
}
예제 #5
0
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;
}
예제 #6
0
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;
}