make exchange API more uniform in how information is returned

This commit is contained in:
Christian Grothoff 2020-04-05 22:05:38 +02:00
parent 5059da7108
commit bf8c5982a2
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
37 changed files with 958 additions and 836 deletions

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014-2018 Taler Systems SA Copyright (C) 2014-2020 Taler Systems SA
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 under the
terms of the GNU Affero General Public License as published by the Free Software terms of the GNU Affero General Public License as published by the Free Software
@ -106,18 +106,59 @@ enum TALER_AUDITOR_VersionCompatibility
}; };
/**
* General information about the HTTP response we obtained
* from the auditor for a request.
*/
struct TALER_AUDITOR_HttpResponse
{
/**
* The complete JSON reply. NULL if we failed to parse the
* reply (too big, invalid JSON).
*/
const json_t *reply;
/**
* Set to the human-readable 'hint' that is optionally
* provided by the exchange together with errors. NULL
* if no hint was provided or if there was no error.
*/
const char *hint;
/**
* HTTP status code for the response. 0 if the
* HTTP request failed and we did not get any answer, or
* if the answer was invalid and we set @a ec to a
* client-side error code.
*/
unsigned int http_status;
/**
* Taler error code. #TALER_EC_NONE if everything was
* OK. Usually set to the "code" field of an error
* response, but may be set to values created at the
* client side, for example when the response was
* not in JSON format or was otherwise ill-formed.
*/
enum TALER_ErrorCode ec;
};
/** /**
* Function called with information about the auditor. * Function called with information about the auditor.
* *
* @param cls closure * @param cls closure
* @param hr HTTP response data
* @param vi basic information about the auditor * @param vi basic information about the auditor
* @param compat protocol compatibility information * @param compat protocol compatibility information
*/ */
typedef void typedef void
(*TALER_AUDITOR_VersionCallback) ( (*TALER_AUDITOR_VersionCallback) (
void *cls, void *cls,
const struct const struct TALER_AUDITOR_HttpResponse *hr,
TALER_AUDITOR_VersionInformation *vi, const struct TALER_AUDITOR_VersionInformation *vi,
enum TALER_AUDITOR_VersionCompatibility compat); enum TALER_AUDITOR_VersionCompatibility compat);
@ -169,15 +210,12 @@ struct TALER_AUDITOR_DepositConfirmationHandle;
* auditor's /deposit-confirmation handler. * auditor's /deposit-confirmation handler.
* *
* @param cls closure * @param cls closure
* @param http_status HTTP status code, 200 on success * @param hr HTTP response data
* @param ec taler protocol error status code, 0 on success
* @param json raw json response
*/ */
typedef void typedef void
(*TALER_AUDITOR_DepositConfirmationResultCallback)(void *cls, (*TALER_AUDITOR_DepositConfirmationResultCallback)(
unsigned int http_status, void *cls,
enum TALER_ErrorCode ec, const struct TALER_AUDITOR_HttpResponse *hr);
const json_t *json);
/** /**
@ -274,20 +312,16 @@ struct TALER_AUDITOR_ExchangeInfo
* Function called with the result from /exchagnes. * Function called with the result from /exchagnes.
* *
* @param cls closure * @param cls closure
* @param http_status the HTTP status code, 200 on success * @param hr HTTP response data
* @param ec detailed Taler error status code, #TALER_EC_NONE on success
* @param num_exchanges length of array at @a ei * @param num_exchanges length of array at @a ei
* @param ei information about exchanges returned by the auditor * @param ei information about exchanges returned by the auditor
* @param raw_response raw JSON response
*/ */
typedef void typedef void
(*TALER_AUDITOR_ListExchangesResultCallback)( (*TALER_AUDITOR_ListExchangesResultCallback)(
void *cls, void *cls,
unsigned int http_status, const struct TALER_AUDITOR_HttpResponse *hr,
enum TALER_ErrorCode ec,
unsigned int num_exchanges, unsigned int num_exchanges,
const struct TALER_AUDITOR_ExchangeInfo *ei, const struct TALER_AUDITOR_ExchangeInfo *ei);
const json_t *raw_response);
/** /**
* Submit an /exchanges request to the auditor and get the * Submit an /exchanges request to the auditor and get the

View File

@ -117,6 +117,13 @@ enum TALER_ErrorCode
*/ */
TALER_EC_HOLE_IN_WIRE_FEE_STRUCTURE = 13, TALER_EC_HOLE_IN_WIRE_FEE_STRUCTURE = 13,
/**
* The version string given does not follow the expected
* CURRENT:REVISION:AGE Format. Generated as an error on the client
* side.
*/
TALER_EC_VERSION_MALFORMED = 14,
/** /**
* The exchange failed to even just initialize its connection to the * The exchange failed to even just initialize its connection to the
* database. This response is provided with HTTP status code * database. This response is provided with HTTP status code
@ -1110,6 +1117,12 @@ enum TALER_ErrorCode
*/ */
TALER_EC_KEYS_TIMETRAVEL_FORBIDDEN = 1902, TALER_EC_KEYS_TIMETRAVEL_FORBIDDEN = 1902,
/**
* The keys response was malformed. This error is generated client-
* side.
*/
TALER_EC_KEYS_INVALID = 1903,
/** /**
* The backend could not find the merchant instance specified in the * The backend could not find the merchant instance specified in the
* request. This response is provided with HTTP status code * request. This response is provided with HTTP status code

View File

@ -351,26 +351,62 @@ enum TALER_EXCHANGE_VersionCompatibility
}; };
/**
* General information about the HTTP response we obtained
* from the exchange for a request.
*/
struct TALER_EXCHANGE_HttpResponse
{
/**
* The complete JSON reply. NULL if we failed to parse the
* reply (too big, invalid JSON).
*/
const json_t *reply;
/**
* Set to the human-readable 'hint' that is optionally
* provided by the exchange together with errors. NULL
* if no hint was provided or if there was no error.
*/
const char *hint;
/**
* HTTP status code for the response. 0 if the
* HTTP request failed and we did not get any answer, or
* if the answer was invalid and we set @a ec to a
* client-side error code.
*/
unsigned int http_status;
/**
* Taler error code. #TALER_EC_NONE if everything was
* OK. Usually set to the "code" field of an error
* response, but may be set to values created at the
* client side, for example when the response was
* not in JSON format or was otherwise ill-formed.
*/
enum TALER_ErrorCode ec;
};
/** /**
* Function called with information about who is auditing * Function called with information about who is auditing
* a particular exchange and what key the exchange is using. * a particular exchange and what key the exchange is using.
* *
* @param cls closure * @param cls closure
* @param hr HTTP response data
* @param keys information about the various keys used * @param keys information about the various keys used
* by the exchange, NULL if /keys failed * by the exchange, NULL if /keys failed
* @param compat protocol compatibility information * @param compat protocol compatibility information
* @param ec error code, #TALER_EC_NONE on success
* @param http_status status returned by /keys, #MHD_HTTP_OK on success
* @param full_reply JSON body of /keys request, NULL if reply was not in JSON
*/ */
typedef void typedef void
(*TALER_EXCHANGE_CertificationCallback) ( (*TALER_EXCHANGE_CertificationCallback) (
void *cls, void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr,
const struct TALER_EXCHANGE_Keys *keys, const struct TALER_EXCHANGE_Keys *keys,
enum TALER_EXCHANGE_VersionCompatibility compat, enum TALER_EXCHANGE_VersionCompatibility compat);
enum TALER_ErrorCode ec,
unsigned int http_status,
const json_t *full_reply);
/** /**
@ -650,21 +686,16 @@ struct TALER_EXCHANGE_WireAccount
* exchange, @a http_status will also be zero. * exchange, @a http_status will also be zero.
* *
* @param cls closure * @param cls closure
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful request; * @param hr HTTP response data
* 0 if the exchange's reply is bogus (fails to follow the protocol)
* @param ec taler-specific error code, #TALER_EC_NONE on success
* @param accounts_len length of the @a accounts array * @param accounts_len length of the @a accounts array
* @param accounts list of wire accounts of the exchange, NULL on error * @param accounts list of wire accounts of the exchange, NULL on error
* @param full_reply the complete reply from the exchange (if it was in JSON)
*/ */
typedef void typedef void
(*TALER_EXCHANGE_WireCallback) ( (*TALER_EXCHANGE_WireCallback) (
void *cls, void *cls,
unsigned int http_status, const struct TALER_EXCHANGE_HttpResponse *hr,
enum TALER_ErrorCode ec,
unsigned int accounts_len, unsigned int accounts_len,
const struct TALER_EXCHANGE_WireAccount *accounts, const struct TALER_EXCHANGE_WireAccount *accounts);
const json_t *full_reply);
/** /**
@ -722,21 +753,16 @@ struct TALER_EXCHANGE_DepositHandle;
* deposit permission request to a exchange. * deposit permission request to a exchange.
* *
* @param cls closure * @param cls closure
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful deposit; * @param hr HTTP response data
* 0 if the exchange's reply is bogus (fails to follow the protocol)
* @param exchange_sig signature provided by the exchange * @param exchange_sig signature provided by the exchange
* @param sign_key exchange key used to sign @a obj, or NULL * @param sign_key exchange key used to sign @a obj, or NULL
* @param obj the received JSON reply, should be kept as proof (and, in case of errors,
* be forwarded to the customer)
*/ */
typedef void typedef void
(*TALER_EXCHANGE_DepositResultCallback) ( (*TALER_EXCHANGE_DepositResultCallback) (
void *cls, void *cls,
unsigned int http_status, const struct TALER_EXCHANGE_HttpResponse *hr,
enum TALER_ErrorCode ec,
const struct TALER_ExchangeSignatureP *exchange_sig, const struct TALER_ExchangeSignatureP *exchange_sig,
const struct TALER_ExchangePublicKeyP *sign_key, const struct TALER_ExchangePublicKeyP *sign_key);
const json_t *obj);
/** /**
@ -822,20 +848,14 @@ struct TALER_EXCHANGE_RefundHandle;
* refund request to an exchange. * refund request to an exchange.
* *
* @param cls closure * @param cls closure
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful deposit; * @param hr HTTP response data
* 0 if the exchange's reply is bogus (fails to follow the protocol)
* @param ec taler-specific error code, #TALER_EC_NONE on success
* @param sign_key exchange key used to sign @a obj, or NULL * @param sign_key exchange key used to sign @a obj, or NULL
* @param obj the received JSON reply, should be kept as proof (and, in particular,
* be forwarded to the customer)
*/ */
typedef void typedef void
(*TALER_EXCHANGE_RefundCallback) ( (*TALER_EXCHANGE_RefundCallback) (
void *cls, void *cls,
unsigned int http_status, const struct TALER_EXCHANGE_HttpResponse *hr,
enum TALER_ErrorCode ec, const struct TALER_ExchangePublicKeyP *sign_key);
const struct TALER_ExchangePublicKeyP *sign_key,
const json_t *obj);
/** /**
@ -1120,10 +1140,7 @@ struct TALER_EXCHANGE_ReserveHistory
* reserve status request to a exchange. * reserve status request to a exchange.
* *
* @param cls closure * @param cls closure
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request * @param hr HTTP response data
* 0 if the exchange's reply is bogus (fails to follow the protocol)
* @param ec taler-specific error code, #TALER_EC_NONE on success
* @param json original response in JSON format (useful only for diagnostics)
* @param balance current balance in the reserve, NULL on error * @param balance current balance in the reserve, NULL on error
* @param history_length number of entries in the transaction history, 0 on error * @param history_length number of entries in the transaction history, 0 on error
* @param history detailed transaction history, NULL on error * @param history detailed transaction history, NULL on error
@ -1131,11 +1148,8 @@ struct TALER_EXCHANGE_ReserveHistory
typedef void typedef void
(*TALER_EXCHANGE_ReservesGetCallback) ( (*TALER_EXCHANGE_ReservesGetCallback) (
void *cls, void *cls,
unsigned int http_status, const struct TALER_EXCHANGE_HttpResponse *hr,
enum TALER_ErrorCode ec, const struct TALER_Amount *balance,
const json_t *json,
const struct
TALER_Amount *balance,
unsigned int history_length, unsigned int history_length,
const struct TALER_EXCHANGE_ReserveHistory *history); const struct TALER_EXCHANGE_ReserveHistory *history);
@ -1189,19 +1203,14 @@ struct TALER_EXCHANGE_WithdrawHandle;
* withdraw request to a exchange. * withdraw request to a exchange.
* *
* @param cls closure * @param cls closure
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request * @param hr HTTP response data
* 0 if the exchange's reply is bogus (fails to follow the protocol)
* @param ec taler-specific error code, #TALER_EC_NONE on success
* @param sig signature over the coin, NULL on error * @param sig signature over the coin, NULL on error
* @param full_response full response from the exchange (for logging, in case of errors)
*/ */
typedef void typedef void
(*TALER_EXCHANGE_WithdrawCallback) ( (*TALER_EXCHANGE_WithdrawCallback) (
void *cls, void *cls,
unsigned int http_status, const struct TALER_EXCHANGE_HttpResponse *hr,
enum TALER_ErrorCode ec, const struct TALER_DenominationSignature *sig);
const struct TALER_DenominationSignature *sig,
const json_t *full_response);
/** /**
@ -1345,21 +1354,17 @@ struct TALER_EXCHANGE_MeltHandle;
* #TALER_EXCHANGE_refreshes_reveal(). * #TALER_EXCHANGE_refreshes_reveal().
* *
* @param cls closure * @param cls closure
* @param http_status HTTP response code, never #MHD_HTTP_OK (200) as for successful intermediate response this callback is skipped. * @param hr HTTP response data
* 0 if the exchange's reply is bogus (fails to follow the protocol)
* @param ec taler-specific error code, #TALER_EC_NONE on success
* @param noreveal_index choice by the exchange in the cut-and-choose protocol, * @param noreveal_index choice by the exchange in the cut-and-choose protocol,
* UINT32_MAX on error * UINT32_MAX on error
* @param sign_key exchange key used to sign @a full_response, or NULL * @param sign_key exchange key used to sign @a full_response, or NULL
* @param full_response full response from the exchange (for logging, in case of errors)
*/ */
typedef void typedef void
(*TALER_EXCHANGE_MeltCallback) (void *cls, (*TALER_EXCHANGE_MeltCallback) (
unsigned int http_status, void *cls,
enum TALER_ErrorCode ec, const struct TALER_EXCHANGE_HttpResponse *hr,
uint32_t noreveal_index, uint32_t noreveal_index,
const struct TALER_ExchangePublicKeyP *sign_key, const struct TALER_ExchangePublicKeyP *sign_key);
const json_t *full_response);
/** /**
@ -1412,23 +1417,18 @@ TALER_EXCHANGE_melt_cancel (struct TALER_EXCHANGE_MeltHandle *mh);
* the original request specified the respective denomination keys. * the original request specified the respective denomination keys.
* *
* @param cls closure * @param cls closure
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request * @param hr HTTP response data
* 0 if the exchange's reply is bogus (fails to follow the protocol)
* @param ec taler-specific error code, #TALER_EC_NONE on success
* @param num_coins number of fresh coins created, length of the @a sigs and @a coin_privs arrays, 0 if the operation failed * @param num_coins number of fresh coins created, length of the @a sigs and @a coin_privs arrays, 0 if the operation failed
* @param coin_privs array of @a num_coins private keys for the coins that were created, NULL on error * @param coin_privs array of @a num_coins private keys for the coins that were created, NULL on error
* @param sigs array of signature over @a num_coins coins, NULL on error * @param sigs array of signature over @a num_coins coins, NULL on error
* @param full_response full response from the exchange (for logging, in case of errors)
*/ */
typedef void typedef void
(*TALER_EXCHANGE_RefreshesRevealCallback)( (*TALER_EXCHANGE_RefreshesRevealCallback)(
void *cls, void *cls,
unsigned int http_status, const struct TALER_EXCHANGE_HttpResponse *hr,
enum TALER_ErrorCode ec,
unsigned int num_coins, unsigned int num_coins,
const struct TALER_PlanchetSecretsP *coin_privs, const struct TALER_PlanchetSecretsP *coin_privs,
const struct TALER_DenominationSignature *sigs, const struct TALER_DenominationSignature *sigs);
const json_t *full_response);
/** /**
@ -1496,25 +1496,20 @@ struct TALER_EXCHANGE_LinkHandle;
* created when the original coin was melted. * created when the original coin was melted.
* *
* @param cls closure * @param cls closure
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request * @param hr HTTP response data
* 0 if the exchange's reply is bogus (fails to follow the protocol)
* @param ec taler-specific error code, #TALER_EC_NONE on success
* @param num_coins number of fresh coins created, length of the @a sigs and @a coin_privs arrays, 0 if the operation failed * @param num_coins number of fresh coins created, length of the @a sigs and @a coin_privs arrays, 0 if the operation failed
* @param coin_privs array of @a num_coins private keys for the coins that were created, NULL on error * @param coin_privs array of @a num_coins private keys for the coins that were created, NULL on error
* @param sigs array of signature over @a num_coins coins, NULL on error * @param sigs array of signature over @a num_coins coins, NULL on error
* @param pubs array of public keys for the @a sigs, NULL on error * @param pubs array of public keys for the @a sigs, NULL on error
* @param full_response full response from the exchange (for logging, in case of errors)
*/ */
typedef void typedef void
(*TALER_EXCHANGE_LinkCallback) ( (*TALER_EXCHANGE_LinkCallback) (
void *cls, void *cls,
unsigned int http_status, const struct TALER_EXCHANGE_HttpResponse *hr,
enum TALER_ErrorCode ec,
unsigned int num_coins, unsigned int num_coins,
const struct TALER_CoinSpendPrivateKeyP *coin_privs, const struct TALER_CoinSpendPrivateKeyP *coin_privs,
const struct TALER_DenominationSignature *sigs, const struct TALER_DenominationSignature *sigs,
const struct TALER_DenominationPublicKey *pubs, const struct TALER_DenominationPublicKey *pubs);
const json_t *full_response);
/** /**
@ -1560,11 +1555,8 @@ struct TALER_EXCHANGE_TransfersGetHandle;
* of the coin transactions that were combined into the wire transfer. * of the coin transactions that were combined into the wire transfer.
* *
* @param cls closure * @param cls closure
* @param http_status HTTP status code we got, 0 on exchange protocol violation * @param hr HTTP response data
* @param ec taler-specific error code, #TALER_EC_NONE on success
* @param sign_key exchange key used to sign @a json, or NULL * @param sign_key exchange key used to sign @a json, or NULL
* @param json original json reply (may include signatures, those have then been
* validated already)
* @param h_wire hash of the wire transfer address the transfer went to, or NULL on error * @param h_wire hash of the wire transfer address the transfer went to, or NULL on error
* @param execution_time time when the exchange claims to have performed the wire transfer * @param execution_time time when the exchange claims to have performed the wire transfer
* @param total_amount total amount of the wire transfer, or NULL if the exchange could * @param total_amount total amount of the wire transfer, or NULL if the exchange could
@ -1576,10 +1568,8 @@ struct TALER_EXCHANGE_TransfersGetHandle;
typedef void typedef void
(*TALER_EXCHANGE_TransfersGetCallback)( (*TALER_EXCHANGE_TransfersGetCallback)(
void *cls, void *cls,
unsigned int http_status, const struct TALER_EXCHANGE_HttpResponse *hr,
enum TALER_ErrorCode ec,
const struct TALER_ExchangePublicKeyP *sign_key, const struct TALER_ExchangePublicKeyP *sign_key,
const json_t *json,
const struct GNUNET_HashCode *h_wire, const struct GNUNET_HashCode *h_wire,
struct GNUNET_TIME_Absolute execution_time, struct GNUNET_TIME_Absolute execution_time,
const struct TALER_Amount *total_amount, const struct TALER_Amount *total_amount,
@ -1630,11 +1620,8 @@ struct TALER_EXCHANGE_DepositGetHandle;
* Function called with detailed wire transfer data. * Function called with detailed wire transfer data.
* *
* @param cls closure * @param cls closure
* @param http_status HTTP status code we got, 0 on exchange protocol violation * @param hr HTTP response data
* @param ec taler-specific error code, #TALER_EC_NONE on success
* @param sign_key exchange key used to sign @a json, or NULL * @param sign_key exchange key used to sign @a json, or NULL
* @param json original json reply (may include signatures, those have then been
* validated already)
* @param wtid wire transfer identifier used by the exchange, NULL if exchange did not * @param wtid wire transfer identifier used by the exchange, NULL if exchange did not
* yet execute the transaction * yet execute the transaction
* @param execution_time actual or planned execution time for the wire transfer * @param execution_time actual or planned execution time for the wire transfer
@ -1643,13 +1630,10 @@ struct TALER_EXCHANGE_DepositGetHandle;
typedef void typedef void
(*TALER_EXCHANGE_DepositGetCallback)( (*TALER_EXCHANGE_DepositGetCallback)(
void *cls, void *cls,
unsigned int http_status, const struct TALER_EXCHANGE_HttpResponse *hr,
enum TALER_ErrorCode ec,
const struct TALER_ExchangePublicKeyP *sign_key, const struct TALER_ExchangePublicKeyP *sign_key,
const json_t *json,
const struct TALER_WireTransferIdentifierRawP *wtid, const struct TALER_WireTransferIdentifierRawP *wtid,
struct GNUNET_TIME_Absolute struct GNUNET_TIME_Absolute execution_time,
execution_time,
const struct TALER_Amount *coin_contribution); const struct TALER_Amount *coin_contribution);
@ -1766,24 +1750,19 @@ struct TALER_EXCHANGE_RecoupHandle;
* the original request specified the respective denomination keys. * the original request specified the respective denomination keys.
* *
* @param cls closure * @param cls closure
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request * @param hr HTTP response data
* 0 if the exchange's reply is bogus (fails to follow the protocol)
* @param ec taler-specific error code, #TALER_EC_NONE on success
* @param amount amount the exchange will wire back for this coin, * @param amount amount the exchange will wire back for this coin,
* on error the total balance remaining, or NULL * on error the total balance remaining, or NULL
* @param timestamp what time did the exchange receive the /recoup request * @param timestamp what time did the exchange receive the /recoup request
* @param reserve_pub public key of the reserve receiving the recoup, NULL if refreshed or on error * @param reserve_pub public key of the reserve receiving the recoup, NULL if refreshed or on error
* @param old_coin_pub public key of the dirty coin, NULL if not refreshed or on error * @param old_coin_pub public key of the dirty coin, NULL if not refreshed or on error
* @param full_response full response from the exchange (for logging, in case of errors)
*/ */
typedef void typedef void
(*TALER_EXCHANGE_RecoupResultCallback) ( (*TALER_EXCHANGE_RecoupResultCallback) (
void *cls, void *cls,
unsigned int http_status, const struct TALER_EXCHANGE_HttpResponse *hr,
enum TALER_ErrorCode ec,
const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_ReservePublicKeyP *reserve_pub,
const struct TALER_CoinSpendPublicKeyP *old_coin_pub, const struct TALER_CoinSpendPublicKeyP *old_coin_pub);
const json_t *full_response);
/** /**

View File

@ -132,6 +132,17 @@ enum TALER_ErrorCode
TALER_JSON_get_error_code (const json_t *json); TALER_JSON_get_error_code (const json_t *json);
/**
* Extract the Taler error hint from the given @a json object.
* Note that NULL is returned if no "hint" is present.
*
* @param json response to extract the error hint from
* @return the "hint" value from @a json; only valid as long as @a json is valid
*/
const char *
TALER_JSON_get_error_hint (const json_t *json);
/** /**
* Extract the Taler error code from the given @a data object, which is expected to be in JSON. * Extract the Taler error code from the given @a data object, which is expected to be in JSON.
* Note that #TALER_EC_INVALID is returned if no "code" is present or if @a data is not in JSON. * Note that #TALER_EC_INVALID is returned if no "code" is present or if @a data is not in JSON.

View File

@ -135,19 +135,15 @@ TALER_TESTING_prepare_exchange (const char *config_filename,
* *
* @param cls closure, typically, the "run" method containing * @param cls closure, typically, the "run" method containing
* all the commands to be run, and a closure for it. * all the commands to be run, and a closure for it.
* @param hr http response details
* @param keys the exchange's keys. * @param keys the exchange's keys.
* @param compat protocol compatibility information. * @param compat protocol compatibility information.
* @param ec error code, #TALER_EC_NONE on success
* @param http_status status returned by /keys, #MHD_HTTP_OK on success
* @param full_reply JSON body of /keys request, NULL if reply was not in JSON
*/ */
void void
TALER_TESTING_cert_cb (void *cls, TALER_TESTING_cert_cb (void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr,
const struct TALER_EXCHANGE_Keys *keys, const struct TALER_EXCHANGE_Keys *keys,
enum TALER_EXCHANGE_VersionCompatibility compat, enum TALER_EXCHANGE_VersionCompatibility compat);
enum TALER_ErrorCode ec,
unsigned int http_status,
const json_t *full_reply);
/** /**

View File

@ -92,6 +92,36 @@ TALER_JSON_get_error_code (const json_t *json)
} }
/**
* Extract the Taler error hint from the given @a json object.
* Note that NULL is returned if no "hint" is present.
*
* @param json response to extract the error hint from
* @return the "hint" value from @a json; only valid as long as @a json is valid
*/
const char *
TALER_JSON_get_error_hint (const json_t *json)
{
const json_t *jc;
if (NULL == json)
{
GNUNET_break_op (0);
return NULL;
}
jc = json_object_get (json, "hint");
if (NULL == jc)
return NULL; /* no hint, is allowed */
if (! json_is_string (jc))
{
/* Hints must be strings */
GNUNET_break_op (0);
return NULL;
}
return json_string_value (jc);
}
/** /**
* Extract the Taler error code from the given @a data object, which is expected to be in JSON. * Extract the Taler error code from the given @a data object, which is expected to be in JSON.
* Note that #TALER_EC_INVALID is returned if no "code" is present or if @a data is not in JSON. * Note that #TALER_EC_INVALID is returned if no "code" is present or if @a data is not in JSON.

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014-2018 Taler Systems SA Copyright (C) 2014-2020 Taler Systems SA
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 under the
terms of the GNU General Public License as published by the Free Software terms of the GNU General Public License as published by the Free Software
@ -87,53 +87,58 @@ handle_deposit_confirmation_finished (void *cls,
{ {
const json_t *json = djson; const json_t *json = djson;
struct TALER_AUDITOR_DepositConfirmationHandle *dh = cls; struct TALER_AUDITOR_DepositConfirmationHandle *dh = cls;
enum TALER_ErrorCode ec; struct TALER_AUDITOR_HttpResponse hr = {
.reply = json,
.http_status = (unsigned int) response_code
};
dh->job = NULL; dh->job = NULL;
switch (response_code) switch (response_code)
{ {
case 0: case 0:
ec = TALER_EC_INVALID_RESPONSE; hr.ec = TALER_EC_INVALID_RESPONSE;
break; break;
case MHD_HTTP_OK: case MHD_HTTP_OK:
ec = TALER_EC_NONE; hr.ec = TALER_EC_NONE;
break; break;
case MHD_HTTP_BAD_REQUEST: case MHD_HTTP_BAD_REQUEST:
ec = TALER_JSON_get_error_code (json); hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
/* This should never happen, either us or the auditor is buggy /* This should never happen, either us or the auditor is buggy
(or API version conflict); just pass JSON reply to the application */ (or API version conflict); just pass JSON reply to the application */
break; break;
case MHD_HTTP_FORBIDDEN: case MHD_HTTP_FORBIDDEN:
ec = TALER_JSON_get_error_code (json); hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
/* Nothing really to verify, auditor says one of the signatures is /* Nothing really to verify, auditor says one of the signatures is
invalid; as we checked them, this should never happen, we invalid; as we checked them, this should never happen, we
should pass the JSON reply to the application */ should pass the JSON reply to the application */
break; break;
case MHD_HTTP_NOT_FOUND: case MHD_HTTP_NOT_FOUND:
ec = TALER_JSON_get_error_code (json); hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
/* Nothing really to verify, this should never /* Nothing really to verify, this should never
happen, we should pass the JSON reply to the application */ happen, we should pass the JSON reply to the application */
break; break;
case MHD_HTTP_INTERNAL_SERVER_ERROR: case MHD_HTTP_INTERNAL_SERVER_ERROR:
ec = TALER_JSON_get_error_code (json); hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
/* Server had an internal issue; we should retry, but this API /* Server had an internal issue; we should retry, but this API
leaves this to the application */ leaves this to the application */
break; break;
default: default:
/* unexpected response code */ /* unexpected response code */
ec = TALER_JSON_get_error_code (json); hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d\n", "Unexpected response code %u/%d\n",
(unsigned int) response_code, (unsigned int) response_code,
ec); hr.ec);
GNUNET_break (0); GNUNET_break_op (0);
response_code = 0;
break; break;
} }
dh->cb (dh->cb_cls, dh->cb (dh->cb_cls,
response_code, &hr);
ec,
json);
TALER_AUDITOR_deposit_confirmation_cancel (dh); TALER_AUDITOR_deposit_confirmation_cancel (dh);
} }

