#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <rpc/xdr.h>
#include "wrappi.h"
-
-/* XXX XDR code should be in its own mini-library.
- * OR we should export a way to serialize function calls.
- */
-#include "internal.h"
+#include "../lib/proto-xdr.h"
static void main_loop (void);
main_loop (void)
{
XDR xdr;
- xdrproc_t xdrp_args;
- xdrproc_t xdrp_ret;
struct wrap_int_message_header hdr;
struct wrap_int_message_error err;
- size_t i;
+ xdrproc_t args_xdrproc;
+ xdrproc_t ret_xdrproc;
+ void *argsv, *retv;
for (;;) {
/* Receive the request header. */
memset (&hdr, 0, sizeof hdr);
if (!wrap_int_xdr_message_header (&xdr, &hdr)) {
fprintf (stderr, "error receiving request header\n");
+ xdr_destroy (&xdr);
return;
}
if (hdr.magic != WRAP_INT_PROTO_MAGIC) {
fprintf (stderr, "error in request: unexpected magic (%x)\n",
hdr.magic);
- return;
+ xdr_destroy (&xdr);
+ return;
}
if (hdr.protocol != WRAP_INT_PROTOCOL) {
fprintf (stderr, "error in request: unexpected protocol number (%d)\n",
hdr.protocol);
+ xdr_destroy (&xdr);
return;
}
if (hdr.type != WRAP_INT_PROTO_TYPE_REQUEST) {
fprintf (stderr, "error in request: unexpected type (%d)\n",
hdr.type);
+ xdr_destroy (&xdr);
return;
}
- /* Convert the proc name to the internal entry point. */
- /* XXX We're going to use gperf here, as we do in libguestfs. */
- for (i = 0; i < wrap_int_nr_procs; ++i) {
- if (STREQ (wrap_int_proc_table[i].name, hdr.proc))
- goto found;
+ args_xdrproc = wrap_call_get_args_xdrproc (w, hdr.proc);
+ if (wrap_error (w)) {
+ xdr_destroy (&xdr);
+ return;
+ }
+ ret_xdrproc = wrap_call_get_ret_xdrproc (w, hdr.proc);
+ if (wrap_error (w)) {
+ xdr_destroy (&xdr);
+ return;
}
- fprintf (stderr, "unknown proc name in request: %s\n", hdr.proc);
- exit (EXIT_FAILURE);
- found:
- xdrp_args = wrap_int_proc_table[i].xdr_args;
- assert (xdrp_args);
- xdrp_ret = wrap_int_proc_table[i].xdr_ret;
- assert (xdrp_ret);
+ argsv = calloc (1, wrap_call_get_args_struct_size (w, hdr.proc));
+ if (argsv == NULL) {
+ perror ("malloc");
+ exit (EXIT_FAILURE);
+ }
+ retv = calloc (1, wrap_call_get_ret_struct_size (w, hdr.proc));
+ if (retv == NULL) {
+ perror ("malloc");
+ exit (EXIT_FAILURE);
+ }
/* Receive the arguments. */
-
+ if (!args_xdrproc (&xdr, argsv)) {
+ fprintf (stderr, "error receiving request arguments\n");
+ xdr_destroy (&xdr);
+ free (argsv);
+ free (retv);
+ return;
+ }
+
+ xdr_destroy (&xdr);
+
+ /* Call the underlying API. */
+ wrap_call (w, hdr.proc, argsv, retv);
+ free (argsv);
+ xdrstdio_create (&xdr, stdout, XDR_ENCODE);
+ if (! wrap_error (w)) {
+ /* Send back a normal reply. */
+ hdr.type = WRAP_INT_PROTO_TYPE_REPLY;
+
+ if (!wrap_int_xdr_message_header (&xdr, &hdr)) {
+ fprintf (stderr, "error sending reply header\n");
+ xdr_destroy (&xdr);
+ free (retv);
+ return;
+ }
+
+ if (!ret_xdrproc (&xdr, retv)) {
+ fprintf (stderr, "error sending reply return value\n");
+ xdr_destroy (&xdr);
+ free (retv);
+ return;
+ }
+ }
+ else {
+ /* Send back an error reply. */
+ err.error_message = (char *) wrap_get_error (w);
+ err.error_func = (char *) wrap_get_error_func (w);
+ err.error_errno = (char *) ""; /* XXX set this properly */
+
+ hdr.type = WRAP_INT_PROTO_TYPE_ERROR;
+
+ if (!wrap_int_xdr_message_header (&xdr, &hdr)) {
+ fprintf (stderr, "error sending reply error header\n");
+ xdr_destroy (&xdr);
+ free (retv);
+ return;
+ }
+
+ if (!wrap_int_xdr_message_error (&xdr, &err)) {
+ fprintf (stderr, "error sending reply error struct\n");
+ xdr_destroy (&xdr);
+ free (retv);
+ return;
+ }
+ }
+ free (retv);
+ xdr_destroy (&xdr);
+ xdr_free ((xdrproc_t) wrap_int_xdr_message_header, (void *) &hdr);
}
}