reduce lock contention in RSA secmod
This commit is contained in:
parent
ae866fc45d
commit
dfe245814c
@ -74,17 +74,15 @@ static volatile bool in_shutdown;
|
|||||||
|
|
||||||
|
|
||||||
enum GNUNET_GenericReturnValue
|
enum GNUNET_GenericReturnValue
|
||||||
TES_transmit (int sock,
|
TES_transmit_raw (int sock,
|
||||||
const struct GNUNET_MessageHeader *hdr)
|
size_t end,
|
||||||
|
const void *pos)
|
||||||
{
|
{
|
||||||
ssize_t off = 0;
|
ssize_t off = 0;
|
||||||
const void *pos = hdr;
|
|
||||||
uint16_t end = ntohs (hdr->size);
|
|
||||||
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
"Sending message of type %u and length %u\n",
|
"Sending message of length %u\n",
|
||||||
(unsigned int) ntohs (hdr->type),
|
(unsigned int) end);
|
||||||
(unsigned int) ntohs (hdr->size));
|
|
||||||
while (off < end)
|
while (off < end)
|
||||||
{
|
{
|
||||||
ssize_t ret = send (sock,
|
ssize_t ret = send (sock,
|
||||||
@ -118,6 +116,20 @@ TES_transmit (int sock,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum GNUNET_GenericReturnValue
|
||||||
|
TES_transmit (int sock,
|
||||||
|
const struct GNUNET_MessageHeader *hdr)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Sending message of type %u and length %u\n",
|
||||||
|
(unsigned int) ntohs (hdr->type),
|
||||||
|
(unsigned int) ntohs (hdr->size));
|
||||||
|
return TES_transmit_raw (sock,
|
||||||
|
ntohs (hdr->size),
|
||||||
|
hdr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct GNUNET_NETWORK_Handle *
|
struct GNUNET_NETWORK_Handle *
|
||||||
TES_open_socket (const char *unixpath)
|
TES_open_socket (const char *unixpath)
|
||||||
{
|
{
|
||||||
|
@ -51,6 +51,19 @@ TES_transmit (int sock,
|
|||||||
const struct GNUNET_MessageHeader *hdr);
|
const struct GNUNET_MessageHeader *hdr);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transmit @a end bytes from @a pos on @a sock.
|
||||||
|
*
|
||||||
|
* @param sock where to send the data
|
||||||
|
* @param end how many bytes to send
|
||||||
|
* @param pos first address with data
|
||||||
|
* @return #GNUNET_OK on success
|
||||||
|
*/
|
||||||
|
enum GNUNET_GenericReturnValue
|
||||||
|
TES_transmit_raw (int sock,
|
||||||
|
size_t end,
|
||||||
|
const void *pos);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Information we keep for a client connected to us.
|
* Information we keep for a client connected to us.
|
||||||
*/
|
*/
|
||||||
|
@ -85,6 +85,11 @@ struct DenominationKey
|
|||||||
*/
|
*/
|
||||||
struct GNUNET_CRYPTO_RsaPublicKey *denom_pub;
|
struct GNUNET_CRYPTO_RsaPublicKey *denom_pub;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message to transmit to clients to introduce this public key.
|
||||||
|
*/
|
||||||
|
struct TALER_CRYPTO_RsaKeyAvailableNotification *an;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hash of this denomination's public key.
|
* Hash of this denomination's public key.
|
||||||
*/
|
*/
|
||||||
@ -214,7 +219,6 @@ static struct GNUNET_CONTAINER_MultiHashMap *keys;
|
|||||||
*/
|
*/
|
||||||
static struct GNUNET_SCHEDULER_Task *keygen_task;
|
static struct GNUNET_SCHEDULER_Task *keygen_task;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lock for the keys queue.
|
* Lock for the keys queue.
|
||||||
*/
|
*/
|
||||||
@ -227,15 +231,12 @@ static uint64_t key_gen;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify @a client about @a dk becoming available.
|
* Generate the announcement message for @a dk.
|
||||||
*
|
*
|
||||||
* @param[in,out] client the client to notify; possible freed if transmission fails
|
* @param[in,out] denomination key to generate the announcement for
|
||||||
* @param dk the key to notify @a client about
|
|
||||||
* @return #GNUNET_OK on success
|
|
||||||
*/
|
*/
|
||||||
static enum GNUNET_GenericReturnValue
|
static void
|
||||||
notify_client_dk_add (struct TES_Client *client,
|
generate_response (struct DenominationKey *dk)
|
||||||
const struct DenominationKey *dk)
|
|
||||||
{
|
{
|
||||||
struct Denomination *denom = dk->denom;
|
struct Denomination *denom = dk->denom;
|
||||||
size_t nlen = strlen (denom->section) + 1;
|
size_t nlen = strlen (denom->section) + 1;
|
||||||
@ -251,7 +252,6 @@ notify_client_dk_add (struct TES_Client *client,
|
|||||||
GNUNET_assert (nlen < UINT16_MAX);
|
GNUNET_assert (nlen < UINT16_MAX);
|
||||||
tlen = buf_len + nlen + sizeof (*an);
|
tlen = buf_len + nlen + sizeof (*an);
|
||||||
GNUNET_assert (tlen < UINT16_MAX);
|
GNUNET_assert (tlen < UINT16_MAX);
|
||||||
// FIXME: do not re-calculate this message for every client!
|
|
||||||
an = GNUNET_malloc (tlen);
|
an = GNUNET_malloc (tlen);
|
||||||
an->header.size = htons ((uint16_t) tlen);
|
an->header.size = htons ((uint16_t) tlen);
|
||||||
an->header.type = htons (TALER_HELPER_RSA_MT_AVAIL);
|
an->header.type = htons (TALER_HELPER_RSA_MT_AVAIL);
|
||||||
@ -274,55 +274,7 @@ notify_client_dk_add (struct TES_Client *client,
|
|||||||
memcpy (p + buf_len,
|
memcpy (p + buf_len,
|
||||||
denom->section,
|
denom->section,
|
||||||
nlen);
|
nlen);
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
dk->an = an;
|
||||||
"Sending RSA denomination key %s (%s)\n",
|
|
||||||
GNUNET_h2s (&dk->h_rsa.hash),
|
|
||||||
denom->section);
|
|
||||||
if (GNUNET_OK !=
|
|
||||||
TES_transmit (client->csock,
|
|
||||||
&an->header))
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
||||||
"Client %p must have disconnected\n",
|
|
||||||
client);
|
|
||||||
GNUNET_free (an);
|
|
||||||
return GNUNET_SYSERR;
|
|
||||||
}
|
|
||||||
GNUNET_free (an);
|
|
||||||
return GNUNET_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify @a client about @a dk being purged.
|
|
||||||
*
|
|
||||||
* @param[in,out] client the client to notify; possible freed if transmission fails
|
|
||||||
* @param dk the key to notify @a client about
|
|
||||||
* @return #GNUNET_OK on success
|
|
||||||
*/
|
|
||||||
static enum GNUNET_GenericReturnValue
|
|
||||||
notify_client_dk_del (struct TES_Client *client,
|
|
||||||
const struct DenominationKey *dk)
|
|
||||||
{
|
|
||||||
struct TALER_CRYPTO_RsaKeyPurgeNotification pn = {
|
|
||||||
.header.type = htons (TALER_HELPER_RSA_MT_PURGE),
|
|
||||||
.header.size = htons (sizeof (pn)),
|
|
||||||
.h_rsa = dk->h_rsa
|
|
||||||
};
|
|
||||||
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
||||||
"Sending RSA denomination expiration %s\n",
|
|
||||||
GNUNET_h2s (&dk->h_rsa.hash));
|
|
||||||
if (GNUNET_OK !=
|
|
||||||
TES_transmit (client->csock,
|
|
||||||
&pn.header))
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
||||||
"Client %p must have disconnected\n",
|
|
||||||
client);
|
|
||||||
return GNUNET_SYSERR;
|
|
||||||
}
|
|
||||||
return GNUNET_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -409,6 +361,7 @@ handle_sign_request (struct TES_Client *client,
|
|||||||
return TES_transmit (client->csock,
|
return TES_transmit (client->csock,
|
||||||
&sf.header);
|
&sf.header);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
struct TALER_CRYPTO_SignResponse *sr;
|
struct TALER_CRYPTO_SignResponse *sr;
|
||||||
void *buf;
|
void *buf;
|
||||||
@ -507,6 +460,7 @@ setup_key (struct DenominationKey *dk,
|
|||||||
dk->denom_priv = priv;
|
dk->denom_priv = priv;
|
||||||
dk->denom_pub = pub;
|
dk->denom_pub = pub;
|
||||||
dk->key_gen = key_gen;
|
dk->key_gen = key_gen;
|
||||||
|
generate_response (dk);
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
GNUNET_CONTAINER_multihashmap_put (
|
GNUNET_CONTAINER_multihashmap_put (
|
||||||
keys,
|
keys,
|
||||||
@ -519,6 +473,7 @@ setup_key (struct DenominationKey *dk,
|
|||||||
GNUNET_CRYPTO_rsa_private_key_free (dk->denom_priv);
|
GNUNET_CRYPTO_rsa_private_key_free (dk->denom_priv);
|
||||||
GNUNET_CRYPTO_rsa_public_key_free (dk->denom_pub);
|
GNUNET_CRYPTO_rsa_public_key_free (dk->denom_pub);
|
||||||
GNUNET_free (dk->filename);
|
GNUNET_free (dk->filename);
|
||||||
|
GNUNET_free (dk->an);
|
||||||
GNUNET_free (dk);
|
GNUNET_free (dk);
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
@ -665,6 +620,9 @@ rsa_work_dispatch (struct TES_Client *client,
|
|||||||
static enum GNUNET_GenericReturnValue
|
static enum GNUNET_GenericReturnValue
|
||||||
rsa_client_init (struct TES_Client *client)
|
rsa_client_init (struct TES_Client *client)
|
||||||
{
|
{
|
||||||
|
size_t obs = 0;
|
||||||
|
char *buf;
|
||||||
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
"Initializing new client %p\n",
|
"Initializing new client %p\n",
|
||||||
client);
|
client);
|
||||||
@ -677,23 +635,39 @@ rsa_client_init (struct TES_Client *client)
|
|||||||
NULL != dk;
|
NULL != dk;
|
||||||
dk = dk->next)
|
dk = dk->next)
|
||||||
{
|
{
|
||||||
// FIXME: avoid holding keys_lock while
|
obs += ntohs (dk->an->header.size);
|
||||||
// doing the IPC with client and the signing!
|
}
|
||||||
// => lock contention candidate!
|
}
|
||||||
if (GNUNET_OK !=
|
buf = GNUNET_malloc (obs);
|
||||||
notify_client_dk_add (client,
|
obs = 0;
|
||||||
dk))
|
for (struct Denomination *denom = denom_head;
|
||||||
|
NULL != denom;
|
||||||
|
denom = denom->next)
|
||||||
{
|
{
|
||||||
|
for (struct DenominationKey *dk = denom->keys_head;
|
||||||
|
NULL != dk;
|
||||||
|
dk = dk->next)
|
||||||
|
{
|
||||||
|
memcpy (&buf[obs],
|
||||||
|
dk->an,
|
||||||
|
ntohs (dk->an->header.size));
|
||||||
|
obs += ntohs (dk->an->header.size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
client->key_gen = key_gen;
|
||||||
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
|
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
TES_transmit_raw (client->csock,
|
||||||
|
obs,
|
||||||
|
buf))
|
||||||
|
{
|
||||||
|
GNUNET_free (buf);
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
"Client %p must have disconnected\n",
|
"Client %p must have disconnected\n",
|
||||||
client);
|
client);
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
}
|
GNUNET_free (buf);
|
||||||
}
|
|
||||||
client->key_gen = key_gen;
|
|
||||||
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
|
|
||||||
{
|
{
|
||||||
struct GNUNET_MessageHeader synced = {
|
struct GNUNET_MessageHeader synced = {
|
||||||
.type = htons (TALER_HELPER_RSA_SYNCED),
|
.type = htons (TALER_HELPER_RSA_SYNCED),
|
||||||
@ -725,6 +699,10 @@ rsa_client_init (struct TES_Client *client)
|
|||||||
static enum GNUNET_GenericReturnValue
|
static enum GNUNET_GenericReturnValue
|
||||||
rsa_update_client_keys (struct TES_Client *client)
|
rsa_update_client_keys (struct TES_Client *client)
|
||||||
{
|
{
|
||||||
|
size_t obs = 0;
|
||||||
|
char *buf;
|
||||||
|
enum GNUNET_GenericReturnValue ret;
|
||||||
|
|
||||||
GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
|
GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
|
||||||
for (struct Denomination *denom = denom_head;
|
for (struct Denomination *denom = denom_head;
|
||||||
NULL != denom;
|
NULL != denom;
|
||||||
@ -737,33 +715,59 @@ rsa_update_client_keys (struct TES_Client *client)
|
|||||||
if (key->key_gen <= client->key_gen)
|
if (key->key_gen <= client->key_gen)
|
||||||
continue;
|
continue;
|
||||||
if (key->purge)
|
if (key->purge)
|
||||||
{
|
obs += sizeof (struct TALER_CRYPTO_RsaKeyPurgeNotification);
|
||||||
if (GNUNET_OK !=
|
else
|
||||||
notify_client_dk_del (client,
|
obs += ntohs (key->an->header.size);
|
||||||
key))
|
|
||||||
{
|
|
||||||
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
|
|
||||||
return GNUNET_SYSERR;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (0 == obs)
|
||||||
|
{
|
||||||
|
/* nothing to do */
|
||||||
|
client->key_gen = key_gen;
|
||||||
|
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
|
||||||
|
return GNUNET_OK;
|
||||||
|
}
|
||||||
|
buf = GNUNET_malloc (obs);
|
||||||
|
obs = 0;
|
||||||
|
for (struct Denomination *denom = denom_head;
|
||||||
|
NULL != denom;
|
||||||
|
denom = denom->next)
|
||||||
|
{
|
||||||
|
for (struct DenominationKey *key = denom->keys_head;
|
||||||
|
NULL != key;
|
||||||
|
key = key->next)
|
||||||
|
{
|
||||||
|
if (key->key_gen <= client->key_gen)
|
||||||
|
continue;
|
||||||
|
if (key->purge)
|
||||||
|
{
|
||||||
|
struct TALER_CRYPTO_RsaKeyPurgeNotification pn = {
|
||||||
|
.header.type = htons (TALER_HELPER_RSA_MT_PURGE),
|
||||||
|
.header.size = htons (sizeof (pn)),
|
||||||
|
.h_rsa = key->h_rsa
|
||||||
|
};
|
||||||
|
|
||||||
|
memcpy (&buf[obs],
|
||||||
|
&pn,
|
||||||
|
sizeof (pn));
|
||||||
|
obs += sizeof (pn);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// FIXME: avoid holding keys_lock while
|
memcpy (&buf[obs],
|
||||||
// doing the IPC with client and the signing!
|
key->an,
|
||||||
// => lock contention candidate!
|
ntohs (key->an->header.size));
|
||||||
if (GNUNET_OK !=
|
obs += ntohs (key->an->header.size);
|
||||||
notify_client_dk_add (client,
|
|
||||||
key))
|
|
||||||
{
|
|
||||||
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
|
|
||||||
return GNUNET_SYSERR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
client->key_gen = key_gen;
|
client->key_gen = key_gen;
|
||||||
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
|
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
|
||||||
return GNUNET_OK;
|
ret = TES_transmit_raw (client->csock,
|
||||||
|
obs,
|
||||||
|
buf);
|
||||||
|
GNUNET_free (buf);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -910,6 +914,7 @@ update_keys (struct Denomination *denom,
|
|||||||
GNUNET_free (key->filename);
|
GNUNET_free (key->filename);
|
||||||
GNUNET_CRYPTO_rsa_private_key_free (key->denom_priv);
|
GNUNET_CRYPTO_rsa_private_key_free (key->denom_priv);
|
||||||
GNUNET_CRYPTO_rsa_public_key_free (key->denom_pub);
|
GNUNET_CRYPTO_rsa_public_key_free (key->denom_pub);
|
||||||
|
GNUNET_free (key->an);
|
||||||
GNUNET_free (key);
|
GNUNET_free (key);
|
||||||
key = nxt;
|
key = nxt;
|
||||||
}
|
}
|
||||||
@ -1059,6 +1064,7 @@ parse_key (struct Denomination *denom,
|
|||||||
TALER_rsa_pub_hash (pub,
|
TALER_rsa_pub_hash (pub,
|
||||||
&dk->h_rsa);
|
&dk->h_rsa);
|
||||||
dk->denom_pub = pub;
|
dk->denom_pub = pub;
|
||||||
|
generate_response (dk);
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
GNUNET_CONTAINER_multihashmap_put (
|
GNUNET_CONTAINER_multihashmap_put (
|
||||||
keys,
|
keys,
|
||||||
@ -1072,6 +1078,7 @@ parse_key (struct Denomination *denom,
|
|||||||
filename);
|
filename);
|
||||||
GNUNET_CRYPTO_rsa_private_key_free (priv);
|
GNUNET_CRYPTO_rsa_private_key_free (priv);
|
||||||
GNUNET_CRYPTO_rsa_public_key_free (pub);
|
GNUNET_CRYPTO_rsa_public_key_free (pub);
|
||||||
|
GNUNET_free (dk->an);
|
||||||
GNUNET_free (dk);
|
GNUNET_free (dk);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user