initial load of upstream version 1.06.32
[xmlrpc-c] / examples / xmlrpc_loop_server.c
1 /* A simple standalone XML-RPC server based on Abyss that contains a
2    simple one-thread request processing loop.  
3
4    xmlrpc_sample_add_server.c is a server that does the same thing, but
5    does it by running a full Abyss daemon in the background, so it has
6    less control over how the requests are served.
7 */
8
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <signal.h>
12 #include <xmlrpc-c/base.h>
13 #include <xmlrpc-c/abyss.h>
14 #include <xmlrpc-c/server.h>
15 #include <xmlrpc-c/server_abyss.h>
16
17 #include "config.h"  /* information about this build environment */
18
19
20 static void
21 setupSignalHandlers(void) {
22
23     /* In UNIX, when you try to write to a socket that has been closed
24        from the other end, your write fails, but you also get a SIGPIPE
25        signal.  That signal will kill you before you even have a chance
26        to see the write fail unless you catch, block, or ignore it.
27        If a client should connect to us and then disconnect before we've
28        sent our response, we see this socket-closed behavior.  We
29        obviously don't want to die just because a client didn't complete
30        an RPC, so we ignore SIGPIPE.
31     */
32     struct sigaction mysigaction;
33     
34     sigemptyset(&mysigaction.sa_mask);
35     mysigaction.sa_flags = 0;
36     mysigaction.sa_handler = SIG_IGN;
37     sigaction(SIGPIPE, &mysigaction, NULL);
38 }
39
40
41
42 static xmlrpc_value *
43 sample_add(xmlrpc_env *   const envP, 
44            xmlrpc_value * const paramArrayP,
45            void *         const userData ATTR_UNUSED) {
46     
47     xmlrpc_int x, y, z;
48
49     /* Parse our argument array. */
50     xmlrpc_decompose_value(envP, paramArrayP, "(ii)", &x, &y);
51     if (envP->fault_occurred)
52         return NULL;
53
54     /* Add our two numbers. */
55     z = x + y;
56
57     /* Return our result. */
58     return xmlrpc_build_value(envP, "i", z);
59 }
60
61
62
63 static xmlrpc_server_shutdown_fn requestShutdown;
64
65 static void
66 requestShutdown(xmlrpc_env * const envP,
67                 void *       const context,
68                 const char * const comment) {
69
70     /* You make this run by executing the system method
71        'system.shutdown'.  This function is registered in the method
72        registry as the thing to call for that.
73     */
74     int * const terminationRequestedP = context;
75
76     xmlrpc_env_init(envP);
77
78     fprintf(stderr, "Termination requested: %s\n", comment);
79     
80     *terminationRequestedP = 1;
81 }
82
83
84
85 int 
86 main(int           const argc, 
87      const char ** const argv) {
88
89     TServer abyssServer;
90     xmlrpc_registry * registryP;
91     xmlrpc_env env;
92     int terminationRequested;  /* A boolean value */
93
94     if (argc-1 != 1) {
95         fprintf(stderr, "You must specify 1 argument:  The TCP port number "
96                 "on which to listen for XML-RPC calls.  "
97                 "You specified %d.\n",  argc-1);
98         exit(1);
99     }
100     
101     xmlrpc_env_init(&env);
102
103     registryP = xmlrpc_registry_new(&env);
104
105     xmlrpc_registry_add_method(
106         &env, registryP, NULL, "sample.add", &sample_add, NULL);
107
108     xmlrpc_registry_set_shutdown(registryP,
109                                  &requestShutdown, &terminationRequested);
110
111     ServerCreate(&abyssServer, "XmlRpcServer", atoi(argv[1]), NULL, NULL);
112     
113     xmlrpc_server_abyss_set_handlers(&abyssServer, registryP);
114
115     ServerInit(&abyssServer);
116
117     setupSignalHandlers();
118
119     terminationRequested = 0;
120
121     while (!terminationRequested) {
122         printf("Waiting for next RPC...\n");
123
124         ServerRunOnce(&abyssServer);
125             /* This waits for the next connection, accepts it, reads the
126                HTTP POST request, executes the indicated RPC, and closes
127                the connection.
128             */
129     }
130
131     ServerFree(&abyssServer);
132     
133     return 0;
134 }