aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2018-10-13 08:15:02 +0200
committerChristian Grothoff <christian@grothoff.org>2018-10-13 08:15:02 +0200
commitc09c900922079be0314009719042a9fd08df798e (patch)
treebe01288ec82d6cd1c8fb16cf3145acb68540e76c
parenteb1b6fbc97895356f2794927f81463d43c23c76a (diff)
implement deserialization logic for #5136
-rw-r--r--src/exchange-lib/exchange_api_handle.c110
-rw-r--r--src/include/taler_exchange_service.h25
2 files changed, 129 insertions, 6 deletions
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
@@ -1103,6 +1103,89 @@ header_cb (char *buffer,
/**
+ * 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
* key and the exchange's auditor. The respective information will
@@ -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
+
};
@@ -349,6 +357,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.
*
* @param exchange the exchange handle