* qemud/dispatch.c, qemud/dispatch.h: Generic code handling dispatch of
RPC messages.
* qemud/Makefile.am: Add dispatch.c to build
* qemud/qemud.c: Include dispatch.h
* qemud/qemud.h: Remove remoteDispatchClientRequest, remoteRelayDomainEvent
now in dispatch.h
* qemud/remote.c: Remove remoteDispatchClientRequest, remoteRelayDomainEvent
now in dispatch.c, and dispatch_args, dispatch_ret, dispatch_fn & dispatch_data
now in remote.h
* qemud/remote.h: Add typedefs for dispatch_args, dispatch_ret,
dispatch_fn, dispath_data. Add remoteGetDispatchData() API
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
qemud/Makefile.am | 3 +-
qemud/dispatch.c | 302 +++++++++++++++++++++++++++++++++++++++++++++++++
qemud/dispatch.h | 58 ++++++++++
qemud/qemud.c | 4 +-
qemud/qemud.h | 11 +--
qemud/remote.c | 325 +++--------------------------------------------------
qemud/remote.h | 72 ++++++++++++
7 files changed, 454 insertions(+), 321 deletions(-)
create mode 100644 qemud/dispatch.c
create mode 100644 qemud/dispatch.h
create mode 100644 qemud/remote.h
diff --git a/qemud/Makefile.am b/qemud/Makefile.am
index 403846a..74dfd22 100644
--- a/qemud/Makefile.am
+++ b/qemud/Makefile.am
@@ -3,7 +3,8 @@
DAEMON_SOURCES = \
event.c event.h \
qemud.c qemud.h \
- remote.c \
+ remote.c remote.h \
+ dispatch.c dispatch.h \
remote_dispatch_prototypes.h \
remote_dispatch_table.h \
remote_dispatch_args.h \
diff --git a/qemud/dispatch.c b/qemud/dispatch.c
new file mode 100644
index 0000000..d2338fb
--- /dev/null
+++ b/qemud/dispatch.c
@@ -0,0 +1,302 @@
+/*
+ * dispatch.h: RPC message dispatching infrastructure
+ *
+ * Copyright (C) 2007, 2008, 2009 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 W.M. Jones <rjones(a)redhat.com>
+ * Author: Daniel P. Berrange <berrange(a)redhat.com>
+ */
+
+#include <config.h>
+
+
+#include "dispatch.h"
+#include "remote.h"
+
+/* Convert a libvirt virError object into wire format */
+static void
+remoteDispatchCopyError (remote_error *rerr,
+ virErrorPtr verr)
+{
+ rerr->code = verr->code;
+ rerr->domain = verr->domain;
+ rerr->message = verr->message ? malloc(sizeof(char*)) : NULL;
+ if (rerr->message) *rerr->message = strdup(verr->message);
+ rerr->level = verr->level;
+ rerr->str1 = verr->str1 ? malloc(sizeof(char*)) : NULL;
+ if (rerr->str1) *rerr->str1 = strdup(verr->str1);
+ rerr->str2 = verr->str2 ? malloc(sizeof(char*)) : NULL;
+ if (rerr->str2) *rerr->str2 = strdup(verr->str2);
+ rerr->str3 = verr->str3 ? malloc(sizeof(char*)) : NULL;
+ if (rerr->str3) *rerr->str3 = strdup(verr->str3);
+ rerr->int1 = verr->int1;
+ rerr->int2 = verr->int2;
+}
+
+
+/* A set of helpers for sending back errors to client
+ in various ways .... */
+
+static void
+remoteDispatchStringError (remote_error *rerr,
+ int code, const char *msg)
+{
+ virError verr;
+
+ memset(&verr, 0, sizeof verr);
+
+ /* Construct the dummy libvirt virError. */
+ verr.code = code;
+ verr.domain = VIR_FROM_REMOTE;
+ verr.message = (char *)msg;
+ verr.level = VIR_ERR_ERROR;
+ verr.str1 = (char *)msg;
+
+ remoteDispatchCopyError(rerr, &verr);
+}
+
+
+void remoteDispatchAuthError (remote_error *rerr)
+{
+ remoteDispatchStringError (rerr, VIR_ERR_AUTH_FAILED, "authentication
failed");
+}
+
+
+void remoteDispatchFormatError (remote_error *rerr,
+ const char *fmt, ...)
+{
+ va_list args;
+ char msgbuf[1024];
+ char *msg = msgbuf;
+
+ va_start (args, fmt);
+ vsnprintf (msgbuf, sizeof msgbuf, fmt, args);
+ va_end (args);
+
+ remoteDispatchStringError (rerr, VIR_ERR_RPC, msg);
+}
+
+
+void remoteDispatchGenericError (remote_error *rerr)
+{
+ remoteDispatchStringError(rerr,
+ VIR_ERR_INTERNAL_ERROR,
+ "library function returned error but did not set
virterror");
+}
+
+
+void remoteDispatchOOMError (remote_error *rerr)
+{
+ remoteDispatchStringError(rerr,
+ VIR_ERR_NO_MEMORY,
+ NULL);
+}
+
+
+void remoteDispatchConnError (remote_error *rerr,
+ virConnectPtr conn)
+{
+ virErrorPtr verr;
+
+ if (conn)
+ verr = virConnGetLastError(conn);
+ else
+ verr = virGetLastError();
+ if (verr)
+ remoteDispatchCopyError(rerr, verr);
+ else
+ remoteDispatchGenericError(rerr);
+}
+
+
+/*
+ * @server: the unlocked server object
+ * @client: the locked client object
+ * @msg: the complete incoming message packet
+ *
+ * This function gets called from qemud when it pulls a incoming
+ * remote protocol messsage off the dispatch queue for processing.
+ *
+ *
+ * Returns 0 if the message was dispatched, -1 upon fatal error
+ */
+int
+remoteDispatchClientRequest (struct qemud_server *server,
+ struct qemud_client *client,
+ struct qemud_client_message *msg)
+{
+ XDR xdr;
+ remote_message_header req, rep;
+ remote_error rerr;
+ dispatch_args args;
+ dispatch_ret ret;
+ const dispatch_data *data = NULL;
+ int rv = -1;
+ unsigned int len;
+ virConnectPtr conn = NULL;
+
+ memset(&args, 0, sizeof args);
+ memset(&ret, 0, sizeof ret);
+ memset(&rerr, 0, sizeof rerr);
+
+ /* Parse the header. */
+ xdrmem_create (&xdr,
+ msg->buffer + REMOTE_MESSAGE_HEADER_XDR_LEN,
+ msg->bufferLength - REMOTE_MESSAGE_HEADER_XDR_LEN,
+ XDR_DECODE);
+
+ if (!xdr_remote_message_header (&xdr, &req))
+ goto fatal_error;
+
+ /* Check version, etc. */
+ if (req.prog != REMOTE_PROGRAM) {
+ remoteDispatchFormatError (&rerr,
+ _("program mismatch (actual %x, expected
%x)"),
+ req.prog, REMOTE_PROGRAM);
+ goto rpc_error;
+ }
+ if (req.vers != REMOTE_PROTOCOL_VERSION) {
+ remoteDispatchFormatError (&rerr,
+ _("version mismatch (actual %x, expected
%x)"),
+ req.vers, REMOTE_PROTOCOL_VERSION);
+ goto rpc_error;
+ }
+ if (req.direction != REMOTE_CALL) {
+ remoteDispatchFormatError (&rerr, _("direction (%d) !=
REMOTE_CALL"),
+ (int) req.direction);
+ goto rpc_error;
+ }
+ if (req.status != REMOTE_OK) {
+ remoteDispatchFormatError (&rerr, _("status (%d) != REMOTE_OK"),
+ (int) req.status);
+ goto rpc_error;
+ }
+
+ /* If client is marked as needing auth, don't allow any RPC ops,
+ * except for authentication ones
+ */
+ if (client->auth) {
+ if (req.proc != REMOTE_PROC_AUTH_LIST &&
+ req.proc != REMOTE_PROC_AUTH_SASL_INIT &&
+ req.proc != REMOTE_PROC_AUTH_SASL_START &&
+ req.proc != REMOTE_PROC_AUTH_SASL_STEP &&
+ req.proc != REMOTE_PROC_AUTH_POLKIT
+ ) {
+ /* Explicitly *NOT* calling remoteDispatchAuthError() because
+ we want back-compatability with libvirt clients which don't
+ support the VIR_ERR_AUTH_FAILED error code */
+ remoteDispatchFormatError (&rerr, "%s", _("authentication
required"));
+ goto rpc_error;
+ }
+ }
+
+ data = remoteGetDispatchData(req.proc);
+
+ if (!data) {
+ remoteDispatchFormatError (&rerr, _("unknown procedure: %d"),
+ req.proc);
+ goto rpc_error;
+ }
+
+ /* De-serialize args off the wire */
+ if (!((data->args_filter)(&xdr, &args))) {
+ remoteDispatchFormatError (&rerr, "%s", _("parse args
failed"));
+ goto rpc_error;
+ }
+
+ /* Call function. */
+ conn = client->conn;
+ virMutexUnlock(&client->lock);
+
+ /*
+ * When the RPC handler is called:
+ *
+ * - Server object is unlocked
+ * - Client object is unlocked
+ *
+ * Without locking, it is safe to use:
+ *
+ * 'conn', 'rerr', 'args and 'ret'
+ */
+ rv = (data->fn)(server, client, conn, &rerr, &args, &ret);
+
+ virMutexLock(&server->lock);
+ virMutexLock(&client->lock);
+ virMutexUnlock(&server->lock);
+
+ xdr_free (data->args_filter, (char*)&args);
+
+rpc_error:
+ xdr_destroy (&xdr);
+
+ /* Return header. */
+ rep.prog = req.prog;
+ rep.vers = req.vers;
+ rep.proc = req.proc;
+ rep.direction = REMOTE_REPLY;
+ rep.serial = req.serial;
+ rep.status = rv < 0 ? REMOTE_ERROR : REMOTE_OK;
+
+ /* Serialise the return header. */
+ xdrmem_create (&xdr, msg->buffer, sizeof msg->buffer, XDR_ENCODE);
+
+ len = 0; /* We'll come back and write this later. */
+ if (!xdr_u_int (&xdr, &len)) {
+ if (rv == 0) xdr_free (data->ret_filter, (char*)&ret);
+ goto fatal_error;
+ }
+
+ if (!xdr_remote_message_header (&xdr, &rep)) {
+ if (rv == 0) xdr_free (data->ret_filter, (char*)&ret);
+ goto fatal_error;
+ }
+
+ /* If OK, serialise return structure, if error serialise error. */
+ if (rv >= 0) {
+ if (!((data->ret_filter) (&xdr, &ret)))
+ goto fatal_error;
+ xdr_free (data->ret_filter, (char*)&ret);
+ } else /* error */ {
+ /* Error was NULL so synthesize an error. */
+ if (rerr.code == 0)
+ remoteDispatchGenericError(&rerr);
+ if (!xdr_remote_error (&xdr, &rerr))
+ goto fatal_error;
+ xdr_free((xdrproc_t)xdr_remote_error, (char *)&rerr);
+ }
+
+ /* Write the length word. */
+ len = xdr_getpos (&xdr);
+ if (xdr_setpos (&xdr, 0) == 0)
+ goto fatal_error;
+
+ if (!xdr_u_int (&xdr, &len))
+ goto fatal_error;
+
+ xdr_destroy (&xdr);
+
+ msg->bufferLength = len;
+ msg->bufferOffset = 0;
+
+ return 0;
+
+fatal_error:
+ /* Seriously bad stuff happened, so we'll kill off this client
+ and not send back any RPC error */
+ xdr_destroy (&xdr);
+ return -1;
+}
diff --git a/qemud/dispatch.h b/qemud/dispatch.h
new file mode 100644
index 0000000..9ab6148
--- /dev/null
+++ b/qemud/dispatch.h
@@ -0,0 +1,58 @@
+/*
+ * dispatch.h: RPC message dispatching infrastructure
+ *
+ * Copyright (C) 2007, 2008, 2009 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 W.M. Jones <rjones(a)redhat.com>
+ * Author: Daniel P. Berrange <berrange(a)redhat.com>
+ */
+
+#ifndef __LIBVIRTD_DISPATCH_H__
+#define __LIBVIRTD_DISPATCH_H__
+
+
+#include "qemud.h"
+
+
+int
+remoteDispatchClientRequest (struct qemud_server *server,
+ struct qemud_client *client,
+ struct qemud_client_message *req);
+
+
+void remoteDispatchFormatError (remote_error *rerr,
+ const char *fmt, ...)
+ ATTRIBUTE_FORMAT(printf, 2, 3);
+
+void remoteDispatchAuthError (remote_error *rerr);
+void remoteDispatchGenericError (remote_error *rerr);
+void remoteDispatchOOMError (remote_error *rerr);
+void remoteDispatchConnError (remote_error *rerr,
+ virConnectPtr conn);
+
+/* Having this here is dubious. It should be in remote.h
+ * but qemud.c shouldn't depend on that header directly.
+ * Refactor this later to deal with this properly.
+ */
+int remoteRelayDomainEvent (virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ int event,
+ int detail,
+ void *opaque);
+
+
+#endif /* __LIBVIRTD_DISPATCH_H__ */
diff --git a/qemud/qemud.c b/qemud/qemud.c
index da20aa9..d300c56 100644
--- a/qemud/qemud.c
+++ b/qemud/qemud.c
@@ -54,6 +54,8 @@
#define VIR_FROM_THIS VIR_FROM_QEMU
#include "qemud.h"
+#include "dispatch.h"
+
#include "util.h"
#include "remote_internal.h"
#include "conf.h"
@@ -219,7 +221,7 @@ qemudClientMessageQueuePush(struct qemud_client_message **queue,
}
}
-static struct qemud_client_message *
+struct qemud_client_message *
qemudClientMessageQueueServe(struct qemud_client_message **queue)
{
struct qemud_client_message *tmp = *queue;
diff --git a/qemud/qemud.h b/qemud/qemud.h
index 8880337..c8273cb 100644
--- a/qemud/qemud.h
+++ b/qemud/qemud.h
@@ -200,10 +200,6 @@ void qemudLog(int priority, const char *fmt, ...)
ATTRIBUTE_FORMAT(printf,2,3);
-int
-remoteDispatchClientRequest (struct qemud_server *server,
- struct qemud_client *client,
- struct qemud_client_message *req);
int qemudRegisterClientEvent(struct qemud_server *server,
struct qemud_client *client,
@@ -214,12 +210,9 @@ void qemudDispatchClientFailure(struct qemud_client *client);
void
qemudClientMessageQueuePush(struct qemud_client_message **queue,
struct qemud_client_message *msg);
+struct qemud_client_message *
+qemudClientMessageQueueServe(struct qemud_client_message **queue);
-int remoteRelayDomainEvent (virConnectPtr conn ATTRIBUTE_UNUSED,
- virDomainPtr dom,
- int event,
- int detail,
- void *opaque);
#if HAVE_POLKIT
diff --git a/qemud/remote.c b/qemud/remote.c
index 1071c21..d0bc677 100644
--- a/qemud/remote.c
+++ b/qemud/remote.c
@@ -1,5 +1,5 @@
/*
- * remote.c: code handling remote requests (from remote_internal.c)
+ * remote.c: handlers for RPC method calls
*
* Copyright (C) 2007, 2008, 2009 Red Hat, Inc.
*
@@ -48,18 +48,17 @@
#include <polkit-dbus/polkit-dbus.h>
#endif
+#include "remote.h"
+#include "dispatch.h"
+
#include "libvirt_internal.h"
#include "datatypes.h"
-#include "qemud.h"
#include "memory.h"
#include "util.h"
#define VIR_FROM_THIS VIR_FROM_REMOTE
#define REMOTE_DEBUG(fmt, ...) DEBUG(fmt, __VA_ARGS__)
-static void remoteDispatchFormatError (remote_error *rerr,
- const char *fmt, ...)
- ATTRIBUTE_FORMAT(printf, 2, 3);
static virDomainPtr get_nonnull_domain (virConnectPtr conn, remote_nonnull_domain
domain);
static virNetworkPtr get_nonnull_network (virConnectPtr conn, remote_nonnull_network
network);
static virInterfacePtr get_nonnull_interface (virConnectPtr conn,
remote_nonnull_interface interface);
@@ -72,47 +71,23 @@ static void make_nonnull_storage_pool (remote_nonnull_storage_pool
*pool_dst, vi
static void make_nonnull_storage_vol (remote_nonnull_storage_vol *vol_dst,
virStorageVolPtr vol_src);
static void make_nonnull_node_device (remote_nonnull_node_device *dev_dst,
virNodeDevicePtr dev_src);
-#include "remote_dispatch_prototypes.h"
-
-typedef union {
-#include "remote_dispatch_args.h"
-} dispatch_args;
-
-typedef union {
-#include "remote_dispatch_ret.h"
-} dispatch_ret;
-
-
-/**
- * When the RPC handler is called:
- *
- * - Server object is unlocked
- * - Client object is unlocked
- *
- * Both must be locked before use. Server lock must
- * be held before attempting to lock client.
- *
- * Without any locking, it is safe to use:
- *
- * 'conn', 'rerr', 'args and 'ret'
- */
-typedef int (*dispatch_fn) (struct qemud_server *server,
- struct qemud_client *client,
- virConnectPtr conn,
- remote_error *err,
- dispatch_args *args,
- dispatch_ret *ret);
-typedef struct {
- dispatch_fn fn;
- xdrproc_t args_filter;
- xdrproc_t ret_filter;
-} dispatch_data;
+#include "remote_dispatch_prototypes.h"
static const dispatch_data const dispatch_table[] = {
#include "remote_dispatch_table.h"
};
+const dispatch_data const *remoteGetDispatchData(int proc)
+{
+ if (proc >= ARRAY_CARDINALITY(dispatch_table) ||
+ dispatch_table[proc].fn == NULL) {
+ return NULL;
+ }
+
+ return &(dispatch_table[proc]);
+}
+
/* Prototypes */
static void
remoteDispatchDomainEventSend (struct qemud_client *client,
@@ -122,276 +97,6 @@ remoteDispatchDomainEventSend (struct qemud_client *client,
int detail);
-/* Convert a libvirt virError object into wire format */
-static void
-remoteDispatchCopyError (remote_error *rerr,
- virErrorPtr verr)
-{
- rerr->code = verr->code;
- rerr->domain = verr->domain;
- rerr->message = verr->message ? malloc(sizeof(char*)) : NULL;
- if (rerr->message) *rerr->message = strdup(verr->message);
- rerr->level = verr->level;
- rerr->str1 = verr->str1 ? malloc(sizeof(char*)) : NULL;
- if (rerr->str1) *rerr->str1 = strdup(verr->str1);
- rerr->str2 = verr->str2 ? malloc(sizeof(char*)) : NULL;
- if (rerr->str2) *rerr->str2 = strdup(verr->str2);
- rerr->str3 = verr->str3 ? malloc(sizeof(char*)) : NULL;
- if (rerr->str3) *rerr->str3 = strdup(verr->str3);
- rerr->int1 = verr->int1;
- rerr->int2 = verr->int2;
-}
-
-
-/* A set of helpers for sending back errors to client
- in various ways .... */
-
-static void
-remoteDispatchStringError (remote_error *rerr,
- int code, const char *msg)
-{
- virError verr;
-
- memset(&verr, 0, sizeof verr);
-
- /* Construct the dummy libvirt virError. */
- verr.code = code;
- verr.domain = VIR_FROM_REMOTE;
- verr.message = (char *)msg;
- verr.level = VIR_ERR_ERROR;
- verr.str1 = (char *)msg;
-
- remoteDispatchCopyError(rerr, &verr);
-}
-
-static void
-remoteDispatchAuthError (remote_error *rerr)
-{
- remoteDispatchStringError (rerr, VIR_ERR_AUTH_FAILED, "authentication
failed");
-}
-
-static void
-remoteDispatchFormatError (remote_error *rerr,
- const char *fmt, ...)
-{
- va_list args;
- char msgbuf[1024];
- char *msg = msgbuf;
-
- va_start (args, fmt);
- vsnprintf (msgbuf, sizeof msgbuf, fmt, args);
- va_end (args);
-
- remoteDispatchStringError (rerr, VIR_ERR_RPC, msg);
-}
-
-static void
-remoteDispatchGenericError (remote_error *rerr)
-{
- remoteDispatchStringError(rerr,
- VIR_ERR_INTERNAL_ERROR,
- "library function returned error but did not set
virterror");
-}
-
-static void
-remoteDispatchOOMError (remote_error *rerr)
-{
- remoteDispatchStringError(rerr,
- VIR_ERR_NO_MEMORY,
- NULL);
-}
-
-static void
-remoteDispatchConnError (remote_error *rerr,
- virConnectPtr conn)
-{
- virErrorPtr verr;
-
- if (conn)
- verr = virConnGetLastError(conn);
- else
- verr = virGetLastError();
- if (verr)
- remoteDispatchCopyError(rerr, verr);
- else
- remoteDispatchGenericError(rerr);
-}
-
-
-/* This function gets called from qemud when it detects an incoming
- * remote protocol message. At this point, client->buffer contains
- * the full call message (including length word which we skip).
- *
- * Server object is unlocked
- * Client object is locked
- */
-int
-remoteDispatchClientRequest (struct qemud_server *server,
- struct qemud_client *client,
- struct qemud_client_message *msg)
-{
- XDR xdr;
- remote_message_header req, rep;
- remote_error rerr;
- dispatch_args args;
- dispatch_ret ret;
- const dispatch_data *data = NULL;
- int rv = -1;
- unsigned int len;
- virConnectPtr conn = NULL;
-
- memset(&args, 0, sizeof args);
- memset(&ret, 0, sizeof ret);
- memset(&rerr, 0, sizeof rerr);
-
- /* Parse the header. */
- xdrmem_create (&xdr,
- msg->buffer + REMOTE_MESSAGE_HEADER_XDR_LEN,
- msg->bufferLength - REMOTE_MESSAGE_HEADER_XDR_LEN,
- XDR_DECODE);
-
- if (!xdr_remote_message_header (&xdr, &req))
- goto fatal_error;
-
- /* Check version, etc. */
- if (req.prog != REMOTE_PROGRAM) {
- remoteDispatchFormatError (&rerr,
- _("program mismatch (actual %x, expected
%x)"),
- req.prog, REMOTE_PROGRAM);
- goto rpc_error;
- }
- if (req.vers != REMOTE_PROTOCOL_VERSION) {
- remoteDispatchFormatError (&rerr,
- _("version mismatch (actual %x, expected
%x)"),
- req.vers, REMOTE_PROTOCOL_VERSION);
- goto rpc_error;
- }
- if (req.direction != REMOTE_CALL) {
- remoteDispatchFormatError (&rerr, _("direction (%d) !=
REMOTE_CALL"),
- (int) req.direction);
- goto rpc_error;
- }
- if (req.status != REMOTE_OK) {
- remoteDispatchFormatError (&rerr, _("status (%d) != REMOTE_OK"),
- (int) req.status);
- goto rpc_error;
- }
-
- /* If client is marked as needing auth, don't allow any RPC ops,
- * except for authentication ones
- */
- if (client->auth) {
- if (req.proc != REMOTE_PROC_AUTH_LIST &&
- req.proc != REMOTE_PROC_AUTH_SASL_INIT &&
- req.proc != REMOTE_PROC_AUTH_SASL_START &&
- req.proc != REMOTE_PROC_AUTH_SASL_STEP &&
- req.proc != REMOTE_PROC_AUTH_POLKIT
- ) {
- /* Explicitly *NOT* calling remoteDispatchAuthError() because
- we want back-compatability with libvirt clients which don't
- support the VIR_ERR_AUTH_FAILED error code */
- remoteDispatchFormatError (&rerr, "%s", _("authentication
required"));
- goto rpc_error;
- }
- }
-
- if (req.proc >= ARRAY_CARDINALITY(dispatch_table) ||
- dispatch_table[req.proc].fn == NULL) {
- remoteDispatchFormatError (&rerr, _("unknown procedure: %d"),
- req.proc);
- goto rpc_error;
- }
-
- data = &(dispatch_table[req.proc]);
-
- /* De-serialize args off the wire */
- if (!((data->args_filter)(&xdr, &args))) {
- remoteDispatchFormatError (&rerr, "%s", _("parse args
failed"));
- goto rpc_error;
- }
-
- /* Call function. */
- conn = client->conn;
- virMutexUnlock(&client->lock);
-
- /*
- * When the RPC handler is called:
- *
- * - Server object is unlocked
- * - Client object is unlocked
- *
- * Without locking, it is safe to use:
- *
- * 'conn', 'rerr', 'args and 'ret'
- */
- rv = (data->fn)(server, client, conn, &rerr, &args, &ret);
-
- virMutexLock(&server->lock);
- virMutexLock(&client->lock);
- virMutexUnlock(&server->lock);
-
- xdr_free (data->args_filter, (char*)&args);
-
-rpc_error:
- xdr_destroy (&xdr);
-
- /* Return header. */
- rep.prog = req.prog;
- rep.vers = req.vers;
- rep.proc = req.proc;
- rep.direction = REMOTE_REPLY;
- rep.serial = req.serial;
- rep.status = rv < 0 ? REMOTE_ERROR : REMOTE_OK;
-
- /* Serialise the return header. */
- xdrmem_create (&xdr, msg->buffer, sizeof msg->buffer, XDR_ENCODE);
-
- len = 0; /* We'll come back and write this later. */
- if (!xdr_u_int (&xdr, &len)) {
- if (rv == 0) xdr_free (data->ret_filter, (char*)&ret);
- goto fatal_error;
- }
-
- if (!xdr_remote_message_header (&xdr, &rep)) {
- if (rv == 0) xdr_free (data->ret_filter, (char*)&ret);
- goto fatal_error;
- }
-
- /* If OK, serialise return structure, if error serialise error. */
- if (rv >= 0) {
- if (!((data->ret_filter) (&xdr, &ret)))
- goto fatal_error;
- xdr_free (data->ret_filter, (char*)&ret);
- } else /* error */ {
- /* Error was NULL so synthesize an error. */
- if (rerr.code == 0)
- remoteDispatchGenericError(&rerr);
- if (!xdr_remote_error (&xdr, &rerr))
- goto fatal_error;
- xdr_free((xdrproc_t)xdr_remote_error, (char *)&rerr);
- }
-
- /* Write the length word. */
- len = xdr_getpos (&xdr);
- if (xdr_setpos (&xdr, 0) == 0)
- goto fatal_error;
-
- if (!xdr_u_int (&xdr, &len))
- goto fatal_error;
-
- xdr_destroy (&xdr);
-
- msg->bufferLength = len;
- msg->bufferOffset = 0;
-
- return 0;
-
-fatal_error:
- /* Seriously bad stuff happened, so we'll kill off this client
- and not send back any RPC error */
- xdr_destroy (&xdr);
- return -1;
-}
int remoteRelayDomainEvent (virConnectPtr conn ATTRIBUTE_UNUSED,
virDomainPtr dom,
diff --git a/qemud/remote.h b/qemud/remote.h
new file mode 100644
index 0000000..e3ee696
--- /dev/null
+++ b/qemud/remote.h
@@ -0,0 +1,72 @@
+/*
+ * remote.h: handlers for RPC method calls
+ *
+ * Copyright (C) 2007, 2008, 2009 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 W.M. Jones <rjones(a)redhat.com>
+ * Author: Daniel P. Berrange <berrange(a)redhat.com>
+ */
+
+#ifndef __LIBVIRTD_REMOTE_H__
+#define __LIBVIRTD_REMOTE_H__
+
+
+#include "qemud.h"
+
+typedef union {
+#include "remote_dispatch_args.h"
+} dispatch_args;
+
+typedef union {
+#include "remote_dispatch_ret.h"
+} dispatch_ret;
+
+
+
+
+/**
+ * When the RPC handler is called:
+ *
+ * - Server object is unlocked
+ * - Client object is unlocked
+ *
+ * Both must be locked before use. Server lock must
+ * be held before attempting to lock client.
+ *
+ * Without any locking, it is safe to use:
+ *
+ * 'conn', 'rerr', 'args and 'ret'
+ */
+typedef int (*dispatch_fn) (struct qemud_server *server,
+ struct qemud_client *client,
+ virConnectPtr conn,
+ remote_error *err,
+ dispatch_args *args,
+ dispatch_ret *ret);
+
+typedef struct {
+ dispatch_fn fn;
+ xdrproc_t args_filter;
+ xdrproc_t ret_filter;
+} dispatch_data;
+
+
+const dispatch_data const *remoteGetDispatchData(int proc);
+
+
+
+#endif /* __LIBVIRTD_REMOTE_H__ */
--
1.6.2.5
--
|: Red Hat, Engineering, London -o-
http://people.redhat.com/berrange/ :|
|:
http://libvirt.org -o-
http://virt-manager.org -o-
http://ovirt.org :|
|:
http://autobuild.org -o-
http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|