initial load of upstream version 1.06.32
[xmlrpc-c] / examples / xmlrpc_loop_server.c
diff --git a/examples/xmlrpc_loop_server.c b/examples/xmlrpc_loop_server.c
new file mode 100644 (file)
index 0000000..239d59b
--- /dev/null
@@ -0,0 +1,134 @@
+/* A simple standalone XML-RPC server based on Abyss that contains a
+   simple one-thread request processing loop.  
+
+   xmlrpc_sample_add_server.c is a server that does the same thing, but
+   does it by running a full Abyss daemon in the background, so it has
+   less control over how the requests are served.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/abyss.h>
+#include <xmlrpc-c/server.h>
+#include <xmlrpc-c/server_abyss.h>
+
+#include "config.h"  /* information about this build environment */
+
+
+static void
+setupSignalHandlers(void) {
+
+    /* In UNIX, when you try to write to a socket that has been closed
+       from the other end, your write fails, but you also get a SIGPIPE
+       signal.  That signal will kill you before you even have a chance
+       to see the write fail unless you catch, block, or ignore it.
+       If a client should connect to us and then disconnect before we've
+       sent our response, we see this socket-closed behavior.  We
+       obviously don't want to die just because a client didn't complete
+       an RPC, so we ignore SIGPIPE.
+    */
+    struct sigaction mysigaction;
+    
+    sigemptyset(&mysigaction.sa_mask);
+    mysigaction.sa_flags = 0;
+    mysigaction.sa_handler = SIG_IGN;
+    sigaction(SIGPIPE, &mysigaction, NULL);
+}
+
+
+
+static xmlrpc_value *
+sample_add(xmlrpc_env *   const envP, 
+           xmlrpc_value * const paramArrayP,
+           void *         const userData ATTR_UNUSED) {
+    
+    xmlrpc_int x, y, z;
+
+    /* Parse our argument array. */
+    xmlrpc_decompose_value(envP, paramArrayP, "(ii)", &x, &y);
+    if (envP->fault_occurred)
+        return NULL;
+
+    /* Add our two numbers. */
+    z = x + y;
+
+    /* Return our result. */
+    return xmlrpc_build_value(envP, "i", z);
+}
+
+
+
+static xmlrpc_server_shutdown_fn requestShutdown;
+
+static void
+requestShutdown(xmlrpc_env * const envP,
+                void *       const context,
+                const char * const comment) {
+
+    /* You make this run by executing the system method
+       'system.shutdown'.  This function is registered in the method
+       registry as the thing to call for that.
+    */
+    int * const terminationRequestedP = context;
+
+    xmlrpc_env_init(envP);
+
+    fprintf(stderr, "Termination requested: %s\n", comment);
+    
+    *terminationRequestedP = 1;
+}
+
+
+
+int 
+main(int           const argc, 
+     const char ** const argv) {
+
+    TServer abyssServer;
+    xmlrpc_registry * registryP;
+    xmlrpc_env env;
+    int terminationRequested;  /* A boolean value */
+
+    if (argc-1 != 1) {
+        fprintf(stderr, "You must specify 1 argument:  The TCP port number "
+                "on which to listen for XML-RPC calls.  "
+                "You specified %d.\n",  argc-1);
+        exit(1);
+    }
+    
+    xmlrpc_env_init(&env);
+
+    registryP = xmlrpc_registry_new(&env);
+
+    xmlrpc_registry_add_method(
+        &env, registryP, NULL, "sample.add", &sample_add, NULL);
+
+    xmlrpc_registry_set_shutdown(registryP,
+                                 &requestShutdown, &terminationRequested);
+
+    ServerCreate(&abyssServer, "XmlRpcServer", atoi(argv[1]), NULL, NULL);
+    
+    xmlrpc_server_abyss_set_handlers(&abyssServer, registryP);
+
+    ServerInit(&abyssServer);
+
+    setupSignalHandlers();
+
+    terminationRequested = 0;
+
+    while (!terminationRequested) {
+        printf("Waiting for next RPC...\n");
+
+        ServerRunOnce(&abyssServer);
+            /* This waits for the next connection, accepts it, reads the
+               HTTP POST request, executes the indicated RPC, and closes
+               the connection.
+            */
+    }
+
+    ServerFree(&abyssServer);
+    
+    return 0;
+}