/** * This method is used to read and consume the input buffer * @arg conn The client connection * @arg bytes The number of bytes to read * @arg buf Output parameter, sets the start of the buffer. * @arg should_free Output parameter, should the buffer be freed by the caller. * @return 0 on success, -1 if there is insufficient data. */ int read_client_bytes(statsite_conn_info *conn, int bytes, char** buf, int* should_free) { if (unlikely(bytes > circbuf_used_buf(&conn->input))) return -1; // Handle the wrap around case if (unlikely(conn->input.write_cursor < conn->input.read_cursor)) { // Check if we can use a contiguous chunk int end_size = conn->input.buf_size - conn->input.read_cursor; if (end_size >= bytes) { *buf = conn->input.buffer + conn->input.read_cursor; *should_free = 0; // Otherwise, allocate a dynamic slab, and copy } else { *buf = malloc(bytes); memcpy(*buf, conn->input.buffer + conn->input.read_cursor, end_size); memcpy(*buf + end_size, conn->input.buffer, bytes - end_size); *should_free = 1; } // Handle the contiguous case } else { *buf = conn->input.buffer + conn->input.read_cursor; *should_free = 0; } // Advance the read cursor circbuf_advance_read(&conn->input, bytes); return 0; }
/** * This method is used to peek into the input buffer without * causing input to be consumed. * @arg conn The client connection * @arg bytes The number of bytes to peek * @arg buf The output buffer to write to * @return 0 on success, -1 if there is insufficient data. */ int peek_client_bytes(statsite_proxy_conn_info *conn, int bytes, char* buf) { // Ensure we have sufficient data if (bytes > circbuf_used_buf(&conn->input)) return -1; // Copy the bytes int offset = conn->input.read_cursor; int buf_size = conn->input.buf_size; for (int i=0; i < bytes; i++) { buf[i] = conn->input.buffer[(offset + i) % buf_size]; } return 0; }
/** * This method is used to seek the input buffer without * consuming input. It can be used in conjunction with * peek_client_bytes to conditionally seek. * @arg conn The client connection * @arg bytes The number of bytes to seek * @return 0 on success, -1 if there is insufficient data. */ int seek_client_bytes(statsite_conn_info *conn, int bytes) { if (unlikely(bytes > circbuf_used_buf(&conn->input))) return -1; circbuf_advance_read(&conn->input, bytes); return 0; }
/** * Lets the caller look at the next byte * @arg conn The client connectoin * @arg byte The output byte * @return 0 on success, -1 if there is no data. */ int peek_client_byte(statsite_conn_info *conn, unsigned char* byte) { if (unlikely(!circbuf_used_buf(&conn->input))) return -1; *byte = *(unsigned char*)(conn->input.buffer+conn->input.read_cursor); return 0; }
/** * This method is used to query how much data is available * to be read from the command buffer. * @arg conn The client connection * @return The bytes available */ uint64_t available_bytes(statsite_conn_info *conn) { // Query the circular buffer return circbuf_used_buf(&conn->input); }