[Libvir] RFC [3/3]: Re-factor QEMU daemon protocol to use XDR

Daniel P. Berrange berrange at redhat.com
Thu Mar 22 20:50:31 UTC 2007


This patch updates the server end to use XDR for processing requests from
the QEMU client. The bulk of the patch is basically a simple string replacement
to deal with slightly different struct/union nesting & names. 

The interesting bit of the code is the changes to the qemud/qemud.c file
which is where the XDR encoding/ decoding takes places. As with the client
equivalent, I feel this code has become much clearer to understand with
the use of XDR. Particularly since it also gives us the endianness & alignment
safety we never had before.

I'd actually consider going one stage further in this refactoring. In the
handcrafted protocol all the strings on the wire had a fixed size as we were
basically throwing structs straight onto the wire. With XDR however, it is
perfectly possible to have regular variable length strings (ie char*) in the
structs and thus the payload on the wire is only as large as actually needed,
and not artificially limited in size.

$ diffstat libvirt-qemu-xdr-server.patch
 conf.c     |    1 
 dispatch.c |  538 +++++++++++++++++++++----------------------------------------
 dispatch.h |    2 
 internal.h |   21 +-
 qemud.c    |  189 ++++++++++++++-------
 uuid.c     |    1 
 6 files changed, 341 insertions(+), 411 deletions(-)


Dan.
-- 
|=- Red Hat, Engineering, Emerging Technologies, Boston.  +1 978 392 2496 -=|
|=-           Perl modules: http://search.cpan.org/~danberr/              -=|
|=-               Projects: http://freshmeat.net/~danielpb/               -=|
|=-  GnuPG: 7D3B9505   F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505  -=| 
-------------- next part --------------
Index: qemud/conf.c
===================================================================
RCS file: /data/cvs/libvirt/qemud/conf.c,v
retrieving revision 1.44
diff -u -p -u -p -r1.44 conf.c
--- qemud/conf.c	20 Mar 2007 16:50:42 -0000	1.44
+++ qemud/conf.c	22 Mar 2007 19:47:10 -0000
@@ -40,7 +40,6 @@
 
 #include <libvirt/virterror.h>
 
-#include "protocol.h"
 #include "internal.h"
 #include "conf.h"
 #include "driver.h"
Index: qemud/dispatch.c
===================================================================
RCS file: /data/cvs/libvirt/qemud/dispatch.c,v
retrieving revision 1.11
diff -u -p -u -p -r1.11 dispatch.c
--- qemud/dispatch.c	15 Mar 2007 18:23:00 -0000	1.11
+++ qemud/dispatch.c	22 Mar 2007 19:47:11 -0000
@@ -40,65 +40,56 @@
 
 static int qemudDispatchFailure(struct qemud_server *server ATTRIBUTE_UNUSED,
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
-                                struct qemud_packet *out) {
-    out->header.type = QEMUD_PKT_FAILURE;
-    out->header.dataSize = sizeof(out->data.failureReply);
-    out->data.failureReply.code = server->errorCode;
-    strcpy(out->data.failureReply.message, server->errorMessage);
+                                struct qemud_packet_server_data *out) {
+    out->type = QEMUD_SERVER_PKT_FAILURE;
+    out->qemud_packet_server_data_u.failureReply.code = server->errorCode;
+    strcpy(out->qemud_packet_server_data_u.failureReply.message, server->errorMessage);
     return 0;
 }
 
 
 static int qemudDispatchGetVersion(struct qemud_server *server, struct qemud_client *client,
-                                   struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != 0)
-        return -1;
-
+                                   struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     int version = qemudGetVersion(server);
     if (version < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_GET_VERSION;
-        out->header.dataSize = sizeof(out->data.getVersionReply);
-        out->data.getVersionReply.version = version;
+        out->type = QEMUD_SERVER_PKT_GET_VERSION;
+        out->qemud_packet_server_data_u.getVersionReply.versionNum = version;
     }
     return 0;
 }
 
 static int qemudDispatchGetNodeInfo(struct qemud_server *server, struct qemud_client *client,
-                                    struct qemud_packet *in, struct qemud_packet *out) {
+                                    struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     struct utsname info;
 
-    if (in->header.dataSize != 0)
-        return -1;
-
     if (uname(&info) < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
         return 0;
     }
 
-    if (qemudGetCPUInfo(&out->data.getNodeInfoReply.cpus,
-                        &out->data.getNodeInfoReply.mhz,
-                        &out->data.getNodeInfoReply.nodes,
-                        &out->data.getNodeInfoReply.sockets,
-                        &out->data.getNodeInfoReply.cores,
-                        &out->data.getNodeInfoReply.threads) < 0) {
+    if (qemudGetCPUInfo(&out->qemud_packet_server_data_u.getNodeInfoReply.cpus,
+                        &out->qemud_packet_server_data_u.getNodeInfoReply.mhz,
+                        &out->qemud_packet_server_data_u.getNodeInfoReply.nodes,
+                        &out->qemud_packet_server_data_u.getNodeInfoReply.sockets,
+                        &out->qemud_packet_server_data_u.getNodeInfoReply.cores,
+                        &out->qemud_packet_server_data_u.getNodeInfoReply.threads) < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
         return 0;
     }
-    if (qemudGetMemInfo(&out->data.getNodeInfoReply.memory) < 0) {
+    if (qemudGetMemInfo(&out->qemud_packet_server_data_u.getNodeInfoReply.memory) < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
         return 0;
     }
 
-    out->header.type = QEMUD_PKT_GET_NODEINFO;
-    out->header.dataSize = sizeof(out->data.getNodeInfoReply);
-    strncpy(out->data.getNodeInfoReply.model, info.machine, sizeof(out->data.getNodeInfoReply.model));
-    out->data.getNodeInfoReply.model[sizeof(out->data.getNodeInfoReply.model)-1] = '\0';
+    out->type = QEMUD_SERVER_PKT_GET_NODEINFO;
+    strncpy(out->qemud_packet_server_data_u.getNodeInfoReply.model, info.machine, sizeof(out->qemud_packet_server_data_u.getNodeInfoReply.model));
+    out->qemud_packet_server_data_u.getNodeInfoReply.model[sizeof(out->qemud_packet_server_data_u.getNodeInfoReply.model)-1] = '\0';
 
     return 0;
 }
@@ -106,8 +97,8 @@ static int qemudDispatchGetNodeInfo(stru
 static int
 qemudDispatchGetCapabilities (struct qemud_server *server,
                               struct qemud_client *client,
-                              struct qemud_packet *in,
-                              struct qemud_packet *out)
+                              struct qemud_packet_client_data *in,
+                              struct qemud_packet_server_data *out)
 {
     struct utsname utsname;
     int i, j, r;
@@ -116,8 +107,6 @@ qemudDispatchGetCapabilities (struct qem
     bufferPtr xml;
     int len;
 
-    if (in->header.dataSize != 0) return -1;
-
     /* Really, this never fails - look at the man-page. */
     uname (&utsname);
 
@@ -268,18 +257,15 @@ qemudDispatchGetCapabilities (struct qem
         qemudDispatchFailure (server, client, out);
         return 0;
     }
-    out->header.type = QEMUD_PKT_GET_CAPABILITIES;
-    out->header.dataSize = sizeof(out->data.getCapabilitiesReply);
-    strcpy (out->data.getCapabilitiesReply.xml, xml->content);
+    out->type = QEMUD_SERVER_PKT_GET_CAPABILITIES;
+    strcpy (out->qemud_packet_server_data_u.getCapabilitiesReply.xml, xml->content);
     bufferFree (xml);
     return 0;
 }
 
 static int qemudDispatchListDomains(struct qemud_server *server, struct qemud_client *client,
-                                    struct qemud_packet *in, struct qemud_packet *out) {
+                                    struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     int i, ndomains, domains[QEMUD_MAX_NUM_DOMAINS];
-    if (in->header.dataSize != 0)
-        return -1;
 
     ndomains = qemudListDomains(server,
                                 domains,
@@ -288,172 +274,136 @@ static int qemudDispatchListDomains(stru
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_LIST_DOMAINS;
-        out->header.dataSize = sizeof(out->data.listDomainsReply);
+        out->type = QEMUD_SERVER_PKT_LIST_DOMAINS;
         for (i = 0 ; i < ndomains ; i++) {
-            out->data.listDomainsReply.domains[i] = domains[i];
+            out->qemud_packet_server_data_u.listDomainsReply.domains[i] = domains[i];
         }
-        out->data.listDomainsReply.numDomains = ndomains;
+        out->qemud_packet_server_data_u.listDomainsReply.numDomains = ndomains;
     }
     return 0;
 }
 
 static int qemudDispatchNumDomains(struct qemud_server *server, struct qemud_client *client,
-                                   struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != 0)
-        return -1;
-
+                                   struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     int ndomains = qemudNumDomains(server);
     if (ndomains < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NUM_DOMAINS;
-        out->header.dataSize = sizeof(out->data.numDomainsReply);
-        out->data.numDomainsReply.numDomains = ndomains;
+        out->type = QEMUD_SERVER_PKT_NUM_DOMAINS;
+        out->qemud_packet_server_data_u.numDomainsReply.numDomains = ndomains;
     }
     return 0;
 }
 
 static int qemudDispatchDomainCreate(struct qemud_server *server, struct qemud_client *client,
-                                     struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.domainCreateRequest))
-        return -1;
-
-    in->data.domainCreateRequest.xml[QEMUD_MAX_XML_LEN-1] ='\0';
+                                     struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
+    in->qemud_packet_client_data_u.domainCreateRequest.xml[QEMUD_MAX_XML_LEN-1] ='\0';
 
-    struct qemud_vm *vm = qemudDomainCreate(server, in->data.domainCreateRequest.xml);
+    struct qemud_vm *vm = qemudDomainCreate(server, in->qemud_packet_client_data_u.domainCreateRequest.xml);
     if (!vm) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_CREATE;
-        out->header.dataSize = sizeof(out->data.domainCreateReply);
-        out->data.domainCreateReply.id = vm->id;
-        memcpy(out->data.domainCreateReply.uuid, vm->def->uuid, QEMUD_UUID_RAW_LEN);
-        strncpy(out->data.domainCreateReply.name, vm->def->name, QEMUD_MAX_NAME_LEN-1);
-        out->data.domainCreateReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
+        out->type = QEMUD_SERVER_PKT_DOMAIN_CREATE;
+        out->qemud_packet_server_data_u.domainCreateReply.id = vm->id;
+        memcpy(out->qemud_packet_server_data_u.domainCreateReply.uuid, vm->def->uuid, QEMUD_UUID_RAW_LEN);
+        strncpy(out->qemud_packet_server_data_u.domainCreateReply.name, vm->def->name, QEMUD_MAX_NAME_LEN-1);
+        out->qemud_packet_server_data_u.domainCreateReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
     }
     return 0;
 }
 
 static int qemudDispatchDomainLookupByID(struct qemud_server *server, struct qemud_client *client,
-                                         struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.domainLookupByIDRequest))
-        return -1;
-
-    struct qemud_vm *vm = qemudFindVMByID(server, in->data.domainLookupByIDRequest.id);
+                                         struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
+    struct qemud_vm *vm = qemudFindVMByID(server, in->qemud_packet_client_data_u.domainLookupByIDRequest.id);
     if (!vm) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_LOOKUP_BY_ID;
