Remote protocol working.
[wrappi.git] / lib / proto-xdr-request.c
diff --git a/lib/proto-xdr-request.c b/lib/proto-xdr-request.c
new file mode 100644 (file)
index 0000000..620c6dd
--- /dev/null
@@ -0,0 +1,137 @@
+/* wrappi
+ * Copyright (C) 2011-2012 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <rpc/xdr.h>
+
+#include "wrappi.h"
+#include "internal.h"
+#include "proto-xdr.h"
+
+void
+wrap_int_make_request_xdr (wrap_h *w, int proc_nr, const void *args, void *ret)
+{
+  XDR xdr;
+  xdrproc_t args_xdrproc;
+  xdrproc_t ret_xdrproc;
+  struct wrap_int_message_header hdr;
+  struct wrap_int_message_error err;
+
+  memset (&hdr, 0, sizeof hdr);
+
+  hdr.proc = (char *) wrap_int_proc_table[proc_nr].name;
+  assert (hdr.proc);
+  args_xdrproc = wrap_int_proc_table[proc_nr].args_xdrproc;
+  ret_xdrproc = wrap_int_proc_table[proc_nr].ret_xdrproc;
+
+  /* Construct the header. */
+  w->serial++;
+
+  hdr.magic = WRAP_INT_PROTO_MAGIC;
+  hdr.protocol = WRAP_INT_PROTOCOL;
+  hdr.serial = w->serial;
+  hdr.type = WRAP_INT_PROTO_TYPE_REQUEST;
+
+  /* Send the header. */
+  xdrstdio_create (&xdr, w->wfp, XDR_ENCODE);
+  if (!wrap_int_xdr_message_header (&xdr, &hdr)) {
+    set_error ("error sending request header");
+    xdr_destroy (&xdr);
+    return;
+  }
+
+  /* Send the request arguments. */
+  if (!args_xdrproc (&xdr, (void *) args)) {
+    set_error ("error sending request arguments");
+    xdr_destroy (&xdr);
+    return;
+  }
+  xdr_destroy (&xdr);
+
+  /* Receive the reply header. */
+  xdrstdio_create (&xdr, w->rfp, XDR_DECODE);
+  memset (&hdr, 0, sizeof hdr);
+  if (!wrap_int_xdr_message_header (&xdr, &hdr)) {
+    set_error ("error receiving reply header");
+    xdr_destroy (&xdr);
+    return;
+  }
+
+  /* Check the reply header. */
+  if (hdr.magic != WRAP_INT_PROTO_MAGIC) {
+    set_error ("error in reply: unexpected magic (%x)", hdr.magic);
+    xdr_destroy (&xdr);
+    xdr_free ((xdrproc_t) wrap_int_xdr_message_header, (void *) &hdr);
+    return;
+  }
+  if (hdr.protocol != WRAP_INT_PROTOCOL) {
+    set_error ("error in reply: unexpected protocol number (%d)", hdr.protocol);
+    xdr_destroy (&xdr);
+    xdr_free ((xdrproc_t) wrap_int_xdr_message_header, (void *) &hdr);
+    return;
+  }
+  if (hdr.serial != w->serial) {
+    set_error ("error in reply: unexpected serial (%d)", hdr.serial);
+    xdr_destroy (&xdr);
+    xdr_free ((xdrproc_t) wrap_int_xdr_message_header, (void *) &hdr);
+    return;
+  }
+
+  switch (hdr.type) {
+  case WRAP_INT_PROTO_TYPE_REPLY:
+    /* Receive the return value. */
+    if (!ret_xdrproc (&xdr, (void *) ret)) {
+      set_error ("error receiving return value");
+      xdr_destroy (&xdr);
+      xdr_free ((xdrproc_t) wrap_int_xdr_message_header, (void *) &hdr);
+      return;
+    }
+    break;
+
+  case WRAP_INT_PROTO_TYPE_ERROR:
+    /* Receive the error message etc. */
+    memset (&err, 0, sizeof err);
+    if (!wrap_int_xdr_message_error (&xdr, &err)) {
+      set_error ("error receiving error message");
+      xdr_destroy (&xdr);
+      xdr_free ((xdrproc_t) wrap_int_xdr_message_header, (void *) &hdr);
+      return;
+    }
+
+    /* XXX errno should be converted to an integer here */
+    /* XXX func should be set, but it's not static! */
+    set_error ("%s", err.error_message);
+    xdr_free ((xdrproc_t) wrap_int_xdr_message_error, (void *) &err);
+    xdr_free ((xdrproc_t) wrap_int_xdr_message_header, (void *) &hdr);
+
+    break;
+
+  default:
+    set_error ("error in reply: unexpected type (%x)", hdr.type);
+    xdr_destroy (&xdr);
+    xdr_free ((xdrproc_t) wrap_int_xdr_message_header, (void *) &hdr);
+    return;
+  }
+
+  xdr_destroy (&xdr);
+  xdr_free ((xdrproc_t) wrap_int_xdr_message_header, (void *) &hdr);
+}