GNUnet 0.28.1-dev.5-1-gae1c02d74
 
Loading...
Searching...
No Matches
curl.c File Reference

API for downloading JSON via CURL. More...

#include "platform.h"
#include <jansson.h>
#include <microhttpd.h>
#include "gnunet_curl_lib.h"
#include "curl_internal.h"
Include dependency graph for curl.c:

Go to the source code of this file.

Data Structures

struct  GNUNET_CURL_Job
 Jobs are CURL requests running within a struct GNUNET_CURL_Context. More...
 
struct  GNUNET_CURL_Context
 Context. More...
 

Macros

#define DEBUG   0
 Set to 1 for extra debug logging.
 
#define CURL_STRERROR(type, function, code)
 Log error related to CURL operations.
 
#define JSON_WARN(error)
 Print JSON parsing related error information.
 

Functions

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 performed with ctx.
 
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 performed with ctx.
 
struct GNUNET_CURL_ContextGNUNET_CURL_init (GNUNET_CURL_RescheduleCallback cb, void *cb_cls)
 Initialise this library.
 
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.
 
enum GNUNET_GenericReturnValue GNUNET_CURL_is_valid_scope_id (const char *scope_id)
 Return GNUNET_YES if given a valid scope ID and GNUNET_NO otherwise.
 
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.
 
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.
 
static size_t stream_write_cb (char *bufptr, size_t size, size_t nitems, void *cls)
 Callback used when the caller wants the response body as it arrives, instead of buffered.
 
static size_t stream_header_cb (char *bufptr, size_t size, size_t nitems, void *cls)
 Callback used to pass the response's header lines on to a streaming caller.
 
static bool setup_job_io (CURL *eh, struct GNUNET_CURL_Job *job)
 Point eh's body and header handling at job, in whichever of the two modes job was set up for.
 
static struct GNUNET_CURL_Jobsetup_job (CURL *eh, struct GNUNET_CURL_Context *ctx, struct curl_slist *all_headers, const struct GNUNET_CURL_StreamHandlers *sh)
 Create a job.
 
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.
 
struct GNUNET_CURL_JobGNUNET_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.
 
struct GNUNET_CURL_JobGNUNET_CURL_job_add_stream (struct GNUNET_CURL_Context *ctx, CURL *eh, const struct curl_slist *job_headers, const struct GNUNET_CURL_StreamHandlers *sh)
 Schedule a CURL request whose response is delivered incrementally, rather than buffered in full and handed over at the end.
 
void GNUNET_CURL_job_set_paused (struct GNUNET_CURL_Job *job, bool recv_paused, bool send_paused)
 Say which directions of job are to be paused from now on.
 
struct GNUNET_CURL_JobGNUNET_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.
 
struct GNUNET_CURL_JobGNUNET_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.
 
struct GNUNET_CURL_JobGNUNET_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.
 
void GNUNET_CURL_job_cancel (struct GNUNET_CURL_Job *job)
 Cancel a job.
 
static bool is_json (const char *ct)
 Test if the given content type ct is JSON.
 
void * GNUNET_CURL_download_get_result_ (struct GNUNET_CURL_DownloadBuffer *db, CURL *eh, long *response_code)
 
enum GNUNET_GenericReturnValue GNUNET_CURL_append_header (struct GNUNET_CURL_Context *ctx, const char *header)
 Add custom request header.
 
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.
 
void GNUNET_CURL_perform (struct GNUNET_CURL_Context *ctx)
 Run the main event loop for the CURL interaction.
 
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.
 
void GNUNET_CURL_fini (struct GNUNET_CURL_Context *ctx)
 Cleanup library initialisation resources.
 
void GNUNET_CURL_constructor__ (void)
 
void __attribute__ ((constructor))
 Initial global setup logic, specifically runs the Curl setup.
 
void GNUNET_CURL_destructor__ (void)
 
void __attribute__ ((destructor))
 Cleans up after us, specifically runs the Curl cleanup.
 

Variables

static int curl_fail
 Failsafe flag.
 

Detailed Description

API for downloading JSON via CURL.

Author
Sree Harsha Totakura sreeh.nosp@m.arsh.nosp@m.a@tot.nosp@m.akur.nosp@m.a.in
Christian Grothoff

Definition in file curl.c.

Macro Definition Documentation

◆ DEBUG

#define DEBUG   0

Set to 1 for extra debug logging.

Definition at line 39 of file curl.c.

◆ CURL_STRERROR