-        out->header.dataSize = sizeof(out->data.domainLookupByIDReply);
-        memcpy(out->data.domainLookupByIDReply.uuid, vm->def->uuid, QEMUD_UUID_RAW_LEN);
-        strncpy(out->data.domainLookupByIDReply.name, vm->def->name, QEMUD_MAX_NAME_LEN-1);
-        out->data.domainLookupByIDReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
+        out->type = QEMUD_SERVER_PKT_DOMAIN_LOOKUP_BY_ID;
+        memcpy(out->qemud_packet_server_data_u.domainLookupByIDReply.uuid, vm->def->uuid, QEMUD_UUID_RAW_LEN);
+        strncpy(out->qemud_packet_server_data_u.domainLookupByIDReply.name, vm->def->name, QEMUD_MAX_NAME_LEN-1);
+        out->qemud_packet_server_data_u.domainLookupByIDReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
     }
     return 0;
 }
 
 static int qemudDispatchDomainLookupByUUID(struct qemud_server *server, struct qemud_client *client,
-                                           struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.domainLookupByUUIDRequest))
-        return -1;
-
-    struct qemud_vm *vm = qemudFindVMByUUID(server, in->data.domainLookupByUUIDRequest.uuid);
+                                           struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
+    struct qemud_vm *vm = qemudFindVMByUUID(server, in->qemud_packet_client_data_u.domainLookupByUUIDRequest.uuid);
     if (!vm) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_LOOKUP_BY_UUID;
-        out->header.dataSize = sizeof(out->data.domainLookupByUUIDReply);
-        out->data.domainLookupByUUIDReply.id = vm->id;
-        strncpy(out->data.domainLookupByUUIDReply.name, vm->def->name, QEMUD_MAX_NAME_LEN-1);
-        out->data.domainLookupByUUIDReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
+        out->type = QEMUD_SERVER_PKT_DOMAIN_LOOKUP_BY_UUID;
+        out->qemud_packet_server_data_u.domainLookupByUUIDReply.id = vm->id;
+        strncpy(out->qemud_packet_server_data_u.domainLookupByUUIDReply.name, vm->def->name, QEMUD_MAX_NAME_LEN-1);
+        out->qemud_packet_server_data_u.domainLookupByUUIDReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
     }
     return 0;
 }
 
 static int qemudDispatchDomainLookupByName(struct qemud_server *server, struct qemud_client *client,
-                                           struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.domainLookupByNameRequest))
-        return -1;
-
+                                           struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     /* Paranoia NULL termination */
-    in->data.domainLookupByNameRequest.name[QEMUD_MAX_NAME_LEN-1] = '\0';
-    struct qemud_vm *vm = qemudFindVMByName(server, in->data.domainLookupByNameRequest.name);
+    in->qemud_packet_client_data_u.domainLookupByNameRequest.name[QEMUD_MAX_NAME_LEN-1] = '\0';
+    struct qemud_vm *vm = qemudFindVMByName(server, in->qemud_packet_client_data_u.domainLookupByNameRequest.name);
     if (!vm) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_LOOKUP_BY_NAME;
