share more code in mint API, misc bugfixes

This commit is contained in:
Christian Grothoff 2015-07-11 23:07:36 +02:00
parent a74f55754a
commit 6170dbbf37
8 changed files with 303 additions and 539 deletions

View File

@ -31,15 +31,6 @@
#include "taler_signatures.h"
/**
* Print JSON parsing related error information
*/
#define JSON_WARN(error) \
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, \
"JSON parsing failed at %s:%u: %s (%s)", \
__FILE__, __LINE__, error.text, error.source)
/**
* @brief An admin/add/incoming Handle
*/
@ -84,18 +75,7 @@ struct TALER_MINT_AdminAddIncomingHandle
/**
* Download buffer
*/
void *buf;
/**
* The size of the download buffer
*/
size_t buf_size;
/**
* Error code (based on libc errno) if we failed to download
* (i.e. response too large).
*/
int eno;
struct MAC_DownloadBuffer db;
};
@ -113,35 +93,12 @@ handle_admin_add_incoming_finished (void *cls,
{
struct TALER_MINT_AdminAddIncomingHandle *aai = cls;
long response_code;
json_error_t error;
json_t *json;
aai->job = NULL;
json = NULL;
if (0 == aai->eno)
{
json = json_loadb (aai->buf,
aai->buf_size,
JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK,
&error);
if (NULL == json)
{
JSON_WARN (error);
response_code = 0;
}
}
if (NULL != json)
{
if (CURLE_OK !=
curl_easy_getinfo (eh,
CURLINFO_RESPONSE_CODE,
&response_code))
{
/* unexpected error... */
GNUNET_break (0);
response_code = 0;
}
}
json = MAC_download_get_result (&aai->db,
eh,
&response_code);
switch (response_code)
{
case 0:
@ -170,6 +127,9 @@ handle_admin_add_incoming_finished (void *cls,
break;
default:
/* unexpected response code */
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u\n",
response_code);
GNUNET_break (0);
response_code = 0;
break;
@ -182,49 +142,6 @@ handle_admin_add_incoming_finished (void *cls,
}
/**
* Callback used when downloading the reply to a /admin/add/incoming
* request. Just appends all of the data to the `buf` in the `struct
* TALER_MINT_AdminAddIncomingHandle` for further processing. The size
* of the download is limited to #GNUNET_MAX_MALLOC_CHECKED, if the
* download exceeds this size, we abort with an error.
*
* @param bufptr data downloaded via HTTP
* @param size size of an item in @a bufptr
* @param nitems number of items in @a bufptr
* @param cls the `struct TALER_MINT_DepositHandle`
* @return number of bytes processed from @a bufptr
*/
static int
admin_add_incoming_download_cb (char *bufptr,
size_t size,
size_t nitems,
void *cls)
{
struct TALER_MINT_AdminAddIncomingHandle *aai = cls;
size_t msize;
void *buf;
if (0 == size * nitems)
{
/* Nothing (left) to do */
return 0;
}
msize = size * nitems;
if ( (msize + aai->buf_size) >= GNUNET_MAX_MALLOC_CHECKED)
{
aai->eno = ENOMEM;
return 0; /* signals an error to curl */
}
aai->buf = GNUNET_realloc (aai->buf,
aai->buf_size + msize);
buf = aai->buf + aai->buf_size;
memcpy (buf, bufptr, msize);
aai->buf_size += msize;
return msize;
}
/**
* Notify the mint that we have received an incoming transaction
* which fills a reserve. Note that this API is an administrative
@ -265,7 +182,7 @@ TALER_MINT_admin_add_incoming (struct TALER_MINT_Handle *mint,
return NULL;
}
admin_obj = json_pack ("{s:o, s:o," /* reserve_pub/amount */
" s:o, s:o}", /* execution_Date/wire */
" s:o, s:O}", /* execution_Date/wire */
"reserve_pub", TALER_json_from_data (reserve_pub,
sizeof (*reserve_pub)),
"amount", TALER_json_from_amount (amount),
@ -297,21 +214,15 @@ TALER_MINT_admin_add_incoming (struct TALER_MINT_Handle *mint,
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_WRITEFUNCTION,
&admin_add_incoming_download_cb));
&MAC_download_cb));
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_WRITEDATA,
aai));
GNUNET_assert (NULL != (aai->headers =
curl_slist_append (aai->headers,
"Content-Type: application/json")));
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_HTTPHEADER,
aai->headers));
&aai->db));
ctx = MAH_handle_to_context (mint);
aai->job = MAC_job_add (ctx,
eh,
GNUNET_YES,
&handle_admin_add_incoming_finished,
aai);
return aai;
@ -333,6 +244,7 @@ TALER_MINT_admin_add_incoming_cancel (struct TALER_MINT_AdminAddIncomingHandle *
aai->job = NULL;
}
curl_slist_free_all (aai->headers);
GNUNET_free_non_null (aai->db.buf);
GNUNET_free (aai->url);
GNUNET_free (aai->json_enc);
GNUNET_free (aai);

