commit 7afcc8275c0e8e19ceeb178bca21c7988966cba5
parent cb930318e14b314288d762d690b69ff86e7ee466
Author: Christian Grothoff <christian@grothoff.org>
Date: Thu, 9 Jun 2016 19:36:24 +0200
skeleton for /track/transfer and /track/transaction, renaming to match latest exchange API
Diffstat:
13 files changed, 1077 insertions(+), 835 deletions(-)
diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am
@@ -21,8 +21,8 @@ taler_merchant_httpd_SOURCES = \
taler-merchant-httpd_exchanges.c taler-merchant-httpd_exchanges.h \
taler-merchant-httpd_contract.c taler-merchant-httpd_contract.h \
taler-merchant-httpd_pay.c taler-merchant-httpd_pay.h \
- taler-merchant-httpd_track-deposit.c taler-merchant-httpd_track-deposit.h \
- taler-merchant-httpd_track-transaction.c taler-merchant-httpd_track-transaction.h
+ taler-merchant-httpd_track-transaction.c taler-merchant-httpd_track-transaction.h \
+ taler-merchant-httpd_track-transfer.c taler-merchant-httpd_track-transfer.h
taler_merchant_httpd_LDADD = \
diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c
@@ -37,8 +37,8 @@
#include "taler-merchant-httpd_exchanges.h"
#include "taler-merchant-httpd_contract.h"
#include "taler-merchant-httpd_pay.h"
-#include "taler-merchant-httpd_track-deposit.h"
#include "taler-merchant-httpd_track-transaction.h"
+#include "taler-merchant-httpd_track-transfer.h"
/**
@@ -188,10 +188,10 @@ url_handler (void *cls,
{ "/pay", NULL, "text/plain",
"Only POST is allowed", 0,
&TMH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
- { "/track/deposit", MHD_HTTP_METHOD_GET, "application/json",
+ { "/track/transfer", MHD_HTTP_METHOD_GET, "application/json",
NULL, 0,
- &MH_handler_track_deposit, MHD_HTTP_OK},
- { "/track/deposit", NULL, "text/plain",
+ &MH_handler_track_transfer, MHD_HTTP_OK},
+ { "/track/transfer", NULL, "text/plain",
"Only GET is allowed", 0,
&TMH_MHD_handler_static_response, MHD_HTTP_OK},
{ "/track/transaction", MHD_HTTP_METHOD_GET, "application/json",
diff --git a/src/backend/taler-merchant-httpd_track-deposit.c b/src/backend/taler-merchant-httpd_track-deposit.c
@@ -1,520 +0,0 @@
-/*
- 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 <http://www.gnu.org/licenses/>
-*/
-/**
- * @file backend/taler-merchant-httpd_track-deposit.c
- * @brief implement API for tracking deposits and wire transfers
- * @author Marcello Stanisci
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <jansson.h>
-#include <taler/taler_signatures.h>
-#include <taler/taler_json_lib.h>
-#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-deposit.h"
-
-
-/**
- * How long to wait before giving up processing with the exchange?
- */
-#define TRACK_TIMEOUT (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30))
-
-
-/**
- * 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;
-
- /**
- * HTTP connection we are handling.
- */
- struct MHD_Connection *connection;
-
- /**
- * Response to return upon resume.
- */
- struct MHD_Response *response;
-
- /**
- * Handle for operation to lookup /keys (and auditors) from
- * the exchange used for this transaction; NULL if no operation is
- * pending.
- */
- struct TMH_EXCHANGES_FindOperation *fo;
-
- /**
- * Task run on timeout.
- */
- struct GNUNET_SCHEDULER_Task *timeout_task;
-
- /**
- * URI of the exchange.
- */
- char *uri;
-
- /**
- * Pointer to the detail that we are currently
- * checking in #check_deposit().
- */
- const struct TALER_WireDepositDetails *current_detail;
-
- /**
- * Argument for the /wire/deposits request.
- */
- struct TALER_WireTransferIdentifierRawP wtid;
-
- /**
- * Response code to return.
- */
- unsigned int response_code;
-
- /**
- * #GNUNET_NO if we did not find a matching coin.
- * #GNUNET_SYSERR if we found a matching coin, but the amounts do not match.
- * #GNUNET_OK if we did find a matching coin.
- */
- int check_deposit_result;
-};
-
-
-/**
- * Free the @a rctx.
- *
- * @param rctx data to free
- */
-static void
-free_deposit_track_context (struct DepositTrackContext *rctx)
-{
- if (NULL != rctx->fo)
- {
- TMH_EXCHANGES_find_exchange_cancel (rctx->fo);
- rctx->fo = NULL;
- }
- if (NULL != rctx->timeout_task)
- {
- GNUNET_SCHEDULER_cancel (rctx->timeout_task);
- rctx->timeout_task = NULL;
- }
- if (NULL != rctx->wdh)
- {
- TALER_EXCHANGE_wire_deposits_cancel (rctx->wdh);
- rctx->wdh = NULL;
- }
- if (NULL != rctx->uri)
- {
- GNUNET_free (rctx->uri);
- rctx->uri = NULL;
- }
- GNUNET_free (rctx);
-}
-
-
-/**
- * Resume the given /track/deposit operation and send the given response.
- * Stores the response in the @a rctx and signals MHD to resume
- * the connection. Also ensures MHD runs immediately.
- *
- * @param rctx deposit tracking context
- * @param response_code response code to use
- * @param response response data to send back
- */
-static void
-resume_track_deposit_with_response (struct DepositTrackContext *rctx,
- unsigned int response_code,
- struct MHD_Response *response)
-{
- rctx->response_code = response_code;
- rctx->response = response;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Resuming /track/transaction handling as exchange interaction is done (%u)\n",
- response_code);
- if (NULL != rctx->timeout_task)
- {
- GNUNET_SCHEDULER_cancel (rctx->timeout_task);
- rctx->timeout_task = NULL;
- }
- MHD_resume_connection (rctx->connection);
- TMH_trigger_daemon (); /* we resumed, kick MHD */
-}
-
-
-/**
- * Custom cleanup routine for a `struct DepositTrackContext`.
- *
- * @param hc the `struct DepositTrackContext` to clean up.
- */
-static void
-track_deposit_cleanup (struct TM_HandlerContext *hc)
-{
- struct DepositTrackContext *rctx = (struct DepositTrackContext *) hc;
-
- free_deposit_track_context (rctx);
-}
-
-
-/**
- * Function called with information about a coin that was deposited.
- * Verify that it matches the information claimed by the exchange.
- * Update the `check_deposit_result` field accordingly.
- *
- * @param cls closure with our `struct DepositTrackContext *`
- * @param transaction_id of the contract
- * @param coin_pub public key of the coin
- * @param amount_with_fee amount the exchange will deposit for this coin
- * @param deposit_fee fee the exchange will charge for this coin
- * @param exchange_proof proof from exchange that coin was accepted
- */
-static void
-check_deposit (void *cls,
- uint64_t transaction_id,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- const struct TALER_Amount *amount_with_fee,
- const struct TALER_Amount *deposit_fee,
- const json_t *exchange_proof)
-{
- struct DepositTrackContext *rctx = cls;
- const struct TALER_WireDepositDetails *wdd = rctx->current_detail;
-
- if (0 != memcmp (&wdd->coin_pub,
- coin_pub,
- sizeof (struct TALER_CoinSpendPublicKeyP)))
- return; /* not the coin we're looking for */
- if ( (0 != TALER_amount_cmp (amount_with_fee,
- &wdd->coin_value)) ||
- (0 != TALER_amount_cmp (deposit_fee,
- &wdd->coin_fee)) )
- {
- /* Disagreement between the exchange and us about how much this
- coin is worth! */
- GNUNET_break_op (0);
- rctx->check_deposit_result = GNUNET_SYSERR;
- return;
- }
- rctx->check_deposit_result = GNUNET_OK;
-}
-
-
-/**
- * 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 exchange_pub public key of the exchange used to sign @a json
- * @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 struct TALER_ExchangePublicKeyP *exchange_pub,
- 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;
- int ret;
-
- rctx->wdh = NULL;
- if (MHD_HTTP_OK != http_status)
- {
- resume_track_deposit_with_response
- (rctx,
- MHD_HTTP_FAILED_DEPENDENCY,
- TMH_RESPONSE_make_json_pack ("{s:I, s:O}",
- "exchange_status", (json_int_t) http_status,
- "details", json));
- return;
- }
-
- if (GNUNET_OK !=
- db->store_transfer_to_proof (db->cls,
- rctx->uri,
- &rctx->wtid,
- exchange_pub,
- json))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to persist wire transfer proof in DB\n");
- }
-
- for (i=0;i<details_length;i++)
- {
- rctx->current_detail = &details[i];
- rctx->check_deposit_result = GNUNET_NO;
- ret = db->find_payments_by_id (rctx,
- details[i].transaction_id,
- &check_deposit,
- rctx);
- if (GNUNET_SYSERR == ret)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to verify existing payment data in DB\n");
- }
- if ( (GNUNET_NO == ret) ||
- (GNUNET_NO == rctx->check_deposit_result) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to find payment data in DB\n");
- }
- if (GNUNET_SYSERR == rctx->check_deposit_result)
- {
- /* #check_deposit() failed, do something! */
- GNUNET_break (0);
- /* FIXME: generate nicer custom response */
- resume_track_deposit_with_response
- (rctx,
- MHD_HTTP_FAILED_DEPENDENCY,
- TMH_RESPONSE_make_json_pack ("{s:I, s:O}",
- "index", (json_int_t) i,
- "details", json));
- return;
- }
- ret = db->store_coin_to_transfer (db->cls,
- details[i].transaction_id,
- &details[i].coin_pub,
- &rctx->wtid);
- if (GNUNET_OK != ret)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to persist coin to wire transfer mapping in DB\n");
- }
- }
- /* FIXME: might want a more custom response here... */
- resume_track_deposit_with_response
- (rctx,
- MHD_HTTP_OK,
- TMH_RESPONSE_make_json_pack ("{s:I, s:O}",
- "exchange_status", (json_int_t) http_status,
- "details", json));
-}
-
-
-/**
- * Function called with the result of our exchange lookup.
- *
- * @param cls the `struct DepositTrackContext`
- * @param eh NULL if exchange was not found to be acceptable
- * @param exchange_trusted #GNUNET_YES if this exchange is trusted by config
- */
-static void
-process_track_deposit_with_exchange (void *cls,
- struct TALER_EXCHANGE_Handle *eh,
- int exchange_trusted)
-{
- struct DepositTrackContext *rctx = cls;
-
- rctx->fo = NULL;
- rctx->eh = eh;
- rctx->wdh = TALER_EXCHANGE_wire_deposits (eh,
- &rctx->wtid,
- &wire_deposit_cb,
- rctx);
-}
-
-
-/**
- * Handle a timeout for the processing of the track deposit request.
- *
- * @param cls closure
- */
-static void
-handle_track_deposit_timeout (void *cls)
-{
- struct DepositTrackContext *rctx = cls;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Resuming /track/deposit with error after timeout\n");
- rctx->timeout_task = NULL;
-
- if (NULL != rctx->fo)
- {
- TMH_EXCHANGES_find_exchange_cancel (rctx->fo);
- rctx->fo = NULL;
- }
- resume_track_deposit_with_response (rctx,
- MHD_HTTP_SERVICE_UNAVAILABLE,
- TMH_RESPONSE_make_internal_error ("exchange not reachable"));
-}
-
-
-/**
- * Function called with information about a wire transfer identifier.
- * Generate a response based on the given @a proof.
- *
- * @param cls closure
- * @param proof proof from exchange about what the wire transfer was for
- */
-static void
-proof_cb (void *cls,
- const json_t *proof)
-{
- struct DepositTrackContext *rctx = cls;
-
- rctx->response_code = MHD_HTTP_OK;
- /* FIXME: might want a more custom response here... */
- rctx->response = TMH_RESPONSE_make_json_pack ("{s:I, s:O}",
- "exchange_status", (json_int_t) MHD_HTTP_OK,
- "details", proof);
-}
-
-
-/**
- * Manages a /track/deposit call, thus it calls the /track/wtid
- * 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;
- int ret;
-
- if (NULL == *connection_cls)
- {
- rctx = GNUNET_new (struct DepositTrackContext);
- rctx->hc.cc = &track_deposit_cleanup;
- rctx->connection = connection;
- *connection_cls = rctx;
- }
- else
- {
- /* not first call, recover state */
- rctx = *connection_cls;
- }
-
- if (0 != rctx->response_code)
- {
- /* We are *done* processing the request, just queue the response (!) */
- if (UINT_MAX == rctx->response_code)
- {
- GNUNET_break (0);
- return MHD_NO; /* hard error */
- }
- ret = MHD_queue_response (connection,
- rctx->response_code,
- rctx->response);
- if (NULL != rctx->response)
- {
- MHD_destroy_response (rctx->response);
- rctx->response = NULL;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Queueing response (%u) for /track/deposit (%s).\n",
- (unsigned int) rctx->response_code,
- ret ? "OK" : "FAILED");
- return ret;
- }
-
- uri = MHD_lookup_connection_value (connection,
- MHD_GET_ARGUMENT_KIND,
- "exchange");
- if (NULL == uri)
- return TMH_RESPONSE_reply_bad_request (connection,
- "exchange argument missing");
- rctx->uri = GNUNET_strdup (uri);
-
- str = MHD_lookup_connection_value (connection,
- MHD_GET_ARGUMENT_KIND,
- "wtid");
- if (NULL == str)
- return TMH_RESPONSE_reply_bad_request (connection,
- "wtid argument missing");
- if (GNUNET_OK !=
- GNUNET_STRINGS_string_to_data (str,
- strlen (str),
- &rctx->wtid,
- sizeof (rctx->wtid)))
- {
- return TMH_RESPONSE_reply_bad_request (connection,
- "wtid argument malformed");
- }
-
- /* Check if reply is already in database! */
- ret = db->find_proof_by_wtid (db->cls,
- rctx->uri,
- &rctx->wtid,
- &proof_cb,
- rctx);
- if (0 != rctx->response_code)
- {
- ret = MHD_queue_response (connection,
- rctx->response_code,
- rctx->response);
- if (NULL != rctx->response)
- {
- MHD_destroy_response (rctx->response);
- rctx->response = NULL;
- }
- return ret;
- }
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Suspending /track/deposit handling while working with the exchange\n");
- MHD_suspend_connection (connection);
- rctx->fo = TMH_EXCHANGES_find_exchange (uri,
- &process_track_deposit_with_exchange,
- rctx);
- rctx->timeout_task = GNUNET_SCHEDULER_add_delayed (TRACK_TIMEOUT,
- &handle_track_deposit_timeout,
- rctx);
- return MHD_NO;
-}
-
-/* end of taler-merchant-httpd_track-deposit.c */
diff --git a/src/backend/taler-merchant-httpd_track-deposit.h b/src/backend/taler-merchant-httpd_track-deposit.h
@@ -1,47 +0,0 @@
-/*
- This file is part of TALER
- (C) 2014, 2015 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU 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 <http://www.gnu.org/licenses/>
-*/
-/**
- * @file backend/taler-merchant-httpd_track-deposit.h
- * @brief headers for /track/deposit handler
- * @author Christian Grothoff
- * @author Marcello Stanisci
- */
-#ifndef TALER_MERCHANT_HTTPD_TRACK_DEPOSIT_H
-#define TALER_MERCHANT_HTTPD_TRACK_DEPOSIT_H
-#include <microhttpd.h>
-#include "taler-merchant-httpd.h"
-
-/**
- * Manages a /track/deposit call, thus it calls the /wire/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);
-
-
-#endif
diff --git a/src/backend/taler-merchant-httpd_track-transaction.c b/src/backend/taler-merchant-httpd_track-transaction.c
@@ -72,7 +72,7 @@ struct TrackCoinContext
/**
* Handle for the request to resolve the WTID for this coin.
*/
- struct TALER_EXCHANGE_DepositWtidHandle *dwh;
+ struct TALER_EXCHANGE_TrackTransactionHandle *dwh;
/**
* Wire transfer identifier for this coin.
@@ -138,7 +138,7 @@ struct TrackTransactionContext
/**
* Handle we use to resolve transactions for a given WTID.
*/
- struct TALER_EXCHANGE_WireDepositsHandle *wdh;
+ struct TALER_EXCHANGE_TrackTransferHandle *wdh;
/**
* Response to return upon resume.
@@ -205,14 +205,14 @@ free_tctx (struct TrackTransactionContext *tctx)
tcc);
if (NULL != tcc->dwh)
{
- TALER_EXCHANGE_deposit_wtid_cancel (tcc->dwh);
+ TALER_EXCHANGE_track_transaction_cancel (tcc->dwh);
tcc->dwh = NULL;
}
GNUNET_free (tcc);
}
if (NULL != tctx->wdh)
{
- TALER_EXCHANGE_wire_deposits_cancel (tctx->wdh);
+ TALER_EXCHANGE_track_transfer_cancel (tctx->wdh);
tctx->wdh = NULL;
}
if (NULL != tctx->fo)
@@ -315,7 +315,7 @@ wire_deposits_cb (void *cls,
const struct GNUNET_HashCode *h_wire,
const struct TALER_Amount *total_amount,
unsigned int details_length,
- const struct TALER_WireDepositDetails *details)
+ const struct TALER_TrackTransferDetails *details)
{
struct TrackTransactionContext *tctx = cls;
struct TrackCoinContext *tcc;
@@ -403,7 +403,7 @@ wtid_cb (void *cls,
tcc->dwh = NULL;
tctx->current_wtid = *wtid;
- tctx->wdh = TALER_EXCHANGE_wire_deposits (tctx->eh,
+ tctx->wdh = TALER_EXCHANGE_track_transfer (tctx->eh,
wtid,
&wire_deposits_cb,
tctx);
@@ -436,14 +436,14 @@ trace_coins (struct TrackTransactionContext *tctx)
#endif
return;
}
- tcc->dwh = TALER_EXCHANGE_deposit_wtid (tctx->eh,
- &privkey,
- &tctx->h_wire,
- &tctx->h_contract,
- &tcc->coin_pub,
- tctx->transaction_id,
- &wtid_cb,
- tcc);
+ tcc->dwh = TALER_EXCHANGE_track_transaction (tctx->eh,
+ &privkey,
+ &tctx->h_wire,
+ &tctx->h_contract,
+ &tcc->coin_pub,
+ tctx->transaction_id,
+ &wtid_cb,
+ tcc);
}
diff --git a/src/backend/taler-merchant-httpd_track-transfer.c b/src/backend/taler-merchant-httpd_track-transfer.c
@@ -0,0 +1,521 @@
+/*
+ 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 <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file backend/taler-merchant-httpd_track-transfer.c
+ * @brief implement API for tracking transfers and wire transfers
+ * @author Marcello Stanisci
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <jansson.h>
+#include <taler/taler_signatures.h>
+#include <taler/taler_json_lib.h>
+#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-transfer.h"
+
+
+/**
+ * How long to wait before giving up processing with the exchange?
+ */
+#define TRACK_TIMEOUT (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30))
+
+
+/**
+ * Context used for handing /track/transfer requests.
+ */
+struct TransferTrackContext
+{
+
+ /**
+ * This MUST be first!
+ */
+ struct TM_HandlerContext hc;
+
+ /**
+ * Handle to the exchange.
+ */
+ struct TALER_EXCHANGE_Handle *eh;
+
+ /**
+ * Handle for the /wire/transfers request.
+ */
+ struct TALER_EXCHANGE_TrackTransferHandle *wdh;
+
+ /**
+ * HTTP connection we are handling.
+ */
+ struct MHD_Connection *connection;
+
+ /**
+ * Response to return upon resume.
+ */
+ struct MHD_Response *response;
+
+ /**
+ * Handle for operation to lookup /keys (and auditors) from
+ * the exchange used for this transaction; NULL if no operation is
+ * pending.
+ */
+ struct TMH_EXCHANGES_FindOperation *fo;
+
+ /**
+ * Task run on timeout.
+ */
+ struct GNUNET_SCHEDULER_Task *timeout_task;
+
+ /**
+ * URI of the exchange.
+ */
+ char *uri;
+
+ /**
+ * Pointer to the detail that we are currently
+ * checking in #check_transfer().
+ */
+ const struct TALER_TrackTransferDetails *current_detail;
+
+ /**
+ * Argument for the /wire/transfers request.
+ */
+ struct TALER_WireTransferIdentifierRawP wtid;
+
+ /**
+ * Response code to return.
+ */
+ unsigned int response_code;
+
+ /**
+ * #GNUNET_NO if we did not find a matching coin.
+ * #GNUNET_SYSERR if we found a matching coin, but the amounts do not match.
+ * #GNUNET_OK if we did find a matching coin.
+ */
+ int check_transfer_result;
+};
+
+
+/**
+ * Free the @a rctx.
+ *
+ * @param rctx data to free
+ */
+static void
+free_transfer_track_context (struct TransferTrackContext *rctx)
+{
+ if (NULL != rctx->fo)
+ {
+ TMH_EXCHANGES_find_exchange_cancel (rctx->fo);
+ rctx->fo = NULL;
+ }
+ if (NULL != rctx->timeout_task)
+ {
+ GNUNET_SCHEDULER_cancel (rctx->timeout_task);
+ rctx->timeout_task = NULL;
+ }
+ if (NULL != rctx->wdh)
+ {
+ TALER_EXCHANGE_track_transfer_cancel (rctx->wdh);
+ rctx->wdh = NULL;
+ }
+ if (NULL != rctx->uri)
+ {
+ GNUNET_free (rctx->uri);
+ rctx->uri = NULL;
+ }
+ GNUNET_free (rctx);
+}
+
+
+/**
+ * Resume the given /track/transfer operation and send the given response.
+ * Stores the response in the @a rctx and signals MHD to resume
+ * the connection. Also ensures MHD runs immediately.
+ *
+ * @param rctx transfer tracking context
+ * @param response_code response code to use
+ * @param response response data to send back
+ */
+static void
+resume_track_transfer_with_response (struct TransferTrackContext *rctx,
+ unsigned int response_code,
+ struct MHD_Response *response)
+{
+ rctx->response_code = response_code;
+ rctx->response = response;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Resuming /track/transaction handling as exchange interaction is done (%u)\n",
+ response_code);
+ if (NULL != rctx->timeout_task)
+ {
+ GNUNET_SCHEDULER_cancel (rctx->timeout_task);
+ rctx->timeout_task = NULL;
+ }
+ MHD_resume_connection (rctx->connection);
+ TMH_trigger_daemon (); /* we resumed, kick MHD */
+}
+
+
+/**
+ * Custom cleanup routine for a `struct TransferTrackContext`.
+ *
+ * @param hc the `struct TransferTrackContext` to clean up.
+ */
+static void
+track_transfer_cleanup (struct TM_HandlerContext *hc)
+{
+ struct TransferTrackContext *rctx = (struct TransferTrackContext *) hc;
+
+ free_transfer_track_context (rctx);
+}
+
+
+/**
+ * Function called with information about a coin that was transfered.
+ * Verify that it matches the information claimed by the exchange.
+ * Update the `check_transfer_result` field accordingly.
+ *
+ * @param cls closure with our `struct TransferTrackContext *`
+ * @param transaction_id of the contract
+ * @param coin_pub public key of the coin
+ * @param amount_with_fee amount the exchange will transfer for this coin
+ * @param transfer_fee fee the exchange will charge for this coin
+ * @param exchange_proof proof from exchange that coin was accepted
+ */
+static void
+check_transfer (void *cls,
+ uint64_t transaction_id,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const struct TALER_Amount *amount_with_fee,
+ const struct TALER_Amount *transfer_fee,
+ const json_t *exchange_proof)
+{
+ struct TransferTrackContext *rctx = cls;
+ const struct TALER_TrackTransferDetails *wdd = rctx->current_detail;
+
+ if (0 != memcmp (&wdd->coin_pub,
+ coin_pub,
+ sizeof (struct TALER_CoinSpendPublicKeyP)))
+ return; /* not the coin we're looking for */
+ if ( (0 != TALER_amount_cmp (amount_with_fee,
+ &wdd->coin_value)) ||
+ (0 != TALER_amount_cmp (transfer_fee,
+ &wdd->coin_fee)) )
+ {
+ /* Disagreement between the exchange and us about how much this
+ coin is worth! */
+ GNUNET_break_op (0);
+ rctx->check_transfer_result = GNUNET_SYSERR;
+ return;
+ }
+ rctx->check_transfer_result = GNUNET_OK;
+}
+
+
+/**
+ * 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 exchange_pub public key of the exchange used to sign @a json
+ * @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_transfer_cb (void *cls,
+ unsigned int http_status,
+ const struct TALER_ExchangePublicKeyP *exchange_pub,
+ const json_t *json,
+ const struct GNUNET_HashCode *h_wire,
+ const struct TALER_Amount *total_amount,
+ unsigned int details_length,
+ const struct TALER_TrackTransferDetails *details)
+{
+ struct TransferTrackContext *rctx = cls;
+ unsigned int i;
+ int ret;
+
+ rctx->wdh = NULL;
+ if (MHD_HTTP_OK != http_status)
+ {
+ resume_track_transfer_with_response
+ (rctx,
+ MHD_HTTP_FAILED_DEPENDENCY,
+ TMH_RESPONSE_make_json_pack ("{s:I, s:O}",
+ "exchange_status", (json_int_t) http_status,
+ "details", json));
+ return;
+ }
+
+ if (GNUNET_OK !=
+ db->store_transfer_to_proof (db->cls,
+ rctx->uri,
+ &rctx->wtid,
+ exchange_pub,
+ json))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to persist wire transfer proof in DB\n");
+ }
+
+ for (i=0;i<details_length;i++)
+ {
+ rctx->current_detail = &details[i];
+ rctx->check_transfer_result = GNUNET_NO;
+ ret = db->find_payments_by_id (rctx,
+ details[i].transaction_id,
+ &check_transfer,
+ rctx);
+ if (GNUNET_SYSERR == ret)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to verify existing payment data in DB\n");
+ }
+ if ( (GNUNET_NO == ret) ||
+ (GNUNET_NO == rctx->check_transfer_result) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to find payment data in DB\n");
+ }
+ if (GNUNET_SYSERR == rctx->check_transfer_result)
+ {
+ /* #check_transfer() failed, do something! */
+ GNUNET_break (0);
+ /* FIXME: generate nicer custom response */
+ resume_track_transfer_with_response
+ (rctx,
+ MHD_HTTP_FAILED_DEPENDENCY,
+ TMH_RESPONSE_make_json_pack ("{s:I, s:O}",
+ "index", (json_int_t) i,
+ "details", json));
+ return;
+ }
+ ret = db->store_coin_to_transfer (db->cls,
+ details[i].transaction_id,
+ &details[i].coin_pub,
+ &rctx->wtid);
+ if (GNUNET_OK != ret)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to persist coin to wire transfer mapping in DB\n");
+ }
+ }
+ /* FIXME: might want a more custom response here... */
+ resume_track_transfer_with_response
+ (rctx,
+ MHD_HTTP_OK,
+ TMH_RESPONSE_make_json_pack ("{s:I, s:O}",
+ "exchange_status", (json_int_t) http_status,
+ "details", json));
+}
+
+
+/**
+ * Function called with the result of our exchange lookup.
+ *
+ * @param cls the `struct TransferTrackContext`
+ * @param eh NULL if exchange was not found to be acceptable
+ * @param exchange_trusted #GNUNET_YES if this exchange is trusted by config
+ */
+static void
+process_track_transfer_with_exchange (void *cls,
+ struct TALER_EXCHANGE_Handle *eh,
+ int exchange_trusted)
+{
+ struct TransferTrackContext *rctx = cls;
+
+ rctx->fo = NULL;
+ rctx->eh = eh;
+ rctx->wdh = TALER_EXCHANGE_track_transfer (eh,
+ &rctx->wtid,
+ &wire_transfer_cb,
+ rctx);
+}
+
+
+/**
+ * Handle a timeout for the processing of the track transfer request.
+ *
+ * @param cls closure
+ */
+static void
+handle_track_transfer_timeout (void *cls)
+{
+ struct TransferTrackContext *rctx = cls;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Resuming /track/transfer with error after timeout\n");
+ rctx->timeout_task = NULL;
+
+ if (NULL != rctx->fo)
+ {
+ TMH_EXCHANGES_find_exchange_cancel (rctx->fo);
+ rctx->fo = NULL;
+ }
+ resume_track_transfer_with_response (rctx,
+ MHD_HTTP_SERVICE_UNAVAILABLE,
+ TMH_RESPONSE_make_internal_error ("exchange not reachable"));
+}
+
+
+/**
+ * Function called with information about a wire transfer identifier.
+ * Generate a response based on the given @a proof.
+ *
+ * @param cls closure
+ * @param proof proof from exchange about what the wire transfer was for
+ */
+static void
+proof_cb (void *cls,
+ const json_t *proof)
+{
+ struct TransferTrackContext *rctx = cls;
+
+ rctx->response_code = MHD_HTTP_OK;
+ /* FIXME: might want a more custom response here... */
+ rctx->response = TMH_RESPONSE_make_json_pack ("{s:I, s:O}",
+ "exchange_status", (json_int_t) MHD_HTTP_OK,
+ "details", proof);
+}
+
+
+/**
+ * Manages a /track/transfer call, thus it calls the /track/wtid
+ * offered by the exchange in order to return the set of transfers
+ * (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_transfer (struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ void **connection_cls,
+ const char *upload_data,
+ size_t *upload_data_size)
+{
+ struct TransferTrackContext *rctx;
+ const char *str;
+ const char *uri;
+ int ret;
+
+ if (NULL == *connection_cls)
+ {
+ rctx = GNUNET_new (struct TransferTrackContext);
+ rctx->hc.cc = &track_transfer_cleanup;
+ rctx->connection = connection;
+ *connection_cls = rctx;
+ }
+ else
+ {
+ /* not first call, recover state */
+ rctx = *connection_cls;
+ }
+
+ if (0 != rctx->response_code)
+ {
+ /* We are *done* processing the request, just queue the response (!) */
+ if (UINT_MAX == rctx->response_code)
+ {
+ GNUNET_break (0);
+ return MHD_NO; /* hard error */
+ }
+ ret = MHD_queue_response (connection,
+ rctx->response_code,
+ rctx->response);
+ if (NULL != rctx->response)
+ {
+ MHD_destroy_response (rctx->response);
+ rctx->response = NULL;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Queueing response (%u) for /track/transfer (%s).\n",
+ (unsigned int) rctx->response_code,
+ ret ? "OK" : "FAILED");
+ return ret;
+ }
+
+ uri = MHD_lookup_connection_value (connection,
+ MHD_GET_ARGUMENT_KIND,
+ "exchange");
+ if (NULL == uri)
+ return TMH_RESPONSE_reply_bad_request (connection,
+ "exchange argument missing");
+ rctx->uri = GNUNET_strdup (uri);
+
+ str = MHD_lookup_connection_value (connection,
+ MHD_GET_ARGUMENT_KIND,
+ "wtid");
+ if (NULL == str)
+ return TMH_RESPONSE_reply_bad_request (connection,
+ "wtid argument missing");
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (str,
+ strlen (str),
+ &rctx->wtid,
+ sizeof (rctx->wtid)))
+ {
+ return TMH_RESPONSE_reply_bad_request (connection,
+ "wtid argument malformed");
+ }
+
+ /* Check if reply is already in database! */
+ ret = db->find_proof_by_wtid (db->cls,
+ rctx->uri,
+ &rctx->wtid,
+ &proof_cb,
+ rctx);
+ if (0 != rctx->response_code)
+ {
+ ret = MHD_queue_response (connection,
+ rctx->response_code,
+ rctx->response);
+ if (NULL != rctx->response)
+ {
+ MHD_destroy_response (rctx->response);
+ rctx->response = NULL;
+ }
+ return ret;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Suspending /track/transfer handling while working with the exchange\n");
+ MHD_suspend_connection (connection);
+ rctx->fo = TMH_EXCHANGES_find_exchange (uri,
+ &process_track_transfer_with_exchange,
+ rctx);
+ rctx->timeout_task
+ = GNUNET_SCHEDULER_add_delayed (TRACK_TIMEOUT,
+ &handle_track_transfer_timeout,
+ rctx);
+ return MHD_NO;
+}
+
+/* end of taler-merchant-httpd_track-transfer.c */
diff --git a/src/backend/taler-merchant-httpd_track-transfer.h b/src/backend/taler-merchant-httpd_track-transfer.h
@@ -0,0 +1,47 @@
+/*
+ This file is part of TALER
+ (C) 2014, 2015 GNUnet e.V.
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU 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 <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file backend/taler-merchant-httpd_track-transfer.h
+ * @brief headers for /track/transfer handler
+ * @author Christian Grothoff
+ * @author Marcello Stanisci
+ */
+#ifndef TALER_MERCHANT_HTTPD_TRACK_TRANSFER_H
+#define TALER_MERCHANT_HTTPD_TRACK_TRANSFER_H
+#include <microhttpd.h>
+#include "taler-merchant-httpd.h"
+
+/**
+ * Manages a /track/transfer call, thus it calls the /wire/transfer
+ * offered by the exchange in order to return the set of transfers
+ * (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_transfer (struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ void **connection_cls,
+ const char *upload_data,
+ size_t *upload_data_size);
+
+
+#endif
diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h
@@ -26,49 +26,6 @@
#include <gnunet/gnunet_curl_lib.h>
#include <jansson.h>
-/* ********************* /track/deposit *********************** */
-
-/**
- * @brief Handle to a /contract operation at a merchant's backend.
- */
-struct TALER_MERCHANT_TrackDepositOperation;
-
-/**
- * Callbacks of this type are used to work the result of submitting a /track/deposit request to a merchant
- */
-typedef void
-(*TALER_MERCHANT_TrackDepositCallback) (void *cls,
- unsigned int http_status,
- const json_t *obj);
-
-/**
- * Request backend to return deposits associated with a given wtid.
- *
- * @param ctx execution context
- * @param backend_uri URI of the backend (having /track/deposit appended)
- * @param wtid base32 string indicating a wtid
- * @param exchange base URL of the exchange in charge of returning the wanted information
- * @param trackdeposit_cb the callback to call when a reply for this request is available
- * @param trackdeposit_cb_cls closure for @a contract_cb
- * @return a handle for this request
- */
-struct TALER_MERCHANT_TrackDepositOperation *
-TALER_MERCHANT_track_deposit (struct GNUNET_CURL_Context *ctx,
- const char *backend_uri,
- const struct TALER_WireTransferIdentifierRawP *wtid,
- const char *exchange_uri,
- TALER_MERCHANT_TrackDepositCallback trackdeposit_cb,
- void *trackdeposit_cb_cls);
-
-
-/**
- * Cancel a /track/deposit request. This function cannot be used
- * on a request handle if a response is already served for it.
- *
- * @param co the deposit's tracking operation
- */
-void
-TALER_MERCHANT_track_deposit_cancel (struct TALER_MERCHANT_TrackDepositOperation *tdo);
/* ********************* /contract *********************** */
@@ -340,5 +297,94 @@ void
TALER_MERCHANT_pay_cancel (struct TALER_MERCHANT_Pay *ph);
+/* ********************* /track/transfer *********************** */
+
+/**
+ * @brief Handle to a /contract operation at a merchant's backend.
+ */
+struct TALER_MERCHANT_TrackTransferHandle;
+
+/**
+ * Callbacks of this type are used to work the result of submitting a /track/transfer request to a merchant
+ */
+typedef void
+(*TALER_MERCHANT_TrackTransferCallback) (void *cls,
+ unsigned int http_status,
+ const json_t *obj);
+
+/**
+ * Request backend to return deposits associated with a given wtid.
+ *
+ * @param ctx execution context
+ * @param backend_uri URI of the backend (having /track/transfer appended)
+ * @param wtid base32 string indicating a wtid
+ * @param exchange base URL of the exchange in charge of returning the wanted information
+ * @param track_transfer_cb the callback to call when a reply for this request is available
+ * @param track_transfer_cb_cls closure for @a track_transfer_cb
+ * @return a handle for this request
+ */
+struct TALER_MERCHANT_TrackTransferHandle *
+TALER_MERCHANT_track_transfer (struct GNUNET_CURL_Context *ctx,
+ const char *backend_uri,
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ const char *exchange_uri,
+ TALER_MERCHANT_TrackTransferCallback track_transfer_cb,
+ void *track_transfer_cb_cls);
+
+
+/**
+ * Cancel a /track/transfer request. This function cannot be used
+ * on a request handle if a response is already served for it.
+ *
+ * @param co the deposit's tracking operation
+ */
+void
+TALER_MERCHANT_track_transfer_cancel (struct TALER_MERCHANT_TrackTransferHandle *tdo);
+
+
+/* ********************* /track/transaction *********************** */
+
+/**
+ * @brief Handle to a /contract operation at a merchant's backend.
+ */
+struct TALER_MERCHANT_TrackTransactionHandle;
+
+/**
+ * Callbacks of this type are used to work the result of submitting a /track/transaction request to a merchant
+ */
+typedef void
+(*TALER_MERCHANT_TrackTransactionCallback) (void *cls,
+ unsigned int http_status,
+ const json_t *obj);
+
+/**
+ * Request backend to return deposits associated with a given wtid.
+ *
+ * @param ctx execution context
+ * @param backend_uri URI of the backend (having /track/transaction appended)
+ * @param wtid base32 string indicating a wtid
+ * @param exchange base URL of the exchange in charge of returning the wanted information
+ * @param track_transaction_cb the callback to call when a reply for this request is available
+ * @param track_transaction_cb_cls closure for @a track_transaction_cb
+ * @return a handle for this request
+ */
+struct TALER_MERCHANT_TrackTransactionHandle *
+TALER_MERCHANT_track_transaction (struct GNUNET_CURL_Context *ctx,
+ const char *backend_uri,
+ uint64_t transaction_id,
+ const char *exchange_uri,
+ TALER_MERCHANT_TrackTransactionCallback track_transaction_cb,
+ void *track_transaction_cb_cls);
+
+
+/**
+ * Cancel a /track/transaction request. This function cannot be used
+ * on a request handle if a response is already served for it.
+ *
+ * @param co the deposit's tracking operation
+ */
+void
+TALER_MERCHANT_track_transaction_cancel (struct TALER_MERCHANT_TrackTransactionHandle *tdo);
+
#endif /* _TALER_MERCHANT_SERVICE_H */
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
@@ -16,7 +16,8 @@ libtalermerchant_la_LDFLAGS = \
libtalermerchant_la_SOURCES = \
merchant_api_contract.c \
merchant_api_pay.c \
- merchant_api_track.c
+ merchant_api_track_transaction.c \
+ merchant_api_track_transfer.c
libtalermerchant_la_LIBADD = \
-ltalerexchange \
diff --git a/src/lib/merchant_api_track.c b/src/lib/merchant_api_track.c
@@ -1,196 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014, 2015, 2016 GNUnet e.V. and INRIA
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU Lesser General Public License as published by the Free Software
- Foundation; either version 2.1, 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 Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License along with
- TALER; see the file COPYING.LGPL. If not, If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file lib/merchant_api_contract.c
- * @brief Implementation of the /track/deposit and /track/wtid request of the
- * merchant's HTTP API
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include <curl/curl.h>
-#include <jansson.h>
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_merchant_service.h"
-#include <taler/taler_json_lib.h>
-#include <taler/taler_signatures.h>
-
-
-/**
- * @brief A Contract Operation Handle
- */
-struct TALER_MERCHANT_TrackDepositOperation
-{
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * base32 identifier being the 'witd' parameter required by the
- * exchange
- */
- char *wtid;
-
- /**
- * Handle for the request.
- */
- struct GNUNET_CURL_Job *job;
-
- /**
- * Function to call with the result.
- */
- TALER_MERCHANT_TrackDepositCallback cb;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
- /**
- * Reference to the execution context.
- */
- struct GNUNET_CURL_Context *ctx;
-};
-
-
-/**
- * Function called when we're done processing the
- * HTTP /track/deposit request.
- *
- * @param cls the `struct TALER_MERCHANT_TrackDepositOperation`
- * @param response_code HTTP response code, 0 on error
- * @param json response body, NULL if not in JSON
- */
-static void
-handle_trackdeposit_finished (void *cls,
- long response_code,
- const json_t *json)
-{
- struct TALER_MERCHANT_TrackDepositOperation *tdo = cls;
-
- tdo->job = NULL;
- switch (response_code)
- {
- case 0:
- break;
- case MHD_HTTP_OK:
- {
- /* Work out argument for external callback from the body .. */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "200 returned from /track/deposit\n");
- /* FIXME: actually verify signature */
- }
- break;
- case MHD_HTTP_NOT_FOUND:
- /* Nothing really to verify, this should never
- happen, we should pass the JSON reply to the application */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "track deposit URI not found\n");
- break;
- case MHD_HTTP_INTERNAL_SERVER_ERROR:
- /* Server had an internal issue; we should retry, but this API
- leaves this to the application */
- break;
- default:
- /* unexpected response code */
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u\n",
- (unsigned int) response_code);
- GNUNET_break (0);
- response_code = 0;
- break;
- }
- /* FIXME: figure out which parameters ought to be passed back */
- tdo->cb (tdo->cb_cls,
- response_code,
- json);
-}
-
-
-/**
- * Request backend to return deposits associated with a given wtid.
- *
- * @param ctx execution context
- * @param backend_uri URI of the backend (having "/track/deposit" appended)
- * @param wtid base32 string indicating a wtid
- * @param exchange base URL of the exchange in charge of returning the wanted information
- * @param trackdeposit_cb the callback to call when a reply for this request is available
- * @param trackdeposit_cb_cls closure for @a contract_cb
- * @return a handle for this request
- */
-struct TALER_MERCHANT_TrackDepositOperation *
-TALER_MERCHANT_track_deposit (struct GNUNET_CURL_Context *ctx,
- const char *backend_uri,
- const struct TALER_WireTransferIdentifierRawP *wtid,
- const char *exchange_uri,
- TALER_MERCHANT_TrackDepositCallback trackdeposit_cb,
- void *trackdeposit_cb_cls)
-{
- struct TALER_MERCHANT_TrackDepositOperation *tdo;
- CURL *eh;
- char *wtid_str;
-
- wtid_str = GNUNET_STRINGS_data_to_string_alloc (wtid,
- sizeof (struct TALER_WireTransferIdentifierRawP));
- tdo = GNUNET_new (struct TALER_MERCHANT_TrackDepositOperation);
- tdo->ctx = ctx;
- tdo->cb = trackdeposit_cb;
- tdo->cb_cls = trackdeposit_cb_cls;
- /* URI gotten with /track/deposit already appended... */
- GNUNET_asprintf (&tdo->url,
- "%s?wtid=%s&exchange=%s",
- backend_uri,
- wtid_str,
- exchange_uri);
- GNUNET_free (wtid_str);
- eh = curl_easy_init ();
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_URL,
- tdo->url));
- tdo->job = GNUNET_CURL_job_add (ctx,
- eh,
- GNUNET_YES,
- &handle_trackdeposit_finished,
- tdo);
- return tdo;
-}
-
-
-/**
- * Cancel a /track/deposit request. This function cannot be used
- * on a request handle if a response is already served for it.
- *
- * @param co the deposit's tracking operation
- */
-void
-TALER_MERCHANT_track_deposit_cancel (struct TALER_MERCHANT_TrackDepositOperation *tdo)
-{
- if (NULL != tdo->job)
- {
- GNUNET_CURL_job_cancel (tdo->job);
- tdo->job = NULL;
- }
- GNUNET_free (tdo->url);
- GNUNET_free (tdo->wtid);
- GNUNET_free (tdo);
-}
-
-/* end of merchant_api_track.c */
diff --git a/src/lib/merchant_api_track_transaction.c b/src/lib/merchant_api_track_transaction.c
@@ -0,0 +1,193 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2014, 2015, 2016 GNUnet e.V. and INRIA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser General Public License as published by the Free Software
+ Foundation; either version 2.1, 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License along with
+ TALER; see the file COPYING.LGPL. If not, If not, see
+ <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file lib/merchant_api_track_transaction.c
+ * @brief Implementation of the /track/transaction request of the
+ * merchant's HTTP API
+ * @author Marcello Stanisci
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <curl/curl.h>
+#include <jansson.h>
+#include <microhttpd.h> /* just for HTTP status codes */
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_curl_lib.h>
+#include "taler_merchant_service.h"
+#include <taler/taler_json_lib.h>
+#include <taler/taler_signatures.h>
+
+
+/**
+ * @brief A handle for tracking transactions.
+ */
+struct TALER_MERCHANT_TrackTransactionHandle
+{
+
+ /**
+ * The url for this request.
+ */
+ char *url;
+
+ /**
+ * base32 identifier being the 'witd' parameter required by the
+ * exchange
+ */
+ char *wtid;
+
+ /**
+ * Handle for the request.
+ */
+ struct GNUNET_CURL_Job *job;
+
+ /**
+ * Function to call with the result.
+ */
+ TALER_MERCHANT_TrackTransactionCallback cb;
+
+ /**
+ * Closure for @a cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Reference to the execution context.
+ */
+ struct GNUNET_CURL_Context *ctx;
+};
+
+
+/**
+ * Function called when we're done processing the
+ * HTTP /track/transaction request.
+ *
+ * @param cls the `struct TALER_MERCHANT_TrackTransactionHandle`
+ * @param response_code HTTP response code, 0 on error
+ * @param json response body, NULL if not in JSON
+ */
+static void
+handle_tracktransaction_finished (void *cls,
+ long response_code,
+ const json_t *json)
+{
+ struct TALER_MERCHANT_TrackTransactionHandle *tdo = cls;
+
+ tdo->job = NULL;
+ switch (response_code)
+ {
+ case 0:
+ break;
+ case MHD_HTTP_OK:
+ {
+ /* Work out argument for external callback from the body .. */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "200 returned from /track/transaction\n");
+ /* FIXME: actually verify signature */
+ }
+ break;
+ case MHD_HTTP_NOT_FOUND:
+ /* Nothing really to verify, this should never
+ happen, we should pass the JSON reply to the application */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "track transaction URI not found\n");
+ break;
+ case MHD_HTTP_INTERNAL_SERVER_ERROR:
+ /* Server had an internal issue; we should retry, but this API
+ leaves this to the application */
+ break;
+ default:
+ /* unexpected response code */
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unexpected response code %u\n",
+ (unsigned int) response_code);
+ GNUNET_break (0);
+ response_code = 0;
+ break;
+ }
+ /* FIXME: figure out which parameters ought to be passed back */
+ tdo->cb (tdo->cb_cls,
+ response_code,
+ json);
+}
+
+
+/**
+ * Request backend to return transactions associated with a given wtid.
+ *
+ * @param ctx execution context
+ * @param backend_uri URI of the backend (having "/track/transaction" appended)
+ * @param wtid base32 string indicating a wtid
+ * @param exchange base URL of the exchange in charge of returning the wanted information
+ * @param track_transaction_cb the callback to call when a reply for this request is available
+ * @param track_transaction_cb_cls closure for @a contract_cb
+ * @return a handle for this request
+ */
+struct TALER_MERCHANT_TrackTransactionHandle *
+TALER_MERCHANT_track_transaction (struct GNUNET_CURL_Context *ctx,
+ const char *backend_uri,
+ uint64_t transaction_id,
+ const char *exchange_uri,
+ TALER_MERCHANT_TrackTransactionCallback track_transaction_cb,
+ void *track_transaction_cb_cls)
+{
+ struct TALER_MERCHANT_TrackTransactionHandle *tdo;
+ CURL *eh;
+
+ tdo = GNUNET_new (struct TALER_MERCHANT_TrackTransactionHandle);
+ tdo->ctx = ctx;
+ tdo->cb = track_transaction_cb;
+ tdo->cb_cls = track_transaction_cb_cls;
+ /* URI gotten with /track/transaction already appended... */
+ GNUNET_asprintf (&tdo->url,
+ "%s?transaction=%llu&exchange=%s",
+ backend_uri,
+ (unsigned long long) transaction_id,
+ exchange_uri);
+ eh = curl_easy_init ();
+ GNUNET_assert (CURLE_OK ==
+ curl_easy_setopt (eh,
+ CURLOPT_URL,
+ tdo->url));
+ tdo->job = GNUNET_CURL_job_add (ctx,
+ eh,
+ GNUNET_YES,
+ &handle_tracktransaction_finished,
+ tdo);
+ return tdo;
+}
+
+
+/**
+ * Cancel a /track/transaction request. This function cannot be used
+ * on a request handle if a response is already served for it.
+ *
+ * @param co the transaction's tracking handle
+ */
+void
+TALER_MERCHANT_track_transaction_cancel (struct TALER_MERCHANT_TrackTransactionHandle *tdo)
+{
+ if (NULL != tdo->job)
+ {
+ GNUNET_CURL_job_cancel (tdo->job);
+ tdo->job = NULL;
+ }
+ GNUNET_free (tdo->url);
+ GNUNET_free (tdo->wtid);
+ GNUNET_free (tdo);
+}
+
+/* end of merchant_api_track_transaction.c */
diff --git a/src/lib/merchant_api_track_transfer.c b/src/lib/merchant_api_track_transfer.c
@@ -0,0 +1,197 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2014, 2015, 2016 GNUnet e.V. and INRIA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser General Public License as published by the Free Software
+ Foundation; either version 2.1, 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License along with
+ TALER; see the file COPYING.LGPL. If not, If not, see
+ <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file lib/merchant_api_track_transfer.c
+ * @brief Implementation of the /track/transfer request of the
+ * merchant's HTTP API
+ * @author Marcello Stanisci
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <curl/curl.h>
+#include <jansson.h>
+#include <microhttpd.h> /* just for HTTP status codes */
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_curl_lib.h>
+#include "taler_merchant_service.h"
+#include <taler/taler_json_lib.h>
+#include <taler/taler_signatures.h>
+
+
+/**
+ * @brief A Handle for tracking wire transfers.
+ */
+struct TALER_MERCHANT_TrackTransferHandle
+{
+
+ /**
+ * The url for this request.
+ */
+ char *url;
+
+ /**
+ * base32 identifier being the 'witd' parameter required by the
+ * exchange
+ */
+ char *wtid;
+
+ /**
+ * Handle for the request.
+ */
+ struct GNUNET_CURL_Job *job;
+
+ /**
+ * Function to call with the result.
+ */
+ TALER_MERCHANT_TrackTransferCallback cb;
+
+ /**
+ * Closure for @a cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Reference to the execution context.
+ */
+ struct GNUNET_CURL_Context *ctx;
+};
+
+
+/**
+ * Function called when we're done processing the
+ * HTTP /track/transfer request.
+ *
+ * @param cls the `struct TALER_MERCHANT_TrackTransferHandle`
+ * @param response_code HTTP response code, 0 on error
+ * @param json response body, NULL if not in JSON
+ */
+static void
+handle_track_transfer_finished (void *cls,
+ long response_code,
+ const json_t *json)
+{
+ struct TALER_MERCHANT_TrackTransferHandle *tdo = cls;
+
+ tdo->job = NULL;
+ switch (response_code)
+ {
+ case 0:
+ break;
+ case MHD_HTTP_OK:
+ {
+ /* Work out argument for external callback from the body .. */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "200 returned from /track/transfer\n");
+ /* FIXME: actually verify signature */
+ }
+ break;
+ case MHD_HTTP_NOT_FOUND:
+ /* Nothing really to verify, this should never
+ happen, we should pass the JSON reply to the application */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "track transfer URI not found\n");
+ break;
+ case MHD_HTTP_INTERNAL_SERVER_ERROR:
+ /* Server had an internal issue; we should retry, but this API
+ leaves this to the application */
+ break;
+ default:
+ /* unexpected response code */
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unexpected response code %u\n",
+ (unsigned int) response_code);
+ GNUNET_break (0);
+ response_code = 0;
+ break;
+ }
+ /* FIXME: figure out which parameters ought to be passed back */
+ tdo->cb (tdo->cb_cls,
+ response_code,
+ json);
+}
+
+
+/**
+ * Request backend to return transfers associated with a given wtid.
+ *
+ * @param ctx execution context
+ * @param backend_uri URI of the backend (having "/track/transfer" appended)
+ * @param wtid base32 string indicating a wtid
+ * @param exchange base URL of the exchange in charge of returning the wanted information
+ * @param tracktransfer_cb the callback to call when a reply for this request is available
+ * @param tracktransfer_cb_cls closure for @a contract_cb
+ * @return a handle for this request
+ */
+struct TALER_MERCHANT_TrackTransferHandle *
+TALER_MERCHANT_track_transfer (struct GNUNET_CURL_Context *ctx,
+ const char *backend_uri,
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ const char *exchange_uri,
+ TALER_MERCHANT_TrackTransferCallback tracktransfer_cb,
+ void *tracktransfer_cb_cls)
+{
+ struct TALER_MERCHANT_TrackTransferHandle *tdo;
+ CURL *eh;
+ char *wtid_str;
+
+ wtid_str = GNUNET_STRINGS_data_to_string_alloc (wtid,
+ sizeof (struct TALER_WireTransferIdentifierRawP));
+ tdo = GNUNET_new (struct TALER_MERCHANT_TrackTransferHandle);
+ tdo->ctx = ctx;
+ tdo->cb = tracktransfer_cb;
+ tdo->cb_cls = tracktransfer_cb_cls;
+ /* URI gotten with /track/transfer already appended... */
+ GNUNET_asprintf (&tdo->url,
+ "%s?wtid=%s&exchange=%s",
+ backend_uri,
+ wtid_str,
+ exchange_uri);
+ GNUNET_free (wtid_str);
+ eh = curl_easy_init ();
+ GNUNET_assert (CURLE_OK ==
+ curl_easy_setopt (eh,
+ CURLOPT_URL,
+ tdo->url));
+ tdo->job = GNUNET_CURL_job_add (ctx,
+ eh,
+ GNUNET_YES,
+ &handle_track_transfer_finished,
+ tdo);
+ return tdo;
+}
+
+
+/**
+ * Cancel a /track/transfer request. This function cannot be used
+ * on a request handle if a response is already served for it.
+ *
+ * @param co the transfer's tracking handle
+ */
+void
+TALER_MERCHANT_track_transfer_cancel (struct TALER_MERCHANT_TrackTransferHandle *tdo)
+{
+ if (NULL != tdo->job)
+ {
+ GNUNET_CURL_job_cancel (tdo->job);
+ tdo->job = NULL;
+ }
+ GNUNET_free (tdo->url);
+ GNUNET_free (tdo->wtid);
+ GNUNET_free (tdo);
+}
+
+/* end of merchant_api_track_transfer.c */
diff --git a/src/lib/test_merchant_api.c b/src/lib/test_merchant_api.c
@@ -459,9 +459,9 @@ struct Command
char *check_bank_ref;
/**
- * Handle to a /track/deposit operation
+ * Handle to a /track/transfer operation
*/
- struct TALER_MERCHANT_TrackDepositOperation *tdo;
+ struct TALER_MERCHANT_TrackTransferHandle *tdo;
} track_deposit;
@@ -944,7 +944,7 @@ maint_child_death (void *cls)
/**
- * Callback for a /track/deposit operation
+ * Callback for a /track/transfer operation
*
* @param cls closure for this function
* @param http_status HTTP response code returned by the server
@@ -963,13 +963,13 @@ track_deposit_cb (void *cls,
if (MHD_HTTP_OK == http_status)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Ok from /track/deposit handler\n");
+ "Ok from /track/transfer handler\n");
result = GNUNET_OK;
}
else
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Not Ok from /track/deposit handler\n");
+ "Not Ok from /track/transfer handler\n");
result = GNUNET_SYSERR;
}
next_command (is);
@@ -1448,7 +1448,7 @@ interpreter_run (void *cls)
cmd->details.track_deposit.check_bank_ref);
GNUNET_assert (NULL != ref);
cmd->details.track_deposit.tdo =
- TALER_MERCHANT_track_deposit (ctx,
+ TALER_MERCHANT_track_transfer (ctx,
MERCHANT_URI "track/deposit",
&ref->details.check_bank_transfer.wtid,
EXCHANGE_URI,
@@ -1594,10 +1594,10 @@ do_shutdown (void *cls)
break;
case OC_TRACK_DEPOSIT:
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "shutting down /track/deposit\n");
+ "shutting down /track/transfer\n");
if (NULL != cmd->details.track_deposit.tdo)
{
- TALER_MERCHANT_track_deposit_cancel (cmd->details.track_deposit.tdo);
+ TALER_MERCHANT_track_transfer_cancel (cmd->details.track_deposit.tdo);
cmd->details.track_deposit.tdo = NULL;
}
break;