curl_reschedule.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. This file is part of GNUnet
  3. Copyright (C) 2015, 2016 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file curl/curl_reschedule.c
  18. * @brief API for event loop integration with GNUnet SCHEDULER.
  19. * @author Christian Grothoff
  20. */
  21. #include "platform.h"
  22. #include <jansson.h>
  23. #include "gnunet_curl_lib.h"
  24. #include "gnunet_util_lib.h"
  25. extern void *
  26. GNUNET_CURL_download_get_result_ (struct GNUNET_CURL_DownloadBuffer *db,
  27. CURL *eh,
  28. long *response_code);
  29. /**
  30. * Closure for #GNUNET_CURL_gnunet_scheduler_reschedule().
  31. */
  32. struct GNUNET_CURL_RescheduleContext
  33. {
  34. /**
  35. * Just the task.
  36. */
  37. struct GNUNET_SCHEDULER_Task *task;
  38. /**
  39. * Context we manage.
  40. */
  41. struct GNUNET_CURL_Context *ctx;
  42. /**
  43. * Parser of the raw response.
  44. */
  45. GNUNET_CURL_RawParser parser;
  46. /**
  47. * Deallocate the response object.
  48. */
  49. GNUNET_CURL_ResponseCleaner cleaner;
  50. };
  51. /**
  52. * Initialize reschedule context; with custom response parser
  53. *
  54. * @param ctx context to manage
  55. * @return closure for #GNUNET_CURL_gnunet_scheduler_reschedule().
  56. */
  57. struct GNUNET_CURL_RescheduleContext *
  58. GNUNET_CURL_gnunet_rc_create_with_parser (struct GNUNET_CURL_Context *ctx,
  59. GNUNET_CURL_RawParser rp,
  60. GNUNET_CURL_ResponseCleaner rc)
  61. {
  62. struct GNUNET_CURL_RescheduleContext *rctx;
  63. rctx = GNUNET_new (struct GNUNET_CURL_RescheduleContext);
  64. rctx->ctx = ctx;
  65. rctx->parser = rp;
  66. rctx->cleaner = rc;
  67. return rctx;
  68. }
  69. /**
  70. * Just a wrapper to avoid casting of function pointers.
  71. *
  72. * @param response the (JSON) response to clean.
  73. */
  74. static void
  75. clean_result (void *response)
  76. {
  77. json_decref (response);
  78. }
  79. /**
  80. * Initialize reschedule context.
  81. *
  82. * @param ctx context to manage
  83. * @return closure for #GNUNET_CURL_gnunet_scheduler_reschedule().
  84. */
  85. struct GNUNET_CURL_RescheduleContext *
  86. GNUNET_CURL_gnunet_rc_create (struct GNUNET_CURL_Context *ctx)
  87. {
  88. struct GNUNET_CURL_RescheduleContext *rc;
  89. rc = GNUNET_new (struct GNUNET_CURL_RescheduleContext);
  90. rc->ctx = ctx;
  91. rc->parser = &GNUNET_CURL_download_get_result_;
  92. rc->cleaner = &clean_result;
  93. return rc;
  94. }
  95. /**
  96. * Destroy reschedule context.
  97. *
  98. * @param rc context to destroy
  99. */
  100. void
  101. GNUNET_CURL_gnunet_rc_destroy (struct GNUNET_CURL_RescheduleContext *rc)
  102. {
  103. if (NULL != rc->task)
  104. GNUNET_SCHEDULER_cancel (rc->task);
  105. GNUNET_free (rc);
  106. }
  107. /**
  108. * Task that runs the context's event loop with the GNUnet scheduler.
  109. *
  110. * @param cls a `struct GNUNET_CURL_RescheduleContext *`
  111. */
  112. static void
  113. context_task (void *cls)
  114. {
  115. struct GNUNET_CURL_RescheduleContext *rc = cls;
  116. long timeout;
  117. int max_fd;
  118. fd_set read_fd_set;
  119. fd_set write_fd_set;
  120. fd_set except_fd_set;
  121. struct GNUNET_NETWORK_FDSet *rs;
  122. struct GNUNET_NETWORK_FDSet *ws;
  123. struct GNUNET_TIME_Relative delay;
  124. rc->task = NULL;
  125. GNUNET_CURL_perform2 (rc->ctx, rc->parser, rc->cleaner);
  126. max_fd = -1;
  127. timeout = -1;
  128. FD_ZERO (&read_fd_set);
  129. FD_ZERO (&write_fd_set);
  130. FD_ZERO (&except_fd_set);
  131. GNUNET_CURL_get_select_info (rc->ctx,
  132. &read_fd_set,
  133. &write_fd_set,
  134. &except_fd_set,
  135. &max_fd,
  136. &timeout);
  137. if (timeout >= 0)
  138. delay =
  139. GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, timeout);
  140. else
  141. delay = GNUNET_TIME_UNIT_FOREVER_REL;
  142. rs = GNUNET_NETWORK_fdset_create ();
  143. GNUNET_NETWORK_fdset_copy_native (rs, &read_fd_set, max_fd + 1);
  144. ws = GNUNET_NETWORK_fdset_create ();
  145. GNUNET_NETWORK_fdset_copy_native (ws, &write_fd_set, max_fd + 1);
  146. if (NULL == rc->task)
  147. rc->task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
  148. delay,
  149. rs,
  150. ws,
  151. &context_task,
  152. rc);
  153. GNUNET_NETWORK_fdset_destroy (rs);
  154. GNUNET_NETWORK_fdset_destroy (ws);
  155. }
  156. /**
  157. * Implementation of the #GNUNET_CURL_RescheduleCallback for GNUnet's
  158. * scheduler. Will run the CURL context using GNUnet's scheduler.
  159. * Note that you MUST immediately destroy the reschedule context after
  160. * calling #GNUNET_CURL_fini().
  161. *
  162. * @param cls must point to a `struct GNUNET_CURL_RescheduleContext *`
  163. * (pointer to a pointer!)
  164. */
  165. void
  166. GNUNET_CURL_gnunet_scheduler_reschedule (void *cls)
  167. {
  168. struct GNUNET_CURL_RescheduleContext *rc = *(void **) cls;
  169. if (NULL != rc->task)
  170. GNUNET_SCHEDULER_cancel (rc->task);
  171. rc->task = GNUNET_SCHEDULER_add_now (&context_task, rc);
  172. }
  173. /* end of curl_reschedule.c */