Example #1
0
File: bio.c Project: androdev4u/bud
long bud_bio_ctrl(BIO* bio, int cmd, long num, void* ptr) {
  ringbuffer* buffer;
  long ret;

  buffer = bio->ptr;
  ret = 1;

  switch (cmd) {
    case BIO_CTRL_EOF:
      ret = ringbuffer_is_empty(buffer);
      break;
    case BIO_C_SET_BUF_MEM_EOF_RETURN:
      bio->num = num;
      break;
    case BIO_CTRL_INFO:
      ret = (long) ringbuffer_size(buffer);
      if (ptr != NULL)
        *(void**)(ptr) = NULL;
      break;
    case BIO_CTRL_RESET:
      ASSERT(0, "BIO_CTRL_RESET Unsupported");
      break;
    case BIO_C_SET_BUF_MEM:
      ASSERT(0, "BIO_C_SET_BUF_MEM Unsupported");
      break;
    case BIO_C_GET_BUF_MEM_PTR:
      ASSERT(0, "BIO_C_GET_BUF_MEM Unsupported");
      break;
    case BIO_CTRL_GET_CLOSE:
      ret = bio->shutdown;
      break;
    case BIO_CTRL_SET_CLOSE:
      bio->shutdown = num;
      break;
    case BIO_CTRL_WPENDING:
      ret = 0;
      break;
    case BIO_CTRL_PENDING:
      ret = (long) ringbuffer_size(buffer);
      break;
    case BIO_CTRL_DUP:
    case BIO_CTRL_FLUSH:
      ret = 1;
      break;
    case BIO_CTRL_PUSH:
    case BIO_CTRL_POP:
    default:
      ret = 0;
      break;
  }
  return ret;
}
Example #2
0
bud_client_error_t bud_client_throttle(bud_client_t* client,
                                       bud_client_side_t* side,
                                       ringbuffer* buf) {
  int err;
  bud_client_side_t* opposite;

  if (!ringbuffer_is_full(buf))
    return bud_client_ok(side);

  opposite = side == &client->frontend ? &client->backend : &client->frontend;
  if (opposite->reading != kBudProgressRunning)
    goto done;

  DBG(opposite, "throttle, buffer full: %ld", ringbuffer_size(buf));

  err = uv_read_stop((uv_stream_t*) &opposite->tcp);
  if (err != 0) {
    NOTICE(opposite,
           "uv_read_stop failed: %d - \"%s\"",
           err,
           uv_strerror(err));
    return bud_client_error(bud_error_num(kBudErrClientReadStop, err), side);
  }
  opposite->reading = kBudProgressNone;

done:
  return bud_client_error(bud_error(kBudErrClientThrottle), side);
}
Example #3
0
size_t ringbuffer_read_into(ringbuffer* rb, char* out, size_t length) {
  size_t bytes_read;
  size_t expected;
  size_t offset;
  size_t left;
  bufent* read_head;
  size_t avail;

  bytes_read = 0;
  expected = ringbuffer_size(rb) > length ? length : ringbuffer_size(rb);
  offset = 0;
  left = length;

  while (bytes_read < expected) {
    read_head = rb->read_head;
    assert(read_head->read_pos <= read_head->write_pos);
    avail = RB_BUF_SIZE(read_head);
    if (avail > left)
      avail = left;

    /* Copy data */
    if (out != NULL)
      memcpy(out + offset, read_head->data + read_head->read_pos, avail);
    read_head->read_pos += avail;

    /* Move pointers */
    bytes_read += avail;
    offset += avail;
    left -= avail;

    /* Move to next buffer */
    ringbuffer_try_move_read_head(rb);
  }
  assert(expected == bytes_read);
  rb->length -= bytes_read;

  /* Free all empty buffers, but write_head's child */
  ringbuffer_free_empty(rb);

  return bytes_read;
}
Example #4
0
bud_client_error_t bud_client_backend_in(bud_client_t* client) {
  size_t size;
  int written;
  int err;
  bud_client_error_t cerr;

  written = 0;
  while (!ringbuffer_is_empty(&client->backend.input)) {
    char* data;

    data = ringbuffer_read_next(&client->backend.input, &size);
    written = SSL_write(client->ssl, data, size);
    DBG(&client->frontend, "SSL_write() => %d", written);
    DBG(&client->frontend,
        "frontend.output => %d",
        ringbuffer_size(&client->frontend.output));
    if (written < 0)
      break;

    ASSERT(written == (int) size, "SSL_write() did unexpected partial write");
    ringbuffer_read_skip(&client->backend.input, written);

    /* info_cb() has closed front-end */
    if (client->frontend.close != kBudProgressNone)
      return bud_client_ok(&client->backend);
  }

  cerr = bud_client_throttle(client,
                             &client->frontend,
                             &client->frontend.output);
  if (!bud_is_ok(cerr.err) && cerr.err.code != kBudErrClientThrottle)
    return cerr;

  if (written >= 0)
    return bud_client_ok(&client->backend);

  err = SSL_get_error(client->ssl, written);
  if (err == SSL_ERROR_WANT_READ ||
      err == SSL_ERROR_WANT_WRITE ||
      err == SSL_ERROR_WANT_X509_LOOKUP) {
    return bud_client_ok(&client->backend);
  }

  return bud_client_error(bud_error_num(kBudErrClientSSLWrite, err),
                          &client->backend);
}
Example #5
0
int ringbuffer_is_full(ringbuffer* rb) {
  return ringbuffer_size(rb) >= RING_MAX_SIZE;
}
Example #6
0
int ringbuffer_is_empty(ringbuffer* rb) {
  return ringbuffer_size(rb) == 0;
}
Example #7
0
int ringbuffer_insert(ringbuffer* rb,
                      size_t off,
                      const char* data,
                      size_t length) {
  bufent* b;
  bufent* next;
  bufent* start;
  size_t left;
  size_t offset;
  int r;

  assert(length < RING_BUFFER_LEN);

  /* Find owner of `off` */
  left = ringbuffer_size(rb);
  start = rb->read_head;
  while (off != 0) {
    if (off < RB_BUF_SIZE(start))
      break;
    off -= RB_BUF_SIZE(start);
    left -= RB_BUF_SIZE(start);
    start = start->next;
  }

  /* Shift everything after `off` forward by `length` */
  b = rb->write_head;

  /* Ensure that we have enough space for shift */
  r = ringbuffer_write_append(rb, length);
  if (r != 0)
    return r;

  next = rb->write_head;
  while (left > 0) {
    /* Copy part of the data from the end of current to the next buffer */
    if (next != b)
      memcpy(next->data, b->data + RING_BUFFER_LEN - length, length);

    /* Move rest inside current buffer */
    offset = b->read_pos;
    if (b == start)
      offset += off;

    if (offset + length < RING_BUFFER_LEN) {
      memmove(b->data + offset + length,
              b->data + offset,
              RING_BUFFER_LEN - offset - length);
    }

    if (b == start)
      break;

    left -= RB_BUF_SIZE(b);

    /* Select previous buffer, O(N) */
    next = b;
    b = start;
    while (b->next != next)
      b = b->next;
  }

  /* Copy input data into the free space */
  if (off + length > RING_BUFFER_LEN) {
    size_t delta;

    delta = off + length - RING_BUFFER_LEN;
    memcpy(start->data + off, data, length - delta);
    memcpy(next->data, data + length - delta, delta);
  } else {
    memcpy(start->data + off, data, length);
  }

  return 0;
}
Example #8
0
File: test.c Project: Acconut/bud
int main() {
  int i;
  int j;
  int r;
  int after;
  ssize_t len;
  char* ptr;

  data = malloc(TEST_DATA_SIZE);
  assert(data != NULL);
  ringbuffer_init(&rb);

  /* Fill test data */
  for (i = 0; i < TEST_DATA_SIZE; i++)
    data[i] = (i * i) % 137;

  /* Fill ringbuffer */
  i = 0;
  after = 0;
  while (i < TEST_DATA_SIZE - TEST_INSERT_LEN) {
    if (after)
      len = TEST_DATA_SIZE - i - TEST_INSERT_LEN;
    else
      len = TEST_INSERT_OFF - i;

    ptr = ringbuffer_write_ptr(&rb, &len);
    ASSERT(ptr != NULL);

    /* Always make progress */
    ASSERT(len > 0);

    if (after)
      memcpy(ptr, data + i + TEST_INSERT_LEN, len);
    else
      memcpy(ptr, data + i, len);

    i += len;
    r = ringbuffer_write_append(&rb, len);
    ASSERT(r == 0);

    if (i == TEST_INSERT_OFF)
      after = 1;
  }
  ASSERT(ringbuffer_size(&rb) == TEST_DATA_SIZE - TEST_INSERT_LEN);

  /* Insert stuff */
  ringbuffer_insert(&rb,
                    TEST_INSERT_OFF,
                    data + TEST_INSERT_OFF,
                    TEST_INSERT_LEN);

  /* Read from it */
  i = 0;
  while (i < TEST_DATA_SIZE) {
    len = TEST_DATA_SIZE - i;
    ptr = ringbuffer_read_next(&rb, &len);
    ASSERT(ptr != NULL);

    /* Always make progress */
    ASSERT(len > 0);

    for (j = 0; j < len; j++)
      ASSERT(ptr[j] == data[i + j]);

    ringbuffer_read_skip(&rb, len);
    i += len;
  }

  /* Destroy it */
  ringbuffer_destroy(&rb);

  return 0;
}
Example #9
0
DECLARE_TEST( ringbuffer, allocate )
{
	ringbuffer_t* buffer;
	char store[256];

	buffer = ringbuffer_allocate( 0 );
	EXPECT_EQ( ringbuffer_size( buffer ), 0 );
	EXPECT_EQ( ringbuffer_total_read( buffer ), 0 );
	EXPECT_EQ( ringbuffer_total_written( buffer ), 0 );

	EXPECT_EQ( ringbuffer_read( buffer, store, 0 ), 0 );
	EXPECT_EQ( ringbuffer_write( buffer, store, 0 ), 0 );
	EXPECT_EQ( ringbuffer_size( buffer ), 0 );
	EXPECT_EQ( ringbuffer_total_read( buffer ), 0 );
	EXPECT_EQ( ringbuffer_total_written( buffer ), 0 );

	EXPECT_EQ( ringbuffer_read( buffer, store, 256 ), 0 );
	EXPECT_EQ( ringbuffer_write( buffer, store, 256 ), 0 );
	EXPECT_EQ( ringbuffer_size( buffer ), 0 );
	EXPECT_EQ( ringbuffer_total_read( buffer ), 0 );
	EXPECT_EQ( ringbuffer_total_written( buffer ), 0 );

	ringbuffer_deallocate( buffer );

	buffer = ringbuffer_allocate( 128 );
	EXPECT_EQ( ringbuffer_size( buffer ), 128 );
	EXPECT_EQ( ringbuffer_total_read( buffer ), 0 );
	EXPECT_EQ( ringbuffer_total_written( buffer ), 0 );

	EXPECT_EQ( ringbuffer_write( buffer, store, 0 ), 0 );
	EXPECT_EQ( ringbuffer_read( buffer, store, 0 ), 0 );
	EXPECT_EQ( ringbuffer_size( buffer ), 128 );
	EXPECT_EQ( ringbuffer_total_read( buffer ), 0 );
	EXPECT_EQ( ringbuffer_total_written( buffer ), 0 );

	EXPECT_EQ( ringbuffer_write( buffer, store, 256 ), 127 );
	EXPECT_EQ( ringbuffer_read( buffer, store, 256 ), 127 );
	EXPECT_EQ( ringbuffer_size( buffer ), 128 );
	EXPECT_EQ( ringbuffer_total_read( buffer ), 127 );
	EXPECT_EQ( ringbuffer_total_written( buffer ), 127 );

	ringbuffer_deallocate( buffer );

	buffer = ringbuffer_allocate( 256 );
	EXPECT_EQ( ringbuffer_size( buffer ), 256 );
	EXPECT_EQ( ringbuffer_total_read( buffer ), 0 );
	EXPECT_EQ( ringbuffer_total_written( buffer ), 0 );

	EXPECT_EQ( ringbuffer_write( buffer, store, 0 ), 0 );
	EXPECT_EQ( ringbuffer_read( buffer, store, 0 ), 0 );
	EXPECT_EQ( ringbuffer_size( buffer ), 256 );
	EXPECT_EQ( ringbuffer_total_read( buffer ), 0 );
	EXPECT_EQ( ringbuffer_total_written( buffer ), 0 );

	EXPECT_EQ( ringbuffer_write( buffer, store, 256 ), 255 );
	EXPECT_EQ( ringbuffer_read( buffer, store, 256 ), 255 );
	EXPECT_EQ( ringbuffer_size( buffer ), 256 );
	EXPECT_EQ( ringbuffer_total_read( buffer ), 255 );
	EXPECT_EQ( ringbuffer_total_written( buffer ), 255 );

	ringbuffer_deallocate( buffer );

	buffer = ringbuffer_allocate( 512 );
	EXPECT_EQ( ringbuffer_size( buffer ), 512 );
	EXPECT_EQ( ringbuffer_total_read( buffer ), 0 );
	EXPECT_EQ( ringbuffer_total_written( buffer ), 0 );

	EXPECT_EQ( ringbuffer_write( buffer, store, 0 ), 0 );
	EXPECT_EQ( ringbuffer_read( buffer, store, 0 ), 0 );
	EXPECT_EQ( ringbuffer_size( buffer ), 512 );
	EXPECT_EQ( ringbuffer_total_read( buffer ), 0 );
	EXPECT_EQ( ringbuffer_total_written( buffer ), 0 );

	EXPECT_EQ( ringbuffer_write( buffer, store, 256 ), 256 );
	EXPECT_EQ( ringbuffer_read( buffer, store, 256 ), 256 );
	EXPECT_EQ( ringbuffer_size( buffer ), 512 );
	EXPECT_EQ( ringbuffer_total_read( buffer ), 256 );
	EXPECT_EQ( ringbuffer_total_written( buffer ), 256 );

	EXPECT_EQ( ringbuffer_write( buffer, store, 256 ), 256 );
	EXPECT_EQ( ringbuffer_read( buffer, store, 256 ), 256 );
	EXPECT_EQ( ringbuffer_size( buffer ), 512 );
	EXPECT_EQ( ringbuffer_total_read( buffer ), 512 );
	EXPECT_EQ( ringbuffer_total_written( buffer ), 512 );

	ringbuffer_deallocate( buffer );
	
	return 0;
}