View File

@ -34,9 +34,18 @@
* @param code what was the curl error code
*/
#define CURL_STRERROR(type, function, code) \
GNUNET_log (type, "Curl function `%s' has failed at `%s:%d' with error: %s", \
GNUNET_log (type, \
"Curl function `%s' has failed at `%s:%d' with error: %s\n", \
function, __FILE__, __LINE__, curl_easy_strerror (code));
/**
* Print JSON parsing related error information
*/
#define JSON_WARN(error) \
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, \
"JSON parsing failed at %s:%u: %s (%s)\n", \
__FILE__, __LINE__, error.text, error.source)
/**
* Failsafe flag. Raised if our constructor fails to initialize
@ -109,6 +118,12 @@ struct TALER_MINT_Context
*/
struct MAC_Job *jobs_tail;
/**
* HTTP header "application/json", created once and used
* for all requests that need it.
*/
struct curl_slist *json_header;
};
@ -146,6 +161,9 @@ TALER_MINT_init ()
ctx = GNUNET_new (struct TALER_MINT_Context);
ctx->multi = multi;
ctx->share = share;
GNUNET_assert (NULL != (ctx->json_header =
curl_slist_append (NULL,
"Content-Type: application/json")));
return ctx;
}
@ -157,20 +175,31 @@ TALER_MINT_init ()
* instead use #MAC_easy_to_closure to extract the @a jcc_cls argument
* from a valid @a eh afterwards.
*
* This function modifies the CURL handle to add the
* "Content-Type: application/json" header if @a add_json is set.
*
* @param ctx context to execute the job in
* @param eh curl easy handle for the request, will
* be executed AND cleaned up
* @param add_json add "application/json" content type header
* @param jcc callback to invoke upon completion
* @param jcc_cls closure for @a jcc
*/
struct MAC_Job *
MAC_job_add (struct TALER_MINT_Context *ctx,
CURL *eh,
int add_json,
MAC_JobCompletionCallback jcc,
void *jcc_cls)
{
struct MAC_Job *job;
if (GNUNET_YES == add_json)
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_HTTPHEADER,
ctx->json_header));
job = GNUNET_new (struct MAC_Job);
job->easy_handle = eh;
job->ctx = ctx;
@ -333,10 +362,112 @@ TALER_MINT_fini (struct TALER_MINT_Context *ctx)
GNUNET_assert (NULL == ctx->jobs_head);
curl_share_cleanup (ctx->share);
curl_multi_cleanup (ctx->multi);
curl_slist_free_all (ctx->json_header);
GNUNET_free (ctx);
}
/**
* Callback used when downloading the reply to an HTTP request.
* Just appends all of the data to the `buf` in the
* `struct MAC_DownloadBuffer` for further processing. The size of
* the download is limited to #GNUNET_MAX_MALLOC_CHECKED, if
* the download exceeds this size, we abort with an error.
*
* @param bufptr data downloaded via HTTP
* @param size size of an item in @a bufptr
* @param nitems number of items in @a bufptr
* @param cls the `struct KeysRequest`
* @return number of bytes processed from @a bufptr
*/
size_t
MAC_download_cb (char *bufptr,
size_t size,
size_t nitems,
void *cls)
{
struct MAC_DownloadBuffer *db = cls;
size_t msize;
void *buf;
if (0 == size * nitems)
{
/* Nothing (left) to do */
return 0;
}
msize = size * nitems;
if ( (msize + db->buf_size) >= GNUNET_MAX_MALLOC_CHECKED)
{
db->eno = ENOMEM;
return 0; /* signals an error to curl */
}
db->buf = GNUNET_realloc (db->buf,
db->buf_size + msize);
buf = db->buf + db->buf_size;
memcpy (buf, bufptr, msize);
db->buf_size += msize;
return msize;
}
/**
* Obtain information about the final result about the
* HTTP download. If the download was successful, parses
* the JSON in the @a db and returns it. Also returns
* the HTTP @a response_code. If the download failed,
* the return value is NULL. The response code is set
* in any case, on download errors to zero.
*
* Calling this function also cleans up @a db.
*
* @param db download buffer
* @param eh CURL handle (to get the response code)
* @param[out] response_code set to the HTTP response code
* (or zero if we aborted the download, i.e.
* because the response was too big, or if
* the JSON we received was malformed).
* @return NULL if downloading a JSON reply failed
*/
json_t *
MAC_download_get_result (struct MAC_DownloadBuffer *db,
CURL *eh,
long *response_code)
{
json_t *json;
json_error_t error;
json = NULL;
if (0 == db->eno)
{
json = json_loadb (db->buf,
db->buf_size,
JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK,
&error);
if (NULL == json)
{
JSON_WARN (error);
*response_code = 0;
}
}
GNUNET_free_non_null (db->buf);
db->buf = NULL;
db->buf_size = 0;
if (NULL != json)
{
if (CURLE_OK !=
curl_easy_getinfo (eh,
CURLINFO_RESPONSE_CODE,
response_code))
{
/* unexpected error... */
GNUNET_break (0);
*response_code = 0;
}
}
return json;
}
/**
* Initial global setup logic, specifically runs the Curl setup.
*/

