LCOV - code coverage report
Current view: top level - bank-lib - fakebank_twg_get_transfers.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 80 0.0 %
Date: 2025-06-22 12:09:43 Functions: 0 1 0.0 %

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   (C) 2024 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_twg_get_transfers.c
      21             :  * @brief routines to return account histories for the Taler Wire Gateway API
      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_twg_get_transfers.h"
      35             : 
      36             : 
      37             : MHD_RESULT
      38           0 : TALER_FAKEBANK_twg_get_transfers_ (
      39             :   struct TALER_FAKEBANK_Handle *h,
      40             :   struct MHD_Connection *connection,
      41             :   const char *account,
      42             :   void **con_cls)
      43             : {
      44             :   struct Transaction *pos;
      45             :   const char *acc_payto_uri;
      46             :   json_t *history;
      47             :   struct Account *acc;
      48           0 :   int64_t limit = -20;
      49             :   uint64_t offset;
      50             :   bool have_start;
      51             :   const char *status;
      52             : 
      53           0 :   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
      54             :               "Handling /transfers connection %p\n",
      55             :               connection);
      56             : 
      57           0 :   TALER_MHD_parse_request_snumber (connection,
      58             :                                    "limit",
      59             :                                    &limit);
      60           0 :   if (limit > 0)
      61           0 :     offset = 0;
      62             :   else
      63           0 :     offset = UINT64_MAX;
      64           0 :   TALER_MHD_parse_request_number (connection,
      65             :                                   "offset",
      66             :                                   &offset);
      67           0 :   have_start = ((0 != offset) && (UINT64_MAX != offset));
      68           0 :   status = MHD_lookup_connection_value (connection,
      69             :                                         MHD_GET_ARGUMENT_KIND,
      70             :                                         "status");
      71           0 :   if ( (NULL != status) &&
      72           0 :        (0 != strcasecmp (status,
      73             :                          "success")) )
      74             :   {
      75             :     /* we only have successful transactions */
      76           0 :     return TALER_MHD_reply_static (connection,
      77             :                                    MHD_HTTP_NO_CONTENT,
      78             :                                    NULL,
      79             :                                    NULL,
      80             :                                    0);
      81             :   }
      82             : 
      83           0 :   GNUNET_assert (0 ==
      84             :                  pthread_mutex_lock (&h->big_lock));
      85           0 :   if (UINT64_MAX == offset)
      86           0 :     offset = h->serial_counter;
      87           0 :   acc = TALER_FAKEBANK_lookup_account_ (h,
      88             :                                         account,
      89             :                                         NULL);
      90           0 :   if (NULL == acc)
      91             :   {
      92           0 :     GNUNET_assert (0 ==
      93             :                    pthread_mutex_unlock (&h->big_lock));
      94           0 :     return TALER_MHD_reply_with_error (connection,
      95             :                                        MHD_HTTP_NOT_FOUND,
      96             :                                        TALER_EC_BANK_UNKNOWN_ACCOUNT,
      97             :                                        account);
      98             :   }
      99           0 :   history = json_array ();
     100           0 :   if (NULL == history)
     101             :   {
     102           0 :     GNUNET_break (0);
     103           0 :     GNUNET_assert (0 ==
     104             :                    pthread_mutex_unlock (&h->big_lock));
     105           0 :     return MHD_NO;
     106             :   }
     107             : 
     108           0 :   if (! have_start)
     109             :   {
     110           0 :     pos = (0 > limit)
     111             :       ? acc->out_tail
     112           0 :       : acc->out_head;
     113             :   }
     114             :   else
     115             :   {
     116           0 :     struct Transaction *t = h->transactions[offset % h->ram_limit];
     117             :     bool overflow;
     118             :     uint64_t dir;
     119           0 :     bool skip = true;
     120             : 
     121           0 :     dir = (0 > limit) ? (h->ram_limit - 1) : 1;
     122           0 :     overflow = (t->row_id != offset);
     123             :     /* If account does not match, linear scan for
     124             :        first matching account. */
     125           0 :     while ( (! overflow) &&
     126           0 :             (NULL != t) &&
     127           0 :             (t->debit_account != acc) )
     128             :     {
     129           0 :       skip = false;
     130           0 :       t = h->transactions[(t->row_id + dir) % h->ram_limit];
     131           0 :       if ( (NULL != t) &&
     132           0 :            (t->row_id == offset) )
     133           0 :         overflow = true; /* full circle, give up! */
     134             :     }
     135           0 :     if ( (NULL == t) ||
     136           0 :          (t->debit_account != acc) )
     137             :     {
     138           0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     139             :                   "Invalid start specified, transaction %llu not with account %s!\n",
     140             :                   (unsigned long long) offset,
     141             :                   account);
     142           0 :       GNUNET_assert (0 ==
     143             :                      pthread_mutex_unlock (&h->big_lock));
     144           0 :       return MHD_NO;
     145             :     }
     146           0 :     if (skip)
     147             :     {
     148             :       /* range is exclusive, skip the matching entry */
     149           0 :       if (0 > limit)
     150           0 :         pos = t->prev_out;
     151             :       else
     152           0 :         pos = t->next_out;
     153             :     }
     154             :     else
     155             :     {
     156           0 :       pos = t;
     157             :     }
     158             :   }
     159           0 :   if (NULL != pos)
     160           0 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     161             :                 "Returning %lld debit transactions starting (inclusive) from %llu\n",
     162             :                 (long long) limit,
     163             :                 (unsigned long long) pos->row_id);
     164           0 :   while ( (0 != limit) &&
     165             :           (NULL != pos) )
     166             :   {
     167             :     json_t *trans;
     168             :     char *credit_payto;
     169             : 
     170           0 :     if (T_DEBIT != pos->type)
     171             :     {
     172           0 :       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     173             :                   "Unexpected CREDIT transaction #%llu for account `%s'\n",
     174             :                   (unsigned long long) pos->row_id,
     175             :                   account);
     176           0 :       if (0 > limit)
     177           0 :         pos = pos->prev_in;
     178           0 :       if (0 < limit)
     179           0 :         pos = pos->next_in;
     180           0 :       continue;
     181             :     }
     182           0 :     GNUNET_asprintf (&credit_payto,
     183             :                      "payto://x-taler-bank/localhost/%s?receiver-name=%s",
     184           0 :                      pos->credit_account->account_name,
     185           0 :                      pos->credit_account->receiver_name);
     186             : 
     187           0 :     trans = GNUNET_JSON_PACK (
     188             :       GNUNET_JSON_pack_uint64 ("row_id",
     189             :                                pos->row_id),
     190             :       GNUNET_JSON_pack_timestamp ("timestamp",
     191             :                                   pos->date),
     192             :       TALER_JSON_pack_amount ("amount",
     193             :                               &pos->amount),
     194             :       GNUNET_JSON_pack_string ("credit_account",
     195             :                                credit_payto),
     196             :       GNUNET_JSON_pack_string ("status",
     197             :                                "success"));
     198           0 :     GNUNET_assert (NULL != trans);
     199           0 :     GNUNET_free (credit_payto);
     200           0 :     GNUNET_assert (0 ==
     201             :                    json_array_append_new (history,
     202             :                                           trans));
     203           0 :     if (limit > 0)
     204           0 :       limit--;
     205             :     else
     206           0 :       limit++;
     207           0 :     if (0 > limit)
     208           0 :       pos = pos->prev_out;
     209           0 :     if (0 < limit)
     210           0 :       pos = pos->next_out;
     211             :   }
     212           0 :   acc_payto_uri = acc->payto_uri;
     213           0 :   GNUNET_assert (0 ==
     214             :                  pthread_mutex_unlock (&h->big_lock));
     215           0 :   if (0 == json_array_size (history))
     216             :   {
     217           0 :     json_decref (history);
     218           0 :     return TALER_MHD_reply_static (connection,
     219             :                                    MHD_HTTP_NO_CONTENT,
     220             :                                    NULL,
     221             :                                    NULL,
     222             :                                    0);
     223             :   }
     224           0 :   return TALER_MHD_REPLY_JSON_PACK (
     225             :     connection,
     226             :     MHD_HTTP_OK,
     227             :     GNUNET_JSON_pack_string (
     228             :       "debit_account",
     229             :       acc_payto_uri),
     230             :     GNUNET_JSON_pack_array_steal (
     231             :       "transfers",
     232             :       history));
     233             : }

Generated by: LCOV version 1.16