From 2e3d4c2080eaa47fe6c2cf7cb52a1ce81e85afe9 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 5 Apr 2011 11:54:44 +0200 Subject: vdagent-virtio-port: add write_{start,append} to help caller write a message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Inspired on a very similar patch for udscs written by Marc-André Lureau. --- src/vdagent-virtio-port.c | 81 +++++++++++++++++++++++++++++++++++++++-------- src/vdagent-virtio-port.h | 14 +++++++- 2 files changed, 81 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/vdagent-virtio-port.c b/src/vdagent-virtio-port.c index 02457d1..84e2e67 100644 --- a/src/vdagent-virtio-port.c +++ b/src/vdagent-virtio-port.c @@ -33,7 +33,8 @@ struct vdagent_virtio_port_buf { uint8_t *buf; size_t pos; size_t size; - + size_t write_pos; + struct vdagent_virtio_port_buf *next; }; @@ -151,12 +152,26 @@ void vdagent_virtio_port_handle_fds(struct vdagent_virtio_port **vportp, vdagent_virtio_port_do_write(vportp); } -int vdagent_virtio_port_write( +static struct vdagent_virtio_port_buf* vdagent_virtio_port_get_last_wbuf( + struct vdagent_virtio_port *vport) +{ + struct vdagent_virtio_port_buf *wbuf; + + wbuf = vport->write_buf; + if (!wbuf) + return NULL; + + while (wbuf->next) + wbuf = wbuf->next; + + return wbuf; +} + +int vdagent_virtio_port_write_start( struct vdagent_virtio_port *vport, uint32_t port_nr, uint32_t message_type, uint32_t message_opaque, - const uint8_t *data, uint32_t data_size) { struct vdagent_virtio_port_buf *wbuf, *new_wbuf; @@ -168,6 +183,7 @@ int vdagent_virtio_port_write( return -1; new_wbuf->pos = 0; + new_wbuf->write_pos = 0; new_wbuf->size = sizeof(chunk_header) + sizeof(message_header) + data_size; new_wbuf->next = NULL; new_wbuf->buf = malloc(new_wbuf->size); @@ -178,32 +194,66 @@ int vdagent_virtio_port_write( chunk_header.port = port_nr; chunk_header.size = sizeof(message_header) + data_size; + memcpy(new_wbuf->buf + new_wbuf->write_pos, &chunk_header, + sizeof(chunk_header)); + new_wbuf->write_pos += sizeof(chunk_header); + message_header.protocol = VD_AGENT_PROTOCOL; message_header.type = message_type; message_header.opaque = message_opaque; message_header.size = data_size; - - memcpy(new_wbuf->buf, &chunk_header, sizeof(chunk_header)); - memcpy(new_wbuf->buf + sizeof(chunk_header), &message_header, + memcpy(new_wbuf->buf + new_wbuf->write_pos, &message_header, sizeof(message_header)); - memcpy(new_wbuf->buf + sizeof(chunk_header) + sizeof(message_header), - data, data_size); + new_wbuf->write_pos += sizeof(message_header); if (!vport->write_buf) { vport->write_buf = new_wbuf; return 0; } - /* maybe we should limit the write_buf stack depth ? */ - wbuf = vport->write_buf; - while (wbuf->next) - wbuf = wbuf->next; - + wbuf = vdagent_virtio_port_get_last_wbuf(vport); wbuf->next = new_wbuf; return 0; } +int vdagent_virtio_port_write_append(struct vdagent_virtio_port *vport, + const uint8_t *data, uint32_t size) +{ + struct vdagent_virtio_port_buf *wbuf; + + wbuf = vdagent_virtio_port_get_last_wbuf(vport); + if (!wbuf) { + fprintf(vport->errfile, "can't append without a buffer"); + return -1; + } + + if (wbuf->size - wbuf->write_pos < size) { + fprintf(vport->errfile, "can't append to full buffer"); + return -1; + } + + memcpy(wbuf->buf + wbuf->write_pos, data, size); + wbuf->write_pos += size; + return 0; +} + +int vdagent_virtio_port_write( + struct vdagent_virtio_port *vport, + uint32_t port_nr, + uint32_t message_type, + uint32_t message_opaque, + const uint8_t *data, + uint32_t data_size) +{ + if (vdagent_virtio_port_write_start(vport, port_nr, message_type, + message_opaque, data_size)) { + return -1; + } + vdagent_virtio_port_write_append(vport, data, data_size); + return 0; +} + void vdagent_virtio_port_flush(struct vdagent_virtio_port **vportp) { while (*vportp && (*vportp)->write_buf) @@ -337,6 +387,11 @@ static void vdagent_virtio_port_do_write(struct vdagent_virtio_port **vportp) return; } + if (wbuf->write_pos != wbuf->size) { + fprintf(vport->errfile, "do_write: buffer is incomplete!!\n"); + return; + } + to_write = wbuf->size - wbuf->pos; n = write(vport->fd, wbuf->buf + wbuf->pos, to_write); if (n < 0) { diff --git a/src/vdagent-virtio-port.h b/src/vdagent-virtio-port.h index db446a1..b69f6a8 100644 --- a/src/vdagent-virtio-port.h +++ b/src/vdagent-virtio-port.h @@ -76,9 +76,21 @@ void vdagent_virtio_port_handle_fds(struct vdagent_virtio_port **vportp, fd_set *readfds, fd_set *writefds); -/* Queue a message for delivery +/* Queue a message for delivery, either bit by bit, or all at once Returns 0 on success -1 on error (only happens when malloc fails) */ +int vdagent_virtio_port_write_start( + struct vdagent_virtio_port *vport, + uint32_t port_nr, + uint32_t message_type, + uint32_t message_opaque, + uint32_t data_size); + +int vdagent_virtio_port_write_append( + struct vdagent_virtio_port *vport, + const uint8_t *data, + uint32_t size); + int vdagent_virtio_port_write( struct vdagent_virtio_port *vport, uint32_t port_nr, -- cgit