From 93a6bbfc58ec48c774ecf475ec7e58184504bbc4 Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Tue, 8 Jan 2019 15:59:14 +0100 Subject: 5136: fix multiple invocations of /keys callback. Basically, we allow such a callback to be invoked only once. Subsequent invocations (due to keys updates / whatever) cause the callback to simply return in a do-nothing fashion. Also: adding a /wire CMD - that uses /keys - after serilized keys have been loaded. --- src/exchange-lib/exchange_api_handle.c | 51 ++++++++++-------- src/exchange-lib/exchange_api_wire.c | 9 ++-- src/exchange-lib/testing_api_cmd_batch.c | 5 +- src/exchange-lib/testing_api_cmd_serialize_keys.c | 65 +++++++++++++++++++---- src/exchange-lib/testing_api_cmd_wire.c | 4 ++ src/exchange-lib/testing_api_loop.c | 15 +++++- 6 files changed, 110 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/exchange-lib/exchange_api_handle.c b/src/exchange-lib/exchange_api_handle.c index 47b984386..6b2e30030 100644 --- a/src/exchange-lib/exchange_api_handle.c +++ b/src/exchange-lib/exchange_api_handle.c @@ -2,18 +2,21 @@ 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 + 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 */ + /** * @file exchange-lib/exchange_api_handle.c * @brief Implementation of the "handle" component of the exchange's HTTP API @@ -1372,25 +1375,29 @@ TALER_EXCHANGE_serialize_data (struct TALER_EXCHANGE_Handle *exchange) /** * 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 - * be passed to the @a cert_cb once available, and all future - * interactions with the exchange will be checked to be signed - * (where appropriate) by the respective master key. + * exchange and obtain information about the exchange's master + * public key and the exchange's auditor. + * The respective information will be passed to the @a cert_cb + * once available, and all future interactions with the exchange + * will be checked to be signed (where appropriate) by the + * respective master key. * * @param ctx the context * @param url HTTP base URL for the exchange - * @param cert_cb function to call with the exchange's certification information + * @param cert_cb function to call with the exchange's + * certification information * @param cert_cb_cls closure for @a cert_cb - * @param ... list of additional arguments, terminated by #TALER_EXCHANGE_OPTION_END. + * @param ... list of additional arguments, + * terminated by #TALER_EXCHANGE_OPTION_END. * @return the exchange handle; NULL upon error */ struct TALER_EXCHANGE_Handle * -TALER_EXCHANGE_connect (struct GNUNET_CURL_Context *ctx, - const char *url, - TALER_EXCHANGE_CertificationCallback cert_cb, - void *cert_cb_cls, - ...) +TALER_EXCHANGE_connect + (struct GNUNET_CURL_Context *ctx, + const char *url, + TALER_EXCHANGE_CertificationCallback cert_cb, + void *cert_cb_cls, + ...) { struct TALER_EXCHANGE_Handle *exchange; va_list ap; diff --git a/src/exchange-lib/exchange_api_wire.c b/src/exchange-lib/exchange_api_wire.c index c57ad6d92..0d4644dbf 100644 --- a/src/exchange-lib/exchange_api_wire.c +++ b/src/exchange-lib/exchange_api_wire.c @@ -213,6 +213,7 @@ handle_wire_finished (void *cls, enum TALER_ErrorCode ec; const json_t *j = response; + TALER_LOG_DEBUG ("Checking raw /wire response\n"); wh->job = NULL; ec = TALER_EC_NONE; switch (response_code) @@ -411,10 +412,10 @@ TALER_EXCHANGE_wire (struct TALER_EXCHANGE_Handle *exchange, eh = TEL_curl_easy_get (wh->url); ctx = TEAH_handle_to_context (exchange); wh->job = GNUNET_CURL_job_add (ctx, - eh, - GNUNET_YES, - &handle_wire_finished, - wh); + eh, + GNUNET_YES, + &handle_wire_finished, + wh); return wh; } diff --git a/src/exchange-lib/testing_api_cmd_batch.c b/src/exchange-lib/testing_api_cmd_batch.c index 85f03b251..a56c959a0 100644 --- a/src/exchange-lib/testing_api_cmd_batch.c +++ b/src/exchange-lib/testing_api_cmd_batch.c @@ -60,8 +60,9 @@ batch_run (void *cls, struct BatchState *bs = cls; bs->batch_ip++; - TALER_LOG_DEBUG ("Running batched command: %s\n", - bs->batch[bs->batch_ip].label); + if (NULL != bs->batch[bs->batch_ip].label) + TALER_LOG_DEBUG ("Running batched command: %s\n", + bs->batch[bs->batch_ip].label); /* hit end command, leap to next top-level command. */ if (NULL == bs->batch[bs->batch_ip].label) diff --git a/src/exchange-lib/testing_api_cmd_serialize_keys.c b/src/exchange-lib/testing_api_cmd_serialize_keys.c index fdc5c14da..38d32eadd 100644 --- a/src/exchange-lib/testing_api_cmd_serialize_keys.c +++ b/src/exchange-lib/testing_api_cmd_serialize_keys.c @@ -48,6 +48,34 @@ struct SerializeKeysState }; +/** + * Internal state for a connect-with-state CMD. + */ +struct ConnectWithStateState +{ + + /** + * Reference to a CMD that offers a serialized key-state + * that will be used in the reconnection. + */ + const char *state_reference; + + /** + * If set to GNUNET_YES, then the /keys callback has already + * been passed the control to the next CMD. This is necessary + * because it is not uncommon that the /keys callback gets + * invoked multiple times, and without this flag, we would keep + * going "next" CMD upon every invocation (causing impredictable + * behaviour as for the instruction pointer.) + */ + unsigned int consumed; + + /** + * Interpreter state. + */ + struct TALER_TESTING_Interpreter *is; +}; + /** * Run the command. * @@ -91,6 +119,7 @@ serialize_keys_cleanup (void *cls, json_decref (sks->keys); } + GNUNET_free ((char *) sks->exchange_url); GNUNET_free (sks); } @@ -140,15 +169,23 @@ cb (void *cls, const struct TALER_EXCHANGE_Keys *keys, enum TALER_EXCHANGE_VersionCompatibility compat) { - struct TALER_TESTING_Interpreter *is = cls; + struct ConnectWithStateState *cwss = cls; + + if (GNUNET_YES == cwss->consumed) + { + TALER_LOG_DEBUG ("Reconnection /keys 'cb' invoked already," + " nothing to do\n"); + return; + } + cwss->consumed = GNUNET_YES; if (NULL == keys) - TALER_TESTING_interpreter_fail (is); + TALER_TESTING_interpreter_fail (cwss->is); - TALER_TESTING_interpreter_next (is); + TALER_LOG_DEBUG ("reconnect next CMD\n"); + TALER_TESTING_interpreter_next (cwss->is); } - /** * Run the command. * @@ -161,13 +198,14 @@ connect_with_state_run (void *cls, const struct TALER_TESTING_Command *cmd, struct TALER_TESTING_Interpreter *is) { + struct ConnectWithStateState *cwss = cls; const struct TALER_TESTING_Command *state_cmd; const json_t *serialized_keys; - const char *state_reference = cls; const char *exchange_url; + cwss->is = is; state_cmd = TALER_TESTING_interpreter_lookup_command - (is, state_reference); + (is, cwss->state_reference); /* Command providing serialized keys not found. */ if (NULL == state_cmd) @@ -197,7 +235,7 @@ connect_with_state_run (void *cls, (is->ctx, exchange_url, cb, - is, + cwss, TALER_EXCHANGE_OPTION_DATA, serialized_keys, TALER_EXCHANGE_OPTION_END); @@ -216,7 +254,9 @@ connect_with_state_cleanup (void *cls, const struct TALER_TESTING_Command *cmd) { - return; + struct ConnectWithStateState *cwss = cls; + + GNUNET_free (cwss); } /** @@ -244,7 +284,6 @@ TALER_TESTING_cmd_serialize_keys (const char *label) return cmd; } - /** * Make a connect-with-state CMD. This command * will use a serialized key state to reconnect @@ -259,8 +298,14 @@ struct TALER_TESTING_Command TALER_TESTING_cmd_connect_with_state (const char *label, const char *state_reference) { + struct ConnectWithStateState *cwss; + + cwss = GNUNET_new (struct ConnectWithStateState); + cwss->state_reference = state_reference; + cwss->consumed = GNUNET_NO; + struct TALER_TESTING_Command cmd = { - .cls = (char *) state_reference, + .cls = cwss, .label = label, .run = connect_with_state_run, .cleanup = connect_with_state_cleanup diff --git a/src/exchange-lib/testing_api_cmd_wire.c b/src/exchange-lib/testing_api_cmd_wire.c index 283e8769f..113545499 100644 --- a/src/exchange-lib/testing_api_cmd_wire.c +++ b/src/exchange-lib/testing_api_cmd_wire.c @@ -94,6 +94,7 @@ wire_cb (void *cls, &ws->is->commands[ws->is->ip]; struct TALER_Amount expected_fee; + TALER_LOG_DEBUG ("Checking parsed /wire response\n"); ws->wh = NULL; if (ws->expected_response_code != http_status) { @@ -137,6 +138,8 @@ wire_cb (void *cls, } } } + TALER_LOG_DEBUG ("Freeing method '%s'\n", + method); GNUNET_free (method); } if (GNUNET_OK != ws->method_found) @@ -148,6 +151,7 @@ wire_cb (void *cls, return; } } + TALER_TESTING_interpreter_next (ws->is); } diff --git a/src/exchange-lib/testing_api_loop.c b/src/exchange-lib/testing_api_loop.c index f81bb75c4..3e7e36432 100644 --- a/src/exchange-lib/testing_api_loop.c +++ b/src/exchange-lib/testing_api_loop.c @@ -237,6 +237,8 @@ struct TALER_TESTING_Command TALER_TESTING_cmd_end (void) { static struct TALER_TESTING_Command cmd; + cmd.label = NULL; + return cmd; } @@ -269,13 +271,18 @@ interpreter_run (void *cls) if (NULL == cmd->label) { + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Running command END\n"); is->result = GNUNET_OK; GNUNET_SCHEDULER_shutdown (); return; } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Running command `%s'\n", cmd->label); + cmd->run (cmd->cls, cmd, is); @@ -293,10 +300,16 @@ do_shutdown (void *cls) { struct TALER_TESTING_Interpreter *is = cls; struct TALER_TESTING_Command *cmd; + const char *label; + + label = is->commands[is->ip].label; + if (NULL == label) + label = "END"; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Executing shutdown at `%s'\n", - is->commands[is->ip].label); + label); + for (unsigned int j=0;NULL != (cmd = &is->commands[j])->label;j++) cmd->cleanup (cmd->cls, cmd); -- cgit v1.2.3