]> xenbits.xensource.com Git - libvirt.git/commitdiff
Defines the basics of a generic RPC protocol in XDR
authorDaniel P. Berrange <berrange@redhat.com>
Mon, 6 Dec 2010 17:03:10 +0000 (17:03 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Fri, 24 Jun 2011 10:48:10 +0000 (11:48 +0100)
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

.gitignore
src/Makefile.am
src/rpc/virnetprotocol.x [new file with mode: 0644]

index a4d3ea1fd0a1c0507a7202bb40c8466b96359aa6..0628732d303b7b83de7561cc3f499ec9a91d96a4 100644 (file)
@@ -53,6 +53,7 @@
 /src/libvirt_iohelper
 /src/remote/*_client_bodies.h
 /src/remote/*_protocol.[ch]
+/src/rpc/virnetprotocol.[ch]
 /tests/*.log
 /tests/cputest
 /tests/hashtest
index b292f9f284fafabc3d13dba0961f2d5fbe36880d..adfc785b68b44a40e66f6b5f024d6c7ffcf3a814 100644 (file)
@@ -571,13 +571,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 \
               $< $@
 
@@ -1190,6 +1188,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 (file)
index 0000000..306fafa
--- /dev/null
@@ -0,0 +1,217 @@
+/* -*- c -*-
+ * virnetprotocol.x: basic protocol for all RPC services.
+ *
+ * Copyright (C) 2006-2011 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@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 */
+};