add batch signing support to taler-exchange-secmod-rsa
This commit is contained in:
parent
6d2ee2c88a
commit
d40da21e90
@ -279,8 +279,8 @@ TEH_handler_purses_get (struct TEH_RequestContext *rc,
|
||||
.header.size = htons (sizeof (rep)),
|
||||
.header.type = htons (
|
||||
gc->wait_for_merge
|
||||
? TALER_DBEVENT_EXCHANGE_PURSE_MERGED
|
||||
: TALER_DBEVENT_EXCHANGE_PURSE_DEPOSITED),
|
||||
? TALER_DBEVENT_EXCHANGE_PURSE_MERGED
|
||||
: TALER_DBEVENT_EXCHANGE_PURSE_DEPOSITED),
|
||||
.purse_pub = gc->purse_pub
|
||||
};
|
||||
|
||||
@ -342,8 +342,8 @@ TEH_handler_purses_get (struct TEH_RequestContext *rc,
|
||||
.header.size = htons (sizeof (rep)),
|
||||
.header.type = htons (
|
||||
gc->wait_for_merge
|
||||
? TALER_DBEVENT_EXCHANGE_PURSE_MERGED
|
||||
: TALER_DBEVENT_EXCHANGE_PURSE_DEPOSITED),
|
||||
? TALER_DBEVENT_EXCHANGE_PURSE_MERGED
|
||||
: TALER_DBEVENT_EXCHANGE_PURSE_DEPOSITED),
|
||||
.purse_pub = gc->purse_pub
|
||||
};
|
||||
struct GNUNET_DB_EventHandler *eh2;
|
||||
|
@ -13874,8 +13874,8 @@ postgres_expire_purse (
|
||||
return qs;
|
||||
GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs);
|
||||
return found
|
||||
? GNUNET_DB_STATUS_SUCCESS_ONE_RESULT
|
||||
: GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
|
||||
? GNUNET_DB_STATUS_SUCCESS_ONE_RESULT
|
||||
: GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
|
||||
}
|
||||
|
||||
|
||||
|
@ -854,8 +854,8 @@ help_melt (struct CoinHistoryParseContext *pc,
|
||||
&rc,
|
||||
pc->h_denom_pub,
|
||||
no_hac
|
||||
? NULL
|
||||
: &h_age_commitment,
|
||||
? NULL
|
||||
: &h_age_commitment,
|
||||
pc->coin_pub,
|
||||
&sig))
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014-2021 Taler Systems SA
|
||||
Copyright (C) 2014-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
@ -163,6 +163,128 @@ struct Denomination
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A semaphore.
|
||||
*/
|
||||
struct Semaphore
|
||||
{
|
||||
/**
|
||||
* Mutex for the semaphore.
|
||||
*/
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
/**
|
||||
* Condition variable for the semaphore.
|
||||
*/
|
||||
pthread_cond_t cv;
|
||||
|
||||
/**
|
||||
* Counter of the semaphore.
|
||||
*/
|
||||
unsigned int ctr;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Job in a batch sign request.
|
||||
*/
|
||||
struct BatchJob;
|
||||
|
||||
/**
|
||||
* Handle for a thread that does work in batch signing.
|
||||
*/
|
||||
struct Worker
|
||||
{
|
||||
/**
|
||||
* Kept in a DLL.
|
||||
*/
|
||||
struct Worker *prev;
|
||||
|
||||
/**
|
||||
* Kept in a DLL.
|
||||
*/
|
||||
struct Worker *next;
|
||||
|
||||
/**
|
||||
* Job this worker should do next.
|
||||
*/
|
||||
struct BatchJob *job;
|
||||
|
||||
/**
|
||||
* Semaphore to signal the worker that a job is available.
|
||||
*/
|
||||
struct Semaphore sem;
|
||||
|
||||
/**
|
||||
* Handle for this thread.
|
||||
*/
|
||||
pthread_t pt;
|
||||
|
||||
/**
|
||||
* Set to true if the worker should terminate.
|
||||
*/
|
||||
bool do_shutdown;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Job in a batch sign request.
|
||||
*/
|
||||
struct BatchJob
|
||||
{
|
||||
/**
|
||||
* Request we are working on.
|
||||
*/
|
||||
const struct TALER_CRYPTO_SignRequest *sr;
|
||||
|
||||
/**
|
||||
* Thread doing the work.
|
||||
*/
|
||||
struct Worker *worker;
|
||||
|
||||
/**
|
||||
* Result with the signature.
|
||||
*/
|
||||
struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
|
||||
|
||||
/**
|
||||
* Semaphore to signal that the job is finished.
|
||||
*/
|
||||
struct Semaphore sem;
|
||||
|
||||
/**
|
||||
* Computation status.
|
||||
*/
|
||||
enum TALER_ErrorCode ec;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Head of DLL of workers ready for more work.
|
||||
*/
|
||||
static struct Worker *worker_head;
|
||||
|
||||
/**
|
||||
* Tail of DLL of workers ready for more work.
|
||||
*/
|
||||
static struct Worker *worker_tail;
|
||||
|
||||
/**
|
||||
* Lock for manipulating the worker DLL.
|
||||
*/
|
||||
static pthread_mutex_t worker_lock;
|
||||
|
||||
/**
|
||||
* Total number of workers that were started.
|
||||
*/
|
||||
static unsigned int workers;
|
||||
|
||||
/**
|
||||
* Semaphore used to grab a worker.
|
||||
*/
|
||||
static struct Semaphore worker_sem;
|
||||
|
||||
/**
|
||||
* Return value from main().
|
||||
*/
|
||||
@ -228,6 +350,12 @@ static pthread_mutex_t keys_lock;
|
||||
*/
|
||||
static uint64_t key_gen;
|
||||
|
||||
/**
|
||||
* Number of workers to launch. Note that connections to
|
||||
* exchanges are NOT workers.
|
||||
*/
|
||||
static unsigned int max_workers = 16;
|
||||
|
||||
|
||||
/**
|
||||
* Generate the announcement message for @a dk.
|
||||
@ -278,63 +406,49 @@ generate_response (struct DenominationKey *dk)
|
||||
|
||||
|
||||
/**
|
||||
* Handle @a client request @a sr to create signature. Create the
|
||||
* signature using the respective key and return the result to
|
||||
* the client.
|
||||
* Do the actual signing work.
|
||||
*
|
||||
* @param client the client making the request
|
||||
* @param sr the request details
|
||||
* @return #GNUNET_OK on success
|
||||
* @param h_rsa key to sign with
|
||||
* @param blinded_msg message to sign
|
||||
* @param blinded_msg_size number of bytes in @a blinded_msg
|
||||
* @param[out] rsa_signaturep set to the RSA signature
|
||||
* @return #TALER_EC_NONE on success
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
handle_sign_request (struct TES_Client *client,
|
||||
const struct TALER_CRYPTO_SignRequest *sr)
|
||||
static enum TALER_ErrorCode
|
||||
do_sign (const struct TALER_RsaPubHashP *h_rsa,
|
||||
const void *blinded_msg,
|
||||
size_t blinded_msg_size,
|
||||
struct GNUNET_CRYPTO_RsaSignature **rsa_signaturep)
|
||||
{
|
||||
struct DenominationKey *dk;
|
||||
const void *blinded_msg = &sr[1];
|
||||
size_t blinded_msg_size = ntohs (sr->header.size) - sizeof (*sr);
|
||||
struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
|
||||
struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
|
||||
|
||||
GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
|
||||
dk = GNUNET_CONTAINER_multihashmap_get (keys,
|
||||
&sr->h_rsa.hash);
|
||||
&h_rsa->hash);
|
||||
if (NULL == dk)
|
||||
{
|
||||
struct TALER_CRYPTO_SignFailure sf = {
|
||||
.header.size = htons (sizeof (sr)),
|
||||
.header.type = htons (TALER_HELPER_RSA_MT_RES_SIGN_FAILURE),
|
||||
.ec = htonl (TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN)
|
||||
};
|
||||
|
||||
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Signing request failed, denomination key %s unknown\n",
|
||||
GNUNET_h2s (&sr->h_rsa.hash));
|
||||
return TES_transmit (client->csock,
|
||||
&sf.header);
|
||||
GNUNET_h2s (&h_rsa->hash));
|
||||
return TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN;
|
||||
}
|
||||
if (GNUNET_TIME_absolute_is_future (dk->anchor.abs_time))
|
||||
{
|
||||
/* it is too early */
|
||||
struct TALER_CRYPTO_SignFailure sf = {
|
||||
.header.size = htons (sizeof (sr)),
|
||||
.header.type = htons (TALER_HELPER_RSA_MT_RES_SIGN_FAILURE),
|
||||
.ec = htonl (TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY)
|
||||
};
|
||||
|
||||
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Signing request failed, denomination key %s is not yet valid\n",
|
||||
GNUNET_h2s (&sr->h_rsa.hash));
|
||||
return TES_transmit (client->csock,
|
||||
&sf.header);
|
||||
GNUNET_h2s (&h_rsa->hash));
|
||||
return TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY;
|
||||
}
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Received request to sign over %u bytes with key %s\n",
|
||||
(unsigned int) blinded_msg_size,
|
||||
GNUNET_h2s (&sr->h_rsa.hash));
|
||||
GNUNET_h2s (&h_rsa->hash));
|
||||
GNUNET_assert (dk->rc < UINT_MAX);
|
||||
dk->rc++;
|
||||
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
|
||||
@ -347,52 +461,378 @@ handle_sign_request (struct TES_Client *client,
|
||||
dk->rc--;
|
||||
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
|
||||
if (NULL == rsa_signature)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Signing request failed, worker failed to produce signature\n");
|
||||
return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
|
||||
}
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Sending RSA signature after %s\n",
|
||||
GNUNET_TIME_relative2s (
|
||||
GNUNET_TIME_absolute_get_duration (now),
|
||||
GNUNET_YES));
|
||||
*rsa_signaturep = rsa_signature;
|
||||
return TALER_EC_NONE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate error response that signing failed.
|
||||
*
|
||||
* @param client client to send response to
|
||||
* @param ec error code to include
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
fail_sign (struct TES_Client *client,
|
||||
enum TALER_ErrorCode ec)
|
||||
{
|
||||
struct TALER_CRYPTO_SignFailure sf = {
|
||||
.header.size = htons (sizeof (sf)),
|
||||
.header.type = htons (TALER_HELPER_RSA_MT_RES_SIGN_FAILURE),
|
||||
.ec = htonl (ec)
|
||||
};
|
||||
|
||||
return TES_transmit (client->csock,
|
||||
&sf.header);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate signature response.
|
||||
*
|
||||
* @param client client to send response to
|
||||
* @param[in] rsa_signature signature to send, freed by this function
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
send_signature (struct TES_Client *client,
|
||||
struct GNUNET_CRYPTO_RsaSignature *rsa_signature)
|
||||
{
|
||||
struct TALER_CRYPTO_SignResponse *sr;
|
||||
void *buf;
|
||||
size_t buf_size;
|
||||
size_t tsize;
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
|
||||
buf_size = GNUNET_CRYPTO_rsa_signature_encode (rsa_signature,
|
||||
&buf);
|
||||
GNUNET_CRYPTO_rsa_signature_free (rsa_signature);
|
||||
tsize = sizeof (*sr) + buf_size;
|
||||
GNUNET_assert (tsize < UINT16_MAX);
|
||||
sr = GNUNET_malloc (tsize);
|
||||
sr->header.size = htons (tsize);
|
||||
sr->header.type = htons (TALER_HELPER_RSA_MT_RES_SIGNATURE);
|
||||
memcpy (&sr[1],
|
||||
buf,
|
||||
buf_size);
|
||||
GNUNET_free (buf);
|
||||
ret = TES_transmit (client->csock,
|
||||
&sr->header);
|
||||
GNUNET_free (sr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle @a client request @a sr to create signature. Create the
|
||||
* signature using the respective key and return the result to
|
||||
* the client.
|
||||
*
|
||||
* @param client the client making the request
|
||||
* @param sr the request details
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
handle_sign_request (struct TES_Client *client,
|
||||
const struct TALER_CRYPTO_SignRequest *sr)
|
||||
{
|
||||
const void *blinded_msg = &sr[1];
|
||||
size_t blinded_msg_size = ntohs (sr->header.size) - sizeof (*sr);
|
||||
struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
|
||||
enum TALER_ErrorCode ec;
|
||||
|
||||
ec = do_sign (&sr->h_rsa,
|
||||
blinded_msg,
|
||||
blinded_msg_size,
|
||||
&rsa_signature);
|
||||
if (TALER_EC_NONE != ec)
|
||||
{
|
||||
return fail_sign (client,
|
||||
ec);
|
||||
}
|
||||
return send_signature (client,
|
||||
rsa_signature);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize a semaphore @a sem with a value of @a val.
|
||||
*
|
||||
* @param[out] sem semaphore to initialize
|
||||
* @param val initial value of the semaphore
|
||||
*/
|
||||
static void
|
||||
sem_init (struct Semaphore *sem,
|
||||
unsigned int val)
|
||||
{
|
||||
GNUNET_assert (0 ==
|
||||
pthread_mutex_init (&sem->mutex,
|
||||
NULL));
|
||||
GNUNET_assert (0 ==
|
||||
pthread_cond_init (&sem->cv,
|
||||
NULL));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decrement semaphore, blocks until this is possible.
|
||||
*
|
||||
* @param[in,out] sem semaphore to decrement
|
||||
*/
|
||||
static void
|
||||
sem_down (struct Semaphore *sem)
|
||||
{
|
||||
GNUNET_assert (0 == pthread_mutex_lock (&sem->mutex));
|
||||
while (0 == sem->ctr)
|
||||
{
|
||||
pthread_cond_wait (&sem->cv,
|
||||
&sem->mutex);
|
||||
}
|
||||
sem->ctr--;
|
||||
GNUNET_assert (0 == pthread_mutex_unlock (&sem->mutex));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Increment semaphore, blocks until this is possible.
|
||||
*
|
||||
* @param[in,out] sem semaphore to decrement
|
||||
*/
|
||||
static void
|
||||
sem_up (struct Semaphore *sem)
|
||||
{
|
||||
GNUNET_assert (0 == pthread_mutex_lock (&sem->mutex));
|
||||
sem->ctr++;
|
||||
GNUNET_assert (0 == pthread_mutex_unlock (&sem->mutex));
|
||||
pthread_cond_signal (&sem->cv);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Release resources used by @a sem.
|
||||
*
|
||||
* @param[in] sem semaphore to release (except the memory itself)
|
||||
*/
|
||||
static void
|
||||
sem_done (struct Semaphore *sem)
|
||||
{
|
||||
pthread_cond_destroy (&sem->cv);
|
||||
pthread_mutex_destroy (&sem->mutex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Main logic of a worker thread. Grabs work, does it,
|
||||
* grabs more work.
|
||||
*
|
||||
* @param cls a `struct Worker *`
|
||||
* @returns cls
|
||||
*/
|
||||
static void *
|
||||
worker (void *cls)
|
||||
{
|
||||
struct Worker *w = cls;
|
||||
|
||||
while (true)
|
||||
{
|
||||
GNUNET_assert (0 == pthread_mutex_lock (&worker_lock));
|
||||
GNUNET_CONTAINER_DLL_insert (worker_head,
|
||||
worker_tail,
|
||||
w);
|
||||
GNUNET_assert (0 == pthread_mutex_unlock (&worker_lock));
|
||||
sem_up (&worker_sem);
|
||||
sem_down (&w->sem);
|
||||
if (w->do_shutdown)
|
||||
break;
|
||||
{
|
||||
struct BatchJob *bj = w->job;
|
||||
const struct TALER_CRYPTO_SignRequest *sr = bj->sr;
|
||||
const void *blinded_msg = &sr[1];
|
||||
size_t blinded_msg_size = ntohs (sr->header.size) - sizeof (*sr);
|
||||
|
||||
bj->ec = do_sign (&sr->h_rsa,
|
||||
blinded_msg,
|
||||
blinded_msg_size,
|
||||
&bj->rsa_signature);
|
||||
sem_up (&bj->sem);
|
||||
w->job = NULL;
|
||||
}
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Start batch job @a bj to sign @a sr.
|
||||
*
|
||||
* @param sr signature request to answer
|
||||
* @param[out] bj job data structure
|
||||
*/
|
||||
static void
|
||||
start_job (const struct TALER_CRYPTO_SignRequest *sr,
|
||||
struct BatchJob *bj)
|
||||
{
|
||||
sem_init (&bj->sem,
|
||||
0);
|
||||
bj->sr = sr;
|
||||
sem_down (&worker_sem);
|
||||
GNUNET_assert (0 == pthread_mutex_lock (&worker_lock));
|
||||
bj->worker = worker_head;
|
||||
GNUNET_CONTAINER_DLL_remove (worker_head,
|
||||
worker_tail,
|
||||
bj->worker);
|
||||
GNUNET_assert (0 == pthread_mutex_unlock (&worker_lock));
|
||||
bj->worker->job = bj;
|
||||
sem_up (&bj->worker->sem);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finish a job @a bj for a @a client.
|
||||
*
|
||||
* @param client who made the request
|
||||
* @param[in,out] bj job to finish
|
||||
*/
|
||||
static void
|
||||
finish_job (struct TES_Client *client,
|
||||
struct BatchJob *bj)
|
||||
{
|
||||
sem_down (&bj->sem);
|
||||
sem_done (&bj->sem);
|
||||
if (TALER_EC_NONE != bj->ec)
|
||||
{
|
||||
fail_sign (client,
|
||||
bj->ec);
|
||||
return;
|
||||
}
|
||||
GNUNET_assert (NULL != bj->rsa_signature);
|
||||
send_signature (client,
|
||||
bj->rsa_signature);
|
||||
bj->rsa_signature = NULL; /* freed in send_signature */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle @a client request @a sr to create a batch of signature. Creates the
|
||||
* signatures using the respective key and return the results to the client.
|
||||
*
|
||||
* @param client the client making the request
|
||||
* @param bsr the request details
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
handle_batch_sign_request (struct TES_Client *client,
|
||||
const struct TALER_CRYPTO_BatchSignRequest *bsr)
|
||||
{
|
||||
uint32_t bs = ntohl (bsr->batch_size);
|
||||
uint16_t size = ntohs (bsr->header.size) - sizeof (*bsr);
|
||||
const void *off = (const void *) &bsr[1];
|
||||
unsigned int idx = 0;
|
||||
struct BatchJob jobs[bs];
|
||||
bool failure = false;
|
||||
|
||||
while ( (bs > 0) &&
|
||||
(size > sizeof (struct TALER_CRYPTO_SignRequest)) )
|
||||
{
|
||||
const struct TALER_CRYPTO_SignRequest *sr = off;
|
||||
uint16_t s = ntohs (sr->header.size);
|
||||
|
||||
if (s > size)
|
||||
{
|
||||
failure = true;
|
||||
bs = idx;
|
||||
break;
|
||||
}
|
||||
start_job (sr,
|
||||
&jobs[idx++]);
|
||||
off += s;
|
||||
size -= s;
|
||||
}
|
||||
for (unsigned int i = 0; i<bs; i++)
|
||||
finish_job (client,
|
||||
&jobs[i]);
|
||||
if (failure)
|
||||
{
|
||||
struct TALER_CRYPTO_SignFailure sf = {
|
||||
.header.size = htons (sizeof (sf)),
|
||||
.header.type = htons (TALER_HELPER_RSA_MT_RES_SIGN_FAILURE),
|
||||
.header.type = htons (TALER_HELPER_RSA_MT_RES_BATCH_FAILURE),
|
||||
.ec = htonl (TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE)
|
||||
};
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Signing request failed, worker failed to produce signature\n");
|
||||
GNUNET_break (0);
|
||||
return TES_transmit (client->csock,
|
||||
&sf.header);
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Start worker thread for batch processing.
|
||||
*
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
start_worker (void)
|
||||
{
|
||||
struct Worker *w;
|
||||
|
||||
w = GNUNET_new (struct Worker);
|
||||
sem_init (&w->sem,
|
||||
0);
|
||||
if (0 != pthread_create (&w->pt,
|
||||
NULL,
|
||||
&worker,
|
||||
w))
|
||||
{
|
||||
struct TALER_CRYPTO_SignResponse *sr;
|
||||
void *buf;
|
||||
size_t buf_size;
|
||||
size_t tsize;
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
|
||||
"pthread_create");
|
||||
GNUNET_free (w);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
workers++;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
buf_size = GNUNET_CRYPTO_rsa_signature_encode (rsa_signature,
|
||||
&buf);
|
||||
GNUNET_CRYPTO_rsa_signature_free (rsa_signature);
|
||||
tsize = sizeof (*sr) + buf_size;
|
||||
GNUNET_assert (tsize < UINT16_MAX);
|
||||
sr = GNUNET_malloc (tsize);
|
||||
sr->header.size = htons (tsize);
|
||||
sr->header.type = htons (TALER_HELPER_RSA_MT_RES_SIGNATURE);
|
||||
memcpy (&sr[1],
|
||||
buf,
|
||||
buf_size);
|
||||
GNUNET_free (buf);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Sending RSA signature after %s\n",
|
||||
GNUNET_TIME_relative2s (
|
||||
GNUNET_TIME_absolute_get_duration (now),
|
||||
GNUNET_YES));
|
||||
ret = TES_transmit (client->csock,
|
||||
&sr->header);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Sent RSA signature after %s\n",
|
||||
GNUNET_TIME_relative2s (
|
||||
GNUNET_TIME_absolute_get_duration (now),
|
||||
GNUNET_YES));
|
||||
GNUNET_free (sr);
|
||||
return ret;
|
||||
|
||||
/**
|
||||
* Stop all worker threads.
|
||||
*/
|
||||
static void
|
||||
stop_workers (void)
|
||||
{
|
||||
while (workers > 0)
|
||||
{
|
||||
struct Worker *w;
|
||||
void *result;
|
||||
|
||||
sem_down (&worker_sem);
|
||||
GNUNET_assert (0 == pthread_mutex_lock (&worker_lock));
|
||||
w = worker_head;
|
||||
GNUNET_CONTAINER_DLL_remove (worker_head,
|
||||
worker_tail,
|
||||
w);
|
||||
GNUNET_assert (0 == pthread_mutex_unlock (&worker_lock));
|
||||
w->do_shutdown = true;
|
||||
sem_up (&w->sem);
|
||||
pthread_join (w->pt,
|
||||
&result);
|
||||
GNUNET_assert (result == w);
|
||||
sem_done (&w->sem);
|
||||
GNUNET_free (w);
|
||||
workers--;
|
||||
}
|
||||
}
|
||||
|
||||
@ -606,6 +1046,15 @@ rsa_work_dispatch (struct TES_Client *client,
|
||||
return handle_revoke_request (
|
||||
client,
|
||||
(const struct TALER_CRYPTO_RevokeRequest *) hdr);
|
||||
case TALER_HELPER_RSA_MT_REQ_BATCH_SIGN:
|
||||
if (msize <= sizeof (struct TALER_CRYPTO_BatchSignRequest))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return handle_batch_sign_request (
|
||||
client,
|
||||
(const struct TALER_CRYPTO_BatchSignRequest *) hdr);
|
||||
default:
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
@ -1452,6 +1901,8 @@ do_shutdown (void *cls)
|
||||
GNUNET_SCHEDULER_cancel (keygen_task);
|
||||
keygen_task = NULL;
|
||||
}
|
||||
stop_workers ();
|
||||
sem_done (&worker_sem);
|
||||
}
|
||||
|
||||
|
||||
@ -1511,8 +1962,19 @@ run (void *cls,
|
||||
&cb);
|
||||
if (0 != global_ret)
|
||||
return;
|
||||
sem_init (&worker_sem,
|
||||
0);
|
||||
GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
|
||||
NULL);
|
||||
if (0 == max_workers)
|
||||
max_workers = 1; /* FIXME: or determine from CPU? */
|
||||
for (unsigned int i = 0; i<max_workers; i++)
|
||||
if (GNUNET_OK !=
|
||||
start_worker ())
|
||||
{
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
return;
|
||||
}
|
||||
/* Load denominations */
|
||||
keys = GNUNET_CONTAINER_multihashmap_create (65536,
|
||||
GNUNET_YES);
|
||||
@ -1570,6 +2032,11 @@ main (int argc,
|
||||
"TIMESTAMP",
|
||||
"pretend it is a different time for the update",
|
||||
&now_tmp),
|
||||
GNUNET_GETOPT_option_uint ('w',
|
||||
"workers",
|
||||
"COUNT",
|
||||
"use COUNT workers for parallel processing of batch requests",
|
||||
&max_workers),
|
||||
GNUNET_GETOPT_OPTION_END
|
||||
};
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
|
@ -24,14 +24,17 @@
|
||||
#define TALER_HELPER_RSA_MT_PURGE 1
|
||||
#define TALER_HELPER_RSA_MT_AVAIL 2
|
||||
|
||||
#define TALER_HELPER_RSA_MT_REQ_BATCH_SIGN 3
|
||||
#define TALER_HELPER_RSA_MT_REQ_INIT 4
|
||||
#define TALER_HELPER_RSA_MT_REQ_SIGN 5
|
||||
#define TALER_HELPER_RSA_MT_REQ_REVOKE 6
|
||||
|
||||
#define TALER_HELPER_RSA_MT_RES_SIGNATURE 7
|
||||
#define TALER_HELPER_RSA_MT_RES_SIGN_FAILURE 8
|
||||
#define TALER_HELPER_RSA_MT_RES_BATCH_FAILURE 9
|
||||
|
||||
#define TALER_HELPER_RSA_SYNCED 10
|
||||
|
||||
#define TALER_HELPER_RSA_SYNCED 9
|
||||
|
||||
GNUNET_NETWORK_STRUCT_BEGIN
|
||||
|
||||
@ -132,6 +135,28 @@ struct TALER_CRYPTO_SignRequest
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Message sent if a signature is requested.
|
||||
*/
|
||||
struct TALER_CRYPTO_BatchSignRequest
|
||||
{
|
||||
/**
|
||||
* Type is #TALER_HELPER_RSA_MT_REQ_BATCH_SIGN.
|
||||
*/
|
||||
struct GNUNET_MessageHeader header;
|
||||
|
||||
/**
|
||||
* Number of signatures to create, in NBO.
|
||||
*/
|
||||
uint32_t batch_size;
|
||||
|
||||
/*
|
||||
* Followed by @e batch_size batch sign requests.
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Message sent if a key was revoked.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user