[Spice-commits] 3 commits - server/reds.c server/spice.h server/spice-server.syms server/spicevmc.c spice-common

Marc-André Lureau elmarco at kemper.freedesktop.org
Wed Dec 5 02:54:25 PST 2012


 server/reds.c            |   11 +++
 server/spice-server.syms |    5 +
 server/spice.h           |    7 +-
 server/spicevmc.c        |  152 ++++++++++++++++++++++++++++++++++++++++++-----
 spice-common             |    2 
 5 files changed, 157 insertions(+), 20 deletions(-)

New commits:
commit 069270f641b617538c17b64d4bebfd4ccb51c6dc
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Fri Nov 30 13:47:55 2012 +0100

    server: add "port" channel support
    
    A Spice port channel carry arbitrary data between the Spice client and
    the Spice server. It may be used to provide additional services on top
    of a Spice connection. For example, a channel can be associated with
    the qemu monitor for the client to interact with it, just like any
    qemu chardev. Or it may be used with various protocols, such as the
    Spice Controller.
    
    A port kind is identified simply by its fqdn, such as org.qemu.monitor,
    org.spice.spicy.test or org.ovirt.controller...
    
    The channel is based on Spicevmc which simply tunnels data between
    client and server, with a few additional messages.
    
    See the description of the channel protocol in spice-common history.

