From 2c2b03cd99c55606d16e02b014a8a63055874867 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 3 Jan 2012 14:59:47 +0000 Subject: [PATCH] Remote protocol working. --- .gitignore | 7 +- configure.ac | 5 ++ daemon/Makefile.am | 3 +- daemon/wrappid.c | 108 +++++++++++++++++++++++------ generator/wrappi_c.ml | 167 +++++++++++++++++++++++++++++++++++++++++++++ generator/wrappi_c_impl.ml | 114 +++++++++++++++---------------- generator/wrappi_c_xdr.ml | 78 ++++++++++----------- lib/Makefile.am | 10 ++- lib/internal.h | 16 ++++- lib/proto-xdr-request.c | 137 +++++++++++++++++++++++++++++++++++++ lib/proto-xdr.c | 105 ---------------------------- lib/proto-xdr.h | 8 +-- lib/wrappi.c | 12 ++++ 13 files changed, 534 insertions(+), 236 deletions(-) create mode 100644 lib/proto-xdr-request.c diff --git a/.gitignore b/.gitignore index 0d890ca..f73b822 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/configure.ac b/configure.ac index cfe9053..54537c3 100644 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/daemon/Makefile.am b/daemon/Makefile.am index cdbc244..94a7a25 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -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 diff --git a/daemon/wrappid.c b/daemon/wrappid.c index 4fb1f11..d6ce2b4 100644 --- a/daemon/wrappid.c +++ b/daemon/wrappid.c @@ -20,14 +20,11 @@ #include #include +#include #include #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); } } diff --git a/generator/wrappi_c.ml b/generator/wrappi_c.ml index 099a7c2..5a73660 100644 --- a/generator/wrappi_c.ml +++ b/generator/wrappi_c.ml @@ -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 + +#include + +#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_. */ + 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 + #include #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 diff --git a/generator/wrappi_c_impl.ml b/generator/wrappi_c_impl.ml index 2b08eb4..0b4b3a3 100644 --- a/generator/wrappi_c_impl.ml +++ b/generator/wrappi_c_impl.ml @@ -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 + +#include + +#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 + #include +#include #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; diff --git a/generator/wrappi_c_xdr.ml b/generator/wrappi_c_xdr.ml index 2eb4b52..78a6961 100644 --- a/generator/wrappi_c_xdr.ml +++ b/generator/wrappi_c_xdr.ml @@ -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 + #include #include @@ -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 diff --git a/lib/Makefile.am b/lib/Makefile.am index edcb328..0c3807b 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -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 = *~ diff --git a/lib/internal.h b/lib/internal.h index 69128e9..311f030 100644 --- a/lib/internal.h +++ b/lib/internal.h @@ -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 index 0000000..620c6dd --- /dev/null +++ b/lib/proto-xdr-request.c @@ -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 + +#include +#include +#include +#include + +#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); +} diff --git a/lib/proto-xdr.c b/lib/proto-xdr.c index aa7a782..5dfb3aa 100644 --- a/lib/proto-xdr.c +++ b/lib/proto-xdr.c @@ -23,8 +23,6 @@ #include #include -#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); -} diff --git a/lib/proto-xdr.h b/lib/proto-xdr.h index a73fffb..02d7b44 100644 --- a/lib/proto-xdr.h +++ b/lib/proto-xdr.h @@ -16,12 +16,10 @@ * 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 -#include -#include #include #include @@ -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_ */ diff --git a/lib/wrappi.c b/lib/wrappi.c index c0350f5..3ea0449 100644 --- a/lib/wrappi.c +++ b/lib/wrappi.c @@ -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; +} -- 1.8.3.1