Remote protocol working.
authorRichard W.M. Jones <rjones@redhat.com>
Tue, 3 Jan 2012 14:59:47 +0000 (14:59 +0000)
committerRichard W.M. Jones <rjones@redhat.com>
Tue, 3 Jan 2012 14:59:47 +0000 (14:59 +0000)
13 files changed:
.gitignore
configure.ac
daemon/Makefile.am
daemon/wrappid.c
generator/wrappi_c.ml
generator/wrappi_c_impl.ml
generator/wrappi_c_xdr.ml
lib/Makefile.am
lib/internal.h
lib/proto-xdr-request.c [new file with mode: 0644]
lib/proto-xdr.c
lib/proto-xdr.h
lib/wrappi.c

index 0d890ca..f73b822 100644 (file)
@@ -28,11 +28,14 @@ Makefile.in
 /generator/generator
 /generator/stamp-generator
 /install-sh
+/lib/call.c
 /lib/free_structs.c
-/lib/internal-procs.h
 /lib/internal-procs.c
-/lib/proto-xdr-impl.c
+/lib/internal-procs.h
+/lib/internal-procs-lookup.c
+/lib/internal-procs-lookup.gperf
 /lib/wrappi.h
+/lib/xdr.c
 /libtool
 /local*
 /ltmain.sh
index cfe9053..54537c3 100644 (file)
@@ -60,6 +60,11 @@ fi
 dnl Check support for 64 bit file offsets.
 AC_SYS_LARGEFILE
 
+dnl Check for gperf.
+AC_CHECK_PROG([GPERF],[gperf],[gperf],[no])
+test "x$GPERF" = "xno" &&
+     AC_MSG_ERROR([gperf must be installed])
+
 dnl Check for OCaml compiler.
 AC_PROG_OCAML
 if test "$OCAMLC" = "no"; then
index cdbc244..94a7a25 100644 (file)
@@ -19,9 +19,8 @@ sbin_PROGRAMS = wrappid
 
 wrappid_SOURCES = \
        ../lib/wrappi.h \
-       ../lib/internal.h \
-       ../lib/internal-procs.h \
        ../lib/proto-xdr.h \
+       ../lib/proto-xdr.c \
        wrappid.c
 wrappid_CFLAGS = -I../lib $(WARN_CFLAGS) $(WERROR_CFLAGS)
 wrappid_LDADD = ../lib/libwrappi.la
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);
   }
 }
index 099a7c2..5a73660 100644 (file)
@@ -173,6 +173,50 @@ extern void wrap_close (wrap_h *w);
 
   pr "\
 
+/* C API introspection. */
+";
+  iter_entry_points api (
+    fun ep ->
+      let name = ep.ep_name in
+      let ret, req, opt = ep.ep_ftype in
+
+      pr "struct wrap_%s_args {\n" name;
+      List.iter (
+        fun (n, t, _) ->
+          let t = c_of_ptype ~param:true t in
+          let sep = (* "const char *" - omit space after asterisk *)
+            let len = String.length t in
+            if isalnum t.[len-1] then " " else "" in
+          pr "  %s%s%s;\n" t sep n
+      ) req;
+      pr "};\n";
+      pr "\n";
+
+      if opt <> [] then assert false; (* XXX not implemented *)
+
+      pr "struct wrap_%s_ret {\n" name;
+      (match ret with
+      | RVoid -> ()
+      | RStaticString -> pr "  const char *r;\n";
+      | Return t ->
+        let t = c_of_ptype ~param:false t in
+        let sep = (* "const char *" - omit space after asterisk *)
+          let len = String.length t in
+          if isalnum t.[len-1] then " " else "" in
+        pr "  %s%sr;\n" t sep
+      );
+
+      pr "};\n";
+      pr "\n";
+  );
+
+  pr "\
+extern void wrap_call (wrap_h *w, const char *name, const void *args, void *ret);
+extern size_t wrap_call_get_args_struct_size (wrap_h *w, const char *name);
+extern size_t wrap_call_get_ret_struct_size (wrap_h *w, const char *name);
+extern /* xdrproc_t */ void *wrap_call_get_args_xdrproc (wrap_h *w, const char *name);
+extern /* xdrproc_t */ void *wrap_call_get_ret_xdrproc (wrap_h *w, const char *name);
+
 #ifdef __cplusplus
 }
 #endif