View File

@ -50,15 +50,20 @@ typedef void
* instead use #MAC_easy_to_closure to extract the @a jcc_cls argument
* from a valid @a eh afterwards.
*
* This function modifies the CURL handle to add the
* "Content-Type: application/json" header if @a add_json is set.
*
* @param ctx context to execute the job in
* @param eh curl easy handle for the request, will
* be executed AND cleaned up
* @param add_json add "application/json" content type header
* @param jcc callback to invoke upon completion
* @param jcc_cls closure for @a jcc
*/
struct MAC_Job *
MAC_job_add (struct TALER_MINT_Context *ctx,
CURL *eh,
int add_json,
MAC_JobCompletionCallback jcc,
void *jcc_cls);
@ -84,4 +89,81 @@ void
MAC_job_cancel (struct MAC_Job *job);
/**
* Buffer data structure we use to buffer the HTTP download
* before giving it to the JSON parser.
*/
struct MAC_DownloadBuffer
{
/**
* Download buffer
*/
void *buf;
/**
* The size of the download buffer
*/
size_t buf_size;
/**
* Error code (based on libc errno) if we failed to download
* (i.e. response too large).
*/
int eno;
};
/**
* Callback used when downloading the reply to an HTTP request.
* Just appends all of the data to the `buf` in the
* `struct MAC_DownloadBuffer` for further processing. The size of
* the download is limited to #GNUNET_MAX_MALLOC_CHECKED, if
* the download exceeds this size, we abort with an error.
*
* Should be used by the various routines as the
* CURLOPT_WRITEFUNCTION. A `struct MAC_DownloadBuffer` needs to be
* passed to the CURLOPT_WRITEDATA.
*
* Afterwards, `eno` needs to be checked to ensure that the download
* completed correctly.
*
* @param bufptr data downloaded via HTTP
* @param size size of an item in @a bufptr
* @param nitems number of items in @a bufptr
* @param cls the `struct KeysRequest`
* @return number of bytes processed from @a bufptr
*/
size_t
MAC_download_cb (char *bufptr,
size_t size,
size_t nitems,
void *cls);
/**
* Obtain information about the final result about the
* HTTP download. If the download was successful, parses
* the JSON in the @a db and returns it. Also returns
* the HTTP @a response_code. If the download failed,
* the return value is NULL. The response code is set
* in any case, on download errors to zero.
*
* Calling this function also cleans up @a db.
*
* @param db download buffer
* @param eh CURL handle (to get the response code)
* @param[out] response_code set to the HTTP response code
* (or zero if we aborted the download, i.e.
* because the response was too big, or if
* the JSON we received was malformed).
* @return NULL if downloading a JSON reply failed
*/
json_t *
MAC_download_get_result (struct MAC_DownloadBuffer *db,
CURL *eh,
long *response_code);
/* end of mint_api_context.h */

View File

