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
---
src/Makefile.am | 19 +++-
src/rpc/virnetprotocol.x | 217 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 232 insertions(+), 4 deletions(-)
create mode 100644 src/rpc/virnetprotocol.x
diff --git a/src/Makefile.am b/src/Makefile.am
index 4f9bfc9..93f39fb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -570,13 +570,11 @@ $(srcdir)/remote/remote_driver.c: $(REMOTE_DRIVER_GENERATED)
endif WITH_REMOTE
-$(srcdir)/remote/%_protocol.c: $(srcdir)/remote/%_protocol.x \
- $(srcdir)/remote/%_protocol.h $(srcdir)/remote/rpcgen_fix.pl
+%protocol.c: %protocol.x %protocol.h $(srcdir)/remote/rpcgen_fix.pl
$(AM_V_GEN)perl -w $(srcdir)/remote/rpcgen_fix.pl $(RPCGEN) -c \
$< $@
-$(srcdir)/remote/%_protocol.h: $(srcdir)/remote/%_protocol.x \
- $(srcdir)/remote/rpcgen_fix.pl
+%protocol.h: %protocol.x $(srcdir)/remote/rpcgen_fix.pl
$(AM_V_GEN)perl -w $(srcdir)/remote/rpcgen_fix.pl $(RPCGEN) -h \
$< $@
@@ -1189,6 +1187,19 @@ else
EXTRA_DIST += $(LOCK_DRIVER_SANLOCK_SOURCES)
endif
+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 =
if WITH_LIBVIRTD
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(a)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.4