2018-10-22 16:00:06 +02:00
|
|
|
/*
|
|
|
|
This file is part of TALER
|
|
|
|
Copyright (C) 2014-2018 GNUnet e.V.
|
|
|
|
|
|
|
|
TALER is free software; you can redistribute it and/or modify it under the
|
|
|
|
terms of the GNU General Public License as published by the Free Software
|
|
|
|
Foundation; either version 3, or (at your option) any later version.
|
|
|
|
|
|
|
|
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
|
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along with
|
|
|
|
TALER; see the file COPYING. If not, see
|
|
|
|
<http://www.gnu.org/licenses/>
|
|
|
|
*/
|
|
|
|
/**
|
|
|
|
* @file auditor-lib/auditor_api_handle.c
|
|
|
|
* @brief Implementation of the "handle" component of the auditor's HTTP API
|
|
|
|
* @author Sree Harsha Totakura <sreeharsha@totakura.in>
|
|
|
|
* @author Christian Grothoff
|
|
|
|
*/
|
|
|
|
#include "platform.h"
|
|
|
|
#include <microhttpd.h>
|
|
|
|
#include <gnunet/gnunet_curl_lib.h>
|
|
|
|
#include "taler_json_lib.h"
|
|
|
|
#include "taler_auditor_service.h"
|
|
|
|
#include "taler_signatures.h"
|
|
|
|
#include "auditor_api_handle.h"
|
2019-01-11 21:27:34 +01:00
|
|
|
#include "auditor_api_curl_defaults.h"
|
2018-10-22 16:00:06 +02:00
|
|
|
#include "backoff.h"
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Which revision of the Taler auditor protocol is implemented
|
|
|
|
* by this library? Used to determine compatibility.
|
|
|
|
*/
|
|
|
|
#define TALER_PROTOCOL_CURRENT 0
|
|
|
|
|
|
|
|
/**
|
|
|
|
* How many revisions back are we compatible to?
|
|
|
|
*/
|
|
|
|
#define TALER_PROTOCOL_AGE 0
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Log error related to CURL operations.
|
|
|
|
*
|
|
|
|
* @param type log level
|
|
|
|
* @param function which function failed to run
|
|
|
|
* @param code what was the curl error code
|
|
|
|
*/
|
|
|
|
#define CURL_STRERROR(type, function, code) \
|
|
|
|
GNUNET_log (type, "Curl function `%s' has failed at `%s:%d' with error: %s", \
|
|
|
|
function, __FILE__, __LINE__, curl_easy_strerror (code));
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Stages of initialization for the `struct TALER_AUDITOR_Handle`
|
|
|
|
*/
|
|
|
|
enum AuditorHandleState
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Just allocated.
|
|
|
|
*/
|
|
|
|
MHS_INIT = 0,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Obtained the auditor's versioning data and version.
|
|
|
|
*/
|
|
|
|
MHS_VERSION = 1,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Failed to initialize (fatal).
|
|
|
|
*/
|
|
|
|
MHS_FAILED = 2
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Data for the request to get the /version of a auditor.
|
|
|
|
*/
|
|
|
|
struct VersionRequest;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle to the auditor
|
|
|
|
*/
|
|
|
|
struct TALER_AUDITOR_Handle
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* The context of this handle
|
|
|
|
*/
|
|
|
|
struct GNUNET_CURL_Context *ctx;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The URL of the auditor (i.e. "http://auditor.taler.net/")
|
|
|
|
*/
|
|
|
|
char *url;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function to call with the auditor's certification data,
|
|
|
|
* NULL if this has already been done.
|
|
|
|
*/
|
|
|
|
TALER_AUDITOR_VersionCallback version_cb;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Closure to pass to @e version_cb.
|
|
|
|
*/
|
|
|
|
void *version_cb_cls;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Data for the request to get the /version of a auditor,
|
|
|
|
* NULL once we are past stage #MHS_INIT.
|
|
|
|
*/
|
2018-10-24 11:56:51 +02:00
|
|
|
struct VersionRequest *vr;
|
2018-10-22 16:00:06 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Task for retrying /version request.
|
|
|
|
*/
|
|
|
|
struct GNUNET_SCHEDULER_Task *retry_task;
|
|
|
|
|
|
|
|
/**
|
2018-10-24 11:56:51 +02:00
|
|
|
* /version data of the auditor, only valid if
|
2018-10-22 16:00:06 +02:00
|
|
|
* @e handshake_complete is past stage #MHS_VERSION.
|
|
|
|
*/
|
2018-10-24 11:56:51 +02:00
|
|
|
struct TALER_AUDITOR_VersionInformation vi;
|
2018-10-22 16:00:06 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Retry /version frequency.
|
|
|
|
*/
|
|
|
|
struct GNUNET_TIME_Relative retry_delay;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Stage of the auditor's initialization routines.
|
|
|
|
*/
|
|
|
|
enum AuditorHandleState state;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/* ***************** Internal /version fetching ************* */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Data for the request to get the /version of a auditor.
|
|
|
|
*/
|
|
|
|
struct VersionRequest
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* The connection to auditor this request handle will use
|
|
|
|
*/
|
|
|
|
struct TALER_AUDITOR_Handle *auditor;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The url for this handle
|
|
|
|
*/
|
|
|
|
char *url;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Entry for this request with the `struct GNUNET_CURL_Context`.
|
|
|
|
*/
|
|
|
|
struct GNUNET_CURL_Job *job;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Release memory occupied by a version request.
|
|
|
|
* Note that this does not cancel the request
|
|
|
|
* itself.
|
|
|
|
*
|
2018-10-24 11:56:51 +02:00
|
|
|
* @param vr request to free
|
2018-10-22 16:00:06 +02:00
|
|
|
*/
|
|
|
|
static void
|
2018-10-24 11:56:51 +02:00
|
|
|
free_version_request (struct VersionRequest *vr)
|
2018-10-22 16:00:06 +02:00
|
|
|
{
|
2018-10-24 11:56:51 +02:00
|
|
|
GNUNET_free (vr->url);
|
|
|
|
GNUNET_free (vr);
|
2018-10-22 16:00:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2018-10-24 11:56:51 +02:00
|
|
|
* Free version data object.
|
2018-10-22 16:00:06 +02:00
|
|
|
*
|
2018-10-24 11:56:51 +02:00
|
|
|
* @param vi data to free (pointer itself excluded)
|
2018-10-22 16:00:06 +02:00
|
|
|
*/
|
2018-10-24 11:56:51 +02:00
|
|
|
static void
|
|
|
|
free_version_info (struct TALER_AUDITOR_VersionInformation *vi)
|
2018-10-22 16:00:06 +02:00
|
|
|
{
|
2018-10-24 11:56:51 +02:00
|
|
|
GNUNET_free_non_null (vi->version);
|
|
|
|
vi->version = NULL;
|
2018-10-22 16:00:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Decode the JSON in @a resp_obj from the /version response and store the data
|
|
|
|
* in the @a key_data.
|
|
|
|
*
|
|
|
|
* @param[in] resp_obj JSON object to parse
|
|
|
|
* @param check_sig #GNUNET_YES if we should check the signature
|
2018-10-24 11:56:51 +02:00
|
|
|
* @param[out] vi where to store the results we decoded
|
|
|
|
* @param[out] vc where to store version compatibility data
|
2018-10-22 16:00:06 +02:00
|
|
|
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error (malformed JSON)
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
decode_version_json (const json_t *resp_obj,
|
2018-10-24 11:56:51 +02:00
|
|
|
int check_sig,
|
|
|
|
struct TALER_AUDITOR_VersionInformation *vi,
|
|
|
|
enum TALER_AUDITOR_VersionCompatibility *vc)
|
2018-10-22 16:00:06 +02:00
|
|
|
{
|
|
|
|
unsigned int age;
|
|
|
|
unsigned int revision;
|
|
|
|
unsigned int current;
|
2018-10-27 18:38:43 +02:00
|
|
|
const char *ver;
|
2018-10-22 16:00:06 +02:00
|
|
|
struct GNUNET_JSON_Specification spec[] = {
|
|
|
|
GNUNET_JSON_spec_string ("version",
|
2018-10-27 18:38:43 +02:00
|
|
|
&ver),
|
2018-10-22 16:00:06 +02:00
|
|
|
GNUNET_JSON_spec_fixed_auto ("master_public_key",
|
2018-10-24 11:56:51 +02:00
|
|
|
&vi->auditor_pub),
|
2018-10-22 16:00:06 +02:00
|
|
|
GNUNET_JSON_spec_end()
|
|
|
|
};
|
|
|
|
|
|
|
|
if (JSON_OBJECT != json_typeof (resp_obj))
|
|
|
|
{
|
|
|
|
GNUNET_break_op (0);
|
|
|
|
return GNUNET_SYSERR;
|
|
|
|
}
|
|
|
|
/* check the version */
|
|
|
|
if (GNUNET_OK !=
|
|
|
|
GNUNET_JSON_parse (resp_obj,
|
|
|
|
spec,
|
|
|
|
NULL, NULL))
|
|
|
|
{
|
|
|
|
GNUNET_break_op (0);
|
|
|
|
return GNUNET_SYSERR;
|
|
|
|
}
|
2018-10-24 11:56:51 +02:00
|
|
|
if (3 != sscanf (vi->version,
|
2018-10-22 16:00:06 +02:00
|
|
|
"%u:%u:%u",
|
|
|
|
¤t,
|
|
|
|
&revision,
|
|
|
|
&age))
|
|
|
|
{
|
|
|
|
GNUNET_break_op (0);
|
2018-10-24 11:56:51 +02:00
|
|
|
free_version_info (vi);
|
2018-10-22 16:00:06 +02:00
|
|
|
return GNUNET_SYSERR;
|
|
|
|
}
|
2018-10-27 18:38:43 +02:00
|
|
|
vi->version = GNUNET_strdup (ver);
|
2018-10-22 16:00:06 +02:00
|
|
|
*vc = TALER_AUDITOR_VC_MATCH;
|
|
|
|
if (TALER_PROTOCOL_CURRENT < current)
|
|
|
|
{
|
|
|
|
*vc |= TALER_AUDITOR_VC_NEWER;
|
|
|
|
if (TALER_PROTOCOL_CURRENT < current - age)
|
|
|
|
*vc |= TALER_AUDITOR_VC_INCOMPATIBLE;
|
|
|
|
}
|
|
|
|
if (TALER_PROTOCOL_CURRENT > current)
|
|
|
|
{
|
|
|
|
*vc |= TALER_AUDITOR_VC_OLDER;
|
|
|
|
if (TALER_PROTOCOL_CURRENT - TALER_PROTOCOL_AGE > current)
|
|
|
|
*vc |= TALER_AUDITOR_VC_INCOMPATIBLE;
|
|
|
|
}
|
|
|
|
return GNUNET_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initiate download of /version from the auditor.
|
|
|
|
*
|
|
|
|
* @param cls auditor where to download /version from
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
request_version (void *cls);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Callback used when downloading the reply to a /version request
|
|
|
|
* is complete.
|
|
|
|
*
|
|
|
|
* @param cls the `struct VersionRequest`
|
|
|
|
* @param response_code HTTP response code, 0 on error
|
|
|
|
* @param resp_obj parsed JSON result, NULL on error
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
version_completed_cb (void *cls,
|
|
|
|
long response_code,
|
2018-10-27 18:38:43 +02:00
|
|
|
const void *gresp_obj)
|
2018-10-22 16:00:06 +02:00
|
|
|
{
|
2018-10-27 18:38:43 +02:00
|
|
|
const json_t *resp_obj = gresp_obj;
|
2018-10-24 11:56:51 +02:00
|
|
|
struct VersionRequest *vr = cls;
|
|
|
|
struct TALER_AUDITOR_Handle *auditor = vr->auditor;
|
2018-10-22 16:00:06 +02:00
|
|
|
enum TALER_AUDITOR_VersionCompatibility vc;
|
|
|
|
|
|
|
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
|
|
"Received version from URL `%s' with status %ld.\n",
|
2018-10-24 11:56:51 +02:00
|
|
|
vr->url,
|
2018-10-22 16:00:06 +02:00
|
|
|
response_code);
|
|
|
|
vc = TALER_AUDITOR_VC_PROTOCOL_ERROR;
|
|
|
|
switch (response_code)
|
|
|
|
{
|
|
|
|
case 0:
|
2018-10-24 11:56:51 +02:00
|
|
|
case MHD_HTTP_INTERNAL_SERVER_ERROR:
|
|
|
|
free_version_request (vr);
|
|
|
|
auditor->vr = NULL;
|
2018-10-22 16:00:06 +02:00
|
|
|
GNUNET_assert (NULL == auditor->retry_task);
|
2019-01-11 21:27:34 +01:00
|
|
|
auditor->retry_delay = EXCHANGE_LIB_BACKOFF (auditor->retry_delay);
|
2018-10-22 16:00:06 +02:00
|
|
|
auditor->retry_task = GNUNET_SCHEDULER_add_delayed (auditor->retry_delay,
|
2018-10-24 11:56:51 +02:00
|
|
|
&request_version,
|
|
|
|
auditor);
|
2018-10-22 16:00:06 +02:00
|
|
|
return;
|
|
|
|
case MHD_HTTP_OK:
|
|
|
|
if (NULL == resp_obj)
|
|
|
|
{
|
|
|
|
response_code = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (GNUNET_OK !=
|
|
|
|
decode_version_json (resp_obj,
|
2018-10-24 11:56:51 +02:00
|
|
|
GNUNET_YES,
|
|
|
|
&auditor->vi,
|
|
|
|
&vc))
|
2018-10-22 16:00:06 +02:00
|
|
|
{
|
|
|
|
response_code = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
auditor->retry_delay = GNUNET_TIME_UNIT_ZERO;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
|
|
|
"Unexpected response code %u\n",
|
|
|
|
(unsigned int) response_code);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (MHD_HTTP_OK != response_code)
|
|
|
|
{
|
2018-10-24 11:56:51 +02:00
|
|
|
auditor->vr = NULL;
|
|
|
|
free_version_request (vr);
|
2018-10-22 16:00:06 +02:00
|
|
|
auditor->state = MHS_FAILED;
|
2018-10-24 11:56:51 +02:00
|
|
|
free_version_info (&auditor->vi);
|
2018-10-22 16:00:06 +02:00
|
|
|
/* notify application that we failed */
|
|
|
|
auditor->version_cb (auditor->version_cb_cls,
|
|
|
|
NULL,
|
|
|
|
vc);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-10-24 11:56:51 +02:00
|
|
|
auditor->vr = NULL;
|
|
|
|
free_version_request (vr);
|
2018-10-22 16:00:06 +02:00
|
|
|
auditor->state = MHS_VERSION;
|
|
|
|
/* notify application about the key information */
|
|
|
|
auditor->version_cb (auditor->version_cb_cls,
|
2018-10-24 11:56:51 +02:00
|
|
|
&auditor->vi,
|
|
|
|
vc);
|
2018-10-22 16:00:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ********************* library internal API ********* */
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the context of a auditor.
|
|
|
|
*
|
|
|
|
* @param h the auditor handle to query
|
|
|
|
* @return ctx context to execute jobs in
|
|
|
|
*/
|
|
|
|
struct GNUNET_CURL_Context *
|
|
|
|
MAH_handle_to_context (struct TALER_AUDITOR_Handle *h)
|
|
|
|
{
|
|
|
|
return h->ctx;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if the handle is ready to process requests.
|
|
|
|
*
|
|
|
|
* @param h the auditor handle to query
|
|
|
|
* @return #GNUNET_YES if we are ready, #GNUNET_NO if not
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
MAH_handle_is_ready (struct TALER_AUDITOR_Handle *h)
|
|
|
|
{
|
|
|
|
return (MHS_VERSION == h->state) ? GNUNET_YES : GNUNET_NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Obtain the URL to use for an API request.
|
|
|
|
*
|
|
|
|
* @param h handle for the auditor
|
2018-10-24 11:56:51 +02:00
|
|
|
* @param path Taler API path (i.e. "/deposit-confirmation")
|
2018-10-22 16:00:06 +02:00
|
|
|
* @return the full URL to use with cURL
|
|
|
|
*/
|
|
|
|
char *
|
|
|
|
MAH_path_to_url (struct TALER_AUDITOR_Handle *h,
|
|
|
|
const char *path)
|
|
|
|
{
|
|
|
|
return MAH_path_to_url2 (h->url,
|
|
|
|
path);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Obtain the URL to use for an API request.
|
|
|
|
*
|
|
|
|
* @param base_url base URL of the auditor (i.e. "http://auditor/")
|
2018-10-24 11:56:51 +02:00
|
|
|
* @param path Taler API path (i.e. "/deposit-confirmation")
|
2018-10-22 16:00:06 +02:00
|
|
|
* @return the full URL to use with cURL
|
|
|
|
*/
|
|
|
|
char *
|
|
|
|
MAH_path_to_url2 (const char *base_url,
|
|
|
|
const char *path)
|
|
|
|
{
|
|
|
|
char *url;
|
|
|
|
|
|
|
|
if ( ('/' == path[0]) &&
|
|
|
|
(0 < strlen (base_url)) &&
|
|
|
|
('/' == base_url[strlen (base_url) - 1]) )
|
|
|
|
path++; /* avoid generating URL with "//" from concat */
|
|
|
|
GNUNET_asprintf (&url,
|
|
|
|
"%s%s",
|
|
|
|
base_url,
|
|
|
|
path);
|
|
|
|
return url;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ********************* public API ******************* */
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initialise a connection to the auditor. Will connect to the
|
|
|
|
* auditor and obtain information about the auditor's master public
|
|
|
|
* key and the auditor's auditor. The respective information will
|
|
|
|
* be passed to the @a version_cb once available, and all future
|
|
|
|
* interactions with the auditor will be checked to be signed
|
|
|
|
* (where appropriate) by the respective master key.
|
|
|
|
*
|
|
|
|
* @param ctx the context
|
|
|
|
* @param url HTTP base URL for the auditor
|
2018-10-24 11:56:51 +02:00
|
|
|
* @param version_cb function to call with the auditor's version information
|
2018-10-22 16:00:06 +02:00
|
|
|
* @param version_cb_cls closure for @a version_cb
|
|
|
|
* @return the auditor handle; NULL upon error
|
|
|
|
*/
|
|
|
|
struct TALER_AUDITOR_Handle *
|
|
|
|
TALER_AUDITOR_connect (struct GNUNET_CURL_Context *ctx,
|
|
|
|
const char *url,
|
2018-10-24 11:38:00 +02:00
|
|
|
TALER_AUDITOR_VersionCallback version_cb,
|
2018-10-22 16:00:06 +02:00
|
|
|
void *version_cb_cls)
|
|
|
|
{
|
|
|
|
struct TALER_AUDITOR_Handle *auditor;
|
|
|
|
|
|
|
|
auditor = GNUNET_new (struct TALER_AUDITOR_Handle);
|
|
|
|
auditor->ctx = ctx;
|
|
|
|
auditor->url = GNUNET_strdup (url);
|
|
|
|
auditor->version_cb = version_cb;
|
|
|
|
auditor->version_cb_cls = version_cb_cls;
|
|
|
|
auditor->retry_task = GNUNET_SCHEDULER_add_now (&request_version,
|
|
|
|
auditor);
|
|
|
|
return auditor;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initiate download of /version from the auditor.
|
|
|
|
*
|
|
|
|
* @param cls auditor where to download /version from
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
request_version (void *cls)
|
|
|
|
{
|
|
|
|
struct TALER_AUDITOR_Handle *auditor = cls;
|
2018-10-24 11:56:51 +02:00
|
|
|
struct VersionRequest *vr;
|
2018-10-22 16:00:06 +02:00
|
|
|
CURL *eh;
|
|
|
|
|
|
|
|
auditor->retry_task = NULL;
|
2018-10-24 11:56:51 +02:00
|
|
|
GNUNET_assert (NULL == auditor->vr);
|
|
|
|
vr = GNUNET_new (struct VersionRequest);
|
|
|
|
vr->auditor = auditor;
|
|
|
|
vr->url = MAH_path_to_url (auditor,
|
2018-10-22 16:00:06 +02:00
|
|
|
"/version");
|
|
|
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
|
|
|
"Requesting version with URL `%s'.\n",
|
2018-10-24 11:56:51 +02:00
|
|
|
vr->url);
|
2018-10-27 18:38:43 +02:00
|
|
|
eh = TAL_curl_easy_get (vr->url);
|
2018-10-22 16:00:06 +02:00
|
|
|
GNUNET_assert (CURLE_OK ==
|
|
|
|
curl_easy_setopt (eh,
|
|
|
|
CURLOPT_VERBOSE,
|
|
|
|
0));
|
|
|
|
GNUNET_assert (CURLE_OK ==
|
|
|
|
curl_easy_setopt (eh,
|
|
|
|
CURLOPT_TIMEOUT,
|
|
|
|
(long) 300));
|
|
|
|
GNUNET_assert (CURLE_OK ==
|
|
|
|
curl_easy_setopt (eh,
|
|
|
|
CURLOPT_HEADERDATA,
|
2018-10-24 11:56:51 +02:00
|
|
|
vr));
|
|
|
|
vr->job = GNUNET_CURL_job_add (auditor->ctx,
|
2018-10-22 16:00:06 +02:00
|
|
|
eh,
|
|
|
|
GNUNET_NO,
|
2018-10-27 18:38:43 +02:00
|
|
|
&version_completed_cb,
|
2018-10-24 11:56:51 +02:00
|
|
|
vr);
|
|
|
|
auditor->vr = vr;
|
2018-10-22 16:00:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Disconnect from the auditor
|
|
|
|
*
|
|
|
|
* @param auditor the auditor handle
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
TALER_AUDITOR_disconnect (struct TALER_AUDITOR_Handle *auditor)
|
|
|
|
{
|
2018-10-24 11:56:51 +02:00
|
|
|
if (NULL != auditor->vr)
|
2018-10-22 16:00:06 +02:00
|
|
|
{
|
2018-10-24 11:56:51 +02:00
|
|
|
GNUNET_CURL_job_cancel (auditor->vr->job);
|
|
|
|
free_version_request (auditor->vr);
|
|
|
|
auditor->vr = NULL;
|
2018-10-22 16:00:06 +02:00
|
|
|
}
|
2018-10-24 11:56:51 +02:00
|
|
|
free_version_info (&auditor->vi);
|
2018-10-22 16:00:06 +02:00
|
|
|
if (NULL != auditor->retry_task)
|
|
|
|
{
|
|
|
|
GNUNET_SCHEDULER_cancel (auditor->retry_task);
|
|
|
|
auditor->retry_task = NULL;
|
|
|
|
}
|
|
|
|
GNUNET_free (auditor->url);
|
|
|
|
GNUNET_free (auditor);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* end of auditor_api_handle.c */
|