Example #1
0
void *buffer_append_space(Buffer *buffer, unsigned int len)
{
    unsigned int newlen;
    void *p;

    if (len > BUFFER_MAX_CHUNK)
        return NULL;

    /* If the buffer is empty, start using it from the beginning. */
    if (buffer->offset == buffer->end) {
        buffer->offset = 0;
        buffer->end = 0;
    }
restart:
    /* If there is enough space to store all data, store it now. */
    if (buffer->end + len < buffer->alloc) {
        p = buffer->buf + buffer->end;
        buffer->end += len;
        return p;
    }

    /* Compact data back to the start of the buffer if necessary */
    if (buffer_compact(buffer))
        goto restart;

    /* Increase the size of the buffer and retry. */
    newlen = roundup(buffer->alloc + len, BUFFER_ALLOCSZ);
    if (newlen > BUFFER_MAX_LEN)
        return NULL;
    buffer->buf = (unsigned char *)realloc(buffer->buf, newlen);
    buffer->alloc = newlen;
    goto restart;
    /* NOTREACHED */
}
Example #2
0
File: fork.c Project: hsaransa/std2
static void write_cb(int fd, int mask, void* user)
{
    int fork_id = (int)user;
    fork_state* fs = get_fork(fork_id);

    fs->has_yielded_writer = 0;

    if (mask & STD2_CALLBACK_ABORT)
    {
        assert(!"abort not implemented");
        abort();
        return;
    }

    int r = write_buffer(fd, &fs->out_buffer);
    if (r < 0)
    {
        // TODO: abort requests and stuff
        fprintf(stderr, "std2: write error: %s\n", strerror(errno));
        abort();
    }

    buffer_compact(&fs->out_buffer);

    yield_callbacks(fork_id);
}
Example #3
0
struct fast_message *fast_session_recv(struct fast_session *self, int flags)
{
	struct buffer *buffer = self->rx_buffer;
	struct fast_message *msg;
	size_t size;
	ssize_t nr;

	msg = fast_message_decode(self);
	if (msg)
		return msg;

	size = buffer_remaining(buffer);
	if (size <= FAST_MESSAGE_MAX_SIZE)
		buffer_compact(buffer);

	/*
	* If buffer's capacity is at least
	* 2 times FAST_MESSAGE_MAX_SIZE then,
	* remaining > FAST_MESSAGE_MAX_SIZE
	*/
	nr = self->recv(buffer, self->sockfd, FAST_MESSAGE_MAX_SIZE, flags);
	if (nr <= 0)
		return NULL;

	return fast_message_decode(self);
}
Example #4
0
File: fork.c Project: hsaransa/std2
static void return_func(int id, void* ret, void* arg0, void* arg1)
{
    (void)arg0;

    request* req = arg1;
    fork_state* fs = get_fork(req->fork_id);

    int ret_id   = buffer_read_32(&fs->in_buffer);
    int ret_size = buffer_read_32(&fs->in_buffer);
    buffer_compact(&fs->in_buffer);

    assert(req->id == ret_id);
    assert(req->return_id == id);

    char* p      = buffer_cursor(&fs->in_buffer);
    char* start = p;

    switch (req->ret_type.type)
    {
    case STD2_VOID:
        break;

    case STD2_INT32:
        *(std2_int32*)ret = *(std2_int32*)p;
        p += 4;
        break;

    case STD2_C_STRING:
        {
            int size = *(int*)p;
            p += 4;
            *(const char**)ret = p;
            p += size;
        }
        break;

    case STD2_INSTANCE:
        *(void**)ret = *(void**)p;
        p += sizeof(void*);
        break;

    default:
        fprintf(stderr, "std2: todo return type %d\n", req->ret_type.type);
        abort();
    }

    assert(p - start == ret_size);

    fs->in_buffer.pos += ret_size;

    fs->return_processed = 1;

    request** prev = &fs->first_request;
    while (*prev != req && *prev)
        prev = &(*prev)->next;
    assert(*prev);
    *prev = (*prev)->next;
    free(req);
}
Example #5
0
char *buffer_deconstruct(buffer *b)
{
  char *data;

  (void) buffer_compact(b);
  data = buffer_data(b);
  free(b);

  return data;
}
Example #6
0
/*
 * Check whether an allocation of 'len' will fit in the buffer
 * This must follow the same math as buffer_append_space
 */
