LCOV - code coverage report
Current view: top level - bank-lib - fakebank_twg_history.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 134 229 58.5 %
Date: 2025-06-22 12:09:43 Functions: 3 3 100.0 %

          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         173 : history_cleanup (void *cls)
      43             : {
      44         173 :   struct HistoryContext *hc = cls;
      45             : 
      46         173 :   json_decref (hc->history);
      47         173 :   GNUNET_free (hc);
      48         173 : }
      49             : 
      50             : 
      51             : MHD_RESULT
      52           3 : 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           3 :   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           3 :   if (NULL == cc)
      66             :   {
      67           3 :     cc = GNUNET_new (struct ConnectionContext);
      68           3 :     cc->ctx_cleaner = &history_cleanup;
      69           3 :     *con_cls = cc;
      70           3 :     hc = GNUNET_new (struct HistoryContext);
      71           3 :     cc->ctx = hc;
      72             : 
      73           3 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
      74             :                 "Handling /history/outgoing connection %p\n",
      75             :                 connection);
      76           3 :     if (GNUNET_OK !=
      77           3 :         (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           3 :     GNUNET_assert (0 ==
      85             :                    pthread_mutex_lock (&h->big_lock));
      86           3 :     if (UINT64_MAX == hc->ha.start_idx)
      87           1 :       hc->ha.start_idx = h->serial_counter;
      88           3 :     hc->acc = TALER_FAKEBANK_lookup_account_ (h,
      89             :                                               account,
      90             :                                               NULL);
      91           3 :     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           3 :     hc->history = json_array ();
     101           3 :     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           3 :     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           3 :   if (! hc->ha.have_start)
     118             :   {
     119           3 :     pos = (0 > hc->ha.delta)
     120           1 :       ? hc->acc->out_tail
     121           3 :       : 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           3 :   if (NULL != pos)
     207           2 :     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           5 :   while ( (0 != hc->ha.delta) &&
     212             :           (NULL != pos) )
     213             :   {
     214             :     json_t *trans;
     215             :     char *credit_payto;
     216             : 
     217           2 :     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           2 :     GNUNET_asprintf (&credit_payto,
     230             :                      "payto://x-taler-bank/localhost/%s?receiver-name=%s",
     231           2 :                      pos->credit_account->account_name,
     232           2 :                      pos->credit_account->receiver_name);
     233             : 
     234           2 :     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           2 :     GNUNET_assert (NULL != trans);
     248           2 :     GNUNET_free (credit_payto);
     249           2 :     GNUNET_assert (0 ==
     250             :                    json_array_append_new (hc->history,
     251             :                                           trans));
     252           2 :     if (hc->ha.delta > 0)
     253           1 :       hc->ha.delta--;
     254             :     else
     255           1 :       hc->ha.delta++;
     256           2 :     if (0 > hc->ha.delta)
     257           1 :       pos = pos->prev_out;
     258           2 :     if (0 < hc->ha.delta)
     259           1 :       pos = pos->next_out;
     260             :   }
     261           3 :   if ( (0 == json_array_size (hc->history)) &&
     262           2 :        (! h->in_shutdown) &&
     263           1 :        (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           3 :   in_shutdown = h->in_shutdown;
     277           3 :   acc_payto_uri = hc->acc->payto_uri;
     278           3 :   GNUNET_assert (0 ==
     279             :                  pthread_mutex_unlock (&h->big_lock));
     280           3 : finish:
     281           3 :   if (0 == json_array_size (hc->history))
     282             :   {
     283           1 :     GNUNET_break (in_shutdown ||
     284             :                   (! GNUNET_TIME_absolute_is_future (hc->timeout)));
     285           1 :     return TALER_MHD_reply_static (connection,
     286             :                                    MHD_HTTP_NO_CONTENT,
     287             :                                    NULL,
     288             :                                    NULL,
     289             :                                    0);
     290             :   }
     291             :   {
     292           2 :     json_t *jh = hc->history;
     293             : 
     294           2 :     hc->history = NULL;
     295           2 :     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         170 : 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         170 :   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         170 :   if (NULL == cc)
     323             :   {
     324         170 :     cc = GNUNET_new (struct ConnectionContext);
     325         170 :     cc->ctx_cleaner = &history_cleanup;
     326         170 :     *con_cls = cc;
     327         170 :     hc = GNUNET_new (struct HistoryContext);
     328         170 :     cc->ctx = hc;
     329         170 :     hc->history = json_array ();
     330         170 :     if (NULL == hc->history)
     331             :     {
     332           0 :       GNUNET_break (0);
     333           0 :       return MHD_NO;
     334             :     }
     335         170 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     336             :                 "Handling /history/incoming connection %p\n",
     337             :                 connection);
     338         170 :     if (GNUNET_OK !=
     339         170 :         (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         170 :     hc->timeout = GNUNET_TIME_relative_to_absolute (hc->ha.lp_timeout);
     347         170 :     GNUNET_assert (0 ==
     348             :                    pthread_mutex_lock (&h->big_lock));
     349         170 :     if (UINT64_MAX == hc->ha.start_idx)
     350           1 :       hc->ha.start_idx = h->serial_counter;
     351         170 :     hc->acc = TALER_FAKEBANK_lookup_account_ (h,
     352             :                                               account,
     353             :                                               NULL);
     354         170 :     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         168 :   if (! hc->ha.have_start)
     372             :   {
     373          24 :     pos = (0 > hc->ha.delta)
     374           1 :           ? hc->acc->in_tail
     375          11 :           : 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         168 :   if (NULL != pos)
     449         107 :     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         275 :   while ( (0 != hc->ha.delta) &&
     454             :           (NULL != pos) )
     455             :   {
     456             :     json_t *trans;
     457             : 
     458         107 :     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         107 :     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          91 :     case T_CREDIT:
     494          91 :       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          91 :       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         107 :     GNUNET_assert (NULL != trans);
     525         107 :     GNUNET_assert (0 ==
     526             :                    json_array_append_new (hc->history,
     527             :                                           trans));
     528         107 :     if (hc->ha.delta > 0)
     529         106 :       hc->ha.delta--;
     530             :     else
     531           1 :       hc->ha.delta++;
     532         107 :     if (0 > hc->ha.delta)
     533           1 :       pos = pos->prev_in;
     534         107 :     if (0 < hc->ha.delta)
     535           1 :       pos = pos->next_in;
     536             :   }
     537         168 :   if ( (0 == json_array_size (hc->history)) &&
     538         122 :        (! h->in_shutdown) &&
     539          61 :        (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         168 :   in_shutdown = h->in_shutdown;
     553         168 :   acc_payto_uri = hc->acc->payto_uri;
     554         168 :   GNUNET_assert (0 ==
     555             :                  pthread_mutex_unlock (&h->big_lock));
     556         168 : finish:
     557         168 :   if (0 == json_array_size (hc->history))
     558             :   {
     559          61 :     GNUNET_break (in_shutdown ||
     560             :                   (! GNUNET_TIME_absolute_is_future (hc->timeout)));
     561          61 :     return TALER_MHD_reply_static (connection,
     562             :                                    MHD_HTTP_NO_CONTENT,
     563             :                                    NULL,
     564             :                                    NULL,
     565             :                                    0);
     566             :   }
     567             :   {
     568         107 :     json_t *jh = hc->history;
     569             : 
     570         107 :     hc->history = NULL;
     571         107 :     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 1.16