GNUnet  0.19.3
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 };
129 
130 
135 {
139  CURLM *multi;
140 
144  CURLSH *share;
145 
150 
155 
159  struct curl_slist *common_headers;
160 
166 
172 
176  void *cb_cls;
177 
182  char *userpass;
183 
187  char *certtype;
188 
192  char *certfile;
193 
198  char *keyfile;
199 
203  char *keypass;
204 
205 };
206 
207 
208 void
210  const char *userpass)
211 {
212  GNUNET_free (ctx->userpass);
213  if (NULL != userpass)
214  ctx->userpass = GNUNET_strdup (userpass);
215 }
216 
217 
218 void
220  const char *certtype,
221  const char *certfile,
222  const char *keyfile,
223  const char *keypass)
224 {
225  GNUNET_free (ctx->certtype);
226  GNUNET_free (ctx->certfile);
227  GNUNET_free (ctx->keyfile);
228  GNUNET_free (ctx->keypass);
229  if (NULL != certtype)
230  ctx->certtype = GNUNET_strdup (certtype);
231  if (NULL != certfile)
232  ctx->certfile = GNUNET_strdup (certfile);
233  if (NULL != keyfile)
234  ctx->certtype = GNUNET_strdup (keyfile);
235  if (NULL != keypass)
236  ctx->certtype = GNUNET_strdup (keypass);
237 }
238 
239 
240 struct GNUNET_CURL_Context *
242  void *cb_cls)
243 {
244  struct GNUNET_CURL_Context *ctx;
245  CURLM *multi;
246  CURLSH *share;
247 
248  if (curl_fail)
249  {
251  "Curl was not initialised properly\n");
252  return NULL;
253  }
254  if (NULL == (multi = curl_multi_init ()))
255  {
257  "Failed to create a Curl multi handle\n");
258  return NULL;
259  }
260  if (NULL == (share = curl_share_init ()))
261  {
263  "Failed to create a Curl share handle\n");
264  return NULL;
265  }
267  ctx->cb = cb;
268  ctx->cb_cls = cb_cls;
269  ctx->multi = multi;
270  ctx->share = share;
271  return ctx;
272 }
273 
274 
275 void
277  const char *header_name)
278 {
279  ctx->async_scope_id_header = header_name;
280 }
281 
282 
283 int
284 GNUNET_CURL_is_valid_scope_id (const char *scope_id)
285 {
286  if (strlen (scope_id) >= 64)
287  return GNUNET_NO;
288  for (size_t i = 0; i < strlen (scope_id); i++)
289  if (! (isalnum (scope_id[i]) || (scope_id[i] == '-')))
290  return GNUNET_NO;
291  return GNUNET_YES;
292 }
293 
294 
308 static size_t
309 download_cb (char *bufptr,
310  size_t size,
311  size_t nitems,
312  void *cls)
313 {
314  struct GNUNET_CURL_DownloadBuffer *db = cls;
315  size_t msize;
316  void *buf;
317 
318  if (0 == size * nitems)
319  {
320  /* Nothing (left) to do */
321  return 0;
322  }
323  msize = size * nitems;
324  if ((msize + db->buf_size) >= GNUNET_MAX_MALLOC_CHECKED)
325  {
326  db->eno = ENOMEM;
327  return 0; /* signals an error to curl */
328  }
329  db->buf = GNUNET_realloc (db->buf,
330  db->buf_size + msize);
331  buf = db->buf + db->buf_size;
332  GNUNET_memcpy (buf, bufptr, msize);
333  db->buf_size += msize;
334  return msize;
335 }
336 
337 
345 static struct curl_slist *
347  const struct curl_slist *job_headers)
348 {
349  struct curl_slist *all_headers = NULL;
350 
351  for (const struct curl_slist *curr = job_headers;
352  NULL != curr;
353  curr = curr->next)
354  {
355  GNUNET_assert (NULL !=
356  (all_headers = curl_slist_append (all_headers,
357  curr->data)));
358  }
359 
360  for (const struct curl_slist *curr = ctx->common_headers;
361  NULL != curr;
362  curr = curr->next)
363  {
364  GNUNET_assert (NULL !=
365  (all_headers = curl_slist_append (all_headers,
366  curr->data)));
367  }
368 
369  if (NULL != ctx->async_scope_id_header)
370  {
372 
374  if (GNUNET_YES == scope.have_scope)
375  {
376  char *aid_header;
377 
378  aid_header =
380  &scope.scope_id,
381  sizeof(struct GNUNET_AsyncScopeId));
382  GNUNET_assert (NULL != aid_header);
383  GNUNET_assert (NULL != curl_slist_append (all_headers,
384  aid_header));
385  GNUNET_free (aid_header);
386  }
387  }
388  return all_headers;
389 }
390 
391 
400 static struct GNUNET_CURL_Job *
401 setup_job (CURL *eh,
402  struct GNUNET_CURL_Context *ctx,
403  struct curl_slist *all_headers)
404 {
405  struct GNUNET_CURL_Job *job;
406 
407  if (CURLE_OK !=
408  curl_easy_setopt (eh,
409  CURLOPT_HTTPHEADER,
410  all_headers))
411  {
412  GNUNET_break (0);
413  curl_slist_free_all (all_headers);
414  curl_easy_cleanup (eh);
415  return NULL;
416  }
417  job = GNUNET_new (struct GNUNET_CURL_Job);
418  job->job_headers = all_headers;
419 
420  if ( (CURLE_OK !=
421  curl_easy_setopt (eh,
422  CURLOPT_PRIVATE,
423  job)) ||
424  (CURLE_OK !=
425  curl_easy_setopt (eh,
426  CURLOPT_WRITEFUNCTION,
427  &download_cb)) ||
428  (CURLE_OK !=
429  curl_easy_setopt (eh,
430  CURLOPT_WRITEDATA,
431  &job->db)) ||
432  (CURLE_OK !=
433  curl_easy_setopt (eh,
434  CURLOPT_SHARE,
435  ctx->share)) )
436  {
437  GNUNET_break (0);
438  GNUNET_free (job);
439  curl_easy_cleanup (eh);
440  return NULL;
441  }
442  if ( (CURLM_OK !=
443  curl_multi_add_handle (ctx->multi,
444  eh)) )
445  {
446  GNUNET_break (0);
447  GNUNET_free (job);
448  curl_easy_cleanup (eh);
449  return NULL;
450  }
451  job->easy_handle = eh;
452  job->ctx = ctx;
453  GNUNET_CONTAINER_DLL_insert (ctx->jobs_head,
454  ctx->jobs_tail,
455  job);
456  return job;
457 }
458 
459 
460 void
462  const struct curl_slist *extra_headers)
463 {
464  struct curl_slist *all_headers = job->job_headers;
465 
466  for (const struct curl_slist *curr = extra_headers;
467  NULL != curr;
468  curr = curr->next)
469  {
470  GNUNET_assert (NULL !=
471  (all_headers = curl_slist_append (all_headers,
472  curr->data)));
473  }
474  job->job_headers = all_headers;
475 }
476 
477 
478 struct GNUNET_CURL_Job *
480  CURL *eh,
481  const struct curl_slist *job_headers,
483  void *jcc_cls)
484 {
485  struct GNUNET_CURL_Job *job;
486  struct curl_slist *all_headers;
487 
488  GNUNET_assert (NULL != jcc);
489  all_headers = setup_job_headers (ctx,
490  job_headers);
491  if (NULL == (job = setup_job (eh,
492  ctx,
493  all_headers)))
494  return NULL;
495  job->jcc_raw = jcc;
496  job->jcc_raw_cls = jcc_cls;
497  ctx->cb (ctx->cb_cls);
498  return job;
499 }
500 
501 
502 struct GNUNET_CURL_Job *
504  CURL *eh,
505  const struct curl_slist *job_headers,
507  void *jcc_cls)
508 {
509  struct GNUNET_CURL_Job *job;
510  struct curl_slist *all_headers;
511 
512  GNUNET_assert (NULL != jcc);
513  if ( (NULL != ctx->userpass) &&
514  (0 != curl_easy_setopt (eh,
515  CURLOPT_USERPWD,
516  ctx->userpass)) )
517  return NULL;
518  if ( (NULL != ctx->certfile) &&
519  (0 != curl_easy_setopt (eh,
520  CURLOPT_SSLCERT,
521  ctx->certfile)) )
522  return NULL;
523  if ( (NULL != ctx->certtype) &&
524  (0 != curl_easy_setopt (eh,
525  CURLOPT_SSLCERTTYPE,
526  ctx->certtype)) )
527  return NULL;
528  if ( (NULL != ctx->keyfile) &&
529  (0 != curl_easy_setopt (eh,
530  CURLOPT_SSLKEY,
531  ctx->keyfile)) )
532  return NULL;
533  if ( (NULL != ctx->keypass) &&
534  (0 != curl_easy_setopt (eh,
535  CURLOPT_KEYPASSWD,
536  ctx->keypass)) )
537  return NULL;
538 
539  all_headers = setup_job_headers (ctx,
540  job_headers);
541  if (NULL == (job = setup_job (eh,
542  ctx,
543  all_headers)))
544  return NULL;
545 
546  job->jcc = jcc;
547  job->jcc_cls = jcc_cls;
548  ctx->cb (ctx->cb_cls);
549  return job;
550 }
551 
552 
553 struct GNUNET_CURL_Job *
555  CURL *eh,
557  void *jcc_cls)
558 {
559  struct GNUNET_CURL_Job *job;
560  struct curl_slist *job_headers = NULL;
561 
562  GNUNET_assert (NULL != (job_headers =
563  curl_slist_append (NULL,
564  "Content-Type: application/json")));
566  eh,
567  job_headers,
568  jcc,
569  jcc_cls);
570  curl_slist_free_all (job_headers);
571  return job;
572 }
573 
574 
575 struct GNUNET_CURL_Job *
577  CURL *eh,
579  void *jcc_cls)
580 {
581  return GNUNET_CURL_job_add2 (ctx,
582  eh,
583  NULL,
584  jcc,
585  jcc_cls);
586 }
587 
588 
589 void
591 {
592  struct GNUNET_CURL_Context *ctx = job->ctx;
593 
594  GNUNET_CONTAINER_DLL_remove (ctx->jobs_head,
595  ctx->jobs_tail,
596  job);
597  GNUNET_break (CURLM_OK ==
598  curl_multi_remove_handle (ctx->multi,
599  job->easy_handle));
600  curl_easy_cleanup (job->easy_handle);
601  GNUNET_free (job->db.buf);
602  curl_slist_free_all (job->job_headers);
603  ctx->cb (ctx->cb_cls);
604  GNUNET_free (job);
605 }
606 
607 
614 static bool
615 is_json (const char *ct)
616 {
617  const char *semi;
618 
619  /* check for "application/json" exact match */
620  if (0 == strcasecmp (ct,
621  "application/json"))
622  return true;
623  /* check for "application/json;[ANYTHING]" */
624  semi = strchr (ct,
625  ';');
626  /* also allow "application/json [ANYTHING]" (note the space!) */
627  if (NULL == semi)
628  semi = strchr (ct,
629  ' ');
630  if (NULL == semi)
631  return false; /* no delimiter we accept, forget it */
632  if (semi - ct != strlen ("application/json"))
633  return false; /* delimiter past desired length, forget it */
634  if (0 == strncasecmp (ct,
635  "application/json",
636  strlen ("application/json")))
637  return true; /* OK */
638  return false;
639 }
640 
641 
642 void *
644  CURL *eh,
645  long *response_code)
646 {
647  json_t *json;
648  json_error_t error;
649  char *ct;
650 
651 #if DEBUG
653  "Downloaded body: %.*s\n",
654  (int) db->buf_size,
655  (char *) db->buf);
656 #endif
657  if (CURLE_OK !=
658  curl_easy_getinfo (eh,
659  CURLINFO_RESPONSE_CODE,
660  response_code))
661  {
662  /* unexpected error... */
663  GNUNET_break (0);
664  *response_code = 0;
665  }
666  if ((CURLE_OK !=
667  curl_easy_getinfo (eh,
668  CURLINFO_CONTENT_TYPE,
669  &ct)) ||
670  (NULL == ct) ||
671  (! is_json (ct)))
672  {
673  /* No content type or explicitly not JSON, refuse to parse
674  (but keep response code) */
675  if (0 != db->buf_size)
677  "Did NOT detect response `%.*s' as JSON\n",
678  (int) db->buf_size,
679  (const char *) db->buf);
680  return NULL;
681  }
682  if (MHD_HTTP_NO_CONTENT == *response_code)
683  return NULL;
684  if (0 == *response_code)
685  {
686  char *url;
687 
688  if (CURLE_OK !=
689  curl_easy_getinfo (eh,
690  CURLINFO_EFFECTIVE_URL,
691  &url))
692  url = "<unknown URL>";
694  "Failed to download response from `%s': \n",
695  url);
696  return NULL;
697  }
698  json = NULL;
699  if (0 == db->eno)
700  {
701  json = json_loadb (db->buf,
702  db->buf_size,
703  JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK,
704  &error);
705  if (NULL == json)
706  {
707  JSON_WARN (error);
708  *response_code = 0;
709  }
710  }
711  GNUNET_free (db->buf);
712  db->buf = NULL;
713  db->buf_size = 0;
714  return json;
715 }
716 
717 
720  const char *header)
721 {
722  ctx->common_headers = curl_slist_append (ctx->common_headers,
723  header);
724  if (NULL == ctx->common_headers)
725  return GNUNET_SYSERR;
726 
727  return GNUNET_OK;
728 }
729 
730 
731 void
735 {
736  CURLMsg *cmsg;
737  int n_running;
738  int n_completed;
739 
740  (void) curl_multi_perform (ctx->multi,
741  &n_running);
742  while (NULL != (cmsg = curl_multi_info_read (ctx->multi,
743  &n_completed)))
744  {
745  struct GNUNET_CURL_Job *job;
746  long response_code;
747  void *response;
748 
749  /* Only documented return value is CURLMSG_DONE */
750  GNUNET_break (CURLMSG_DONE == cmsg->msg);
751  GNUNET_assert (CURLE_OK ==
752  curl_easy_getinfo (cmsg->easy_handle,
753  CURLINFO_PRIVATE,
754  (char **) &job));
755  GNUNET_assert (job->ctx == ctx);
756  response_code = 0;
757  if (NULL != job->jcc_raw)
758  {
759  /* RAW mode, no parsing */
760  GNUNET_break (CURLE_OK ==
761  curl_easy_getinfo (job->easy_handle,
762  CURLINFO_RESPONSE_CODE,
763  &response_code));
764  job->jcc_raw (job->jcc_raw_cls,
765  response_code,
766  job->db.buf,
767  job->db.buf_size);
768  }
769  else
770  {
771  /* to be parsed via 'rp' */
772  response = rp (&job->db,
773  job->easy_handle,
774  &response_code);
775  job->jcc (job->jcc_cls,
776  response_code,
777  response);
778  rc (response);
779  }
781  }
782 }
783 
784 
785 void
787 {
790  (GNUNET_CURL_ResponseCleaner) & json_decref);
791 }
792 
793 
794 void
796  fd_set *read_fd_set,
797  fd_set *write_fd_set,
798  fd_set *except_fd_set,
799  int *max_fd,
800  long *timeout)
801 {
802  long to;
803  int m;
804 
805  m = -1;
806  GNUNET_assert (CURLM_OK ==
807  curl_multi_fdset (ctx->multi,
808  read_fd_set,
809  write_fd_set,
810  except_fd_set,
811  &m));
812  to = *timeout;
813  *max_fd = GNUNET_MAX (m, *max_fd);
814  GNUNET_assert (CURLM_OK ==
815  curl_multi_timeout (ctx->multi,
816  &to));
817 
818  /* Only if what we got back from curl is smaller than what we
819  already had (-1 == infinity!), then update timeout */
820  if ((to < *timeout) && (-1 != to))
821  *timeout = to;
822  if ((-1 == (*timeout)) && (NULL != ctx->jobs_head))
823  *timeout = to;
824 }
825 
826 
827 void
829 {
830  /* all jobs must have been cancelled at this time, assert this */
831  GNUNET_assert (NULL == ctx->jobs_head);
832  curl_share_cleanup (ctx->share);
833  curl_multi_cleanup (ctx->multi);
834  curl_slist_free_all (ctx->common_headers);
835  GNUNET_free (ctx->userpass);
836  GNUNET_free (ctx->certtype);
837  GNUNET_free (ctx->certfile);
838  GNUNET_free (ctx->keyfile);
839  GNUNET_free (ctx->keypass);
840  GNUNET_free (ctx);
841 }
842 
843 
847 __attribute__ ((constructor)) void
848 GNUNET_CURL_constructor__ (void)
849 {
850  CURLcode ret;
851 
852  if (CURLE_OK != (ret = curl_global_init (CURL_GLOBAL_DEFAULT)))
853  {
855  "curl_global_init",
856  ret);
857  curl_fail = 1;
858  }
859 }
860 
861 
865 __attribute__ ((destructor)) void
866 GNUNET_CURL_destructor__ (void)
867 {
868  if (curl_fail)
869  return;
870  curl_global_cleanup ();
871 }
872 
873 
874 /* end of curl.c */
__attribute__((constructor))
Initial global setup logic, specifically runs the Curl setup.
Definition: curl.c:847
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:346
#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:615
#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:309
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:643
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:401
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_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:219
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:795
void GNUNET_CURL_fini(struct GNUNET_CURL_Context *ctx)
Cleanup library initialisation resources.
Definition: curl.c:828
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:503
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:461
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:576
struct GNUNET_CURL_Context * GNUNET_CURL_init(GNUNET_CURL_RescheduleCallback cb, void *cb_cls)
Initialise this library.
Definition: curl.c:241
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:732
void GNUNET_CURL_job_cancel(struct GNUNET_CURL_Job *job)
Cancel a job.
Definition: curl.c:590
void GNUNET_CURL_perform(struct GNUNET_CURL_Context *ctx)
Run the main event loop for the CURL interaction.
Definition: curl.c:786
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:554
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:209
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:284
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:719
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:479
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:276
#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
#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
@ 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:135
char * userpass
USERNAME:PASSWORD to use for client-authentication with all requests of this context,...
Definition: curl.c:182
char * keypass
Passphrase to decrypt keyfile, or NULL.
Definition: curl.c:203
void * cb_cls
Closure for cb.
Definition: curl.c:176
char * certtype
Type of the TLS client certificate used, or NULL.
Definition: curl.c:187
char * keyfile
File with the private key to authenticate the TLS client, or NULL.
Definition: curl.c:198
struct curl_slist * common_headers
Headers common for all requests in the context.
Definition: curl.c:159
CURLSH * share
Curl share handle.
Definition: curl.c:144
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:165
CURLM * multi
Curl multi handle.
Definition: curl.c:139
GNUNET_CURL_RescheduleCallback cb
Function we need to call whenever the event loop's socket set changed.
Definition: curl.c:171
struct GNUNET_CURL_Job * jobs_head
We keep jobs in a DLL.
Definition: curl.c:149
char * certfile
File with the TLS client certificate, or NULL.
Definition: curl.c:192
struct GNUNET_CURL_Job * jobs_tail
We keep jobs in a DLL.
Definition: curl.c:154
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
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