View File

@ -89,13 +89,16 @@ handle_exchanges_finished (void *cls,
const json_t *ja; const json_t *ja;
unsigned int ja_len; unsigned int ja_len;
struct TALER_AUDITOR_ListExchangesHandle *leh = cls; struct TALER_AUDITOR_ListExchangesHandle *leh = cls;
enum TALER_ErrorCode ec; struct TALER_AUDITOR_HttpResponse hr = {
.reply = json,
.http_status = (unsigned int) response_code
};
leh->job = NULL; leh->job = NULL;
switch (response_code) switch (response_code)
{ {
case 0: case 0:
ec = TALER_EC_INVALID_RESPONSE; hr.ec = TALER_EC_INVALID_RESPONSE;
break; break;
case MHD_HTTP_OK: case MHD_HTTP_OK:
ja = json_object_get (json, ja = json_object_get (json,
@ -104,8 +107,8 @@ handle_exchanges_finished (void *cls,
(! json_is_array (ja)) ) (! json_is_array (ja)) )
{ {
GNUNET_break (0); GNUNET_break (0);
ec = TALER_EC_AUDITOR_EXCHANGES_REPLY_MALFORMED; hr.ec = TALER_EC_AUDITOR_EXCHANGES_REPLY_MALFORMED;
response_code = 0; hr.http_status = 0;
break; break;
} }
@ -113,8 +116,8 @@ handle_exchanges_finished (void *cls,
if (ja_len > MAX_EXCHANGES) if (ja_len > MAX_EXCHANGES)
{ {
GNUNET_break (0); GNUNET_break (0);
ec = TALER_EC_AUDITOR_EXCHANGES_REPLY_MALFORMED; hr.ec = TALER_EC_AUDITOR_EXCHANGES_REPLY_MALFORMED;
response_code = 0; hr.http_status = 0;
break; break;
} }
{ {
@ -138,54 +141,54 @@ handle_exchanges_finished (void *cls,
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
ok = GNUNET_NO; ok = GNUNET_NO;
ec = TALER_EC_AUDITOR_EXCHANGES_REPLY_MALFORMED; hr.ec = TALER_EC_AUDITOR_EXCHANGES_REPLY_MALFORMED;
hr.http_status = 0;
break; break;
} }
} }
if (GNUNET_YES != ok) if (GNUNET_YES != ok)
break; break;
leh->cb (leh->cb_cls, leh->cb (leh->cb_cls,
response_code, &hr,
TALER_EC_NONE,
ja_len, ja_len,
ei, ei);
json);
TALER_AUDITOR_list_exchanges_cancel (leh); TALER_AUDITOR_list_exchanges_cancel (leh);
return; return;
} }
case MHD_HTTP_BAD_REQUEST: case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the auditor is buggy /* This should never happen, either us or the auditor is buggy
(or API version conflict); just pass JSON reply to the application */ (or API version conflict); just pass JSON reply to the application */
ec = TALER_JSON_get_error_code (json); hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
break; break;
case MHD_HTTP_NOT_FOUND: case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify, this should never /* Nothing really to verify, this should never
happen, we should pass the JSON reply to the application */ happen, we should pass the JSON reply to the application */
ec = TALER_JSON_get_error_code (json); hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
break; break;
case MHD_HTTP_INTERNAL_SERVER_ERROR: case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API /* Server had an internal issue; we should retry, but this API
leaves this to the application */ leaves this to the application */
ec = TALER_JSON_get_error_code (json); hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
break; break;
default: default:
/* unexpected response code */ /* unexpected response code */
ec = TALER_JSON_get_error_code (json); hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d\n", "Unexpected response code %u/%d\n",
(unsigned int) response_code, (unsigned int) response_code,
(int) ec); (int) hr.ec);
GNUNET_break (0); GNUNET_break_op (0);
response_code = 0;
break; break;
} }
if (NULL != leh->cb) if (NULL != leh->cb)
leh->cb (leh->cb_cls, leh->cb (leh->cb_cls,
response_code, &hr,
TALER_JSON_get_error_code (json),
0, 0,
NULL, NULL);
json);
TALER_AUDITOR_list_exchanges_cancel (leh); TALER_AUDITOR_list_exchanges_cancel (leh);
} }

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014-2018 Taler Systems SA Copyright (C) 2014-2020 Taler Systems SA
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 under the
terms of the GNU General Public License as published by the Free Software terms of the GNU General Public License as published by the Free Software
@ -197,9 +197,9 @@ free_version_info (struct TALER_AUDITOR_VersionInformation *vi)
* @param[in] resp_obj JSON object to parse * @param[in] resp_obj JSON object to parse
* @param[out] vi where to store the results we decoded * @param[out] vi where to store the results we decoded
* @param[out] vc where to store version compatibility data * @param[out] vc where to store version compatibility data
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error (malformed JSON) * @return #TALER_EC_NONE on success
*/ */
static int static enum TALER_ErrorCode
decode_version_json (const json_t *resp_obj, decode_version_json (const json_t *resp_obj,
struct TALER_AUDITOR_VersionInformation *vi, struct TALER_AUDITOR_VersionInformation *vi,
enum TALER_AUDITOR_VersionCompatibility *vc) enum TALER_AUDITOR_VersionCompatibility *vc)
@ -219,7 +219,7 @@ decode_version_json (const json_t *resp_obj,
if (JSON_OBJECT != json_typeof (resp_obj)) if (JSON_OBJECT != json_typeof (resp_obj))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return GNUNET_SYSERR; return TALER_EC_JSON_INVALID;
} }
/* check the version */ /* check the version */
if (GNUNET_OK != if (GNUNET_OK !=
@ -228,7 +228,7 @@ decode_version_json (const json_t *resp_obj,
NULL, NULL)) NULL, NULL))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return GNUNET_SYSERR; return TALER_EC_JSON_INVALID;
} }
if (3 != sscanf (ver, if (3 != sscanf (ver,
"%u:%u:%u", "%u:%u:%u",
@ -237,7 +237,7 @@ decode_version_json (const json_t *resp_obj,
&age)) &age))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return GNUNET_SYSERR; return TALER_EC_VERSION_MALFORMED;
} }
vi->version = GNUNET_strdup (ver); vi->version = GNUNET_strdup (ver);
*vc = TALER_AUDITOR_VC_MATCH; *vc = TALER_AUDITOR_VC_MATCH;
@ -253,7 +253,7 @@ decode_version_json (const json_t *resp_obj,
if (TALER_PROTOCOL_CURRENT - TALER_PROTOCOL_AGE > current) if (TALER_PROTOCOL_CURRENT - TALER_PROTOCOL_AGE > current)
*vc |= TALER_AUDITOR_VC_INCOMPATIBLE; *vc |= TALER_AUDITOR_VC_INCOMPATIBLE;
} }
return GNUNET_OK; return TALER_EC_NONE;
} }
@ -283,6 +283,10 @@ version_completed_cb (void *cls,
struct VersionRequest *vr = cls; struct VersionRequest *vr = cls;
struct TALER_AUDITOR_Handle *auditor = vr->auditor; struct TALER_AUDITOR_Handle *auditor = vr->auditor;
enum TALER_AUDITOR_VersionCompatibility vc; enum TALER_AUDITOR_VersionCompatibility vc;
struct TALER_AUDITOR_HttpResponse hr = {
.reply = resp_obj,
.http_status = (unsigned int) response_code
};
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Received version from URL `%s' with status %ld.\n", "Received version from URL `%s' with status %ld.\n",
@ -293,6 +297,8 @@ version_completed_cb (void *cls,
{ {
case 0: case 0:
case MHD_HTTP_INTERNAL_SERVER_ERROR: case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* NOTE: this design is debatable. We MAY want to throw this error at the
client. We may then still additionally internally re-try. */
free_version_request (vr); free_version_request (vr);
auditor->vr = NULL; auditor->vr = NULL;
GNUNET_assert (NULL == auditor->retry_task); GNUNET_assert (NULL == auditor->retry_task);
@ -306,24 +312,28 @@ version_completed_cb (void *cls,
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
TALER_LOG_WARNING ("NULL body for a 200-OK /version\n"); TALER_LOG_WARNING ("NULL body for a 200-OK /version\n");
response_code = 0; hr.http_status = 0;
hr.ec = TALER_EC_INVALID_RESPONSE;
break; break;
} }
if (GNUNET_OK != hr.ec = decode_version_json (resp_obj,
decode_version_json (resp_obj, &auditor->vi,
&auditor->vi, &vc);
&vc)) if (TALER_EC_NONE != hr.ec)
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
response_code = 0; hr.http_status = 0;
break; break;
} }
auditor->retry_delay = GNUNET_TIME_UNIT_ZERO; /* restart quickly */ auditor->retry_delay = GNUNET_TIME_UNIT_ZERO; /* restart quickly */
break; break;
default: default:
hr.ec = TALER_JSON_get_error_code (resp_obj);
hr.hint = TALER_JSON_get_error_hint (resp_obj);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u\n", "Unexpected response code %u/%d\n",
(unsigned int) response_code); (unsigned int) response_code,
(int) hr.ec);
break; break;
} }
if (MHD_HTTP_OK != response_code) if (MHD_HTTP_OK != response_code)
@ -338,6 +348,7 @@ version_completed_cb (void *cls,
free_version_info (&auditor->vi); free_version_info (&auditor->vi);
/* notify application that we failed */ /* notify application that we failed */
auditor->version_cb (auditor->version_cb_cls, auditor->version_cb (auditor->version_cb_cls,
&hr,
NULL, NULL,
vc); vc);
return; return;
@ -352,6 +363,7 @@ version_completed_cb (void *cls,
auditor); auditor);
/* notify application about the key information */ /* notify application about the key information */
auditor->version_cb (auditor->version_cb_cls, auditor->version_cb (auditor->version_cb_cls,
&hr,
&auditor->vi, &auditor->vi,
vc); vc);
} }

