merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

taler-merchant-httpd_post-private-accounts-H_WIRE-kycauth.c (20688B)


      1 /*
      2   This file is part of TALER
      3   (C) 2026 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU Affero General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12 
     13   You should have received a copy of the GNU Affero General Public License
     14   along with TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 /**
     17  * @file src/backend/taler-merchant-httpd_post-private-accounts-H_WIRE-kycauth.c
     18  * @brief Handle POST /private/accounts/$H_WIRE/kycauth requests
     19  * @author Christian Grothoff
     20  */
     21 #include "platform.h"
     22 #include <jansson.h>
     23 #include <microhttpd.h>
     24 #include <gnunet/gnunet_json_lib.h>
     25 #include <taler/taler_json_lib.h>
     26 #include <taler/taler_mhd_lib.h>
     27 #include <taler/taler_bank_service.h>
     28 #include "taler-merchant-httpd.h"
     29 #include "taler-merchant-httpd_exchanges.h"
     30 #include "taler-merchant-httpd_post-private-accounts-H_WIRE-kycauth.h"
     31 #include "merchant-database/select_account.h"
     32 
     33 
     34 /**
     35  * Processing phases for a kycauth POST request.
     36  */
     37 enum KycAuthPhase
     38 {
     39   /**
     40    * Parse the request body and URL path.
     41    */
     42   KP_PARSE = 0,
     43 
     44   /**
     45    * Fetch exchange /keys (and optionally register with bank gateway).
     46    * The connection is suspended in this phase.
     47    */
     48   KP_CHECK_EXCHANGES,
     49 
     50   /**
     51    * Return the prepared response to the client.
     52    */
     53   KP_RETURN_RESPONSE,
     54 
     55   /**
     56    * Return MHD_YES to finish handling.
     57    */
     58   KP_END_YES,
     59 
     60   /**
     61    * Return MHD_NO to close the connection.
     62    */
     63   KP_END_NO
     64 };
     65 
     66 
     67 struct ExchangeAccount
     68 {
     69 
     70   /**
     71    * Payto URI of the exchange, saved from /keys.
     72    */
     73   struct TALER_FullPayto payto;
     74 
     75   /**
     76    * Pending bank gateway registration handle, or NULL.
     77    */
     78   struct TALER_BANK_RegistrationHandle *brh;
     79 
     80   /**
     81    * Context we are operating in.
     82    */
     83   struct KycAuthContext *kac;
     84 
     85   /**
     86    * Transfer subjects to use for the account.
     87    */
     88   struct TALER_BANK_TransferSubject *subjects;
     89 
     90   /**
     91    * Length of the @e subjects array.
     92    */
     93   unsigned int num_subjects;
     94 
     95   /**
     96    * Expiration time for the given @e ts.
     97    */
     98   struct GNUNET_TIME_Timestamp expiration;
     99 };
    100 
    101 
    102 /**
    103  * Per-request context for POST /private/accounts/$H_WIRE/kycauth.
    104  */
    105 struct KycAuthContext
    106 {
    107 
    108   /**
    109    * Kept in doubly-linked list.
    110    */
    111   struct KycAuthContext *next;
    112 
    113   /**
    114    * Kept in doubly-linked list.
    115    */
    116   struct KycAuthContext *prev;
    117 
    118   /**
    119    * MHD connection we are handling.
    120    */
    121   struct MHD_Connection *connection;
    122 
    123   /**
    124    * Handler context for this request.
    125    */
    126   struct TMH_HandlerContext *hc;
    127 
    128   /**
    129    * Prepared HTTP response to return, or NULL.
    130    */
    131   struct MHD_Response *response;
    132 
    133   /**
    134    * Exchange URL from the request body.
    135    */
    136   char *exchange_url;
    137 
    138   /**
    139    * Payto URI of our merchant bank account (from DB).
    140    */
    141   struct TALER_FullPayto payto_uri;
    142 
    143   /**
    144    * Pending /keys lookup operation with the exchange.
    145    */
    146   struct TMH_EXCHANGES_KeysOperation *fo;
    147 
    148   /**
    149    * Tiny amount from exchange /keys, used as the transfer amount.
    150    */
    151   struct TALER_Amount tiny_amount;
    152 
    153   /**
    154    * Array of exchange wire account payto URIs, saved from /keys.
    155    * Length is @e exchange_accounts_len.
    156    */
    157   struct ExchangeAccount *exchange_accounts;
    158 
    159   /**
    160    * Number of entries in @e exchange_accounts.
    161    */
    162   unsigned int exchange_accounts_len;
    163 
    164   /**
    165    * Number of active registrations in @e exchange_accounts.
    166    */
    167   unsigned int active_registrations;
    168 
    169   /**
    170    * HTTP status code to send with @e response.
    171    * UINT_MAX indicates a hard error (return MHD_NO).
    172    */
    173   unsigned int response_code;
    174 
    175   /**
    176    * Current processing phase.
    177    */
    178   enum KycAuthPhase phase;
    179 
    180   /**
    181    * #GNUNET_NO if the connection is not suspended,
    182    * #GNUNET_YES if the connection is suspended,
    183    * #GNUNET_SYSERR if suspended and being force-resumed during shutdown.
    184    */
    185   enum GNUNET_GenericReturnValue suspended;
    186 
    187 };
    188 
    189 
    190 /**
    191  * Head of the doubly-linked list of active kycauth contexts.
    192  */
    193 static struct KycAuthContext *kac_head;
    194 
    195 /**
    196  * Tail of the doubly-linked list of active kycauth contexts.
    197  */
    198 static struct KycAuthContext *kac_tail;
    199 
    200 
    201 void
    202 TMH_force_kac_resume (void)
    203 {
    204   for (struct KycAuthContext *kac = kac_head;
    205        NULL != kac;
    206        kac = kac->next)
    207   {
    208     if (NULL != kac->fo)
    209     {
    210       TMH_EXCHANGES_keys4exchange_cancel (kac->fo);
    211       kac->fo = NULL;
    212     }
    213     if (GNUNET_YES == kac->suspended)
    214     {
    215       kac->suspended = GNUNET_SYSERR;
    216       MHD_resume_connection (kac->connection);
    217     }
    218   }
    219 }
    220 
    221 
    222 /**
    223  * Resume processing of @a kac after an async operation completed.
    224  *
    225  * @param[in,out] kac context to resume
    226  */
    227 static void
    228 kac_resume (struct KycAuthContext *kac)
    229 {
    230   GNUNET_assert (GNUNET_YES == kac->suspended);
    231   kac->suspended = GNUNET_NO;
    232   MHD_resume_connection (kac->connection);
    233   TALER_MHD_daemon_trigger ();
    234 }
    235 
    236 
    237 /**
    238  * Clean up a kycauth context, freeing all resources.
    239  *
    240  * @param cls a `struct KycAuthContext` to clean up
    241  */
    242 static void
    243 kac_cleanup (void *cls)
    244 {
    245   struct KycAuthContext *kac = cls;
    246 
    247   if (NULL != kac->fo)
    248   {
    249     TMH_EXCHANGES_keys4exchange_cancel (kac->fo);
    250     kac->fo = NULL;
    251   }
    252   if (NULL != kac->response)
    253   {
    254     MHD_destroy_response (kac->response);
    255     kac->response = NULL;
    256   }
    257   GNUNET_free (kac->exchange_url);
    258   GNUNET_free (kac->payto_uri.full_payto);
    259   for (unsigned int i = 0; i < kac->exchange_accounts_len; i++)
    260   {
    261     struct ExchangeAccount *acc = &kac->exchange_accounts[i];
    262 
    263     if (NULL != acc->brh)
    264     {
    265       TALER_BANK_registration_cancel (acc->brh);
    266       acc->brh = NULL;
    267     }
    268     for (unsigned int j = 0; j<acc->num_subjects; j++)
    269       TALER_BANK_transfer_subject_free (&acc->subjects[j]);
    270     GNUNET_free (acc->subjects);
    271     GNUNET_free (acc->payto.full_payto);
    272   }
    273   GNUNET_free (kac->exchange_accounts);
    274   GNUNET_CONTAINER_DLL_remove (kac_head,
    275                                kac_tail,
    276                                kac);
    277   GNUNET_free (kac);
    278 }
    279 
    280 
    281 /**
    282  * Convert a @a ts (transfer subject) to a JSON object.
    283  * The resulting object has a "type" field discriminating the format,
    284  * matching the JSON format returned by the bank gateway's /registration.
    285  *
    286  * @param acc general account details
    287  * @param ts the specific transfer subject to convert
    288  * @return freshly allocated JSON object, or NULL on error
    289  */
    290 static json_t *
    291 transfer_subject_to_json (const struct ExchangeAccount *acc,
    292                           const struct TALER_BANK_TransferSubject *ts)
    293 {
    294   struct KycAuthContext *kac = acc->kac;
    295 
    296   switch (ts->format)
    297   {
    298   case TALER_BANK_SUBJECT_FORMAT_SIMPLE:
    299     return GNUNET_JSON_PACK (
    300       GNUNET_JSON_pack_string ("type",
    301                                "SIMPLE"),
    302       TALER_JSON_pack_amount ("credit_amount",
    303                               &kac->tiny_amount),
    304       GNUNET_JSON_pack_data_auto ("subject",
    305                                   &kac->hc->instance->merchant_pub));
    306   case TALER_BANK_SUBJECT_FORMAT_URI:
    307     return GNUNET_JSON_PACK (
    308       GNUNET_JSON_pack_string ("type",
    309                                "URI"),
    310       TALER_JSON_pack_amount ("credit_amount",
    311                               &kac->tiny_amount),
    312       GNUNET_JSON_pack_string ("uri",
    313                                ts->details.uri.uri));
    314   case TALER_BANK_SUBJECT_FORMAT_CH_QR_BILL:
    315     return GNUNET_JSON_PACK (
    316       GNUNET_JSON_pack_string ("type",
    317                                "CH_QR_BILL"),
    318       TALER_JSON_pack_amount ("credit_amount",
    319                               &ts->details.ch_qr_bill.credit_amount),
    320       GNUNET_JSON_pack_string ("qr_reference_number",
    321                                ts->details.ch_qr_bill.qr_reference_number));
    322   }
    323   GNUNET_break (0);
    324   return NULL;
    325 }
    326 
    327 
    328 /**
    329  * Generate the final "OK" response for the request in @a kac.
    330  * Builds the wire_instructions JSON array from the saved exchange accounts
    331  * and the given transfer subject.
    332  *
    333  * @param[in,out] kac request with all the details ready to build a response
    334  */
    335 static void
    336 generate_ok_response (struct KycAuthContext *kac)
    337 {
    338   json_t *arr;
    339 
    340   arr = json_array ();
    341   GNUNET_assert (NULL != arr);
    342   for (unsigned int i = 0; i < kac->exchange_accounts_len; i++)
    343   {
    344     const struct ExchangeAccount *acc = &kac->exchange_accounts[i];
    345     json_t *subj;
    346     json_t *entry;
    347 
    348     for (unsigned int j = 0; j < acc->num_subjects; j++)
    349     {
    350       subj = transfer_subject_to_json (acc,
    351                                        &acc->subjects[j]);
    352       GNUNET_assert (NULL != subj);
    353       entry = GNUNET_JSON_PACK (
    354         TALER_JSON_pack_amount ("amount",
    355                                 &kac->tiny_amount),
    356         TALER_JSON_pack_full_payto ("target_payto",
    357                                     acc->payto),
    358         GNUNET_JSON_pack_object_steal ("subject",
    359                                        subj),
    360         GNUNET_JSON_pack_timestamp ("expiration",
    361                                     acc->expiration));
    362       GNUNET_assert (NULL != entry);
    363       GNUNET_assert (0 ==
    364                      json_array_append_new (arr,
    365                                             entry));
    366     }
    367   }
    368   kac->response_code = MHD_HTTP_OK;
    369   kac->response = TALER_MHD_MAKE_JSON_PACK (
    370     GNUNET_JSON_pack_array_steal ("wire_instructions",
    371                                   arr));
    372   kac->phase = KP_RETURN_RESPONSE;
    373   kac_resume (kac);
    374 }
    375 
    376 
    377 /**
    378  * Callback invoked with the result of the bank gateway /registration request.
    379  *
    380  * @param cls our `struct KycAuthContext`
    381  * @param rr response details
    382  */
    383 static void
    384 registration_cb (void *cls,
    385                  const struct TALER_BANK_RegistrationResponse *rr)
    386 {
    387   struct ExchangeAccount *acc = cls;
    388   struct KycAuthContext *kac = acc->kac;
    389 
    390   acc->brh = NULL;
    391   kac->active_registrations--;
    392   if (MHD_HTTP_OK != rr->http_status)
    393   {
    394     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    395                 "Bank gateway registration failed with HTTP status %u\n",
    396                 rr->http_status);
    397     kac->response_code = MHD_HTTP_BAD_GATEWAY;
    398     kac->response = TALER_MHD_make_error (
    399       TALER_EC_MERCHANT_POST_ACCOUNTS_KYCAUTH_BANK_GATEWAY_UNREACHABLE,
    400       "bank gateway /registration failed");
    401   }
    402   GNUNET_free (acc->subjects);
    403   acc->num_subjects = rr->details.ok.num_subjects;
    404   acc->subjects = GNUNET_new_array (acc->num_subjects,
    405                                     struct TALER_BANK_TransferSubject);
    406   for (unsigned int i = 0; i<acc->num_subjects; i++)
    407   {
    408     TALER_BANK_transfer_subject_copy (&acc->subjects[i],
    409                                       &rr->details.ok.subjects[i]);
    410   }
    411   acc->expiration = rr->details.ok.expiration;
    412   if (0 != kac->active_registrations)
    413     return; /* wait for more replies */
    414   generate_ok_response (kac);
    415 }
    416 
    417 
    418 /**
    419  * Callback invoked with the /keys of the selected exchange.
    420  *
    421  * Saves tiny_amount and exchange account payto URIs from the keys, then
    422  * either calls the bank gateway /registration (if wire_transfer_gateway is
    423  * present) or directly constructs the SIMPLE-format response.
    424  *
    425  * @param cls our `struct KycAuthContext`
    426  * @param keys the exchange's key material, or NULL on failure
    427  * @param exchange internal exchange handle (unused)
    428  */
    429 static void
    430 process_keys_cb (void *cls,
    431                  struct TALER_EXCHANGE_Keys *keys,
    432                  struct TMH_Exchange *exchange)
    433 {
    434   struct KycAuthContext *kac = cls;
    435   struct TMH_MerchantInstance *mi = kac->hc->instance;
    436 
    437   (void) exchange;
    438   kac->fo = NULL;
    439   if (NULL == keys)
    440   {
    441     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    442                 "Could not get /keys from exchange `%s'\n",
    443                 kac->exchange_url);
    444     kac->response_code = MHD_HTTP_BAD_GATEWAY;
    445     kac->response = TALER_MHD_make_error (
    446       TALER_EC_MERCHANT_POST_ACCOUNTS_KYCAUTH_EXCHANGE_UNREACHABLE,
    447       kac->exchange_url);
    448     kac->phase = KP_RETURN_RESPONSE;
    449     kac_resume (kac);
    450     return;
    451   }
    452   if (! keys->tiny_amount_available)
    453   {
    454     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    455                 "Exchange `%s' did not provide tiny_amount in /keys\n",
    456                 kac->exchange_url);
    457     kac->response_code = MHD_HTTP_BAD_GATEWAY;
    458     kac->response = TALER_MHD_make_error (
    459       TALER_EC_MERCHANT_POST_ACCOUNTS_EXCHANGE_TOO_OLD,
    460       "exchange /keys missing tiny_amount");
    461     kac->phase = KP_RETURN_RESPONSE;
    462     kac_resume (kac);
    463     return;
    464   }
    465 
    466   /* Save tiny_amount and exchange wire accounts from keys */
    467   kac->tiny_amount = keys->tiny_amount;
    468   kac->exchange_accounts_len = keys->accounts_len;
    469   if (0 == keys->accounts_len)
    470   {
    471     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    472                 "Exchange `%s' did not provide any wire accounts in /keys\n",
    473                 kac->exchange_url);
    474     kac->response_code = MHD_HTTP_BAD_GATEWAY;
    475     kac->response = TALER_MHD_make_error (
    476       TALER_EC_MERCHANT_GENERIC_EXCHANGE_UNEXPECTED_STATUS,
    477       "exchange /keys missing wire accounts");
    478     kac->phase = KP_RETURN_RESPONSE;
    479     kac_resume (kac);
    480     return;
    481   }
    482 
    483   kac->exchange_accounts
    484     = GNUNET_new_array (keys->accounts_len,
    485                         struct ExchangeAccount);
    486   for (unsigned int i = 0; i < keys->accounts_len; i++)
    487   {
    488     struct ExchangeAccount *acc = &kac->exchange_accounts[i];
    489     struct TALER_ReserveMapAuthorizationPrivateKeyP apk;
    490 
    491     GNUNET_CRYPTO_eddsa_key_create (&apk.eddsa_priv);
    492     acc->kac = kac;
    493     acc->payto.full_payto
    494       = GNUNET_strdup (keys->accounts[i].fpayto_uri.full_payto);
    495     acc->subjects = GNUNET_new (struct TALER_BANK_TransferSubject);
    496     acc->num_subjects = 1;
    497     acc->subjects[0].format = TALER_BANK_SUBJECT_FORMAT_SIMPLE;
    498     acc->expiration = GNUNET_TIME_UNIT_FOREVER_TS;
    499     if (NULL == keys->accounts[i].wire_transfer_gateway)
    500       continue;
    501     acc->brh = TALER_BANK_registration (
    502       TMH_curl_ctx,
    503       keys->accounts[i].wire_transfer_gateway,
    504       &kac->tiny_amount,
    505       TALER_BANK_REGISTRATION_TYPE_KYC,
    506       (const union TALER_AccountPublicKeyP *) &mi->merchant_pub,
    507       // FIXME: turn this into an option when modernizing the BANK API...
    508       &apk,
    509       false, /* recurrent */
    510       &registration_cb,
    511       acc);
    512     if (NULL == acc->brh)
    513     {
    514       GNUNET_break (0);
    515       kac->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
    516       kac->response = TALER_MHD_make_error (
    517         TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
    518         "could not start bank gateway registration");
    519       kac->phase = KP_RETURN_RESPONSE;
    520       kac_resume (kac);
    521       return;
    522     }
    523     kac->active_registrations++;
    524   }
    525   if (0 != kac->active_registrations)
    526     return;
    527   generate_ok_response (kac);
    528 }
    529 
    530 
    531 /**
    532  * Process the PARSE phase: validate the URL path, parse the request body,
    533  * and look up the merchant account in the database.
    534  *
    535  * @param[in,out] kac context to process
    536  */
    537 static void
    538 phase_parse (struct KycAuthContext *kac)
    539 {
    540   const char *h_wire_s = kac->hc->infix;
    541   struct TALER_MerchantWireHashP h_wire;
    542   const char *exchange_url;
    543   enum GNUNET_GenericReturnValue res;
    544   struct GNUNET_JSON_Specification spec[] = {
    545     GNUNET_JSON_spec_string ("exchange_url",
    546                              &exchange_url),
    547     GNUNET_JSON_spec_end ()
    548   };
    549 
    550   GNUNET_assert (NULL != h_wire_s);
    551   if (GNUNET_OK !=
    552       GNUNET_STRINGS_string_to_data (h_wire_s,
    553                                      strlen (h_wire_s),
    554                                      &h_wire,
    555                                      sizeof (h_wire)))
    556   {
    557     GNUNET_break_op (0);
    558     kac->response_code = MHD_HTTP_BAD_REQUEST;
    559     kac->response = TALER_MHD_make_error (
    560       TALER_EC_MERCHANT_GENERIC_H_WIRE_MALFORMED,
    561       h_wire_s);
    562     kac->phase = KP_RETURN_RESPONSE;
    563     return;
    564   }
    565 
    566   res = TALER_MHD_parse_json_data (kac->connection,
    567                                    kac->hc->request_body,
    568                                    spec);
    569   if (GNUNET_OK != res)
    570   {
    571     kac->phase = (GNUNET_NO == res) ? KP_END_YES : KP_END_NO;
    572     return;
    573   }
    574 
    575   /* Look up the merchant account in the database */
    576   {
    577     struct TALER_MERCHANTDB_AccountDetails ad = { 0 };
    578     enum GNUNET_DB_QueryStatus qs;
    579 
    580     qs = TALER_MERCHANTDB_select_account (TMH_db,
    581                                           kac->hc->instance->settings.id,
    582                                           &h_wire,
    583                                           &ad);
    584     if (0 > qs)
    585     {
    586       GNUNET_break (0);
    587       GNUNET_JSON_parse_free (spec);
    588       kac->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
    589       kac->response = TALER_MHD_make_error (
    590         TALER_EC_GENERIC_DB_FETCH_FAILED,
    591         "select_account");
    592       kac->phase = KP_RETURN_RESPONSE;
    593       return;
    594     }
    595     if (0 == qs)
    596     {
    597       GNUNET_JSON_parse_free (spec);
    598       kac->response_code = MHD_HTTP_NOT_FOUND;
    599       kac->response = TALER_MHD_make_error (
    600         TALER_EC_MERCHANT_GENERIC_ACCOUNT_UNKNOWN,
    601         h_wire_s);
    602       kac->phase = KP_RETURN_RESPONSE;
    603       return;
    604     }
    605     kac->payto_uri.full_payto = GNUNET_strdup (ad.payto_uri.full_payto);
    606     /* Free fields we do not need */
    607     GNUNET_free (ad.payto_uri.full_payto);
    608     GNUNET_free (ad.credit_facade_url);
    609     GNUNET_free (ad.extra_wire_subject_metadata);
    610     json_decref (ad.credit_facade_credentials);
    611   }
    612 
    613   kac->exchange_url = GNUNET_strdup (exchange_url);
    614   GNUNET_JSON_parse_free (spec);
    615   kac->phase = KP_CHECK_EXCHANGES;
    616 }
    617 
    618 
    619 /**
    620  * Process the CHECK_EXCHANGES phase: start an async /keys fetch from
    621  * the requested exchange and suspend the connection.
    622  *
    623  * @param[in,out] kac context to process
    624  */
    625 static void
    626 phase_check_exchanges (struct KycAuthContext *kac)
    627 {
    628   kac->fo = TMH_EXCHANGES_keys4exchange (kac->exchange_url,
    629                                          false,
    630                                          &process_keys_cb,
    631                                          kac);
    632   if (NULL == kac->fo)
    633   {
    634     GNUNET_break_op (0);
    635     kac->response_code = MHD_HTTP_BAD_REQUEST;
    636     kac->response = TALER_MHD_make_error (
    637       TALER_EC_MERCHANT_GENERIC_EXCHANGE_UNTRUSTED,
    638       kac->exchange_url);
    639     kac->phase = KP_RETURN_RESPONSE;
    640     return;
    641   }
    642   MHD_suspend_connection (kac->connection);
    643   kac->suspended = GNUNET_YES;
    644 }
    645 
    646 
    647 /**
    648  * Process the RETURN_RESPONSE phase: queue the prepared response into MHD.
    649  *
    650  * @param[in,out] kac context to process
    651  */
    652 static void
    653 phase_return_response (struct KycAuthContext *kac)
    654 {
    655   enum MHD_Result ret;
    656 
    657   if (UINT_MAX == kac->response_code)
    658   {
    659     GNUNET_break (0);
    660     kac->phase = KP_END_NO;
    661     return;
    662   }
    663   GNUNET_assert (0 != kac->response_code);
    664   ret = MHD_queue_response (kac->connection,
    665                             kac->response_code,
    666                             kac->response);
    667   kac->phase = (MHD_YES == ret) ? KP_END_YES : KP_END_NO;
    668 }
    669 
    670 
    671 enum MHD_Result
    672 TMH_private_post_accounts_H_WIRE_kycauth (
    673   const struct TMH_RequestHandler *rh,
    674   struct MHD_Connection *connection,
    675   struct TMH_HandlerContext *hc)
    676 {
    677   struct KycAuthContext *kac = hc->ctx;
    678 
    679   (void) rh;
    680   GNUNET_assert (NULL != hc->infix);
    681   if (NULL == kac)
    682   {
    683     kac = GNUNET_new (struct KycAuthContext);
    684     kac->connection = connection;
    685     kac->hc = hc;
    686     hc->ctx = kac;
    687     hc->cc = &kac_cleanup;
    688     GNUNET_CONTAINER_DLL_insert (kac_head,
    689                                  kac_tail,
    690                                  kac);
    691   }
    692 
    693   while (1)
    694   {
    695     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    696                 "Processing POST /private/accounts/$H_WIRE/kycauth"
    697                 " in phase %d\n",
    698                 (int) kac->phase);
    699     switch (kac->phase)
    700     {
    701     case KP_PARSE:
    702       phase_parse (kac);
    703       break;
    704     case KP_CHECK_EXCHANGES:
    705       phase_check_exchanges (kac);
    706       break;
    707     case KP_RETURN_RESPONSE:
    708       phase_return_response (kac);
    709       break;
    710     case KP_END_YES:
    711       return MHD_YES;
    712     case KP_END_NO:
    713       return MHD_NO;
    714     default:
    715       GNUNET_assert (0);
    716       return MHD_NO;
    717     }
    718 
    719     switch (kac->suspended)
    720     {
    721     case GNUNET_SYSERR:
    722       /* Shutdown in progress */
    723       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    724                   "Processing POST /private/accounts/$H_WIRE/kycauth"
    725                   " ends due to shutdown in phase %d\n",
    726                   (int) kac->phase);
    727       return MHD_NO;
    728     case GNUNET_NO:
    729       /* Not suspended, continue with next phase */
    730       break;
    731     case GNUNET_YES:
    732       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    733                   "Processing POST /private/accounts/$H_WIRE/kycauth"
    734                   " suspended in phase %d\n",
    735                   (int) kac->phase);
    736       return MHD_YES;
    737     }
    738   }
    739   GNUNET_assert (0);
    740   return MHD_YES;
    741 }
    742 
    743 
    744 /* end of taler-merchant-httpd_private-post-accounts-H_WIRE-kycauth.c */