#define CURL_STRERROR (   type,
  function,
  code 
)
Value:
"Curl function `%s' has failed at `%s:%d' with error: %s\n", \
function, \
__FILE__, \
__LINE__, \
curl_easy_strerror (code));
static uint32_t type
Type string converted to DNS type value.
#define GNUNET_log(kind,...)

Log error related to CURL operations.

Parameters
typelog level
functionwhich function failed to run
codewhat was the curl error code

Definition at line 48 of file curl.c.

50 :%d' with error: %s\n", \
51 function, \
52 __FILE__, \
53 __LINE__, \
54 curl_easy_strerror (code));
static mp_limb_t d[(((256)+GMP_NUMB_BITS - 1)/GMP_NUMB_BITS)]

◆ JSON_WARN

#define JSON_WARN (   error)
Value:
"JSON parsing failed at %s:%u: %s (%s)\n", \
__FILE__, \
__LINE__, \
error.text, \
error.source)
@ GNUNET_ERROR_TYPE_WARNING

Print JSON parsing related error information.

Definition at line 59 of file curl.c.

61 :%u: %s (%s)\n", \
62 __FILE__, \
63 __LINE__, \
64 error.text, \
65 error.source)
static mp_limb_t u[(((256)+GMP_NUMB_BITS - 1)/GMP_NUMB_BITS)]

Function Documentation

◆ download_cb()

static size_t download_cb ( char *  bufptr,
size_t  size,
size_t  nitems,
void *  cls 
)
static

Callback used when downloading the reply to an HTTP request.

Just appends all of the data to the buf in the struct DownloadBuffer for further processing. The size of the download is limited to GNUNET_MAX_MALLOC_CHECKED, if the download exceeds this size, we abort with an error.

Parameters
bufptrdata downloaded via HTTP
sizesize of an item in bufptr
nitemsnumber of items in bufptr
clsthe struct DownloadBuffer
Returns
number of bytes processed from bufptr

Definition at line 327 of file curl.c.

331{
332 struct GNUNET_CURL_DownloadBuffer *db = cls;
333 size_t msize;
334 void *buf;
335
336 if (0 == size * nitems)
337 {
338 /* Nothing (left) to do */
339 return 0;
340 }
341 msize = size * nitems;
342 if ((msize + db->buf_size) >= GNUNET_MAX_MALLOC_CHECKED)
343 {
344 db->eno = ENOMEM;
345 return 0; /* signals an error to curl */
346 }
347 db->buf = GNUNET_realloc (db->buf,
348 db->buf_size + msize);
349 buf = db->buf + db->buf_size;
350 GNUNET_memcpy (buf, bufptr, msize);
351 db->buf_size += msize;
352 return msize;
353}
static struct GNUNET_FS_DirectoryBuilder * db
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_MAX_MALLOC_CHECKED
Maximum allocation with GNUNET_malloc macro.
#define GNUNET_realloc(ptr, size)
Wrapper around realloc.
static unsigned int size
Size of the "table".
Definition peer.c:68
Buffer data structure we use to buffer the HTTP download before giving it to the JSON parser.
void * buf
Download buffer.

References GNUNET_CURL_DownloadBuffer::buf, db, GNUNET_MAX_MALLOC_CHECKED, GNUNET_memcpy, GNUNET_realloc, and size.

Referenced by setup_job_io().

Here is the caller graph for this function:

◆ setup_job_headers()

static struct curl_slist * setup_job_headers ( struct GNUNET_CURL_Context ctx,
const struct curl_slist *  job_headers 
)
static

Create the HTTP headers for the request.

Parameters
ctxcontext we run in
job_headersjob-specific headers
Returns
all headers to use

Definition at line 364 of file curl.c.

366{
367 struct curl_slist *all_headers = NULL;
368
369 for (const struct curl_slist *curr = job_headers;
370 NULL != curr;
371 curr = curr->next)
372 {
373 GNUNET_assert (NULL !=
374 (all_headers = curl_slist_append (all_headers,
375 curr->data)));
376 }
377
378 for (const struct curl_slist *curr = ctx->common_headers;
379 NULL != curr;
380 curr = curr->next)
381 {
382 GNUNET_assert (NULL !=
383 (all_headers = curl_slist_append (all_headers,
384 curr->data)));
385 }
386
387 if (NULL != ctx->async_scope_id_header)
388 {
389 struct GNUNET_AsyncScopeSave scope;
390
391 GNUNET_async_scope_get (&scope);
392 if (GNUNET_YES == scope.have_scope)
393 {
394 char *aid_header;
395
396 aid_header =
398 &scope.scope_id,
399 sizeof(struct GNUNET_AsyncScopeId));
400 GNUNET_assert (NULL != aid_header);
401 GNUNET_assert (NULL != curl_slist_append (all_headers,
402 aid_header));
403 GNUNET_free (aid_header);
404 }
405 }
406 return all_headers;
407}
static struct GNUNET_FS_Handle * ctx
void GNUNET_async_scope_get(struct GNUNET_AsyncScopeSave *scope_ret)
Get the current async scope.
@ GNUNET_YES
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#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:818
Identifier for an asynchronous execution context.
Saved async scope identifier or root scope.

