mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 21:34:54 +03:00
Split out code for handling incoming method call messages
The remoteDispatchClientRequest() method is currently hardwired to assume there is only one type of incoming message, a method call. To allow for alternate types of incoming messags, the code that is specific to method calls is being split into a separate method remoteDispatchClientCall * qemud/dispatch.c: Move method call specific code out into remoteDispatchClientCall. Add a helper remoteSerializeError for returning error messages to client
This commit is contained in:
parent
af4dad0fa2
commit
47cab73499
211
qemud/dispatch.c
211
qemud/dispatch.c
@ -23,10 +23,11 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
|
||||
#include "dispatch.h"
|
||||
#include "remote.h"
|
||||
|
||||
#include "memory.h"
|
||||
|
||||
/* Convert a libvirt virError object into wire format */
|
||||
static void
|
||||
remoteDispatchCopyError (remote_error *rerr,
|
||||
@ -122,6 +123,101 @@ void remoteDispatchConnError (remote_error *rerr,
|
||||
remoteDispatchGenericError(rerr);
|
||||
}
|
||||
|
||||
static int
|
||||
remoteSerializeError(struct qemud_client *client,
|
||||
remote_error *rerr,
|
||||
int program,
|
||||
int version,
|
||||
int procedure,
|
||||
int direction,
|
||||
int serial)
|
||||
{
|
||||
XDR xdr;
|
||||
unsigned int len;
|
||||
struct qemud_client_message *msg = NULL;
|
||||
|
||||
if (VIR_ALLOC(msg) < 0)
|
||||
goto fatal_error;
|
||||
|
||||
/* Return header. */
|
||||
msg->hdr.prog = program;
|
||||
msg->hdr.vers = version;
|
||||
msg->hdr.proc = procedure;
|
||||
msg->hdr.direction = direction;
|
||||
msg->hdr.serial = serial;
|
||||
msg->hdr.status = REMOTE_ERROR;
|
||||
|
||||
msg->bufferLength = sizeof(msg->buffer);
|
||||
|
||||
/* Serialise the return header. */
|
||||
xdrmem_create (&xdr,
|
||||
msg->buffer,
|
||||
msg->bufferLength,
|
||||
XDR_ENCODE);
|
||||
|
||||
len = 0; /* We'll come back and write this later. */
|
||||
if (!xdr_u_int (&xdr, &len))
|
||||
goto xdr_error;
|
||||
|
||||
if (!xdr_remote_message_header (&xdr, &msg->hdr))
|
||||
goto xdr_error;
|
||||
|
||||
/* Error was not set, so synthesize a generic error message. */
|
||||
if (rerr->code == 0)
|
||||
remoteDispatchGenericError(rerr);
|
||||
|
||||
if (!xdr_remote_error (&xdr, rerr))
|
||||
goto xdr_error;
|
||||
|
||||
/* Write the length word. */
|
||||
len = xdr_getpos (&xdr);
|
||||
if (xdr_setpos (&xdr, 0) == 0)
|
||||
goto xdr_error;
|
||||
|
||||
if (!xdr_u_int (&xdr, &len))
|
||||
goto xdr_error;
|
||||
|
||||
xdr_destroy (&xdr);
|
||||
|
||||
msg->bufferLength = len;
|
||||
msg->bufferOffset = 0;
|
||||
|
||||
/* Put reply on end of tx queue to send out */
|
||||
qemudClientMessageQueuePush(&client->tx, msg);
|
||||
qemudUpdateClientEvent(client);
|
||||
xdr_free((xdrproc_t)xdr_remote_error, (char *)rerr);
|
||||
|
||||
return 0;
|
||||
|
||||
xdr_error:
|
||||
xdr_destroy(&xdr);
|
||||
fatal_error:
|
||||
xdr_free((xdrproc_t)xdr_remote_error, (char *)rerr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @client: the client to send the error to
|
||||
* @rerr: the error object to send
|
||||
* @req: the message this error is in reply to
|
||||
*
|
||||
* Send an error message to the client
|
||||
*
|
||||
* Returns 0 if the error was sent, -1 upon fatal error
|
||||
*/
|
||||
static int
|
||||
remoteSerializeReplyError(struct qemud_client *client,
|
||||
remote_error *rerr,
|
||||
remote_message_header *req) {
|
||||
return remoteSerializeError(client,
|
||||
rerr,
|
||||
req->prog,
|
||||
req->vers,
|
||||
req->proc,
|
||||
REMOTE_REPLY,
|
||||
req->serial);
|
||||
}
|
||||
|
||||
/*
|
||||
* @msg: the complete incoming message, whose header to decode
|
||||
@ -216,6 +312,12 @@ cleanup:
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
remoteDispatchClientCall (struct qemud_server *server,
|
||||
struct qemud_client *client,
|
||||
struct qemud_client_message *msg);
|
||||
|
||||
|
||||
/*
|
||||
* @server: the unlocked server object
|
||||
* @client: the locked client object
|
||||
@ -233,6 +335,55 @@ int
|
||||
remoteDispatchClientRequest (struct qemud_server *server,
|
||||
struct qemud_client *client,
|
||||
struct qemud_client_message *msg)
|
||||
{
|
||||
remote_error rerr;
|
||||
|
||||
memset(&rerr, 0, sizeof rerr);
|
||||
|
||||
/* Check version, etc. */
|
||||
if (msg->hdr.prog != REMOTE_PROGRAM) {
|
||||
remoteDispatchFormatError (&rerr,
|
||||
_("program mismatch (actual %x, expected %x)"),
|
||||
msg->hdr.prog, REMOTE_PROGRAM);
|
||||
goto error;
|
||||
}
|
||||
if (msg->hdr.vers != REMOTE_PROTOCOL_VERSION) {
|
||||
remoteDispatchFormatError (&rerr,
|
||||
_("version mismatch (actual %x, expected %x)"),
|
||||
msg->hdr.vers, REMOTE_PROTOCOL_VERSION);
|
||||
goto error;
|
||||
}
|
||||
|
||||
switch (msg->hdr.direction) {
|
||||
case REMOTE_CALL:
|
||||
return remoteDispatchClientCall(server, client, msg);
|
||||
|
||||
default:
|
||||
remoteDispatchFormatError (&rerr, _("direction (%d) != REMOTE_CALL"),
|
||||
(int) msg->hdr.direction);
|
||||
}
|
||||
|
||||
error:
|
||||
return remoteSerializeReplyError(client, &rerr, &msg->hdr);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @server: the unlocked server object
|
||||
* @client: the locked client object
|
||||
* @msg: the complete incoming method call, with header already decoded
|
||||
*
|
||||
* This method is used to dispatch an message representing an
|
||||
* incoming method call from a client. It decodes the payload
|
||||
* to obtain method call arguments, invokves the method and
|
||||
* then sends a reply packet with the return values
|
||||
*
|
||||
* Returns 0 if the reply was sent, or -1 upon fatal error
|
||||
*/
|
||||
int
|
||||
remoteDispatchClientCall (struct qemud_server *server,
|
||||
struct qemud_client *client,
|
||||
struct qemud_client_message *msg)
|
||||
{
|
||||
XDR xdr;
|
||||
remote_error rerr;
|
||||
@ -247,25 +398,6 @@ remoteDispatchClientRequest (struct qemud_server *server,
|
||||
memset(&ret, 0, sizeof ret);
|
||||
memset(&rerr, 0, sizeof rerr);
|
||||
|
||||
|
||||
/* Check version, etc. */
|
||||
if (msg->hdr.prog != REMOTE_PROGRAM) {
|
||||
remoteDispatchFormatError (&rerr,
|
||||
_("program mismatch (actual %x, expected %x)"),
|
||||
msg->hdr.prog, REMOTE_PROGRAM);
|
||||
goto rpc_error;
|
||||
}
|
||||
if (msg->hdr.vers != REMOTE_PROTOCOL_VERSION) {
|
||||
remoteDispatchFormatError (&rerr,
|
||||
_("version mismatch (actual %x, expected %x)"),
|
||||
msg->hdr.vers, REMOTE_PROTOCOL_VERSION);
|
||||
goto rpc_error;
|
||||
}
|
||||
if (msg->hdr.direction != REMOTE_CALL) {
|
||||
remoteDispatchFormatError (&rerr, _("direction (%d) != REMOTE_CALL"),
|
||||
(int) msg->hdr.direction);
|
||||
goto rpc_error;
|
||||
}
|
||||
if (msg->hdr.status != REMOTE_OK) {
|
||||
remoteDispatchFormatError (&rerr, _("status (%d) != REMOTE_OK"),
|
||||
(int) msg->hdr.status);
|
||||
@ -332,7 +464,8 @@ remoteDispatchClientRequest (struct qemud_server *server,
|
||||
|
||||
xdr_free (data->args_filter, (char*)&args);
|
||||
|
||||
rpc_error:
|
||||
if (rv < 0)
|
||||
goto rpc_error;
|
||||
|
||||
/* Return header. We're re-using same message object, so
|
||||
* only need to tweak direction/status fields */
|
||||
@ -341,10 +474,10 @@ rpc_error:
|
||||
/*msg->hdr.proc = msg->hdr.proc;*/
|
||||
msg->hdr.direction = REMOTE_REPLY;
|
||||
/*msg->hdr.serial = msg->hdr.serial;*/
|
||||
msg->hdr.status = rv < 0 ? REMOTE_ERROR : REMOTE_OK;
|
||||
msg->hdr.status = REMOTE_OK;
|
||||
|
||||
if (remoteEncodeClientMessageHeader(msg) < 0) {
|
||||
if (rv == 0) xdr_free (data->ret_filter, (char*)&ret);
|
||||
xdr_free (data->ret_filter, (char*)&ret);
|
||||
goto fatal_error;
|
||||
}
|
||||
|
||||
@ -356,32 +489,24 @@ rpc_error:
|
||||
XDR_ENCODE);
|
||||
|
||||
if (xdr_setpos(&xdr, msg->bufferOffset) == 0)
|
||||
goto fatal_error;
|
||||
goto xdr_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);
|
||||
}
|
||||
/* Serialise reply data */
|
||||
if (!((data->ret_filter) (&xdr, &ret)))
|
||||
goto xdr_error;
|
||||
|
||||
/* Update the length word. */
|
||||
msg->bufferOffset += xdr_getpos (&xdr);
|
||||
len = msg->bufferOffset;
|
||||
if (xdr_setpos (&xdr, 0) == 0)
|
||||
goto fatal_error;
|
||||
goto xdr_error;
|
||||
|
||||
if (!xdr_u_int (&xdr, &len))
|
||||
goto fatal_error;
|
||||
goto xdr_error;
|
||||
|
||||
xdr_destroy (&xdr);
|
||||
xdr_free (data->ret_filter, (char*)&ret);
|
||||
|
||||
/* Reset ready for I/O */
|
||||
msg->bufferLength = len;
|
||||
@ -393,9 +518,17 @@ rpc_error:
|
||||
|
||||
return 0;
|
||||
|
||||
fatal_error:
|
||||
rpc_error:
|
||||
/* Semi-bad stuff happened, we can still try to send back
|
||||
* an RPC error message to client */
|
||||
return remoteSerializeReplyError(client, &rerr, &msg->hdr);
|
||||
|
||||
|
||||
xdr_error:
|
||||
/* Seriously bad stuff happened, so we'll kill off this client
|
||||
and not send back any RPC error */
|
||||
xdr_free (data->ret_filter, (char*)&ret);
|
||||
xdr_destroy (&xdr);
|
||||
fatal_error:
|
||||
return -1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user