summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarcello Stanisci <marcello.stanisci@inria.fr>2016-12-12 16:17:49 +0100
committerMarcello Stanisci <marcello.stanisci@inria.fr>2016-12-12 16:17:49 +0100
commit6e4004bf1a978435b7b4c8c928d38cba12a3d7a1 (patch)
tree26b08b56d65f26341c4663e33e54d77847ee9b2d /src
parentcb6e9292a4ed554d92c6c265f557afca78012be5 (diff)
downloadmerchant-6e4004bf1a978435b7b4c8c928d38cba12a3d7a1.tar.gz
merchant-6e4004bf1a978435b7b4c8c928d38cba12a3d7a1.tar.bz2
merchant-6e4004bf1a978435b7b4c8c928d38cba12a3d7a1.zip
Unifying map-in and map-out handles
Diffstat (limited to 'src')
-rw-r--r--src/backend/taler-merchant-httpd_map.c45
-rw-r--r--src/backenddb/plugin_merchantdb_postgres.c4
-rw-r--r--src/backenddb/test_merchantdb.c2
-rw-r--r--src/include/taler_merchant_service.h35
-rw-r--r--src/include/taler_merchantdb_plugin.h2
-rw-r--r--src/lib/merchant_api_history.c2
-rw-r--r--src/lib/merchant_api_map.c140
-rw-r--r--src/lib/test_merchant_api.c64
8 files changed, 214 insertions, 80 deletions
diff --git a/src/backend/taler-merchant-httpd_map.c b/src/backend/taler-merchant-httpd_map.c
index e508dee1..a41968a0 100644
--- a/src/backend/taler-merchant-httpd_map.c
+++ b/src/backend/taler-merchant-httpd_map.c
@@ -45,8 +45,6 @@ struct TMH_JsonParseContext
void *json_parse_context;
};
-
-
/**
* Custom cleanup routine for a `struct TMH_JsonParseContext`.
*
@@ -199,7 +197,50 @@ MH_handler_map_out (struct TMH_RequestHandler *rh,
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 */
diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c
index 572c0f5e..8fbed465 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -408,7 +408,7 @@ postgres_initialize (void *cls)
*/
static int
postgres_find_contract (void *cls,
- json_t *contract,
+ json_t **contract,
struct GNUNET_HashCode *h_contract)
{
struct PostgresClosure *pg = cls;
@@ -440,7 +440,7 @@ postgres_find_contract (void *cls,
/* FIXME, figure out how to pass back json_t's */
struct GNUNET_PQ_ResultSpec rs[] = {
TALER_PQ_result_spec_json ("plain_contract",
- &contract),
+ contract),
GNUNET_PQ_result_spec_end
};
if (GNUNET_OK !=
diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c
index f6f1ab42..d30b7f5e 100644
--- a/src/backenddb/test_merchantdb.c
+++ b/src/backenddb/test_merchantdb.c
@@ -363,7 +363,7 @@ run (void *cls)
FAILIF (GNUNET_OK !=
plugin->find_contract (plugin->cls,
- out,
+ &out,
&h_contract));
FAILIF (GNUNET_OK !=
diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h
index 66c2fd8f..0ed6856e 100644
--- a/src/include/taler_merchant_service.h
+++ b/src/include/taler_merchant_service.h
@@ -27,13 +27,32 @@
#include <gnunet/gnunet_curl_lib.h>
#include <jansson.h>
-/* ********************* /map/in *********************** */
-struct TALER_MERCHANT_MapInOperation;
+/* ********************* /map/{in,out} *********************** */
+
+struct TALER_MERCHANT_MapOutOperation;
typedef void
-(*TALER_MERCHANT_MapInOperationCallback) (void *cls,
- unsigned int http_status);
+(*TALER_MERCHANT_MapOperationCallback) (void *cls,
+ unsigned int http_status,
+ const json_t *body);
+
+/**
+ * Issue a /map/out request to the backend.
+ *
+ * @param ctx execution context
+ * @param backend_uri base URL of the merchant backend
+ * @param h_contract hashcode of `contract`
+ * @param map_in_cb callback which will work the response gotten from the backend
+ * @param map_in_cb_cls closure to pass to @a history_cb
+ * @return handle for this operation, NULL upon errors
+ */
+struct TALER_MERCHANT_MapOperation *
+TALER_MERCHANT_map_out (struct GNUNET_CURL_Context *ctx,
+ const char *backend_uri,
+ const struct GNUNET_HashCode *h_contract,
+ TALER_MERCHANT_MapOperationCallback map_cb,
+ void *map_cb_cls);
/**
* Issue a /map/in request to the backend.
@@ -46,13 +65,13 @@ typedef void
* @param map_in_cb_cls closure to pass to @a history_cb
* @return handle for this operation, NULL upon errors
*/
-struct TALER_MERCHANT_MapInOperation *
+struct TALER_MERCHANT_MapOperation *
TALER_MERCHANT_map_in (struct GNUNET_CURL_Context *ctx,
const char *backend_uri,
const json_t *contract,
const struct GNUNET_HashCode *h_contract,
- TALER_MERCHANT_MapInOperationCallback map_in_cb,
- void *map_in_cb_cls);
+ TALER_MERCHANT_MapOperationCallback map_cb,
+ void *map_cb_cls);
/**
* Cancel a /map/in request.
@@ -60,7 +79,7 @@ TALER_MERCHANT_map_in (struct GNUNET_CURL_Context *ctx,
* @param mio handle to the request to be canceled
*/
void
-TALER_MERCHANT_map_in_cancel (struct TALER_MERCHANT_MapInOperation *mio);
+TALER_MERCHANT_map_cancel (struct TALER_MERCHANT_MapOperation *mo);
/* ********************* /contract *********************** */
diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h
index a11fa7c7..3923fde1 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -174,7 +174,7 @@ struct TALER_MERCHANTDB_Plugin
*/
int
(*find_contract) (void *cls,
- json_t *contract,
+ json_t **contract,
struct GNUNET_HashCode *h_contract);
/**
diff --git a/src/lib/merchant_api_history.c b/src/lib/merchant_api_history.c
index f296c030..39f9bd82 100644
--- a/src/lib/merchant_api_history.c
+++ b/src/lib/merchant_api_history.c
@@ -170,8 +170,6 @@ TALER_MERCHANT_history (struct GNUNET_CURL_Context *ctx,
return NULL;
}
-
-
if (NULL == (ho->job = GNUNET_CURL_job_add (ctx,
eh,
GNUNET_YES,
diff --git a/src/lib/merchant_api_map.c b/src/lib/merchant_api_map.c
index 8185ffd2..d1aaf5a1 100644
--- a/src/lib/merchant_api_map.c
+++ b/src/lib/merchant_api_map.c
@@ -28,7 +28,13 @@
#include "taler_merchant_service.h"
#include <taler/taler_json_lib.h>
-struct TALER_MERCHANT_MapInOperation
+
+/**
+ * This structure acts like a "handle" for both /map/in and
+ * /map/out operations, as they only differ about the 'json_enc'
+ * field (which is just left NULL when not needed).
+ */
+struct TALER_MERCHANT_MapOperation
{
/**
* Full URI, includes "/map/in".
@@ -36,7 +42,7 @@ struct TALER_MERCHANT_MapInOperation
char *url;
/**
- * Request's body
+ * Request's body. Left NULL in case of /map/out.
*/
char *json_enc;
@@ -48,7 +54,7 @@ struct TALER_MERCHANT_MapInOperation
/**
* Function to call with the result.
*/
- TALER_MERCHANT_MapInOperationCallback cb;
+ TALER_MERCHANT_MapOperationCallback cb;
/**
* Closure for @a cb.
@@ -62,46 +68,100 @@ struct TALER_MERCHANT_MapInOperation
};
+
/**
- * Cancel a /map/in request.
+ * Cancel a /map/{in,out} request.
*
* @param mio handle to the request to be canceled
*/
void
-TALER_MERCHANT_map_in_cancel (struct TALER_MERCHANT_MapInOperation *mio)
+TALER_MERCHANT_map_cancel (struct TALER_MERCHANT_MapOperation *mo)
{
- if (NULL != mio->job)
+ if (NULL != mo->job)
{
- GNUNET_CURL_job_cancel (mio->job);
- mio->job = NULL;
+ GNUNET_CURL_job_cancel (mo->job);
+ mo->job = NULL;
}
- GNUNET_free (mio->url);
- GNUNET_free (mio->json_enc);
- GNUNET_free (mio);
+ GNUNET_free (mo->url);
+ GNUNET_free_non_null (mo->json_enc);
+ GNUNET_free (mo);
}
+
/**
- * Function called when we're done processing the
- * HTTP /map/in request.
+ * Function called when we're done processing the HTTP /map/{in,out} request.
*
- * @param cls the `struct TALER_MERCHANT_FIXME`
+ * @param cls the `struct TALER_MERCHANT_MapInOperation`
* @param response_code HTTP response code, 0 on error
* @param json response body, should be NULL
*/
static void
-handle_map_in_finished (void *cls,
- long response_code,
- const json_t *json)
+handle_map_finished (void *cls,
+ long response_code,
+ const json_t *json)
{
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "|\n");
- struct TALER_MERCHANT_MapInOperation *mio = cls;
+ struct TALER_MERCHANT_MapOperation *mo = cls;
/**
* As no data is supposed to be extracted from this
* call, we just invoke the provided callback from here.
*/
- mio->cb (mio->cb_cls,
- response_code);
+ mo->cb (mo->cb_cls,
+ response_code,
+ json);
+}
+
+/**
+ * Issue a /map/out request to the backend.
+ *
+ * @param ctx execution context
+ * @param backend_uri base URL of the merchant backend
+ * @param h_contract hashcode of `contract`
+ * @param map_in_cb callback which will work the response gotten from the backend
+ * @param map_in_cb_cls closure to pass to @a history_cb
+ * @return handle for this operation, NULL upon errors
+ */
+struct TALER_MERCHANT_MapOperation *
+TALER_MERCHANT_map_out (struct GNUNET_CURL_Context *ctx,
+ const char *backend_uri,
+ const struct GNUNET_HashCode *h_contract,
+ TALER_MERCHANT_MapOperationCallback map_cb,
+ void *map_cb_cls)
+{
+ struct TALER_MERCHANT_MapOperation *mo;
+ CURL *eh;
+ char *hash_enc;
+
+ mo = GNUNET_new (struct TALER_MERCHANT_MapOperation);
+ mo->ctx = ctx;
+ mo->cb = map_cb;
+ mo->cb_cls = map_cb_cls;
+
+ hash_enc = GNUNET_STRINGS_data_to_string_alloc (h_contract,
+ sizeof (struct GNUNET_HashCode));
+ GNUNET_asprintf (&mo->url,
+ "%s/map/out?h_contract=%s",
+ backend_uri,
+ hash_enc);
+ eh = curl_easy_init ();
+ if (CURLE_OK != curl_easy_setopt (eh,
+ CURLOPT_URL,
+ mo->url))
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+
+ if (NULL == (mo->job = GNUNET_CURL_job_add (ctx,
+ eh,
+ GNUNET_YES,
+ &handle_map_finished,
+ mo)))
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ return mo;
}
/**
@@ -115,24 +175,24 @@ handle_map_in_finished (void *cls,
* @param map_in_cb_cls closure to pass to @a history_cb
* @return handle for this operation, NULL upon errors
*/
-struct TALER_MERCHANT_MapInOperation *
+struct TALER_MERCHANT_MapOperation *
TALER_MERCHANT_map_in (struct GNUNET_CURL_Context *ctx,
const char *backend_uri,
const json_t *contract,
const struct GNUNET_HashCode *h_contract,
- TALER_MERCHANT_MapInOperationCallback map_in_cb,
- void *map_in_cb_cls)
+ TALER_MERCHANT_MapOperationCallback map_cb,
+ void *map_cb_cls)
{
- struct TALER_MERCHANT_MapInOperation *mio;
+ struct TALER_MERCHANT_MapOperation *mo;
CURL *eh;
json_t *req;
- mio = GNUNET_new (struct TALER_MERCHANT_MapInOperation);
- mio->ctx = ctx;
- mio->cb = map_in_cb;
- mio->cb_cls = map_in_cb_cls;
+ mo = GNUNET_new (struct TALER_MERCHANT_MapOperation);
+ mo->ctx = ctx;
+ mo->cb = map_cb;
+ mo->cb_cls = map_cb_cls;
- GNUNET_asprintf (&mio->url,
+ GNUNET_asprintf (&mo->url,
"%s%s",
backend_uri,
"/map/in");
@@ -143,7 +203,7 @@ TALER_MERCHANT_map_in (struct GNUNET_CURL_Context *ctx,
"h_contract", GNUNET_JSON_from_data_auto (h_contract));
GNUNET_assert (NULL !=
- (mio->json_enc = json_dumps (req, JSON_COMPACT))
+ (mo->json_enc = json_dumps (req, JSON_COMPACT))
);
json_decref (req);
@@ -152,19 +212,19 @@ TALER_MERCHANT_map_in (struct GNUNET_CURL_Context *ctx,
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_URL,
- mio->url));
+ mo->url));
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_POSTFIELDS,
- mio->json_enc));
+ mo->json_enc));
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_POSTFIELDSIZE,
- strlen (mio->json_enc)));
- mio->job = GNUNET_CURL_job_add (ctx,
- eh,
- GNUNET_YES,
- &handle_map_in_finished,
- mio);
- return mio;
+ strlen (mo->json_enc)));
+ mo->job = GNUNET_CURL_job_add (ctx,
+ eh,
+ GNUNET_YES,
+ &handle_map_finished,
+ mo);
+ return mo;
}
diff --git a/src/lib/test_merchant_api.c b/src/lib/test_merchant_api.c
index 602f3469..31a617cd 100644
--- a/src/lib/test_merchant_api.c
+++ b/src/lib/test_merchant_api.c
@@ -124,6 +124,12 @@ enum OpCode
OC_MAP_IN,
/**
+ * Ask the backend to retrieve a contract from the database, according
+ * to its hashcode.
+ */
+ OC_MAP_OUT,
+
+ /**
* Add funds to a reserve by (faking) incoming wire transfer.
*/
OC_ADMIN_ADD_INCOMING,
@@ -298,7 +304,7 @@ struct Command
} admin_add_incoming;
/**
- * Information for a #OC_MAP_IN command.
+ * Information for both #OC_MAP_{IN,OUT} command.
*/
struct
{
@@ -308,12 +314,9 @@ struct Command
*/
const char *contract_reference;
- /**
- * Handle to a /map/in operation
- */
- struct TALER_MERCHANT_MapInOperation *mio;
+ struct TALER_MERCHANT_MapOperation *mo;
- } map_in;
+ } map;
/**
* Information for a #OC_WITHDRAW_STATUS command.
@@ -1305,15 +1308,14 @@ track_transfer_cb (void *cls,
* @param http_status HTTP status code we got
*/
static void
-map_in_cb (void *cls,
- unsigned int http_status)
+map_cb (void *cls,
+ unsigned int http_status,
+ const json_t *json)
{
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Cb for /map/in\n");
struct InterpreterState *is = cls;
struct Command *cmd = &is->commands[is->ip];
- cmd->details.map_in.mio = NULL;
+ cmd->details.map.mo = NULL;
GNUNET_assert (cmd->expected_response_code == http_status);
next_command (is);
}
@@ -1520,14 +1522,16 @@ interpreter_run (void *cls)
is->task = GNUNET_SCHEDULER_add_now (interpreter_run,
is);
return;
+
case OC_MAP_IN:
+ case OC_MAP_OUT:
{
struct GNUNET_HashCode h_proposal;
json_error_t error;
json_t *proposal;
- GNUNET_assert (NULL != cmd->details.map_in.contract_reference);
- ref = find_command (is, cmd->details.map_in.contract_reference);
+ GNUNET_assert (NULL != cmd->details.map.contract_reference);
+ ref = find_command (is, cmd->details.map.contract_reference);
GNUNET_assert (NULL != ref);
/**
@@ -1541,16 +1545,27 @@ interpreter_run (void *cls)
GNUNET_assert (GNUNET_SYSERR !=
TALER_JSON_hash (proposal, &h_proposal));
- GNUNET_assert (NULL !=
- TALER_MERCHANT_map_in (ctx,
- MERCHANT_URI,
- proposal,
- &h_proposal,
- map_in_cb,
- is));
+ if (OC_MAP_IN == cmd->oc)
+ GNUNET_assert (NULL !=
+ (cmd->details.map.mo
+ = TALER_MERCHANT_map_in (ctx,
+ MERCHANT_URI,
+ proposal,
+ &h_proposal,
+ map_cb,
+ is)));
+ else
+ GNUNET_assert (NULL !=
+ (cmd->details.map.mo
+ = TALER_MERCHANT_map_out (ctx,
+ MERCHANT_URI,
+ &h_proposal,
+ map_cb,
+ is)));
}
return;
+
case OC_ADMIN_ADD_INCOMING:
if (NULL !=
cmd->details.admin_add_incoming.reserve_reference)
@@ -2037,13 +2052,14 @@ do_shutdown (void *cls)
GNUNET_assert (0);
break;
case OC_MAP_IN:
- if (NULL != cmd->details.map_in.mio)
+ case OC_MAP_OUT:
+ if (NULL != cmd->details.map.mo)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Command %u (%s) did not complete\n",
i,
cmd->label);
- TALER_MERCHANT_map_in_cancel (cmd->details.map_in.mio);
+ TALER_MERCHANT_map_cancel (cmd->details.map.mo);
}
break;
@@ -2304,7 +2320,7 @@ run (void *cls)
.oc = OC_MAP_IN,
.label = "store-contract-1",
.expected_response_code = MHD_HTTP_OK,
- .details.map_in.contract_reference = "create-contract-1",
+ .details.map.contract_reference = "create-contract-1",
},
/* Create another contract */
@@ -2344,7 +2360,7 @@ run (void *cls)
.oc = OC_MAP_IN,
.label = "store-contract-2",
.expected_response_code = MHD_HTTP_OK,
- .details.map_in.contract_reference = "create-contract-2",
+ .details.map.contract_reference = "create-contract-2",
},
/* Add another 4.01 EUR to reserve #2 */