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

Generated by: LCOV version 2.0-1