diff options
Diffstat (limited to 'src/merchant')
-rw-r--r-- | src/merchant/.gitignore | 1 | ||||
-rw-r--r-- | src/merchant/Makefile.am | 55 | ||||
-rw-r--r-- | src/merchant/merchant.c | 173 | ||||
-rw-r--r-- | src/merchant/merchant.h | 110 | ||||
-rw-r--r-- | src/merchant/merchant_db.c | 347 | ||||
-rw-r--r-- | src/merchant/merchant_db.h | 98 | ||||
-rw-r--r-- | src/merchant/taler_merchant_dbinit.c | 79 | ||||
-rw-r--r-- | src/merchant/taler_merchant_serve.c | 1539 | ||||
-rw-r--r-- | src/merchant/test_merchant.c | 96 | ||||
-rw-r--r-- | src/merchant/test_merchant.conf | 36 | ||||
-rw-r--r-- | src/merchant/test_merchant.ecc | 2 | ||||
-rw-r--r-- | src/merchant/test_merchant_db.c | 147 |
12 files changed, 0 insertions, 2683 deletions
diff --git a/src/merchant/.gitignore b/src/merchant/.gitignore deleted file mode 100644 index ebe41680..00000000 --- a/src/merchant/.gitignore +++ /dev/null @@ -1 +0,0 @@ -taler-merchant-* diff --git a/src/merchant/Makefile.am b/src/merchant/Makefile.am deleted file mode 100644 index fbe80e0a..00000000 --- a/src/merchant/Makefile.am +++ /dev/null @@ -1,55 +0,0 @@ -AM_CPPFLAGS = -I$(top_srcdir)/src/include $(POSTGRESQL_CPPFLAGS) - -MERCHANT_DB = merchant_db.c merchant_db.h -bin_PROGRAMS = \ - taler-merchant-dbinit \ - taler-merchant-serve - -taler_merchant_dbinit_SOURCES = \ - taler_merchant_dbinit.c \ - $(MERCHANT_DB) -taler_merchant_dbinit_LDADD = \ - -lpq \ - -lgnunetutil \ - -ltalerutil \ - -ltalerpq \ - -lgnunetpostgres -taler_merchant_dbinit_LDFLAGS = \ - $(POSTGRESQL_LDFLAGS) - -check_PROGRAMS = \ - test-merchant \ - test-merchant-db - -test_merchant_SOURCES = \ - merchant.c \ - test_merchant.c -test_merchant_LDADD = \ - -ltalerutil \ - -lgnunetutil - -test_merchant_db_SOURCES = \ - $(MERCHANT_DB) \ - test_merchant_db.c -test_merchant_db_LDADD = \ - -ltalerutil \ - -ltalerpq \ - -lgnunetutil \ - -lgnunetpostgres \ - -lpq - -taler_merchant_serve_SOURCES = \ - taler_merchant_serve.c \ - merchant.c merchant.h \ - $(MERCHANT_DB) -taler_merchant_serve_LDADD = \ - -lpq \ - -lgnunetutil \ - -lgnunetpostgres \ - -lmicrohttpd \ - -ltalermint \ - -ltalerutil \ - -ltalerpq \ - -ljansson -taler_merchant_serve_LDFLAGS = \ - $(POSTGRESQL_LDFLAGS) diff --git a/src/merchant/merchant.c b/src/merchant/merchant.c deleted file mode 100644 index f124a030..00000000 --- a/src/merchant/merchant.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - This file is part of TALER - (C) 2014 Christian Grothoff (and other contributing authors) - - 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 merchant/merchant.c - * @brief Common utility functions for merchant - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include <gnunet/gnunet_util_lib.h> -#include "merchant.h" - - -#define EXITIF(cond) \ - do { \ - if (cond) { GNUNET_break (0); goto EXITIF_exit; } \ - } while (0) - - -/** - * Parses mints from the configuration. - * - * @param cfg the configuration - * @param mints the array of mints upon successful parsing. Will be NULL upon - * error. - * @return the number of mints in the above array; GNUNET_SYSERR upon error in - * parsing. - */ -int -TALER_MERCHANT_parse_mints (const struct GNUNET_CONFIGURATION_Handle *cfg, - struct MERCHANT_MintInfo **mints) -{ - char *mints_str; - char *token_nf; /* do no free (nf) */ - char *mint_section; - char *mint_hostname; - char *mint_pubkey_enc; - struct MERCHANT_MintInfo *r_mints; - struct MERCHANT_MintInfo mint; - unsigned long long mint_port; - unsigned int cnt; - int OK; - - OK = 0; - mints_str = NULL; - token_nf = NULL; - mint_section = NULL; - mint_hostname = NULL; - mint_pubkey_enc = NULL; - r_mints = NULL; - cnt = 0; - EXITIF (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, - "merchant", - "TRUSTED_MINTS", - &mints_str)); - for (token_nf = strtok (mints_str, " "); - NULL != token_nf; - token_nf = strtok (NULL, " ")) - { - GNUNET_assert (0 < GNUNET_asprintf (&mint_section, - "mint-%s", token_nf)); - EXITIF (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, - mint_section, - "HOSTNAME", - &mint_hostname)); - EXITIF (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (cfg, - mint_section, - "PORT", - &mint_port)); - EXITIF (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, - mint_section, - "PUBKEY", - &mint_pubkey_enc)); - EXITIF (GNUNET_OK != - GNUNET_CRYPTO_eddsa_public_key_from_string (mint_pubkey_enc, - strlen (mint_pubkey_enc), - &mint.pubkey)); - mint.hostname = mint_hostname; - mint.port = (uint16_t) mint_port; - GNUNET_array_append (r_mints, cnt, mint); - mint_hostname = NULL; - GNUNET_free (mint_pubkey_enc); - mint_pubkey_enc = NULL; - GNUNET_free (mint_section); - mint_section = NULL; - } - OK = 1; - - EXITIF_exit: - GNUNET_free_non_null (mints_str); - GNUNET_free_non_null (mint_section); - GNUNET_free_non_null (mint_hostname); - GNUNET_free_non_null (mint_pubkey_enc); - if (!OK) - { - GNUNET_free_non_null (r_mints); - return GNUNET_SYSERR; - } - - *mints = r_mints; - return cnt; -} - - -/** - * Parse the SEPA information from the configuration. If any of the required - * fileds is missing return NULL. - * - * @param cfg the configuration - * @return Sepa details as a structure; NULL upon error - */ -struct MERCHANT_WIREFORMAT_Sepa * -TALER_MERCHANT_parse_wireformat_sepa (const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - struct MERCHANT_WIREFORMAT_Sepa *wf; - - wf = GNUNET_new (struct MERCHANT_WIREFORMAT_Sepa); - EXITIF (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, - "wire-sepa", - "IBAN", - &wf->iban)); - EXITIF (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, - "wire-sepa", - "NAME", - &wf->name)); - EXITIF (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, - "wire-sepa", - "BIC", - &wf->bic)); - return wf; - - EXITIF_exit: - GNUNET_free_non_null (wf->iban); - GNUNET_free_non_null (wf->name); - GNUNET_free_non_null (wf->bic); - GNUNET_free (wf); - return NULL; - -} - - -/** - * Destroy and free resouces occupied by the wireformat structure - * - * @param wf the wireformat structure - */ -void -TALER_MERCHANT_destroy_wireformat_sepa (struct MERCHANT_WIREFORMAT_Sepa *wf) -{ - GNUNET_free_non_null (wf->iban); - GNUNET_free_non_null (wf->name); - GNUNET_free_non_null (wf->bic); - GNUNET_free (wf); -} - -/* end of merchant.c */ diff --git a/src/merchant/merchant.h b/src/merchant/merchant.h deleted file mode 100644 index c66131ed..00000000 --- a/src/merchant/merchant.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - This file is part of TALER - (C) 2014 Christian Grothoff (and other contributing authors) - - 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 merchant/merchant.c - * @brief Common utility functions for merchant - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#ifndef MERCHANT_H -#define MERCHANT_H - -#include <gnunet/gnunet_common.h> -#include <gnunet/gnunet_crypto_lib.h> - -/** - * A mint - */ -struct MERCHANT_MintInfo { - /** - * Hostname - */ - char *hostname; - - /** - * The public key of the mint - */ - struct GNUNET_CRYPTO_EddsaPublicKey pubkey; - - /** - * The port where the mint's service is running - */ - uint16_t port; - -}; - - -/** - * Parses mints from the configuration. - * - * @param cfg the configuration - * @param mints the array of mints upon successful parsing. Will be NULL upon - * error. - * @return the number of mints in the above array; GNUNET_SYSERR upon error in - * parsing. - */ -int -TALER_MERCHANT_parse_mints (const struct GNUNET_CONFIGURATION_Handle *cfg, - struct MERCHANT_MintInfo **mints); - - -GNUNET_NETWORK_STRUCT_BEGIN -struct MERCHANT_WIREFORMAT_Sepa -{ - /** - * The international bank account number - */ - char *iban; - - /** - * Name of the bank account holder - */ - char *name; - - /** - *The bank identification code - */ - char *bic; - - /** - * The latest payout date when the payment corresponding to this account has - * to take place. A value of 0 indicates a transfer as soon as possible. - */ - struct GNUNET_TIME_AbsoluteNBO payout; -}; -GNUNET_NETWORK_STRUCT_END - -/** - * Parse the SEPA information from the configuration. If any of the required - * fileds is missing return NULL. - * - * @param cfg the configuration - * @return Sepa details as a structure; NULL upon error - */ -struct MERCHANT_WIREFORMAT_Sepa * -TALER_MERCHANT_parse_wireformat_sepa (const struct GNUNET_CONFIGURATION_Handle *cfg); - - -/** - * Destroy and free resouces occupied by the wireformat structure - * - * @param wf the wireformat structure - */ -void -TALER_MERCHANT_destroy_wireformat_sepa (struct MERCHANT_WIREFORMAT_Sepa *wf); - -#endif /* MERCHANT_H */ diff --git a/src/merchant/merchant_db.c b/src/merchant/merchant_db.c deleted file mode 100644 index e87dbcc8..00000000 --- a/src/merchant/merchant_db.c +++ /dev/null @@ -1,347 +0,0 @@ -/* - This file is part of TALER - (C) 2014 Christian Grothoff (and other contributing authors) - - 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 merchant/merchant_db.c - * @brief database helper functions used by the merchant - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include <gnunet/gnunet_util_lib.h> -#include <taler/taler_util.h> -#include <taler/db_pq.h> -#include "merchant_db.h" - - -#define PQSQL_strerror(kind, cmd, res) \ - GNUNET_log_from (kind, "merchant-db", \ - "SQL %s failed at %s:%u with error: %s", \ - cmd, __FILE__, __LINE__, PQresultErrorMessage (res)); - -/** - * Shorthand for exit jumps. - */ -#define EXITIF(cond) \ - do { \ - if (cond) { GNUNET_break (0); goto EXITIF_exit; } \ - } while (0) - - -/** - * Connect to postgresql database - * - * @param cfg the configuration handle - * @return connection to the postgresql database; NULL upon error - */ -PGconn * -MERCHANT_DB_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - return GNUNET_POSTGRES_connect (cfg, "merchant-db"); -} - - -/** - * Disconnect from the database - * - * @param conn database handle to close - */ -void -MERCHANT_DB_disconnect (PGconn *conn) -{ - PQfinish (conn); -} - - -/** - * Initialise merchant tables - * - * @param conn the connection handle to postgres db. - * @param tmp GNUNET_YES if the tables are to be made temporary i.e. their - * contents are dropped when the @a conn is closed - * @return GNUNET_OK upon success; GNUNET_SYSERR upon failure - */ -int -MERCHANT_DB_initialise (PGconn *conn, int tmp) -{ - const char *tmp_str = (1 == tmp) ? "TEMPORARY" : ""; - char *sql; - PGresult *res; - ExecStatusType status; - int ret; - - res = NULL; - (void) GNUNET_asprintf (&sql, - "BEGIN TRANSACTION;" - "CREATE %1$s TABLE IF NOT EXISTS contracts (" - "transaction_id SERIAL8 PRIMARY KEY," - "amount INT4 NOT NULL," - "amount_fraction INT4 NOT NULL," - "description TEXT NOT NULL," - "nounce BYTEA NOT NULL," - "expiry INT8 NOT NULL," - "product INT8 NOT NULL);" - "CREATE %1$s TABLE IF NOT EXISTS checkouts (" - "coin_pub BYTEA PRIMARY KEY," - "transaction_id INT8 REFERENCES contracts(transaction_id)," - "amount INT4 NOT NULL," - "amount_fraction INT4 NOT NULL," - "coin_sig BYTEA NOT NULL);", - tmp_str); - ret = GNUNET_POSTGRES_exec (conn, sql); - (void) GNUNET_POSTGRES_exec (conn, - (GNUNET_OK == ret) ? "COMMIT;" : "ROLLBACK"); - GNUNET_free (sql); - if (GNUNET_OK != ret) - return ret; - - while (NULL != (res = PQgetResult (conn))) - { - status = PQresultStatus (res); - PQclear (res); - } - - EXITIF (NULL == (res = PQprepare - (conn, - "contract_create", - "INSERT INTO contracts" - "(amount, amount_fraction, description," - "nounce, expiry, product) VALUES" - "($1, $2, $3, $4, $5, $6)" - "RETURNING transaction_id", - 6, NULL))); - EXITIF (PGRES_COMMAND_OK != (status = PQresultStatus(res))); - PQclear (res); - - EXITIF (NULL == (res = PQprepare - (conn, - "get_contract_product", - "SELECT (" - "product" - ") FROM contracts " - "WHERE (" - "transaction_id=$1" - ")", - 1, NULL))); - EXITIF (PGRES_COMMAND_OK != (status = PQresultStatus(res))); - PQclear (res); - - EXITIF (NULL == (res = PQprepare - (conn, - "checkout_create", - "INSERT INTO checkouts (" - "coin_pub," - "transaction_id," - "amount," - "amount_fraction," - "coin_sig" - ") VALUES (" - "$1, $2, $3, $4, $5" - ")", - 5, NULL))); - EXITIF (PGRES_COMMAND_OK != (status = PQresultStatus (res))); - PQclear (res); - - EXITIF (NULL == (res = PQprepare - (conn, - "get_checkout_product", - "SELECT (" - "product" - ") FROM contracts " - "WHERE " - "transaction_id IN (" - "SELECT (transaction_id) FROM checkouts " - "WHERE coin_pub=$1" - ")", - 1, NULL))); - EXITIF (PGRES_COMMAND_OK != (status = PQresultStatus (res))); - PQclear (res); - - return GNUNET_OK; - - EXITIF_exit: - if (NULL != res) - { - PQSQL_strerror (GNUNET_ERROR_TYPE_ERROR, "PQprepare", res); - PQclear (res); - } - return GNUNET_SYSERR; -} - - -/** - * Inserts a contract record into the database and if successfull returns the - * serial number of the inserted row. - * - * @param conn the database connection - * @param expiry the time when the contract will expire - * @param amount the taler amount corresponding to the contract - * @param desc descripition of the contract - * @param nounce a random 64-bit nounce - * @param product description to identify a product - * @return -1 upon error; the serial id of the inserted contract upon success - */ -long long -MERCHANT_DB_contract_create (PGconn *conn, - struct GNUNET_TIME_Absolute expiry, - struct TALER_Amount *amount, - const char *desc, - uint64_t nounce, - uint64_t product) -{ - PGresult *res; - uint64_t expiry_ms_nbo; - uint32_t value_nbo; - uint32_t fraction_nbo; - uint64_t nounce_nbo; - ExecStatusType status; - long long id; - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR (&value_nbo), - TALER_DB_QUERY_PARAM_PTR (&fraction_nbo), - TALER_DB_QUERY_PARAM_PTR_SIZED (desc, strlen(desc)), - TALER_DB_QUERY_PARAM_PTR (&nounce_nbo), - TALER_DB_QUERY_PARAM_PTR (&expiry_ms_nbo), - TALER_DB_QUERY_PARAM_PTR (&product), - TALER_DB_QUERY_PARAM_END - }; - struct TALER_DB_ResultSpec rs[] = { - TALER_DB_RESULT_SPEC("transaction_id", &id), - TALER_DB_RESULT_SPEC_END - }; - - expiry_ms_nbo = GNUNET_htonll (expiry.abs_value_us); - value_nbo = htonl (amount->value); - fraction_nbo = htonl (amount->fraction); - nounce_nbo = GNUNET_htonll (nounce); - product = GNUNET_htonll (product); - res = TALER_DB_exec_prepared (conn, "contract_create", params); - status = PQresultStatus (res); - EXITIF (PGRES_TUPLES_OK != status); - EXITIF (1 != PQntuples (res)); - EXITIF (GNUNET_YES != TALER_DB_extract_result (res, rs, 0)); - PQclear (res); - return GNUNET_ntohll ((uint64_t) id); - - EXITIF_exit: - PQclear (res); - return -1; -} - -long long -MERCHANT_DB_get_contract_product (PGconn *conn, - uint64_t contract_id) -{ - PGresult *res; - int64_t product; - ExecStatusType status; - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR (&contract_id), - TALER_DB_QUERY_PARAM_END - }; - struct TALER_DB_ResultSpec rs[] = { - TALER_DB_RESULT_SPEC("product", &product), - TALER_DB_RESULT_SPEC_END - }; - - contract_id = GNUNET_htonll (contract_id); - res = TALER_DB_exec_prepared (conn, "get_contract_product", params); - status = PQresultStatus (res); - EXITIF (PGRES_TUPLES_OK != status); - EXITIF (1 != PQntuples (res)); - EXITIF (GNUNET_YES != TALER_DB_extract_result (res, rs, 0)); - PQclear (res); - return GNUNET_ntohll ((uint64_t) product); - - EXITIF_exit: - PQclear (res); - return -1; -} - -unsigned int -MERCHANT_DB_checkout_create (PGconn *conn, - struct GNUNET_CRYPTO_EddsaPublicKey *coin_pub, - uint64_t transaction_id, - struct TALER_Amount *amount, - struct GNUNET_CRYPTO_EddsaSignature *coin_sig) -{ - PGresult *res; - ExecStatusType status; - uint32_t value_nbo; - uint32_t fraction_nbo; - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR (coin_pub), - TALER_DB_QUERY_PARAM_PTR (&transaction_id), - TALER_DB_QUERY_PARAM_PTR (&value_nbo), - TALER_DB_QUERY_PARAM_PTR (&fraction_nbo), - TALER_DB_QUERY_PARAM_PTR (coin_sig), - TALER_DB_QUERY_PARAM_END - }; - - transaction_id = GNUNET_htonll (transaction_id); - value_nbo = htonl (amount->value); - fraction_nbo = htonl (amount->fraction); - res = TALER_DB_exec_prepared (conn, "checkout_create", params); - status = PQresultStatus (res); - EXITIF (PGRES_COMMAND_OK != status); - PQclear (res); - return GNUNET_OK; - - EXITIF_exit: - PQclear (res); - return GNUNET_SYSERR; -} - - -long long -MERCHANT_DB_get_checkout_product (PGconn *conn, - struct GNUNET_CRYPTO_EddsaPublicKey *coin_pub) -{ - PGresult *res; - ExecStatusType status; - uint64_t product; - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR (coin_pub), - TALER_DB_QUERY_PARAM_END - }; - struct TALER_DB_ResultSpec rs[] = { - TALER_DB_RESULT_SPEC("product", &product), - TALER_DB_RESULT_SPEC_END - }; - - product = -1; - res = TALER_DB_exec_prepared (conn, "get_checkout_product", params); - status = PQresultStatus (res); - EXITIF (PGRES_TUPLES_OK != status); - if (0 == PQntuples (res)) - { - char *coin_pub_enc; - coin_pub_enc = GNUNET_CRYPTO_eddsa_public_key_to_string (coin_pub); - LOG_DEBUG ("Checkout not found for given coin: %s\n", - coin_pub_enc); - GNUNET_free (coin_pub_enc); - goto EXITIF_exit; - } - EXITIF (1 != PQntuples (res)); - EXITIF (GNUNET_YES != TALER_DB_extract_result (res, rs, 0)); - PQclear (res); - return GNUNET_ntohll ((uint64_t) product); - - EXITIF_exit: - PQclear (res); - return -1; -} -/* end of merchant-db.c */ diff --git a/src/merchant/merchant_db.h b/src/merchant/merchant_db.h deleted file mode 100644 index 734d547f..00000000 --- a/src/merchant/merchant_db.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - This file is part of TALER - (C) 2014 Christian Grothoff (and other contributing authors) - - 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 merchant/merchant_db.h - * @brief database helper functions used by the merchant - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#ifndef MERCHANT_DB_H -#define MERCHANT_DB_H - -#include <gnunet/gnunet_postgres_lib.h> -#include <taler/taler_util.h> - -/** - * Connect to postgresql database - * - * @param cfg the configuration handle - * @return connection to the postgresql database; NULL upon error - */ -PGconn * -MERCHANT_DB_connect (const struct GNUNET_CONFIGURATION_Handle *cfg); - - -/** - * Disconnect from the database - * - * @param conn database handle to close - */ -void -MERCHANT_DB_disconnect (PGconn *conn); - - -/** - * Initialise merchant tables - * - * @param conn the connection handle to postgres db. - * @param tmp GNUNET_YES if the tables are to be made temporary i.e. their - * contents are dropped when the @a conn is closed - * @return GNUNET_OK upon success; GNUNET_SYSERR upon failure - */ -int -MERCHANT_DB_initialise (PGconn *conn, int tmp); - - -/** - * Inserts a contract record into the database and if successfull returns the - * serial number of the inserted row. - * - * @param conn the database connection - * @param expiry the time when the contract will expire - * @param amount the taler amount corresponding to the contract - * @param desc descripition of the contract - * @param nounce a random 64-bit nounce - * @param product description to identify a product - * @return -1 upon error; the serial id of the inserted contract upon success - */ -long long -MERCHANT_DB_contract_create (PGconn *conn, - struct GNUNET_TIME_Absolute expiry, - struct TALER_Amount *amount, - const char *desc, - uint64_t nounce, - uint64_t product); - -long long -MERCHANT_DB_get_contract_product (PGconn *conn, - uint64_t contract_id); - -unsigned int -MERCHANT_DB_checkout_create (PGconn *conn, - struct GNUNET_CRYPTO_EddsaPublicKey *coin_pub, - uint64_t transaction_id, - struct TALER_Amount *amount, - struct GNUNET_CRYPTO_EddsaSignature *coin_sig); - - -long long -MERCHANT_DB_get_checkout_product (PGconn *conn, - struct GNUNET_CRYPTO_EddsaPublicKey *coin_pub); - -#endif /* MERCHANT_DB_H */ - -/* end of merchant-db.h */ diff --git a/src/merchant/taler_merchant_dbinit.c b/src/merchant/taler_merchant_dbinit.c deleted file mode 100644 index e6d0af9d..00000000 --- a/src/merchant/taler_merchant_dbinit.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - This file is part of TALER - (C) 2014 Christian Grothoff (and other contributing authors) - - 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 merchant/taler_merchant_dbinit.c - * @brief Program to initialise merchant database - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include <gnunet/gnunet_util_lib.h> -#include "merchant_db.h" - - -/** - * Global execution result - */ -static int result; - - -/** - * Main function that will be run by the scheduler. - * - * @param cls closure - * @param args remaining command-line arguments - * @param cfgfile name of the configuration file used (for saving, can be NULL!) - * @param config configuration - */ -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *config) -{ - PGconn *conn; - - conn = MERCHANT_DB_connect (config); - if (NULL == conn) - return; - if (GNUNET_OK == MERCHANT_DB_initialise (conn, GNUNET_NO)) - result = GNUNET_OK; - MERCHANT_DB_disconnect (conn); -} - - -/** - * The main function - * - * @param argc number of arguments from the command line - * @param argv command line arguments - * @return 0 ok, 1 on error - */ -int -main (int argc, char *const *argv) -{ - static const struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - - result = GNUNET_SYSERR; - if (GNUNET_OK != - GNUNET_PROGRAM_run (argc, argv, "taler-merchant-dbinit", - gettext_noop - ("Initialise Taler Merchant's database"), - options, &run, NULL)) - return 3; - return (GNUNET_OK == result) ? 0 : 1; -} diff --git a/src/merchant/taler_merchant_serve.c b/src/merchant/taler_merchant_serve.c deleted file mode 100644 index 0f00a8c2..00000000 --- a/src/merchant/taler_merchant_serve.c +++ /dev/null @@ -1,1539 +0,0 @@ -#include "platform.h" -#include <gnunet/gnunet_util_lib.h> -#include <microhttpd.h> -#include <taler/taler_util.h> -#include "merchant.h" -#include "merchant_db.h" -#include <taler/taler_mint_service.h> -#include <taler/taler_signatures.h> -#include <taler/taler_json_lib.h> - - -/** - * Shorthand for exit jumps. - */ -#define EXITIF(cond) \ - do { \ - if (cond) { GNUNET_break (0); goto EXITIF_exit; } \ - } while (0) - -/** - * Shorthand for exit jumps due to protocol exceptions resulting from client's - * mistakes - */ -#define EXITIF_OP(cond) \ - do { \ - if (cond) { GNUNET_break_op (0); goto EXITIF_exit; } \ - } while (0) - -/** - * Print JSON parsing related error information - */ -#define WARN_JSON(error) \ - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, \ - "JSON parsing failed at %s:%u: %s (%s)", \ - __FILE__, __LINE__, error.text, error.source) - -/** - * Macro to round microseconds to seconds in GNUNET_TIME_* structs. - */ -#define ROUND_TO_SECS(name,us_field) name.us_field -= name.us_field % (1000 * 1000) - - -struct ContractData -{ - char *product; -}; - - -GNUNET_NETWORK_STRUCT_BEGIN - -struct Contract -{ - /** - * The signature of the merchant for this contract - */ - struct GNUNET_CRYPTO_EddsaSignature sig; - - /** - * Purpose header for the signature over contract - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * The transaction identifier - */ - char m[13]; - - /** - * Expiry time - */ - struct GNUNET_TIME_AbsoluteNBO t; - - /** - * The invoice amount - */ - struct TALER_AmountNBO amount; - - /** - * The hash of the preferred wire format + nounce - */ - struct GNUNET_HashCode h_wire; - - /** - * The contract data - */ - char a[]; -}; - -GNUNET_NETWORK_STRUCT_END - -/** - * A download object - */ -struct Download { - struct Download *next; - struct Download *prev; - char *filename; - struct MHD_Response *resp; - unsigned int id; -}; - -/** - * DLL for downloadable objects - */ -struct Download *dwn_head; -struct Download *dwn_tail; - -/** - * MHD response object for listing all products - */ -struct MHD_Response *list_products_resp; - -/** - * Number of files we make available for downloading - */ -static unsigned int ndownloads; - - -/** - * Context information of the mints we trust - */ -struct Mint -{ - /** - * Public key of this mint - */ - struct GNUNET_CRYPTO_EddsaPublicKey pubkey; - - /** - * Connection handle to this mint - */ - struct TALER_MINT_Handle *conn; -}; - -/** - * Hashmap to store the mint context information - */ -static struct GNUNET_CONTAINER_MultiPeerMap *mints_map; - -/** - * Our private key - */ -struct GNUNET_CRYPTO_EddsaPrivateKey *privkey; - -/** - * Connection handle to the our database - */ -PGconn *db_conn; - -/** - * The MHD Daemon - */ -static struct MHD_Daemon *mhd; - -/** - * Our wireformat - */ -static struct MERCHANT_WIREFORMAT_Sepa *wire; - -/** - * Hash of the wireformat - */ -static struct GNUNET_HashCode h_wire; - -/** - * Shutdown task identifier - */ -static struct GNUNET_SCHEDULER_Task *shutdown_task; - -/** - * Task for calling the select on MHD's sockets - */ -static struct GNUNET_SCHEDULER_Task *select_task; - -/** - * The port we are running on - */ -static long long unsigned port; - -/** - * Mint context - */ -static struct TALER_MINT_Context *mctx; - -/** - * Our hostname - */ -static char *hostname; - -/** - * Directory of data items to serve - */ -static char *data_dir; - -/** - * Should we do a dry run where temporary tables are used for storing the data. - */ -static int dry; - -/** - * Global return code - */ -static int result; - - - -/** - * Send JSON object as response. Decreases the reference count of the - * JSON object. - * - * @param connection the MHD connection - * @param json the json object - * @param status_code the http status code - * @return MHD result code - */ -static int -send_response_json (struct MHD_Connection *connection, - json_t *json, - unsigned int status_code) -{ - struct MHD_Response *resp; - char *json_str; - - json_str = json_dumps (json, JSON_INDENT(2)); - json_decref (json); - resp = MHD_create_response_from_buffer (strlen (json_str), json_str, - MHD_RESPMEM_MUST_FREE); - if (NULL == resp) - return MHD_NO; - return MHD_queue_response (connection, status_code, resp); -} - - -/* ************ JSON post-processing logic; FIXME: why do we use JSON here!? ********** */ - - -/** - * Initial size for POST - * request buffer. - */ -#define REQUEST_BUFFER_INITIAL 1024 - -/** - * Maximum POST request size - */ -#define REQUEST_BUFFER_MAX (1024*1024) - - -/** - * Buffer for POST requests. - */ -struct Buffer -{ - /** - * Allocated memory - */ - char *data; - - /** - * Number of valid bytes in buffer. - */ - size_t fill; - - /** - * Number of allocated bytes in buffer. - */ - size_t alloc; -}; - - -/** - * Initialize a buffer. - * - * @param buf the buffer to initialize - * @param data the initial data - * @param data_size size of the initial data - * @param alloc_size size of the buffer - * @param max_size maximum size that the buffer can grow to - * @return a GNUnet result code - */ -static int -buffer_init (struct Buffer *buf, const void *data, size_t data_size, size_t alloc_size, size_t max_size) -{ - if (data_size > max_size || alloc_size > max_size) - return GNUNET_SYSERR; - if (data_size > alloc_size) - alloc_size = data_size; - buf->data = GNUNET_malloc (alloc_size); - memcpy (buf->data, data, data_size); - return GNUNET_OK; -} - - -/** - * Free the data in a buffer. Does *not* free - * the buffer object itself. - * - * @param buf buffer to de-initialize - */ -static void -buffer_deinit (struct Buffer *buf) -{ - GNUNET_free (buf->data); - buf->data = NULL; -} - - -/** - * Append data to a buffer, growing the buffer if necessary. - * - * @param buf the buffer to append to - * @param data the data to append - * @param size the size of @a data - * @param max_size maximum size that the buffer can grow to - * @return GNUNET_OK on success, - * GNUNET_NO if the buffer can't accomodate for the new data - * GNUNET_SYSERR on fatal error (out of memory?) - */ -static int -buffer_append (struct Buffer *buf, const void *data, size_t data_size, size_t max_size) -{ - if (buf->fill + data_size > max_size) - return GNUNET_NO; - if (data_size + buf->fill > buf->alloc) - { - char *new_buf; - size_t new_size = buf->alloc; - while (new_size < buf->fill + data_size) - new_size += 2; - if (new_size > max_size) - return GNUNET_NO; - new_buf = GNUNET_malloc (new_size); - memcpy (new_buf, buf->data, buf->fill); - buf->data = new_buf; - buf->alloc = new_size; - } - memcpy (buf->data + buf->fill, data, data_size); - buf->fill += data_size; - return GNUNET_OK; -} - - - -/** - * Process a POST request containing a JSON object. - * - * @param connection the MHD connection - * @param con_cs the closure (contains a 'struct Buffer *') - * @param upload_data the POST data - * @param upload_data_size the POST data size - * @param json the JSON object for a completed request - * - * @returns - * GNUNET_YES if json object was parsed - * GNUNET_NO is request incomplete or invalid - * GNUNET_SYSERR on internal error - */ -static int -process_post_json (struct MHD_Connection *connection, - void **con_cls, - const char *upload_data, - size_t *upload_data_size, - json_t **json) -{ - struct Buffer *r = *con_cls; - - if (NULL == *con_cls) - { - /* We are seeing a fresh POST request. */ - - r = GNUNET_new (struct Buffer); - if (GNUNET_OK != buffer_init (r, upload_data, *upload_data_size, - REQUEST_BUFFER_INITIAL, REQUEST_BUFFER_MAX)) - { - *con_cls = NULL; - buffer_deinit (r); - GNUNET_free (r); - return GNUNET_SYSERR; - } - *upload_data_size = 0; - *con_cls = r; - return GNUNET_NO; - } - if (0 != *upload_data_size) - { - /* We are seeing an old request with more data available. */ - - if (GNUNET_OK != buffer_append (r, upload_data, *upload_data_size, - REQUEST_BUFFER_MAX)) - { - /* Request too long or we're out of memory. */ - - *con_cls = NULL; - buffer_deinit (r); - GNUNET_free (r); - return GNUNET_SYSERR; - } - *upload_data_size = 0; - return GNUNET_NO; - } - - /* We have seen the whole request. */ - - *json = json_loadb (r->data, r->fill, 0, NULL); - buffer_deinit (r); - GNUNET_free (r); - if (NULL == *json) - { - struct MHD_Response *resp; - int ret; - - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Can't parse JSON request body\n"); - resp = MHD_create_response_from_buffer (strlen ("parse error"), - "parse error", - MHD_RESPMEM_PERSISTENT); - ret = MHD_queue_response (connection, - MHD_HTTP_BAD_REQUEST, - resp); - MHD_destroy_response (resp); - return ret; - } - *con_cls = NULL; - - return GNUNET_YES; -} - - -/* ************** END of JSON POST processing logic ************ */ - - -static struct GNUNET_HashCode -hash_wireformat (uint64_t nounce) -{ - struct GNUNET_HashContext *hc; - struct GNUNET_HashCode hash; - - hc = GNUNET_CRYPTO_hash_context_start (); - GNUNET_CRYPTO_hash_context_read (hc, wire->iban, strlen (wire->iban)); - GNUNET_CRYPTO_hash_context_read (hc, wire->name, strlen (wire->name)); - GNUNET_CRYPTO_hash_context_read (hc, wire->bic, strlen (wire->bic)); - nounce = GNUNET_htonll (nounce); - GNUNET_CRYPTO_hash_context_read (hc, &nounce, sizeof (nounce)); - GNUNET_CRYPTO_hash_context_finish (hc, &hash); - return hash; -} - - -static json_t * -build_json_contract (struct Contract *contract) -{ - return json_pack ("{s:s, s:o, s:o, s:s, s:o, s:o}", - "transaction_id", contract->m, - "expiry", TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (contract->t)), - "amount", TALER_JSON_from_amount (TALER_amount_ntoh (contract->amount)), - "description", contract->a, - "H_wire", TALER_JSON_from_data (&contract->h_wire, sizeof (struct GNUNET_HashCode)), - "msig", TALER_JSON_from_data (&contract->sig, sizeof (struct GNUNET_CRYPTO_EddsaSignature))); -} - -/** - * Cleeanup entries in the peer map. - * - * @param cls closure - * @param key current public key - * @param value value in the hash map - * @return #GNUNET_YES if we should continue to - * iterate, - * #GNUNET_NO if not. - */ -static int -mints_cleanup_iterator (void *cls, - const struct GNUNET_PeerIdentity *key, - void *value) -{ - struct Mint *mint = value; - - if (NULL != mint->conn) - TALER_MINT_disconnect (mint->conn); - GNUNET_CONTAINER_multipeermap_remove (mints_map, key, mint); - GNUNET_free (mint); - return GNUNET_YES; -} - - -/** - * Shutdown task - * - * @param cls NULL - * @param tc scheduler task context - */ -static void -do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct Download *dwn; - - shutdown_task = NULL; - if (NULL != select_task) - { - GNUNET_SCHEDULER_cancel (select_task); - select_task = NULL; - } - if (NULL != list_products_resp) - { - MHD_destroy_response (list_products_resp); - list_products_resp = NULL; - } - if (NULL != mhd) - { - MHD_stop_daemon (mhd); - mhd = NULL; - } - if (NULL != db_conn) - { - MERCHANT_DB_disconnect (db_conn); - db_conn = NULL; - } - if (NULL != mints_map) - { - GNUNET_CONTAINER_multipeermap_iterate (mints_map, - &mints_cleanup_iterator, - NULL); - GNUNET_CONTAINER_multipeermap_destroy (mints_map); - mints_map = NULL; - } - if (NULL != mctx) - { - TALER_MINT_cleanup (mctx); - mctx = NULL; - } - if (NULL != wire) - { - TALER_MERCHANT_destroy_wireformat_sepa (wire); - wire = NULL; - } - while (NULL != (dwn = dwn_head)) - { - GNUNET_CONTAINER_DLL_remove (dwn_head, dwn_tail, dwn); - if (NULL != dwn->resp) - MHD_destroy_response (dwn->resp); - GNUNET_free (dwn->filename); - GNUNET_free (dwn); - } -} - - -/** - * Get the MHD's sockets which are to be called with select() and schedule the - * select task. - * - * @return GNUNET_YES upon success; GNUNET_NO upon error, in this case the - * select task will not be queued. - */ -static int -poll_mhd (); - - -/** - * One of the MHD's sockets are ready. Call MHD_run_from_select (). - * - * @param cls NULL - * @param tc scheduler task context - */ -static void -run_mhd (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - fd_set fd_rs; - fd_set fd_ws; - select_task = NULL; - if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) - return; - FD_ZERO (&fd_rs); - FD_ZERO (&fd_ws); - if (0 != (GNUNET_SCHEDULER_REASON_READ_READY & tc->reason)) - fd_rs = tc->read_ready->sds; - if (0 != (GNUNET_SCHEDULER_REASON_WRITE_READY & tc->reason)) - fd_ws = tc->write_ready->sds; - EXITIF (MHD_YES != MHD_run_from_select (mhd, - &fd_rs, - &fd_ws, - NULL)); - EXITIF (GNUNET_NO == poll_mhd ()); - return; - - EXITIF_exit: - result = GNUNET_SYSERR; - GNUNET_SCHEDULER_shutdown (); -} - - -/** - * Get the MHD's sockets which are to be called with select() and schedule the - * select task. - * - * @return GNUNET_YES upon success; GNUNET_NO upon error, in this case the - * select task will not be queued. - */ -static int -poll_mhd () -{ - struct GNUNET_NETWORK_FDSet rs; - struct GNUNET_NETWORK_FDSet ws; - fd_set fd_rs; - fd_set fd_ws; - fd_set fd_es; - struct GNUNET_TIME_Relative delay; - unsigned long long timeout; - int max_fd; - - FD_ZERO (&fd_rs); - FD_ZERO (&fd_ws); - FD_ZERO (&fd_es); - max_fd = 0; - if (MHD_YES != MHD_get_fdset (mhd, - &fd_rs, - &fd_ws, - &fd_es, - &max_fd)) - return GNUNET_SYSERR; - GNUNET_NETWORK_fdset_zero (&rs); - GNUNET_NETWORK_fdset_zero (&ws); - GNUNET_NETWORK_fdset_copy_native (&rs, &fd_rs, max_fd + 1); - GNUNET_NETWORK_fdset_copy_native (&ws, &fd_ws, max_fd + 1); - if (MHD_NO == MHD_get_timeout (mhd, &timeout)) - timeout = 0; - if (0 == timeout) - delay = GNUNET_TIME_UNIT_FOREVER_REL; - else - delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, - timeout); - if (NULL != select_task) - GNUNET_SCHEDULER_cancel (select_task); - select_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_KEEP, - delay, - &rs, - &ws, - &run_mhd, - NULL); - return GNUNET_OK; -} - -static int -failure_resp (struct MHD_Connection *connection, unsigned int status) -{ - static char page_404[]="\ -<!DOCTYPE html> \ -<html><title>Resource not found</title><body><center> \ -<h3>The resource you are looking for is not found.</h3> \ -</center></body></html>"; - static char page_500[]="\ -<!DOCTYPE html> <html><title>Internal Server Error</title><body><center> \ -<h3>The server experienced an internal error and hence cannot serve your \ -request</h3></center></body></html>"; - struct MHD_Response *resp; - char *page; - size_t size; -#define PAGE(number) \ - do {page=page_ ## number; size=sizeof(page_ ## number)-1;} while(0) - - GNUNET_assert (400 <= status); - resp = NULL; - switch (status) - { - case 404: - PAGE(404); - break; - default: - status = 500; - case 500: - PAGE(500); - } -#undef PAGE - - EXITIF (NULL == (resp = MHD_create_response_from_buffer (size, - page, - MHD_RESPMEM_PERSISTENT))); - EXITIF (MHD_YES != MHD_queue_response (connection, status, resp)); - MHD_destroy_response (resp); - return GNUNET_OK; - - EXITIF_exit: - if (NULL != resp) - MHD_destroy_response (resp); - return GNUNET_SYSERR; -} - - -/** - * Iterator over key-value pairs. This iterator - * can be used to iterate over all of the cookies, - * headers, or POST-data fields of a request, and - * also to iterate over the headers that have been - * added to a response. - * - * @param cls closure - * @param kind kind of the header we are looking at - * @param key key for the value, can be an empty string - * @param value corresponding value, can be NULL - * @return #MHD_YES to continue iterating, - * #MHD_NO to abort the iteration - * @ingroup request - */ -static int -get_contract_values_iter (void *cls, - enum MHD_ValueKind kind, - const char *key, const char *value) -{ - unsigned long long id; - uint64_t *product = cls; - -#define STR_PRODUCT "product" - if (0 == strncasecmp (key, STR_PRODUCT, sizeof (STR_PRODUCT) - 1)) - { - if (1 > sscanf (value, "%llu", &id)) - return GNUNET_NO; - *product = (uint64_t) id; - } - return GNUNET_YES; -} - -#if 0 -static const char * -uint64_to_enc (uint64_t i) -{ - static char buf[14]; - i = GNUNET_htonll (i); - GNUNET_break (NULL != - GNUNET_STRINGS_data_to_string (&i, sizeof (i), buf, sizeof (buf))); - buf[13] = '\0'; - return buf; -} - -static uint64_t -enc_to_uint64 (const char *enc) -{ - uint64_t i; - GNUNET_break (GNUNET_OK == - GNUNET_STRINGS_string_to_data (enc, strlen(enc), &i, sizeof - (i))); - return GNUNET_ntohll (i); -} -#endif - -/** - * Prepare a contract, store it in database and send the corresponding JSON. - * - * @param connection MHD connection handle - * @param _resp pointer to hold the result response upon success - * @return the status code 200 when a contract is generated; 404 when the - * product is not found or upon other errors. - */ -static unsigned int -handle_get_contract (struct MHD_Connection *connection, - struct MHD_Response **_resp) -{ - struct MHD_Response *resp; - struct Contract *contract; - struct GNUNET_TIME_Absolute expiry; - struct TALER_Amount amount; - char *template = "A contract from GNUnet e.V thanking you for a" - " donation of the aforementioned amount. As a token of gratitude, upon" - " successful payment, you may download your image at " - "`http://%s:%u/download?ref=[]'"; - char *desc; - json_t *json; - char *json_str; - uint64_t nounce; - uint64_t product; - uint64_t contract_id_nbo; - long long contract_id; - unsigned int ret; - - resp = NULL; - contract = NULL; - desc = NULL; - ret = 400; - product = UINT64_MAX; - MHD_get_connection_values (connection, MHD_GET_ARGUMENT_KIND, - &get_contract_values_iter, &product); - if (UINT64_MAX == product) - goto EXITIF_exit; - - expiry = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), - GNUNET_TIME_UNIT_DAYS); - ROUND_TO_SECS (expiry, abs_value_us); - amount.value = 1; - amount.fraction = 0; - strcpy (amount.currency, "EUR"); - nounce = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX); - - /* Prepare contract */ - (void) GNUNET_asprintf (&desc, - template, - hostname, - port); - contract_id = MERCHANT_DB_contract_create (db_conn, - expiry, - &amount, - desc, - nounce, - product); - EXITIF (-1 == contract_id); - contract_id_nbo = GNUNET_htonll ((uint64_t) contract_id); - contract = GNUNET_malloc (sizeof (struct Contract) + strlen (desc) + 1); - contract->purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_CONTRACT); - contract->purpose.size = htonl (sizeof (struct Contract) - - offsetof (struct Contract, purpose) - + strlen (desc) + 1); - GNUNET_STRINGS_data_to_string (&contract_id_nbo, sizeof (contract_id_nbo), - contract->m, sizeof (contract->m)); - contract->t = GNUNET_TIME_absolute_hton (expiry); - (void) strcpy (contract->a, desc); - contract->h_wire = hash_wireformat (nounce); - contract->amount = TALER_amount_hton (amount); - GNUNET_CRYPTO_eddsa_sign (privkey, &contract->purpose, &contract->sig); - json = build_json_contract (contract); - json_str = json_dumps (json, JSON_INDENT(2)); - json_decref (json); - resp = MHD_create_response_from_buffer (strlen (json_str), json_str, - MHD_RESPMEM_MUST_FREE); - ret = 200; - - EXITIF_exit: - GNUNET_free_non_null (desc); - if (NULL != resp) - *_resp = resp; - if (NULL != contract) - { - GNUNET_free (contract); - } - return ret; -} - -static struct Download * -find_product (unsigned int id) -{ - struct Download *dwn; - - for (dwn = dwn_head; NULL != dwn; dwn = dwn->next) - { - if (dwn->id == id) - return dwn; - } - return NULL; -} - - -static int -get_download_ref (void *cls, - enum MHD_ValueKind kind, - const char *key, const char *value) -{ - char **coin_pub_enc = cls; - - if (0 == strncasecmp (key, "ref", sizeof ("ref"))) - { - *coin_pub_enc = GNUNET_strdup (value); - return MHD_NO; - } - return MHD_YES; -} - -static unsigned int -handle_download (struct MHD_Connection *conn, - struct MHD_Response **_resp) -{ - char *coin_pub_enc; - struct Download *item; - struct GNUNET_DISK_FileHandle *fh; - struct GNUNET_CRYPTO_EddsaPublicKey coin_pub; - long long product_id; - off_t size; - int ret; - - coin_pub_enc = NULL; - ret = MHD_HTTP_NOT_FOUND; - MHD_get_connection_values (conn, MHD_GET_ARGUMENT_KIND, - &get_download_ref, &coin_pub_enc); - LOG_WARNING ("Trying to start downloading with coin: %s\n", coin_pub_enc); - EXITIF (NULL == coin_pub_enc); - EXITIF (GNUNET_SYSERR == - GNUNET_CRYPTO_eddsa_public_key_from_string (coin_pub_enc, - strlen (coin_pub_enc), - &coin_pub)); - product_id = MERCHANT_DB_get_checkout_product (db_conn, - &coin_pub); - EXITIF (-1 == product_id); - EXITIF (NULL == (item = find_product ((unsigned int) product_id))); - if (NULL != item->resp) - { - *_resp = item->resp; - ret = MHD_HTTP_OK; - goto EXITIF_exit; - } - fh = GNUNET_DISK_file_open (item->filename, - GNUNET_DISK_OPEN_READ, - GNUNET_DISK_PERM_USER_READ); - GNUNET_assert (NULL != fh); - GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_handle_size (fh, - &size)); - item->resp = MHD_create_response_from_fd (size, fh->fd); - GNUNET_assert (MHD_NO != MHD_add_response_header (item->resp, - "Content-Type", - "image/jpeg")); - GNUNET_free (fh); - - EXITIF_exit: - GNUNET_free_non_null (coin_pub_enc); - return ret; -} - -struct CheckoutCtx -{ - /* FIXME: Hook into a DLL for cleaner shutdown */ - struct MHD_Connection *conn; - struct TALER_MINT_DepositHandle *dh; - struct Download *product; - char *coin_pub_enc; - uint64_t transaction_id; - struct GNUNET_CRYPTO_EddsaPublicKey coin_pub; - struct GNUNET_CRYPTO_EddsaSignature coin_sig; - struct TALER_Amount amount; - struct GNUNET_SCHEDULER_Task *timeout_task; - -}; - - -/** - * Callbacks of this type are used to serve the result of submitting a deposit - * permission object to a mint - * - * @param cls closure - * @param status 1 for successful deposit, 2 for retry, 0 for failure - * @param obj the received JSON object; can be NULL if it cannot be constructed - * from the reply - * @param emsg in case of unsuccessful deposit, this contains a human readable - * explanation. - */ -static void -checkout_status (void *cls, int status, json_t *obj, char *emsg) -{ - struct CheckoutCtx *ctx = cls; - const char *tmplt_download_page = - "<!DOCTYPE HTML><html>" - "<body>You are being redirected to the product download page<br>" - "If your browser is unable to redirect, you may click " - "<a href=\"%s\">here</a> to download.</body>" - "</html>"; - char *download_page; - char *location; - struct MHD_Response *resp; - int size; - - LOG_DEBUG ("Processing checkout request reply\n"); - GNUNET_SCHEDULER_cancel (ctx->timeout_task); - ctx->timeout_task = NULL; - download_page = NULL; - location = NULL; - switch (status) - { - case 1: - { - struct GNUNET_CRYPTO_EddsaPublicKey coin_pub; - - GNUNET_assert (GNUNET_SYSERR != - GNUNET_CRYPTO_eddsa_public_key_from_string - (ctx->coin_pub_enc, - strlen (ctx->coin_pub_enc), - &coin_pub)); - /* FIXME: Put the contract into the checkout DB. */ - } - /* redirect with HTTP FOUND 302 to the product download page */ - GNUNET_assert (NULL != obj); - GNUNET_assert (0 < (size = GNUNET_asprintf (&location, - "/download?ref=%s", - ctx->coin_pub_enc))); - GNUNET_assert (0 < (size = GNUNET_asprintf (&download_page, - tmplt_download_page, - location))); - resp = MHD_create_response_from_buffer (size, - download_page, - MHD_RESPMEM_MUST_FREE); - /* IMP: do not free `download_page' */ - GNUNET_assert (NULL != resp); - GNUNET_assert (MHD_NO != MHD_add_response_header (resp, - "Location", - location)); - GNUNET_assert (MHD_YES == MHD_queue_response (ctx->conn, - MHD_HTTP_FOUND, - resp)); - MHD_destroy_response (resp); - GNUNET_free (location); - location = NULL; - resp = NULL; -#if 0 - struct Download *product; - struct GNUNET_DISK_FileHandle *fh; - GNUNET_assert (NULL != (product = ctx->product)); - if (NULL != product->resp) - { - MHD_queue_response (ctx->conn, MHD_HTTP_OK, product->resp); - break; - } - fh = GNUNET_DISK_file_open (product->filename, - GNUNET_DISK_OPEN_READ, - GNUNET_DISK_PERM_USER_READ); - GNUNET_assert (NULL != fh); - GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_handle_size (fh, - &size)); - product->resp = MHD_create_response_from_fd (size, fh->fd); - GNUNET_assert (MHD_NO != MHD_add_response_header (product->resp, - "Content-Type", - "image/jpeg")); - GNUNET_free (fh); - MHD_queue_response (ctx->conn, MHD_HTTP_OK, product->resp); -#endif - - break; - case 2: - send_response_json (ctx->conn, - json_pack ("{s:s}", "status", "pending"), - 200); /* FIXME: Send Image data */ - break; - case 0: - send_response_json (ctx->conn, - json_pack ("{s:s s:s}", - "status", "failed", - "error", (NULL != emsg) ? emsg : "unknown"), - 400); /* FIXME */ - break; - default: - GNUNET_assert (0); /* should never reach */ - } - GNUNET_free (ctx->coin_pub_enc); - GNUNET_free (ctx); - if (GNUNET_SYSERR == poll_mhd ()) - { - GNUNET_break (0); - GNUNET_SCHEDULER_shutdown (); - } -} - -static void -checkout_status_timedout (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct CheckoutCtx *ctx = cls; - - LOG_DEBUG ("Checkout request timed out\n"); - ctx->timeout_task = NULL; - TALER_MINT_deposit_submit_cancel (ctx->dh); - ctx->dh = NULL; - send_response_json (ctx->conn, - json_pack ("{s:s}", "error", "timeout"), - 400); /* FIXME */ - GNUNET_free (ctx->coin_pub_enc); - GNUNET_free (ctx); - EXITIF (GNUNET_SYSERR == poll_mhd ()); - return; - - EXITIF_exit: - GNUNET_SCHEDULER_shutdown (); -} - -static int -handle_checkout (struct MHD_Connection *conn, - json_t *checkout_json) -{ - struct CheckoutCtx *ctx; - const char *pkey_enc; - const char *tid_enc; - const char *emsg; - const char *coin_pub_enc; - const char *coin_sig_enc; - struct Mint *mint; - struct Download *product; - struct GNUNET_CRYPTO_EddsaPublicKey pkey; - struct GNUNET_CRYPTO_EddsaPublicKey coin_pub; - struct GNUNET_CRYPTO_EddsaSignature coin_sig; - uint64_t tid; - uint64_t product_id; - json_error_t jerror; - unsigned int status; - - coin_pub_enc = NULL; - emsg = "Public key of Mint is missing in the request"; - status = MHD_HTTP_BAD_REQUEST; - if (-1 == json_unpack_ex (checkout_json, - &jerror, - 0, - "{s:s s:s s:s s:s}", - "mint_pub", &pkey_enc, - "transaction_id", &tid_enc, - "coin_pub", &coin_pub_enc, - "coin_sig", &coin_sig_enc)) - { - WARN_JSON (jerror); - goto EXITIF_exit; - } - - EXITIF (GNUNET_OK != GNUNET_STRINGS_string_to_data - (tid_enc, strlen (tid_enc), &tid, sizeof (tid))); - tid = GNUNET_ntohll (tid); - - emsg = "Public key of the coin is missing/malformed in the request"; - EXITIF (NULL == coin_pub_enc); - EXITIF (GNUNET_SYSERR == - GNUNET_CRYPTO_eddsa_public_key_from_string (coin_pub_enc, - strlen (coin_pub_enc), - &coin_pub)); - - emsg = "Signature of the coin is missing/malformed in the request"; - EXITIF (NULL == coin_sig_enc); - EXITIF (GNUNET_SYSERR == - GNUNET_STRINGS_string_to_data (coin_sig_enc, strlen (coin_sig_enc), - &coin_sig, sizeof (coin_sig))); - - emsg = "Contract not found"; - status = MHD_HTTP_NOT_FOUND; - LOG_DEBUG ("Looking for product associated with transaction %u\n", tid); - EXITIF (-1 == (product_id = MERCHANT_DB_get_contract_product (db_conn, tid))); - - emsg = "Could not find the downloadable product. Sorry :("; - EXITIF (NULL == (product = find_product (product_id))); - - emsg = "Invalid public key given for a mint"; - EXITIF (52 != strlen (pkey_enc)); - EXITIF (GNUNET_SYSERR == GNUNET_STRINGS_string_to_data (pkey_enc, 52, - &pkey, sizeof (pkey))); - - emsg = "The provided mint is not trusted by us"; - status = MHD_HTTP_FORBIDDEN; - EXITIF (NULL == (mint = - GNUNET_CONTAINER_multipeermap_get (mints_map, - (const struct - GNUNET_PeerIdentity *) - &pkey))); - - LOG_DEBUG ("Creating a new checkout request\n"); - ctx = GNUNET_new (struct CheckoutCtx); - ctx->product = product; - ctx->conn = conn; - ctx->coin_pub_enc = GNUNET_strdup (coin_pub_enc); - ctx->transaction_id = tid; - ctx->coin_pub = coin_pub; - ctx->coin_sig = coin_sig; - /* FIXME: parse amount */ - /* ctx->amount = ?? */ - ctx->dh = TALER_MINT_deposit_submit_json (mint->conn, - checkout_status, - ctx, - checkout_json); - ctx->timeout_task = GNUNET_SCHEDULER_add_delayed - (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3), - &checkout_status_timedout, ctx); - return MHD_YES; - - EXITIF_exit: - json_decref (checkout_json); - return send_response_json (conn, - json_pack ("{s:s s:s}", - "status", "failed", - "error", emsg), - status); -} - -/** - * A client has requested the given url using the given method - * (#MHD_HTTP_METHOD_GET, #MHD_HTTP_METHOD_PUT, - * #MHD_HTTP_METHOD_DELETE, #MHD_HTTP_METHOD_POST, etc). The callback - * must call MHD callbacks to provide content to give back to the - * client and return an HTTP status code (i.e. #MHD_HTTP_OK, - * #MHD_HTTP_NOT_FOUND, etc.). - * - * @param cls argument given together with the function - * pointer when the handler was registered with MHD - * @param url the requested url - * @param method the HTTP method used (#MHD_HTTP_METHOD_GET, - * #MHD_HTTP_METHOD_PUT, etc.) - * @param version the HTTP version string (i.e. - * #MHD_HTTP_VERSION_1_1) - * @param upload_data the data being uploaded (excluding HEADERS, - * for a POST that fits into memory and that is encoded - * with a supported encoding, the POST data will NOT be - * given in upload_data and is instead available as - * part of #MHD_get_connection_values; very large POST - * data *will* be made available incrementally in - * @a upload_data) - * @param upload_data_size set initially to the size of the - * @a upload_data provided; the method must update this - * value to the number of bytes NOT processed; - * @param con_cls pointer that the callback can set to some - * address and that will be preserved by MHD for future - * calls for this request; since the access handler may - * be called many times (i.e., for a PUT/POST operation - * with plenty of upload data) this allows the application - * to easily associate some request-specific state. - * If necessary, this state can be cleaned up in the - * global #MHD_RequestCompletedCallback (which - * can be set with the #MHD_OPTION_NOTIFY_COMPLETED). - * Initially, `*con_cls` will be NULL. - * @return #MHD_YES if the connection was handled successfully, - * #MHD_NO if the socket must be closed due to a serios - * error while handling the request - */ -static int -url_handler (void *cls, - struct MHD_Connection *connection, - const char *url, - const char *method, - const char *version, - const char *upload_data, - size_t *upload_data_size, - void **con_cls) -{ -#define URL_PRODUCTS "/products" -#define URL_CONTRACT "/contract" -#define URL_CHECKOUT "/checkout" -#define URL_HTTPTEST "/httptest" -#define URL_DOWNLOAD "/download" -#define STR_404_NOTFOUND "The requested resource is not found" - struct MHD_Response *resp; - int no_destroy; - unsigned int status; - - resp = NULL; - status = 404; - no_destroy = 0; - LOG_DEBUG ("request for URL `%s'\n", url); - - if (0 == strncasecmp (url, URL_PRODUCTS, sizeof (URL_PRODUCTS))) - { - /* parse for /contract */ - if (0 == strcmp (MHD_HTTP_METHOD_GET, method)) - { - resp = list_products_resp; - no_destroy = 1; - status = 200; - } - else - GNUNET_break (0); /* FIXME: implement for post */ - } - - if (0 == strncasecmp (url, URL_CONTRACT, sizeof (URL_CONTRACT))) - { - /* parse for /contract */ - if (0 == strcmp (MHD_HTTP_METHOD_GET, method)) - status = handle_get_contract (connection, &resp); - else - GNUNET_break (0); /* FIXME: implement for post */ - } - - if (0 == strncasecmp (url, URL_CHECKOUT, sizeof (URL_CHECKOUT))) - { - json_t *checkout_obj; - int ret; - /* parse for /checkout */ - ret = process_post_json (connection, - con_cls, - upload_data, - upload_data_size, - &checkout_obj); - if (GNUNET_SYSERR == ret) - return MHD_NO; - if (GNUNET_NO == ret) - return MHD_YES; - /* Handle the response in the request handler */ - ret = handle_checkout (connection, checkout_obj); - return ret; - } - - if (0 == strncasecmp (url, URL_HTTPTEST, sizeof (URL_HTTPTEST))) - { - static char page[]="\ -<!DOCTYPE html> \ -<html><title>HTTP Test page</title><body><center><h3>HTTP Test page</h3> \ -</center></body></html>"; - resp = MHD_create_response_from_buffer (sizeof (page) - 1, - page, - MHD_RESPMEM_PERSISTENT); - EXITIF (NULL == resp); - } - - if ((0 == strncasecmp (url, URL_DOWNLOAD, sizeof (URL_DOWNLOAD))) - && (0 == strcmp (MHD_HTTP_METHOD_GET, method))) - { - status = handle_download (connection, &resp); - if (status != MHD_HTTP_OK) - no_destroy = 1; - } - if (NULL != resp) - { - EXITIF (MHD_YES != MHD_queue_response (connection, status, resp)); - if (!no_destroy) - MHD_destroy_response (resp); - } - else - EXITIF (GNUNET_OK != failure_resp (connection, status)); - return MHD_YES; - - EXITIF_exit: - result = GNUNET_SYSERR; - GNUNET_SCHEDULER_shutdown (); - return MHD_NO; -} - - -/** - * Callback for catching serious error conditions from MHD. - * - * @param cls user specified value - * @param file where the error occured - * @param line where the error occured - * @param reason error detail, may be NULL - */ -static void -mhd_panic_cb (void *cls, - const char *file, - unsigned int line, - const char *reason) -{ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "MHD panicked at %s:%u: %s", - file, line, reason); - result = GNUNET_SYSERR; - GNUNET_SCHEDULER_shutdown (); -} - -/** - * Function called with a filename. - * - * @param cls closure - * @param filename complete filename (absolute path) - * @return #GNUNET_OK to continue to iterate, - * #GNUNET_NO to stop iteration with no error, - * #GNUNET_SYSERR to abort iteration with error! - */ -static int -add_download_file (void *cls, const char *filename) -{ - struct Download *dwn; - - dwn = GNUNET_new (struct Download); - dwn->filename = GNUNET_strdup (filename); - dwn->id = ndownloads++; - GNUNET_CONTAINER_DLL_insert (dwn_head, dwn_tail, dwn); - return GNUNET_OK; -} - - -/** - * Function to build a MHD response object to list products - * - * @return GNUNET_OK upon success; GNUNET_SYSERR otherwise - */ -static int -build_list_product_response () -{ - const char *header = "\ -<!DOCTYPE html> \ -<html><title>Products List</title> \ -<body><center><ol>"; - char **partials; - const char *footer = "</ol></center></body></html>"; - char *page; - struct Download *dwn; - size_t size; - unsigned int cnt; - int psize; - unsigned int header_size; - unsigned int footer_size; - unsigned int *partial_sizes; - int ret; - - ret = GNUNET_SYSERR; - GNUNET_assert (NULL == list_products_resp); - header_size = strlen (header); - footer_size = strlen (footer); - size = header_size; - size += footer_size; - partials = GNUNET_malloc (sizeof (char *) * ndownloads); - partial_sizes = GNUNET_malloc (sizeof (unsigned int) * ndownloads); - EXITIF (0 == ndownloads); - for (cnt = 0, dwn = dwn_head; cnt < ndownloads; cnt++, dwn=dwn->next) - { - EXITIF (NULL == dwn); - psize = GNUNET_asprintf (&partials[cnt], - "<li><a href=\"/contract?product=%u\">%s</a></li>", - cnt, - GNUNET_STRINGS_get_short_name (dwn->filename)); - EXITIF (psize < 0); - size += psize; - partial_sizes [cnt] = psize; - } - page = GNUNET_malloc (size); - size = 0; - (void) memcpy (page, header, header_size); - size += header_size; - for (cnt = 0; cnt < ndownloads; cnt++) - { - (void) memcpy (page + size, partials[cnt], partial_sizes[cnt]); - size += partial_sizes[cnt]; - } - (void) memcpy (page + size, footer, footer_size); - size += footer_size; - list_products_resp = MHD_create_response_from_buffer (size, page, MHD_RESPMEM_MUST_FREE); - ret = GNUNET_OK; - - EXITIF_exit: - for (cnt = 0; cnt < ndownloads; cnt++) - GNUNET_free_non_null (partials[cnt]); - GNUNET_free_non_null (partials); - GNUNET_free_non_null (partial_sizes); - return ret; -} - -/** - * Main function that will be run by the scheduler. - * - * @param cls closure - * @param args remaining command-line arguments - * @param cfgfile name of the configuration file used (for saving, can be NULL!) - * @param config configuration - */ -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *config) -{ - char *keyfile; - struct MERCHANT_MintInfo *mint_infos; - unsigned int nmints; - unsigned int cnt; - - result = GNUNET_SYSERR; - keyfile = NULL; - mint_infos = NULL; - shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, - &do_shutdown, NULL); - if (NULL == data_dir) - { - LOG_ERROR ("Data directory for download files is missing. It can be given with the `-d' option\n"); - goto EXITIF_exit; - } - EXITIF (GNUNET_SYSERR == (nmints = TALER_MERCHANT_parse_mints (config, - &mint_infos))); - EXITIF (NULL == (wire = TALER_MERCHANT_parse_wireformat_sepa (config))); - EXITIF (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (config, - "merchant", - "KEYFILE", - &keyfile)); - EXITIF (NULL == (privkey = GNUNET_CRYPTO_eddsa_key_create_from_file (keyfile))); - EXITIF (0 == GNUNET_DISK_directory_scan (data_dir, - &add_download_file, - NULL)); - EXITIF (GNUNET_SYSERR == build_list_product_response ()); - EXITIF (NULL == (db_conn = MERCHANT_DB_connect (config))); - EXITIF (GNUNET_OK != MERCHANT_DB_initialise (db_conn, dry)); - EXITIF (GNUNET_SYSERR == - GNUNET_CONFIGURATION_get_value_number (config, - "merchant", - "port", - &port)); - EXITIF (GNUNET_SYSERR == - GNUNET_CONFIGURATION_get_value_string (config, - "merchant", - "hostname", - &hostname)); - EXITIF (NULL == (mctx = TALER_MINT_init ())); - EXITIF (NULL == (mints_map = GNUNET_CONTAINER_multipeermap_create (nmints, GNUNET_YES))); - for (cnt = 0; cnt < nmints; cnt++) - { - struct Mint *mint; - - mint = GNUNET_new (struct Mint); - mint->pubkey = mint_infos[cnt].pubkey; - mint->conn = TALER_MINT_connect (mctx, - mint_infos[cnt].hostname, - mint_infos[cnt].port, - &mint->pubkey); - EXITIF (NULL == mint->conn); - EXITIF (GNUNET_SYSERR == GNUNET_CONTAINER_multipeermap_put - (mints_map, - (struct GNUNET_PeerIdentity *) &mint->pubkey, - mint, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); - } - MHD_set_panic_func (&mhd_panic_cb, NULL); - mhd = MHD_start_daemon (MHD_USE_DEBUG, //| MHD_USE_TCP_FASTOPEN, - (unsigned short) port, - NULL, NULL, - &url_handler, NULL, - //MHD_OPTION_TCP_FASTOPEN_QUEUE_SIZE, - //(unsigned int) 16, - MHD_OPTION_END); - EXITIF (NULL == mhd); - EXITIF (GNUNET_SYSERR == poll_mhd ()); - GNUNET_CRYPTO_hash (wire, sizeof (*wire), &h_wire); - result = GNUNET_OK; - - EXITIF_exit: - if (NULL != mint_infos) - { - for (cnt = 0; cnt < nmints; cnt++) - GNUNET_free (mint_infos[cnt].hostname); - GNUNET_free (mint_infos); - } - GNUNET_free_non_null (keyfile); - if (GNUNET_OK != result) - GNUNET_SCHEDULER_shutdown (); -} - - -/** - * The main function of the serve tool - * - * @param argc number of arguments from the command line - * @param argv command line arguments - * @return 0 ok, 1 on error - */ -int -main (int argc, char *const *argv) -{ - static const struct GNUNET_GETOPT_CommandLineOption options[] = { - {'t', "temp", NULL, - gettext_noop ("Use temporary database tables"), GNUNET_NO, - &GNUNET_GETOPT_set_one, &dry}, - {'d', "dir", "DIRECTORY", - gettext_noop ("Directory of the data files to serve"), GNUNET_YES, - &GNUNET_GETOPT_set_string, &data_dir}, - GNUNET_GETOPT_OPTION_END - }; - - if (GNUNET_OK != - GNUNET_PROGRAM_run (argc, argv, - "taler-merchant-serve", - "Serve merchant's HTTP interface", - options, &run, NULL)) - return 3; - return (GNUNET_OK == result) ? 0 : 1; -} diff --git a/src/merchant/test_merchant.c b/src/merchant/test_merchant.c deleted file mode 100644 index bcec09ae..00000000 --- a/src/merchant/test_merchant.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - This file is part of TALER - (C) 2014 Christian Grothoff (and other contributing authors) - - 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 merchant/test_merchant.c - * @brief File to test merchant-internal helper functions. - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include <gnunet/gnunet_util_lib.h> -#include "merchant.h" - -/** - * Array of parsed mints - */ -struct MERCHANT_MintInfo *mints; - -/** - * Number of mints in the above array - */ -int n_mints; - -/** - * Test result - */ -static int result; - -static void -do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - unsigned int cnt; - - for (cnt=0; cnt < n_mints; cnt++) - GNUNET_free (mints[cnt].hostname); - GNUNET_free_non_null (mints); - mints = 0; -} - - -/** - * Main function that will be run by the scheduler. - * - * @param cls closure - * @param args remaining command-line arguments - * @param cfgfile name of the configuration file used (for saving, can be NULL!) - * @param config configuration - */ -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *config) -{ - - mints = NULL; - n_mints = GNUNET_SYSERR; - n_mints = TALER_MERCHANT_parse_mints (config, &mints); - GNUNET_assert (GNUNET_SYSERR != n_mints); - GNUNET_assert (NULL != mints); - result = GNUNET_OK; - GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); -} - -int -main (int argc, char *const argv[]) -{ - char *argv2[] = { - "test-merchant", - "-c", "test_merchant.conf", - NULL - }; - static const struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - - result = GNUNET_SYSERR; - if (GNUNET_OK != - GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, - argv2, "test-merchant", - "File to test merchant-internal helper functions.", - options, &run, NULL)) - return 3; - return (GNUNET_OK == result) ? 0 : 1; -} diff --git a/src/merchant/test_merchant.conf b/src/merchant/test_merchant.conf deleted file mode 100644 index 7d32769a..00000000 --- a/src/merchant/test_merchant.conf +++ /dev/null @@ -1,36 +0,0 @@ -# Sample configuration file test-merchant testcase -[merchant] -PORT = 4251 -HOSTNAME = localhost -# List of mints the merchant trusts delimited by a single space -TRUSTED_MINTS = nayapaisa - -#nayapaisa nyadirahim - -# Our secret key file -KEYFILE = test_merchant.ecc - -[mint-taler] -HOSTNAME = localhost -PORT = 4241 -PUBKEY = 8MF3D4V40K4J7654Q7NT3YHZVJ22SJAMBG07GEQ0QSXHWF4M9X6G - -[mint-nayapaisa] -HOSTNAME = localhost -PORT = 4241 -# The public key of this mint -PUBKEY = 6ZE0HEY2M0FWP61M0470HYBF4K6RRD5DP54372PD2TN9N9VX2VJG - -[mint-nyadirahim] -HOSTNAME = nyadirahim.org -PORT = 4241 -# The public key of this mint -PUBKEY = 7995WKK71KPKTBBMA5BHNBSZFGNRZPYNXDJMQ8EK86V9598H03TG - -[merchant-db] -CONFIG = postgres:///taler - -[wire-sepa] -IBAN = DE67830654080004822650 -NAME = GNUNET E.V -BIC = GENODEF1SRL diff --git a/src/merchant/test_merchant.ecc b/src/merchant/test_merchant.ecc deleted file mode 100644 index ac8ee6e9..00000000 --- a/src/merchant/test_merchant.ecc +++ /dev/null @@ -1,2 +0,0 @@ -MY{.ӂce -ف
\ No newline at end of file diff --git a/src/merchant/test_merchant_db.c b/src/merchant/test_merchant_db.c deleted file mode 100644 index caaa1be4..00000000 --- a/src/merchant/test_merchant_db.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - This file is part of TALER - (C) 2014 Christian Grothoff (and other contributing authors) - - 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 merchant/test_merchant_db.c - * @brief File to test merchant database helper functions. - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include <gnunet/gnunet_util_lib.h> -#include <taler/taler_util.h> -#include "merchant_db.h" - -/** - * Shorthand for exit jumps. - */ -#define EXITIF(cond) \ - do { \ - if (cond) { GNUNET_break (0); goto EXITIF_exit; } \ - } while (0) - -/** - * Macro to round microseconds to seconds in GNUNET_TIME_* structs. - */ -#define ROUND_TO_SECS(name,us_field) name.us_field -= name.us_field % (1000 * 1000); - -/** - * The database handle - */ -PGconn *conn; - -/** - * Test result - */ -static int result; - -static void -do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - if (NULL != conn) - MERCHANT_DB_disconnect (conn); - conn = NULL; -} - - -/** - * Main function that will be run by the scheduler. - * - * @param cls closure - * @param args remaining command-line arguments - * @param cfgfile name of the configuration file used (for saving, can be NULL!) - * @param config configuration - */ -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *config) -{ - struct GNUNET_TIME_Absolute expiry; - struct TALER_Amount amount; - char *desc = "A contract from GNUnet e.V to say a big Thank You for a donation of the aforementioned amount."; - uint64_t nounce; - uint64_t product; - long long transaction_id; - - conn = MERCHANT_DB_connect (config); - EXITIF (NULL == conn); - GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); - EXITIF (GNUNET_OK != MERCHANT_DB_initialise (conn, GNUNET_YES)); - expiry = GNUNET_TIME_absolute_get (); - expiry = GNUNET_TIME_absolute_add (expiry, GNUNET_TIME_UNIT_DAYS); - ROUND_TO_SECS (expiry, abs_value_us); - amount.value = 1; - amount.fraction = 0; - nounce = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX); - product = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX); - product &= (UINT64_MAX >> 1); - EXITIF (-1 == (transaction_id = MERCHANT_DB_contract_create (conn, - expiry, - &amount, - desc, - nounce, - product))); - { - struct GNUNET_CRYPTO_EddsaPublicKey coin_pub; - struct GNUNET_CRYPTO_EddsaSignature coin_sig; - long long paid_product; - - GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, - &coin_pub, sizeof (coin_pub)); - GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, - &coin_sig, sizeof (coin_sig)); - EXITIF (GNUNET_SYSERR == MERCHANT_DB_checkout_create (conn, - &coin_pub, - transaction_id, - &amount, - &coin_sig)); - EXITIF (-1 == (paid_product = MERCHANT_DB_get_checkout_product (conn, - &coin_pub))); - EXITIF (paid_product < 0); - EXITIF (((uint64_t) paid_product) != product); - /* We should get -1 for product if a coin is not paid to us */ - GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, - &coin_pub, sizeof (coin_pub)); - EXITIF (-1 != (product = MERCHANT_DB_get_checkout_product (conn, - &coin_pub))); - } - result = GNUNET_OK; - - EXITIF_exit: - return; -} - -int -main (int argc, char *const argv[]) -{ - char *argv2[] = { - "test-merchant-db", - "-c", "test_merchant.conf", - NULL - }; - static const struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - - result = GNUNET_SYSERR; - if (GNUNET_OK != - GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, - argv2, "test-merchant-db", - "File to test merchant database helper functions.", - options, &run, NULL)) - return 3; - return (GNUNET_OK == result) ? 0 : 1; -} |