Пример #1
0
void test1() {
    struct Buffer *buffer;
    char input[] = "This is a test.";
    char output[sizeof(input)];
    int len, i;

    buffer = new_buffer();

    len = buffer_push(buffer, input, sizeof(input));
    assert(len == sizeof(input));


    len = buffer_peek(buffer, output, sizeof(output));
    assert(len == sizeof(input));

    for (i = 0; i < len; i++)
        assert(input[i] == output[i]);

    len = buffer_peek(buffer, output, sizeof(output));
    assert(len == sizeof(input));

    for (i = 0; i < len; i++)
        assert(input[i] == output[i]);

    len = buffer_pop(buffer, output, sizeof(output));
    assert(len == sizeof(input));

    for (i = 0; i < len; i++)
        assert(input[i] == output[i]);

    len = buffer_pop(buffer, output, sizeof(output));
    assert(len == 0);
    
    free_buffer(buffer);
}
Пример #2
0
static void test2() {
    struct Buffer *buffer;
    char input[] = "Testing wrap around behaviour.";
    char output[sizeof(input)];
    int len, i = 0;

    buffer = new_buffer(200, EV_DEFAULT);
    assert(buffer != NULL);

    while (i < 180) {
        len = buffer_push(buffer, input, sizeof(input));
        assert(len == sizeof(input));

        i += len;
    }

    while (len) {
        len = buffer_pop(buffer, output, sizeof(output));
    }

    len = buffer_push(buffer, input, sizeof(input));
    assert(len == sizeof(input));


    len = buffer_peek(buffer, output, sizeof(output));
    assert(len == sizeof(input));

    for (i = 0; i < len; i++)
        assert(input[i] == output[i]);

    len = buffer_pop(buffer, output, sizeof(output));
    assert(len == sizeof(input));

    for (i = 0; i < len; i++)
        assert(input[i] == output[i]);

    len = buffer_push(buffer, input, sizeof(input));
    assert(len == sizeof(input));


    len = buffer_peek(buffer, output, sizeof(output));
    assert(len == sizeof(input));

    for (i = 0; i < len; i++)
        assert(input[i] == output[i]);

    free_buffer(buffer);
}
Пример #3
0
void Lexer::consumeIdentifier()
{
	m_value = "";

	for (;;) {
		if (buffer_empty()) {
			buffer_put(m_input->get());
		}
		char current = buffer_peek();

		/*
		 * The XML spec allows much narrower set of valid identifiers, but
		 * I see not charm in accepting some of the malformed identifiers
		 * since the parser is not very strict about standard too.
		 */
		// TODO: Replace it with std::isspace in the future.
		if (isspace(current) ||
		    current == '<' || current == '>' ||
		    current == '=' || current == '/' || current == '?' ||
		    current == '"' || current == '\'' ||
		    current == std::char_traits<char>::eof())
		{
			break;
		}

		m_value.push_back(buffer_pop());
	}

	m_token = token::identifier;
}
Пример #4
0
void Lexer::consumeString()
{
	m_value = "";

	char delim = buffer_pop();
	for (;;) {
		if (buffer_empty()) {
			buffer_put(m_input->get());
		}
		char current = buffer_peek();

		if (current == delim) {
			buffer_pop();
			break;
		}

		if (current == std::char_traits<char>::eof()) {
			break;
		}

		m_value.push_back(buffer_pop());
	}

	m_token = token::string;
}
Пример #5
0
static void test3() {
    struct Buffer *buffer;
    char input[] = "Test buffer resizing.";
    char output[sizeof(input)];
    int len, i;

    buffer = new_buffer(200, EV_DEFAULT);
    assert(buffer != NULL);

    len = buffer_push(buffer, input, sizeof(input));
    assert(len == sizeof(input));

    /* Test resizing to too small of a buffer size */
    len = buffer_resize(buffer, 5);
    assert(len == -1);


    buffer_resize(buffer, 40);
    assert(buffer_room(buffer) == 40 - sizeof(input));

    len = buffer_peek(buffer, output, sizeof(output));
    assert(len == sizeof(input));

    for (i = 0; i < len; i++)
        assert(input[i] == output[i]);

    free_buffer(buffer);
}
Пример #6
0
int
send_file_fd (int out_fd, int in_fd, uint64 offset, uint64 size, uint64 *sent)
{
  char data_in[BUFFER_INSIZE];
  char data_out[BUFFER_OUTSIZE];
  struct buffer buf_in;
  struct buffer buf_out;
  int64 r;
  int64 w;
  uint64 r_sent = 0;
  char *x;

  buffer_init (&buf_in, (buffer_op) read, in_fd, data_in, sizeof (data_in));
  buffer_init (&buf_out, (buffer_op) write, out_fd, data_out, sizeof (data_out));

  for (;;) {
    r = buffer_feed (&buf_in);
    if (r == 0) break;
    if (r == -1) goto FAIL;
    x = buffer_peek (&buf_in);
    w = buffer_put (&buf_out, x, r);
    if (w == -1) goto FAIL;
    buffer_seek (&buf_in, r);
    r_sent += w;
  }
  *sent = r_sent;
  return 0;

  FAIL:
  *sent = r_sent;
  return -1;
}
Пример #7
0
size_t
buffer_pop(struct Buffer *src, void *dst, size_t len) {
    size_t bytes;

    bytes = buffer_peek(src, dst, len);

    if (bytes > 0)
        advance_read_position(src, bytes);

    return bytes;
}
Пример #8
0
static void test1() {
    struct Buffer *buffer;
    char input[] = "This is a test.";
    char output[sizeof(input)];
    int len, i;

    buffer = new_buffer(200, EV_DEFAULT);
    assert(buffer != NULL);

    len = buffer_push(buffer, input, sizeof(input));
    assert(len == sizeof(input));


    len = buffer_peek(buffer, output, sizeof(output));
    assert(len == sizeof(input));

    for (i = 0; i < len; i++)
        assert(input[i] == output[i]);

    /* second peek to ensure the first didn't permute the state of the buffer */
    len = buffer_peek(buffer, output, sizeof(output));
    assert(len == sizeof(input));

    for (i = 0; i < len; i++)
        assert(input[i] == output[i]);

    /* test pop */
    len = buffer_pop(buffer, output, sizeof(output));
    assert(len == sizeof(input));

    for (i = 0; i < len; i++)
        assert(input[i] == output[i]);

    len = buffer_pop(buffer, output, sizeof(output));
    assert(len == 0);

    free_buffer(buffer);
}
unsigned short buffer_read( register struct buffer_t * buffer, register char * local, const unsigned short count)
{
	//read_ptr moves by number of bytes read
	unsigned short did_read = buffer_peek( buffer, local, count );
	buffer->read_ptr += did_read;
	
	//whenever the read and write ptrs are equal, pounsigned short them all back to the start
	if(buffer->read_ptr == buffer->write_ptr )
	{
		buffer->read_ptr = buffer->write_ptr = buffer->buffer;	
	}

	return did_read; //number of bytes read
}
Пример #10
0
xml::token Lexer::nextToken()
{
	while (skipWhitespace() || skipComments()) {
	}

	if (buffer_empty()) {
		buffer_put(m_input->get());
	}

	switch (buffer_peek()) {
	case '<':
		m_token = token::chevron_left;
		buffer_pop();
		break;
	case '>':
		m_token = token::chevron_right;
		buffer_pop();
		break;
	case '?':
		m_token = token::questionMark;
		buffer_pop();
		break;
	case '=':
		m_token = token::assignment;
		buffer_pop();
		break;
	case '/':
		m_token = token::slash;
		buffer_pop();
		break;
	case '"': case '\'':
		consumeString();
		break;
	case EOF:
		/*
		 * TODO: Replace EOF with std::char_traits<char>::eof() once VS
		 * will learn what "constexpr" is.
		 */
		m_token = token::eof;
		buffer_pop();
		break;
	default:
		consumeIdentifier();
		break;
	}

	return m_token;
}
Пример #11
0
ssize_t
buffer_resize(struct Buffer *buf, size_t new_size) {
    char *new_buffer;

    if (new_size < buf->len)
        return -1; /* new_size too small to hold existing data */

    new_buffer = malloc(new_size);
    if (new_buffer == NULL)
        return -2;

    buffer_peek(buf, new_buffer, new_size);

    free(buf->buffer);
    buf->buffer = new_buffer;
    buf->size = new_size;
    buf->head = 0;

    return buf->len;
}
Пример #12
0
bool Lexer::skipWhitespace()
{
	bool consumed = false;

	for (;;) {
		if (buffer_empty()) {
			buffer_put(m_input->get());
		}
		char current = buffer_peek();

		// TODO: Replace it with std::isspace in the future.
		if (!isspace(current)) {
			break;
		}

		buffer_pop();
		consumed = true;
	}

	return consumed;
}
Пример #13
0
void Lexer::consumeText()
{
	m_value = "";

	for (;;) {
		while (skipComments()) {
		}

		if (buffer_empty()) {
			buffer_put(m_input->get());
		}
		char current = buffer_peek();

		// TODO: Escape '&lt;' and '&gt;' as '<' and '>';
		if (current == '<' || current == '>' ||
		    current == std::char_traits<char>::eof())
		{
			break;
		}

		m_value.push_back(buffer_pop());
	}
}
//This is the implementation of the UIPAPP that uIP will call when
//something network data related happens.
//The purpose of this app is to move buffer data to and from the network
void uip_socket_app(void)
{
    int i;
    file_handle_t file_handle =  (uip_conn->appstate)[0];
    struct file_t* file = NULL;
    struct buffer_t *rxbuf = NULL;
    struct buffer_t *txbuf = NULL;
    bool may_send = true;

#ifdef __DEBUG
    printf("\r\napp: process conn @ %p", uip_conn);
#endif


    if(uip_connected())
    {
#ifdef __DEBUG
        printf("\r\napp: connected. Ports %hd:%hd", uip_conn->lport, uip_conn->rport);
#endif
        if( file_handle == FILE_INVALID_HANDLE )
        {
            //it's an incoming connection (no assigned handle)
            //find the index of the listening port
            for( i = 0; i < UIP_LISTENPORTS ; i++ )
            {
                if( uip_listenports[i] == uip_conn->lport )
                {
                    file_handle = listenports[i](uip_conn->lport, uip_conn->ripaddr, uip_conn->rport);
                    if( file_handle != FILE_INVALID_HANDLE )
                    {
                        uip_conn->appstate[0] = file_handle;
                    }
                    break;
                }
            }
        }
    }
    if( file_handle == FILE_INVALID_HANDLE)
    {
        goto close_or_abort;
    }

    file =  file_get_by_handle(file_handle);
    rxbuf = file->read_buffer;
    txbuf = file->write_buffer;


    if( file->state == ClosePending )
    {
#ifdef __DEBUG
        printf("\r\napp: freeing handle %hhd",uip_conn->appstate[0]);
#endif
        file_free(uip_conn->appstate[0]);
        uip_conn->appstate[0] = FILE_INVALID_HANDLE;
        goto close_or_abort;
    }


    if( rxbuf == NULL || txbuf == NULL )
    {
        goto close_or_abort;
    }

    if( uip_connected() ) file->state = Open;

    if( uip_acked() ) {
#ifdef __DEBUG
        printf("\r\napp: acked %d bytes", uip_this_ack);
#endif
        buffer_seek( txbuf, uip_this_ack );
    }

    int free = buffer_free( rxbuf );//free to write to
    int available = buffer_available( txbuf );//available to read

    if(uip_rexmit()) {
//#ifdef __DEBUG
        printf("\r\napp: rexmit. Handle: %hhd", file_handle);
//#endif
        buffer_peek( txbuf, (char*)uip_appdata, uip_conn->len);
        uip_send(uip_appdata, uip_conn->len);
        may_send = false;
    }
    else if(uip_newdata())
    {
#ifdef __DEBUG
        printf("\r\napp: newdata. Handle: %hhd. len=%u\n", file_handle, uip_datalen() );
#endif
        if( free >= uip_datalen() )
        {
            free -= buffer_write( rxbuf, (char*)uip_appdata, uip_datalen() );
        }
        else {
            puts("buffer overflow\n");
        }
    }
    else if( uip_closed() )
    {
#ifdef __DEBUG
        printf("\r\napp: connection id %hhd closed\n", file_handle );
#endif
        file->state = Closed;
        may_send = false;
    }
    else if( uip_aborted() )
    {
#ifdef __DEBUG
        printf("\r\napp: connection id %hhd aborted\n", file_handle );
#endif
        file->state = Aborted;
        may_send = false;
    }
    else if( uip_timedout() )
    {
#ifdef __DEBUG
        printf("\r\napp: connection id %hhd timed out\n", file_handle );
#endif
        file->state = TimedOut;
        may_send = false;
    }
//	if( available >  0 && file->state > Open )
//	{
//		buffer_seek( txbuf, available);
//	}
    if( available > 0 && may_send && uip_conn->len == 0) {
        //we can send the smaller of what's available or the connection mss
        int size = available < uip_mss() ? available : uip_mss() ;
        int peek = buffer_peek( txbuf, (char*)uip_appdata, size);
        uip_appdata[peek] = '\0';
#ifdef __DEBUG
        printf("\r\napp: sending %d of %d available bytes: [%s] ", peek,available, (char*)uip_appdata);
#endif
        uip_send(uip_appdata, peek);

    }
    /*
    This code prevents the "silly-window" TCP problem
    The problem is though, that we want to fill our rx buffer entirely
    sometimes before acting on it.
    I've disabled this code in the meantime, until we can
    set the behaviour on a connection basis
    ...Or it becomes apparent that we just don't need it.

    if( free < rxbuf->size / 2 )
    {
    	puts("\napp: stopping rx\n");
    	uip_stop();
    }
    else if( uip_stopped(uip_conn) )
    {
    	puts("\napp: restarting rx\n");
    	uip_restart(); //TODO NEED to be able to set the window size?
    }
    */
    //...instead let's try setting the window size
    uip_receive_window = free;
    return;

close_or_abort:
    if( uip_closed() || uip_aborted() || uip_timedout() )
    {
        puts("\r\napp: abort chosen");
        uip_abort();
    }
    else
    {
        puts("\r\napp: close chosen");
        uip_close();
    }

}
Пример #15
0
uint8_t uart1_peek(uint8_t position)
{
	return buffer_peek(&buffer_rx1, position); // doesn't modify buffer, no need to disable interrupts
}
Пример #16
0
static 
void connection_onevent(int fd, int event, void* userdata)
{
    tcp_connection_t *connection = (tcp_connection_t*)userdata;
	inetaddr_t *peer_addr = &connection->peer_addr;
	
    buffer_t* in_buffer;
    buffer_t* out_buffer;
    void* data;
    unsigned size;
    unsigned written;
    int error;

    log_debug("connection_onevent: fd(%d), event(%d), peer addr: %s:%u", fd, event, peer_addr->ip, peer_addr->port);

    if (event & EPOLLHUP)
    {
        connection->is_connected = 0;
        connection->is_in_callback = 1;
        connection->closecb(connection, connection->userdata);
        connection->is_in_callback = 0;
    }
    else
    {
        if (event & EPOLLIN)
        {
            if (connection->need_closed_after_sent_done == 0)
            {
                in_buffer = connection->in_buffer;
                size = buffer_readFd(in_buffer, connection->fd);
                if (0 == size)
                {
                    assert(NULL != connection->closecb);
                    connection->is_connected = 0;
                    connection->is_in_callback = 1;
                    connection->closecb(connection, connection->userdata);
                    connection->is_in_callback = 0;
                }
                else
                {
                    assert(NULL != connection->datacb);
                    connection->is_in_callback = 1;
                    connection->datacb(connection, in_buffer, connection->userdata);
                    connection->is_in_callback = 0;
                }
            }
            else
            {
                char temp[256];
                while (read(fd, temp, sizeof(temp)) > 0);
            }
        }

        if (event & EPOLLOUT)
        {
            out_buffer = connection->out_buffer;
            data = buffer_peek(out_buffer);
            size = buffer_readablebytes(out_buffer);
            written = write(connection->fd, data, size);
            if (written < 0)
            {
                error = errno;
                if (error != EAGAIN && error != EINTR)
                {
                    log_error("connection_onevent: write() failed, fd(%d), errno(%d), peer addr: %s:%u", fd, error, peer_addr->ip, peer_addr->port);
                    return;
                }
                else
                {
                    written = 0;
                }
            }

            buffer_retrieve(out_buffer, written);

            if(written >= size)
            {
                channel_clearevent(connection->channel, EPOLLOUT);
                
                if (connection->need_closed_after_sent_done)
                {
                    connection->is_alive = 0;
                }
            }
        }
    }

    if (0 == connection->is_alive)
    {
        delete_connection(connection);
    }

    return;
}
Пример #17
0
void
xml_read_callback(xmlreader* r, xml_read_callback_fn* fn) {
  ssize_t n;
  buffer* b = r->b;
  stralloc tag, attr, val;
  stralloc_init(&tag);
  stralloc_init(&attr);
  stralloc_init(&val);
  hmap_init(XML_HMAP_BUCKETS, &r->attrmap);

  while((n = buffer_skip_until(b, "<", 1)) > 0) {
    const char* s;
    stralloc_zero(&tag);
    r->self_closing = r->closing = 0;
    s = buffer_peek(b);

    if(*s == '/') {
      r->closing = 1;
      buffer_skipc(b);
    } else if(*s == '?') {
      r->self_closing = 1;
    } else if(*s == '!') {
      if(buffer_skip_until(b, ">", 1) <= 0)
        return;
      continue;
    }
    if((n = buffer_gettok_sa(b, &tag, " \n\t\r\v/>", 7)) < 0)
      return;
    stralloc_nul(&tag);
    buffer_skipspace(b);

    while((s = buffer_peek(b)) && isalpha(*s)) {
      char ch;
      int quoted = 0;
      const char* charset;
      stralloc_zero(&attr);
      stralloc_zero(&val);
      if((n = buffer_gettok_sa(b, &attr, "=", 1)) < 0)
        break;
      if(buffer_skipc(b) < 0)
        return;

      if(*buffer_peek(b) == '"') {
        if(buffer_skipc(b) < 0)
          return;
        quoted = 1;
      }
      charset = quoted ? "\"" : "/> \t\r\n\v";
      if((n = buffer_gettok_sa(b, &val, charset, str_len(charset))) < 0)
        break;
      if(quoted && buffer_skipc(b) < 0)
        return;
      stralloc_nul(&attr);
      stralloc_nul(&val);
      hmap_set(&r->attrmap, attr.s, attr.len, val.s, val.len + 1);
      if(!fn(r, XML_ATTRIBUTE, &attr, &val, NULL))
        return;
      buffer_skipspace(b);
    }
    buffer_skipspace(b);

    if((s = buffer_peek(b)) && str_chr("/?", *s) < 2) {
      r->self_closing = 1;
      r->closing = 0;
      buffer_skipc(b);
    }
    buffer_skipspace(b);
    if((s = buffer_peek(b)) && *s == '>')
      buffer_skipc(b);
    if(!fn(r, XML_ELEMENT, &tag, NULL, &r->attrmap))
      return;

    if(r->attrmap) {
      hmap_destroy(&r->attrmap);
      r->attrmap = NULL;
    }
    hmap_init(XML_HMAP_BUCKETS, &r->attrmap);
    stralloc_zero(&tag);
    if((n = buffer_gettok_sa(b, &tag, "<", 1)) < 0)
      return;
    s = buffer_peek(b);

    if(!is_whitespace(tag.s, tag.len)) {
      if(!fn(r, XML_TEXT, NULL, &tag, NULL))
        return;
    }
  }
}
Пример #18
0
struct Buffer *
new_buffer(int size) {
    struct Buffer *buf;

    buf = malloc(sizeof(struct Buffer));
    if (buf == NULL)
        return NULL;

    buf->size = size;
    buf->len = 0;
    buf->head = 0;
    buf->tx_bytes = 0;
    buf->rx_bytes = 0;
    buf->last_recv = (struct timespec){.tv_sec = 0, .tv_nsec = 0};
    buf->last_send = (struct timespec){.tv_sec = 0, .tv_nsec = 0};
    buf->buffer = malloc(buf->size);
    if (buf->buffer == NULL) {
        free(buf);
        buf = NULL;
    }

    return buf;
}

