123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- /* A simple standalone XML-RPC server program based on Abyss that contains a
- simple one-thread request processing loop.
- This uses the "provide your own Abyss server" mode of operation.
- 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.
- */
- #define _XOPEN_SOURCE 600
- #include <stdlib.h>
- #include <stdio.h>
- #include <signal.h>
- #include <sys/socket.h>
- #include <netinet/in.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.
- */
- #ifndef WIN32
- struct sigaction mysigaction;
-
- sigemptyset(&mysigaction.sa_mask);
- mysigaction.sa_flags = 0;
- mysigaction.sa_handler = SIG_IGN;
- sigaction(SIGPIPE, &mysigaction, NULL);
- #endif
- }
- static void
- printPeerIpAddr(TSession * const abyssSessionP) {
- struct abyss_unix_chaninfo * channelInfoP;
- struct sockaddr_in * sockAddrInP;
- unsigned char * ipAddr; /* 4 byte array */
- SessionGetChannelInfo(abyssSessionP, (void*)&channelInfoP);
- sockAddrInP = (struct sockaddr_in *) &channelInfoP->peerAddr;
- ipAddr = (unsigned char *)&sockAddrInP->sin_addr.s_addr;
- printf("RPC is from IP address %u.%u.%u.%u\n",
- ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3]);
- }
- static xmlrpc_value *
- sample_add(xmlrpc_env * const envP,
- xmlrpc_value * const paramArrayP,
- void * const serverInfo,
- void * const channelInfo) {
-
- xmlrpc_int x, y, z;
- printPeerIpAddr(channelInfo);
- /* 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 faultP,
- void * const context,
- const char * const comment,
- void * const callInfo) {
- /* 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;
- TSession * const abyssSessionP = callInfo;
- xmlrpc_env_init(faultP);
- fprintf(stderr, "Termination requested: %s\n", comment);
- printPeerIpAddr(abyssSessionP);
-
- *terminationRequestedP = 1;
- }
- int
- main(int const argc,
- const char ** const argv) {
- struct xmlrpc_method_info3 const methodInfo = {
- .methodName = "sample.add",
- .methodFunction = &sample_add,
- .serverInfo = NULL
- };
- TServer abyssServer;
- xmlrpc_registry * registryP;
- xmlrpc_env env;
- int terminationRequested; /* A boolean value */
- const char * error;
- 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);
- }
- AbyssInit(&error);
-
- xmlrpc_env_init(&env);
- registryP = xmlrpc_registry_new(&env);
- xmlrpc_registry_add_method3(&env, registryP, &methodInfo);
- xmlrpc_registry_set_shutdown(registryP,
- &requestShutdown, &terminationRequested);
- ServerCreate(&abyssServer, "XmlRpcServer", atoi(argv[1]), NULL, NULL);
-
- xmlrpc_server_abyss_set_handlers2(&abyssServer, "/RPC2", 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);
- AbyssTerm();
- return 0;
- }
|