WiP: added auction_brandt as extension
- added an extension to handle auctions via libbrandt - /extensions/auction_brandt GET and POST handler defined - initial parsing of transcript.json implemented, yet WiP - multiple cleanups and changes to extension handling
This commit is contained in:
parent
04c7e0bb33
commit
72cbf66395
@ -4255,13 +4255,17 @@ do_extensions_show (char *const *args)
|
||||
|
||||
GNUNET_assert (NULL != exts);
|
||||
for (it = TALER_extensions_get_head ();
|
||||
NULL != it;
|
||||
NULL != it && NULL != it->extension;
|
||||
it = it->next)
|
||||
{
|
||||
const struct TALER_Extension *extension = it->extension;
|
||||
|
||||
GNUNET_assert (0 ==
|
||||
json_object_set_new (exts,
|
||||
it->extension->name,
|
||||
it->extension->config_to_json (
|
||||
it->extension)));
|
||||
}
|
||||
obj = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_object_steal ("extensions",
|
||||
exts));
|
||||
|
@ -1040,6 +1040,42 @@ handle_post_auditors (struct TEH_RequestContext *rc,
|
||||
root);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle GET "/extensions/..." requests.
|
||||
*
|
||||
* @param rc request context
|
||||
* @param args array of additional options
|
||||
* @return MHD result code
|
||||
*/
|
||||
static MHD_RESULT
|
||||
handle_get_extensions (struct TEH_RequestContext *rc,
|
||||
const char *const args[])
|
||||
{
|
||||
const struct TALER_Extension *ext = NULL;
|
||||
|
||||
if (NULL == args[0])
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return r404 (rc->connection,
|
||||
"/extensions/$EXTENSION");
|
||||
}
|
||||
|
||||
ext = TALER_extensions_get_by_name (args[0]);
|
||||
if (NULL == ext)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return r404 (rc->connection,
|
||||
"/extensions/$EXTENSION unknown");
|
||||
}
|
||||
|
||||
if (NULL == ext->http_get_handler)
|
||||
return MHD_HTTP_NOT_IMPLEMENTED;
|
||||
|
||||
return ext->http_get_handler (
|
||||
rc->connection,
|
||||
&args[1]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle POST "/extensions/..." requests.
|
||||
@ -1299,6 +1335,13 @@ handle_mhd_request (void *cls,
|
||||
.nargs_is_upper_bound = true
|
||||
},
|
||||
/* extensions endpoints */
|
||||
{
|
||||
.url = "extensions",
|
||||
.method = MHD_HTTP_METHOD_GET,
|
||||
.handler.get = &handle_get_extensions,
|
||||
.nargs = 4, /* Arbitrary upper bound */
|
||||
.nargs_is_upper_bound = true,
|
||||
},
|
||||
{
|
||||
.url = "extensions",
|
||||
.method = MHD_HTTP_METHOD_POST,
|
||||
|
@ -78,6 +78,7 @@ extension_update_event_cb (void *cls,
|
||||
}
|
||||
|
||||
// Get the config from the database as string
|
||||
if (extension->has_config)
|
||||
{
|
||||
char *config_str = NULL;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
@ -190,12 +191,16 @@ TEH_extensions_init ()
|
||||
it = it->next)
|
||||
{
|
||||
const struct TALER_Extension *ext = it->extension;
|
||||
uint32_t typ = htonl (ext->type);
|
||||
char *conf = json_dumps (ext->config_to_json (ext), JSON_COMPACT);
|
||||
|
||||
TEH_plugin->set_extension_config (TEH_plugin->cls,
|
||||
ext->name,
|
||||
conf);
|
||||
extension_update_event_cb (NULL, &ext->type, sizeof(ext->type));
|
||||
|
||||
extension_update_event_cb (NULL,
|
||||
&typ,
|
||||
sizeof(typ));
|
||||
free (conf);
|
||||
}
|
||||
|
||||
|
@ -1916,18 +1916,23 @@ create_krd (struct TEH_KeyStateHandle *ksh,
|
||||
|
||||
/* flag our findings so far */
|
||||
has_extensions = true;
|
||||
GNUNET_assert (NULL != extension->config_json);
|
||||
|
||||
ext = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_bool ("critical",
|
||||
extension->critical),
|
||||
GNUNET_JSON_pack_string ("version",
|
||||
extension->version),
|
||||
GNUNET_JSON_pack_object_incref ("config",
|
||||
extension->config_json)
|
||||
extension->version)
|
||||
);
|
||||
GNUNET_assert (NULL != ext);
|
||||
|
||||
if (extension->has_config)
|
||||
{
|
||||
GNUNET_assert (extension->config_json);
|
||||
json_object_set_new (ext,
|
||||
"config",
|
||||
extension->config_json);
|
||||
}
|
||||
|
||||
r = json_object_set_new (
|
||||
extensions,
|
||||
extension->name,
|
||||
|
@ -188,6 +188,7 @@ struct TALER_Extension TE_extension_age_restriction = {
|
||||
.critical = false,
|
||||
.version = "1",
|
||||
.enabled = false, /* disabled per default */
|
||||
.has_config = true, /* we need to store configuration */
|
||||
.config = NULL,
|
||||
.config_json = NULL,
|
||||
.disable = &age_restriction_disable,
|
||||
|
@ -26,11 +26,245 @@
|
||||
#include "stdint.h"
|
||||
#include <microhttpd.h>
|
||||
|
||||
#define EXTENSION_NAME "auction_brandt"
|
||||
#define AUCTION_BRANDT "auction_brandt"
|
||||
|
||||
/* Path to the replay program. */
|
||||
static char *replay_program;
|
||||
|
||||
/* This is basically BRANDT_Result with an extra string field */
|
||||
struct result
|
||||
{
|
||||
uint16_t bidder;
|
||||
uint16_t price_idx;
|
||||
const char *price;
|
||||
};
|
||||
|
||||
/*
|
||||
* TODO: Transcript information
|
||||
*/
|
||||
struct transcript
|
||||
{
|
||||
// All fields from json come here.
|
||||
uint16_t n; // #bidders + 1
|
||||
uint16_t k; // #prices
|
||||
uint16_t m; // type of auction
|
||||
struct GNUNET_TIME_Absolute time_start;
|
||||
struct GNUNET_TIME_Relative time_round;
|
||||
bool public;
|
||||
char **prices; // Must be of length k. We do not parse those
|
||||
// struct msg *msgs; // Array must be of length 4*n
|
||||
|
||||
// struct BRANDT_Auction *auction;
|
||||
|
||||
struct result *results;
|
||||
size_t results_len;
|
||||
struct result *expected;
|
||||
size_t expected_len;
|
||||
uint16_t id;
|
||||
struct GNUNET_CRYPTO_EccDlogContext *edc;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief returns an JSON with the error
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
json_error (json_t **output,
|
||||
char *error)
|
||||
{
|
||||
GNUNET_assert (error);
|
||||
|
||||
*output = json_pack ("{s:s}", "error", error);
|
||||
GNUNET_assert (*output);
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"[auction_brandt] got error: %s\n",
|
||||
error);
|
||||
|
||||
return GNUNET_SYSERR;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief returns an JSON with the result
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
json_result (json_t **output,
|
||||
const struct transcript *tr)
|
||||
{
|
||||
json_t *results;
|
||||
|
||||
GNUNET_assert (NULL != tr);
|
||||
|
||||
*output = json_object ();
|
||||
results = json_array ();
|
||||
GNUNET_assert (*output);
|
||||
GNUNET_assert (results);
|
||||
|
||||
for (size_t i = 0; i < tr->results_len; i++)
|
||||
{
|
||||
json_t *result = json_pack ("{s:i, s:s}",
|
||||
"bidder", tr->results[i].bidder,
|
||||
"price", tr->results[i].price);
|
||||
GNUNET_assert (result);
|
||||
|
||||
GNUNET_assert (-1 !=
|
||||
json_array_append_new (results, result));
|
||||
}
|
||||
|
||||
GNUNET_assert (-1 !=
|
||||
json_object_set_new (*output,
|
||||
"winners",
|
||||
results));
|
||||
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @brief Parses a given json as transcript.
|
||||
*
|
||||
* @param[in] jtr JSON input
|
||||
* @param[out] transcript Parsed transcript data
|
||||
* @param[out] jresult JSON output, both, for results or errors
|
||||
* @return GNUNET_OK on succes
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
parse_transcript (const json_t *jtr,
|
||||
struct transcript *tr,
|
||||
json_t **output)
|
||||
{
|
||||
// TODO: json_error_t jerror;
|
||||
// TODO: struct GNUNET_CRYPTO_EddsaSignature sig;
|
||||
|
||||
GNUNET_assert (jtr);
|
||||
GNUNET_assert (tr);
|
||||
|
||||
{
|
||||
json_t *auc;
|
||||
char *perr;
|
||||
unsigned int eline;
|
||||
struct GNUNET_JSON_Specification au_spec[] = {
|
||||
GNUNET_JSON_spec_bool ("public", &tr->public),
|
||||
GNUNET_JSON_spec_uint16 ("type", &tr->m),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
auc = json_object_get (jtr, "auction");
|
||||
if (NULL == auc)
|
||||
return json_error (output, "no auction found in transcript");
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (auc,
|
||||
au_spec,
|
||||
(const char **) &perr,
|
||||
&eline))
|
||||
return json_error (output, perr);
|
||||
|
||||
// Prices...
|
||||
{
|
||||
json_t *prices = json_object_get (auc, "prices");
|
||||
size_t idx;
|
||||
json_t *val;
|
||||
|
||||
|
||||
if (! json_is_array (prices))
|
||||
// TODO: leak!?
|
||||
return json_error (output, "no prices found");
|
||||
|
||||
tr->k = json_array_size (prices);
|
||||
|
||||
tr->prices = GNUNET_new_array (tr->k, char *);
|
||||
json_array_foreach (prices, idx, val)
|
||||
{
|
||||
if (! json_is_string (val))
|
||||
// TODO: leak!_
|
||||
return json_error (output, "prices not strings");
|
||||
|
||||
tr->prices[idx] = (char *) json_string_value (val);
|
||||
|
||||
// TODO: parse prices
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bidders
|
||||
{
|
||||
json_t *bidders;
|
||||
|
||||
bidders = json_object_get (jtr, "bidders");
|
||||
if (! bidders || ! json_is_array (bidders))
|
||||
// TODO: leak!_
|
||||
return json_error (output, "bidders not found");
|
||||
|
||||
// TODO: parse bidders as pub keys;
|
||||
tr->n = json_array_size (bidders);
|
||||
}
|
||||
|
||||
|
||||
// Messages
|
||||
{
|
||||
json_t *messages;
|
||||
size_t nm;
|
||||
|
||||
messages = json_object_get (jtr, "transcript");
|
||||
if (! json_is_array (messages))
|
||||
// TODO: leak!
|
||||
return json_error (output, "no messages found");
|
||||
|
||||
|
||||
nm = json_array_size (messages);
|
||||
|
||||
if (nm != (4 * tr->n))
|
||||
// TODO: leak!
|
||||
return json_error (output, "not the right no. of messages found");
|
||||
}
|
||||
|
||||
// Winners
|
||||
{
|
||||
json_t *winners;
|
||||
size_t idx;
|
||||
json_t *val;
|
||||
|
||||
winners = json_object_get (jtr, "winners");
|
||||
|
||||
if (! json_is_array (winners))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"winners not provided, continuing without\n");
|
||||
goto CONT;
|
||||
}
|
||||
|
||||
tr->expected_len = json_array_size (winners);
|
||||
tr->expected = GNUNET_new_array (tr->expected_len,
|
||||
struct result);
|
||||
|
||||
json_array_foreach (winners, idx, val) {
|
||||
char *error;
|
||||
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_uint16 ("bidder",
|
||||
&(tr->expected[idx].bidder)),
|
||||
GNUNET_JSON_spec_uint16 ("price_idx",
|
||||
&(tr->expected[idx].price_idx)),
|
||||
GNUNET_JSON_spec_string ("price",
|
||||
&(tr->expected[idx].price)),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (val,
|
||||
spec,
|
||||
(const char**) &error,
|
||||
NULL))
|
||||
// TODO: leak!
|
||||
return json_error (output, "couldn't parse winners");
|
||||
}
|
||||
|
||||
CONT:
|
||||
}
|
||||
return json_result (output, tr);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief implements the TALER_Extension.disable interface.
|
||||
*
|
||||
@ -70,7 +304,9 @@ auction_config_to_json (
|
||||
const struct TALER_Extension *ext)
|
||||
{
|
||||
/* This extension has no configuration */
|
||||
return json_null ();
|
||||
return GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_bool ("critical", ext->critical),
|
||||
GNUNET_JSON_pack_string ("version", ext->version));
|
||||
}
|
||||
|
||||
|
||||
@ -91,36 +327,68 @@ auction_load_json_config (
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief implements the TALER_Extension.http_get_handler
|
||||
*/
|
||||
static MHD_RESULT
|
||||
auction_http_get_handler (
|
||||
struct MHD_Connection *connection,
|
||||
const char *const args[])
|
||||
{
|
||||
/* TODO: return some meta-data about supported version, limits, etc.*/
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"auction_http_get_handler not implemented yet\n");
|
||||
|
||||
return TALER_MHD_reply_with_error (connection,
|
||||
MHD_HTTP_NOT_IMPLEMENTED,
|
||||
TALER_EC_EXCHANGE_GENERIC_OPERATION_UNKNOWN,
|
||||
"auction_http_get_handler not implemented yet\n");
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief implements the TALER_Extension.http_post_handler
|
||||
*/
|
||||
|
||||
static MHD_RESULT
|
||||
auction_http_post_handler (
|
||||
struct MHD_Connection *connection,
|
||||
const json_t *root,
|
||||
const char *const args[])
|
||||
{
|
||||
struct transcript tr = {};
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
json_t *result;
|
||||
|
||||
ret = parse_transcript (root, &tr, &result);
|
||||
|
||||
/* TODO */
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"auction_http_post_handler not implemented yet");
|
||||
return MHD_HTTP_NOT_IMPLEMENTED;
|
||||
"auction_http_post_handler not implemented yet\n");
|
||||
|
||||
return TALER_MHD_reply_json_steal (connection,
|
||||
result,
|
||||
GNUNET_OK == ret? MHD_HTTP_OK :
|
||||
MHD_HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
|
||||
/* The extension struct for auctions of brandt-style */
|
||||
struct TALER_Extension TE_auction_brandt = {
|
||||
.type = 0x0815, /* TODO: where do we get this from? */
|
||||
.name = EXTENSION_NAME,
|
||||
.type = TALER_Extension_AuctionBrandt,
|
||||
.name = AUCTION_BRANDT,
|
||||
.critical = false,
|
||||
.version = "0",
|
||||
.enabled = false, /* disabled per default */
|
||||
.has_config = false, /* This extension has no configuration */
|
||||
.config = NULL,
|
||||
.config_json = NULL,
|
||||
.disable = &auction_disable,
|
||||
.test_json_config = &auction_test_json_config,
|
||||
.load_json_config = &auction_load_json_config,
|
||||
.config_to_json = &auction_config_to_json,
|
||||
.http_get_handler = &auction_http_get_handler,
|
||||
.http_post_handler = &auction_http_post_handler,
|
||||
};
|
||||
|
||||
@ -141,25 +409,31 @@ struct TALER_Extension TE_auction_brandt = {
|
||||
* @return Pointer to TE_auction_brandt
|
||||
*/
|
||||
struct TALER_Extension *
|
||||
init (void *arg)
|
||||
libtaler_extension_auction_brandt_init (void *arg)
|
||||
{
|
||||
const struct GNUNET_CONFIGURATION_Handle *cfg = arg;
|
||||
|
||||
if (GNUNET_SYSERR ==
|
||||
GNUNET_CONFIGURATION_get_value_string (cfg,
|
||||
"extension_" EXTENSION_NAME,
|
||||
"replay_program",
|
||||
TALER_EXTENSION_SECTION_PREFIX
|
||||
AUCTION_BRANDT,
|
||||
"REPLAY_PROGRAM",
|
||||
&replay_program))
|
||||
{
|
||||
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
||||
"extension_" EXTENSION_NAME,
|
||||
"replay_program");
|
||||
TALER_EXTENSION_SECTION_PREFIX AUCTION_BRANDT,
|
||||
"REPLAY_PROGRAM");
|
||||
return NULL;
|
||||
}
|
||||
/* TODO: check if replay_program is actually executable */
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"[auction_brandt] loading... using replay_program '%s'\n",
|
||||
replay_program);
|
||||
|
||||
return &TE_auction_brandt;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Tear-down function for the extension.
|
||||
* Will be called by GNUNET_PLUGIN_unload.
|
||||
@ -168,7 +442,7 @@ init (void *arg)
|
||||
* @return null
|
||||
*/
|
||||
void *
|
||||
done (void *arg)
|
||||
libtaler_extension_auction_brandt_done (void *arg)
|
||||
{
|
||||
auction_disable (&TE_auction_brandt);
|
||||
GNUNET_free (replay_program);
|
||||
@ -178,5 +452,4 @@ done (void *arg)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* end of extension_auction_brandt.c */
|
||||
|
@ -31,8 +31,12 @@
|
||||
|
||||
enum TALER_Extension_Type
|
||||
{
|
||||
TALER_Extension_AgeRestriction = 0,
|
||||
TALER_Extension_MaxPredefined = 1 // Must be last of the predefined
|
||||
TALER_Extension_Refund = 0,
|
||||
TALER_Extension_AgeRestriction = 1,
|
||||
TALER_Extension_P2P = 2,
|
||||
TALER_Extension_AuctionBrandt = 3,
|
||||
TALER_Extension_Escrow = 4,
|
||||
TALER_Extension_MaxPredefined = 5 // Must be last of the predefined
|
||||
};
|
||||
|
||||
|
||||
@ -59,6 +63,7 @@ struct TALER_Extension
|
||||
char *version;
|
||||
void *config;
|
||||
bool enabled;
|
||||
bool has_config; /* some extension might not have a configuration */
|
||||
json_t *config_json;
|
||||
|
||||
void (*disable)(struct TALER_Extension *ext);
|
||||
@ -78,6 +83,10 @@ struct TALER_Extension
|
||||
const json_t *root,
|
||||
const char *const args[]);
|
||||
|
||||
MHD_RESULT (*http_get_handler)(
|
||||
struct MHD_Connection *connection,
|
||||
const char *const args[]);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -931,6 +931,9 @@ decode_keys_json (const json_t *resp_obj,
|
||||
|
||||
if (! no_extensions && ! no_signature)
|
||||
{
|
||||
GNUNET_log(GNUNET_ERROR_TYPE_INFO,
|
||||
"DEBUG: got extensions object %s\n",
|
||||
json_dumps(extensions, JSON_INDENT(2)));
|
||||
/* 2. We have an extensions object. Verify its signature. */
|
||||
EXITIF (GNUNET_OK !=
|
||||
TALER_extensions_verify_json_config_signature (
|
||||
|
Loading…
Reference in New Issue
Block a user