/* This file is part of TALER (C) 2014, 2015, 2016 INRIA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. TALER is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with TALER; see the file COPYING. If not, If not, see */ /** * @file backend/taler-merchant-httpd_track.c * @brief implement API for tracking deposits and wire transfers * @author Marcello Stanisci * @author Christian Grothoff */ #include "platform.h" #include #include #include #include "taler-merchant-httpd.h" #include "taler-merchant-httpd_mhd.h" #include "taler-merchant-httpd_parsing.h" #include "taler-merchant-httpd_auditors.h" #include "taler-merchant-httpd_exchanges.h" #include "taler-merchant-httpd_responses.h" #include "taler-merchant-httpd_track.h" extern char *TMH_merchant_currency_string; /** * Context used for handing /track/deposit requests. */ struct DepositTrackContext { /** * This MUST be first! */ struct TM_HandlerContext hc; /** * Handle to the exchange. */ struct TALER_EXCHANGE_Handle *eh; /** * Handle for the /wire/deposits request. */ struct TALER_EXCHANGE_WireDepositsHandle *wdh; /** * */ struct TALER_WireDepositDetails *details; /** * Argument for the /wire/deposits request. */ struct TALER_WireTransferIdentifierRawP wtid; /** * */ unsigned int details_length; struct MHD_Connection *connection; unsigned int response_code; json_t *json; const char *error; }; /** * Function called with detailed wire transfer data, including all * of the coin transactions that were combined into the wire transfer. * * @param cls closure * @param http_status HTTP status code we got, 0 on exchange protocol violation * @param json original json reply (may include signatures, those have then been * validated already) * @param wtid extracted wire transfer identifier, or NULL if the exchange could * not provide any (set only if @a http_status is #MHD_HTTP_OK) * @param total_amount total amount of the wire transfer, or NULL if the exchange could * not provide any @a wtid (set only if @a http_status is #MHD_HTTP_OK) * @param details_length length of the @a details array * @param details array with details about the combined transactions */ static void wire_deposit_cb (void *cls, unsigned int http_status, const json_t *json, const struct GNUNET_HashCode *h_wire, const struct TALER_Amount *total_amount, unsigned int details_length, const struct TALER_WireDepositDetails *details) { struct DepositTrackContext *rctx = cls; // unsigned int i; rctx->wdh = NULL; if (NULL == total_amount) { rctx->error = "failed to obtain /wire/deposit response from exchange"; rctx->json = json_incref ((json_t *) json); rctx->response_code = http_status; MHD_resume_connection (rctx->connection); return; } rctx->details_length = details_length; rctx->details = GNUNET_new_array (details_length, struct TALER_WireDepositDetails); memcpy (rctx->details, details, details_length * sizeof (struct TALER_WireDepositDetails)); GNUNET_break (0); /* FIXME: now check that these details match what we have in our database... */ } /** * Function called with information about who is auditing * a particular exchange and what key the exchange is using. * * @param cls closure * @param keys information about the various keys used * by the exchange, NULL if /keys failed */ static void cert_cb (void *cls, const struct TALER_EXCHANGE_Keys *keys) { struct DepositTrackContext *rctx = cls; if (NULL == keys) { rctx->error = "failed to obtain /keys from exchange"; rctx->response_code = MHD_HTTP_SERVICE_UNAVAILABLE; MHD_resume_connection (rctx->connection); return; } rctx->wdh = TALER_EXCHANGE_wire_deposits (rctx->eh, &rctx->wtid, &wire_deposit_cb, rctx); } /** * Manages a /track/wtid call, thus it calls the /track/deposit * offered by the exchange in order to return the set of deposits * (of coins) associated with a given wire transfer. * * @param rh context of the handler * @param connection the MHD connection to handle * @param[in,out] connection_cls the connection's closure (can be updated) * @param upload_data upload data * @param[in,out] upload_data_size number of bytes (left) in @a upload_data * @return MHD result code */ int MH_handler_track_deposit (struct TMH_RequestHandler *rh, struct MHD_Connection *connection, void **connection_cls, const char *upload_data, size_t *upload_data_size) { struct DepositTrackContext *rctx; const char *str; const char *uri; rctx = *connection_cls; if (NULL != rctx) { // ... } uri = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "exchange"); if (NULL == uri) return TMH_RESPONSE_reply_external_error (connection, "exchange argument missing"); str = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "wtid"); if (NULL == str) return TMH_RESPONSE_reply_external_error (connection, "wtid argument missing"); if (GNUNET_OK != GNUNET_STRINGS_string_to_data (str, strlen (str), &rctx->wtid, sizeof (rctx->wtid))) return TMH_RESPONSE_reply_external_error (connection, "wtid argument malformed"); rctx->eh = TALER_EXCHANGE_connect (NULL /* FIXME */, uri, &cert_cb, rctx, TALER_EXCHANGE_OPTION_END); GNUNET_break (0); return MHD_NO; } /** * Handle a "/track/transaction" request. * * @param rh context of the handler * @param connection the MHD connection to handle * @param[in,out] connection_cls the connection's closure (can be updated) * @param upload_data upload data * @param[in,out] upload_data_size number of bytes (left) in @a upload_data * @return MHD result code */ int MH_handler_track_transaction (struct TMH_RequestHandler *rh, struct MHD_Connection *connection, void **connection_cls, const char *upload_data, size_t *upload_data_size) { unsigned long long transaction_id; const char *str; str = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "id"); if (NULL == str) return TMH_RESPONSE_reply_external_error (connection, "id argument missing"); if (1 != sscanf (str, "%llu", &transaction_id)) return TMH_RESPONSE_reply_external_error (connection, "id argument must be a number"); GNUNET_break (0); return MHD_NO; } /* end of taler-merchant-httpd_contract.c */