[Spice-commits] 40 commits - client/application.cpp configure.ac server/Makefile.am server/red_channel.c server/red_channel.h server/red_dispatcher.c server/red_dispatcher.h server/red_tunnel_worker.c server/red_tunnel_worker.h server/red_worker.c server/red_worker.h server/reds.c server/reds.h server/snd_worker.c server/snd_worker.h server/spice-experimental.h server/spice.h server/vd_interface.h

Gerd Hoffmann kraxel at kemper.freedesktop.org
Wed May 19 03:01:13 PDT 2010


 client/application.cpp      |    2 
 configure.ac                |    2 
 server/Makefile.am          |    4 
 server/red_channel.c        |   44 
 server/red_channel.h        |    7 
 server/red_dispatcher.c     |   67 -
 server/red_dispatcher.h     |    2 
 server/red_tunnel_worker.c  |   33 
 server/red_tunnel_worker.h  |    4 
 server/red_worker.c         |  188 +--
 server/red_worker.h         |    5 
 server/reds.c               | 2603 ++++++++------------------------------------
 server/reds.h               |   27 
 server/snd_worker.c         |  198 +--
 server/snd_worker.h         |   10 
 server/spice-experimental.h |   63 +
 server/spice.h              |  322 ++++-
 server/vd_interface.h       |  444 -------
 18 files changed, 1142 insertions(+), 2883 deletions(-)

New commits:
commit f67b2e74880ff17592acf739b91097be3cec9903
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed May 19 11:44:40 2010 +0200

    complete NetWireInterface redesign, make red_tunnel_worker.c build.

diff --git a/server/red_tunnel_worker.c b/server/red_tunnel_worker.c
index d4da0b3..210de9d 100644
--- a/server/red_tunnel_worker.c
+++ b/server/red_tunnel_worker.c
@@ -28,6 +28,8 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <errno.h>
+#include "spice.h"
+#include "spice-experimental.h"
 #include "red_tunnel_worker.h"
 #include "red_common.h"
 #include <spice/protocol.h>
@@ -535,7 +537,8 @@ struct TunnelWorker {
     TunnelChannel *channel;
 
     SpiceCoreInterface *core_interface;
-    NetWireInterface *vlan_interface;
+    SpiceNetWireInstance *sin;
+    SpiceNetWireInterface *sif;
     RedSlirpNetworkInterface tunnel_interface;
     RedSlirpNetworkInterface null_interface;
 
@@ -958,9 +961,10 @@ static TunneledBufferProcessQueue *tunnel_socket_alloc_simple_print_reply_proces
                                                       PROCESS_DIRECTION_TYPE_REPLY);
 }
 
-static void tunnel_send_packet(void *opaque_tunnel, const uint8_t *pkt, int pkt_len)
+__visible__ void spice_server_net_wire_recv_packet(SpiceNetWireInstance *sin,
+                                                   const uint8_t *pkt, int pkt_len)
 {
-    TunnelWorker *worker = (TunnelWorker *)opaque_tunnel;
+    TunnelWorker *worker = sin->st->worker;
     ASSERT(worker);
 
     if (worker->channel && worker->channel->base.migrate) {
@@ -971,12 +975,14 @@ static void tunnel_send_packet(void *opaque_tunnel, const uint8_t *pkt, int pkt_
 }
 
 void *red_tunnel_attach(SpiceCoreInterface *core_interface,
-                        NetWireInterface *vlan_interface)
+                        SpiceNetWireInstance *sin)
 {
     TunnelWorker *worker = spice_new0(TunnelWorker, 1);
 
     worker->core_interface = core_interface;
-    worker->vlan_interface = vlan_interface;
+    worker->sin = sin;
+    worker->sin->st->worker = worker;
+    worker->sif = SPICE_CONTAINEROF(sin->base.sif, SpiceNetWireInterface, base);
 
     worker->tunnel_interface.base.slirp_can_output = qemu_can_output;
     worker->tunnel_interface.base.slirp_output = qemu_output;
@@ -1014,12 +1020,9 @@ void *red_tunnel_attach(SpiceCoreInterface *core_interface,
     ring_init(&worker->services);
     reds_register_channel(&worker->channel_interface);
 
-    net_slirp_init(worker->vlan_interface->get_ip(worker->vlan_interface),
+    net_slirp_init(worker->sif->get_ip(worker->sin),
                    TRUE,
                    &worker->null_interface.base);
-    if (!vlan_interface->register_route_packet(vlan_interface, tunnel_send_packet, worker)) {
-        red_error("register route packet failed");
-    }
     return worker;
 }
 
@@ -2892,13 +2895,13 @@ static void tunnel_channel_release_pipe_item(RedChannel *channel, PipeItem *item
 static int qemu_can_output(SlirpUsrNetworkInterface *usr_interface)
 {
     TunnelWorker *worker = ((RedSlirpNetworkInterface *)usr_interface)->worker;
-    return worker->vlan_interface->can_send_packet(worker->vlan_interface);
+    return worker->sif->can_send_packet(worker->sin);
 }
 
 static void qemu_output(SlirpUsrNetworkInterface *usr_interface, const uint8_t *pkt, int pkt_len)
 {
     TunnelWorker *worker = ((RedSlirpNetworkInterface *)usr_interface)->worker;
-    worker->vlan_interface->send_packet(worker->vlan_interface, pkt, pkt_len);
+    worker->sif->send_packet(worker->sin, pkt, pkt_len);
 }
 
 static int null_tunnel_socket_connect(SlirpUsrNetworkInterface *usr_interface,
diff --git a/server/reds.h b/server/reds.h
index b508283..b9d5336 100644
--- a/server/reds.h
+++ b/server/reds.h
@@ -75,8 +75,9 @@ struct QXLState {
     struct RedDispatcher  *dispatcher;
 };
 
+struct TunnelWorker;
 struct SpiceNetWireState {
-    int dummy;
+    struct TunnelWorker *worker;
 };
 
 void reds_desable_mm_timer();
diff --git a/server/spice-experimental.h b/server/spice-experimental.h
index 0b732bc..aede4ce 100644
--- a/server/spice-experimental.h
+++ b/server/spice-experimental.h
@@ -31,12 +31,12 @@ typedef struct SpiceNetWireInterface SpiceNetWireInterface;
 typedef struct SpiceNetWireInstance SpiceNetWireInstance;
 typedef struct SpiceNetWireState SpiceNetWireState;
 
-struct NetWireInterface {
+struct SpiceNetWireInterface {
     SpiceBaseInterface base;
 
-    struct in_addr (*get_ip)(SpiceNetWireInterface *sin);
-    int (*can_send_packet)(SpiceNetWireInterface *sin);
-    void (*send_packet)(SpiceNetWireInterface *sin, const uint8_t *pkt, int len);
+    struct in_addr (*get_ip)(SpiceNetWireInstance *sin);
+    int (*can_send_packet)(SpiceNetWireInstance *sin);
+    void (*send_packet)(SpiceNetWireInstance *sin, const uint8_t *pkt, int len);
 };
 
 struct SpiceNetWireInstance {
commit 9204a5903ab7a2cc39f1c078ce503d337a815be0
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue May 18 15:32:35 2010 +0200

    add spice-experimental.h
    
    Supposed to be used for work-in-progress bits,
    where interfaces are not finalized yet.
    
    Moved over vdi port interface, tunnel interface
    and spice client migration functions.

diff --git a/server/Makefile.am b/server/Makefile.am
index cf504a7..efda902 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -86,6 +86,7 @@ libspice_server_la_SOURCES =			\
 	red_channel.h				\
 	red_channel.c				\
 	spice.h					\
+	spice-experimental.h			\
 	$(TUNNEL_SRCS)				\
 	$(COMMON_SRCS)				\
 	$(NULL)
@@ -93,6 +94,7 @@ libspice_server_la_SOURCES =			\
 libspice_serverincludedir = $(includedir)/spice-server
 libspice_serverinclude_HEADERS =
 	spice.h					\
+	spice-experimental.h			\
 	$(NULL)
 
 EXTRA_DIST =					\
diff --git a/server/red_tunnel_worker.h b/server/red_tunnel_worker.h
index 42d23d1..3df4aea 100755
--- a/server/red_tunnel_worker.h
+++ b/server/red_tunnel_worker.h
@@ -22,8 +22,6 @@
 #ifndef _H_RED_TUNNEL_WORKER
 #define _H_RED_TUNNEL_WORKER
 
-#include "spice.h"
-
 void *red_tunnel_attach(SpiceCoreInterface *core_interface, SpiceNetWireInstance *sin);
 
 #endif
diff --git a/server/reds.c b/server/reds.c
index e9bf716..45946f0 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -39,6 +39,7 @@
 #include <openssl/err.h>
 
 #include "spice.h"
+#include "spice-experimental.h"
 #include "reds.h"
 #include <spice/protocol.h>
 #include <spice/vd_agent.h>
diff --git a/server/spice-experimental.h b/server/spice-experimental.h
new file mode 100644
index 0000000..0b732bc
--- /dev/null
+++ b/server/spice-experimental.h
@@ -0,0 +1,63 @@
+/* vdi port interface */
+
+#define SPICE_INTERFACE_VDI_PORT "vdi_port"
+#define SPICE_INTERFACE_VDI_PORT_MAJOR 1
+#define SPICE_INTERFACE_VDI_PORT_MINOR 1
+typedef struct SpiceVDIPortInterface SpiceVDIPortInterface;
+typedef struct SpiceVDIPortInstance SpiceVDIPortInstance;
+typedef struct SpiceVDIPortState SpiceVDIPortState;
+
+struct SpiceVDIPortInterface {
+    SpiceBaseInterface base;
+
+    void (*state)(SpiceVDIPortInstance *sin, int connected);
+    int (*write)(SpiceVDIPortInstance *sin, const uint8_t *buf, int len);
+    int (*read)(SpiceVDIPortInstance *sin, uint8_t *buf, int len);
+};
+
+struct SpiceVDIPortInstance {
+    SpiceBaseInstance base;
+    SpiceVDIPortState *st;
+};
+
+void spice_server_vdi_port_wakeup(SpiceVDIPortInstance *sin);
+
+/* tunnel interface */
+
+#define SPICE_INTERFACE_NET_WIRE "net_wire"
+#define SPICE_INTERFACE_NET_WIRE_MAJOR 1
+#define SPICE_INTERFACE_NET_WIRE_MINOR 1
+typedef struct SpiceNetWireInterface SpiceNetWireInterface;
+typedef struct SpiceNetWireInstance SpiceNetWireInstance;
+typedef struct SpiceNetWireState SpiceNetWireState;
+
+struct NetWireInterface {
+    SpiceBaseInterface base;
+
+    struct in_addr (*get_ip)(SpiceNetWireInterface *sin);
+    int (*can_send_packet)(SpiceNetWireInterface *sin);
+    void (*send_packet)(SpiceNetWireInterface *sin, const uint8_t *pkt, int len);
+};
+
+struct SpiceNetWireInstance {
+    SpiceBaseInstance base;
+    SpiceNetWireState *st;
+};
+
+void spice_server_net_wire_recv_packet(SpiceNetWireInstance *sin,
+                                       const uint8_t *pkt, int len);
+
+/* spice client migration */
+
+enum {
+    SPICE_MIGRATE_CLIENT_NONE = 1,
+    SPICE_MIGRATE_CLIENT_WAITING,
+    SPICE_MIGRATE_CLIENT_READY,
+};
+
+int spice_server_migrate_info(SpiceServer *s, const char* dest, int port, int secure_port,
+                              const char* cert_subject);
+int spice_server_migrate_start(SpiceServer *s);
+int spice_server_migrate_client_state(SpiceServer *s);
+int spice_server_migrate_end(SpiceServer *s, int completed);
+
diff --git a/server/spice.h b/server/spice.h
index ccbae92..6c5853d 100644
--- a/server/spice.h
+++ b/server/spice.h
@@ -310,55 +310,6 @@ void spice_server_record_stop(SpiceRecordInstance *sin);
 uint32_t spice_server_record_get_samples(SpiceRecordInstance *sin,
                                          uint32_t *samples, uint32_t bufsize);
 
-/* vdi port interface */
-
-#define SPICE_INTERFACE_VDI_PORT "vdi_port"
-#define SPICE_INTERFACE_VDI_PORT_MAJOR 1
-#define SPICE_INTERFACE_VDI_PORT_MINOR 1
-typedef struct SpiceVDIPortInterface SpiceVDIPortInterface;
-typedef struct SpiceVDIPortInstance SpiceVDIPortInstance;
-typedef struct SpiceVDIPortState SpiceVDIPortState;
-
-struct SpiceVDIPortInterface {
-    SpiceBaseInterface base;
-
-    void (*state)(SpiceVDIPortInstance *sin, int connected);
-    int (*write)(SpiceVDIPortInstance *sin, const uint8_t *buf, int len);
-    int (*read)(SpiceVDIPortInstance *sin, uint8_t *buf, int len);
-};
-
-struct SpiceVDIPortInstance {
-    SpiceBaseInstance base;
-    SpiceVDIPortState *st;
-};
-
-void spice_server_vdi_port_wakeup(SpiceVDIPortInstance *sin);
-
-/* tunnel interface */
-
-#define SPICE_INTERFACE_NET_WIRE "net_wire"
-#define SPICE_INTERFACE_NET_WIRE_MAJOR 1
-#define SPICE_INTERFACE_NET_WIRE_MINOR 1
-typedef struct SpiceNetWireInterface SpiceNetWireInterface;
-typedef struct SpiceNetWireInstance SpiceNetWireInstance;
-typedef struct SpiceNetWireState SpiceNetWireState;
-
-struct NetWireInterface {
-    SpiceBaseInterface base;
-
-    struct in_addr (*get_ip)(SpiceNetWireInterface *sin);
-    int (*can_send_packet)(SpiceNetWireInterface *sin);
-    void (*send_packet)(SpiceNetWireInterface *sin, const uint8_t *pkt, int len);
-};
-
-struct SpiceNetWireInstance {
-    SpiceBaseInstance base;
-    SpiceNetWireState *st;
-};
-
-void spice_server_net_wire_recv_packet(SpiceNetWireInstance *sin,
-                                       const uint8_t *pkt, int len);
-
 /* spice server setup */
 
 typedef struct RedsState SpiceServer;
@@ -407,18 +358,4 @@ int spice_server_add_renderer(SpiceServer *s, const char *name);
 int spice_server_get_sock_info(SpiceServer *s, struct sockaddr *sa, socklen_t *salen);
 int spice_server_get_peer_info(SpiceServer *s, struct sockaddr *sa, socklen_t *salen);
 
-/* spice client migration */
-
-enum {
-    SPICE_MIGRATE_CLIENT_NONE = 1,
-    SPICE_MIGRATE_CLIENT_WAITING,
-    SPICE_MIGRATE_CLIENT_READY,
-};
-
-int spice_server_migrate_info(SpiceServer *s, const char* dest, int port, int secure_port,
-                              const char* cert_subject);
-int spice_server_migrate_start(SpiceServer *s);
-int spice_server_migrate_client_state(SpiceServer *s);
-int spice_server_migrate_end(SpiceServer *s, int completed);
-
 #endif
commit 981abd3fee93efb4578e1ae6442ea4b320a710a9
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue May 18 15:24:22 2010 +0200

    zap vd_interface.h
    
    move over content to spice.h

diff --git a/server/Makefile.am b/server/Makefile.am
index 1fdcc31..cf504a7 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -86,7 +86,6 @@ libspice_server_la_SOURCES =			\
 	red_channel.h				\
 	red_channel.c				\
 	spice.h					\
-	vd_interface.h				\
 	$(TUNNEL_SRCS)				\
 	$(COMMON_SRCS)				\
 	$(NULL)
@@ -94,7 +93,6 @@ libspice_server_la_SOURCES =			\
 libspice_serverincludedir = $(includedir)/spice-server
 libspice_serverinclude_HEADERS =
 	spice.h					\
-	vd_interface.h				\
 	$(NULL)
 
 EXTRA_DIST =					\
diff --git a/server/red_channel.h b/server/red_channel.h
index 1fc92e5..c53bf6d 100644
--- a/server/red_channel.h
+++ b/server/red_channel.h
@@ -24,7 +24,7 @@
 
 #include "red_common.h"
 #include "reds.h"
-#include "vd_interface.h"
+#include "spice.h"
 #include "ring.h"
 
 #define MAX_SEND_BUFS 1000
diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
index 2d23cbe..735d6c0 100644
--- a/server/red_dispatcher.c
+++ b/server/red_dispatcher.c
@@ -25,7 +25,7 @@
 #include <signal.h>
 
 #include <spice/qxl_dev.h>
-#include "vd_interface.h"
+#include "spice.h"
 #include "red_worker.h"
 #include "quic.h"
 #include "sw_canvas.h"
diff --git a/server/red_tunnel_worker.h b/server/red_tunnel_worker.h
index d4bf4b7..42d23d1 100755
--- a/server/red_tunnel_worker.h
+++ b/server/red_tunnel_worker.h
@@ -22,7 +22,7 @@
 #ifndef _H_RED_TUNNEL_WORKER
 #define _H_RED_TUNNEL_WORKER
 
-#include "vd_interface.h"
+#include "spice.h"
 
 void *red_tunnel_attach(SpiceCoreInterface *core_interface, SpiceNetWireInstance *sin);
 
diff --git a/server/red_worker.c b/server/red_worker.c
index 6dbbc22..f509ea2 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -32,7 +32,7 @@
 #include <openssl/ssl.h>
 
 #include <spice/qxl_dev.h>
-#include "vd_interface.h"
+#include "spice.h"
 #include "region.h"
 #include <spice/protocol.h>
 #include "red_worker.h"
diff --git a/server/snd_worker.c b/server/snd_worker.c
index c43ef2d..1c9da5a 100644
--- a/server/snd_worker.c
+++ b/server/snd_worker.c
@@ -22,7 +22,7 @@
 #include <netinet/tcp.h>
 #include <celt051/celt.h>
 
-#include "vd_interface.h"
+#include "spice.h"
 #include "red_common.h"
 #include "reds.h"
 #include "red_dispatcher.h"
diff --git a/server/snd_worker.h b/server/snd_worker.h
index 291f321..4d5a1b4 100644
--- a/server/snd_worker.h
+++ b/server/snd_worker.h
@@ -18,7 +18,7 @@
 #ifndef _H_SND_WORKER
 #define _H_SND_WORKER
 
-#include "vd_interface.h"
+#include "spice.h"
 
 void snd_attach_playback(SpicePlaybackInstance *sin);
 void snd_detach_playback(SpicePlaybackInstance *sin);
diff --git a/server/spice.h b/server/spice.h
index 70434c2..ccbae92 100644
--- a/server/spice.h
+++ b/server/spice.h
@@ -18,10 +18,349 @@
 #ifndef _H_SPICE
 #define _H_SPICE
 
+#include <stdint.h>
 #include <sys/socket.h>
-#include "vd_interface.h"
 
-/* new interface */
+/* interface base type */
+
+typedef struct SpiceBaseInterface SpiceBaseInterface;
+typedef struct SpiceBaseInstance SpiceBaseInstance;
+
+struct SpiceBaseInterface {
+    const char *type;
+    const char *description;
+    uint32_t major_version;
+    uint32_t minor_version;
+};
+struct SpiceBaseInstance {
+    const SpiceBaseInterface *sif;
+};
+
+/* core interface */
+
+#define SPICE_INTERFACE_CORE "core"
+#define SPICE_INTERFACE_CORE_MAJOR 1
+#define SPICE_INTERFACE_CORE_MINOR 2
+typedef struct SpiceCoreInterface SpiceCoreInterface;
+
+#define SPICE_WATCH_EVENT_READ  (1 << 0)
+#define SPICE_WATCH_EVENT_WRITE (1 << 1)
+
+typedef struct SpiceWatch SpiceWatch;
+typedef void (*SpiceWatchFunc)(int fd, int event, void *opaque);
+
+typedef struct SpiceTimer SpiceTimer;
+typedef void (*SpiceTimerFunc)(void *opaque);
+
+struct SpiceCoreInterface {
+    SpiceBaseInterface base;
+
+    SpiceTimer *(*timer_add)(SpiceTimerFunc func, void *opaque);
+    void (*timer_start)(SpiceTimer *timer, uint32_t ms);
+    void (*timer_cancel)(SpiceTimer *timer);
+    void (*timer_remove)(SpiceTimer *timer);
+
+    SpiceWatch *(*watch_add)(int fd, int event_mask, SpiceWatchFunc func, void *opaque);
+    void (*watch_update_mask)(SpiceWatch *watch, int event_mask);
+    void (*watch_remove)(SpiceWatch *watch);
+
+};
+
+/* qxl interface */
+
+#define SPICE_INTERFACE_QXL "qxl"
+#define SPICE_INTERFACE_QXL_MAJOR 3
+#define SPICE_INTERFACE_QXL_MINOR 0
+typedef struct QXLInterface QXLInterface;
+typedef struct QXLInstance QXLInstance;
+typedef struct QXLState QXLState;
+typedef struct QXLWorker QXLWorker;
+typedef struct QXLDevMemSlot QXLDevMemSlot;
+typedef struct QXLDevSurfaceCreate QXLDevSurfaceCreate;
+union QXLReleaseInfo;
+struct QXLReleaseInfoExt;
+struct QXLCommand;
+struct QXLCommandExt;
+struct SpiceRect;
+struct QXLWorker {
+    uint32_t minor_version;
+    uint32_t major_version;
+    void (*wakeup)(QXLWorker *worker);
+    void (*oom)(QXLWorker *worker);
+    void (*start)(QXLWorker *worker);
+    void (*stop)(QXLWorker *worker);
+    void (*update_area)(QXLWorker *qxl_worker, uint32_t surface_id,
+                       struct SpiceRect *area, struct SpiceRect *dirty_rects,
+                       uint32_t num_dirty_rects, uint32_t clear_dirty_region);
+    void (*add_memslot)(QXLWorker *worker, QXLDevMemSlot *slot);
+    void (*del_memslot)(QXLWorker *worker, uint32_t slot_group_id, uint32_t slot_id);
+    void (*reset_memslots)(QXLWorker *worker);
+    void (*destroy_surfaces)(QXLWorker *worker);
+    void (*destroy_primary_surface)(QXLWorker *worker, uint32_t surface_id);
+    void (*create_primary_surface)(QXLWorker *worker, uint32_t surface_id,
+                                   QXLDevSurfaceCreate *surface);
+    void (*reset_image_cache)(QXLWorker *worker);
+    void (*reset_cursor)(QXLWorker *worker);
+    void (*destroy_surface_wait)(QXLWorker *worker, uint32_t surface_id);
+    void (*loadvm_commands)(QXLWorker *worker, struct QXLCommandExt *ext, uint32_t count);
+};
+
+typedef struct QXLDrawArea {
+    uint8_t *buf;
+    uint32_t size;
+    uint8_t *line_0;
+    uint32_t width;
+    uint32_t heigth;
+    int stride;
+} QXLDrawArea;
+
+typedef struct QXLDevInfo {
+    uint32_t x_res;
+    uint32_t y_res;
+    uint32_t bits;
+    uint32_t use_hardware_cursor;
+
+    QXLDrawArea draw_area;
+
+    uint32_t ram_size;
+} QXLDevInfo;
+
+typedef struct QXLDevInitInfo {
+    uint32_t num_memslots_groups;
+    uint32_t num_memslots;
+    uint8_t memslot_gen_bits;
+    uint8_t memslot_id_bits;
+    uint32_t qxl_ram_size;
+    uint8_t internal_groupslot_id;
+    uint32_t n_surfaces;
+} QXLDevInitInfo;
+
+struct QXLDevMemSlot {
+    uint32_t slot_group_id;
+    uint32_t slot_id;
+    uint32_t generation;
+    unsigned long virt_start;
+    unsigned long virt_end;
+    uint64_t addr_delta;
+    uint32_t qxl_ram_size;
+};
+
+struct QXLDevSurfaceCreate {
+    uint32_t width;
+    uint32_t height;
+    int32_t stride;
+    uint32_t format;
+    uint32_t position;
+    uint32_t mouse_mode;
+    uint32_t flags;
+    uint32_t type;
+    uint64_t mem;
+    uint32_t group_id;
+};
+
+struct SpiceRect;
+
+struct QXLInterface {
+    SpiceBaseInterface base;
+
+    uint16_t pci_vendor;
+    uint16_t pci_id;
+    uint8_t pci_revision;
+
+    void (*attache_worker)(QXLInstance *qin, QXLWorker *qxl_worker);
+    void (*set_compression_level)(QXLInstance *qin, int level);
+    void (*set_mm_time)(QXLInstance *qin, uint32_t mm_time);
+
+    void (*get_init_info)(QXLInstance *qin, QXLDevInitInfo *info);
+    int (*get_command)(QXLInstance *qin, struct QXLCommandExt *cmd);
+    int (*req_cmd_notification)(QXLInstance *qin);
+    int (*has_command)(QXLInstance *qin);
+    void (*release_resource)(QXLInstance *qin, struct QXLReleaseInfoExt release_info);
+    int (*get_cursor_command)(QXLInstance *qin, struct QXLCommandExt *cmd);
+    int (*req_cursor_notification)(QXLInstance *qin);
+    void (*notify_update)(QXLInstance *qin, uint32_t update_id);
+    int (*flush_resources)(QXLInstance *qin);
+};
+
+struct QXLInstance {
+    SpiceBaseInstance  base;
+    int                id;
+    QXLState           *st;
+};
+
+/* input interfaces */
+
+#define SPICE_INTERFACE_KEYBOARD "keyboard"
+#define SPICE_INTERFACE_KEYBOARD_MAJOR 1
+#define SPICE_INTERFACE_KEYBOARD_MINOR 1
+typedef struct SpiceKbdInterface SpiceKbdInterface;
+typedef struct SpiceKbdInstance SpiceKbdInstance;
+typedef struct SpiceKbdState SpiceKbdState;
+
+struct SpiceKbdInterface {
+    SpiceBaseInterface base;
+
+    void (*push_scan_freg)(SpiceKbdInstance *sin, uint8_t frag);
+    uint8_t (*get_leds)(SpiceKbdInstance *sin);
+};
+
+struct SpiceKbdInstance {
+    SpiceBaseInstance base;
+    SpiceKbdState     *st;
+};
+
+int spice_server_kbd_leds(SpiceKbdInstance *sin, int leds);
+
+#define SPICE_INTERFACE_MOUSE "mouse"
+#define SPICE_INTERFACE_MOUSE_MAJOR 1
+#define SPICE_INTERFACE_MOUSE_MINOR 1
+typedef struct SpiceMouseInterface SpiceMouseInterface;
+typedef struct SpiceMouseInstance SpiceMouseInstance;
+typedef struct SpiceMouseState SpiceMouseState;
+
+struct SpiceMouseInterface {
+    SpiceBaseInterface base;
+
+    void (*motion)(SpiceMouseInstance *sin, int dx, int dy, int dz,
+                   uint32_t buttons_state);
+    void (*buttons)(SpiceMouseInstance *sin, uint32_t buttons_state);
+};
+
+struct SpiceMouseInstance {
+    SpiceBaseInstance base;
+    SpiceMouseState   *st;
+};
+
+#define SPICE_INTERFACE_TABLET "tablet"
+#define SPICE_INTERFACE_TABLET_MAJOR 1
+#define SPICE_INTERFACE_TABLET_MINOR 1
+typedef struct SpiceTabletInterface SpiceTabletInterface;
+typedef struct SpiceTabletInstance SpiceTabletInstance;
+typedef struct SpiceTabletState SpiceTabletState;
+
+struct SpiceTabletInterface {
+    SpiceBaseInterface base;
+
+    void (*set_logical_size)(SpiceTabletInstance* tablet, int width, int height);
+    void (*position)(SpiceTabletInstance* tablet, int x, int y, uint32_t buttons_state);
+    void (*wheel)(SpiceTabletInstance* tablet, int wheel_moution, uint32_t buttons_state);
+    void (*buttons)(SpiceTabletInstance* tablet, uint32_t buttons_state);
+};
+
+struct SpiceTabletInstance {
+    SpiceBaseInstance base;
+    SpiceTabletState  *st;
+};
+
+/* sound interfaces */
+
+#define SPICE_INTERFACE_PLAYBACK "playback"
+#define SPICE_INTERFACE_PLAYBACK_MAJOR 1
+#define SPICE_INTERFACE_PLAYBACK_MINOR 1
+typedef struct SpicePlaybackInterface SpicePlaybackInterface;
+typedef struct SpicePlaybackInstance SpicePlaybackInstance;
+typedef struct SpicePlaybackState SpicePlaybackState;
+
+enum {
+    SPICE_INTERFACE_AUDIO_FMT_S16 = 1,
+};
+
+#define SPICE_INTERFACE_PLAYBACK_FREQ  44100
+#define SPICE_INTERFACE_PLAYBACK_CHAN  2
+#define SPICE_INTERFACE_PLAYBACK_FMT   SPICE_INTERFACE_AUDIO_FMT_S16
+
+struct SpicePlaybackInterface {
+    SpiceBaseInterface base;
+};
+
+struct SpicePlaybackInstance {
+    SpiceBaseInstance  base;
+    SpicePlaybackState *st;
+};
+
+void spice_server_playback_start(SpicePlaybackInstance *sin);
+void spice_server_playback_stop(SpicePlaybackInstance *sin);
+void spice_server_playback_get_buffer(SpicePlaybackInstance *sin,
+                                      uint32_t **samples, uint32_t *nsamples);
+void spice_server_playback_put_samples(SpicePlaybackInstance *sin,
+                                       uint32_t *samples);
+
+#define SPICE_INTERFACE_RECORD "record"
+#define SPICE_INTERFACE_RECORD_MAJOR 2
+#define SPICE_INTERFACE_RECORD_MINOR 1
+typedef struct SpiceRecordInterface SpiceRecordInterface;
+typedef struct SpiceRecordInstance SpiceRecordInstance;
+typedef struct SpiceRecordState SpiceRecordState;
+
+#define SPICE_INTERFACE_RECORD_FREQ  44100
+#define SPICE_INTERFACE_RECORD_CHAN  2
+#define SPICE_INTERFACE_RECORD_FMT   SPICE_INTERFACE_AUDIO_FMT_S16
+
+struct SpiceRecordInterface {
+    SpiceBaseInterface base;
+};
+
+struct SpiceRecordInstance {
+    SpiceBaseInstance base;
+    SpiceRecordState  *st;
+};
+
+void spice_server_record_start(SpiceRecordInstance *sin);
+void spice_server_record_stop(SpiceRecordInstance *sin);
+uint32_t spice_server_record_get_samples(SpiceRecordInstance *sin,
+                                         uint32_t *samples, uint32_t bufsize);
+
+/* vdi port interface */
+
+#define SPICE_INTERFACE_VDI_PORT "vdi_port"
+#define SPICE_INTERFACE_VDI_PORT_MAJOR 1
+#define SPICE_INTERFACE_VDI_PORT_MINOR 1
+typedef struct SpiceVDIPortInterface SpiceVDIPortInterface;
+typedef struct SpiceVDIPortInstance SpiceVDIPortInstance;
+typedef struct SpiceVDIPortState SpiceVDIPortState;
+
+struct SpiceVDIPortInterface {
+    SpiceBaseInterface base;
+
+    void (*state)(SpiceVDIPortInstance *sin, int connected);
+    int (*write)(SpiceVDIPortInstance *sin, const uint8_t *buf, int len);
+    int (*read)(SpiceVDIPortInstance *sin, uint8_t *buf, int len);
+};
+
+struct SpiceVDIPortInstance {
+    SpiceBaseInstance base;
+    SpiceVDIPortState *st;
+};
+
+void spice_server_vdi_port_wakeup(SpiceVDIPortInstance *sin);
+
+/* tunnel interface */
+
+#define SPICE_INTERFACE_NET_WIRE "net_wire"
+#define SPICE_INTERFACE_NET_WIRE_MAJOR 1
+#define SPICE_INTERFACE_NET_WIRE_MINOR 1
+typedef struct SpiceNetWireInterface SpiceNetWireInterface;
+typedef struct SpiceNetWireInstance SpiceNetWireInstance;
+typedef struct SpiceNetWireState SpiceNetWireState;
+
+struct NetWireInterface {
+    SpiceBaseInterface base;
+
+    struct in_addr (*get_ip)(SpiceNetWireInterface *sin);
+    int (*can_send_packet)(SpiceNetWireInterface *sin);
+    void (*send_packet)(SpiceNetWireInterface *sin, const uint8_t *pkt, int len);
+};
+
+struct SpiceNetWireInstance {
+    SpiceBaseInstance base;
+    SpiceNetWireState *st;
+};
+
+void spice_server_net_wire_recv_packet(SpiceNetWireInstance *sin,
+                                       const uint8_t *pkt, int len);
+
+/* spice server setup */
+
 typedef struct RedsState SpiceServer;
 SpiceServer *spice_server_new(void);
 int spice_server_init(SpiceServer *s, SpiceCoreInterface *core);
@@ -43,7 +382,6 @@ int spice_server_set_tls(SpiceServer *s, int port,
 int spice_server_add_interface(SpiceServer *s,
                                SpiceBaseInstance *sin);
 int spice_server_remove_interface(SpiceBaseInstance *sin);
-int spice_server_kbd_leds(SpiceKbdInstance *sin, int leds);
 
 typedef enum {
     SPICE_IMAGE_COMPRESS_INVALID  = 0,
@@ -69,6 +407,8 @@ int spice_server_add_renderer(SpiceServer *s, const char *name);
 int spice_server_get_sock_info(SpiceServer *s, struct sockaddr *sa, socklen_t *salen);
 int spice_server_get_peer_info(SpiceServer *s, struct sockaddr *sa, socklen_t *salen);
 
+/* spice client migration */
+
 enum {
     SPICE_MIGRATE_CLIENT_NONE = 1,
     SPICE_MIGRATE_CLIENT_WAITING,
diff --git a/server/vd_interface.h b/server/vd_interface.h
deleted file mode 100644
index fc81a24..0000000
--- a/server/vd_interface.h
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
-   Copyright (C) 2009 Red Hat, Inc.
-
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions are
-   met:
-
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in
-         the documentation and/or other materials provided with the
-         distribution.
-       * Neither the name of the copyright holder nor the names of its
-         contributors may be used to endorse or promote products derived
-         from this software without specific prior written permission.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
-   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-   HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef _H_VD_INTERFACE
-#define _H_VD_INTERFACE
-
-#include <stdint.h>
-
-typedef struct SpiceBaseInterface SpiceBaseInterface;
-typedef struct SpiceBaseInstance SpiceBaseInstance;
-
-struct SpiceBaseInterface {
-    const char *type;
-    const char *description;
-    uint32_t major_version;
-    uint32_t minor_version;
-};
-struct SpiceBaseInstance {
-    const SpiceBaseInterface *sif;
-};
-
-#define SPICE_INTERFACE_CORE "core"
-#define SPICE_INTERFACE_CORE_MAJOR 1
-#define SPICE_INTERFACE_CORE_MINOR 2
-typedef struct SpiceCoreInterface SpiceCoreInterface;
-
-#define SPICE_WATCH_EVENT_READ  (1 << 0)
-#define SPICE_WATCH_EVENT_WRITE (1 << 1)
-
-typedef struct SpiceWatch SpiceWatch;
-typedef void (*SpiceWatchFunc)(int fd, int event, void *opaque);
-
-typedef struct SpiceTimer SpiceTimer;
-typedef void (*SpiceTimerFunc)(void *opaque);
-
-struct SpiceCoreInterface {
-    SpiceBaseInterface base;
-
-    SpiceTimer *(*timer_add)(SpiceTimerFunc func, void *opaque);
-    void (*timer_start)(SpiceTimer *timer, uint32_t ms);
-    void (*timer_cancel)(SpiceTimer *timer);
-    void (*timer_remove)(SpiceTimer *timer);
-
-    SpiceWatch *(*watch_add)(int fd, int event_mask, SpiceWatchFunc func, void *opaque);
-    void (*watch_update_mask)(SpiceWatch *watch, int event_mask);
-    void (*watch_remove)(SpiceWatch *watch);
-
-};
-
-#define SPICE_INTERFACE_QXL "qxl"
-#define SPICE_INTERFACE_QXL_MAJOR 3
-#define SPICE_INTERFACE_QXL_MINOR 0
-typedef struct QXLInterface QXLInterface;
-typedef struct QXLInstance QXLInstance;
-typedef struct QXLState QXLState;
-typedef struct QXLWorker QXLWorker;
-typedef struct QXLDevMemSlot QXLDevMemSlot;
-typedef struct QXLDevSurfaceCreate QXLDevSurfaceCreate;
-union QXLReleaseInfo;
-struct QXLReleaseInfoExt;
-struct QXLCommand;
-struct QXLCommandExt;
-struct SpiceRect;
-struct QXLWorker {
-    uint32_t minor_version;
-    uint32_t major_version;
-    void (*wakeup)(QXLWorker *worker);
-    void (*oom)(QXLWorker *worker);
-    void (*start)(QXLWorker *worker);
-    void (*stop)(QXLWorker *worker);
-    void (*update_area)(QXLWorker *qxl_worker, uint32_t surface_id,
-                       struct SpiceRect *area, struct SpiceRect *dirty_rects,
-                       uint32_t num_dirty_rects, uint32_t clear_dirty_region);
-    void (*add_memslot)(QXLWorker *worker, QXLDevMemSlot *slot);
-    void (*del_memslot)(QXLWorker *worker, uint32_t slot_group_id, uint32_t slot_id);
-    void (*reset_memslots)(QXLWorker *worker);
-    void (*destroy_surfaces)(QXLWorker *worker);
-    void (*destroy_primary_surface)(QXLWorker *worker, uint32_t surface_id);
-    void (*create_primary_surface)(QXLWorker *worker, uint32_t surface_id,
-                                   QXLDevSurfaceCreate *surface);
-    void (*reset_image_cache)(QXLWorker *worker);
-    void (*reset_cursor)(QXLWorker *worker);
-    void (*destroy_surface_wait)(QXLWorker *worker, uint32_t surface_id);
-    void (*loadvm_commands)(QXLWorker *worker, struct QXLCommandExt *ext, uint32_t count);
-};
-
-typedef struct QXLDrawArea {
-    uint8_t *buf;
-    uint32_t size;
-    uint8_t *line_0;
-    uint32_t width;
-    uint32_t heigth;
-    int stride;
-} QXLDrawArea;
-
-typedef struct QXLDevInfo {
-    uint32_t x_res;
-    uint32_t y_res;
-    uint32_t bits;
-    uint32_t use_hardware_cursor;
-
-    QXLDrawArea draw_area;
-
-    uint32_t ram_size;
-} QXLDevInfo;
-
-typedef struct QXLDevInitInfo {
-    uint32_t num_memslots_groups;
-    uint32_t num_memslots;
-    uint8_t memslot_gen_bits;
-    uint8_t memslot_id_bits;
-    uint32_t qxl_ram_size;
-    uint8_t internal_groupslot_id;
-    uint32_t n_surfaces;
-} QXLDevInitInfo;
-
-struct QXLDevMemSlot {
-    uint32_t slot_group_id;
-    uint32_t slot_id;
-    uint32_t generation;
-    unsigned long virt_start;
-    unsigned long virt_end;
-    uint64_t addr_delta;
-    uint32_t qxl_ram_size;
-};
-
-struct QXLDevSurfaceCreate {
-    uint32_t width;
-    uint32_t height;
-    int32_t stride;
-    uint32_t format;
-    uint32_t position;
-    uint32_t mouse_mode;
-    uint32_t flags;
-    uint32_t type;
-    uint64_t mem;
-    uint32_t group_id;
-};
-
-struct SpiceRect;
-
-struct QXLInterface {
-    SpiceBaseInterface base;
-
-    uint16_t pci_vendor;
-    uint16_t pci_id;
-    uint8_t pci_revision;
-
-    void (*attache_worker)(QXLInstance *qin, QXLWorker *qxl_worker);
-    void (*set_compression_level)(QXLInstance *qin, int level);
-    void (*set_mm_time)(QXLInstance *qin, uint32_t mm_time);
-
-    void (*get_init_info)(QXLInstance *qin, QXLDevInitInfo *info);
-    int (*get_command)(QXLInstance *qin, struct QXLCommandExt *cmd);
-    int (*req_cmd_notification)(QXLInstance *qin);
-    int (*has_command)(QXLInstance *qin);
-    void (*release_resource)(QXLInstance *qin, struct QXLReleaseInfoExt release_info);
-    int (*get_cursor_command)(QXLInstance *qin, struct QXLCommandExt *cmd);
-    int (*req_cursor_notification)(QXLInstance *qin);
-    void (*notify_update)(QXLInstance *qin, uint32_t update_id);
-    int (*flush_resources)(QXLInstance *qin);
-};
-
-struct QXLInstance {
-    SpiceBaseInstance  base;
-    int                id;
-    QXLState           *st;
-};
-
-#define SPICE_INTERFACE_KEYBOARD "keyboard"
-#define SPICE_INTERFACE_KEYBOARD_MAJOR 1
-#define SPICE_INTERFACE_KEYBOARD_MINOR 1
-typedef struct SpiceKbdInterface SpiceKbdInterface;
-typedef struct SpiceKbdInstance SpiceKbdInstance;
-typedef struct SpiceKbdState SpiceKbdState;
-
-struct SpiceKbdInterface {
-    SpiceBaseInterface base;
-
-    void (*push_scan_freg)(SpiceKbdInstance *sin, uint8_t frag);
-    uint8_t (*get_leds)(SpiceKbdInstance *sin);
-};
-
-struct SpiceKbdInstance {
-    SpiceBaseInstance base;
-    SpiceKbdState     *st;
-};
-
-#define SPICE_INTERFACE_MOUSE "mouse"
-#define SPICE_INTERFACE_MOUSE_MAJOR 1
-#define SPICE_INTERFACE_MOUSE_MINOR 1
-typedef struct SpiceMouseInterface SpiceMouseInterface;
-typedef struct SpiceMouseInstance SpiceMouseInstance;
-typedef struct SpiceMouseState SpiceMouseState;
-
-struct SpiceMouseInterface {
-    SpiceBaseInterface base;
-
-    void (*motion)(SpiceMouseInstance *sin, int dx, int dy, int dz,
-                   uint32_t buttons_state);
-    void (*buttons)(SpiceMouseInstance *sin, uint32_t buttons_state);
-};
-
-struct SpiceMouseInstance {
-    SpiceBaseInstance base;
-    SpiceMouseState   *st;
-};
-
-#define SPICE_INTERFACE_TABLET "tablet"
-#define SPICE_INTERFACE_TABLET_MAJOR 1
-#define SPICE_INTERFACE_TABLET_MINOR 1
-typedef struct SpiceTabletInterface SpiceTabletInterface;
-typedef struct SpiceTabletInstance SpiceTabletInstance;
-typedef struct SpiceTabletState SpiceTabletState;
-
-struct SpiceTabletInterface {
-    SpiceBaseInterface base;
-
-    void (*set_logical_size)(SpiceTabletInstance* tablet, int width, int height);
-    void (*position)(SpiceTabletInstance* tablet, int x, int y, uint32_t buttons_state);
-    void (*wheel)(SpiceTabletInstance* tablet, int wheel_moution, uint32_t buttons_state);
-    void (*buttons)(SpiceTabletInstance* tablet, uint32_t buttons_state);
-};
-
-struct SpiceTabletInstance {
-    SpiceBaseInstance base;
-    SpiceTabletState  *st;
-};
-
-#define SPICE_INTERFACE_PLAYBACK "playback"
-#define SPICE_INTERFACE_PLAYBACK_MAJOR 1
-#define SPICE_INTERFACE_PLAYBACK_MINOR 1
-typedef struct SpicePlaybackInterface SpicePlaybackInterface;
-typedef struct SpicePlaybackInstance SpicePlaybackInstance;
-typedef struct SpicePlaybackState SpicePlaybackState;
-
-enum {
-    SPICE_INTERFACE_AUDIO_FMT_S16 = 1,
-};
-
-#define SPICE_INTERFACE_PLAYBACK_FREQ  44100
-#define SPICE_INTERFACE_PLAYBACK_CHAN  2
-#define SPICE_INTERFACE_PLAYBACK_FMT   SPICE_INTERFACE_AUDIO_FMT_S16
-
-struct SpicePlaybackInterface {
-    SpiceBaseInterface base;
-};
-
-struct SpicePlaybackInstance {
-    SpiceBaseInstance  base;
-    SpicePlaybackState *st;
-};
-
-void spice_server_playback_start(SpicePlaybackInstance *sin);
-void spice_server_playback_stop(SpicePlaybackInstance *sin);
-void spice_server_playback_get_buffer(SpicePlaybackInstance *sin,
-                                      uint32_t **samples, uint32_t *nsamples);
-void spice_server_playback_put_samples(SpicePlaybackInstance *sin,
-                                       uint32_t *samples);
-
-#define SPICE_INTERFACE_RECORD "record"
-#define SPICE_INTERFACE_RECORD_MAJOR 2
-#define SPICE_INTERFACE_RECORD_MINOR 1
-typedef struct SpiceRecordInterface SpiceRecordInterface;
-typedef struct SpiceRecordInstance SpiceRecordInstance;
-typedef struct SpiceRecordState SpiceRecordState;
-
-#define SPICE_INTERFACE_RECORD_FREQ  44100
-#define SPICE_INTERFACE_RECORD_CHAN  2
-#define SPICE_INTERFACE_RECORD_FMT   SPICE_INTERFACE_AUDIO_FMT_S16
-
-struct SpiceRecordInterface {
-    SpiceBaseInterface base;
-};
-
-struct SpiceRecordInstance {
-    SpiceBaseInstance base;
-    SpiceRecordState  *st;
-};
-
-void spice_server_record_start(SpiceRecordInstance *sin);
-void spice_server_record_stop(SpiceRecordInstance *sin);
-uint32_t spice_server_record_get_samples(SpiceRecordInstance *sin,
-                                         uint32_t *samples, uint32_t bufsize);
-
-#define SPICE_INTERFACE_VDI_PORT "vdi_port"
-#define SPICE_INTERFACE_VDI_PORT_MAJOR 1
-#define SPICE_INTERFACE_VDI_PORT_MINOR 1
-typedef struct SpiceVDIPortInterface SpiceVDIPortInterface;
-typedef struct SpiceVDIPortInstance SpiceVDIPortInstance;
-typedef struct SpiceVDIPortState SpiceVDIPortState;
-
-struct SpiceVDIPortInterface {
-    SpiceBaseInterface base;
-
-    void (*state)(SpiceVDIPortInstance *sin, int connected);
-    int (*write)(SpiceVDIPortInstance *sin, const uint8_t *buf, int len);
-    int (*read)(SpiceVDIPortInstance *sin, uint8_t *buf, int len);
-};
-
-struct SpiceVDIPortInstance {
-    SpiceBaseInstance base;
-    SpiceVDIPortState *st;
-};
-
-void spice_server_vdi_port_wakeup(SpiceVDIPortInstance *sin);
-
-#define SPICE_INTERFACE_NET_WIRE "net_wire"
-#define SPICE_INTERFACE_NET_WIRE_MAJOR 1
-#define SPICE_INTERFACE_NET_WIRE_MINOR 1
-typedef struct SpiceNetWireInterface SpiceNetWireInterface;
-typedef struct SpiceNetWireInstance SpiceNetWireInstance;
-typedef struct SpiceNetWireState SpiceNetWireState;
-
-struct NetWireInterface {
-    SpiceBaseInterface base;
-
-    struct in_addr (*get_ip)(SpiceNetWireInterface *sin);
-    int (*can_send_packet)(SpiceNetWireInterface *sin);
-    void (*send_packet)(SpiceNetWireInterface *sin, const uint8_t *pkt, int len);
-};
-
-struct SpiceNetWireInstance {
-    SpiceBaseInstance base;
-    SpiceNetWireState *st;
-};
-
-void spice_server_net_wire_recv_packet(SpiceNetWireInstance *sin,
-                                       const uint8_t *pkt, int len);
-
-#endif
-
commit 3f4d6c6ad6d8cc7f43e970da2b49e76be147e3d7
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue May 18 15:07:41 2010 +0200

    vd_interface.h cleanups.
    
    Drop leftover bits which are not used any more.
    Rename DrawArea to QXLDrawArea.

diff --git a/server/reds.c b/server/reds.c
index 4fc0392..e9bf716 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -254,7 +254,6 @@ typedef struct RedsState {
     VDIPortState agent_state;
     InputsState *inputs_state;
 
-    VDObjectRef mig_notifier;
     int mig_wait_connect;
     int mig_wait_disconnect;
     int mig_inprogress;
@@ -372,21 +371,6 @@ static int default_channel_security =
 
 static RedSSLParameters ssl_parameters;
 
-static int args_is_empty(const VDICmdArg* args)
-{
-    return !args || args[0].descriptor.type == ARG_TYPE_INVALID;
-}
-
-const int args_is_string(const VDICmdArg* args)
-{
-    return !args_is_empty(args) && args->descriptor.type == ARG_TYPE_STRING;
-}
-
-const int args_is_int(const VDICmdArg* args)
-{
-    return !args_is_empty(args) && args->descriptor.type == ARG_TYPE_INT;
-}
-
 static ChannelSecurityOptions *find_channel_security(int id)
 {
     ChannelSecurityOptions *now = channels_security;
diff --git a/server/snd_worker.c b/server/snd_worker.c
index 6a08e92..c43ef2d 100644
--- a/server/snd_worker.c
+++ b/server/snd_worker.c
@@ -121,7 +121,6 @@ struct AudioFrame {
 typedef struct PlaybackChannel {
     SndChannel base;
     AudioFrame frames[3];
-    VDObjectRef plug_ref;
     AudioFrame *free_frames;
     AudioFrame *in_progress;
     AudioFrame *pending_frame;
@@ -172,7 +171,6 @@ typedef struct __attribute__ ((__packed__)) RecordMigrateMessage {
 
 typedef struct RecordChannel {
     SndChannel base;
-    VDObjectRef plug_ref;
     uint32_t samples[RECORD_SAMPLES_SIZE];
     uint32_t write_pos;
     uint32_t read_pos;
diff --git a/server/vd_interface.h b/server/vd_interface.h
index aaa1ca8..fc81a24 100644
--- a/server/vd_interface.h
+++ b/server/vd_interface.h
@@ -33,10 +33,6 @@
 
 #include <stdint.h>
 
-#define VM_INTERFACE_VERSION 1
-typedef unsigned long VDObjectRef;
-#define INVALID_VD_OBJECT_REF 0
-
 typedef struct SpiceBaseInterface SpiceBaseInterface;
 typedef struct SpiceBaseInstance SpiceBaseInstance;
 
@@ -55,12 +51,6 @@ struct SpiceBaseInstance {
 #define SPICE_INTERFACE_CORE_MINOR 2
 typedef struct SpiceCoreInterface SpiceCoreInterface;
 
-typedef enum {
-    VD_LOG_ERROR = 1,
-    VD_LOG_WARN,
-    VD_LOG_INFO,
-} LogLevel;
-
 #define SPICE_WATCH_EVENT_READ  (1 << 0)
 #define SPICE_WATCH_EVENT_WRITE (1 << 1)
 
@@ -121,14 +111,14 @@ struct QXLWorker {
     void (*loadvm_commands)(QXLWorker *worker, struct QXLCommandExt *ext, uint32_t count);
 };
 
-typedef struct DrawArea {
+typedef struct QXLDrawArea {
     uint8_t *buf;
     uint32_t size;
     uint8_t *line_0;
     uint32_t width;
     uint32_t heigth;
     int stride;
-} DrawArea;
+} QXLDrawArea;
 
 typedef struct QXLDevInfo {
     uint32_t x_res;
@@ -136,7 +126,7 @@ typedef struct QXLDevInfo {
     uint32_t bits;
     uint32_t use_hardware_cursor;
 
-    DrawArea draw_area;
+    QXLDrawArea draw_area;
 
     uint32_t ram_size;
 } QXLDevInfo;
@@ -264,29 +254,6 @@ struct SpiceTabletInstance {
     SpiceTabletState  *st;
 };
 
-enum VDIArgType{
-    ARG_TYPE_INVALID,
-    ARG_TYPE_INT,
-    ARG_TYPE_STRING,
-};
-
-typedef struct VDIArgDescriptor {
-    char* name;
-    int type;
-    int optional;
-} VDIArgDescriptor;
-
-typedef struct VDICmdArg {
-    VDIArgDescriptor descriptor;
-    union {
-        uint64_t int_val;
-        const char *string_val;
-    };
-} VDICmdArg;
-
-typedef void (*VDICmdHandler)(const VDICmdArg* args);
-typedef void (*VDIInfoCmdHandler)(void);
-
 #define SPICE_INTERFACE_PLAYBACK "playback"
 #define SPICE_INTERFACE_PLAYBACK_MAJOR 1
 #define SPICE_INTERFACE_PLAYBACK_MINOR 1
commit 5b0bc279c952d0677f83e2c09faa30639cbd0579
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue May 18 14:11:25 2010 +0200

    NetWireInterface: redesign

diff --git a/server/red_tunnel_worker.h b/server/red_tunnel_worker.h
index 9f3a61c..d4bf4b7 100755
--- a/server/red_tunnel_worker.h
+++ b/server/red_tunnel_worker.h
@@ -24,6 +24,6 @@
 
 #include "vd_interface.h"
 
-void *red_tunnel_attach(SpiceCoreInterface *core_interface, NetWireInterface *vlan_interface);
+void *red_tunnel_attach(SpiceCoreInterface *core_interface, SpiceNetWireInstance *sin);
 
 #endif
diff --git a/server/reds.c b/server/reds.c
index 891cd74..4fc0392 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -3521,20 +3521,22 @@ __visible__ int spice_server_add_interface(SpiceServer *s,
         }
         attach_to_red_agent(SPICE_CONTAINEROF(sin, SpiceVDIPortInstance, base));
 
-    } else if (strcmp(interface->type, VD_INTERFACE_NET_WIRE) == 0) {
+    } else if (strcmp(interface->type, SPICE_INTERFACE_NET_WIRE) == 0) {
 #ifdef HAVE_SLIRP
-        NetWireInterface * net_wire = (NetWireInterface *)interface;
-        red_printf("VD_INTERFACE_NET_WIRE");
+        SpiceNetWireInstance *net;
+        red_printf("SPICE_INTERFACE_NET_WIRE");
         if (red_tunnel) {
             red_printf("net wire already attached");
             return -1;
         }
-        if (interface->major_version != VD_INTERFACE_NET_WIRE_MAJOR ||
-            interface->minor_version < VD_INTERFACE_NET_WIRE_MINOR) {
+        if (interface->major_version != SPICE_INTERFACE_NET_WIRE_MAJOR ||
+            interface->minor_version < SPICE_INTERFACE_NET_WIRE_MINOR) {
             red_printf("unsuported net wire interface");
             return -1;
         }
-        red_tunnel = red_tunnel_attach(core, net_wire);
+        net = SPICE_CONTAINEROF(sin, SpiceNetWireInstance, base);
+        net->st = spice_new0(SpiceNetWireState, 1);
+        red_tunnel = red_tunnel_attach(core, net);
 #else
         red_printf("unsupported net wire interface");
         return -1;
diff --git a/server/reds.h b/server/reds.h
index 78581f8..b508283 100644
--- a/server/reds.h
+++ b/server/reds.h
@@ -75,6 +75,10 @@ struct QXLState {
     struct RedDispatcher  *dispatcher;
 };
 
+struct SpiceNetWireState {
+    int dummy;
+};
+
 void reds_desable_mm_timer();
 void reds_enable_mm_timer();
 void reds_update_mm_timer(uint32_t mm_time);
diff --git a/server/vd_interface.h b/server/vd_interface.h
index 5d50ee9..aaa1ca8 100644
--- a/server/vd_interface.h
+++ b/server/vd_interface.h
@@ -365,23 +365,28 @@ struct SpiceVDIPortInstance {
 
 void spice_server_vdi_port_wakeup(SpiceVDIPortInstance *sin);
 
-#define VD_INTERFACE_NET_WIRE "net_wire"
-#define VD_INTERFACE_NET_WIRE_MAJOR 1
-#define VD_INTERFACE_NET_WIRE_MINOR 1
-
-typedef struct NetWireInterface NetWireInterface;
-typedef void (*net_wire_packet_route_proc_t)(void *opaque, const uint8_t *pkt, int pkt_len);
+#define SPICE_INTERFACE_NET_WIRE "net_wire"
+#define SPICE_INTERFACE_NET_WIRE_MAJOR 1
+#define SPICE_INTERFACE_NET_WIRE_MINOR 1
+typedef struct SpiceNetWireInterface SpiceNetWireInterface;
+typedef struct SpiceNetWireInstance SpiceNetWireInstance;
+typedef struct SpiceNetWireState SpiceNetWireState;
 
 struct NetWireInterface {
     SpiceBaseInterface base;
 
-    struct in_addr (*get_ip)(NetWireInterface *vlan);
-    int (*can_send_packet)(NetWireInterface *vlan);
-    void (*send_packet)(NetWireInterface *vlan, const uint8_t *buf, int size);
-    VDObjectRef (*register_route_packet)(NetWireInterface *vlan, net_wire_packet_route_proc_t proc,
-                                         void *opaque);
-    void (*unregister_route_packet)(NetWireInterface *vlan, VDObjectRef proc);
+    struct in_addr (*get_ip)(SpiceNetWireInterface *sin);
+    int (*can_send_packet)(SpiceNetWireInterface *sin);
+    void (*send_packet)(SpiceNetWireInterface *sin, const uint8_t *pkt, int len);
 };
 
+struct SpiceNetWireInstance {
+    SpiceBaseInstance base;
+    SpiceNetWireState *st;
+};
+
+void spice_server_net_wire_recv_packet(SpiceNetWireInstance *sin,
+                                       const uint8_t *pkt, int len);
+
 #endif
 
commit a8419b00dc348720ba008cc66754fa91478b1ab9
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue May 11 13:21:14 2010 +0200

    zap MigrationInterface
    
    Remove remaining MigrationInterface bits.

diff --git a/server/reds.c b/server/reds.c
index 3c832b5..891cd74 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -55,7 +55,6 @@
 #endif
 
 SpiceCoreInterface *core = NULL;
-static MigrationInterface *mig = NULL;
 static SpiceKbdInstance *keyboard = NULL;
 static SpiceMouseInstance *mouse = NULL;
 static SpiceTabletInstance *tablet = NULL;
@@ -688,7 +687,6 @@ static void reds_mig_cleanup()
         reds->mig_wait_connect = FALSE;
         reds->mig_wait_disconnect = FALSE;
         core->timer_cancel(reds->mig_timer);
-        mig->notifier_done(mig, reds->mig_notifier);
     }
 }
 
@@ -3315,7 +3313,6 @@ static void reds_mig_finished(int completed)
 
     if (reds->peer == NULL) {
         red_printf("no peer connected");
-        mig->notifier_done(mig, reds->mig_notifier);
         return;
     }
     reds->mig_inprogress = TRUE;
@@ -3457,19 +3454,6 @@ __visible__ int spice_server_add_interface(SpiceServer *s,
         mouse = SPICE_CONTAINEROF(sin, SpiceMouseInstance, base);
         mouse->st = spice_new0(SpiceMouseState, 1);
 
-    } else if (strcmp(interface->type, VD_INTERFACE_MIGRATION) == 0) {
-        red_printf("VD_INTERFACE_MIGRATION");
-        if (mig) {
-            red_printf("already have migration");
-            return -1;
-        }
-        if (interface->major_version != VD_INTERFACE_MIGRATION_MAJOR ||
-            interface->minor_version < VD_INTERFACE_MIGRATION_MINOR) {
-            red_printf("unsuported migration interface");
-            return -1;
-        }
-        mig = (MigrationInterface *)interface;
-
     } else if (strcmp(interface->type, SPICE_INTERFACE_QXL) == 0) {
         QXLInstance *qxl;
 
diff --git a/server/vd_interface.h b/server/vd_interface.h
index a5a20ec..5d50ee9 100644
--- a/server/vd_interface.h
+++ b/server/vd_interface.h
@@ -264,17 +264,6 @@ struct SpiceTabletInstance {
     SpiceTabletState  *st;
 };
 
-#define VD_INTERFACE_MIGRATION "migration"
-#define VD_INTERFACE_MIGRATION_MAJOR 1
-#define VD_INTERFACE_MIGRATION_MINOR 1
-typedef struct MigrationInterface MigrationInterface;
-
-struct MigrationInterface {
-    SpiceBaseInterface base;
-
-    void (*notifier_done)(MigrationInterface *mig, VDObjectRef notifier);
-};
-
 enum VDIArgType{
     ARG_TYPE_INVALID,
     ARG_TYPE_INT,
commit cb5f500aa6c04298be1f13c07063675c83b1d883
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Apr 23 22:40:18 2010 +0200

    migration: new api
    
    Add new API for migration, based on what RHEL-6 has.

diff --git a/server/reds.c b/server/reds.c
index 3deac36..3c832b5 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -241,6 +241,8 @@ typedef struct RedsStatValue {
 
 #endif
 
+typedef struct RedsMigSpice RedsMigSpice;
+
 typedef struct RedsState {
     int listen_socket;
     int secure_listen_socket;
@@ -258,6 +260,7 @@ typedef struct RedsState {
     int mig_wait_disconnect;
     int mig_inprogress;
     int mig_target;
+    RedsMigSpice *mig_spice;
     int num_of_channels;
     IncomingHandler in_handler;
     RedsOutgoingData outgoing;
@@ -3209,7 +3212,7 @@ static void set_one_channel_security(int id, uint32_t security)
 
 #define REDS_SAVE_VERSION 1
 
-typedef struct RedsMigSpice {
+struct RedsMigSpice {
     char pub_key[SPICE_TICKET_PUBKEY_BYTES];
     uint32_t mig_key;
     char *host;
@@ -3218,7 +3221,7 @@ typedef struct RedsMigSpice {
     uint16_t cert_pub_key_type;
     uint32_t cert_pub_key_len;
     uint8_t* cert_pub_key;
-} RedsMigSpice;
+};
 
 typedef struct RedsMigSpiceMessage {
     uint32_t link_id;
@@ -3229,8 +3232,9 @@ typedef struct RedsMigCertPubKeyInfo {
     uint32_t len;
 } RedsMigCertPubKeyInfo;
 
-static void reds_mig_continue(RedsMigSpice *s)
+static void reds_mig_continue(void)
 {
+    RedsMigSpice *s = reds->mig_spice;
     SpiceMsgMainMigrationBegin *migrate;
     SimpleOutItem *item;
     int host_len;
@@ -3251,15 +3255,16 @@ static void reds_mig_continue(RedsMigSpice *s)
     memcpy((uint8_t*)(migrate) + migrate->pub_key_offset, s->cert_pub_key, s->cert_pub_key_len);
     reds_push_pipe_item(&item->base);
 
-    free(s);
+    free(reds->mig_spice->host);
+    free(reds->mig_spice);
+    reds->mig_spice = NULL;
+
     reds->mig_wait_connect = TRUE;
     core->timer_start(reds->mig_timer, MIGRATE_TIMEOUT);
 }
 
-static void reds_mig_started(void *opaque)
+static void reds_mig_started(void)
 {
-    RedsMigSpice *spice_migration = NULL;
-
     red_printf("");
 
     reds->mig_inprogress = TRUE;
@@ -3283,30 +3288,19 @@ static void reds_mig_started(void *opaque)
         goto error;
     }
 
-    spice_migration = spice_new0(RedsMigSpice, 1);
-    spice_migration->port = -1;
-    spice_migration->sport = -1;
-
-    /* FIXME */
-
-    if ((spice_migration->sport == -1 && spice_migration->port == -1) || !spice_migration->host) {
-        red_printf("invalid args port %d sport %d host %s",
-                   spice_migration->port,
-                   spice_migration->sport,
-                   (spice_migration->host) ? spice_migration->host : "NULL");
-        goto error;
-    }
-
-    /* FIXME: send SPICE_MSG_MAIN_MIGRATE_BEGIN ??? */
-    reds_mig_continue(spice_migration);
+    reds_mig_continue();
     return;
 
 error:
-    free(spice_migration);
+    if (reds->mig_spice) {
+        free(reds->mig_spice->host);
+        free(reds->mig_spice);
+        reds->mig_spice = NULL;
+    }
     reds_mig_disconnect();
 }
 
-static void reds_mig_finished(void *opaque, int completed)
+static void reds_mig_finished(int completed)
 {
     SimpleOutItem *item;
 
@@ -3475,13 +3469,6 @@ __visible__ int spice_server_add_interface(SpiceServer *s,
             return -1;
         }
         mig = (MigrationInterface *)interface;
-        reds->mig_notifier = mig->register_notifiers(mig,
-                                                     reds_mig_started,
-                                                     reds_mig_finished,
-                                                     NULL);
-        if (reds->mig_notifier == INVALID_VD_OBJECT_REF) {
-            red_error("migration register failed");
-        }
 
     } else if (strcmp(interface->type, SPICE_INTERFACE_QXL) == 0) {
         QXLInstance *qxl;
@@ -3967,3 +3954,59 @@ __visible__ int spice_server_kbd_leds(SpiceKbdInstance *sin, int leds)
     reds_on_keyboard_leds_change(NULL, leds);
     return 0;
 }
+
+__visible__ int spice_server_migrate_info(SpiceServer *s, const char* dest,
+                                          int port, int secure_port,
+                                          const char* cert_subject)
+{
+    RedsMigSpice *spice_migration = NULL;
+
+    ASSERT(reds == s);
+
+    if ((port == -1 && secure_port == -1) || !dest)
+        return -1;
+
+    spice_migration = spice_new0(RedsMigSpice, 1);
+    spice_migration->port = port;
+    spice_migration->sport = secure_port;
+    spice_migration->host = strdup(dest);
+
+    if (cert_subject) {
+        /* TODO */
+    }
+
+    reds->mig_spice = spice_migration;
+    return 0;
+}
+
+__visible__ int spice_server_migrate_start(SpiceServer *s)
+{
+    ASSERT(reds == s);
+
+    if (!reds->mig_spice) {
+        return -1;
+    }
+    reds_mig_started();
+    return 0;
+}
+
+__visible__ int spice_server_migrate_client_state(SpiceServer *s)
+{
+    ASSERT(reds == s);
+
+    if (!reds->peer) {
+        return SPICE_MIGRATE_CLIENT_NONE;
+    } else if (reds->mig_wait_connect) {
+        return SPICE_MIGRATE_CLIENT_WAITING;
+    } else {
+        return SPICE_MIGRATE_CLIENT_READY;
+    }
+    return 0;
+}
+
+__visible__ int spice_server_migrate_end(SpiceServer *s, int completed)
+{
+    ASSERT(reds == s);
+    reds_mig_finished(completed);
+    return 0;
+}
diff --git a/server/spice.h b/server/spice.h
index 80291b9..70434c2 100644
--- a/server/spice.h
+++ b/server/spice.h
@@ -69,4 +69,16 @@ int spice_server_add_renderer(SpiceServer *s, const char *name);
 int spice_server_get_sock_info(SpiceServer *s, struct sockaddr *sa, socklen_t *salen);
 int spice_server_get_peer_info(SpiceServer *s, struct sockaddr *sa, socklen_t *salen);
 
+enum {
+    SPICE_MIGRATE_CLIENT_NONE = 1,
+    SPICE_MIGRATE_CLIENT_WAITING,
+    SPICE_MIGRATE_CLIENT_READY,
+};
+
+int spice_server_migrate_info(SpiceServer *s, const char* dest, int port, int secure_port,
+                              const char* cert_subject);
+int spice_server_migrate_start(SpiceServer *s);
+int spice_server_migrate_client_state(SpiceServer *s);
+int spice_server_migrate_end(SpiceServer *s, int completed);
+
 #endif
diff --git a/server/vd_interface.h b/server/vd_interface.h
index 7c7c202..a5a20ec 100644
--- a/server/vd_interface.h
+++ b/server/vd_interface.h
@@ -268,17 +268,10 @@ struct SpiceTabletInstance {
 #define VD_INTERFACE_MIGRATION_MAJOR 1
 #define VD_INTERFACE_MIGRATION_MINOR 1
 typedef struct MigrationInterface MigrationInterface;
-typedef void (*migration_notify_started_t)(void *opaque);
-typedef void (*migration_notify_finished_t)(void *opaque, int completed);
 
 struct MigrationInterface {
     SpiceBaseInterface base;
 
-    VDObjectRef (*register_notifiers)(MigrationInterface* mig,
-                                      migration_notify_started_t,
-                                      migration_notify_finished_t,
-                                      void *opaque);
-    void (*unregister_notifiers)(MigrationInterface* mig, VDObjectRef notifier);
     void (*notifier_done)(MigrationInterface *mig, VDObjectRef notifier);
 };
 
commit 08927fabe57c17086fe3bce3a9ca166e2309349e
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue May 11 13:20:02 2010 +0200

    [debug] migration troubleshooting

diff --git a/client/application.cpp b/client/application.cpp
index 4eb8ac8..74f5543 100644
--- a/client/application.cpp
+++ b/client/application.cpp
@@ -2110,7 +2110,7 @@ void Application::init_logger()
     }
 
     log4cpp::Category& root = log4cpp::Category::getRoot();
-#ifdef RED_DEBUG
+#if 1 // RED_DEBUG
     root.setPriority(log4cpp::Priority::DEBUG);
     root.removeAllAppenders();
     root.addAppender(new log4cpp::FileAppender("_", fd));
diff --git a/server/reds.c b/server/reds.c
index b066961..3deac36 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -93,7 +93,7 @@ int agent_mouse = TRUE;
 
 static void openssl_init();
 
-#define MIGRATE_TIMEOUT (1000 * 10) /* 10sec */
+#define MIGRATE_TIMEOUT (1000 * 100) /* 10sec */
 #define PING_INTERVAL (1000 * 10)
 #define KEY_MODIFIERS_TTL (1000 * 2) /*2sec*/
 #define MM_TIMER_GRANULARITY_MS (1000 / 30)
commit 230356858178efaeec2dc5a9088c4fc675b178eb
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Apr 23 11:54:26 2010 +0200

    zap migration code
    
    Drop all code which depends on accessing the migration file handle.

diff --git a/server/reds.c b/server/reds.c
index 9b42cbf..b066961 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -3169,58 +3169,6 @@ typedef struct OptionsMap {
     int val;
 } OptionsMap;
 
-static int find_option(const char *str, OptionsMap *options_map)
-{
-    int i = 0;
-
-    for (i = 0; options_map[i].name != NULL; i++) {
-        if (strcmp(str, options_map[i].name) == 0) {
-            return options_map[i].val;
-        }
-    }
-    return SPICE_OPTION_INVALID;
-}
-
-static void clear_blanks(char **ptr)
-{
-    char *str = *ptr;
-    while (isspace(*str)) {
-        str++;
-    }
-    while (isspace(str[strlen(str) - 1])) {
-        str[strlen(str) - 1] = 0;
-    }
-    *ptr = str;
-}
-
-static int get_option(char **args, char **out_val, OptionsMap *map, char seperator)
-{
-    char *p;
-    char *next;
-    char *val;
-
-    ASSERT(args && out_val);
-
-    p = *args;
-    if ((next = strchr(p, seperator))) {
-        *next = 0;
-        *args = next + 1;
-    } else {
-        *args = NULL;
-    }
-
-    if ((val = strchr(p, '='))) {
-        *(val++) = 0;
-        clear_blanks(&val);
-        *out_val = (strlen(val) == 0) ? NULL : val;
-    } else {
-        *out_val = NULL;
-    }
-
-    clear_blanks(&p);
-    return find_option(p, map);
-}
-
 enum {
     SPICE_TICKET_OPTION_INVALID,
     SPICE_TICKET_OPTION_EXPIRATION,
@@ -3261,41 +3209,9 @@ static void set_one_channel_security(int id, uint32_t security)
 
 #define REDS_SAVE_VERSION 1
 
-static OptionsMap spice_mig_options[] = {
-    {"spicesport", SPICE_OPTION_SPORT},
-    {"spiceport", SPICE_OPTION_PORT},
-    {"spicehost", SPICE_OPTION_HOST},
-    {NULL, 0},
-};
-
-struct RedsMigSpice;
-
-typedef struct RedsMigRead {
-    uint8_t buf[RECIVE_BUF_SIZE];
-    uint32_t end_pos;
-    uint32_t size;
-
-    void (*handle_data)(struct RedsMigSpice *message);
-} RedsMigRead;
-
-typedef struct RedsMigWrite {
-    uint8_t buf[SEND_BUF_SIZE];
-    uint8_t *now;
-    uint32_t length;
-
-    void (*handle_done)(struct RedsMigSpice *s);
-} RedsMigWrite;
-
 typedef struct RedsMigSpice {
-    int fd;
-    SpiceWatch *watch;
-    RedsMigWrite write;
-    RedsMigRead read;
-
     char pub_key[SPICE_TICKET_PUBKEY_BYTES];
     uint32_t mig_key;
-
-    char *local_args;
     char *host;
     int port;
     int sport;
@@ -3313,104 +3229,6 @@ typedef struct RedsMigCertPubKeyInfo {
     uint32_t len;
 } RedsMigCertPubKeyInfo;
 
-static int reds_mig_actual_read(RedsMigSpice *s)
-{
-    for (;;) {
-        uint8_t *buf = s->read.buf;
-        uint32_t pos = s->read.end_pos;
-        int n;
-        n = read(s->fd, buf + pos, s->read.size - pos);
-        if (n <= 0) {
-            if (n == 0) {
-                return -1;
-            }
-            switch (errno) {
-            case EAGAIN:
-                return 0;
-            case EINTR:
-                break;
-            case EPIPE:
-                return -1;
-            default:
-                red_printf("%s", strerror(errno));
-                return -1;
-            }
-        } else {
-            s->read.end_pos += n;
-            if (s->read.end_pos == s->read.size) {
-                s->read.handle_data(s);
-                return 0;
-            }
-        }
-    }
-}
-
-static int reds_mig_actual_write(RedsMigSpice *s)
-{
-    if (!s->write.length) {
-        return 0;
-    }
-
-    while (s->write.length) {
-        int n;
-
-        n = write(s->fd, s->write.now, s->write.length);
-        if (n <= 0) {
-            if (n == 0) {
-                return -1;
-            }
-            switch (errno) {
-            case EAGAIN:
-                return 0;
-            case EINTR:
-                break;
-            case EPIPE:
-                return -1;
-            default:
-                red_printf("%s", strerror(errno));
-                return -1;
-            }
-        } else {
-            s->write.now += n;
-            s->write.length -= n;
-        }
-    }
-
-    s->write.handle_done(s);
-    return 0;
-}
-
-static void reds_mig_failed(RedsMigSpice *s)
-{
-    red_printf("");
-    core->watch_remove(s->watch);
-    s->watch = NULL;
-    if (s->local_args) {
-        free(s->local_args);
-    }
-    free(s);
-
-    reds_mig_disconnect();
-}
-
-static void reds_mig_event(int fd, int event, void *data)
-{
-    RedsMigSpice *s = data;
-
-    if (event & SPICE_WATCH_EVENT_READ) {
-        if (reds_mig_actual_read((RedsMigSpice *)data)) {
-            red_printf("read error cannot continue spice migration");
-            reds_mig_failed(s);
-        }
-    }
-    if (event & SPICE_WATCH_EVENT_WRITE) {
-        if (reds_mig_actual_write((RedsMigSpice *)data)) {
-            red_printf("write error cannot continue spice migration");
-            reds_mig_failed(s);
-        }
-    }
-}
-
 static void reds_mig_continue(RedsMigSpice *s)
 {
     SpiceMsgMainMigrationBegin *migrate;
@@ -3418,8 +3236,6 @@ static void reds_mig_continue(RedsMigSpice *s)
     int host_len;
 
     red_printf("");
-    core->watch_remove(s->watch);
-    s->watch = NULL;
     host_len = strlen(s->host) + 1;
     item = new_simple_out_item(SPICE_MSG_MAIN_MIGRATE_BEGIN,
                                sizeof(SpiceMsgMainMigrationBegin) + host_len + s->cert_pub_key_len);
@@ -3435,174 +3251,15 @@ static void reds_mig_continue(RedsMigSpice *s)
     memcpy((uint8_t*)(migrate) + migrate->pub_key_offset, s->cert_pub_key, s->cert_pub_key_len);
     reds_push_pipe_item(&item->base);
 
-    free(s->local_args);
     free(s);
     reds->mig_wait_connect = TRUE;
     core->timer_start(reds->mig_timer, MIGRATE_TIMEOUT);
 }
 
-static void reds_mig_receive_ack(RedsMigSpice *s)
-{
-    s->read.size = sizeof(uint32_t);
-    s->read.end_pos = 0;
-    s->read.handle_data = reds_mig_continue;
-
-    core->watch_update_mask(s->watch, SPICE_WATCH_EVENT_READ);
-}
-
-static void reds_mig_send_link_id(RedsMigSpice *s)
-{
-    RedsMigSpiceMessage *data = (RedsMigSpiceMessage *)s->write.buf;
-
-    memcpy(&data->link_id, &reds->link_id, sizeof(reds->link_id));
-
-    s->write.now = s->write.buf;
-    s->write.length = sizeof(RedsMigSpiceMessage);
-    s->write.handle_done = reds_mig_receive_ack;
-
-    core->watch_update_mask(s->watch, SPICE_WATCH_EVENT_READ | SPICE_WATCH_EVENT_WRITE);
-}
-
-static void reds_mig_send_ticket(RedsMigSpice *s)
-{
-    EVP_PKEY *pubkey = NULL;
-    BIO *bio_key;
-    RSA *rsa;
-    int rsa_size = 0;
-
-    red_printf("");
-
-    bio_key = BIO_new(BIO_s_mem());
-    if (bio_key != NULL) {
-        BIO_write(bio_key, s->read.buf, SPICE_TICKET_PUBKEY_BYTES);
-        pubkey = d2i_PUBKEY_bio(bio_key, NULL);
-        rsa = pubkey->pkey.rsa;
-        rsa_size = RSA_size(rsa);
-        if (RSA_public_encrypt(strlen(reds->taTicket.password) + 1,
-                               (unsigned char *)reds->taTicket.password,
-                               (uint8_t *)(s->write.buf),
-                               rsa, RSA_PKCS1_OAEP_PADDING) > 0) {
-            s->write.length = RSA_size(rsa);
-            s->write.now = s->write.buf;
-            s->write.handle_done = reds_mig_send_link_id;
-            core->watch_update_mask(s->watch, SPICE_WATCH_EVENT_READ | SPICE_WATCH_EVENT_WRITE);
-        } else {
-            reds_mig_failed(s);
-        }
-    } else {
-        reds_mig_failed(s);
-    }
-
-    EVP_PKEY_free(pubkey);
-    BIO_free(bio_key);
-}
-
-static void reds_mig_receive_cert_public_key(RedsMigSpice *s)
-{
-    s->cert_pub_key = spice_memdup(s->read.buf, s->cert_pub_key_len);
-
-    s->read.size = SPICE_TICKET_PUBKEY_BYTES;
-    s->read.end_pos = 0;
-    s->read.handle_data = reds_mig_send_ticket;
-
-    core->watch_update_mask(s->watch, SPICE_WATCH_EVENT_READ);
-}
-
-static void reds_mig_receive_cert_public_key_info(RedsMigSpice *s)
-{
-    RedsMigCertPubKeyInfo* pubkey_info = (RedsMigCertPubKeyInfo*)s->read.buf;
-    s->cert_pub_key_type = pubkey_info->type;
-    s->cert_pub_key_len = pubkey_info->len;
-
-    if (s->cert_pub_key_len > RECIVE_BUF_SIZE) {
-        red_printf("certificate public key length exceeds buffer size");
-        reds_mig_failed(s);
-        return;
-    }
-
-    if (s->cert_pub_key_len) {
-        s->read.size = s->cert_pub_key_len;
-        s->read.end_pos = 0;
-        s->read.handle_data = reds_mig_receive_cert_public_key;
-    } else {
-        s->cert_pub_key = NULL;
-        s->read.size = SPICE_TICKET_PUBKEY_BYTES;
-        s->read.end_pos = 0;
-        s->read.handle_data = reds_mig_send_ticket;
-    }
-
-    core->watch_update_mask(s->watch, SPICE_WATCH_EVENT_READ);
-}
-
-static void reds_mig_handle_send_abort_done(RedsMigSpice *s)
-{
-    reds_mig_failed(s);
-}
-
-static void reds_mig_receive_version(RedsMigSpice *s)
-{
-    uint32_t* dest_version;
-    uint32_t resault;
-    dest_version = (uint32_t*)s->read.buf;
-    resault = REDS_MIG_ABORT;
-    memcpy(s->write.buf, &resault, sizeof(resault));
-    s->write.length = sizeof(resault);
-    s->write.now = s->write.buf;
-    s->write.handle_done = reds_mig_handle_send_abort_done;
-    core->watch_update_mask(s->watch, SPICE_WATCH_EVENT_READ | SPICE_WATCH_EVENT_WRITE);
-}
-
-static void reds_mig_control(RedsMigSpice *spice_migration)
-{
-    uint32_t *control;
-
-    core->watch_update_mask(spice_migration->watch, 0);
-    control = (uint32_t *)spice_migration->read.buf;
-
-    switch (*control) {
-    case REDS_MIG_CONTINUE:
-        spice_migration->read.size = sizeof(RedsMigCertPubKeyInfo);
-        spice_migration->read.end_pos = 0;
-        spice_migration->read.handle_data = reds_mig_receive_cert_public_key_info;
-
-        core->watch_update_mask(spice_migration->watch, SPICE_WATCH_EVENT_READ);
-        break;
-    case REDS_MIG_ABORT:
-        red_printf("abort");
-        reds_mig_failed(spice_migration);
-        break;
-    case REDS_MIG_DIFF_VERSION:
-        red_printf("different versions");
-        spice_migration->read.size = sizeof(uint32_t);
-        spice_migration->read.end_pos = 0;
-        spice_migration->read.handle_data = reds_mig_receive_version;
-
-        core->watch_update_mask(spice_migration->watch, SPICE_WATCH_EVENT_READ);
-        break;
-    default:
-        red_printf("invalid control");
-        reds_mig_failed(spice_migration);
-    }
-}
-
-static void reds_mig_receive_control(RedsMigSpice *spice_migration)
-{
-    spice_migration->read.size = sizeof(uint32_t);
-    spice_migration->read.end_pos = 0;
-    spice_migration->read.handle_data = reds_mig_control;
-
-    core->watch_update_mask(spice_migration->watch, SPICE_WATCH_EVENT_READ);
-}
-
-static void reds_mig_started(void *opaque, const char *in_args)
+static void reds_mig_started(void *opaque)
 {
     RedsMigSpice *spice_migration = NULL;
-    uint32_t *version;
-    char *val;
-    char *args;
-    int option;
 
-    ASSERT(in_args);
     red_printf("");
 
     reds->mig_inprogress = TRUE;
@@ -3630,48 +3287,7 @@ static void reds_mig_started(void *opaque, const char *in_args)
     spice_migration->port = -1;
     spice_migration->sport = -1;
 
-    spice_migration->local_args = spice_strdup(in_args);
-
-    args = spice_migration->local_args;
-    do {
-        switch (option = get_option(&args, &val, spice_mig_options, ',')) {
-        case SPICE_OPTION_SPORT: {
-            char *endptr;
-
-            if (!val) {
-                goto error;
-            }
-            spice_migration->sport = strtol(val, &endptr, 0);
-            if (endptr != val + strlen(val) || spice_migration->sport < 0 ||
-                                                                  spice_migration->sport > 0xffff) {
-                goto error;
-            }
-            break;
-        }
-        case SPICE_OPTION_PORT: {
-            char *endptr;
-
-            if (!val) {
-                goto error;
-            }
-            spice_migration->port = strtol(val, &endptr, 0);
-            if (
-                endptr != val + strlen(val) ||
-                spice_migration->port < 0 ||
-                spice_migration->port > 0xffff
-                ) {
-                goto error;
-            }
-            break;
-        }
-        case SPICE_OPTION_HOST:
-            if (!val) {
-                goto error;
-            }
-            spice_migration->host = val;
-            break;
-        }
-    } while (args);
+    /* FIXME */
 
     if ((spice_migration->sport == -1 && spice_migration->port == -1) || !spice_migration->host) {
         red_printf("invalid args port %d sport %d host %s",
@@ -3681,31 +3297,12 @@ static void reds_mig_started(void *opaque, const char *in_args)
         goto error;
     }
 
-    spice_migration->fd = mig->begin_hook(mig, reds->mig_notifier);
-
-    if (spice_migration->fd == -1) {
-        goto error;
-    }
-
-    spice_migration->write.now = spice_migration->write.buf;
-    spice_migration->write.length = sizeof(uint32_t);
-    version = (uint32_t *)spice_migration->write.buf;
-    *version = REDS_MIG_VERSION;
-    spice_migration->write.handle_done = reds_mig_receive_control;
-    spice_migration->watch = core->watch_add(spice_migration->fd,
-                                             SPICE_WATCH_EVENT_READ | SPICE_WATCH_EVENT_WRITE,
-                                             reds_mig_event,
-                                             spice_migration);
+    /* FIXME: send SPICE_MSG_MAIN_MIGRATE_BEGIN ??? */
+    reds_mig_continue(spice_migration);
     return;
 
 error:
-    if (spice_migration) {
-        if (spice_migration->local_args) {
-            free(spice_migration->local_args);
-        }
-        free(spice_migration);
-    }
-
+    free(spice_migration);
     reds_mig_disconnect();
 }
 
@@ -3752,228 +3349,6 @@ static void reds_mig_finished(void *opaque, int completed)
     }
 }
 
-static int write_all(int fd, const void *in_buf, int len1)
-{
-    int ret, len;
-    uint8_t *buf = (uint8_t *)in_buf;
-
-    len = len1;
-    while (len > 0) {
-        ret = write(fd, buf, len);
-        if (ret < 0) {
-            if (errno != EINTR && errno != EAGAIN) {
-                return -1;
-            }
-        } else if (ret == 0) {
-            break;
-        } else {
-            buf += ret;
-            len -= ret;
-        }
-    }
-    return len1 - len;
-}
-
-static int read_all(int fd, void *in_nuf, int lenl)
-{
-    int ret, len;
-    uint8_t *buf = in_nuf;
-
-    len = lenl;
-    while (len > 0) {
-        ret = read(fd, buf, len);
-        if (ret < 0) {
-            if (errno != EINTR && errno != EAGAIN) {
-                return -1;
-            }
-        } else if (ret == 0) {
-            break;
-        } else {
-            buf += ret;
-            len -= ret;
-        }
-    }
-    return lenl - len;
-}
-
-static void reds_mig_read_all(int fd, void *buf, int len, const char *name)
-{
-    int n = read_all(fd, buf, len);
-    if (n != len) {
-        red_error("read %s failed, n=%d (%s)", name, n, strerror(errno));
-    }
-}
-
-static void reds_mig_write_all(int fd, void *buf, int len, const char *name)
-{
-    int n = write_all(fd, buf, len);
-    if (n != len) {
-        red_error("write %s faile, n=%d (%s)", name, n, strerror(errno));
-    }
-}
-
-static void reds_mig_send_cert_public_key(int fd)
-{
-    FILE* cert_file;
-    X509* x509;
-    EVP_PKEY* pub_key;
-    unsigned char* pp = NULL;
-    int length;
-    BIO* mem_bio;
-    RedsMigCertPubKeyInfo pub_key_info_msg;
-
-    if (spice_secure_port == -1) {
-        pub_key_info_msg.type = SPICE_PUBKEY_TYPE_INVALID;
-        pub_key_info_msg.len = 0;
-        reds_mig_write_all(fd, &pub_key_info_msg, sizeof(pub_key_info_msg), "cert public key info");
-        return;
-    }
-
-    cert_file =  fopen(ssl_parameters.certs_file, "r");
-    if (!cert_file) {
-        red_error("opening certificate failed");
-    }
-
-    x509 = PEM_read_X509_AUX(cert_file, NULL, NULL, NULL);
-    if (!x509) {
-        red_error("reading x509 cert failed");
-    }
-    pub_key = X509_get_pubkey(x509);
-    if (!pub_key) {
-        red_error("reading public key failed");
-    }
-
-    mem_bio = BIO_new(BIO_s_mem());
-    i2d_PUBKEY_bio(mem_bio, pub_key);
-    if (BIO_flush(mem_bio) != 1) {
-        red_error("bio flush failed");
-    }
-    length = BIO_get_mem_data(mem_bio, &pp);
-
-    switch(pub_key->type) {
-    case EVP_PKEY_RSA:
-        pub_key_info_msg.type = SPICE_PUBKEY_TYPE_RSA;
-        break;
-    case EVP_PKEY_RSA2:
-        pub_key_info_msg.type = SPICE_PUBKEY_TYPE_RSA2;
-        break;
-    case EVP_PKEY_DSA:
-        pub_key_info_msg.type = SPICE_PUBKEY_TYPE_DSA;
-        break;
-    case EVP_PKEY_DSA1:
-        pub_key_info_msg.type = SPICE_PUBKEY_TYPE_DSA1;
-        break;
-    case EVP_PKEY_DSA2:
-        pub_key_info_msg.type = SPICE_PUBKEY_TYPE_DSA2;
-        break;
-    case EVP_PKEY_DSA3:
-        pub_key_info_msg.type = SPICE_PUBKEY_TYPE_DSA3;
-        break;
-    case EVP_PKEY_DSA4:
-        pub_key_info_msg.type = SPICE_PUBKEY_TYPE_DSA4;
-        break;
-    case EVP_PKEY_DH:
-        pub_key_info_msg.type = SPICE_PUBKEY_TYPE_DH;
-        break;
-    case EVP_PKEY_EC:
-        pub_key_info_msg.type = SPICE_PUBKEY_TYPE_EC;
-        break;
-    default:
-        red_error("invalid public key type");
-    }
-    pub_key_info_msg.len = length;
-    reds_mig_write_all(fd, &pub_key_info_msg, sizeof(pub_key_info_msg), "cert public key info");
-    reds_mig_write_all(fd, pp, length, "cert public key");
-
-    BIO_free(mem_bio);
-    fclose(cert_file);
-    EVP_PKEY_free(pub_key);
-    X509_free(x509);
-}
-
-static void reds_mig_recv(void *opaque, int fd)
-{
-    uint32_t ack_message = *(uint32_t *)"ack_";
-    char password[SPICE_MAX_PASSWORD_LENGTH];
-    RedsMigSpiceMessage mig_message;
-    unsigned long f4 = RSA_F4;
-    TicketInfo ticketing_info;
-    uint32_t version;
-    uint32_t resault;
-    BIO *bio;
-
-    BUF_MEM *buff;
-
-    reds_mig_read_all(fd, &version, sizeof(version), "version");
-    // starting from version 3, if the version of the src is bigger
-    // than ours, we send our version to the src.
-    if (version < REDS_MIG_VERSION) {
-        resault = REDS_MIG_ABORT;
-        reds_mig_write_all(fd, &resault, sizeof(resault), "resault");
-        mig->notifier_done(mig, reds->mig_notifier);
-        return;
-    } else if (version > REDS_MIG_VERSION) {
-        uint32_t src_resault;
-        uint32_t self_version = REDS_MIG_VERSION;
-        resault = REDS_MIG_DIFF_VERSION;
-        reds_mig_write_all(fd, &resault, sizeof(resault), "resault");
-        reds_mig_write_all(fd, &self_version, sizeof(self_version), "dest-version");
-        reds_mig_read_all(fd, &src_resault, sizeof(src_resault), "src resault");
-
-        if (src_resault == REDS_MIG_ABORT) {
-            red_printf("abort (response to REDS_MIG_DIFF_VERSION)");
-            mig->notifier_done(mig, reds->mig_notifier);
-            return;
-        } else if (src_resault != REDS_MIG_CONTINUE) {
-            red_printf("invalid response to REDS_MIG_DIFF_VERSION");
-            mig->notifier_done(mig, reds->mig_notifier);
-            return;
-        }
-    } else {
-        resault = REDS_MIG_CONTINUE;
-        reds_mig_write_all(fd, &resault, sizeof(resault), "resault");
-    }
-
-    reds_mig_send_cert_public_key(fd);
-
-    ticketing_info.bn = BN_new();
-    if (!ticketing_info.bn) {
-        red_error("OpenSSL BIGNUMS alloc failed");
-    }
-
-    BN_set_word(ticketing_info.bn, f4);
-    if (!(ticketing_info.rsa = RSA_new())) {
-        red_error("OpenSSL RSA alloc failed");
-    }
-
-    RSA_generate_key_ex(ticketing_info.rsa, SPICE_TICKET_KEY_PAIR_LENGTH, ticketing_info.bn, NULL);
-    ticketing_info.rsa_size = RSA_size(ticketing_info.rsa);
-
-    if (!(bio = BIO_new(BIO_s_mem()))) {
-        red_error("OpenSSL BIO alloc failed");
-    }
-
-    i2d_RSA_PUBKEY_bio(bio, ticketing_info.rsa);
-    BIO_get_mem_ptr(bio, &buff);
-
-    reds_mig_write_all(fd, buff->data, SPICE_TICKET_PUBKEY_BYTES, "publick key");
-    reds_mig_read_all(fd, ticketing_info.encrypted_ticket.encrypted_data, ticketing_info.rsa_size,
-                      "ticket");
-
-    RSA_private_decrypt(ticketing_info.rsa_size, ticketing_info.encrypted_ticket.encrypted_data,
-                        (unsigned char *)password, ticketing_info.rsa, RSA_PKCS1_OAEP_PADDING);
-
-    BN_free(ticketing_info.bn);
-    BIO_free(bio);
-    RSA_free(ticketing_info.rsa);
-
-    memcpy(reds->taTicket.password, password, sizeof(reds->taTicket.password));
-    reds_mig_read_all(fd, &mig_message, sizeof(mig_message), "mig data");
-    reds->link_id = mig_message.link_id;
-    reds_mig_write_all(fd, &ack_message, sizeof(uint32_t), "ack");
-    mig->notifier_done(mig, reds->mig_notifier);
-}
-
 static void migrate_timout(void *opaque)
 {
     red_printf("");
@@ -4100,9 +3475,10 @@ __visible__ int spice_server_add_interface(SpiceServer *s,
             return -1;
         }
         mig = (MigrationInterface *)interface;
-        reds->mig_notifier = mig->register_notifiers(mig, MIGRATION_NOTIFY_SPICE_KEY,
-                                                     reds_mig_started, reds_mig_finished,
-                                                     reds_mig_recv, NULL);
+        reds->mig_notifier = mig->register_notifiers(mig,
+                                                     reds_mig_started,
+                                                     reds_mig_finished,
+                                                     NULL);
         if (reds->mig_notifier == INVALID_VD_OBJECT_REF) {
             red_error("migration register failed");
         }
diff --git a/server/vd_interface.h b/server/vd_interface.h
index d3cf5cb..7c7c202 100644
--- a/server/vd_interface.h
+++ b/server/vd_interface.h
@@ -268,21 +268,18 @@ struct SpiceTabletInstance {
 #define VD_INTERFACE_MIGRATION_MAJOR 1
 #define VD_INTERFACE_MIGRATION_MINOR 1
 typedef struct MigrationInterface MigrationInterface;
-typedef void (*migration_notify_started_t)(void *opaque, const char *args);
+typedef void (*migration_notify_started_t)(void *opaque);
 typedef void (*migration_notify_finished_t)(void *opaque, int completed);
-typedef void (*migration_notify_recv_t)(void *opaque, int fd);
 
 struct MigrationInterface {
     SpiceBaseInterface base;
 
-    VDObjectRef (*register_notifiers)(MigrationInterface* mig, const char *key,
+    VDObjectRef (*register_notifiers)(MigrationInterface* mig,
                                       migration_notify_started_t,
                                       migration_notify_finished_t,
-                                      migration_notify_recv_t,
                                       void *opaque);
     void (*unregister_notifiers)(MigrationInterface* mig, VDObjectRef notifier);
     void (*notifier_done)(MigrationInterface *mig, VDObjectRef notifier);
-    int (*begin_hook)(MigrationInterface *mig, VDObjectRef notifier);
 };
 
 enum VDIArgType{
commit 20da2f162af24f2dbbe0709fa986bcce8b26586c
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue May 11 15:23:29 2010 +0200

    replace worker load/save with loadvm_commands, allow keeping surface content
    
    Add worker->loadvm_commands.  qemu will uses this to send a series of
    commands needed to restore state after savevm/loadvm and migration.
    That will be one create-surface command per surface and one cursor-set
    command for the local pointer.
    
    The worker->save/load functions are not needed any more.
    Likewise the interface->{get,set}_save_data callbacks.
    
    Surfaces created via loadvm_commands *will* not be cleared.  Also
    primary surfaces are not cleared any more (unconditionally, although
    we could do that conditionally on loadvm using the flags field in
    QXLSurfaceCreate).

diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
index 3d1d6f9..2d23cbe 100644
--- a/server/red_dispatcher.c
+++ b/server/red_dispatcher.c
@@ -345,40 +345,34 @@ static void qxl_worker_oom(QXLWorker *qxl_worker)
     }
 }
 
-static void qxl_worker_save(QXLWorker *qxl_worker)
+static void qxl_worker_start(QXLWorker *qxl_worker)
 {
     RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker;
-    RedWorkeMessage message = RED_WORKER_MESSAGE_SAVE;
+    RedWorkeMessage message = RED_WORKER_MESSAGE_START;
 
     write_message(dispatcher->channel, &message);
-    read_message(dispatcher->channel, &message);
-    ASSERT(message == RED_WORKER_MESSAGE_READY);
 }
 
-static void qxl_worker_load(QXLWorker *qxl_worker)
+static void qxl_worker_stop(QXLWorker *qxl_worker)
 {
     RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker;
-    RedWorkeMessage message = RED_WORKER_MESSAGE_LOAD;
+    RedWorkeMessage message = RED_WORKER_MESSAGE_STOP;
 
     write_message(dispatcher->channel, &message);
     read_message(dispatcher->channel, &message);
     ASSERT(message == RED_WORKER_MESSAGE_READY);
 }
 
-static void qxl_worker_start(QXLWorker *qxl_worker)
+void qxl_worker_loadvm_commands(QXLWorker *qxl_worker,
+                                struct QXLCommandExt *ext, uint32_t count)
 {
     RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker;
-    RedWorkeMessage message = RED_WORKER_MESSAGE_START;
-
-    write_message(dispatcher->channel, &message);
-}
-
-static void qxl_worker_stop(QXLWorker *qxl_worker)
-{
-    RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker;
-    RedWorkeMessage message = RED_WORKER_MESSAGE_STOP;
+    RedWorkeMessage message = RED_WORKER_MESSAGE_LOADVM_COMMANDS;
 
+    red_printf("");
     write_message(dispatcher->channel, &message);
+    send_data(dispatcher->channel, &count, sizeof(uint32_t));
+    send_data(dispatcher->channel, ext, sizeof(QXLCommandExt) * count);
     read_message(dispatcher->channel, &message);
     ASSERT(message == RED_WORKER_MESSAGE_READY);
 }
@@ -506,8 +500,6 @@ RedDispatcher *red_dispatcher_init(QXLInstance *qxl)
     dispatcher->base.minor_version = SPICE_INTERFACE_QXL_MINOR;
     dispatcher->base.wakeup = qxl_worker_wakeup;
     dispatcher->base.oom = qxl_worker_oom;
-    dispatcher->base.save = qxl_worker_save;
-    dispatcher->base.load = qxl_worker_load;
     dispatcher->base.start = qxl_worker_start;
     dispatcher->base.stop = qxl_worker_stop;
     dispatcher->base.update_area = qxl_worker_update_area;
@@ -521,6 +513,7 @@ RedDispatcher *red_dispatcher_init(QXLInstance *qxl)
     dispatcher->base.reset_image_cache = qxl_worker_reset_image_cache;
     dispatcher->base.reset_cursor = qxl_worker_reset_cursor;
     dispatcher->base.destroy_surface_wait = qxl_worker_destroy_surface_wait;
+    dispatcher->base.loadvm_commands = qxl_worker_loadvm_commands;
 
     qxl->st->qif->get_init_info(qxl, &init_info);
 
diff --git a/server/red_worker.c b/server/red_worker.c
index 680bca1..6dbbc22 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -3878,9 +3878,9 @@ static inline void red_process_drawable(RedWorker *worker, QXLDrawable *drawable
 
 static inline void red_create_surface(RedWorker *worker, uint32_t surface_id,uint32_t width,
                                       uint32_t height, int32_t stride, uint32_t format,
-                                      void *line_0);
+                                      void *line_0, int data_is_valid);
 
-static inline void red_process_surface(RedWorker *worker, QXLSurfaceCmd *surface, uint32_t group_id)
+static inline void red_process_surface(RedWorker *worker, QXLSurfaceCmd *surface, uint32_t group_id, int data_is_valid)
 {
     int surface_id;
     RedSurface *red_surface;
@@ -3902,7 +3902,8 @@ static inline void red_process_surface(RedWorker *worker, QXLSurfaceCmd *surface
             data -= (int32_t)(stride * (height - 1));
         }
         red_create_surface(worker, surface_id, surface->u.surface_create.width,
-                           height, stride, surface->u.surface_create.format, data);
+                           height, stride, surface->u.surface_create.format, data,
+                           data_is_valid);
         set_surface_release_info(worker, surface_id, 1, &surface->release_info, group_id);
         break;
     }
@@ -4923,7 +4924,7 @@ static int red_process_commands(RedWorker *worker, uint32_t max_pipe_size)
         case QXL_CMD_SURFACE: {
             QXLSurfaceCmd *surface = (QXLSurfaceCmd *)get_virt(&worker->mem_slots, ext_cmd.cmd.data,
                                                                sizeof(QXLSurfaceCmd), ext_cmd.group_id);
-            red_process_surface(worker, surface, ext_cmd.group_id);
+            red_process_surface(worker, surface, ext_cmd.group_id, 0);
             break;
         }
         default:
@@ -8041,7 +8042,7 @@ static inline void red_create_surface_item(RedWorker *worker, int surface_id)
 
 static inline void red_create_surface(RedWorker *worker, uint32_t surface_id, uint32_t width,
                                       uint32_t height, int32_t stride, uint32_t format,
-                                      void *line_0)
+                                      void *line_0, int data_is_valid)
 {
     uint32_t i;
     RedSurface *surface = &worker->surfaces[surface_id];
@@ -8056,7 +8057,9 @@ static inline void red_create_surface(RedWorker *worker, uint32_t surface_id, ui
     surface->context.format = format;
     surface->context.stride = stride;
     surface->context.line_0 = line_0;
-    memset(line_0 + (int32_t)(stride * (height - 1)), 0, height*abs(stride));
+    if (!data_is_valid) {
+        memset(line_0 + (int32_t)(stride * (height - 1)), 0, height*abs(stride));
+    }
     surface->create.info = NULL;
     surface->destroy.info = NULL;
     ring_init(&surface->current);
@@ -8850,29 +8853,6 @@ typedef struct __attribute__ ((__packed__)) CursorData {
     SpiceCursor _cursor;
 } CursorData;
 
-static void red_save_cursor(RedWorker *worker)
-{
-    CursorData *cursor_data;
-    LocalCursor *local;
-    int size;
-
-    ASSERT(worker->cursor);
-    ASSERT(worker->cursor->type == CURSOR_TYPE_LOCAL);
-
-    local = (LocalCursor *)worker->cursor;
-    size = sizeof(CursorData) + sizeof(SpiceCursor) + local->data_size;
-    cursor_data = spice_malloc(size);
-
-    cursor_data->position = worker->cursor_position;
-    cursor_data->visible = worker->cursor_visible;
-    cursor_data->trail_frequency = worker->cursor_trail_frequency;
-    cursor_data->trail_length = worker->cursor_trail_length;
-    cursor_data->data_size = local->data_size;
-    cursor_data->_cursor.header = local->red_cursor.header;
-    memcpy(cursor_data->_cursor.data, local->red_cursor.data, local->data_size);
-    worker->qxl->st->qif->set_save_data(worker->qxl, cursor_data, size);
-}
-
 static LocalCursor *_new_local_cursor(SpiceCursorHeader *header, int data_size, SpicePoint16 position)
 {
     LocalCursor *local;
@@ -8932,37 +8912,6 @@ static void red_cursor_flush(RedWorker *worker)
     red_release_cursor(worker, &local->base);
 }
 
-static void red_save(RedWorker *worker)
-{
-    if (!worker->cursor) {
-        worker->qxl->st->qif->set_save_data(worker->qxl, NULL, 0);
-        return;
-    }
-    red_save_cursor(worker);
-}
-
-static void red_cursor_load(RedWorker *worker)
-{
-    CursorData *cursor_data = worker->qxl->st->qif->get_save_data(worker->qxl);
-    LocalCursor *local;
-
-    if (!cursor_data) {
-        return;
-    }
-
-    worker->cursor_position = cursor_data->position;
-    worker->cursor_visible = cursor_data->visible;
-    worker->cursor_trail_frequency = cursor_data->trail_frequency;
-    worker->cursor_trail_length = cursor_data->trail_length;
-
-    local = _new_local_cursor(&cursor_data->_cursor.header, cursor_data->data_size,
-                              cursor_data->position);
-    ASSERT(local);
-    memcpy(local->red_cursor.data, cursor_data->_cursor.data, cursor_data->data_size);
-    red_set_cursor(worker, &local->base);
-    red_release_cursor(worker, &local->base);
-}
-
 static void red_wait_outgoiong_item(RedChannel *channel)
 {
     uint64_t end_time;
@@ -9155,7 +9104,7 @@ static inline void handle_dev_create_primary_surface(RedWorker *worker)
     }
 
     red_create_surface(worker, 0, surface.width, surface.height, surface.stride, surface.format,
-                       line_0);
+                       line_0, surface.flags & QXL_SURF_FLAG_KEEP_DATA);
 
     if (worker->display_channel) {
         red_pipe_add_verb(&worker->display_channel->base, SPICE_MSG_DISPLAY_MARK);
@@ -9289,22 +9238,7 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
         red_printf("disconnect");
         red_disconnect_display((RedChannel *)worker->display_channel);
         break;
-    case RED_WORKER_MESSAGE_SAVE:
-        red_printf("save");
-        ASSERT(!worker->running);
-        red_save(worker);
-        message = RED_WORKER_MESSAGE_READY;
-        write_message(worker->channel, &message);
-        break;
-    case RED_WORKER_MESSAGE_LOAD:
-        red_printf("load");
-        ASSERT(!worker->running);
-        red_add_surface_image(worker, 0);
-        red_cursor_load(worker);
-        message = RED_WORKER_MESSAGE_READY;
-        write_message(worker->channel, &message);
-        break;
-        case RED_WORKER_MESSAGE_STOP: {
+    case RED_WORKER_MESSAGE_STOP: {
         int x;
 
         red_printf("stop");
@@ -9420,6 +9354,41 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
     case RED_WORKER_MESSAGE_RESET_MEMSLOTS:
         red_memslot_info_reset(&worker->mem_slots);
         break;
+    case RED_WORKER_MESSAGE_LOADVM_COMMANDS: {
+        uint32_t count;
+        QXLCommandExt ext;
+        QXLCursorCmd *cursor_cmd;
+        QXLSurfaceCmd *surface_cmd;
+
+        red_printf("loadvm_commands");
+        receive_data(worker->channel, &count, sizeof(uint32_t));
+        while (count > 0) {
+            receive_data(worker->channel, &ext, sizeof(QXLCommandExt));
+            switch (ext.cmd.type) {
+            case QXL_CMD_CURSOR:
+                cursor_cmd = (QXLCursorCmd *)get_virt(&worker->mem_slots,
+                                                      ext.cmd.data,
+                                                      sizeof(QXLCursorCmd),
+                                                      ext.group_id);
+                qxl_process_cursor(worker, cursor_cmd, ext.group_id);
+                break;
+            case QXL_CMD_SURFACE:
+                surface_cmd = (QXLSurfaceCmd *)get_virt(&worker->mem_slots,
+                                                        ext.cmd.data,
+                                                        sizeof(QXLSurfaceCmd),
+                                                        ext.group_id);
+                red_process_surface(worker, surface_cmd, ext.group_id, 1);
+                break;
+            default:
+                red_printf("unhandled loadvm command type (%d)", ext.cmd.type);
+                break;
+            }
+            count--;
+        }
+        message = RED_WORKER_MESSAGE_READY;
+        write_message(worker->channel, &message);
+        break;
+    }
     default:
         red_error("message error");
     }
diff --git a/server/red_worker.h b/server/red_worker.h
index e53d518..88c1e90 100644
--- a/server/red_worker.h
+++ b/server/red_worker.h
@@ -50,8 +50,6 @@ enum {
     RED_WORKER_MESSAGE_DISPLAY_CONNECT,
     RED_WORKER_MESSAGE_DISPLAY_DISCONNECT,
     RED_WORKER_MESSAGE_DISPLAY_MIGRATE,
-    RED_WORKER_MESSAGE_SAVE,
-    RED_WORKER_MESSAGE_LOAD,
     RED_WORKER_MESSAGE_START,
     RED_WORKER_MESSAGE_STOP,
     RED_WORKER_MESSAGE_CURSOR_CONNECT,
@@ -69,6 +67,7 @@ enum {
     RED_WORKER_MESSAGE_RESET_CURSOR,
     RED_WORKER_MESSAGE_RESET_IMAGE_CACHE,
     RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT,
+    RED_WORKER_MESSAGE_LOADVM_COMMANDS,
 };
 
 typedef uint32_t RedWorkeMessage;
diff --git a/server/vd_interface.h b/server/vd_interface.h
index 0f26822..d3cf5cb 100644
--- a/server/vd_interface.h
+++ b/server/vd_interface.h
@@ -103,8 +103,6 @@ struct QXLWorker {
     uint32_t major_version;
     void (*wakeup)(QXLWorker *worker);
     void (*oom)(QXLWorker *worker);
-    void (*save)(QXLWorker *worker);
-    void (*load)(QXLWorker *worker);
     void (*start)(QXLWorker *worker);
     void (*stop)(QXLWorker *worker);
     void (*update_area)(QXLWorker *qxl_worker, uint32_t surface_id,
@@ -120,6 +118,7 @@ struct QXLWorker {
     void (*reset_image_cache)(QXLWorker *worker);
     void (*reset_cursor)(QXLWorker *worker);
     void (*destroy_surface_wait)(QXLWorker *worker, uint32_t surface_id);
+    void (*loadvm_commands)(QXLWorker *worker, struct QXLCommandExt *ext, uint32_t count);
 };
 
 typedef struct DrawArea {
@@ -196,8 +195,6 @@ struct QXLInterface {
     int (*get_cursor_command)(QXLInstance *qin, struct QXLCommandExt *cmd);
     int (*req_cursor_notification)(QXLInstance *qin);
     void (*notify_update)(QXLInstance *qin, uint32_t update_id);
-    void (*set_save_data)(QXLInstance *qin, void *data, int size);
-    void *(*get_save_data)(QXLInstance *qin);
     int (*flush_resources)(QXLInstance *qin);
 };
 
commit 6bdf38daf8796a596fe992bd79b79dd312870b89
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri May 7 14:03:36 2010 +0200

    surface: keep metadata (aka create command) in device memory.
    
    With this patch applied the spice server will not release surface create
    commands for the whole lifecycle of the surface.  When the surface is
    destroyed both create and destroy commands are released.
    
    This has the effect that the surface metadata (size, depth, ...) is kept
    in qxl device memory.  This in turn makes it alot easier for qemu to
    handle savevm/loadvm.  It just needs to do some minimal command parsing
    and maintain pointers to the create commands for the active surfaces.

diff --git a/server/red_worker.c b/server/red_worker.c
index b66d098..680bca1 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -893,8 +893,7 @@ typedef struct RedSurface {
     QRegion draw_dirty_region;
 
     //fix me - better handling here
-    QXLReleaseInfo *release_info;
-    uint32_t release_group_id;
+    QXLReleaseInfoExt create, destroy;
 } RedSurface;
 
 #ifdef STREAM_TRACE
@@ -1503,12 +1502,11 @@ static inline void red_destroy_surface(RedWorker *worker, uint32_t surface_id)
 #endif
         if (surface->context.canvas) {
             surface->context.canvas->ops->destroy(surface->context.canvas);
-            if (surface->release_info) {
-                QXLReleaseInfoExt release_info_ext;
-
-                release_info_ext.group_id = surface->release_group_id;
-                release_info_ext.info = surface->release_info;
-                worker->qxl->st->qif->release_resource(worker->qxl, release_info_ext);
+            if (surface->create.info) {
+                worker->qxl->st->qif->release_resource(worker->qxl, surface->create);
+            }
+            if (surface->destroy.info) {
+                worker->qxl->st->qif->release_resource(worker->qxl, surface->destroy);
             }
 
             region_destroy(&surface->draw_dirty_region);
@@ -1520,15 +1518,20 @@ static inline void red_destroy_surface(RedWorker *worker, uint32_t surface_id)
     }
 }
 
-static inline void set_surface_release_info(RedWorker *worker, uint32_t surface_id,
+static inline void set_surface_release_info(RedWorker *worker, uint32_t surface_id, int is_create, 
                                             QXLReleaseInfo *release_info, uint32_t group_id)
 {
     RedSurface *surface;
 
     surface = &worker->surfaces[surface_id];
 
-    surface->release_info = release_info;
-    surface->release_group_id = group_id;
+    if (is_create) {
+        surface->create.info = release_info;
+        surface->create.group_id = group_id;
+    } else {
+        surface->destroy.info = release_info;
+        surface->destroy.group_id = group_id;
+    }
 }
 
 static inline void free_qxl_drawable(RedWorker *worker, QXLDrawable *drawable, uint32_t group_id,
@@ -3893,7 +3896,6 @@ static inline void red_process_surface(RedWorker *worker, QXLSurfaceCmd *surface
         unsigned long saved_data = (unsigned long)surface->u.surface_create.data;
         uint32_t height = surface->u.surface_create.height;
         int32_t stride = surface->u.surface_create.stride;
-        QXLReleaseInfoExt release_info_ext;
 
         data = (uint8_t *)get_virt(&worker->mem_slots, saved_data, height * abs(stride), group_id);
         if (stride < 0) {
@@ -3901,14 +3903,12 @@ static inline void red_process_surface(RedWorker *worker, QXLSurfaceCmd *surface
         }
         red_create_surface(worker, surface_id, surface->u.surface_create.width,
                            height, stride, surface->u.surface_create.format, data);
-        release_info_ext.group_id = group_id;
-        release_info_ext.info = &surface->release_info;
-        worker->qxl->st->qif->release_resource(worker->qxl, release_info_ext);
+        set_surface_release_info(worker, surface_id, 1, &surface->release_info, group_id);
         break;
     }
     case QXL_SURFACE_CMD_DESTROY:
         PANIC_ON(!red_surface->context.canvas);
-        set_surface_release_info(worker, surface_id, &surface->release_info, group_id);
+        set_surface_release_info(worker, surface_id, 0, &surface->release_info, group_id);
         red_handle_depends_on_target_surface(worker, surface_id);
         red_current_clear(worker, surface_id);
         red_clear_surface_glz_drawables(worker, surface_id);
@@ -8057,7 +8057,8 @@ static inline void red_create_surface(RedWorker *worker, uint32_t surface_id, ui
     surface->context.stride = stride;
     surface->context.line_0 = line_0;
     memset(line_0 + (int32_t)(stride * (height - 1)), 0, height*abs(stride));
-    surface->release_info = NULL;
+    surface->create.info = NULL;
+    surface->destroy.info = NULL;
     ring_init(&surface->current);
     ring_init(&surface->current_list);
     ring_init(&surface->depend_on_me);
commit 3cffcf98a1d8ef35c86b6fb0b381856e52677171
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon May 3 14:03:43 2010 +0200

    kill spice_server_set_mouse_absolute
    
    Not needed.  Just register/unregister the tablet interface instead.

diff --git a/server/reds.c b/server/reds.c
index 01f610d..9b42cbf 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -4552,15 +4552,6 @@ __visible__ int spice_server_set_channel_security(SpiceServer *s, const char *ch
     return -1;
 }
 
-__visible__ int spice_server_set_mouse_absolute(SpiceServer *s, int absolute)
-{
-    uint32_t mode = absolute ? SPICE_MOUSE_MODE_CLIENT : SPICE_MOUSE_MODE_SERVER;
-
-    ASSERT(reds == s);
-    reds_set_mouse_mode(mode);
-    return 0;
-}
-
 __visible__ int spice_server_get_sock_info(SpiceServer *s, struct sockaddr *sa, socklen_t *salen)
 {
     ASSERT(reds == s);
diff --git a/server/spice.h b/server/spice.h
index f1bc80d..80291b9 100644
--- a/server/spice.h
+++ b/server/spice.h
@@ -64,8 +64,6 @@ spice_image_compression_t spice_server_get_image_compression(SpiceServer *s);
 
 int spice_server_set_channel_security(SpiceServer *s, const char *channel, int security);
 
-int spice_server_set_mouse_absolute(SpiceServer *s, int absolute);
-
 int spice_server_add_renderer(SpiceServer *s, const char *name);
 
 int spice_server_get_sock_info(SpiceServer *s, struct sockaddr *sa, socklen_t *salen);
commit ccfbbae513adb4aeaea1c9e09be7e0a23d8aeded
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Apr 19 21:39:14 2010 +0200

    vdi port: redesign.
    
    Pretty straight forward.
    
    One thing we should think about is if and how we are going to deal
    with multiple ports here?
    
    With vdi port using virtio-serial as communication channel to the guest
    it is easy to have multiple ports, i.e. we might want to use a second
    instance for clipboard data.  That implies that we need support for
    multiple channels all the way through the stack ...

diff --git a/server/reds.c b/server/reds.c
index 71ce409..01f610d 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -59,7 +59,7 @@ static MigrationInterface *mig = NULL;
 static SpiceKbdInstance *keyboard = NULL;
 static SpiceMouseInstance *mouse = NULL;
 static SpiceTabletInstance *tablet = NULL;
-static VDIPortInterface *vdagent = NULL;
+static SpiceVDIPortInstance *vdagent = NULL;
 
 #define MIGRATION_NOTIFY_SPICE_KEY "spice_mig_ext"
 
@@ -176,8 +176,7 @@ typedef struct __attribute__ ((__packed__)) VDIChunkHeader {
 } VDIChunkHeader;
 
 typedef struct VDIPortState {
-    VDIPortPlug plug;
-    VDObjectRef plug_ref;
+    int connected;
     uint32_t plug_generation;
 
     uint32_t num_tokens;
@@ -743,10 +742,13 @@ static void reds_disconnect()
     reds->disconnecting = TRUE;
     reds_reset_outgoing();
 
-    if (reds->agent_state.plug_ref != INVALID_VD_OBJECT_REF) {
-        ASSERT(vdagent);
-        vdagent->unplug(vdagent, reds->agent_state.plug_ref);
-        reds->agent_state.plug_ref = INVALID_VD_OBJECT_REF;
+    if (reds->agent_state.connected) {
+        SpiceVDIPortInterface *sif;
+        sif = SPICE_CONTAINEROF(vdagent->base.sif, SpiceVDIPortInterface, base);
+        reds->agent_state.connected = 0;
+        if (sif->state) {
+            sif->state(vdagent, reds->agent_state.connected);
+        }
         reds_reset_vdp();
     }
 
@@ -1122,18 +1124,22 @@ static void reds_send_agent_disconnected()
 
 static void reds_agent_remove()
 {
-    VDIPortInterface *interface = vdagent;
+    SpiceVDIPortInstance *sin = vdagent;
+    SpiceVDIPortInterface *sif;
 
     vdagent = NULL;
     reds_update_mouse_mode();
 
-    if (!reds->peer || !interface) {
+    if (!reds->peer || !sin) {
         return;
     }
 
-    ASSERT(reds->agent_state.plug_ref != INVALID_VD_OBJECT_REF);
-    interface->unplug(interface, reds->agent_state.plug_ref);
-    reds->agent_state.plug_ref = INVALID_VD_OBJECT_REF;
+    ASSERT(reds->agent_state.connected)
+    sif = SPICE_CONTAINEROF(sin->base.sif, SpiceVDIPortInterface, base);
+    reds->agent_state.connected = 0;
+    if (sif->state) {
+        sif->state(sin, reds->agent_state.connected);
+    }
 
     if (reds->mig_target) {
         return;
@@ -1164,21 +1170,23 @@ static void reds_send_tokens()
 static int write_to_vdi_port()
 {
     VDIPortState *state = &reds->agent_state;
+    SpiceVDIPortInterface *sif;
     RingItem *ring_item;
     VDIPortBuf *buf;
     int total = 0;
     int n;
 
-    if (reds->agent_state.plug_ref == INVALID_VD_OBJECT_REF || reds->mig_target) {
+    if (!reds->agent_state.connected || reds->mig_target) {
         return 0;
     }
 
-    for (;;) {
+    sif = SPICE_CONTAINEROF(vdagent->base.sif, SpiceVDIPortInterface, base);
+    while (reds->agent_state.connected) {
         if (!(ring_item = ring_get_tail(&state->write_queue))) {
             break;
         }
         buf = (VDIPortBuf *)ring_item;
-        n = vdagent->write(vdagent, state->plug_ref, buf->now, buf->write_len);
+        n = sif->write(vdagent, buf->now, buf->write_len);
         if (n == 0) {
             break;
         }
@@ -1217,18 +1225,20 @@ static void dispatch_vdi_port_data(int port, VDIReadBuf *buf)
 static int read_from_vdi_port()
 {
     VDIPortState *state = &reds->agent_state;
+    SpiceVDIPortInterface *sif;
     VDIReadBuf *dispatch_buf;
     int total = 0;
     int n;
 
-    if (reds->mig_target) {
+    if (!reds->agent_state.connected || reds->mig_target) {
         return 0;
     }
 
-    while (reds->agent_state.plug_ref != INVALID_VD_OBJECT_REF) {
+    sif = SPICE_CONTAINEROF(vdagent->base.sif, SpiceVDIPortInterface, base);
+    while (reds->agent_state.connected) {
         switch (state->read_state) {
         case VDI_PORT_READ_STATE_READ_HADER:
-            n = vdagent->read(vdagent, state->plug_ref, state->recive_pos, state->recive_len);
+            n = sif->read(vdagent, state->recive_pos, state->recive_len);
             if (!n) {
                 return total;
             }
@@ -1262,7 +1272,7 @@ static int read_from_vdi_port()
             state->read_state = VDI_PORT_READ_STATE_READ_DATA;
         }
         case VDI_PORT_READ_STATE_READ_DATA:
-            n = vdagent->read(vdagent, state->plug_ref, state->recive_pos, state->recive_len);
+            n = sif->read(vdagent, state->recive_pos, state->recive_len);
             if (!n) {
                 return total;
             }
@@ -1287,7 +1297,7 @@ static int read_from_vdi_port()
     return total;
 }
 
-static void reds_agent_wakeup(VDIPortPlug *plug)
+__visible__ void spice_server_vdi_port_wakeup(SpiceVDIPortInstance *sin)
 {
     while (write_to_vdi_port() || read_from_vdi_port());
 }
@@ -1385,7 +1395,7 @@ static void main_channel_send_migrate_data_item(RedsOutItem *in_item, struct iov
     item->data.serial = reds->serial;
     item->data.ping_id = reds->ping_id;
 
-    item->data.agent_connected = !!state->plug_ref;
+    item->data.agent_connected = !!state->connected;
     item->data.client_agent_started = state->client_agent_started;
     item->data.num_client_tokens = state->num_client_tokens;
     item->data.send_tokens = state->send_tokens;
@@ -1634,13 +1644,13 @@ static void main_channel_recive_migrate_data(MainMigrateData *data, uint8_t *end
 
 
     if (!data->agent_connected) {
-        if (state->plug_ref) {
+        if (state->connected) {
             reds_send_agent_connected();
         }
         return;
     }
 
-    if (state->plug_ref == INVALID_VD_OBJECT_REF) {
+    if (!state->connected) {
         reds_send_agent_disconnected();
         return;
     }
@@ -2054,9 +2064,11 @@ static void reds_handle_main_link(RedLinkInfo *link)
     reds_show_new_channel(link);
     __reds_release_link(link);
     if (vdagent) {
-        reds->agent_state.plug_ref = vdagent->plug(vdagent, &reds->agent_state.plug);
-        if (reds->agent_state.plug_ref == INVALID_VD_OBJECT_REF) {
-            PANIC("vdagent plug failed");
+        SpiceVDIPortInterface *sif;
+        sif = SPICE_CONTAINEROF(vdagent->base.sif, SpiceVDIPortInterface, base);
+        reds->agent_state.connected = 1;
+        if (sif->state) {
+            sif->state(vdagent, reds->agent_state.connected);
         }
         reds->agent_state.plug_generation++;
     }
@@ -4017,16 +4029,21 @@ static void mm_timer_proc(void *opaque)
     core->timer_start(reds->mm_timer, MM_TIMER_GRANULARITY_MS);
 }
 
-static void attach_to_red_agent(VDIPortInterface *interface)
+static void attach_to_red_agent(SpiceVDIPortInstance *sin)
 {
     VDIPortState *state = &reds->agent_state;
+    SpiceVDIPortInterface *sif;
 
-    vdagent = interface;
+    vdagent = sin;
     reds_update_mouse_mode();
     if (!reds->peer) {
         return;
     }
-    state->plug_ref = vdagent->plug(vdagent, &state->plug);
+    sif = SPICE_CONTAINEROF(vdagent->base.sif, SpiceVDIPortInterface, base);
+    state->connected = 1;
+    if (sif->state) {
+        sif->state(vdagent, state->connected);
+    }
     reds->agent_state.plug_generation++;
 
     if (reds->mig_target) {
@@ -4144,18 +4161,18 @@ __visible__ int spice_server_add_interface(SpiceServer *s,
         }
         snd_attach_record(SPICE_CONTAINEROF(sin, SpiceRecordInstance, base));
 
-    } else if (strcmp(interface->type, VD_INTERFACE_VDI_PORT) == 0) {
-        red_printf("VD_INTERFACE_VDI_PORT");
+    } else if (strcmp(interface->type, SPICE_INTERFACE_VDI_PORT) == 0) {
+        red_printf("SPICE_INTERFACE_VDI_PORT");
         if (vdagent) {
             red_printf("vdi port already attached");
             return -1;
         }
-        if (interface->major_version != VD_INTERFACE_VDI_PORT_MAJOR ||
-            interface->minor_version < VD_INTERFACE_VDI_PORT_MINOR) {
+        if (interface->major_version != SPICE_INTERFACE_VDI_PORT_MAJOR ||
+            interface->minor_version < SPICE_INTERFACE_VDI_PORT_MINOR) {
             red_printf("unsuported vdi port interface");
             return -1;
         }
-        attach_to_red_agent((VDIPortInterface *)interface);
+        attach_to_red_agent(SPICE_CONTAINEROF(sin, SpiceVDIPortInstance, base));
 
     } else if (strcmp(interface->type, VD_INTERFACE_NET_WIRE) == 0) {
 #ifdef HAVE_SLIRP
@@ -4199,9 +4216,9 @@ __visible__ int spice_server_remove_interface(SpiceBaseInstance *sin)
         red_printf("remove SPICE_INTERFACE_RECORD");
         snd_detach_record(SPICE_CONTAINEROF(sin, SpiceRecordInstance, base));
 
-    } else if (strcmp(interface->type, VD_INTERFACE_VDI_PORT) == 0) {
-        red_printf("remove VD_INTERFACE_VDI_PORT");
-        if (interface == (SpiceBaseInterface *)vdagent) {
+    } else if (strcmp(interface->type, SPICE_INTERFACE_VDI_PORT) == 0) {
+        red_printf("remove SPICE_INTERFACE_VDI_PORT");
+        if (sin == &vdagent->base) {
             reds_agent_remove();
         }
 
@@ -4294,10 +4311,6 @@ static void init_vd_agent_resources()
         ring_item_init(&buf->out_item.link);
         ring_add(&reds->agent_state.read_bufs, &buf->out_item.link);
     }
-
-    state->plug.major_version = VD_INTERFACE_VDI_PORT_MAJOR;
-    state->plug.minor_version = VD_INTERFACE_VDI_PORT_MINOR;
-    state->plug.wakeup = reds_agent_wakeup;
 }
 
 const char *version_string = VERSION;
diff --git a/server/vd_interface.h b/server/vd_interface.h
index 78f0f62..0f26822 100644
--- a/server/vd_interface.h
+++ b/server/vd_interface.h
@@ -367,27 +367,28 @@ void spice_server_record_stop(SpiceRecordInstance *sin);
 uint32_t spice_server_record_get_samples(SpiceRecordInstance *sin,
                                          uint32_t *samples, uint32_t bufsize);
 
-#define VD_INTERFACE_VDI_PORT "vdi_port"
-#define VD_INTERFACE_VDI_PORT_MAJOR 1
-#define VD_INTERFACE_VDI_PORT_MINOR 1
-typedef struct VDIPortInterface VDIPortInterface;
+#define SPICE_INTERFACE_VDI_PORT "vdi_port"
+#define SPICE_INTERFACE_VDI_PORT_MAJOR 1
+#define SPICE_INTERFACE_VDI_PORT_MINOR 1
+typedef struct SpiceVDIPortInterface SpiceVDIPortInterface;
+typedef struct SpiceVDIPortInstance SpiceVDIPortInstance;
+typedef struct SpiceVDIPortState SpiceVDIPortState;
+
+struct SpiceVDIPortInterface {
+    SpiceBaseInterface base;
 
-typedef struct VDIPortPlug VDIPortPlug;
-struct VDIPortPlug {
-    uint32_t minor_version;
-    uint32_t major_version;
-    void (*wakeup)(VDIPortPlug *plug);
+    void (*state)(SpiceVDIPortInstance *sin, int connected);
+    int (*write)(SpiceVDIPortInstance *sin, const uint8_t *buf, int len);
+    int (*read)(SpiceVDIPortInstance *sin, uint8_t *buf, int len);
 };
 
-struct VDIPortInterface {
-    SpiceBaseInterface base;
-
-    VDObjectRef (*plug)(VDIPortInterface *port, VDIPortPlug* plug);
-    void (*unplug)(VDIPortInterface *port, VDObjectRef plug);
-    int (*write)(VDIPortInterface *port, VDObjectRef plug, const uint8_t *buf, int len);
-    int (*read)(VDIPortInterface *port, VDObjectRef plug, uint8_t *buf, int len);
+struct SpiceVDIPortInstance {
+    SpiceBaseInstance base;
+    SpiceVDIPortState *st;
 };
 
+void spice_server_vdi_port_wakeup(SpiceVDIPortInstance *sin);
+
 #define VD_INTERFACE_NET_WIRE "net_wire"
 #define VD_INTERFACE_NET_WIRE_MAJOR 1
 #define VD_INTERFACE_NET_WIRE_MINOR 1
commit 2e47435ecbe3d163fa9607deaa972ea4aecdbbf4
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Apr 16 12:25:12 2010 +0200

    constify SpiceBaseInterface

diff --git a/server/reds.c b/server/reds.c
index a5e6c1b..71ce409 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -4039,7 +4039,7 @@ static void attach_to_red_agent(VDIPortInterface *interface)
 __visible__ int spice_server_add_interface(SpiceServer *s,
                                            SpiceBaseInstance *sin)
 {
-    SpiceBaseInterface *interface = sin->sif;
+    const SpiceBaseInterface *interface = sin->sif;
 
     ASSERT(reds == s);
 
@@ -4182,7 +4182,7 @@ __visible__ int spice_server_add_interface(SpiceServer *s,
 
 __visible__ int spice_server_remove_interface(SpiceBaseInstance *sin)
 {
-    SpiceBaseInterface *interface = sin->sif;
+    const SpiceBaseInterface *interface = sin->sif;
 
     if (strcmp(interface->type, SPICE_INTERFACE_TABLET) == 0) {
         red_printf("remove SPICE_INTERFACE_TABLET");
diff --git a/server/vd_interface.h b/server/vd_interface.h
index d3ce999..78f0f62 100644
--- a/server/vd_interface.h
+++ b/server/vd_interface.h
@@ -47,7 +47,7 @@ struct SpiceBaseInterface {
     uint32_t minor_version;
 };
 struct SpiceBaseInstance {
-    SpiceBaseInterface *sif;
+    const SpiceBaseInterface *sif;
 };
 
 #define SPICE_INTERFACE_CORE "core"
commit 6fdcb9310d8bd0383af97951ff7ba270c5ba08be
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Apr 13 14:35:32 2010 +0200

    SoundInterfaces: redesign

diff --git a/server/reds.c b/server/reds.c
index d5a28c6..a5e6c1b 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -4126,23 +4126,23 @@ __visible__ int spice_server_add_interface(SpiceServer *s,
                                   reds->monitor_mode.y_res);
         }
 
-    } else if (strcmp(interface->type, VD_INTERFACE_PLAYBACK) == 0) {
-        red_printf("VD_INTERFACE_PLAYBACK");
-        if (interface->major_version != VD_INTERFACE_PLAYBACK_MAJOR ||
-            interface->minor_version < VD_INTERFACE_PLAYBACK_MINOR) {
+    } else if (strcmp(interface->type, SPICE_INTERFACE_PLAYBACK) == 0) {
+        red_printf("SPICE_INTERFACE_PLAYBACK");
+        if (interface->major_version != SPICE_INTERFACE_PLAYBACK_MAJOR ||
+            interface->minor_version < SPICE_INTERFACE_PLAYBACK_MINOR) {
             red_printf("unsuported playback interface");
             return -1;
         }
-        snd_attach_playback((PlaybackInterface *)interface);
+        snd_attach_playback(SPICE_CONTAINEROF(sin, SpicePlaybackInstance, base));
 
-    } else if (strcmp(interface->type, VD_INTERFACE_RECORD) == 0) {
+    } else if (strcmp(interface->type, SPICE_INTERFACE_RECORD) == 0) {
         red_printf("VD_INTERFACE_RECORD");
-        if (interface->major_version != VD_INTERFACE_RECORD_MAJOR ||
-            interface->minor_version < VD_INTERFACE_RECORD_MINOR) {
+        if (interface->major_version != SPICE_INTERFACE_RECORD_MAJOR ||
+            interface->minor_version < SPICE_INTERFACE_RECORD_MINOR) {
             red_printf("unsuported record interface");
             return -1;
         }
-        snd_attach_record((RecordInterface *)interface);
+        snd_attach_record(SPICE_CONTAINEROF(sin, SpiceRecordInstance, base));
 
     } else if (strcmp(interface->type, VD_INTERFACE_VDI_PORT) == 0) {
         red_printf("VD_INTERFACE_VDI_PORT");
@@ -4191,13 +4191,13 @@ __visible__ int spice_server_remove_interface(SpiceBaseInstance *sin)
             reds_update_mouse_mode();
         }
 
-    } else if (strcmp(interface->type, VD_INTERFACE_PLAYBACK) == 0) {
-        red_printf("remove VD_INTERFACE_PLAYBACK");
-        snd_detach_playback((PlaybackInterface *)interface);
+    } else if (strcmp(interface->type, SPICE_INTERFACE_PLAYBACK) == 0) {
+        red_printf("remove SPICE_INTERFACE_PLAYBACK");
+        snd_detach_playback(SPICE_CONTAINEROF(sin, SpicePlaybackInstance, base));
 
-    } else if (strcmp(interface->type, VD_INTERFACE_RECORD) == 0) {
-        red_printf("remove VD_INTERFACE_RECORD");
-        snd_detach_record((RecordInterface *)interface);
+    } else if (strcmp(interface->type, SPICE_INTERFACE_RECORD) == 0) {
+        red_printf("remove SPICE_INTERFACE_RECORD");
+        snd_detach_record(SPICE_CONTAINEROF(sin, SpiceRecordInstance, base));
 
     } else if (strcmp(interface->type, VD_INTERFACE_VDI_PORT) == 0) {
         red_printf("remove VD_INTERFACE_VDI_PORT");
diff --git a/server/snd_worker.c b/server/snd_worker.c
index afffb00..6a08e92 100644
--- a/server/snd_worker.c
+++ b/server/snd_worker.c
@@ -37,7 +37,7 @@
 #define PLAYBACK_BUF_SIZE (FRAME_SIZE * 4)
 
 #define CELT_BIT_RATE (64 * 1024)
-#define CELT_COMPRESSED_FRAME_BYTES (FRAME_SIZE * CELT_BIT_RATE / VD_INTERFACE_PLAYBACK_FREQ / 8)
+#define CELT_COMPRESSED_FRAME_BYTES (FRAME_SIZE * CELT_BIT_RATE / SPICE_INTERFACE_PLAYBACK_FREQ / 8)
 
 #define RECORD_SAMPLES_SIZE (RECIVE_BUF_SIZE >> 2)
 
@@ -121,7 +121,6 @@ struct AudioFrame {
 typedef struct PlaybackChannel {
     SndChannel base;
     AudioFrame frames[3];
-    PlaybackPlug plug;
     VDObjectRef plug_ref;
     AudioFrame *free_frames;
     AudioFrame *in_progress;
@@ -147,6 +146,14 @@ struct SndWorker {
     SndWorker *next;
 };
 
+struct SpicePlaybackState {
+    struct SndWorker worker;
+};
+
+struct SpiceRecordState {
+    struct SndWorker worker;
+};
+
 #define RECORD_MIG_VERSION 1
 
 typedef struct __attribute__ ((__packed__)) RecordMigrateData {
@@ -165,7 +172,6 @@ typedef struct __attribute__ ((__packed__)) RecordMigrateMessage {
 
 typedef struct RecordChannel {
     SndChannel base;
-    RecordPlug plug;
     VDObjectRef plug_ref;
     uint32_t samples[RECORD_SAMPLES_SIZE];
     uint32_t write_pos;
@@ -551,9 +557,9 @@ static int snd_playback_send_start(PlaybackChannel *playback_channel)
     }
 
     start = &playback_channel->send_data.u.start;
-    start->channels = VD_INTERFACE_PLAYBACK_CHAN;
-    start->frequency = VD_INTERFACE_PLAYBACK_FREQ;
-    ASSERT(VD_INTERFACE_PLAYBACK_FMT == VD_INTERFACE_AUDIO_FMT_S16);
+    start->channels = SPICE_INTERFACE_PLAYBACK_CHAN;
+    start->frequency = SPICE_INTERFACE_PLAYBACK_FREQ;
+    ASSERT(SPICE_INTERFACE_PLAYBACK_FMT == SPICE_INTERFACE_AUDIO_FMT_S16);
     start->format = SPICE_AUDIO_FMT_S16;
     start->time = reds_get_mm_time();
     snd_add_buf(channel, start, sizeof(*start));
@@ -592,9 +598,9 @@ static int snd_record_send_start(RecordChannel *record_channel)
     }
 
     start = &record_channel->send_data.u.start;
-    start->channels = VD_INTERFACE_RECORD_CHAN;
-    start->frequency = VD_INTERFACE_RECORD_FREQ;
-    ASSERT(VD_INTERFACE_RECORD_FMT == VD_INTERFACE_AUDIO_FMT_S16);
+    start->channels = SPICE_INTERFACE_RECORD_CHAN;
+    start->frequency = SPICE_INTERFACE_RECORD_FREQ;
+    ASSERT(SPICE_INTERFACE_RECORD_FMT == SPICE_INTERFACE_AUDIO_FMT_S16);
     start->format = SPICE_AUDIO_FMT_S16;
     snd_add_buf(channel, start, sizeof(*start));
 
@@ -846,10 +852,13 @@ static void snd_set_command(SndChannel *channel, uint32_t command)
     channel->command |= command;
 }
 
-static void snd_playback_start(PlaybackPlug *plug)
+__visible__ void spice_server_playback_start(SpicePlaybackInstance *sin)
 {
-    PlaybackChannel *playback_channel = SPICE_CONTAINEROF(plug, PlaybackChannel, plug);
+    SndChannel *channel = sin->st->worker.connection;
+    PlaybackChannel *playback_channel = SPICE_CONTAINEROF(channel, PlaybackChannel, base);
 
+    if (!channel)
+        return;
     ASSERT(!playback_channel->base.active);
     reds_desable_mm_timer();
     playback_channel->base.active = TRUE;
@@ -861,10 +870,13 @@ static void snd_playback_start(PlaybackPlug *plug)
     }
 }
 
-static void snd_playback_stop(PlaybackPlug *plug)
+__visible__ void spice_server_playback_stop(SpicePlaybackInstance *sin)
 {
-    PlaybackChannel *playback_channel = SPICE_CONTAINEROF(plug, PlaybackChannel, plug);
+    SndChannel *channel = sin->st->worker.connection;
+    PlaybackChannel *playback_channel = SPICE_CONTAINEROF(channel, PlaybackChannel, base);
 
+    if (!channel)
+        return;
     ASSERT(playback_channel->base.active);
     reds_enable_mm_timer();
     playback_channel->base.active = FALSE;
@@ -884,27 +896,32 @@ static void snd_playback_stop(PlaybackPlug *plug)
     }
 }
 
-static void snd_playback_get_frame(PlaybackPlug *plug, uint32_t **frame, uint32_t *num_samples)
+__visible__ void spice_server_playback_get_buffer(SpicePlaybackInstance *sin,
+                                                  uint32_t **frame, uint32_t *num_samples)
 {
-    PlaybackChannel *playback_channel = SPICE_CONTAINEROF(plug, PlaybackChannel, plug);
+    SndChannel *channel = sin->st->worker.connection;
+    PlaybackChannel *playback_channel = SPICE_CONTAINEROF(channel, PlaybackChannel, base);
 
-    ASSERT(playback_channel->base.active);
-    if (!playback_channel->free_frames) {
+    if (!channel || !playback_channel->free_frames) {
         *frame = NULL;
         *num_samples = 0;
         return;
     }
+    ASSERT(playback_channel->base.active);
 
     *frame = playback_channel->free_frames->samples;
     playback_channel->free_frames = playback_channel->free_frames->next;
     *num_samples = FRAME_SIZE;
 }
 
-static void snd_playback_put_frame(PlaybackPlug *plug, uint32_t *samples)
+__visible__ void spice_server_playback_put_samples(SpicePlaybackInstance *sin, uint32_t *samples)
 {
-    PlaybackChannel *playback_channel = SPICE_CONTAINEROF(plug, PlaybackChannel, plug);
+    SndChannel *channel = sin->st->worker.connection;
+    PlaybackChannel *playback_channel = SPICE_CONTAINEROF(channel, PlaybackChannel, base);
     AudioFrame *frame;
 
+    if (!channel)
+        return;
     ASSERT(playback_channel->base.active);
 
     if (playback_channel->pending_frame) {
@@ -920,12 +937,11 @@ static void snd_playback_put_frame(PlaybackPlug *plug, uint32_t *samples)
 
 static void on_new_playback_channel(SndWorker *worker)
 {
-    PlaybackChannel *playback_channel = (PlaybackChannel *)worker->connection;
-    PlaybackInterface *interface = (PlaybackInterface *)worker->interface;
+    PlaybackChannel *playback_channel =
+        SPICE_CONTAINEROF(worker->connection, PlaybackChannel, base);
+
     ASSERT(playback_channel);
 
-    playback_channel->plug_ref = interface->plug(interface, &playback_channel->plug,
-                                                 &playback_channel->base.active);
     snd_set_command((SndChannel *)playback_channel, SND_PLAYBACK_MODE_MASK);
     if (!playback_channel->base.migrate && playback_channel->base.active) {
         snd_set_command((SndChannel *)playback_channel, SND_PLAYBACK_CTRL_MASK);
@@ -937,13 +953,11 @@ static void on_new_playback_channel(SndWorker *worker)
 
 static void snd_playback_cleanup(SndChannel *channel)
 {
-    PlaybackChannel *playback_channel = (PlaybackChannel *)channel;
-    PlaybackInterface *interface = (PlaybackInterface *)channel->worker->interface;
+    PlaybackChannel *playback_channel = SPICE_CONTAINEROF(channel, PlaybackChannel, base);
 
     if (playback_channel->base.active) {
         reds_enable_mm_timer();
     }
-    interface->unplug(interface, playback_channel->plug_ref);
 
     celt051_encoder_destroy(playback_channel->celt_encoder);
     celt051_mode_destroy(playback_channel->celt_mode);
@@ -961,7 +975,8 @@ static void snd_set_playback_peer(Channel *channel, RedsStreamContext *peer, int
 
     snd_disconnect_channel(worker->connection);
 
-    if (!(celt_mode = celt051_mode_create(VD_INTERFACE_PLAYBACK_FREQ, VD_INTERFACE_PLAYBACK_CHAN,
+    if (!(celt_mode = celt051_mode_create(SPICE_INTERFACE_PLAYBACK_FREQ,
+                                          SPICE_INTERFACE_PLAYBACK_CHAN,
                                           FRAME_SIZE, &celt_error))) {
         red_printf("create celt mode failed %d", celt_error);
         return;
@@ -987,12 +1002,6 @@ static void snd_set_playback_peer(Channel *channel, RedsStreamContext *peer, int
     snd_playback_free_frame(playback_channel, &playback_channel->frames[1]);
     snd_playback_free_frame(playback_channel, &playback_channel->frames[2]);
 
-    playback_channel->plug.major_version = VD_INTERFACE_PLAYBACK_MAJOR;
-    playback_channel->plug.minor_version = VD_INTERFACE_PLAYBACK_MINOR;
-    playback_channel->plug.start = snd_playback_start;
-    playback_channel->plug.stop = snd_playback_stop;
-    playback_channel->plug.get_frame = snd_playback_get_frame;
-    playback_channel->plug.put_frame = snd_playback_put_frame;
     playback_channel->celt_mode = celt_mode;
     playback_channel->celt_encoder = celt_encoder;
     playback_channel->celt_allowed = num_caps > 0 && (caps[0] & (1 << SPICE_PLAYBACK_CAP_CELT_0_5_1));
@@ -1019,10 +1028,13 @@ static void snd_record_migrate(Channel *channel)
     }
 }
 
-static void snd_record_start(RecordPlug *plug)
+__visible__ void spice_server_record_start(SpiceRecordInstance *sin)
 {
-    RecordChannel *record_channel = SPICE_CONTAINEROF(plug, RecordChannel, plug);
+    SndChannel *channel = sin->st->worker.connection;
+    RecordChannel *record_channel = SPICE_CONTAINEROF(channel, RecordChannel, base);
 
+    if (!channel)
+        return;
     ASSERT(!record_channel->base.active);
     record_channel->base.active = TRUE;
     record_channel->read_pos = record_channel->write_pos = 0;   //todo: improve by
@@ -1035,10 +1047,13 @@ static void snd_record_start(RecordPlug *plug)
     }
 }
 
-static void snd_record_stop(RecordPlug *plug)
+__visible__ void spice_server_record_stop(SpiceRecordInstance *sin)
 {
-    RecordChannel *record_channel = SPICE_CONTAINEROF(plug, RecordChannel, plug);
+    SndChannel *channel = sin->st->worker.connection;
+    RecordChannel *record_channel = SPICE_CONTAINEROF(channel, RecordChannel, base);
 
+    if (!channel)
+        return;
     ASSERT(record_channel->base.active);
     record_channel->base.active = FALSE;
     if (record_channel->base.client_active) {
@@ -1049,28 +1064,32 @@ static void snd_record_stop(RecordPlug *plug)
     }
 }
 
-static uint32_t snd_record_read(RecordPlug *plug, uint32_t num_samples, uint32_t *samples)
+__visible__ uint32_t spice_server_record_get_samples(SpiceRecordInstance *sin,
+                                                     uint32_t *samples, uint32_t bufsize)
 {
-    RecordChannel *record_channel = SPICE_CONTAINEROF(plug, RecordChannel, plug);
+    SndChannel *channel = sin->st->worker.connection;
+    RecordChannel *record_channel = SPICE_CONTAINEROF(channel, RecordChannel, base);
     uint32_t read_pos;
     uint32_t now;
     uint32_t len;
 
+    if (!channel)
+        return 0;
     ASSERT(record_channel->base.active);
 
     if (record_channel->write_pos < RECORD_SAMPLES_SIZE / 2) {
         return 0;
     }
 
-    len = MIN(record_channel->write_pos - record_channel->read_pos, num_samples);
+    len = MIN(record_channel->write_pos - record_channel->read_pos, bufsize);
 
-    if (len < num_samples) {
+    if (len < bufsize) {
         SndWorker *worker = record_channel->base.worker;
         snd_receive(record_channel);
         if (!worker->connection) {
             return 0;
         }
-        len = MIN(record_channel->write_pos - record_channel->read_pos, num_samples);
+        len = MIN(record_channel->write_pos - record_channel->read_pos, bufsize);
     }
 
     read_pos = record_channel->read_pos % RECORD_SAMPLES_SIZE;
@@ -1086,11 +1105,8 @@ static uint32_t snd_record_read(RecordPlug *plug, uint32_t num_samples, uint32_t
 static void on_new_record_channel(SndWorker *worker)
 {
     RecordChannel *record_channel = (RecordChannel *)worker->connection;
-    RecordInterface *interface = (RecordInterface *)worker->interface;
     ASSERT(record_channel);
 
-    record_channel->plug_ref = interface->plug(interface, &record_channel->plug,
-                                               &record_channel->base.active);
     if (!record_channel->base.migrate) {
         if (record_channel->base.active) {
             snd_set_command((SndChannel *)record_channel, SND_RECORD_CTRL_MASK);
@@ -1101,8 +1117,6 @@ static void on_new_record_channel(SndWorker *worker)
 static void snd_record_cleanup(SndChannel *channel)
 {
     RecordChannel *record_channel = (RecordChannel *)channel;
-    RecordInterface *interface = (RecordInterface *)channel->worker->interface;
-    interface->unplug(interface, record_channel->plug_ref);
 
     celt051_decoder_destroy(record_channel->celt_decoder);
     celt051_mode_destroy(record_channel->celt_mode);
@@ -1120,7 +1134,8 @@ static void snd_set_record_peer(Channel *channel, RedsStreamContext *peer, int m
 
     snd_disconnect_channel(worker->connection);
 
-    if (!(celt_mode = celt051_mode_create(VD_INTERFACE_RECORD_FREQ, VD_INTERFACE_RECORD_CHAN,
+    if (!(celt_mode = celt051_mode_create(SPICE_INTERFACE_RECORD_FREQ,
+                                          SPICE_INTERFACE_RECORD_CHAN,
                                           FRAME_SIZE, &celt_error))) {
         red_printf("create celt mode failed %d", celt_error);
         return;
@@ -1144,11 +1159,6 @@ static void snd_set_record_peer(Channel *channel, RedsStreamContext *peer, int m
 
     worker->connection = &record_channel->base;
 
-    record_channel->plug.major_version = VD_INTERFACE_RECORD_MAJOR;
-    record_channel->plug.minor_version = VD_INTERFACE_RECORD_MINOR;
-    record_channel->plug.start = snd_record_start;
-    record_channel->plug.stop = snd_record_stop;
-    record_channel->plug.read = snd_record_read;
     record_channel->celt_mode = celt_mode;
     record_channel->celt_decoder = celt_decoder;
 
@@ -1192,29 +1202,19 @@ static void remove_worker(SndWorker *worker)
     red_printf("not found");
 }
 
-static SndWorker *find_worker(SpiceBaseInterface *interface)
-{
-    SndWorker *worker = workers;
-    while (worker) {
-        if (worker->interface == interface) {
-            break;
-        }
-        worker = worker->next;
-    }
-    return worker;
-}
-
-void snd_attach_playback(PlaybackInterface *interface)
+void snd_attach_playback(SpicePlaybackInstance *sin)
 {
     SndWorker *playback_worker;
-    playback_worker = spice_new0(SndWorker, 1);
+
+    sin->st = spice_new0(SpicePlaybackState, 1);
+    playback_worker = &sin->st->worker;
+
     playback_worker->base.type = SPICE_CHANNEL_PLAYBACK;
     playback_worker->base.link = snd_set_playback_peer;
     playback_worker->base.shutdown = snd_shutdown;
     playback_worker->base.migrate = snd_playback_migrate;
     playback_worker->base.data = NULL;
 
-    playback_worker->interface = &interface->base;
     playback_worker->base.num_caps = 1;
     playback_worker->base.caps = spice_new(uint32_t, 1);
     playback_worker->base.caps[0] = (1 << SPICE_PLAYBACK_CAP_CELT_0_5_1);
@@ -1223,18 +1223,19 @@ void snd_attach_playback(PlaybackInterface *interface)
     reds_register_channel(&playback_worker->base);
 }
 
-void snd_attach_record(RecordInterface *interface)
+void snd_attach_record(SpiceRecordInstance *sin)
 {
     SndWorker *record_worker;
-    record_worker = spice_new0(SndWorker, 1);
+
+    sin->st = spice_new0(SpiceRecordState, 1);
+    record_worker = &sin->st->worker;
+
     record_worker->base.type = SPICE_CHANNEL_RECORD;
     record_worker->base.link = snd_set_record_peer;
     record_worker->base.shutdown = snd_shutdown;
     record_worker->base.migrate = snd_record_migrate;
     record_worker->base.data = NULL;
 
-    record_worker->interface = &interface->base;
-
     record_worker->base.num_caps = 1;
     record_worker->base.caps = spice_new(uint32_t, 1);
     record_worker->base.caps[0] = (1 << SPICE_RECORD_CAP_CELT_0_5_1);
@@ -1242,10 +1243,8 @@ void snd_attach_record(RecordInterface *interface)
     reds_register_channel(&record_worker->base);
 }
 
-static void snd_detach_common(SpiceBaseInterface *interface)
+static void snd_detach_common(SndWorker *worker)
 {
-    SndWorker *worker = find_worker(interface);
-
     if (!worker) {
         return;
     }
@@ -1255,17 +1254,18 @@ static void snd_detach_common(SpiceBaseInterface *interface)
 
     free(worker->base.common_caps);
     free(worker->base.caps);
-    free(worker);
 }
 
-void snd_detach_playback(PlaybackInterface *interface)
+void snd_detach_playback(SpicePlaybackInstance *sin)
 {
-    snd_detach_common(&interface->base);
+    snd_detach_common(&sin->st->worker);
+    free(sin->st);
 }
 
-void snd_detach_record(RecordInterface *interface)
+void snd_detach_record(SpiceRecordInstance *sin)
 {
-    snd_detach_common(&interface->base);
+    snd_detach_common(&sin->st->worker);
+    free(sin->st);
 }
 
 void snd_set_playback_compression(int on)
diff --git a/server/snd_worker.h b/server/snd_worker.h
index d7f9674..291f321 100644
--- a/server/snd_worker.h
+++ b/server/snd_worker.h
@@ -20,11 +20,11 @@
 
 #include "vd_interface.h"
 
-void snd_attach_playback(PlaybackInterface *interface);
-void snd_detach_playback(PlaybackInterface *interface);
+void snd_attach_playback(SpicePlaybackInstance *sin);
+void snd_detach_playback(SpicePlaybackInstance *sin);
 
-void snd_attach_record(RecordInterface *interface);
-void snd_detach_record(RecordInterface *interface);
+void snd_attach_record(SpiceRecordInstance *sin);
+void snd_detach_record(SpiceRecordInstance *sin);
 
 void snd_set_playback_compression(int on);
 int snd_get_playback_compression();
diff --git a/server/vd_interface.h b/server/vd_interface.h
index 6b1315a..d3ce999 100644
--- a/server/vd_interface.h
+++ b/server/vd_interface.h
@@ -311,62 +311,62 @@ typedef struct VDICmdArg {
 typedef void (*VDICmdHandler)(const VDICmdArg* args);
 typedef void (*VDIInfoCmdHandler)(void);
 
-#define VD_INTERFACE_PLAYBACK "playback"
-#define VD_INTERFACE_PLAYBACK_MAJOR 1
-#define VD_INTERFACE_PLAYBACK_MINOR 1
-typedef struct PlaybackInterface PlaybackInterface;
+#define SPICE_INTERFACE_PLAYBACK "playback"
+#define SPICE_INTERFACE_PLAYBACK_MAJOR 1
+#define SPICE_INTERFACE_PLAYBACK_MINOR 1
+typedef struct SpicePlaybackInterface SpicePlaybackInterface;
+typedef struct SpicePlaybackInstance SpicePlaybackInstance;
+typedef struct SpicePlaybackState SpicePlaybackState;
 
 enum {
-    VD_INTERFACE_AUDIO_FMT_S16 = 1,
+    SPICE_INTERFACE_AUDIO_FMT_S16 = 1,
 };
 
-#define VD_INTERFACE_PLAYBACK_FREQ 44100
-#define VD_INTERFACE_PLAYBACK_CHAN 2
-#define VD_INTERFACE_PLAYBACK_FMT VD_INTERFACE_AUDIO_FMT_S16
+#define SPICE_INTERFACE_PLAYBACK_FREQ  44100
+#define SPICE_INTERFACE_PLAYBACK_CHAN  2
+#define SPICE_INTERFACE_PLAYBACK_FMT   SPICE_INTERFACE_AUDIO_FMT_S16
 
-typedef struct PlaybackPlug PlaybackPlug;
-struct PlaybackPlug {
-    uint32_t minor_version;
-    uint32_t major_version;
-    void (*start)(PlaybackPlug *plug);
-    void (*stop)(PlaybackPlug *plug);
-    void (*get_frame)(PlaybackPlug *plug, uint32_t **frame, uint32_t *samples);
-    void (*put_frame)(PlaybackPlug *plug, uint32_t *frame);
-};
-
-struct PlaybackInterface {
+struct SpicePlaybackInterface {
     SpiceBaseInterface base;
-
-    VDObjectRef (*plug)(PlaybackInterface *playback, PlaybackPlug* plug, int *enable);
-    void (*unplug)(PlaybackInterface *playback, VDObjectRef);
 };
 
-#define VD_INTERFACE_RECORD "record"
-#define VD_INTERFACE_RECORD_MAJOR 2
-#define VD_INTERFACE_RECORD_MINOR 1
-typedef struct RecordInterface RecordInterface;
-
-#define VD_INTERFACE_RECORD_FREQ 44100
-#define VD_INTERFACE_RECORD_CHAN 2
-#define VD_INTERFACE_RECORD_FMT VD_INTERFACE_AUDIO_FMT_S16
-
-
-typedef struct RecordPlug RecordPlug;
-struct RecordPlug {
-    uint32_t minor_version;
-    uint32_t major_version;
-    void (*start)(RecordPlug *plug);
-    void (*stop)(RecordPlug *plug);
-    uint32_t (*read)(RecordPlug *plug, uint32_t num_samples, uint32_t *samples);
+struct SpicePlaybackInstance {
+    SpiceBaseInstance  base;
+    SpicePlaybackState *st;
 };
 
-struct RecordInterface {
+void spice_server_playback_start(SpicePlaybackInstance *sin);
+void spice_server_playback_stop(SpicePlaybackInstance *sin);
+void spice_server_playback_get_buffer(SpicePlaybackInstance *sin,
+                                      uint32_t **samples, uint32_t *nsamples);
+void spice_server_playback_put_samples(SpicePlaybackInstance *sin,
+                                       uint32_t *samples);
+
+#define SPICE_INTERFACE_RECORD "record"
+#define SPICE_INTERFACE_RECORD_MAJOR 2
+#define SPICE_INTERFACE_RECORD_MINOR 1
+typedef struct SpiceRecordInterface SpiceRecordInterface;
+typedef struct SpiceRecordInstance SpiceRecordInstance;
+typedef struct SpiceRecordState SpiceRecordState;
+
+#define SPICE_INTERFACE_RECORD_FREQ  44100
+#define SPICE_INTERFACE_RECORD_CHAN  2
+#define SPICE_INTERFACE_RECORD_FMT   SPICE_INTERFACE_AUDIO_FMT_S16
+
+struct SpiceRecordInterface {
     SpiceBaseInterface base;
+};
 
-    VDObjectRef (*plug)(RecordInterface *recorder, RecordPlug* plug, int *enable);
-    void (*unplug)(RecordInterface *recorder, VDObjectRef);
+struct SpiceRecordInstance {
+    SpiceBaseInstance base;
+    SpiceRecordState  *st;
 };
 
+void spice_server_record_start(SpiceRecordInstance *sin);
+void spice_server_record_stop(SpiceRecordInstance *sin);
+uint32_t spice_server_record_get_samples(SpiceRecordInstance *sin,
+                                         uint32_t *samples, uint32_t bufsize);
+
 #define VD_INTERFACE_VDI_PORT "vdi_port"
 #define VD_INTERFACE_VDI_PORT_MAJOR 1
 #define VD_INTERFACE_VDI_PORT_MINOR 1
commit 4701a063da5c00b33bc9ccb264b042e046c97df9
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Apr 7 16:34:49 2010 +0200

    TabletInterface: redesign

diff --git a/server/reds.c b/server/reds.c
index ab1f6da..d5a28c6 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -58,7 +58,7 @@ SpiceCoreInterface *core = NULL;
 static MigrationInterface *mig = NULL;
 static SpiceKbdInstance *keyboard = NULL;
 static SpiceMouseInstance *mouse = NULL;
-static TabletInterface *tablet = NULL;
+static SpiceTabletInstance *tablet = NULL;
 static VDIPortInterface *vdagent = NULL;
 
 #define MIGRATION_NOTIFY_SPICE_KEY "spice_mig_ext"
@@ -2192,7 +2192,9 @@ static void inputs_handle_input(void *opaque, SpiceDataHeader *header)
         }
         ASSERT((agent_mouse && vdagent) || tablet);
         if (!agent_mouse || !vdagent) {
-            tablet->position(tablet, pos->x, pos->y, RED_MOUSE_STATE_TO_LOCAL(pos->buttons_state));
+            SpiceTabletInterface *sif;
+            sif = SPICE_CONTAINEROF(tablet->base.sif, SpiceTabletInterface, base);
+            sif->position(tablet, pos->x, pos->y, RED_MOUSE_STATE_TO_LOCAL(pos->buttons_state));
             break;
         }
         VDAgentMouseState *mouse_state = &state->mouse_state;
@@ -2219,7 +2221,9 @@ static void inputs_handle_input(void *opaque, SpiceDataHeader *header)
                     (dz == 1 ? VD_AGENT_DBUTTON_MASK : 0);
                 reds_handle_agent_mouse_event();
             } else if (tablet) {
-                tablet->wheel(tablet, dz, RED_MOUSE_STATE_TO_LOCAL(mouse_press->buttons_state));
+                SpiceTabletInterface *sif;
+                sif = SPICE_CONTAINEROF(tablet->base.sif, SpiceTabletInterface, base);
+                sif->wheel(tablet, dz, RED_MOUSE_STATE_TO_LOCAL(mouse_press->buttons_state));
             }
         } else if (mouse) {
             SpiceMouseInterface *sif;
@@ -2237,7 +2241,9 @@ static void inputs_handle_input(void *opaque, SpiceDataHeader *header)
                     RED_MOUSE_BUTTON_STATE_TO_AGENT(mouse_release->buttons_state);
                 reds_handle_agent_mouse_event();
             } else if (tablet) {
-                tablet->buttons(tablet, RED_MOUSE_STATE_TO_LOCAL(mouse_release->buttons_state));
+                SpiceTabletInterface *sif;
+                sif = SPICE_CONTAINEROF(tablet->base.sif, SpiceTabletInterface, base);
+                sif->buttons(tablet, RED_MOUSE_STATE_TO_LOCAL(mouse_release->buttons_state));
             }
         } else if (mouse) {
             SpiceMouseInterface *sif;
@@ -2285,7 +2291,9 @@ void reds_set_client_mouse_allowed(int is_client_mouse_allowed, int x_res, int y
     reds->dispatcher_allows_client_mouse = is_client_mouse_allowed;
     reds_update_mouse_mode();
     if (reds->is_client_mouse_allowed && tablet) {
-        tablet->set_logical_size(tablet, reds->monitor_mode.x_res, reds->monitor_mode.y_res);
+        SpiceTabletInterface *sif;
+        sif = SPICE_CONTAINEROF(tablet->base.sif, SpiceTabletInterface, base);
+        sif->set_logical_size(tablet, reds->monitor_mode.x_res, reds->monitor_mode.y_res);
     }
 }
 
@@ -4097,22 +4105,25 @@ __visible__ int spice_server_add_interface(SpiceServer *s,
         qxl->st->qif = SPICE_CONTAINEROF(interface, QXLInterface, base);
         qxl->st->dispatcher = red_dispatcher_init(qxl);
 
-    } else if (strcmp(interface->type, VD_INTERFACE_TABLET) == 0) {
-        red_printf("VD_INTERFACE_TABLET");
+    } else if (strcmp(interface->type, SPICE_INTERFACE_TABLET) == 0) {
+        red_printf("SPICE_INTERFACE_TABLET");
         if (tablet) {
             red_printf("already have tablet");
             return -1;
         }
-        if (interface->major_version != VD_INTERFACE_TABLET_MAJOR ||
-            interface->minor_version < VD_INTERFACE_TABLET_MINOR) {
+        if (interface->major_version != SPICE_INTERFACE_TABLET_MAJOR ||
+            interface->minor_version < SPICE_INTERFACE_TABLET_MINOR) {
             red_printf("unsuported tablet interface");
             return -1;
         }
-        tablet = (TabletInterface *)interface;
+        tablet = SPICE_CONTAINEROF(sin, SpiceTabletInstance, base);
+        tablet->st = spice_new0(SpiceTabletState, 1);
         reds_update_mouse_mode();
         if (reds->is_client_mouse_allowed) {
-            tablet->set_logical_size(tablet, reds->monitor_mode.x_res,
-                                     reds->monitor_mode.y_res);
+            SpiceTabletInterface *sif;
+            sif = SPICE_CONTAINEROF(tablet->base.sif, SpiceTabletInterface, base);
+            sif->set_logical_size(tablet, reds->monitor_mode.x_res,
+                                  reds->monitor_mode.y_res);
         }
 
     } else if (strcmp(interface->type, VD_INTERFACE_PLAYBACK) == 0) {
@@ -4173,9 +4184,9 @@ __visible__ int spice_server_remove_interface(SpiceBaseInstance *sin)
 {
     SpiceBaseInterface *interface = sin->sif;
 
-    if (strcmp(interface->type, VD_INTERFACE_TABLET) == 0) {
-        red_printf("remove VD_INTERFACE_TABLET");
-        if (interface == (SpiceBaseInterface *)tablet) {
+    if (strcmp(interface->type, SPICE_INTERFACE_TABLET) == 0) {
+        red_printf("remove SPICE_INTERFACE_TABLET");
+        if (sin == &tablet->base) {
             tablet = NULL;
             reds_update_mouse_mode();
         }
diff --git a/server/reds.h b/server/reds.h
index b3dcd4b..78581f8 100644
--- a/server/reds.h
+++ b/server/reds.h
@@ -66,6 +66,10 @@ struct SpiceMouseState {
     int dummy;
 };
 
+struct SpiceTabletState {
+    int dummy;
+};
+
 struct QXLState {
     QXLInterface          *qif;
     struct RedDispatcher  *dispatcher;
diff --git a/server/vd_interface.h b/server/vd_interface.h
index bbe8436..6b1315a 100644
--- a/server/vd_interface.h
+++ b/server/vd_interface.h
@@ -246,18 +246,25 @@ struct SpiceMouseInstance {
     SpiceMouseState   *st;
 };
 
-#define VD_INTERFACE_TABLET "tablet"
-#define VD_INTERFACE_TABLET_MAJOR 1
-#define VD_INTERFACE_TABLET_MINOR 1
-typedef struct TabletInterface TabletInterface;
-
-struct TabletInterface {
+#define SPICE_INTERFACE_TABLET "tablet"
+#define SPICE_INTERFACE_TABLET_MAJOR 1
+#define SPICE_INTERFACE_TABLET_MINOR 1
+typedef struct SpiceTabletInterface SpiceTabletInterface;
+typedef struct SpiceTabletInstance SpiceTabletInstance;
+typedef struct SpiceTabletState SpiceTabletState;
+
+struct SpiceTabletInterface {
     SpiceBaseInterface base;
 
-    void (*set_logical_size)(TabletInterface* tablet, int width, int height);
-    void (*position)(TabletInterface* tablet, int x, int y, uint32_t buttons_state);
-    void (*wheel)(TabletInterface* tablet, int wheel_moution, uint32_t buttons_state);
-    void (*buttons)(TabletInterface* tablet, uint32_t buttons_state);
+    void (*set_logical_size)(SpiceTabletInstance* tablet, int width, int height);
+    void (*position)(SpiceTabletInstance* tablet, int x, int y, uint32_t buttons_state);
+    void (*wheel)(SpiceTabletInstance* tablet, int wheel_moution, uint32_t buttons_state);
+    void (*buttons)(SpiceTabletInstance* tablet, uint32_t buttons_state);
+};
+
+struct SpiceTabletInstance {
+    SpiceBaseInstance base;
+    SpiceTabletState  *st;
 };
 
 #define VD_INTERFACE_MIGRATION "migration"
commit d3735feea6b50acef050a79fff5c4dd8143e3e38
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Mar 30 12:55:32 2010 +0200

    QXL: redesign.

diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
index f7c6646..3d1d6f9 100644
--- a/server/red_dispatcher.c
+++ b/server/red_dispatcher.c
@@ -40,7 +40,7 @@ static int num_active_workers = 0;
 typedef struct RedDispatcher RedDispatcher;
 struct RedDispatcher {
     QXLWorker base;
-    QXLInterface *qxl_interface;
+    QXLInstance *qxl;
     int channel;
     pthread_t worker_thread;
     uint32_t pending;
@@ -387,7 +387,7 @@ void red_dispatcher_set_mm_time(uint32_t mm_time)
 {
     RedDispatcher *now = dispatchers;
     while (now) {
-        now->qxl_interface->set_mm_time(now->qxl_interface, mm_time);
+        now->qxl->st->qif->set_mm_time(now->qxl, mm_time);
         now = now->next;
     }
 }
@@ -409,7 +409,7 @@ void red_dispatcher_on_ic_change()
     RedDispatcher *now = dispatchers;
     while (now) {
         RedWorkeMessage message = RED_WORKER_MESSAGE_SET_COMPRESSION;
-        now->qxl_interface->set_compression_level(now->qxl_interface, compression_level);
+        now->qxl->st->qif->set_compression_level(now->qxl, compression_level);
         write_message(now->channel, &message);
         send_data(now->channel, &image_compression, sizeof(spice_image_compression_t));
         now = now->next;
@@ -422,7 +422,7 @@ void red_dispatcher_on_sv_change()
     RedDispatcher *now = dispatchers;
     while (now) {
         RedWorkeMessage message = RED_WORKER_MESSAGE_SET_STREAMING_VIDEO;
-        now->qxl_interface->set_compression_level(now->qxl_interface, compression_level);
+        now->qxl->st->qif->set_compression_level(now->qxl, compression_level);
         write_message(now->channel, &message);
         send_data(now->channel, &streaming_video, sizeof(uint32_t));
         now = now->next;
@@ -458,11 +458,11 @@ uint32_t red_dispatcher_qxl_ram_size()
     if (!dispatchers) {
         return 0;
     }
-    dispatchers->qxl_interface->get_init_info(dispatchers->qxl_interface, &qxl_info);
+    dispatchers->qxl->st->qif->get_init_info(dispatchers->qxl, &qxl_info);
     return qxl_info.qxl_ram_size;
 }
 
-RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface, int id)
+RedDispatcher *red_dispatcher_init(QXLInstance *qxl)
 {
     RedDispatcher *dispatcher;
     int channels[2];
@@ -475,9 +475,9 @@ RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface, int id)
     sigset_t thread_sig_mask;
     sigset_t curr_sig_mask;
 
-    if (qxl_interface->pci_vendor != REDHAT_PCI_VENDOR_ID ||
-        qxl_interface->pci_id != QXL_DEVICE_ID ||
-        qxl_interface->pci_revision != QXL_REVISION) {
+    if (qxl->st->qif->pci_vendor != REDHAT_PCI_VENDOR_ID ||
+        qxl->st->qif->pci_id != QXL_DEVICE_ID ||
+        qxl->st->qif->pci_revision != QXL_REVISION) {
         red_printf("pci mismatch");
         return NULL;
     }
@@ -492,8 +492,8 @@ RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface, int id)
 
     dispatcher = spice_new0(RedDispatcher, 1);
     dispatcher->channel = channels[0];
-    init_data.qxl_interface = dispatcher->qxl_interface = qxl_interface;
-    init_data.id = id;
+    init_data.qxl = dispatcher->qxl = qxl;
+    init_data.id = qxl->id;
     init_data.channel = channels[1];
     init_data.pending = &dispatcher->pending;
     init_data.num_renderers = num_renderers;
@@ -502,8 +502,8 @@ RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface, int id)
     init_data.image_compression = image_compression;
     init_data.streaming_video = streaming_video;
 
-    dispatcher->base.major_version = VD_INTERFACE_QXL_MAJOR;
-    dispatcher->base.major_version = VD_INTERFACE_QXL_MINOR;
+    dispatcher->base.major_version = SPICE_INTERFACE_QXL_MAJOR;
+    dispatcher->base.minor_version = SPICE_INTERFACE_QXL_MINOR;
     dispatcher->base.wakeup = qxl_worker_wakeup;
     dispatcher->base.oom = qxl_worker_oom;
     dispatcher->base.save = qxl_worker_save;
@@ -522,7 +522,7 @@ RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface, int id)
     dispatcher->base.reset_cursor = qxl_worker_reset_cursor;
     dispatcher->base.destroy_surface_wait = qxl_worker_destroy_surface_wait;
 
-    qxl_interface->get_init_info(qxl_interface, &init_info);
+    qxl->st->qif->get_init_info(qxl, &init_info);
 
     init_data.memslot_id_bits = init_info.memslot_id_bits;
     init_data.memslot_gen_bits = init_info.memslot_gen_bits;
@@ -548,7 +548,7 @@ RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface, int id)
 
     reds_channel = spice_new0(Channel, 1);
     reds_channel->type = SPICE_CHANNEL_DISPLAY;
-    reds_channel->id = id;
+    reds_channel->id = qxl->id;
     reds_channel->link = red_dispatcher_set_peer;
     reds_channel->shutdown = red_dispatcher_shutdown_peer;
     reds_channel->migrate = red_dispatcher_migrate;
@@ -557,14 +557,14 @@ RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface, int id)
 
     cursor_channel = spice_new0(Channel, 1);
     cursor_channel->type = SPICE_CHANNEL_CURSOR;
-    cursor_channel->id = id;
+    cursor_channel->id = qxl->id;
     cursor_channel->link = red_dispatcher_set_cursor_peer;
     cursor_channel->shutdown = red_dispatcher_shutdown_cursor_peer;
     cursor_channel->migrate = red_dispatcher_cursor_migrate;
     cursor_channel->data = dispatcher;
     reds_register_channel(cursor_channel);
-    qxl_interface->attache_worker(qxl_interface, &dispatcher->base);
-    qxl_interface->set_compression_level(qxl_interface, calc_compression_level());
+    qxl->st->qif->attache_worker(qxl, &dispatcher->base);
+    qxl->st->qif->set_compression_level(qxl, calc_compression_level());
 
     dispatcher->next = dispatchers;
     dispatchers = dispatcher;
diff --git a/server/red_dispatcher.h b/server/red_dispatcher.h
index b0bc040..7f8973a 100644
--- a/server/red_dispatcher.h
+++ b/server/red_dispatcher.h
@@ -19,7 +19,7 @@
 #define _H_RED_DISPATCHER
 
 
-struct RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface, int id);
+struct RedDispatcher *red_dispatcher_init(QXLInstance *qxl);
 
 void red_dispatcher_set_mm_time(uint32_t);
 void red_dispatcher_on_ic_change();
diff --git a/server/red_worker.c b/server/red_worker.c
index 7499d8f..b66d098 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -921,7 +921,7 @@ typedef struct RedWorker {
     EventListener dev_listener;
     DisplayChannel *display_channel;
     CursorChannel *cursor_channel;
-    QXLInterface *qxl;
+    QXLInstance *qxl;
     int id;
     int channel;
     int running;
@@ -1508,7 +1508,7 @@ static inline void red_destroy_surface(RedWorker *worker, uint32_t surface_id)
 
                 release_info_ext.group_id = surface->release_group_id;
                 release_info_ext.info = surface->release_info;
-                worker->qxl->release_resource(worker->qxl, release_info_ext);
+                worker->qxl->st->qif->release_resource(worker->qxl, release_info_ext);
             }
 
             region_destroy(&surface->draw_dirty_region);
@@ -1542,7 +1542,7 @@ static inline void free_qxl_drawable(RedWorker *worker, QXLDrawable *drawable, u
     }
     release_info_ext.group_id = group_id;
     release_info_ext.info = &drawable->release_info;
-    worker->qxl->release_resource(worker->qxl, release_info_ext);
+    worker->qxl->st->qif->release_resource(worker->qxl, release_info_ext);
 }
 
 static void remove_depended_item(DependItem *item)
@@ -3903,7 +3903,7 @@ static inline void red_process_surface(RedWorker *worker, QXLSurfaceCmd *surface
                            height, stride, surface->u.surface_create.format, data);
         release_info_ext.group_id = group_id;
         release_info_ext.info = &surface->release_info;
-        worker->qxl->release_resource(worker->qxl, release_info_ext);
+        worker->qxl->st->qif->release_resource(worker->qxl, release_info_ext);
         break;
     }
     case QXL_SURFACE_CMD_DESTROY:
@@ -4730,7 +4730,7 @@ static void red_release_cursor(RedWorker *worker, CursorItem *cursor)
         cursor_cmd = cursor->qxl_cursor;
         release_info_ext.group_id = cursor->group_id;
         release_info_ext.info = &cursor_cmd->release_info;
-        worker->qxl->release_resource(worker->qxl, release_info_ext);
+        worker->qxl->st->qif->release_resource(worker->qxl, release_info_ext);
         free_cursor_item(worker, cursor);
     }
 }
@@ -4836,14 +4836,14 @@ static int red_process_cursor(RedWorker *worker, uint32_t max_pipe_size)
     int n = 0;
 
     while (!worker->cursor_channel || worker->cursor_channel->base.pipe_size <= max_pipe_size) {
-        if (!worker->qxl->get_cursor_command(worker->qxl, &ext_cmd)) {
+        if (!worker->qxl->st->qif->get_cursor_command(worker->qxl, &ext_cmd)) {
             if (worker->repoll_cursor_ring < CMD_RING_POLL_RETRIES) {
                 worker->repoll_cursor_ring++;
                 worker->epoll_timeout = MIN(worker->epoll_timeout, CMD_RING_POLL_TIMEOUT);
                 break;
             }
             if (worker->repoll_cursor_ring > CMD_RING_POLL_RETRIES ||
-                worker->qxl->req_cursor_notification(worker->qxl)) {
+                worker->qxl->st->qif->req_cursor_notification(worker->qxl)) {
                 worker->repoll_cursor_ring++;
                 break;
             }
@@ -4873,14 +4873,14 @@ static int red_process_commands(RedWorker *worker, uint32_t max_pipe_size)
     uint64_t start = red_now();
 
     while (!worker->display_channel || worker->display_channel->base.pipe_size <= max_pipe_size) {
-        if (!worker->qxl->get_command(worker->qxl, &ext_cmd)) {
+        if (!worker->qxl->st->qif->get_command(worker->qxl, &ext_cmd)) {
             if (worker->repoll_cmd_ring < CMD_RING_POLL_RETRIES) {
                 worker->repoll_cmd_ring++;
                 worker->epoll_timeout = MIN(worker->epoll_timeout, CMD_RING_POLL_TIMEOUT);
                 break;
             }
             if (worker->repoll_cmd_ring > CMD_RING_POLL_RETRIES ||
-                         worker->qxl->req_cmd_notification(worker->qxl)) {
+                         worker->qxl->st->qif->req_cmd_notification(worker->qxl)) {
                 worker->repoll_cmd_ring++;
                 break;
             }
@@ -4904,10 +4904,10 @@ static int red_process_commands(RedWorker *worker, uint32_t max_pipe_size)
             surface_id = draw_cmd->surface_id;
             validate_surface(worker, surface_id);
             red_update_area(worker, &draw_cmd->area, draw_cmd->surface_id);
-            worker->qxl->notify_update(worker->qxl, draw_cmd->update_id);
+            worker->qxl->st->qif->notify_update(worker->qxl, draw_cmd->update_id);
             release_info_ext.group_id = ext_cmd.group_id;
             release_info_ext.info = &draw_cmd->release_info;
-            worker->qxl->release_resource(worker->qxl, release_info_ext);
+            worker->qxl->st->qif->release_resource(worker->qxl, release_info_ext);
             break;
         }
         case QXL_CMD_MESSAGE: {
@@ -4917,7 +4917,7 @@ static int red_process_commands(RedWorker *worker, uint32_t max_pipe_size)
             red_printf("MESSAGE: %s", message->data);
             release_info_ext.group_id = ext_cmd.group_id;
             release_info_ext.info = &message->release_info;
-            worker->qxl->release_resource(worker->qxl, release_info_ext);
+            worker->qxl->st->qif->release_resource(worker->qxl, release_info_ext);
             break;
         }
         case QXL_CMD_SURFACE: {
@@ -8098,7 +8098,7 @@ static inline void flush_display_commands(RedWorker *worker)
         uint64_t end_time;
 
         red_process_commands(worker, MAX_PIPE_SIZE);
-        if (!worker->qxl->has_command(worker->qxl)) {
+        if (!worker->qxl->st->qif->has_command(worker->qxl)) {
             break;
         }
 
@@ -8106,7 +8106,7 @@ static inline void flush_display_commands(RedWorker *worker)
             display_channel_push(worker);
         }
 
-        if (!worker->qxl->has_command(worker->qxl)) {
+        if (!worker->qxl->st->qif->has_command(worker->qxl)) {
             break;
         }
         end_time = red_now() + DISPLAY_CLIENT_TIMEOUT * 10;
@@ -8869,7 +8869,7 @@ static void red_save_cursor(RedWorker *worker)
     cursor_data->data_size = local->data_size;
     cursor_data->_cursor.header = local->red_cursor.header;
     memcpy(cursor_data->_cursor.data, local->red_cursor.data, local->data_size);
-    worker->qxl->set_save_data(worker->qxl, cursor_data, size);
+    worker->qxl->st->qif->set_save_data(worker->qxl, cursor_data, size);
 }
 
 static LocalCursor *_new_local_cursor(SpiceCursorHeader *header, int data_size, SpicePoint16 position)
@@ -8934,7 +8934,7 @@ static void red_cursor_flush(RedWorker *worker)
 static void red_save(RedWorker *worker)
 {
     if (!worker->cursor) {
-        worker->qxl->set_save_data(worker->qxl, NULL, 0);
+        worker->qxl->st->qif->set_save_data(worker->qxl, NULL, 0);
         return;
     }
     red_save_cursor(worker);
@@ -8942,7 +8942,7 @@ static void red_save(RedWorker *worker)
 
 static void red_cursor_load(RedWorker *worker)
 {
-    CursorData *cursor_data = worker->qxl->get_save_data(worker->qxl);
+    CursorData *cursor_data = worker->qxl->st->qif->get_save_data(worker->qxl);
     LocalCursor *local;
 
     if (!cursor_data) {
@@ -9228,7 +9228,7 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
         while (red_process_commands(worker, MAX_PIPE_SIZE)) {
             display_channel_push(worker);
         }
-        if (worker->qxl->flush_resources(worker->qxl) == 0) {
+        if (worker->qxl->st->qif->flush_resources(worker->qxl) == 0) {
             red_printf("oom current %u pipe %u", worker->current_size, worker->display_channel ?
                        worker->display_channel->base.pipe_size : 0);
             red_free_some(worker);
@@ -9437,7 +9437,7 @@ static void red_init(RedWorker *worker, WorkerInitData *init_data)
     ASSERT(sizeof(CursorItem) <= QXL_CURSUR_DEVICE_DATA_SIZE);
 
     memset(worker, 0, sizeof(RedWorker));
-    worker->qxl = init_data->qxl_interface;
+    worker->qxl = init_data->qxl;
     worker->id = init_data->id;
     worker->channel = init_data->channel;
     worker->pending = init_data->pending;
diff --git a/server/red_worker.h b/server/red_worker.h
index 5807237..e53d518 100644
--- a/server/red_worker.h
+++ b/server/red_worker.h
@@ -83,7 +83,7 @@ enum {
 };
 
 typedef struct WorkerInitData {
-    struct QXLInterface *qxl_interface;
+    struct QXLInstance *qxl;
     int id;
     int channel;
     uint32_t *pending;
diff --git a/server/reds.c b/server/reds.c
index 8d6e14d..ab1f6da 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -4029,8 +4029,7 @@ static void attach_to_red_agent(VDIPortInterface *interface)
 }
 
 __visible__ int spice_server_add_interface(SpiceServer *s,
-                                           SpiceBaseInstance *sin,
-                                           int id)
+                                           SpiceBaseInstance *sin)
 {
     SpiceBaseInterface *interface = sin->sif;
 
@@ -4083,17 +4082,20 @@ __visible__ int spice_server_add_interface(SpiceServer *s,
             red_error("migration register failed");
         }
 
-    } else if (strcmp(interface->type, VD_INTERFACE_QXL) == 0) {
-        QXLInterface *qxl_interface;
+    } else if (strcmp(interface->type, SPICE_INTERFACE_QXL) == 0) {
+        QXLInstance *qxl;
 
-        red_printf("VD_INTERFACE_QXL");
-        if (interface->major_version != VD_INTERFACE_QXL_MAJOR ||
-            interface->minor_version < VD_INTERFACE_QXL_MINOR) {
+        red_printf("SPICE_INTERFACE_QXL");
+        if (interface->major_version != SPICE_INTERFACE_QXL_MAJOR ||
+            interface->minor_version < SPICE_INTERFACE_QXL_MINOR) {
             red_printf("unsuported qxl interface");
             return -1;
         }
-        qxl_interface = (QXLInterface *)interface;
-        red_dispatcher_init(qxl_interface, id);
+
+        qxl = SPICE_CONTAINEROF(sin, QXLInstance, base);
+        qxl->st = spice_new0(QXLState, 1);
+        qxl->st->qif = SPICE_CONTAINEROF(interface, QXLInterface, base);
+        qxl->st->dispatcher = red_dispatcher_init(qxl);
 
     } else if (strcmp(interface->type, VD_INTERFACE_TABLET) == 0) {
         red_printf("VD_INTERFACE_TABLET");
diff --git a/server/reds.h b/server/reds.h
index 68359ae..b3dcd4b 100644
--- a/server/reds.h
+++ b/server/reds.h
@@ -66,6 +66,11 @@ struct SpiceMouseState {
     int dummy;
 };
 
+struct QXLState {
+    QXLInterface          *qif;
+    struct RedDispatcher  *dispatcher;
+};
+
 void reds_desable_mm_timer();
 void reds_enable_mm_timer();
 void reds_update_mm_timer(uint32_t mm_time);
diff --git a/server/spice.h b/server/spice.h
index 8a7764e..f1bc80d 100644
--- a/server/spice.h
+++ b/server/spice.h
@@ -41,8 +41,7 @@ int spice_server_set_tls(SpiceServer *s, int port,
                          const char *dh_key_file, const char *ciphersuite);
 
 int spice_server_add_interface(SpiceServer *s,
-                               SpiceBaseInstance *sin,
-                               int id);
+                               SpiceBaseInstance *sin);
 int spice_server_remove_interface(SpiceBaseInstance *sin);
 int spice_server_kbd_leds(SpiceKbdInstance *sin, int leds);
 
diff --git a/server/vd_interface.h b/server/vd_interface.h
index 1567b12..bbe8436 100644
--- a/server/vd_interface.h
+++ b/server/vd_interface.h
@@ -84,11 +84,12 @@ struct SpiceCoreInterface {
 
 };
 
-#define VD_INTERFACE_QXL "qxl"
-#define VD_INTERFACE_QXL_MAJOR 3
-#define VD_INTERFACE_QXL_MINOR 0
+#define SPICE_INTERFACE_QXL "qxl"
+#define SPICE_INTERFACE_QXL_MAJOR 3
+#define SPICE_INTERFACE_QXL_MINOR 0
 typedef struct QXLInterface QXLInterface;
-typedef void (*qxl_mode_change_notifier_t)(void *opaque);
+typedef struct QXLInstance QXLInstance;
+typedef struct QXLState QXLState;
 typedef struct QXLWorker QXLWorker;
 typedef struct QXLDevMemSlot QXLDevMemSlot;
 typedef struct QXLDevSurfaceCreate QXLDevSurfaceCreate;
@@ -183,21 +184,27 @@ struct QXLInterface {
     uint16_t pci_id;
     uint8_t pci_revision;
 
-    void (*attache_worker)(QXLInterface *qxl, QXLWorker *qxl_worker);
-    void (*set_compression_level)(QXLInterface *qxl, int level);
-    void (*set_mm_time)(QXLInterface *qxl, uint32_t mm_time);
-
-    void (*get_init_info)(QXLInterface *qxl, QXLDevInitInfo *info);
-    int (*get_command)(QXLInterface *qxl, struct QXLCommandExt *cmd);
-    int (*req_cmd_notification)(QXLInterface *qxl);
-    int (*has_command)(QXLInterface *qxl);
-    void (*release_resource)(QXLInterface *qxl, struct QXLReleaseInfoExt release_info);
-    int (*get_cursor_command)(QXLInterface *qxl, struct QXLCommandExt *cmd);
-    int (*req_cursor_notification)(QXLInterface *qxl);
-    void (*notify_update)(QXLInterface *qxl, uint32_t update_id);
-    void (*set_save_data)(QXLInterface *qxl, void *data, int size);
-    void *(*get_save_data)(QXLInterface *qxl);
-    int (*flush_resources)(QXLInterface *qxl);
+    void (*attache_worker)(QXLInstance *qin, QXLWorker *qxl_worker);
+    void (*set_compression_level)(QXLInstance *qin, int level);
+    void (*set_mm_time)(QXLInstance *qin, uint32_t mm_time);
+
+    void (*get_init_info)(QXLInstance *qin, QXLDevInitInfo *info);
+    int (*get_command)(QXLInstance *qin, struct QXLCommandExt *cmd);
+    int (*req_cmd_notification)(QXLInstance *qin);
+    int (*has_command)(QXLInstance *qin);
+    void (*release_resource)(QXLInstance *qin, struct QXLReleaseInfoExt release_info);
+    int (*get_cursor_command)(QXLInstance *qin, struct QXLCommandExt *cmd);
+    int (*req_cursor_notification)(QXLInstance *qin);
+    void (*notify_update)(QXLInstance *qin, uint32_t update_id);
+    void (*set_save_data)(QXLInstance *qin, void *data, int size);
+    void *(*get_save_data)(QXLInstance *qin);
+    int (*flush_resources)(QXLInstance *qin);
+};
+
+struct QXLInstance {
+    SpiceBaseInstance  base;
+    int                id;
+    QXLState           *st;
 };
 
 #define SPICE_INTERFACE_KEYBOARD "keyboard"
commit 58273e3a32d89e59eb7da742c9b4a059dbfdfd37
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Mar 30 12:20:41 2010 +0200

    MouseInterface: redesign

diff --git a/server/reds.c b/server/reds.c
index 1eee21d..8d6e14d 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -57,7 +57,7 @@
 SpiceCoreInterface *core = NULL;
 static MigrationInterface *mig = NULL;
 static SpiceKbdInstance *keyboard = NULL;
-static MouseInterface *mouse = NULL;
+static SpiceMouseInstance *mouse = NULL;
 static TabletInterface *tablet = NULL;
 static VDIPortInterface *vdagent = NULL;
 
@@ -2163,8 +2163,11 @@ static void inputs_handle_input(void *opaque, SpiceDataHeader *header)
             }
         }
         if (mouse && reds->mouse_mode == SPICE_MOUSE_MODE_SERVER) {
-            mouse->moution(mouse, mouse_motion->dx, mouse_motion->dy, 0,
-                           RED_MOUSE_STATE_TO_LOCAL(mouse_motion->buttons_state));
+            SpiceMouseInterface *sif;
+            sif = SPICE_CONTAINEROF(mouse->base.sif, SpiceMouseInterface, base);
+            sif->motion(mouse,
+                        mouse_motion->dx, mouse_motion->dy, 0,
+                        RED_MOUSE_STATE_TO_LOCAL(mouse_motion->buttons_state));
         }
         break;
     }
@@ -2219,7 +2222,10 @@ static void inputs_handle_input(void *opaque, SpiceDataHeader *header)
                 tablet->wheel(tablet, dz, RED_MOUSE_STATE_TO_LOCAL(mouse_press->buttons_state));
             }
         } else if (mouse) {
-            mouse->moution(mouse, 0, 0, dz, RED_MOUSE_STATE_TO_LOCAL(mouse_press->buttons_state));
+            SpiceMouseInterface *sif;
+            sif = SPICE_CONTAINEROF(mouse->base.sif, SpiceMouseInterface, base);
+            sif->motion(mouse, 0, 0, dz,
+                        RED_MOUSE_STATE_TO_LOCAL(mouse_press->buttons_state));
         }
         break;
     }
@@ -2234,7 +2240,10 @@ static void inputs_handle_input(void *opaque, SpiceDataHeader *header)
                 tablet->buttons(tablet, RED_MOUSE_STATE_TO_LOCAL(mouse_release->buttons_state));
             }
         } else if (mouse) {
-            mouse->buttons(mouse, RED_MOUSE_STATE_TO_LOCAL(mouse_release->buttons_state));
+            SpiceMouseInterface *sif;
+            sif = SPICE_CONTAINEROF(mouse->base.sif, SpiceMouseInterface, base);
+            sif->buttons(mouse,
+                         RED_MOUSE_STATE_TO_LOCAL(mouse_release->buttons_state));
         }
         break;
     }
@@ -4041,18 +4050,19 @@ __visible__ int spice_server_add_interface(SpiceServer *s,
         keyboard = SPICE_CONTAINEROF(sin, SpiceKbdInstance, base);
         keyboard->st = spice_new0(SpiceKbdState, 1);
 
-    } else if (strcmp(interface->type, VD_INTERFACE_MOUSE) == 0) {
-        red_printf("VD_INTERFACE_MOUSE");
+    } else if (strcmp(interface->type, SPICE_INTERFACE_MOUSE) == 0) {
+        red_printf("SPICE_INTERFACE_MOUSE");
         if (mouse) {
             red_printf("already have mouse");
             return -1;
         }
-        if (interface->major_version != VD_INTERFACE_MOUSE_MAJOR ||
-            interface->minor_version < VD_INTERFACE_MOUSE_MINOR) {
+        if (interface->major_version != SPICE_INTERFACE_MOUSE_MAJOR ||
+            interface->minor_version < SPICE_INTERFACE_MOUSE_MINOR) {
             red_printf("unsuported mouse interface");
             return -1;
         }
-        mouse = (MouseInterface *)interface;
+        mouse = SPICE_CONTAINEROF(sin, SpiceMouseInstance, base);
+        mouse->st = spice_new0(SpiceMouseState, 1);
 
     } else if (strcmp(interface->type, VD_INTERFACE_MIGRATION) == 0) {
         red_printf("VD_INTERFACE_MIGRATION");
diff --git a/server/reds.h b/server/reds.h
index 2ba7398..68359ae 100644
--- a/server/reds.h
+++ b/server/reds.h
@@ -62,6 +62,10 @@ struct SpiceKbdState {
     int dummy;
 };
 
+struct SpiceMouseState {
+    int dummy;
+};
+
 void reds_desable_mm_timer();
 void reds_enable_mm_timer();
 void reds_update_mm_timer(uint32_t mm_time);
diff --git a/server/vd_interface.h b/server/vd_interface.h
index e2e5d26..1567b12 100644
--- a/server/vd_interface.h
+++ b/server/vd_interface.h
@@ -219,17 +219,24 @@ struct SpiceKbdInstance {
     SpiceKbdState     *st;
 };
 
-#define VD_INTERFACE_MOUSE "mouse"
-#define VD_INTERFACE_MOUSE_MAJOR 1
-#define VD_INTERFACE_MOUSE_MINOR 1
-typedef struct MouseInterface MouseInterface;
-
-struct MouseInterface {
+#define SPICE_INTERFACE_MOUSE "mouse"
+#define SPICE_INTERFACE_MOUSE_MAJOR 1
+#define SPICE_INTERFACE_MOUSE_MINOR 1
+typedef struct SpiceMouseInterface SpiceMouseInterface;
+typedef struct SpiceMouseInstance SpiceMouseInstance;
+typedef struct SpiceMouseState SpiceMouseState;
+
+struct SpiceMouseInterface {
     SpiceBaseInterface base;
 
-    void (*moution)(MouseInterface* mouse, int dx, int dy, int dz,
-                    uint32_t buttons_state);
-    void (*buttons)(MouseInterface* mouse, uint32_t buttons_state);
+    void (*motion)(SpiceMouseInstance *sin, int dx, int dy, int dz,
+                   uint32_t buttons_state);
+    void (*buttons)(SpiceMouseInstance *sin, uint32_t buttons_state);
+};
+
+struct SpiceMouseInstance {
+    SpiceBaseInstance base;
+    SpiceMouseState   *st;
 };
 
 #define VD_INTERFACE_TABLET "tablet"
commit 4461c749187a704a1d17b29695cf9f8a68cd3f80
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Mar 30 11:57:02 2010 +0200

    KeyboardInterface: redesign.
    
    This is the direction I wanna take with all interfaces:  Clearly
    separate interface (aka version information and function pointers)
    and state information.  SpiceKbdInterface defines the interface,
    SpiceKbdInstance maintains per-instance state information.  Keyboard
    hasn't much beside a pointer to SpiceKbdInterface, for other
    interfaces this very likely will be different.

diff --git a/server/reds.c b/server/reds.c
index 740de36..1eee21d 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -56,7 +56,7 @@
 
 SpiceCoreInterface *core = NULL;
 static MigrationInterface *mig = NULL;
-static KeyboardInterface *keyboard = NULL;
+static SpiceKbdInstance *keyboard = NULL;
 static MouseInterface *mouse = NULL;
 static TabletInterface *tablet = NULL;
 static VDIPortInterface *vdagent = NULL;
@@ -2102,12 +2102,26 @@ static void activate_modifiers_watch()
     core->timer_start(reds->key_modifiers_timer, KEY_MODIFIERS_TTL);
 }
 
-static void push_key_scan(uint8_t scan)
+static void kbd_push_scan(SpiceKbdInstance *sin, uint8_t scan)
 {
-    if (!keyboard) {
+    SpiceKbdInterface *sif;
+
+    if (!sin) {
         return;
     }
-    keyboard->push_scan_freg(keyboard, scan);
+    sif = SPICE_CONTAINEROF(sin->base.sif, SpiceKbdInterface, base);
+    sif->push_scan_freg(sin, scan);
+}
+
+static uint8_t kbd_get_leds(SpiceKbdInstance *sin)
+{
+    SpiceKbdInterface *sif;
+
+    if (!sin) {
+        return 0;
+    }
+    sif = SPICE_CONTAINEROF(sin->base.sif, SpiceKbdInterface, base);
+    return sif->get_leds(sin);
 }
 
 static void inputs_handle_input(void *opaque, SpiceDataHeader *header)
@@ -2128,7 +2142,7 @@ static void inputs_handle_input(void *opaque, SpiceDataHeader *header)
         uint8_t *now = (uint8_t *)&key_down->code;
         uint8_t *end = now + sizeof(key_down->code);
         for (; now < end && *now; now++) {
-            push_key_scan(*now);
+            kbd_push_scan(keyboard, *now);
         }
         break;
     }
@@ -2226,22 +2240,24 @@ static void inputs_handle_input(void *opaque, SpiceDataHeader *header)
     }
     case SPICE_MSGC_INPUTS_KEY_MODIFIERS: {
         SpiceMsgcKeyModifiers *modifiers = (SpiceMsgcKeyModifiers *)buf;
+        uint8_t leds;
+
         if (!keyboard) {
             break;
         }
-        uint8_t leds = keyboard->get_leds(keyboard);
+        leds = kbd_get_leds(keyboard);
         if ((modifiers->modifiers & SPICE_SCROLL_LOCK_MODIFIER) !=
                                                                 (leds & SPICE_SCROLL_LOCK_MODIFIER)) {
-            push_key_scan(SCROLL_LOCK_SCAN_CODE);
-            push_key_scan(SCROLL_LOCK_SCAN_CODE | 0x80);
+            kbd_push_scan(keyboard, SCROLL_LOCK_SCAN_CODE);
+            kbd_push_scan(keyboard, SCROLL_LOCK_SCAN_CODE | 0x80);
         }
         if ((modifiers->modifiers & SPICE_NUM_LOCK_MODIFIER) != (leds & SPICE_NUM_LOCK_MODIFIER)) {
-            push_key_scan(NUM_LOCK_SCAN_CODE);
-            push_key_scan(NUM_LOCK_SCAN_CODE | 0x80);
+            kbd_push_scan(keyboard, NUM_LOCK_SCAN_CODE);
+            kbd_push_scan(keyboard, NUM_LOCK_SCAN_CODE | 0x80);
         }
         if ((modifiers->modifiers & SPICE_CAPS_LOCK_MODIFIER) != (leds & SPICE_CAPS_LOCK_MODIFIER)) {
-            push_key_scan(CAPS_LOCK_SCAN_CODE);
-            push_key_scan(CAPS_LOCK_SCAN_CODE | 0x80);
+            kbd_push_scan(keyboard, CAPS_LOCK_SCAN_CODE);
+            kbd_push_scan(keyboard, CAPS_LOCK_SCAN_CODE | 0x80);
         }
         activate_modifiers_watch();
         break;
@@ -2266,12 +2282,12 @@ void reds_set_client_mouse_allowed(int is_client_mouse_allowed, int x_res, int y
 
 static void inputs_relase_keys(void)
 {
-    push_key_scan(0x2a | 0x80); //LSHIFT
-    push_key_scan(0x36 | 0x80); //RSHIFT
-    push_key_scan(0xe0); push_key_scan(0x1d | 0x80); //RCTRL
-    push_key_scan(0x1d | 0x80); //LCTRL
-    push_key_scan(0xe0); push_key_scan(0x38 | 0x80); //RALT
-    push_key_scan(0x38 | 0x80); //LALT
+    kbd_push_scan(keyboard, 0x2a | 0x80); //LSHIFT
+    kbd_push_scan(keyboard, 0x36 | 0x80); //RSHIFT
+    kbd_push_scan(keyboard, 0xe0); kbd_push_scan(keyboard, 0x1d | 0x80); //RCTRL
+    kbd_push_scan(keyboard, 0x1d | 0x80); //LCTRL
+    kbd_push_scan(keyboard, 0xe0); kbd_push_scan(keyboard, 0x38 | 0x80); //RALT
+    kbd_push_scan(keyboard, 0x38 | 0x80); //LALT
 }
 
 static void inputs_event(int fd, int event, void *data)
@@ -2393,7 +2409,7 @@ static void inputs_link(Channel *channel, RedsStreamContext *peer, int migration
     header.type = SPICE_MSG_INPUTS_INIT;
     header.size = sizeof(SpiceMsgInputsInit);
     header.sub_list = 0;
-    inputs_init.keyboard_modifiers = keyboard ? keyboard->get_leds(keyboard) : 0;
+    inputs_init.keyboard_modifiers = kbd_get_leds(keyboard);
     if (outgoing_write(inputs_state->peer, &inputs_state->out_handler, &header,
                        sizeof(SpiceDataHeader)) != OUTGOING_OK ||
         outgoing_write(inputs_state->peer, &inputs_state->out_handler, &inputs_init,
@@ -3938,7 +3954,7 @@ static void migrate_timout(void *opaque)
 
 static void key_modifiers_sender(void *opaque)
 {
-    reds_send_keyboard_modifiers(keyboard ? keyboard->get_leds(keyboard) : 0);
+    reds_send_keyboard_modifiers(kbd_get_leds(keyboard));
 }
 
 uint32_t reds_get_mm_time()
@@ -4011,23 +4027,19 @@ __visible__ int spice_server_add_interface(SpiceServer *s,
 
     ASSERT(reds == s);
 
-    if (strcmp(interface->type, VD_INTERFACE_KEYBOARD) == 0) {
-        red_printf("VD_INTERFACE_KEYBOARD");
+    if (strcmp(interface->type, SPICE_INTERFACE_KEYBOARD) == 0) {
+        red_printf("SPICE_INTERFACE_KEYBOARD");
         if (keyboard) {
             red_printf("already have keyboard");
             return -1;
         }
-        if (interface->major_version != VD_INTERFACE_KEYBOARD_MAJOR ||
-            interface->minor_version < VD_INTERFACE_KEYBOARD_MINOR) {
+        if (interface->major_version != SPICE_INTERFACE_KEYBOARD_MAJOR ||
+            interface->minor_version < SPICE_INTERFACE_KEYBOARD_MINOR) {
             red_printf("unsuported keyboard interface");
             return -1;
         }
-        keyboard = (KeyboardInterface *)interface;
-        if (keyboard->register_leds_notifier) {
-            if (!keyboard->register_leds_notifier(keyboard, reds_on_keyboard_leds_change, NULL)) {
-                red_error("register leds notifier failed");
-            }
-        }
+        keyboard = SPICE_CONTAINEROF(sin, SpiceKbdInstance, base);
+        keyboard->st = spice_new0(SpiceKbdState, 1);
 
     } else if (strcmp(interface->type, VD_INTERFACE_MOUSE) == 0) {
         red_printf("VD_INTERFACE_MOUSE");
@@ -4547,7 +4559,7 @@ __visible__ int spice_server_add_renderer(SpiceServer *s, const char *name)
     return 0;
 }
 
-__visible__ int spice_server_kbd_leds(SpiceBaseInstance *sin, int leds)
+__visible__ int spice_server_kbd_leds(SpiceKbdInstance *sin, int leds)
 {
     reds_on_keyboard_leds_change(NULL, leds);
     return 0;
diff --git a/server/reds.h b/server/reds.h
index 9a171f6..2ba7398 100644
--- a/server/reds.h
+++ b/server/reds.h
@@ -58,6 +58,10 @@ typedef struct Channel {
     void *data;
 } Channel;
 
+struct SpiceKbdState {
+    int dummy;
+};
+
 void reds_desable_mm_timer();
 void reds_enable_mm_timer();
 void reds_update_mm_timer(uint32_t mm_time);
diff --git a/server/spice.h b/server/spice.h
index caf2830..8a7764e 100644
--- a/server/spice.h
+++ b/server/spice.h
@@ -44,7 +44,7 @@ int spice_server_add_interface(SpiceServer *s,
                                SpiceBaseInstance *sin,
                                int id);
 int spice_server_remove_interface(SpiceBaseInstance *sin);
-int spice_server_kbd_leds(SpiceBaseInstance *sin, int leds);
+int spice_server_kbd_leds(SpiceKbdInstance *sin, int leds);
 
 typedef enum {
     SPICE_IMAGE_COMPRESS_INVALID  = 0,
diff --git a/server/vd_interface.h b/server/vd_interface.h
index abfe088..e2e5d26 100644
--- a/server/vd_interface.h
+++ b/server/vd_interface.h
@@ -200,20 +200,23 @@ struct QXLInterface {
     int (*flush_resources)(QXLInterface *qxl);
 };
 
-#define VD_INTERFACE_KEYBOARD "keyboard"
-#define VD_INTERFACE_KEYBOARD_MAJOR 1
-#define VD_INTERFACE_KEYBOARD_MINOR 1
-typedef struct KeyboardInterface KeyboardInterface;
-typedef void (*keyborad_leads_notifier_t)(void *opaque, uint8_t leds);
-
-struct KeyboardInterface {
+#define SPICE_INTERFACE_KEYBOARD "keyboard"
+#define SPICE_INTERFACE_KEYBOARD_MAJOR 1
+#define SPICE_INTERFACE_KEYBOARD_MINOR 1
+typedef struct SpiceKbdInterface SpiceKbdInterface;
+typedef struct SpiceKbdInstance SpiceKbdInstance;
+typedef struct SpiceKbdState SpiceKbdState;
+
+struct SpiceKbdInterface {
     SpiceBaseInterface base;
 
-    void (*push_scan_freg)(KeyboardInterface *keyboard, uint8_t frag);
-    uint8_t (*get_leds)(KeyboardInterface *keyboard);
-    VDObjectRef (*register_leds_notifier)(KeyboardInterface *keyboard,
-                                          keyborad_leads_notifier_t notifier, void *opaque);
-    void (*unregister_leds_notifayer)(KeyboardInterface *keyboard, VDObjectRef notifier);
+    void (*push_scan_freg)(SpiceKbdInstance *sin, uint8_t frag);
+    uint8_t (*get_leds)(SpiceKbdInstance *sin);
+};
+
+struct SpiceKbdInstance {
+    SpiceBaseInstance base;
+    SpiceKbdState     *st;
 };
 
 #define VD_INTERFACE_MOUSE "mouse"
commit 10e6d8b53cf89b9e7c58b0696f078d18af21827e
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Mar 30 11:28:50 2010 +0200

    s/CoreInterface/SpiceCoreInterface/

diff --git a/server/red_channel.c b/server/red_channel.c
index 3f46147..9f02822 100644
--- a/server/red_channel.c
+++ b/server/red_channel.c
@@ -228,7 +228,8 @@ static void red_channel_peer_on_out_msg_done(void *opaque)
     }
 }
 
-RedChannel *red_channel_create(int size, RedsStreamContext *peer, CoreInterface *core,
+RedChannel *red_channel_create(int size, RedsStreamContext *peer,
+                               SpiceCoreInterface *core,
                                int migrate, int handle_acks,
                                channel_configure_socket_proc config_socket,
                                channel_disconnect_proc disconnect,
diff --git a/server/red_channel.h b/server/red_channel.h
index e222f63..1fc92e5 100644
--- a/server/red_channel.h
+++ b/server/red_channel.h
@@ -101,7 +101,7 @@ typedef void (*channel_release_pipe_item_proc)(RedChannel *channel,
 
 struct RedChannel {
     RedsStreamContext *peer;
-    CoreInterface *core;
+    SpiceCoreInterface *core;
     int migrate;
     int handle_acks;
 
@@ -141,7 +141,8 @@ struct RedChannel {
 
 /* if one of the callbacks should cause disconnect, use red_channel_shutdown and don't
    explicitly destroy the channel */
-RedChannel *red_channel_create(int size, RedsStreamContext *peer, CoreInterface *core,
+RedChannel *red_channel_create(int size, RedsStreamContext *peer,
+                               SpiceCoreInterface *core,
                                int migrate, int handle_acks,
                                channel_configure_socket_proc config_socket,
                                channel_disconnect_proc disconnect,
diff --git a/server/red_tunnel_worker.c b/server/red_tunnel_worker.c
index cf1f317..d4da0b3 100644
--- a/server/red_tunnel_worker.c
+++ b/server/red_tunnel_worker.c
@@ -534,7 +534,7 @@ struct TunnelWorker {
     Channel channel_interface; // for reds
     TunnelChannel *channel;
 
-    CoreInterface *core_interface;
+    SpiceCoreInterface *core_interface;
     NetWireInterface *vlan_interface;
     RedSlirpNetworkInterface tunnel_interface;
     RedSlirpNetworkInterface null_interface;
@@ -970,7 +970,8 @@ static void tunnel_send_packet(void *opaque_tunnel, const uint8_t *pkt, int pkt_
     net_slirp_input(pkt, pkt_len);
 }
 
-void *red_tunnel_attach(CoreInterface *core_interface, NetWireInterface *vlan_interface)
+void *red_tunnel_attach(SpiceCoreInterface *core_interface,
+                        NetWireInterface *vlan_interface)
 {
     TunnelWorker *worker = spice_new0(TunnelWorker, 1);
 
diff --git a/server/red_tunnel_worker.h b/server/red_tunnel_worker.h
index 606c9dd..9f3a61c 100755
--- a/server/red_tunnel_worker.h
+++ b/server/red_tunnel_worker.h
@@ -24,6 +24,6 @@
 
 #include "vd_interface.h"
 
-void *red_tunnel_attach(CoreInterface *core_interface, NetWireInterface *vlan_interface);
+void *red_tunnel_attach(SpiceCoreInterface *core_interface, NetWireInterface *vlan_interface);
 
 #endif
diff --git a/server/reds.c b/server/reds.c
index b81e0b3..740de36 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -54,7 +54,7 @@
 #include "red_tunnel_worker.h"
 #endif
 
-CoreInterface *core = NULL;
+SpiceCoreInterface *core = NULL;
 static MigrationInterface *mig = NULL;
 static KeyboardInterface *keyboard = NULL;
 static MouseInterface *mouse = NULL;
@@ -4267,11 +4267,11 @@ static void init_vd_agent_resources()
 
 const char *version_string = VERSION;
 
-static void do_spice_init(CoreInterface *core_interface)
+static void do_spice_init(SpiceCoreInterface *core_interface)
 {
     red_printf("starting %s", version_string);
 
-    if (core_interface->base.major_version != VD_INTERFACE_CORE_MAJOR) {
+    if (core_interface->base.major_version != SPICE_INTERFACE_CORE_MAJOR) {
         red_error("bad core interface version");
     }
     core = core_interface;
@@ -4335,12 +4335,6 @@ static void do_spice_init(CoreInterface *core_interface)
     atexit(reds_exit);
 }
 
-__visible__ void spice_init(CoreInterface *core_interface)
-{
-    spice_server_new();
-    do_spice_init(core_interface);
-}
-
 /* new interface */
 __visible__ SpiceServer *spice_server_new(void)
 {
@@ -4351,7 +4345,7 @@ __visible__ SpiceServer *spice_server_new(void)
     return reds;
 }
 
-__visible__ int spice_server_init(SpiceServer *s, CoreInterface *core)
+__visible__ int spice_server_init(SpiceServer *s, SpiceCoreInterface *core)
 {
     ASSERT(reds == s);
     do_spice_init(core);
diff --git a/server/reds.h b/server/reds.h
index 60eef4a..9a171f6 100644
--- a/server/reds.h
+++ b/server/reds.h
@@ -67,7 +67,7 @@ void reds_set_client_mouse_allowed(int is_client_mouse_allowed,
 void reds_register_channel(Channel *channel);
 void reds_unregister_channel(Channel *channel);
 
-extern struct CoreInterface *core;
+extern struct SpiceCoreInterface *core;
 extern uint64_t bitrate_per_sec;
 
 #define IS_LOW_BANDWIDTH() (bitrate_per_sec < 10 * 1024 * 1024)
diff --git a/server/spice.h b/server/spice.h
index 5b768ef..caf2830 100644
--- a/server/spice.h
+++ b/server/spice.h
@@ -21,13 +21,10 @@
 #include <sys/socket.h>
 #include "vd_interface.h"
 
-/* old interface */
-void spice_init(CoreInterface *core);
-
 /* new interface */
 typedef struct RedsState SpiceServer;
 SpiceServer *spice_server_new(void);
-int spice_server_init(SpiceServer *s, CoreInterface *core);
+int spice_server_init(SpiceServer *s, SpiceCoreInterface *core);
 void spice_server_destroy(SpiceServer *s);
 
 #define SPICE_ADDR_FLAG_IPV4_ONLY (1 << 0)
diff --git a/server/vd_interface.h b/server/vd_interface.h
index 6b86dc8..abfe088 100644
--- a/server/vd_interface.h
+++ b/server/vd_interface.h
@@ -50,14 +50,10 @@ struct SpiceBaseInstance {
     SpiceBaseInterface *sif;
 };
 
-#define VD_INTERFACE_CORE "core"
-#define VD_INTERFACE_CORE_MAJOR 1
-#define VD_INTERFACE_CORE_MINOR 2
-typedef struct CoreInterface CoreInterface;
-typedef enum {
-    VD_INTERFACE_ADDING,
-    VD_INTERFACE_REMOVING,
-} SpiceBaseInterfaceChangeType;
+#define SPICE_INTERFACE_CORE "core"
+#define SPICE_INTERFACE_CORE_MAJOR 1
+#define SPICE_INTERFACE_CORE_MINOR 2
+typedef struct SpiceCoreInterface SpiceCoreInterface;
 
 typedef enum {
     VD_LOG_ERROR = 1,
@@ -65,9 +61,6 @@ typedef enum {
     VD_LOG_INFO,
 } LogLevel;
 
-typedef void (*vd_interface_change_notifier_t)(void *opaque, SpiceBaseInterface *interface,
-                                               SpiceBaseInterfaceChangeType change);
-
 #define SPICE_WATCH_EVENT_READ  (1 << 0)
 #define SPICE_WATCH_EVENT_WRITE (1 << 1)
 
@@ -77,7 +70,7 @@ typedef void (*SpiceWatchFunc)(int fd, int event, void *opaque);
 typedef struct SpiceTimer SpiceTimer;
 typedef void (*SpiceTimerFunc)(void *opaque);
 
-struct CoreInterface {
+struct SpiceCoreInterface {
     SpiceBaseInterface base;
 
     SpiceTimer *(*timer_add)(SpiceTimerFunc func, void *opaque);
commit 30c740201d1b111ca28e7881ddbcc91f259b8a11
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Mar 30 11:15:01 2010 +0200

    VDInterface: redesign.
    
    VDInterface has been renamed to SpiceBaseInterface. Dropped base_version
    element, shlib versioning should be used instead.  Dropped id element,
    it is passed to spice_server_add_interface() instead.  Now
    SpiceBaseInterface has static information only, multiple interface
    instances can share it.
    
    Added SpiceBaseInstance struct for maintaining per-instance state
    information.  Adapted spice_server_{add,remove}_interface() functions
    to the new world.

diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
index b3cf8cd..f7c6646 100644
--- a/server/red_dispatcher.c
+++ b/server/red_dispatcher.c
@@ -462,7 +462,7 @@ uint32_t red_dispatcher_qxl_ram_size()
     return qxl_info.qxl_ram_size;
 }
 
-RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface)
+RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface, int id)
 {
     RedDispatcher *dispatcher;
     int channels[2];
@@ -493,7 +493,7 @@ RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface)
     dispatcher = spice_new0(RedDispatcher, 1);
     dispatcher->channel = channels[0];
     init_data.qxl_interface = dispatcher->qxl_interface = qxl_interface;
-    init_data.id = qxl_interface->base.id;
+    init_data.id = id;
     init_data.channel = channels[1];
     init_data.pending = &dispatcher->pending;
     init_data.num_renderers = num_renderers;
@@ -548,7 +548,7 @@ RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface)
 
     reds_channel = spice_new0(Channel, 1);
     reds_channel->type = SPICE_CHANNEL_DISPLAY;
-    reds_channel->id = qxl_interface->base.id;
+    reds_channel->id = id;
     reds_channel->link = red_dispatcher_set_peer;
     reds_channel->shutdown = red_dispatcher_shutdown_peer;
     reds_channel->migrate = red_dispatcher_migrate;
@@ -557,7 +557,7 @@ RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface)
 
     cursor_channel = spice_new0(Channel, 1);
     cursor_channel->type = SPICE_CHANNEL_CURSOR;
-    cursor_channel->id = qxl_interface->base.id;
+    cursor_channel->id = id;
     cursor_channel->link = red_dispatcher_set_cursor_peer;
     cursor_channel->shutdown = red_dispatcher_shutdown_cursor_peer;
     cursor_channel->migrate = red_dispatcher_cursor_migrate;
diff --git a/server/red_dispatcher.h b/server/red_dispatcher.h
index df15104..b0bc040 100644
--- a/server/red_dispatcher.h
+++ b/server/red_dispatcher.h
@@ -19,7 +19,7 @@
 #define _H_RED_DISPATCHER
 
 
-struct RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface);
+struct RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface, int id);
 
 void red_dispatcher_set_mm_time(uint32_t);
 void red_dispatcher_on_ic_change();
diff --git a/server/reds.c b/server/reds.c
index e9bfeb0..b81e0b3 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -359,7 +359,6 @@ typedef struct PingItem {
     int size;
 } PingItem;
 
-
 #define ZERO_BUF_SIZE 4096
 
 static uint8_t zero_page[ZERO_BUF_SIZE] = {0};
@@ -4004,163 +4003,179 @@ static void attach_to_red_agent(VDIPortInterface *interface)
     reds_send_agent_connected();
 }
 
-static void interface_change_notifier(void *opaque, VDInterface *interface,
-                                      VDInterfaceChangeType change)
+__visible__ int spice_server_add_interface(SpiceServer *s,
+                                           SpiceBaseInstance *sin,
+                                           int id)
 {
-    if (interface->base_version != VM_INTERFACE_VERSION) {
-        red_printf("unsuported base interface version");
-        return;
-    }
-    switch (change) {
-    case VD_INTERFACE_ADDING:
-        if (strcmp(interface->type, VD_INTERFACE_KEYBOARD) == 0) {
-            red_printf("VD_INTERFACE_KEYBOARD");
-            if (keyboard) {
-                red_printf("already have keyboard");
-                return;
-            }
-            if (interface->major_version != VD_INTERFACE_KEYBOARD_MAJOR ||
-                interface->minor_version < VD_INTERFACE_KEYBOARD_MINOR) {
-                red_printf("unsuported keyboard interface");
-                return;
-            }
-            keyboard = (KeyboardInterface *)interface;
-            if (keyboard->register_leds_notifier) {
-                if (!keyboard->register_leds_notifier(keyboard, reds_on_keyboard_leds_change, NULL)) {
-                    red_error("register leds notifier failed");
-                }
-            }
-        } else if (strcmp(interface->type, VD_INTERFACE_MOUSE) == 0) {
-            red_printf("VD_INTERFACE_MOUSE");
-            if (mouse) {
-                red_printf("already have mouse");
-                return;
-            }
-            if (interface->major_version != VD_INTERFACE_MOUSE_MAJOR ||
-                interface->minor_version < VD_INTERFACE_MOUSE_MINOR) {
-                red_printf("unsuported mouse interface");
-                return;
-            }
-            mouse = (MouseInterface *)interface;
-        } else if (strcmp(interface->type, VD_INTERFACE_MIGRATION) == 0) {
-            red_printf("VD_INTERFACE_MIGRATION");
-            if (mig) {
-                red_printf("already have migration");
-                return;
-            }
-            if (interface->major_version != VD_INTERFACE_MIGRATION_MAJOR ||
-                interface->minor_version < VD_INTERFACE_MIGRATION_MINOR) {
-                red_printf("unsuported migration interface");
-                return;
-            }
-            mig = (MigrationInterface *)interface;
-            reds->mig_notifier = mig->register_notifiers(mig, MIGRATION_NOTIFY_SPICE_KEY,
-                                                         reds_mig_started, reds_mig_finished,
-                                                         reds_mig_recv, NULL);
-            if (reds->mig_notifier == INVALID_VD_OBJECT_REF) {
-                red_error("migration register failed");
-            }
-        } else if (strcmp(interface->type, VD_INTERFACE_QXL) == 0) {
-            QXLInterface *qxl_interface;
+    SpiceBaseInterface *interface = sin->sif;
 
-            red_printf("VD_INTERFACE_QXL");
-            if (interface->major_version != VD_INTERFACE_QXL_MAJOR ||
-                interface->minor_version < VD_INTERFACE_QXL_MINOR) {
-                red_printf("unsuported qxl interface");
-                return;
-            }
-            qxl_interface = (QXLInterface *)interface;
-            red_dispatcher_init(qxl_interface);
-        } else if (strcmp(interface->type, VD_INTERFACE_TABLET) == 0) {
-            red_printf("VD_INTERFACE_TABLET");
-            if (tablet) {
-                red_printf("already have tablet");
-                return;
-            }
-            if (interface->major_version != VD_INTERFACE_TABLET_MAJOR ||
-                interface->minor_version < VD_INTERFACE_TABLET_MINOR) {
-                red_printf("unsuported tablet interface");
-                return;
-            }
-            tablet = (TabletInterface *)interface;
-            reds_update_mouse_mode();
-            if (reds->is_client_mouse_allowed) {
-                tablet->set_logical_size(tablet, reds->monitor_mode.x_res,
-                                         reds->monitor_mode.y_res);
-            }
-        } else if (strcmp(interface->type, VD_INTERFACE_PLAYBACK) == 0) {
-            red_printf("VD_INTERFACE_PLAYBACK");
-            if (interface->major_version != VD_INTERFACE_PLAYBACK_MAJOR ||
-                interface->minor_version < VD_INTERFACE_PLAYBACK_MINOR) {
-                red_printf("unsuported playback interface");
-                return;
-            }
-            snd_attach_playback((PlaybackInterface *)interface);
-        } else if (strcmp(interface->type, VD_INTERFACE_RECORD) == 0) {
-            red_printf("VD_INTERFACE_RECORD");
-            if (interface->major_version != VD_INTERFACE_RECORD_MAJOR ||
-                interface->minor_version < VD_INTERFACE_RECORD_MINOR) {
-                red_printf("unsuported record interface");
-                return;
-            }
-            snd_attach_record((RecordInterface *)interface);
-        } else if (strcmp(interface->type, VD_INTERFACE_VDI_PORT) == 0) {
-            red_printf("VD_INTERFACE_VDI_PORT");
-            if (vdagent) {
-                red_printf("vdi port already attached");
-                return;
-            }
-            if (interface->major_version != VD_INTERFACE_VDI_PORT_MAJOR ||
-                interface->minor_version < VD_INTERFACE_VDI_PORT_MINOR) {
-                red_printf("unsuported vdi port interface");
-                return;
+    ASSERT(reds == s);
+
+    if (strcmp(interface->type, VD_INTERFACE_KEYBOARD) == 0) {
+        red_printf("VD_INTERFACE_KEYBOARD");
+        if (keyboard) {
+            red_printf("already have keyboard");
+            return -1;
+        }
+        if (interface->major_version != VD_INTERFACE_KEYBOARD_MAJOR ||
+            interface->minor_version < VD_INTERFACE_KEYBOARD_MINOR) {
+            red_printf("unsuported keyboard interface");
+            return -1;
+        }
+        keyboard = (KeyboardInterface *)interface;
+        if (keyboard->register_leds_notifier) {
+            if (!keyboard->register_leds_notifier(keyboard, reds_on_keyboard_leds_change, NULL)) {
+                red_error("register leds notifier failed");
             }
-            attach_to_red_agent((VDIPortInterface *)interface);
-        } else if (strcmp(interface->type, VD_INTERFACE_NET_WIRE) == 0) {
+        }
+
+    } else if (strcmp(interface->type, VD_INTERFACE_MOUSE) == 0) {
+        red_printf("VD_INTERFACE_MOUSE");
+        if (mouse) {
+            red_printf("already have mouse");
+            return -1;
+        }
+        if (interface->major_version != VD_INTERFACE_MOUSE_MAJOR ||
+            interface->minor_version < VD_INTERFACE_MOUSE_MINOR) {
+            red_printf("unsuported mouse interface");
+            return -1;
+        }
+        mouse = (MouseInterface *)interface;
+
+    } else if (strcmp(interface->type, VD_INTERFACE_MIGRATION) == 0) {
+        red_printf("VD_INTERFACE_MIGRATION");
+        if (mig) {
+            red_printf("already have migration");
+            return -1;
+        }
+        if (interface->major_version != VD_INTERFACE_MIGRATION_MAJOR ||
+            interface->minor_version < VD_INTERFACE_MIGRATION_MINOR) {
+            red_printf("unsuported migration interface");
+            return -1;
+        }
+        mig = (MigrationInterface *)interface;
+        reds->mig_notifier = mig->register_notifiers(mig, MIGRATION_NOTIFY_SPICE_KEY,
+                                                     reds_mig_started, reds_mig_finished,
+                                                     reds_mig_recv, NULL);
+        if (reds->mig_notifier == INVALID_VD_OBJECT_REF) {
+            red_error("migration register failed");
+        }
+
+    } else if (strcmp(interface->type, VD_INTERFACE_QXL) == 0) {
+        QXLInterface *qxl_interface;
+
+        red_printf("VD_INTERFACE_QXL");
+        if (interface->major_version != VD_INTERFACE_QXL_MAJOR ||
+            interface->minor_version < VD_INTERFACE_QXL_MINOR) {
+            red_printf("unsuported qxl interface");
+            return -1;
+        }
+        qxl_interface = (QXLInterface *)interface;
+        red_dispatcher_init(qxl_interface, id);
+
+    } else if (strcmp(interface->type, VD_INTERFACE_TABLET) == 0) {
+        red_printf("VD_INTERFACE_TABLET");
+        if (tablet) {
+            red_printf("already have tablet");
+            return -1;
+        }
+        if (interface->major_version != VD_INTERFACE_TABLET_MAJOR ||
+            interface->minor_version < VD_INTERFACE_TABLET_MINOR) {
+            red_printf("unsuported tablet interface");
+            return -1;
+        }
+        tablet = (TabletInterface *)interface;
+        reds_update_mouse_mode();
+        if (reds->is_client_mouse_allowed) {
+            tablet->set_logical_size(tablet, reds->monitor_mode.x_res,
+                                     reds->monitor_mode.y_res);
+        }
+
+    } else if (strcmp(interface->type, VD_INTERFACE_PLAYBACK) == 0) {
+        red_printf("VD_INTERFACE_PLAYBACK");
+        if (interface->major_version != VD_INTERFACE_PLAYBACK_MAJOR ||
+            interface->minor_version < VD_INTERFACE_PLAYBACK_MINOR) {
+            red_printf("unsuported playback interface");
+            return -1;
+        }
+        snd_attach_playback((PlaybackInterface *)interface);
+
+    } else if (strcmp(interface->type, VD_INTERFACE_RECORD) == 0) {
+        red_printf("VD_INTERFACE_RECORD");
+        if (interface->major_version != VD_INTERFACE_RECORD_MAJOR ||
+            interface->minor_version < VD_INTERFACE_RECORD_MINOR) {
+            red_printf("unsuported record interface");
+            return -1;
+        }
+        snd_attach_record((RecordInterface *)interface);
+
+    } else if (strcmp(interface->type, VD_INTERFACE_VDI_PORT) == 0) {
+        red_printf("VD_INTERFACE_VDI_PORT");
+        if (vdagent) {
+            red_printf("vdi port already attached");
+            return -1;
+        }
+        if (interface->major_version != VD_INTERFACE_VDI_PORT_MAJOR ||
+            interface->minor_version < VD_INTERFACE_VDI_PORT_MINOR) {
+            red_printf("unsuported vdi port interface");
+            return -1;
+        }
+        attach_to_red_agent((VDIPortInterface *)interface);
+
+    } else if (strcmp(interface->type, VD_INTERFACE_NET_WIRE) == 0) {
 #ifdef HAVE_SLIRP
-            NetWireInterface * net_wire = (NetWireInterface *)interface;
-            red_printf("VD_INTERFACE_NET_WIRE");
-            if (red_tunnel) {
-                red_printf("net wire already attached");
-                return;
-            }
-            if (interface->major_version != VD_INTERFACE_NET_WIRE_MAJOR ||
-                interface->minor_version < VD_INTERFACE_NET_WIRE_MINOR) {
-                red_printf("unsuported net wire interface");
-                return;
-            }
-            red_tunnel = red_tunnel_attach(core, net_wire);
+        NetWireInterface * net_wire = (NetWireInterface *)interface;
+        red_printf("VD_INTERFACE_NET_WIRE");
+        if (red_tunnel) {
+            red_printf("net wire already attached");
+            return -1;
+        }
+        if (interface->major_version != VD_INTERFACE_NET_WIRE_MAJOR ||
+            interface->minor_version < VD_INTERFACE_NET_WIRE_MINOR) {
+            red_printf("unsuported net wire interface");
+            return -1;
+        }
+        red_tunnel = red_tunnel_attach(core, net_wire);
 #else
-            red_printf("unsupported net wire interface");
+        red_printf("unsupported net wire interface");
+        return -1;
 #endif
+    }
+
+    return 0;
+}
+
+__visible__ int spice_server_remove_interface(SpiceBaseInstance *sin)
+{
+    SpiceBaseInterface *interface = sin->sif;
+
+    if (strcmp(interface->type, VD_INTERFACE_TABLET) == 0) {
+        red_printf("remove VD_INTERFACE_TABLET");
+        if (interface == (SpiceBaseInterface *)tablet) {
+            tablet = NULL;
+            reds_update_mouse_mode();
         }
-        break;
-    case VD_INTERFACE_REMOVING:
-        if (strcmp(interface->type, VD_INTERFACE_TABLET) == 0) {
-            red_printf("remove VD_INTERFACE_TABLET");
-            if (interface == (VDInterface *)tablet) {
-                tablet = NULL;
-                reds_update_mouse_mode();
-            }
-            break;
-        } else if (strcmp(interface->type, VD_INTERFACE_PLAYBACK) == 0) {
-            red_printf("remove VD_INTERFACE_PLAYBACK");
-            snd_detach_playback((PlaybackInterface *)interface);
-            break;
-        } else if (strcmp(interface->type, VD_INTERFACE_RECORD) == 0) {
-            red_printf("remove VD_INTERFACE_RECORD");
-            snd_detach_record((RecordInterface *)interface);
-            break;
-        } else if (strcmp(interface->type, VD_INTERFACE_VDI_PORT) == 0) {
-            red_printf("remove VD_INTERFACE_VDI_PORT");
-            if (interface == (VDInterface *)vdagent) {
-                reds_agent_remove();
-            }
-            break;
+
+    } else if (strcmp(interface->type, VD_INTERFACE_PLAYBACK) == 0) {
+        red_printf("remove VD_INTERFACE_PLAYBACK");
+        snd_detach_playback((PlaybackInterface *)interface);
+
+    } else if (strcmp(interface->type, VD_INTERFACE_RECORD) == 0) {
+        red_printf("remove VD_INTERFACE_RECORD");
+        snd_detach_record((RecordInterface *)interface);
+
+    } else if (strcmp(interface->type, VD_INTERFACE_VDI_PORT) == 0) {
+        red_printf("remove VD_INTERFACE_VDI_PORT");
+        if (interface == (SpiceBaseInterface *)vdagent) {
+            reds_agent_remove();
         }
+
+    } else {
         red_error("VD_INTERFACE_REMOVING unsupported");
-        break;
+        return -1;
     }
+
+    return 0;
 }
 
 static void free_external_agent_buff(VDIPortBuf *in_buf)
@@ -4256,10 +4271,6 @@ static void do_spice_init(CoreInterface *core_interface)
 {
     red_printf("starting %s", version_string);
 
-    if (core_interface->base.base_version != VM_INTERFACE_VERSION) {
-        red_error("bad base interface version");
-    }
-
     if (core_interface->base.major_version != VD_INTERFACE_CORE_MAJOR) {
         red_error("bad core interface version");
     }
@@ -4542,23 +4553,8 @@ __visible__ int spice_server_add_renderer(SpiceServer *s, const char *name)
     return 0;
 }
 
-__visible__ int spice_server_add_interface(SpiceServer *s, VDInterface *interface)
+__visible__ int spice_server_kbd_leds(SpiceBaseInstance *sin, int leds)
 {
-    ASSERT(reds == s);
-    interface_change_notifier(NULL, interface, VD_INTERFACE_ADDING);
-    return 0;
-}
-
-__visible__ int spice_server_remove_interface(SpiceServer *s, VDInterface *interface)
-{
-    ASSERT(reds == s);
-    interface_change_notifier(NULL, interface, VD_INTERFACE_REMOVING);
-    return 0;
-}
-
-__visible__ int spice_server_kbd_leds(SpiceServer *s, KeyboardInterface *kbd, int leds)
-{
-    ASSERT(reds == s);
     reds_on_keyboard_leds_change(NULL, leds);
     return 0;
 }
diff --git a/server/snd_worker.c b/server/snd_worker.c
index d5f5f37..afffb00 100644
--- a/server/snd_worker.c
+++ b/server/snd_worker.c
@@ -142,7 +142,7 @@ typedef struct PlaybackChannel {
 
 struct SndWorker {
     Channel base;
-    VDInterface *interface;
+    SpiceBaseInterface *interface;
     SndChannel *connection;
     SndWorker *next;
 };
@@ -1192,7 +1192,7 @@ static void remove_worker(SndWorker *worker)
     red_printf("not found");
 }
 
-static SndWorker *find_worker(VDInterface *interface)
+static SndWorker *find_worker(SpiceBaseInterface *interface)
 {
     SndWorker *worker = workers;
     while (worker) {
@@ -1242,7 +1242,7 @@ void snd_attach_record(RecordInterface *interface)
     reds_register_channel(&record_worker->base);
 }
 
-static void snd_detach_common(VDInterface *interface)
+static void snd_detach_common(SpiceBaseInterface *interface)
 {
     SndWorker *worker = find_worker(interface);
 
diff --git a/server/spice.h b/server/spice.h
index 094caae..5b768ef 100644
--- a/server/spice.h
+++ b/server/spice.h
@@ -43,9 +43,11 @@ int spice_server_set_tls(SpiceServer *s, int port,
                          const char *private_key_file, const char *key_passwd,
                          const char *dh_key_file, const char *ciphersuite);
 
-int spice_server_add_interface(SpiceServer *s, VDInterface *interface);
-int spice_server_remove_interface(SpiceServer *s, VDInterface *interface);
-int spice_server_kbd_leds(SpiceServer *s, KeyboardInterface *kbd, int leds);
+int spice_server_add_interface(SpiceServer *s,
+                               SpiceBaseInstance *sin,
+                               int id);
+int spice_server_remove_interface(SpiceBaseInstance *sin);
+int spice_server_kbd_leds(SpiceBaseInstance *sin, int leds);
 
 typedef enum {
     SPICE_IMAGE_COMPRESS_INVALID  = 0,
diff --git a/server/vd_interface.h b/server/vd_interface.h
index 891ef52..6b86dc8 100644
--- a/server/vd_interface.h
+++ b/server/vd_interface.h
@@ -36,17 +36,18 @@
 #define VM_INTERFACE_VERSION 1
 typedef unsigned long VDObjectRef;
 #define INVALID_VD_OBJECT_REF 0
-typedef struct VDInterface VDInterface;
 
-struct VDInterface {
-    uint32_t base_version;
+typedef struct SpiceBaseInterface SpiceBaseInterface;
+typedef struct SpiceBaseInstance SpiceBaseInstance;
+
+struct SpiceBaseInterface {
     const char *type;
-    unsigned int id;
     const char *description;
-    //todo: swap minor major order on VM_INTERFACE_VERSION change
-    //      (here and in spacific interfaces)
-    uint32_t minor_version;
     uint32_t major_version;
+    uint32_t minor_version;
+};
+struct SpiceBaseInstance {
+    SpiceBaseInterface *sif;
 };
 
 #define VD_INTERFACE_CORE "core"
@@ -56,7 +57,7 @@ typedef struct CoreInterface CoreInterface;
 typedef enum {
     VD_INTERFACE_ADDING,
     VD_INTERFACE_REMOVING,
-} VDInterfaceChangeType;
+} SpiceBaseInterfaceChangeType;
 
 typedef enum {
     VD_LOG_ERROR = 1,
@@ -64,8 +65,8 @@ typedef enum {
     VD_LOG_INFO,
 } LogLevel;
 
-typedef void (*vd_interface_change_notifier_t)(void *opaque, VDInterface *interface,
-                                               VDInterfaceChangeType change);
+typedef void (*vd_interface_change_notifier_t)(void *opaque, SpiceBaseInterface *interface,
+                                               SpiceBaseInterfaceChangeType change);
 
 #define SPICE_WATCH_EVENT_READ  (1 << 0)
 #define SPICE_WATCH_EVENT_WRITE (1 << 1)
@@ -77,7 +78,7 @@ typedef struct SpiceTimer SpiceTimer;
 typedef void (*SpiceTimerFunc)(void *opaque);
 
 struct CoreInterface {
-    VDInterface base;
+    SpiceBaseInterface base;
 
     SpiceTimer *(*timer_add)(SpiceTimerFunc func, void *opaque);
     void (*timer_start)(SpiceTimer *timer, uint32_t ms);
@@ -183,7 +184,7 @@ struct QXLDevSurfaceCreate {
 struct SpiceRect;
 
 struct QXLInterface {
-    VDInterface base;
+    SpiceBaseInterface base;
 
     uint16_t pci_vendor;
     uint16_t pci_id;
@@ -213,7 +214,7 @@ typedef struct KeyboardInterface KeyboardInterface;
 typedef void (*keyborad_leads_notifier_t)(void *opaque, uint8_t leds);
 
 struct KeyboardInterface {
-    VDInterface base;
+    SpiceBaseInterface base;
 
     void (*push_scan_freg)(KeyboardInterface *keyboard, uint8_t frag);
     uint8_t (*get_leds)(KeyboardInterface *keyboard);
@@ -228,7 +229,7 @@ struct KeyboardInterface {
 typedef struct MouseInterface MouseInterface;
 
 struct MouseInterface {
-    VDInterface base;
+    SpiceBaseInterface base;
 
     void (*moution)(MouseInterface* mouse, int dx, int dy, int dz,
                     uint32_t buttons_state);
@@ -241,7 +242,7 @@ struct MouseInterface {
 typedef struct TabletInterface TabletInterface;
 
 struct TabletInterface {
-    VDInterface base;
+    SpiceBaseInterface base;
 
     void (*set_logical_size)(TabletInterface* tablet, int width, int height);
     void (*position)(TabletInterface* tablet, int x, int y, uint32_t buttons_state);
@@ -258,7 +259,7 @@ typedef void (*migration_notify_finished_t)(void *opaque, int completed);
 typedef void (*migration_notify_recv_t)(void *opaque, int fd);
 
 struct MigrationInterface {
-    VDInterface base;
+    SpiceBaseInterface base;
 
     VDObjectRef (*register_notifiers)(MigrationInterface* mig, const char *key,
                                       migration_notify_started_t,
@@ -317,7 +318,7 @@ struct PlaybackPlug {
 };
 
 struct PlaybackInterface {
-    VDInterface base;
+    SpiceBaseInterface base;
 
     VDObjectRef (*plug)(PlaybackInterface *playback, PlaybackPlug* plug, int *enable);
     void (*unplug)(PlaybackInterface *playback, VDObjectRef);
@@ -343,7 +344,7 @@ struct RecordPlug {
 };
 
 struct RecordInterface {
-    VDInterface base;
+    SpiceBaseInterface base;
 
     VDObjectRef (*plug)(RecordInterface *recorder, RecordPlug* plug, int *enable);
     void (*unplug)(RecordInterface *recorder, VDObjectRef);
@@ -362,7 +363,7 @@ struct VDIPortPlug {
 };
 
 struct VDIPortInterface {
-    VDInterface base;
+    SpiceBaseInterface base;
 
     VDObjectRef (*plug)(VDIPortInterface *port, VDIPortPlug* plug);
     void (*unplug)(VDIPortInterface *port, VDObjectRef plug);
@@ -378,7 +379,7 @@ typedef struct NetWireInterface NetWireInterface;
 typedef void (*net_wire_packet_route_proc_t)(void *opaque, const uint8_t *pkt, int pkt_len);
 
 struct NetWireInterface {
-    VDInterface base;
+    SpiceBaseInterface base;
 
     struct in_addr (*get_ip)(NetWireInterface *vlan);
     int (*can_send_packet)(NetWireInterface *vlan);
commit 455cae7c74048da24e816aa3e00a3b62257f687d
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Mar 29 17:47:31 2010 +0200

    shlib major

diff --git a/configure.ac b/configure.ac
index 94cd65f..0958b6d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -26,7 +26,7 @@ AC_PROG_LIBTOOL
 AM_PROG_CC_C_O
 AC_C_BIGENDIAN
 
-SPICE_LT_VERSION=m4_format("%d:%d:%d", SPICE_MAJOR, SPICE_MINOR, SPICE_MICRO)
+SPICE_LT_VERSION=m4_format("%d:%d:%d", 1, 0, 0)
 AC_SUBST(SPICE_LT_VERSION)
 
 # Check for the CPU we are using
commit a97875bc3fb3e1c794139508370df9083cd144c3
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Mar 29 15:59:26 2010 +0200

    minor timer interface cleanups.
    
    Make the timer interface largely look like the watch interface.
    Simliar naming convention for the functions (timer_*) and a
    opaque SpiceTimer type.

diff --git a/server/red_tunnel_worker.c b/server/red_tunnel_worker.c
index 751a339..cf1f317 100644
--- a/server/red_tunnel_worker.c
+++ b/server/red_tunnel_worker.c
@@ -3311,8 +3311,7 @@ static UserTimer *create_timer(SlirpUsrNetworkInterface *usr_interface,
 
     worker = ((RedSlirpNetworkInterface *)usr_interface)->worker;
 
-    return (void *)worker->core_interface->create_timer(worker->core_interface,
-                                                        proc, opaque);
+    return (void *)worker->core_interface->timer_add(proc, opaque);
 }
 
 static void arm_timer(SlirpUsrNetworkInterface *usr_interface, UserTimer *timer, uint32_t ms)
@@ -3333,7 +3332,7 @@ static void arm_timer(SlirpUsrNetworkInterface *usr_interface, UserTimer *timer,
         return;
     }
 
-    worker->core_interface->arm_timer(worker->core_interface, (VDObjectRef)timer, ms);
+    worker->core_interface->timer_start((SpiceTimer*)timer, ms);
 }
 
 /***********************************************
diff --git a/server/reds.c b/server/reds.c
index ff90f5d..e9bfeb0 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -267,9 +267,9 @@ typedef struct RedsState {
     int is_client_mouse_allowed;
     int dispatcher_allows_client_mouse;
     MonitorMode monitor_mode;
-    VDObjectRef mig_timer;
-    VDObjectRef key_modifiers_timer;
-    VDObjectRef mm_timer;
+    SpiceTimer *mig_timer;
+    SpiceTimer *key_modifiers_timer;
+    SpiceTimer *mm_timer;
 
     TicketAuthentication taTicket;
     SSL_CTX *ctx;
@@ -279,7 +279,7 @@ typedef struct RedsState {
     SpiceStat *stat;
     pthread_mutex_t stat_lock;
     RedsStatValue roundtrip_stat;
-    VDObjectRef ping_timer;
+    SpiceTimer *ping_timer;
     int ping_interval;
 #endif
     uint32_t ping_id;
@@ -686,7 +686,7 @@ static void reds_mig_cleanup()
         reds->mig_inprogress = FALSE;
         reds->mig_wait_connect = FALSE;
         reds->mig_wait_disconnect = FALSE;
-        core->disarm_timer(core, reds->mig_timer);
+        core->timer_cancel(reds->mig_timer);
         mig->notifier_done(mig, reds->mig_notifier);
     }
 }
@@ -1034,9 +1034,9 @@ static void do_ping_client(const char *opt, int has_interval, int interval)
         if (has_interval && interval > 0) {
             reds->ping_interval = interval * 1000;
         }
-        core->arm_timer(core, reds->ping_timer, reds->ping_interval);
+        core->timer_start(reds->ping_timer, reds->ping_interval);
     } else if (!strcmp(opt, "off")) {
-        core->disarm_timer(core, reds->ping_timer);
+        core->timer_cancel(reds->ping_timer);
     } else {
         return;
     }
@@ -1046,11 +1046,11 @@ static void ping_timer_cb()
 {
     if (!reds->peer) {
         red_printf("not connected to peer, ping off");
-        core->disarm_timer(core, reds->ping_timer);
+        core->timer_cancel(reds->ping_timer);
         return;
     }
     do_ping_client(NULL, 0, 0);
-    core->arm_timer(core, reds->ping_timer, reds->ping_interval);
+    core->timer_start(reds->ping_timer, reds->ping_interval);
 }
 
 #endif
@@ -2100,7 +2100,7 @@ static void reds_handle_main_link(RedLinkInfo *link)
 
 static void activate_modifiers_watch()
 {
-    core->arm_timer(core, reds->key_modifiers_timer, KEY_MODIFIERS_TTL);
+    core->timer_start(reds->key_modifiers_timer, KEY_MODIFIERS_TTL);
 }
 
 static void push_key_scan(uint8_t scan)
@@ -3394,7 +3394,7 @@ static void reds_mig_continue(RedsMigSpice *s)
     free(s->local_args);
     free(s);
     reds->mig_wait_connect = TRUE;
-    core->arm_timer(core, reds->mig_timer, MIGRATE_TIMEOUT);
+    core->timer_start(reds->mig_timer, MIGRATE_TIMEOUT);
 }
 
 static void reds_mig_receive_ack(RedsMigSpice *s)
@@ -3690,7 +3690,7 @@ static void reds_mig_finished(void *opaque, int completed)
         SpiceMsgMigrate *migrate;
 
         reds->mig_wait_disconnect = TRUE;
-        core->arm_timer(core, reds->mig_timer, MIGRATE_TIMEOUT);
+        core->timer_start(reds->mig_timer, MIGRATE_TIMEOUT);
 
         item = new_simple_out_item(SPICE_MSG_MIGRATE, sizeof(SpiceMsgMigrate));
         migrate = (SpiceMsgMigrate *)item->data;
@@ -3959,7 +3959,7 @@ void reds_enable_mm_timer()
     SpiceMsgMainMultiMediaTime *time_mes;
     SimpleOutItem *item;
 
-    core->arm_timer(core, reds->mm_timer, MM_TIMER_GRANULARITY_MS);
+    core->timer_start(reds->mm_timer, MM_TIMER_GRANULARITY_MS);
     if (!reds->peer) {
         return;
     }
@@ -3976,13 +3976,13 @@ void reds_enable_mm_timer()
 
 void reds_desable_mm_timer()
 {
-    core->disarm_timer(core, reds->mm_timer);
+    core->timer_cancel(reds->mm_timer);
 }
 
 static void mm_timer_proc(void *opaque)
 {
     red_dispatcher_set_mm_time(reds_get_mm_time());
-    core->arm_timer(core, reds->mm_timer, MM_TIMER_GRANULARITY_MS);
+    core->timer_start(reds->mm_timer, MM_TIMER_GRANULARITY_MS);
 }
 
 static void attach_to_red_agent(VDIPortInterface *interface)
@@ -4273,10 +4273,10 @@ static void do_spice_init(CoreInterface *core_interface)
 
     init_vd_agent_resources();
 
-    if (!(reds->mig_timer = core->create_timer(core, migrate_timout, NULL))) {
+    if (!(reds->mig_timer = core->timer_add(migrate_timout, NULL))) {
         red_error("migration timer create failed");
     }
-    if (!(reds->key_modifiers_timer = core->create_timer(core, key_modifiers_sender, NULL))) {
+    if (!(reds->key_modifiers_timer = core->timer_add(key_modifiers_sender, NULL))) {
         red_error("key modifiers timer create failed");
     }
 
@@ -4303,16 +4303,16 @@ static void do_spice_init(CoreInterface *core_interface)
     if (pthread_mutex_init(&reds->stat_lock, NULL)) {
         red_error("mutex init failed");
     }
-    if (!(reds->ping_timer = core->create_timer(core, ping_timer_cb, NULL))) {
+    if (!(reds->ping_timer = core->timer_add(ping_timer_cb, NULL))) {
         red_error("ping timer create failed");
     }
     reds->ping_interval = PING_INTERVAL;
 #endif
 
-    if (!(reds->mm_timer = core->create_timer(core, mm_timer_proc, NULL))) {
+    if (!(reds->mm_timer = core->timer_add(mm_timer_proc, NULL))) {
         red_error("mm timer create failed");
     }
-    core->arm_timer(core, reds->mm_timer, MM_TIMER_GRANULARITY_MS);
+    core->timer_start(reds->mm_timer, MM_TIMER_GRANULARITY_MS);
 
     reds_init_net();
     if (reds->secure_listen_socket != -1) {
diff --git a/server/vd_interface.h b/server/vd_interface.h
index 2bb3bcc..891ef52 100644
--- a/server/vd_interface.h
+++ b/server/vd_interface.h
@@ -66,7 +66,6 @@ typedef enum {
 
 typedef void (*vd_interface_change_notifier_t)(void *opaque, VDInterface *interface,
                                                VDInterfaceChangeType change);
-typedef void (*timer_callback_t)(void *opaque);
 
 #define SPICE_WATCH_EVENT_READ  (1 << 0)
 #define SPICE_WATCH_EVENT_WRITE (1 << 1)
@@ -74,13 +73,16 @@ typedef void (*timer_callback_t)(void *opaque);
 typedef struct SpiceWatch SpiceWatch;
 typedef void (*SpiceWatchFunc)(int fd, int event, void *opaque);
 
+typedef struct SpiceTimer SpiceTimer;
+typedef void (*SpiceTimerFunc)(void *opaque);
+
 struct CoreInterface {
     VDInterface base;
 
-    VDObjectRef (*create_timer)(CoreInterface *core, timer_callback_t, void *opaue);
-    void (*arm_timer)(CoreInterface *core, VDObjectRef timer, uint32_t ms);
-    void (*disarm_timer)(CoreInterface *core, VDObjectRef timer);
-    void (*destroy_timer)(CoreInterface *core, VDObjectRef timer);
+    SpiceTimer *(*timer_add)(SpiceTimerFunc func, void *opaque);
+    void (*timer_start)(SpiceTimer *timer, uint32_t ms);
+    void (*timer_cancel)(SpiceTimer *timer);
+    void (*timer_remove)(SpiceTimer *timer);
 
     SpiceWatch *(*watch_add)(int fd, int event_mask, SpiceWatchFunc func, void *opaque);
     void (*watch_update_mask)(SpiceWatch *watch, int event_mask);
commit 536212322b64af7900da170878244cdd97b6f7aa
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Mar 29 15:46:58 2010 +0200

    new watch api: kill old api

diff --git a/server/reds.c b/server/reds.c
index 6f5957f..ff90f5d 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -494,8 +494,6 @@ static void __reds_release_link(RedLinkInfo *link)
     if (link->peer->watch) {
         core->watch_remove(link->peer->watch);
         link->peer->watch = NULL;
-    } else {
-        core->set_file_handlers(core, link->peer->socket, NULL, NULL, NULL);
     }
     free(link->link_mess);
     BN_free(link->tiTicketing.bn);
diff --git a/server/vd_interface.h b/server/vd_interface.h
index a370431..2bb3bcc 100644
--- a/server/vd_interface.h
+++ b/server/vd_interface.h
@@ -82,11 +82,6 @@ struct CoreInterface {
     void (*disarm_timer)(CoreInterface *core, VDObjectRef timer);
     void (*destroy_timer)(CoreInterface *core, VDObjectRef timer);
 
-    int (*set_file_handlers)(CoreInterface *core, int fd,
-                             void (*on_read)(void *),
-                             void (*on_write)(void *),
-                             void *opaque);
-
     SpiceWatch *(*watch_add)(int fd, int event_mask, SpiceWatchFunc func, void *opaque);
     void (*watch_update_mask)(SpiceWatch *watch, int event_mask);
     void (*watch_remove)(SpiceWatch *watch);
commit a5145cc93e8ca9594b7fedc81ffd36d7a5e982af
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Mar 29 15:46:42 2010 +0200

    new watch api: switch channels

diff --git a/server/red_channel.c b/server/red_channel.c
index dbfbd42..3f46147 100644
--- a/server/red_channel.c
+++ b/server/red_channel.c
@@ -28,11 +28,10 @@
 #include <errno.h>
 #include "red_channel.h"
 
-static void red_channel_receive(void *data);
 static void red_channel_push(RedChannel *channel);
-static void red_channel_opaque_push(void *data);
 static PipeItem *red_channel_pipe_get(RedChannel *channel);
 static void red_channel_pipe_clear(RedChannel *channel);
+static void red_channel_event(int fd, int event, void *data);
 
 /* return the number of bytes read. -1 in case of error */
 static int red_peer_receive(RedsStreamContext *peer, uint8_t *buf, uint32_t size)
@@ -207,9 +206,9 @@ static void red_channel_peer_on_out_block(void *opaque)
 {
     RedChannel *channel = (RedChannel *)opaque;
     channel->send_data.blocked = TRUE;
-    channel->core->set_file_handlers(channel->core, channel->peer->socket,
-                                     red_channel_receive, red_channel_opaque_push,
-                                     channel);
+    channel->core->watch_update_mask(channel->peer->watch,
+                                     SPICE_WATCH_EVENT_READ |
+                                     SPICE_WATCH_EVENT_WRITE);
 }
 
 static void red_channel_peer_on_out_msg_done(void *opaque)
@@ -224,9 +223,8 @@ static void red_channel_peer_on_out_msg_done(void *opaque)
     }
     if (channel->send_data.blocked) {
         channel->send_data.blocked = FALSE;
-        channel->core->set_file_handlers(channel->core, channel->peer->socket,
-                                         red_channel_receive, NULL,
-                                         channel);
+        channel->core->watch_update_mask(channel->peer->watch,
+                                         SPICE_WATCH_EVENT_READ);
     }
 }
 
@@ -281,8 +279,9 @@ RedChannel *red_channel_create(int size, RedsStreamContext *peer, CoreInterface
         goto error;
     }
 
-    channel->core->set_file_handlers(channel->core, channel->peer->socket,
-                                     red_channel_receive, NULL, channel);
+    channel->peer->watch = channel->core->watch_add(channel->peer->socket,
+                                                    SPICE_WATCH_EVENT_READ,
+                                                    red_channel_event, channel);
 
     return channel;
 
@@ -299,8 +298,7 @@ void red_channel_destroy(RedChannel *channel)
         return;
     }
     red_channel_pipe_clear(channel);
-    channel->core->set_file_handlers(channel->core, channel->peer->socket,
-                                     NULL, NULL, NULL);
+    channel->core->watch_remove(channel->peer->watch);
     channel->peer->cb_free(channel->peer);
     free(channel);
 }
@@ -309,8 +307,8 @@ void red_channel_shutdown(RedChannel *channel)
 {
     red_printf("");
     if (!channel->peer->shutdown) {
-        channel->core->set_file_handlers(channel->core, channel->peer->socket,
-                                         red_channel_receive, NULL, channel);
+        channel->core->watch_update_mask(channel->peer->watch,
+                                         SPICE_WATCH_EVENT_READ);
         red_channel_pipe_clear(channel);
         shutdown(channel->peer->socket, SHUT_RDWR);
         channel->peer->shutdown = TRUE;
@@ -346,10 +344,16 @@ int red_channel_handle_message(RedChannel *channel, SpiceDataHeader *header, uin
     return TRUE;
 }
 
-static void red_channel_receive(void *data)
+static void red_channel_event(int fd, int event, void *data)
 {
     RedChannel *channel = (RedChannel *)data;
-    red_peer_handle_incoming(channel->peer, &channel->incoming);
+
+    if (event & SPICE_WATCH_EVENT_READ) {
+        red_peer_handle_incoming(channel->peer, &channel->incoming);
+    }
+    if (event & SPICE_WATCH_EVENT_WRITE) {
+        red_channel_push(channel);
+    }
 }
 
 static void inline __red_channel_add_buf(RedChannel *channel, void *data, uint32_t size)
@@ -428,11 +432,6 @@ static void red_channel_push(RedChannel *channel)
     channel->during_send = FALSE;
 }
 
-static void red_channel_opaque_push(void *data)
-{
-    red_channel_push((RedChannel *)data);
-}
-
 uint64_t red_channel_get_message_serial(RedChannel *channel)
 {
     return channel->send_data.header.serial;
commit e8a2cca02675be797e76bc51acda87eadf52e790
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Mar 29 13:28:21 2010 +0200

    new watch api: switch sound

diff --git a/server/snd_worker.c b/server/snd_worker.c
index 66dc856..d5f5f37 100644
--- a/server/snd_worker.c
+++ b/server/snd_worker.c
@@ -239,7 +239,8 @@ static void snd_disconnect_channel(SndChannel *channel)
     channel->cleanup(channel);
     worker = channel->worker;
     worker->connection = NULL;
-    core->set_file_handlers(core, channel->peer->socket, NULL, NULL, NULL);
+    core->watch_remove(channel->peer->watch);
+    channel->peer->watch = NULL;
     channel->peer->cb_free(channel->peer);
     free(channel);
 }
@@ -287,10 +288,7 @@ static int snd_send_data(SndChannel *channel)
 
             if (channel->blocked) {
                 channel->blocked = FALSE;
-                if (core->set_file_handlers(core, channel->peer->socket, snd_receive,
-                                            NULL, channel) == -1) {
-                    red_printf("qemu_set_fd_handler failed");
-                }
+                core->watch_update_mask(channel->peer->watch, SPICE_WATCH_EVENT_READ);
             }
             break;
         }
@@ -300,10 +298,8 @@ static int snd_send_data(SndChannel *channel)
             switch (errno) {
             case EAGAIN:
                 channel->blocked = TRUE;
-                if (core->set_file_handlers(core, channel->peer->socket, snd_receive,
-                                            channel->send_messages, channel) == -1) {
-                    red_printf("qemu_set_fd_handler failed");
-                }
+                core->watch_update_mask(channel->peer->watch, SPICE_WATCH_EVENT_READ |
+                                        SPICE_WATCH_EVENT_WRITE);
                 return FALSE;
             case EINTR:
                 break;
@@ -492,6 +488,18 @@ static void snd_receive(void* data)
     }
 }
 
+static void snd_event(int fd, int event, void *data)
+{
+    SndChannel *channel = data;
+
+    if (event & SPICE_WATCH_EVENT_READ) {
+        snd_receive(channel);
+    }
+    if (event & SPICE_WATCH_EVENT_WRITE) {
+        channel->send_messages(channel);
+    }
+}
+
 static inline void __snd_add_buf(SndChannel *channel, void *data, uint32_t size)
 {
     int pos = channel->send_data.n_bufs++;
@@ -802,8 +810,10 @@ static SndChannel *__new_channel(SndWorker *worker, int size, RedsStreamContext
     channel->recive_data.now = channel->recive_data.buf;
     channel->recive_data.end = channel->recive_data.buf + sizeof(channel->recive_data.buf);
 
-    if (core->set_file_handlers(core, peer->socket, snd_receive, NULL, channel) == -1) {
-        red_printf("qemu_set_fd_handler failed, %s", strerror(errno));
+    peer->watch = core->watch_add(peer->socket, SPICE_WATCH_EVENT_READ,
+                                  snd_event, channel);
+    if (peer->watch == NULL) {
+        red_printf("watch_add failed, %s", strerror(errno));
         goto error2;
     }
 
commit 614fa009036abc6e376339ecd97d49a674615af4
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Mar 29 13:21:28 2010 +0200

    new watch api: switch migration

diff --git a/server/reds.c b/server/reds.c
index cd4fd57..6f5957f 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -3246,6 +3246,7 @@ typedef struct RedsMigWrite {
 
 typedef struct RedsMigSpice {
     int fd;
+    SpiceWatch *watch;
     RedsMigWrite write;
     RedsMigRead read;
 
@@ -3340,7 +3341,8 @@ static int reds_mig_actual_write(RedsMigSpice *s)
 static void reds_mig_failed(RedsMigSpice *s)
 {
     red_printf("");
-    core->set_file_handlers(core, s->fd, NULL, NULL, NULL);
+    core->watch_remove(s->watch);
+    s->watch = NULL;
     if (s->local_args) {
         free(s->local_args);
     }
@@ -3349,23 +3351,21 @@ static void reds_mig_failed(RedsMigSpice *s)
     reds_mig_disconnect();
 }
 
-static void reds_mig_write(void *data)
+static void reds_mig_event(int fd, int event, void *data)
 {
     RedsMigSpice *s = data;
 
-    if (reds_mig_actual_write((RedsMigSpice *)data)) {
-        red_printf("write error cannot continue spice migration");
-        reds_mig_failed(s);
+    if (event & SPICE_WATCH_EVENT_READ) {
+        if (reds_mig_actual_read((RedsMigSpice *)data)) {
+            red_printf("read error cannot continue spice migration");
+            reds_mig_failed(s);
+        }
     }
-}
-
-static void reds_mig_read(void *data)
-{
-    RedsMigSpice *s = data;
-
-    if (reds_mig_actual_read((RedsMigSpice *)data)) {
-        red_printf("read error cannot continue spice migration");
-        reds_mig_failed(s);
+    if (event & SPICE_WATCH_EVENT_WRITE) {
+        if (reds_mig_actual_write((RedsMigSpice *)data)) {
+            red_printf("write error cannot continue spice migration");
+            reds_mig_failed(s);
+        }
     }
 }
 
@@ -3376,7 +3376,8 @@ static void reds_mig_continue(RedsMigSpice *s)
     int host_len;
 
     red_printf("");
-    core->set_file_handlers(core, s->fd, NULL, NULL, NULL);
+    core->watch_remove(s->watch);
+    s->watch = NULL;
     host_len = strlen(s->host) + 1;
     item = new_simple_out_item(SPICE_MSG_MAIN_MIGRATE_BEGIN,
                                sizeof(SpiceMsgMainMigrationBegin) + host_len + s->cert_pub_key_len);
@@ -3404,7 +3405,7 @@ static void reds_mig_receive_ack(RedsMigSpice *s)
     s->read.end_pos = 0;
     s->read.handle_data = reds_mig_continue;
 
-    core->set_file_handlers(core, s->fd, reds_mig_read, NULL, s);
+    core->watch_update_mask(s->watch, SPICE_WATCH_EVENT_READ);
 }
 
 static void reds_mig_send_link_id(RedsMigSpice *s)
@@ -3417,7 +3418,7 @@ static void reds_mig_send_link_id(RedsMigSpice *s)
     s->write.length = sizeof(RedsMigSpiceMessage);
     s->write.handle_done = reds_mig_receive_ack;
 
-    core->set_file_handlers(core, s->fd, reds_mig_write, reds_mig_write, s);
+    core->watch_update_mask(s->watch, SPICE_WATCH_EVENT_READ | SPICE_WATCH_EVENT_WRITE);
 }
 
 static void reds_mig_send_ticket(RedsMigSpice *s)
@@ -3442,7 +3443,7 @@ static void reds_mig_send_ticket(RedsMigSpice *s)
             s->write.length = RSA_size(rsa);
             s->write.now = s->write.buf;
             s->write.handle_done = reds_mig_send_link_id;
-            core->set_file_handlers(core, s->fd, reds_mig_write, reds_mig_write, s);
+            core->watch_update_mask(s->watch, SPICE_WATCH_EVENT_READ | SPICE_WATCH_EVENT_WRITE);
         } else {
             reds_mig_failed(s);
         }
@@ -3462,7 +3463,7 @@ static void reds_mig_receive_cert_public_key(RedsMigSpice *s)
     s->read.end_pos = 0;
     s->read.handle_data = reds_mig_send_ticket;
 
-    core->set_file_handlers(core, s->fd, reds_mig_read, NULL, s);
+    core->watch_update_mask(s->watch, SPICE_WATCH_EVENT_READ);
 }
 
 static void reds_mig_receive_cert_public_key_info(RedsMigSpice *s)
@@ -3488,7 +3489,7 @@ static void reds_mig_receive_cert_public_key_info(RedsMigSpice *s)
         s->read.handle_data = reds_mig_send_ticket;
     }
 
-    core->set_file_handlers(core, s->fd, reds_mig_read, NULL, s);
+    core->watch_update_mask(s->watch, SPICE_WATCH_EVENT_READ);
 }
 
 static void reds_mig_handle_send_abort_done(RedsMigSpice *s)
@@ -3506,14 +3507,14 @@ static void reds_mig_receive_version(RedsMigSpice *s)
     s->write.length = sizeof(resault);
     s->write.now = s->write.buf;
     s->write.handle_done = reds_mig_handle_send_abort_done;
-    core->set_file_handlers(core, s->fd, reds_mig_write, reds_mig_write, s);
+    core->watch_update_mask(s->watch, SPICE_WATCH_EVENT_READ | SPICE_WATCH_EVENT_WRITE);
 }
 
 static void reds_mig_control(RedsMigSpice *spice_migration)
 {
     uint32_t *control;
 
-    core->set_file_handlers(core, spice_migration->fd, NULL, NULL, NULL);
+    core->watch_update_mask(spice_migration->watch, 0);
     control = (uint32_t *)spice_migration->read.buf;
 
     switch (*control) {
@@ -3522,8 +3523,7 @@ static void reds_mig_control(RedsMigSpice *spice_migration)
         spice_migration->read.end_pos = 0;
         spice_migration->read.handle_data = reds_mig_receive_cert_public_key_info;
 
-        core->set_file_handlers(core, spice_migration->fd, reds_mig_read,
-                                NULL, spice_migration);
+        core->watch_update_mask(spice_migration->watch, SPICE_WATCH_EVENT_READ);
         break;
     case REDS_MIG_ABORT:
         red_printf("abort");
@@ -3535,8 +3535,7 @@ static void reds_mig_control(RedsMigSpice *spice_migration)
         spice_migration->read.end_pos = 0;
         spice_migration->read.handle_data = reds_mig_receive_version;
 
-        core->set_file_handlers(core, spice_migration->fd, reds_mig_read,
-                                NULL, spice_migration);
+        core->watch_update_mask(spice_migration->watch, SPICE_WATCH_EVENT_READ);
         break;
     default:
         red_printf("invalid control");
@@ -3550,7 +3549,7 @@ static void reds_mig_receive_control(RedsMigSpice *spice_migration)
     spice_migration->read.end_pos = 0;
     spice_migration->read.handle_data = reds_mig_control;
 
-    core->set_file_handlers(core, spice_migration->fd, reds_mig_read, NULL, spice_migration);
+    core->watch_update_mask(spice_migration->watch, SPICE_WATCH_EVENT_READ);
 }
 
 static void reds_mig_started(void *opaque, const char *in_args)
@@ -3651,8 +3650,10 @@ static void reds_mig_started(void *opaque, const char *in_args)
     version = (uint32_t *)spice_migration->write.buf;
     *version = REDS_MIG_VERSION;
     spice_migration->write.handle_done = reds_mig_receive_control;
-    core->set_file_handlers(core, spice_migration->fd, reds_mig_write,
-                            reds_mig_write, spice_migration);
+    spice_migration->watch = core->watch_add(spice_migration->fd,
+                                             SPICE_WATCH_EVENT_READ | SPICE_WATCH_EVENT_WRITE,
+                                             reds_mig_event,
+                                             spice_migration);
     return;
 
 error:
commit 5549de4b107f4250e94be895aad0d7af7e70c355
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Mar 29 12:42:47 2010 +0200

    new watch api: switch inputs

diff --git a/server/reds.c b/server/reds.c
index e50ae63..cd4fd57 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -2277,31 +2277,31 @@ static void inputs_relase_keys(void)
     push_key_scan(0x38 | 0x80); //LALT
 }
 
-static void inputs_read(void *data)
-{
-    InputsState *inputs_state = (InputsState *)data;
-    if (handle_incoming(inputs_state->peer, &inputs_state->in_handler)) {
-        inputs_relase_keys();
-        core->set_file_handlers(core, inputs_state->peer->socket, NULL, NULL, NULL);
-        if (inputs_state->channel) {
-            inputs_state->channel->data = NULL;
-            reds->inputs_state = NULL;
-        }
-        inputs_state->peer->cb_free(inputs_state->peer);
-        free(inputs_state);
-    }
-}
-
-static void inputs_write(void *data)
+static void inputs_event(int fd, int event, void *data)
 {
-    InputsState *inputs_state = (InputsState *)data;
+    InputsState *inputs_state = data;
 
-    red_printf("");
-    if (handle_outgoing(inputs_state->peer, &inputs_state->out_handler)) {
-        reds_disconnect();
+    if (event & SPICE_WATCH_EVENT_READ) {
+        if (handle_incoming(inputs_state->peer, &inputs_state->in_handler)) {
+            inputs_relase_keys();
+            core->watch_remove(inputs_state->peer->watch);
+            inputs_state->peer->watch = NULL;
+            if (inputs_state->channel) {
+                inputs_state->channel->data = NULL;
+                reds->inputs_state = NULL;
+            }
+            inputs_state->peer->cb_free(inputs_state->peer);
+            free(inputs_state);
+        }
+    }
+    if (event & SPICE_WATCH_EVENT_WRITE) {
+        if (handle_outgoing(inputs_state->peer, &inputs_state->out_handler)) {
+            reds_disconnect();
+        }
     }
 }
 
+
 static void inputs_shutdown(Channel *channel)
 {
     InputsState *state = (InputsState *)channel->data;
@@ -2337,15 +2337,14 @@ static void inputs_migrate(Channel *channel)
 static void inputs_select(void *opaque, int select)
 {
     InputsState *inputs_state;
+    int eventmask = SPICE_WATCH_EVENT_READ;
     red_printf("");
 
     inputs_state = (InputsState *)opaque;
     if (select) {
-        core->set_file_handlers(core, inputs_state->peer->socket, inputs_read, inputs_write,
-                                inputs_state);
-    } else {
-        core->set_file_handlers(core, inputs_state->peer->socket, inputs_read, NULL, inputs_state);
+        eventmask |= SPICE_WATCH_EVENT_WRITE;
     }
+    core->watch_update_mask(inputs_state->peer->watch, eventmask);
 }
 
 static void inputs_may_write(void *opaque)
@@ -2388,7 +2387,8 @@ static void inputs_link(Channel *channel, RedsStreamContext *peer, int migration
     inputs_state->pending_mouse_event = FALSE;
     channel->data = inputs_state;
     reds->inputs_state = inputs_state;
-    core->set_file_handlers(core, peer->socket, inputs_read, NULL, inputs_state);
+    peer->watch = core->watch_add(peer->socket, SPICE_WATCH_EVENT_READ,
+                                  inputs_event, inputs_state);
 
     SpiceDataHeader header;
     SpiceMsgInputsInit inputs_init;
commit d54f1103facb956248ac61ea59378352149c8893
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Mar 29 12:29:19 2010 +0200

    new watch api: switch ssl accept

diff --git a/server/reds.c b/server/reds.c
index 6a21d6e..e50ae63 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -491,7 +491,12 @@ static int reds_ssl_free(RedsStreamContext *peer)
 static void __reds_release_link(RedLinkInfo *link)
 {
     ASSERT(link->peer);
-    core->set_file_handlers(core, link->peer->socket, NULL, NULL, NULL);
+    if (link->peer->watch) {
+        core->watch_remove(link->peer->watch);
+        link->peer->watch = NULL;
+    } else {
+        core->set_file_handlers(core, link->peer->socket, NULL, NULL, NULL);
+    }
     free(link->link_mess);
     BN_free(link->tiTicketing.bn);
     if (link->tiTicketing.rsa) {
@@ -2709,20 +2714,27 @@ static void reds_handle_new_link(RedLinkInfo *link)
     async_read_handler(0, 0, &link->asyc_read);
 }
 
-static void reds_handle_ssl_accept(void *data)
+static void reds_handle_ssl_accept(int fd, int event, void *data)
 {
     RedLinkInfo *link = (RedLinkInfo *)data;
     int return_code;
 
     if ((return_code = SSL_accept(link->peer->ssl)) != 1) {
         int ssl_error = SSL_get_error(link->peer->ssl, return_code);
-
         if (ssl_error != SSL_ERROR_WANT_READ && ssl_error != SSL_ERROR_WANT_WRITE) {
             red_printf("SSL_accept failed, error=%d", ssl_error);
             reds_release_link(link);
+        } else {
+            if (ssl_error == SSL_ERROR_WANT_READ) {
+                core->watch_update_mask(link->peer->watch, SPICE_WATCH_EVENT_READ);
+            } else {
+                core->watch_update_mask(link->peer->watch, SPICE_WATCH_EVENT_WRITE);
+            }
         }
         return;
     }
+    core->watch_remove(link->peer->watch);
+    link->peer->watch = NULL;
     reds_handle_new_link(link);
 }
 
@@ -2829,8 +2841,10 @@ static void reds_accept_ssl_connection(int fd, int event, void *data)
     ssl_error = SSL_get_error(link->peer->ssl, return_code);
     if (return_code == -1 && (ssl_error == SSL_ERROR_WANT_READ ||
                               ssl_error == SSL_ERROR_WANT_WRITE)) {
-        core->set_file_handlers(core, link->peer->socket, reds_handle_ssl_accept,
-                                reds_handle_ssl_accept, link);
+        int eventmask = ssl_error == SSL_ERROR_WANT_READ ?
+            SPICE_WATCH_EVENT_READ : SPICE_WATCH_EVENT_WRITE;
+        link->peer->watch = core->watch_add(link->peer->socket, eventmask,
+                                            reds_handle_ssl_accept, link);
         return;
     }
 
commit 2dda5683b6b0dd8fa04df19a388d0898a127ec8b
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Mar 29 11:24:32 2010 +0200

    new watch api: switch main channel

diff --git a/server/reds.c b/server/reds.c
index 80f5fca..6a21d6e 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -364,7 +364,6 @@ typedef struct PingItem {
 
 static uint8_t zero_page[ZERO_BUF_SIZE] = {0};
 
-static void reds_main_write(void *data);
 static void reds_push();
 
 static ChannelSecurityOptions *channels_security = NULL;
@@ -750,7 +749,8 @@ static void reds_disconnect()
     }
 
     reds_shatdown_channels();
-    core->set_file_handlers(core, reds->peer->socket, NULL, NULL, NULL);
+    core->watch_remove(reds->peer->watch);
+    reds->peer->watch = NULL;
     reds->peer->cb_free(reds->peer);
     reds->peer = NULL;
     reds->in_handler.shut = TRUE;
@@ -1830,13 +1830,6 @@ static void reds_main_handle_message(void *opaque, SpiceDataHeader *message)
     }
 }
 
-static void reds_main_read(void *data)
-{
-    if (handle_incoming(reds->peer, &reds->in_handler)) {
-        reds_disconnect();
-    }
-}
-
 static int reds_send_data()
 {
     RedsOutgoingData *outgoing = &reds->outgoing;
@@ -1851,8 +1844,8 @@ static int reds_send_data()
         if ((n = reds->peer->cb_writev(reds->peer->ctx, outgoing->vec, outgoing->vec_size)) == -1) {
             switch (errno) {
             case EAGAIN:
-                core->set_file_handlers(core, reds->peer->socket, reds_main_read, reds_main_write,
-                                        NULL);
+                core->watch_update_mask(reds->peer->watch,
+                                        SPICE_WATCH_EVENT_READ | SPICE_WATCH_EVENT_WRITE);
                 return FALSE;
             case EINTR:
                 break;
@@ -1892,14 +1885,21 @@ static void reds_push()
     }
 }
 
-static void reds_main_write(void *data)
+static void reds_main_event(int fd, int event, void *data)
 {
-    RedsOutgoingData *outgoing = &reds->outgoing;
-
-    if (reds_send_data()) {
-        reds_push();
-        if (!outgoing->item) {
-            core->set_file_handlers(core, reds->peer->socket, reds_main_read, NULL, NULL);
+    if (event & SPICE_WATCH_EVENT_READ) {
+        if (handle_incoming(reds->peer, &reds->in_handler)) {
+            reds_disconnect();
+        }
+    }
+    if (event & SPICE_WATCH_EVENT_WRITE) {
+        RedsOutgoingData *outgoing = &reds->outgoing;
+        if (reds_send_data()) {
+            reds_push();
+            if (!outgoing->item) {
+                core->watch_update_mask(reds->peer->watch,
+                                        SPICE_WATCH_EVENT_READ);
+            }
         }
     }
 }
@@ -2058,7 +2058,9 @@ static void reds_handle_main_link(RedLinkInfo *link)
         }
         reds->agent_state.plug_generation++;
     }
-    core->set_file_handlers(core, reds->peer->socket, reds_main_read, NULL, NULL);
+    reds->peer->watch = core->watch_add(reds->peer->socket,
+                                        SPICE_WATCH_EVENT_READ,
+                                        reds_main_event, NULL);
 
     if (!reds->mig_target) {
         SimpleOutItem *item;
commit 1a69ea662719b607546375b1b18683914ec6af33
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Mar 29 11:10:51 2010 +0200

    new watch api: switch liasync read

diff --git a/server/reds.c b/server/reds.c
index 8ce07a0..80f5fca 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -298,7 +298,6 @@ typedef struct AsyncRead {
     void *opaque;
     uint8_t *now;
     uint8_t *end;
-    int active_file_handlers;
     void (*done)(void *opaque);
     void (*error)(void *opaque, int err);
 } AsyncRead;
@@ -2549,14 +2548,14 @@ static void reds_handle_ticket(void *opaque)
 
 static inline void async_read_clear_handlers(AsyncRead *obj)
 {
-    if (!obj->active_file_handlers) {
+    if (!obj->peer->watch) {
         return;
     }
-    obj->active_file_handlers = FALSE;
-    core->set_file_handlers(core, obj->peer->socket, NULL, NULL, NULL);
+    core->watch_remove(obj->peer->watch);
+    obj->peer->watch = NULL;
 }
 
-static void async_read_handler(void *data)
+static void async_read_handler(int fd, int event, void *data)
 {
     AsyncRead *obj = (AsyncRead *)data;
 
@@ -2568,10 +2567,10 @@ static void async_read_handler(void *data)
             if (n < 0) {
                 switch (errno) {
                 case EAGAIN:
-                    if (!obj->active_file_handlers) {
-                        obj->active_file_handlers = TRUE;
-                        core->set_file_handlers(core, obj->peer->socket, async_read_handler, NULL,
-                                                obj);
+                    if (!obj->peer->watch) {
+                        obj->peer->watch = core->watch_add(obj->peer->socket,
+                                                           SPICE_WATCH_EVENT_READ,
+                                                           async_read_handler, obj);
                     }
                     return;
                 case EINTR:
@@ -2640,7 +2639,7 @@ static void reds_handle_read_link_done(void *opaque)
     obj->now = (uint8_t *)&link->tiTicketing.encrypted_ticket.encrypted_data;
     obj->end = obj->now + link->tiTicketing.rsa_size;
     obj->done = reds_handle_ticket;
-    async_read_handler(&link->asyc_read);
+    async_read_handler(0, 0, &link->asyc_read);
 }
 
 static void reds_handle_link_error(void *opaque, int err)
@@ -2693,7 +2692,7 @@ static void reds_handle_read_header_done(void *opaque)
     obj->now = (uint8_t *)link->link_mess;
     obj->end = obj->now + header->size;
     obj->done = reds_handle_read_link_done;
-    async_read_handler(&link->asyc_read);
+    async_read_handler(0, 0, &link->asyc_read);
 }
 
 static void reds_handle_new_link(RedLinkInfo *link)
@@ -2703,10 +2702,9 @@ static void reds_handle_new_link(RedLinkInfo *link)
     obj->peer = link->peer;
     obj->now = (uint8_t *)&link->link_header;
     obj->end = (uint8_t *)((SpiceLinkHeader *)&link->link_header + 1);
-    obj->active_file_handlers = FALSE;
     obj->done = reds_handle_read_header_done;
     obj->error = reds_handle_link_error;
-    async_read_handler(&link->asyc_read);
+    async_read_handler(0, 0, &link->asyc_read);
 }
 
 static void reds_handle_ssl_accept(void *data)
diff --git a/server/reds.h b/server/reds.h
index a4c9f89..60eef4a 100644
--- a/server/reds.h
+++ b/server/reds.h
@@ -28,6 +28,7 @@ typedef struct RedsStreamContext {
     void *ctx;
 
     int socket;
+    SpiceWatch *watch;
 
     /* set it to TRUE if you shutdown the socket. shutdown read doesn't work as accepted -
        receive may return data afterwards. check the flag before calling receive*/
commit d1ab29c1af10c810ac0718a11188029e92be0cbe
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Mar 29 10:58:04 2010 +0200

    new watch api: switch listening sockets

diff --git a/server/reds.c b/server/reds.c
index 50753c0..8ce07a0 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -245,6 +245,8 @@ typedef struct RedsStatValue {
 typedef struct RedsState {
     int listen_socket;
     int secure_listen_socket;
+    SpiceWatch *listen_watch;
+    SpiceWatch *secure_listen_watch;
     RedsStreamContext *peer;
     int disconnecting;
     uint32_t link_id;
@@ -2784,7 +2786,7 @@ static RedLinkInfo *reds_accept_connection(int listen_socket)
     return link;
 }
 
-static void reds_accept_ssl_connection(void *data)
+static void reds_accept_ssl_connection(int fd, int event, void *data)
 {
     RedLinkInfo *link;
     int return_code;
@@ -2843,7 +2845,7 @@ error:
     free(link);
 }
 
-static void reds_accept(void *data)
+static void reds_accept(int fd, int event, void *data)
 {
     RedLinkInfo *link;
 
@@ -2917,7 +2919,10 @@ static void reds_init_net()
 {
     if (spice_port != -1) {
         reds->listen_socket = reds_init_socket(spice_addr, spice_port, spice_family);
-        if (core->set_file_handlers(core, reds->listen_socket, reds_accept, NULL, NULL)) {
+        reds->listen_watch = core->watch_add(reds->listen_socket,
+                                             SPICE_WATCH_EVENT_READ,
+                                             reds_accept, NULL);
+        if (reds->listen_watch == NULL) {
             red_error("set fd handle failed");
         }
     }
@@ -2925,8 +2930,10 @@ static void reds_init_net()
     if (spice_secure_port != -1) {
         reds->secure_listen_socket = reds_init_socket(spice_addr, spice_secure_port,
                                                       spice_family);
-        if (core->set_file_handlers(core, reds->secure_listen_socket,
-                                    reds_accept_ssl_connection, NULL, NULL)) {
+        reds->secure_listen_watch = core->watch_add(reds->secure_listen_socket,
+                                                    SPICE_WATCH_EVENT_READ,
+                                                    reds_accept_ssl_connection, NULL);
+        if (reds->secure_listen_watch == NULL) {
             red_error("set fd handle failed");
         }
     }
@@ -3545,12 +3552,12 @@ static void reds_mig_started(void *opaque, const char *in_args)
 
     reds->mig_inprogress = TRUE;
 
-    if (reds->listen_socket != -1) {
-        core->set_file_handlers(core, reds->listen_socket, NULL, NULL, NULL);
+    if (reds->listen_watch != NULL) {
+        core->watch_update_mask(reds->listen_watch, 0);
     }
 
-    if (reds->secure_listen_socket != -1) {
-        core->set_file_handlers(core, reds->secure_listen_socket, NULL, NULL, NULL);
+    if (reds->secure_listen_watch != NULL) {
+        core->watch_update_mask(reds->secure_listen_watch, 0);
     }
 
     if (reds->peer == NULL) {
@@ -3650,13 +3657,12 @@ static void reds_mig_finished(void *opaque, int completed)
     SimpleOutItem *item;
 
     red_printf("");
-    if (reds->listen_socket != -1) {
-        core->set_file_handlers(core, reds->listen_socket, reds_accept, NULL, NULL);
+    if (reds->listen_watch != NULL) {
+        core->watch_update_mask(reds->listen_watch, SPICE_WATCH_EVENT_READ);
     }
 
-    if (reds->secure_listen_socket != -1) {
-        core->set_file_handlers(core, reds->secure_listen_socket, reds_accept_ssl_connection,
-                                NULL, NULL);
+    if (reds->secure_listen_watch != NULL) {
+        core->watch_update_mask(reds->secure_listen_watch, SPICE_WATCH_EVENT_READ);
     }
 
     if (reds->peer == NULL) {
commit 4c67874a6db9f985a55e50ffcab0e68f36a8089e
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Mar 25 23:26:56 2010 +0100

    introduce new watch api
    
    This patch adds a new file handle watch interface to libspice, featuring
    three callbacks:
    
      (1) watch_add() -- create a new file watch.
      (2) watch_update_mask() -- change event mask.  spice frequently
                                 enables/disables write notification.
      (3) watch_remove() -- remove a file watch.
    
    libspice users must implement these functions to allow libspice
    monitoring file handles.
    
    The old interface (set_file_handlers) doesn't explicitly express the
    lifecycle of a watch.  Also it maps 1:1 to a qemu-internal function.
    In case the way qemu implements file watches changes (someone sayed
    QemuIONotifier?) this will break horribly.  Beside that it is very
    bad style.
    
    Follwing patches will switch over users one by one to the new interface
    and finally zap the old one.

diff --git a/server/vd_interface.h b/server/vd_interface.h
index 04be96c..a370431 100644
--- a/server/vd_interface.h
+++ b/server/vd_interface.h
@@ -68,6 +68,12 @@ typedef void (*vd_interface_change_notifier_t)(void *opaque, VDInterface *interf
                                                VDInterfaceChangeType change);
 typedef void (*timer_callback_t)(void *opaque);
 
+#define SPICE_WATCH_EVENT_READ  (1 << 0)
+#define SPICE_WATCH_EVENT_WRITE (1 << 1)
+
+typedef struct SpiceWatch SpiceWatch;
+typedef void (*SpiceWatchFunc)(int fd, int event, void *opaque);
+
 struct CoreInterface {
     VDInterface base;
 
@@ -80,6 +86,11 @@ struct CoreInterface {
                              void (*on_read)(void *),
                              void (*on_write)(void *),
                              void *opaque);
+
+    SpiceWatch *(*watch_add)(int fd, int event_mask, SpiceWatchFunc func, void *opaque);
+    void (*watch_update_mask)(SpiceWatch *watch, int event_mask);
+    void (*watch_remove)(SpiceWatch *watch);
+
 };
 
 #define VD_INTERFACE_QXL "qxl"
commit 91f747ea1dfb7b7984ac0783c2f2c867ae1c6c0a
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Mar 24 11:05:46 2010 +0100

    fix visibility

diff --git a/server/reds.c b/server/reds.c
index 88f6a72..50753c0 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -4305,14 +4305,14 @@ static void do_spice_init(CoreInterface *core_interface)
     atexit(reds_exit);
 }
 
-void __attribute__ ((visibility ("default"))) spice_init(CoreInterface *core_interface)
+__visible__ void spice_init(CoreInterface *core_interface)
 {
     spice_server_new();
     do_spice_init(core_interface);
 }
 
 /* new interface */
-SpiceServer *spice_server_new(void)
+__visible__ SpiceServer *spice_server_new(void)
 {
     /* we can't handle multiple instances (yet) */
     ASSERT(reds == NULL);
@@ -4321,7 +4321,7 @@ SpiceServer *spice_server_new(void)
     return reds;
 }
 
-int spice_server_init(SpiceServer *s, CoreInterface *core)
+__visible__ int spice_server_init(SpiceServer *s, CoreInterface *core)
 {
     ASSERT(reds == s);
     do_spice_init(core);
@@ -4331,13 +4331,13 @@ int spice_server_init(SpiceServer *s, CoreInterface *core)
     return 0;
 }
 
-void spice_server_destroy(SpiceServer *s)
+__visible__ void spice_server_destroy(SpiceServer *s)
 {
     ASSERT(reds == s);
     reds_exit();
 }
 
-int spice_server_set_port(SpiceServer *s, int port)
+__visible__ int spice_server_set_port(SpiceServer *s, int port)
 {
     ASSERT(reds == s);
     if (port < 0 || port > 0xffff) {
@@ -4347,7 +4347,7 @@ int spice_server_set_port(SpiceServer *s, int port)
     return 0;
 }
 
-void spice_server_set_addr(SpiceServer *s, const char *addr, int flags)
+__visible__ void spice_server_set_addr(SpiceServer *s, const char *addr, int flags)
 {
     ASSERT(reds == s);
     strncpy(spice_addr, addr, sizeof(spice_addr));
@@ -4359,7 +4359,7 @@ void spice_server_set_addr(SpiceServer *s, const char *addr, int flags)
     }
 }
 
-int spice_server_set_noauth(SpiceServer *s)
+__visible__ int spice_server_set_noauth(SpiceServer *s)
 {
     ASSERT(reds == s);
     memset(taTicket.password, 0, sizeof(taTicket.password));
@@ -4367,8 +4367,10 @@ int spice_server_set_noauth(SpiceServer *s)
     return 0;
 }
 
-int spice_server_set_ticket(SpiceServer *s, const char *passwd, int lifetime,
-                            int fail_if_connected, int disconnect_if_connected)
+__visible__ int spice_server_set_ticket(SpiceServer *s,
+                                        const char *passwd, int lifetime,
+                                        int fail_if_connected,
+                                        int disconnect_if_connected)
 {
     ASSERT(reds == s);
 
@@ -4398,10 +4400,10 @@ int spice_server_set_ticket(SpiceServer *s, const char *passwd, int lifetime,
     return 0;
 }
 
-int spice_server_set_tls(SpiceServer *s, int port,
-                         const char *ca_cert_file, const char *certs_file,
-                         const char *private_key_file, const char *key_passwd,
-                         const char *dh_key_file, const char *ciphersuite)
+__visible__ int spice_server_set_tls(SpiceServer *s, int port,
+                                     const char *ca_cert_file, const char *certs_file,
+                                     const char *private_key_file, const char *key_passwd,
+                                     const char *dh_key_file, const char *ciphersuite)
 {
     ASSERT(reds == s);
     if (port == 0 || ca_cert_file == NULL || certs_file == NULL ||
@@ -4436,21 +4438,21 @@ int spice_server_set_tls(SpiceServer *s, int port,
     return 0;
 }
 
-int spice_server_set_image_compression(SpiceServer *s,
-                                       spice_image_compression_t comp)
+__visible__ int spice_server_set_image_compression(SpiceServer *s,
+                                                   spice_image_compression_t comp)
 {
     ASSERT(reds == s);
     set_image_compression(comp);
     return 0;
 }
 
-spice_image_compression_t spice_server_get_image_compression(SpiceServer *s)
+__visible__ spice_image_compression_t spice_server_get_image_compression(SpiceServer *s)
 {
     ASSERT(reds == s);
     return image_compression;
 }
 
-int spice_server_set_channel_security(SpiceServer *s, const char *channel, int security)
+__visible__ int spice_server_set_channel_security(SpiceServer *s, const char *channel, int security)
 {
     static const char *names[] = {
         [ SPICE_CHANNEL_MAIN     ] = "main",
@@ -4478,7 +4480,7 @@ int spice_server_set_channel_security(SpiceServer *s, const char *channel, int s
     return -1;
 }
 
-int spice_server_set_mouse_absolute(SpiceServer *s, int absolute)
+__visible__ int spice_server_set_mouse_absolute(SpiceServer *s, int absolute)
 {
     uint32_t mode = absolute ? SPICE_MOUSE_MODE_CLIENT : SPICE_MOUSE_MODE_SERVER;
 
@@ -4487,7 +4489,7 @@ int spice_server_set_mouse_absolute(SpiceServer *s, int absolute)
     return 0;
 }
 
-int spice_server_get_sock_info(SpiceServer *s, struct sockaddr *sa, socklen_t *salen)
+__visible__ int spice_server_get_sock_info(SpiceServer *s, struct sockaddr *sa, socklen_t *salen)
 {
     ASSERT(reds == s);
     if (!reds->peer) {
@@ -4499,7 +4501,7 @@ int spice_server_get_sock_info(SpiceServer *s, struct sockaddr *sa, socklen_t *s
     return 0;
 }
 
-int spice_server_get_peer_info(SpiceServer *s, struct sockaddr *sa, socklen_t *salen)
+__visible__ int spice_server_get_peer_info(SpiceServer *s, struct sockaddr *sa, socklen_t *salen)
 {
     ASSERT(reds == s);
     if (!reds->peer) {
@@ -4511,7 +4513,7 @@ int spice_server_get_peer_info(SpiceServer *s, struct sockaddr *sa, socklen_t *s
     return 0;
 }
 
-int spice_server_add_renderer(SpiceServer *s, const char *name)
+__visible__ int spice_server_add_renderer(SpiceServer *s, const char *name)
 {
     ASSERT(reds == s);
     if (!red_dispatcher_add_renderer(name)) {
@@ -4521,21 +4523,21 @@ int spice_server_add_renderer(SpiceServer *s, const char *name)
     return 0;
 }
 
-int spice_server_add_interface(SpiceServer *s, VDInterface *interface)
+__visible__ int spice_server_add_interface(SpiceServer *s, VDInterface *interface)
 {
     ASSERT(reds == s);
     interface_change_notifier(NULL, interface, VD_INTERFACE_ADDING);
     return 0;
 }
 
-int spice_server_remove_interface(SpiceServer *s, VDInterface *interface)
+__visible__ int spice_server_remove_interface(SpiceServer *s, VDInterface *interface)
 {
     ASSERT(reds == s);
     interface_change_notifier(NULL, interface, VD_INTERFACE_REMOVING);
     return 0;
 }
 
-int spice_server_kbd_leds(SpiceServer *s, KeyboardInterface *kbd, int leds)
+__visible__ int spice_server_kbd_leds(SpiceServer *s, KeyboardInterface *kbd, int leds)
 {
     ASSERT(reds == s);
     reds_on_keyboard_leds_change(NULL, leds);
diff --git a/server/reds.h b/server/reds.h
index 029beff..a4c9f89 100644
--- a/server/reds.h
+++ b/server/reds.h
@@ -22,6 +22,8 @@
 #include <openssl/ssl.h>
 #include <sys/uio.h>
 
+#define __visible__ __attribute__ ((visibility ("default")))
+
 typedef struct RedsStreamContext {
     void *ctx;
 
commit fe8b8383419f25bd5de827d4906bfa53fd08c7ca
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Mar 23 16:33:00 2010 +0100

    zap CoreInterface->{term_printf,log}
    
    Was used to print stuff to the qemu monitor.
    Fundamentally incompatible with QMP.  Remove.

diff --git a/server/reds.c b/server/reds.c
index a61de3c..88f6a72 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -372,16 +372,6 @@ static int default_channel_security =
 
 static RedSSLParameters ssl_parameters;
 
-
-void (*log_proc)(CoreInterface *core, LogLevel level, const char* component,
-                 const char* format, ...) = NULL;
-
-#define LOG_MESSAGE(level, format, ...) {                           \
-    if (log_proc) {                                                 \
-        log_proc(core, level, "spice", format, ## __VA_ARGS__ );    \
-    }                                                               \
-}
-
 static int args_is_empty(const VDICmdArg* args)
 {
     return !args || args[0].descriptor.type == ARG_TYPE_INVALID;
@@ -748,7 +738,6 @@ static void reds_disconnect()
     }
 
     red_printf("");
-    LOG_MESSAGE(VD_LOG_INFO, "user disconnected");
     reds->disconnecting = TRUE;
     reds_reset_outgoing();
 
@@ -1042,12 +1031,9 @@ static void do_ping_client(const char *opt, int has_interval, int interval)
             reds->ping_interval = interval * 1000;
         }
         core->arm_timer(core, reds->ping_timer, reds->ping_interval);
-        core->term_printf(core, "ping on, interval %u s\n", reds->ping_interval / 1000);
     } else if (!strcmp(opt, "off")) {
         core->disarm_timer(core, reds->ping_timer);
-        core->term_printf(core, "ping off\n");
     } else {
-        core->term_printf(core, "ping invalid option: %s\n", opt);
         return;
     }
 }
@@ -1063,13 +1049,6 @@ static void ping_timer_cb()
     core->arm_timer(core, reds->ping_timer, reds->ping_interval);
 }
 
-static void do_info_rtt_client()
-{
-    core->term_printf(core, "rtt=%uus, min/max/avg=%u/%u/%uus\n", reds->roundtrip_stat.value,
-                      reds->roundtrip_stat.min, reds->roundtrip_stat.max,
-                      reds->roundtrip_stat.average);
-}
-
 #endif
 
 static void reds_send_mouse_mode()
@@ -1831,7 +1810,6 @@ static void reds_main_handle_message(void *opaque, SpiceDataHeader *message)
         }
 #ifdef RED_STATISTICS
         reds_update_stat_value(&reds->roundtrip_stat, roundtrip);
-        do_info_rtt_client();
 #endif
         break;
     }
@@ -2069,11 +2047,6 @@ static void reds_handle_main_link(RedLinkInfo *link)
     reds->mig_wait_disconnect = FALSE;
     reds->peer = link->peer;
     reds->in_handler.shut = FALSE;
-    if (reds->mig_target) {
-        LOG_MESSAGE(VD_LOG_INFO, "migrate connection");
-    } else {
-        LOG_MESSAGE(VD_LOG_INFO, "new user connection");
-    }
 
     reds_show_new_channel(link);
     __reds_release_link(link);
@@ -2510,9 +2483,12 @@ static void reds_handle_other_links(RedLinkInfo *link)
         char *mess = "keybord channel is unsecure";
         const int mess_len = strlen(mess);
 
-        LOG_MESSAGE(VD_LOG_WARN, "%s", mess);
+        if (!(item = new_simple_out_item(SPICE_MSG_NOTIFY, sizeof(SpiceMsgNotify) + mess_len + 1))) {
+            red_printf("alloc item failed");
+            reds_disconnect();
+            return;
+        }
 
-        item = new_simple_out_item(SPICE_MSG_NOTIFY, sizeof(SpiceMsgNotify) + mess_len + 1);
         notify = (SpiceMsgNotify *)item->data;
         notify->time_stamp = get_time_stamp();
         notify->severty = SPICE_NOTIFY_SEVERITY_WARN;
@@ -2558,7 +2534,6 @@ static void reds_handle_ticket(void *opaque)
 
         if (expired || strncmp(password, actual_sever_pass, SPICE_MAX_PASSWORD_LENGTH) != 0) {
             reds_send_link_result(link, SPICE_LINK_ERR_PERMISSION_DENIED);
-            LOG_MESSAGE(VD_LOG_WARN, "bad connection password or time expired");
             reds_release_link(link);
             return;
         }
@@ -2645,13 +2620,9 @@ static void reds_handle_read_link_done(void *opaque)
 
     if (!reds_security_check(link)) {
         if (link->peer->ssl) {
-            LOG_MESSAGE(VD_LOG_INFO, "channels of type %d should connect only over "
-                                     "a non secure link", link_mess->channel_type);
             red_printf("spice channels %d should not be encrypted", link_mess->channel_type);
             reds_send_link_error(link, SPICE_LINK_ERR_NEED_UNSECURED);
         } else {
-            LOG_MESSAGE(VD_LOG_INFO, "channels of type %d should connect only over "
-                                     "a secure link", link_mess->channel_type);
             red_printf("spice channels %d should be encrypted", link_mess->channel_type);
             reds_send_link_error(link, SPICE_LINK_ERR_NEED_SECURED);
         }
@@ -2692,7 +2663,6 @@ static void reds_handle_read_header_done(void *opaque)
 
     if (header->magic != SPICE_MAGIC) {
         reds_send_link_error(link, SPICE_LINK_ERR_INVALID_MAGIC);
-        LOG_MESSAGE(VD_LOG_ERROR, "bad magic %u", header->magic);
         reds_release_link(link);
         return;
     }
@@ -2701,11 +2671,6 @@ static void reds_handle_read_header_done(void *opaque)
         if (header->major_version > 0) {
             reds_send_link_error(link, SPICE_LINK_ERR_VERSION_MISMATCH);
         }
-        LOG_MESSAGE(VD_LOG_INFO, "version mismatch client %u.%u server %u.%u",
-                    header->major_version,
-                    header->minor_version,
-                    SPICE_VERSION_MAJOR,
-                    SPICE_VERSION_MINOR);
 
         red_printf("version mismatch");
         reds_release_link(link);
@@ -4280,9 +4245,6 @@ static void do_spice_init(CoreInterface *core_interface)
         red_error("bad core interface version");
     }
     core = core_interface;
-    if (core_interface->base.minor_version > 1) {
-        log_proc = core->log;
-    }
     reds->listen_socket = -1;
     reds->secure_listen_socket = -1;
     reds->peer = NULL;
diff --git a/server/vd_interface.h b/server/vd_interface.h
index 6a4834a..04be96c 100644
--- a/server/vd_interface.h
+++ b/server/vd_interface.h
@@ -80,10 +80,6 @@ struct CoreInterface {
                              void (*on_read)(void *),
                              void (*on_write)(void *),
                              void *opaque);
-
-    void (*term_printf)(CoreInterface *core, const char* str, ...);
-    void (*log)(CoreInterface *core, LogLevel level, const char* component,
-                const char* format, ...);
 };
 
 #define VD_INTERFACE_QXL "qxl"
commit 3f7ea8e7a45b951f74a94c5eb04dd348f3906033
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Mar 23 16:27:09 2010 +0100

    zap qterm interfaces
    
    old way to handle monitor, obsolete.

diff --git a/server/reds.c b/server/reds.c
index a84fe04..a61de3c 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -517,85 +517,6 @@ static inline void reds_release_link(RedLinkInfo *link)
     peer->cb_free(peer);
 }
 
-static void reds_do_disable_ticketing(void)
-{
-    ticketing_enabled = 0;
-    memset(taTicket.password, 0, sizeof(taTicket.password));
-    core->term_printf(core, "Ticketing is now disabled.\n");
-}
-
-static void reds_do_disable_ticketing_2(const VDICmdArg* args)
-{
-    if (!args_is_empty(args)) {
-        red_printf("invalid args");
-        return;
-    }
-
-    reds_do_disable_ticketing();
-}
-
-static char *base64decode(const char *input, int length)
-{
-    BIO *b64;
-    BIO *bmem;
-    int n;
-    char *buffer = (char *)spice_malloc0(length);
-    char *inbuffer = (char *)spice_malloc0(length + 1);
-
-    memcpy(inbuffer, input, length);
-    inbuffer[length] = '\n';
-
-    b64 = BIO_new(BIO_f_base64());
-    bmem = BIO_new_mem_buf(inbuffer, length + 1);
-
-    if (b64 != NULL && bmem != NULL) {
-        bmem = BIO_push(b64, bmem);
-
-        n = BIO_read(bmem, buffer, length);
-
-        if (n != 0) {
-            buffer[n - 1] = '\0';
-        } else {
-            free(buffer);
-            buffer = NULL;
-        }
-    } else {
-        free(buffer);
-        buffer = NULL;
-    }
-
-    BIO_free_all(bmem);
-
-    return buffer;
-}
-
-static void reds_do_info_ticket(void)
-{
-    core->term_printf(core, "Ticket Information:");
-    if (ticketing_enabled) {
-        if (strlen(taTicket.password) == 0) {
-            core->term_printf(core, " blocked\n");
-        } else {
-            if (taTicket.expiration_time == INT_MAX) {
-                core->term_printf(core, " expiration NEVER\n");
-            } else {
-                time_t now;
-
-                time(&now);
-                int expired = taTicket.expiration_time < now;
-                if (expired) {
-                    core->term_printf(core, " expiration EXPIRED\n");
-                } else {
-                    core->term_printf(core, " expiration %s\n",
-                                      ctime((time_t *)&(taTicket.expiration_time)));
-                }
-            }
-        }
-    } else {
-        core->term_printf(core, " disabled\n");
-    }
-}
-
 static struct iovec *reds_iovec_skip(struct iovec vec[], int skip, int *vec_size)
 {
     struct iovec *now = vec;
@@ -612,60 +533,6 @@ static struct iovec *reds_iovec_skip(struct iovec vec[], int skip, int *vec_size
 
 #ifdef RED_STATISTICS
 
-#define STAT_TAB_LEN 4
-#define STAT_VALUE_TABS 7
-
-static void print_stat_tree(uint32_t node_index, int depth)
-{
-    SpiceStatNode *node = &reds->stat->nodes[node_index];
-
-    if ((node->flags & SPICE_STAT_NODE_MASK_SHOW) == SPICE_STAT_NODE_MASK_SHOW) {
-        core->term_printf(core, "%*s%s", depth * STAT_TAB_LEN, "", node->name);
-        if (node->flags & SPICE_STAT_NODE_FLAG_VALUE) {
-            core->term_printf(core, ":%*s%llu\n",
-                              (STAT_VALUE_TABS - depth) * STAT_TAB_LEN - strlen(node->name) - 1, "",
-                              node->value);
-        } else {
-            core->term_printf(core, "\n");
-            if (node->first_child_index != INVALID_STAT_REF) {
-                print_stat_tree(node->first_child_index, depth + 1);
-            }
-        }
-    }
-    if (node->next_sibling_index != INVALID_STAT_REF) {
-        print_stat_tree(node->next_sibling_index, depth);
-    }
-}
-
-static void do_info_statistics()
-{
-    core->term_printf(core, "Spice Statistics:\n");
-    print_stat_tree(reds->stat->root_index, 0);
-}
-
-static void do_reset_statistics()
-{
-    SpiceStatNode *node;
-    int i;
-
-    for (i = 0; i <= REDS_MAX_STAT_NODES; i++) {
-        node = &reds->stat->nodes[i];
-        if (node->flags & SPICE_STAT_NODE_FLAG_VALUE) {
-            node->value = 0;
-        }
-    }
-}
-
-static void do_reset_statistics_2(const VDICmdArg* args)
-{
-    if (!args_is_empty(args)) {
-        red_printf("invalid args");
-        return;
-    }
-
-    do_reset_statistics();
-}
-
 void insert_stat_node(StatNodeRef parent, StatNodeRef ref)
 {
     SpiceStatNode *node = &reds->stat->nodes[ref];
@@ -1185,31 +1052,6 @@ static void do_ping_client(const char *opt, int has_interval, int interval)
     }
 }
 
-static void do_ping_client_2(const VDICmdArg* args)
-{
-    if (args_is_empty(args)) {
-        do_ping_client(NULL, FALSE, 0);
-        return;
-    }
-
-    if (!args_is_string(args)) {
-        red_printf("invalid args");
-        return;
-    }
-
-    if (args_is_empty(&args[1])) {
-        do_ping_client(args[0].string_val, FALSE, 0);
-        return;
-    }
-
-    if (!args_is_int(&args[1])) {
-        red_printf("invalid args");
-        return;
-    }
-
-    do_ping_client(args[0].string_val, TRUE, args[1].int_val);
-}
-
 static void ping_timer_cb()
 {
     if (!reds->peer) {
@@ -3357,12 +3199,6 @@ enum {
     SPICE_TICKET_OPTION_CONNECTED,
 };
 
-static OptionsMap _spice_ticket_options[] = {
-    {"expiration", SPICE_TICKET_OPTION_EXPIRATION},
-    {"connected", SPICE_TICKET_OPTION_CONNECTED},
-    {NULL, 0},
-};
-
 static inline void on_activating_ticketing()
 {
     if (!ticketing_enabled && reds->peer) {
@@ -3371,224 +3207,6 @@ static inline void on_activating_ticketing()
     }
 }
 
-static void reds_reset_ticketing()
-{
-    on_activating_ticketing();
-    ticketing_enabled = 1;
-    taTicket.expiration_time = 0;
-    memset(taTicket.password, 0, sizeof(taTicket.password));
-}
-
-static void reds_set_ticketing(const char *pass, long expiration)
-{
-    ASSERT(expiration >= 0);
-    on_activating_ticketing();
-    ticketing_enabled = 1;
-    if (expiration == 0) {
-        taTicket.expiration_time = INT_MAX;
-    } else {
-        time_t ltime;
-
-        time(&ltime);
-        taTicket.expiration_time = ltime + expiration;
-    }
-    strncpy(taTicket.password, pass, sizeof(taTicket.password));
-}
-
-static void reds_do_set_ticket(const char *password, const char *args)
-{
-    long expiration = 0;
-    char *local_args = NULL;
-    const char *term_str = "invalid args";
-    int disconnect = FALSE;
-    int fail = FALSE;
-
-    if (!password) {
-        term_str = "unexpected NULL password";
-        goto error;
-    }
-
-    if (args) {
-        char *in_args;
-        int option;
-        char *val;
-
-        in_args = local_args = spice_strdup(args);
-        do {
-            switch (option = get_option(&in_args, &val, _spice_ticket_options, ',')) {
-            case SPICE_TICKET_OPTION_EXPIRATION: {
-                char *endptr;
-
-                if (!val) {
-                    goto error;
-                }
-                expiration = strtol(val, &endptr, 0);
-                if (endptr != val + strlen(val) || expiration < 0) {
-                    term_str = "invalid expiration";
-                    goto error;
-                }
-                break;
-            }
-            case SPICE_TICKET_OPTION_CONNECTED:
-                if (!val) {
-                    goto error;
-                }
-
-                if (strcmp(val, "disconnect") == 0) {
-                    disconnect = TRUE;
-                    fail = FALSE;
-                } else if (strcmp(val, "fail") == 0) {
-                    fail = TRUE;
-                    disconnect = FALSE;
-                } else if (strcmp(val, "keep") == 0) {
-                    fail = FALSE;
-                    disconnect = FALSE;
-                } else {
-                    goto error;
-                }
-                break;
-            default:
-                goto error;
-            }
-        } while (in_args);
-    }
-
-    if (fail && reds->peer) {
-        term_str = "Ticket set failed";
-    } else {
-        if (disconnect) {
-            reds_disconnect();
-        }
-        reds_set_ticketing(password, expiration);
-        term_str = "Ticket set successfully";
-    }
-    core->term_printf(core, "%s\n", term_str);
-    free(local_args);
-    return;
-
-error:
-    reds_reset_ticketing();
-    core->term_printf(core, "%s\n", term_str);
-    free(local_args);
-}
-
-static void reds_do_set_ticket_2(const VDICmdArg *args)
-{
-    const char *arg2 = NULL;
-
-    if (!args_is_string(args)) {
-        red_printf("invalid args");
-        return;
-    }
-
-    if (!args_is_empty(&args[1])) {
-        if (!args_is_string(&args[1])) {
-            red_printf("invalid args");
-            return;
-        }
-        arg2 = args[1].string_val;
-    }
-
-    reds_do_set_ticket(args[0].string_val, arg2);
-}
-
-static void reds_do_set_ticket64(const char *password64, const char *args)
-{
-    char *password;
-
-    if (!password64) {
-        reds_reset_ticketing();
-        core->term_printf(core, "unexpected NULL password\n");
-        return;
-    }
-
-    if (!(password = base64decode(password64, strlen(password64)))) {
-        reds_reset_ticketing();
-        core->term_printf(core, "set_ticket64 failed!\n");
-        return;
-    }
-    reds_do_set_ticket(password, args);
-    free(password);
-}
-
-static void reds_do_set_ticket64_2(const VDICmdArg *args)
-{
-    const char *arg2 = NULL;
-
-    if (!args_is_string(args)) {
-        red_printf("invalid args");
-        return;
-    }
-
-    if (!args_is_empty(&args[1])) {
-        if (!args_is_string(&args[1])) {
-            red_printf("invalid args");
-            return;
-        }
-        arg2 = args[1].string_val;
-    }
-
-    reds_do_set_ticket64(args[0].string_val, arg2);
-}
-
-static void reds_do_info_spice()
-{
-    core->term_printf(core, "spice info:");
-    if (reds->peer) {
-        char *ip = NULL;
-        struct sockaddr_in sock_addr;
-        socklen_t len = sizeof(sock_addr);
-        if (getpeername(reds->peer->socket, (struct sockaddr *)&sock_addr, &len) != -1) {
-            ip = inet_ntoa(sock_addr.sin_addr);
-        }
-        core->term_printf(core, " client=%s", ip);
-    } else {
-        core->term_printf(core, " disconnected");
-    }
-    core->term_printf(core, " ticketing=%s", ticketing_enabled ? "on" : "off");
-    switch (image_compression) {
-    case SPICE_IMAGE_COMPRESS_AUTO_GLZ:
-        core->term_printf(core, " ic=auto_glz");
-        break;
-    case SPICE_IMAGE_COMPRESS_AUTO_LZ:
-        core->term_printf(core, " ic=auto_lz");
-        break;
-    case SPICE_IMAGE_COMPRESS_QUIC:
-        core->term_printf(core, " ic=quic");
-        break;
-    case SPICE_IMAGE_COMPRESS_LZ:
-        core->term_printf(core, " ic=lz");
-        break;
-    case SPICE_IMAGE_COMPRESS_GLZ:
-        core->term_printf(core, " ic=glz");
-        break;
-    case SPICE_IMAGE_COMPRESS_OFF:
-        core->term_printf(core, " ic=off");
-        break;
-    case SPICE_IMAGE_COMPRESS_INVALID:
-    default:
-        core->term_printf(core, " ic=invalid");
-    }
-
-    switch (streaming_video) {
-        case STREAM_VIDEO_ALL:
-            core->term_printf(core, " sv=all");
-            break;
-        case STREAM_VIDEO_FILTER:
-            core->term_printf(core, " sv=filter");
-            break;
-        case STREAM_VIDEO_OFF:
-            core->term_printf(core, " sv=off");
-            break;
-        case STREAM_VIDEO_INVALID:
-        default:
-            core->term_printf(core, " sv=invalid");
-
-    }
-    core->term_printf(core, " playback-compression=%s\n",
-                      snd_get_playback_compression() ? "on" : "off");
-}
-
 static void set_image_compression(spice_image_compression_t val)
 {
     if (val == image_compression) {
@@ -3598,136 +3216,6 @@ static void set_image_compression(spice_image_compression_t val)
     red_dispatcher_on_ic_change();
 }
 
-static spice_image_compression_t reds_get_image_compression(const char *val)
-{
-    if ((strcmp(val, "on") == 0) || (strcmp(val, "auto_glz") == 0)) {
-        return SPICE_IMAGE_COMPRESS_AUTO_GLZ;
-    } else if (strcmp(val, "auto_lz") == 0) {
-        return SPICE_IMAGE_COMPRESS_AUTO_LZ;
-    } else if (strcmp(val, "quic") == 0) {
-        return SPICE_IMAGE_COMPRESS_QUIC;
-    } else if (strcmp(val, "glz") == 0) {
-        return SPICE_IMAGE_COMPRESS_GLZ;
-    } else if (strcmp(val, "lz") == 0) {
-        return SPICE_IMAGE_COMPRESS_LZ;
-    } else if (strcmp(val, "off") == 0) {
-        return SPICE_IMAGE_COMPRESS_OFF;
-    }
-    return SPICE_IMAGE_COMPRESS_INVALID;
-}
-
-static void reds_do_set_image_compression(const char *val)
-{
-    spice_image_compression_t real_val = reds_get_image_compression(val);
-    if (real_val == SPICE_IMAGE_COMPRESS_INVALID) {
-        core->term_printf(core, "bad image compression arg\n");
-        return;
-    }
-    set_image_compression(real_val);
-}
-
-static void reds_do_set_image_compression_2(const VDICmdArg *args)
-{
-    if (!args_is_string(args)) {
-        red_printf("invalid args");
-        return;
-    }
-
-    reds_do_set_image_compression(args[0].string_val);
-}
-
-static int reds_get_streaming_video(const char *val)
-{
-    if (strcmp(val, "on") == 0) {
-        return STREAM_VIDEO_FILTER;
-    } else if (strcmp(val, "filter") == 0) {
-        return STREAM_VIDEO_FILTER;
-    } else if (strcmp(val, "all") == 0) {
-        return STREAM_VIDEO_ALL;
-    } else if (strcmp(val, "off") == 0){
-        return STREAM_VIDEO_OFF;
-    } else {
-        return STREAM_VIDEO_INVALID;
-    }
-}
-
-static void reds_do_set_streaming_video(const char *val)
-{
-    uint32_t new_val = reds_get_streaming_video(val);
-    if (new_val == STREAM_VIDEO_INVALID) {
-        core->term_printf(core, "bad streaming video arg\n");
-        return;
-    }
-
-    if (new_val == streaming_video) {
-        return;
-    }
-    streaming_video = new_val;
-    red_dispatcher_on_sv_change();
-}
-
-static void reds_do_set_streaming_video_2(const VDICmdArg *args)
-{
-    if (!args_is_string(args)) {
-        red_printf("invalid args");
-        return;
-    }
-
-    reds_do_set_streaming_video(args[0].string_val);
-}
-
-static void reds_do_set_agent_mouse(const char *val)
-{
-    int new_val;
-    if (strcmp(val, "on") == 0) {
-        new_val = TRUE;
-    } else if (strcmp(val, "off") == 0) {
-        new_val = FALSE;
-    } else {
-        core->term_printf(core, "bad agent mouse arg\n");
-        return;
-    }
-    if (new_val == agent_mouse) {
-        return;
-    }
-    agent_mouse = new_val;
-    reds_update_mouse_mode();
-}
-
-static void reds_do_set_agent_mouse_2(const VDICmdArg *args)
-{
-    if (!args_is_string(args)) {
-        red_printf("invalid args");
-        return;
-    }
-
-    reds_do_set_agent_mouse(args[0].string_val);
-}
-
-static void reds_do_set_playback_compression(const char *val)
-{
-    int on;
-    if (strcmp(val, "on") == 0) {
-        on = TRUE;
-    } else if (strcmp(val, "off") == 0) {
-        on = FALSE;
-    } else {
-        core->term_printf(core, "bad playback compression arg\n");
-        return;
-    }
-    snd_set_playback_compression(on);
-}
-
-static void reds_do_set_playback_compression_2(const VDICmdArg *args)
-{
-    if (!args_is_string(args)) {
-        red_printf("invalid args");
-        return;
-    }
-
-    reds_do_set_playback_compression(args[0].string_val);
-}
-
 static void set_one_channel_security(int id, uint32_t security)
 {
     ChannelSecurityOptions *security_options;
@@ -4513,154 +4001,6 @@ static void mm_timer_proc(void *opaque)
     core->arm_timer(core, reds->mm_timer, MM_TIMER_GRANULARITY_MS);
 }
 
-static void add_monitor_action_commands(QTermInterface *mon)
-{
-    mon->add_action_command_handler(mon, "spice", "set_image_compression", "s",
-                                    reds_do_set_image_compression,
-                                    "",
-                                    "<[on|auto_glz|auto_lz|quic|glz|lz|off]>");
-    mon->add_action_command_handler(mon, "spice", "set_streaming_video", "s",
-                                    reds_do_set_streaming_video,
-                                    "",
-                                    "<on|filter|all|off>");
-    mon->add_action_command_handler(mon, "spice", "set_playback_compression", "s",
-                                    reds_do_set_playback_compression,
-                                    "",
-                                    "<on|off>");
-    mon->add_action_command_handler(mon, "spice", "set_ticket", "ss?",
-                                    reds_do_set_ticket,
-                                    "<password> [expiration=<seconds>]"
-                                    "[,connected=keep|disconnect|fail]",
-                                    "set the spice connection ticket");
-    mon->add_action_command_handler(mon, "spice", "set_ticket64", "ss?",
-                                    reds_do_set_ticket64,
-                                    "<password> [expiration=<seconds>]"
-                                    "[,connected=keep|disconnect|fail]",
-                                    "set the spice connection ticket");
-    mon->add_action_command_handler(mon, "spice", "disable_ticketing", "",
-                                    reds_do_disable_ticketing,
-                                    "",
-                                    "entirely disables OTP");
-    mon->add_action_command_handler(mon, "spice", "set_agent_mouse", "s",
-                                    reds_do_set_agent_mouse,
-                                    "",
-                                    "<on|off>");
-#ifdef RED_STATISTICS
-    mon->add_action_command_handler(mon, "spice", "reset_stat", "",
-                                    do_reset_statistics,
-                                    "",
-                                    "reset spice statistics");
-    mon->add_action_command_handler(mon, "spice", "ping_client", "s?i?",
-                                    do_ping_client,
-                                    "[on [interval]|off]",
-                                    "ping spice client to measure roundtrip");
-#endif
-}
-
-static void add_monitor_action_commands_2(QTerm2Interface *mon)
-{
-    VDIArgDescriptor s[] = {
-        { "arg1", ARG_TYPE_STRING, FALSE},
-        { NULL, 0, 0},
-    };
-
-    VDIArgDescriptor empty[] = {
-        { NULL, 0, 0}
-    };
-
-    VDIArgDescriptor s_s_o[] = {
-        { "arg1", ARG_TYPE_STRING, FALSE},
-        { "arg2", ARG_TYPE_STRING, TRUE},
-        { NULL, 0, 0}
-    };
-
-    VDIArgDescriptor s_o_i_o[] = {
-        { "arg1", ARG_TYPE_STRING, TRUE},
-        { "arg2", ARG_TYPE_INT, TRUE},
-        { NULL, 0, 0}
-    };
-
-    mon->add_action_command_handler(mon, "spice", "set_image_compression", s,
-                                    reds_do_set_image_compression_2,
-                                    "<[on|auto_glz|auto_lz|quic|glz|lz|off]>",
-                                    "");
-
-    mon->add_action_command_handler(mon, "spice", "set_streaming_video", s,
-                                    reds_do_set_streaming_video_2,
-                                    "<on|filter|all|off>",
-                                    "");
-
-    mon->add_action_command_handler(mon, "spice", "set_playback_compression", s,
-                                    reds_do_set_playback_compression_2,
-                                    "<on|off>",
-                                    "");
-
-    mon->add_action_command_handler(mon, "spice", "set_ticket", s_s_o,
-                                    reds_do_set_ticket_2,
-                                    "<password> [expiration=<seconds>]"
-                                    "[,connected=keep|disconnect|fail]",
-                                    "set the spice connection ticket");
-    mon->add_action_command_handler(mon, "spice", "set_ticket64", s_s_o,
-                                    reds_do_set_ticket64_2,
-                                    "<password> [expiration=<seconds>]"
-                                    "[,connected=keep|disconnect|fail]",
-                                    "set the spice connection ticket");
-    mon->add_action_command_handler(mon, "spice", "disable_ticketing", empty,
-                                    reds_do_disable_ticketing_2,
-                                    "",
-                                    "entirely disables OTP");
-    mon->add_action_command_handler(mon, "spice", "set_agent_mouse", s,
-                                    reds_do_set_agent_mouse_2,
-                                    "<on|off>",
-                                    "");
-#ifdef RED_STATISTICS
-    mon->add_action_command_handler(mon, "spice", "reset_stat", empty,
-                                    do_reset_statistics_2,
-                                    "",
-                                    "reset spice statistics");
-    mon->add_action_command_handler(mon, "spice", "ping_client", s_o_i_o,
-                                    do_ping_client_2,
-                                    "[on [interval]|off]",
-                                    "ping spice client to measure roundtrip");
-#endif
-}
-
-static void add_monitor_info_commands(QTermInterface *mon)
-{
-    mon->add_info_command_handler(mon, "spice", "state",
-                                  reds_do_info_spice,
-                                  "show spice state");
-    mon->add_info_command_handler(mon, "spice", "ticket",
-                                  reds_do_info_ticket,
-                                  "show ticket");
-#ifdef RED_STATISTICS
-    mon->add_info_command_handler(mon, "spice", "stat",
-                                  do_info_statistics,
-                                  "show spice statistics");
-    mon->add_info_command_handler(mon, "spice", "rtt_client",
-                                  do_info_rtt_client,
-                                  "show rtt to spice client");
-#endif
-}
-
-static void add_monitor_info_commands_2(QTerm2Interface *mon)
-{
-    mon->add_info_command_handler(mon, "spice", "state",
-                                  reds_do_info_spice,
-                                  "show spice state");
-    mon->add_info_command_handler(mon, "spice", "ticket",
-                                  reds_do_info_ticket,
-                                  "show ticket");
-#ifdef RED_STATISTICS
-    mon->add_info_command_handler(mon, "spice", "stat",
-                                  do_info_statistics,
-                                  "show spice statistics");
-    mon->add_info_command_handler(mon, "spice", "rtt_client",
-                                  do_info_rtt_client,
-                                  "show rtt to spice client");
-#endif
-}
-
 static void attach_to_red_agent(VDIPortInterface *interface)
 {
     VDIPortState *state = &reds->agent_state;
@@ -4747,34 +4087,6 @@ static void interface_change_notifier(void *opaque, VDInterface *interface,
             }
             qxl_interface = (QXLInterface *)interface;
             red_dispatcher_init(qxl_interface);
-        } else if (strcmp(interface->type, VD_INTERFACE_QTERM) == 0) {
-            static int was_here = FALSE;
-            red_printf("VD_INTERFACE_QTERM");
-            if (was_here) {
-                return;
-            }
-            was_here = TRUE;
-            if (interface->major_version != VD_INTERFACE_QTERM_MAJOR ||
-                interface->minor_version < VD_INTERFACE_QTERM_MINOR) {
-                red_printf("unsuported qterm interface");
-                return;
-            }
-            add_monitor_action_commands((QTermInterface *)interface);
-            add_monitor_info_commands((QTermInterface *)interface);
-        } else if (strcmp(interface->type, VD_INTERFACE_QTERM2) == 0) {
-            static int was_here = FALSE;
-            red_printf("VD_INTERFACE_QTERM2");
-            if (was_here) {
-                return;
-            }
-            was_here = TRUE;
-            if (interface->major_version != VD_INTERFACE_QTERM2_MAJOR ||
-                interface->minor_version < VD_INTERFACE_QTERM2_MINOR) {
-                red_printf("unsuported qterm interface");
-                return;
-            }
-            add_monitor_action_commands_2((QTerm2Interface *)interface);
-            add_monitor_info_commands_2((QTerm2Interface *)interface);
         } else if (strcmp(interface->type, VD_INTERFACE_TABLET) == 0) {
             red_printf("VD_INTERFACE_TABLET");
             if (tablet) {
diff --git a/server/vd_interface.h b/server/vd_interface.h
index 0040ede..6a4834a 100644
--- a/server/vd_interface.h
+++ b/server/vd_interface.h
@@ -266,34 +266,6 @@ struct MigrationInterface {
     int (*begin_hook)(MigrationInterface *mig, VDObjectRef notifier);
 };
 
-#define VD_INTERFACE_QTERM "qemu_terminal"
-#define VD_INTERFACE_QTERM_MAJOR 1
-#define VD_INTERFACE_QTERM_MINOR 1
-typedef struct QTermInterface QTermInterface;
-
-struct QTermInterface {
-    VDInterface base;
-
-    VDObjectRef (*add_action_command_handler)(QTermInterface *term, const char *module_name,
-                                              const char *name,
-                                              const char *args_type,
-                                              void *handler,
-                                              const char *params,
-                                              const char *help);
-    void (*remove_action_command_handler)(QTermInterface *term, VDObjectRef obj);
-
-    VDObjectRef (*add_info_command_handler)(QTermInterface *term, const char *module_name,
-                                            const char *name,
-                                            void *handler,
-                                            const char *help);
-    void (*remove_info_command_handler)(QTermInterface *term, VDObjectRef obj);
-};
-
-#define VD_INTERFACE_QTERM2 "qemu_terminal_2"
-#define VD_INTERFACE_QTERM2_MAJOR 1
-#define VD_INTERFACE_QTERM2_MINOR 0
-typedef struct QTerm2Interface QTerm2Interface;
-
 enum VDIArgType{
     ARG_TYPE_INVALID,
     ARG_TYPE_INT,
@@ -317,28 +289,6 @@ typedef struct VDICmdArg {
 typedef void (*VDICmdHandler)(const VDICmdArg* args);
 typedef void (*VDIInfoCmdHandler)(void);
 
-struct QTerm2Interface {
-    VDInterface base;
-
-    VDObjectRef (*add_action_command_handler)(QTerm2Interface *term,
-                                              const char *module_name,
-                                              const char *command_name,
-                                              const VDIArgDescriptor *args_type,
-                                              VDICmdHandler handler,
-                                              const char *params_text,
-                                              const char *help_text);
-
-    void (*remove_action_command_handler)(QTerm2Interface *term, VDObjectRef obj);
-
-    VDObjectRef (*add_info_command_handler)(QTerm2Interface *term,
-                                            const char *module_name,
-                                            const char *command_name,
-                                            VDIInfoCmdHandler handler,
-                                            const char *help_text);
-
-    void (*remove_info_command_handler)(QTerm2Interface *term, VDObjectRef obj);
-};
-
 #define VD_INTERFACE_PLAYBACK "playback"
 #define VD_INTERFACE_PLAYBACK_MAJOR 1
 #define VD_INTERFACE_PLAYBACK_MINOR 1
commit 881c685f904c098c968303c1ae60d0c9840d2f4c
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Mar 23 16:07:56 2010 +0100

    zap CoreInterface->(un)register_change_notifiers()
    
    spice_server_add_interface() and spice_server_remove_interface()
    can be used instead.

diff --git a/server/reds.c b/server/reds.c
index bfd4847..a84fe04 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -4987,10 +4987,6 @@ static void do_spice_init(CoreInterface *core_interface)
         red_error("key modifiers timer create failed");
     }
 
-    if (core->register_change_notifiers) {
-        core->register_change_notifiers(core, &reds, interface_change_notifier);
-    }
-
 #ifdef RED_STATISTICS
     int shm_name_len = strlen(SPICE_STAT_SHM_NAME) + 20;
     int fd;
diff --git a/server/vd_interface.h b/server/vd_interface.h
index 35d006b..0040ede 100644
--- a/server/vd_interface.h
+++ b/server/vd_interface.h
@@ -71,10 +71,6 @@ typedef void (*timer_callback_t)(void *opaque);
 struct CoreInterface {
     VDInterface base;
 
-    VDObjectRef (*register_change_notifiers)(CoreInterface *core, void *opaque,
-                                             vd_interface_change_notifier_t in_notifier);
-    void (*unregister_change_notifiers)(CoreInterface *core, VDObjectRef notifier);
-
     VDObjectRef (*create_timer)(CoreInterface *core, timer_callback_t, void *opaue);
     void (*arm_timer)(CoreInterface *core, VDObjectRef timer, uint32_t ms);
     void (*disarm_timer)(CoreInterface *core, VDObjectRef timer);
commit df95728bf050b1753218832854c7b4db1b6e3377
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Mar 23 16:01:54 2010 +0100

    zap CoreInterface->next()
    
    Interfaces must be registered after spice_server_init().
    The "next" callback is used to discover interfaces
    registered before spice_server_init().  Which is a empty
    list and thus pretty pointless.  Remove it.

diff --git a/server/reds.c b/server/reds.c
index 529eb86..bfd4847 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -4958,8 +4958,6 @@ const char *version_string = VERSION;
 
 static void do_spice_init(CoreInterface *core_interface)
 {
-    VDInterface *interface = NULL;
-
     red_printf("starting %s", version_string);
 
     if (core_interface->base.base_version != VM_INTERFACE_VERSION) {
@@ -4989,11 +4987,6 @@ static void do_spice_init(CoreInterface *core_interface)
         red_error("key modifiers timer create failed");
     }
 
-    if (core->next) {
-        while ((interface = core->next(core, interface))) {
-            interface_change_notifier(&reds, interface, VD_INTERFACE_ADDING);
-        }
-    }
     if (core->register_change_notifiers) {
         core->register_change_notifiers(core, &reds, interface_change_notifier);
     }
diff --git a/server/vd_interface.h b/server/vd_interface.h
index e91539f..35d006b 100644
--- a/server/vd_interface.h
+++ b/server/vd_interface.h
@@ -71,8 +71,6 @@ typedef void (*timer_callback_t)(void *opaque);
 struct CoreInterface {
     VDInterface base;
 
-    VDInterface *(*next)(CoreInterface *core, VDInterface *prev);
-
     VDObjectRef (*register_change_notifiers)(CoreInterface *core, void *opaque,
                                              vd_interface_change_notifier_t in_notifier);
     void (*unregister_change_notifiers)(CoreInterface *core, VDObjectRef notifier);
commit 43caec519ec7aec3a6170414ea812df83a72eae4
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Mar 23 15:47:25 2010 +0100

    channel security cleanup
    
    - drop spice_channel_name_t enum, use spice-protocol defines instead.
    - switch spice_server_set_channel_security() channel parameter from
      enum to string.
    - drop spice_server_set_default_channel_security(), use
      spice_server_set_channel_security with channel == NULL instead.

diff --git a/server/reds.c b/server/reds.c
index 42b88c3..529eb86 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -3728,16 +3728,6 @@ static void reds_do_set_playback_compression_2(const VDICmdArg *args)
     reds_do_set_playback_compression(args[0].string_val);
 }
 
-static void set_all_channels_security(uint32_t security)
-{
-    while (channels_security) {
-        ChannelSecurityOptions *temp = channels_security;
-        channels_security = channels_security->next;
-        free(temp);
-    }
-    default_channel_security = security;
-}
-
 static void set_one_channel_security(int id, uint32_t security)
 {
     ChannelSecurityOptions *security_options;
@@ -5197,17 +5187,32 @@ spice_image_compression_t spice_server_get_image_compression(SpiceServer *s)
     return image_compression;
 }
 
-int spice_server_set_channel_security(SpiceServer *s,
-                                      spice_channel_name_t channel,
-                                      int security)
+int spice_server_set_channel_security(SpiceServer *s, const char *channel, int security)
 {
+    static const char *names[] = {
+        [ SPICE_CHANNEL_MAIN     ] = "main",
+        [ SPICE_CHANNEL_DISPLAY  ] = "display",
+        [ SPICE_CHANNEL_INPUTS   ] = "inputs",
+        [ SPICE_CHANNEL_CURSOR   ] = "cursor",
+        [ SPICE_CHANNEL_PLAYBACK ] = "playback",
+        [ SPICE_CHANNEL_RECORD   ] = "record",
+        [ SPICE_CHANNEL_TUNNEL   ] = "tunnel",
+    };
+    int i;
+
     ASSERT(reds == s);
-    if (channel == SPICE_CHANNEL_NAME_ALL) {
-        set_all_channels_security(security);
-    } else {
-        set_one_channel_security(channel, security);
+
+    if (channel == NULL) {
+        default_channel_security = security;
+        return 0;
     }
-    return 0;
+    for (i = 0; i < SPICE_N_ELEMENTS(names); i++) {
+        if (names[i] && strcmp(names[i], channel) == 0) {
+            set_one_channel_security(i, security);
+            return 0;
+        }
+    }
+    return -1;
 }
 
 int spice_server_set_mouse_absolute(SpiceServer *s, int absolute)
diff --git a/server/spice.h b/server/spice.h
index b2a09b3..094caae 100644
--- a/server/spice.h
+++ b/server/spice.h
@@ -61,24 +61,10 @@ int spice_server_set_image_compression(SpiceServer *s,
                                        spice_image_compression_t comp);
 spice_image_compression_t spice_server_get_image_compression(SpiceServer *s);
 
-typedef enum {
-    SPICE_CHANNEL_NAME_INVALID  = 0,
-    SPICE_CHANNEL_NAME_MAIN     = 1,
-    SPICE_CHANNEL_NAME_DISPLAY,
-    SPICE_CHANNEL_NAME_INPUTS,
-    SPICE_CHANNEL_NAME_CURSOR,
-    SPICE_CHANNEL_NAME_PLAYBACK,
-    SPICE_CHANNEL_NAME_RECORD,
-    SPICE_CHANNEL_NAME_TUNNEL,
-    SPICE_CHANNEL_NAME_ALL      = 999,
-} spice_channel_name_t;
-
 #define SPICE_CHANNEL_SECURITY_NONE (1 << 0)
 #define SPICE_CHANNEL_SECURITY_SSL (1 << 1)
 
-int spice_server_set_channel_security(SpiceServer *s,
-                                      spice_channel_name_t channel,
-                                      int security);
+int spice_server_set_channel_security(SpiceServer *s, const char *channel, int security);
 
 int spice_server_set_mouse_absolute(SpiceServer *s, int absolute);
 
commit edc1af5f670bcedce49e6b2e88caac35422aad7b
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Mar 23 15:53:05 2010 +0100

    zap spice_parse_args + spice_usage_str
    
    First step to throw out the old interface.

diff --git a/server/reds.c b/server/reds.c
index fdada68..42b88c3 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -3728,39 +3728,6 @@ static void reds_do_set_playback_compression_2(const VDICmdArg *args)
     reds_do_set_playback_compression(args[0].string_val);
 }
 
-static OptionsMap _spice_options[] = {
-    {"port", SPICE_OPTION_PORT},
-    {"sport", SPICE_OPTION_SPORT},
-    {"host", SPICE_OPTION_HOST},
-    {"ic", SPICE_OPTION_IMAGE_COMPRESSION},
-    {"password", SPICE_OPTION_PASSWORD},
-    {"disable-ticketing", SPICE_OPTION_DISABLE_TICKET},
-    {"renderer", SPICE_OPTION_RENDERER},
-    {"sslkey", SPICE_OPTION_SSLKEY},
-    {"sslcert", SPICE_OPTION_SSLCERTS},
-    {"sslcafile", SPICE_OPTION_SSLCAFILE},
-    {"ssldhfile", SPICE_OPTION_SSLDHFILE},
-    {"sslpassword", SPICE_OPTION_SSLPASSWORD},
-    {"sslciphersuite", SPICE_OPTION_SSLCIPHERSUITE},
-    {"secure-channels", SPICE_SECURED_CHANNELS},
-    {"unsecure-channels", SPICE_UNSECURED_CHANNELS},
-    {"sv", SPICE_OPTION_STREAMING_VIDEO},
-    {"agent-mouse", SPICE_OPTION_AGENT_MOUSE},
-    {"playback-compression", SPICE_OPTION_PLAYBACK_COMPRESSION},
-    {NULL, 0},
-};
-
-static OptionsMap _channel_map[] = {
-    {"all", SPICE_CHANNEL_NAME_ALL},
-    {"main", SPICE_CHANNEL_NAME_MAIN},
-    {"display", SPICE_CHANNEL_NAME_DISPLAY},
-    {"inputs", SPICE_CHANNEL_NAME_INPUTS},
-    {"cursor", SPICE_CHANNEL_NAME_CURSOR},
-    {"playback", SPICE_CHANNEL_NAME_PLAYBACK},
-    {"record", SPICE_CHANNEL_NAME_RECORD},
-    {NULL, 0},
-};
-
 static void set_all_channels_security(uint32_t security)
 {
     while (channels_security) {
@@ -3786,306 +3753,6 @@ static void set_one_channel_security(int id, uint32_t security)
     channels_security = security_options;
 }
 
-static int set_channels_security(const char *channels, uint32_t security)
-{
-    char *local_str;
-    int channel_name;
-    char *str;
-    char *val;
-    int all = 0;
-    int specific = 0;
-
-    local_str = spice_strdup(channels);
-    str = local_str;
-    do {
-        switch (channel_name = get_option(&str, &val, _channel_map, '+')) {
-        case SPICE_CHANNEL_NAME_ALL:
-            all++;
-            break;
-        case SPICE_CHANNEL_NAME_MAIN:
-            specific++;
-            set_one_channel_security(SPICE_CHANNEL_MAIN, security);
-            break;
-        case SPICE_CHANNEL_NAME_DISPLAY:
-            specific++;
-            set_one_channel_security(SPICE_CHANNEL_DISPLAY, security);
-            break;
-        case SPICE_CHANNEL_NAME_INPUTS:
-            specific++;
-            set_one_channel_security(SPICE_CHANNEL_INPUTS, security);
-            break;
-        case SPICE_CHANNEL_NAME_CURSOR:
-            specific++;
-            set_one_channel_security(SPICE_CHANNEL_CURSOR, security);
-            break;
-        case SPICE_CHANNEL_NAME_PLAYBACK:
-            specific++;
-            set_one_channel_security(SPICE_CHANNEL_PLAYBACK, security);
-            break;
-        case SPICE_CHANNEL_NAME_RECORD:
-            specific++;
-            set_one_channel_security(SPICE_CHANNEL_RECORD, security);
-            break;
-        default:
-            goto error;
-        }
-        if (val) {
-            goto error;
-        }
-    } while (str);
-
-    if (all) {
-        if (specific || all > 1) {
-            goto error;
-        }
-        set_all_channels_security(security);
-        return TRUE;
-    }
-    return TRUE;
-
-error:
-    free(local_str);
-    return FALSE;
-}
-
-int __attribute__ ((visibility ("default"))) spice_parse_args(const char *in_args)
-{
-    char *local_args;
-    char *args;
-    int option;
-    char *val;
-    int renderers_opt = FALSE;
-
-    int ssl_port = FALSE;
-    int ssl_key = FALSE;
-    int ssl_certs = FALSE;
-    int ssl_ciphersuite = FALSE;
-    int ssl_cafile = FALSE;
-    int ssl_dhfile = FALSE;
-
-    memset(&ssl_parameters, 0, sizeof(ssl_parameters));
-
-    local_args = spice_strdup(in_args);
-
-    args = local_args;
-    do {
-        switch (option = get_option(&args, &val, _spice_options, ',')) {
-        case SPICE_OPTION_PORT: {
-            char *endptr;
-            long int port;
-
-            if (!val) {
-                goto error;
-            }
-            port = strtol(val, &endptr, 0);
-            if (endptr != val + strlen(val) || port < 0 || port > 0xffff) {
-                goto error;
-            }
-            spice_port = port;
-            break;
-        }
-        case SPICE_OPTION_SPORT: {
-            char *endptr;
-            long int port;
-
-            if (!val) {
-                goto error;
-            }
-            port = strtol(val, &endptr, 0);
-            if (endptr != val + strlen(val) || port < 0 || port > 0xffff) {
-                goto error;
-            }
-
-            ssl_port = TRUE;
-            spice_secure_port = port;
-            break;
-        }
-        case SPICE_OPTION_HOST: {
-            if (val) {
-                strncpy(spice_addr, val, sizeof(spice_addr));
-                /* force ipv4 here for backward compatibility */
-                spice_family = PF_INET;
-            }
-            break;
-        }
-        case SPICE_OPTION_IMAGE_COMPRESSION:
-            if (!val) {
-                goto error;
-            }
-            image_compression = reds_get_image_compression(val);
-            if (image_compression == SPICE_IMAGE_COMPRESS_INVALID) {
-                goto error;
-            }
-            break;
-        case SPICE_OPTION_PASSWORD:
-            ticketing_enabled = 1;
-
-            if (val) {
-                strncpy(taTicket.password, val, sizeof taTicket.password);
-                //todo: add expiration option
-                taTicket.expiration_time = INT_MAX;
-            }
-
-            break;
-        case SPICE_OPTION_DISABLE_TICKET:
-            ticketing_enabled = 0;
-            break;
-        case SPICE_OPTION_RENDERER:
-            renderers_opt = TRUE;
-            if (!val) {
-                goto error;
-            }
-            while (val) {
-                char *now = val;
-                if ((val = strchr(now, '+'))) {
-                    *val++ = 0;
-                }
-                if (!red_dispatcher_add_renderer(now)) {
-                    goto error;
-                }
-            }
-
-            break;
-        case SPICE_OPTION_SSLCIPHERSUITE:
-            ssl_ciphersuite = TRUE;
-
-            if (val) {
-                strncpy(ssl_parameters.ciphersuite, val, sizeof(ssl_parameters.ciphersuite));
-            }
-
-            break;
-        case SPICE_OPTION_SSLPASSWORD:
-            if (val) {
-                strncpy(ssl_parameters.keyfile_password, val,
-                        sizeof(ssl_parameters.keyfile_password));
-            }
-            break;
-        case SPICE_OPTION_SSLKEY:
-            ssl_key = TRUE;
-
-            if (val) {
-                strncpy(ssl_parameters.private_key_file, val,
-                        sizeof(ssl_parameters.private_key_file));
-            }
-            break;
-        case SPICE_OPTION_SSLCERTS:
-            ssl_certs = TRUE;
-
-            if (val) {
-                strncpy(ssl_parameters.certs_file, val, sizeof(ssl_parameters.certs_file));
-            }
-            break;
-        case SPICE_OPTION_SSLCAFILE:
-            ssl_cafile = TRUE;
-
-            if (val) {
-                strncpy(ssl_parameters.ca_certificate_file, val,
-                        sizeof(ssl_parameters.ca_certificate_file));
-            }
-            break;
-        case SPICE_OPTION_SSLDHFILE:
-            ssl_dhfile = TRUE;
-
-            if (val) {
-                strncpy(ssl_parameters.dh_key_file, val, sizeof(ssl_parameters.dh_key_file));
-            }
-            break;
-        case SPICE_SECURED_CHANNELS:
-            if (!val || !set_channels_security(val, SPICE_CHANNEL_SECURITY_SSL)) {
-                goto error;
-            }
-            break;
-        case SPICE_UNSECURED_CHANNELS:
-            if (!val || !set_channels_security(val, SPICE_CHANNEL_SECURITY_NONE)) {
-                goto error;
-            }
-            break;
-        case SPICE_OPTION_STREAMING_VIDEO:
-            if (!val) {
-                goto error;
-            }
-            streaming_video = reds_get_streaming_video(val);
-            if (streaming_video == STREAM_VIDEO_INVALID) {
-                goto error;
-            }
-            break;
-        case SPICE_OPTION_PLAYBACK_COMPRESSION:
-            if (!val) {
-                goto error;
-            }
-            if (strcmp(val, "on") == 0) {
-                snd_set_playback_compression(TRUE);
-            } else if (strcmp(val, "off") == 0) {
-                snd_set_playback_compression(FALSE);
-            } else {
-                goto error;
-            }
-            break;
-        case SPICE_OPTION_AGENT_MOUSE:
-            if (!val) {
-                goto error;
-            }
-            if (strcmp(val, "on") == 0) {
-                agent_mouse = TRUE;
-            } else if (strcmp(val, "off") == 0) {
-                agent_mouse = FALSE;
-            } else {
-                goto error;
-            }
-            break;
-        default:
-            goto error;
-        }
-    } while (args);
-
-    if (!renderers_opt && !red_dispatcher_add_renderer("sw")) {
-        goto error;
-    }
-
-    // All SSL parameters should be either on or off.
-    if (ssl_port != ssl_key || ssl_key != ssl_certs || ssl_certs != ssl_cafile ||
-            ssl_cafile != ssl_dhfile || ssl_dhfile != ssl_ciphersuite) {
-
-        goto error;
-    }
-    free(local_args);
-    return TRUE;
-
-error:
-    free(local_args);
-    return FALSE;
-}
-
-const char *spice_usage_str[] __attribute__ ((visibility ("default"))) = {
-    "[port=<port>][,sport=<port>][,host=<host>]",
-    "[,ic=on|auto_glz|auto_lz|quic|glz|lz|off]",
-    "[,playback-compression=on|off]",
-    "[,password=password][,disable-ticketing]",
-    "[,renderer=oglpbuf+oglpixmap+sw]",
-    "[,sslkeys=key directory,sslcerts=certs directory,sslpassword=pem password,",
-    "                                              sslciphersuite=cipher suite]",
-    "[,secure-channels=all|channel+channel+...]",
-    "[,unsecure-channels=all|channel+channel+...]",
-    "[,vs=on|off] [,ac=on|off]",
-    "    listen on interface address <host> port <port> and/or sport <port>",
-    "    setting ticket password using \"ticket\" option",
-    "    setting image compression using \"ic\" option [default=auto_local]",
-    "    setting playback compression using \"playback-compression\" option [default=on]",
-    "    select renderers using \"renderer\" option",
-    "    sslkeys - set directory where ssl key file resides.",
-    "    sslcerts - set directory where ssl cert file resides.",
-    "    sslpassword - set the password to open the private key file.",
-    "    sslciphersuite - set the cipher suite to use.",
-    "    setting streaming video using \"sv\" option [default=on]",
-    "    setting audio compression codec using \"ac\" option [default=off]",
-    "    secure-channels - force secure connection on all/specific chnnels.",
-    "                       channels names: main, inputs, display, cursor,",
-    "                                       playback and record.",
-    "    unsecure-channels - force unsecure connection on all/specific chnnels.",
-    "                         channels names as in secure-channels.",
-    NULL,
-};
-
 #define REDS_SAVE_VERSION 1
 
 static OptionsMap spice_mig_options[] = {
diff --git a/server/spice.h b/server/spice.h
index dda2134..b2a09b3 100644
--- a/server/spice.h
+++ b/server/spice.h
@@ -22,9 +22,6 @@
 #include "vd_interface.h"
 
 /* old interface */
-extern const char *spice_usage_str[];
-
-int spice_parse_args(const char *args);
 void spice_init(CoreInterface *core);
 
 /* new interface */


More information about the Spice-commits mailing list