GNUnet  0.19.4
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 
31 #if ENABLE_BENCHMARK
32 #include "../util/benchmark.h"
33 #endif
34 
38 #define DEBUG 0
39 
47 #define CURL_STRERROR(type, function, code) \
48  GNUNET_log (type, \
49  "Curl function `%s' has failed at `%s:%d' with error: %s\n", \
50  function, \
51  __FILE__, \
52  __LINE__, \
53  curl_easy_strerror (code));
54 
58 #define JSON_WARN(error) \
59  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, \
60  "JSON parsing failed at %s:%u: %s (%s)\n", \
61  __FILE__, \
62  __LINE__, \
63  error.text, \
64  error.source)
65 
66 
71 static int curl_fail;
72 
77 {
82 
87 
91  CURL *easy_handle;
92 
97 
102 
106  void *jcc_cls;
107 
112 
116  void *jcc_raw_cls;
117 
122 
127  struct curl_slist *job_headers;
128 
133 };
134 
135 
140 {
144  CURLM *multi;
145 
149  CURLSH *share;
150 
155 
160 
164  struct curl_slist *common_headers;
165 
171 
177 
181  void *cb_cls;
182 
187  char *userpass;
188 
192  char *certtype;
193 
197  char *certfile;
198 
203  char *keyfile;
204 
208  char *keypass;
209 
210 };
211 
212 
213 void
215  const char *userpass)
216 {
217  GNUNET_free (ctx->userpass);
218  if (NULL != userpass)
219  ctx->userpass = GNUNET_strdup (userpass);
220 }
221 
222 
223 void
225  const char *certtype,
226  const char *certfile,
227  const char *keyfile,
228  const char *keypass)
229 {
230  GNUNET_free (ctx->certtype);
231  GNUNET_free (ctx->certfile);
232  GNUNET_free (ctx->keyfile);
233  GNUNET_free (ctx->keypass);
234  if (NULL != certtype)
235  ctx->certtype = GNUNET_strdup (certtype);
236  if (NULL != certfile)
237  ctx->certfile = GNUNET_strdup (certfile);
238  if (NULL != keyfile)
239  ctx->certtype = GNUNET_strdup (keyfile);
240  if (NULL != keypass)
241  ctx->certtype = GNUNET_strdup (keypass);
242 }
243 
244 
245 struct GNUNET_CURL_Context *
247  void *cb_cls)
248 {
249  struct GNUNET_CURL_Context *ctx;
250  CURLM *multi;
251  CURLSH *share;
252 
253  if (curl_fail)
254  {
256  "Curl was not initialised properly\n");
257  return NULL;
258  }
259  if (NULL == (multi = curl_multi_init ()))
260  {
262  "Failed to create a Curl multi handle\n");
263  return NULL;
264  }
265  if (NULL == (share = curl_share_init ()))
266  {
268  "Failed to create a Curl share handle\n");
269  return NULL;
270  }
272  ctx->cb = cb;
273  ctx->cb_cls = cb_cls;
274  ctx->multi = multi;
275  ctx->share = share;
276  return ctx;
277 }
278 
279 
280 void
282  const char *header_name)
283 {
284  ctx->async_scope_id_header = header_name;
285 }
286 
287 
288 int
289 GNUNET_CURL_is_valid_scope_id (const char *scope_id)
290 {
291  if (strlen (scope_id) >= 64)
292  return GNUNET_NO;
293  for (size_t i = 0; i < strlen (scope_id); i++)
294  if (! (isalnum (scope_id[i]) || (scope_id[i] == '-')))
295  return GNUNET_NO;
296  return GNUNET_YES;
297 }
298 
299 
313 static size_t
314 download_cb (char *bufptr,
315  size_t size,
316  size_t nitems,
317  void *cls)
318 {
319  struct GNUNET_CURL_DownloadBuffer *db = cls;
320  size_t msize;
321  void *buf;
322 
323  if (0 == size * nitems)
324  {
325  /* Nothing (left) to do */
326  return 0;
327  }
328  msize = size * nitems;
329  if ((msize + db->buf_size) >= GNUNET_MAX_MALLOC_CHECKED)
330  {
331  db->eno = ENOMEM;
332  return 0; /* signals an error to curl */
333  }
334  db->buf = GNUNET_realloc (db->buf,
335  db->buf_size + msize);
336  buf = db->buf + db->buf_size;
337  GNUNET_memcpy (buf, bufptr, msize);
338  db->buf_size += msize;
339  return msize;
340 }
341 
342 
350 static struct curl_slist *
352  const struct curl_slist *job_headers)
353 {
354  struct curl_slist *all_headers = NULL;
355 
356  for (const struct curl_slist *curr = job_headers;
357  NULL != curr;
358  curr = curr->next)
359  {
360  GNUNET_assert (NULL !=
361  (all_headers = curl_slist_append (all_headers,
362  curr->data)));
363  }
364 
365  for (const struct curl_slist *curr = ctx->common_headers;
366  NULL != curr;
367  curr = curr->next)
368  {
369  GNUNET_assert (NULL !=
370  (all_headers = curl_slist_append (all_headers,
371  curr->data)));
372  }
373 
374  if (NULL != ctx->async_scope_id_header)
375  {
377 
379  if (GNUNET_YES == scope.have_scope)
380  {
381  char *aid_header;
382 
383  aid_header =
385  &scope.scope_id,
386  sizeof(struct GNUNET_AsyncScopeId));
387  GNUNET_assert (NULL != aid_header);
388  GNUNET_assert (NULL != curl_slist_append (all_headers,
389  aid_header));
390  GNUNET_free (aid_header);
391  }
392  }
393  return all_headers;
394 }
395 
396 
405 static struct GNUNET_CURL_Job *
406 setup_job (CURL *eh,
407  struct GNUNET_CURL_Context *ctx,
408  struct curl_slist *all_headers)
409 {
410  struct GNUNET_CURL_Job *job;
411 
412  if (CURLE_OK !=
413  curl_easy_setopt (eh,
414  CURLOPT_HTTPHEADER,
415  all_headers))
416  {
417  GNUNET_break (0);
418  curl_slist_free_all (all_headers);
419  curl_easy_cleanup (eh);
420  return NULL;
421  }
422  job = GNUNET_new (struct GNUNET_CURL_Job);
423  job->start_time = GNUNET_TIME_absolute_get ();
424  job->job_headers = all_headers;
425 
426  if ( (CURLE_OK !=
427  curl_easy_setopt (eh,
428  CURLOPT_PRIVATE,
429  job)) ||
430  (CURLE_OK !=
431  curl_easy_setopt (eh,
432  CURLOPT_WRITEFUNCTION,
433  &download_cb)) ||
434  (CURLE_OK !=
435  curl_easy_setopt (eh,
436  CURLOPT_WRITEDATA,
437  &job->db)) ||
438  (CURLE_OK !=
439  curl_easy_setopt (eh,
440  CURLOPT_SHARE,
441  ctx->share)) )
442  {
443  GNUNET_break (0);
444  GNUNET_free (job);
445  curl_easy_cleanup (eh);
446  return NULL;
447  }
448  if ( (CURLM_OK !=
449  curl_multi_add_handle (ctx->multi,
450  eh)) )
451  {
452  GNUNET_break (0);
453  GNUNET_free (job);
454  curl_easy_cleanup (eh);
455  return NULL;
456  }
457  job->easy_handle = eh;
458  job->ctx = ctx;
459  GNUNET_CONTAINER_DLL_insert (ctx->jobs_head,
460  ctx->jobs_tail,
461  job);
462  return job;
463 }
464 
465 
466 void
468  const struct curl_slist *extra_headers)
469 {
470  struct curl_slist *all_headers = job->job_headers;
471 
472  for (const struct curl_slist *curr = extra_headers;
473  NULL != curr;
474  curr = curr->next)
475  {
476  GNUNET_assert (NULL !=
477  (all_headers = curl_slist_append (all_headers,
478  curr->data)));
479  }
480  job->job_headers = all_headers;
481 }
482 
483 
484 struct GNUNET_CURL_Job *
486  CURL *eh,
487  const struct curl_slist *job_headers,
489  void *jcc_cls)
490 {
491  struct GNUNET_CURL_Job *job;
492  struct curl_slist *all_headers;
493 
494  GNUNET_assert (NULL != jcc);
495  all_headers = setup_job_headers (ctx,
496  job_headers);
497  if (NULL == (job = setup_job (eh,
498  ctx,
499  all_headers)))
500  return NULL;
501  job->jcc_raw = jcc;
502  job->jcc_raw_cls = jcc_cls;
503  ctx->cb (ctx->cb_cls);
504  return job;
505 }
506 
507 
508 struct GNUNET_CURL_Job *
510  CURL *eh,
511  const struct curl_slist *job_headers,
513  void *jcc_cls)
514 {
515  struct GNUNET_CURL_Job *job;
516  struct curl_slist *all_headers;
517 
518  GNUNET_assert (NULL != jcc);
519  if ( (NULL != ctx->userpass) &&
520  (0 != curl_easy_setopt (eh,
521  CURLOPT_USERPWD,
522  ctx->userpass)) )
523  return NULL;
524  if ( (NULL != ctx->certfile) &&
525  (0 != curl_easy_setopt (eh,
526  CURLOPT_SSLCERT,
527  ctx->certfile)) )
528  return NULL;
529  if ( (NULL != ctx->certtype) &&
530  (0 != curl_easy_setopt (eh,
531  CURLOPT_SSLCERTTYPE,
532  ctx->certtype)) )
533  return NULL;
534  if ( (NULL != ctx->keyfile) &&
535  (0 != curl_easy_setopt (eh,
536  CURLOPT_SSLKEY,
537  ctx->keyfile)) )
538  return NULL;
539  if ( (NULL != ctx->keypass) &&
540  (0 != curl_easy_setopt (eh,
541  CURLOPT_KEYPASSWD,
542  ctx->keypass)) )
543  return NULL;
544 
545  all_headers = setup_job_headers (ctx,
546  job_headers);
547  if (NULL == (job = setup_job (eh,
548  ctx,
549  all_headers)))
550  return NULL;
551 
552  job->jcc = jcc;
553  job->jcc_cls = jcc_cls;
554  ctx->cb (ctx->cb_cls);
555  return job;
556 }
557 
558 
559 struct GNUNET_CURL_Job *
561  CURL *eh,
563  void *jcc_cls)
564 {
565  struct GNUNET_CURL_Job *job;
566  struct curl_slist *job_headers = NULL;
567 
568  GNUNET_assert (NULL != (job_headers =
569  curl_slist_append (NULL,
570  "Content-Type: application/json")));
572  eh,
573  job_headers,
574  jcc,
575  jcc_cls);
576  curl_slist_free_all (job_headers);
577  return job;
578 }
579 
580 
581 struct GNUNET_CURL_Job *
583  CURL *eh,
585  void *jcc_cls)
586 {
587  return GNUNET_CURL_job_add2 (ctx,
588  eh,
589  NULL,
590  jcc,
591  jcc_cls);
592 }
593 
594 
595 void
597 {
598  struct GNUNET_CURL_Context *ctx = job->ctx;
599 
600  GNUNET_CONTAINER_DLL_remove (ctx->jobs_head,
601  ctx->jobs_tail,
602  job);
603  GNUNET_break (CURLM_OK ==
604  curl_multi_remove_handle (ctx->multi,
605  job->easy_handle));
606  curl_easy_cleanup (job->easy_handle);
607  GNUNET_free (job->db.buf);
608  curl_slist_free_all (job->job_headers);
609  ctx->cb (ctx->cb_cls);
610  GNUNET_free (job);
611 }
612 
613 
620 static bool
621 is_json (const char *ct)
622 {
623  const char *semi;
624 
625  /* check for "application/json" exact match */
626  if (0 == strcasecmp (ct,
627  "application/json"))
628  return true;
629  /* check for "application/json;[ANYTHING]" */
630  semi = strchr (ct,
631  ';');
632  /* also allow "application/json [ANYTHING]" (note the space!) */
633  if (NULL == semi)
634  semi = strchr (ct,
635  ' ');
636  if (NULL == semi)
637  return false; /* no delimiter we accept, forget it */
638  if (semi - ct != strlen ("application/json"))
639  return false; /* delimiter past desired length, forget it */
640  if (0 == strncasecmp (ct,
641  "application/json",
642  strlen ("application/json")))
643  return true; /* OK */
644  return false;
645 }
646 
647 
648 void *
650  CURL *eh,
651  long *response_code)
652 {
653  json_t *json;
654  json_error_t error;
655  char *ct;
656 
657 #if DEBUG
659  "Downloaded body: %.*s\n",
660  (int) db->buf_size,
661  (char *) db->buf);
662 #endif
663  if (CURLE_OK !=
664  curl_easy_getinfo (eh,
665  CURLINFO_RESPONSE_CODE,
666  response_code))
667  {
668  /* unexpected error... */
669  GNUNET_break (0);
670  *response_code = 0;
671  }
672  if ((CURLE_OK !=
673  curl_easy_getinfo (eh,
674  CURLINFO_CONTENT_TYPE,
675  &ct)) ||
676  (NULL == ct) ||
677  (! is_json (ct)))
678  {
679  /* No content type or explicitly not JSON, refuse to parse
680  (but keep response code) */
681  if (0 != db->buf_size)
683  "Did NOT detect response `%.*s' as JSON\n",
684  (int) db->buf_size,
685  (const char *) db->buf);
686  return NULL;
687  }
688  if (MHD_HTTP_NO_CONTENT == *response_code)
689  return NULL;
690  if (0 == *response_code)
691  {
692  char *url;
693 
694  if (CURLE_OK !=
695  curl_easy_getinfo (eh,
696  CURLINFO_EFFECTIVE_URL,
697  &url))
698  url = "<unknown URL>";
700  "Failed to download response from `%s': \n",
701  url);
702  return NULL;
703  }
704  json = NULL;
705  if (0 == db->eno)
706  {
707  json = json_loadb (db->buf,
708  db->buf_size,
709  JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK,
710  &error);
711  if (NULL == json)
712  {
713  JSON_WARN (error);
714  *response_code = 0;
715  }
716  }
717  GNUNET_free (db->buf);
718  db->buf = NULL;
719  db->buf_size = 0;
720  return json;
721 }
722 
723 
726  const char *header)
727 {
728  ctx->common_headers = curl_slist_append (ctx->common_headers,
729  header);
730  if (NULL == ctx->common_headers)
731  return GNUNET_SYSERR;
732 
733  return GNUNET_OK;
734 }
735 
736 
737 void
741 {
742  CURLMsg *cmsg;
743  int n_running;
744  int n_completed;
745 
746  (void) curl_multi_perform (ctx->multi,
747  &n_running);
748  while (NULL != (cmsg = curl_multi_info_read (ctx->multi,
749  &n_completed)))
750  {
751  struct GNUNET_CURL_Job *job;
753  long response_code;
754  void *response;
755 
756  /* Only documented return value is CURLMSG_DONE */
757  GNUNET_break (CURLMSG_DONE == cmsg->msg);
758  GNUNET_assert (CURLE_OK ==
759  curl_easy_getinfo (cmsg->easy_handle,
760  CURLINFO_PRIVATE,
761  (char **) &job));
762  GNUNET_assert (job->ctx == ctx);
763  response_code = 0;
765  if (NULL != job->jcc_raw)
766  {
767  /* RAW mode, no parsing */
768  GNUNET_break (CURLE_OK ==
769  curl_easy_getinfo (job->easy_handle,
770  CURLINFO_RESPONSE_CODE,
771  &response_code));
772  job->jcc_raw (job->jcc_raw_cls,
773  response_code,
774  job->db.buf,
775  job->db.buf_size);
776  }
777  else
778  {
779  /* to be parsed via 'rp' */
780  response = rp (&job->db,
781  job->easy_handle,
782  &response_code);
783  job->jcc (job->jcc_cls,
784  response_code,
785  response);
786  rc (response);
787  }
788  {
789  char *url = NULL;
790 
791  if (CURLE_UNKNOWN_OPTION ==
792  curl_easy_getinfo (job->easy_handle,
793  CURLINFO_EFFECTIVE_URL,
794  &url))
795  url = "<unknown>";
797  "HTTP request for `%s' finished with %u after %s\n",
798  url,
799  (unsigned int) response_code,
801  true));
802  /* Note: we MUST NOT free 'url' here */
803  }
805  }
806 }
807 
808 
809 void
811 {
814  (GNUNET_CURL_ResponseCleaner) & json_decref);
815 }
816 
817 
818 void
820  fd_set *read_fd_set,
821  fd_set *write_fd_set,
822  fd_set *except_fd_set,
823  int *max_fd,
824  long *timeout)
825 {
826  long to;
827  int m;
828 
829  m = -1;
830  GNUNET_assert (CURLM_OK ==
831  curl_multi_fdset (ctx->multi,
832  read_fd_set,
833  write_fd_set,
834  except_fd_set,
835  &m));
836  to = *timeout;
837  *max_fd = GNUNET_MAX (m, *max_fd);
838  GNUNET_assert (CURLM_OK ==
839  curl_multi_timeout (ctx->multi,
840  &to));
841 
842  /* Only if what we got back from curl is smaller than what we
843  already had (-1 == infinity!), then update timeout */
844  if ((to < *timeout) && (-1 != to))
845  *timeout = to;
846  if ((-1 == (*timeout)) && (NULL != ctx->jobs_head))
847  *timeout = to;
848 }
849 
850 
851 void
853 {
854  /* all jobs must have been cancelled at this time, assert this */
855  GNUNET_assert (NULL == ctx->jobs_head);
856  curl_share_cleanup (ctx->share);
857  curl_multi_cleanup (ctx->multi);
858  curl_slist_free_all (ctx->common_headers);
859  GNUNET_free (ctx->userpass);
860  GNUNET_free (ctx->certtype);
861  GNUNET_free (ctx->certfile);
862  GNUNET_free (ctx->keyfile);
863  GNUNET_free (ctx->keypass);
864  GNUNET_free (ctx);
865 }
866 
867 
871 __attribute__ ((constructor)) void
872 GNUNET_CURL_constructor__ (void)
873 {
874  CURLcode ret;
875 
876  if (CURLE_OK != (ret = curl_global_init (CURL_GLOBAL_DEFAULT)))
877  {
879  "curl_global_init",
880  ret);
881  curl_fail = 1;
882  }
883 }
884 
885 
889 __attribute__ ((destructor)) void
890 GNUNET_CURL_destructor__ (void)
891 {
892  if (curl_fail)
893  return;
894  curl_global_cleanup ();
895 }
896 
897 
898 /* end of curl.c */
__attribute__((constructor))
Initial global setup logic, specifically runs the Curl setup.
Definition: curl.c:871
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:351
#define CURL_STRERROR(type, function, code)
Log error related to CURL operations.
Definition: curl.c:47
static bool is_json(const char *ct)
Test if the given content type ct is JSON.
Definition: curl.c:621
#define JSON_WARN(error)
Print JSON parsing related error information.
Definition: curl.c:58
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:314
static int curl_fail
Failsafe flag.
Definition: curl.c:71
void * GNUNET_CURL_download_get_result_(struct GNUNET_CURL_DownloadBuffer *db, CURL *eh, long *response_code)
Definition: curl.c:649
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:406
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gnunet-abd.c:61
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:104
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 char * rp
Relying party.
static struct GNUNET_TIME_Relative duration
How long do we run the test?
static struct GNUNET_FS_DirectoryBuilder * db
Definition: gnunet-search.c:97
static char buf[2048]
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
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:224
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.
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:819
void GNUNET_CURL_fini(struct GNUNET_CURL_Context *ctx)
Cleanup library initialisation resources.
Definition: curl.c:852
void(* GNUNET_CURL_ResponseCleaner)(void *response)
Deallocate the response.
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:509
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:467
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:582
struct GNUNET_CURL_Context * GNUNET_CURL_init(GNUNET_CURL_RescheduleCallback cb, void *cb_cls)
Initialise this library.
Definition: curl.c:246
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:738
void GNUNET_CURL_job_cancel(struct GNUNET_CURL_Job *job)
Cancel a job.
Definition: curl.c:596
void GNUNET_CURL_perform(struct GNUNET_CURL_Context *ctx)
Run the main event loop for the CURL interaction.
Definition: curl.c:810
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:560
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:214
int 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:289
void *(* GNUNET_CURL_RawParser)(struct GNUNET_CURL_DownloadBuffer *db, CURL *eh, long *response_code)
Parses the raw response we got from the Web server.
enum GNUNET_GenericReturnValue GNUNET_CURL_append_header(struct GNUNET_CURL_Context *ctx, const char *header)
Add custom request header.
Definition: curl.c:725
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...
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:485
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:281
#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)
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.
@ 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:763
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:436
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
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
@ MHD_HTTP_NO_CONTENT
No Content [RFC7231, Section 6.3.5].
static unsigned int size
Size of the "table".
Definition: peer.c:68
static enum GNUNET_NetworkType scope
Which network scope do we belong to?
Identifier for an asynchronous execution context.
Saved async scope identifier or root scope.
Context.
Definition: curl.c:140
char * userpass
USERNAME:PASSWORD to use for client-authentication with all requests of this context,...
Definition: curl.c:187
char * keypass
Passphrase to decrypt keyfile, or NULL.
Definition: curl.c:208
void * cb_cls
Closure for cb.
Definition: curl.c:181
char * certtype
Type of the TLS client certificate used, or NULL.
Definition: curl.c:192
char * keyfile
File with the private key to authenticate the TLS client, or NULL.
Definition: curl.c:203
struct curl_slist * common_headers
Headers common for all requests in the context.
Definition: curl.c:164
CURLSH * share
Curl share handle.
Definition: curl.c:149
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:170
CURLM * multi
Curl multi handle.
Definition: curl.c:144
GNUNET_CURL_RescheduleCallback cb
Function we need to call whenever the event loop's socket set changed.
Definition: curl.c:176
struct GNUNET_CURL_Job * jobs_head
We keep jobs in a DLL.
Definition: curl.c:154
char * certfile
File with the TLS client certificate, or NULL.
Definition: curl.c:197
struct GNUNET_CURL_Job * jobs_tail
We keep jobs in a DLL.
Definition: curl.c:159
Buffer data structure we use to buffer the HTTP download before giving it to the JSON parser.
Jobs are CURL requests running within a struct GNUNET_CURL_Context.
Definition: curl.c:77
struct GNUNET_CURL_Job * prev
We keep jobs in a DLL.
Definition: curl.c:86
CURL * easy_handle
Easy handle of the job.
Definition: curl.c:91
struct curl_slist * job_headers
Headers used for this job, the list needs to be freed after the job has finished.
Definition: curl.c:127
void * jcc_raw_cls
Closure for jcc_raw.
Definition: curl.c:116
struct GNUNET_CURL_Context * ctx
Context this job runs in.
Definition: curl.c:96
struct GNUNET_TIME_Absolute start_time
When did we start the job?
Definition: curl.c:132
GNUNET_CURL_JobCompletionCallback jcc
Function to call upon completion.
Definition: curl.c:101
void * jcc_cls
Closure for jcc.
Definition: curl.c:106
struct GNUNET_CURL_DownloadBuffer db
Buffer for response received from CURL.
Definition: curl.c:121
struct GNUNET_CURL_Job * next
We keep jobs in a DLL.
Definition: curl.c:81
GNUNET_CURL_RawJobCompletionCallback jcc_raw
Function to call upon completion.
Definition: curl.c:111
Time for absolute times used by GNUnet, in microseconds.
Time for relative time used by GNUnet, in microseconds.