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
|
This file is part of TALER
|
||||||
Copyright (C) 2014-2018 GNUnet e.V.
|
Copyright (C) 2014-2018 GNUnet e.V.
|
||||||
|
|
||||||
TALER is free software; you can redistribute it and/or modify it under the
|
TALER is free software; you can redistribute it and/or modify it
|
||||||
terms of the GNU General Public License as published by the Free Software
|
under the terms of the GNU General Public License as published
|
||||||
Foundation; either version 3, or (at your option) any later version.
|
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
|
TALER is distributed in the hope that it will be useful, but
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
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
|
You should have received a copy of the GNU General Public
|
||||||
TALER; see the file COPYING. If not, see
|
License along with TALER; see the file COPYING. If not, see
|
||||||
<http://www.gnu.org/licenses/>
|
<http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file exchange-lib/exchange_api_handle.c
|
* @file exchange-lib/exchange_api_handle.c
|
||||||
* @brief Implementation of the "handle" component of the exchange's HTTP API
|
* @brief Implementation of the "handle" component of the exchange's HTTP API
|
||||||
@ -1372,21 +1375,25 @@ TALER_EXCHANGE_serialize_data (struct TALER_EXCHANGE_Handle *exchange)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialise a connection to the exchange. Will connect to the
|
* Initialise a connection to the exchange. Will connect to the
|
||||||
* exchange and obtain information about the exchange's master public
|
* exchange and obtain information about the exchange's master
|
||||||
* key and the exchange's auditor. The respective information will
|
* public key and the exchange's auditor.
|
||||||
* be passed to the @a cert_cb once available, and all future
|
* The respective information will be passed to the @a cert_cb
|
||||||
* interactions with the exchange will be checked to be signed
|
* once available, and all future interactions with the exchange
|
||||||
* (where appropriate) by the respective master key.
|
* will be checked to be signed (where appropriate) by the
|
||||||
|
* respective master key.
|
||||||
*
|
*
|
||||||
* @param ctx the context
|
* @param ctx the context
|
||||||
* @param url HTTP base URL for the exchange
|
* @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 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
|
* @return the exchange handle; NULL upon error
|
||||||
*/
|
*/
|
||||||
struct TALER_EXCHANGE_Handle *
|
struct TALER_EXCHANGE_Handle *
|
||||||
TALER_EXCHANGE_connect (struct GNUNET_CURL_Context *ctx,
|
TALER_EXCHANGE_connect
|
||||||
|
(struct GNUNET_CURL_Context *ctx,
|
||||||
const char *url,
|
const char *url,
|
||||||
TALER_EXCHANGE_CertificationCallback cert_cb,
|
TALER_EXCHANGE_CertificationCallback cert_cb,
|
||||||
void *cert_cb_cls,
|
void *cert_cb_cls,
|
||||||
|
@ -213,6 +213,7 @@ handle_wire_finished (void *cls,
|
|||||||
enum TALER_ErrorCode ec;
|
enum TALER_ErrorCode ec;
|
||||||
const json_t *j = response;
|
const json_t *j = response;
|
||||||
|
|
||||||
|
TALER_LOG_DEBUG ("Checking raw /wire response\n");
|
||||||
wh->job = NULL;
|
wh->job = NULL;
|
||||||
ec = TALER_EC_NONE;
|
ec = TALER_EC_NONE;
|
||||||
switch (response_code)
|
switch (response_code)
|
||||||
|
@ -60,6 +60,7 @@ batch_run (void *cls,
|
|||||||
struct BatchState *bs = cls;
|
struct BatchState *bs = cls;
|
||||||
|
|
||||||
bs->batch_ip++;
|
bs->batch_ip++;
|
||||||
|
if (NULL != bs->batch[bs->batch_ip].label)
|
||||||
TALER_LOG_DEBUG ("Running batched command: %s\n",
|
TALER_LOG_DEBUG ("Running batched command: %s\n",
|
||||||
bs->batch[bs->batch_ip].label);
|
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.
|
* Run the command.
|
||||||
*
|
*
|
||||||
@ -91,6 +119,7 @@ serialize_keys_cleanup (void *cls,
|
|||||||
json_decref (sks->keys);
|
json_decref (sks->keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GNUNET_free ((char *) sks->exchange_url);
|
||||||
GNUNET_free (sks);
|
GNUNET_free (sks);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,14 +169,22 @@ cb (void *cls,
|
|||||||
const struct TALER_EXCHANGE_Keys *keys,
|
const struct TALER_EXCHANGE_Keys *keys,
|
||||||
enum TALER_EXCHANGE_VersionCompatibility compat)
|
enum TALER_EXCHANGE_VersionCompatibility compat)
|
||||||
{
|
{
|
||||||
struct TALER_TESTING_Interpreter *is = cls;
|
struct ConnectWithStateState *cwss = cls;
|
||||||
|
|
||||||
if (NULL == keys)
|
if (GNUNET_YES == cwss->consumed)
|
||||||
TALER_TESTING_interpreter_fail (is);
|
{
|
||||||
|
TALER_LOG_DEBUG ("Reconnection /keys 'cb' invoked already,"
|
||||||
TALER_TESTING_interpreter_next (is);
|
" nothing to do\n");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cwss->consumed = GNUNET_YES;
|
||||||
|
if (NULL == keys)
|
||||||
|
TALER_TESTING_interpreter_fail (cwss->is);
|
||||||
|
|
||||||
|
TALER_LOG_DEBUG ("reconnect next CMD\n");
|
||||||
|
TALER_TESTING_interpreter_next (cwss->is);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run the command.
|
* Run the command.
|
||||||
@ -161,13 +198,14 @@ connect_with_state_run (void *cls,
|
|||||||
const struct TALER_TESTING_Command *cmd,
|
const struct TALER_TESTING_Command *cmd,
|
||||||
struct TALER_TESTING_Interpreter *is)
|
struct TALER_TESTING_Interpreter *is)
|
||||||
{
|
{
|
||||||
|
struct ConnectWithStateState *cwss = cls;
|
||||||
const struct TALER_TESTING_Command *state_cmd;
|
const struct TALER_TESTING_Command *state_cmd;
|
||||||
const json_t *serialized_keys;
|
const json_t *serialized_keys;
|
||||||
const char *state_reference = cls;
|
|
||||||
const char *exchange_url;
|
const char *exchange_url;
|
||||||
|
|
||||||
|
cwss->is = is;
|
||||||
state_cmd = TALER_TESTING_interpreter_lookup_command
|
state_cmd = TALER_TESTING_interpreter_lookup_command
|
||||||
(is, state_reference);
|
(is, cwss->state_reference);
|
||||||
|
|
||||||
/* Command providing serialized keys not found. */
|
/* Command providing serialized keys not found. */
|
||||||
if (NULL == state_cmd)
|
if (NULL == state_cmd)
|
||||||
@ -197,7 +235,7 @@ connect_with_state_run (void *cls,
|
|||||||
(is->ctx,
|
(is->ctx,
|
||||||
exchange_url,
|
exchange_url,
|
||||||
cb,
|
cb,
|
||||||
is,
|
cwss,
|
||||||
TALER_EXCHANGE_OPTION_DATA,
|
TALER_EXCHANGE_OPTION_DATA,
|
||||||
serialized_keys,
|
serialized_keys,
|
||||||
TALER_EXCHANGE_OPTION_END);
|
TALER_EXCHANGE_OPTION_END);
|
||||||
@ -216,7 +254,9 @@ connect_with_state_cleanup
|
|||||||
(void *cls,
|
(void *cls,
|
||||||
const struct TALER_TESTING_Command *cmd)
|
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;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make a connect-with-state CMD. This command
|
* Make a connect-with-state CMD. This command
|
||||||
* will use a serialized key state to reconnect
|
* 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,
|
TALER_TESTING_cmd_connect_with_state (const char *label,
|
||||||
const char *state_reference)
|
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 = {
|
struct TALER_TESTING_Command cmd = {
|
||||||
.cls = (char *) state_reference,
|
.cls = cwss,
|
||||||
.label = label,
|
.label = label,
|
||||||
.run = connect_with_state_run,
|
.run = connect_with_state_run,
|
||||||
.cleanup = connect_with_state_cleanup
|
.cleanup = connect_with_state_cleanup
|
||||||
|
@ -94,6 +94,7 @@ wire_cb (void *cls,
|
|||||||
&ws->is->commands[ws->is->ip];
|
&ws->is->commands[ws->is->ip];
|
||||||
struct TALER_Amount expected_fee;
|
struct TALER_Amount expected_fee;
|
||||||
|
|
||||||
|
TALER_LOG_DEBUG ("Checking parsed /wire response\n");
|
||||||
ws->wh = NULL;
|
ws->wh = NULL;
|
||||||
if (ws->expected_response_code != http_status)
|
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);
|
GNUNET_free (method);
|
||||||
}
|
}
|
||||||
if (GNUNET_OK != ws->method_found)
|
if (GNUNET_OK != ws->method_found)
|
||||||
@ -148,6 +151,7 @@ wire_cb (void *cls,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TALER_TESTING_interpreter_next (ws->is);
|
TALER_TESTING_interpreter_next (ws->is);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,6 +237,8 @@ struct TALER_TESTING_Command
|
|||||||
TALER_TESTING_cmd_end (void)
|
TALER_TESTING_cmd_end (void)
|
||||||
{
|
{
|
||||||
static struct TALER_TESTING_Command cmd;
|
static struct TALER_TESTING_Command cmd;
|
||||||
|
cmd.label = NULL;
|
||||||
|
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,13 +271,18 @@ interpreter_run (void *cls)
|
|||||||
|
|
||||||
if (NULL == cmd->label)
|
if (NULL == cmd->label)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
|
"Running command END\n");
|
||||||
is->result = GNUNET_OK;
|
is->result = GNUNET_OK;
|
||||||
GNUNET_SCHEDULER_shutdown ();
|
GNUNET_SCHEDULER_shutdown ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
"Running command `%s'\n",
|
"Running command `%s'\n",
|
||||||
cmd->label);
|
cmd->label);
|
||||||
|
|
||||||
cmd->run (cmd->cls,
|
cmd->run (cmd->cls,
|
||||||
cmd,
|
cmd,
|
||||||
is);
|
is);
|
||||||
@ -293,10 +300,16 @@ do_shutdown (void *cls)
|
|||||||
{
|
{
|
||||||
struct TALER_TESTING_Interpreter *is = cls;
|
struct TALER_TESTING_Interpreter *is = cls;
|
||||||
struct TALER_TESTING_Command *cmd;
|
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,
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
"Executing shutdown at `%s'\n",
|
"Executing shutdown at `%s'\n",
|
||||||
is->commands[is->ip].label);
|
label);
|
||||||
|
|
||||||
for (unsigned int j=0;NULL != (cmd = &is->commands[j])->label;j++)
|
for (unsigned int j=0;NULL != (cmd = &is->commands[j])->label;j++)
|
||||||
cmd->cleanup (cmd->cls,
|
cmd->cleanup (cmd->cls,
|
||||||
cmd);
|
cmd);
|
||||||
|
Loading…
Reference in New Issue
Block a user