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); }
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); }
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; }
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; }
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); }
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; }
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; }
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 }
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; }
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; }
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; }
void Lexer::consumeText() { m_value = ""; for (;;) { while (skipComments()) { } if (buffer_empty()) { buffer_put(m_input->get()); } char current = buffer_peek(); // TODO: Escape '<' and '>' 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(); } }
uint8_t uart1_peek(uint8_t position) { return buffer_peek(&buffer_rx1, position); // doesn't modify buffer, no need to disable interrupts }
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; }
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; } } }
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; }
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; }