diff options
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | src/stream-send.c | 99 |
3 files changed, 100 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am index 272542f..3a13c55 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,6 +8,7 @@ common_sources = \ src_spice_stream_send_CFLAGS = \ $(SPICE_CFLAGS) \ + $(GLIB2_CFLAGS) \ -I$(srcdir)/src \ $(NULL) diff --git a/configure.ac b/configure.ac index e44c667..e8dd6b9 100644 --- a/configure.ac +++ b/configure.ac @@ -17,6 +17,7 @@ AC_DEFINE(_GNU_SOURCE, [1], [Enable GNU extensions]) PKG_PROG_PKG_CONFIG PKG_CHECK_MODULES(SPICE, [spice-protocol >= 0.12.8]) +PKG_CHECK_MODULES([GLIB2], [glib-2.0 >= 2.28]) # If no CFLAGS are set, set some sane default CFLAGS if test "$ac_test_CFLAGS" != set; then diff --git a/src/stream-send.c b/src/stream-send.c index 27504c0..fee9961 100644 --- a/src/stream-send.c +++ b/src/stream-send.c @@ -22,10 +22,14 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <stdbool.h> #include <errno.h> #include <unistd.h> #include <fcntl.h> #include <err.h> +#include <poll.h> +#include <assert.h> +#include <glib.h> #include <spice/stream-device.h> #include <spice/enums.h> @@ -65,6 +69,82 @@ write_all(int fd, const void *buf, size_t len) return written; } +static bool got_start = false; +static bool got_stop = false; + +static void +on_message(StreamDevType type, const uint8_t *data, size_t size) +{ + assert(type == STREAM_TYPE_STREAM_START); + assert(size >= sizeof(StreamMsgStart)); + + const StreamMsgStart *start = (const StreamMsgStart *) data; + if (start->num_codecs) { + printf("got start\n"); + got_start = true; + } else { + printf("got stop\n"); + got_stop = true; + } +} + +static void +on_data(void) +{ + static unsigned hdr_pos = 0; + static StreamDevHeader hdr; + static unsigned data_pos = 0; + static uint8_t data[128]; + + // read header + while (hdr_pos < sizeof(hdr)) { + int n = read(device_fd, ((uint8_t *) &hdr) + hdr_pos, sizeof(hdr) - hdr_pos); + if (n == -1 && errno == EINTR) + continue; + if (n == -1) + err(1, "read"); + hdr_pos += n; + if (hdr_pos >= sizeof(hdr)) { + assert(hdr.protocol_version == STREAM_DEVICE_PROTOCOL); + hdr.type = GUINT16_FROM_LE(hdr.type); + hdr.size = GUINT32_FROM_LE(hdr.size); + data_pos = 0; + } + } + + // read data + assert(hdr.size < sizeof(data)); + while (data_pos < hdr.size) { + int n = read(device_fd, data + data_pos, hdr.size - data_pos); + if (n == -1 && errno == EINTR) + continue; + if (n == -1) + err(1, "read"); + data_pos += n; + } + + hdr_pos = 0; + on_message((StreamDevType) hdr.type, data, data_pos); +} + +static int +wait_read(int fd, int timeout) +{ + for (;;) { + struct pollfd poll_fd = { fd, POLLIN, 0 }; + switch (poll(&poll_fd, 1, timeout)) { + case -1: + if (errno == EINTR) + continue; + err(1, "poll"); + break; + case 0: + return 0; + } + return 1; + } +} + int main(int argc, char *argv[]) { int c; @@ -107,7 +187,16 @@ int main(int argc, char *argv[]) if (!f_in) { err(1, "open %s", fn); } - + + // we must wait for beginning +again: + while (!got_start) { + wait_read(device_fd, -1); + on_data(); + } + got_start = got_stop = false; + rewind(f_in); + StreamDevHeader hdr; hdr.protocol_version = STREAM_DEVICE_PROTOCOL; hdr.padding = 0; @@ -134,6 +223,14 @@ int main(int argc, char *argv[]) write_all(device_fd, &hdr, sizeof(hdr)); write_all(device_fd, buffer, l); sleep(1); + // TODO check for request from host + if (wait_read(device_fd, 0)) { + on_data(); + if (got_stop) { + got_start = got_stop = false; + goto again; + } + } } fclose(f_in); |