Introduces an API for encoding the header field for outgoing messages
allowing some duplicated code to be eliminated
* qemud/dispatch.c, qemud/dispatch.h: add remoteEncodeClientMessageHeader
for encoding message header. Update remoteDispatchClientRequest to
use this method.
* qemud/remote.c: Update remoteDispatchDomainEventSend to use the
generic remoteEncodeClientMessageHeader() for encoding event
message hedaders. Push some logic from remoteRelayDomainEvent
down into remoteDispatchDomainEventSend.
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
qemud/dispatch.c | 99 +++++++++++++++++++++++++++++++++++++++++++----------
qemud/dispatch.h | 2 +
qemud/remote.c | 79 ++++++++++++++++++-------------------------
3 files changed, 115 insertions(+), 65 deletions(-)
diff --git a/qemud/dispatch.c b/qemud/dispatch.c
index 127f93b..29970e4 100644
--- a/qemud/dispatch.c
+++ b/qemud/dispatch.c
@@ -127,7 +127,10 @@ void remoteDispatchConnError (remote_error *rerr,
* @msg: the complete incoming message, whose header to decode
*
* Decodes the header part of the client message, but does not
- * validate the decoded fields in the header.
+ * validate the decoded fields in the header. It expects
+ * bufferLength to refer to length of the data packet. Upon
+ * return bufferOffset will refer to the amount of the packet
+ * consumed by decoding of the header.
*
* returns 0 if successfully decoded, -1 upon fatal error
*/
@@ -159,6 +162,61 @@ cleanup:
/*
+ * @msg: the outgoing message, whose header to encode
+ *
+ * Encodes the header part of the client message, setting the
+ * message offset ready to encode the payload. Leaves space
+ * for the length field later. Upon return bufferLength will
+ * refer to the total available space for message, while
+ * bufferOffset will refer to current space used by header
+ *
+ * returns 0 if successfully encoded, -1 upon fatal error
+ */
+int
+remoteEncodeClientMessageHeader (struct qemud_client_message *msg)
+{
+ XDR xdr;
+ int ret = -1;
+ unsigned int len = 0;
+
+ msg->bufferLength = sizeof(msg->buffer);
+ msg->bufferOffset = 0;
+
+ /* Format the header. */
+ xdrmem_create (&xdr,
+ msg->buffer,
+ msg->bufferLength,
+ XDR_ENCODE);
+
+ /* The real value is filled in shortly */
+ if (!xdr_u_int (&xdr, &len)) {
+ goto cleanup;
+ }
+
+ if (!xdr_remote_message_header (&xdr, &msg->hdr))
+ goto cleanup;
+
+ len = xdr_getpos(&xdr);
+ xdr_setpos(&xdr, 0);
+
+ /* Fill in current length - may be re-written later
+ * if a payload is added
+ */
+ if (!xdr_u_int (&xdr, &len)) {
+ goto cleanup;
+ }
+
+ msg->bufferOffset += len;
+
+ ret = 0;
+
+cleanup:
+ xdr_destroy(&xdr);
+ return ret;
+}
+
+
+/*
* @server: the unlocked server object
* @client: the locked client object
* @msg: the complete incoming message packet, with header already decoded
@@ -177,7 +235,6 @@ remoteDispatchClientRequest (struct qemud_server *server,
struct qemud_client_message *msg)
{
XDR xdr;
- remote_message_header rep;
remote_error rerr;
dispatch_args args;
dispatch_ret ret;
@@ -277,27 +334,29 @@ remoteDispatchClientRequest (struct qemud_server *server,
rpc_error:
- /* Return header. */
- rep.prog = msg->hdr.prog;
- rep.vers = msg->hdr.vers;
- rep.proc = msg->hdr.proc;
- rep.direction = REMOTE_REPLY;
- rep.serial = msg->hdr.serial;
- rep.status = rv < 0 ? REMOTE_ERROR : REMOTE_OK;
+ /* Return header. We're re-using same message object, so
+ * only need to tweak direction/status fields */
+ /*msg->hdr.prog = msg->hdr.prog;*/
+ /*msg->hdr.vers = msg->hdr.vers;*/
+ /*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;
- /* 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 (remoteEncodeClientMessageHeader(msg) < 0) {
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);
+
+ /* Now for the payload */
+ xdrmem_create (&xdr,
+ msg->buffer,
+ msg->bufferLength,
+ XDR_ENCODE);
+
+ if (xdr_setpos(&xdr, msg->bufferOffset) == 0)
goto fatal_error;
- }
/* If OK, serialise return structure, if error serialise error. */
if (rv >= 0) {
@@ -313,8 +372,9 @@ rpc_error:
xdr_free((xdrproc_t)xdr_remote_error, (char *)&rerr);
}
- /* Write the length word. */
- len = xdr_getpos (&xdr);
+ /* Update the length word. */
+ msg->bufferOffset += xdr_getpos (&xdr);
+ len = msg->bufferOffset;
if (xdr_setpos (&xdr, 0) == 0)
goto fatal_error;
@@ -323,6 +383,7 @@ rpc_error:
xdr_destroy (&xdr);
+ /* Reset ready for I/O */
msg->bufferLength = len;
msg->bufferOffset = 0;
diff --git a/qemud/dispatch.h b/qemud/dispatch.h
index db372f1..ab45b19 100644
--- a/qemud/dispatch.h
+++ b/qemud/dispatch.h
@@ -30,6 +30,8 @@
int
remoteDecodeClientMessageHeader (struct qemud_client_message *req);
+int
+remoteEncodeClientMessageHeader (struct qemud_client_message *req);
int
remoteDispatchClientRequest (struct qemud_server *server,
diff --git a/qemud/remote.c b/qemud/remote.c
index d0bc677..fb06dc3 100644
--- a/qemud/remote.c
+++ b/qemud/remote.c
@@ -91,7 +91,6 @@ const dispatch_data const *remoteGetDispatchData(int proc)
/* Prototypes */
static void
remoteDispatchDomainEventSend (struct qemud_client *client,
- struct qemud_client_message *msg,
virDomainPtr dom,
int event,
int detail);
@@ -108,14 +107,9 @@ int remoteRelayDomainEvent (virConnectPtr conn ATTRIBUTE_UNUSED,
REMOTE_DEBUG("Relaying domain event %d %d", event, detail);
if (client) {
- struct qemud_client_message *ev;
-
- if (VIR_ALLOC(ev) < 0)
- return -1;
-
virMutexLock(&client->lock);
- remoteDispatchDomainEventSend (client, ev, dom, event, detail);
+ remoteDispatchDomainEventSend (client, dom, event, detail);
if (qemudRegisterClientEvent(client->server, client, 1) < 0)
qemudDispatchClientFailure(client);
@@ -4433,72 +4427,65 @@ remoteDispatchDomainEventsDeregister (struct qemud_server *server
ATTRIBUTE_UNUS
static void
remoteDispatchDomainEventSend (struct qemud_client *client,
- struct qemud_client_message *msg,
virDomainPtr dom,
int event,
int detail)
{
- remote_message_header rep;
+ struct qemud_client_message *msg = NULL;
XDR xdr;
unsigned int len;
remote_domain_event_ret data;
- if (!client)
+ if (VIR_ALLOC(msg) < 0)
return;
- rep.prog = REMOTE_PROGRAM;
- rep.vers = REMOTE_PROTOCOL_VERSION;
- rep.proc = REMOTE_PROC_DOMAIN_EVENT;
- rep.direction = REMOTE_MESSAGE;
- rep.serial = 1;
- rep.status = REMOTE_OK;
+ msg->hdr.prog = REMOTE_PROGRAM;
+ msg->hdr.vers = REMOTE_PROTOCOL_VERSION;
+ msg->hdr.proc = REMOTE_PROC_DOMAIN_EVENT;
+ msg->hdr.direction = REMOTE_MESSAGE;
+ msg->hdr.serial = 1;
+ msg->hdr.status = REMOTE_OK;
- /* Serialise the return header and event. */
- 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)) {
- /*remoteDispatchError (client, NULL, "%s", _("xdr_u_int failed
(1)"));*/
- xdr_destroy (&xdr);
- return;
- }
+ if (remoteEncodeClientMessageHeader(msg) < 0)
+ goto error;
- if (!xdr_remote_message_header (&xdr, &rep)) {
- xdr_destroy (&xdr);
- return;
- }
+ /* Serialise the return header and event. */
+ xdrmem_create (&xdr,
+ msg->buffer + msg->bufferOffset,
+ msg->bufferLength - msg->bufferOffset,
+ XDR_ENCODE);
/* build return data */
make_nonnull_domain (&data.dom, dom);
data.event = event;
data.detail = detail;
- if (!xdr_remote_domain_event_ret(&xdr, &data)) {
- /*remoteDispatchError (client, NULL, "%s", _("serialise return
struct"));*/
- xdr_destroy (&xdr);
- return;
- }
+ if (!xdr_remote_domain_event_ret(&xdr, &data))
+ goto xdr_error;
- len = xdr_getpos (&xdr);
- if (xdr_setpos (&xdr, 0) == 0) {
- /*remoteDispatchError (client, NULL, "%s", _("xdr_setpos
failed"));*/
- xdr_destroy (&xdr);
- return;
- }
- if (!xdr_u_int (&xdr, &len)) {
- /*remoteDispatchError (client, NULL, "%s", _("xdr_u_int failed
(2)"));*/
- xdr_destroy (&xdr);
- return;
- }
+ /* Update length word */
+ msg->bufferOffset += xdr_getpos (&xdr);
+ len = msg->bufferOffset;
+ if (xdr_setpos (&xdr, 0) == 0)
+ goto xdr_error;
- xdr_destroy (&xdr);
+ if (!xdr_u_int (&xdr, &len))
+ goto xdr_error;
/* Send it. */
msg->async = 1;
msg->bufferLength = len;
msg->bufferOffset = 0;
qemudClientMessageQueuePush(&client->tx, msg);
+
+ xdr_destroy (&xdr);
+ return;
+
+xdr_error:
+ xdr_destroy(&xdr);
+error:
+ VIR_FREE(msg);
}
/*----- Helpers. -----*/
--
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 :|