-        out->header.dataSize = sizeof(out->data.domainLookupByNameReply);
-        out->data.domainLookupByNameReply.id = vm->id;
-        memcpy(out->data.domainLookupByNameReply.uuid, vm->def->uuid, QEMUD_UUID_RAW_LEN);
+        out->type = QEMUD_SERVER_PKT_DOMAIN_LOOKUP_BY_NAME;
+        out->qemud_packet_server_data_u.domainLookupByNameReply.id = vm->id;
+        memcpy(out->qemud_packet_server_data_u.domainLookupByNameReply.uuid, vm->def->uuid, QEMUD_UUID_RAW_LEN);
     }
     return 0;
 }
 
 static int qemudDispatchDomainSuspend(struct qemud_server *server, struct qemud_client *client,
-                                      struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.domainSuspendRequest))
-        return -1;
-
-    int ret = qemudDomainSuspend(server, in->data.domainSuspendRequest.id);
+                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
+    int ret = qemudDomainSuspend(server, in->qemud_packet_client_data_u.domainSuspendRequest.id);
     if (ret < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_SUSPEND;
-        out->header.dataSize = 0;
+        out->type = QEMUD_SERVER_PKT_DOMAIN_SUSPEND;
     }
     return 0;
 }
 
 static int qemudDispatchDomainResume(struct qemud_server *server, struct qemud_client *client,
-                                     struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.domainResumeRequest))
-        return -1;
-
-    int ret = qemudDomainResume(server, in->data.domainResumeRequest.id);
+                                     struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
+    int ret = qemudDomainResume(server, in->qemud_packet_client_data_u.domainResumeRequest.id);
     if (ret < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_RESUME;
-        out->header.dataSize = 0;
+        out->type = QEMUD_SERVER_PKT_DOMAIN_RESUME;
     }
     return 0;
 }
 
 static int qemudDispatchDomainDestroy(struct qemud_server *server, struct qemud_client *client,
-                                      struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.domainDestroyRequest))
-        return -1;
-
-    if (qemudDomainDestroy(server, in->data.domainDestroyRequest.id) < 0) {
+                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
+    if (qemudDomainDestroy(server, in->qemud_packet_client_data_u.domainDestroyRequest.id) < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_DESTROY;
-        out->header.dataSize = 0;
+        out->type = QEMUD_SERVER_PKT_DOMAIN_DESTROY;
     }
     return 0;
 }
 
 static int qemudDispatchDomainGetInfo(struct qemud_server *server, struct qemud_client *client,
-                                      struct qemud_packet *in, struct qemud_packet *out) {
+                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     int runstate;
     unsigned long long cpuTime;
     unsigned long memory;
     unsigned long maxmem;
     unsigned int nrVirtCpu;
 
-    if (in->header.dataSize != sizeof(in->data.domainGetInfoRequest))
-        return -1;
-
-    int ret = qemudDomainGetInfo(server, in->data.domainGetInfoRequest.uuid,
+    int ret = qemudDomainGetInfo(server, in->qemud_packet_client_data_u.domainGetInfoRequest.uuid,
                                  &runstate,
                                  &cpuTime,
                                  &maxmem,
@@ -463,91 +413,77 @@ static int qemudDispatchDomainGetInfo(st
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_GET_INFO;
-        out->header.dataSize = sizeof(out->data.domainGetInfoReply);
-        out->data.domainGetInfoReply.runstate = runstate;
-        out->data.domainGetInfoReply.cpuTime = cpuTime;
-        out->data.domainGetInfoReply.maxmem = maxmem;
-        out->data.domainGetInfoReply.memory = memory;
-        out->data.domainGetInfoReply.nrVirtCpu = nrVirtCpu;
+        out->type = QEMUD_SERVER_PKT_DOMAIN_GET_INFO;
+        out->qemud_packet_server_data_u.domainGetInfoReply.runstate = runstate;
+        out->qemud_packet_server_data_u.domainGetInfoReply.cpuTime = cpuTime;
+        out->qemud_packet_server_data_u.domainGetInfoReply.maxmem = maxmem;
+        out->qemud_packet_server_data_u.domainGetInfoReply.memory = memory;
+        out->qemud_packet_server_data_u.domainGetInfoReply.nrVirtCpu = nrVirtCpu;
     }
     return 0;
 }
 
 static int qemudDispatchDomainSave(struct qemud_server *server, struct qemud_client *client,
-                                   struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.domainSaveRequest))
-        return -1;
-
+                                   struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     /* Paranoia NULL termination */
-    in->data.domainSaveRequest.file[PATH_MAX-1] ='\0';
+    in->qemud_packet_client_data_u.domainSaveRequest.file[PATH_MAX-1] ='\0';
 
     int ret = qemudDomainSave(server,
-                              in->data.domainSaveRequest.id,
-                              in->data.domainSaveRequest.file);
+                              in->qemud_packet_client_data_u.domainSaveRequest.id,
+                              in->qemud_packet_client_data_u.domainSaveRequest.file);
     if (ret < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_SAVE;
-        out->header.dataSize = 0;
+        out->type = QEMUD_SERVER_PKT_DOMAIN_SAVE;
     }
     return 0;
 }
 
 static int qemudDispatchDomainRestore(struct qemud_server *server, struct qemud_client *client,
-                                      struct qemud_packet *in, struct qemud_packet *out) {
+                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     int id;
-    if (in->header.dataSize != sizeof(in->data.domainRestoreRequest))
-        return -1;
 
     /* Paranoia null termination */
-    in->data.domainRestoreRequest.file[PATH_MAX-1] ='\0';
+    in->qemud_packet_client_data_u.domainRestoreRequest.file[PATH_MAX-1] ='\0';
 
-    id = qemudDomainRestore(server, in->data.domainRestoreRequest.file);
+    id = qemudDomainRestore(server, in->qemud_packet_client_data_u.domainRestoreRequest.file);
     if (id < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_RESTORE;
-        out->header.dataSize = sizeof(out->data.domainRestoreReply);
-        out->data.domainRestoreReply.id = id;
+        out->type = QEMUD_SERVER_PKT_DOMAIN_RESTORE;
+        out->qemud_packet_server_data_u.domainRestoreReply.id = id;
     }
     return 0;
 }
 
 static int qemudDispatchDumpXML(struct qemud_server *server, struct qemud_client *client,
-                                struct qemud_packet *in, struct qemud_packet *out) {
+                                struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     int ret;
-    if (in->header.dataSize != sizeof(in->data.domainDumpXMLRequest))
-        return -1;
-
     ret = qemudDomainDumpXML(server,
-                             in->data.domainDumpXMLRequest.uuid,
-                             out->data.domainDumpXMLReply.xml,
+                             in->qemud_packet_client_data_u.domainDumpXMLRequest.uuid,
+                             out->qemud_packet_server_data_u.domainDumpXMLReply.xml,
                              QEMUD_MAX_XML_LEN);
     if (ret < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DUMP_XML;
-        out->header.dataSize = sizeof(out->data.domainDumpXMLReply);
+        out->type = QEMUD_SERVER_PKT_DUMP_XML;
     }
     return 0;
 }
 
 static int qemudDispatchListDefinedDomains(struct qemud_server *server, struct qemud_client *client,
-                                           struct qemud_packet *in, struct qemud_packet *out) {
+                                           struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     char **names;
     int i, ndomains;
-    if (in->header.dataSize != 0)
-        return -1;
 
     if (!(names = malloc(sizeof(char *)*QEMUD_MAX_NUM_DOMAINS)))
         return -1;
 
     for (i = 0 ; i < QEMUD_MAX_NUM_DOMAINS ; i++) {
-        names[i] = out->data.listDefinedDomainsReply.domains[i];
+        names[i] = &out->qemud_packet_server_data_u.listDefinedDomainsReply.domains[i*QEMUD_MAX_NAME_LEN];
     }
 
     ndomains = qemudListDefinedDomains(server,
@@ -558,114 +494,95 @@ static int qemudDispatchListDefinedDomai
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_LIST_DEFINED_DOMAINS;
-        out->header.dataSize = sizeof(out->data.listDefinedDomainsReply);
-        out->data.listDefinedDomainsReply.numDomains = ndomains;
+        out->type = QEMUD_SERVER_PKT_LIST_DEFINED_DOMAINS;
+        out->qemud_packet_server_data_u.listDefinedDomainsReply.numDomains = ndomains;
+    }
+    printf("%d %d\n", out->type, out->qemud_packet_server_data_u.listDefinedDomainsReply.numDomains);
+    for (i = 0 ; i < ndomains;i++) {
+        printf("[%s]\n", &out->qemud_packet_server_data_u.listDefinedDomainsReply.domains[i*QEMUD_MAX_NAME_LEN]);
     }
     return 0;
 }
 
 static int qemudDispatchNumDefinedDomains(struct qemud_server *server, struct qemud_client *client,
-                                          struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != 0)
-        return -1;
-
+                                          struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     int ndomains = qemudNumDefinedDomains(server);
     if (ndomains < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NUM_DEFINED_DOMAINS;
-        out->header.dataSize = sizeof(out->data.numDefinedDomainsReply);
-        out->data.numDefinedDomainsReply.numDomains = ndomains;
+        out->type = QEMUD_SERVER_PKT_NUM_DEFINED_DOMAINS;
+        out->qemud_packet_server_data_u.numDefinedDomainsReply.numDomains = ndomains;
     }
     return 0;
 }
 
 static int qemudDispatchDomainStart(struct qemud_server *server, struct qemud_client *client,
-                                    struct qemud_packet *in, struct qemud_packet *out) {
+                                    struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     struct qemud_vm *vm;
 
-    if (in->header.dataSize != sizeof(in->data.domainStartRequest))
-        return -1;
-
-    if (!(vm = qemudDomainStart(server, in->data.domainStartRequest.uuid))) {
+    if (!(vm = qemudDomainStart(server, in->qemud_packet_client_data_u.domainStartRequest.uuid))) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_START;
-        out->header.dataSize = sizeof(out->data.domainStartReply);
-        out->data.domainStartReply.id = vm->id;
+        out->type = QEMUD_SERVER_PKT_DOMAIN_START;
+        out->qemud_packet_server_data_u.domainStartReply.id = vm->id;
     }
     return 0;
 }
 
 static int qemudDispatchDomainDefine(struct qemud_server *server, struct qemud_client *client,
-                                     struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.domainDefineRequest))
-        return -1;
-
-    in->data.domainDefineRequest.xml[QEMUD_MAX_XML_LEN-1] ='\0';
+                                     struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
+    in->qemud_packet_client_data_u.domainDefineRequest.xml[QEMUD_MAX_XML_LEN-1] ='\0';
 
