From d185fd574e54c82799d3519bf774b50d421fa370 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 24 Nov 2015 15:59:05 +0100 Subject: rearranging code to (1) satisfy naming and coding conventions a bit more, and (2) provide a task handle for each mint, which may fix #4042 --- src/backend/Makefile.am | 1 - src/backend/merchant.c | 183 ------------- src/backend/taler-merchant-httpd.c | 403 +++++++++++++++++++++------- src/backend/taler-merchant-httpd.h | 114 +++++++- src/backend/taler-merchant-httpd_contract.c | 20 +- src/backend/taler-merchant-httpd_pay.c | 57 +++- src/backend/taler-mint-httpd_parsing.c | 6 +- 7 files changed, 465 insertions(+), 319 deletions(-) (limited to 'src/backend') diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am index 08601781..c1d71a68 100644 --- a/src/backend/Makefile.am +++ b/src/backend/Makefile.am @@ -6,7 +6,6 @@ bin_PROGRAMS = \ taler_merchant_httpd_SOURCES = \ taler-merchant-httpd.c taler-merchant-httpd.h \ - merchant.c merchant.h \ ../backend-lib/merchant_db.c ../backend-lib/merchant_db.h \ taler-mint-httpd_parsing.c taler-mint-httpd_parsing.h \ taler-mint-httpd_responses.c taler-mint-httpd_responses.h \ diff --git a/src/backend/merchant.c b/src/backend/merchant.c index 02b37fb8..b0ab811f 100644 --- a/src/backend/merchant.c +++ b/src/backend/merchant.c @@ -31,189 +31,6 @@ } 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_Mint **mints) -{ - char *mints_str; - char *token_nf; /* do no free (nf) */ - char *mint_section; - char *mint_hostname; - struct MERCHANT_Mint *r_mints; - struct MERCHANT_Mint mint; - unsigned int cnt; - int OK; - - OK = 0; - mints_str = NULL; - token_nf = NULL; - mint_section = NULL; - mint_hostname = 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)); - mint.hostname = mint_hostname; - GNUNET_array_append (r_mints, cnt, mint); - mint_hostname = 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); - if (!OK) - { - GNUNET_free_non_null (r_mints); - return GNUNET_SYSERR; - } - - *mints = r_mints; - return cnt; -} - -/** - * Parses auditors from the configuration. - * - * @param cfg the configuration - * @param mints the array of auditors upon successful parsing. Will be NULL upon - * error. - * @return the number of auditors in the above array; GNUNET_SYSERR upon error in - * parsing. - */ -int -TALER_MERCHANT_parse_auditors (const struct GNUNET_CONFIGURATION_Handle *cfg, - struct MERCHANT_Auditor **auditors) -{ - char *auditors_str; - char *token_nf; /* do no free (nf) */ - char *auditor_section; - char *auditor_name; - struct MERCHANT_Auditor *r_auditors; - struct MERCHANT_Auditor auditor; - unsigned int cnt; - int OK; - - OK = 0; - auditors_str = NULL; - token_nf = NULL; - auditor_section = NULL; - auditor_name = NULL; - r_auditors = NULL; - cnt = 0; - EXITIF (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, - "merchant", - "AUDITORS", - &auditors_str)); - for (token_nf = strtok (auditors_str, " "); - NULL != token_nf; - token_nf = strtok (NULL, " ")) - { - GNUNET_assert (0 < GNUNET_asprintf (&auditor_section, - "auditor-%s", token_nf)); - EXITIF (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, - auditor_section, - "NAME", - &auditor_name)); - auditor.name = auditor_name; - GNUNET_array_append (r_auditors, cnt, auditor); - auditor_name = NULL; - GNUNET_free (auditor_section); - auditor_section = NULL; - } - OK = 1; - - EXITIF_exit: - GNUNET_free_non_null (auditors_str); - GNUNET_free_non_null (auditor_section); - GNUNET_free_non_null (auditor_name); - if (!OK) - { - GNUNET_free_non_null (r_auditors); - return GNUNET_SYSERR; - } - - *auditors = r_auditors; - 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/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c index ba359bd1..d135a7c5 100644 --- a/src/backend/taler-merchant-httpd.c +++ b/src/backend/taler-merchant-httpd.c @@ -1,6 +1,6 @@ /* This file is part of TALER - (C) 2014 Christian Grothoff (and other contributing authors) + (C) 2014, 2015 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 @@ -30,14 +30,29 @@ #include #include "taler-mint-httpd_parsing.h" #include "taler-mint-httpd_responses.h" -#include "merchant_db.h" -#include "merchant.h" -#include "taler_merchant_lib.h" +#include "taler_merchantdb_lib.h" #include "taler-merchant-httpd.h" #include "taler-mint-httpd_mhd.h" #include "taler-merchant-httpd_contract.h" #include "taler-merchant-httpd_pay.h" + + +/** + * Merchant's private key + */ +struct GNUNET_CRYPTO_EddsaPrivateKey *privkey; + +/** + * Our wireformat + */ +struct MERCHANT_WIREFORMAT_Sepa *wire; + +/** + * Salt used to hash the wire object + */ +long long salt; + /** * Our hostname */ @@ -48,15 +63,10 @@ static char *hostname; */ static long long unsigned port; -/** - * Merchant's private key - */ -struct GNUNET_CRYPTO_EddsaPrivateKey *privkey; - /** * File holding the merchant's private key */ -char *keyfile; +static char *keyfile; /** * This value tells the mint by which date this merchant would like @@ -65,14 +75,14 @@ char *keyfile; struct GNUNET_TIME_Relative edate_delay; /** - * To make 'TMH_PARSE_navigate_json ()' compile + * Which currency is supported by this merchant? */ -char *TMH_mint_currency_string; +char *TMH_merchant_currency_string; /** - * Trusted mints + * Trusted mints (FIXME: they are NOT all trusted!). */ -struct MERCHANT_Mint *mints; +struct MERCHANT_Mint **mints; /** * Active auditors @@ -90,22 +100,7 @@ static struct GNUNET_SCHEDULER_Task *shutdown_task; static struct GNUNET_SCHEDULER_Task *mhd_task; /** - * Context "poller" identifier - */ -struct GNUNET_SCHEDULER_Task *poller_task; - -/** - * Our wireformat - */ -struct MERCHANT_WIREFORMAT_Sepa *wire; - -/** - * Salt used to hash the wire object - */ -long long salt; - -/** - * The number of accepted mints + * Length of the #mints array. */ unsigned int nmints; @@ -134,6 +129,36 @@ PGconn *db_conn; */ static struct MHD_Daemon *mhd; + +/** + * Take the global wire details and return a JSON containing them, + * compliantly with the Taler's API. + * + * @param wire the merchant's wire details + * @param salt the nounce for hashing the wire details with + * @param edate when the beneficiary wants this transfer to take place + * @return JSON representation of the wire details, NULL upon errors + */ +json_t * +MERCHANT_get_wire_json (const struct MERCHANT_WIREFORMAT_Sepa *wire, + uint64_t salt) + +{ + json_t *root; + json_t *j_salt; + + j_salt = json_integer (salt); + if (NULL == (root = json_pack ("{s:s, s:s, s:s, s:s, s:I}", + "type", "SEPA", + "IBAN", wire->iban, + "name", wire->name, + "bic", wire->bic, + "r", json_integer_value (j_salt)))) + return NULL; + return root; +} + + /** * A client has requested the given url using the given method * (#MHD_HTTP_METHOD_GET, #MHD_HTTP_METHOD_PUT, @@ -255,6 +280,7 @@ url_handler (void *cls, } + /** * Function called with information about who is auditing * a particular mint and what key the mint is using. @@ -288,7 +314,6 @@ keys_mgmt_cb (void *cls, const struct TALER_MINT_Keys *keys) } else printf ("no keys gotten\n"); - } @@ -306,14 +331,13 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) for (cnt = 0; cnt < nmints; cnt++) { - if (NULL != mints[cnt].conn) - TALER_MINT_disconnect (mints[cnt].conn); - - } - if (NULL != poller_task) - { - GNUNET_SCHEDULER_cancel (poller_task); - poller_task = NULL; + if (NULL != mints[cnt]->conn) + TALER_MINT_disconnect (mints[cnt]->conn); + if (NULL != mints[cnt]->poller_task) + { + GNUNET_SCHEDULER_cancel (mints[cnt]->poller_task); + mints[cnt]->poller_task = NULL; + } } if (NULL != mhd_task) { @@ -338,13 +362,14 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) /** * Task that runs the context's event loop using the GNUnet scheduler. * - * @param cls mint context + * @param cls a `struct MERCHANT_Mint *` * @param tc scheduler context (unused) */ void context_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { + struct MERCHANT_Mint *mint = cls; long timeout; int max_fd; fd_set read_fd_set; @@ -353,17 +378,15 @@ context_task (void *cls, struct GNUNET_NETWORK_FDSet *rs; struct GNUNET_NETWORK_FDSet *ws; struct GNUNET_TIME_Relative delay; - struct TALER_MINT_Context *ctx; - ctx = (struct TALER_MINT_Context *) cls; - poller_task = NULL; - TALER_MINT_perform (ctx); + mint->poller_task = NULL; + TALER_MINT_perform (mint->ctx); max_fd = -1; timeout = -1; FD_ZERO (&read_fd_set); FD_ZERO (&write_fd_set); FD_ZERO (&except_fd_set); - TALER_MINT_get_select_info (ctx, + TALER_MINT_get_select_info (mint->ctx, &read_fd_set, &write_fd_set, &except_fd_set, @@ -383,13 +406,13 @@ context_task (void *cls, GNUNET_NETWORK_fdset_copy_native (ws, &write_fd_set, max_fd + 1); - poller_task = - GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, - delay, - rs, - ws, - &context_task, - cls); + mint->poller_task = + GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, + delay, + rs, + ws, + &context_task, + mint); GNUNET_NETWORK_fdset_destroy (rs); GNUNET_NETWORK_fdset_destroy (ws); } @@ -460,6 +483,191 @@ TM_trigger_daemon () } +/** + * Parses mints listed in the configuration. + * + * @param cfg the configuration + * @return the number of mints in the above array; #GNUNET_SYSERR upon error in + * parsing. + */ +static int +parse_mints (const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + char *mints_str; + char *token_nf; /* do no free (nf) */ + char *mint_section; + char *mint_hostname; + struct MERCHANT_Mint **r_mints; + struct MERCHANT_Mint *mint; + unsigned int cnt; + int ok; + + ok = 0; + mints_str = NULL; + token_nf = NULL; + mint_section = NULL; + mint_hostname = 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)); + mint = GNUNET_new (struct MERCHANT_Mint); + mint->hostname = mint_hostname; + GNUNET_array_append (r_mints, + cnt, + mint); + 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); + if (! ok) + { + GNUNET_free_non_null (r_mints); + return GNUNET_SYSERR; + } + mints = r_mints; + return cnt; +} + + +/** + * Parses auditors from the configuration. + * + * @param cfg the configuration + * @param mints the array of auditors upon successful parsing. Will be NULL upon + * error. + * @return the number of auditors in the above array; #GNUNET_SYSERR upon error in + * parsing. + */ +static int +parse_auditors (const struct GNUNET_CONFIGURATION_Handle *cfg, + struct MERCHANT_Auditor **auditors) +{ + char *auditors_str; + char *token_nf; /* do no free (nf) */ + char *auditor_section; + char *auditor_name; + struct MERCHANT_Auditor *r_auditors; + struct MERCHANT_Auditor auditor; + unsigned int cnt; + int ok; + + ok = 0; + auditors_str = NULL; + token_nf = NULL; + auditor_section = NULL; + auditor_name = NULL; + r_auditors = NULL; + cnt = 0; + EXITIF (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + "merchant", + "AUDITORS", + &auditors_str)); + for (token_nf = strtok (auditors_str, " "); + NULL != token_nf; + token_nf = strtok (NULL, " ")) + { + GNUNET_assert (0 < GNUNET_asprintf (&auditor_section, + "auditor-%s", token_nf)); + EXITIF (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + auditor_section, + "NAME", + &auditor_name)); + auditor.name = auditor_name; + GNUNET_array_append (r_auditors, cnt, auditor); + auditor_name = NULL; + GNUNET_free (auditor_section); + auditor_section = NULL; + } + ok = 1; + + EXITIF_exit: + GNUNET_free_non_null (auditors_str); + GNUNET_free_non_null (auditor_section); + GNUNET_free_non_null (auditor_name); + if (! ok) + { + GNUNET_free_non_null (r_auditors); + return GNUNET_SYSERR; + } + + *auditors = r_auditors; + 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 + */ +static struct MERCHANT_WIREFORMAT_Sepa * +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 + */ +static void +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); +} + + /** * Function that queries MHD's select sets and * starts the task waiting for them. @@ -510,7 +718,6 @@ prepare_daemon () } - /** * Main function that will be run by the scheduler. * @@ -521,42 +728,42 @@ prepare_daemon () * @param config configuration */ void -run (void *cls, char *const *args, const char *cfgfile, +run (void *cls, + char *const *args, + const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *config) { - unsigned int cnt; - mints = NULL; - keyfile = NULL; + result = GNUNET_SYSERR; shutdown_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, - &do_shutdown, - NULL); + GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, + &do_shutdown, + NULL); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "merchant launched\n"); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "merchant launched\n"); EXITIF (GNUNET_SYSERR == - (nmints = - TALER_MERCHANT_parse_mints (config, - &mints))); + (nmints = + parse_mints (config))); EXITIF (GNUNET_SYSERR == - (nauditors = - TALER_MERCHANT_parse_auditors (config, - &auditors))); + (nauditors = + parse_auditors (config, + &auditors))); EXITIF (NULL == - (wire = - TALER_MERCHANT_parse_wireformat_sepa (config))); + (wire = + parse_wireformat_sepa (config))); EXITIF (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (config, - "merchant", - "KEYFILE", - &keyfile)); + GNUNET_CONFIGURATION_get_value_filename (config, + "merchant", + "KEYFILE", + &keyfile)); EXITIF (NULL == - (privkey = - GNUNET_CRYPTO_eddsa_key_create_from_file (keyfile))); + (privkey = + GNUNET_CRYPTO_eddsa_key_create_from_file (keyfile))); EXITIF (NULL == - (db_conn = MERCHANT_DB_connect (config))); + (db_conn = MERCHANT_DB_connect (config))); EXITIF (GNUNET_OK != MERCHANT_DB_initialize (db_conn, dry)); EXITIF (GNUNET_SYSERR == @@ -573,7 +780,7 @@ run (void *cls, char *const *args, const char *cfgfile, GNUNET_CONFIGURATION_get_value_string (config, "merchant", "CURRENCY", - &TMH_mint_currency_string)); + &TMH_merchant_currency_string)); EXITIF (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (config, @@ -586,16 +793,17 @@ run (void *cls, char *const *args, const char *cfgfile, for (cnt = 0; cnt < nmints; cnt++) { - EXITIF (NULL == (mints[cnt].ctx = TALER_MINT_init ())); - mints[cnt].pending = 1; - mints[cnt].conn = TALER_MINT_connect (mints[cnt].ctx, - mints[cnt].hostname, - &keys_mgmt_cb, - &mints[cnt], - TALER_MINT_OPTION_END); - EXITIF (NULL == mints[cnt].conn); - poller_task = - GNUNET_SCHEDULER_add_now (&context_task, mints[cnt].ctx); + EXITIF (NULL == (mints[cnt]->ctx = TALER_MINT_init ())); + mints[cnt]->pending = 1; + mints[cnt]->conn = TALER_MINT_connect (mints[cnt]->ctx, + mints[cnt]->hostname, + &keys_mgmt_cb, + mints[cnt], + TALER_MINT_OPTION_END); + EXITIF (NULL == mints[cnt]->conn); + mints[cnt]->poller_task = + GNUNET_SCHEDULER_add_now (&context_task, + mints[cnt]); } mhd = MHD_start_daemon (MHD_USE_SUSPEND_RESUME, @@ -609,15 +817,15 @@ run (void *cls, char *const *args, const char *cfgfile, result = GNUNET_OK; mhd_task = prepare_daemon (); - EXITIF_exit: - if (GNUNET_OK != result) - GNUNET_SCHEDULER_shutdown (); + EXITIF_exit: + if (GNUNET_OK != result) + GNUNET_SCHEDULER_shutdown (); GNUNET_free_non_null (keyfile); - if (GNUNET_OK != result) - GNUNET_SCHEDULER_shutdown (); - + if (GNUNET_OK != result) + GNUNET_SCHEDULER_shutdown (); } + /** * The main function of the serve tool * @@ -628,14 +836,12 @@ run (void *cls, char *const *args, const char *cfgfile, int main (int argc, char *const *argv) { - - static const struct GNUNET_GETOPT_CommandLineOption options[] = { + static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'t', "temp", NULL, gettext_noop ("Use temporary database tables"), GNUNET_NO, &GNUNET_GETOPT_set_one, &dry}, - GNUNET_GETOPT_OPTION_END - }; - + GNUNET_GETOPT_OPTION_END + }; if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, @@ -644,5 +850,4 @@ main (int argc, char *const *argv) options, &run, NULL)) return 3; return (GNUNET_OK == result) ? 0 : 1; - } diff --git a/src/backend/taler-merchant-httpd.h b/src/backend/taler-merchant-httpd.h index b60d91bd..7dc1b647 100644 --- a/src/backend/taler-merchant-httpd.h +++ b/src/backend/taler-merchant-httpd.h @@ -19,13 +19,86 @@ * @author Marcello Stanisci */ -#include "merchant_db.h" +#include "platform.h" +#include "taler_merchantdb_lib.h" /** - * Kick MHD to run now, to be called after MHD_resume_connection(). + * Shorthand for exit jumps. */ -void -TM_trigger_daemon (void); +#define EXITIF(cond) \ + do { \ + if (cond) { GNUNET_break (0); goto EXITIF_exit; } \ + } while (0) + + +/** + * Mint + */ +struct MERCHANT_Mint +{ + /** + * Hostname + */ + char *hostname; + + /** + * A connection to this mint + */ + struct TALER_MINT_Handle *conn; + + /** + * This mint's context (useful to the event loop) + */ + struct TALER_MINT_Context *ctx; + + /** + * Task we use to drive the interaction with this mint. + */ + struct GNUNET_SCHEDULER_Task *poller_task; + + /** + * Flag which indicates whether some HTTP transfer between + * this merchant and the mint is still ongoing + */ + int pending; + +}; + + +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; +}; + + +struct MERCHANT_Auditor +{ + /** + * Auditor's legal name + */ + char *name; + +}; + struct TM_HandlerContext; @@ -48,10 +121,15 @@ struct TM_HandlerContext }; -extern struct MERCHANT_Mint *mints; extern struct MERCHANT_WIREFORMAT_Sepa *wire; + +extern struct MERCHANT_Mint **mints; + +extern struct GNUNET_CRYPTO_EddsaPrivateKey *privkey; + + extern PGconn *db_conn; extern long long salt; @@ -60,11 +138,29 @@ extern unsigned int nmints; extern struct GNUNET_TIME_Relative edate_delay; -extern struct GNUNET_CRYPTO_EddsaPrivateKey *privkey; - -extern struct GNUNET_SCHEDULER_Task *poller_task; - void context_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); + + + + +/** + * Take the global wire details and return a JSON containing them, + * compliantly with the Taler's API. + * + * @param wire the merchant's wire details + * @param salt the nounce for hashing the wire details with + * @return JSON representation of the wire details, NULL upon errors + */ +json_t * +MERCHANT_get_wire_json (const struct MERCHANT_WIREFORMAT_Sepa *wire, + uint64_t salt); + + +/** + * Kick MHD to run now, to be called after MHD_resume_connection(). + */ +void +TM_trigger_daemon (void); diff --git a/src/backend/taler-merchant-httpd_contract.c b/src/backend/taler-merchant-httpd_contract.c index c42a8b37..d6c1b8fd 100644 --- a/src/backend/taler-merchant-httpd_contract.c +++ b/src/backend/taler-merchant-httpd_contract.c @@ -32,9 +32,7 @@ #include "taler-mint-httpd.h" #include "taler-mint-httpd_parsing.h" #include "taler-mint-httpd_responses.h" -#include "merchant_db.h" -#include "merchant.h" -#include "taler_merchant_lib.h" +#include "taler_merchantdb_lib.h" #include "taler-merchant-httpd.h" extern struct MERCHANT_Auditor *auditors; @@ -71,7 +69,7 @@ MH_handler_contract (struct TMH_RequestHandler *rh, int cnt; struct GNUNET_HashCode h_wire; struct GNUNET_CRYPTO_EddsaPublicKey pubkey; - struct MERCHANT_Contract contract; + struct TALER_ContractPS contract; char *contract_str; struct GNUNET_CRYPTO_EddsaSignature contract_sig; @@ -86,15 +84,15 @@ MH_handler_contract (struct TMH_RequestHandler *rh, return MHD_YES; /* Generate preferred mint(s) array. */ - + trusted_mints = json_array (); for (cnt = 0; cnt < nmints; cnt++) { - if (!mints[cnt].pending) + if (! mints[cnt]->pending) { - keys = TALER_MINT_get_keys (mints[cnt].conn); + keys = TALER_MINT_get_keys (mints[cnt]->conn); mint = json_pack ("{s:s, s:o}", - "url", mints[cnt].hostname, + "url", mints[cnt]->hostname, "master_pub", TALER_json_from_data (&keys->master_pub.eddsa_pub, @@ -131,7 +129,7 @@ MH_handler_contract (struct TMH_RequestHandler *rh, json_object_set_new (root, "auditors", j_auditors); if (NULL == (j_wire = MERCHANT_get_wire_json (wire, - salt))) + salt))) return MHD_NO; /* hash wire objcet */ @@ -149,7 +147,7 @@ MH_handler_contract (struct TMH_RequestHandler *rh, TALER_json_from_data (&pubkey, sizeof (pubkey))); /* Sign */ - contract_str = json_dumps (root, JSON_COMPACT | JSON_SORT_KEYS); + contract_str = json_dumps (root, JSON_COMPACT | JSON_SORT_KEYS); GNUNET_CRYPTO_hash (contract_str, strlen (contract_str), &contract.h_contract); contract.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_CONTRACT); contract.purpose.size = htonl (sizeof (contract)); @@ -164,5 +162,5 @@ MH_handler_contract (struct TMH_RequestHandler *rh, "H_contract", TALER_json_from_data (&contract.h_contract, sizeof (contract.h_contract))); - + } diff --git a/src/backend/taler-merchant-httpd_pay.c b/src/backend/taler-merchant-httpd_pay.c index 1951d2d0..1885c59c 100644 --- a/src/backend/taler-merchant-httpd_pay.c +++ b/src/backend/taler-merchant-httpd_pay.c @@ -18,7 +18,6 @@ * @brief HTTP serving layer mainly intended to communicate with the frontend * @author Marcello Stanisci */ - #include "platform.h" #include #include @@ -33,9 +32,41 @@ #include "taler-mint-httpd_parsing.h" #include "taler-mint-httpd_responses.h" #include "taler-mint-httpd_mhd.h" -#include "merchant_db.h" -#include "merchant.h" -#include "taler_merchant_lib.h" +#include "taler_merchantdb_lib.h" + + +/** + * Outcome of a /deposit request for a coin. Typically forming an array enclosed + * into the unique PayContext + */ +struct MERCHANT_DepositConfirmation +{ + /** + * Reference to the per-deposit-handler Context. Needed by the + * cleanup function to get it freed + */ + struct DepositCallbackContext *dcc; + + /** + * The mint's response body (JSON). Mainly useful in case + * some callback needs to send back to the to the wallet the + * outcome of an erroneous coin + */ + json_t *proof; + + /** + * True if this coin's outcome has been read from + * its cb + */ + unsigned int ackd; + + /** + * The mint's response to this /deposit + */ + unsigned int exit_status; + +}; + /** @@ -73,9 +104,9 @@ deposit_fee_from_coin_aggregate (struct MHD_Connection *connection, if (GNUNET_OK != res) return res; /* may return GNUNET_NO */ - if (1 == mints[mint_index].pending) + if (1 == mints[mint_index]->pending) return GNUNET_SYSERR; - keys = TALER_MINT_get_keys (mints[mint_index].conn); + keys = TALER_MINT_get_keys (mints[mint_index]->conn); denom_details = TALER_MINT_get_denomination_key (keys, &denom); if (NULL == denom_details) { @@ -203,7 +234,7 @@ deposit_cb (void *cls, return; } } - + printf ("All /deposit(s) ack'd\n"); dcc->pc->response = MHD_create_response_from_buffer (strlen ("All coins ack'd by the mint\n"), @@ -386,7 +417,7 @@ MH_handler_pay (struct TMH_RequestHandler *rh, } /* test it by checking public key */ - if (0 == strcmp (mints[mint_index].hostname, + if (0 == strcmp (mints[mint_index]->hostname, chosen_mint)) break; @@ -498,7 +529,7 @@ MH_handler_pay (struct TMH_RequestHandler *rh, deposit_permission_str, transaction_id, 1, - mints[mint_index].hostname)) + mints[mint_index]->hostname)) return TMH_RESPONSE_reply_internal_error (connection, "internal DB failure"); res = TMH_PARSE_json_data (connection, coin_aggregate, @@ -512,7 +543,7 @@ MH_handler_pay (struct TMH_RequestHandler *rh, percoin_dcc->index = coins_index; percoin_dcc->pc = pc; - dh = TALER_MINT_deposit (mints[mint_index].conn, + dh = TALER_MINT_deposit (mints[mint_index]->conn, &percoin_amount, edate, wire_details, @@ -535,13 +566,13 @@ MH_handler_pay (struct TMH_RequestHandler *rh, return TMH_RESPONSE_reply_json_pack (connection, MHD_HTTP_SERVICE_UNAVAILABLE, "{s:s, s:i}", - "mint", mints[mint_index].hostname, + "mint", mints[mint_index]->hostname, "transaction_id", transaction_id); } } - GNUNET_SCHEDULER_cancel (poller_task); - GNUNET_SCHEDULER_add_now (context_task, mints[mint_index].ctx); + GNUNET_SCHEDULER_cancel (mints[mint_index]->poller_task); + GNUNET_SCHEDULER_add_now (context_task, mints[mint_index]->ctx); return MHD_YES; /* 4 Return response code: success, or whatever data the diff --git a/src/backend/taler-mint-httpd_parsing.c b/src/backend/taler-mint-httpd_parsing.c index 9efd6c23..314d8839 100644 --- a/src/backend/taler-mint-httpd_parsing.c +++ b/src/backend/taler-mint-httpd_parsing.c @@ -32,8 +32,8 @@ 'TMH_PARSE_nagivate_json ()' compile fine; so its value will be kept on some merchant's accepted currency. For multi currencies merchants, that of course would require a patch */ +extern char *TMH_merchant_currency_string; -extern char *TMH_mint_currency_string; /** * Initial size for POST request buffer. */ @@ -634,7 +634,7 @@ TMH_PARSE_navigate_json (struct MHD_Connection *connection, case TMH_PARSE_JNC_RET_STRING: { - void **where = va_arg (argp, void **); + void **where = va_arg (argp, void **); *where = (void*) json_string_value (root); ret = GNUNET_OK; } @@ -876,7 +876,7 @@ TMH_PARSE_navigate_json (struct MHD_Connection *connection, break; } if (0 != strcmp (where->currency, - TMH_mint_currency_string)) + TMH_merchant_currency_string)) { GNUNET_break_op (0); ret = (MHD_YES != -- cgit v1.2.3