xmlrpc_loop_server.c 4.7 KB

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