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@xxxxxxxxxx> --- 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 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list