GNUnet 0.24.1-15-gab6ed22f1
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 GNUNET_break (CURLE_OK ==
483 curl_easy_setopt (job->easy_handle,
484 CURLOPT_HTTPHEADER,
485 all_headers));
486}
487
488
489struct GNUNET_CURL_Job *
491 CURL *eh,
492 const struct curl_slist *job_headers,
494 void *jcc_cls)
495{
496 struct GNUNET_CURL_Job *job;
497 struct curl_slist *all_headers;
498
499 GNUNET_assert (NULL != jcc);
500 all_headers = setup_job_headers (ctx,
501 job_headers);
502 if (NULL == (job = setup_job (eh,
503 ctx,
504 all_headers)))
505 return NULL;
506 job->jcc_raw = jcc;
507 job->jcc_raw_cls = jcc_cls;
508 ctx->cb (ctx->cb_cls);
509 return job;
510}
511
512
513struct GNUNET_CURL_Job *
515 CURL *eh,
516 const struct curl_slist *job_headers,
518 void *jcc_cls)
519{
520 struct GNUNET_CURL_Job *job;
521 struct curl_slist *all_headers;
522
523 GNUNET_assert (NULL != jcc);
524 if ( (NULL != ctx->userpass) &&
525 (0 != curl_easy_setopt (eh,
526 CURLOPT_USERPWD,
527 ctx->userpass)) )
528 return NULL;
529 if ( (NULL != ctx->certfile) &&
530 (0 != curl_easy_setopt (eh,
531 CURLOPT_SSLCERT,
532 ctx->certfile)) )
533 return NULL;
534 if ( (NULL != ctx->certtype) &&
535 (0 != curl_easy_setopt (eh,
536 CURLOPT_SSLCERTTYPE,
537 ctx->certtype)) )
538 return NULL;
539 if ( (NULL != ctx->keyfile) &&
540 (0 != curl_easy_setopt (eh,
541 CURLOPT_SSLKEY,
542 ctx->keyfile)) )
543 return NULL;
544 if ( (NULL != ctx->keypass) &&
545 (0 != curl_easy_setopt (eh,
546 CURLOPT_KEYPASSWD,
547 ctx->keypass)) )
548 return NULL;
549
550 all_headers = setup_job_headers (ctx,
551 job_headers);
552 if (NULL == (job = setup_job (eh,
553 ctx,
554 all_headers)))
555 return NULL;
556
557 job->jcc = jcc;
558 job->jcc_cls = jcc_cls;
559 ctx->cb (ctx->cb_cls);
560 return job;
561}
562
563
564struct GNUNET_CURL_Job *
566 CURL *eh,
568 void *jcc_cls)
569{
570 struct GNUNET_CURL_Job *job;
571 struct curl_slist *job_headers = NULL;
572
573 GNUNET_assert (NULL != (job_headers =
574 curl_slist_append (NULL,
575 "Content-Type: application/json")
576 ));
578 eh,
579 job_headers,
580 jcc,
581 jcc_cls);
582 curl_slist_free_all (job_headers);
583 return job;
584}
585
586
587struct GNUNET_CURL_Job *
589 CURL *eh,
591 void *jcc_cls)
592{
594 eh,
595 NULL,
596 jcc,
597 jcc_cls);
598}
599
600
601void
603{
604 struct GNUNET_CURL_Context *ctx = job->ctx;
605
607 ctx->jobs_tail,
608 job);
609 GNUNET_break (CURLM_OK ==
610 curl_multi_remove_handle (ctx->multi,
611 job->easy_handle));
612 curl_easy_cleanup (job->easy_handle);
613 GNUNET_free (job->db.buf);
614 curl_slist_free_all (job->job_headers);
615 ctx->cb (ctx->cb_cls);
617}
618
619
626static bool
627is_json (const char *ct)
628{
629 const char *semi;
630
631 /* check for "application/json" exact match */
632 if (0 == strcasecmp (ct,
633 "application/json"))
634 return true;
635 /* check for "application/json;[ANYTHING]" */
636 semi = strchr (ct,
637 ';');
638 /* also allow "application/json [ANYTHING]" (note the space!) */
639 if (NULL == semi)
640 semi = strchr (ct,
641 ' ');
642 if (NULL == semi)
643 return false; /* no delimiter we accept, forget it */
644 if (semi - ct != strlen ("application/json"))
645 return false; /* delimiter past desired length, forget it */
646 if (0 == strncasecmp (ct,
647 "application/json",
648 strlen ("application/json")))
649 return true; /* OK */
650 return false;
651}
652
653
654void *
656 CURL *eh,
657 long *response_code)
658{
659 json_t *json;
660 char *ct;
661
662#if DEBUG
664 "Downloaded body: %.*s\n",
665 (int) db->buf_size,
666 (char *) db->buf);
667#endif
668 if (CURLE_OK !=
669 curl_easy_getinfo (eh,
670 CURLINFO_RESPONSE_CODE,
671 response_code))
672 {
673 /* unexpected error... */
674 GNUNET_break (0);
675 *response_code = 0;
676 }
677 if (MHD_HTTP_NO_CONTENT == *response_code)
678 return NULL;
679 if ((CURLE_OK !=
680 curl_easy_getinfo (eh,
681 CURLINFO_CONTENT_TYPE,
682 &ct)) ||
683 (NULL == ct) ||
684 (! is_json (ct)))
685 {
686 /* No content type or explicitly not JSON, refuse to parse
687 (but keep response code) */
688 if (0 != db->buf_size)
689 {
690 const char *url;
691
692 if (CURLE_OK !=
693 curl_easy_getinfo (eh,
694 CURLINFO_EFFECTIVE_URL,
695 &url))
696 url = "<unknown URL>";
698 "Request to `%s' was expected to return a body of type `application/json', got `%s'\n",
699 url,
700 ct);
701 }
702 return NULL;
703 }
704 if (0 == *response_code)
705 {
706 const char *url;
707
708 if (CURLE_OK !=
709 curl_easy_getinfo (eh,
710 CURLINFO_EFFECTIVE_URL,
711 &url))
712 url = "<unknown URL>";
714 "Failed to download response from `%s': \n",
715 url);
716 return NULL;
717 }
718 json = NULL;
719 if (0 == db->eno)
720 {
721 json_error_t error;
722
723 json = json_loadb (db->buf,
724 db->buf_size,
725 JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK,
726 &error);
727 if (NULL == json)
728 {
729 JSON_WARN (error);
730 *response_code = 0;
732 "Failed to parse JSON response: %s\n",
733 error.text);
734 }
735 }
736 GNUNET_free (db->buf);
737 db->buf = NULL;
738 db->buf_size = 0;
739 return json;
740}
741
742
745 const char *header)
746{
747 ctx->common_headers = curl_slist_append (ctx->common_headers,
748 header);
749 if (NULL == ctx->common_headers)
750 return GNUNET_SYSERR;
751
752 return GNUNET_OK;
753}
754
755
756void
760{
761 CURLMsg *cmsg;
762 int n_running;
763 int n_completed;
764
765 (void) curl_multi_perform (ctx->multi,
766 &n_running);
767 while (NULL != (cmsg = curl_multi_info_read (ctx->multi,
768 &n_completed)))
769 {
770 struct GNUNET_CURL_Job *job;
772 long response_code;
773 void *response;
774
775 /* Only documented return value is CURLMSG_DONE */
776 GNUNET_break (CURLMSG_DONE == cmsg->msg);
777 GNUNET_assert (CURLE_OK ==
778 curl_easy_getinfo (cmsg->easy_handle,
779 CURLINFO_PRIVATE,
780 (char **) &job));
781 GNUNET_assert (job->ctx == ctx);
782 response_code = 0;
784 if (NULL != job->jcc_raw)
785 {
786 /* RAW mode, no parsing */
787 GNUNET_break (CURLE_OK ==
788 curl_easy_getinfo (job->easy_handle,
789 CURLINFO_RESPONSE_CODE,
790 &response_code));
791 job->jcc_raw (job->jcc_raw_cls,
792 response_code,
793 job->db.buf,
794 job->db.buf_size);
795 }
796 else
797 {
798 /* to be parsed via 'rp' */
799 response = rp (&job->db,
800 job->easy_handle,
801 &response_code);
802 job->jcc (job->jcc_cls,
803 response_code,
804 response);
805 rc (response);
806 }
807 {
808 const char *url = NULL;
809
810 if (CURLE_UNKNOWN_OPTION ==
811 curl_easy_getinfo (job->easy_handle,
812 CURLINFO_EFFECTIVE_URL,
813 &url))
814 url = "<unknown>";
816 "HTTP request for `%s' finished with %u after %s\n",
817 url,
818 (unsigned int) response_code,
820 true));
821 /* Note: we MUST NOT free 'url' here */
822 }
824 }
825}
826
827
828void
830{
833 (GNUNET_CURL_ResponseCleaner) & json_decref);
834}
835
836
837void
839 fd_set *read_fd_set,
840 fd_set *write_fd_set,
841 fd_set *except_fd_set,
842 int *max_fd,
843 long *timeout)
844{
845 long to;
846 int m;
847
848 m = -1;
849 GNUNET_assert (CURLM_OK ==
850 curl_multi_fdset (ctx->multi,
851 read_fd_set,
852 write_fd_set,
853 except_fd_set,
854 &m));
855 to = *timeout;
856 *max_fd = GNUNET_MAX (m, *max_fd);
857 GNUNET_assert (CURLM_OK ==
858 curl_multi_timeout (ctx->multi,
859 &to));
860
861 /* Only if what we got back from curl is smaller than what we
862 already had (-1 == infinity!), then update timeout */
863 if ((to < *timeout) && (-1 != to))
864 *timeout = to;
865 if ((-1 == (*timeout)) && (NULL != ctx->jobs_head))
866 *timeout = to;
867}
868
869
870void
872{
873 /* all jobs must have been cancelled at this time, assert this */
874 GNUNET_assert (NULL == ctx->jobs_head);
875 curl_share_cleanup (ctx->share);
876 curl_multi_cleanup (ctx->multi);
877 curl_slist_free_all (ctx->common_headers);
878 GNUNET_free (ctx->userpass);
879 GNUNET_free (ctx->certtype);
880 GNUNET_free (ctx->certfile);
881 GNUNET_free (ctx->keyfile);
882 GNUNET_free (ctx->keypass);
884}
885
886
887void
889
893void __attribute__ ((constructor))
895{
896 CURLcode ret;
897
898 if (CURLE_OK != (ret = curl_global_init (CURL_GLOBAL_DEFAULT)))
899 {
901 "curl_global_init",
902 ret);
903 curl_fail = 1;
904 }
905}
906
907
908void
910
914void __attribute__ ((destructor))
916{
917 if (curl_fail)
918 return;
919 curl_global_cleanup ();
920}
921
922
923/* 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:627
#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:655
void __attribute__((constructor))
Initial global setup logic, specifically runs the Curl setup.
Definition: curl.c:893
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:490
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:588
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:838
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:871
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:757
void GNUNET_CURL_job_cancel(struct GNUNET_CURL_Job *job)
Cancel a job.
Definition: curl.c:602
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:829
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:565
enum GNUNET_GenericReturnValue GNUNET_CURL_append_header(struct GNUNET_CURL_Context *ctx, const char *header)
Add custom request header.
Definition: curl.c:744
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:514
#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:791
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
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.