@ -32,15 +32,6 @@
#include "taler_signatures.h"
/**
* Print JSON parsing related error information
*/
#define JSON_WARN(error) \
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, \
"JSON parsing failed at %s:%u: %s (%s)\n", \
__FILE__, __LINE__, error.text, error.source)
/**
* @brief A Deposit Handle
*/
@ -67,11 +58,6 @@ struct TALER_MINT_DepositHandle
*/
struct MAC_Job *job;
/**
* HTTP headers for the request.
*/
struct curl_slist *headers;
/**
* Function to call with the result.
*/
@ -85,7 +71,7 @@ struct TALER_MINT_DepositHandle
/**
* Download buffer
*/
void *buf;
struct MAC_DownloadBuffer db;
/**
* Information the mint should sign in response.
@ -102,17 +88,6 @@ struct TALER_MINT_DepositHandle
*/
struct TALER_Amount coin_value;
/**
* The size of the download buffer
*/
size_t buf_size;
/**
* Error code (based on libc errno) if we failed to download
* (i.e. response too large).
*/
int eno;
};
@ -321,35 +296,12 @@ handle_deposit_finished (void *cls,
{
struct TALER_MINT_DepositHandle *dh = cls;
long response_code;
json_error_t error;
json_t *json;
dh->job = NULL;
json = NULL;
if (0 == dh->eno)
{
json = json_loadb (dh->buf,
dh->buf_size,
JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK,
&error);
if (NULL == json)
{
JSON_WARN (error);
response_code = 0;
}
}
if (NULL != json)
{
if (CURLE_OK !=
curl_easy_getinfo (eh,
CURLINFO_RESPONSE_CODE,
&response_code))
{
/* unexpected error... */
GNUNET_break (0);
response_code = 0;
}
}
json = MAC_download_get_result (&dh->db,
eh,
&response_code);
switch (response_code)
{
case 0:
@ -484,49 +436,6 @@ verify_signatures (const struct TALER_MINT_DenomPublicKey *dki,
}
/**
* Callback used when downloading the reply to a /deposit request.
* Just appends all of the data to the `buf` in the
* `struct TALER_MINT_DepositHandle` for further processing. The size of
* the download is limited to #GNUNET_MAX_MALLOC_CHECKED, if
* the download exceeds this size, we abort with an error.
*
* @param bufptr data downloaded via HTTP
* @param size size of an item in @a bufptr
* @param nitems number of items in @a bufptr
* @param cls the `struct TALER_MINT_DepositHandle`
* @return number of bytes processed from @a bufptr
*/
static int
deposit_download_cb (char *bufptr,
size_t size,
size_t nitems,
void *cls)
{
struct TALER_MINT_DepositHandle *dh = cls;
size_t msize;
void *buf;
if (0 == size * nitems)
{
/* Nothing (left) to do */
return 0;
}
msize = size * nitems;
if ( (msize + dh->buf_size) >= GNUNET_MAX_MALLOC_CHECKED)
{
dh->eno = ENOMEM;
return 0; /* signals an error to curl */
}
dh->buf = GNUNET_realloc (dh->buf,
dh->buf_size + msize);
buf = dh->buf + dh->buf_size;
memcpy (buf, bufptr, msize);
dh->buf_size += msize;
return msize;
}
/**
* Submit a deposit permission to the mint and get the mint's response.
* Note that while we return the response verbatim to the caller for
@ -624,7 +533,7 @@ TALER_MINT_deposit (struct TALER_MINT_Handle *mint,
return NULL;
}
deposit_obj = json_pack ("{s:o, s:o," /* f/wire */
deposit_obj = json_pack ("{s:o, s:O," /* f/wire */
" s:o, s:o," /* H_wire, H_contract */
" s:o, s:o," /* coin_pub, denom_pub */
" s:o, s:o," /* ub_sig, timestamp */
@ -691,21 +600,15 @@ TALER_MINT_deposit (struct TALER_MINT_Handle *mint,
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_WRITEFUNCTION,
&deposit_download_cb));
&MAC_download_cb));
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_WRITEDATA,
dh));
GNUNET_assert (NULL != (dh->headers =
curl_slist_append (dh->headers,
"Content-Type: application/json")));
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_HTTPHEADER,
dh->headers));
&dh->db));
ctx = MAH_handle_to_context (mint);
dh->job = MAC_job_add (ctx,
eh,
GNUNET_YES,
&handle_deposit_finished,
dh);
return dh;
@ -726,7 +629,7 @@ TALER_MINT_deposit_cancel (struct TALER_MINT_DepositHandle *deposit)
MAC_job_cancel (deposit->job);
deposit->job = NULL;
}
curl_slist_free_all (deposit->headers);
GNUNET_free_non_null (deposit->db.buf);
GNUNET_free (deposit->url);
GNUNET_free (deposit->json_enc);
GNUNET_free (deposit);

View File