ssize_t
buffer_resize(struct Buffer *buf, size_t new_size) {
    char *new_buffer;

    if (new_size < buf->len)
        return -1; /* new_size too small to hold existing data */

    new_buffer = malloc(new_size);
    if (new_buffer == NULL)
        return -2;

    if (buffer_peek(buf, new_buffer, new_size) != buf->len) {
        err("failed to copy existing buffer contents into new buffer");
        free(new_buffer);
        return -3;
    }

    free(buf->buffer);
    buf->buffer = new_buffer;
    buf->head = 0;

    return buf->len;
}

void
free_buffer(struct Buffer *buf) {
    if (buf == NULL)
        return;

    free(buf->buffer);
    free(buf);
}

ssize_t
buffer_recv(struct Buffer *buffer, int sockfd, int flags) {
    ssize_t bytes;
    struct iovec iov[2];
    struct msghdr msg;

    /* coalesce when reading into an empty buffer */
    if (buffer->len == 0)
        buffer->head = 0;

    msg.msg_name = NULL;
    msg.msg_namelen = 0;
    msg.msg_iov = iov;
    msg.msg_iovlen = setup_write_iov(buffer, iov, 0);
    msg.msg_control = NULL;
    msg.msg_controllen = 0;
    msg.msg_flags = 0;

    bytes = recvmsg(sockfd, &msg, flags);

    if (clock_gettime(CLOCK_MONOTONIC, &buffer->last_recv) < 0)
        err("clock_gettime() failed: %s", strerror(errno));

    if (bytes > 0)
        advance_write_position(buffer, bytes);

    return bytes;
}
Пример #19
0
static 
int tcp_connection_sendInLoop(tcp_connection_t* connection, const void* data, unsigned size)
{
	inetaddr_t *peer_addr = &connection->peer_addr;
	
    int fd;
    void* buffer_data;
    channel_t *channel;
    buffer_t* out_buffer;
    int written;
    unsigned buffer_left_data_size;
    struct iovec vecs[2];

    int error;

    out_buffer = connection->out_buffer;
    channel = connection->channel;
    fd = connection->fd;

    buffer_left_data_size = buffer_readablebytes(out_buffer);

    if (buffer_left_data_size > 0)
    {
        buffer_data = buffer_peek(out_buffer);
        vecs[0].iov_base = buffer_data;
        vecs[0].iov_len = buffer_left_data_size;
        vecs[1].iov_base = (void*)data;
        vecs[1].iov_len = size;
        
        written = writev(fd, vecs, 2);
        if (written < 0)
        {
            error = errno;
            
            if (error != EAGAIN)
            {
                log_error("tcp_connection_sendInLoop: writev() failed, errno: %d, peer addr: %s:%u", errno, peer_addr->ip, peer_addr->port);
                return -1;
            }
        }
        else if (written == (buffer_left_data_size+size))
        {
            /* 当前所有的数据都发送完毕,一切安好则去除EPOLLOUT事件 */
            channel_clearevent(channel, EPOLLOUT);
        }
        else if (written < buffer_left_data_size)
        {
            /* out_buffer中的数据尚未发送完毕,则将本次的数据放入out_buffer后再发送 */
            buffer_retrieve(out_buffer, written);
            buffer_append(out_buffer, data, size);
            channel_setevent(channel, EPOLLOUT);
        }
        else if (written < (buffer_left_data_size+size))
        {
            buffer_retrieveall(out_buffer);
            buffer_append(out_buffer, ((const char*)data+written-buffer_left_data_size), ((buffer_left_data_size+size)-written));
            channel_setevent(channel, EPOLLOUT);
        }
    }
    else
    {
        written = write(fd, data, size);
        if (written < 0)
        {
            log_error("tcp_connection_sendInLoop: write() failed, errno: %d, peer addr: %s:%u", errno, peer_addr->ip, peer_addr->port);
            return -1;
        }
        else if (written < size)
        {
            buffer_append(out_buffer, ((const char*)data+written), (size-written));
            channel_setevent(channel, EPOLLOUT);
        }
    }

    return 0;
}