int
buffer_check_alloc(Buffer *buffer, u_int len)
{
	if (buffer->offset == buffer->end) {
		buffer->offset = 0;
		buffer->end = 0;
	}
 restart:
	if (buffer->end + len < buffer->alloc)
		return (1);
	if (buffer_compact(buffer))
		goto restart;
	if (roundup(buffer->alloc + len, BUFFER_ALLOCSZ) <= BUFFER_MAX_LEN)
		return (1);
	return (0);
}
Example #7
0
void *
buffer_append_space(Buffer *buffer, uint32_t len)
{
  uint32_t newlen;
  void *p;

  if (len > BUFFER_MAX_CHUNK)
    croak("buffer_append_space: len %u too large (max %u)", len, BUFFER_MAX_CHUNK);

  /* If the buffer is empty, start using it from the beginning. */
  if (buffer->offset == buffer->end) {
    buffer->offset = 0;
    buffer->end = 0;
  }

restart:
  /* If there is enough space to store all data, store it now. */
  if (buffer->end + len <= buffer->alloc) {
    p = buffer->buf + buffer->end;
    buffer->end += len;
    return p;
  }

  /* Compact data back to the start of the buffer if necessary */
  if (buffer_compact(buffer))
    goto restart;

  /* Increase the size of the buffer and retry. */
  if (buffer->alloc + len < 4096)
    newlen = (buffer->alloc + len) * 2;
  else
    newlen = buffer->alloc + len + 4096;
  
  if (newlen > BUFFER_MAX_LEN)
    croak("buffer_append_space: alloc %u too large (max %u)",
        newlen, BUFFER_MAX_LEN);
#ifdef XS_DEBUG
  PerlIO_printf(PerlIO_stderr(), "Buffer extended to %d\n", newlen);
#endif
  Renew(buffer->buf, (int)newlen, u_char);
  buffer->alloc = newlen;
  goto restart;
  /* NOTREACHED */
}
Example #8
0
frameparser_outcome frameparser_parse(frameparser *fp, buffer *b)
{
  // Parse as much as we can from the buffer
  bool done = false;
  while ((!done) && (buffer_get_length(b) > 0))
  {
    if (!frameparser_parse_internal(fp, b))
      done = true;
  }

  // Can't make any more parsing progress for now. Might as well compact the buffer.
  buffer_compact(b);

  if (fp->state == FP_STATE_ERROR)
    return FP_OUTCOME_ERROR;
  else if (fp->fin_frame)
    return FP_OUTCOME_FRAME;

  return FP_OUTCOME_WAITING;
}
Example #9
0
void *
pamsshagentauth_buffer_append_space(Buffer *buffer, u_int len)
{
	u_int newlen;
	void *p;

	if (len > BUFFER_MAX_CHUNK)
		pamsshagentauth_fatal("buffer_append_space: len %u not supported", len);

	/* If the buffer is empty, start using it from the beginning. */
	if (buffer->offset == buffer->end) {
		buffer->offset = 0;
		buffer->end = 0;
	}
restart:
	/* If there is enough space to store all data, store it now. */
	if (buffer->end + len < buffer->alloc) {
		p = buffer->buf + buffer->end;
		buffer->end += len;
		return p;
	}

	/* Compact data back to the start of the buffer if necessary */
	if (buffer_compact(buffer))
		goto restart;

	/* Increase the size of the buffer and retry. */
	newlen = roundup(buffer->alloc + len, BUFFER_ALLOCSZ);
	if (newlen > BUFFER_MAX_LEN)
		pamsshagentauth_fatal("buffer_append_space: alloc %u not supported",
		    newlen);
	buffer->buf = pamsshagentauth_xrealloc(buffer->buf, 1, newlen);
	buffer->alloc = newlen;
	goto restart;
	/* NOTREACHED */
}
Example #10
0
int string_shrink_to_fit(string *s)
{
  return buffer_compact(&s->buffer);
}
Example #11
0
int cmd_check(int argc, char *argv[])
{
	struct buffer *comp_buf, *uncomp_buf;
	z_stream stream;
	struct stat st;
	int fd;

	setlocale(LC_ALL, "");

	if (argc < 2)
		usage();

	parse_args(argc, argv);

	init_stream(&stream);

	fd = open(filename, O_RDONLY);
	if (fd < 0)
		die("%s: %s: %s\n", program, filename, strerror(errno));

	if (fstat(fd, &st) < 0)
		die("%s: %s: %s\n", program, filename, strerror(errno));

	comp_buf = buffer_mmap(fd, st.st_size);
	if (!comp_buf)
		die("%s: %s\n", program, strerror(errno));

	stream.next_in = (void *) buffer_start(comp_buf);

	uncomp_buf = buffer_new(BUFFER_SIZE);
	if (!uncomp_buf)
		die("%s: %s\n", program, strerror(errno));

	for (;;) {
		struct itch41_message *msg;

retry_size:
		if (buffer_size(uncomp_buf) < sizeof(u16)) {
			ssize_t nr;

			buffer_compact(uncomp_buf);

			nr = buffer_inflate(comp_buf, uncomp_buf, &stream);
			if (nr < 0)
				die("%s: zlib error\n", program);

			if (!nr)
				break;

			if (show_progress)
				print_progress(comp_buf, st.st_size);

			goto retry_size;
		}

		buffer_advance(uncomp_buf, sizeof(u16));

retry_message:
		msg = itch41_message_decode(uncomp_buf);
		if (!msg) {
			ssize_t nr;

			buffer_compact(uncomp_buf);

			nr = buffer_inflate(comp_buf, uncomp_buf, &stream);
			if (nr < 0)
				die("%s: zlib error\n", program);

			if (!nr)
				break;

			if (show_progress)
				print_progress(comp_buf, st.st_size);

			goto retry_message;
		}

		if (verbose)
			printf("%c", msg->MessageType);

		stats[msg->MessageType - 'A']++;
	}

	printf("\n");

	buffer_munmap(comp_buf);

	buffer_delete(uncomp_buf);

	if (close(fd) < 0)
		die("%s: %s: %s\n", program, filename, strerror(errno));

	release_stream(&stream);

	print_stats();

	return 0;
}
Example #12
0
int
main(void)
{
    struct buffer one = { 0, 0, 0, NULL };
    struct buffer two = { 0, 0, 0, NULL };
    struct buffer *three;
    int fd;
    char *data;
    ssize_t count;
    size_t offset;

    plan(89);

    /* buffer_set, buffer_append, buffer_swap */
    buffer_set(&one, test_string1, sizeof(test_string1));
    is_int(1024, one.size, "minimum size is 1024");
    is_int(0, one.used, "used starts at 0");
    is_int(sizeof(test_string1), one.left, "left is correct");
    is_string(test_string1, one.data, "data is corect");
    buffer_append(&one, test_string2, sizeof(test_string2));
    is_int(1024, one.size, "appended data doesn't change size");
    is_int(0, one.used, "or used");
    is_int(sizeof(test_string3), one.left, "but left is the right size");
    ok(memcmp(one.data, test_string3, sizeof(test_string3)) == 0,
       "and the resulting data is correct");
    one.left -= sizeof(test_string1);
    one.used += sizeof(test_string1);
    buffer_append(&one, test_string1, sizeof(test_string1));
    is_int(1024, one.size, "size still isn't larger after adding data");
    is_int(sizeof(test_string1), one.used, "and used is preserved on append");
    is_int(sizeof(test_string3), one.left, "and left is updated properly");
    ok(memcmp(one.data + one.used, test_string2, sizeof(test_string2)) == 0,
       "and the middle data is unchanged");
    ok(memcmp(one.data + one.used + sizeof(test_string2), test_string1,
              sizeof(test_string1)) == 0, "and the final data is correct");
    buffer_set(&one, test_string1, sizeof(test_string1));
    buffer_set(&two, test_string2, sizeof(test_string2));
    buffer_swap(&one, &two);
    is_int(1024, one.size, "swap #1 size is correct");
    is_int(0, one.used, "swap #1 used is correct");
    is_int(sizeof(test_string2), one.left, "swap #1 left is correct");
    is_string(test_string2, one.data, "swap #1 data is correct");
    is_int(1024, two.size, "swap #2 size is correct");
    is_int(0, two.used, "swap #2 used is correct");
    is_int(sizeof(test_string1), two.left, "swap #2 left is correct");
    is_string(test_string1, two.data, "swap #2 data is correct");
    free(one.data);
    free(two.data);
    one.data = NULL;
    two.data = NULL;
    one.size = 0;
    two.size = 0;

    /* buffer_resize */
    three = buffer_new();
    ok(three != NULL, "buffer_new works");
    if (three == NULL)
        bail("buffer_new returned NULL");
    is_int(0, three->size, "initial size is 0");
    buffer_set(three, test_string1, sizeof(test_string1));
    is_int(1024, three->size, "size becomes 1024 when adding data");
    buffer_resize(three, 512);
    is_int(1024, three->size, "resizing to something smaller doesn't change");
    buffer_resize(three, 1025);
    is_int(2048, three->size, "resizing to something larger goes to 2048");
    buffer_free(three);

    /* buffer_read, buffer_find_string, buffer_compact */
    fd = open("buffer-test", O_RDWR | O_CREAT | O_TRUNC, 0666);
    if (fd < 0)
        sysbail("cannot create buffer-test");
    data = bmalloc(2048);
    memset(data, 'a', 1023);
    data[1023] = '\r';
    data[1024] = '\n';
    memset(data + 1025, 'b', 1023);
    if (xwrite(fd, data, 2048) < 2048)
        sysbail("cannot write to buffer-test");
    if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
        sysbail("cannot rewind buffer-test");
    three = buffer_new();
    ok(three != NULL, "buffer_new works");
    if (three == NULL)
        bail("buffer_new returned NULL");
    is_int(0, three->size, "and initial size is 0");
    buffer_resize(three, 1024);
    is_int(1024, three->size, "resize to 1024 works");
    count = buffer_read(three, fd);
    is_int(1024, count, "reading into a buffer of size 1024 reads 1024");
    offset = 0;
    ok(!buffer_find_string(three, "\r\n", 0, &offset),
       "buffer_find_string with truncated string fails");
    is_int(0, offset, "and offset is unchanged");
    ok(memcmp(three->data, data, three->size) == 0, "buffer data is correct");
    buffer_resize(three, 2048);
    is_int(2048, three->size, "resizing the buffer to 2048 works");
    count = buffer_read(three, fd);
    is_int(1024, count, "and now we can read the rest of the data");
    ok(memcmp(three->data, data, 2048) == 0, "and it's all there");
    ok(!buffer_find_string(three, "\r\n", 1024, &offset),
       "buffer_find_string with a string starting before offset fails");
    is_int(0, offset, "and offset is unchanged");
    ok(buffer_find_string(three, "\r\n", 0, &offset),
       "finding the string on the whole buffer works");
    is_int(1023, offset, "and returns the correct location");
    three->used += 400;
    three->left -= 400;
    buffer_compact(three);
    is_int(2048, three->size, "compacting buffer doesn't change the size");
    is_int(0, three->used, "but used is now zero");
    is_int(1648, three->left, "and left is decreased appropriately");
    ok(memcmp(three->data, data + 400, 1648) == 0, "and the data is correct");
    count = buffer_read(three, fd);
    is_int(0, count, "reading at EOF returns 0");
    close(fd);
    unlink("buffer-test");
    free(data);
    buffer_free(three);

    /* buffer_sprintf and buffer_append_sprintf */
    three = buffer_new();
    buffer_append_sprintf(three, "testing %d testing", 6);
    is_int(0, three->used, "buffer_append_sprintf doesn't change used");
    is_int(17, three->left, "but sets left correctly");
    buffer_append(three, "", 1);
    is_int(18, three->left, "appending a nul works");
    is_string("testing 6 testing", three->data, "and the data is correct");
    three->left--;
    three->used += 5;
    three->left -= 5;
    buffer_append_sprintf(three, " %d", 7);
    is_int(14, three->left, "appending a digit works");
    buffer_append(three, "", 1);
    is_string("testing 6 testing 7", three->data, "and the data is correct");
    buffer_sprintf(three, "%d testing", 8);
    is_int(9, three->left, "replacing the buffer works");
    is_string("8 testing", three->data, "and the results are correct");
    data = bmalloc(1050);
    memset(data, 'a', 1049);
    data[1049] = '\0';
    is_int(1024, three->size, "size before large sprintf is 1024");
    buffer_sprintf(three, "%s", data);
    is_int(2048, three->size, "size after large sprintf is 2048");
    is_int(1049, three->left, "and left is correct");
    buffer_append(three, "", 1);
    is_string(data, three->data, "and data is correct");
    free(data);
    buffer_free(three);

    /* buffer_read_all */
    fd = open("buffer-test", O_RDWR | O_CREAT | O_TRUNC, 0666);
    if (fd < 0)
        sysbail("cannot create buffer-test");
    data = bmalloc(2049);
    memset(data, 'a', 2049);
    if (xwrite(fd, data, 2049) < 2049)
        sysbail("cannot write to buffer-test");
    if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
        sysbail("cannot rewind buffer-test");
    three = buffer_new();
    ok(buffer_read_all(three, fd), "buffer_read_all succeeds");
    is_int(0, three->used, "and unused is zero");
    is_int(2049, three->left, "and left is correct");
    is_int(4096, three->size, "and size is correct");
    ok(memcmp(data, three->data, 2049) == 0, "and data is correct");
    if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
        sysbail("cannot rewind buffer-test");
    ok(buffer_read_all(three, fd), "reading again succeeds");
    is_int(0, three->used, "and used is correct");
    is_int(4098, three->left, "and left is now larger");
    is_int(8192, three->size, "and size doubled");
    ok(memcmp(data, three->data + 2049, 2049) == 0, "and data is correct");

    /* buffer_read_file */
    if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
        sysbail("cannot rewind buffer-test");
    buffer_free(three);
    three = buffer_new();
    ok(buffer_read_file(three, fd), "buffer_read_file succeeds");
    is_int(0, three->used, "and leaves unused at 0");
    is_int(2049, three->left, "and left is correct");
    is_int(3072, three->size, "and size is a multiple of 1024");
    ok(memcmp(data, three->data, 2049) == 0, "and the data is correct");

    /* buffer_read_all and buffer_read_file errors */
    close(fd);
    ok(!buffer_read_all(three, fd), "buffer_read_all on closed fd fails");
    is_int(3072, three->size, "and size is unchanged");
    ok(!buffer_read_file(three, fd), "buffer_read_file on closed fd fails");
    is_int(3072, three->size, "and size is unchanged");
    is_int(2049, three->left, "and left is unchanged");
    unlink("buffer-test");
    free(data);
    buffer_free(three);

    /* buffer_vsprintf and buffer_append_vsprintf */
    three = buffer_new();
    test_append_vsprintf(three, "testing %d testing", 6);
    is_int(0, three->used, "buffer_append_vsprintf leaves used as 0");
    is_int(17, three->left, "and left is correct");
    buffer_append(three, "", 1);
    is_int(18, three->left, "and left is correct after appending a nul");
    is_string("testing 6 testing", three->data, "and data is correct");
    three->left--;
    three->used += 5;
    three->left -= 5;
    test_append_vsprintf(three, " %d", 7);
    is_int(14, three->left, "and appending results in the correct left");
    buffer_append(three, "", 1);
    is_string("testing 6 testing 7", three->data, "and the right data");
    test_vsprintf(three, "%d testing", 8);
    is_int(9, three->left, "replacing the buffer results in the correct size");
    is_string("8 testing", three->data, "and the correct data");
    data = bmalloc(1050);
    memset(data, 'a', 1049);
    data[1049] = '\0';
    is_int(1024, three->size, "size is 1024 before large vsprintf");
    test_vsprintf(three, "%s", data);
    is_int(2048, three->size, "and 2048 afterwards");
    is_int(1049, three->left, "and left is correct");
    buffer_append(three, "", 1);
    is_string(data, three->data, "and data is correct");
    free(data);
    buffer_free(three);

    /* Test buffer_free with NULL and ensure it doesn't explode. */
    buffer_free(NULL);

    return 0;
}
Example #13
0
bool do_write(struct epoll_event *p_entry, some_fd epoll_fd)
{
	g2_connection_t *w_entry = (g2_connection_t *)p_entry->data.ptr;
	bool ret_val = true, more_write;
	ssize_t result = 0;
#ifdef DEBUG_DEVEL
	if(!w_entry->send) {
		logg_posd(LOGF_DEBUG, "%s Ip: %p#I\tFDNum: %i\n",
		          "no send buffer!", &w_entry->remote_host, w_entry->com_socket);
		w_entry->flags.dismissed = true;
		ret_val = false;
	}
#endif

	buffer_flip(*w_entry->send);
	do	{
		set_s_errno(0);
		result = my_epoll_send(epoll_fd, w_entry->com_socket, w_entry->send->data, w_entry->send->limit, 0);
	} while(-1 == result && EINTR == s_errno);

	switch(result)
	{
	default:
		w_entry->send->pos += result;
		w_entry->flags.has_written = true;
		w_entry->last_send = local_time_now;
		if(buffer_remaining(*w_entry->send))
			break;

		shortlock_lock(&w_entry->pts_lock);
		if(list_empty(&w_entry->packets_to_send)) {
			w_entry->poll_interrests &= ~((uint32_t)EPOLLOUT);
			more_write = true;
		} else
			more_write = false;

		if(more_write)
		{
			if(!(w_entry->poll_interrests & EPOLLONESHOT))
			{
				struct epoll_event t_entry;
				t_entry.data.u64 = p_entry->data.u64;
				t_entry.events = w_entry->poll_interrests;
				shortlock_unlock(&w_entry->pts_lock);

				if(0 > my_epoll_ctl(epoll_fd, EPOLL_CTL_MOD, w_entry->com_socket, &t_entry)) {
					logg_serrno(LOGF_DEBUG, "changing sockets Epoll-interrests");
					w_entry->flags.dismissed = true;
					ret_val = false;
				}
			}
			else
			{
				shortlock_unlock(&w_entry->pts_lock);

				if(w_entry->flags.dismissed) {
					logg_posd(LOGF_DEVEL_OLD, "%s\tIP: %p#I\tFDNum: %i\n",
					          "Dismissed!", &w_entry->remote_host, w_entry->com_socket);
					ret_val = false;
				}
			}
		}
		else
			shortlock_unlock(&w_entry->pts_lock);
		break;
	case  0:
		if(buffer_remaining(*w_entry->send))
		{
			if(EAGAIN != s_errno) {
				logg_posd(LOGF_DEVEL_OLD, "%s Ip: %p#I\tFDNum: %i\n",
				          "Dismissed!", &w_entry->remote_host, w_entry->com_socket);
				w_entry->flags.dismissed = true;
				ret_val = false;
			} else
				logg_devel("not ready to write\n");
		}
		else
		{
			shortlock_lock(&w_entry->pts_lock);
			w_entry->poll_interrests &= ~((uint32_t)EPOLLOUT);
			if(!(w_entry->poll_interrests & EPOLLONESHOT))
			{
				struct epoll_event t_entry;
				t_entry.data.u64 = p_entry->data.u64;
				t_entry.events = w_entry->poll_interrests;
				shortlock_unlock(&w_entry->pts_lock);

				if(0 > my_epoll_ctl(epoll_fd, EPOLL_CTL_MOD, w_entry->com_socket, &t_entry)) {
					logg_serrno(LOGF_DEBUG, "changing sockets Epoll-interrests");
					w_entry->flags.dismissed = true;
					ret_val = false;
				}
			}
			else
			{
				shortlock_unlock(&w_entry->pts_lock);

				if(w_entry->flags.dismissed) {
					logg_posd(LOGF_DEVEL_OLD, "%s ERRNO=%i Ip: %p#I\tFDNum: %i\n",
					          "EOF reached!", s_errno, &w_entry->remote_host, w_entry->com_socket);
					ret_val = false;
				}
			}
		}
		break;
	case -1:
		if(!(EAGAIN == errno || EWOULDBLOCK == s_errno)) {
			logg_serrno(LOGF_DEBUG, "write");
			ret_val = false;
		}
		break;
	}
	logg_develd_old("ret_val: %i\tpos: %u\tlim: %u\n", ret_val, w_entry->send->pos, w_entry->send->limit);
	buffer_compact(*w_entry->send);
	logg_develd_old("ret_val: %i\tpos: %u\tlim: %u\n", ret_val, w_entry->send->pos, w_entry->send->limit);
	return ret_val;
}
Example #14
0
int bats_pitch_read(struct stream *stream, struct pitch_message **msg_p)
{
	struct pitch_message *msg;
	unsigned char ch;

	*msg_p = NULL;

retry_size:
	if (buffer_size(stream->uncomp_buf) < sizeof(u8) + sizeof(struct pitch_message)) {
		ssize_t nr;

		buffer_compact(stream->uncomp_buf);

		nr = buffer_inflate(stream->comp_buf, stream->uncomp_buf, stream->zstream);
		if (nr < 0)
			return nr;

		if (!nr)
			return 0;

		if (stream->progress)
			stream->progress(stream->comp_buf);

		goto retry_size;
	}

	ch = buffer_peek_8(stream->uncomp_buf);
	if (ch != 0x53)
		return -EINVAL;

	buffer_advance(stream->uncomp_buf, sizeof(u8));

retry_message:
	msg = pitch_message_decode(stream->uncomp_buf, 1);
	if (!msg) {
		ssize_t nr;

		buffer_compact(stream->uncomp_buf);

		nr = buffer_inflate(stream->comp_buf, stream->uncomp_buf, stream->zstream);
		if (nr < 0)
			return nr;

		if (!nr)
			return 0;

		if (stream->progress)
			stream->progress(stream->comp_buf);

		goto retry_message;
	}

	ch = buffer_peek_8(stream->uncomp_buf);
	if (ch != 0x0A)
		return -EINVAL;

	buffer_advance(stream->uncomp_buf, sizeof(u8));

	*msg_p = msg;

	return 0;
}
Example #15
0
File: fork.c Project: hsaransa/std2
void std2_process_request()
{
    fork_state* fs = get_fork(current_fork_id);

    if (read_buffer_append(fs->to_client_fd[0], &fs->in_buffer, 20))
    {
        fprintf(stderr, "std2: child got disconnection\n");
        exit(1);
    }

    int marker = buffer_read_32(&fs->in_buffer);
    int req_id = buffer_read_32(&fs->in_buffer);

    if (marker == 'c')
    {
        int m = buffer_read_32(&fs->in_buffer);
        int f = buffer_read_32(&fs->in_buffer);
        int params_size = buffer_read_32(&fs->in_buffer);

        read_buffer_append(fs->to_client_fd[0], &fs->in_buffer, params_size);

        fprintf(stderr, "call id=%d, %d, %d, %d\n", req_id, m, f, params_size);

        // Construct parameters.

        void* start_ptr = buffer_cursor(&fs->in_buffer);
        void* end_ptr = (char*)buffer_cursor(&fs->in_buffer) + params_size;
        void* p = start_ptr;

        void* args[16];

        int param_count = std2_get_param_count(m, f);
        int i;
        for (i = 0; i < param_count; i++)
        {
            struct std2_param t = std2_get_param_type(m, f, i);
            switch (t.type)
            {
                case STD2_INT32:
                    args[i] = p;
                    p = (char*)p + 4;
                    break;

                case STD2_C_STRING:
                    {
                        int size = *(int*)p;
                        p = (char*)p + 4;
                        args[i] = p;
                        p = (char*)p + size;
                    }
                    break;

                case STD2_INSTANCE:
                    args[i] = *(void**)p;
                    p = (char*)p + sizeof(void*);
                    break;

                default:
                    fprintf(stderr, "std2: (c) unknown type %d\n", t.type);
                    abort();
            }

            assert(p <= end_ptr);
        }

        fs->in_buffer.pos += (char*)p - (char*)start_ptr;

        // Do the call.

        struct std2_param ret_type = std2_get_return_type(m, f);

        buffer_append_32(&fs->out_buffer, req_id); // size will be filled afterwards

        int size_pos = fs->out_buffer.size;
        buffer_append_32(&fs->out_buffer, 0); // size will be filled afterwards

        int ret;

        switch (ret_type.type)
        {
            case STD2_VOID:
                ret = std2_call(0, m, f, 0, args);
                break;

            case STD2_INT32:
                {
                    std2_int32 v;
                    ret = std2_call(0, m, f, &v, args);
                    if (!ret)
                        buffer_append_32(&fs->out_buffer, v);
                }
                break;

            case STD2_C_STRING:
                {
                    const char* v;
                    ret = std2_call(0, m, f, &v, args);
                    if (!ret)
                    {
                        int l = strlen(v) + 1;
                        int n = (l + 3) & ~3;
                        buffer_append_32(&fs->out_buffer, n);
                        buffer_append_data(&fs->out_buffer, v, l);
                        buffer_append_alignment(&fs->out_buffer, 4);
                    }
                }
                break;

            case STD2_INSTANCE:
                {
                    void* v;
                    ret = std2_call(0, m, f, &v, args);
                    if (!ret)
                        buffer_append_data(&fs->out_buffer, &v, sizeof(void*));
                }
                break;

            default:
                fprintf(stderr, "std2: (a) unknown type %d\n", ret_type.type);
                abort();
        }

        if (ret)
        {
            fprintf(stderr, "delayed return\n");
            fs->out_buffer.size -= 8; // req_id and size
            return;
        }

        *(int*)((char*)fs->out_buffer.data + size_pos) =
            fs->out_buffer.size - size_pos - 4;

        while (buffer_avail(&fs->out_buffer))
            write_buffer(fs->to_host_fd[1], &fs->out_buffer);

        fprintf(stderr, "response written\n");

        buffer_compact(&fs->in_buffer);
        buffer_compact(&fs->out_buffer);
    }
    else if (marker == 'u')
    {
        assert(!"todo unrefer");
    }
    else
    {
        fprintf(stderr, "std2: protocol error, bad marker %d\n", marker);
        abort();
    }
}