finish first implementation of /version API call for the auditor

This commit is contained in:
Christian Grothoff 2018-10-24 11:56:51 +02:00
parent d83c840d25
commit 69a8c16e58
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
4 changed files with 94 additions and 109 deletions

View File

@ -15,9 +15,8 @@
<http://www.gnu.org/licenses/> <http://www.gnu.org/licenses/>
*/ */
/** /**
* @file auditor-lib/auditor_api_deposit.c * @file auditor-lib/auditor_api_deposit_confirmation.c
* @brief Implementation of the /deposit request of the auditor's HTTP API * @brief Implementation of the /deposit request of the auditor's HTTP API
* @author Sree Harsha Totakura <sreeharsha@totakura.in>
* @author Christian Grothoff * @author Christian Grothoff
*/ */
#include "platform.h" #include "platform.h"

View File

@ -111,7 +111,7 @@ struct TALER_AUDITOR_Handle
* Data for the request to get the /version of a auditor, * Data for the request to get the /version of a auditor,
* NULL once we are past stage #MHS_INIT. * NULL once we are past stage #MHS_INIT.
*/ */
struct VersionRequest *kr; struct VersionRequest *vr;
/** /**
* Task for retrying /version request. * Task for retrying /version request.
@ -119,10 +119,10 @@ struct TALER_AUDITOR_Handle
struct GNUNET_SCHEDULER_Task *retry_task; struct GNUNET_SCHEDULER_Task *retry_task;
/** /**
* Key data of the auditor, only valid if * /version data of the auditor, only valid if
* @e handshake_complete is past stage #MHS_VERSION. * @e handshake_complete is past stage #MHS_VERSION.
*/ */
struct TALER_AUDITOR_Version key_data; struct TALER_AUDITOR_VersionInformation vi;
/** /**
* Retry /version frequency. * Retry /version frequency.
@ -167,54 +167,26 @@ struct VersionRequest
* Note that this does not cancel the request * Note that this does not cancel the request
* itself. * itself.
* *
* @param kr request to free * @param vr request to free
*/ */
static void static void
free_version_request (struct VersionRequest *kr) free_version_request (struct VersionRequest *vr)
{ {
GNUNET_free (kr->url); GNUNET_free (vr->url);
GNUNET_free (kr); GNUNET_free (vr);
} }
/** /**
* Parse a auditor's auditor information encoded in JSON. * Free version data object.
* *
* @param[out] auditor where to return the result * @param vi data to free (pointer itself excluded)
* @param check_sig should we check signatures
* @param[in] auditor_obj json to parse
* @param key_data information about denomination version
* @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if the signature is
* invalid or the json malformed.
*/ */
static int static void
parse_json_auditor (struct TALER_AUDITOR_AuditorInformation *auditor, free_version_info (struct TALER_AUDITOR_VersionInformation *vi)
int check_sigs,
json_t *auditor_obj,
const struct TALER_AUDITOR_Version *key_data)
{ {
const char *auditor_url; GNUNET_free_non_null (vi->version);
struct GNUNET_JSON_Specification spec[] = { vi->version = NULL;
GNUNET_JSON_spec_fixed_auto ("auditor_pub",
&auditor->auditor_pub),
GNUNET_JSON_spec_string ("auditor_url",
&auditor_url),
GNUNET_JSON_spec_json ("denomination_version",
&version),
GNUNET_JSON_spec_end()
};
if (GNUNET_OK !=
GNUNET_JSON_parse (auditor_obj,
spec,
NULL, NULL))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
auditor->auditor_url = GNUNET_strdup (auditor_url);
GNUNET_JSON_parse_free (spec);
return GNUNET_OK;
} }
@ -224,15 +196,15 @@ parse_json_auditor (struct TALER_AUDITOR_AuditorInformation *auditor,
* *
* @param[in] resp_obj JSON object to parse * @param[in] resp_obj JSON object to parse
* @param check_sig #GNUNET_YES if we should check the signature * @param check_sig #GNUNET_YES if we should check the signature
* @param[out] key_data where to store the results we decoded * @param[out] vi where to store the results we decoded
* @param[out] where to store version compatibility data * @param[out] vc where to store version compatibility data
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error (malformed JSON) * @return #GNUNET_OK on success, #GNUNET_SYSERR on error (malformed JSON)
*/ */
static int static int
decode_version_json (const json_t *resp_obj, decode_version_json (const json_t *resp_obj,
int check_sig, int check_sig,
struct TALER_AUDITOR_Version *key_data, struct TALER_AUDITOR_VersionInformation *vi,
enum TALER_AUDITOR_VersionCompatibility *vc) enum TALER_AUDITOR_VersionCompatibility *vc)
{ {
struct TALER_AuditorPublicKeyP pub; struct TALER_AuditorPublicKeyP pub;
unsigned int age; unsigned int age;
@ -240,9 +212,9 @@ decode_version_json (const json_t *resp_obj,
unsigned int current; unsigned int current;
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_string ("version", GNUNET_JSON_spec_string ("version",
&ver), &vi->version),
GNUNET_JSON_spec_fixed_auto ("master_public_key", GNUNET_JSON_spec_fixed_auto ("master_public_key",
&key_data->master_pub), &vi->auditor_pub),
GNUNET_JSON_spec_end() GNUNET_JSON_spec_end()
}; };
@ -260,13 +232,14 @@ decode_version_json (const json_t *resp_obj,
GNUNET_break_op (0); GNUNET_break_op (0);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
if (3 != sscanf (ver, if (3 != sscanf (vi->version,
"%u:%u:%u", "%u:%u:%u",
&current, &current,
&revision, &revision,
&age)) &age))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
free_version_info (vi);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
*vc = TALER_AUDITOR_VC_MATCH; *vc = TALER_AUDITOR_VC_MATCH;
@ -282,24 +255,10 @@ decode_version_json (const json_t *resp_obj,
if (TALER_PROTOCOL_CURRENT - TALER_PROTOCOL_AGE > current) if (TALER_PROTOCOL_CURRENT - TALER_PROTOCOL_AGE > current)
*vc |= TALER_AUDITOR_VC_INCOMPATIBLE; *vc |= TALER_AUDITOR_VC_INCOMPATIBLE;
} }
key_data->version = GNUNET_strdup (ver);
return GNUNET_OK; return GNUNET_OK;
} }
/**
* Free key data object.
*
* @param key_data data to free (pointer itself excluded)
*/
static void
free_key_data (struct TALER_AUDITOR_Keys *key_data)
{
GNUNET_free_non_null (key_data->version);
key_data->version = NULL;
}
/** /**
* Initiate download of /version from the auditor. * Initiate download of /version from the auditor.
* *
@ -322,25 +281,26 @@ version_completed_cb (void *cls,
long response_code, long response_code,
const json_t *resp_obj) const json_t *resp_obj)
{ {
struct VersionRequest *kr = cls; struct VersionRequest *vr = cls;
struct TALER_AUDITOR_Handle *auditor = kr->auditor; struct TALER_AUDITOR_Handle *auditor = vr->auditor;
enum TALER_AUDITOR_VersionCompatibility vc; enum TALER_AUDITOR_VersionCompatibility vc;
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Received version from URL `%s' with status %ld.\n", "Received version from URL `%s' with status %ld.\n",
kr->url, vr->url,
response_code); response_code);
vc = TALER_AUDITOR_VC_PROTOCOL_ERROR; vc = TALER_AUDITOR_VC_PROTOCOL_ERROR;
switch (response_code) switch (response_code)
{ {
case 0: case 0:
free_version_request (kr); case MHD_HTTP_INTERNAL_SERVER_ERROR:
auditor->kr = NULL; free_version_request (vr);
auditor->vr = NULL;
GNUNET_assert (NULL == auditor->retry_task); GNUNET_assert (NULL == auditor->retry_task);
auditor->retry_delay = AUDITOR_LIB_BACKOFF (auditor->retry_delay); auditor->retry_delay = AUDITOR_LIB_BACKOFF (auditor->retry_delay);
auditor->retry_task = GNUNET_SCHEDULER_add_delayed (auditor->retry_delay, auditor->retry_task = GNUNET_SCHEDULER_add_delayed (auditor->retry_delay,
&request_version, &request_version,
auditor); auditor);
return; return;
case MHD_HTTP_OK: case MHD_HTTP_OK:
if (NULL == resp_obj) if (NULL == resp_obj)
@ -348,13 +308,11 @@ version_completed_cb (void *cls,
response_code = 0; response_code = 0;
break; break;
} }
/* We keep the denomination version and auditor signatures from the
previous iteration (/version cherry picking) */
if (GNUNET_OK != if (GNUNET_OK !=
decode_version_json (resp_obj, decode_version_json (resp_obj,
GNUNET_YES, GNUNET_YES,
&kd, &auditor->vi,
&vc)) &vc))
{ {
response_code = 0; response_code = 0;
break; break;
@ -367,14 +325,12 @@ version_completed_cb (void *cls,
(unsigned int) response_code); (unsigned int) response_code);
break; break;
} }
auditor->key_data = kd;
if (MHD_HTTP_OK != response_code) if (MHD_HTTP_OK != response_code)
{ {
auditor->kr = NULL; auditor->vr = NULL;
free_version_request (kr); free_version_request (vr);
auditor->state = MHS_FAILED; auditor->state = MHS_FAILED;
free_key_data (&kd_old); free_version_info (&auditor->vi);
/* notify application that we failed */ /* notify application that we failed */
auditor->version_cb (auditor->version_cb_cls, auditor->version_cb (auditor->version_cb_cls,
NULL, NULL,
@ -382,14 +338,13 @@ version_completed_cb (void *cls,
return; return;
} }
auditor->kr = NULL; auditor->vr = NULL;
free_version_request (kr); free_version_request (vr);
auditor->state = MHS_VERSION; auditor->state = MHS_VERSION;
/* notify application about the key information */ /* notify application about the key information */
auditor->version_cb (auditor->version_cb_cls, auditor->version_cb (auditor->version_cb_cls,
&auditor->key_data, &auditor->vi,
vc); vc);
free_key_data (&kd_old);
} }
@ -426,7 +381,7 @@ MAH_handle_is_ready (struct TALER_AUDITOR_Handle *h)
* Obtain the URL to use for an API request. * Obtain the URL to use for an API request.
* *
* @param h handle for the auditor * @param h handle for the auditor
* @param path Taler API path (i.e. "/reserve/withdraw") * @param path Taler API path (i.e. "/deposit-confirmation")
* @return the full URL to use with cURL * @return the full URL to use with cURL
*/ */
char * char *
@ -442,7 +397,7 @@ MAH_path_to_url (struct TALER_AUDITOR_Handle *h,
* Obtain the URL to use for an API request. * Obtain the URL to use for an API request.
* *
* @param base_url base URL of the auditor (i.e. "http://auditor/") * @param base_url base URL of the auditor (i.e. "http://auditor/")
* @param path Taler API path (i.e. "/reserve/withdraw") * @param path Taler API path (i.e. "/deposit-confirmation")
* @return the full URL to use with cURL * @return the full URL to use with cURL
*/ */
char * char *
@ -476,7 +431,7 @@ MAH_path_to_url2 (const char *base_url,
* *
* @param ctx the context * @param ctx the context
* @param url HTTP base URL for the auditor * @param url HTTP base URL for the auditor
* @param version_cb function to call with the auditor's versionification information * @param version_cb function to call with the auditor's version information
* @param version_cb_cls closure for @a version_cb * @param version_cb_cls closure for @a version_cb
* @return the auditor handle; NULL upon error * @return the auditor handle; NULL upon error
*/ */
@ -508,19 +463,19 @@ static void
request_version (void *cls) request_version (void *cls)
{ {
struct TALER_AUDITOR_Handle *auditor = cls; struct TALER_AUDITOR_Handle *auditor = cls;
struct VersionRequest *kr; struct VersionRequest *vr;
CURL *eh; CURL *eh;
auditor->retry_task = NULL; auditor->retry_task = NULL;
GNUNET_assert (NULL == auditor->kr); GNUNET_assert (NULL == auditor->vr);
kr = GNUNET_new (struct VersionRequest); vr = GNUNET_new (struct VersionRequest);
kr->auditor = auditor; vr->auditor = auditor;
kr->url = MAH_path_to_url (auditor, vr->url = MAH_path_to_url (auditor,
"/version"); "/version");
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Requesting version with URL `%s'.\n", "Requesting version with URL `%s'.\n",
kr->url); vr->url);
eh = TEL_curl_easy_get (kr->url); eh = TEL_curl_easy_get (vr->url);
GNUNET_assert (CURLE_OK == GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh, curl_easy_setopt (eh,
CURLOPT_VERBOSE, CURLOPT_VERBOSE,
@ -532,13 +487,13 @@ request_version (void *cls)
GNUNET_assert (CURLE_OK == GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh, curl_easy_setopt (eh,
CURLOPT_HEADERDATA, CURLOPT_HEADERDATA,
kr)); vr));
kr->job = GNUNET_CURL_job_add (auditor->ctx, vr->job = GNUNET_CURL_job_add (auditor->ctx,
eh, eh,
GNUNET_NO, GNUNET_NO,
(GC_JCC) &version_completed_cb, (GC_JCC) &version_completed_cb,
kr); vr);
auditor->kr = kr; auditor->vr = vr;
} }
@ -550,13 +505,13 @@ request_version (void *cls)
void void
TALER_AUDITOR_disconnect (struct TALER_AUDITOR_Handle *auditor) TALER_AUDITOR_disconnect (struct TALER_AUDITOR_Handle *auditor)
{ {
if (NULL != auditor->kr) if (NULL != auditor->vr)
{ {
GNUNET_CURL_job_cancel (auditor->kr->job); GNUNET_CURL_job_cancel (auditor->vr->job);
free_version_request (auditor->kr); free_version_request (auditor->vr);
auditor->kr = NULL; auditor->vr = NULL;
} }
free_key_data (&auditor->key_data); free_version_info (&auditor->vi);
if (NULL != auditor->retry_task) if (NULL != auditor->retry_task)
{ {
GNUNET_SCHEDULER_cancel (auditor->retry_task); GNUNET_SCHEDULER_cancel (auditor->retry_task);

View File

@ -48,7 +48,7 @@ MAH_handle_is_ready (struct TALER_AUDITOR_Handle *h);
* Obtain the URL to use for an API request. * Obtain the URL to use for an API request.
* *
* @param h the auditor handle to query * @param h the auditor handle to query
* @param path Taler API path (i.e. "/reserve/withdraw") * @param path Taler API path (i.e. "/deposit-confirmation")
* @return the full URL to use with cURL * @return the full URL to use with cURL
*/ */
char * char *
@ -60,7 +60,7 @@ MAH_path_to_url (struct TALER_AUDITOR_Handle *h,
* Obtain the URL to use for an API request. * Obtain the URL to use for an API request.
* *
* @param base_url base URL of the auditor (i.e. "http://auditor/") * @param base_url base URL of the auditor (i.e. "http://auditor/")
* @param path Taler API path (i.e. "/reserve/withdraw") * @param path Taler API path (i.e. "/deposit-confirmation")
* @return the full URL to use with cURL * @return the full URL to use with cURL
*/ */
char * char *

View File

@ -136,7 +136,7 @@ struct TALER_AUDITOR_Handle;
* *
* @param ctx the context * @param ctx the context
* @param url HTTP base URL for the auditor * @param url HTTP base URL for the auditor
* @param version_cb function to call with the auditor's versionification information * @param version_cb function to call with the auditor's version information
* @param version_cb_cls closure for @a version_cb * @param version_cb_cls closure for @a version_cb
* @return the auditor handle; NULL upon error * @return the auditor handle; NULL upon error
*/ */
@ -156,4 +156,35 @@ void
TALER_AUDITOR_disconnect (struct TALER_AUDITOR_Handle *auditor); TALER_AUDITOR_disconnect (struct TALER_AUDITOR_Handle *auditor);
/**
* @brief A DepositConfirmation Handle
*/
struct TALER_AUDITOR_DepositConfirmationHandle;
/**
* Signature of functions called with the result from our call to the
* auditor's /deposit-confirmation handler.
*
* @param cls closure
* @param http_status HTTP status code, 200 on success
* @param ec taler protocol error status code, 0 on success
* @param json raw json response
*/
typedef void
(*TALER_AUDITOR_DepositConfirmationResultCallback)(void *cls,
unsigned int http_status,
enum TALER_ErrorCode ec,
const json_t *json);
/**
* Cancel a deposit-confirmation permission request. This function cannot be used
* on a request handle if a response is already served for it.
*
* @param deposit-confirmation the deposit-confirmation permission request handle
*/
void
TALER_AUDITOR_deposit_confirmation_cancel (struct TALER_AUDITOR_DepositConfirmationHandle *deposit_confirmation);
#endif /* _TALER_AUDITOR_SERVICE_H */ #endif /* _TALER_AUDITOR_SERVICE_H */