On 18/09/2015 15:19, Daniel P. Berrange wrote: > The Buffer code in the VNC server is useful for the IO channel > code, so pull it out into a shared module, QIOBuffer.
Do all traces disappear from VNC once you're done? If not, can you instead move it to util/? Paolo > Signed-off-by: Daniel P. Berrange <berra...@redhat.com> > --- > include/io/buffer.h | 118 > ++++++++++++++++++++++++++++++++++++++++++++++++++++ > io/Makefile.objs | 3 +- > io/buffer.c | 65 +++++++++++++++++++++++++++++ > ui/vnc-auth-sasl.c | 4 +- > ui/vnc-enc-tight.c | 38 ++++++++--------- > ui/vnc-enc-zlib.c | 6 +-- > ui/vnc-enc-zrle.c | 18 ++++---- > ui/vnc-jobs.c | 15 +++---- > ui/vnc-ws.c | 36 ++++++++-------- > ui/vnc-ws.h | 6 +-- > ui/vnc.c | 67 ++++++----------------------- > ui/vnc.h | 50 ++++++++-------------- > 12 files changed, 277 insertions(+), 149 deletions(-) > create mode 100644 include/io/buffer.h > create mode 100644 io/buffer.c > > diff --git a/include/io/buffer.h b/include/io/buffer.h > new file mode 100644 > index 0000000..2b1b261 > --- /dev/null > +++ b/include/io/buffer.h > @@ -0,0 +1,118 @@ > +/* > + * QEMU I/O buffers > + * > + * Copyright (c) 2015 Red Hat, Inc. > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, see > <http://www.gnu.org/licenses/>. > + * > + */ > + > +#ifndef QIO_BUFFER_H__ > +#define QIO_BUFFER_H__ > + > +#include "qemu-common.h" > + > +typedef struct QIOBuffer QIOBuffer; > + > +/** > + * QIOBuffer: > + * > + * The QIOBuffer object provides a simple dynamically resizing > + * array, with separate tracking of capacity and usage. This > + * is typically useful when buffering I/O data. > + */ > + > +struct QIOBuffer { > + size_t capacity; > + size_t offset; > + uint8_t *buffer; > +}; > + > +/** > + * qio_buffer_reserve: > + * @buffer: the buffer object > + * @len: the minimum required free space > + * > + * Ensure that the buffer has space allocated for at least > + * @len bytes. If the current buffer is too small, it will > + * be reallocated, possibly to a larger size than requested. > + */ > +void qio_buffer_reserve(QIOBuffer *buffer, size_t len); > + > +/** > + * qio_buffer_reset: > + * @buffer: the buffer object > + * > + * Reset the length of the stored data to zero, but do > + * not free / reallocate the memory buffer > + */ > +void qio_buffer_reset(QIOBuffer *buffer); > + > +/** > + * qio_buffer_free: > + * @buffer: the buffer object > + * > + * Reset the length of the stored data to zero and also > + * free the internal memory buffer > + */ > +void qio_buffer_free(QIOBuffer *buffer); > + > +/** > + * qio_buffer_append: > + * @buffer: the buffer object > + * @data: the data block to append > + * @len: the length of @data in bytes > + * > + * Append the contents of @data to the end of the buffer. > + * The caller must ensure that the buffer has sufficient > + * free space for @len bytes, typically by calling the > + * qio_buffer_reserve() method prior to appending. > + */ > +void qio_buffer_append(QIOBuffer *buffer, const void *data, size_t len); > + > +/** > + * qio_buffer_advance: > + * @buffer: the buffer object > + * @len: the number of bytes to skip > + * > + * Remove @len bytes of data from the head of the buffer. > + * The internal buffer will not be reallocated, so will > + * have at least @len bytes of free space after this > + * call completes > + */ > +void qio_buffer_advance(QIOBuffer *buffer, size_t len); > + > +/** > + * qio_buffer_end: > + * @buffer: the buffer object > + * > + * Get a pointer to the tail end of the internal buffer > + * The returned pointer is only valid until the next > + * call to qio_buffer_reserve(). > + * > + * Returns: the tail of the buffer > + */ > +uint8_t *qio_buffer_end(QIOBuffer *buffer); > + > +/** > + * qio_buffer_empty: > + * @buffer: the buffer object > + * > + * Determine if the buffer contains any current data > + * > + * Returns: true if the buffer holds data, false otherwise > + */ > +gboolean qio_buffer_empty(QIOBuffer *buffer); > + > +#endif /* QIO_BUFFER_H__ */ > diff --git a/io/Makefile.objs b/io/Makefile.objs > index b02ea90..593ed9e 100644 > --- a/io/Makefile.objs > +++ b/io/Makefile.objs > @@ -1,2 +1,3 @@ > -io-obj-y = channel.o > +io-obj-y = buffer.o > +io-obj-y += channel.o > io-obj-y += channel-watch.o > diff --git a/io/buffer.c b/io/buffer.c > new file mode 100644 > index 0000000..68ae68d > --- /dev/null > +++ b/io/buffer.c > @@ -0,0 +1,65 @@ > +/* > + * QEMU I/O buffers > + * > + * Copyright (c) 2015 Red Hat, Inc. > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, see > <http://www.gnu.org/licenses/>. > + * > + */ > + > +#include "io/buffer.h" > + > +void qio_buffer_reserve(QIOBuffer *buffer, size_t len) > +{ > + if ((buffer->capacity - buffer->offset) < len) { > + buffer->capacity += (len + 1024); > + buffer->buffer = g_realloc(buffer->buffer, buffer->capacity); > + } > +} > + > +gboolean qio_buffer_empty(QIOBuffer *buffer) > +{ > + return buffer->offset == 0; > +} > + > +uint8_t *qio_buffer_end(QIOBuffer *buffer) > +{ > + return buffer->buffer + buffer->offset; > +} > + > +void qio_buffer_reset(QIOBuffer *buffer) > +{ > + buffer->offset = 0; > +} > + > +void qio_buffer_free(QIOBuffer *buffer) > +{ > + g_free(buffer->buffer); > + buffer->offset = 0; > + buffer->capacity = 0; > + buffer->buffer = NULL; > +} > + > +void qio_buffer_append(QIOBuffer *buffer, const void *data, size_t len) > +{ > + memcpy(buffer->buffer + buffer->offset, data, len); > + buffer->offset += len; > +} > + > +void qio_buffer_advance(QIOBuffer *buffer, size_t len) > +{ > + memmove(buffer->buffer, buffer->buffer + len, > + (buffer->offset - len)); > + buffer->offset -= len; > +} > diff --git a/ui/vnc-auth-sasl.c b/ui/vnc-auth-sasl.c > index fc732bd..d118266 100644 > --- a/ui/vnc-auth-sasl.c > +++ b/ui/vnc-auth-sasl.c > @@ -113,8 +113,8 @@ long vnc_client_read_sasl(VncState *vs) > return vnc_client_io_error(vs, -1, -EIO); > VNC_DEBUG("Read SASL Encoded %p size %ld Decoded %p size %d\n", > encoded, ret, decoded, decodedLen); > - buffer_reserve(&vs->input, decodedLen); > - buffer_append(&vs->input, decoded, decodedLen); > + qio_buffer_reserve(&vs->input, decodedLen); > + qio_buffer_append(&vs->input, decoded, decodedLen); > return decodedLen; > } > > diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c > index 9a9ddf2..772ec79 100644 > --- a/ui/vnc-enc-tight.c > +++ b/ui/vnc-enc-tight.c > @@ -856,7 +856,7 @@ static int tight_compress_data(VncState *vs, int > stream_id, size_t bytes, > } > > /* reserve memory in output buffer */ > - buffer_reserve(&vs->tight.zlib, bytes + 64); > + qio_buffer_reserve(&vs->tight.zlib, bytes + 64); > > /* set pointers */ > zstream->next_in = vs->tight.tight.buffer; > @@ -879,7 +879,7 @@ static int tight_compress_data(VncState *vs, int > stream_id, size_t bytes, > tight_send_compact_size(vs, bytes); > vnc_write(vs, vs->tight.zlib.buffer, bytes); > > - buffer_reset(&vs->tight.zlib); > + qio_buffer_reset(&vs->tight.zlib); > > return bytes; > } > @@ -1053,7 +1053,7 @@ static bool send_gradient_rect(VncState *vs, int x, int > y, int w, int h) > vnc_write_u8(vs, (stream | VNC_TIGHT_EXPLICIT_FILTER) << 4); > vnc_write_u8(vs, VNC_TIGHT_FILTER_GRADIENT); > > - buffer_reserve(&vs->tight.gradient, w * 3 * sizeof (int)); > + qio_buffer_reserve(&vs->tight.gradient, w * 3 * sizeof(int)); > > if (vs->tight.pixel24) { > tight_filter_gradient24(vs, vs->tight.tight.buffer, w, h); > @@ -1066,7 +1066,7 @@ static bool send_gradient_rect(VncState *vs, int x, int > y, int w, int h) > bytes = 2; > } > > - buffer_reset(&vs->tight.gradient); > + qio_buffer_reset(&vs->tight.gradient); > > bytes = w * h * bytes; > vs->tight.tight.offset = bytes; > @@ -1149,7 +1149,7 @@ static int send_palette_rect(VncState *vs, int x, int y, > static void jpeg_init_destination(j_compress_ptr cinfo) > { > VncState *vs = cinfo->client_data; > - Buffer *buffer = &vs->tight.jpeg; > + QIOBuffer *buffer = &vs->tight.jpeg; > > cinfo->dest->next_output_byte = (JOCTET *)buffer->buffer + > buffer->offset; > cinfo->dest->free_in_buffer = (size_t)(buffer->capacity - > buffer->offset); > @@ -1159,10 +1159,10 @@ static void jpeg_init_destination(j_compress_ptr > cinfo) > static boolean jpeg_empty_output_buffer(j_compress_ptr cinfo) > { > VncState *vs = cinfo->client_data; > - Buffer *buffer = &vs->tight.jpeg; > + QIOBuffer *buffer = &vs->tight.jpeg; > > buffer->offset = buffer->capacity; > - buffer_reserve(buffer, 2048); > + qio_buffer_reserve(buffer, 2048); > jpeg_init_destination(cinfo); > return TRUE; > } > @@ -1171,7 +1171,7 @@ static boolean jpeg_empty_output_buffer(j_compress_ptr > cinfo) > static void jpeg_term_destination(j_compress_ptr cinfo) > { > VncState *vs = cinfo->client_data; > - Buffer *buffer = &vs->tight.jpeg; > + QIOBuffer *buffer = &vs->tight.jpeg; > > buffer->offset = buffer->capacity - cinfo->dest->free_in_buffer; > } > @@ -1190,7 +1190,7 @@ static int send_jpeg_rect(VncState *vs, int x, int y, > int w, int h, int quality) > return send_full_color_rect(vs, x, y, w, h); > } > > - buffer_reserve(&vs->tight.jpeg, 2048); > + qio_buffer_reserve(&vs->tight.jpeg, 2048); > > cinfo.err = jpeg_std_error(&jerr); > jpeg_create_compress(&cinfo); > @@ -1227,7 +1227,7 @@ static int send_jpeg_rect(VncState *vs, int x, int y, > int w, int h, int quality) > > tight_send_compact_size(vs, vs->tight.jpeg.offset); > vnc_write(vs, vs->tight.jpeg.buffer, vs->tight.jpeg.offset); > - buffer_reset(&vs->tight.jpeg); > + qio_buffer_reset(&vs->tight.jpeg); > > return 1; > } > @@ -1270,7 +1270,7 @@ static void png_write_data(png_structp png_ptr, > png_bytep data, > { > VncState *vs = png_get_io_ptr(png_ptr); > > - buffer_reserve(&vs->tight.png, vs->tight.png.offset + length); > + qio_buffer_reserve(&vs->tight.png, vs->tight.png.offset + length); > memcpy(vs->tight.png.buffer + vs->tight.png.offset, data, length); > > vs->tight.png.offset += length; > @@ -1351,7 +1351,7 @@ static int send_png_rect(VncState *vs, int x, int y, > int w, int h, > > png_write_info(png_ptr, info_ptr); > > - buffer_reserve(&vs->tight.png, 2048); > + qio_buffer_reserve(&vs->tight.png, 2048); > linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, w); > buf = (uint8_t *)pixman_image_get_data(linebuf); > for (dy = 0; dy < h; dy++) > @@ -1377,14 +1377,14 @@ static int send_png_rect(VncState *vs, int x, int y, > int w, int h, > > tight_send_compact_size(vs, vs->tight.png.offset); > vnc_write(vs, vs->tight.png.buffer, vs->tight.png.offset); > - buffer_reset(&vs->tight.png); > + qio_buffer_reset(&vs->tight.png); > return 1; > } > #endif /* CONFIG_VNC_PNG */ > > static void vnc_tight_start(VncState *vs) > { > - buffer_reset(&vs->tight.tight); > + qio_buffer_reset(&vs->tight.tight); > > // make the output buffer be the zlib buffer, so we can compress it later > vs->tight.tmp = vs->output; > @@ -1686,13 +1686,13 @@ void vnc_tight_clear(VncState *vs) > } > } > > - buffer_free(&vs->tight.tight); > - buffer_free(&vs->tight.zlib); > - buffer_free(&vs->tight.gradient); > + qio_buffer_free(&vs->tight.tight); > + qio_buffer_free(&vs->tight.zlib); > + qio_buffer_free(&vs->tight.gradient); > #ifdef CONFIG_VNC_JPEG > - buffer_free(&vs->tight.jpeg); > + qio_buffer_free(&vs->tight.jpeg); > #endif > #ifdef CONFIG_VNC_PNG > - buffer_free(&vs->tight.png); > + qio_buffer_free(&vs->tight.png); > #endif > } > diff --git a/ui/vnc-enc-zlib.c b/ui/vnc-enc-zlib.c > index d1b97f2..47ba146 100644 > --- a/ui/vnc-enc-zlib.c > +++ b/ui/vnc-enc-zlib.c > @@ -47,7 +47,7 @@ void vnc_zlib_zfree(void *x, void *addr) > > static void vnc_zlib_start(VncState *vs) > { > - buffer_reset(&vs->zlib.zlib); > + qio_buffer_reset(&vs->zlib.zlib); > > // make the output buffer be the zlib buffer, so we can compress it later > vs->zlib.tmp = vs->output; > @@ -96,7 +96,7 @@ static int vnc_zlib_stop(VncState *vs) > } > > // reserve memory in output buffer > - buffer_reserve(&vs->output, vs->zlib.zlib.offset + 64); > + qio_buffer_reserve(&vs->output, vs->zlib.zlib.offset + 64); > > // set pointers > zstream->next_in = vs->zlib.zlib.buffer; > @@ -148,5 +148,5 @@ void vnc_zlib_clear(VncState *vs) > if (vs->zlib.stream.opaque) { > deflateEnd(&vs->zlib.stream); > } > - buffer_free(&vs->zlib.zlib); > + qio_buffer_free(&vs->zlib.zlib); > } > diff --git a/ui/vnc-enc-zrle.c b/ui/vnc-enc-zrle.c > index ed3b484..bd1e320 100644 > --- a/ui/vnc-enc-zrle.c > +++ b/ui/vnc-enc-zrle.c > @@ -36,7 +36,7 @@ static const int bits_per_packed_pixel[] = { > > static void vnc_zrle_start(VncState *vs) > { > - buffer_reset(&vs->zrle.zrle); > + qio_buffer_reset(&vs->zrle.zrle); > > /* make the output buffer be the zlib buffer, so we can compress it > later */ > vs->zrle.tmp = vs->output; > @@ -53,10 +53,10 @@ static void vnc_zrle_stop(VncState *vs) > static void *zrle_convert_fb(VncState *vs, int x, int y, int w, int h, > int bpp) > { > - Buffer tmp; > + QIOBuffer tmp; > > - buffer_reset(&vs->zrle.fb); > - buffer_reserve(&vs->zrle.fb, w * h * bpp + bpp); > + qio_buffer_reset(&vs->zrle.fb); > + qio_buffer_reserve(&vs->zrle.fb, w * h * bpp + bpp); > > tmp = vs->output; > vs->output = vs->zrle.fb; > @@ -72,7 +72,7 @@ static int zrle_compress_data(VncState *vs, int level) > { > z_streamp zstream = &vs->zrle.stream; > > - buffer_reset(&vs->zrle.zlib); > + qio_buffer_reset(&vs->zrle.zlib); > > if (zstream->opaque != vs) { > int err; > @@ -92,7 +92,7 @@ static int zrle_compress_data(VncState *vs, int level) > } > > /* reserve memory in output buffer */ > - buffer_reserve(&vs->zrle.zlib, vs->zrle.zrle.offset + 64); > + qio_buffer_reserve(&vs->zrle.zlib, vs->zrle.zrle.offset + 64); > > /* set pointers */ > zstream->next_in = vs->zrle.zrle.buffer; > @@ -360,7 +360,7 @@ void vnc_zrle_clear(VncState *vs) > if (vs->zrle.stream.opaque) { > deflateEnd(&vs->zrle.stream); > } > - buffer_free(&vs->zrle.zrle); > - buffer_free(&vs->zrle.fb); > - buffer_free(&vs->zrle.zlib); > + qio_buffer_free(&vs->zrle.zrle); > + qio_buffer_free(&vs->zrle.fb); > + qio_buffer_free(&vs->zrle.zlib); > } > diff --git a/ui/vnc-jobs.c b/ui/vnc-jobs.c > index 22c9abc..9824c34 100644 > --- a/ui/vnc-jobs.c > +++ b/ui/vnc-jobs.c > @@ -54,7 +54,7 @@ struct VncJobQueue { > QemuCond cond; > QemuMutex mutex; > QemuThread thread; > - Buffer buffer; > + QIOBuffer buffer; > bool exit; > QTAILQ_HEAD(, VncJob) jobs; > }; > @@ -167,7 +167,7 @@ void vnc_jobs_consume_buffer(VncState *vs) > vnc_lock_output(vs); > if (vs->jobs_buffer.offset) { > vnc_write(vs, vs->jobs_buffer.buffer, vs->jobs_buffer.offset); > - buffer_reset(&vs->jobs_buffer); > + qio_buffer_reset(&vs->jobs_buffer); > } > flush = vs->csock != -1 && vs->abort != true; > vnc_unlock_output(vs); > @@ -196,7 +196,7 @@ static void vnc_async_encoding_start(VncState *orig, > VncState *local) > local->output = queue->buffer; > local->csock = -1; /* Don't do any network work on this thread */ > > - buffer_reset(&local->output); > + qio_buffer_reset(&local->output); > } > > static void vnc_async_encoding_end(VncState *orig, VncState *local) > @@ -273,10 +273,11 @@ static int vnc_worker_thread_loop(VncJobQueue *queue) > vs.output.buffer[saved_offset + 1] = n_rectangles & 0xFF; > > vnc_lock_output(job->vs); > + > if (job->vs->csock != -1) { > - buffer_reserve(&job->vs->jobs_buffer, vs.output.offset); > - buffer_append(&job->vs->jobs_buffer, vs.output.buffer, > - vs.output.offset); > + qio_buffer_reserve(&job->vs->jobs_buffer, vs.output.offset); > + qio_buffer_append(&job->vs->jobs_buffer, vs.output.buffer, > + vs.output.offset); > /* Copy persistent encoding data */ > vnc_async_encoding_end(job->vs, &vs); > > @@ -310,7 +311,7 @@ static void vnc_queue_clear(VncJobQueue *q) > { > qemu_cond_destroy(&queue->cond); > qemu_mutex_destroy(&queue->mutex); > - buffer_free(&queue->buffer); > + qio_buffer_free(&queue->buffer); > g_free(q); > queue = NULL; /* Unset global queue */ > } > diff --git a/ui/vnc-ws.c b/ui/vnc-ws.c > index 175ea50..2fe4476 100644 > --- a/ui/vnc-ws.c > +++ b/ui/vnc-ws.c > @@ -95,8 +95,8 @@ void vncws_handshake_read(void *opaque) > /* Typical HTTP headers from novnc are 512 bytes, so limiting > * total header size to 4096 is easily enough. */ > size_t want = 4096 - vs->ws_input.offset; > - buffer_reserve(&vs->ws_input, want); > - ret = vnc_client_read_buf(vs, buffer_end(&vs->ws_input), want); > + qio_buffer_reserve(&vs->ws_input, want); > + ret = vnc_client_read_buf(vs, qio_buffer_end(&vs->ws_input), want); > > if (!ret) { > if (vs->csock == -1) { > @@ -111,7 +111,7 @@ void vncws_handshake_read(void *opaque) > if (handshake_end) { > qemu_set_fd_handler(vs->csock, vnc_client_read, NULL, vs); > vncws_process_handshake(vs, vs->ws_input.buffer, > vs->ws_input.offset); > - buffer_advance(&vs->ws_input, handshake_end - vs->ws_input.buffer + > + qio_buffer_advance(&vs->ws_input, handshake_end - > vs->ws_input.buffer + > strlen(WS_HANDSHAKE_END)); > } else if (vs->ws_input.offset >= 4096) { > VNC_DEBUG("End of headers not found in first 4096 bytes\n"); > @@ -127,8 +127,8 @@ long vnc_client_read_ws(VncState *vs) > size_t payload_size, header_size; > VNC_DEBUG("Read websocket %p size %zd offset %zd\n", vs->ws_input.buffer, > vs->ws_input.capacity, vs->ws_input.offset); > - buffer_reserve(&vs->ws_input, 4096); > - ret = vnc_client_read_buf(vs, buffer_end(&vs->ws_input), 4096); > + qio_buffer_reserve(&vs->ws_input, 4096); > + ret = vnc_client_read_buf(vs, qio_buffer_end(&vs->ws_input), 4096); > if (!ret) { > return 0; > } > @@ -146,7 +146,7 @@ long vnc_client_read_ws(VncState *vs) > return err; > } > > - buffer_advance(&vs->ws_input, header_size); > + qio_buffer_advance(&vs->ws_input, header_size); > } > if (vs->ws_payload_remain != 0) { > err = vncws_decode_frame_payload(&vs->ws_input, > @@ -162,10 +162,10 @@ long vnc_client_read_ws(VncState *vs) > } > ret += err; > > - buffer_reserve(&vs->input, payload_size); > - buffer_append(&vs->input, payload, payload_size); > + qio_buffer_reserve(&vs->input, payload_size); > + qio_buffer_append(&vs->input, payload, payload_size); > > - buffer_advance(&vs->ws_input, payload_size); > + qio_buffer_advance(&vs->ws_input, payload_size); > } > } while (vs->ws_input.offset > 0); > > @@ -178,13 +178,13 @@ long vnc_client_write_ws(VncState *vs) > VNC_DEBUG("Write WS: Pending output %p size %zd offset %zd\n", > vs->output.buffer, vs->output.capacity, vs->output.offset); > vncws_encode_frame(&vs->ws_output, vs->output.buffer, vs->output.offset); > - buffer_reset(&vs->output); > + qio_buffer_reset(&vs->output); > ret = vnc_client_write_buf(vs, vs->ws_output.buffer, > vs->ws_output.offset); > if (!ret) { > return 0; > } > > - buffer_advance(&vs->ws_output, ret); > + qio_buffer_advance(&vs->ws_output, ret); > > if (vs->ws_output.offset == 0) { > qemu_set_fd_handler(vs->csock, vnc_client_read, NULL, vs); > @@ -267,8 +267,8 @@ void vncws_process_handshake(VncState *vs, uint8_t *line, > size_t size) > g_free(key); > } > > -void vncws_encode_frame(Buffer *output, const void *payload, > - const size_t payload_size) > +void vncws_encode_frame(QIOBuffer *output, const void *payload, > + const size_t payload_size) > { > size_t header_size = 0; > unsigned char opcode = WS_OPCODE_BINARY_FRAME; > @@ -295,12 +295,12 @@ void vncws_encode_frame(Buffer *output, const void > *payload, > header_size = 10; > } > > - buffer_reserve(output, header_size + payload_size); > - buffer_append(output, header.buf, header_size); > - buffer_append(output, payload, payload_size); > + qio_buffer_reserve(output, header_size + payload_size); > + qio_buffer_append(output, header.buf, header_size); > + qio_buffer_append(output, payload, payload_size); > } > > -int vncws_decode_frame_header(Buffer *input, > +int vncws_decode_frame_header(QIOBuffer *input, > size_t *header_size, > size_t *payload_remain, > WsMask *payload_mask) > @@ -354,7 +354,7 @@ int vncws_decode_frame_header(Buffer *input, > return 1; > } > > -int vncws_decode_frame_payload(Buffer *input, > +int vncws_decode_frame_payload(QIOBuffer *input, > size_t *payload_remain, WsMask *payload_mask, > uint8_t **payload, size_t *payload_size) > { > diff --git a/ui/vnc-ws.h b/ui/vnc-ws.h > index 4ab0a8c..2a222a8 100644 > --- a/ui/vnc-ws.h > +++ b/ui/vnc-ws.h > @@ -77,13 +77,13 @@ void vncws_handshake_read(void *opaque); > long vnc_client_write_ws(VncState *vs); > long vnc_client_read_ws(VncState *vs); > void vncws_process_handshake(VncState *vs, uint8_t *line, size_t size); > -void vncws_encode_frame(Buffer *output, const void *payload, > +void vncws_encode_frame(QIOBuffer *output, const void *payload, > const size_t payload_size); > -int vncws_decode_frame_header(Buffer *input, > +int vncws_decode_frame_header(QIOBuffer *input, > size_t *header_size, > size_t *payload_remain, > WsMask *payload_mask); > -int vncws_decode_frame_payload(Buffer *input, > +int vncws_decode_frame_payload(QIOBuffer *input, > size_t *payload_remain, WsMask *payload_mask, > uint8_t **payload, size_t *payload_size); > > diff --git a/ui/vnc.c b/ui/vnc.c > index 952e551..c4dec90 100644 > --- a/ui/vnc.c > +++ b/ui/vnc.c > @@ -647,49 +647,6 @@ void vnc_framebuffer_update(VncState *vs, int x, int y, > int w, int h, > vnc_write_s32(vs, encoding); > } > > -void buffer_reserve(Buffer *buffer, size_t len) > -{ > - if ((buffer->capacity - buffer->offset) < len) { > - buffer->capacity += (len + 1024); > - buffer->buffer = g_realloc(buffer->buffer, buffer->capacity); > - } > -} > - > -static int buffer_empty(Buffer *buffer) > -{ > - return buffer->offset == 0; > -} > - > -uint8_t *buffer_end(Buffer *buffer) > -{ > - return buffer->buffer + buffer->offset; > -} > - > -void buffer_reset(Buffer *buffer) > -{ > - buffer->offset = 0; > -} > - > -void buffer_free(Buffer *buffer) > -{ > - g_free(buffer->buffer); > - buffer->offset = 0; > - buffer->capacity = 0; > - buffer->buffer = NULL; > -} > - > -void buffer_append(Buffer *buffer, const void *data, size_t len) > -{ > - memcpy(buffer->buffer + buffer->offset, data, len); > - buffer->offset += len; > -} > - > -void buffer_advance(Buffer *buf, size_t len) > -{ > - memmove(buf->buffer, buf->buffer + len, > - (buf->offset - len)); > - buf->offset -= len; > -} > > static void vnc_desktop_resize(VncState *vs) > { > @@ -1220,10 +1177,10 @@ void vnc_disconnect_finish(VncState *vs) > vnc_lock_output(vs); > vnc_qmp_event(vs, QAPI_EVENT_VNC_DISCONNECTED); > > - buffer_free(&vs->input); > - buffer_free(&vs->output); > - buffer_free(&vs->ws_input); > - buffer_free(&vs->ws_output); > + qio_buffer_free(&vs->input); > + qio_buffer_free(&vs->output); > + qio_buffer_free(&vs->ws_input); > + qio_buffer_free(&vs->ws_output); > > qapi_free_VncClientInfo(vs->info); > > @@ -1251,7 +1208,7 @@ void vnc_disconnect_finish(VncState *vs) > if (vs->bh != NULL) { > qemu_bh_delete(vs->bh); > } > - buffer_free(&vs->jobs_buffer); > + qio_buffer_free(&vs->jobs_buffer); > > for (i = 0; i < VNC_STAT_ROWS; ++i) { > g_free(vs->lossy_rect[i]); > @@ -1393,7 +1350,7 @@ static ssize_t vnc_client_write_plain(VncState *vs) > if (!ret) > return 0; > > - buffer_advance(&vs->output, ret); > + qio_buffer_advance(&vs->output, ret); > > if (vs->output.offset == 0) { > qemu_set_fd_handler(vs->csock, vnc_client_read, NULL, vs); > @@ -1496,8 +1453,8 @@ static ssize_t vnc_client_read_plain(VncState *vs) > ssize_t ret; > VNC_DEBUG("Read plain %p size %zd offset %zd\n", > vs->input.buffer, vs->input.capacity, vs->input.offset); > - buffer_reserve(&vs->input, 4096); > - ret = vnc_client_read_buf(vs, buffer_end(&vs->input), 4096); > + qio_buffer_reserve(&vs->input, 4096); > + ret = vnc_client_read_buf(vs, qio_buffer_end(&vs->input), 4096); > if (!ret) > return 0; > vs->input.offset += ret; > @@ -1555,7 +1512,7 @@ void vnc_client_read(void *opaque) > } > > if (!ret) { > - buffer_advance(&vs->input, len); > + qio_buffer_advance(&vs->input, len); > } else { > vs->read_handler_expect = ret; > } > @@ -1564,13 +1521,13 @@ void vnc_client_read(void *opaque) > > void vnc_write(VncState *vs, const void *data, size_t len) > { > - buffer_reserve(&vs->output, len); > + qio_buffer_reserve(&vs->output, len); > > - if (vs->csock != -1 && buffer_empty(&vs->output)) { > + if (vs->csock != -1 && qio_buffer_empty(&vs->output)) { > qemu_set_fd_handler(vs->csock, vnc_client_read, vnc_client_write, > vs); > } > > - buffer_append(&vs->output, data, len); > + qio_buffer_append(&vs->output, data, len); > } > > void vnc_write_s32(VncState *vs, int32_t value) > diff --git a/ui/vnc.h b/ui/vnc.h > index 4dd769c..339a1bf 100644 > --- a/ui/vnc.h > +++ b/ui/vnc.h > @@ -34,6 +34,7 @@ > #include "audio/audio.h" > #include "qemu/bitmap.h" > #include "crypto/tlssession.h" > +#include "io/buffer.h" > #include <zlib.h> > #include <stdbool.h> > > @@ -56,13 +57,6 @@ > * > > *****************************************************************************/ > > -typedef struct Buffer > -{ > - size_t capacity; > - size_t offset; > - uint8_t *buffer; > -} Buffer; > - > typedef struct VncState VncState; > typedef struct VncJob VncJob; > typedef struct VncRect VncRect; > @@ -191,15 +185,15 @@ typedef struct VncTight { > uint8_t quality; > uint8_t compression; > uint8_t pixel24; > - Buffer tight; > - Buffer tmp; > - Buffer zlib; > - Buffer gradient; > + QIOBuffer tight; > + QIOBuffer tmp; > + QIOBuffer zlib; > + QIOBuffer gradient; > #ifdef CONFIG_VNC_JPEG > - Buffer jpeg; > + QIOBuffer jpeg; > #endif > #ifdef CONFIG_VNC_PNG > - Buffer png; > + QIOBuffer png; > #endif > int levels[4]; > z_stream stream[4]; > @@ -210,18 +204,18 @@ typedef struct VncHextile { > } VncHextile; > > typedef struct VncZlib { > - Buffer zlib; > - Buffer tmp; > + QIOBuffer zlib; > + QIOBuffer tmp; > z_stream stream; > int level; > } VncZlib; > > typedef struct VncZrle { > int type; > - Buffer fb; > - Buffer zrle; > - Buffer tmp; > - Buffer zlib; > + QIOBuffer fb; > + QIOBuffer zrle; > + QIOBuffer tmp; > + QIOBuffer zlib; > z_stream stream; > VncPalette palette; > } VncZrle; > @@ -290,10 +284,10 @@ struct VncState > > VncClientInfo *info; > > - Buffer output; > - Buffer input; > - Buffer ws_input; > - Buffer ws_output; > + QIOBuffer output; > + QIOBuffer input; > + QIOBuffer ws_input; > + QIOBuffer ws_output; > size_t ws_payload_remain; > WsMask ws_payload_mask; > /* current output mode information */ > @@ -315,7 +309,7 @@ struct VncState > bool initialized; > QemuMutex output_mutex; > QEMUBH *bh; > - Buffer jobs_buffer; > + QIOBuffer jobs_buffer; > > /* Encoding specific, if you add something here, don't forget to > * update vnc_async_encoding_start() > @@ -535,14 +529,6 @@ ssize_t vnc_client_io_error(VncState *vs, ssize_t ret, > int last_errno); > void start_client_init(VncState *vs); > void start_auth_vnc(VncState *vs); > > -/* Buffer management */ > -void buffer_reserve(Buffer *buffer, size_t len); > -void buffer_reset(Buffer *buffer); > -void buffer_free(Buffer *buffer); > -void buffer_append(Buffer *buffer, const void *data, size_t len); > -void buffer_advance(Buffer *buf, size_t len); > -uint8_t *buffer_end(Buffer *buffer); > - > > /* Misc helpers */ > >