LCOV - code coverage report
Current view: top level - bank-lib - fakebank_tbr_get_history.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 116 0
Test Date: 2026-04-14 15:39:31 Functions: 0.0 % 2 0

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   (C) 2016-2023 Taler Systems SA
       4              : 
       5              :   TALER is free software; you can redistribute it and/or
       6              :   modify it under the terms of the GNU General Public License
       7              :   as published by the Free Software Foundation; either version 3,
       8              :   or (at your option) any later version.
       9              : 
      10              :   TALER is distributed in the hope that it will be useful,
      11              :   but WITHOUT ANY WARRANTY; without even the implied warranty of
      12              :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13              :   GNU General Public License for more details.
      14              : 
      15              :   You should have received a copy of the GNU General Public
      16              :   License along with TALER; see the file COPYING.  If not,
      17              :   see <http://www.gnu.org/licenses/>
      18              : */
      19              : /**
      20              :  * @file bank-lib/fakebank_tbr_get_history.c
      21              :  * @brief library that fakes being a Taler bank for testcases
      22              :  * @author Christian Grothoff <christian@grothoff.org>
      23              :  */
      24              : #include <pthread.h>
      25              : #include "taler/taler_fakebank_lib.h"
      26              : #include "taler/taler_bank_service.h"
      27              : #include "taler/taler_mhd_lib.h"
      28              : #include <gnunet/gnunet_mhd_compat.h>
      29              : #include "fakebank.h"
      30              : #include "fakebank_common_lookup.h"
      31              : #include "fakebank_common_lp.h"
      32              : #include "fakebank_common_parser.h"
      33              : #include "fakebank_tbr_get_history.h"
      34              : 
      35              : 
      36              : /**
      37              :  * Function called to clean up a history context.
      38              :  *
      39              :  * @param cls a `struct HistoryContext *`
      40              :  */
      41              : static void
      42            0 : history_cleanup (void *cls)
      43              : {
      44            0 :   struct HistoryContext *hc = cls;
      45              : 
      46            0 :   json_decref (hc->history);
      47            0 :   GNUNET_free (hc);
      48            0 : }
      49              : 
      50              : 
      51              : MHD_RESULT
      52            0 : TALER_FAKEBANK_tbr_get_history (
      53              :   struct TALER_FAKEBANK_Handle *h,
      54              :   struct MHD_Connection *connection,
      55              :   const char *account,
      56              :   void **con_cls)
      57              : {
      58            0 :   struct ConnectionContext *cc = *con_cls;
      59              :   struct HistoryContext *hc;
      60              :   const struct Transaction *pos;
      61              :   enum GNUNET_GenericReturnValue ret;
      62              :   bool in_shutdown;
      63              :   const char *acc_payto_uri;
      64              : 
      65            0 :   if (NULL == cc)
      66              :   {
      67            0 :     cc = GNUNET_new (struct ConnectionContext);
      68            0 :     cc->ctx_cleaner = &history_cleanup;
      69            0 :     *con_cls = cc;
      70            0 :     hc = GNUNET_new (struct HistoryContext);
      71            0 :     cc->ctx = hc;
      72            0 :     hc->history = json_array ();
      73            0 :     if (NULL == hc->history)
      74              :     {
      75            0 :       GNUNET_break (0);
      76            0 :       return MHD_NO;
      77              :     }
      78            0 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
      79              :                 "Handling /accounts/%s/taler-revenue/history request\n",
      80              :                 account);
      81            0 :     if (GNUNET_OK !=
      82            0 :         (ret = TALER_FAKEBANK_common_parse_history_args (h,
      83              :                                                          connection,
      84              :                                                          &hc->ha)))
      85              :     {
      86            0 :       GNUNET_break_op (0);
      87            0 :       return (GNUNET_SYSERR == ret) ? MHD_NO : MHD_YES;
      88              :     }
      89            0 :     hc->timeout = GNUNET_TIME_relative_to_absolute (hc->ha.lp_timeout);
      90            0 :     GNUNET_assert (0 ==
      91              :                    pthread_mutex_lock (&h->big_lock));
      92            0 :     if (UINT64_MAX == hc->ha.start_idx)
      93            0 :       hc->ha.start_idx = h->serial_counter;
      94            0 :     hc->acc = TALER_FAKEBANK_lookup_account_ (h,
      95              :                                               account,
      96              :                                               NULL);
      97            0 :     if (NULL == hc->acc)
      98              :     {
      99            0 :       GNUNET_assert (0 ==
     100              :                      pthread_mutex_unlock (&h->big_lock));
     101            0 :       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     102              :                   "Account %s is unknown\n",
     103              :                   account);
     104            0 :       return TALER_MHD_reply_with_error (connection,
     105              :                                          MHD_HTTP_NOT_FOUND,
     106              :                                          TALER_EC_BANK_UNKNOWN_ACCOUNT,
     107              :                                          account);
     108              :     }
     109              :   }
     110              :   else
     111              :   {
     112            0 :     hc = cc->ctx;
     113            0 :     GNUNET_assert (0 ==
     114              :                    pthread_mutex_lock (&h->big_lock));
     115              :   }
     116              : 
     117            0 :   if (! hc->ha.have_start)
     118              :   {
     119            0 :     pos = (0 > hc->ha.delta)
     120            0 :           ? hc->acc->in_tail
     121            0 :           : hc->acc->in_head;
     122              :   }
     123              :   else
     124              :   {
     125            0 :     struct Transaction *t = h->transactions[hc->ha.start_idx % h->ram_limit];
     126              :     bool overflow;
     127              :     uint64_t dir;
     128            0 :     bool skip = true;
     129              : 
     130            0 :     overflow = ( (NULL != t) && (t->row_id != hc->ha.start_idx) );
     131            0 :     dir = (0 > hc->ha.delta) ? (h->ram_limit - 1) : 1;
     132              :     /* If account does not match, linear scan for
     133              :        first matching account. */
     134            0 :     while ( (! overflow) &&
     135            0 :             (NULL != t) &&
     136            0 :             (t->credit_account != hc->acc) )
     137              :     {
     138            0 :       skip = false;
     139            0 :       t = h->transactions[(t->row_id + dir) % h->ram_limit];
     140            0 :       if ( (NULL != t) &&
     141            0 :            (t->row_id == hc->ha.start_idx) )
     142            0 :         overflow = true; /* full circle, give up! */
     143              :     }
     144            0 :     if ( (NULL == t) ||
     145              :          overflow)
     146              :     {
     147            0 :       in_shutdown = h->in_shutdown;
     148              :       /* FIXME: these conditions are unclear to me. */
     149            0 :       if (GNUNET_TIME_relative_is_zero (hc->ha.lp_timeout) &&
     150            0 :           (0 < hc->ha.delta))
     151              :       {
     152            0 :         acc_payto_uri = hc->acc->payto_uri;
     153            0 :         GNUNET_assert (0 ==
     154              :                        pthread_mutex_unlock (&h->big_lock));
     155            0 :         if (overflow)
     156              :         {
     157            0 :           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     158              :                       "Transactions lost due to RAM limits\n");
     159            0 :           return TALER_MHD_reply_with_ec (
     160              :             connection,
     161              :             TALER_EC_BANK_ANCIENT_TRANSACTION_GONE,
     162              :             NULL);
     163              :         }
     164            0 :         goto finish;
     165              :       }
     166            0 :       if (in_shutdown)
     167              :       {
     168            0 :         acc_payto_uri = hc->acc->payto_uri;
     169            0 :         GNUNET_assert (0 ==
     170              :                        pthread_mutex_unlock (&h->big_lock));
     171            0 :         goto finish;
     172              :       }
     173            0 :       TALER_FAKEBANK_start_lp_ (h,
     174              :                                 connection,
     175              :                                 hc->acc,
     176              :                                 GNUNET_TIME_absolute_get_remaining (
     177              :                                   hc->timeout),
     178              :                                 LP_CREDIT,
     179              :                                 NULL);
     180            0 :       GNUNET_assert (0 ==
     181              :                      pthread_mutex_unlock (&h->big_lock));
     182            0 :       return MHD_YES;
     183              :     }
     184            0 :     if (skip)
     185              :     {
     186              :       /* range from application is exclusive, skip the
     187              :   matching entry */
     188            0 :       if (0 > hc->ha.delta)
     189            0 :         pos = t->prev_in;
     190              :       else
     191            0 :         pos = t->next_in;
     192              :     }
     193              :     else
     194              :     {
     195            0 :       pos = t;
     196              :     }
     197              :   }
     198            0 :   if (NULL != pos)
     199            0 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     200              :                 "Returning %lld credit transactions starting (inclusive) from %llu\n",
     201              :                 (long long) hc->ha.delta,
     202              :                 (unsigned long long) pos->row_id);
     203            0 :   while ( (0 != hc->ha.delta) &&
     204              :           (NULL != pos) )
     205              :   {
     206              :     json_t *trans;
     207              :     char *subject;
     208              : 
     209            0 :     if (T_DEBIT != pos->type)
     210              :     {
     211            0 :       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     212              :                   "Unexpected CREDIT transaction #%llu for account `%s'\n",
     213              :                   (unsigned long long) pos->row_id,
     214              :                   account);
     215            0 :       if (0 > hc->ha.delta)
     216            0 :         pos = pos->prev_in;
     217            0 :       if (0 < hc->ha.delta)
     218            0 :         pos = pos->next_in;
     219            0 :       continue;
     220              :     }
     221              : 
     222              :     {
     223              :       char *wtids;
     224              : 
     225            0 :       wtids = GNUNET_STRINGS_data_to_string_alloc (
     226            0 :         &pos->subject.debit.wtid,
     227              :         sizeof (pos->subject.debit.wtid));
     228            0 :       GNUNET_asprintf (&subject,
     229              :                        "%s %s",
     230              :                        wtids,
     231            0 :                        pos->subject.debit.exchange_base_url);
     232            0 :       GNUNET_free (wtids);
     233              :     }
     234            0 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     235              :                 "Found transaction over %s with subject %s\n",
     236              :                 TALER_amount2s (&pos->amount),
     237              :                 subject);
     238            0 :     trans = GNUNET_JSON_PACK (
     239              :       GNUNET_JSON_pack_string ("type",
     240              :                                "RESERVE"),
     241              :       GNUNET_JSON_pack_uint64 ("row_id",
     242              :                                pos->row_id),
     243              :       GNUNET_JSON_pack_timestamp ("date",
     244              :                                   pos->date),
     245              :       TALER_JSON_pack_amount ("amount",
     246              :                               &pos->amount),
     247              :       GNUNET_JSON_pack_string ("debit_account",
     248              :                                pos->debit_account->payto_uri),
     249              :       GNUNET_JSON_pack_string ("subject",
     250              :                                subject));
     251            0 :     GNUNET_free (subject);
     252            0 :     GNUNET_assert (NULL != trans);
     253            0 :     GNUNET_assert (0 ==
     254              :                    json_array_append_new (hc->history,
     255              :                                           trans));
     256            0 :     if (hc->ha.delta > 0)
     257            0 :       hc->ha.delta--;
     258              :     else
     259            0 :       hc->ha.delta++;
     260            0 :     if (0 > hc->ha.delta)
     261            0 :       pos = pos->prev_in;
     262            0 :     if (0 < hc->ha.delta)
     263            0 :       pos = pos->next_in;
     264              :   }
     265            0 :   if ( (0 == json_array_size (hc->history)) &&
     266            0 :        (! h->in_shutdown) &&
     267            0 :        (GNUNET_TIME_absolute_is_future (hc->timeout)) &&
     268            0 :        (0 < hc->ha.delta))
     269              :   {
     270            0 :     TALER_FAKEBANK_start_lp_ (h,
     271              :                               connection,
     272              :                               hc->acc,
     273              :                               GNUNET_TIME_absolute_get_remaining (hc->timeout),
     274              :                               LP_CREDIT,
     275              :                               NULL);
     276            0 :     GNUNET_assert (0 ==
     277              :                    pthread_mutex_unlock (&h->big_lock));
     278            0 :     return MHD_YES;
     279              :   }
     280            0 :   in_shutdown = h->in_shutdown;
     281            0 :   acc_payto_uri = hc->acc->payto_uri;
     282            0 :   GNUNET_assert (0 ==
     283              :                  pthread_mutex_unlock (&h->big_lock));
     284            0 : finish:
     285            0 :   if (0 == json_array_size (hc->history))
     286              :   {
     287            0 :     GNUNET_break (in_shutdown ||
     288              :                   (! GNUNET_TIME_absolute_is_future (hc->timeout)));
     289            0 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     290              :                 "Zero transactions found\n");
     291            0 :     return TALER_MHD_reply_static (connection,
     292              :                                    MHD_HTTP_NO_CONTENT,
     293              :                                    NULL,
     294              :                                    NULL,
     295              :                                    0);
     296              :   }
     297              :   {
     298            0 :     json_t *jh = hc->history;
     299              : 
     300            0 :     hc->history = NULL;
     301            0 :     return TALER_MHD_REPLY_JSON_PACK (
     302              :       connection,
     303              :       MHD_HTTP_OK,
     304              :       GNUNET_JSON_pack_string (
     305              :         "credit_account",
     306              :         acc_payto_uri),
     307              :       GNUNET_JSON_pack_array_steal (
     308              :         "incoming_transactions",
     309              :         jh));
     310              :   }
     311              : }
        

Generated by: LCOV version 2.0-1