[libvirt] [PATCH 01/12] Defines the basics of a generic RPC protocol in XDR

Daniel P. Berrange berrange at redhat.com
Fri Mar 18 18:54:16 UTC 2011


This patch defines the basics of a generic RPC protocol in XDR.
This is wire ABI compatible with the original remote_protocol.x.
It takes everything except for the RPC calls / events from that
protocol

 - The basic header virNetMessageHeader (aka remote_message_header)
 - The error object virNetMessageError  (aka remote_error)
 - Two dummy objects virNetMessageDomain & virNetMessageNetwork
   sadly needed to keep virNetMessageError ABI compatible with
   the old remote_error

The RPC protocol supports method calls, async events and
bidirectional data streams as before

* src/Makefile.am: Add rules for generating RPC code from
  protocol & define a new libvirt-net-rpc.la helper library
* src/rpc/virnetprotocol.x: New generic RPC protocol
* src/rpc/virnetprotocol.c, src/rpc/virnetprotocol.h: Generated
  from virnetprotocol.x
---
 cfg.mk                   |    2 +-
 src/Makefile.am          |   34 +++++++-
 src/rpc/virnetprotocol.c |  207 +++++++++++++++++++++++++++++++++++++++++++
 src/rpc/virnetprotocol.h |  137 +++++++++++++++++++++++++++++
 src/rpc/virnetprotocol.x |  217 ++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 595 insertions(+), 2 deletions(-)
 create mode 100644 src/rpc/virnetprotocol.c
 create mode 100644 src/rpc/virnetprotocol.h
 create mode 100644 src/rpc/virnetprotocol.x

diff --git a/cfg.mk b/cfg.mk
index 2076173..a7120e2 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -454,7 +454,7 @@ sc_prohibit_newline_at_end_of_diagnostic:
 	    exit 1; } || :
 
 # Regex for grep -E that exempts generated files from style rules.
-preprocessor_exempt = ((qemu|remote)_(driver|protocol)\.h)$$
+preprocessor_exempt = ((qemu_|remote_|virnet)(protocol)\.h)$$
 # Enforce recommended preprocessor indentation style.
 sc_preprocessor_indentation:
 	@if cppi --version >/dev/null 2>&1; then			\
diff --git a/src/Makefile.am b/src/Makefile.am
index 1d8115b..e575a61 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -577,6 +577,24 @@ else
 	mv -f rp_qemu.c-t $(srcdir)/remote/qemu_protocol.c
 endif
 
+rpcgen-net:
+	rm -f rp_net.c-t rp_net.h-t rp_net.c-t1 rp_net.c-t2 rp_net.h-t1
+	$(RPCGEN) -h -o rp_net.h-t $(srcdir)/rpc/virnetprotocol.x
+	$(RPCGEN) -c -o rp_net.c-t $(srcdir)/rpc/virnetprotocol.x
+if HAVE_GLIBC_RPCGEN
+	perl -w $(srcdir)/remote/rpcgen_fix.pl rp_net.h-t > rp_net.h-t1
+	perl -w $(srcdir)/remote/rpcgen_fix.pl rp_net.c-t > rp_net.c-t1
+	(echo '#include <config.h>'; cat rp_net.c-t1) > rp_net.c-t2
+	chmod 0444 rp_net.c-t2 rp_net.h-t1
+	mv -f rp_net.h-t1 $(srcdir)/rpc/virnetprotocol.h
+	mv -f rp_net.c-t2 $(srcdir)/rpc/virnetprotocol.c
+	rm -f rp_net.c-t rp_net.h-t rp_net.c-t1
+else
+	chmod 0444 rp_net.c-t rp_net.h-t
+	mv -f rp_net.h-t $(srcdir)/rpc/virnetprotocol.h
+	mv -f rp_net.c-t $(srcdir)/rpc/virnetprotocol.c
+endif
+
 #
 # Maintainer-only target for re-generating the derived .c/.h source
 # files, which are actually derived from the .x file.
@@ -587,7 +605,7 @@ endif
 # Support for non-GLIB rpcgen is here as a convenience for
 # non-Linux people needing to test changes during dev.
 #
-rpcgen: rpcgen-normal rpcgen-qemu
+rpcgen: rpcgen-normal rpcgen-qemu rpcgen-net
 
 endif
 
