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  {
192  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Curl was not initialised properly\n");
193  return NULL;
194  }
195  if (NULL == (multi = curl_multi_init ()))
196  {
198  "Failed to create a Curl multi handle\n");
199  return NULL;
200  }
201  if (NULL == (share = curl_share_init ()))
202  {
204  "Failed to create a Curl share handle\n");
205  return NULL;
206  }
207  ctx = GNUNET_new (struct GNUNET_CURL_Context);
208  ctx->cb = cb;
209  ctx->cb_cls = cb_cls;
210  ctx->multi = multi;
211  ctx->share = share;
212  return ctx;
213 }
214 
215 
222 void
224  const char *header_name)
225 {
226  ctx->async_scope_id_header = header_name;
227 }
228 
229 
243 static size_t
244 download_cb (char *bufptr, size_t size, size_t nitems, void *cls)
245 {
246  struct GNUNET_CURL_DownloadBuffer *db = cls;
247  size_t msize;
248  void *buf;
249 
250  if (0 == size * nitems)
251  {
252  /* Nothing (left) to do */
253  return 0;
254  }
255  msize = size * nitems;
256  if ((msize + db->buf_size) >= GNUNET_MAX_MALLOC_CHECKED)
257  {
258  db->eno = ENOMEM;
259  return 0; /* signals an error to curl */
260  }
261  db->buf = GNUNET_realloc (db->buf, db->buf_size + msize);
262  buf = db->buf + db->buf_size;
263  GNUNET_memcpy (buf, bufptr, msize);
264  db->buf_size += msize;
265  return msize;
266 }
267 
268 
276 static struct curl_slist *
278  const struct curl_slist *job_headers)
279 {
280  struct curl_slist *all_headers = NULL;
281 
282  for (const struct curl_slist *curr = job_headers; curr != NULL;
283  curr = curr->next)
284  {
285  GNUNET_assert (NULL !=
286  (all_headers = curl_slist_append (all_headers, curr->data)));
287  }
288 
289  for (const struct curl_slist *curr = ctx->common_headers; curr != NULL;
290  curr = curr->next)
291  {
292  GNUNET_assert (NULL !=
293  (all_headers = curl_slist_append (all_headers, curr->data)));
294  }
295 
296  if (NULL != ctx->async_scope_id_header)
297  {
298  struct GNUNET_AsyncScopeSave scope;
299 
300  GNUNET_async_scope_get (&scope);
301  if (GNUNET_YES == scope.have_scope)
302  {
303  char *aid_header = NULL;
304  aid_header =
306  sizeof(
307  struct GNUNET_AsyncScopeId));
308  GNUNET_assert (NULL != aid_header);
309  GNUNET_assert (NULL != curl_slist_append (all_headers, aid_header));
310  GNUNET_free (aid_header);
311  }
312  }
313  return all_headers;
314 }
315 
316 
325 static struct GNUNET_CURL_Job *
326 setup_job (CURL *eh,
327  struct GNUNET_CURL_Context *ctx,
328  struct curl_slist *all_headers)
329 {
330  struct GNUNET_CURL_Job *job;
331 
332  if (CURLE_OK !=
333  curl_easy_setopt (eh, CURLOPT_HTTPHEADER, all_headers))
334  {
335  GNUNET_break (0);
336  curl_slist_free_all (all_headers);
337  curl_easy_cleanup (eh);
338  return NULL;
339  }
340  job = GNUNET_new (struct GNUNET_CURL_Job);
341  job->job_headers = all_headers;
342 
343  if ((CURLE_OK != curl_easy_setopt (eh, CURLOPT_PRIVATE, job)) ||
344  (CURLE_OK !=
345  curl_easy_setopt (eh, CURLOPT_WRITEFUNCTION, &download_cb)) ||
346  (CURLE_OK != curl_easy_setopt (eh, CURLOPT_WRITEDATA, &job->db)) ||
347  (CURLE_OK != curl_easy_setopt (eh, CURLOPT_SHARE, ctx->share)) ||
348  (CURLM_OK != curl_multi_add_handle (ctx->multi, eh)))
349  {
350  GNUNET_break (0);
351  GNUNET_free (job);
352  curl_easy_cleanup (eh);
353  return NULL;
354  }
355  job->easy_handle = eh;
356  job->ctx = ctx;
358  return job;
359 }
360 
361 
377 struct GNUNET_CURL_Job *
379  CURL *eh,
380  const struct curl_slist *job_headers,
382  void *jcc_cls)
383 {
384  struct GNUNET_CURL_Job *job;
385  struct curl_slist *all_headers;
386 
387  GNUNET_assert (NULL != jcc);
388  all_headers = setup_job_headers (ctx,
389  job_headers);
390  if (NULL == (job = setup_job (eh,
391  ctx,
392  all_headers)))
393  return NULL;
394  job->jcc_raw = jcc;
395  job->jcc_raw_cls = jcc_cls;
396  ctx->cb (ctx->cb_cls);
397  return job;
398 }
399 
400 
420 struct GNUNET_CURL_Job *
422  CURL *eh,
423  const struct curl_slist *job_headers,
425  void *jcc_cls)
426 {
427  struct GNUNET_CURL_Job *job;
428  struct curl_slist *all_headers;
429 
430  GNUNET_assert (NULL != jcc);
431  all_headers = setup_job_headers (ctx,
432  job_headers);
433  if (NULL == (job = setup_job (eh,
434  ctx,
435  all_headers)))
436  return NULL;
437 
438  job->jcc = jcc;
439  job->jcc_cls = jcc_cls;
440  ctx->cb (ctx->cb_cls);
441  return job;
442 }
443 
444 
461 struct GNUNET_CURL_Job *
463  CURL *eh,
464  int add_json,
466  void *jcc_cls)
467 {
468  struct GNUNET_CURL_Job *job;
469  struct curl_slist *job_headers = NULL;
470 
471  if (GNUNET_YES == add_json)
472  {
473  GNUNET_assert (
474  NULL != (job_headers =
475  curl_slist_append (NULL, "Content-Type: application/json")));
476  }
477 
478  job = GNUNET_CURL_job_add2 (ctx, eh, job_headers, jcc, jcc_cls);
479  curl_slist_free_all (job_headers);
480  return job;
481 }
482 
483 
490 void
492 {
493  struct GNUNET_CURL_Context *ctx = job->ctx;
494 
496  GNUNET_break (CURLM_OK ==
497  curl_multi_remove_handle (ctx->multi, job->easy_handle));
498  curl_easy_cleanup (job->easy_handle);
499  GNUNET_free_non_null (job->db.buf);
500  curl_slist_free_all (job->job_headers);
501  ctx->cb (ctx->cb_cls);
502  GNUNET_free (job);
503 }
504 
505 
524 void *
526  CURL *eh,
527  long *response_code)
528 {
529  json_t *json;
530  json_error_t error;
531  char *ct;
532 
534  "Downloaded body: %.*s\n",
535  (int) db->buf_size,
536  (char *) db->buf);
537 
538  if ((CURLE_OK !=
539  curl_easy_getinfo (eh,
540  CURLINFO_CONTENT_TYPE,
541  &ct)) ||
542  (NULL == ct) ||
543  (0 != strcasecmp (ct,
544  "application/json")))
545  {
546  /* No content type or explicitly not JSON, refuse to parse
547  (but keep response code) */
548  if (CURLE_OK !=
549  curl_easy_getinfo (eh,
550  CURLINFO_RESPONSE_CODE,
551  response_code))
552  {
553  /* unexpected error... */
554  GNUNET_break (0);
555  *response_code = 0;
556  }
557  if (0 != db->buf_size)
559  "Did NOT detect response `%.*s' as JSON\n",
560  (int) db->buf_size,
561  (const char *) db->buf);
562  return NULL;
563  }
564  json = NULL;
565  if (0 == db->eno)
566  {
567  json = json_loadb (db->buf,
568  db->buf_size,
569  JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK,
570  &error);
571  if (NULL == json)
572  {
573  JSON_WARN (error);
574  *response_code = 0;
575  }
576  }
578  db->buf = NULL;
579  db->buf_size = 0;
580  if (NULL != json)
581  {
582  if (CURLE_OK !=
583  curl_easy_getinfo (eh,
584  CURLINFO_RESPONSE_CODE,
585  response_code))
586  {
587  /* unexpected error... */
588  GNUNET_break (0);
589  *response_code = 0;
590  }
591  }
592  return json;
593 }
594 
595 
603 int
604 GNUNET_CURL_append_header (struct GNUNET_CURL_Context *ctx, const char *header)
605 {
606  ctx->common_headers = curl_slist_append (ctx->common_headers, header);
607  if (NULL == ctx->common_headers)
608  return GNUNET_SYSERR;
609 
610  return GNUNET_OK;
611 }
612 
613 
614 #if ENABLE_BENCHMARK
615 static void
616 do_benchmark (CURLMsg *cmsg)
617 {
618  char *url = NULL;
619  double total_as_double = 0;
620  struct GNUNET_TIME_Relative total;
621  struct UrlRequestData *urd;
622  /* Some care required, as curl is using data types (long vs curl_off_t vs
623  * double) inconsistently to store byte count. */
624  curl_off_t size_curl = 0;
625  long size_long = 0;
626  uint64_t bytes_sent = 0;
627  uint64_t bytes_received = 0;
628 
629  GNUNET_break (CURLE_OK == curl_easy_getinfo (cmsg->easy_handle,
630  CURLINFO_TOTAL_TIME,
631  &total_as_double));
632  total.rel_value_us = total_as_double * 1000 * 1000;
633 
634  GNUNET_break (CURLE_OK == curl_easy_getinfo (cmsg->easy_handle,
635  CURLINFO_EFFECTIVE_URL,
636  &url));
637 
638  /* HEADER_SIZE + SIZE_DOWNLOAD_T is hopefully the total
639  number of bytes received, not clear from curl docs. */
640 
641  GNUNET_break (CURLE_OK == curl_easy_getinfo (cmsg->easy_handle,
642  CURLINFO_HEADER_SIZE,
643  &size_long));
644  bytes_received += size_long;
645 
646  GNUNET_break (CURLE_OK == curl_easy_getinfo (cmsg->easy_handle,
647  CURLINFO_SIZE_DOWNLOAD_T,
648  &size_curl));
649  bytes_received += size_curl;
650 
651  /* REQUEST_SIZE + SIZE_UPLOAD_T is hopefully the total number of bytes
652  sent, again docs are not completely clear. */
653 
654  GNUNET_break (CURLE_OK == curl_easy_getinfo (cmsg->easy_handle,
655  CURLINFO_REQUEST_SIZE,
656  &size_long));
657  bytes_sent += size_long;
658 
659  /* We obtain this value to check an invariant, but never use it otherwise. */
660  GNUNET_break (CURLE_OK == curl_easy_getinfo (cmsg->easy_handle,
661  CURLINFO_SIZE_UPLOAD_T,
662  &size_curl));
663 
664  /* CURLINFO_SIZE_UPLOAD_T <= CURLINFO_REQUEST_SIZE should
665  be an invariant.
666  As verified with
667  curl -w "foo%{size_request} -XPOST --data "ABC" $URL
668  the CURLINFO_REQUEST_SIZE should be the whole size of the request
669  including headers and body.
670  */GNUNET_break (size_curl <= size_long);
671 
672  urd = get_url_benchmark_data (url, (unsigned int) response_code);
673  urd->count++;
674  urd->time = GNUNET_TIME_relative_add (urd->time, total);
675  urd->time_max = GNUNET_TIME_relative_max (total, urd->time_max);
676  urd->bytes_sent += bytes_sent;
678 }
679 
680 
681 #endif
682 
683 
692 void
696 {
697  CURLMsg *cmsg;
698  int n_running;
699  int n_completed;
700 
701  (void) curl_multi_perform (ctx->multi,
702  &n_running);
703  while (NULL != (cmsg = curl_multi_info_read (ctx->multi, &n_completed)))
704  {
705  struct GNUNET_CURL_Job *job;
706  long response_code;
707  void *response;
708 
709  /* Only documented return value is CURLMSG_DONE */
710  GNUNET_break (CURLMSG_DONE == cmsg->msg);
711  GNUNET_assert (CURLE_OK == curl_easy_getinfo (cmsg->easy_handle,
712  CURLINFO_PRIVATE,
713  (char **) &job));
714  GNUNET_assert (job->ctx == ctx);
715  response_code = 0;
716  if (NULL != job->jcc_raw)
717  {
718  /* RAW mode, no parsing */
719  GNUNET_break (CURLE_OK ==
720  curl_easy_getinfo (job->easy_handle,
721  CURLINFO_RESPONSE_CODE,
722  &response_code));
723  job->jcc_raw (job->jcc_raw_cls,
724  response_code,
725  job->db.buf,
726  job->db.buf_size);
727  }
728  else
729  {
730  /* to be parsed via 'rp' */
731  response = rp (&job->db,
732  job->easy_handle,
733  &response_code);
734  job->jcc (job->jcc_cls,
735  response_code,
736  response);
737  rc (response);
738  }
739 #if ENABLE_BENCHMARK
740  do_benchmark (cmsg);
741 #endif
743  }
744 }
745 
746 
752 void
754 {
757  (GNUNET_CURL_ResponseCleaner) & json_decref);
758 }
759 
760 
789 void
791  fd_set *read_fd_set,
792  fd_set *write_fd_set,
793  fd_set *except_fd_set,
794  int *max_fd,
795  long *timeout)
796 {
797  long to;
798  int m;
799 
800  m = -1;
801  GNUNET_assert (CURLM_OK == curl_multi_fdset (ctx->multi,
802  read_fd_set,
803  write_fd_set,
804  except_fd_set,
805  &m));
806  to = *timeout;
807  *max_fd = GNUNET_MAX (m, *max_fd);
808  GNUNET_assert (CURLM_OK == curl_multi_timeout (ctx->multi, &to));
809 
810  /* Only if what we got back from curl is smaller than what we
811  already had (-1 == infinity!), then update timeout */
812  if ((to < *timeout) && (-1 != to))
813  *timeout = to;
814  if ((-1 == (*timeout)) && (NULL != ctx->jobs_head))
815  *timeout = to;
816 }
817 
818 
826 void
828 {
829  /* all jobs must have been cancelled at this time, assert this */
830  GNUNET_assert (NULL == ctx->jobs_head);
831  curl_share_cleanup (ctx->share);
832  curl_multi_cleanup (ctx->multi);
833  curl_slist_free_all (ctx->common_headers);
834  GNUNET_free (ctx);
835 }
836 
837 
841 __attribute__ ((constructor)) void
842 GNUNET_CURL_constructor__ (void)
843 {
844  CURLcode ret;
845 
846  if (CURLE_OK != (ret = curl_global_init (CURL_GLOBAL_DEFAULT)))
847  {
848  CURL_STRERROR (GNUNET_ERROR_TYPE_ERROR, "curl_global_init", ret);
849  curl_fail = 1;
850  }
851 }
852 
853 
857 __attribute__ ((destructor)) void
858 GNUNET_CURL_destructor__ (void)
859 {
860  if (curl_fail)
861  return;
862  curl_global_cleanup ();
863 }
864 
865 
866 /* 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:421
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_append_header(struct GNUNET_CURL_Context *ctx, const char *header)
Add custom request header.
Definition: curl.c:604
#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:827
#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:491
#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:378
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:277
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:841
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:790
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:753
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:462
char * GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
Return the base32crockford encoding of the given buffer.
Definition: strings.c:920
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:693
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:223
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:326
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:525
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:244