GNUnet  0.11.x
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 "gnunet_curl_lib.h"
29 
30 #if ENABLE_BENCHMARK
31 #include "../util/benchmark.h"
32 #endif
33 
34 
42 #define CURL_STRERROR(type, function, code) \
43  GNUNET_log (type, \
44  "Curl function `%s' has failed at `%s:%d' with error: %s\n", \
45  function, \
46  __FILE__, \
47  __LINE__, \
48  curl_easy_strerror (code));
49 
53 #define JSON_WARN(error) \
54  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, \
55  "JSON parsing failed at %s:%u: %s (%s)\n", \
56  __FILE__, \
57  __LINE__, \
58  error.text, \
59  error.source)
60 
61 
66 static int curl_fail;
67 
72 {
77 
82 
86  CURL *easy_handle;
87 
92 
97 
101  void *jcc_cls;
102 
107 
111  void *jcc_raw_cls;
112 
117 
122  struct curl_slist *job_headers;
123 };
124 
125 
130 {
134  CURLM *multi;
135 
139  CURLSH *share;
140 
145 
150 
154  struct curl_slist *common_headers;
155 
161 
167 
171  void *cb_cls;
172 };
173 
174 
183 struct GNUNET_CURL_Context *
185 {
186  struct GNUNET_CURL_Context *ctx;
187  CURLM *multi;
188  CURLSH *share;
189 
190  if (curl_fail)
191  {
193  "Curl was not initialised properly\n");
194  return NULL;
195  }
196  if (NULL == (multi = curl_multi_init ()))
197  {
199  "Failed to create a Curl multi handle\n");
200  return NULL;
201  }
202  if (NULL == (share = curl_share_init ()))
203  {
205  "Failed to create a Curl share handle\n");
206  return NULL;
207  }
208  ctx = GNUNET_new (struct GNUNET_CURL_Context);
209  ctx->cb = cb;
210  ctx->cb_cls = cb_cls;
211  ctx->multi = multi;
212  ctx->share = share;
213  return ctx;
214 }
215 
216 
223 void
225  const char *header_name)
226 {
227  ctx->async_scope_id_header = header_name;
228 }
229 
230 
240 int
241 GNUNET_CURL_is_valid_scope_id (const char *scope_id)
242 {
243  if (strlen (scope_id) >= 64)
244  return GNUNET_NO;
245  for (size_t i = 0; i < strlen (scope_id); i++)
246  if (! (isalnum (scope_id[i]) || (scope_id[i] == '-')))
247  return GNUNET_NO;
248  return GNUNET_YES;
249 }
250 
251 
265 static size_t
266 download_cb (char *bufptr, size_t size, size_t nitems, void *cls)
267 {
268  struct GNUNET_CURL_DownloadBuffer *db = cls;
269  size_t msize;
270  void *buf;
271 
272  if (0 == size * nitems)
273  {
274  /* Nothing (left) to do */
275  return 0;
276  }
277  msize = size * nitems;
278  if ((msize + db->buf_size) >= GNUNET_MAX_MALLOC_CHECKED)
279  {
280  db->eno = ENOMEM;
281  return 0; /* signals an error to curl */
282  }
283  db->buf = GNUNET_realloc (db->buf, db->buf_size + msize);
284  buf = db->buf + db->buf_size;
285  GNUNET_memcpy (buf, bufptr, msize);
286  db->buf_size += msize;
287  return msize;
288 }
289 
290 
298 static struct curl_slist *
300  const struct curl_slist *job_headers)
301 {
302  struct curl_slist *all_headers = NULL;
303 
304  for (const struct curl_slist *curr = job_headers; curr != NULL;
305  curr = curr->next)
306  {
307  GNUNET_assert (NULL !=
308  (all_headers = curl_slist_append (all_headers, curr->data)));
309  }
310 
311  for (const struct curl_slist *curr = ctx->common_headers; curr != NULL;
312  curr = curr->next)
313  {
314  GNUNET_assert (NULL !=
315  (all_headers = curl_slist_append (all_headers, curr->data)));
316  }
317 
318  if (NULL != ctx->async_scope_id_header)
319  {
320  struct GNUNET_AsyncScopeSave scope;
321 
322  GNUNET_async_scope_get (&scope);
323  if (GNUNET_YES == scope.have_scope)
324  {
325  char *aid_header = NULL;
326  aid_header =
328  sizeof(
329  struct GNUNET_AsyncScopeId));
330  GNUNET_assert (NULL != aid_header);
331  GNUNET_assert (NULL != curl_slist_append (all_headers, aid_header));
332  GNUNET_free (aid_header);
333  }
334  }
335  return all_headers;
336 }
337 
338 
347 static struct GNUNET_CURL_Job *
348 setup_job (CURL *eh,
349  struct GNUNET_CURL_Context *ctx,
350  struct curl_slist *all_headers)
351 {
352  struct GNUNET_CURL_Job *job;
353 
354  if (CURLE_OK !=
355  curl_easy_setopt (eh, CURLOPT_HTTPHEADER, all_headers))
356  {
357  GNUNET_break (0);
358  curl_slist_free_all (all_headers);
359  curl_easy_cleanup (eh);
360  return NULL;
361  }
362  job = GNUNET_new (struct GNUNET_CURL_Job);
363  job->job_headers = all_headers;
364 
365  if ((CURLE_OK != curl_easy_setopt (eh, CURLOPT_PRIVATE, job)) ||
366  (CURLE_OK !=
367  curl_easy_setopt (eh, CURLOPT_WRITEFUNCTION, &download_cb)) ||
368  (CURLE_OK != curl_easy_setopt (eh, CURLOPT_WRITEDATA, &job->db)) ||
369  (CURLE_OK != curl_easy_setopt (eh, CURLOPT_SHARE, ctx->share)) ||
370  (CURLM_OK != curl_multi_add_handle (ctx->multi, eh)))
371  {
372  GNUNET_break (0);
373  GNUNET_free (job);
374  curl_easy_cleanup (eh);
375  return NULL;
376  }
377  job->easy_handle = eh;
378  job->ctx = ctx;
380  return job;
381 }
382 
383 
399 struct GNUNET_CURL_Job *
401  CURL *eh,
402  const struct curl_slist *job_headers,
404  void *jcc_cls)
405 {
406  struct GNUNET_CURL_Job *job;
407  struct curl_slist *all_headers;
408 
409  GNUNET_assert (NULL != jcc);
410  all_headers = setup_job_headers (ctx,
411  job_headers);
412  if (NULL == (job = setup_job (eh,
413  ctx,
414  all_headers)))
415  return NULL;
416  job->jcc_raw = jcc;
417  job->jcc_raw_cls = jcc_cls;
418  ctx->cb (ctx->cb_cls);
419  return job;
420 }
421 
422 
442 struct GNUNET_CURL_Job *
444  CURL *eh,
445  const struct curl_slist *job_headers,
447  void *jcc_cls)
448 {
449  struct GNUNET_CURL_Job *job;
450  struct curl_slist *all_headers;
451 
452  GNUNET_assert (NULL != jcc);
453  all_headers = setup_job_headers (ctx,
454  job_headers);
455  if (NULL == (job = setup_job (eh,
456  ctx,
457  all_headers)))
458  return NULL;
459 
460  job->jcc = jcc;
461  job->jcc_cls = jcc_cls;
462  ctx->cb (ctx->cb_cls);
463  return job;
464 }
465 
466 
483 struct GNUNET_CURL_Job *
485  CURL *eh,
486  int add_json,
488  void *jcc_cls)
489 {
490  struct GNUNET_CURL_Job *job;
491  struct curl_slist *job_headers = NULL;
492 
493  if (GNUNET_YES == add_json)
494  {
495  GNUNET_assert (
496  NULL != (job_headers =
497  curl_slist_append (NULL, "Content-Type: application/json")));
498  }
499 
500  job = GNUNET_CURL_job_add2 (ctx, eh, job_headers, jcc, jcc_cls);
501  curl_slist_free_all (job_headers);
502  return job;
503 }
504 
505 
512 void
514 {
515  struct GNUNET_CURL_Context *ctx = job->ctx;
516 
518  GNUNET_break (CURLM_OK ==
519  curl_multi_remove_handle (ctx->multi, job->easy_handle));
520  curl_easy_cleanup (job->easy_handle);
521  GNUNET_free_non_null (job->db.buf);
522  curl_slist_free_all (job->job_headers);
523  ctx->cb (ctx->cb_cls);
524  GNUNET_free (job);
525 }
526 
527 
546 void *
548  CURL *eh,
549  long *response_code)
550 {
551  json_t *json;
552  json_error_t error;
553  char *ct;
554 
556  "Downloaded body: %.*s\n",
557  (int) db->buf_size,
558  (char *) db->buf);
559 
560  if ((CURLE_OK !=
561  curl_easy_getinfo (eh,
562  CURLINFO_CONTENT_TYPE,
563  &ct)) ||
564  (NULL == ct) ||
565  (0 != strcasecmp (ct,
566  "application/json")))
567  {
568  /* No content type or explicitly not JSON, refuse to parse
569  (but keep response code) */
570  if (CURLE_OK !=
571  curl_easy_getinfo (eh,
572  CURLINFO_RESPONSE_CODE,
573  response_code))
574  {
575  /* unexpected error... */
576  GNUNET_break (0);
577  *response_code = 0;
578  }
579  if (0 != db->buf_size)
581  "Did NOT detect response `%.*s' as JSON\n",
582  (int) db->buf_size,
583  (const char *) db->buf);
584  return NULL;
585  }
586  json = NULL;
587  if (0 == db->eno)
588  {
589  json = json_loadb (db->buf,
590  db->buf_size,
591  JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK,
592  &error);
593  if (NULL == json)
594  {
595  JSON_WARN (error);
596  *response_code = 0;
597  }
598  }
600  db->buf = NULL;
601  db->buf_size = 0;
602  if (NULL != json)
603  {
604  if (CURLE_OK !=
605  curl_easy_getinfo (eh,
606  CURLINFO_RESPONSE_CODE,
607  response_code))
608  {
609  /* unexpected error... */
610  GNUNET_break (0);
611  *response_code = 0;
612  }
613  }
614  return json;
615 }
616 
617 
625 int
626 GNUNET_CURL_append_header (struct GNUNET_CURL_Context *ctx, const char *header)
627 {
628  ctx->common_headers = curl_slist_append (ctx->common_headers, header);
629  if (NULL == ctx->common_headers)
630  return GNUNET_SYSERR;
631 
632  return GNUNET_OK;
633 }
634 
635 
636 #if ENABLE_BENCHMARK
637 static void
638 do_benchmark (CURLMsg *cmsg)
639 {
640  char *url = NULL;
641  double total_as_double = 0;
642  struct GNUNET_TIME_Relative total;
643  struct UrlRequestData *urd;
644  /* Some care required, as curl is using data types (long vs curl_off_t vs
645  * double) inconsistently to store byte count. */
646  curl_off_t size_curl = 0;
647  long size_long = 0;
648  uint64_t bytes_sent = 0;
649  uint64_t bytes_received = 0;
650 
651  GNUNET_break (CURLE_OK == curl_easy_getinfo (cmsg->easy_handle,
652  CURLINFO_TOTAL_TIME,
653  &total_as_double));
654  total.rel_value_us = total_as_double * 1000 * 1000;
655 
656  GNUNET_break (CURLE_OK == curl_easy_getinfo (cmsg->easy_handle,
657  CURLINFO_EFFECTIVE_URL,
658  &url));
659 
660  /* HEADER_SIZE + SIZE_DOWNLOAD_T is hopefully the total
661  number of bytes received, not clear from curl docs. */
662 
663  GNUNET_break (CURLE_OK == curl_easy_getinfo (cmsg->easy_handle,
664  CURLINFO_HEADER_SIZE,
665  &size_long));
666  bytes_received += size_long;
667 
668  GNUNET_break (CURLE_OK == curl_easy_getinfo (cmsg->easy_handle,
669  CURLINFO_SIZE_DOWNLOAD_T,
670  &size_curl));
671  bytes_received += size_curl;
672 
673  /* REQUEST_SIZE + SIZE_UPLOAD_T is hopefully the total number of bytes
674  sent, again docs are not completely clear. */
675 
676  GNUNET_break (CURLE_OK == curl_easy_getinfo (cmsg->easy_handle,
677  CURLINFO_REQUEST_SIZE,
678  &size_long));
679  bytes_sent += size_long;
680 
681  /* We obtain this value to check an invariant, but never use it otherwise. */
682  GNUNET_break (CURLE_OK == curl_easy_getinfo (cmsg->easy_handle,
683  CURLINFO_SIZE_UPLOAD_T,
684  &size_curl));
685 
686  /* CURLINFO_SIZE_UPLOAD_T <= CURLINFO_REQUEST_SIZE should
687  be an invariant.
688  As verified with
689  curl -w "foo%{size_request} -XPOST --data "ABC" $URL
690  the CURLINFO_REQUEST_SIZE should be the whole size of the request
691  including headers and body.
692  */GNUNET_break (size_curl <= size_long);
693 
694  urd = get_url_benchmark_data (url, (unsigned int) response_code);
695  urd->count++;
696  urd->time = GNUNET_TIME_relative_add (urd->time, total);
697  urd->time_max = GNUNET_TIME_relative_max (total, urd->time_max);
698  urd->bytes_sent += bytes_sent;
700 }
701 
702 
703 #endif
704 
705 
714 void
718 {
719  CURLMsg *cmsg;
720  int n_running;
721  int n_completed;
722 
723  (void) curl_multi_perform (ctx->multi,
724  &n_running);
725  while (NULL != (cmsg = curl_multi_info_read (ctx->multi, &n_completed)))
726  {
727  struct GNUNET_CURL_Job *job;
728  long response_code;
729  void *response;
730 
731  /* Only documented return value is CURLMSG_DONE */
732  GNUNET_break (CURLMSG_DONE == cmsg->msg);
733  GNUNET_assert (CURLE_OK == curl_easy_getinfo (cmsg->easy_handle,
734  CURLINFO_PRIVATE,
735  (char **) &job));
736  GNUNET_assert (job->ctx == ctx);
737  response_code = 0;
738  if (NULL != job->jcc_raw)
739  {
740  /* RAW mode, no parsing */
741  GNUNET_break (CURLE_OK ==
742  curl_easy_getinfo (job->easy_handle,
743  CURLINFO_RESPONSE_CODE,
744  &response_code));
745  job->jcc_raw (job->jcc_raw_cls,
746  response_code,
747  job->db.buf,
748  job->db.buf_size);
749  }
750  else
751  {
752  /* to be parsed via 'rp' */
753  response = rp (&job->db,
754  job->easy_handle,
755  &response_code);
756  job->jcc (job->jcc_cls,
757  response_code,
758  response);
759  rc (response);
760  }
761 #if ENABLE_BENCHMARK
762  do_benchmark (cmsg);
763 #endif
765  }
766 }
767 
768 
774 void
776 {
779  (GNUNET_CURL_ResponseCleaner) & json_decref);
780 }
781 
782 
811 void
813  fd_set *read_fd_set,
814  fd_set *write_fd_set,
815  fd_set *except_fd_set,
816  int *max_fd,
817  long *timeout)
818 {
819  long to;
820  int m;
821 
822  m = -1;
823  GNUNET_assert (CURLM_OK == curl_multi_fdset (ctx->multi,
824  read_fd_set,
825  write_fd_set,
826  except_fd_set,
827  &m));
828  to = *timeout;
829  *max_fd = GNUNET_MAX (m, *max_fd);
830  GNUNET_assert (CURLM_OK == curl_multi_timeout (ctx->multi, &to));
831 
832  /* Only if what we got back from curl is smaller than what we
833  already had (-1 == infinity!), then update timeout */
834  if ((to < *timeout) && (-1 != to))
835  *timeout = to;
836  if ((-1 == (*timeout)) && (NULL != ctx->jobs_head))
837  *timeout = to;
838 }
839 
840 
848 void
850 {
851  /* all jobs must have been cancelled at this time, assert this */
852  GNUNET_assert (NULL == ctx->jobs_head);
853  curl_share_cleanup (ctx->share);
854  curl_multi_cleanup (ctx->multi);
855  curl_slist_free_all (ctx->common_headers);
856  GNUNET_free (ctx);
857 }
858 
859 
863 __attribute__ ((constructor)) void
864 GNUNET_CURL_constructor__ (void)
865 {
866  CURLcode ret;
867 
868  if (CURLE_OK != (ret = curl_global_init (CURL_GLOBAL_DEFAULT)))
869  {
870  CURL_STRERROR (GNUNET_ERROR_TYPE_ERROR, "curl_global_init", ret);
871  curl_fail = 1;
872  }
873 }
874 
875 
879 __attribute__ ((destructor)) void
880 GNUNET_CURL_destructor__ (void)
881 {
882  if (curl_fail)
883  return;
884  curl_global_cleanup ();
885 }
886 
887 
888 /* end of curl.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define CURL_STRERROR(type, function, code)
Log error related to CURL operations.
Definition: curl.c:42
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:443
uint64_t rel_value_us
The actual value.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
library to make it easy to download JSON replies over HTTP
struct GNUNET_TIME_Relative GNUNET_TIME_relative_max(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the maximum of two relative time values.
Definition: time.c:287
struct GNUNET_CURL_Job * prev
We keep jobs in a DLL.
Definition: curl.c:81
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
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:241
int GNUNET_CURL_append_header(struct GNUNET_CURL_Context *ctx, const char *header)
Add custom request header.
Definition: curl.c:626
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
void GNUNET_CURL_fini(struct GNUNET_CURL_Context *ctx)
Cleanup library initialisation resources.
Definition: curl.c:849
#define GNUNET_NO
Definition: gnunet_common.h:86
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:83
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
Identifier for an asynchronous execution context.
Struct for benchmark data for one URL.
Definition: benchmark.h:65
GNUNET_CURL_RescheduleCallback cb
Function we need to call whenever the event loop&#39;s socket set changed.
Definition: curl.c:166
struct GNUNET_TIME_Relative time_max
Slowest time to response.
Definition: benchmark.h:100
void(* GNUNET_CURL_JobCompletionCallback)(void *cls, long response_code, const void *response)
Function to call upon completion of a job.
void GNUNET_CURL_job_cancel(struct GNUNET_CURL_Job *job)
Cancel a job.
Definition: curl.c:513
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
uint64_t count
How often was the URL requested?
Definition: benchmark.h:80
void * jcc_cls
Closure for jcc.
Definition: curl.c:101
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:104
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:400
void *(* GNUNET_CURL_RawParser)(struct GNUNET_CURL_DownloadBuffer *db, CURL *eh, long *response_code)
Parses the raw response we got from the Web server.
GNUNET_CURL_JobCompletionCallback jcc
Function to call upon completion.
Definition: curl.c:96
struct GNUNET_CURL_Job * jobs_head
We keep jobs in a DLL.
Definition: curl.c:144
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gnunet-abd.c:61
#define GNUNET_realloc(ptr, size)
Wrapper around realloc.
struct GNUNET_CURL_Job * next
We keep jobs in a DLL.
Definition: curl.c:76
#define JSON_WARN(error)
Print JSON parsing related error information.
Definition: curl.c:53
#define GNUNET_MAX(a, b)
Definition: gnunet_common.h:90
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:299
static CURLM * multi
Current multi-CURL handle.
CURLSH * share
Curl share handle.
Definition: curl.c:139
static char buf[2048]
static int curl_fail
Failsafe flag.
Definition: curl.c:66
Context.
Definition: curl.c:129
uint64_t bytes_sent
How many bytes were sent in total to request the URL.
Definition: benchmark.h:85
struct GNUNET_TIME_Relative time
Total time spent requesting this URL.
Definition: benchmark.h:95
void GNUNET_async_scope_get(struct GNUNET_AsyncScopeSave *scope_ret)
Get the current async scope.
GNUNET_CURL_RawJobCompletionCallback jcc_raw
Function to call upon completion.
Definition: curl.c:106
void(* GNUNET_CURL_ResponseCleaner)(void *response)
Deallocate the response.
__attribute__((constructor))
Initial global setup logic, specifically runs the Curl setup.
Definition: curl.c:863
CURLM * multi
Curl multi handle.
Definition: curl.c:134
#define GNUNET_SYSERR
Definition: gnunet_common.h:84
static unsigned int size
Size of the "table".
Definition: peer.c:67
uint64_t bytes_received
How many bytes were received in total as response to requesting this URL.
Definition: benchmark.h:90
int have_scope
GNUNET_YES unless this saved scope is the unnamed root scope.
Saved async scope identifier or root scope.
CURL * easy_handle
Easy handle of the job.
Definition: curl.c:86
#define GNUNET_MAX_MALLOC_CHECKED
Maximum allocation with GNUNET_malloc macro.
static struct GNUNET_SCHEDULER_Task * job
Task for main job.
Definition: gnunet-cadet.c:137
struct GNUNET_TIME_Relative GNUNET_TIME_relative_add(struct GNUNET_TIME_Relative a1, struct GNUNET_TIME_Relative a2)
Add relative times together.
Definition: time.c:579
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:812
Buffer data structure we use to buffer the HTTP download before giving it to the JSON parser...
struct GNUNET_AsyncScopeId scope_id
Saved scope.
void GNUNET_CURL_perform(struct GNUNET_CURL_Context *ctx)
Run the main event loop for the HTTP interaction.
Definition: curl.c:775
void * buf
Download buffer.
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 * cb_cls
Closure for cb.
Definition: curl.c:171
Jobs are CURL requests running within a struct GNUNET_CURL_Context.
Definition: curl.c:71
#define GNUNET_log(kind,...)
struct GNUNET_CURL_Context * GNUNET_CURL_init(GNUNET_CURL_RescheduleCallback cb, void *cb_cls)
Initialise this library.
Definition: curl.c:184
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:160
static char * rp
Relying party.
struct GNUNET_CURL_Job * jobs_tail
We keep jobs in a DLL.
Definition: curl.c:149
static struct MHD_Response * response
Our canonical response.
#define GNUNET_YES
Definition: gnunet_common.h:85
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.
struct GNUNET_CURL_DownloadBuffer db
Buffer for response received from CURL.
Definition: curl.c:116
struct UrlRequestData * get_url_benchmark_data(char *url, unsigned int status)
Get benchmark data for a URL.
Definition: benchmark.c:241
struct GNUNET_CURL_Job * GNUNET_CURL_job_add(struct GNUNET_CURL_Context *ctx, CURL *eh, int add_json, 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:484
char * GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
Return the base32crockford encoding of the given buffer.
Definition: strings.c:923
size_t buf_size
The size of the download buffer.
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:715
struct curl_slist * job_headers
Headers used for this job, the list needs to be freed after the job has finished. ...
Definition: curl.c:122
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:224
void * jcc_raw_cls
Closure for jcc_raw.
Definition: curl.c:111
#define GNUNET_free(ptr)
Wrapper around free.
struct GNUNET_CURL_Context * ctx
Context this job runs in.
Definition: curl.c:91
struct curl_slist * common_headers
Headers common for all requests in the context.
Definition: curl.c:154
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:348
Time for relative time used by GNUnet, in microseconds.
int eno
Error code (based on libc errno) if we failed to download (i.e.
void * GNUNET_CURL_download_get_result_(struct GNUNET_CURL_DownloadBuffer *db, CURL *eh, long *response_code)
Obtain information about the final result about the HTTP download.
Definition: curl.c:547
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:266