improved error handling
This commit is contained in:
parent
424bbddaa3
commit
3ec07d62c3
@ -33,6 +33,9 @@
|
||||
/* Path to the replay program. */
|
||||
static char *replay_program;
|
||||
|
||||
/* supported currency */
|
||||
static char *currency;
|
||||
|
||||
/* This is basically BRANDT_Result with an extra string field */
|
||||
struct result
|
||||
{
|
||||
@ -42,28 +45,54 @@ struct result
|
||||
};
|
||||
|
||||
/*
|
||||
* TODO: Transcript information
|
||||
* @brief 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;
|
||||
/*
|
||||
* The first couple of fields are from a JSON transcript
|
||||
*/
|
||||
|
||||
/* Public key of seller */
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey seller_pub;
|
||||
|
||||
/* Payto URL */
|
||||
const char *payto;
|
||||
|
||||
/* Number of bidders + 1 (for seller) */
|
||||
uint16_t n;
|
||||
|
||||
/* (n-1) public keys of bidders */
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey *bidder_pub;
|
||||
|
||||
/* Type of auction, see libbrandt */
|
||||
uint16_t m;
|
||||
|
||||
/* Auction public outcome? */
|
||||
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;
|
||||
/* Start date of the auction */
|
||||
struct GNUNET_TIME_Timestamp time_start;
|
||||
|
||||
struct result *results;
|
||||
size_t results_len;
|
||||
/* End date of the auction */
|
||||
struct GNUNET_TIME_Relative time_round;
|
||||
|
||||
/* Number of prices */
|
||||
uint16_t k;
|
||||
|
||||
/* Prices, must be length k */
|
||||
struct TALER_Amount *prices;
|
||||
|
||||
/* Expected winner(s), maybe NULL */
|
||||
struct result *expected;
|
||||
size_t expected_len;
|
||||
uint16_t id;
|
||||
struct GNUNET_CRYPTO_EccDlogContext *edc;
|
||||
|
||||
/*
|
||||
* These are the results from the replay via the external program.
|
||||
*/
|
||||
struct result *results;
|
||||
size_t results_len;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -71,16 +100,25 @@ struct transcript
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
json_error (json_t **output,
|
||||
char *error)
|
||||
char *error, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int n = 0;
|
||||
char buf[4096];
|
||||
GNUNET_assert (error);
|
||||
|
||||
*output = json_pack ("{s:s}", "error", error);
|
||||
GNUNET_assert (*output);
|
||||
va_start (ap, error);
|
||||
n = vsprintf (buf, error, ap);
|
||||
va_end (ap);
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
LOG_PREFIX "got error: %s\n",
|
||||
error);
|
||||
n < 0 ? error: buf);
|
||||
|
||||
*output = json_pack ("{s:s}",
|
||||
"error",
|
||||
n < 0 ? error : buf);
|
||||
GNUNET_assert (*output);
|
||||
|
||||
return GNUNET_SYSERR;
|
||||
};
|
||||
@ -129,118 +167,153 @@ json_result (json_t **output,
|
||||
* @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
|
||||
* @param[out] tr Parsed transcript data
|
||||
* @param[out] jerror JSON output for errors
|
||||
* @return GNUNET_OK on succes
|
||||
*
|
||||
* TODO:
|
||||
* - fix leakages
|
||||
* - parse and verify signatures
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
parse_transcript (const json_t *jtr,
|
||||
struct transcript *tr,
|
||||
json_t **output)
|
||||
json_t **jerror)
|
||||
{
|
||||
json_t *auc;
|
||||
|
||||
// TODO: struct GNUNET_CRYPTO_EddsaSignature sig;
|
||||
|
||||
GNUNET_assert (jtr);
|
||||
GNUNET_assert (tr);
|
||||
|
||||
// Parse auction
|
||||
{
|
||||
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_fixed_auto ("pubkey", &tr->seller_pub),
|
||||
GNUNET_JSON_spec_timestamp ("time_start", &tr->time_start),
|
||||
GNUNET_JSON_spec_relative_time ("time_round", &tr->time_round),
|
||||
GNUNET_JSON_spec_string ("payto", &tr->payto),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
auc = json_object_get (jtr, "auction");
|
||||
if (NULL == auc)
|
||||
return json_error (output, "no auction found in transcript");
|
||||
return json_error (jerror,
|
||||
"no auction found in transcript");
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (auc,
|
||||
au_spec,
|
||||
(const char **) &perr,
|
||||
&eline))
|
||||
return json_error (output, perr);
|
||||
return json_error (jerror,
|
||||
perr);
|
||||
|
||||
// Prices...
|
||||
{
|
||||
json_t *prices = json_object_get (auc, "prices");
|
||||
size_t idx;
|
||||
json_t *val;
|
||||
json_t *prices;
|
||||
|
||||
|
||||
prices = json_object_get (auc, "prices");
|
||||
if (! json_is_array (prices))
|
||||
// TODO: fix leak!?
|
||||
return json_error (output, "no prices found");
|
||||
return json_error (jerror,
|
||||
"no prices found");
|
||||
|
||||
tr->k = json_array_size (prices);
|
||||
|
||||
tr->prices = GNUNET_new_array (tr->k, char *);
|
||||
tr->prices = GNUNET_new_array (tr->k, struct TALER_Amount);
|
||||
json_array_foreach (prices, idx, val)
|
||||
{
|
||||
if (! json_is_string (val))
|
||||
// TODO: fix leak!_
|
||||
return json_error (output, "prices not strings");
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
TALER_JSON_spec_amount (NULL,
|
||||
currency,
|
||||
&(tr->prices[idx])),
|
||||
GNUNET_JSON_spec_end (),
|
||||
};
|
||||
|
||||
tr->prices[idx] = (char *) json_string_value (val);
|
||||
|
||||
// TODO: parse prices
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (val,
|
||||
spec,
|
||||
NULL,
|
||||
NULL))
|
||||
return json_error (jerror,
|
||||
"price no. %ld couldn't be parsed",
|
||||
idx + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bidders
|
||||
{
|
||||
size_t idx;
|
||||
json_t *val;
|
||||
json_t *bidders;
|
||||
|
||||
bidders = json_object_get (jtr, "bidders");
|
||||
if (! bidders || ! json_is_array (bidders))
|
||||
// TODO: fix leak!_
|
||||
return json_error (output, "bidders not found");
|
||||
return json_error (jerror,
|
||||
"no bidders found");
|
||||
|
||||
// TODO: parse bidders as pub keys;
|
||||
tr->n = json_array_size (bidders);
|
||||
|
||||
tr->bidder_pub = GNUNET_new_array (tr->n, struct
|
||||
GNUNET_CRYPTO_EddsaPublicKey);
|
||||
json_array_foreach (bidders, idx, val)
|
||||
{
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_fixed_auto (NULL,
|
||||
&(tr->bidder_pub[idx])),
|
||||
GNUNET_JSON_spec_end (),
|
||||
};
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (val,
|
||||
spec,
|
||||
NULL,
|
||||
NULL))
|
||||
return json_error (jerror,
|
||||
"bidder no %ld public key couldn't be parsed",
|
||||
idx + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: parse and verify signatures from bidders of the auction
|
||||
|
||||
|
||||
// Messages
|
||||
{
|
||||
json_t *messages;
|
||||
size_t nm;
|
||||
json_t *messages = json_object_get (jtr, "transcript");
|
||||
|
||||
messages = json_object_get (jtr, "transcript");
|
||||
if (! json_is_array (messages))
|
||||
// TODO: fix leak!
|
||||
return json_error (output, "no messages found");
|
||||
return json_error (jerror,
|
||||
"no messages found");
|
||||
|
||||
|
||||
nm = json_array_size (messages);
|
||||
|
||||
if (nm != (4 * tr->n))
|
||||
// TODO: fix leak!
|
||||
return json_error (output, "not the right no. of messages found");
|
||||
return json_error (jerror,
|
||||
"not the right no. of messages found");
|
||||
|
||||
/* TODO: parse and evaluate signatures */
|
||||
}
|
||||
|
||||
// Winners
|
||||
{
|
||||
json_t *winners;
|
||||
size_t idx;
|
||||
json_t *val;
|
||||
|
||||
winners = json_object_get (jtr, "winners");
|
||||
json_t *winners = json_object_get (jtr, "winners");
|
||||
|
||||
if (! json_is_array (winners))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
LOG_PREFIX "winners not provided, continuing without\n");
|
||||
// TODO: fix leakage
|
||||
goto CONT;
|
||||
goto DONE;
|
||||
}
|
||||
|
||||
tr->expected_len = json_array_size (winners);
|
||||
@ -248,8 +321,6 @@ parse_transcript (const json_t *jtr,
|
||||
struct result);
|
||||
|
||||
json_array_foreach (winners, idx, val) {
|
||||
char *error;
|
||||
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_uint16 ("bidder",
|
||||
&(tr->expected[idx].bidder)),
|
||||
@ -263,16 +334,21 @@ parse_transcript (const json_t *jtr,
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (val,
|
||||
spec,
|
||||
(const char**) &error,
|
||||
NULL,
|
||||
NULL))
|
||||
// TODO: fix leak!
|
||||
return json_error (output, "couldn't parse winners");
|
||||
return json_error (jerror,
|
||||
"couldn't parse winner no. %ld",
|
||||
idx + 1);
|
||||
}
|
||||
|
||||
CONT:
|
||||
// TODO: fix leakages
|
||||
}
|
||||
*output = NULL;
|
||||
|
||||
// TODO: parse and evalue sig of seller
|
||||
|
||||
// TODO: check for max values
|
||||
|
||||
DONE:
|
||||
|
||||
*jerror = NULL;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
@ -285,7 +361,7 @@ CONT:
|
||||
* @param[out] result The JSON result from the program
|
||||
* @return GNUNET_OK on success
|
||||
*
|
||||
* TODO: Make this asynchronous (giving out a replay-ID to poll from)?
|
||||
* TODO: Make this resumable
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
replay_transcript (const json_t*root,
|
||||
@ -338,6 +414,9 @@ replay_transcript (const json_t*root,
|
||||
{
|
||||
ssize_t sz;
|
||||
char buf[MAX_RESULT_SIZE];
|
||||
json_error_t error;
|
||||
json_t *res;
|
||||
|
||||
fd = GNUNET_DISK_pipe_handle (po, GNUNET_DISK_PIPE_END_READ);
|
||||
|
||||
sz = GNUNET_DISK_file_read (fd,
|
||||
@ -347,21 +426,62 @@ replay_transcript (const json_t*root,
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
LOG_PREFIX "couldn't read data from replay_program\n");
|
||||
return json_error (result, "internal error");
|
||||
}
|
||||
else
|
||||
|
||||
buf[sz] = 0;
|
||||
res = json_loads (buf,
|
||||
JSON_DECODE_ANY,
|
||||
&error);
|
||||
|
||||
if (! res)
|
||||
{
|
||||
json_error_t error;
|
||||
json_t *res;
|
||||
res = json_loads (buf,
|
||||
JSON_DECODE_ANY,
|
||||
&error);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
LOG_PREFIX
|
||||
"couldn't parse response from replay_program: %s (for '%s')\n",
|
||||
error.text,
|
||||
buf);
|
||||
return json_error (result, error.text);
|
||||
}
|
||||
|
||||
if (! res)
|
||||
return json_error (result, error.text);
|
||||
// Handle error case first
|
||||
{
|
||||
json_t *err = json_object_get (res,
|
||||
"error");
|
||||
if (NULL != err)
|
||||
{
|
||||
*result = json_copy (res);
|
||||
json_decref (res);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the result
|
||||
{
|
||||
json_t *winners = json_object_get (res,
|
||||
"winners");
|
||||
if ((NULL == winners) ||
|
||||
(! json_is_array (winners)))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
LOG_PREFIX
|
||||
"replay program didn't return a known result type, instead: '%s'\n",
|
||||
json_dumps (res, JSON_INDENT (2)));
|
||||
return json_error (result, "internal error");
|
||||
}
|
||||
|
||||
{
|
||||
// TODO: check each winner with tr->expected, if applicable
|
||||
json_object_set (res, "exchange_sig", json_string (
|
||||
"sig(priv_E, winners)"));
|
||||
|
||||
}
|
||||
|
||||
// TODO: return own result object.
|
||||
*result = json_copy (res);
|
||||
json_decref (res);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (GNUNET_OK != GNUNET_OS_process_wait (proc))
|
||||
@ -375,7 +495,6 @@ replay_transcript (const json_t*root,
|
||||
}
|
||||
|
||||
|
||||
// TODO: parse result
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
@ -389,6 +508,7 @@ static void
|
||||
auction_disable (
|
||||
struct TALER_Extension *ext)
|
||||
{
|
||||
/* TODO: cleanup configuration */
|
||||
ext->enabled = false;
|
||||
}
|
||||
|
||||
@ -418,7 +538,7 @@ static json_t *
|
||||
auction_config_to_json (
|
||||
const struct TALER_Extension *ext)
|
||||
{
|
||||
/* This extension has no configuration */
|
||||
/* TODO: add configuration */
|
||||
return GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_bool ("critical", ext->critical),
|
||||
GNUNET_JSON_pack_string ("version", ext->version));
|
||||
@ -436,7 +556,7 @@ auction_load_json_config (
|
||||
struct TALER_Extension *ext,
|
||||
json_t *jconfig)
|
||||
{
|
||||
/* This extension has no configuration */
|
||||
/* TODO: add configuration */
|
||||
ext->enabled = true;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
@ -465,6 +585,8 @@ auction_http_get_handler (
|
||||
|
||||
/**
|
||||
* @brief implements the TALER_Extension.http_post_handler
|
||||
*
|
||||
* TODO: make this non-blocking
|
||||
*/
|
||||
static MHD_RESULT
|
||||
auction_http_post_handler (
|
||||
@ -505,7 +627,7 @@ struct TALER_Extension TE_auction_brandt = {
|
||||
.critical = false,
|
||||
.version = "0",
|
||||
.enabled = false, /* disabled per default */
|
||||
.has_config = false, /* This extension has no configuration */
|
||||
.has_config = true,
|
||||
.config = NULL,
|
||||
.config_json = NULL,
|
||||
.disable = &auction_disable,
|
||||
@ -537,6 +659,12 @@ libtaler_extension_auction_brandt_init (void *arg)
|
||||
{
|
||||
const struct GNUNET_CONFIGURATION_Handle *cfg = arg;
|
||||
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_config_get_currency (cfg,
|
||||
¤cy))
|
||||
return NULL;
|
||||
|
||||
if (GNUNET_SYSERR ==
|
||||
GNUNET_CONFIGURATION_get_value_string (cfg,
|
||||
TALER_EXTENSION_SECTION_PREFIX
|
||||
@ -549,11 +677,37 @@ libtaler_extension_auction_brandt_init (void *arg)
|
||||
"REPLAY_PROGRAM");
|
||||
return NULL;
|
||||
}
|
||||
/* TODO: check if replay_program is actually executable */
|
||||
|
||||
/* check if replay_program is actually an executable */
|
||||
{
|
||||
struct stat sb;
|
||||
|
||||
if (0 != stat (replay_program, &sb))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
LOG_PREFIX "replay_program '%s' not found\n",
|
||||
replay_program);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( (sb.st_mode & S_IFDIR) ||
|
||||
! (sb.st_mode & S_IXUSR))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
LOG_PREFIX "replay_program '%s' is not an executable\n",
|
||||
replay_program);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
LOG_PREFIX "loading... using replay_program '%s'\n",
|
||||
replay_program);
|
||||
|
||||
/* TODO: read other config parameters and generate configuration */
|
||||
|
||||
|
||||
return &TE_auction_brandt;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user