LCOV - code coverage report
Current view: top level - bank-lib - fakebank_twg_get_transfers.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 80 0
Test Date: 2026-01-12 22:36:41 Functions: 0.0 % 1 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 2.0-1