-    struct qemud_vm *vm = qemudDomainDefine(server, in->data.domainDefineRequest.xml);
+    struct qemud_vm *vm = qemudDomainDefine(server, in->qemud_packet_client_data_u.domainDefineRequest.xml);
     if (!vm) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_DEFINE;
-        out->header.dataSize = sizeof(out->data.domainDefineReply);
-        memcpy(out->data.domainDefineReply.uuid, vm->def->uuid, QEMUD_UUID_RAW_LEN);
-        strncpy(out->data.domainDefineReply.name, vm->def->name, QEMUD_MAX_NAME_LEN-1);
-        out->data.domainDefineReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
+        out->type = QEMUD_SERVER_PKT_DOMAIN_DEFINE;
+        memcpy(out->qemud_packet_server_data_u.domainDefineReply.uuid, vm->def->uuid, QEMUD_UUID_RAW_LEN);
+        strncpy(out->qemud_packet_server_data_u.domainDefineReply.name, vm->def->name, QEMUD_MAX_NAME_LEN-1);
+        out->qemud_packet_server_data_u.domainDefineReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
     }
     return 0;
 }
 
 static int qemudDispatchDomainUndefine(struct qemud_server *server, struct qemud_client *client,
-                                       struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.domainUndefineRequest))
-        return -1;
-
-    int ret = qemudDomainUndefine(server, in->data.domainUndefineRequest.uuid);
+                                       struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
+    int ret = qemudDomainUndefine(server, in->qemud_packet_client_data_u.domainUndefineRequest.uuid);
     if (ret < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_UNDEFINE;
-        out->header.dataSize = 0;
+        out->type = QEMUD_SERVER_PKT_DOMAIN_UNDEFINE;
     }
     return 0;
 }
 
 static int qemudDispatchNumNetworks(struct qemud_server *server, struct qemud_client *client,
-                                    struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != 0)
-        return -1;
-
+                                    struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     int nnetworks = qemudNumNetworks(server);
     if (nnetworks < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NUM_NETWORKS;
-        out->header.dataSize = sizeof(out->data.numNetworksReply);
-        out->data.numNetworksReply.numNetworks = nnetworks;
+        out->type = QEMUD_SERVER_PKT_NUM_NETWORKS;
+        out->qemud_packet_server_data_u.numNetworksReply.numNetworks = nnetworks;
     }
     return 0;
 }
 
 static int qemudDispatchListNetworks(struct qemud_server *server, struct qemud_client *client,
-                                     struct qemud_packet *in, struct qemud_packet *out) {
+                                     struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     char **names;
     int i;
-    if (in->header.dataSize != 0)
-        return -1;
 
     if (!(names = malloc(sizeof(char *)*QEMUD_MAX_NUM_NETWORKS)))
         return -1;
 
     for (i = 0 ; i < QEMUD_MAX_NUM_NETWORKS ; i++) {
-        names[i] = out->data.listNetworksReply.networks[i];
+        names[i] = &out->qemud_packet_server_data_u.listNetworksReply.networks[i*QEMUD_MAX_NAME_LEN];
     }
 
     int nnetworks = qemudListNetworks(server,
@@ -676,42 +593,35 @@ static int qemudDispatchListNetworks(str
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_LIST_NETWORKS;
-        out->header.dataSize = sizeof(out->data.listNetworksReply);
-        out->data.listNetworksReply.numNetworks = nnetworks;
+        out->type = QEMUD_SERVER_PKT_LIST_NETWORKS;
+        out->qemud_packet_server_data_u.listNetworksReply.numNetworks = nnetworks;
     }
     return 0;
 }
 
 static int qemudDispatchNumDefinedNetworks(struct qemud_server *server, struct qemud_client *client,
-                                           struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != 0)
-        return -1;
-
+                                           struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     int nnetworks = qemudNumDefinedNetworks(server);
     if (nnetworks < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NUM_DEFINED_NETWORKS;
-        out->header.dataSize = sizeof(out->data.numDefinedNetworksReply);
-        out->data.numDefinedNetworksReply.numNetworks = nnetworks;
+        out->type = QEMUD_SERVER_PKT_NUM_DEFINED_NETWORKS;
+        out->qemud_packet_server_data_u.numDefinedNetworksReply.numNetworks = nnetworks;
     }
     return 0;
 }
 
 static int qemudDispatchListDefinedNetworks(struct qemud_server *server, struct qemud_client *client,
-                                            struct qemud_packet *in, struct qemud_packet *out) {
+                                            struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     char **names;
     int i;
-    if (in->header.dataSize != 0)
-        return -1;
 
     if (!(names = malloc(sizeof(char *)*QEMUD_MAX_NUM_NETWORKS)))
         return -1;
 
     for (i = 0 ; i < QEMUD_MAX_NUM_NETWORKS ; i++) {
-        names[i] = out->data.listDefinedNetworksReply.networks[i];
+        names[i] = &out->qemud_packet_server_data_u.listDefinedNetworksReply.networks[i*QEMUD_MAX_NAME_LEN];
     }
 
     int nnetworks = qemudListDefinedNetworks(server,
@@ -722,276 +632,222 @@ static int qemudDispatchListDefinedNetwo
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_LIST_DEFINED_NETWORKS;
-        out->header.dataSize = sizeof(out->data.listDefinedNetworksReply);
-        out->data.listDefinedNetworksReply.numNetworks = nnetworks;
+        out->type = QEMUD_SERVER_PKT_LIST_DEFINED_NETWORKS;
+        out->qemud_packet_server_data_u.listDefinedNetworksReply.numNetworks = nnetworks;
     }
     return 0;
 }
 
 static int qemudDispatchNetworkLookupByName(struct qemud_server *server, struct qemud_client *client,
-                                            struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.networkLookupByNameRequest))
-        return -1;
-
+                                            struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     /* Paranoia NULL termination */
-    in->data.networkLookupByNameRequest.name[QEMUD_MAX_NAME_LEN-1] = '\0';
-    struct qemud_network *network = qemudFindNetworkByName(server, in->data.networkLookupByNameRequest.name);
+    in->qemud_packet_client_data_u.networkLookupByNameRequest.name[QEMUD_MAX_NAME_LEN-1] = '\0';
+    struct qemud_network *network = qemudFindNetworkByName(server, in->qemud_packet_client_data_u.networkLookupByNameRequest.name);
     if (!network) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NETWORK_LOOKUP_BY_NAME;