References ctx, GNUNET_assert, GNUNET_async_scope_get(), GNUNET_free, GNUNET_STRINGS_data_to_string_alloc(), GNUNET_YES, GNUNET_AsyncScopeSave::have_scope, and GNUNET_AsyncScopeSave::scope_id.

Referenced by GNUNET_CURL_job_add2(), GNUNET_CURL_job_add_raw(), and GNUNET_CURL_job_add_stream().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ stream_write_cb()

static size_t stream_write_cb ( char *  bufptr,
size_t  size,
size_t  nitems,
void *  cls 
)
static

Callback used when the caller wants the response body as it arrives, instead of buffered.

Hands the chunk straight to the caller's GNUNET_CURL_StreamCallback, whose return value libcurl understands directly: msize accepts, GNUNET_CURL_STREAM_PAUSE suspends delivery, anything else fails the transfer.

Parameters
bufptrdata downloaded via HTTP
sizesize of an item in bufptr
nitemsnumber of items in bufptr
clsthe struct GNUNET_CURL_Job
Returns
number of bytes processed from bufptr

Definition at line 424 of file curl.c.

428{
429 struct GNUNET_CURL_Job *job = cls;
430 size_t msize = size * nitems;
431
432 if (0 == msize)
433 return 0; /* nothing (left) to do */
434 return job->sh.scb (job->sh.scb_cls,
435 bufptr,
436 msize);
437}
static struct GNUNET_SCHEDULER_Task * job
Task for main job.
Jobs are CURL requests running within a struct GNUNET_CURL_Context.
Definition curl.c:78

References job, and size.

Referenced by setup_job_io().

Here is the caller graph for this function:

◆ stream_header_cb()

static size_t stream_header_cb ( char *  bufptr,
size_t  size,
size_t  nitems,
void *  cls 
)
static

Callback used to pass the response's header lines on to a streaming caller.

Note that libcurl routes everything through here that it reads in a header section, including status lines, the blank line ending each section, interim (1xx) responses and trailers; sorting those out is the caller's job, and GNUNET_CURL_StreamHeaderCallback says so.

Parameters
bufptrone header line, not 0-terminated
sizesize of an item in bufptr
nitemsnumber of items in bufptr
clsthe struct GNUNET_CURL_Job
Returns
size * nitems to continue, anything else to fail the transfer

Definition at line 456 of file curl.c.

460{
461 struct GNUNET_CURL_Job *job = cls;
462 size_t msize = size * nitems;
463
464 if (NULL == job->sh.hcb)
465 return msize;
466 if (GNUNET_OK !=
467 job->sh.hcb (job->sh.hcb_cls,
468 bufptr,
469 msize))
470 return 0; /* signals an error to curl */
471 return msize;
472}
@ GNUNET_OK

References GNUNET_OK, job, and size.

Referenced by setup_job_io().

Here is the caller graph for this function:

◆ setup_job_io()

static bool setup_job_io ( CURL *  eh,
struct GNUNET_CURL_Job job 
)
static

Point eh's body and header handling at job, in whichever of the two modes job was set up for.

Parameters
eheasy handle to configure
[in,out]jobthe job eh belongs to
Returns
true on success

Definition at line 484 of file curl.c.

