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.
This commit is contained in:
parent
00596e245e
commit
93a6bbfc58
@ -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 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.
|
||||
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
|
||||
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 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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user