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

Generated by: LCOV version 2.0-1