View File

@ -156,25 +156,24 @@ auditor_cb (void *cls,
TALER_amount_ntoh (&amount_without_fee, TALER_amount_ntoh (&amount_without_fee,
&dh->depconf.amount_without_fee); &dh->depconf.amount_without_fee);
aie = GNUNET_new (struct TEAH_AuditorInteractionEntry); aie = GNUNET_new (struct TEAH_AuditorInteractionEntry);
aie->dch = TALER_AUDITOR_deposit_confirmation (ah, aie->dch = TALER_AUDITOR_deposit_confirmation (
&dh->depconf.h_wire, ah,
&dh->depconf.h_contract_terms, &dh->depconf.h_wire,
GNUNET_TIME_absolute_ntoh ( &dh->depconf.h_contract_terms,
dh->depconf.timestamp), GNUNET_TIME_absolute_ntoh (dh->depconf.timestamp),
GNUNET_TIME_absolute_ntoh ( GNUNET_TIME_absolute_ntoh (dh->depconf.refund_deadline),
dh->depconf.refund_deadline), &amount_without_fee,
&amount_without_fee, &dh->depconf.coin_pub,
&dh->depconf.coin_pub, &dh->depconf.merchant,
&dh->depconf.merchant, &dh->exchange_pub,
&dh->exchange_pub, &dh->exchange_sig,
&dh->exchange_sig, &key_state->master_pub,
&key_state->master_pub, spk->valid_from,
spk->valid_from, spk->valid_until,
spk->valid_until, spk->valid_legal,
spk->valid_legal, &spk->master_sig,
&spk->master_sig, &TEAH_acc_confirmation_cb,
&TEAH_acc_confirmation_cb, aie);
aie);
return aie; return aie;
} }
@ -305,13 +304,16 @@ handle_deposit_finished (void *cls,
struct TALER_ExchangeSignatureP *es = NULL; struct TALER_ExchangeSignatureP *es = NULL;
struct TALER_ExchangePublicKeyP *ep = NULL; struct TALER_ExchangePublicKeyP *ep = NULL;
const json_t *j = response; const json_t *j = response;
enum TALER_ErrorCode ec; struct TALER_EXCHANGE_HttpResponse hr = {
.reply = j,
.http_status = (unsigned int) response_code
};
dh->job = NULL; dh->job = NULL;
switch (response_code) switch (response_code)
{ {
case 0: case 0:
ec = TALER_EC_INVALID_RESPONSE; hr.ec = TALER_EC_INVALID_RESPONSE;
break; break;
case MHD_HTTP_OK: case MHD_HTTP_OK:
if (GNUNET_OK != if (GNUNET_OK !=
@ -321,66 +323,71 @@ handle_deposit_finished (void *cls,
&exchange_pub)) &exchange_pub))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
response_code = 0; hr.http_status = 0;
ec = TALER_EC_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE; hr.ec = TALER_EC_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE;
} }
else else
{ {
es = &exchange_sig; es = &exchange_sig;
ep = &exchange_pub; ep = &exchange_pub;
ec = TALER_EC_NONE;
} }
break; break;
case MHD_HTTP_BAD_REQUEST: case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the exchange is buggy /* This should never happen, either us or the exchange is buggy
(or API version conflict); just pass JSON reply to the application */ (or API version conflict); just pass JSON reply to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_CONFLICT: case MHD_HTTP_CONFLICT:
/* Double spending; check signatures on transaction history */ /* Double spending; check signatures on transaction history */
ec = TALER_JSON_get_error_code (j);
if (GNUNET_OK != if (GNUNET_OK !=
verify_deposit_signature_forbidden (dh, verify_deposit_signature_forbidden (dh,
j)) j))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
response_code = 0; hr.http_status = 0;
ec = TALER_EC_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE; hr.ec = TALER_EC_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE;
}
else
{
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
} }
break; break;
case MHD_HTTP_FORBIDDEN: case MHD_HTTP_FORBIDDEN:
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
/* Nothing really to verify, exchange says one of the signatures is /* Nothing really to verify, exchange says one of the signatures is
invalid; as we checked them, this should never happen, we invalid; as we checked them, this should never happen, we
should pass the JSON reply to the application */ should pass the JSON reply to the application */
break; break;
case MHD_HTTP_NOT_FOUND: case MHD_HTTP_NOT_FOUND:
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
/* Nothing really to verify, this should never /* Nothing really to verify, this should never
happen, we should pass the JSON reply to the application */ happen, we should pass the JSON reply to the application */
break; break;
case MHD_HTTP_INTERNAL_SERVER_ERROR: case MHD_HTTP_INTERNAL_SERVER_ERROR:
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
/* Server had an internal issue; we should retry, but this API /* Server had an internal issue; we should retry, but this API
leaves this to the application */ leaves this to the application */
break; break;
default: default:
/* unexpected response code */ /* unexpected response code */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d\n", "Unexpected response code %u/%d\n",
(unsigned int) response_code, (unsigned int) response_code,
ec); hr.ec);
GNUNET_break (0); GNUNET_break_op (0);
response_code = 0;
break; break;
} }
dh->cb (dh->cb_cls, dh->cb (dh->cb_cls,
response_code, &hr,
ec,
es, es,
ep, ep);
j);
TALER_EXCHANGE_deposit_cancel (dh); TALER_EXCHANGE_deposit_cancel (dh);
} }

View File

@ -151,13 +151,16 @@ handle_deposit_wtid_finished (void *cls,
struct TALER_ExchangePublicKeyP exchange_pub; struct TALER_ExchangePublicKeyP exchange_pub;
struct TALER_ExchangePublicKeyP *ep = NULL; struct TALER_ExchangePublicKeyP *ep = NULL;
const json_t *j = response; const json_t *j = response;
enum TALER_ErrorCode ec; struct TALER_EXCHANGE_HttpResponse hr = {
.reply = j,
.http_status = (unsigned int) response_code
};
dwh->job = NULL; dwh->job = NULL;
switch (response_code) switch (response_code)
{ {
case 0: case 0:
ec = TALER_EC_INVALID_RESPONSE; hr.ec = TALER_EC_INVALID_RESPONSE;
break; break;
case MHD_HTTP_OK: case MHD_HTTP_OK:
{ {
@ -174,8 +177,8 @@ handle_deposit_wtid_finished (void *cls,
NULL, NULL)) NULL, NULL))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
response_code = 0; hr.http_status = 0;
ec = TALER_EC_DEPOSITS_INVALID_BODY_BY_EXCHANGE; hr.ec = TALER_EC_DEPOSITS_INVALID_BODY_BY_EXCHANGE;
break; break;
} }
wtid = &dwh->depconf.wtid; wtid = &dwh->depconf.wtid;
@ -189,13 +192,12 @@ handle_deposit_wtid_finished (void *cls,
&exchange_pub)) &exchange_pub))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
response_code = 0; hr.http_status = 0;
ec = TALER_EC_DEPOSITS_INVALID_SIGNATURE_BY_EXCHANGE; hr.ec = TALER_EC_DEPOSITS_INVALID_SIGNATURE_BY_EXCHANGE;
} }
else else
{ {
ep = &exchange_pub; ep = &exchange_pub;
ec = TALER_EC_NONE;
} }
} }
break; break;
@ -213,49 +215,51 @@ handle_deposit_wtid_finished (void *cls,
NULL, NULL)) NULL, NULL))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
response_code = 0; hr.http_status = 0;
ec = TALER_EC_DEPOSITS_INVALID_BODY_BY_EXCHANGE; hr.ec = TALER_EC_DEPOSITS_INVALID_BODY_BY_EXCHANGE;
break; break;
} }
ec = TALER_EC_NONE;
} }
break; break;
case MHD_HTTP_BAD_REQUEST: case MHD_HTTP_BAD_REQUEST:
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
/* This should never happen, either us or the exchange is buggy /* This should never happen, either us or the exchange is buggy
(or API version conflict); just pass JSON reply to the application */ (or API version conflict); just pass JSON reply to the application */
break; break;
case MHD_HTTP_FORBIDDEN: case MHD_HTTP_FORBIDDEN:
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
/* Nothing really to verify, exchange says one of the signatures is /* Nothing really to verify, exchange says one of the signatures is
invalid; as we checked them, this should never happen, we invalid; as we checked them, this should never happen, we
should pass the JSON reply to the application */ should pass the JSON reply to the application */
break; break;
case MHD_HTTP_NOT_FOUND: case MHD_HTTP_NOT_FOUND:
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
/* Exchange does not know about transaction; /* Exchange does not know about transaction;
we should pass the reply to the application */ we should pass the reply to the application */
break; break;
case MHD_HTTP_INTERNAL_SERVER_ERROR: case MHD_HTTP_INTERNAL_SERVER_ERROR:
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
/* Server had an internal issue; we should retry, but this API /* Server had an internal issue; we should retry, but this API
leaves this to the application */ leaves this to the application */
break; break;
default: default:
/* unexpected response code */ /* unexpected response code */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u\n", "Unexpected response code %u/%d\n",
(unsigned int) response_code); (unsigned int) response_code,
GNUNET_break (0); (int) hr.ec);
ec = TALER_JSON_get_error_code (j); GNUNET_break_op (0);
response_code = 0;
break; break;
} }
dwh->cb (dwh->cb_cls, dwh->cb (dwh->cb_cls,
response_code, &hr,
ec,
ep, ep,
j,
wtid, wtid,
execution_time, execution_time,
coin_contribution); coin_contribution);

View File

@ -265,27 +265,22 @@ struct KeysRequest
* auditor's /deposit-confirmation handler. * auditor's /deposit-confirmation handler.
* *
* @param cls closure of type `struct TEAH_AuditorInteractionEntry *` * @param cls closure of type `struct TEAH_AuditorInteractionEntry *`
* @param http_status HTTP status code, 200 on success * @param hr HTTP response
* @param ec taler protocol error status code, 0 on success
* @param json raw json response
*/ */
void void
TEAH_acc_confirmation_cb (void *cls, TEAH_acc_confirmation_cb (void *cls,
unsigned int http_status, const struct TALER_AUDITOR_HttpResponse *hr)
enum TALER_ErrorCode ec,
const json_t *json)
{ {
struct TEAH_AuditorInteractionEntry *aie = cls; struct TEAH_AuditorInteractionEntry *aie = cls;
struct TEAH_AuditorListEntry *ale = aie->ale; struct TEAH_AuditorListEntry *ale = aie->ale;
(void) json; if (MHD_HTTP_OK != hr->http_status)
if (MHD_HTTP_OK != http_status)
{ {
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Failed to submit deposit confirmation to auditor `%s' with HTTP status %d (EC: %d). This is acceptable if it does not happen often.\n", "Failed to submit deposit confirmation to auditor `%s' with HTTP status %d (EC: %d). This is acceptable if it does not happen often.\n",
ale->auditor_url, ale->auditor_url,
http_status, hr->http_status,
(int) ec); hr->ec);
} }
GNUNET_CONTAINER_DLL_remove (ale->ai_head, GNUNET_CONTAINER_DLL_remove (ale->ai_head,
ale->ai_tail, ale->ai_tail,
@ -664,12 +659,14 @@ parse_json_auditor (struct TALER_EXCHANGE_AuditorInformation *auditor,
* auditor as 'up'. * auditor as 'up'.
* *
* @param cls closure, a `struct TEAH_AuditorListEntry *` * @param cls closure, a `struct TEAH_AuditorListEntry *`
* @param hr http response from the auditor
* @param vi basic information about the auditor * @param vi basic information about the auditor
* @param compat protocol compatibility information * @param compat protocol compatibility information
*/ */
static void static void
auditor_version_cb ( auditor_version_cb (
void *cls, void *cls,
const struct TALER_AUDITOR_HttpResponse *hr,
const struct TALER_AUDITOR_VersionInformation *vi, const struct TALER_AUDITOR_VersionInformation *vi,
enum TALER_AUDITOR_VersionCompatibility compat) enum TALER_AUDITOR_VersionCompatibility compat)
{ {
@ -1252,6 +1249,10 @@ keys_completed_cb (void *cls,
struct TALER_EXCHANGE_Keys kd_old; struct TALER_EXCHANGE_Keys kd_old;
enum TALER_EXCHANGE_VersionCompatibility vc; enum TALER_EXCHANGE_VersionCompatibility vc;
const json_t *j = resp_obj; const json_t *j = resp_obj;
struct TALER_EXCHANGE_HttpResponse hr = {
.reply = j,
.http_status = (unsigned int) response_code
};
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Received keys from URL `%s' with status %ld.\n", "Received keys from URL `%s' with status %ld.\n",
@ -1328,7 +1329,8 @@ keys_completed_cb (void *cls,
&vc)) &vc))
{ {
TALER_LOG_ERROR ("Could not decode /keys response\n"); TALER_LOG_ERROR ("Could not decode /keys response\n");
response_code = 0; hr.http_status = 0;
hr.ec = TALER_EC_KEYS_INVALID;
for (unsigned int i = 0; i<kd.num_auditors; i++) for (unsigned int i = 0; i<kd.num_auditors; i++)
{ {
struct TALER_EXCHANGE_AuditorInformation *anew = &kd.auditors[i]; struct TALER_EXCHANGE_AuditorInformation *anew = &kd.auditors[i];
@ -1354,9 +1356,12 @@ keys_completed_cb (void *cls,
exchange->retry_delay = GNUNET_TIME_UNIT_ZERO; exchange->retry_delay = GNUNET_TIME_UNIT_ZERO;
break; break;
default: default:
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u\n", "Unexpected response code %u/%d\n",
(unsigned int) response_code); (unsigned int) response_code,
(int) hr.ec);
break; break;
} }
exchange->key_data = kd; exchange->key_data = kd;
@ -1380,11 +1385,9 @@ keys_completed_cb (void *cls,
free_key_data (&kd_old); free_key_data (&kd_old);
/* notify application that we failed */ /* notify application that we failed */
exchange->cert_cb (exchange->cert_cb_cls, exchange->cert_cb (exchange->cert_cb_cls,
&hr,
NULL, NULL,
vc, vc);
TALER_JSON_get_error_code (j),
response_code,
j);
return; return;
} }
@ -1397,11 +1400,9 @@ keys_completed_cb (void *cls,
update_auditors (exchange); update_auditors (exchange);
/* notify application about the key information */ /* notify application about the key information */
exchange->cert_cb (exchange->cert_cb_cls, exchange->cert_cb (exchange->cert_cb_cls,
&hr,
&exchange->key_data, &exchange->key_data,
vc, vc);
TALER_EC_NONE,
MHD_HTTP_OK,
j);
free_key_data (&kd_old); free_key_data (&kd_old);
} }
@ -1575,6 +1576,11 @@ deserialize_data (struct TALER_EXCHANGE_Handle *exchange,
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
}; };
struct TALER_EXCHANGE_Keys key_data; struct TALER_EXCHANGE_Keys key_data;
struct TALER_EXCHANGE_HttpResponse hr = {
.ec = TALER_EC_NONE,
.http_status = MHD_HTTP_OK,
.reply = data
};
if (NULL == data) if (NULL == data)
return; return;
@ -1622,11 +1628,9 @@ deserialize_data (struct TALER_EXCHANGE_Handle *exchange,
update_auditors (exchange); update_auditors (exchange);
/* notify application about the key information */ /* notify application about the key information */
exchange->cert_cb (exchange->cert_cb_cls, exchange->cert_cb (exchange->cert_cb_cls,
&hr,
&exchange->key_data, &exchange->key_data,
vc, vc);
TALER_EC_NONE,
MHD_HTTP_OK,
data);
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
} }

View File

@ -79,15 +79,11 @@ typedef struct TEAH_AuditorInteractionEntry *
* auditor's /deposit-confirmation handler. * auditor's /deposit-confirmation handler.
* *
* @param cls closure of type `struct TEAH_AuditorInteractionEntry *` * @param cls closure of type `struct TEAH_AuditorInteractionEntry *`
* @param http_status HTTP status code, 200 on success * @param hr HTTP response
* @param ec taler protocol error status code, 0 on success
* @param json raw json response
*/ */
void void
TEAH_acc_confirmation_cb (void *cls, TEAH_acc_confirmation_cb (void *cls,
unsigned int http_status, const struct TALER_AUDITOR_HttpResponse *hr);
enum TALER_ErrorCode ec,
const json_t *json);
/** /**

View File

@ -186,6 +186,10 @@ parse_link_ok (struct TALER_EXCHANGE_LinkHandle *lh,
unsigned int session; unsigned int session;
unsigned int num_coins; unsigned int num_coins;
int ret; int ret;
struct TALER_EXCHANGE_HttpResponse hr = {
.reply = json,
.http_status = MHD_HTTP_OK
};
if (! json_is_array (json)) if (! json_is_array (json))
{ {
@ -305,13 +309,11 @@ parse_link_ok (struct TALER_EXCHANGE_LinkHandle *lh,
if (off_coin == num_coins) if (off_coin == num_coins)
{ {
lh->link_cb (lh->link_cb_cls, lh->link_cb (lh->link_cb_cls,
MHD_HTTP_OK, &hr,
TALER_EC_NONE,
num_coins, num_coins,
coin_privs, coin_privs,
sigs, sigs,
pubs, pubs);
json);
lh->link_cb = NULL; lh->link_cb = NULL;
ret = GNUNET_OK; ret = GNUNET_OK;
} }
@ -350,13 +352,16 @@ handle_link_finished (void *cls,
{ {
struct TALER_EXCHANGE_LinkHandle *lh = cls; struct TALER_EXCHANGE_LinkHandle *lh = cls;
const json_t *j = response; const json_t *j = response;
enum TALER_ErrorCode ec; struct TALER_EXCHANGE_HttpResponse hr = {
.reply = j,
.http_status = (unsigned int) response_code
};
lh->job = NULL; lh->job = NULL;
switch (response_code) switch (response_code)
{ {
case 0: case 0:
ec = TALER_EC_INVALID_RESPONSE; hr.ec = TALER_EC_INVALID_RESPONSE;
break; break;
case MHD_HTTP_OK: case MHD_HTTP_OK:
if (GNUNET_OK != if (GNUNET_OK !=
@ -364,47 +369,49 @@ handle_link_finished (void *cls,
j)) j))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
response_code = 0; hr.http_status = 0;
ec = TALER_EC_LINK_REPLY_MALFORMED; hr.ec = TALER_EC_LINK_REPLY_MALFORMED;
break; break;
} }
GNUNET_assert (NULL == lh->link_cb); GNUNET_assert (NULL == lh->link_cb);
TALER_EXCHANGE_link_cancel (lh); TALER_EXCHANGE_link_cancel (lh);
return; return;
case MHD_HTTP_BAD_REQUEST: case MHD_HTTP_BAD_REQUEST:
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
/* This should never happen, either us or the exchange is buggy /* This should never happen, either us or the exchange is buggy
(or API version conflict); just pass JSON reply to the application */ (or API version conflict); just pass JSON reply to the application */
break; break;
case MHD_HTTP_NOT_FOUND: case MHD_HTTP_NOT_FOUND:
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
/* Nothing really to verify, exchange says this coin was not melted; we /* Nothing really to verify, exchange says this coin was not melted; we
should pass the JSON reply to the application */ should pass the JSON reply to the application */
break; break;
case MHD_HTTP_INTERNAL_SERVER_ERROR: case MHD_HTTP_INTERNAL_SERVER_ERROR:
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
/* Server had an internal issue; we should retry, but this API /* Server had an internal issue; we should retry, but this API
leaves this to the application */ leaves this to the application */
break; break;
default: default:
/* unexpected response code */ /* unexpected response code */
GNUNET_break_op (0);
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u\n", "Unexpected response code %u/%d\n",
(unsigned int) response_code); (unsigned int) response_code,
GNUNET_break (0); (int) hr.ec);
response_code = 0;
ec = TALER_JSON_get_error_code (j);
break; break;
} }
if (NULL != lh->link_cb) if (NULL != lh->link_cb)
lh->link_cb (lh->link_cb_cls, lh->link_cb (lh->link_cb_cls,
response_code, &hr,
ec,
0, 0,
NULL, NULL,
NULL, NULL,
NULL, NULL);
j);
TALER_EXCHANGE_link_cancel (lh); TALER_EXCHANGE_link_cancel (lh);
} }

