* 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@xxxxxxxxxx> --- 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@xxxxxxxxxx> + * Author: Daniel P. Berrange <berrange@xxxxxxxxxx> + */ + +#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@xxxxxxxxxx> + * Author: Daniel P. Berrange <berrange@xxxxxxxxxx> + */ + +#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@xxxxxxxxxx> + * Author: Daniel P. Berrange <berrange@xxxxxxxxxx> + */ + +#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 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list