X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fidentity%2Fidentity_api.c;h=a31086f5db88498b8288ea4f3cd347e7edfc3c0f;hb=8aa21ee7de6c4a6cb9c1e132ab4218d3d10e0e30;hp=f7f1530fca71a2910c5a5737d9b02b045b1f5847;hpb=1cd462e473e674fa5ab78110ec4f4c26dce1fb73;p=oweals%2Fgnunet.git diff --git a/src/identity/identity_api.c b/src/identity/identity_api.c index f7f1530fc..a31086f5d 100644 --- a/src/identity/identity_api.c +++ b/src/identity/identity_api.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2013 Christian Grothoff (and other contributing authors) + Copyright (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public Liceidentity as published @@ -24,33 +24,28 @@ * @author Christian Grothoff */ #include "platform.h" -#include "gnunet_client_lib.h" +#include "gnunet_util_lib.h" #include "gnunet_constants.h" -#include "gnunet_container_lib.h" -#include "gnunet_arm_service.h" -#include "gnunet_hello_lib.h" #include "gnunet_protocols.h" -#include "gnunet_server_lib.h" -#include "gnunet_time_lib.h" #include "gnunet_identity_service.h" #include "identity.h" #define LOG(kind,...) GNUNET_log_from (kind, "identity-api",__VA_ARGS__) -/** - * Handle for a ego. +/** + * Handle for an ego. */ struct GNUNET_IDENTITY_Ego { /** * Private key associated with this ego. */ - struct GNUNET_CRYPTO_EccPrivateKey *pk; + struct GNUNET_CRYPTO_EcdsaPrivateKey *pk; /** - * Current identifier (name) associated with this ego. + * Current name associated with this ego. */ - char *identifier; + char *name; /** * Client context associated with this ego. @@ -64,7 +59,7 @@ struct GNUNET_IDENTITY_Ego }; -/** +/** * Handle for an operation with the identity service. */ struct GNUNET_IDENTITY_Operation @@ -74,7 +69,7 @@ struct GNUNET_IDENTITY_Operation * Main identity handle. */ struct GNUNET_IDENTITY_Handle *h; - + /** * We keep operations in a DLL. */ @@ -92,19 +87,19 @@ struct GNUNET_IDENTITY_Operation const struct GNUNET_MessageHeader *msg; /** - * Continuation to invoke with the result of the transmission; 'cb' + * Continuation to invoke with the result of the transmission; @e cb * will be NULL in this case. */ GNUNET_IDENTITY_Continuation cont; /** * Continuation to invoke with the result of the transmission for - * 'get' operations ('cont' will be NULL in this case). + * 'get' operations (@e cont will be NULL in this case). */ GNUNET_IDENTITY_Callback cb; /** - * Closure for 'cont' or 'cb'. + * Closure for @e cont or @e cb. */ void *cls; @@ -144,12 +139,12 @@ struct GNUNET_IDENTITY_Handle /** * Head of active operations. - */ + */ struct GNUNET_IDENTITY_Operation *op_head; /** * Tail of active operations. - */ + */ struct GNUNET_IDENTITY_Operation *op_tail; /** @@ -160,7 +155,7 @@ struct GNUNET_IDENTITY_Handle /** * Task doing exponential back-off trying to reconnect. */ - GNUNET_SCHEDULER_TaskIdentifier reconnect_task; + struct GNUNET_SCHEDULER_Task * reconnect_task; /** * Time for next connect retry. @@ -175,11 +170,31 @@ struct GNUNET_IDENTITY_Handle }; +/** + * Obtain the ego representing 'anonymous' users. + * + * @return handle for the anonymous user, must not be freed + */ +const struct GNUNET_IDENTITY_Ego * +GNUNET_IDENTITY_ego_get_anonymous () +{ + static struct GNUNET_IDENTITY_Ego anon; + struct GNUNET_CRYPTO_EcdsaPublicKey pub; + + if (NULL != anon.pk) + return &anon; + anon.pk = (struct GNUNET_CRYPTO_EcdsaPrivateKey *) GNUNET_CRYPTO_ecdsa_key_get_anonymous (); + GNUNET_CRYPTO_ecdsa_key_get_public (anon.pk, + &pub); + GNUNET_CRYPTO_hash (&pub, sizeof (pub), &anon.id); + return &anon; +} + /** - * Try again to connect to network size estimation service. + * Try again to connect to the identity service. * - * @param cls the handle to the transport service + * @param cls handle to the identity service. * @param tc scheduler context */ static void @@ -195,7 +210,7 @@ reconnect (void *cls, static void reschedule_connect (struct GNUNET_IDENTITY_Handle *h) { - GNUNET_assert (h->reconnect_task == GNUNET_SCHEDULER_NO_TASK); + GNUNET_assert (h->reconnect_task == NULL); if (NULL != h->th) { @@ -225,7 +240,7 @@ reschedule_connect (struct GNUNET_IDENTITY_Handle *h) * @param msg message received, NULL on timeout or fatal error */ static void -message_handler (void *cls, +message_handler (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_IDENTITY_Handle *h = cls; @@ -234,12 +249,10 @@ message_handler (void *cls, const struct GNUNET_IDENTITY_ResultCodeMessage *rcm; const struct GNUNET_IDENTITY_UpdateMessage *um; const struct GNUNET_IDENTITY_SetDefaultMessage *sdm; - struct GNUNET_CRYPTO_EccPrivateKey *priv; - struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded pub; + struct GNUNET_CRYPTO_EcdsaPublicKey pub; struct GNUNET_HashCode id; const char *str; uint16_t size; - uint16_t pk_len; uint16_t name_len; if (NULL == msg) @@ -247,6 +260,9 @@ message_handler (void *cls, reschedule_connect (h); return; } + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Received message of type %d from identity service\n", + ntohs (msg->type)); size = ntohs (msg->size); switch (ntohs (msg->type)) { @@ -273,6 +289,8 @@ message_handler (void *cls, GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op); + GNUNET_CLIENT_receive (h->client, &message_handler, h, + GNUNET_TIME_UNIT_FOREVER_REL); if (NULL != op->cont) op->cont (op->cls, str); @@ -288,31 +306,33 @@ message_handler (void *cls, return; } um = (const struct GNUNET_IDENTITY_UpdateMessage *) msg; - pk_len = ntohs (um->pk_len); - name_len = ntohs (um->name_len); + name_len = ntohs (um->name_len); + str = (const char *) &um[1]; - if ( (size != pk_len + name_len + sizeof (struct GNUNET_IDENTITY_UpdateMessage)) || + if ( (size != name_len + sizeof (struct GNUNET_IDENTITY_UpdateMessage)) || ( (0 != name_len) && - ('\0' != str[pk_len + name_len - 1])) ) + ('\0' != str[name_len - 1])) ) { GNUNET_break (0); reschedule_connect (h); return; } - priv = GNUNET_CRYPTO_ecc_decode_key (str, pk_len, GNUNET_YES); - if (NULL == priv) + if (GNUNET_YES == ntohs (um->end_of_list)) { - GNUNET_break (0); - reschedule_connect (h); - return; + /* end of initial list of data */ + GNUNET_CLIENT_receive (h->client, &message_handler, h, + GNUNET_TIME_UNIT_FOREVER_REL); + if (NULL != h->cb) + h->cb (h->cb_cls, NULL, NULL, NULL); + break; } - GNUNET_CRYPTO_ecc_key_get_public (priv, + GNUNET_CRYPTO_ecdsa_key_get_public (&um->private_key, &pub); GNUNET_CRYPTO_hash (&pub, sizeof (pub), &id); if (0 == name_len) str = NULL; else - str = &str[pk_len]; + str = (const char *) &um[1]; ego = GNUNET_CONTAINER_multihashmap_get (h->egos, &id); if (NULL == ego) @@ -322,13 +342,13 @@ message_handler (void *cls, { /* deletion of unknown ego? not allowed */ GNUNET_break (0); - GNUNET_CRYPTO_ecc_key_free (priv); reschedule_connect (h); return; } ego = GNUNET_new (struct GNUNET_IDENTITY_Ego); - ego->pk = priv; - ego->identifier = GNUNET_strdup (str); + ego->pk = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey); + *ego->pk = um->private_key; + ego->name = GNUNET_strdup (str); ego->id = id; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_put (h->egos, @@ -336,10 +356,22 @@ message_handler (void *cls, ego, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); } + if (NULL == str) + { + /* ego was deleted */ + GNUNET_assert (GNUNET_YES == + GNUNET_CONTAINER_multihashmap_remove (h->egos, + &ego->id, + ego)); + } else { - GNUNET_CRYPTO_ecc_key_free (priv); + /* ego changed name */ + GNUNET_free (ego->name); + ego->name = GNUNET_strdup (str); } + GNUNET_CLIENT_receive (h->client, &message_handler, h, + GNUNET_TIME_UNIT_FOREVER_REL); /* inform application about change */ if (NULL != h->cb) h->cb (h->cb_cls, @@ -348,21 +380,10 @@ message_handler (void *cls, str); if (NULL == str) { - /* ego was deleted */ - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (h->egos, - &ego->id, - ego)); - GNUNET_CRYPTO_ecc_key_free (ego->pk); - GNUNET_free (ego->identifier); + GNUNET_free (ego->pk); + GNUNET_free (ego->name); GNUNET_free (ego); } - else - { - /* ego changed name */ - GNUNET_free (ego->identifier); - ego->identifier = GNUNET_strdup (str); - } break; case GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT: if (size < sizeof (struct GNUNET_IDENTITY_SetDefaultMessage)) @@ -372,32 +393,22 @@ message_handler (void *cls, return; } sdm = (const struct GNUNET_IDENTITY_SetDefaultMessage *) msg; - pk_len = ntohs (sdm->pk_len); + GNUNET_break (0 == ntohs (sdm->reserved)); name_len = ntohs (sdm->name_len); str = (const char *) &sdm[1]; - if ( (size != pk_len + name_len + sizeof (struct GNUNET_IDENTITY_SetDefaultMessage)) || + if ( (size != name_len + sizeof (struct GNUNET_IDENTITY_SetDefaultMessage)) || ( (0 != name_len) && - ('\0' != str[pk_len + name_len - 1]) ) ) - { - GNUNET_break (0); - reschedule_connect (h); - return; - } - priv = GNUNET_CRYPTO_ecc_decode_key (str, pk_len, GNUNET_YES); - if (NULL == priv) + ('\0' != str[name_len - 1]) ) ) { GNUNET_break (0); reschedule_connect (h); return; } - GNUNET_CRYPTO_ecc_key_get_public (priv, + /* Note: we know which service this should be for, so we're not + really using 'str' henceforth */ + GNUNET_CRYPTO_ecdsa_key_get_public (&sdm->private_key, &pub); - GNUNET_CRYPTO_ecc_key_free (priv); GNUNET_CRYPTO_hash (&pub, sizeof (pub), &id); - if (0 == name_len) - str = NULL; - else - str = &str[pk_len]; ego = GNUNET_CONTAINER_multihashmap_get (h->egos, &id); if (NULL == ego) @@ -407,14 +418,24 @@ message_handler (void *cls, return; } op = h->op_head; + if (NULL == op) + { + GNUNET_break (0); + reschedule_connect (h); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received SET_DEFAULT message from identity service\n"); GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op); + GNUNET_CLIENT_receive (h->client, &message_handler, h, + GNUNET_TIME_UNIT_FOREVER_REL); if (NULL != op->cb) op->cb (op->cls, ego, &ego->ctx, - ego->identifier); + ego->name); GNUNET_free (op); break; default: @@ -422,8 +443,6 @@ message_handler (void *cls, reschedule_connect (h); return; } - GNUNET_CLIENT_receive (h->client, &message_handler, h, - GNUNET_TIME_UNIT_FOREVER_REL); } @@ -439,20 +458,20 @@ transmit_next (struct GNUNET_IDENTITY_Handle *h); /** * Transmit next message to service. * - * @param cls the 'struct GNUNET_IDENTITY_Handle'. - * @param size number of bytes available in buf + * @param cls the `struct GNUNET_IDENTITY_Handle`. + * @param size number of bytes available in @a buf * @param buf where to copy the message * @return number of bytes copied to buf */ static size_t -send_next_message (void *cls, - size_t size, +send_next_message (void *cls, + size_t size, void *buf) { struct GNUNET_IDENTITY_Handle *h = cls; struct GNUNET_IDENTITY_Operation *op = h->op_head; size_t ret; - + h->th = NULL; if (NULL == op) return 0; @@ -461,7 +480,10 @@ send_next_message (void *cls, { reschedule_connect (h); return 0; - } + } + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Sending message of type %d to identity service\n", + ntohs (op->msg->type)); memcpy (buf, op->msg, ret); if ( (NULL == op->cont) && (NULL == op->cb) ) @@ -496,6 +518,8 @@ transmit_next (struct GNUNET_IDENTITY_Handle *h) GNUNET_assert (NULL == h->th); if (NULL == op) return; + if (NULL == h->client) + return; h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, ntohs (op->msg->size), GNUNET_TIME_UNIT_FOREVER_REL, @@ -506,9 +530,9 @@ transmit_next (struct GNUNET_IDENTITY_Handle *h) /** - * Try again to connect to network size estimation service. + * Try again to connect to the identity service. * - * @param cls the handle to the transport service + * @param cls handle to the identity service. * @param tc scheduler context */ static void @@ -518,22 +542,26 @@ reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) struct GNUNET_IDENTITY_Operation *op; struct GNUNET_MessageHeader msg; - h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; + h->reconnect_task = NULL; LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to identity service.\n"); GNUNET_assert (NULL == h->client); h->client = GNUNET_CLIENT_connect ("identity", h->cfg); GNUNET_assert (NULL != h->client); - op = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_Operation) + - sizeof (struct GNUNET_MessageHeader)); - op->h = h; - op->msg = (const struct GNUNET_MessageHeader *) &op[1]; - msg.size = htons (sizeof (msg)); - msg.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_START); - memcpy (&op[1], &msg, sizeof (msg)); - GNUNET_CONTAINER_DLL_insert (h->op_head, - h->op_tail, - op); + if ( (NULL == h->op_head) || + (GNUNET_MESSAGE_TYPE_IDENTITY_START != ntohs (h->op_head->msg->type)) ) + { + op = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_Operation) + + sizeof (struct GNUNET_MessageHeader)); + op->h = h; + op->msg = (const struct GNUNET_MessageHeader *) &op[1]; + msg.size = htons (sizeof (msg)); + msg.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_START); + memcpy (&op[1], &msg, sizeof (msg)); + GNUNET_CONTAINER_DLL_insert (h->op_head, + h->op_tail, + op); + } transmit_next (h); GNUNET_assert (NULL != h->th); } @@ -544,7 +572,7 @@ reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) * * @param cfg the configuration to use * @param cb function to call on all identity events, can be NULL - * @param cb_cls closure for 'cb' + * @param cb_cls closure for @a cb * @return handle to use */ struct GNUNET_IDENTITY_Handle * @@ -554,10 +582,11 @@ GNUNET_IDENTITY_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, { struct GNUNET_IDENTITY_Handle *h; - h = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_Handle)); + h = GNUNET_new (struct GNUNET_IDENTITY_Handle); h->cfg = cfg; h->cb = cb; h->cb_cls = cb_cls; + h->egos = GNUNET_CONTAINER_multihashmap_create (16, GNUNET_YES); h->reconnect_delay = GNUNET_TIME_UNIT_ZERO; h->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, h); return h; @@ -570,13 +599,28 @@ GNUNET_IDENTITY_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, * @param ego the ego * @return associated ECC key, valid as long as the ego is valid */ -const struct GNUNET_CRYPTO_EccPrivateKey * -GNUNET_IDENTITY_ego_get_key (struct GNUNET_IDENTITY_Ego *ego) +const struct GNUNET_CRYPTO_EcdsaPrivateKey * +GNUNET_IDENTITY_ego_get_private_key (const struct GNUNET_IDENTITY_Ego *ego) { return ego->pk; } +/** + * Get the identifier (public key) of an ego. + * + * @param ego identity handle with the private key + * @param pk set to ego's public key + */ +void +GNUNET_IDENTITY_ego_get_public_key (const struct GNUNET_IDENTITY_Ego *ego, + struct GNUNET_CRYPTO_EcdsaPublicKey *pk) +{ + GNUNET_CRYPTO_ecdsa_key_get_public (ego->pk, + pk); +} + + /** * Obtain the identity that is currently preferred/default * for a service. @@ -584,7 +628,7 @@ GNUNET_IDENTITY_ego_get_key (struct GNUNET_IDENTITY_Ego *ego) * @param id identity service to query * @param service_name for which service is an identity wanted * @param cb function to call with the result (will only be called once) - * @param cb_cls closure for cb + * @param cb_cls closure for @a cb * @return handle to abort the operation */ struct GNUNET_IDENTITY_Operation * @@ -597,7 +641,7 @@ GNUNET_IDENTITY_get (struct GNUNET_IDENTITY_Handle *id, struct GNUNET_IDENTITY_GetDefaultMessage *gdm; size_t slen; - slen = strlen (service_name) + 1; + slen = strlen (service_name) + 1; if (slen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_IDENTITY_GetDefaultMessage)) { GNUNET_break (0); @@ -605,7 +649,8 @@ GNUNET_IDENTITY_get (struct GNUNET_IDENTITY_Handle *id, } op = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_Operation) + sizeof (struct GNUNET_IDENTITY_GetDefaultMessage) + - slen); + slen); + op->h = id; op->cb = cb; op->cls = cb_cls; gdm = (struct GNUNET_IDENTITY_GetDefaultMessage *) &op[1]; @@ -632,7 +677,7 @@ GNUNET_IDENTITY_get (struct GNUNET_IDENTITY_Handle *id, * @param service_name for which service is an identity set * @param ego new default identity to be set for this service * @param cont function to call once the operation finished - * @param cont_cls closure for cont + * @param cont_cls closure for @a cont * @return handle to abort the operation */ struct GNUNET_IDENTITY_Operation * @@ -642,37 +687,30 @@ GNUNET_IDENTITY_set (struct GNUNET_IDENTITY_Handle *id, GNUNET_IDENTITY_Continuation cont, void *cont_cls) { - struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *enc; struct GNUNET_IDENTITY_Operation *op; struct GNUNET_IDENTITY_SetDefaultMessage *sdm; - char *str; - uint16_t enc_len; size_t slen; slen = strlen (service_name) + 1; - enc = GNUNET_CRYPTO_ecc_encode_key (ego->pk); - enc_len = ntohs (enc->size); - - if (slen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_IDENTITY_SetDefaultMessage) - enc_len) + if (slen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_IDENTITY_SetDefaultMessage)) { GNUNET_break (0); - GNUNET_free (enc); return NULL; } op = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_Operation) + sizeof (struct GNUNET_IDENTITY_SetDefaultMessage) + - enc_len + slen); + slen); + op->h = id; op->cont = cont; op->cls = cont_cls; sdm = (struct GNUNET_IDENTITY_SetDefaultMessage *) &op[1]; sdm->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT); sdm->header.size = htons (sizeof (struct GNUNET_IDENTITY_SetDefaultMessage) + - slen + enc_len); + slen); sdm->name_len = htons (slen); - sdm->pk_len = htons (enc_len); - str = (char *) &sdm[1]; - memcpy (str, enc, enc_len); - memcpy (&str[enc_len], service_name, slen); + sdm->reserved = htons (0); + sdm->private_key = *ego->pk; + memcpy (&sdm[1], service_name, slen); op->msg = &sdm->header; GNUNET_CONTAINER_DLL_insert_tail (id->op_head, id->op_tail, @@ -683,79 +721,74 @@ GNUNET_IDENTITY_set (struct GNUNET_IDENTITY_Handle *id, } -/** - * Create a new identity with the given identifier. +/** + * Create a new identity with the given name. * * @param id identity service to use - * @param identifier desired identifier - * @param cb function to call with the result (will only be called once) - * @param cb_cls closure for cb + * @param name desired name + * @param cont function to call with the result (will only be called once) + * @param cont_cls closure for @a cont * @return handle to abort the operation */ struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_create (struct GNUNET_IDENTITY_Handle *id, - const char *identifier, - GNUNET_IDENTITY_Callback cb, - void *cb_cls) + const char *name, + GNUNET_IDENTITY_Continuation cont, + void *cont_cls) { - struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *enc; struct GNUNET_IDENTITY_Operation *op; struct GNUNET_IDENTITY_CreateRequestMessage *crm; - struct GNUNET_CRYPTO_EccPrivateKey *pk; - char *str; - uint16_t enc_len; + struct GNUNET_CRYPTO_EcdsaPrivateKey *pk; size_t slen; - slen = strlen (identifier) + 1; - pk = GNUNET_CRYPTO_ecc_key_create (); - enc = GNUNET_CRYPTO_ecc_encode_key (pk); - GNUNET_CRYPTO_ecc_key_free (pk); - enc_len = ntohs (enc->size); + slen = strlen (name) + 1; + pk = GNUNET_CRYPTO_ecdsa_key_create (); - if (slen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_IDENTITY_CreateRequestMessage) - enc_len) + if (slen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_IDENTITY_CreateRequestMessage)) { GNUNET_break (0); - GNUNET_free (enc); + GNUNET_free (pk); return NULL; } op = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_Operation) + sizeof (struct GNUNET_IDENTITY_CreateRequestMessage) + - enc_len + slen); - op->cb = cb; - op->cls = cb_cls; + slen); + op->h = id; + op->cont = cont; + op->cls = cont_cls; crm = (struct GNUNET_IDENTITY_CreateRequestMessage *) &op[1]; crm->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_CREATE); crm->header.size = htons (sizeof (struct GNUNET_IDENTITY_CreateRequestMessage) + - slen + enc_len); + slen); crm->name_len = htons (slen); - crm->pk_len = htons (enc_len); - str = (char *) &crm[1]; - memcpy (str, enc, enc_len); - memcpy (&str[enc_len], identifier, slen); + crm->reserved = htons (0); + crm->private_key = *pk; + memcpy (&crm[1], name, slen); op->msg = &crm->header; GNUNET_CONTAINER_DLL_insert_tail (id->op_head, id->op_tail, op); if (NULL == id->th) transmit_next (id); + GNUNET_free (pk); return op; } -/** +/** * Renames an existing identity. * * @param id identity service to use - * @param old_identifier old identifier - * @param new_identifier desired new identifier + * @param old_name old name + * @param new_name desired new name * @param cb function to call with the result (will only be called once) - * @param cb_cls closure for cb + * @param cb_cls closure for @a cb * @return handle to abort the operation */ struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_rename (struct GNUNET_IDENTITY_Handle *id, - const char *old_identifier, - const char *new_identifier, + const char *old_name, + const char *new_name, GNUNET_IDENTITY_Continuation cb, void *cb_cls) { @@ -765,8 +798,8 @@ GNUNET_IDENTITY_rename (struct GNUNET_IDENTITY_Handle *id, size_t slen_new; char *dst; - slen_old = strlen (old_identifier) + 1; - slen_new = strlen (new_identifier) + 1; + slen_old = strlen (old_name) + 1; + slen_new = strlen (new_name) + 1; if ( (slen_old >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || (slen_new >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || (slen_old + slen_new >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_IDENTITY_RenameMessage)) ) @@ -777,6 +810,7 @@ GNUNET_IDENTITY_rename (struct GNUNET_IDENTITY_Handle *id, op = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_Operation) + sizeof (struct GNUNET_IDENTITY_RenameMessage) + slen_old + slen_new); + op->h = id; op->cont = cb; op->cls = cb_cls; grm = (struct GNUNET_IDENTITY_RenameMessage *) &op[1]; @@ -786,8 +820,8 @@ GNUNET_IDENTITY_rename (struct GNUNET_IDENTITY_Handle *id, grm->old_name_len = htons (slen_old); grm->new_name_len = htons (slen_new); dst = (char *) &grm[1]; - memcpy (dst, old_identifier, slen_old); - memcpy (&dst[slen_old], new_identifier, slen_new); + memcpy (dst, old_name, slen_old); + memcpy (&dst[slen_old], new_name, slen_new); op->msg = &grm->header; GNUNET_CONTAINER_DLL_insert_tail (id->op_head, id->op_tail, @@ -798,18 +832,18 @@ GNUNET_IDENTITY_rename (struct GNUNET_IDENTITY_Handle *id, } -/** +/** * Delete an existing identity. * * @param id identity service to use - * @param identifier identifier of the identity to delete + * @param name name of the identity to delete * @param cb function to call with the result (will only be called once) - * @param cb_cls closure for cb + * @param cb_cls closure for @a cb * @return handle to abort the operation */ struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_delete (struct GNUNET_IDENTITY_Handle *id, - const char *identifier, + const char *name, GNUNET_IDENTITY_Continuation cb, void *cb_cls) { @@ -817,7 +851,7 @@ GNUNET_IDENTITY_delete (struct GNUNET_IDENTITY_Handle *id, struct GNUNET_IDENTITY_DeleteMessage *gdm; size_t slen; - slen = strlen (identifier) + 1; + slen = strlen (name) + 1; if (slen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_IDENTITY_DeleteMessage)) { GNUNET_break (0); @@ -825,7 +859,8 @@ GNUNET_IDENTITY_delete (struct GNUNET_IDENTITY_Handle *id, } op = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_Operation) + sizeof (struct GNUNET_IDENTITY_DeleteMessage) + - slen); + slen); + op->h = id; op->cont = cb; op->cls = cb_cls; gdm = (struct GNUNET_IDENTITY_DeleteMessage *) &op[1]; @@ -834,7 +869,7 @@ GNUNET_IDENTITY_delete (struct GNUNET_IDENTITY_Handle *id, slen); gdm->name_len = htons (slen); gdm->reserved = htons (0); - memcpy (&gdm[1], identifier, slen); + memcpy (&gdm[1], name, slen); op->msg = &gdm->header; GNUNET_CONTAINER_DLL_insert_tail (id->op_head, id->op_tail, @@ -854,7 +889,7 @@ GNUNET_IDENTITY_delete (struct GNUNET_IDENTITY_Handle *id, * @param op operation to cancel */ void -GNUNET_IDENITY_cancel (struct GNUNET_IDENTITY_Operation *op) +GNUNET_IDENTITY_cancel (struct GNUNET_IDENTITY_Operation *op) { struct GNUNET_IDENTITY_Handle *h = op->h; @@ -862,6 +897,8 @@ GNUNET_IDENITY_cancel (struct GNUNET_IDENTITY_Operation *op) (NULL == h->client) ) { /* request not active, can simply remove */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Client aborted non-head operation, simply removing it\n"); GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op); @@ -871,6 +908,8 @@ GNUNET_IDENITY_cancel (struct GNUNET_IDENTITY_Operation *op) if (NULL != h->th) { /* request active but not yet with service, can still abort */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Client aborted head operation prior to transmission, aborting it\n"); GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; GNUNET_CONTAINER_DLL_remove (h->op_head, @@ -881,11 +920,41 @@ GNUNET_IDENITY_cancel (struct GNUNET_IDENTITY_Operation *op) return; } /* request active with service, simply ensure continuations are not called */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Client aborted active request, NULLing continuation\n"); op->cont = NULL; op->cb = NULL; } +/** + * Free ego from hash map. + * + * @param cls identity service handle + * @param key unused + * @param value ego to free + * @return #GNUNET_OK (continue to iterate) + */ +static int +free_ego (void *cls, + const struct GNUNET_HashCode *key, + void *value) +{ + struct GNUNET_IDENTITY_Handle *h = cls; + struct GNUNET_IDENTITY_Ego *ego = value; + + if (NULL != h->cb) + h->cb (h->cb_cls, + ego, + &ego->ctx, + NULL); + GNUNET_free (ego->pk); + GNUNET_free (ego->name); + GNUNET_free (ego); + return GNUNET_OK; +} + + /** * Disconnect from identity service * @@ -894,17 +963,35 @@ GNUNET_IDENITY_cancel (struct GNUNET_IDENTITY_Operation *op) void GNUNET_IDENTITY_disconnect (struct GNUNET_IDENTITY_Handle *h) { + struct GNUNET_IDENTITY_Operation *op; + GNUNET_assert (NULL != h); - if (h->reconnect_task != GNUNET_SCHEDULER_NO_TASK) + if (h->reconnect_task != NULL) { GNUNET_SCHEDULER_cancel (h->reconnect_task); - h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; + h->reconnect_task = NULL; } if (NULL != h->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; } + if (NULL != h->egos) + { + GNUNET_CONTAINER_multihashmap_iterate (h->egos, + &free_ego, + h); + GNUNET_CONTAINER_multihashmap_destroy (h->egos); + h->egos = NULL; + } + while (NULL != (op = h->op_head)) + { + GNUNET_break (NULL == op->cont); + GNUNET_CONTAINER_DLL_remove (h->op_head, + h->op_tail, + op); + GNUNET_free (op); + } if (NULL != h->client) { GNUNET_CLIENT_disconnect (h->client);