486{
487 if (! job->streaming)
488 return (CURLE_OK ==
489 curl_easy_setopt (eh,
490 CURLOPT_WRITEFUNCTION,
491 &download_cb)) &&
492 (CURLE_OK ==
493 curl_easy_setopt (eh,
494 CURLOPT_WRITEDATA,
495 &job->db));
496 return (CURLE_OK ==
497 curl_easy_setopt (eh,
498 CURLOPT_WRITEFUNCTION,
499 &stream_write_cb)) &&
500 (CURLE_OK ==
501 curl_easy_setopt (eh,
502 CURLOPT_WRITEDATA,
503 job)) &&
504 (CURLE_OK ==
505 curl_easy_setopt (eh,
506 CURLOPT_HEADERFUNCTION,
507 &stream_header_cb)) &&
508 (CURLE_OK ==
509 curl_easy_setopt (eh,
510 CURLOPT_HEADERDATA,
511 job));
512}
static size_t stream_write_cb(char *bufptr, size_t size, size_t nitems, void *cls)
Callback used when the caller wants the response body as it arrives, instead of buffered.
Definition curl.c:424
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:327
static size_t stream_header_cb(char *bufptr, size_t size, size_t nitems, void *cls)
Callback used to pass the response's header lines on to a streaming caller.
Definition curl.c:456

References download_cb(), job, stream_header_cb(), and stream_write_cb().

Referenced by setup_job().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setup_job()

static struct GNUNET_CURL_Job * setup_job ( CURL *  eh,
struct GNUNET_CURL_Context ctx,
struct curl_slist *  all_headers,
const struct GNUNET_CURL_StreamHandlers sh 
)
static

Create a job.

Parameters
eheasy handle to use
ctxcontext to run the job in
all_headersHTTP client headers to use (free'd)
shhandlers for a streaming job, or NULL for a buffering one
Returns
NULL on error

Definition at line 525 of file curl.c.

529{
530 struct GNUNET_CURL_Job *job;
531
532 if (CURLE_OK !=
533 curl_easy_setopt (eh,
534 CURLOPT_HTTPHEADER,
535 all_headers))
536 {
537 GNUNET_break (0);
538 curl_slist_free_all (all_headers);
539 curl_easy_cleanup (eh);
540 return NULL;
541 }
542 job = GNUNET_new (struct GNUNET_CURL_Job);
543 job->start_time = GNUNET_TIME_absolute_get ();
544 job->job_headers = all_headers;
545 if (NULL != sh)
546 {
547 job->streaming = true;
548 job->sh = *sh;
549 }
550
551 if ( (CURLE_OK !=
552 curl_easy_setopt (eh,
553 CURLOPT_PRIVATE,
554 job)) ||
555 (! setup_job_io (eh,
556 job)) ||
557 (CURLE_OK !=
558 curl_easy_setopt (eh,
559 CURLOPT_SHARE,
560 ctx->share)) )
561 {
562 GNUNET_break (0);
564 curl_easy_cleanup (eh);
565 return NULL;
566 }
567 if ( (CURLM_OK !=
568 curl_multi_add_handle (ctx->multi,
569 eh)) )
570 {
571 GNUNET_break (0);
573 curl_easy_cleanup (eh);
574 return NULL;
575 }
576 job->easy_handle = eh;
577 job->ctx = ctx;
579 ctx->jobs_tail,
580 job);
581 return job;
582}
static bool setup_job_io(CURL *eh, struct GNUNET_CURL_Job *job)
Point eh's body and header handling at job, in whichever of the two modes job was set up for.
Definition curl.c:484
static struct GNUNET_IDENTITY_Handle * sh
Handle to IDENTITY service.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition time.c:111

References ctx, GNUNET_break, GNUNET_CONTAINER_DLL_insert, GNUNET_free, GNUNET_new, GNUNET_TIME_absolute_get(), job, setup_job_io(), and sh.

Referenced by GNUNET_CURL_job_add2(), GNUNET_CURL_job_add_raw(), and GNUNET_CURL_job_add_stream().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_json()

static bool is_json ( const char *  ct)
static

Test if the given content type ct is JSON.

Parameters
cta content type, e.g. "application/json; charset=UTF-8"
Returns
true if ct denotes JSON

Definition at line 792 of file curl.c.

793{
794 const char *semi;
795
796 /* check for "application/json" exact match */
797 if (0 == strcasecmp (ct,
798 "application/json"))
799 return true;
800 /* check for "application/json;[ANYTHING]" */
801 semi = strchr (ct,
802 ';');
803 /* also allow "application/json [ANYTHING]" (note the space!) */
804 if (NULL == semi)
805 semi = strchr (ct,
806 ' ');
807 if (NULL == semi)
808 return false; /* no delimiter we accept, forget it */
809 if (semi - ct != strlen ("application/json"))
810 return false; /* delimiter past desired length, forget it */
811 if (0 == strncasecmp (ct,
812 "application/json",
813 strlen ("application/json")))
814 return true; /* OK */
815 return false;
816}

