interrupted_client.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /* Same as xmlrpc_sample_add_client.c, except the call is interruptible,
  2. both by timeout and by control-C.
  3. */
  4. #define _XOPEN_SOURCE 600
  5. #include <stdlib.h>
  6. #include <unistd.h>
  7. #include <stdio.h>
  8. #include <signal.h>
  9. #include <xmlrpc-c/base.h>
  10. #include <xmlrpc-c/client.h>
  11. #include "config.h" /* information about this build environment */
  12. static int interrupt;
  13. /* This is a flag telling libxmlrpc_client to abort whatever it's
  14. doing. It's global because we set it with a signal handler.
  15. */
  16. static void
  17. die_if_fault_occurred (xmlrpc_env * const envP) {
  18. if (envP->fault_occurred) {
  19. fprintf(stderr, "XML-RPC Fault: %s (%d)\n",
  20. envP->fault_string, envP->fault_code);
  21. exit(1);
  22. }
  23. }
  24. static void
  25. interruptRpc(int const signalClass) {
  26. switch (signalClass) {
  27. case SIGINT:
  28. printf("SIGINT signal received.\n");
  29. break;
  30. case SIGALRM:
  31. printf("SIGALRM signal received.\n");
  32. break;
  33. default:
  34. printf("Internal error: signal of class %u caught even though "
  35. "we didn't set up a handler for that class\n", signalClass);
  36. };
  37. interrupt = 1;
  38. }
  39. static void
  40. setupSignalHandlers(void) {
  41. struct sigaction mysigaction;
  42. sigemptyset(&mysigaction.sa_mask);
  43. mysigaction.sa_flags = 0;
  44. /* Usually, this signal indicates the user pressed Ctl-C */
  45. mysigaction.sa_handler = interruptRpc;
  46. sigaction(SIGINT, &mysigaction, NULL);
  47. /* This signal indicates a timed alarm you requested happened */
  48. sigaction(SIGALRM, &mysigaction, NULL);
  49. }
  50. static void
  51. addInterruptibly(xmlrpc_client * const clientP,
  52. const char * const serverUrl,
  53. int const addend,
  54. int const adder) {
  55. const char * const methodName = "sample.add";
  56. xmlrpc_env env;
  57. xmlrpc_value * resultP;
  58. xmlrpc_int32 sum;
  59. xmlrpc_env_init(&env);
  60. printf("Making XMLRPC call to server url '%s' method '%s' "
  61. "to request the sum "
  62. "of %d and %d...\n", serverUrl, methodName, addend, adder);
  63. interrupt = 0; /* Global variable */
  64. alarm(2); /* Interrupt the call if it hasn't finished 2 seconds from now */
  65. /* Make the remote procedure call */
  66. xmlrpc_client_call2f(&env, clientP, serverUrl, methodName, &resultP,
  67. "(ii)", (xmlrpc_int32) addend, (xmlrpc_int32) adder);
  68. die_if_fault_occurred(&env);
  69. alarm(0); /* Cancel alarm, if it hasn't happened yet */
  70. /* Get our sum and print it out. */
  71. xmlrpc_read_int(&env, resultP, &sum);
  72. die_if_fault_occurred(&env);
  73. printf("The sum is %d\n", sum);
  74. /* Dispose of our result value. */
  75. xmlrpc_DECREF(resultP);
  76. xmlrpc_env_clean(&env);
  77. }
  78. int
  79. main(int const argc,
  80. const char ** const argv) {
  81. const char * const serverUrl = "http://localhost:8080/RPC2";
  82. xmlrpc_env env;
  83. struct xmlrpc_clientparms clientParms;
  84. xmlrpc_client * clientP;
  85. if (argc-1 > 0) {
  86. fprintf(stderr, "This program has no arguments\n");
  87. exit(1);
  88. }
  89. setupSignalHandlers();
  90. /* Initialize our error-handling environment. */
  91. xmlrpc_env_init(&env);
  92. /* Required before any use of Xmlrpc-c client library: */
  93. xmlrpc_client_setup_global_const(&env);
  94. die_if_fault_occurred(&env);
  95. clientParms.transport = "curl";
  96. /* Create a client object */
  97. xmlrpc_client_create(&env, 0, NULL, NULL,
  98. &clientParms, XMLRPC_CPSIZE(transport),
  99. &clientP);
  100. die_if_fault_occurred(&env);
  101. xmlrpc_client_set_interrupt(clientP, &interrupt);
  102. /* If our server is running 'xmlrpc_sample_add_server' normally, the
  103. RPC will finish almost instantly. UNLESS the adder is 1, in which
  104. case said server is programmed to take 3 seconds to do the
  105. computation, thus allowing us to demonstrate a timeout or CTL-C.
  106. */
  107. addInterruptibly(clientP, serverUrl, 5, 7);
  108. /* Should finish instantly */
  109. addInterruptibly(clientP, serverUrl, 5, 1);
  110. /* Should time out after 2 seconds */
  111. xmlrpc_env_clean(&env);
  112. xmlrpc_client_destroy(clientP);
  113. xmlrpc_client_teardown_global_const();
  114. return 0;
  115. }