diff options
Diffstat (limited to 'src/backend/taler-merchant-httpd_map.c')
-rw-r--r-- | src/backend/taler-merchant-httpd_map.c | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/src/backend/taler-merchant-httpd_map.c b/src/backend/taler-merchant-httpd_map.c new file mode 100644 index 00000000..a41968a0 --- /dev/null +++ b/src/backend/taler-merchant-httpd_map.c @@ -0,0 +1,246 @@ +/* + This file is part of TALER + (C) 2014, 2015, 2016 INRIA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +*/ +/** + * @file backend/taler-merchant-httpd_map.c + * @brief Provides the frontend the mean to store plain contracts in database + * @author Marcello Stanisci + */ +#include "platform.h" +#include <jansson.h> +#include <taler/taler_signatures.h> +#include <taler/taler_json_lib.h> +#include "taler-merchant-httpd.h" +#include "taler-merchant-httpd_responses.h" +#include "taler-merchant-httpd_parsing.h" + +/** + * Information we keep for individual calls + * to requests that parse JSON, but keep no other state. + */ +struct TMH_JsonParseContext +{ + + /** + * This field MUST be first. + * FIXME: Explain why! + */ + struct TM_HandlerContext hc; + + /** + * Placeholder for #TMH_PARSE_post_json() to keep its internal state. + */ + void *json_parse_context; +}; + +/** + * Custom cleanup routine for a `struct TMH_JsonParseContext`. + * + * @param hc the `struct TMH_JsonParseContext` to clean up. + */ +static void +json_parse_cleanup (struct TM_HandlerContext *hc) +{ + struct TMH_JsonParseContext *jpc = (struct TMH_JsonParseContext *) hc; + + TMH_PARSE_post_cleanup_callback (jpc->json_parse_context); + GNUNET_free (jpc); +} + + +/** + * Manage a /map/in request. Store in db a plain text contract + * and its hashcode. + * + * @param rh context of the handler + * @param connection the MHD connection to handle + * @param[in,out] connection_cls the connection's closure (can be updated) + * @param upload_data upload data + * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @return MHD result code + */ +int +MH_handler_map_in (struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + void **connection_cls, + const char *upload_data, + size_t *upload_data_size) +{ + + int res; + json_t *root; + json_t *contract; + struct GNUNET_HashCode h_contract; + struct GNUNET_HashCode tmp; + struct TMH_JsonParseContext *ctx; + +/* Fetch body */ + + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_json ("contract", &contract), + GNUNET_JSON_spec_fixed_auto ("h_contract", &h_contract), + GNUNET_JSON_spec_end () + }; + + if (NULL == *connection_cls) + { + ctx = GNUNET_new (struct TMH_JsonParseContext); + ctx->hc.cc = &json_parse_cleanup; + *connection_cls = ctx; + } + else + { + ctx = *connection_cls; + } + + res = TMH_PARSE_post_json (connection, + &ctx->json_parse_context, + upload_data, + upload_data_size, + &root); + if (GNUNET_SYSERR == res) + return MHD_NO; + /* the POST's body has to be further fetched */ + if ((GNUNET_NO == res) || (NULL == root)) + return MHD_YES; + + res = TMH_PARSE_json_data (connection, + root, + spec); + if (GNUNET_NO == res) + { + json_decref (root); + return MHD_YES; + } + if (GNUNET_SYSERR == res) + { + json_decref (root); + return TMH_RESPONSE_reply_internal_error (connection, + TALER_EC_NONE, + "Impossible to parse JSON"); + } + + /* Sanity checks */ + if (GNUNET_SYSERR == + TALER_JSON_hash (contract, + &tmp)) + return TMH_RESPONSE_reply_invalid_json (connection); + + /** + * Check hashes match. This check does NOT detect invalid + * contracts though. + */ + + if (0 != memcmp (&tmp, + &h_contract, + sizeof (struct GNUNET_HashCode))) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "'h_contract' does not match 'contract'\n"); + return TMH_RESPONSE_reply_json_pack + (connection, + MHD_HTTP_UNPROCESSABLE_ENTITY, + "{s:I, s:s}", + "code", (json_int_t) TALER_EC_MAP_IN_UNMATCHED_HASH, + "error", "field 'h_contract' is not hash of 'contract'"); + } + + /* Store body */ + if (GNUNET_OK != db->store_map (db->cls, + &h_contract, + contract)) + { + return TMH_RESPONSE_reply_internal_error (connection, + TALER_EC_MAP_IN_STORE_DB_ERROR, + "Could not store data into db"); + } + + /* Test */ + json_t *hello; + + hello = json_pack ("{s:s}", "ok", "computer"); + return TMH_RESPONSE_reply_json (connection, + hello, + MHD_HTTP_OK); + + +} + + +/** + * Manage a /map/out request. Query the db and returns a plain + * text contract associated with the hashcode given as input + * + * @param rh context of the handler + * @param connection the MHD connection to handle + * @param[in,out] connection_cls the connection's closure (can be updated) + * @param upload_data upload data + * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @return MHD result code + */ +int +MH_handler_map_out (struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + void **connection_cls, + const char *upload_data, + size_t *upload_data_size) +{ + const char *h_contract_enc; + struct GNUNET_HashCode h_contract; + int res; + json_t *contract; + + h_contract_enc = MHD_lookup_connection_value (connection, + MHD_GET_ARGUMENT_KIND, + "h_contract"); + if (NULL == h_contract_enc) + return TMH_RESPONSE_reply_arg_missing (connection, + TALER_EC_PARAMETER_MISSING, + "h_contract"); + + if (GNUNET_OK != GNUNET_STRINGS_string_to_data (h_contract_enc, + strlen (h_contract_enc), + &h_contract, + sizeof (h_contract))) + { + GNUNET_break_op (0); + return TMH_RESPONSE_reply_bad_request (connection, + TALER_EC_PARAMETER_MALFORMED, + "Could not decode hashcode into binary form"); + } + + res = db->find_contract (db->cls, + &contract, + &h_contract); + + if (GNUNET_SYSERR == res) + { + return TMH_RESPONSE_reply_internal_error (connection, + TALER_EC_MAP_OUT_GET_FROM_DB_ERROR, + "Could not retrieve data from db"); + } + + if (GNUNET_NO == res) + { + return TMH_RESPONSE_reply_not_found (connection, + TALER_EC_MAP_OUT_CONTRACT_UNKNOWN, + "contract"); + } + + return TMH_RESPONSE_reply_json (connection, + contract, + MHD_HTTP_OK); +} +/* end of taler-merchant-httpd_history.c */ |