-        out->header.dataSize = sizeof(out->data.networkLookupByNameReply);
-        memcpy(out->data.networkLookupByNameReply.uuid, network->def->uuid, QEMUD_UUID_RAW_LEN);
+        out->type = QEMUD_SERVER_PKT_NETWORK_LOOKUP_BY_NAME;
+        memcpy(out->qemud_packet_server_data_u.networkLookupByNameReply.uuid, network->def->uuid, QEMUD_UUID_RAW_LEN);
     }
     return 0;
 }
 
 static int qemudDispatchNetworkLookupByUUID(struct qemud_server *server, struct qemud_client *client,
-                                            struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.networkLookupByUUIDRequest))
-        return -1;
-
-    struct qemud_network *network = qemudFindNetworkByUUID(server, in->data.networkLookupByUUIDRequest.uuid);
+                                            struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
+    struct qemud_network *network = qemudFindNetworkByUUID(server, in->qemud_packet_client_data_u.networkLookupByUUIDRequest.uuid);
     if (!network) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NETWORK_LOOKUP_BY_UUID;
-        out->header.dataSize = sizeof(out->data.networkLookupByUUIDReply);
-        strncpy(out->data.networkLookupByUUIDReply.name, network->def->name, QEMUD_MAX_NAME_LEN-1);
-        out->data.networkLookupByUUIDReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
+        out->type = QEMUD_SERVER_PKT_NETWORK_LOOKUP_BY_UUID;
+        strncpy(out->qemud_packet_server_data_u.networkLookupByUUIDReply.name, network->def->name, QEMUD_MAX_NAME_LEN-1);
+        out->qemud_packet_server_data_u.networkLookupByUUIDReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
     }
     return 0;
 }
 
 static int qemudDispatchNetworkCreate(struct qemud_server *server, struct qemud_client *client,
-                                      struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.networkCreateRequest))
-        return -1;
-
-    in->data.networkCreateRequest.xml[QEMUD_MAX_XML_LEN-1] ='\0';
+                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
+    in->qemud_packet_client_data_u.networkCreateRequest.xml[QEMUD_MAX_XML_LEN-1] ='\0';
 
-    struct qemud_network *network = qemudNetworkCreate(server, in->data.networkCreateRequest.xml);
+    struct qemud_network *network = qemudNetworkCreate(server, in->qemud_packet_client_data_u.networkCreateRequest.xml);
     if (!network) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NETWORK_CREATE;
-        out->header.dataSize = sizeof(out->data.networkCreateReply);
-        memcpy(out->data.networkCreateReply.uuid, network->def->uuid, QEMUD_UUID_RAW_LEN);
-        strncpy(out->data.networkCreateReply.name, network->def->name, QEMUD_MAX_NAME_LEN-1);
-        out->data.networkCreateReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
+        out->type = QEMUD_SERVER_PKT_NETWORK_CREATE;
+        memcpy(out->qemud_packet_server_data_u.networkCreateReply.uuid, network->def->uuid, QEMUD_UUID_RAW_LEN);
+        strncpy(out->qemud_packet_server_data_u.networkCreateReply.name, network->def->name, QEMUD_MAX_NAME_LEN-1);
+        out->qemud_packet_server_data_u.networkCreateReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
     }
     return 0;
 }
 
 static int qemudDispatchNetworkDefine(struct qemud_server *server, struct qemud_client *client,
-                                      struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.networkDefineRequest))
-        return -1;
+                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
+    in->qemud_packet_client_data_u.networkDefineRequest.xml[QEMUD_MAX_XML_LEN-1] ='\0';
 
-    in->data.networkDefineRequest.xml[QEMUD_MAX_XML_LEN-1] ='\0';
-
-    struct qemud_network *network = qemudNetworkDefine(server, in->data.networkDefineRequest.xml);
+    struct qemud_network *network = qemudNetworkDefine(server, in->qemud_packet_client_data_u.networkDefineRequest.xml);
     if (!network) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NETWORK_DEFINE;
