Remote protocol working.
[wrappi.git] / daemon / wrappid.c
index 4fb1f11..d6ce2b4 100644 (file)
 
 #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);
 
@@ -59,11 +56,11 @@ static 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. */
@@ -71,44 +68,111 @@ main_loop (void)
     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);
   }
 }