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

Generated by: LCOV version 2.0-1