View File

@ -267,13 +267,16 @@ handle_melt_finished (void *cls,
uint32_t noreveal_index = TALER_CNC_KAPPA; /* invalid value */ uint32_t noreveal_index = TALER_CNC_KAPPA; /* invalid value */
struct TALER_ExchangePublicKeyP exchange_pub; struct TALER_ExchangePublicKeyP exchange_pub;
const json_t *j = response; const json_t *j = response;
enum TALER_ErrorCode ec; struct TALER_EXCHANGE_HttpResponse hr = {
.reply = j,
.http_status = (unsigned int) response_code
};
mh->job = NULL; mh->job = NULL;
switch (response_code) switch (response_code)
{ {
case 0: case 0:
ec = TALER_EC_INVALID_RESPONSE; hr.ec = TALER_EC_INVALID_RESPONSE;
break; break;
case MHD_HTTP_OK: case MHD_HTTP_OK:
if (GNUNET_OK != if (GNUNET_OK !=
@ -283,30 +286,25 @@ handle_melt_finished (void *cls,
&noreveal_index)) &noreveal_index))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
response_code = 0; hr.http_status = 0;
ec = TALER_EC_MELT_INVALID_SIGNATURE_BY_EXCHANGE; hr.ec = TALER_EC_MELT_INVALID_SIGNATURE_BY_EXCHANGE;
}
else
{
ec = TALER_EC_NONE;
} }
if (NULL != mh->melt_cb) if (NULL != mh->melt_cb)
{ {
mh->melt_cb (mh->melt_cb_cls, mh->melt_cb (mh->melt_cb_cls,
response_code, &hr,
ec,
noreveal_index, noreveal_index,
(0 == response_code) (0 == response_code)
? NULL ? NULL
: &exchange_pub, : &exchange_pub);
j);
mh->melt_cb = NULL; mh->melt_cb = NULL;
} }
break; break;
case MHD_HTTP_BAD_REQUEST: case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the exchange is buggy /* This should never happen, either us or the exchange is buggy
(or API version conflict); just pass JSON reply to the application */ (or API version conflict); just pass JSON reply to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_CONFLICT: case MHD_HTTP_CONFLICT:
/* Double spending; check signatures on transaction history */ /* Double spending; check signatures on transaction history */
@ -315,46 +313,46 @@ handle_melt_finished (void *cls,
j)) j))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
response_code = 0; hr.http_status = 0;
ec = TALER_EC_MELT_INVALID_SIGNATURE_BY_EXCHANGE; hr.ec = TALER_EC_MELT_INVALID_SIGNATURE_BY_EXCHANGE;
hr.hint = TALER_JSON_get_error_hint (j);
} }
else
ec = TALER_EC_NONE;
break; break;
case MHD_HTTP_FORBIDDEN: case MHD_HTTP_FORBIDDEN:
/* Nothing really to verify, exchange says one of the signatures is /* Nothing really to verify, exchange says one of the signatures is
invalid; assuming we checked them, this should never happen, we invalid; assuming we checked them, this should never happen, we
should pass the JSON reply to the application */ should pass the JSON reply to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_NOT_FOUND: case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify, this should never /* Nothing really to verify, this should never
happen, we should pass the JSON reply to the application */ happen, we should pass the JSON reply to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_INTERNAL_SERVER_ERROR: case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API /* Server had an internal issue; we should retry, but this API
leaves this to the application */ leaves this to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
default: default:
/* unexpected response code */ /* unexpected response code */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d\n", "Unexpected response code %u/%d\n",
(unsigned int) response_code, (unsigned int) response_code,
ec); hr.ec);
GNUNET_break (0); GNUNET_break_op (0);
response_code = 0;
break; break;
} }
if (NULL != mh->melt_cb) if (NULL != mh->melt_cb)
mh->melt_cb (mh->melt_cb_cls, mh->melt_cb (mh->melt_cb_cls,
response_code, &hr,
ec,
UINT32_MAX, UINT32_MAX,
NULL, NULL);
j);
TALER_EXCHANGE_melt_cancel (mh); TALER_EXCHANGE_melt_cancel (mh);
} }

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2017 Taler Systems SA Copyright (C) 2017-2020 Taler Systems SA
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 under the
terms of the GNU General Public License as published by the Free Software terms of the GNU General Public License as published by the Free Software
@ -112,6 +112,10 @@ process_recoup_response (const struct TALER_EXCHANGE_RecoupHandle *ph,
GNUNET_JSON_spec_fixed_auto ("old_coin_pub", &old_coin_pub), GNUNET_JSON_spec_fixed_auto ("old_coin_pub", &old_coin_pub),
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
}; };
struct TALER_EXCHANGE_HttpResponse hr = {
.reply = json,
.http_status = MHD_HTTP_OK
};
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_JSON_parse (json, GNUNET_JSON_parse (json,
@ -127,11 +131,9 @@ process_recoup_response (const struct TALER_EXCHANGE_RecoupHandle *ph,
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
ph->cb (ph->cb_cls, ph->cb (ph->cb_cls,
MHD_HTTP_OK, &hr,
TALER_EC_NONE,
ph->was_refreshed ? NULL : &reserve_pub, ph->was_refreshed ? NULL : &reserve_pub,
ph->was_refreshed ? &old_coin_pub : NULL, ph->was_refreshed ? &old_coin_pub : NULL);
json);
return GNUNET_OK; return GNUNET_OK;
} }
@ -151,23 +153,25 @@ handle_recoup_finished (void *cls,
{ {
struct TALER_EXCHANGE_RecoupHandle *ph = cls; struct TALER_EXCHANGE_RecoupHandle *ph = cls;
const json_t *j = response; const json_t *j = response;
enum TALER_ErrorCode ec; struct TALER_EXCHANGE_HttpResponse hr = {
.reply = j,
.http_status = (unsigned int) response_code
};
ph->job = NULL; ph->job = NULL;
switch (response_code) switch (response_code)
{ {
case 0: case 0:
ec = TALER_EC_INVALID_RESPONSE; hr.ec = TALER_EC_INVALID_RESPONSE;
break; break;
case MHD_HTTP_OK: case MHD_HTTP_OK:
ec = TALER_EC_NONE;
if (GNUNET_OK != if (GNUNET_OK !=
process_recoup_response (ph, process_recoup_response (ph,
j)) j))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
ec = TALER_EC_RECOUP_REPLY_MALFORMED; hr.ec = TALER_EC_RECOUP_REPLY_MALFORMED;
response_code = 0; hr.http_status = 0;
break; break;
} }
TALER_EXCHANGE_recoup_cancel (ph); TALER_EXCHANGE_recoup_cancel (ph);
@ -175,7 +179,8 @@ handle_recoup_finished (void *cls,
case MHD_HTTP_BAD_REQUEST: case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the exchange is buggy /* This should never happen, either us or the exchange is buggy
(or API version conflict); just pass JSON reply to the application */ (or API version conflict); just pass JSON reply to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_CONFLICT: case MHD_HTTP_CONFLICT:
{ {
@ -195,15 +200,18 @@ handle_recoup_finished (void *cls,
&total)) &total))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
response_code = 0; hr.http_status = 0;
hr.ec = TALER_EC_RECOUP_REPLY_MALFORMED;
}
else
{
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
} }
ec = TALER_JSON_get_error_code (j);
ph->cb (ph->cb_cls, ph->cb (ph->cb_cls,
response_code, &hr,
ec,
NULL, NULL,
NULL, NULL);
j);
TALER_EXCHANGE_recoup_cancel (ph); TALER_EXCHANGE_recoup_cancel (ph);
return; return;
} }
@ -211,39 +219,42 @@ handle_recoup_finished (void *cls,
/* Nothing really to verify, exchange says one of the signatures is /* Nothing really to verify, exchange says one of the signatures is
invalid; as we checked them, this should never happen, we invalid; as we checked them, this should never happen, we
should pass the JSON reply to the application */ should pass the JSON reply to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_NOT_FOUND: case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify, this should never /* Nothing really to verify, this should never
happen, we should pass the JSON reply to the application */ happen, we should pass the JSON reply to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_GONE: case MHD_HTTP_GONE:
/* Kind of normal: the money was already sent to the merchant /* Kind of normal: the money was already sent to the merchant
(it was too late for the refund). */ (it was too late for the refund). */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_INTERNAL_SERVER_ERROR: case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API /* Server had an internal issue; we should retry, but this API
leaves this to the application */ leaves this to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
default: default:
/* unexpected response code */ /* unexpected response code */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u\n", "Unexpected response code %u/%d\n",
(unsigned int) response_code); (unsigned int) response_code,
(int) hr.ec);
GNUNET_break (0); GNUNET_break (0);
response_code = 0;
break; break;
} }
ph->cb (ph->cb_cls, ph->cb (ph->cb_cls,
response_code, &hr,
ec,
NULL, NULL,
NULL, NULL);
j);
TALER_EXCHANGE_recoup_cancel (ph); TALER_EXCHANGE_recoup_cancel (ph);
} }

View File

@ -202,13 +202,16 @@ handle_refresh_reveal_finished (void *cls,
{ {
struct TALER_EXCHANGE_RefreshesRevealHandle *rrh = cls; struct TALER_EXCHANGE_RefreshesRevealHandle *rrh = cls;
const json_t *j = response; const json_t *j = response;
enum TALER_ErrorCode ec; struct TALER_EXCHANGE_HttpResponse hr = {
.reply = j,
.http_status = MHD_HTTP_OK
};
rrh->job = NULL; rrh->job = NULL;
switch (response_code) switch (response_code)
{ {
case 0: case 0:
ec = TALER_EC_INVALID_RESPONSE; hr.ec = TALER_EC_INVALID_RESPONSE;
break; break;
case MHD_HTTP_OK: case MHD_HTTP_OK:
{ {
@ -221,19 +224,16 @@ handle_refresh_reveal_finished (void *cls,
sigs); sigs);
if (GNUNET_OK != ret) if (GNUNET_OK != ret)
{ {
response_code = 0; hr.http_status = 0;
ec = TALER_EC_REVEAL_REPLY_MALFORMED; hr.ec = TALER_EC_REVEAL_REPLY_MALFORMED;
} }
else else
{ {
ec = TALER_EC_NONE;
rrh->reveal_cb (rrh->reveal_cb_cls, rrh->reveal_cb (rrh->reveal_cb_cls,
MHD_HTTP_OK, &hr,
ec,
rrh->md->num_fresh_coins, rrh->md->num_fresh_coins,
rrh->md->fresh_coins[rrh->noreveal_index], rrh->md->fresh_coins[rrh->noreveal_index],
sigs, sigs);
j);
rrh->reveal_cb = NULL; rrh->reveal_cb = NULL;
} }
for (unsigned int i = 0; i<rrh->md->num_fresh_coins; i++) for (unsigned int i = 0; i<rrh->md->num_fresh_coins; i++)
@ -245,37 +245,39 @@ handle_refresh_reveal_finished (void *cls,
case MHD_HTTP_BAD_REQUEST: case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the exchange is buggy /* This should never happen, either us or the exchange is buggy
(or API version conflict); just pass JSON reply to the application */ (or API version conflict); just pass JSON reply to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_CONFLICT: case MHD_HTTP_CONFLICT:
/* Nothing really to verify, exchange says our reveal is inconsistent /* Nothing really to verify, exchange says our reveal is inconsistent
with our commitment, so either side is buggy; we with our commitment, so either side is buggy; we
should pass the JSON reply to the application */ should pass the JSON reply to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_INTERNAL_SERVER_ERROR: case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API /* Server had an internal issue; we should retry, but this API
leaves this to the application */ leaves this to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
default: default:
/* unexpected response code */ /* unexpected response code */
GNUNET_break_op (0);
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u\n", "Unexpected response code %u/%d\n",
(unsigned int) response_code); (unsigned int) response_code,
GNUNET_break (0); (int) hr.ec);
response_code = 0;
ec = TALER_JSON_get_error_code (j);
break; break;
} }
if (NULL != rrh->reveal_cb) if (NULL != rrh->reveal_cb)
rrh->reveal_cb (rrh->reveal_cb_cls, rrh->reveal_cb (rrh->reveal_cb_cls,
response_code, &hr,
ec,
0, 0,
NULL, NULL,
NULL, NULL);
j);
TALER_EXCHANGE_refreshes_reveal_cancel (rrh); TALER_EXCHANGE_refreshes_reveal_cancel (rrh);
} }

View File

@ -145,13 +145,16 @@ handle_refund_finished (void *cls,
struct TALER_ExchangePublicKeyP exchange_pub; struct TALER_ExchangePublicKeyP exchange_pub;
struct TALER_ExchangePublicKeyP *ep = NULL; struct TALER_ExchangePublicKeyP *ep = NULL;
const json_t *j = response; const json_t *j = response;
enum TALER_ErrorCode ec; struct TALER_EXCHANGE_HttpResponse hr = {
.reply = j,
.http_status = (unsigned int) response_code
};
rh->job = NULL; rh->job = NULL;
switch (response_code) switch (response_code)
{ {
case 0: case 0:
ec = TALER_EC_INVALID_RESPONSE; hr.ec = TALER_EC_INVALID_RESPONSE;
break; break;
case MHD_HTTP_OK: case MHD_HTTP_OK:
if (GNUNET_OK != if (GNUNET_OK !=
@ -160,67 +163,71 @@ handle_refund_finished (void *cls,
&exchange_pub)) &exchange_pub))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
response_code = 0; hr.http_status = 0;
ec = TALER_EC_REFUND_INVALID_SIGNATURE_BY_EXCHANGE; hr.ec = TALER_EC_REFUND_INVALID_SIGNATURE_BY_EXCHANGE;
} }
else else
{ {
ep = &exchange_pub; ep = &exchange_pub;
ec = TALER_EC_NONE;
} }
break; break;
case MHD_HTTP_BAD_REQUEST: case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the exchange is buggy /* This should never happen, either us or the exchange is buggy
(or API version conflict); just pass JSON reply to the application */ (or API version conflict); just pass JSON reply to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_FORBIDDEN: case MHD_HTTP_FORBIDDEN:
/* Nothing really to verify, exchange says one of the signatures is /* Nothing really to verify, exchange says one of the signatures is
invalid; as we checked them, this should never happen, we invalid; as we checked them, this should never happen, we
should pass the JSON reply to the application */ should pass the JSON reply to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_NOT_FOUND: case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify, this should never /* Nothing really to verify, this should never
happen, we should pass the JSON reply to the application */ happen, we should pass the JSON reply to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_GONE: case MHD_HTTP_GONE:
/* Kind of normal: the money was already sent to the merchant /* Kind of normal: the money was already sent to the merchant
(it was too late for the refund). */ (it was too late for the refund). */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_PRECONDITION_FAILED: case MHD_HTTP_PRECONDITION_FAILED:
/* Client request was inconsistent; might be a currency mismatch /* Client request was inconsistent; might be a currency mismatch
problem. */ problem. */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_CONFLICT: case MHD_HTTP_CONFLICT:
/* Two refund requests were made about the same deposit, but /* Two refund requests were made about the same deposit, but
carrying different refund transaction ids. */ carrying different refund transaction ids. */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_INTERNAL_SERVER_ERROR: case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API /* Server had an internal issue; we should retry, but this API
leaves this to the application */ leaves this to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
default: default:
/* unexpected response code */ /* unexpected response code */
ec = TALER_JSON_get_error_code (j); GNUNET_break_op (0);
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d\n", "Unexpected response code %u/%d\n",
(unsigned int) response_code, (unsigned int) response_code,
ec); hr.ec);
GNUNET_break (0);
response_code = 0;
break; break;
} }
rh->cb (rh->cb_cls, rh->cb (rh->cb_cls,
response_code, &hr,
ec, ep);
ep,
j);
TALER_EXCHANGE_refund_cancel (rh); TALER_EXCHANGE_refund_cancel (rh);
} }

View File

