/*
This file is part of TALER
Copyright (C) 2014-2017, 2020 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2.1, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with
TALER; see the file COPYING.LGPL. If not, see
*/
/**
* @file lib/merchant_api_tip_pickup.c
* @brief Implementation of the /tip-pickup request of the merchant's HTTP API
* @author Marcello Stanisci
* @author Christian Grothoff
*/
#include "platform.h"
#include
#include
#include /* just for HTTP status codes */
#include
#include
#include "taler_merchant_service.h"
#include
#include
#include
/**
* Data we keep per planchet.
*/
struct PlanchetData
{
/**
* Secrets of the planchet.
*/
struct TALER_PlanchetSecretsP ps;
/**
* Denomination key we are withdrawing.
*/
struct TALER_EXCHANGE_DenomPublicKey pk;
/**
* Hash of the public key of the coin we are signing.
*/
struct GNUNET_HashCode c_hash;
};
/**
* Handle for a /tip-pickup operation.
*/
struct TALER_MERCHANT_TipPickupHandle
{
/**
* Function to call with the result.
*/
TALER_MERCHANT_TipPickupCallback cb;
/**
* Closure for @a cb.
*/
void *cb_cls;
/**
* Handle for the actual (internal) withdraw operation.
*/
struct TALER_MERCHANT_TipPickup2Handle *tpo2;
/**
* Number of planchets/coins used for this operation.
*/
unsigned int num_planchets;
/**
* Array of length @e num_planchets.
*/
struct PlanchetData *planchets;
};
/**
* Callback for a /tip-pickup request. Returns the result of the operation.
* Note that the client MUST still do the unblinding of the @a blind_sigs.
*
* @param cls closure, a `struct TALER_MERCHANT_TipPickupHandle *`
* @param hr HTTP response details
* @param num_blind_sigs length of the @a reserve_sigs array, 0 on error
* @param blind_sigs array of blind signatures over the planchets, NULL on error
*/
static void
pickup_done_cb (void *cls,
const struct TALER_MERCHANT_HttpResponse *hr,
unsigned int num_blind_sigs,
const struct TALER_MERCHANT_BlindSignature *blind_sigs)
{
struct TALER_MERCHANT_TipPickupHandle *tp = cls;
tp->tpo2 = NULL;
if (NULL == blind_sigs)
{
tp->cb (tp->cb_cls,
hr,
0,
NULL);
TALER_MERCHANT_tip_pickup_cancel (tp);
return;
}
{
struct TALER_DenominationSignature sigs[num_blind_sigs];
int ok;
ok = GNUNET_OK;
memset (sigs,
0,
sizeof (sigs));
for (unsigned int i = 0; iplanchets[i].pk.key,
blind_sigs[i].blind_sig,
&tp->planchets[i].ps,
&tp->planchets[i].c_hash,
&fc))
{
ok = GNUNET_SYSERR;
break;
}
sigs[i] = fc.sig;
}
if (GNUNET_OK == ok)
{
tp->cb (tp->cb_cls,
hr,
num_blind_sigs,
sigs);
}
else
{
struct TALER_MERCHANT_HttpResponse hrx = {
.reply = hr->reply,
.http_status = 0,
.ec = TALER_EC_TIP_PICKUP_UNBLIND_FAILURE
};
tp->cb (tp->cb_cls,
&hrx,
0,
NULL);
}
for (unsigned int i = 0; iplanchets,
tp->num_planchets,
num_planchets);
for (unsigned int i = 0; iplanchets[i].ps = pds[i].ps;
if (GNUNET_OK !=
TALER_planchet_prepare (&pds[i].pk->key,
&tp->planchets[i].ps,
&tp->planchets[i].c_hash,
&details[i]))
{
GNUNET_break (0);
GNUNET_array_grow (tp->planchets,
tp->num_planchets,
0);
GNUNET_free (tp);
return NULL;
}
}
for (unsigned int i = 0; iplanchets[i].pk = *pds[i].pk;
tp->planchets[i].pk.key.rsa_public_key
= GNUNET_CRYPTO_rsa_public_key_dup (pds[i].pk->key.rsa_public_key);
}
tp->cb = pickup_cb;
tp->cb_cls = pickup_cb_cls;
tp->tpo2 = TALER_MERCHANT_tip_pickup2 (ctx,
backend_url,
tip_id,
num_planchets,
details,
&pickup_done_cb,
tp);
if (NULL == tp->tpo2)
{
GNUNET_break (0);
TALER_MERCHANT_tip_pickup_cancel (tp);
return NULL;
}
return tp;
}
/**
* Cancel a pending /tip-pickup request
*
* @param tp handle from the operation to cancel
*/
void
TALER_MERCHANT_tip_pickup_cancel (struct TALER_MERCHANT_TipPickupHandle *tp)
{
for (unsigned int i = 0; inum_planchets; i++)
GNUNET_CRYPTO_rsa_public_key_dup (tp->planchets[i].pk.key.rsa_public_key);
GNUNET_array_grow (tp->planchets,
tp->num_planchets,
0);
if (NULL != tp->tpo2)
{
TALER_MERCHANT_tip_pickup2_cancel (tp->tpo2);
tp->tpo2 = NULL;
}
GNUNET_free (tp);
}
/* end of merchant_api_tip_pickup.c */