LCOV - code coverage report
Current view: top level - bank-lib - fakebank_twg_history.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 58.5 % 229 134
Test Date: 2026-04-14 15:39:31 Functions: 100.0 % 3 3

            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_twg_history.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_twg_history.h"
      31              : #include "fakebank_common_lookup.h"
      32              : #include "fakebank_common_lp.h"
      33              : #include "fakebank_common_parser.h"
      34              : 
      35              : /**
      36              :  * Function called to clean up a history context.
      37              :  *
      38              :  * @param cls a `struct HistoryContext *`
      39              :  */
      40              : static void
      41          177 : history_cleanup (void *cls)
      42              : {
      43          177 :   struct HistoryContext *hc = cls;
      44              : 
      45          177 :   json_decref (hc->history);
      46          177 :   GNUNET_free (hc);
      47          177 : }
      48              : 
      49              : 
      50              : MHD_RESULT
      51            5 : TALER_FAKEBANK_twg_get_debit_history_ (
      52              :   struct TALER_FAKEBANK_Handle *h,
      53              :   struct MHD_Connection *connection,
      54              :   const char *account,
      55              :   void **con_cls)
      56              : {
      57            5 :   struct ConnectionContext *cc = *con_cls;
      58              :   struct HistoryContext *hc;
      59              :   struct Transaction *pos;
      60              :   enum GNUNET_GenericReturnValue ret;
      61              :   bool in_shutdown;
      62              :   const char *acc_payto_uri;
      63              : 
      64            5 :   if (NULL == cc)
      65              :   {
      66            5 :     cc = GNUNET_new (struct ConnectionContext);
      67            5 :     cc->ctx_cleaner = &history_cleanup;
      68            5 :     *con_cls = cc;
      69            5 :     hc = GNUNET_new (struct HistoryContext);
      70            5 :     cc->ctx = hc;
      71              : 
      72            5 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
      73              :                 "Handling /history/outgoing connection %p\n",
      74              :                 connection);
      75            5 :     if (GNUNET_OK !=
      76            5 :         (ret = TALER_FAKEBANK_common_parse_history_args (h,
      77              :                                                          connection,
      78              :                                                          &hc->ha)))
      79              :     {
      80            0 :       GNUNET_break_op (0);
      81            0 :       return (GNUNET_SYSERR == ret) ? MHD_NO : MHD_YES;
      82              :     }
      83            5 :     GNUNET_assert (0 ==
      84              :                    pthread_mutex_lock (&h->big_lock));
      85            5 :     if (UINT64_MAX == hc->ha.start_idx)
      86            1 :       hc->ha.start_idx = h->serial_counter;
      87            5 :     hc->acc = TALER_FAKEBANK_lookup_account_ (h,
      88              :                                               account,
      89              :                                               NULL);
      90            5 :     if (NULL == hc->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            5 :     hc->history = json_array ();
     100            5 :     if (NULL == hc->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            5 :     hc->timeout = GNUNET_TIME_relative_to_absolute (hc->ha.lp_timeout);
     108              :   }
     109              :   else
     110              :   {
     111            0 :     hc = cc->ctx;
     112            0 :     GNUNET_assert (0 ==
     113              :                    pthread_mutex_lock (&h->big_lock));
     114              :   }
     115              : 
     116            5 :   if (! hc->ha.have_start)
     117              :   {
     118            5 :     pos = (0 > hc->ha.delta)
     119            1 :       ? hc->acc->out_tail
     120            5 :       : hc->acc->out_head;
     121              :   }
     122              :   else
     123              :   {
     124            0 :     struct Transaction *t = h->transactions[hc->ha.start_idx % h->ram_limit];
     125              :     bool overflow;
     126              :     uint64_t dir;
     127            0 :     bool skip = true;
     128              : 
     129            0 :     dir = (0 > hc->ha.delta) ? (h->ram_limit - 1) : 1;
     130            0 :     overflow = (t->row_id != hc->ha.start_idx);
     131              :     /* If account does not match, linear scan for
     132              :        first matching account. */
     133            0 :     while ( (! overflow) &&
     134            0 :             (NULL != t) &&
     135            0 :             (t->debit_account != hc->acc) )
     136              :     {
     137            0 :       skip = false;
     138            0 :       t = h->transactions[(t->row_id + dir) % h->ram_limit];
     139            0 :       if ( (NULL != t) &&
     140            0 :            (t->row_id == hc->ha.start_idx) )
     141            0 :         overflow = true; /* full circle, give up! */
     142              :     }
     143            0 :     if ( (NULL == t) ||
     144              :          overflow)
     145              :     {
     146              :       /* FIXME: these conditions are unclear to me. */
     147            0 :       if ( (GNUNET_TIME_relative_is_zero (hc->ha.lp_timeout)) &&
     148            0 :            (0 < hc->ha.delta))
     149              :       {
     150            0 :         acc_payto_uri = hc->acc->payto_uri;
     151            0 :         in_shutdown = h->in_shutdown;
     152            0 :         GNUNET_assert (0 ==
     153              :                        pthread_mutex_unlock (&h->big_lock));
     154            0 :         if (overflow)
     155              :         {
     156            0 :           return TALER_MHD_reply_with_ec (
     157              :             connection,
     158              :             TALER_EC_BANK_ANCIENT_TRANSACTION_GONE,
     159              :             NULL);
     160              :         }
     161            0 :         goto finish;
     162              :       }
     163            0 :       if (h->in_shutdown)
     164              :       {
     165            0 :         acc_payto_uri = hc->acc->payto_uri;
     166            0 :         in_shutdown = h->in_shutdown;
     167            0 :         GNUNET_assert (0 ==
     168              :                        pthread_mutex_unlock (&h->big_lock));
     169            0 :         goto finish;
     170              :       }
     171            0 :       TALER_FAKEBANK_start_lp_ (h,
     172              :                                 connection,
     173              :                                 hc->acc,
     174              :                                 GNUNET_TIME_absolute_get_remaining (
     175              :                                   hc->timeout),
     176              :                                 LP_DEBIT,
     177              :                                 NULL);
     178            0 :       GNUNET_assert (0 ==
     179              :                      pthread_mutex_unlock (&h->big_lock));
     180            0 :       return MHD_YES;
     181              :     }
     182            0 :     if (t->debit_account != hc->acc)
     183              :     {
     184            0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     185              :                   "Invalid start specified, transaction %llu not with account %s!\n",
     186              :                   (unsigned long long) hc->ha.start_idx,
     187              :                   account);
     188            0 :       GNUNET_assert (0 ==
     189              :                      pthread_mutex_unlock (&h->big_lock));
     190            0 :       return MHD_NO;
     191              :     }
     192            0 :     if (skip)
     193              :     {
     194              :       /* range is exclusive, skip the matching entry */
     195            0 :       if (0 > hc->ha.delta)
     196            0 :         pos = t->prev_out;
     197              :       else
     198            0 :         pos = t->next_out;
     199              :     }
     200              :     else
     201              :     {
     202            0 :       pos = t;
     203              :     }
     204              :   }
     205            5 :   if (NULL != pos)
     206            3 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     207              :                 "Returning %lld debit transactions starting (inclusive) from %llu\n",
     208              :                 (long long) hc->ha.delta,
     209              :                 (unsigned long long) pos->row_id);
     210            8 :   while ( (0 != hc->ha.delta) &&
     211              :           (NULL != pos) )
     212              :   {
     213              :     json_t *trans;
     214              :     char *credit_payto;
     215              : 
     216            3 :     if (T_DEBIT != pos->type)
     217              :     {
     218            0 :       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     219              :                   "Unexpected CREDIT transaction #%llu for account `%s'\n",
     220              :                   (unsigned long long) pos->row_id,
     221              :                   account);
     222            0 :       if (0 > hc->ha.delta)
     223            0 :         pos = pos->prev_in;
     224            0 :       if (0 < hc->ha.delta)
     225            0 :         pos = pos->next_in;
     226            0 :       continue;
     227              :     }
     228            3 :     GNUNET_asprintf (&credit_payto,
     229              :                      "payto://x-taler-bank/localhost/%s?receiver-name=%s",
     230            3 :                      pos->credit_account->account_name,
     231            3 :                      pos->credit_account->receiver_name);
     232              : 
     233            3 :     trans = GNUNET_JSON_PACK (
     234              :       GNUNET_JSON_pack_uint64 ("row_id",
     235              :                                pos->row_id),
     236              :       GNUNET_JSON_pack_timestamp ("date",
     237              :                                   pos->date),
     238              :       TALER_JSON_pack_amount ("amount",
     239              :                               &pos->amount),
     240              :       GNUNET_JSON_pack_string ("credit_account",
     241              :                                credit_payto),
     242              :       GNUNET_JSON_pack_string ("exchange_base_url",
     243              :                                pos->subject.debit.exchange_base_url),
     244              :       GNUNET_JSON_pack_data_auto ("wtid",
     245              :                                   &pos->subject.debit.wtid));
     246            3 :     GNUNET_assert (NULL != trans);
     247            3 :     GNUNET_free (credit_payto);
     248            3 :     GNUNET_assert (0 ==
     249              :                    json_array_append_new (hc->history,
     250              :                                           trans));
     251            3 :     if (hc->ha.delta > 0)
     252            2 :       hc->ha.delta--;
     253              :     else
     254            1 :       hc->ha.delta++;
     255            3 :     if (0 > hc->ha.delta)
     256            1 :       pos = pos->prev_out;
     257            3 :     if (0 < hc->ha.delta)
     258            2 :       pos = pos->next_out;
     259              :   }
     260            5 :   if ( (0 == json_array_size (hc->history)) &&
     261            4 :        (! h->in_shutdown) &&
     262            2 :        (GNUNET_TIME_absolute_is_future (hc->timeout)) &&
     263            0 :        (0 < hc->ha.delta))
     264              :   {
     265            0 :     TALER_FAKEBANK_start_lp_ (h,
     266              :                               connection,
     267              :                               hc->acc,
     268              :                               GNUNET_TIME_absolute_get_remaining (hc->timeout),
     269              :                               LP_DEBIT,
     270              :                               NULL);
     271            0 :     GNUNET_assert (0 ==
     272              :                    pthread_mutex_unlock (&h->big_lock));
     273            0 :     return MHD_YES;
     274              :   }
     275            5 :   in_shutdown = h->in_shutdown;
     276            5 :   acc_payto_uri = hc->acc->payto_uri;
     277            5 :   GNUNET_assert (0 ==
     278              :                  pthread_mutex_unlock (&h->big_lock));
     279            5 : finish:
     280            5 :   if (0 == json_array_size (hc->history))
     281              :   {
     282            2 :     GNUNET_break (in_shutdown ||
     283              :                   (! GNUNET_TIME_absolute_is_future (hc->timeout)));
     284            2 :     return TALER_MHD_reply_static (connection,
     285              :                                    MHD_HTTP_NO_CONTENT,
     286              :                                    NULL,
     287              :                                    NULL,
     288              :                                    0);
     289              :   }
     290              :   {
     291            3 :     json_t *jh = hc->history;
     292              : 
     293            3 :     hc->history = NULL;
     294            3 :     return TALER_MHD_REPLY_JSON_PACK (
     295              :       connection,
     296              :       MHD_HTTP_OK,
     297              :       GNUNET_JSON_pack_string (
     298              :         "debit_account",
     299              :         acc_payto_uri),
     300              :       GNUNET_JSON_pack_array_steal (
     301              :         "outgoing_transactions",
     302              :         jh));
     303              :   }
     304              : }
     305              : 
     306              : 
     307              : MHD_RESULT
     308          172 : TALER_FAKEBANK_twg_get_credit_history_ (
     309              :   struct TALER_FAKEBANK_Handle *h,
     310              :   struct MHD_Connection *connection,
     311              :   const char *account,
     312              :   void **con_cls)
     313              : {
     314          172 :   struct ConnectionContext *cc = *con_cls;
     315              :   struct HistoryContext *hc;
     316              :   const struct Transaction *pos;
     317              :   enum GNUNET_GenericReturnValue ret;
     318              :   bool in_shutdown;
     319              :   const char *acc_payto_uri;
     320              : 
     321          172 :   if (NULL == cc)
     322              :   {
     323          172 :     cc = GNUNET_new (struct ConnectionContext);
     324          172 :     cc->ctx_cleaner = &history_cleanup;
     325          172 :     *con_cls = cc;
     326          172 :     hc = GNUNET_new (struct HistoryContext);
     327          172 :     cc->ctx = hc;
     328          172 :     hc->history = json_array ();
     329          172 :     if (NULL == hc->history)
     330              :     {
     331            0 :       GNUNET_break (0);
     332            0 :       return MHD_NO;
     333              :     }
     334          172 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     335              :                 "Handling /history/incoming connection %p\n",
     336              :                 connection);
     337          172 :     if (GNUNET_OK !=
     338          172 :         (ret = TALER_FAKEBANK_common_parse_history_args (h,
     339              :                                                          connection,
     340              :                                                          &hc->ha)))
     341              :     {
     342            0 :       GNUNET_break_op (0);
     343            0 :       return (GNUNET_SYSERR == ret) ? MHD_NO : MHD_YES;
     344              :     }
     345          172 :     hc->timeout = GNUNET_TIME_relative_to_absolute (hc->ha.lp_timeout);
     346          172 :     GNUNET_assert (0 ==
     347              :                    pthread_mutex_lock (&h->big_lock));
     348          172 :     if (UINT64_MAX == hc->ha.start_idx)
     349            1 :       hc->ha.start_idx = h->serial_counter;
     350          172 :     hc->acc = TALER_FAKEBANK_lookup_account_ (h,
     351              :                                               account,
     352              :                                               NULL);
     353          172 :     if (NULL == hc->acc)
     354              :     {
     355            2 :       GNUNET_assert (0 ==
     356              :                      pthread_mutex_unlock (&h->big_lock));
     357            2 :       return TALER_MHD_reply_with_error (connection,
     358              :                                          MHD_HTTP_NOT_FOUND,
     359              :                                          TALER_EC_BANK_UNKNOWN_ACCOUNT,
     360              :                                          account);
     361              :     }
     362              :   }
     363              :   else
     364              :   {
     365            0 :     hc = cc->ctx;
     366            0 :     GNUNET_assert (0 ==
     367              :                    pthread_mutex_lock (&h->big_lock));
     368              :   }
     369              : 
     370          170 :   if (! hc->ha.have_start)
     371              :   {
     372           28 :     pos = (0 > hc->ha.delta)
     373            1 :           ? hc->acc->in_tail
     374           13 :           : hc->acc->in_head;
     375              :   }
     376              :   else
     377              :   {
     378          156 :     struct Transaction *t = h->transactions[hc->ha.start_idx % h->ram_limit];
     379              :     bool overflow;
     380              :     uint64_t dir;
     381          156 :     bool skip = true;
     382              : 
     383          156 :     overflow = ( (NULL != t) && (t->row_id != hc->ha.start_idx) );
     384          156 :     dir = (0 > hc->ha.delta) ? (h->ram_limit - 1) : 1;
     385              :     /* If account does not match, linear scan for
     386              :        first matching account. */
     387          505 :     while ( (! overflow) &&
     388          349 :             (NULL != t) &&
     389          349 :             (t->credit_account != hc->acc) )
     390              :     {
     391          193 :       skip = false;
     392          193 :       t = h->transactions[(t->row_id + dir) % h->ram_limit];
     393          193 :       if ( (NULL != t) &&
     394          193 :            (t->row_id == hc->ha.start_idx) )
     395            0 :         overflow = true; /* full circle, give up! */
     396              :     }
     397          156 :     if ( (NULL == t) ||
     398              :          overflow)
     399              :     {
     400            0 :       in_shutdown = h->in_shutdown;
     401              :       /* FIXME: these conditions are unclear to me. */
     402            0 :       if (GNUNET_TIME_relative_is_zero (hc->ha.lp_timeout) &&
     403            0 :           (0 < hc->ha.delta))
     404              :       {
     405            0 :         acc_payto_uri = hc->acc->payto_uri;
     406            0 :         GNUNET_assert (0 ==
     407              :                        pthread_mutex_unlock (&h->big_lock));
     408            0 :         if (overflow)
     409            0 :           return TALER_MHD_reply_with_ec (
     410              :             connection,
     411              :             TALER_EC_BANK_ANCIENT_TRANSACTION_GONE,
     412              :             NULL);
     413            0 :         goto finish;
     414              :       }
     415            0 :       if (in_shutdown)
     416              :       {
     417            0 :         acc_payto_uri = hc->acc->payto_uri;
     418            0 :         GNUNET_assert (0 ==
     419              :                        pthread_mutex_unlock (&h->big_lock));
     420            0 :         goto finish;
     421              :       }
     422            0 :       TALER_FAKEBANK_start_lp_ (h,
     423              :                                 connection,
     424              :                                 hc->acc,
     425              :                                 GNUNET_TIME_absolute_get_remaining (
     426              :                                   hc->timeout),
     427              :                                 LP_CREDIT,
     428              :                                 NULL);
     429            0 :       GNUNET_assert (0 ==
     430              :                      pthread_mutex_unlock (&h->big_lock));
     431            0 :       return MHD_YES;
     432              :     }
     433          156 :     if (skip)
     434              :     {
     435              :       /* range from application is exclusive, skip the
     436              :   matching entry */
     437          121 :       if (0 > hc->ha.delta)
     438            0 :         pos = t->prev_in;
     439              :       else
     440          121 :         pos = t->next_in;
     441              :     }
     442              :     else
     443              :     {
     444           35 :       pos = t;
     445              :     }
     446              :   }
     447          170 :   if (NULL != pos)
     448          108 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     449              :                 "Returning %lld credit transactions starting (inclusive) from %llu\n",
     450              :                 (long long) hc->ha.delta,
     451              :                 (unsigned long long) pos->row_id);
     452          278 :   while ( (0 != hc->ha.delta) &&
     453              :           (NULL != pos) )
     454              :   {
     455              :     json_t *trans;
     456              : 
     457          108 :     if ( (T_CREDIT != pos->type) &&
     458           16 :          (T_AUTH != pos->type) )
     459              :     {
     460            0 :       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     461              :                   "Unexpected DEBIT transaction #%llu for account `%s'\n",
     462              :                   (unsigned long long) pos->row_id,
     463              :                   account);
     464            0 :       if (0 > hc->ha.delta)
     465            0 :         pos = pos->prev_in;
     466            0 :       if (0 < hc->ha.delta)
     467            0 :         pos = pos->next_in;
     468            0 :       continue;
     469              :     }
     470          108 :     switch (pos->type)
     471              :     {
     472            0 :     case T_DEBIT:
     473            0 :       GNUNET_assert (0);
     474              :       break;
     475            0 :     case T_WAD:
     476            0 :       trans = GNUNET_JSON_PACK (
     477              :         GNUNET_JSON_pack_string ("type",
     478              :                                  "WAD"),
     479              :         GNUNET_JSON_pack_uint64 ("row_id",
     480              :                                  pos->row_id),
     481              :         GNUNET_JSON_pack_timestamp ("date",
     482              :                                     pos->date),
     483              :         TALER_JSON_pack_amount ("amount",
     484              :                                 &pos->amount),
     485              :         GNUNET_JSON_pack_string ("debit_account",
     486              :                                  pos->debit_account->payto_uri),
     487              :         GNUNET_JSON_pack_string ("origin_exchange_url",
     488              :                                  pos->subject.wad.origin_base_url),
     489              :         GNUNET_JSON_pack_data_auto ("wad_id",
     490              :                                     &pos->subject.wad.wad_id));
     491            0 :       break;
     492           92 :     case T_CREDIT:
     493           92 :       trans = GNUNET_JSON_PACK (
     494              :         GNUNET_JSON_pack_string ("type",
     495              :                                  "RESERVE"),
     496              :         GNUNET_JSON_pack_uint64 ("row_id",
     497              :                                  pos->row_id),
     498              :         GNUNET_JSON_pack_timestamp ("date",
     499              :                                     pos->date),
     500              :         TALER_JSON_pack_amount ("amount",
     501              :                                 &pos->amount),
     502              :         GNUNET_JSON_pack_string ("debit_account",
     503              :                                  pos->debit_account->payto_uri),
     504              :         GNUNET_JSON_pack_data_auto ("reserve_pub",
     505              :                                     &pos->subject.credit.reserve_pub));
     506           92 :       break;
     507           16 :     case T_AUTH:
     508           16 :       trans = GNUNET_JSON_PACK (
     509              :         GNUNET_JSON_pack_string ("type",
     510              :                                  "KYCAUTH"),
     511              :         GNUNET_JSON_pack_uint64 ("row_id",
     512              :                                  pos->row_id),
     513              :         GNUNET_JSON_pack_timestamp ("date",
     514              :                                     pos->date),
     515              :         TALER_JSON_pack_amount ("amount",
     516              :                                 &pos->amount),
     517              :         GNUNET_JSON_pack_string ("debit_account",
     518              :                                  pos->debit_account->payto_uri),
     519              :         GNUNET_JSON_pack_data_auto ("account_pub",
     520              :                                     &pos->subject.auth.account_pub));
     521           16 :       break;
     522              :     }
     523          108 :     GNUNET_assert (NULL != trans);
     524          108 :     GNUNET_assert (0 ==
     525              :                    json_array_append_new (hc->history,
     526              :                                           trans));
     527          108 :     if (hc->ha.delta > 0)
     528          107 :       hc->ha.delta--;
     529              :     else
     530            1 :       hc->ha.delta++;
     531          108 :     if (0 > hc->ha.delta)
     532            1 :       pos = pos->prev_in;
     533          108 :     if (0 < hc->ha.delta)
     534            2 :       pos = pos->next_in;
     535              :   }
     536          170 :   if ( (0 == json_array_size (hc->history)) &&
     537          124 :        (! h->in_shutdown) &&
     538           62 :        (GNUNET_TIME_absolute_is_future (hc->timeout)) &&
     539            0 :        (0 < hc->ha.delta))
     540              :   {
     541            0 :     TALER_FAKEBANK_start_lp_ (h,
     542              :                               connection,
     543              :                               hc->acc,
     544              :                               GNUNET_TIME_absolute_get_remaining (hc->timeout),
     545              :                               LP_CREDIT,
     546              :                               NULL);
     547            0 :     GNUNET_assert (0 ==
     548              :                    pthread_mutex_unlock (&h->big_lock));
     549            0 :     return MHD_YES;
     550              :   }
     551          170 :   in_shutdown = h->in_shutdown;
     552          170 :   acc_payto_uri = hc->acc->payto_uri;
     553          170 :   GNUNET_assert (0 ==
     554              :                  pthread_mutex_unlock (&h->big_lock));
     555          170 : finish:
     556          170 :   if (0 == json_array_size (hc->history))
     557              :   {
     558           62 :     GNUNET_break (in_shutdown ||
     559              :                   (! GNUNET_TIME_absolute_is_future (hc->timeout)));
     560           62 :     return TALER_MHD_reply_static (connection,
     561              :                                    MHD_HTTP_NO_CONTENT,
     562              :                                    NULL,
     563              :                                    NULL,
     564              :                                    0);
     565              :   }
     566              :   {
     567          108 :     json_t *jh = hc->history;
     568              : 
     569          108 :     hc->history = NULL;
     570          108 :     return TALER_MHD_REPLY_JSON_PACK (
     571              :       connection,
     572              :       MHD_HTTP_OK,
     573              :       GNUNET_JSON_pack_string (
     574              :         "credit_account",
     575              :         acc_payto_uri),
     576              :       GNUNET_JSON_pack_array_steal (
     577              :         "incoming_transactions",
     578              :         jh));
     579              :   }
     580              : }
        

Generated by: LCOV version 2.0-1