-        out->header.dataSize = sizeof(out->data.networkDefineReply);
-        memcpy(out->data.networkDefineReply.uuid, network->def->uuid, QEMUD_UUID_RAW_LEN);
-        strncpy(out->data.networkDefineReply.name, network->def->name, QEMUD_MAX_NAME_LEN-1);
-        out->data.networkDefineReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
+        out->type = QEMUD_SERVER_PKT_NETWORK_DEFINE;
+        memcpy(out->qemud_packet_server_data_u.networkDefineReply.uuid, network->def->uuid, QEMUD_UUID_RAW_LEN);
+        strncpy(out->qemud_packet_server_data_u.networkDefineReply.name, network->def->name, QEMUD_MAX_NAME_LEN-1);
+        out->qemud_packet_server_data_u.networkDefineReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
     }
     return 0;
 }
 
 static int qemudDispatchNetworkUndefine(struct qemud_server *server, struct qemud_client *client,
-                                        struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.networkUndefineRequest))
-        return -1;
-
-    int ret = qemudNetworkUndefine(server, in->data.networkUndefineRequest.uuid);
+                                        struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
+    int ret = qemudNetworkUndefine(server, in->qemud_packet_client_data_u.networkUndefineRequest.uuid);
     if (ret < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NETWORK_UNDEFINE;
-        out->header.dataSize = 0;
+        out->type = QEMUD_SERVER_PKT_NETWORK_UNDEFINE;
     }
     return 0;
 }
 
 static int qemudDispatchNetworkStart(struct qemud_server *server, struct qemud_client *client,
-                                     struct qemud_packet *in, struct qemud_packet *out) {
+                                     struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     struct qemud_network *network;
 
-    if (in->header.dataSize != sizeof(in->data.networkStartRequest))
-        return -1;
-
-    if (!(network = qemudNetworkStart(server, in->data.networkStartRequest.uuid))) {
+    if (!(network = qemudNetworkStart(server, in->qemud_packet_client_data_u.networkStartRequest.uuid))) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NETWORK_START;
-        out->header.dataSize = 0;
+        out->type = QEMUD_SERVER_PKT_NETWORK_START;
     }
     return 0;
 }
 
 static int qemudDispatchNetworkDestroy(struct qemud_server *server, struct qemud_client *client,
-                                      struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.networkDestroyRequest))
-        return -1;
-
-    if (qemudNetworkDestroy(server, in->data.networkDestroyRequest.uuid) < 0) {
+                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
+    if (qemudNetworkDestroy(server, in->qemud_packet_client_data_u.networkDestroyRequest.uuid) < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NETWORK_DESTROY;
-        out->header.dataSize = 0;
+        out->type = QEMUD_SERVER_PKT_NETWORK_DESTROY;
     }
     return 0;
 }
 
 static int qemudDispatchNetworkDumpXML(struct qemud_server *server, struct qemud_client *client,
-                                      struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.networkDumpXMLRequest))
-        return -1;
-
+                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     int ret = qemudNetworkDumpXML(server,
-                                  in->data.networkDumpXMLRequest.uuid,
-                                  out->data.networkDumpXMLReply.xml, QEMUD_MAX_XML_LEN);
+                                  in->qemud_packet_client_data_u.networkDumpXMLRequest.uuid,
+                                  out->qemud_packet_server_data_u.networkDumpXMLReply.xml, QEMUD_MAX_XML_LEN);
     if (ret < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NETWORK_DUMP_XML;
-        out->header.dataSize = sizeof(out->data.networkDumpXMLReply);
+        out->type = QEMUD_SERVER_PKT_NETWORK_DUMP_XML;
     }
     return 0;
 }
 
 static int qemudDispatchNetworkGetBridgeName(struct qemud_server *server, struct qemud_client *client,
-                                             struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.networkGetBridgeNameRequest))
-        return -1;
-
+                                             struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     int ret = qemudNetworkGetBridgeName(server,
-                                        in->data.networkDumpXMLRequest.uuid,
-                                        out->data.networkGetBridgeNameReply.ifname, QEMUD_MAX_IFNAME_LEN);
+                                        in->qemud_packet_client_data_u.networkDumpXMLRequest.uuid,
+                                        out->qemud_packet_server_data_u.networkGetBridgeNameReply.ifname, QEMUD_MAX_IFNAME_LEN);
     if (ret < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NETWORK_GET_BRIDGE_NAME;
-        out->header.dataSize = sizeof(out->data.networkGetBridgeNameReply);
+        out->type = QEMUD_SERVER_PKT_NETWORK_GET_BRIDGE_NAME;
     }
     return 0;
 }
 
 static int qemudDispatchDomainGetAutostart(struct qemud_server *server, struct qemud_client *client,
-                                           struct qemud_packet *in, struct qemud_packet *out)
+                                           struct qemud_packet_client_data *in, struct qemud_packet_server_data *out)
 {
     int ret;
     int autostart;
 
-    if (in->header.dataSize != sizeof(in->data.domainGetAutostartRequest))
-        return -1;
-
     autostart = 0;
 
     ret = qemudDomainGetAutostart(server,
-                                  in->data.domainGetAutostartRequest.uuid,
+                                  in->qemud_packet_client_data_u.domainGetAutostartRequest.uuid,
                                   &autostart);
     if (ret < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_GET_AUTOSTART;
-        out->header.dataSize = sizeof(out->data.networkGetAutostartReply);
-        out->data.networkGetAutostartReply.autostart = (autostart != 0);
+        out->type = QEMUD_SERVER_PKT_DOMAIN_GET_AUTOSTART;
+        out->qemud_packet_server_data_u.networkGetAutostartReply.autostart = (autostart != 0);
     }
     return 0;
 }
 
 static int qemudDispatchDomainSetAutostart(struct qemud_server *server, struct qemud_client *client,
-                                           struct qemud_packet *in, struct qemud_packet *out)
+                                           struct qemud_packet_client_data *in, struct qemud_packet_server_data *out)
 {
     int ret;
 
-    if (in->header.dataSize != sizeof(in->data.domainSetAutostartRequest))
-        return -1;
-
     ret = qemudDomainSetAutostart(server,
-                                  in->data.domainGetAutostartRequest.uuid,
-                                  in->data.domainSetAutostartRequest.autostart);
+                                  in->qemud_packet_client_data_u.domainGetAutostartRequest.uuid,
+                                  in->qemud_packet_client_data_u.domainSetAutostartRequest.autostart);
     if (ret < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_SET_AUTOSTART;
-        out->header.dataSize = 0;
+        out->type = QEMUD_SERVER_PKT_DOMAIN_SET_AUTOSTART;
     }
     return 0;
 }
 
 static int qemudDispatchNetworkGetAutostart(struct qemud_server *server, struct qemud_client *client,
-                                            struct qemud_packet *in, struct qemud_packet *out)
+                                            struct qemud_packet_client_data *in, struct qemud_packet_server_data *out)
 {
     int ret;
     int autostart;
 
-    if (in->header.dataSize != sizeof(in->data.networkGetAutostartRequest))
-        return -1;
-
     autostart = 0;
 
     ret = qemudNetworkGetAutostart(server,
-                                   in->data.networkGetAutostartRequest.uuid,
+                                   in->qemud_packet_client_data_u.networkGetAutostartRequest.uuid,
                                    &autostart);
     if (ret < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NETWORK_GET_AUTOSTART;
-        out->header.dataSize = sizeof(out->data.networkGetAutostartReply);
-        out->data.networkGetAutostartReply.autostart = (autostart != 0);
+        out->type = QEMUD_SERVER_PKT_NETWORK_GET_AUTOSTART;
+        out->qemud_packet_server_data_u.networkGetAutostartReply.autostart = (autostart != 0);
     }
     return 0;
 }
 
 static int qemudDispatchNetworkSetAutostart(struct qemud_server *server, struct qemud_client *client,
-                                            struct qemud_packet *in, struct qemud_packet *out)
+                                            struct qemud_packet_client_data *in, struct qemud_packet_server_data *out)
 {
     int ret;
 
-    if (in->header.dataSize != sizeof(in->data.networkSetAutostartRequest))
-        return -1;
-
     ret = qemudNetworkSetAutostart(server,
-                                   in->data.networkGetAutostartRequest.uuid,
-                                   in->data.networkSetAutostartRequest.autostart);
+                                   in->qemud_packet_client_data_u.networkGetAutostartRequest.uuid,
+                                   in->qemud_packet_client_data_u.networkSetAutostartRequest.autostart);
     if (ret < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NETWORK_SET_AUTOSTART;
-        out->header.dataSize = 0;
+        out->type = QEMUD_SERVER_PKT_NETWORK_SET_AUTOSTART;
     }
     return 0;
 }
 
 typedef int (*clientFunc)(struct qemud_server *server, struct qemud_client *client,
-                          struct qemud_packet *in, struct qemud_packet *out);
+                          struct qemud_packet_client_data *in, struct qemud_packet_server_data *out);
 
 
 /* One per message type recorded in qemud_packet_type enum */
 
