GNUnet 0.22.1
curl.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet
3 Copyright (C) 2014, 2015, 2016, 2018 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
26#include "platform.h"
27#include <jansson.h>
28#include <microhttpd.h>
29#include "gnunet_curl_lib.h"
30#include "curl_internal.h"
31
32#if ENABLE_BENCHMARK
33#include "../util/benchmark.h"
34#endif
35
39#define DEBUG 0
40
48#define CURL_STRERROR(type, function, code) \
49 GNUNET_log (type, \
50 "Curl function `%s' has failed at `%s:%d' with error: %s\n", \
51 function, \
52 __FILE__, \
53 __LINE__, \
54 curl_easy_strerror (code));
55
59#define JSON_WARN(error) \
60 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, \
61 "JSON parsing failed at %s:%u: %s (%s)\n", \
62 __FILE__, \
63 __LINE__, \
64 error.text, \
65 error.source)
66
67
72static int curl_fail;
73
78{
83
88
93
98
103
107 void *jcc_cls;
108
113
118
123
128 struct curl_slist *job_headers;
129
134};
135
136
141{
145 CURLM *multi;
146
150 CURLSH *share;
151
156
161
165 struct curl_slist *common_headers;
166
172
178
182 void *cb_cls;
183
188 char *userpass;
189
193 char *certtype;
194
198 char *certfile;
199
204 char *keyfile;
205
209 char *keypass;
210
211};
212
213
214void
216 const char *userpass)
217{
218 GNUNET_free (ctx->userpass);
219 if (NULL != userpass)
220 ctx->userpass = GNUNET_strdup (userpass);
221}
222
223
224void
226 const char *certtype,
227 const char *certfile,
228 const char *keyfile,
229 const char *keypass)
230{
231 GNUNET_free (ctx->certtype);
232 GNUNET_free (ctx->certfile);
233 GNUNET_free (ctx->keyfile);
234 GNUNET_free (ctx->keypass);
235 if (NULL != certtype)
236 ctx->certtype = GNUNET_strdup (certtype);
237 if (NULL != certfile)
238 ctx->certfile = GNUNET_strdup (certfile);
239 if (NULL != keyfile)
240 ctx->certtype = GNUNET_strdup (keyfile);
241 if (NULL != keypass)
242 ctx->certtype = GNUNET_strdup (keypass);
243}
244
245
246struct GNUNET_CURL_Context *
248 void *cb_cls)
249{
250 struct GNUNET_CURL_Context *ctx;
251 CURLM *multi;
252 CURLSH *share;
253
254 if (curl_fail)
255 {
257 "Curl was not initialised properly\n");
258 return NULL;
259 }
260 if (NULL == (multi = curl_multi_init ()))
261 {
263 "Failed to create a Curl multi handle\n");
264 return NULL;
265 }
266 if (NULL == (share = curl_share_init ()))
267 {
269 "Failed to create a Curl share handle\n");
270 return NULL;
271 }
273 ctx->cb = cb;
274 ctx->cb_cls = cb_cls;
275 ctx->multi = multi;
276 ctx->share = share;
277 return ctx;
278}
279
280
281void
283 const char *header_name)
284{
285 ctx->async_scope_id_header = header_name;
286}
287
288
290GNUNET_CURL_is_valid_scope_id (const char *scope_id)
291{
292 if (strlen (scope_id) >= 64)
293 return GNUNET_NO;
294 for (size_t i = 0; i < strlen (scope_id); i++)
295 if (! (isalnum (scope_id[i]) || (scope_id[i] == '-')))
296 return GNUNET_NO;
297 return GNUNET_YES;
298}
299
300
314static size_t
315download_cb (char *bufptr,
316 size_t size,
317 size_t nitems,
318 void *cls)
319{
320 struct GNUNET_CURL_DownloadBuffer *db = cls;
321 size_t msize;
322 void *buf;
323
324 if (0 == size * nitems)
325 {
326 /* Nothing (left) to do */
327 return 0;
328 }
329 msize = size * nitems;
330 if ((msize + db->buf_size) >= GNUNET_MAX_MALLOC_CHECKED)
331 {
332 db->eno = ENOMEM;
333 return 0; /* signals an error to curl */
334 }
335 db->buf = GNUNET_realloc (db->buf,
336 db->buf_size + msize);
337 buf = db->buf + db->buf_size;
338 GNUNET_memcpy (buf, bufptr, msize);
339 db->buf_size += msize;
340 return msize;
341}
342
343
351static struct curl_slist *
353 const struct curl_slist *job_headers)
354{
355 struct curl_slist *all_headers = NULL;
356
357 for (const struct curl_slist *curr = job_headers;
358 NULL != curr;
359 curr = curr->next)
360 {
361 GNUNET_assert (NULL !=
362 (all_headers = curl_slist_append (all_headers,
363 curr->data)));
364 }
365
366 for (const struct curl_slist *curr = ctx->common_headers;
367 NULL != curr;
368 curr = curr->next)
369 {
370 GNUNET_assert (NULL !=
371 (all_headers = curl_slist_append (all_headers,
372 curr->data)));
373 }
374
375 if (NULL != ctx->async_scope_id_header)
376 {
377 struct GNUNET_AsyncScopeSave scope;
378
379 GNUNET_async_scope_get (&scope);
380 if (GNUNET_YES == scope.have_scope)
381 {
382 char *aid_header;
383
384 aid_header =
386 &scope.scope_id,
387 sizeof(struct GNUNET_AsyncScopeId));
388 GNUNET_assert (NULL != aid_header);
389 GNUNET_assert (NULL != curl_slist_append (all_headers,
390 aid_header));
391 GNUNET_free (aid_header);
392 }
393 }
394 return all_headers;
395}
396
397
406static struct GNUNET_CURL_Job *
407setup_job (CURL *eh,
408 struct GNUNET_CURL_Context *ctx,
409 struct curl_slist *all_headers)
410{
411 struct GNUNET_CURL_Job *job;
412
413 if (CURLE_OK !=
414 curl_easy_setopt (eh,
415 CURLOPT_HTTPHEADER,
416 all_headers))
417 {
418 GNUNET_break (0);
419 curl_slist_free_all (all_headers);
420 curl_easy_cleanup (eh);
421 return NULL;
422 }
423 job = GNUNET_new (struct GNUNET_CURL_Job);
424 job->start_time = GNUNET_TIME_absolute_get ();
425 job->job_headers = all_headers;
426
427 if ( (CURLE_OK !=
428 curl_easy_setopt (eh,
429 CURLOPT_PRIVATE,
430 job)) ||
431 (CURLE_OK !=
432 curl_easy_setopt (eh,
433 CURLOPT_WRITEFUNCTION,
434 &download_cb)) ||
435 (CURLE_OK !=
436 curl_easy_setopt (eh,
437 CURLOPT_WRITEDATA,
438 &job->db)) ||
439 (CURLE_OK !=
440 curl_easy_setopt (eh,
441 CURLOPT_SHARE,
442 ctx->share)) )
443 {
444 GNUNET_break (0);
446 curl_easy_cleanup (eh);
447 return NULL;
448 }
449 if ( (CURLM_OK !=
450 curl_multi_add_handle (ctx->multi,
451 eh)) )
452 {
453 GNUNET_break (0);
455 curl_easy_cleanup (eh);
456 return NULL;
457 }
458 job->easy_handle = eh;
459 job->ctx = ctx;
461 ctx->jobs_tail,
462 job);
463 return job;
464}
465
466
467void
469 const struct curl_slist *extra_headers)
470{
471 struct curl_slist *all_headers = job->job_headers;
472
473 for (const struct curl_slist *curr = extra_headers;
474 NULL != curr;
475 curr = curr->next)
476 {
477 GNUNET_assert (NULL !=
478 (all_headers = curl_slist_append (all_headers,
479 curr->data)));
480 }
481 job->job_headers = all_headers;
482}
483
484
485struct GNUNET_CURL_Job *
487 CURL *eh,
488 const struct curl_slist *job_headers,
490 void *jcc_cls)
491{
492 struct GNUNET_CURL_Job *job;
493 struct curl_slist *all_headers;
494
495 GNUNET_assert (NULL != jcc);
496 all_headers = setup_job_headers (ctx,
497 job_headers);
498 if (NULL == (job = setup_job (eh,
499 ctx,
500 all_headers)))
501 return NULL;
502 job->jcc_raw = jcc;
503 job->jcc_raw_cls = jcc_cls;
504 ctx->cb (ctx->cb_cls);
505 return job;
506}
507
508
509struct GNUNET_CURL_Job *
511 CURL *eh,
512 const struct curl_slist *job_headers,
514 void *jcc_cls)
515{
516 struct GNUNET_CURL_Job *job;
517 struct curl_slist *all_headers;
518
519 GNUNET_assert (NULL != jcc);
520 if ( (NULL != ctx->userpass) &&
521 (0 != curl_easy_setopt (eh,
522 CURLOPT_USERPWD,
523 ctx->userpass)) )
524 return NULL;
525 if ( (NULL != ctx->certfile) &&
526 (0 != curl_easy_setopt (eh,
527 CURLOPT_SSLCERT,
528 ctx->certfile)) )
529 return NULL;
530 if ( (NULL != ctx->certtype) &&
531 (0 != curl_easy_setopt (eh,
532 CURLOPT_SSLCERTTYPE,
533 ctx->certtype)) )
534 return NULL;
535 if ( (NULL != ctx->keyfile) &&
536 (0 != curl_easy_setopt (eh,
537 CURLOPT_SSLKEY,
538 ctx->keyfile)) )
539 return NULL;
540 if ( (NULL != ctx->keypass) &&
541 (0 != curl_easy_setopt (eh,
542 CURLOPT_KEYPASSWD,
543 ctx->keypass)) )
544 return NULL;
545
546 all_headers = setup_job_headers (ctx,
547 job_headers);
548 if (NULL == (job = setup_job (eh,
549 ctx,
550 all_headers)))
551 return NULL;
552
553 job->jcc = jcc;
554 job->jcc_cls = jcc_cls;
555 ctx->cb (ctx->cb_cls);
556 return job;
557}
558
559
560struct GNUNET_CURL_Job *
562 CURL *eh,
564 void *jcc_cls)
565{
566 struct GNUNET_CURL_Job *job;
567 struct curl_slist *job_headers = NULL;
568
569 GNUNET_assert (NULL != (job_headers =
570 curl_slist_append (NULL,
571 "Content-Type: application/json")
572 ));
574 eh,
575 job_headers,
576 jcc,
577 jcc_cls);
578 curl_slist_free_all (job_headers);
579 return job;
580}
581
582
583struct GNUNET_CURL_Job *
585 CURL *eh,
587 void *jcc_cls)
588{
590 eh,
591 NULL,
592 jcc,
593 jcc_cls);
594}
595
596
597void
599{
600 struct GNUNET_CURL_Context *ctx = job->ctx;
601
603 ctx->jobs_tail,
604 job);
605 GNUNET_break (CURLM_OK ==
606 curl_multi_remove_handle (ctx->multi,
607 job->easy_handle));
608 curl_easy_cleanup (job->easy_handle);
609 GNUNET_free (job->db.buf);
610 curl_slist_free_all (job->job_headers);
611 ctx->cb (ctx->cb_cls);
613}
614
615
622static bool
623is_json (const char *ct)
624{
625 const char *semi;
626
627 /* check for "application/json" exact match */
628 if (0 == strcasecmp (ct,
629 "application/json"))
630 return true;
631 /* check for "application/json;[ANYTHING]" */
632 semi = strchr (ct,
633 ';');
634 /* also allow "application/json [ANYTHING]" (note the space!) */
635 if (NULL == semi)
636 semi = strchr (ct,
637 ' ');
638 if (NULL == semi)
639 return false; /* no delimiter we accept, forget it */
640 if (semi - ct != strlen ("application/json"))
641 return false; /* delimiter past desired length, forget it */
642 if (0 == strncasecmp (ct,
643 "application/json",
644 strlen ("application/json")))
645 return true; /* OK */
646 return false;
647}
648
649
650void *
652 CURL *eh,
653 long *response_code)
654{
655 json_t *json;
656 char *ct;
657
658#if DEBUG
660 "Downloaded body: %.*s\n",
661 (int) db->buf_size,
662 (char *) db->buf);
663#endif
664 if (CURLE_OK !=
665 curl_easy_getinfo (eh,
666 CURLINFO_RESPONSE_CODE,
667 response_code))
668 {
669 /* unexpected error... */
670 GNUNET_break (0);
671 *response_code = 0;
672 }
673 if (MHD_HTTP_NO_CONTENT == *response_code)
674 return NULL;
675 if ((CURLE_OK !=
676 curl_easy_getinfo (eh,
677 CURLINFO_CONTENT_TYPE,
678 &ct)) ||
679 (NULL == ct) ||
680 (! is_json (ct)))
681 {
682 /* No content type or explicitly not JSON, refuse to parse
683 (but keep response code) */
684 if (0 != db->buf_size)
685 {
686 const char *url;
687
688 if (CURLE_OK !=
689 curl_easy_getinfo (eh,
690 CURLINFO_EFFECTIVE_URL,
691 &url))
692 url = "<unknown URL>";
694 "Request to `%s' was expected to return a body of type `application/json', got `%s'\n",
695 url,
696 ct);
697 }
698 return NULL;
699 }
700 if (0 == *response_code)
701 {
702 const char *url;
703
704 if (CURLE_OK !=
705 curl_easy_getinfo (eh,
706 CURLINFO_EFFECTIVE_URL,
707 &url))
708 url = "<unknown URL>";
710 "Failed to download response from `%s': \n",
711 url);
712 return NULL;
713 }
714 json = NULL;
715 if (0 == db->eno)
716 {
717 json_error_t error;
718
719 json = json_loadb (db->buf,
720 db->buf_size,
721 JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK,
722 &error);
723 if (NULL == json)
724 {
725 JSON_WARN (error);
726 *response_code = 0;
728 "Failed to parse JSON response: %s\n",
729 error.text);
730 }
731 }
732 GNUNET_free (db->buf);
733 db->buf = NULL;
734 db->buf_size = 0;
735 return json;
736}
737
738
741 const char *header)
742{
743 ctx->common_headers = curl_slist_append (ctx->common_headers,
744 header);
745 if (NULL == ctx->common_headers)
746 return GNUNET_SYSERR;
747
748 return GNUNET_OK;
749}
750
751
752void
756{
757 CURLMsg *cmsg;
758 int n_running;
759 int n_completed;
760
761 (void) curl_multi_perform (ctx->multi,
762 &n_running);
763 while (NULL != (cmsg = curl_multi_info_read (ctx->multi,
764 &n_completed)))
765 {
766 struct GNUNET_CURL_Job *job;
768 long response_code;
769 void *response;
770
771 /* Only documented return value is CURLMSG_DONE */
772 GNUNET_break (CURLMSG_DONE == cmsg->msg);
773 GNUNET_assert (CURLE_OK ==
774 curl_easy_getinfo (cmsg->easy_handle,
775 CURLINFO_PRIVATE,
776 (char **) &job));
777 GNUNET_assert (job->ctx == ctx);
778 response_code = 0;
780 if (NULL != job->jcc_raw)
781 {
782 /* RAW mode, no parsing */
783 GNUNET_break (CURLE_OK ==
784 curl_easy_getinfo (job->easy_handle,
785 CURLINFO_RESPONSE_CODE,
786 &response_code));
787 job->jcc_raw (job->jcc_raw_cls,
788 response_code,
789 job->db.buf,
790 job->db.buf_size);
791 }
792 else
793 {
794 /* to be parsed via 'rp' */
795 response = rp (&job->db,
796 job->easy_handle,
797 &response_code);
798 job->jcc (job->jcc_cls,
799 response_code,
800 response);
801 rc (response);
802 }
803 {
804 const char *url = NULL;
805
806 if (CURLE_UNKNOWN_OPTION ==
807 curl_easy_getinfo (job->easy_handle,
808 CURLINFO_EFFECTIVE_URL,
809 &url))
810 url = "<unknown>";
812 "HTTP request for `%s' finished with %u after %s\n",
813 url,
814 (unsigned int) response_code,
816 true));
817 /* Note: we MUST NOT free 'url' here */
818 }
820 }
821}
822
823
824void
826{
829 (GNUNET_CURL_ResponseCleaner) & json_decref);
830}
831
832
833void
835 fd_set *read_fd_set,
836 fd_set *write_fd_set,
837 fd_set *except_fd_set,
838 int *max_fd,
839 long *timeout)
840{
841 long to;
842 int m;
843
844 m = -1;
845 GNUNET_assert (CURLM_OK ==
846 curl_multi_fdset (ctx->multi,
847 read_fd_set,
848 write_fd_set,
849 except_fd_set,
850 &m));
851 to = *timeout;
852 *max_fd = GNUNET_MAX (m, *max_fd);
853 GNUNET_assert (CURLM_OK ==
854 curl_multi_timeout (ctx->multi,
855 &to));
856
857 /* Only if what we got back from curl is smaller than what we
858 already had (-1 == infinity!), then update timeout */
859 if ((to < *timeout) && (-1 != to))
860 *timeout = to;
861 if ((-1 == (*timeout)) && (NULL != ctx->jobs_head))
862 *timeout = to;
863}
864
865
866void
868{
869 /* all jobs must have been cancelled at this time, assert this */
870 GNUNET_assert (NULL == ctx->jobs_head);
871 curl_share_cleanup (ctx->share);
872 curl_multi_cleanup (ctx->multi);
873 curl_slist_free_all (ctx->common_headers);
874 GNUNET_free (ctx->userpass);
875 GNUNET_free (ctx->certtype);
876 GNUNET_free (ctx->certfile);
877 GNUNET_free (ctx->keyfile);
878 GNUNET_free (ctx->keypass);
880}
881
882void
884
888void __attribute__ ((constructor))
890{
891 CURLcode ret;
892
893 if (CURLE_OK != (ret = curl_global_init (CURL_GLOBAL_DEFAULT)))
894 {
896 "curl_global_init",
897 ret);
898 curl_fail = 1;
899 }
900}
901
902void
904
908void __attribute__ ((destructor))
910{
911 if (curl_fail)
912 return;
913 curl_global_cleanup ();
914}
915
916
917/* end of curl.c */
void GNUNET_CURL_constructor__(void)
#define CURL_STRERROR(type, function, code)
Log error related to CURL operations.
Definition: curl.c:48
static bool is_json(const char *ct)
Test if the given content type ct is JSON.
Definition: curl.c:623
#define JSON_WARN(error)
Print JSON parsing related error information.
Definition: curl.c:59
static struct GNUNET_CURL_Job * setup_job(CURL *eh, struct GNUNET_CURL_Context *ctx, struct curl_slist *all_headers)
Create a job.
Definition: curl.c:407
static size_t download_cb(char *bufptr, size_t size, size_t nitems, void *cls)
Callback used when downloading the reply to an HTTP request.
Definition: curl.c:315
static int curl_fail
Failsafe flag.
Definition: curl.c:72
static struct curl_slist * setup_job_headers(struct GNUNET_CURL_Context *ctx, const struct curl_slist *job_headers)
Create the HTTP headers for the request.
Definition: curl.c:352
void GNUNET_CURL_destructor__(void)
void * GNUNET_CURL_download_get_result_(struct GNUNET_CURL_DownloadBuffer *db, CURL *eh, long *response_code)
Definition: curl.c:651
void __attribute__((constructor))
Initial global setup logic, specifically runs the Curl setup.
Definition: curl.c:888
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:103
static int ret
Final status code.
Definition: gnunet-arm.c:93
static struct GNUNET_TIME_Relative timeout
User defined timestamp for completing operations.
Definition: gnunet-arm.c:118
static struct GNUNET_SCHEDULER_Task * job
Task for main job.
Definition: gnunet-cadet.c:137
static CURLM * multi
Current multi-CURL handle.
static struct MHD_Response * response
Our canonical response.
static struct GNUNET_FS_Handle * ctx
static char * rp
Relying party.
static struct GNUNET_FS_DirectoryBuilder * db
static struct GNUNET_TIME_Relative duration
Option '-d': duration of the mapping.
Definition: gnunet-vpn.c:90
library to make it easy to download JSON replies over HTTP
void GNUNET_CURL_set_tlscert(struct GNUNET_CURL_Context *ctx, const char *certtype, const char *certfile, const char *keyfile, const char *keypass)
Force use of the provided TLS client certificate for client authentication for all operations perform...
Definition: curl.c:225
void(* GNUNET_CURL_RawJobCompletionCallback)(void *cls, long response_code, const void *body, size_t body_size)
Function to call upon completion of a raw job.
void(* GNUNET_CURL_JobCompletionCallback)(void *cls, long response_code, const void *response)
Function to call upon completion of a job.
struct GNUNET_CURL_Job * GNUNET_CURL_job_add_raw(struct GNUNET_CURL_Context *ctx, CURL *eh, const struct curl_slist *job_headers, GNUNET_CURL_RawJobCompletionCallback jcc, void *jcc_cls)
Schedule a CURL request to be executed and call the given jcc upon its completion.
Definition: curl.c:486
struct GNUNET_CURL_Job * GNUNET_CURL_job_add(struct GNUNET_CURL_Context *ctx, CURL *eh, GNUNET_CURL_JobCompletionCallback jcc, void *jcc_cls)
Schedule a CURL request to be executed and call the given jcc upon its completion.
Definition: curl.c:584
void GNUNET_CURL_get_select_info(struct GNUNET_CURL_Context *ctx, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, int *max_fd, long *timeout)
Obtain the information for a select() call to wait until GNUNET_CURL_perform() is ready again.
Definition: curl.c:834
struct GNUNET_CURL_Context * GNUNET_CURL_init(GNUNET_CURL_RescheduleCallback cb, void *cb_cls)
Initialise this library.
Definition: curl.c:247
void GNUNET_CURL_fini(struct GNUNET_CURL_Context *ctx)
Cleanup library initialisation resources.
Definition: curl.c:867
void(* GNUNET_CURL_ResponseCleaner)(void *response)
Deallocate the response.
void GNUNET_CURL_extend_headers(struct GNUNET_CURL_Job *job, const struct curl_slist *extra_headers)
Add extra_headers to the HTTP headers for job.
Definition: curl.c:468
void GNUNET_CURL_perform2(struct GNUNET_CURL_Context *ctx, GNUNET_CURL_RawParser rp, GNUNET_CURL_ResponseCleaner rc)
Run the main event loop for the HTTP interaction.
Definition: curl.c:753
void GNUNET_CURL_job_cancel(struct GNUNET_CURL_Job *job)
Cancel a job.
Definition: curl.c:598
enum GNUNET_GenericReturnValue GNUNET_CURL_is_valid_scope_id(const char *scope_id)
Return GNUNET_YES if given a valid scope ID and GNUNET_NO otherwise.
Definition: curl.c:290
void GNUNET_CURL_perform(struct GNUNET_CURL_Context *ctx)
Run the main event loop for the CURL interaction.
Definition: curl.c:825
void GNUNET_CURL_set_userpass(struct GNUNET_CURL_Context *ctx, const char *userpass)
Force use of the provided username and password for client authentication for all operations performe...
Definition: curl.c:215
void *(* GNUNET_CURL_RawParser)(struct GNUNET_CURL_DownloadBuffer *db, CURL *eh, long *response_code)
Parses the raw response we got from the Web server.
struct GNUNET_CURL_Job * GNUNET_CURL_job_add_with_ct_json(struct GNUNET_CURL_Context *ctx, CURL *eh, GNUNET_CURL_JobCompletionCallback jcc, void *jcc_cls)
Schedule a CURL request to be executed and call the given jcc upon its completion.
Definition: curl.c:561
enum GNUNET_GenericReturnValue GNUNET_CURL_append_header(struct GNUNET_CURL_Context *ctx, const char *header)
Add custom request header.
Definition: curl.c:740
void(* GNUNET_CURL_RescheduleCallback)(void *cls)
Function called by the context to ask for the event loop to be rescheduled, that is the application s...
void GNUNET_CURL_enable_async_scope_header(struct GNUNET_CURL_Context *ctx, const char *header_name)
Enable sending the async scope ID as a header.
Definition: curl.c:282
struct GNUNET_CURL_Job * GNUNET_CURL_job_add2(struct GNUNET_CURL_Context *ctx, CURL *eh, const struct curl_slist *job_headers, GNUNET_CURL_JobCompletionCallback jcc, void *jcc_cls)
Schedule a CURL request to be executed and call the given jcc upon its completion.
Definition: curl.c:510
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_log(kind,...)
#define GNUNET_MAX(a, b)
int have_scope
GNUNET_YES unless this saved scope is the unnamed root scope.
void GNUNET_async_scope_get(struct GNUNET_AsyncScopeSave *scope_ret)
Get the current async scope.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
struct GNUNET_AsyncScopeId scope_id
Saved scope.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_MAX_MALLOC_CHECKED
Maximum allocation with GNUNET_malloc macro.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_realloc(ptr, size)
Wrapper around realloc.
#define GNUNET_free(ptr)
Wrapper around free.
char * GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
Return the base32crockford encoding of the given buffer.
Definition: strings.c:787
const char * GNUNET_TIME_relative2s(struct GNUNET_TIME_Relative delta, bool do_round)
Give relative time in human-readable fancy format.
Definition: time.c:264
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:438
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
@ MHD_HTTP_NO_CONTENT
No Content [RFC7231, Section 6.3.5].
static unsigned int size
Size of the "table".
Definition: peer.c:68
Identifier for an asynchronous execution context.
Saved async scope identifier or root scope.
Context.
Definition: curl.c:141
char * userpass
USERNAME:PASSWORD to use for client-authentication with all requests of this context,...
Definition: curl.c:188
char * keypass
Passphrase to decrypt keyfile, or NULL.
Definition: curl.c:209
void * cb_cls
Closure for cb.
Definition: curl.c:182
char * certtype
Type of the TLS client certificate used, or NULL.
Definition: curl.c:193
char * keyfile
File with the private key to authenticate the TLS client, or NULL.
Definition: curl.c:204
struct curl_slist * common_headers
Headers common for all requests in the context.
Definition: curl.c:165
CURLSH * share
Curl share handle.
Definition: curl.c:150
const char * async_scope_id_header
If non-NULL, the async scope ID is sent in a request header of this name.
Definition: curl.c:171
CURLM * multi
Curl multi handle.
Definition: curl.c:145
GNUNET_CURL_RescheduleCallback cb
Function we need to call whenever the event loop's socket set changed.
Definition: curl.c:177
struct GNUNET_CURL_Job * jobs_head
We keep jobs in a DLL.
Definition: curl.c:155
char * certfile
File with the TLS client certificate, or NULL.
Definition: curl.c:198
struct GNUNET_CURL_Job * jobs_tail
We keep jobs in a DLL.
Definition: curl.c:160
Buffer data structure we use to buffer the HTTP download before giving it to the JSON parser.
void * buf
Download buffer.
Jobs are CURL requests running within a struct GNUNET_CURL_Context.
Definition: curl.c:78
struct GNUNET_CURL_Job * prev
We keep jobs in a DLL.
Definition: curl.c:87
CURL * easy_handle
Easy handle of the job.
Definition: curl.c:92
struct curl_slist * job_headers
Headers used for this job, the list needs to be freed after the job has finished.
Definition: curl.c:128
void * jcc_raw_cls
Closure for jcc_raw.
Definition: curl.c:117
struct GNUNET_CURL_Context * ctx
Context this job runs in.
Definition: curl.c:97
struct GNUNET_TIME_Absolute start_time
When did we start the job?
Definition: curl.c:133
GNUNET_CURL_JobCompletionCallback jcc
Function to call upon completion.
Definition: curl.c:102
void * jcc_cls
Closure for jcc.
Definition: curl.c:107
struct GNUNET_CURL_DownloadBuffer db
Buffer for response received from CURL.
Definition: curl.c:122
struct GNUNET_CURL_Job * next
We keep jobs in a DLL.
Definition: curl.c:82
GNUNET_CURL_RawJobCompletionCallback jcc_raw
Function to call upon completion.
Definition: curl.c:112
Time for absolute times used by GNUnet, in microseconds.
Time for relative time used by GNUnet, in microseconds.