From c09c900922079be0314009719042a9fd08df798e Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 13 Oct 2018 08:15:02 +0200 Subject: implement deserialization logic for #5136 --- src/exchange-lib/exchange_api_handle.c | 110 +++++++++++++++++++++++++++++++-- src/include/taler_exchange_service.h | 25 +++++++- 2 files changed, 129 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/exchange-lib/exchange_api_handle.c b/src/exchange-lib/exchange_api_handle.c index a5f4f6969..3891ee9c1 100644 --- a/src/exchange-lib/exchange_api_handle.c +++ b/src/exchange-lib/exchange_api_handle.c @@ -1102,6 +1102,89 @@ header_cb (char *buffer, /* ********************* public API ******************* */ +/** + * Deserialize the key data and use it to bootstrap @a exchange to + * more efficiently recover the state. Errors in @a data must be + * tolerated (i.e. by re-downloading instead). + * + * @param exchange which exchange's key and wire data should be deserialized + * @return data the data to deserialize + */ +static void +deserialize_data (struct TALER_EXCHANGE_Handle *exchange, + const json_t *data) +{ + enum TALER_EXCHANGE_VersionCompatibility vc; + json_t *keys; + const char *url; + struct GNUNET_TIME_Absolute expire; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_json ("keys", + &keys), + GNUNET_JSON_spec_string ("url", + &url), + GNUNET_JSON_spec_absolute_time ("expire", + &expire), + GNUNET_JSON_spec_end() + }; + struct TALER_EXCHANGE_Keys key_data; + + if (NULL == data) + return; + if (GNUNET_OK != + GNUNET_JSON_parse (data, + spec, + NULL, NULL)) + { + GNUNET_break_op (0); + return; + } + if (0 != strcmp (url, + exchange->url)) + { + GNUNET_break (0); + return; + } + memset (&key_data, + 0, + sizeof (struct TALER_EXCHANGE_Keys)); + if (GNUNET_OK != + decode_keys_json (keys, + &key_data, + &vc)) + { + GNUNET_break (0); + return; + } + /* decode successful, initialize with the result */ + GNUNET_assert (NULL == exchange->key_data_raw); + exchange->key_data_raw = json_deep_copy (keys); + exchange->key_data = key_data; + exchange->key_data_expiration = expire; + exchange->state = MHS_CERT; + /* notify application about the key information */ + exchange->cert_cb (exchange->cert_cb_cls, + &exchange->key_data, + vc); +} + + +/** + * Serialize the latest key data from @a exchange to be persisted on + * disk (to be used with #TALER_EXCHANGE_OPTION_DATA to more + * efficiently recover the state). + * + * @param exchange which exchange's key and wire data should be serialized + * @return NULL on error (i.e. no current data available); otherwise + * json object owned by the caller + */ +json_t * +TALER_EXCHANGE_serialize_data (struct TALER_EXCHANGE_Handle *exchange) +{ + return NULL; +} + + /** * Initialise a connection to the exchange. Will connect to the * exchange and obtain information about the exchange's master public @@ -1126,11 +1209,8 @@ TALER_EXCHANGE_connect (struct GNUNET_CURL_Context *ctx, { struct TALER_EXCHANGE_Handle *exchange; va_list ap; + enum TALER_EXCHANGE_Option opt; - va_start (ap, cert_cb_cls); - GNUNET_assert (TALER_EXCHANGE_OPTION_END == - va_arg (ap, int)); - va_end (ap); exchange = GNUNET_new (struct TALER_EXCHANGE_Handle); exchange->ctx = ctx; exchange->url = GNUNET_strdup (url); @@ -1138,6 +1218,28 @@ TALER_EXCHANGE_connect (struct GNUNET_CURL_Context *ctx, exchange->cert_cb_cls = cert_cb_cls; exchange->retry_task = GNUNET_SCHEDULER_add_now (&request_keys, exchange); + va_start (ap, cert_cb_cls); + while (TALER_EXCHANGE_OPTION_END != + (opt = va_arg (ap, int))) + { + switch (opt) { + case TALER_EXCHANGE_OPTION_END: + GNUNET_assert (0); + break; + case TALER_EXCHANGE_OPTION_DATA: + { + const json_t *data = va_arg (ap, const json_t *); + + deserialize_data (exchange, + data); + break; + } + default: + GNUNET_assert (0); + break; + } + } + va_end (ap); return exchange; } diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h index a18672f5a..1ddd7c13e 100644 --- a/src/include/taler_exchange_service.h +++ b/src/include/taler_exchange_service.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2017 Taler Systems SA + Copyright (C) 2014-2018 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software @@ -39,8 +39,16 @@ enum TALER_EXCHANGE_Option /** * Terminator (end of option list). */ - TALER_EXCHANGE_OPTION_END = 0 + TALER_EXCHANGE_OPTION_END = 0, + /** + * Followed by a "const json_t *" that was previously returned for + * this exchange URL by #TALER_EXCHANGE_serialize_data(). Used to + * resume a connection to an exchange without having to re-download + * /keys data (or at least only download the deltas). + */ + TALER_EXCHANGE_OPTION_DATA + }; @@ -348,6 +356,19 @@ TALER_EXCHANGE_connect (struct GNUNET_CURL_Context *ctx, ...); +/** + * Serialize the latest key data from @a exchange to be persisted + * on disk (to be used with #TALER_EXCHANGE_OPTION_DATA to more + * efficiently recover the state). + * + * @param exchange which exchange's key and wire data should be serialized + * @return NULL on error (i.e. no current data available); otherwise + * json object owned by the caller + */ +json_t * +TALER_EXCHANGE_serialize_data (struct TALER_EXCHANGE_Handle *exchange); + + /** * Disconnect from the exchange. * -- cgit v1.2.3