@ -44,14 +44,6 @@
function, __FILE__, __LINE__, curl_easy_strerror (code));
/**
* Print JSON parsing related error information
*/
#define JSON_WARN(error) \
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, \
"JSON parsing failed at %s:%u: %s (%s)", \
__FILE__, __LINE__, error.text, error.source)
/**
* Stages of initialization for the `struct TALER_MINT_Handle`
*/
@ -149,72 +141,13 @@ struct KeysRequest
struct MAC_Job *job;
/**
* Error buffer for Curl. Do we need this?
* Data structure for the download.
*/
char emsg[CURL_ERROR_SIZE];
/**
* Download buffer
*/
void *buf;
/**
* The size of the download buffer
*/
size_t buf_size;
/**
* Error code (based on libc errno) if we failed to download
* (i.e. response too large).
*/
int eno;
struct MAC_DownloadBuffer db;
};
/**
* Callback used when downloading the reply to a /keys request.
* Just appends all of the data to the `buf` in the
* `struct KeysRequest` for further processing. The size of
* the download is limited to #GNUNET_MAX_MALLOC_CHECKED, if
* the download exceeds this size, we abort with an error.
*
* @param bufptr data downloaded via HTTP
* @param size size of an item in @a bufptr
* @param nitems number of items in @a bufptr
* @param cls the `struct KeysRequest`
* @return number of bytes processed from @a bufptr
*/
static size_t
keys_download_cb (char *bufptr,
size_t size,
size_t nitems,
void *cls)
{
struct KeysRequest *kr = cls;
size_t msize;
void *buf;
if (0 == size * nitems)
{
/* Nothing (left) to do */
return 0;
}
msize = size * nitems;
if ( (msize + kr->buf_size) >= GNUNET_MAX_MALLOC_CHECKED)
{
kr->eno = ENOMEM;
return 0; /* signals an error to curl */
}
kr->buf = GNUNET_realloc (kr->buf,
kr->buf_size + msize);
buf = kr->buf + kr->buf_size;
memcpy (buf, bufptr, msize);
kr->buf_size += msize;
return msize;
}
/**
* Release memory occupied by a keys request.
* Note that this does not cancel the request
@ -225,7 +158,7 @@ keys_download_cb (char *bufptr,
static void
free_keys_request (struct KeysRequest *kr)
{
GNUNET_free_non_null (kr->buf);
GNUNET_free_non_null (kr->db.buf);
GNUNET_free (kr->url);
GNUNET_free (kr);
}
@ -493,7 +426,6 @@ decode_keys_json (json_t *resp_obj,
hash_context));
}
}
return GNUNET_OK;
/* FIXME: parse the auditor keys (#3847) */
@ -521,48 +453,6 @@ decode_keys_json (json_t *resp_obj,
}
/**
* We have successfully received the reply to the /keys
* request from the mint. We now need to parse the reply
* and, if successful, store the resulting information
* in the `key_data` structure.
*
* @param kr key request with all of the data to parse
* and references to the `struct TALER_MINT_Handle`
* where we need to store the result
* @return #GNUNET_OK on success,
* #GNUNET_SYSERR on failure
*/
static int
parse_response_keys_get (struct KeysRequest *kr)
{
json_t *resp_obj;
json_error_t error;
int ret;
resp_obj = json_loadb (kr->buf,
kr->buf_size,
JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK,
&error);
if (NULL == resp_obj)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unable to parse received /keys data as JSON object\n");
GNUNET_free_non_null (kr->buf);
kr->buf = NULL;
kr->buf_size = 0;
return GNUNET_SYSERR;
}
GNUNET_free_non_null (kr->buf);
kr->buf = NULL;
kr->buf_size = 0;
ret = decode_keys_json (resp_obj,
&kr->mint->key_data);
json_decref (resp_obj);
return ret;
}
/**
* Callback used when downloading the reply to a /keys request
* is complete.
@ -576,35 +466,32 @@ keys_completed_cb (void *cls,
{
struct KeysRequest *kr = cls;
struct TALER_MINT_Handle *mint = kr->mint;
json_t *resp_obj;
long response_code;
/* FIXME: might want to check response code? */
if (CURLE_OK !=
curl_easy_getinfo (eh,
CURLINFO_RESPONSE_CODE,
&response_code))
{
/* unexpected error... */
GNUNET_break (0);
response_code = 0;
}
resp_obj = MAC_download_get_result (&kr->db,
eh,
&response_code);
switch (response_code) {
case 0:
kr->eno = 1;
break;
case MHD_HTTP_OK:
if ( (NULL == resp_obj) ||
(GNUNET_OK !=
decode_keys_json (resp_obj,
&kr->mint->key_data)) )
response_code = 0;
break;
default:
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Mint returned status code %u for /keys\n",
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u\n",
response_code);
kr->eno = 1;
break;
}
if (NULL != resp_obj)
json_decref (resp_obj);
if ( (0 != kr->eno) ||
(GNUNET_OK !=
parse_response_keys_get (kr)) )
if (MHD_HTTP_OK != response_code)
{
mint->kr = NULL;
free_keys_request (kr);
@ -722,20 +609,17 @@ TALER_MINT_connect (struct TALER_MINT_Context *ctx,
curl_easy_setopt (c,
CURLOPT_URL,
kr->url));
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (c,
CURLOPT_ERRORBUFFER,
kr->emsg));
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (c,
CURLOPT_WRITEFUNCTION,
&keys_download_cb));
&MAC_download_cb));
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (c,
CURLOPT_WRITEDATA,
kr));
&kr->db));
kr->job = MAC_job_add (mint->ctx,
c,
GNUNET_NO,
&keys_completed_cb,
kr);
mint->kr = kr;
@ -751,6 +635,8 @@ TALER_MINT_connect (struct TALER_MINT_Context *ctx,
void
TALER_MINT_disconnect (struct TALER_MINT_Handle *mint)
{
unsigned int i;
if (NULL != mint->kr)
{
MAC_job_cancel (mint->kr->job);
@ -760,6 +646,8 @@ TALER_MINT_disconnect (struct TALER_MINT_Handle *mint)
GNUNET_array_grow (mint->key_data.sign_keys,
mint->key_data.num_sign_keys,
0);
for (i=0;i<mint->key_data.num_denom_keys;i++)
GNUNET_CRYPTO_rsa_public_key_free (mint->key_data.denom_keys[i].key.rsa_public_key);
GNUNET_array_grow (mint->key_data.denom_keys,
mint->key_data.num_denom_keys,
0);

View File

@ -31,15 +31,6 @@
#include "taler_signatures.h"
/**
* Print JSON parsing related error information
*/
#define JSON_WARN(error) \
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, \
"JSON parsing failed at %s:%u: %s (%s)\n", \
__FILE__, __LINE__, error.text, error.source)
/* ********************** /withdraw/status ********************** */
/**
@ -81,18 +72,7 @@ struct TALER_MINT_WithdrawStatusHandle
/**
* Download buffer
*/
void *buf;
/**
* The size of the download buffer
*/
size_t buf_size;
/**
* Error code (based on libc errno) if we failed to download
* (i.e. response too large).
*/
int eno;
struct MAC_DownloadBuffer db;
};
@ -295,35 +275,12 @@ handle_withdraw_status_finished (void *cls,
{
struct TALER_MINT_WithdrawStatusHandle *wsh = cls;
long response_code;
json_error_t error;
json_t *json;
wsh->job = NULL;
json = NULL;
if (0 == wsh->eno)
{
json = json_loadb (wsh->buf,
wsh->buf_size,
JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK,
&error);
if (NULL == json)
{
JSON_WARN (error);
response_code = 0;
}
}
if (NULL != json)
{
if (CURLE_OK !=
curl_easy_getinfo (eh,
CURLINFO_RESPONSE_CODE,
&response_code))
{
/* unexpected error... */
GNUNET_break (0);
response_code = 0;
}
}
json = MAC_download_get_result (&wsh->db,
eh,
&response_code);
switch (response_code)
{
case 0:
@ -404,6 +361,9 @@ handle_withdraw_status_finished (void *cls,
break;
default:
/* unexpected response code */
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u\n",
response_code);
GNUNET_break (0);
response_code = 0;
break;
@ -419,49 +379,6 @@ handle_withdraw_status_finished (void *cls,
}
/**
* Callback used when downloading the reply to a /withdraw/status request.
* Just appends all of the data to the `buf` in the
* `struct TALER_MINT_WithdrawStatusHandle` for further processing. The size of
* the download is limited to #GNUNET_MAX_MALLOC_CHECKED, if
* the download exceeds this size, we abort with an error.
*
* @param bufptr data downloaded via HTTP
* @param size size of an item in @a bufptr
* @param nitems number of items in @a bufptr
* @param cls the `struct TALER_MINT_DepositHandle`
* @return number of bytes processed from @a bufptr
*/
static int
withdraw_status_download_cb (char *bufptr,
size_t size,
size_t nitems,
void *cls)
{
struct TALER_MINT_WithdrawStatusHandle *wsh = cls;
size_t msize;
void *buf;
if (0 == size * nitems)
{
/* Nothing (left) to do */
return 0;
}
msize = size * nitems;
if ( (msize + wsh->buf_size) >= GNUNET_MAX_MALLOC_CHECKED)
{
wsh->eno = ENOMEM;
return 0; /* signals an error to curl */
}
wsh->buf = GNUNET_realloc (wsh->buf,
wsh->buf_size + msize);
buf = wsh->buf + wsh->buf_size;
memcpy (buf, bufptr, msize);
wsh->buf_size += msize;
return msize;
}
/**
* Submit a request to obtain the transaction history of a reserve
* from the mint. Note that while we return the full response to the
@ -519,14 +436,15 @@ TALER_MINT_withdraw_status (struct TALER_MINT_Handle *mint,
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_WRITEFUNCTION,
&withdraw_status_download_cb));
&MAC_download_cb));
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_WRITEDATA,
wsh));
&wsh->db));
ctx = MAH_handle_to_context (mint);
wsh->job = MAC_job_add (ctx,
eh,
GNUNET_NO,
&handle_withdraw_status_finished,
wsh);
return wsh;
@ -547,6 +465,7 @@ TALER_MINT_withdraw_status_cancel (struct TALER_MINT_WithdrawStatusHandle *wsh)
MAC_job_cancel (wsh->job);
wsh->job = NULL;
}
GNUNET_free_non_null (wsh->db.buf);
GNUNET_free (wsh->url);
GNUNET_free (wsh);
}
@ -580,11 +499,6 @@ struct TALER_MINT_WithdrawSignHandle
*/
struct MAC_Job *job;
/**
* HTTP headers for the request.
*/
struct curl_slist *headers;
/**
* Function to call with the result.
*/
@ -608,7 +522,7 @@ struct TALER_MINT_WithdrawSignHandle
/**
* Download buffer
*/
void *buf;
struct MAC_DownloadBuffer db;
/**
* Hash of the public key of the coin we are signing.
@ -620,17 +534,6 @@ struct TALER_MINT_WithdrawSignHandle
*/
struct TALER_ReservePublicKeyP reserve_pub;
/**
* The size of the download buffer
*/
size_t buf_size;
/**
* Error code (based on libc errno) if we failed to download
* (i.e. response too large).
*/
int eno;
};
@ -797,33 +700,12 @@ handle_withdraw_sign_finished (void *cls,
{
struct TALER_MINT_WithdrawSignHandle *wsh = cls;
long response_code;
json_error_t error;
json_t *json;
wsh->job = NULL;
json = NULL;
if (CURLE_OK !=
curl_easy_getinfo (eh,
CURLINFO_RESPONSE_CODE,
&response_code))
{
/* unexpected error... */
GNUNET_break (0);
response_code = 0;
}
if ( (0 == wsh->eno) &&
(0 != response_code) )
{
json = json_loadb (wsh->buf,
wsh->buf_size,
JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK,
&error);
if (NULL == json)
{
JSON_WARN (error);
response_code = 0;
}
}
json = MAC_download_get_result (&wsh->db,
eh,
&response_code);
switch (response_code)
{
case 0:
@ -870,6 +752,9 @@ handle_withdraw_sign_finished (void *cls,
break;
default:
/* unexpected response code */
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u\n",
response_code);
GNUNET_break (0);
response_code = 0;
break;
@ -884,49 +769,6 @@ handle_withdraw_sign_finished (void *cls,
}
/**
* Callback used when downloading the reply to a /withdraw/sign request.
* Just appends all of the data to the `buf` in the
* `struct TALER_MINT_WithdrawSignHandle` for further processing. The size of
* the download is limited to #GNUNET_MAX_MALLOC_CHECKED, if
* the download exceeds this size, we abort with an error.
*
* @param bufptr data downloaded via HTTP
* @param size size of an item in @a bufptr
* @param nitems number of items in @a bufptr
* @param cls the `struct TALER_MINT_DepositHandle`
* @return number of bytes processed from @a bufptr
*/
static int
withdraw_sign_download_cb (char *bufptr,
size_t size,
size_t nitems,
void *cls)
{
struct TALER_MINT_WithdrawSignHandle *wsh = cls;
size_t msize;
void *buf;
if (0 == size * nitems)
{
/* Nothing (left) to do */
return 0;
}
msize = size * nitems;
if ( (msize + wsh->buf_size) >= GNUNET_MAX_MALLOC_CHECKED)
{
wsh->eno = ENOMEM;
return 0; /* signals an error to curl */
}
wsh->buf = GNUNET_realloc (wsh->buf,
wsh->buf_size + msize);
buf = wsh->buf + wsh->buf_size;
memcpy (buf, bufptr, msize);
wsh->buf_size += msize;
return msize;
}
/**
* Withdraw a coin from the mint using a /withdraw/sign request. Note
* that to ensure that no money is lost in case of hardware failures,
@ -1045,21 +887,15 @@ TALER_MINT_withdraw_sign (struct TALER_MINT_Handle *mint,
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_WRITEFUNCTION,
&withdraw_sign_download_cb));
&MAC_download_cb));
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_WRITEDATA,
wsh));
GNUNET_assert (NULL != (wsh->headers =
curl_slist_append (wsh->headers,
"Content-Type: application/json")));
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_HTTPHEADER,
wsh->headers));
&wsh->db));
ctx = MAH_handle_to_context (mint);
wsh->job = MAC_job_add (ctx,
eh,
GNUNET_YES,
&handle_withdraw_sign_finished,
wsh);
return wsh;
@ -1080,7 +916,7 @@ TALER_MINT_withdraw_sign_cancel (struct TALER_MINT_WithdrawSignHandle *sign)
MAC_job_cancel (sign->job);
sign->job = NULL;
}
curl_slist_free_all (sign->headers);
GNUNET_free_non_null (sign->db.buf);
GNUNET_free (sign->url);
GNUNET_free (sign->json_enc);
GNUNET_free (sign);

View File

@ -146,6 +146,7 @@ TMH_ADMIN_handler_admin_add_incoming (struct TMH_RequestHandler *rh,
wire))
{
TMH_PARSE_release_data (spec);
json_decref (root);
return TMH_RESPONSE_reply_arg_unknown (connection,
"wire");
}

View File

@ -152,7 +152,6 @@ release_data (struct TMH_PARSE_FieldSpecification *spec,
unsigned int spec_len)
{
unsigned int i;
void *ptr;
for (i=0; i < spec_len; i++)
{
@ -175,11 +174,15 @@ release_data (struct TMH_PARSE_FieldSpecification *spec,
}
break;
case TMH_PARSE_JNC_RET_TYPED_JSON:
ptr = *(void **) spec[i].destination;
if (NULL != ptr)
{
json_decref (ptr);
*(void**) spec[i].destination = NULL;
json_t *json;
json = *(json_t **) spec[i].destination;
if (NULL != json)
{
json_decref (json);
*(json_t**) spec[i].destination = NULL;
}
}
break;
case TMH_PARSE_JNC_RET_RSA_PUBLIC_KEY:
@ -606,7 +609,9 @@ TMH_PARSE_navigate_json (struct MHD_Connection *connection,
int typ = va_arg (argp, int);
const json_t **r_json = va_arg (argp, const json_t **);
if ( (-1 != typ) && (json_typeof (root) != typ))
if ( (NULL == root) ||
( (-1 != typ) &&
(json_typeof (root) != typ)) )
{
*r_json = NULL;
ret = (MHD_YES ==
@ -899,7 +904,7 @@ TMH_PARSE_json_data (struct MHD_Connection *connection,
spec[i].field_name,
TMH_PARSE_JNC_RET_TYPED_JSON,
spec[i].type,
&spec[i].destination);
spec[i].destination);
break;
case TMH_PARSE_JNC_RET_RSA_PUBLIC_KEY:
ret = TMH_PARSE_navigate_json (connection,
@ -994,7 +999,7 @@ TMH_PARSE_member_uint64 (const char *field,
* Generate line in parser specification for JSON object value.
*
* @param field name of the field
* @param jsonp address of pointer to JSON to initialize
* @param[out] jsonp address of pointer to JSON to initialize
* @return corresponding field spec
*/
struct TMH_PARSE_FieldSpecification
@ -1002,7 +1007,8 @@ TMH_PARSE_member_object (const char *field,
json_t **jsonp)
{
struct TMH_PARSE_FieldSpecification ret =
{ field, (void **) jsonp, 0, NULL, TMH_PARSE_JNC_RET_TYPED_JSON, JSON_OBJECT };
{ field, jsonp, 0, NULL, TMH_PARSE_JNC_RET_TYPED_JSON, JSON_OBJECT };
*jsonp = NULL;
return ret;
}
@ -1011,7 +1017,7 @@ TMH_PARSE_member_object (const char *field,
* Generate line in parser specification for JSON array value.
*
* @param field name of the field
* @param jsonp address of JSON pointer to initialize
* @param[out] jsonp address of JSON pointer to initialize
* @return corresponding field spec
*/
struct TMH_PARSE_FieldSpecification
@ -1020,6 +1026,7 @@ TMH_PARSE_member_array (const char *field,
{
struct TMH_PARSE_FieldSpecification ret =
{ field, jsonp, 0, NULL, TMH_PARSE_JNC_RET_TYPED_JSON, JSON_ARRAY };
*jsonp = NULL;
return ret;
}
@ -1053,6 +1060,7 @@ TMH_PARSE_member_denomination_public_key (const char *field,
{
struct TMH_PARSE_FieldSpecification ret =
{ field, pk, 0, NULL, TMH_PARSE_JNC_RET_RSA_PUBLIC_KEY, 0 };
pk->rsa_public_key = NULL;
return ret;
}
@ -1070,6 +1078,7 @@ TMH_PARSE_member_denomination_signature (const char *field,
{
struct TMH_PARSE_FieldSpecification ret =
{ field, sig, 0, NULL, TMH_PARSE_JNC_RET_RSA_SIGNATURE, 0 };
sig->rsa_signature = NULL;
return ret;
}
@ -1087,6 +1096,7 @@ TMH_PARSE_member_amount (const char *field,
{
struct TMH_PARSE_FieldSpecification ret =
{ field, amount, sizeof(struct TALER_Amount), NULL, TMH_PARSE_JNC_RET_AMOUNT, 0 };
memset (amount, 0, sizeof (struct TALER_Amount));
return ret;
}
@ -1106,6 +1116,7 @@ TMH_PARSE_member_variable (const char *field,
{
struct TMH_PARSE_FieldSpecification ret =
{ field, ptr, 0, ptr_size, TMH_PARSE_JNC_RET_DATA_VAR, 0 };
*ptr = NULL;
return ret;
}