diff --git a/server/reds.c b/server/reds.c
index 3a8a28d..a896cf2 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -3541,6 +3541,7 @@ SPICE_GNUC_VISIBLE void spice_server_char_device_wakeup(SpiceCharDeviceInstance*
 #define SUBTYPE_VDAGENT "vdagent"
 #define SUBTYPE_SMARTCARD "smartcard"
 #define SUBTYPE_USBREDIR "usbredir"
+#define SUBTYPE_PORT "port"
 
 const char *spice_server_char_device_recognized_subtypes_list[] = {
     SUBTYPE_VDAGENT,
@@ -3614,6 +3615,10 @@ static int spice_server_char_device_add_interface(SpiceServer *s,
     else if (strcmp(char_device->subtype, SUBTYPE_USBREDIR) == 0) {
         dev_state = spicevmc_device_connect(char_device, SPICE_CHANNEL_USBREDIR);
     }
+    else if (strcmp(char_device->subtype, SUBTYPE_PORT) == 0) {
+        dev_state = spicevmc_device_connect(char_device, SPICE_CHANNEL_PORT);
+    }
+
     if (dev_state) {
         spice_assert(char_device->st);
         /* setting the char_device state to "started" for backward compatibily with
@@ -3645,9 +3650,13 @@ static void spice_server_char_device_remove_interface(SpiceBaseInstance *sin)
         smartcard_device_disconnect(char_device);
     }
 #endif
-    else if (strcmp(char_device->subtype, SUBTYPE_USBREDIR) == 0) {
+    else if (strcmp(char_device->subtype, SUBTYPE_USBREDIR) == 0 ||
+             strcmp(char_device->subtype, SUBTYPE_PORT) == 0) {
         spicevmc_device_disconnect(char_device);
+    } else {
+        spice_warning("failed to remove char device %s", char_device->subtype);
     }
+
     char_device->st = NULL;
 }
 
diff --git a/server/spice-server.syms b/server/spice-server.syms
index eadfed8..2091fe0 100644
--- a/server/spice-server.syms
+++ b/server/spice-server.syms
@@ -130,3 +130,8 @@ SPICE_SERVER_0.11.4 {
 global:
     spice_server_set_exit_on_disconnect;
 } SPICE_SERVER_0.11.2;
+
+SPICE_SERVER_0.12.2 {
+global:
+    spice_server_port_event;
+} SPICE_SERVER_0.11.4;
diff --git a/server/spice.h b/server/spice.h
index aabc909..45b7408 100644
--- a/server/spice.h
+++ b/server/spice.h
@@ -388,7 +388,7 @@ void spice_server_record_set_mute(SpiceRecordInstance *sin, uint8_t mute);
 
 #define SPICE_INTERFACE_CHAR_DEVICE "char_device"
 #define SPICE_INTERFACE_CHAR_DEVICE_MAJOR 1
-#define SPICE_INTERFACE_CHAR_DEVICE_MINOR 1
+#define SPICE_INTERFACE_CHAR_DEVICE_MINOR 2
 typedef struct SpiceCharDeviceInterface SpiceCharDeviceInterface;
 typedef struct SpiceCharDeviceInstance SpiceCharDeviceInstance;
 typedef struct SpiceCharDeviceState SpiceCharDeviceState;
@@ -399,15 +399,18 @@ struct SpiceCharDeviceInterface {
     void (*state)(SpiceCharDeviceInstance *sin, int connected);
     int (*write)(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len);
     int (*read)(SpiceCharDeviceInstance *sin, uint8_t *buf, int len);
+    void (*event)(SpiceCharDeviceInstance *sin, uint8_t event);
 };
 
 struct SpiceCharDeviceInstance {
     SpiceBaseInstance base;
     const char* subtype;
     SpiceCharDeviceState *st;
+    const char* portname;
 };
 
 void spice_server_char_device_wakeup(SpiceCharDeviceInstance *sin);
+void spice_server_port_event(SpiceCharDeviceInstance *char_device, uint8_t event);
 const char** spice_server_char_device_recognized_subtypes(void);
 
 /* spice server setup */
diff --git a/server/spicevmc.c b/server/spicevmc.c
index 058a182..aba2a5d 100644
--- a/server/spicevmc.c
+++ b/server/spicevmc.c
@@ -28,6 +28,8 @@
 #include <netinet/in.h> // IPPROTO_TCP
 #include <netinet/tcp.h> // TCP_NODELAY
 
+#include "common/generated_server_marshallers.h"
+
 #include "char_device.h"
 #include "red_channel.h"
 #include "reds.h"
@@ -56,11 +58,25 @@ typedef struct SpiceVmcState {
     SpiceCharDeviceInstance *chardev_sin;
     SpiceVmcPipeItem *pipe_item;
     SpiceCharDeviceWriteBuffer *recv_from_client_buf;
+    uint8_t port_opened;
 } SpiceVmcState;
 
+typedef struct PortInitPipeItem {
+    PipeItem base;
+    char* name;
+    uint8_t opened;
+} PortInitPipeItem;
+
+typedef struct PortEventPipeItem {
+    PipeItem base;
+    uint8_t event;
+} PortEventPipeItem;
+
 enum {
     PIPE_ITEM_TYPE_SPICEVMC_DATA = PIPE_ITEM_TYPE_CHANNEL_BASE,
     PIPE_ITEM_TYPE_SPICEVMC_MIGRATE_DATA,
+    PIPE_ITEM_TYPE_PORT_INIT,
+    PIPE_ITEM_TYPE_PORT_EVENT,
 };
 
 static SpiceVmcPipeItem *spicevmc_pipe_item_ref(SpiceVmcPipeItem *item)
@@ -137,6 +153,27 @@ static void spicevmc_chardev_send_msg_to_client(SpiceCharDeviceMsgToClient *msg,
     red_channel_client_pipe_add_push(state->rcc, &vmc_msg->base);
 }
 
+static void spicevmc_port_send_init(RedChannelClient *rcc)
+{
+    SpiceVmcState *state = SPICE_CONTAINEROF(rcc->channel, SpiceVmcState, channel);
+    SpiceCharDeviceInstance *sin = state->chardev_sin;
+    PortInitPipeItem *item = spice_malloc(sizeof(PortInitPipeItem));
+
+    red_channel_pipe_item_init(rcc->channel, &item->base, PIPE_ITEM_TYPE_PORT_INIT);
+    item->name = strdup(sin->portname);
+    item->opened = state->port_opened;
+    red_channel_client_pipe_add_push(rcc, &item->base);
+}
+
+static void spicevmc_port_send_event(RedChannelClient *rcc, uint8_t event)
+{
+    PortEventPipeItem *item = spice_malloc(sizeof(PortEventPipeItem));
+
+    red_channel_pipe_item_init(rcc->channel, &item->base, PIPE_ITEM_TYPE_PORT_EVENT);
+    item->event = event;
+    red_channel_client_pipe_add_push(rcc, &item->base);
+}
+
 static void spicevmc_char_dev_send_tokens_to_client(RedClient *client,
                                                     uint32_t tokens,
                                                     void *opaque)
@@ -245,16 +282,32 @@ static int spicevmc_red_channel_client_handle_message(RedChannelClient *rcc,
                                                       uint8_t *msg)
 {
     SpiceVmcState *state;
+    SpiceCharDeviceInstance *sin;
+    SpiceCharDeviceInterface *sif;
 
     state = spicevmc_red_channel_client_get_state(rcc);
-    if (type != SPICE_MSGC_SPICEVMC_DATA) {
+    sin = state->chardev_sin;
+    sif = SPICE_CONTAINEROF(sin->base.sif, SpiceCharDeviceInterface, base);
+
+    switch (type) {
+    case SPICE_MSGC_SPICEVMC_DATA:
+        spice_assert(state->recv_from_client_buf->buf == msg);
+        state->recv_from_client_buf->buf_used = size;
+        spice_char_device_write_buffer_add(state->chardev_st, state->recv_from_client_buf);
+        state->recv_from_client_buf = NULL;
+        break;
+    case SPICE_MSGC_PORT_EVENT:
+        if (size != sizeof(uint8_t)) {
+            spice_warning("bad port event message size");
+            return FALSE;
+        }
+        if (sif->base.minor_version >= 2 && sif->event != NULL)
+            sif->event(sin, *msg);
+        break;
+    default:
         return red_channel_client_handle_message(rcc, size, type, msg);
     }
 
-    spice_assert(state->recv_from_client_buf->buf == msg);
-    state->recv_from_client_buf->buf_used = size;
-    spice_char_device_write_buffer_add(state->chardev_st, state->recv_from_client_buf);
-    state->recv_from_client_buf = NULL;
     return TRUE;
 }
 
@@ -266,16 +319,23 @@ static uint8_t *spicevmc_red_channel_alloc_msg_rcv_buf(RedChannelClient *rcc,
 
     state = SPICE_CONTAINEROF(rcc->channel, SpiceVmcState, channel);
 
-    assert(!state->recv_from_client_buf);
+    switch (type) {
+    case SPICE_MSGC_SPICEVMC_DATA:
+        assert(!state->recv_from_client_buf);
 
-    state->recv_from_client_buf = spice_char_device_write_buffer_get(state->chardev_st,
-                                                                     rcc->client,
-                                                                     size);
-    if (!state->recv_from_client_buf) {
-        spice_error("failed to allocate write buffer");
-        return NULL;
+        state->recv_from_client_buf = spice_char_device_write_buffer_get(state->chardev_st,
+                                                                         rcc->client,
+                                                                         size);
+        if (!state->recv_from_client_buf) {
+            spice_error("failed to allocate write buffer");
+            return NULL;
+        }
+        return state->recv_from_client_buf->buf;
+
+    default:
+        return spice_malloc(size);
     }
-    return state->recv_from_client_buf->buf;
+
 }
 
 static void spicevmc_red_channel_release_msg_rcv_buf(RedChannelClient *rcc,
@@ -287,9 +347,15 @@ static void spicevmc_red_channel_release_msg_rcv_buf(RedChannelClient *rcc,
 
     state = SPICE_CONTAINEROF(rcc->channel, SpiceVmcState, channel);
 
-    if (state->recv_from_client_buf) { /* buffer wasn't pushed to device */
-        spice_char_device_write_buffer_release(state->chardev_st, state->recv_from_client_buf);
-        state->recv_from_client_buf = NULL;
+    switch (type) {
+    case SPICE_MSGC_SPICEVMC_DATA:
+        if (state->recv_from_client_buf) { /* buffer wasn't pushed to device */
+            spice_char_device_write_buffer_release(state->chardev_st, state->recv_from_client_buf);
+            state->recv_from_client_buf = NULL;
+        }
+        break;
+    default:
+        free(msg);
     }
 }
 
@@ -323,6 +389,32 @@ static void spicevmc_red_channel_send_migrate_data(RedChannelClient *rcc,
     spice_char_device_state_migrate_data_marshall(state->chardev_st, m);
 }
 
+static void spicevmc_red_channel_send_port_init(RedChannelClient *rcc,
+                                                SpiceMarshaller *m,
+                                                PipeItem *item)
+{
+    PortInitPipeItem *i = SPICE_CONTAINEROF(item, PortInitPipeItem, base);
+    SpiceMsgPortInit init;
+
+    red_channel_client_init_send_data(rcc, SPICE_MSG_PORT_INIT, item);
+    init.name = (uint8_t *)i->name;
+    init.name_size = strlen(i->name) + 1;
+    init.opened = i->opened;
+    spice_marshall_msg_port_init(m, &init);
+}
+
+static void spicevmc_red_channel_send_port_event(RedChannelClient *rcc,
+                                                 SpiceMarshaller *m,
+                                                 PipeItem *item)
+{
+    PortEventPipeItem *i = SPICE_CONTAINEROF(item, PortEventPipeItem, base);
+    SpiceMsgPortEvent event;
+
+    red_channel_client_init_send_data(rcc, SPICE_MSG_PORT_EVENT, item);
+    event.event = i->event;
+    spice_marshall_msg_port_event(m, &event);
+}
+
 static void spicevmc_red_channel_send_item(RedChannelClient *rcc,
                                            PipeItem *item)
 {
@@ -335,6 +427,12 @@ static void spicevmc_red_channel_send_item(RedChannelClient *rcc,
     case PIPE_ITEM_TYPE_SPICEVMC_MIGRATE_DATA:
         spicevmc_red_channel_send_migrate_data(rcc, m, item);
         break;
+    case PIPE_ITEM_TYPE_PORT_INIT:
+        spicevmc_red_channel_send_port_init(rcc, m, item);
+        break;
+    case PIPE_ITEM_TYPE_PORT_EVENT:
+        spicevmc_red_channel_send_port_event(rcc, m, item);
+        break;
     default:
         spice_error("bad pipe item %d", item->type);
         free(item);
@@ -384,6 +482,10 @@ static void spicevmc_connect(RedChannel *channel, RedClient *client,
     state->rcc = rcc;
     red_channel_client_ack_zero_messages_window(rcc);
 
+    if (strcmp(sin->subtype, "port") == 0) {
+        spicevmc_port_send_init(rcc);
+    }
+
     if (!spice_char_device_client_add(state->chardev_st, client, FALSE, 0, ~0, ~0,
                                       red_channel_client_waits_for_migrate_data(rcc))) {
         spice_warning("failed to add client to spicevmc");
@@ -461,3 +563,21 @@ void spicevmc_device_disconnect(SpiceCharDeviceInstance *sin)
     free(state->pipe_item);
     red_channel_destroy(&state->channel);
 }
+
+SPICE_GNUC_VISIBLE void spice_server_port_event(SpiceCharDeviceInstance *sin, uint8_t event)
+{
+    SpiceVmcState *state;
+
+    state = (SpiceVmcState *)spice_char_device_state_opaque_get(sin->st);
+    if (event == SPICE_PORT_EVENT_OPENED) {
+        state->port_opened = TRUE;
+    } else if (event == SPICE_PORT_EVENT_CLOSED) {
+        state->port_opened = FALSE;
+    }
+
+    if (state->rcc == NULL) {
+        return;
+    }
+
+    spicevmc_port_send_event(state->rcc, event);
+}
commit 616eee84c11939ebe3a28b6134fe819720426f05
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Fri Nov 30 13:49:59 2012 +0100

    server: bump SPICE_SERVER_VERSION to 0.12.2

diff --git a/server/spice.h b/server/spice.h
index f878b52..aabc909 100644
--- a/server/spice.h
+++ b/server/spice.h
@@ -23,7 +23,7 @@
 #include <spice/qxl_dev.h>
 #include <spice/vd_agent.h>
 
-#define SPICE_SERVER_VERSION 0x000c01 /* release 0.12.1 */
+#define SPICE_SERVER_VERSION 0x000c02 /* release 0.12.2 */
 
 /* interface base type */
 
commit 293ae5cd3f42a76004d901b20dc424fd550dff13
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Wed Dec 5 11:46:15 2012 +0100

    update spice-common

diff --git a/spice-common b/spice-common
index be6392a..b46d36b 160000
--- a/spice-common
+++ b/spice-common
@@ -1 +1 @@
-Subproject commit be6392a5ad338e3f55a279adafaa30bc64e03e4a
+Subproject commit b46d36bc1c01ca17a64262e157022fd21ad1e795


More information about the Spice-commits mailing list