@ -91,6 +91,10 @@ handle_reserves_get_ok (struct TALER_EXCHANGE_ReservesGetHandle *rgh,
TALER_JSON_spec_amount ("balance", &balance), TALER_JSON_spec_amount ("balance", &balance),
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
}; };
struct TALER_EXCHANGE_HttpResponse hr = {
.reply = j,
.http_status = MHD_HTTP_OK
};
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_JSON_parse (j, GNUNET_JSON_parse (j,
@ -141,9 +145,7 @@ handle_reserves_get_ok (struct TALER_EXCHANGE_ReservesGetHandle *rgh,
if (NULL != rgh->cb) if (NULL != rgh->cb)
{ {
rgh->cb (rgh->cb_cls, rgh->cb (rgh->cb_cls,
MHD_HTTP_OK, &hr,
TALER_EC_NONE,
j,
&balance, &balance,
len, len,
rhistory); rhistory);
@ -171,55 +173,59 @@ handle_reserves_get_finished (void *cls,
{ {
struct TALER_EXCHANGE_ReservesGetHandle *rgh = cls; struct TALER_EXCHANGE_ReservesGetHandle *rgh = cls;
const json_t *j = response; const json_t *j = response;
enum TALER_ErrorCode ec; struct TALER_EXCHANGE_HttpResponse hr = {
.reply = j,
.http_status = (unsigned int) response_code
};
rgh->job = NULL; rgh->job = NULL;
switch (response_code) switch (response_code)
{ {
case 0: case 0:
ec = TALER_EC_INVALID_RESPONSE; hr.ec = TALER_EC_INVALID_RESPONSE;
break; break;
case MHD_HTTP_OK: case MHD_HTTP_OK:
ec = TALER_EC_NONE;
if (GNUNET_OK != if (GNUNET_OK !=
handle_reserves_get_ok (rgh, handle_reserves_get_ok (rgh,
j)) j))
{ {
response_code = 0; hr.http_status = 0;
ec = TALER_EC_RESERVE_STATUS_REPLY_MALFORMED; hr.ec = TALER_EC_RESERVE_STATUS_REPLY_MALFORMED;
} }
break; break;
case MHD_HTTP_BAD_REQUEST: case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the exchange is buggy /* This should never happen, either us or the exchange is buggy
(or API version conflict); just pass JSON reply to the application */ (or API version conflict); just pass JSON reply to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_NOT_FOUND: case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify, this should never /* Nothing really to verify, this should never
happen, we should pass the JSON reply to the application */ happen, we should pass the JSON reply to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_INTERNAL_SERVER_ERROR: case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API /* Server had an internal issue; we should retry, but this API
leaves this to the application */ leaves this to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
default: default:
/* unexpected response code */ /* unexpected response code */
ec = TALER_JSON_get_error_code (j); GNUNET_break_op (0);
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u\n", "Unexpected response code %u/%d\n",
(unsigned int) response_code); (unsigned int) response_code,
GNUNET_break (0); (int) hr.ec);
response_code = 0;
break; break;
} }
if (NULL != rgh->cb) if (NULL != rgh->cb)
{ {
rgh->cb (rgh->cb_cls, rgh->cb (rgh->cb_cls,
response_code, &hr,
ec,
j,
NULL, NULL,
0, NULL); 0, NULL);
rgh->cb = NULL; rgh->cb = NULL;

View File

@ -105,6 +105,10 @@ check_transfers_get_response_ok (
GNUNET_JSON_spec_fixed_auto ("exchange_pub", &exchange_pub), GNUNET_JSON_spec_fixed_auto ("exchange_pub", &exchange_pub),
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
}; };
struct TALER_EXCHANGE_HttpResponse hr = {
.reply = json,
.http_status = MHD_HTTP_OK
};
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_JSON_parse (json, GNUNET_JSON_parse (json,
@ -175,10 +179,10 @@ check_transfers_get_response_ok (
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
GNUNET_CRYPTO_hash_context_read (hash_context, GNUNET_CRYPTO_hash_context_read (
&dd, hash_context,
sizeof (struct &dd,
TALER_WireDepositDetailP)); sizeof (struct TALER_WireDepositDetailP));
} }
/* Check signature */ /* Check signature */
wdp.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT); wdp.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT);
@ -200,8 +204,9 @@ check_transfers_get_response_ok (
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify if (GNUNET_OK !=
(TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT, GNUNET_CRYPTO_eddsa_verify (
TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT,
&wdp.purpose, &wdp.purpose,
&exchange_sig.eddsa_signature, &exchange_sig.eddsa_signature,
&exchange_pub.eddsa_pub)) &exchange_pub.eddsa_pub))
@ -229,10 +234,8 @@ check_transfers_get_response_ok (
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
wdh->cb (wdh->cb_cls, wdh->cb (wdh->cb_cls,
MHD_HTTP_OK, &hr,
TALER_EC_NONE,
&exchange_pub, &exchange_pub,
json,
&h_wire, &h_wire,
exec_time, exec_time,
&total_amount, &total_amount,
@ -261,13 +264,16 @@ handle_transfers_get_finished (void *cls,
{ {
struct TALER_EXCHANGE_TransfersGetHandle *wdh = cls; struct TALER_EXCHANGE_TransfersGetHandle *wdh = cls;
const json_t *j = response; const json_t *j = response;
enum TALER_ErrorCode ec; struct TALER_EXCHANGE_HttpResponse hr = {
.reply = j,
.http_status = (unsigned int) response_code
};
wdh->job = NULL; wdh->job = NULL;
switch (response_code) switch (response_code)
{ {
case 0: case 0:
ec = TALER_EC_INVALID_RESPONSE; hr.ec = TALER_EC_INVALID_RESPONSE;
break; break;
case MHD_HTTP_OK: case MHD_HTTP_OK:
if (GNUNET_OK == if (GNUNET_OK ==
@ -275,45 +281,48 @@ handle_transfers_get_finished (void *cls,
j)) j))
return; return;
GNUNET_break_op (0); GNUNET_break_op (0);
ec = TALER_EC_TRANSFERS_GET_REPLY_MALFORMED; hr.ec = TALER_EC_TRANSFERS_GET_REPLY_MALFORMED;
response_code = 0; hr.http_status = 0;
break; break;
case MHD_HTTP_BAD_REQUEST: case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the exchange is buggy /* This should never happen, either us or the exchange is buggy
(or API version conflict); just pass JSON reply to the application */ (or API version conflict); just pass JSON reply to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_FORBIDDEN: case MHD_HTTP_FORBIDDEN:
/* Nothing really to verify, exchange says one of the signatures is /* Nothing really to verify, exchange says one of the signatures is
invalid; as we checked them, this should never happen, we invalid; as we checked them, this should never happen, we
should pass the JSON reply to the application */ should pass the JSON reply to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_NOT_FOUND: case MHD_HTTP_NOT_FOUND:
/* Exchange does not know about transaction; /* Exchange does not know about transaction;
we should pass the reply to the application */ we should pass the reply to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_INTERNAL_SERVER_ERROR: case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API /* Server had an internal issue; we should retry, but this API
leaves this to the application */ leaves this to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
default: default:
/* unexpected response code */ /* unexpected response code */
ec = TALER_JSON_get_error_code (j); GNUNET_break_op (0);
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u\n", "Unexpected response code %u/%d\n",
(unsigned int) response_code); (unsigned int) response_code,
GNUNET_break (0); (int) hr.ec);
response_code = 0;
break; break;
} }
wdh->cb (wdh->cb_cls, wdh->cb (wdh->cb_cls,
response_code, &hr,
ec,
NULL, NULL,
j,
NULL, NULL,
GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
NULL, NULL,

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014-2018 Taler Systems SA Copyright (C) 2014-2020 Taler Systems SA
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 under the
terms of the GNU General Public License as published by the Free Software terms of the GNU General Public License as published by the Free Software
@ -208,15 +208,18 @@ handle_wire_finished (void *cls,
const void *response) const void *response)
{ {
struct TALER_EXCHANGE_WireHandle *wh = cls; struct TALER_EXCHANGE_WireHandle *wh = cls;
enum TALER_ErrorCode ec;
const json_t *j = response; const json_t *j = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.reply = j,
.http_status = (unsigned int) response_code
};
TALER_LOG_DEBUG ("Checking raw /wire response\n"); TALER_LOG_DEBUG ("Checking raw /wire response\n");
wh->job = NULL; wh->job = NULL;
switch (response_code) switch (response_code)
{ {
case 0: case 0:
ec = TALER_EC_INVALID_RESPONSE; hr.ec = TALER_EC_INVALID_RESPONSE;
break; break;
case MHD_HTTP_OK: case MHD_HTTP_OK:
{ {
@ -238,8 +241,8 @@ handle_wire_finished (void *cls,
{ {
/* bogus reply */ /* bogus reply */
GNUNET_break_op (0); GNUNET_break_op (0);
response_code = 0; hr.http_status = 0;
ec = TALER_EC_SERVER_JSON_INVALID; hr.ec = TALER_EC_SERVER_JSON_INVALID;
break; break;
} }
if (0 == (num_accounts = json_array_size (accounts))) if (0 == (num_accounts = json_array_size (accounts)))
@ -247,8 +250,8 @@ handle_wire_finished (void *cls,
/* bogus reply */ /* bogus reply */
GNUNET_break_op (0); GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
response_code = 0; hr.http_status = 0;
ec = TALER_EC_SERVER_JSON_INVALID; hr.ec = TALER_EC_SERVER_JSON_INVALID;
break; break;
} }
if (NULL == (fm = parse_fees (fees))) if (NULL == (fm = parse_fees (fees)))
@ -256,12 +259,11 @@ handle_wire_finished (void *cls,
/* bogus reply */ /* bogus reply */
GNUNET_break_op (0); GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
response_code = 0; hr.http_status = 0;
ec = TALER_EC_SERVER_JSON_INVALID; hr.ec = TALER_EC_SERVER_JSON_INVALID;
break; break;
} }
ec = TALER_EC_NONE;
key_state = TALER_EXCHANGE_get_keys (wh->exchange); key_state = TALER_EXCHANGE_get_keys (wh->exchange);
/* parse accounts */ /* parse accounts */
{ {
@ -286,8 +288,8 @@ handle_wire_finished (void *cls,
{ {
/* bogus reply */ /* bogus reply */
GNUNET_break_op (0); GNUNET_break_op (0);
response_code = 0; hr.http_status = 0;
ec = TALER_EC_SERVER_SIGNATURE_INVALID; hr.ec = TALER_EC_SERVER_SIGNATURE_INVALID;
break; break;
} }
if (GNUNET_OK != if (GNUNET_OK !=
@ -297,16 +299,16 @@ handle_wire_finished (void *cls,
{ {
/* bogus reply */ /* bogus reply */
GNUNET_break_op (0); GNUNET_break_op (0);
response_code = 0; hr.http_status = 0;
ec = TALER_EC_SERVER_JSON_INVALID; hr.ec = TALER_EC_SERVER_JSON_INVALID;
break; break;
} }
if (NULL == (method = TALER_payto_get_method (wa->payto_uri))) if (NULL == (method = TALER_payto_get_method (wa->payto_uri)))
{ {
/* bogus reply */ /* bogus reply */
GNUNET_break_op (0); GNUNET_break_op (0);
response_code = 0; hr.http_status = 0;
ec = TALER_EC_SERVER_JSON_INVALID; hr.ec = TALER_EC_SERVER_JSON_INVALID;
break; break;
} }
if (NULL == (wa->fees = lookup_fee (fm, if (NULL == (wa->fees = lookup_fee (fm,
@ -314,8 +316,8 @@ handle_wire_finished (void *cls,
{ {
/* bogus reply */ /* bogus reply */
GNUNET_break_op (0); GNUNET_break_op (0);
response_code = 0; hr.http_status = 0;
ec = TALER_EC_SERVER_JSON_INVALID; hr.ec = TALER_EC_SERVER_JSON_INVALID;
GNUNET_free (method); GNUNET_free (method);
break; break;
} }
@ -325,11 +327,9 @@ handle_wire_finished (void *cls,
(NULL != wh->cb) ) (NULL != wh->cb) )
{ {
wh->cb (wh->cb_cls, wh->cb (wh->cb_cls,
response_code, &hr,
ec,
num_accounts, num_accounts,
was, was);
j);
wh->cb = NULL; wh->cb = NULL;
} }
} /* end of 'parse accounts */ } /* end of 'parse accounts */
@ -340,36 +340,37 @@ handle_wire_finished (void *cls,
case MHD_HTTP_BAD_REQUEST: case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the exchange is buggy /* This should never happen, either us or the exchange is buggy
(or API version conflict); just pass JSON reply to the application */ (or API version conflict); just pass JSON reply to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_NOT_FOUND: case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify, this should never /* Nothing really to verify, this should never
happen, we should pass the JSON reply to the application */ happen, we should pass the JSON reply to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_INTERNAL_SERVER_ERROR: case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API /* Server had an internal issue; we should retry, but this API
leaves this to the application */ leaves this to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
default: default:
/* unexpected response code */ /* unexpected response code */
ec = TALER_JSON_get_error_code (j); GNUNET_break_op (0);
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d\n", "Unexpected response code %u/%d\n",
(unsigned int) response_code, (unsigned int) response_code,
(int) ec); (int) hr.ec);
GNUNET_break (0);
response_code = 0;
break; break;
} }
if (NULL != wh->cb) if (NULL != wh->cb)
wh->cb (wh->cb_cls, wh->cb (wh->cb_cls,
response_code, &hr,
ec,
0, 0,
NULL, NULL);
j);
TALER_EXCHANGE_wire_cancel (wh); TALER_EXCHANGE_wire_cancel (wh);
} }

View File

@ -116,6 +116,10 @@ reserve_withdraw_ok (struct TALER_EXCHANGE_WithdrawHandle *wh,
&blind_sig), &blind_sig),
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
}; };
struct TALER_EXCHANGE_HttpResponse hr = {
.reply = json,
.http_status = MHD_HTTP_OK
};
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_JSON_parse (json, GNUNET_JSON_parse (json,
@ -140,10 +144,8 @@ reserve_withdraw_ok (struct TALER_EXCHANGE_WithdrawHandle *wh,
/* signature is valid, return it to the application */ /* signature is valid, return it to the application */
wh->cb (wh->cb_cls, wh->cb (wh->cb_cls,
MHD_HTTP_OK, &hr,
TALER_EC_NONE, &fc.sig);
&fc.sig,
json);
/* make sure callback isn't called again after return */ /* make sure callback isn't called again after return */
wh->cb = NULL; wh->cb = NULL;
GNUNET_CRYPTO_rsa_signature_free (fc.sig.rsa_signature); GNUNET_CRYPTO_rsa_signature_free (fc.sig.rsa_signature);
@ -277,13 +279,16 @@ handle_reserve_withdraw_finished (void *cls,
{ {
struct TALER_EXCHANGE_WithdrawHandle *wh = cls; struct TALER_EXCHANGE_WithdrawHandle *wh = cls;
const json_t *j = response; const json_t *j = response;
enum TALER_ErrorCode ec; struct TALER_EXCHANGE_HttpResponse hr = {
.reply = j,
.http_status = (unsigned int) response_code
};
wh->job = NULL; wh->job = NULL;
switch (response_code) switch (response_code)
{ {
case 0: case 0:
ec = TALER_EC_INVALID_RESPONSE; hr.ec = TALER_EC_INVALID_RESPONSE;
break; break;
case MHD_HTTP_OK: case MHD_HTTP_OK:
if (GNUNET_OK != if (GNUNET_OK !=
@ -291,8 +296,8 @@ handle_reserve_withdraw_finished (void *cls,
j)) j))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
response_code = 0; hr.http_status = 0;
ec = TALER_EC_WITHDRAW_REPLY_MALFORMED; hr.ec = TALER_EC_WITHDRAW_REPLY_MALFORMED;
break; break;
} }
GNUNET_assert (NULL == wh->cb); GNUNET_assert (NULL == wh->cb);
@ -301,7 +306,8 @@ handle_reserve_withdraw_finished (void *cls,
case MHD_HTTP_BAD_REQUEST: case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the exchange is buggy /* This should never happen, either us or the exchange is buggy
(or API version conflict); just pass JSON reply to the application */ (or API version conflict); just pass JSON reply to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_CONFLICT: case MHD_HTTP_CONFLICT:
/* The exchange says that the reserve has insufficient funds; /* The exchange says that the reserve has insufficient funds;
@ -311,51 +317,53 @@ handle_reserve_withdraw_finished (void *cls,
j)) j))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
response_code = 0; hr.http_status = 0;
ec = TALER_EC_WITHDRAW_REPLY_MALFORMED; hr.ec = TALER_EC_WITHDRAW_REPLY_MALFORMED;
} }
else else
{ {
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
} }
break; break;
case MHD_HTTP_FORBIDDEN: case MHD_HTTP_FORBIDDEN:
GNUNET_break (0); GNUNET_break_op (0);
/* Nothing really to verify, exchange says one of the signatures is /* Nothing really to verify, exchange says one of the signatures is
invalid; as we checked them, this should never happen, we invalid; as we checked them, this should never happen, we
should pass the JSON reply to the application */ should pass the JSON reply to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_NOT_FOUND: case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify, the exchange basically just says /* Nothing really to verify, the exchange basically just says
that it doesn't know this reserve. Can happen if we that it doesn't know this reserve. Can happen if we
query before the wire transfer went through. query before the wire transfer went through.
We should simply pass the JSON reply to the application. */ We should simply pass the JSON reply to the application. */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_INTERNAL_SERVER_ERROR: case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API /* Server had an internal issue; we should retry, but this API
leaves this to the application */ leaves this to the application */
ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break; break;
default: default:
/* unexpected response code */ /* unexpected response code */
ec = TALER_JSON_get_error_code (j); GNUNET_break_op (0);
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d\n", "Unexpected response code %u/%d\n",
(unsigned int) response_code, (unsigned int) response_code,
(int) ec); (int) hr.ec);
GNUNET_break (0);
response_code = 0;
break; break;
} }
if (NULL != wh->cb) if (NULL != wh->cb)
{ {
wh->cb (wh->cb_cls, wh->cb (wh->cb_cls,
response_code, &hr,
ec, NULL);
NULL,
j);
wh->cb = NULL; wh->cb = NULL;
} }
TALER_EXCHANGE_withdraw_cancel (wh); TALER_EXCHANGE_withdraw_cancel (wh);

View File

@ -56,6 +56,7 @@ libtalertesting_la_SOURCES = \
testing_api_cmd_exec_keyup.c \ testing_api_cmd_exec_keyup.c \
testing_api_cmd_exec_transfer.c \ testing_api_cmd_exec_transfer.c \
testing_api_cmd_exec_wirewatch.c \ testing_api_cmd_exec_wirewatch.c \
testing_api_cmd_insert_deposit.c \
testing_api_cmd_recoup.c \ testing_api_cmd_recoup.c \
testing_api_cmd_refund.c \ testing_api_cmd_refund.c \
testing_api_cmd_refresh.c \ testing_api_cmd_refresh.c \
@ -69,7 +70,6 @@ libtalertesting_la_SOURCES = \
testing_api_cmd_wait.c \ testing_api_cmd_wait.c \
testing_api_cmd_wire.c \ testing_api_cmd_wire.c \
testing_api_cmd_withdraw.c \ testing_api_cmd_withdraw.c \
testing_api_cmd_insert_deposit.c \
testing_api_helpers_auditor.c \ testing_api_helpers_auditor.c \
testing_api_helpers_bank.c \ testing_api_helpers_bank.c \
testing_api_helpers_exchange.c \ testing_api_helpers_exchange.c \

View File

@ -81,14 +81,17 @@ do_timeout (void *cls)
* Function called with information about the auditor. * Function called with information about the auditor.
* *
* @param cls closure * @param cls closure
* @param hr http response details
* @param vi basic information about the auditor * @param vi basic information about the auditor
* @param compat protocol compatibility information * @param compat protocol compatibility information
*/ */
static void static void
version_cb (void *cls, version_cb (void *cls,
const struct TALER_AUDITOR_HttpResponse *hr,
const struct TALER_AUDITOR_VersionInformation *vi, const struct TALER_AUDITOR_VersionInformation *vi,
enum TALER_AUDITOR_VersionCompatibility compat) enum TALER_AUDITOR_VersionCompatibility compat)
{ {
(void) hr;
if ( (NULL != vi) && if ( (NULL != vi) &&
(TALER_AUDITOR_VC_MATCH == compat) ) (TALER_AUDITOR_VC_MATCH == compat) )
global_ret = 0; global_ret = 0;

View File

@ -138,34 +138,30 @@ do_retry (void *cls)
* to check if the response code is acceptable. * to check if the response code is acceptable.
* *
* @param cls closure. * @param cls closure.
* @param http_status HTTP response code. * @param hr HTTP response details
* @param ec taler-specific error code.
* @param obj raw response from the auditor.
*/ */
static void static void
deposit_confirmation_cb (void *cls, deposit_confirmation_cb (void *cls,
unsigned int http_status, const struct TALER_AUDITOR_HttpResponse *hr)
enum TALER_ErrorCode ec,
const json_t *obj)
{ {
struct DepositConfirmationState *dcs = cls; struct DepositConfirmationState *dcs = cls;
dcs->dc = NULL; dcs->dc = NULL;
if (dcs->expected_response_code != http_status) if (dcs->expected_response_code != hr->http_status)
{ {
if (0 != dcs->do_retry) if (0 != dcs->do_retry)
{ {
dcs->do_retry--; dcs->do_retry--;
if ( (0 == http_status) || if ( (0 == hr->http_status) ||
(TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) || (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == hr->ec) ||
(MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) ) (MHD_HTTP_INTERNAL_SERVER_ERROR == hr->http_status) )
{ {
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Retrying deposit confirmation failed with %u/%d\n", "Retrying deposit confirmation failed with %u/%d\n",
http_status, hr->http_status,
(int) ec); (int) hr->ec);
/* on DB conflicts, do not use backoff */ /* on DB conflicts, do not use backoff */
if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == hr->ec)
dcs->backoff = GNUNET_TIME_UNIT_ZERO; dcs->backoff = GNUNET_TIME_UNIT_ZERO;
else else
dcs->backoff = GNUNET_TIME_randomized_backoff (dcs->backoff, dcs->backoff = GNUNET_TIME_randomized_backoff (dcs->backoff,
@ -179,11 +175,11 @@ deposit_confirmation_cb (void *cls,
} }
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u to command %s in %s:%u\n", "Unexpected response code %u to command %s in %s:%u\n",
http_status, hr->http_status,
dcs->is->commands[dcs->is->ip].label, dcs->is->commands[dcs->is->ip].label,
__FILE__, __FILE__,
__LINE__); __LINE__);
json_dumpf (obj, stderr, 0); json_dumpf (hr->reply, stderr, 0);
TALER_TESTING_interpreter_fail (dcs->is); TALER_TESTING_interpreter_fail (dcs->is);
return; return;
} }
@ -310,24 +306,23 @@ deposit_confirmation_run (void *cls,
refund_deadline = timestamp; refund_deadline = timestamp;
} }
} }
dcs->dc = TALER_AUDITOR_deposit_confirmation dcs->dc = TALER_AUDITOR_deposit_confirmation (dcs->auditor,
(dcs->auditor, &h_wire,
&h_wire, &h_contract_terms,
&h_contract_terms, timestamp,
timestamp, refund_deadline,
refund_deadline, &amount_without_fee,
&amount_without_fee, &coin_pub,
&coin_pub, &merchant_pub,
&merchant_pub, exchange_pub,
exchange_pub, exchange_sig,
exchange_sig, &keys->master_pub,
&keys->master_pub, spk->valid_from,
spk->valid_from, spk->valid_until,
spk->valid_until, spk->valid_legal,
spk->valid_legal, &spk->master_sig,
&spk->master_sig, &deposit_confirmation_cb,
&deposit_confirmation_cb, dcs);
dcs);
if (NULL == dcs->dc) if (NULL == dcs->dc)
{ {

View File

@ -127,38 +127,34 @@ do_retry (void *cls)
* Callback to analyze the /exchanges response. * Callback to analyze the /exchanges response.
* *
* @param cls closure. * @param cls closure.
* @param http_status HTTP response code. * @param hr HTTP response details
* @param ec taler-specific error code.
* @param num_exchanges length of the @a ei array * @param num_exchanges length of the @a ei array
* @param ei array with information about the exchanges * @param ei array with information about the exchanges
* @param raw_response raw response from the auditor.
*/ */
static void static void
exchanges_cb (void *cls, exchanges_cb (void *cls,
unsigned int http_status, const struct TALER_AUDITOR_HttpResponse *hr,
enum TALER_ErrorCode ec,
unsigned int num_exchanges, unsigned int num_exchanges,
const struct TALER_AUDITOR_ExchangeInfo *ei, const struct TALER_AUDITOR_ExchangeInfo *ei)
const json_t *raw_response)
{ {
struct ExchangesState *es = cls; struct ExchangesState *es = cls;
es->leh = NULL; es->leh = NULL;
if (es->expected_response_code != http_status) if (es->expected_response_code != hr->http_status)
{ {
if (0 != es->do_retry) if (0 != es->do_retry)
{ {
es->do_retry--; es->do_retry--;
if ( (0 == http_status) || if ( (0 == hr->http_status) ||
(TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) || (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == hr->ec) ||
(MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) ) (MHD_HTTP_INTERNAL_SERVER_ERROR == hr->http_status) )
{ {
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Retrying list exchanges failed with %u/%d\n", "Retrying list exchanges failed with %u/%d\n",
http_status, hr->http_status,
(int) ec); (int) hr->ec);
/* on DB conflicts, do not use backoff */ /* on DB conflicts, do not use backoff */
if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == hr->ec)
es->backoff = GNUNET_TIME_UNIT_ZERO; es->backoff = GNUNET_TIME_UNIT_ZERO;
else else
es->backoff = GNUNET_TIME_randomized_backoff (es->backoff, es->backoff = GNUNET_TIME_randomized_backoff (es->backoff,
@ -170,14 +166,16 @@ exchanges_cb (void *cls,
return; return;
} }
} }
GNUNET_log GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
(GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u/%d to command %s in %s:%u\n",
"Unexpected response code %u to command %s in %s:%u\n", hr->http_status,
http_status, (int) hr->ec,
es->is->commands[es->is->ip].label, es->is->commands[es->is->ip].label,
__FILE__, __FILE__,
__LINE__); __LINE__);
json_dumpf (raw_response, stderr, 0); json_dumpf (hr->reply,
stderr,
0);
TALER_TESTING_interpreter_fail (es->is); TALER_TESTING_interpreter_fail (es->is);
return; return;
} }
@ -193,9 +191,8 @@ exchanges_cb (void *cls,
found = GNUNET_YES; found = GNUNET_YES;
if (GNUNET_NO == found) if (GNUNET_NO == found)
{ {
TALER_LOG_ERROR TALER_LOG_ERROR ("Exchange '%s' doesn't exist at this auditor\n",
("Exchange '%s' doesn't exist at this auditor\n", es->exchange_url);
es->exchange_url);
TALER_TESTING_interpreter_fail (es->is); TALER_TESTING_interpreter_fail (es->is);
return; return;
} }

View File

@ -197,40 +197,36 @@ do_retry (void *cls)
* check if the response code is acceptable. * check if the response code is acceptable.
* *
* @param cls closure. * @param cls closure.
* @param http_status HTTP response code. * @param hr HTTP response details
* @param ec taler-specific error code.
* @param exchange_sig signature provided by the exchange * @param exchange_sig signature provided by the exchange
* (NULL on errors) * (NULL on errors)
* @param exchange_pub public key of the exchange, * @param exchange_pub public key of the exchange,
* used for signing the response. * used for signing the response.
* @param obj raw response from the exchange.
*/ */
static void static void
deposit_cb (void *cls, deposit_cb (void *cls,
unsigned int http_status, const struct TALER_EXCHANGE_HttpResponse *hr,
enum TALER_ErrorCode ec,
const struct TALER_ExchangeSignatureP *exchange_sig, const struct TALER_ExchangeSignatureP *exchange_sig,
const struct TALER_ExchangePublicKeyP *exchange_pub, const struct TALER_ExchangePublicKeyP *exchange_pub)
const json_t *obj)
{ {
struct DepositState *ds = cls; struct DepositState *ds = cls;
ds->dh = NULL; ds->dh = NULL;
if (ds->expected_response_code != http_status) if (ds->expected_response_code != hr->http_status)
{ {
if (0 != ds->do_retry) if (0 != ds->do_retry)
{ {
ds->do_retry--; ds->do_retry--;
if ( (0 == http_status) || if ( (0 == hr->http_status) ||
(TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) || (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == hr->ec) ||
(MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) ) (MHD_HTTP_INTERNAL_SERVER_ERROR == hr->http_status) )
{ {
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Retrying deposit failed with %u/%d\n", "Retrying deposit failed with %u/%d\n",
http_status, hr->http_status,
(int) ec); (int) hr->ec);
/* on DB conflicts, do not use backoff */ /* on DB conflicts, do not use backoff */
if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == hr->ec)
ds->backoff = GNUNET_TIME_UNIT_ZERO; ds->backoff = GNUNET_TIME_UNIT_ZERO;
else else
ds->backoff = GNUNET_TIME_randomized_backoff (ds->backoff, ds->backoff = GNUNET_TIME_randomized_backoff (ds->backoff,
@ -245,15 +241,17 @@ deposit_cb (void *cls,
} }
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u to command %s in %s:%u\n", "Unexpected response code %u to command %s in %s:%u\n",
http_status, hr->http_status,
ds->is->commands[ds->is->ip].label, ds->is->commands[ds->is->ip].label,
__FILE__, __FILE__,
__LINE__); __LINE__);
json_dumpf (obj, stderr, 0); json_dumpf (hr->reply,
stderr,
0);
TALER_TESTING_interpreter_fail (ds->is); TALER_TESTING_interpreter_fail (ds->is);
return; return;
} }
if (MHD_HTTP_OK == http_status) if (MHD_HTTP_OK == hr->http_status)
{ {
ds->deposit_succeeded = GNUNET_YES; ds->deposit_succeeded = GNUNET_YES;
ds->exchange_pub = *exchange_pub; ds->exchange_pub = *exchange_pub;

View File

@ -80,11 +80,8 @@ struct TrackTransactionState
* line matches our expectations. * line matches our expectations.
* *
* @param cls closure. * @param cls closure.
* @param http_status HTTP status code we got. * @param hr HTTP response details
* @param ec taler-specific error code.
* @param exchange_pub public key of the exchange * @param exchange_pub public key of the exchange
* @param json original json reply (may include signatures, those
* have then been validated already).
* @param wtid wire transfer identifier, NULL if exchange did not * @param wtid wire transfer identifier, NULL if exchange did not
* execute the transaction yet. * execute the transaction yet.
* @param execution_time actual or planned execution time for the * @param execution_time actual or planned execution time for the
@ -94,10 +91,8 @@ struct TrackTransactionState
*/ */
static void static void
deposit_wtid_cb (void *cls, deposit_wtid_cb (void *cls,
unsigned int http_status, const struct TALER_EXCHANGE_HttpResponse *hr,
enum TALER_ErrorCode ec,
const struct TALER_ExchangePublicKeyP *exchange_pub, const struct TALER_ExchangePublicKeyP *exchange_pub,
const json_t *json,
const struct TALER_WireTransferIdentifierRawP *wtid, const struct TALER_WireTransferIdentifierRawP *wtid,
struct GNUNET_TIME_Absolute execution_time, struct GNUNET_TIME_Absolute execution_time,
const struct TALER_Amount *coin_contribution) const struct TALER_Amount *coin_contribution)
@ -108,22 +103,24 @@ deposit_wtid_cb (void *cls,
(void) coin_contribution; (void) coin_contribution;
(void) exchange_pub; (void) exchange_pub;
(void) ec;
(void) execution_time; (void) execution_time;
tts->tth = NULL; tts->tth = NULL;
if (tts->expected_response_code != http_status) if (tts->expected_response_code != hr->http_status)
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u to command %s in %s:%u\n", "Unexpected response code %u/%d to command %s in %s:%u\n",
http_status, hr->http_status,
(int) hr->ec,
cmd->label, cmd->label,
__FILE__, __FILE__,
__LINE__); __LINE__);
json_dumpf (json, stderr, 0); json_dumpf (hr->reply,
stderr,
0);
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
} }
switch (http_status) switch (hr->http_status)
{ {
case MHD_HTTP_OK: case MHD_HTTP_OK:
tts->wtid = *wtid; tts->wtid = *wtid;
@ -133,8 +130,9 @@ deposit_wtid_cb (void *cls,
const struct TALER_WireTransferIdentifierRawP *wtid_want; const struct TALER_WireTransferIdentifierRawP *wtid_want;
/* _this_ wire transfer subject line. */ /* _this_ wire transfer subject line. */
bank_transfer_cmd = TALER_TESTING_interpreter_lookup_command bank_transfer_cmd
(is, tts->bank_transfer_reference); = TALER_TESTING_interpreter_lookup_command (is,
tts->bank_transfer_reference);
if (NULL == bank_transfer_cmd) if (NULL == bank_transfer_cmd)
{ {
GNUNET_break (0); GNUNET_break (0);
@ -143,8 +141,9 @@ deposit_wtid_cb (void *cls,
} }
if (GNUNET_OK != if (GNUNET_OK !=
TALER_TESTING_get_trait_wtid TALER_TESTING_get_trait_wtid (bank_transfer_cmd,
(bank_transfer_cmd, 0, &wtid_want)) 0,
&wtid_want))
{ {
GNUNET_break (0); GNUNET_break (0);
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);

View File

@ -123,19 +123,15 @@ parse_coin_reference (const char *coin_reference,
* was paid back belonged to the right reserve. * was paid back belonged to the right reserve.
* *
* @param cls closure * @param cls closure
* @param http_status HTTP response code. * @param hr HTTP response details
* @param ec taler-specific error code.
* @param reserve_pub public key of the reserve receiving the recoup, NULL if refreshed or on error * @param reserve_pub public key of the reserve receiving the recoup, NULL if refreshed or on error
* @param old_coin_pub public key of the dirty coin, NULL if not refreshed or on error * @param old_coin_pub public key of the dirty coin, NULL if not refreshed or on error
* @param full_response raw response from the exchange.
*/ */
static void static void
recoup_cb (void *cls, recoup_cb (void *cls,
unsigned int http_status, const struct TALER_EXCHANGE_HttpResponse *hr,
enum TALER_ErrorCode ec,
const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_ReservePublicKeyP *reserve_pub,
const struct TALER_CoinSpendPublicKeyP *old_coin_pub, const struct TALER_CoinSpendPublicKeyP *old_coin_pub)
const json_t *full_response)
{ {
struct RecoupState *ps = cls; struct RecoupState *ps = cls;
struct TALER_TESTING_Interpreter *is = ps->is; struct TALER_TESTING_Interpreter *is = ps->is;
@ -145,15 +141,18 @@ recoup_cb (void *cls,
unsigned int idx; unsigned int idx;
ps->ph = NULL; ps->ph = NULL;
if (ps->expected_response_code != http_status) if (ps->expected_response_code != hr->http_status)
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u to command %s in %s:%u\n", "Unexpected response code %u/%d to command %s in %s:%u\n",
http_status, hr->http_status,
(int) hr->ec,
cmd->label, cmd->label,
__FILE__, __FILE__,
__LINE__); __LINE__);
json_dumpf (full_response, stderr, 0); json_dumpf (hr->reply,
stderr,
0);
fprintf (stderr, "\n"); fprintf (stderr, "\n");
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
@ -179,7 +178,7 @@ recoup_cb (void *cls,
return; return;
} }
switch (http_status) switch (hr->http_status)
{ {
case MHD_HTTP_OK: case MHD_HTTP_OK:
/* check old_coin_pub or reserve_pub, respectively */ /* check old_coin_pub or reserve_pub, respectively */
@ -256,8 +255,9 @@ recoup_cb (void *cls,
break; break;
default: default:
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Unmanaged HTTP status code %u.\n", "Unmanaged HTTP status code %u/%d.\n",
http_status); hr->http_status,
(int) hr->ec);
break; break;
} }
TALER_TESTING_interpreter_next (is); TALER_TESTING_interpreter_next (is);

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2018 Taler Systems SA Copyright (C) 2018-2020 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it TALER is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by under the terms of the GNU General Public License as published by
@ -328,9 +328,8 @@ do_reveal_retry (void *cls)
* code is expected and copies into its command's state the data * code is expected and copies into its command's state the data
* coming from the exchange, namely the fresh coins. * coming from the exchange, namely the fresh coins.
* *
* @param cls closure. * @param cls closure, a `struct RefreshRevealState`
* @param http_status HTTP response code. * @param hr HTTP response details
* @param ec taler-specific error code.
* @param num_coins number of fresh coins created, length of the * @param num_coins number of fresh coins created, length of the
* @a sigs and @a coin_privs arrays, 0 if the operation * @a sigs and @a coin_privs arrays, 0 if the operation
* failed. * failed.
@ -338,36 +337,33 @@ do_reveal_retry (void *cls)
* coins that were created, NULL on error. * coins that were created, NULL on error.
* @param sigs array of signature over @a num_coins coins, * @param sigs array of signature over @a num_coins coins,
* NULL on error. * NULL on error.
* @param full_response raw exchange response.
*/ */
static void static void
reveal_cb (void *cls, reveal_cb (void *cls,
unsigned int http_status, const struct TALER_EXCHANGE_HttpResponse *hr,
enum TALER_ErrorCode ec,
unsigned int num_coins, unsigned int num_coins,
const struct TALER_PlanchetSecretsP *coin_privs, const struct TALER_PlanchetSecretsP *coin_privs,
const struct TALER_DenominationSignature *sigs, const struct TALER_DenominationSignature *sigs)
const json_t *full_response)
{ {
struct RefreshRevealState *rrs = cls; struct RefreshRevealState *rrs = cls;
const struct TALER_TESTING_Command *melt_cmd; const struct TALER_TESTING_Command *melt_cmd;
rrs->rrh = NULL; rrs->rrh = NULL;
if (rrs->expected_response_code != http_status) if (rrs->expected_response_code != hr->http_status)
{ {
if (0 != rrs->do_retry) if (0 != rrs->do_retry)
{ {
rrs->do_retry--; rrs->do_retry--;
if ( (0 == http_status) || if ( (0 == hr->http_status) ||
(TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) || (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == hr->ec) ||
(MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) ) (MHD_HTTP_INTERNAL_SERVER_ERROR == hr->http_status) )
{ {
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Retrying refresh reveal failed with %u/%d\n", "Retrying refresh reveal failed with %u/%d\n",
http_status, hr->http_status,
(int) ec); (int) hr->ec);
/* on DB conflicts, do not use backoff */ /* on DB conflicts, do not use backoff */
if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == hr->ec)
rrs->backoff = GNUNET_TIME_UNIT_ZERO; rrs->backoff = GNUNET_TIME_UNIT_ZERO;
else else
rrs->backoff = GNUNET_TIME_randomized_backoff (rrs->backoff, rrs->backoff = GNUNET_TIME_randomized_backoff (rrs->backoff,
@ -383,17 +379,19 @@ reveal_cb (void *cls,
} }
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d to command %s in %s:%u\n", "Unexpected response code %u/%d to command %s in %s:%u\n",
http_status, hr->http_status,
(int) ec, (int) hr->ec,
rrs->is->commands[rrs->is->ip].label, rrs->is->commands[rrs->is->ip].label,
__FILE__, __FILE__,
__LINE__); __LINE__);
json_dumpf (full_response, stderr, 0); json_dumpf (hr->reply,
stderr,
0);
TALER_TESTING_interpreter_fail (rrs->is); TALER_TESTING_interpreter_fail (rrs->is);
return; return;
} }
melt_cmd = TALER_TESTING_interpreter_lookup_command melt_cmd = TALER_TESTING_interpreter_lookup_command (rrs->is,
(rrs->is, rrs->melt_reference); rrs->melt_reference);
if (NULL == melt_cmd) if (NULL == melt_cmd)
{ {
GNUNET_break (0); GNUNET_break (0);
@ -401,7 +399,7 @@ reveal_cb (void *cls,
return; return;
} }
rrs->num_fresh_coins = num_coins; rrs->num_fresh_coins = num_coins;
switch (http_status) switch (hr->http_status)
{ {
case MHD_HTTP_OK: case MHD_HTTP_OK:
rrs->fresh_coins = GNUNET_new_array (num_coins, rrs->fresh_coins = GNUNET_new_array (num_coins,
@ -435,8 +433,9 @@ reveal_cb (void *cls,
break; break;
default: default:
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Unknown HTTP status %d\n", "Unknown HTTP status %u/%d\n",
http_status); hr->http_status,
(int) hr->ec);
} }
TALER_TESTING_interpreter_next (rrs->is); TALER_TESTING_interpreter_next (rrs->is);
} }
@ -560,8 +559,7 @@ do_link_retry (void *cls)
* withdrawn by the "refresh reveal" CMD. * withdrawn by the "refresh reveal" CMD.
* *
* @param cls closure. * @param cls closure.
* @param http_status HTTP response code. * @param hr HTTP response details
* @param ec taler-specific error code
* @param num_coins number of fresh coins created, length of the * @param num_coins number of fresh coins created, length of the
* @a sigs and @a coin_privs arrays, 0 if the operation * @a sigs and @a coin_privs arrays, 0 if the operation
* failed. * failed.
@ -571,42 +569,38 @@ do_link_retry (void *cls)
* error. * error.
* @param pubs array of public keys for the @a sigs, * @param pubs array of public keys for the @a sigs,
* NULL on error. * NULL on error.
* @param full_response raw response from the exchange.
*/ */
static void static void
link_cb (void *cls, link_cb (void *cls,
unsigned int http_status, const struct TALER_EXCHANGE_HttpResponse *hr,
enum TALER_ErrorCode ec,
unsigned int num_coins, unsigned int num_coins,
const struct TALER_CoinSpendPrivateKeyP *coin_privs, const struct TALER_CoinSpendPrivateKeyP *coin_privs,
const struct TALER_DenominationSignature *sigs, const struct TALER_DenominationSignature *sigs,
const struct TALER_DenominationPublicKey *pubs, const struct TALER_DenominationPublicKey *pubs)
const json_t *full_response)
{ {
struct RefreshLinkState *rls = cls; struct RefreshLinkState *rls = cls;
const struct TALER_TESTING_Command *reveal_cmd; const struct TALER_TESTING_Command *reveal_cmd;
struct TALER_TESTING_Command *link_cmd struct TALER_TESTING_Command *link_cmd = &rls->is->commands[rls->is->ip];
= &rls->is->commands[rls->is->ip];
unsigned int found; unsigned int found;
const unsigned int *num_fresh_coins; const unsigned int *num_fresh_coins;
rls->rlh = NULL; rls->rlh = NULL;
if (rls->expected_response_code != http_status) if (rls->expected_response_code != hr->http_status)
{ {
if (0 != rls->do_retry) if (0 != rls->do_retry)
{ {
rls->do_retry--; rls->do_retry--;
if ( (0 == http_status) || if ( (0 == hr->http_status) ||
(TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) || (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == hr->ec) ||
(MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) ) (MHD_HTTP_INTERNAL_SERVER_ERROR == hr->http_status) )
{ {
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Retrying refresh link failed with %u/%d\n", "Retrying refresh link failed with %u/%d\n",
http_status, hr->http_status,
(int) ec); (int) hr->ec);
/* on DB conflicts, do not use backoff */ /* on DB conflicts, do not use backoff */
if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == hr->ec)
rls->backoff = GNUNET_TIME_UNIT_ZERO; rls->backoff = GNUNET_TIME_UNIT_ZERO;
else else
rls->backoff = GNUNET_TIME_randomized_backoff (rls->backoff, rls->backoff = GNUNET_TIME_randomized_backoff (rls->backoff,
@ -622,18 +616,19 @@ link_cb (void *cls,
} }
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d to command %s in %s:%u\n", "Unexpected response code %u/%d to command %s in %s:%u\n",
http_status, hr->http_status,
(int) ec, (int) hr->ec,
link_cmd->label, link_cmd->label,
__FILE__, __FILE__,
__LINE__); __LINE__);
json_dumpf (full_response, stderr, 0); json_dumpf (hr->reply,
stderr,
0);
TALER_TESTING_interpreter_fail (rls->is); TALER_TESTING_interpreter_fail (rls->is);
return; return;
} }
reveal_cmd = TALER_TESTING_interpreter_lookup_command reveal_cmd = TALER_TESTING_interpreter_lookup_command (rls->is,
(rls->is, rls->reveal_reference); rls->reveal_reference);
if (NULL == reveal_cmd) if (NULL == reveal_cmd)
{ {
GNUNET_break (0); GNUNET_break (0);
@ -641,12 +636,14 @@ link_cb (void *cls,
return; return;
} }
switch (http_status) switch (hr->http_status)
{ {
case MHD_HTTP_OK: case MHD_HTTP_OK:
/* check that number of coins returned matches */ /* check that number of coins returned matches */
if (GNUNET_OK != TALER_TESTING_get_trait_uint if (GNUNET_OK !=
(reveal_cmd, 0, &num_fresh_coins)) TALER_TESTING_get_trait_uint (reveal_cmd,
0,
&num_fresh_coins))
{ {
GNUNET_break (0); GNUNET_break (0);
TALER_TESTING_interpreter_fail (rls->is); TALER_TESTING_interpreter_fail (rls->is);
@ -666,39 +663,45 @@ link_cb (void *cls,
/* check that the coins match */ /* check that the coins match */
for (unsigned int i = 0; i<num_coins; i++) for (unsigned int i = 0; i<num_coins; i++)
for (unsigned int j = i + 1; j<num_coins; j++) for (unsigned int j = i + 1; j<num_coins; j++)
if (0 == GNUNET_memcmp if (0 ==
(&coin_privs[i], &coin_privs[j])) GNUNET_memcmp (&coin_privs[i],
&coin_privs[j]))
GNUNET_break (0); GNUNET_break (0);
/* Note: coins might be legitimately permutated in here... */ /* Note: coins might be legitimately permutated in here... */
found = 0; found = 0;
/* Will point to the pointer inside the cmd state. */ /* Will point to the pointer inside the cmd state. */
const struct TALER_TESTING_FreshCoinData *fc = NULL;
if (GNUNET_OK != TALER_TESTING_get_trait_fresh_coins
(reveal_cmd, 0, &fc))
{ {
GNUNET_break (0); const struct TALER_TESTING_FreshCoinData *fc = NULL;
TALER_TESTING_interpreter_fail (rls->is);
return;
}
for (unsigned int i = 0; i<num_coins; i++) if (GNUNET_OK !=
for (unsigned int j = 0; j<num_coins; j++) TALER_TESTING_get_trait_fresh_coins (reveal_cmd,
0,
&fc))
{ {
if ( (0 == GNUNET_memcmp GNUNET_break (0);
(&coin_privs[i], &fc[j].coin_priv)) && TALER_TESTING_interpreter_fail (rls->is);
(0 == GNUNET_CRYPTO_rsa_signature_cmp return;
(fc[i].sig.rsa_signature,
sigs[j].rsa_signature)) &&
(0 == GNUNET_CRYPTO_rsa_public_key_cmp
(fc[i].pk->key.rsa_public_key,
pubs[j].rsa_public_key)) )
{
found++;
break;
}
} }
for (unsigned int i = 0; i<num_coins; i++)
for (unsigned int j = 0; j<num_coins; j++)
{
if ( (0 ==
GNUNET_memcmp (&coin_privs[i],
&fc[j].coin_priv)) &&
(0 ==
GNUNET_CRYPTO_rsa_signature_cmp (fc[i].sig.rsa_signature,
sigs[j].rsa_signature)) &&
(0 ==
GNUNET_CRYPTO_rsa_public_key_cmp (fc[i].pk->key.rsa_public_key,
pubs[j].rsa_public_key)) )
{
found++;
break;
}
}
}
if (found != num_coins) if (found != num_coins)
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@ -719,8 +722,9 @@ link_cb (void *cls,
break; break;
default: default:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unknown HTTP response code %u.\n", "Unknown HTTP response code %u/%d.\n",
http_status); hr->http_status,
hr->ec);
} }
TALER_TESTING_interpreter_next (rls->is); TALER_TESTING_interpreter_next (rls->is);
} }
@ -746,9 +750,8 @@ refresh_link_run (void *cls,
const struct TALER_TESTING_Command *coin_cmd; const struct TALER_TESTING_Command *coin_cmd;
rls->is = is; rls->is = is;
reveal_cmd = TALER_TESTING_interpreter_lookup_command reveal_cmd = TALER_TESTING_interpreter_lookup_command (rls->is,
(rls->is, rls->reveal_reference); rls->reveal_reference);
if (NULL == reveal_cmd) if (NULL == reveal_cmd)
{ {
GNUNET_break (0); GNUNET_break (0);
@ -756,9 +759,8 @@ refresh_link_run (void *cls,
return; return;
} }
rrs = reveal_cmd->cls; rrs = reveal_cmd->cls;
melt_cmd = TALER_TESTING_interpreter_lookup_command melt_cmd = TALER_TESTING_interpreter_lookup_command (rls->is,
(rls->is, rrs->melt_reference); rrs->melt_reference);
if (NULL == melt_cmd) if (NULL == melt_cmd)
{ {
GNUNET_break (0); GNUNET_break (0);
@ -769,8 +771,8 @@ refresh_link_run (void *cls,
/* find reserve_withdraw command */ /* find reserve_withdraw command */
{ {
rms = melt_cmd->cls; rms = melt_cmd->cls;
coin_cmd = TALER_TESTING_interpreter_lookup_command coin_cmd = TALER_TESTING_interpreter_lookup_command (rls->is,
(rls->is, rms->coin_reference); rms->coin_reference);
if (NULL == coin_cmd) if (NULL == coin_cmd)
{ {
GNUNET_break (0); GNUNET_break (0);
@ -789,8 +791,10 @@ refresh_link_run (void *cls,
} }
/* finally, use private key from withdraw sign command */ /* finally, use private key from withdraw sign command */
rls->rlh = TALER_EXCHANGE_link rls->rlh = TALER_EXCHANGE_link (is->exchange,
(is->exchange, coin_priv, &link_cb, rls); coin_priv,
&link_cb,
rls);
if (NULL == rls->rlh) if (NULL == rls->rlh)
{ {
@ -871,39 +875,35 @@ do_melt_retry (void *cls)
* CMD was set to do so. * CMD was set to do so.
* *
* @param cls closure. * @param cls closure.
* @param http_status HTTP response code. * @param hr HTTP response details
* @param ec taler-specific error code.
* @param noreveal_index choice by the exchange in the * @param noreveal_index choice by the exchange in the
* cut-and-choose protocol, UINT16_MAX on error. * cut-and-choose protocol, UINT16_MAX on error.
* @param exchange_pub public key the exchange used for signing. * @param exchange_pub public key the exchange used for signing.
* @param full_response raw response body from the exchange.
*/ */
static void static void
melt_cb (void *cls, melt_cb (void *cls,
unsigned int http_status, const struct TALER_EXCHANGE_HttpResponse *hr,
enum TALER_ErrorCode ec,
uint32_t noreveal_index, uint32_t noreveal_index,
const struct TALER_ExchangePublicKeyP *exchange_pub, const struct TALER_ExchangePublicKeyP *exchange_pub)
const json_t *full_response)
{ {
struct RefreshMeltState *rms = cls; struct RefreshMeltState *rms = cls;
rms->rmh = NULL; rms->rmh = NULL;
if (rms->expected_response_code != http_status) if (rms->expected_response_code != hr->http_status)
{ {
if (0 != rms->do_retry) if (0 != rms->do_retry)
{ {
rms->do_retry--; rms->do_retry--;
if ( (0 == http_status) || if ( (0 == hr->http_status) ||
(TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) || (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == hr->ec) ||
(MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) ) (MHD_HTTP_INTERNAL_SERVER_ERROR == hr->http_status) )
{ {
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Retrying refresh melt failed with %u/%d\n", "Retrying refresh melt failed with %u/%d\n",
http_status, hr->http_status,
(int) ec); (int) hr->ec);
/* on DB conflicts, do not use backoff */ /* on DB conflicts, do not use backoff */
if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == hr->ec)
rms->backoff = GNUNET_TIME_UNIT_ZERO; rms->backoff = GNUNET_TIME_UNIT_ZERO;
else else
rms->backoff = GNUNET_TIME_randomized_backoff (rms->backoff, rms->backoff = GNUNET_TIME_randomized_backoff (rms->backoff,
@ -911,22 +911,22 @@ melt_cb (void *cls,
rms->total_backoff = GNUNET_TIME_relative_add (rms->total_backoff, rms->total_backoff = GNUNET_TIME_relative_add (rms->total_backoff,
rms->backoff); rms->backoff);
rms->is->commands[rms->is->ip].num_tries++; rms->is->commands[rms->is->ip].num_tries++;
rms->retry_task = GNUNET_SCHEDULER_add_delayed rms->retry_task = GNUNET_SCHEDULER_add_delayed (rms->backoff,
(rms->backoff, &do_melt_retry,
&do_melt_retry, rms);
rms);
return; return;
} }
} }
GNUNET_log GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
(GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u/%d to command %s in %s:%u\n",
"Unexpected response code %u/%d to command %s in %s:%u\n", hr->http_status,
http_status, (int) hr->ec,
(int) ec, rms->is->commands[rms->is->ip].label,
rms->is->commands[rms->is->ip].label, __FILE__,
__FILE__, __LINE__);
__LINE__); json_dumpf (hr->reply,
json_dumpf (full_response, stderr, 0); stderr,
0);
TALER_TESTING_interpreter_fail (rms->is); TALER_TESTING_interpreter_fail (rms->is);
return; return;
} }
@ -943,9 +943,11 @@ melt_cb (void *cls,
{ {
TALER_LOG_DEBUG ("Doubling the melt (%s)\n", TALER_LOG_DEBUG ("Doubling the melt (%s)\n",
rms->is->commands[rms->is->ip].label); rms->is->commands[rms->is->ip].label);
rms->rmh = TALER_EXCHANGE_melt rms->rmh = TALER_EXCHANGE_melt (rms->is->exchange,
(rms->is->exchange, rms->refresh_data_length, rms->refresh_data_length,
rms->refresh_data, &melt_cb, rms); rms->refresh_data,
&melt_cb,
rms);
rms->double_melt = GNUNET_NO; rms->double_melt = GNUNET_NO;
return; return;
} }

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014-2018 Taler Systems SA Copyright (C) 2014-2020 Taler Systems SA
TALER is free software; you can redistribute it and/or modify TALER is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as it under the terms of the GNU General Public License as
@ -80,18 +80,14 @@ struct RefundState
* response code is acceptable. * response code is acceptable.
* *
* @param cls closure * @param cls closure
* @param http_status HTTP response code. * @param hr HTTP response details
* @param ec taler-specific error code.
* @param exchange_pub public key the exchange * @param exchange_pub public key the exchange
* used for signing @a obj. * used for signing @a obj.
* @param obj response object.
*/ */
static void static void
refund_cb (void *cls, refund_cb (void *cls,
unsigned int http_status, const struct TALER_EXCHANGE_HttpResponse *hr,
enum TALER_ErrorCode ec, const struct TALER_ExchangePublicKeyP *exchange_pub)
const struct TALER_ExchangePublicKeyP *exchange_pub,
const json_t *obj)
{ {
struct RefundState *rs = cls; struct RefundState *rs = cls;
@ -99,15 +95,18 @@ refund_cb (void *cls,
refund_cmd = &rs->is->commands[rs->is->ip]; refund_cmd = &rs->is->commands[rs->is->ip];
rs->rh = NULL; rs->rh = NULL;
if (rs->expected_response_code != http_status) if (rs->expected_response_code != hr->http_status)
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u to command %s in %s:%u\n", "Unexpected response code %u/%d to command %s in %s:%u\n",
http_status, hr->http_status,
hr->ec,
refund_cmd->label, refund_cmd->label,
__FILE__, __FILE__,
__LINE__); __LINE__);
json_dumpf (obj, stderr, 0); json_dumpf (hr->reply,
stderr,
0);
TALER_TESTING_interpreter_fail (rs->is); TALER_TESTING_interpreter_fail (rs->is);
return; return;
} }

View File

@ -237,9 +237,7 @@ analyze_command (const struct TALER_ReservePublicKeyP *reserve_pub,
* both acceptable. * both acceptable.
* *
* @param cls closure. * @param cls closure.
* @param http_status HTTP response code. * @param hr HTTP response details
* @param ec taler-specific error code.
* @param json original JSON response from the exchange
* @param balance current balance in the reserve, NULL on error. * @param balance current balance in the reserve, NULL on error.
* @param history_length number of entries in the transaction * @param history_length number of entries in the transaction
* history, 0 on error. * history, 0 on error.
@ -247,9 +245,7 @@ analyze_command (const struct TALER_ReservePublicKeyP *reserve_pub,
*/ */
static void static void
reserve_status_cb (void *cls, reserve_status_cb (void *cls,
unsigned int http_status, const struct TALER_EXCHANGE_HttpResponse *hr,
enum TALER_ErrorCode ec,
const json_t *json,
const struct TALER_Amount *balance, const struct TALER_Amount *balance,
unsigned int history_length, unsigned int history_length,
const struct TALER_EXCHANGE_ReserveHistory *history) const struct TALER_EXCHANGE_ReserveHistory *history)
@ -259,14 +255,16 @@ reserve_status_cb (void *cls,
struct TALER_Amount eb; struct TALER_Amount eb;
ss->rsh = NULL; ss->rsh = NULL;
if (ss->expected_response_code != http_status) if (ss->expected_response_code != hr->http_status)
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected HTTP response code: %d in %s:%u\n", "Unexpected HTTP response code: %d in %s:%u\n",
http_status, hr->http_status,
__FILE__, __FILE__,
__LINE__); __LINE__);
json_dumpf (json, stderr, 0); json_dumpf (hr->reply,
stderr,
0);
TALER_TESTING_interpreter_fail (ss->is); TALER_TESTING_interpreter_fail (ss->is);
return; return;
} }
@ -287,7 +285,9 @@ reserve_status_cb (void *cls,
{ {
int found[history_length]; int found[history_length];
memset (found, 0, sizeof (found)); memset (found,
0,
sizeof (found));
for (unsigned int i = 0; i<=is->ip; i++) for (unsigned int i = 0; i<=is->ip; i++)
{ {
struct TALER_TESTING_Command *cmd = &is->commands[i]; struct TALER_TESTING_Command *cmd = &is->commands[i];

View File

@ -43,11 +43,6 @@ struct TrackTransferState
*/ */
const char *expected_wire_fee; const char *expected_wire_fee;
/**
* Expected HTTP response code.
*/
unsigned int expected_response_code;
/** /**
* Reference to any operation that can provide a WTID. * Reference to any operation that can provide a WTID.
* Will be the WTID to track. * Will be the WTID to track.
@ -69,12 +64,6 @@ struct TrackTransferState
*/ */
const char *total_amount_reference; const char *total_amount_reference;
/**
* Index to the WTID to pick, in case @a wtid_reference has
* many on offer.
*/
unsigned int index;
/** /**
* Handle to a pending "track transfer" operation. * Handle to a pending "track transfer" operation.
*/ */
@ -84,6 +73,17 @@ struct TrackTransferState
* Interpreter state. * Interpreter state.
*/ */
struct TALER_TESTING_Interpreter *is; struct TALER_TESTING_Interpreter *is;
/**
* Expected HTTP response code.
*/
unsigned int expected_response_code;
/**
* Index to the WTID to pick, in case @a wtid_reference has
* many on offer.
*/
unsigned int index;
}; };
@ -120,12 +120,9 @@ track_transfer_cleanup (void *cls,
* wire fees and hashed wire details as well. * wire fees and hashed wire details as well.
* *
* @param cls closure. * @param cls closure.
* @param http_status HTTP status code we got. * @param hr HTTP response details
* @param ec taler-specific error code.
* @param exchange_pub public key the exchange used for signing * @param exchange_pub public key the exchange used for signing
* the response. * the response.
* @param json original json reply (may include signatures, those
* have then been validated already).
* @param h_wire hash of the wire transfer address the transfer * @param h_wire hash of the wire transfer address the transfer
* went to, or NULL on error. * went to, or NULL on error.
* @param execution_time time when the exchange claims to have * @param execution_time time when the exchange claims to have
@ -140,10 +137,8 @@ track_transfer_cleanup (void *cls,
*/ */
static void static void
track_transfer_cb (void *cls, track_transfer_cb (void *cls,
unsigned int http_status, const struct TALER_EXCHANGE_HttpResponse *hr,
enum TALER_ErrorCode ec,
const struct TALER_ExchangePublicKeyP *exchange_pub, const struct TALER_ExchangePublicKeyP *exchange_pub,
const json_t *json,
const struct GNUNET_HashCode *h_wire, const struct GNUNET_HashCode *h_wire,
struct GNUNET_TIME_Absolute execution_time, struct GNUNET_TIME_Absolute execution_time,
const struct TALER_Amount *total_amount, const struct TALER_Amount *total_amount,
@ -158,20 +153,23 @@ track_transfer_cb (void *cls,
(void) exchange_pub; (void) exchange_pub;
tts->tth = NULL; tts->tth = NULL;
if (tts->expected_response_code != http_status) if (tts->expected_response_code != hr->http_status)
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u to command %s in %s:%u\n", "Unexpected response code %u/%d to command %s in %s:%u\n",
http_status, hr->http_status,
(int) hr->ec,
cmd->label, cmd->label,
__FILE__, __FILE__,
__LINE__); __LINE__);
json_dumpf (json, stderr, 0); json_dumpf (hr->reply,
stderr,
0);
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
} }
switch (http_status) switch (hr->http_status)
{ {
case MHD_HTTP_OK: case MHD_HTTP_OK:
if (NULL == tts->expected_total_amount) if (NULL == tts->expected_total_amount)
@ -204,7 +202,9 @@ track_transfer_cb (void *cls,
cmd->label, cmd->label,
TALER_amount_to_string (total_amount), TALER_amount_to_string (total_amount),
TALER_amount_to_string (&expected_amount)); TALER_amount_to_string (&expected_amount));
json_dumpf (json, stderr, 0); json_dumpf (hr->reply,
stderr,
0);
fprintf (stderr, "\n"); fprintf (stderr, "\n");
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
@ -225,7 +225,9 @@ track_transfer_cb (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Wire fee mismatch to command %s\n", "Wire fee mismatch to command %s\n",
cmd->label); cmd->label);
json_dumpf (json, stderr, 0); json_dumpf (hr->reply,
stderr,
0);
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
} }
@ -242,15 +244,15 @@ track_transfer_cb (void *cls,
const json_t *wire_details; const json_t *wire_details;
struct GNUNET_HashCode h_wire_details; struct GNUNET_HashCode h_wire_details;
if (NULL == (wire_details_cmd wire_details_cmd
= TALER_TESTING_interpreter_lookup_command = TALER_TESTING_interpreter_lookup_command (is,
(is, tts->wire_details_reference))) tts->wire_details_reference);
if (NULL == wire_details_cmd)
{ {
GNUNET_break (0); GNUNET_break (0);
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
} }
if (GNUNET_OK != if (GNUNET_OK !=
TALER_TESTING_get_trait_wire_details (wire_details_cmd, TALER_TESTING_get_trait_wire_details (wire_details_cmd,
0, 0,
@ -260,19 +262,18 @@ track_transfer_cb (void *cls,
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
} }
GNUNET_assert (GNUNET_OK ==
GNUNET_assert TALER_JSON_merchant_wire_signature_hash (wire_details,
(GNUNET_OK == &h_wire_details));
TALER_JSON_merchant_wire_signature_hash (wire_details,
&h_wire_details));
if (0 != GNUNET_memcmp (&h_wire_details, if (0 != GNUNET_memcmp (&h_wire_details,
h_wire)) h_wire))
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Wire hash missmath to command %s\n", "Wire hash missmath to command %s\n",
cmd->label); cmd->label);
json_dumpf (json, stderr, 0); json_dumpf (hr->reply,
stderr,
0);
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
} }
@ -282,15 +283,15 @@ track_transfer_cb (void *cls,
const struct TALER_TESTING_Command *total_amount_cmd; const struct TALER_TESTING_Command *total_amount_cmd;
const struct TALER_Amount *total_amount_from_reference; const struct TALER_Amount *total_amount_from_reference;
if (NULL == (total_amount_cmd total_amount_cmd
= TALER_TESTING_interpreter_lookup_command = TALER_TESTING_interpreter_lookup_command (is,
(is, tts->total_amount_reference))) tts->total_amount_reference);
if (NULL == total_amount_cmd)
{ {
GNUNET_break (0); GNUNET_break (0);
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
} }
if (GNUNET_OK != if (GNUNET_OK !=
TALER_TESTING_get_trait_amount_obj (total_amount_cmd, TALER_TESTING_get_trait_amount_obj (total_amount_cmd,
0, 0,
@ -300,14 +301,15 @@ track_transfer_cb (void *cls,
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
} }
if (0 != TALER_amount_cmp (total_amount, if (0 != TALER_amount_cmp (total_amount,
total_amount_from_reference)) total_amount_from_reference))
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Amount missmath to command %s\n", "Amount missmath to command %s\n",
cmd->label); cmd->label);
json_dumpf (json, stderr, 0); json_dumpf (hr->reply,
stderr,
0);
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
} }

View File

@ -72,37 +72,31 @@ struct WireState
* that the wire fee is acceptable too. * that the wire fee is acceptable too.
* *
* @param cls closure. * @param cls closure.
* @param http_status HTTP response code. * @param hr HTTP response details
* @param ec taler-specific error code.
* @param accounts_len length of the @a accounts array. * @param accounts_len length of the @a accounts array.
* @param accounts list of wire accounts of the exchange, * @param accounts list of wire accounts of the exchange,
* NULL on error. * NULL on error.
* @param full_reply the complete response from the exchange
*/ */
static void static void
wire_cb (void *cls, wire_cb (void *cls,
unsigned int http_status, const struct TALER_EXCHANGE_HttpResponse *hr,
enum TALER_ErrorCode ec,
unsigned int accounts_len, unsigned int accounts_len,
const struct TALER_EXCHANGE_WireAccount *accounts, const struct TALER_EXCHANGE_WireAccount *accounts)
const json_t *full_reply)
{ {
struct WireState *ws = cls; struct WireState *ws = cls;
struct TALER_TESTING_Command *cmd = &ws->is->commands[ws->is->ip]; struct TALER_TESTING_Command *cmd = &ws->is->commands[ws->is->ip];
struct TALER_Amount expected_fee; struct TALER_Amount expected_fee;
(void) ec;
(void) full_reply;
TALER_LOG_DEBUG ("Checking parsed /wire response\n"); 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 != hr->http_status)
{ {
GNUNET_break (0); GNUNET_break (0);
TALER_TESTING_interpreter_fail (ws->is); TALER_TESTING_interpreter_fail (ws->is);
return; return;
} }
if (MHD_HTTP_OK == http_status) if (MHD_HTTP_OK == hr->http_status)
{ {
for (unsigned int i = 0; i<accounts_len; i++) for (unsigned int i = 0; i<accounts_len; i++)
{ {
@ -115,12 +109,11 @@ wire_cb (void *cls,
ws->method_found = GNUNET_OK; ws->method_found = GNUNET_OK;
if (NULL != ws->expected_fee) if (NULL != ws->expected_fee)
{ {
GNUNET_assert GNUNET_assert (GNUNET_OK ==
(GNUNET_OK == TALER_string_to_amount (ws->expected_fee,
TALER_string_to_amount (ws->expected_fee, &expected_fee));
&expected_fee)); for (const struct TALER_EXCHANGE_WireAggregateFees *waf
const struct TALER_EXCHANGE_WireAggregateFees *waf; = accounts[i].fees;
for (waf = accounts[i].fees;
NULL != waf; NULL != waf;
waf = waf->next) waf = waf->next)
{ {
@ -150,7 +143,6 @@ wire_cb (void *cls,
return; return;
} }
} }
TALER_TESTING_interpreter_next (ws->is); TALER_TESTING_interpreter_next (ws->is);
} }

View File

@ -172,42 +172,38 @@ do_retry (void *cls)
* in the state. * in the state.
* *
* @param cls closure. * @param cls closure.
* @param http_status HTTP response code. * @param hr HTTP response details
* @param ec taler-specific error code.
* @param sig signature over the coin, NULL on error. * @param sig signature over the coin, NULL on error.
* @param full_response raw response.
*/ */
static void static void
reserve_withdraw_cb (void *cls, reserve_withdraw_cb (void *cls,
unsigned int http_status, const struct TALER_EXCHANGE_HttpResponse *hr,
enum TALER_ErrorCode ec, const struct TALER_DenominationSignature *sig)
const struct TALER_DenominationSignature *sig,
const json_t *full_response)
{ {
struct WithdrawState *ws = cls; struct WithdrawState *ws = cls;
struct TALER_TESTING_Interpreter *is = ws->is; struct TALER_TESTING_Interpreter *is = ws->is;
ws->wsh = NULL; ws->wsh = NULL;
if (ws->expected_response_code != http_status) if (ws->expected_response_code != hr->http_status)
{ {
if (0 != ws->do_retry) if (0 != ws->do_retry)
{ {
if (TALER_EC_WITHDRAW_RESERVE_UNKNOWN != ec) if (TALER_EC_WITHDRAW_RESERVE_UNKNOWN != hr->ec)
ws->do_retry--; /* we don't count reserve unknown as failures here */ ws->do_retry--; /* we don't count reserve unknown as failures here */
if ( (0 == http_status) || if ( (0 == hr->http_status) ||
(TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) || (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == hr->ec) ||
(TALER_EC_WITHDRAW_INSUFFICIENT_FUNDS == ec) || (TALER_EC_WITHDRAW_INSUFFICIENT_FUNDS == hr->ec) ||
(TALER_EC_WITHDRAW_RESERVE_UNKNOWN == ec) || (TALER_EC_WITHDRAW_RESERVE_UNKNOWN == hr->ec) ||
(MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) ) (MHD_HTTP_INTERNAL_SERVER_ERROR == hr->http_status) )
{ {
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Retrying withdraw failed with %u/%d\n", "Retrying withdraw failed with %u/%d\n",
http_status, hr->http_status,
(int) ec); (int) hr->ec);
/* on DB conflicts, do not use backoff */ /* on DB conflicts, do not use backoff */
if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == hr->ec)
ws->backoff = GNUNET_TIME_UNIT_ZERO; ws->backoff = GNUNET_TIME_UNIT_ZERO;
else if (TALER_EC_WITHDRAW_RESERVE_UNKNOWN != ec) else if (TALER_EC_WITHDRAW_RESERVE_UNKNOWN != hr->ec)
ws->backoff = EXCHANGE_LIB_BACKOFF (ws->backoff); ws->backoff = EXCHANGE_LIB_BACKOFF (ws->backoff);
else else
ws->backoff = GNUNET_TIME_relative_max (UNKNOWN_MIN_BACKOFF, ws->backoff = GNUNET_TIME_relative_max (UNKNOWN_MIN_BACKOFF,
@ -225,19 +221,19 @@ reserve_withdraw_cb (void *cls,
} }
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d to command %s in %s:%u\n", "Unexpected response code %u/%d to command %s in %s:%u\n",
http_status, hr->http_status,
(int) ec, (int) hr->ec,
TALER_TESTING_interpreter_get_current_label (is), TALER_TESTING_interpreter_get_current_label (is),
__FILE__, __FILE__,
__LINE__); __LINE__);
json_dumpf (full_response, json_dumpf (hr->reply,
stderr, stderr,
0); 0);
GNUNET_break (0); GNUNET_break (0);
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
} }
switch (http_status) switch (hr->http_status)
{ {
case MHD_HTTP_OK: case MHD_HTTP_OK:
if (NULL == sig) if (NULL == sig)
@ -246,8 +242,8 @@ reserve_withdraw_cb (void *cls,
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
} }
ws->sig.rsa_signature ws->sig.rsa_signature = GNUNET_CRYPTO_rsa_signature_dup (
= GNUNET_CRYPTO_rsa_signature_dup (sig->rsa_signature); sig->rsa_signature);
if (0 != ws->total_backoff.rel_value_us) if (0 != ws->total_backoff.rel_value_us)
{ {
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@ -270,7 +266,7 @@ reserve_withdraw_cb (void *cls,
/* Unsupported status code (by test harness) */ /* Unsupported status code (by test harness) */
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Withdraw test command does not support status code %u\n", "Withdraw test command does not support status code %u\n",
http_status); hr->http_status);
GNUNET_break (0); GNUNET_break (0);
break; break;
} }

View File

@ -101,22 +101,24 @@ struct MainWrapperContext
* Function called with information about the auditor. * Function called with information about the auditor.
* *
* @param cls closure * @param cls closure
* @param hr http response details
* @param vi basic information about the auditor * @param vi basic information about the auditor
* @param compat protocol compatibility information * @param compat protocol compatibility information
*/ */
static void static void
auditor_version_cb (void *cls, auditor_version_cb (void *cls,
const struct TALER_AUDITOR_HttpResponse *hr,
const struct TALER_AUDITOR_VersionInformation *vi, const struct TALER_AUDITOR_VersionInformation *vi,
enum TALER_AUDITOR_VersionCompatibility compat) enum TALER_AUDITOR_VersionCompatibility compat)
{ {
struct TALER_TESTING_Interpreter *is = cls; struct TALER_TESTING_Interpreter *is = cls;
(void) hr;
if (TALER_AUDITOR_VC_MATCH != compat) if (TALER_AUDITOR_VC_MATCH != compat)
{ {
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
} }
is->auditor_working = GNUNET_YES; is->auditor_working = GNUNET_YES;
} }

View File

@ -589,49 +589,43 @@ sighandler_child_death (void)
* *
* @param cls closure, typically, the "run" method containing * @param cls closure, typically, the "run" method containing
* all the commands to be run, and a closure for it. * all the commands to be run, and a closure for it.
* @param hr HTTP response details
* @param keys the exchange's keys. * @param keys the exchange's keys.
* @param compat protocol compatibility information. * @param compat protocol compatibility information.
* @param ec error code, #TALER_EC_NONE on success
* @param http_status status returned by /keys, #MHD_HTTP_OK on success
* @param full_reply JSON body of /keys request, NULL if reply was not in JSON
*/ */
void void
TALER_TESTING_cert_cb (void *cls, TALER_TESTING_cert_cb (void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr,
const struct TALER_EXCHANGE_Keys *keys, const struct TALER_EXCHANGE_Keys *keys,
enum TALER_EXCHANGE_VersionCompatibility compat, enum TALER_EXCHANGE_VersionCompatibility compat)
enum TALER_ErrorCode ec,
unsigned int http_status,
const json_t *full_reply)
{ {
struct MainContext *main_ctx = cls; struct MainContext *main_ctx = cls;
struct TALER_TESTING_Interpreter *is = main_ctx->is; struct TALER_TESTING_Interpreter *is = main_ctx->is;
(void) compat; (void) compat;
(void) full_reply;
if (NULL == keys) if (NULL == keys)
{ {
if (GNUNET_NO == is->working) if (GNUNET_NO == is->working)
{ {
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Got NULL response for /keys during startup (%u/%d), retrying!\n", "Got NULL response for /keys during startup (%u/%d), retrying!\n",
http_status, hr->http_status,
(int) ec); (int) hr->ec);
TALER_EXCHANGE_disconnect (is->exchange); TALER_EXCHANGE_disconnect (is->exchange);
GNUNET_assert GNUNET_assert (NULL != (is->exchange
(NULL != (is->exchange = TALER_EXCHANGE_connect = TALER_EXCHANGE_connect (is->ctx,
(is->ctx, main_ctx->exchange_url,
main_ctx->exchange_url, &TALER_TESTING_cert_cb,
&TALER_TESTING_cert_cb, main_ctx,
main_ctx, TALER_EXCHANGE_OPTION_END)));
TALER_EXCHANGE_OPTION_END)));
return; return;
} }
else else
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Got NULL response for /keys during execution (%u/%d)!\n", "Got NULL response for /keys during execution (%u/%d)!\n",
http_status, hr->http_status,
(int) ec); (int) hr->ec);
} }
} }
else else