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); buffer->last_recv = ev_now(EV_DEFAULT); if (bytes > 0) advance_write_position(buffer, bytes); return bytes; }
/* * Read data from file into buffer */ ssize_t buffer_read(struct Buffer *buffer, int fd) { ssize_t bytes; struct iovec iov[2]; /* coalesce when reading into an empty buffer */ if (buffer->len == 0) buffer->head = 0; bytes = readv(fd, iov, setup_write_iov(buffer, iov, 0)); if (bytes > 0) advance_write_position(buffer, bytes); return bytes; }
size_t buffer_push(struct Buffer *dst, const void *src, size_t len) { struct iovec iov[2]; size_t bytes_appended = 0; /* coalesce when reading into an empty buffer */ if (dst->len == 0) dst->head = 0; if (dst->size - dst->len < len) return -1; /* insufficient room */ size_t iov_len = setup_write_iov(dst, iov, len); for (size_t i = 0; i < iov_len; i++) { memcpy(iov[i].iov_base, (char *)src + bytes_appended, iov[i].iov_len); bytes_appended += iov[i].iov_len; } if (bytes_appended > 0) advance_write_position(dst, bytes_appended); return bytes_appended; }
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; }