Referenced by GNUNET_CURL_download_get_result_().

Here is the caller graph for this function:

◆ GNUNET_CURL_download_get_result_()

void * GNUNET_CURL_download_get_result_ ( struct GNUNET_CURL_DownloadBuffer db,
CURL *  eh,
long *  response_code 
)

Definition at line 820 of file curl.c.

823{
824 json_t *json;
825 char *ct;
826
827#if DEBUG
829 "Downloaded body: %.*s\n",
830 (int) db->buf_size,
831 (char *) db->buf);
832#endif
833 if (CURLE_OK !=
834 curl_easy_getinfo (eh,
835 CURLINFO_RESPONSE_CODE,
836 response_code))
837 {
838 /* unexpected error... */
839 GNUNET_break (0);
840 *response_code = 0;
841 }
842 if (MHD_HTTP_NO_CONTENT == *response_code)
843 return NULL;
844 if ((CURLE_OK !=
845 curl_easy_getinfo (eh,
846 CURLINFO_CONTENT_TYPE,
847 &ct)) ||
848 (NULL == ct) ||
849 (! is_json (ct)))
850 {
851 /* No content type or explicitly not JSON, refuse to parse
852 (but keep response code) */
853 if (0 != db->buf_size)
854 {
855 const char *url;
856
857 if (CURLE_OK !=
858 curl_easy_getinfo (eh,
859 CURLINFO_EFFECTIVE_URL,
860 &url))
861 url = "<unknown URL>";
863 "Request to `%s' was expected to return a body of type `application/json', got `%s'\n",
864 url,
865 ct);
866 }
867 return NULL;
868 }
869 if (0 == *response_code)
870 {
871 const char *url;
872
873 if (CURLE_OK !=
874 curl_easy_getinfo (eh,
875 CURLINFO_EFFECTIVE_URL,
876 &url))
877 url = "<unknown URL>";
879 "Failed to download response from `%s': \n",
880 url);
881 return NULL;
882 }
883 json = NULL;
884 if (0 == db->eno)
885 {
886 json_error_t error;
887
888 json = json_loadb (db->buf,
889 db->buf_size,
890 JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK,
891 &error);
892 if (NULL == json)
893 {
894 JSON_WARN (error);
895 *response_code = 0;
897 "Failed to parse JSON response: %s\n",
898 error.text);
899 }
900 }
901 GNUNET_free (db->buf);
902 db->buf = NULL;
903 db->buf_size = 0;
904 return json;
905}
static bool is_json(const char *ct)
Test if the given content type ct is JSON.
Definition curl.c:792
#define JSON_WARN(error)
Print JSON parsing related error information.
Definition curl.c:59
@ GNUNET_ERROR_TYPE_DEBUG

References db, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, is_json(), and JSON_WARN.

Referenced by GNUNET_CURL_gnunet_rc_create(), and GNUNET_CURL_perform().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNUNET_CURL_constructor__()

void GNUNET_CURL_constructor__ ( void  )

◆ __attribute__() [1/2]

void __attribute__ ( (constructor)  )

Initial global setup logic, specifically runs the Curl setup.

Definition at line 1095 of file curl.c.

1097{
1098 CURLcode ret;
1099
1100 if (CURLE_OK != (ret = curl_global_init (CURL_GLOBAL_DEFAULT)))
1101 {
1103 "curl_global_init",
1104 ret);
1105 curl_fail = 1;
1106 }
1107}
#define CURL_STRERROR(type, function, code)
Log error related to CURL operations.
Definition curl.c:48
static int curl_fail
Failsafe flag.
Definition curl.c:72
static int ret
Final status code.
Definition gnunet-arm.c:93
@ GNUNET_ERROR_TYPE_ERROR

References curl_fail, CURL_STRERROR, GNUNET_ERROR_TYPE_ERROR, and ret.

◆ GNUNET_CURL_destructor__()

void GNUNET_CURL_destructor__ ( void  )

◆ __attribute__() [2/2]

void __attribute__ ( (destructor)  )

Cleans up after us, specifically runs the Curl cleanup.

Definition at line 1116 of file curl.c.

1118{
1119 if (curl_fail)
1120 return;
1121 curl_global_cleanup ();
1122}

References curl_fail.

Variable Documentation

◆ curl_fail

int curl_fail
static

Failsafe flag.

Raised if our constructor fails to initialize the Curl library.

Definition at line 72 of file curl.c.

Referenced by __attribute__(), __attribute__(), and GNUNET_CURL_init().