LCOV - code coverage report
Current view: top level - bank-lib - fakebank_tbr_get_history.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 116 0.0 %
Date: 2025-06-22 12:09:43 Functions: 0 2 0.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 1.16