-clientFunc funcsTransmitRW[QEMUD_PKT_MAX] = {
-    NULL, /* FAILURE code */
+clientFunc funcsTransmitRW[QEMUD_CLIENT_PKT_MAX] = {
     qemudDispatchGetVersion,
     qemudDispatchGetNodeInfo,
     qemudDispatchListDomains,
@@ -1032,8 +888,7 @@ clientFunc funcsTransmitRW[QEMUD_PKT_MAX
     qemudDispatchGetCapabilities,
 };
 
-clientFunc funcsTransmitRO[QEMUD_PKT_MAX] = {
-    NULL, /* FAILURE code */
+clientFunc funcsTransmitRO[QEMUD_CLIENT_PKT_MAX] = {
     qemudDispatchGetVersion,
     qemudDispatchGetNodeInfo,
     qemudDispatchListDomains,
@@ -1084,22 +939,18 @@ clientFunc funcsTransmitRO[QEMUD_PKT_MAX
  * incoming type, or is QEMUD_PKT_FAILURE
  */
 int qemudDispatch(struct qemud_server *server, struct qemud_client *client,
-                  struct qemud_packet *in, struct qemud_packet *out) {
+                  qemud_packet_client_data *in, qemud_packet_server_data *out) {
     clientFunc *funcs;
-    unsigned int type = in->header.type;
-    qemudDebug("> Dispatching request %d readonly ? %d", type, client->readonly);
+    unsigned int type = in->type;
+    qemudDebug("> Dispatching request type %d, readonly ? %d",
+               in->type, client->readonly);
 
     server->errorCode = 0;
     server->errorMessage[0] = '\0';
 
-    memset(out, 0, sizeof(struct qemud_packet));
+    memset(out, 0, sizeof(*out));
 
-    if (type >= QEMUD_PKT_MAX) {
-        qemudDebug("Illegal request type");
-        return -1;
-    }
-
-    if (type == QEMUD_PKT_FAILURE) {
+    if (type >= QEMUD_CLIENT_PKT_MAX) {
         qemudDebug("Illegal request type");
         return -1;
     }
@@ -1116,18 +967,15 @@ int qemudDispatch(struct qemud_server *s
     } else {
         if ((funcs[type])(server, client, in, out) < 0) {
             qemudDebug("Dispatch failed");
-            return -1;
+            return 0;
         }
     }
 
-    qemudDebug("< Returning reply %d (%d bytes)",
-           out->header.type,
-           out->header.dataSize);
+    qemudDebug("< Returning reply %d", out->type);
 
     return 0;
 }
 
-
 /*
  * Local variables:
  *  indent-tabs-mode: nil
Index: qemud/dispatch.h
===================================================================
RCS file: /data/cvs/libvirt/qemud/dispatch.h,v
retrieving revision 1.1
diff -u -p -u -p -r1.1 dispatch.h
--- qemud/dispatch.h	14 Feb 2007 01:40:09 -0000	1.1
+++ qemud/dispatch.h	22 Mar 2007 19:47:11 -0000
@@ -29,7 +29,7 @@
 
 
 int qemudDispatch(struct qemud_server *server, struct qemud_client *client,
-                  struct qemud_packet *in, struct qemud_packet *out);
+                  struct qemud_packet_client_data *in, struct qemud_packet_server_data *out);
 
 #endif
 
Index: qemud/internal.h
===================================================================
RCS file: /data/cvs/libvirt/qemud/internal.h,v
retrieving revision 1.21
diff -u -p -u -p -r1.21 internal.h
--- qemud/internal.h	16 Mar 2007 15:03:21 -0000	1.21
+++ qemud/internal.h	22 Mar 2007 19:47:11 -0000
@@ -272,15 +272,26 @@ struct qemud_network {
     struct qemud_network *next;
 };
 
+
+enum {
+    QEMUD_MODE_RX_HEADER,
+    QEMUD_MODE_RX_PAYLOAD,
+    QEMUD_MODE_TX_PACKET,
+};
+
 /* Stores the per-client connection state */
 struct qemud_client {
     int fd;
     int readonly;
-    struct qemud_packet incoming;
-    unsigned int incomingReceived;
-    struct qemud_packet outgoing;
-    unsigned int outgoingSent;
-    int tx;
+    int mode;
+
+    unsigned int incomingSerial;
+    unsigned int outgoingSerial;
+
+    char buffer[QEMUD_PKT_PACKET_XDR_LEN];
+    unsigned int bufferLength;
+    unsigned int bufferOffset;
+
     struct qemud_client *next;
 };
 
Index: qemud/qemud.c
===================================================================
RCS file: /data/cvs/libvirt/qemud/qemud.c,v
retrieving revision 1.34
diff -u -p -u -p -r1.34 qemud.c
--- qemud/qemud.c	22 Mar 2007 18:30:57 -0000	1.34
+++ qemud/qemud.c	22 Mar 2007 19:47:12 -0000
@@ -522,6 +522,8 @@ static int qemudDispatchServer(struct qe
     client = calloc(1, sizeof(struct qemud_client));
     client->fd = fd;
     client->readonly = sock->readonly;
+    client->mode = QEMUD_MODE_RX_HEADER;
+    client->bufferLength = QEMUD_PKT_HEADER_XDR_LEN;
 
     client->next = server->clients;
     server->clients = client;
@@ -902,108 +904,179 @@ static void qemudDispatchClientFailure(s
 }
 
 
-static int qemudDispatchClientRequest(struct qemud_server *server, struct qemud_client *client) {
+static void qemudDispatchClientRequest(struct qemud_server *server,
+                                       struct qemud_client *client,
+                                       qemud_packet_client *req) {
+    qemud_packet_server res;
+    qemud_packet_header h;
+    XDR x;
+
+    if (req->serial != ++client->incomingSerial) {
+        qemudDebug("Invalid serial number. Got %d expect %d",
+                   req->serial, client->incomingSerial);
+        qemudDispatchClientFailure(server, client);
+        return;
+    }
+
     if (qemudDispatch(server,
                       client,
-                      &client->incoming,
-                      &client->outgoing) < 0) {
-        return -1;
+                      &req->data,
+                      &res.data) < 0) {
+        qemudDispatchClientFailure(server, client);
+        return;
     }
 
-    client->outgoingSent = 0;
-    client->tx = 1;
-    client->incomingReceived = 0;
+    res.serial = ++client->outgoingSerial;
+    res.inReplyTo = req->serial;
 
-    return 0;
+    /*
+     * We have to encode the payload first, to find out its
+     * encoded size, which we then put into the header. Fun
+     */
+    xdrmem_create(&x,
+                  client->buffer+QEMUD_PKT_HEADER_XDR_LEN,
+                  QEMUD_PKT_PAYLOAD_XDR_LEN, XDR_ENCODE);
+
+    if (!xdr_qemud_packet_server(&x, &res)) {
+        qemudDebug("Failed to XDR encode reply payload");
+        qemudDispatchClientFailure(server, client);
+        return;
+    }
+
+    /* Now we're ready to encode the header */
+    h.magic = QEMUD_PKT_HEADER_MAGIC;
+    h.length = xdr_getpos(&x);
+
+    xdrmem_create(&x, client->buffer,
+                  QEMUD_PKT_HEADER_XDR_LEN, XDR_ENCODE);
+
+    if (!xdr_qemud_packet_header(&x, &h)) {
+        qemudDebug("Failed to XDR encode reply header");
+        qemudDispatchClientFailure(server, client);
+        return;
+    }
+
+    client->mode = QEMUD_MODE_TX_PACKET;
+    client->bufferLength = QEMUD_PKT_HEADER_XDR_LEN + h.length;
+    client->bufferOffset = 0;
 }
 
 static int qemudClientRead(struct qemud_server *server,
-                           struct qemud_client *client,
-                           char *buf, size_t want) {
+                           struct qemud_client *client) {
     int ret;
-    if ((ret = read(client->fd, buf, want)) <= 0) {
+    if ((ret = read(client->fd,
+                    client->buffer + client->bufferOffset,
+                    client->bufferLength - client->bufferOffset)) <= 0) {
         qemudDebug("Plain read error %d", ret);
         if (!ret || errno != EAGAIN)
             qemudDispatchClientFailure(server, client);
         return -1;
     }
     qemudDebug("Plain data read %d", ret);
-    return ret;
+    client->bufferOffset += ret;
+    return 0;
 }
 
 static void qemudDispatchClientRead(struct qemud_server *server, struct qemud_client *client) {
-    char *data = (char *)&client->incoming;
-    unsigned int got = client->incomingReceived;
-    int want;
-    int ret;
 
- restart:
-    if (got >= sizeof(struct qemud_packet_header)) {
-        want = sizeof(struct qemud_packet_header) + client->incoming.header.dataSize - got;
-    } else {
-        want = sizeof(struct qemud_packet_header) - got;
-    }
+    if (client->mode == QEMUD_MODE_RX_HEADER) {
+        XDR x;
+        qemud_packet_header h;
 
-    if ((ret = qemudClientRead(server, client, data+got, want)) < 0) {
-        return;
-    }
-    got += ret;
-    client->incomingReceived += ret;
+        if (qemudClientRead(server, client) < 0)
+            return; /* Error, or blocking */
+
+        if (client->bufferOffset < client->bufferLength)
+            return; /* Not read enough */
+
+        xdrmem_create(&x, client->buffer, client->bufferLength, XDR_DECODE);
+        memset(&h, 0, sizeof(h));
+
+        if (!xdr_qemud_packet_header(&x, &h)) {
+            qemudDebug("Failed to decode packet header");
+            qemudDispatchClientFailure(server, client);
+            return;
+        }
 
-    /* If we've finished header, move onto body */
-    if (client->incomingReceived == sizeof(struct qemud_packet_header)) {
-        qemudDebug("Type %d, data %d",
-                    client->incoming.header.type,
-                    client->incoming.header.dataSize);
-        /* Client lied about dataSize */
-        if (client->incoming.header.dataSize > sizeof(union qemud_packet_data)) {
-            qemudDebug("Bogus data size %u", client->incoming.header.dataSize);
+        if (h.magic != QEMUD_PKT_HEADER_MAGIC) {
+            qemudDebug("Header magic byte %u mismatched", h.magic);
             qemudDispatchClientFailure(server, client);
             return;
         }
-        if (client->incoming.header.dataSize) {
-            qemudDebug("- Restarting recv to process body (%d bytes)",
-                        client->incoming.header.dataSize);
-            goto restart;
+
+        if (h.length > QEMUD_PKT_PAYLOAD_XDR_LEN) {
+            qemudDebug("Packet length %u too large", h.length);
+            qemudDispatchClientFailure(server, client);
+            return;
         }
+
+        client->mode = QEMUD_MODE_RX_PAYLOAD;
+        client->bufferLength = h.length;
+        client->bufferOffset = 0;
+
+        /* Fall through */
     }
 
-    /* If we've finished body, dispatch the request */
-    if (ret == want) {
-        if (qemudDispatchClientRequest(server, client) < 0)
+    if (client->mode == QEMUD_MODE_RX_PAYLOAD) {
+        XDR x;
+        qemud_packet_client p;
+
+        if (qemudClientRead(server, client) < 0)
+            return; /* Error, or blocking */
+
+        if (client->bufferOffset < client->bufferLength)
+            return; /* Not read enough */
+
+        xdrmem_create(&x, client->buffer, client->bufferLength, XDR_DECODE);
+        memset(&p, 0, sizeof(p));
+
+        if (!xdr_qemud_packet_client(&x, &p)) {
+            qemudDebug("Failed to decode client packet");
             qemudDispatchClientFailure(server, client);
-        qemudDebug("Dispatch");
+            return;
+        }
+
+        qemudDispatchClientRequest(server, client, &p);
+    } else {
+        qemudDebug("Got unexpected data read while in %d mode", client->mode);
+        qemudDispatchClientFailure(server, client);
     }
 }
 
 
 static int qemudClientWrite(struct qemud_server *server,
-                           struct qemud_client *client,
-                           char *buf, size_t want) {
+                            struct qemud_client *client) {
     int ret;
-    if ((ret = write(client->fd, buf, want)) < 0) {
+    if ((ret = write(client->fd,
+                     client->buffer + client->bufferOffset,
+                     client->bufferLength - client->bufferOffset)) < 0) {
         qemudDebug("Plain write error %d", ret);
         if (errno != EAGAIN)
             qemudDispatchClientFailure(server, client);
         return -1;
     }
+    client->bufferOffset += ret;
     qemudDebug("Plain data write %d", ret);
-    return ret;
+    return 0;
 }
 
 
 static void qemudDispatchClientWrite(struct qemud_server *server, struct qemud_client *client) {
-    char *data = (char *)&client->outgoing;
-    int sent = client->outgoingSent;
-    int todo = sizeof(struct qemud_packet_header) + client->outgoing.header.dataSize - sent;
-    int ret;
-    if ((ret = qemudClientWrite(server, client, data+sent, todo)) < 0) {
-        return;
+    if (client->mode == QEMUD_MODE_TX_PACKET) {
+        if (qemudClientWrite(server, client) < 0)
+            return;
+
+        if (client->bufferOffset == client->bufferLength) {
+            /* Done writing, switch back to receive */
+            client->mode = QEMUD_MODE_RX_HEADER;
+            client->bufferLength = QEMUD_PKT_HEADER_XDR_LEN;
+            client->bufferOffset = 0;
+        }
+        /* Still writing */
+    } else {
+        qemudDebug("Got unexpected data write while in %d mode", client->mode);
+        qemudDispatchClientFailure(server, client);
     }
-    client->outgoingSent += ret;
-    qemudDebug("Done %d %d", todo, ret);
-    if (todo == ret)
-        client->tx = 0;
 }
 
 static int qemudVMData(struct qemud_server *server ATTRIBUTE_UNUSED,
@@ -1635,7 +1708,7 @@ static void qemudPreparePoll(struct qemu
         fds[fd].fd = client->fd;
         /* Refuse to read more from client if tx is pending to
            rate limit */
-        if (client->tx)
+        if (client->mode == QEMUD_MODE_TX_PACKET)
             fds[fd].events = POLLOUT | POLLERR | POLLHUP;
         else
             fds[fd].events = POLLIN | POLLERR | POLLHUP;
Index: qemud/uuid.c
===================================================================
RCS file: /data/cvs/libvirt/qemud/uuid.c,v
retrieving revision 1.2
diff -u -p -u -p -r1.2 uuid.c
--- qemud/uuid.c	26 Feb 2007 15:34:24 -0000	1.2
+++ qemud/uuid.c	22 Mar 2007 19:47:12 -0000
@@ -32,7 +32,6 @@
 #include <time.h>
 #include <unistd.h>
 
-#include "protocol.h"
 #include "internal.h"
 
 static int


More information about the libvir-list mailing list