@@ -1204,6 +1222,20 @@ libvirt_qemu_la_CFLAGS = $(AM_CFLAGS)
 libvirt_qemu_la_LIBADD = libvirt.la $(CYGWIN_EXTRA_LIBADD)
 EXTRA_DIST += $(LIBVIRT_QEMU_SYMBOL_FILE)
 
+
+noinst_LTLIBRARIES += libvirt-net-rpc.la
+
+libvirt_net_rpc_la_SOURCES = \
+	rpc/virnetprotocol.h rpc/virnetprotocol.c
+libvirt_net_rpc_la_CFLAGS = \
+			$(AM_CFLAGS)
+libvirt_net_rpc_la_LDFLAGS = \
+			$(AM_LDFLAGS) \
+			$(CYGWIN_EXTRA_LDFLAGS) \
+			$(MINGW_EXTRA_LDFLAGS)
+libvirt_net_rpc_la_LIBADD = \
+			$(CYGWIN_EXTRA_LIBADD)
+
 libexec_PROGRAMS =
 
 libexec_PROGRAMS += libvirt_iohelper
diff --git a/src/rpc/virnetprotocol.c b/src/rpc/virnetprotocol.c
new file mode 100644
index 0000000..0484267
--- /dev/null
+++ b/src/rpc/virnetprotocol.c
@@ -0,0 +1,207 @@
+#include <config.h>
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#include "./rpc/virnetprotocol.h"
+#include "internal.h"
+#include <arpa/inet.h>
+#ifdef HAVE_XDR_U_INT64_T
+# define xdr_uint64_t xdr_u_int64_t
+#endif
+#ifndef IXDR_PUT_INT32
+# define IXDR_PUT_INT32 IXDR_PUT_LONG
+#endif
+#ifndef IXDR_GET_INT32
+# define IXDR_GET_INT32 IXDR_GET_LONG
+#endif
+#ifndef IXDR_PUT_U_INT32
+# define IXDR_PUT_U_INT32 IXDR_PUT_U_LONG
+#endif
+#ifndef IXDR_GET_U_INT32
+# define IXDR_GET_U_INT32 IXDR_GET_U_LONG
+#endif
+
+bool_t
+xdr_virNetMessageType (XDR *xdrs, virNetMessageType *objp)
+{
+
+         if (!xdr_enum (xdrs, (enum_t *) objp))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_virNetMessageStatus (XDR *xdrs, virNetMessageStatus *objp)
+{
+
+         if (!xdr_enum (xdrs, (enum_t *) objp))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_virNetMessageHeader (XDR *xdrs, virNetMessageHeader *objp)
+{
+        register int32_t *buf;
+
+
+        if (xdrs->x_op == XDR_ENCODE) {
+                buf = (int32_t*)XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT);
+                if (buf == NULL) {
+                         if (!xdr_u_int (xdrs, &objp->prog))
+                                 return FALSE;
+                         if (!xdr_u_int (xdrs, &objp->vers))
+                                 return FALSE;
+                         if (!xdr_int (xdrs, &objp->proc))
+                                 return FALSE;
+
+                } else {
+                (void)IXDR_PUT_U_INT32(buf, objp->prog);
+                (void)IXDR_PUT_U_INT32(buf, objp->vers);
+                (void)IXDR_PUT_INT32(buf, objp->proc);
+                }
+                 if (!xdr_virNetMessageType (xdrs, &objp->type))
+                         return FALSE;
+                 if (!xdr_u_int (xdrs, &objp->serial))
+                         return FALSE;
+                 if (!xdr_virNetMessageStatus (xdrs, &objp->status))
+                         return FALSE;
+                return TRUE;
+        } else if (xdrs->x_op == XDR_DECODE) {
+                buf = (int32_t*)XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT);
+                if (buf == NULL) {
+                         if (!xdr_u_int (xdrs, &objp->prog))
+                                 return FALSE;
+                         if (!xdr_u_int (xdrs, &objp->vers))
+                                 return FALSE;
+                         if (!xdr_int (xdrs, &objp->proc))
+                                 return FALSE;
+
+                } else {
+                objp->prog = IXDR_GET_U_LONG(buf);
+                objp->vers = IXDR_GET_U_LONG(buf);
+                objp->proc = IXDR_GET_INT32(buf);
+                }
+                 if (!xdr_virNetMessageType (xdrs, &objp->type))
+                         return FALSE;
+                 if (!xdr_u_int (xdrs, &objp->serial))
+                         return FALSE;
+                 if (!xdr_virNetMessageStatus (xdrs, &objp->status))
+                         return FALSE;
+         return TRUE;
+        }
+
+         if (!xdr_u_int (xdrs, &objp->prog))
+                 return FALSE;
+         if (!xdr_u_int (xdrs, &objp->vers))
+                 return FALSE;
+         if (!xdr_int (xdrs, &objp->proc))
+                 return FALSE;
+         if (!xdr_virNetMessageType (xdrs, &objp->type))
+                 return FALSE;
+         if (!xdr_u_int (xdrs, &objp->serial))
+                 return FALSE;
+         if (!xdr_virNetMessageStatus (xdrs, &objp->status))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_virNetMessageUUID (XDR *xdrs, virNetMessageUUID objp)
+{
+
+         if (!xdr_opaque (xdrs, objp, VIR_UUID_BUFLEN))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_virNetMessageNonnullString (XDR *xdrs, virNetMessageNonnullString *objp)
+{
+
+         if (!xdr_string (xdrs, objp, VIR_NET_MESSAGE_STRING_MAX))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_virNetMessageString (XDR *xdrs, virNetMessageString *objp)
+{
+
+         if (!xdr_pointer (xdrs, (char **)objp, sizeof (virNetMessageNonnullString), (xdrproc_t) xdr_virNetMessageNonnullString))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_virNetMessageNonnullDomain (XDR *xdrs, virNetMessageNonnullDomain *objp)
+{
+
+         if (!xdr_virNetMessageNonnullString (xdrs, &objp->name))
+                 return FALSE;
+         if (!xdr_virNetMessageUUID (xdrs, objp->uuid))
+                 return FALSE;
+         if (!xdr_int (xdrs, &objp->id))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_virNetMessageNonnullNetwork (XDR *xdrs, virNetMessageNonnullNetwork *objp)
+{
+
+         if (!xdr_virNetMessageNonnullString (xdrs, &objp->name))
+                 return FALSE;
+         if (!xdr_virNetMessageUUID (xdrs, objp->uuid))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_virNetMessageDomain (XDR *xdrs, virNetMessageDomain *objp)
+{
+
+         if (!xdr_pointer (xdrs, (char **)objp, sizeof (virNetMessageNonnullDomain), (xdrproc_t) xdr_virNetMessageNonnullDomain))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_virNetMessageNetwork (XDR *xdrs, virNetMessageNetwork *objp)
+{
+
+         if (!xdr_pointer (xdrs, (char **)objp, sizeof (virNetMessageNonnullNetwork), (xdrproc_t) xdr_virNetMessageNonnullNetwork))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_virNetMessageError (XDR *xdrs, virNetMessageError *objp)
+{
+
+         if (!xdr_int (xdrs, &objp->code))
+                 return FALSE;
+         if (!xdr_int (xdrs, &objp->domain))
+                 return FALSE;
+         if (!xdr_virNetMessageString (xdrs, &objp->message))
+                 return FALSE;
+         if (!xdr_int (xdrs, &objp->level))
+                 return FALSE;
+         if (!xdr_virNetMessageDomain (xdrs, &objp->dom))
+                 return FALSE;
+         if (!xdr_virNetMessageString (xdrs, &objp->str1))
+                 return FALSE;
+         if (!xdr_virNetMessageString (xdrs, &objp->str2))
+                 return FALSE;
+         if (!xdr_virNetMessageString (xdrs, &objp->str3))
+                 return FALSE;
+         if (!xdr_int (xdrs, &objp->int1))
+                 return FALSE;
+         if (!xdr_int (xdrs, &objp->int2))
+                 return FALSE;
+         if (!xdr_virNetMessageNetwork (xdrs, &objp->net))
+                 return FALSE;
+        return TRUE;
+}
diff --git a/src/rpc/virnetprotocol.h b/src/rpc/virnetprotocol.h
new file mode 100644
index 0000000..4f4c331
--- /dev/null
+++ b/src/rpc/virnetprotocol.h
@@ -0,0 +1,137 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#ifndef _RP_NET_H_RPCGEN
+#define _RP_NET_H_RPCGEN
+
+#include <rpc/rpc.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "internal.h"
+#include <arpa/inet.h>
+#ifdef HAVE_XDR_U_INT64_T
+# define xdr_uint64_t xdr_u_int64_t
+#endif
+#ifndef IXDR_PUT_INT32
+# define IXDR_PUT_INT32 IXDR_PUT_LONG
+#endif
+#ifndef IXDR_GET_INT32
+# define IXDR_GET_INT32 IXDR_GET_LONG
+#endif
+#ifndef IXDR_PUT_U_INT32
+# define IXDR_PUT_U_INT32 IXDR_PUT_U_LONG
+#endif
+#ifndef IXDR_GET_U_INT32
+# define IXDR_GET_U_INT32 IXDR_GET_U_LONG
+#endif
+#define VIR_NET_MESSAGE_MAX 262144
+#define VIR_NET_MESSAGE_HEADER_MAX 24
+#define VIR_NET_MESSAGE_PAYLOAD_MAX 262120
+#define VIR_NET_MESSAGE_LEN_MAX 4
+#define VIR_NET_MESSAGE_STRING_MAX 65536
+
+enum virNetMessageType {
+        VIR_NET_CALL = 0,
+        VIR_NET_REPLY = 1,
+        VIR_NET_MESSAGE = 2,
+        VIR_NET_STREAM = 3,
+};
+typedef enum virNetMessageType virNetMessageType;
+
+enum virNetMessageStatus {
+        VIR_NET_OK = 0,
+        VIR_NET_ERROR = 1,
+        VIR_NET_CONTINUE = 2,
+};
+typedef enum virNetMessageStatus virNetMessageStatus;
+#define VIR_NET_MESSAGE_HEADER_XDR_LEN 4
+
+struct virNetMessageHeader {
+        u_int prog;
+        u_int vers;
+        int proc;
+        virNetMessageType type;
+        u_int serial;
+        virNetMessageStatus status;
+};
+typedef struct virNetMessageHeader virNetMessageHeader;
+
+typedef char virNetMessageUUID[VIR_UUID_BUFLEN];
+
+typedef char *virNetMessageNonnullString;
+
+typedef virNetMessageNonnullString *virNetMessageString;
+
+struct virNetMessageNonnullDomain {
+        virNetMessageNonnullString name;
+        virNetMessageUUID uuid;
+        int id;
+};
+typedef struct virNetMessageNonnullDomain virNetMessageNonnullDomain;
+
+struct virNetMessageNonnullNetwork {
+        virNetMessageNonnullString name;
+        virNetMessageUUID uuid;
+};
+typedef struct virNetMessageNonnullNetwork virNetMessageNonnullNetwork;
+
+typedef virNetMessageNonnullDomain *virNetMessageDomain;
+
+typedef virNetMessageNonnullNetwork *virNetMessageNetwork;
+
+struct virNetMessageError {
+        int code;
+        int domain;
+        virNetMessageString message;
+        int level;
+        virNetMessageDomain dom;
+        virNetMessageString str1;
+        virNetMessageString str2;
+        virNetMessageString str3;
+        int int1;
+        int int2;
+        virNetMessageNetwork net;
+};
+typedef struct virNetMessageError virNetMessageError;
+
+/* the xdr functions */
+
+#if defined(__STDC__) || defined(__cplusplus)
+extern  bool_t xdr_virNetMessageType (XDR *, virNetMessageType*);
+extern  bool_t xdr_virNetMessageStatus (XDR *, virNetMessageStatus*);
+extern  bool_t xdr_virNetMessageHeader (XDR *, virNetMessageHeader*);
+extern  bool_t xdr_virNetMessageUUID (XDR *, virNetMessageUUID);
+extern  bool_t xdr_virNetMessageNonnullString (XDR *, virNetMessageNonnullString*);
+extern  bool_t xdr_virNetMessageString (XDR *, virNetMessageString*);
+extern  bool_t xdr_virNetMessageNonnullDomain (XDR *, virNetMessageNonnullDomain*);
+extern  bool_t xdr_virNetMessageNonnullNetwork (XDR *, virNetMessageNonnullNetwork*);
+extern  bool_t xdr_virNetMessageDomain (XDR *, virNetMessageDomain*);
+extern  bool_t xdr_virNetMessageNetwork (XDR *, virNetMessageNetwork*);
+extern  bool_t xdr_virNetMessageError (XDR *, virNetMessageError*);
+
+#else /* K&R C */
+extern bool_t xdr_virNetMessageType ();
+extern bool_t xdr_virNetMessageStatus ();
+extern bool_t xdr_virNetMessageHeader ();
+extern bool_t xdr_virNetMessageUUID ();
+extern bool_t xdr_virNetMessageNonnullString ();
+extern bool_t xdr_virNetMessageString ();
+extern bool_t xdr_virNetMessageNonnullDomain ();
+extern bool_t xdr_virNetMessageNonnullNetwork ();
+extern bool_t xdr_virNetMessageDomain ();
+extern bool_t xdr_virNetMessageNetwork ();
+extern bool_t xdr_virNetMessageError ();
+
+#endif /* K&R C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_RP_NET_H_RPCGEN */
diff --git a/src/rpc/virnetprotocol.x b/src/rpc/virnetprotocol.x
new file mode 100644
index 0000000..15066b8
--- /dev/null
+++ b/src/rpc/virnetprotocol.x
@@ -0,0 +1,217 @@
+/* -*- c -*-
+ * virnetprotocol.x: basic protocol for all RPC services.
+ *
+ * Copyright (C) 2006-2010 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Author: Richard Jones <rjones at redhat.com>
+ */
+
+%#include "internal.h"
+%#include <arpa/inet.h>
+
+/* cygwin's xdr implementation defines xdr_u_int64_t instead of xdr_uint64_t
+ * and lacks IXDR_PUT_INT32 and IXDR_GET_INT32
+ */
+%#ifdef HAVE_XDR_U_INT64_T
+%# define xdr_uint64_t xdr_u_int64_t
+%#endif
+%#ifndef IXDR_PUT_INT32
+%# define IXDR_PUT_INT32 IXDR_PUT_LONG
+%#endif
+%#ifndef IXDR_GET_INT32
+%# define IXDR_GET_INT32 IXDR_GET_LONG
+%#endif
+%#ifndef IXDR_PUT_U_INT32
+%# define IXDR_PUT_U_INT32 IXDR_PUT_U_LONG
+%#endif
+%#ifndef IXDR_GET_U_INT32
+%# define IXDR_GET_U_INT32 IXDR_GET_U_LONG
+%#endif
+
+/*----- Data types. -----*/
+
+/* Maximum total message size (serialised). */
+const VIR_NET_MESSAGE_MAX = 262144;
+
+/* Size of struct virNetMessageHeader (serialised)*/
+const VIR_NET_MESSAGE_HEADER_MAX = 24;
+
+/* Size of message payload */
+const VIR_NET_MESSAGE_PAYLOAD_MAX = 262120;
+
+/* Size of message length field. Not counted in VIR_NET_MESSAGE_MAX */
+const VIR_NET_MESSAGE_LEN_MAX = 4;
+
+/* Length of long, but not unbounded, strings.
+ * This is an arbitrary limit designed to stop the decoder from trying
+ * to allocate unbounded amounts of memory when fed with a bad message.
+ */
+const VIR_NET_MESSAGE_STRING_MAX = 65536;
+
+/*
+ * RPC wire format
+ *
+ * Each message consists of:
+ *
+ *    Name    | Type                  | Description
+ * -----------+-----------------------+------------------
+ *    Length  | int                   | Total number of bytes in message _including_ length.
+ *    Header  | virNetMessageHeader   | Control information about procedure call
+ *    Payload | -                     | Variable payload data per procedure
+ *
+ * In header, the 'serial' field varies according to:
+ *
+ *  - type == VIR_NET_CALL
+ *      * serial is set by client, incrementing by 1 each time
+ *
+ *  - type == VIR_NET_REPLY
+ *      * serial matches that from the corresponding VIR_NET_CALL
+ *
+ *  - type == VIR_NET_MESSAGE
+ *      * serial is always zero
+ *
+ *  - type == VIR_NET_STREAM
+ *      * serial matches that from the corresponding VIR_NET_CALL
+ *
+ * and the 'status' field varies according to:
+ *
+ *  - type == VIR_NET_CALL
+ *     * VIR_NET_OK always
+ *
+ *  - type == VIR_NET_REPLY
+ *     * VIR_NET_OK if RPC finished successfully
+ *     * VIR_NET_ERROR if something failed
+ *
+ *  - type == VIR_NET_MESSAGE
+ *     * VIR_NET_OK always
+ *
+ *  - type == VIR_NET_STREAM
+ *     * VIR_NET_CONTINUE if more data is following
+ *     * VIR_NET_OK if stream is complete
+ *     * VIR_NET_ERROR if stream had an error
+ *
+ * Payload varies according to type and status:
+ *
+ *  - type == VIR_NET_CALL
+ *          XXX_args  for procedure
+ *
+ *  - type == VIR_NET_REPLY
+ *     * status == VIR_NET_OK
+ *          XXX_ret         for procedure
+ *     * status == VIR_NET_ERROR
+ *          remote_error    Error information
+ *
+ *  - type == VIR_NET_MESSAGE
+ *     * status == VIR_NET_OK
+ *          XXX_msg        for event information
+ *
+ *  - type == VIR_NET_STREAM
+ *     * status == VIR_NET_CONTINUE
+ *          byte[]       raw stream data
+ *     * status == VIR_NET_ERROR
+ *          remote_error error information
+ *     * status == VIR_NET_OK
+ *          <empty>
+ */
+enum virNetMessageType {
+    /* client -> server. args from a method call */
+    VIR_NET_CALL = 0,
+    /* server -> client. reply/error from a method call */
+    VIR_NET_REPLY = 1,
+    /* either direction. async notification */
+    VIR_NET_MESSAGE = 2,
+    /* either direction. stream data packet */
+    VIR_NET_STREAM = 3
+};
+
+enum virNetMessageStatus {
+    /* Status is always VIR_NET_OK for calls.
+     * For replies, indicates no error.
+     */
+    VIR_NET_OK = 0,
+
+    /* For replies, indicates that an error happened, and a struct
+     * remote_error follows.
+     */
+    VIR_NET_ERROR = 1,
+
+    /* For streams, indicates that more data is still expected
+     */
+    VIR_NET_CONTINUE = 2
+};
+
+/* 4 byte length word per header */
+const VIR_NET_MESSAGE_HEADER_XDR_LEN = 4;
+
+struct virNetMessageHeader {
+    unsigned prog;              /* Unique ID for the program */
+    unsigned vers;              /* Program version number */
+    int proc;                   /* Unique ID for the procedure within the program */
+    virNetMessageType type;     /* Type of message */
+    unsigned serial;            /* Serial number of message. */
+    virNetMessageStatus status;
+};
+
+/* Error message. See <virterror.h> for explanation of fields. */
+
+/* Most of these don't really belong here. There are sadly needed
+ * for wire ABI backwards compatibility with the rather crazy
+ * error struct we previously defined :-(
+ */
+
+typedef opaque virNetMessageUUID[VIR_UUID_BUFLEN];
+typedef string virNetMessageNonnullString<VIR_NET_MESSAGE_STRING_MAX>;
+
+/* A long string, which may be NULL. */
+typedef virNetMessageNonnullString *virNetMessageString;
+
+/* A domain which may not be NULL. */
+struct virNetMessageNonnullDomain {
+    virNetMessageNonnullString name;
+    virNetMessageUUID uuid;
+    int id;
+};
+
+/* A network which may not be NULL. */
+struct virNetMessageNonnullNetwork {
+    virNetMessageNonnullString name;
+    virNetMessageUUID uuid;
+};
+
+
+typedef virNetMessageNonnullDomain *virNetMessageDomain;
+typedef virNetMessageNonnullNetwork *virNetMessageNetwork;
+
+/* NB. Fields "code", "domain" and "level" are really enums.  The
+ * numeric value should remain compatible between libvirt and
+ * libvirtd.  This means, no changing or reordering the enums as
+ * defined in <virterror.h> (but we don't do that anyway, for separate
+ * ABI reasons).
+ */
+struct virNetMessageError {
+    int code;
+    int domain;
+    virNetMessageString message;
+    int level;
+    virNetMessageDomain dom; /* unused */
+    virNetMessageString str1;
+    virNetMessageString str2;
+    virNetMessageString str3;
+    int int1;
+    int int2;
+    virNetMessageNetwork net; /* unused */
+};
-- 
1.7.4




More information about the libvir-list mailing list