gnunet_curl_lib.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. /*
  2. This file is part of GNUnet
  3. Copyright (C) 2014, 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 src/include/gnunet_curl_lib.h
  18. * @brief library to make it easy to download JSON replies over HTTP
  19. * @author Sree Harsha Totakura <sreeharsha@totakura.in>
  20. * @author Christian Grothoff
  21. *
  22. * @defgroup curl CURL integration library
  23. * Download JSON using libcurl.
  24. * @{
  25. */
  26. #ifndef GNUNET_CURL_LIB_H
  27. #define GNUNET_CURL_LIB_H
  28. #if HAVE_LIBCURL
  29. #include <curl/curl.h>
  30. #elif HAVE_LIBGNURL
  31. #include <gnurl/curl.h>
  32. #else
  33. #error "needs curl or gnurl"
  34. #endif
  35. #include "gnunet_util_lib.h"
  36. /**
  37. * Function called by the context to ask for the event loop to be
  38. * rescheduled, that is the application should call
  39. * #GNUNET_CURL_get_select_info() as the set of sockets we care about
  40. * just changed.
  41. *
  42. * @param cls closure
  43. */
  44. typedef void
  45. (*GNUNET_CURL_RescheduleCallback)(void *cls);
  46. /**
  47. * @brief Buffer data structure we use to buffer the HTTP download
  48. * before giving it to the JSON parser.
  49. */
  50. struct GNUNET_CURL_DownloadBuffer
  51. {
  52. /**
  53. * Download buffer
  54. */
  55. void *buf;
  56. /**
  57. * The size of the download buffer
  58. */
  59. size_t buf_size;
  60. /**
  61. * Error code (based on libc errno) if we failed to download
  62. * (i.e. response too large).
  63. */
  64. int eno;
  65. };
  66. /**
  67. * Parses the raw response we got from the Web server.
  68. *
  69. * @param db the raw data
  70. * @param eh handle
  71. * @param response_code HTTP response code
  72. * @return the parsed object
  73. */
  74. typedef void *
  75. (*GNUNET_CURL_RawParser) (struct GNUNET_CURL_DownloadBuffer *db,
  76. CURL *eh,
  77. long *response_code);
  78. /**
  79. * Deallocate the response.
  80. *
  81. * @param response object to clean
  82. */
  83. typedef void
  84. (*GNUNET_CURL_ResponseCleaner) (void *response);
  85. /**
  86. * Initialise this library. This function should be called before using any of
  87. * the following functions.
  88. *
  89. * @param cb function to call when rescheduling is required
  90. * @param cb_cls closure for @a cb
  91. * @return library context
  92. */
  93. struct GNUNET_CURL_Context *
  94. GNUNET_CURL_init (GNUNET_CURL_RescheduleCallback cb,
  95. void *cb_cls);
  96. /**
  97. * Obtain the information for a select() call to wait until
  98. * #GNUNET_CURL_perform() is ready again.
  99. *
  100. * Basically, a client should use this API to prepare for select(),
  101. * then block on select(), then call #GNUNET_CURL_perform() and then
  102. * start again until the work with the context is done.
  103. *
  104. * This function will NOT zero out the sets and assumes that @a max_fd
  105. * and @a timeout are already set to minimal applicable values. It is
  106. * safe to give this API FD-sets and @a max_fd and @a timeout that are
  107. * already initialized to some other descriptors that need to go into
  108. * the select() call.
  109. *
  110. * @param ctx context to get the event loop information for
  111. * @param read_fd_set will be set for any pending read operations
  112. * @param write_fd_set will be set for any pending write operations
  113. * @param except_fd_set is here because curl_multi_fdset() has this argument
  114. * @param max_fd set to the highest FD included in any set;
  115. * if the existing sets have no FDs in it, the initial
  116. * value should be "-1". (Note that `max_fd + 1` will need
  117. * to be passed to select().)
  118. * @param timeout set to the timeout in milliseconds (!); -1 means
  119. * no timeout (NULL, blocking forever is OK), 0 means to
  120. * proceed immediately with #GNUNET_CURL_perform().
  121. */
  122. void
  123. GNUNET_CURL_get_select_info (struct GNUNET_CURL_Context *ctx,
  124. fd_set *read_fd_set,
  125. fd_set *write_fd_set,
  126. fd_set *except_fd_set,
  127. int *max_fd,
  128. long *timeout);
  129. /**
  130. * Add custom request header.
  131. *
  132. * @param ctx cURL context.
  133. * @param header header string; will be given to the context AS IS.
  134. * @return #GNUNET_OK if no errors occurred, #GNUNET_SYSERR otherwise.
  135. */
  136. int
  137. GNUNET_CURL_append_header (struct GNUNET_CURL_Context *ctx,
  138. const char *header);
  139. /**
  140. * Run the main event loop for the CURL interaction.
  141. *
  142. * @param ctx the library context
  143. */
  144. void
  145. GNUNET_CURL_perform (struct GNUNET_CURL_Context *ctx);
  146. /**
  147. * Run the main event loop for the HTTP interaction.
  148. *
  149. * @param ctx the library context
  150. * @param rp parses the raw response returned from
  151. * the Web server.
  152. * @param rc cleans/frees the response
  153. */
  154. void
  155. GNUNET_CURL_perform2 (struct GNUNET_CURL_Context *ctx,
  156. GNUNET_CURL_RawParser rp,
  157. GNUNET_CURL_ResponseCleaner rc);
  158. /**
  159. * Cleanup library initialisation resources. This function should be called
  160. * after using this library to cleanup the resources occupied during library's
  161. * initialisation.
  162. *
  163. * @param ctx the library context
  164. */
  165. void
  166. GNUNET_CURL_fini (struct GNUNET_CURL_Context *ctx);
  167. /**
  168. * Entry in the context's job queue.
  169. */
  170. struct GNUNET_CURL_Job;
  171. /**
  172. * Function to call upon completion of a job.
  173. *
  174. * @param cls closure
  175. * @param response_code HTTP response code from server, 0 on hard error
  176. * @param response in JSON, NULL if response was not in JSON format
  177. */
  178. typedef void
  179. (*GNUNET_CURL_JobCompletionCallback)(void *cls,
  180. long response_code,
  181. const void *response);
  182. /**
  183. * Function to call upon completion of a raw job.
  184. *
  185. * @param cls closure
  186. * @param response_code HTTP response code from server, 0 on hard error
  187. * @param body http body of the response
  188. * @param body_size number of bytes in @a body
  189. */
  190. typedef void
  191. (*GNUNET_CURL_RawJobCompletionCallback)(void *cls,
  192. long response_code,
  193. const void *body,
  194. size_t body_size);
  195. /**
  196. * Schedule a CURL request to be executed and call the given @a jcc
  197. * upon its completion. Note that the context will make use of the
  198. * CURLOPT_PRIVATE facility of the CURL @a eh.
  199. *
  200. * @param ctx context to execute the job in
  201. * @param eh curl easy handle for the request, will
  202. * be executed AND cleaned up
  203. * @param jcc callback to invoke upon completion
  204. * @param jcc_cls closure for @a jcc
  205. * @return NULL on error (in this case, @eh is still released!)
  206. */
  207. struct GNUNET_CURL_Job *
  208. GNUNET_CURL_job_add (struct GNUNET_CURL_Context *ctx,
  209. CURL *eh,
  210. GNUNET_CURL_JobCompletionCallback jcc,
  211. void *jcc_cls);
  212. /**
  213. * Schedule a CURL request to be executed and call the given @a jcc
  214. * upon its completion. Note that the context will make use of the
  215. * CURLOPT_PRIVATE facility of the CURL @a eh.
  216. *
  217. * This function modifies the CURL handle to add the
  218. * "Content-Type: application/json" header.
  219. *
  220. * @param ctx context to execute the job in
  221. * @param eh curl easy handle for the request, will
  222. * be executed AND cleaned up
  223. * @param jcc callback to invoke upon completion
  224. * @param jcc_cls closure for @a jcc
  225. * @return NULL on error (in this case, @eh is still released!)
  226. */
  227. struct GNUNET_CURL_Job *
  228. GNUNET_CURL_job_add_with_ct_json (struct GNUNET_CURL_Context *ctx,
  229. CURL *eh,
  230. GNUNET_CURL_JobCompletionCallback jcc,
  231. void *jcc_cls);
  232. /**
  233. * Force use of the provided username and password
  234. * for client authentication for all operations performed
  235. * with @a ctx.
  236. *
  237. * @param ctx context to set authentication data for
  238. * @param userpass string with "$USERNAME:$PASSWORD"
  239. */
  240. void
  241. GNUNET_CURL_set_userpass (struct GNUNET_CURL_Context *ctx,
  242. const char *userpass);
  243. /**
  244. * Force use of the provided TLS client certificate for client authentication
  245. * for all operations performed with @a ctx.
  246. *
  247. * Note that if the provided information is incorrect,
  248. * the earliest operation that could fail is
  249. * #GNUNET_CURL_job_add() or #GNUNET_CURL_job_add2()!
  250. *
  251. * @param ctx context to set authentication data for
  252. * @param certtype type of the certificate
  253. * @param certfile file with the certificate
  254. * @param keyfile file with the private key
  255. * @param keypass passphrase to decrypt @a keyfile (or NULL)
  256. */
  257. void
  258. GNUNET_CURL_set_tlscert (struct GNUNET_CURL_Context *ctx,
  259. const char *certtype,
  260. const char *certfile,
  261. const char *keyfile,
  262. const char *keypass);
  263. /**
  264. * Schedule a CURL request to be executed and call the given @a jcc upon its
  265. * completion. Note that the context will make use of the CURLOPT_PRIVATE
  266. * facility of the CURL @a eh.
  267. *
  268. * This function modifies the CURL handle to add the
  269. * "Content-Type: application/json" header if @a add_json is set.
  270. *
  271. * @param ctx context to execute the job in
  272. * @param eh curl easy handle for the request, will
  273. * be executed AND cleaned up
  274. * @param job_headers extra headers to add for this request
  275. * @param jcc callback to invoke upon completion
  276. * @param jcc_cls closure for @a jcc
  277. * @return NULL on error (in this case, @eh is still released!)
  278. */
  279. struct GNUNET_CURL_Job *
  280. GNUNET_CURL_job_add2 (struct GNUNET_CURL_Context *ctx,
  281. CURL *eh,
  282. const struct curl_slist *job_headers,
  283. GNUNET_CURL_JobCompletionCallback jcc,
  284. void *jcc_cls);
  285. /**
  286. * Schedule a CURL request to be executed and call the given @a jcc
  287. * upon its completion. Note that the context will make use of the
  288. * CURLOPT_PRIVATE facility of the CURL @a eh. Used to download
  289. * resources that are NOT in JSON. The raw body will be returned.
  290. *
  291. * @param ctx context to execute the job in
  292. * @param eh curl easy handle for the request, will
  293. * be executed AND cleaned up
  294. * @param job_headers extra headers to add for this request
  295. * @param max_reply_size largest acceptable response body
  296. * @param jcc callback to invoke upon completion
  297. * @param jcc_cls closure for @a jcc
  298. * @return NULL on error (in this case, @eh is still released!)
  299. */
  300. struct GNUNET_CURL_Job *
  301. GNUNET_CURL_job_add_raw (struct GNUNET_CURL_Context *ctx,
  302. CURL *eh,
  303. const struct curl_slist *job_headers,
  304. GNUNET_CURL_RawJobCompletionCallback jcc,
  305. void *jcc_cls);
  306. /**
  307. * Add @a extra_headers to the HTTP headers for @a job.
  308. *
  309. * @param[in,out] job the job to modify
  310. * @param extra_headers headers to append
  311. */
  312. void
  313. GNUNET_CURL_extend_headers (struct GNUNET_CURL_Job *job,
  314. const struct curl_slist *extra_headers);
  315. /**
  316. * Cancel a job. Must only be called before the job completion
  317. * callback is called for the respective job.
  318. *
  319. * @param job job to cancel
  320. */
  321. void
  322. GNUNET_CURL_job_cancel (struct GNUNET_CURL_Job *job);
  323. /* ******* GNUnet SCHEDULER integration ************ */
  324. /**
  325. * Closure for #GNUNET_CURL_gnunet_scheduler_reschedule().
  326. */
  327. struct GNUNET_CURL_RescheduleContext;
  328. /**
  329. * Initialize reschedule context.
  330. *
  331. * @param ctx context to manage
  332. * @return closure for #GNUNET_CURL_gnunet_scheduler_reschedule().
  333. */
  334. struct GNUNET_CURL_RescheduleContext *
  335. GNUNET_CURL_gnunet_rc_create (struct GNUNET_CURL_Context *ctx);
  336. /**
  337. * Initialize reschedule context; with custom response parser
  338. *
  339. * @param ctx context to manage
  340. * @return closure for #GNUNET_CURL_gnunet_scheduler_reschedule().
  341. */
  342. struct GNUNET_CURL_RescheduleContext *
  343. GNUNET_CURL_gnunet_rc_create_with_parser (struct GNUNET_CURL_Context *ctx,
  344. GNUNET_CURL_RawParser rp,
  345. GNUNET_CURL_ResponseCleaner rc);
  346. /**
  347. * Destroy reschedule context.
  348. *
  349. * @param rc context to destroy
  350. */
  351. void
  352. GNUNET_CURL_gnunet_rc_destroy (struct GNUNET_CURL_RescheduleContext *rc);
  353. /**
  354. * Implementation of the #GNUNET_CURL_RescheduleCallback for GNUnet's
  355. * scheduler. Will run the CURL context using GNUnet's scheduler.
  356. * Note that you MUST immediately destroy the reschedule context after
  357. * calling #GNUNET_CURL_fini().
  358. *
  359. * @param cls must point to a `struct GNUNET_CURL_RescheduleContext *`
  360. * (pointer to a pointer!)
  361. */
  362. void
  363. GNUNET_CURL_gnunet_scheduler_reschedule (void *cls);
  364. /**
  365. * Enable sending the async scope ID as a header.
  366. *
  367. * @param ctx the context to enable this for
  368. * @param header_name name of the header to send.
  369. */
  370. void
  371. GNUNET_CURL_enable_async_scope_header (struct GNUNET_CURL_Context *ctx,
  372. const char *header_name);
  373. /**
  374. * Return #GNUNET_YES if given a valid scope ID and
  375. * #GNUNET_NO otherwise. See
  376. * #GNUNET_CURL_enable_async_scope_header() for the
  377. * code that generates such a @a scope_id in an HTTP
  378. * header.
  379. *
  380. * @returns #GNUNET_YES iff given a valid scope ID
  381. */
  382. int
  383. GNUNET_CURL_is_valid_scope_id (const char *scope_id);
  384. #endif
  385. /** @} */ /* end of group */
  386. /* end of gnunet_curl_lib.h */