@@ -180,6 +224,126 @@ extern void wrap_close (wrap_h *w);
 #endif /* WRAPPI_H_ */
 "
 
+let generate_lib_call_c api =
+  generate_header inputs CStyle LGPLv2plus;
+
+  pr "\
+#include <config.h>
+
+#include <stdio.h>
+
+#include \"wrappi.h\"
+#include \"internal.h\"
+
+void
+wrap_call (wrap_h *w, const char *name, const void *args, void *ret)
+{
+  int proc;
+
+  proc = wrap_int_lookup_proc_entry (name);
+  if (proc == -1) {
+    set_error (\"procedure not found: %%s\", name);
+    return;
+  }
+
+  /* This ends up calling wrap_int_call_<name>. */
+  wrap_int_proc_table[proc].call (w, args, ret);
+}
+
+size_t
+wrap_call_get_args_struct_size (wrap_h *w, const char *name)
+{
+  int proc;
+
+  proc = wrap_int_lookup_proc_entry (name);
+  if (proc == -1) {
+    set_error (\"procedure not found: %%s\", name);
+    return 0;
+  }
+
+  return wrap_int_proc_table[proc].args_struct_size;
+}
+
+size_t
+wrap_call_get_ret_struct_size (wrap_h *w, const char *name)
+{
+  int proc;
+
+  proc = wrap_int_lookup_proc_entry (name);
+  if (proc == -1) {
+    set_error (\"procedure not found: %%s\", name);
+    return 0;
+  }
+
+  return wrap_int_proc_table[proc].ret_struct_size;
+}
+
+/* Really this returns xdrproc_t but we don't want to have to include
+ * XDR headers in the public API.
+ */
+void *
+wrap_call_get_args_xdrproc (wrap_h *w, const char *name)
+{
+  int proc;
+
+  proc = wrap_int_lookup_proc_entry (name);
+  if (proc == -1) {
+    set_error (\"procedure not found: %%s\", name);
+    return 0;
+  }
+
+  return wrap_int_proc_table[proc].args_xdrproc;
+}
+
+/* Really this returns xdrproc_t but we don't want to have to include
+ * XDR headers in the public API.
+ */
+void *
+wrap_call_get_ret_xdrproc (wrap_h *w, const char *name)
+{
+  int proc;
+
+  proc = wrap_int_lookup_proc_entry (name);
+  if (proc == -1) {
+    set_error (\"procedure not found: %%s\", name);
+    return 0;
+  }
+
+  return wrap_int_proc_table[proc].ret_xdrproc;
+}
+";
+
+  iter_entry_points api (
+    fun ep ->
+      pr "\n";
+
+      let name = ep.ep_name in
+      let ret, req, opt = ep.ep_ftype in
+
+      pr "void\n";
+      pr "wrap_int_call_%s (wrap_h *w, const void *argsv, void *retv)\n" name;
+      pr "{\n";
+      if req <> [] || opt <> [] then
+        pr "  const struct wrap_%s_args *args = argsv;\n" name;
+      if ret <> RVoid then
+        pr "  struct wrap_%s_ret *ret = retv;\n" name;
+      pr "\n";
+
+      pr "  ";
+      (match ret with
+      | RVoid -> ()
+      | _ -> pr "ret->r = "
+      );
+
+      pr "wrap_%s (w" name;
+      List.iter (fun (n, _, _) -> pr ", args->%s" n) req;
+
+      if opt <> [] then assert false; (* XXX not implemented *)
+
+      pr ");\n";
+      pr "}\n";
+  )
+
 (* Functions for freeing structs are part of the C bindings.  We don't
  * want them to be exposed in other languages, although they will be
  * used by other bindings.
@@ -188,6 +352,8 @@ let generate_lib_free_structs_c api =
   generate_header inputs CStyle LGPLv2plus;
 
   pr "\
+#include <config.h>
+
 #include <stdlib.h>
 
 #include \"wrappi.h\"
@@ -226,4 +392,5 @@ let generate_lib_free_structs_c api =
 
 let generate api =
   output_to "lib/wrappi.h" generate_lib_wrappi_h api;
+  output_to "lib/call.c" generate_lib_call_c api;
   output_to "lib/free_structs.c" generate_lib_free_structs_c api
index 2b08eb4..0b4b3a3 100644 (file)
@@ -182,8 +182,8 @@ pr "\
 
     pr "  } else {\n";
     pr "    /* Remote connection. */\n";
-    pr "    struct wrap_int_%s_args args;\n" name;
-    pr "    struct wrap_int_%s_ret ret;\n" name;
+    pr "    struct wrap_%s_args args;\n" name;
+    pr "    struct wrap_%s_ret ret;\n" name;
     pr "\n";
     List.iter (fun (n, _, _) -> pr "    args.%s = %s;\n" n n) req;
 
@@ -236,89 +236,84 @@ enum {
   pr "#define wrap_int_nr_procs %d\n" (StringMap.cardinal api.api_entry_points);
 
   pr "\n";
+  pr "#endif /* WRAPPI_INTERNAL_PROCS_H_ */\n"
+
+let generate_lib_internal_procs_c api =
+  generate_header inputs CStyle LGPLv2plus;
 
   pr "\
-/* These structures are used as the first stage of marshalling
- * arguments and return types of entry points.  It is much more
- * convenient to be able to pass around one of these structs,
- * than to have to pass a variable list of arguments.  They must
- * not be exposed externally.
- */
+#include <config.h>
+
+#include <stdlib.h>
+
+#include \"wrappi.h\"
+#include \"internal.h\"
+
+/* Defined in lib/call.c */
 ";
 
   iter_entry_points api (
     fun ep ->
-      let name = ep.ep_name in
-      let ret, req, opt = ep.ep_ftype in
-
-      pr "struct wrap_int_%s_args {\n" name;
-      List.iter (
-        fun (n, t, _) ->
-          let t = c_of_ptype ~param:true t in
-          let sep = (* "const char *" - omit space after asterisk *)
-            let len = String.length t in
-            if isalnum t.[len-1] then " " else "" in
-          pr "  %s%s%s;\n" t sep n
-      ) req;
-      pr "};\n";
-      pr "\n";
+      pr "extern void wrap_int_call_%s (wrap_h *w, const void *args, void *ret);\n" ep.ep_name
+  );
+  pr "\n";
 
-      if opt <> [] then assert false; (* XXX not implemented *)
-
-      pr "struct wrap_int_%s_ret {\n" name;
-      (match ret with
-      | RVoid -> ()
-      | RStaticString -> pr "  const char *r;\n";
-      | Return t ->
-        let t = c_of_ptype ~param:false t in
-        let sep = (* "const char *" - omit space after asterisk *)
-          let len = String.length t in
-          if isalnum t.[len-1] then " " else "" in
-        pr "  %s%sr;\n" t sep
-      );
-
-      pr "};\n";
-      pr "\n";
+  pr "/* Defined in lib/xdr.c */\n";
+
+  iter_entry_points api (
+    fun ep ->
+      let name = ep.ep_name in
+      pr "extern bool_t wrap_int_xdr_%s_args (XDR *, struct wrap_%s_args *);\n" name name;
+      pr "extern bool_t wrap_int_xdr_%s_ret (XDR *, struct wrap_%s_ret *);\n" name name
   );
+  pr "\n";
+
+  pr "const struct proc_table wrap_int_proc_table[] = {\n";
 
   iter_entry_points api (
     fun ep ->
-      if not ep.ep_local then (
-        let name = ep.ep_name in
-        pr "extern bool_t wrap_int_xdr_%s_args (XDR *, struct wrap_int_%s_args *);\n" name name;
-        pr "extern bool_t wrap_int_xdr_%s_ret (XDR *, struct wrap_int_%s_ret *);\n" name name
-      )
+      let name = ep.ep_name in
+      pr "  [wrap_int_%s_num] = {\n" name;
+      pr "    .name = \"%s\",\n" name;
+      pr "    .args_struct_size = sizeof (struct wrap_%s_args),\n" name;
+      pr "    .ret_struct_size = sizeof (struct wrap_%s_ret),\n" name;
+      pr "    .call = &wrap_int_call_%s,\n" name;
+      pr "    .args_xdrproc = (xdrproc_t) &wrap_int_xdr_%s_args,\n" name;
+      pr "    .ret_xdrproc = (xdrproc_t) &wrap_int_xdr_%s_ret,\n" name;
+      pr "  },\n"
   );
 
-  pr "\n";
-  pr "#endif /* WRAPPI_INTERNAL_PROCS_H_ */\n"
+  pr "};\n"
 
-let generate_lib_internal_procs_c api =
+let generate_lib_internal_procs_lookup_gperf api =
   generate_header inputs CStyle LGPLv2plus;
 
   pr "\
+%%language=ANSI-C
+%%define lookup-function-name wrap_int_gperf_lookup_proc_entry
+%%readonly-tables
+%%null-strings
+
+%%{
+#include <config.h>
+
 #include <stdlib.h>
+#include <string.h>
 
 #include \"wrappi.h\"
 #include \"internal.h\"
+%%}
 
-";
+struct proc_entry;
 
-  pr "const struct proc_table wrap_int_proc_table[] = {\n";
+%%%%
+";
 
   iter_entry_points api (
     fun ep ->
       let name = ep.ep_name in
-      pr "  [wrap_int_%s_num] = {\n" name;
-      pr "    .name = \"%s\",\n" name;
-      if not ep.ep_local then (
-        pr "    .xdr_args = (xdrproc_t) &wrap_int_xdr_%s_args,\n" name;
-        pr "    .xdr_ret = (xdrproc_t) &wrap_int_xdr_%s_ret,\n" name;
-      );
-      pr "  },\n"
-  );
-
-  pr "};\n"
+      pr "%s, wrap_int_%s_num\n" name name
+  )
 
 (* Make a unique, reproducible filename for each entry point. *)
 let filename_of_ep ep =
@@ -377,6 +372,9 @@ let generate api =
   output_to "lib/internal-procs.c"
     generate_lib_internal_procs_c api;
 
+  output_to "lib/internal-procs-lookup.gperf"
+    generate_lib_internal_procs_lookup_gperf api;
+
   output_to "lib/implementation_files.mk"
     generate_lib_implementation_files_mk api;
 
index 2eb4b52..78a6961 100644 (file)
@@ -64,10 +64,12 @@ let pr_xdr_of_ptype n = function
   | TUnion uname ->
     pr "  if (!xdr_union_%s (xdrs, %s)) return FALSE;\n" uname n
 
-let generate_lib_proto_xdr_impl_c api =
+let generate_lib_xdr_c api =
   generate_header inputs CStyle LGPLv2plus;
 
   pr "\
+#include <config.h>
+
 #include <stdlib.h>
 #include <rpc/xdr.h>
 
@@ -105,44 +107,42 @@ xdr_unlimited_string (XDR *xdrs, unlimited_string *objp)
 
   iter_entry_points api (
     fun ep ->
-      if not ep.ep_local then (
-        let name = ep.ep_name in
-        let ret, req, opt = ep.ep_ftype in
-
-        pr "\n";
-        pr "bool_t\n";
-        pr "wrap_int_xdr_%s_args (XDR *xdrs, struct wrap_int_%s_args *args)\n"
-          name name;
-        pr "{\n";
-
-        List.iter (
-          fun (n, t, _) ->
-            pr_xdr_of_ptype (sprintf "args->%s" n) t
-        ) req;
-
-        if opt <> [] then assert false; (* XXX not implemented *)
-
-        pr "  return TRUE;\n";
-        pr "}\n";
-
-        pr "\n";
-        pr "bool_t\n";
-        pr "wrap_int_xdr_%s_ret (XDR *xdrs, struct wrap_int_%s_ret *ret)\n"
-          name name;
-        pr "{\n";
-
-        (match ret with
-        | RVoid -> ()
-        | RStaticString ->
-          assert false (* RStaticString cannot be used for remote functions. *)
-        | Return t ->
-          pr_xdr_of_ptype "ret->r" t
-        );
-
-        pr "  return TRUE;\n";
-        pr "}\n"
-      )
+      let name = ep.ep_name in
+      let ret, req, opt = ep.ep_ftype in
+
+      pr "\n";
+      pr "bool_t\n";
+      pr "wrap_int_xdr_%s_args (XDR *xdrs, struct wrap_%s_args *args)\n"
+        name name;
+      pr "{\n";
+
+      List.iter (
+        fun (n, t, _) ->
+          pr_xdr_of_ptype (sprintf "args->%s" n) t
+      ) req;
+
+      if opt <> [] then assert false; (* XXX not implemented *)
+
+      pr "  return TRUE;\n";
+      pr "}\n";
+
+      pr "\n";
+      pr "bool_t\n";
+      pr "wrap_int_xdr_%s_ret (XDR *xdrs, struct wrap_%s_ret *ret)\n"
+        name name;
+      pr "{\n";
+
+      (match ret with
+      | RVoid -> ()
+      | RStaticString ->
+        pr_xdr_of_ptype "ret->r" TString (* XXX is this right? *)
+      | Return t ->
+        pr_xdr_of_ptype "ret->r" t
+      );
+
+      pr "  return TRUE;\n";
+      pr "}\n"
   )
 
 let generate api =
-  output_to "lib/proto-xdr-impl.c" generate_lib_proto_xdr_impl_c api
+  output_to "lib/xdr.c" generate_lib_xdr_c api
index edcb328..0c3807b 100644 (file)
@@ -29,16 +29,24 @@ libwrappi_la_LDFLAGS = -version-info $(LIB_MINOR):0:$(LIB_MINOR)
 libwrappi_la_SOURCES = \
        wrappi.h \
        wrappi.c \
+       call.c \
        connect.c \
        free_structs.c \
        internal-procs.c \
+       internal-procs-lookup.c \
        internal-procs.h \
        proto-ssh.c \
        proto-xdr.c \
        proto-xdr.h \
-       proto-xdr-impl.c \
+       proto-xdr-request.c \
+       xdr.c \
        $(local_implementation_files) \
        $(remote_implementation_files)
 libwrappi_la_CFLAGS = $(WARN_CFLAGS) $(WERROR_CFLAGS)
 
+internal-procs-lookup.c: internal-procs-lookup.gperf
+       rm -f $@
+       $(GPERF) -t $< > $@-t
+       mv $@-t $@
+
 CLEANFILES = *~
index 69128e9..311f030 100644 (file)
@@ -72,6 +72,7 @@ struct wrap_h {
   wrap_int_set_error_errno ((struct wrap_internal_h *)w, (errno), __func__, fs)
 
 extern void wrap_int_connect_ssh (wrap_h *w);
+extern int wrap_int_lookup_proc_entry (const char *name);
 extern void wrap_int_make_request (wrap_h *w, int proc_nr, const void *args, void *ret);
 extern void wrap_int_make_request_xdr (wrap_h *w, int proc_nr, const void *args, void *ret);
 extern void wrap_int_set_error (struct wrap_internal_h *w, const char *func, const char *fs, ...);
@@ -84,13 +85,24 @@ extern void wrap_int_set_error_errno (struct wrap_internal_h *w, int errnum, con
 struct proc_table {
   const char *name;             /* The name of this entry point. */
 
+  /* Size of the args and ret structs. */
+  size_t args_struct_size;
+  size_t ret_struct_size;
+
+  /* Call this procedure. */
+  void (*call) (wrap_h *w, const void *args, void *ret);
+
   /* XDR encode/decode functions for serializing the args and ret. */
-  xdrproc_t xdr_args;
-  xdrproc_t xdr_ret;
+  xdrproc_t args_xdrproc;
+  xdrproc_t ret_xdrproc;
 };
 
 extern const struct proc_table wrap_int_proc_table[];
 
 #include "internal-procs.h"
 
+/* Defined and used by lib/internal-procs-lookup.gperf */
+struct proc_entry { char *name; int proc_nr; };
+extern const struct proc_entry *wrap_int_gperf_lookup_proc_entry (register const char *str, register unsigned int len);
+
 #endif /* WRAPPI_INTERNAL_H_ */
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);
+}
index aa7a782..5dfb3aa 100644 (file)
@@ -23,8 +23,6 @@
 #include <assert.h>
 #include <rpc/xdr.h>
 
-#include "wrappi.h"
-#include "internal.h"
 #include "proto-xdr.h"
 
 bool_t
@@ -48,106 +46,3 @@ wrap_int_xdr_message_error (XDR *xdrs, struct wrap_int_message_error *err)
 
   return TRUE;
 }
-
-void
-wrap_int_make_request_xdr (wrap_h *w, int proc_nr, const void *args, void *ret)
-{
-  XDR xdr;
-  xdrproc_t xdrp_args;
-  xdrproc_t xdrp_ret;
-  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);
-  xdrp_args = wrap_int_proc_table[proc_nr].xdr_args;
-  assert (xdrp_args);
-  xdrp_ret = wrap_int_proc_table[proc_nr].xdr_ret;
-  assert (xdrp_ret);
-
-  /* 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 (!xdrp_args (&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);
-    return;
-  }
-  if (hdr.protocol != WRAP_INT_PROTOCOL) {
-    set_error ("error in reply: unexpected protocol number (%d)", hdr.protocol);
-    xdr_destroy (&xdr);
-    return;
-  }
-  if (hdr.serial != w->serial) {
-    set_error ("error in reply: unexpected serial (%d)", hdr.serial);
-    xdr_destroy (&xdr);
-    return;
-  }
-
-  switch (hdr.type) {
-  case WRAP_INT_PROTO_TYPE_REPLY:
-    /* Receive the return value. */
-    if (!xdrp_ret (&xdr, (void *) ret)) {
-      set_error ("error receiving return value");
-      xdr_destroy (&xdr);
-      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);
-      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);
-
-    break;
-
-  default:
-    set_error ("error in reply: unexpected type (%x)", hdr.type);
-    xdr_destroy (&xdr);
-    return;
-  }
-
-  xdr_destroy (&xdr);
-}
index a73fffb..02d7b44 100644 (file)
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#ifndef PROTO_XDR_H_
-#define PROTO_XDR_H_
+#ifndef WRAPPI_PROTO_XDR_H_
+#define WRAPPI_PROTO_XDR_H_
 
 #include <stdint.h>
-#include <string.h>
-#include <errno.h>
 #include <rpc/types.h>
 #include <rpc/xdr.h>
 
@@ -48,4 +46,4 @@ struct wrap_int_message_error {
 extern bool_t wrap_int_xdr_message_header (XDR *, struct wrap_int_message_header *);
 extern bool_t wrap_int_xdr_message_error (XDR *, struct wrap_int_message_error *);
 
-#endif /* WRAPPI_INTERNAL_H_ */
+#endif /* WRAPPI_PROTO_XDR_H_ */
index c0350f5..3ea0449 100644 (file)
@@ -112,3 +112,15 @@ wrap_int_set_error_errno (struct wrap_internal_h *w,
 
   set_error_buf (w, msg, errnum, func);
 }
+
+/* Note the gperf perfect hash in lib/internal-procs-lookup.gperf */
+int
+wrap_int_lookup_proc_entry (const char *name)
+{
+  const struct proc_entry *v =
+    wrap_int_gperf_lookup_proc_entry (name, strlen (name));
+  if (v)
+    return v->proc_nr;
+  else
+    return -1;
+}