From 0b4a4a37a011945adbc7a01899ef548b3aa027af Mon Sep 17 00:00:00 2001 From: Matthias Wachs Date: Fri, 2 Mar 2012 17:29:46 +0000 Subject: [PATCH] --- src/namestore/Makefile.am | 8 ++ src/namestore/gnunet-service-namestore.c | 165 ++++++++++++++++++++--- src/namestore/namestore.h | 25 +++- src/namestore/namestore_api.c | 92 ++++++++++--- src/namestore/test_namestore_api_put.c | 3 +- 5 files changed, 254 insertions(+), 39 deletions(-) diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am index 852788a2d..7bd014fd9 100644 --- a/src/namestore/Makefile.am +++ b/src/namestore/Makefile.am @@ -30,6 +30,7 @@ check_PROGRAMS = \ test_namestore_api_put \ test_namestore_api_lookup \ test_namestore_api_create \ + test_namestore_api_create_update \ test_namestore_api_remove \ test_namestore_api_remove_not_existing_record \ test_namestore_api_zone_iteration \ @@ -111,6 +112,13 @@ test_namestore_api_create_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la +test_namestore_api_create_update_SOURCES = \ + test_namestore_api_create_update.c +test_namestore_api_create_update_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + + test_namestore_api_remove_SOURCES = \ test_namestore_api_remove.c test_namestore_api_remove_LDADD = \ diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c index 286512dca..8734ee34a 100644 --- a/src/namestore/gnunet-service-namestore.c +++ b/src/namestore/gnunet-service-namestore.c @@ -138,7 +138,6 @@ client_lookup (struct GNUNET_SERVER_Client *client) return nc; } - /** * Called whenever a client is disconnected. Frees our * resources associated with that client. @@ -172,6 +171,8 @@ client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client) GNUNET_free (nc); } + + static void handle_start (void *cls, struct GNUNET_SERVER_Client * client, const struct GNUNET_MessageHeader * message) @@ -195,8 +196,80 @@ struct LookupNameContext char * name; }; +void drop_iterator (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, + struct GNUNET_TIME_Absolute expire, + const char *name, + unsigned int rd_len, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + GNUNET_HashCode zone_hash; + int * stop = cls; + if (NULL != zone_key) + { + GNUNET_CRYPTO_hash(zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone_hash); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting zone `%s'\n", GNUNET_h2s (&zone_hash)); + GSN_database->delete_zone (GSN_database->cls, &zone_hash); + } + else + { + (*stop) = GNUNET_YES; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "NULL \n"); + } +} + + +/** + * Called whenever a client is disconnected. Frees our + * resources associated with that client. + * + * @param cls closure + * @param client identification of the client + */ +static void handle_stop (void *cls, + struct GNUNET_SERVER_Client * client, + const struct GNUNET_MessageHeader * message) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_REMOVE"); + struct DisconnectMessage * msg = (struct DisconnectMessage *) message; + struct GNUNET_NAMESTORE_ZoneIteration * no; + struct GNUNET_NAMESTORE_Client * nc; + int drop; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected \n", client); + + nc = client_lookup (client); + if (nc == NULL) + { + GNUNET_break (0); + return; + } + + for (no = nc->op_head; no != NULL; no = no->next) + { + GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no); + GNUNET_free (no); + } + drop = ntohl(msg->drop); + if (GNUNET_YES == drop) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Dropping namestore content\n"); + int stop = GNUNET_NO; + int offset = 0; + while (stop == GNUNET_NO) + { + GSN_database->iterate_records (GSN_database->cls, NULL, NULL, offset, &drop_iterator, &stop); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "STOP %u \n"); + offset ++; + } + } + GNUNET_SERVER_client_drop(nc->client); + GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc); + GNUNET_free (nc); +} static void handle_lookup_name_it (void *cls, @@ -532,35 +605,91 @@ handle_create_record_it (void *cls, const struct GNUNET_CRYPTO_RsaSignature *signature) { struct CreateRecordContext * crc = cls; - struct GNUNET_CRYPTO_RsaSignature *signature_new; + struct GNUNET_CRYPTO_RsaSignature *signature_new = NULL; + struct GNUNET_NAMESTORE_RecordData *rd_new = NULL; int res; + int exist = GNUNET_SYSERR; + int update = GNUNET_NO; + int c; + int rd_count_new = 0; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u existing records for `%s'\n", rd_count, crc->name); - struct GNUNET_NAMESTORE_RecordData *rd_new = GNUNET_malloc ((rd_count+1) * sizeof (struct GNUNET_NAMESTORE_RecordData)); - memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData)); - rd_new[rd_count] = *(crc->rd); + for (c = 0; c < rd_count; c++) + { + + if ((crc->rd->record_type == rd[c].record_type) && + (crc->rd->data_size == rd[c].data_size) && + (0 == memcmp (crc->rd->data, rd[c].data, rd[c].data_size))) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found existing records for `%s' to update!\n", crc->name); + exist = c; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "exp %llu %llu!\n", rd[c].expiration.abs_value, crc->rd->expiration.abs_value); + if (crc->rd->expiration.abs_value != rd[c].expiration.abs_value) + + update = GNUNET_YES; + break; + } + } - signature_new = GNUNET_NAMESTORE_create_signature (crc->pkey, crc->name, rd_new, rd_count+1); - if (NULL == signature_new) + if (exist == GNUNET_SYSERR) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "NO existing records for `%s' to update!\n", crc->name); + + if (exist == GNUNET_SYSERR) { - GNUNET_break (0); - res = GNUNET_SYSERR; + rd_new = GNUNET_malloc ((rd_count+1) * sizeof (struct GNUNET_NAMESTORE_RecordData)); + memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData)); + rd_count_new = rd_count + 1; + rd_new[rd_count] = *(crc->rd); + signature_new = GNUNET_NAMESTORE_create_signature (crc->pkey, crc->name, rd_new, rd_count+1); + + if (NULL == signature_new) + { + GNUNET_break (0); + res = GNUNET_SYSERR; + goto end; + } + } + else if (update == GNUNET_NO) + { + /* Exact same record already exists */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No update for %s' record required!\n", crc->name); + res = GNUNET_NO; + goto end; + } + else if (update == GNUNET_YES) + { + /* Update record */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating existing records for `%s'!\n", crc->name); + rd_new = GNUNET_malloc ((rd_count) * sizeof (struct GNUNET_NAMESTORE_RecordData)); + memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData)); + rd_count_new = rd_count; + rd_new[exist].expiration = crc->rd->expiration; + signature_new = GNUNET_NAMESTORE_create_signature (crc->pkey, crc->name, rd_new, rd_count_new); + if (NULL == signature_new) + { + GNUNET_break (0); + res = GNUNET_SYSERR; + goto end; + } } /* Database operation */ + GNUNET_assert ((rd_new != NULL) && (rd_count_new > 0)); res = GSN_database->put_records(GSN_database->cls, (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) crc->pubkey, crc->expire, crc->name, - rd_count +1, rd_new, + rd_count_new, rd_new, signature_new); GNUNET_break (GNUNET_OK == res); + res = GNUNET_YES; - GNUNET_free (rd_new); - GNUNET_free (signature_new); +end: + GNUNET_free_non_null (rd_new); + GNUNET_free_non_null (signature_new); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Update result for name `%s' %s\n", crc->name, (res == GNUNET_OK) ? "SUCCESS" : "FAIL"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Update result for name `%s' %u\n", crc->name, res); crc->res = res; } @@ -671,10 +800,12 @@ send: rcr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE); rcr_msg.gns_header.r_id = htonl (rid); rcr_msg.gns_header.header.size = htons (sizeof (struct RecordCreateResponseMessage)); - if ((GNUNET_OK == res) && (crc.res == GNUNET_OK)) - rcr_msg.op_result = htons (GNUNET_OK); - else + if ((GNUNET_OK == res) && (crc.res == GNUNET_YES)) + rcr_msg.op_result = htons (GNUNET_YES); + else if ((GNUNET_OK == res) && (crc.res == GNUNET_NO)) rcr_msg.op_result = htons (GNUNET_NO); + else + rcr_msg.op_result = htons (GNUNET_SYSERR); GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rcr_msg, GNUNET_NO); GNUNET_SERVER_receive_done (client, GNUNET_OK); @@ -1128,6 +1259,8 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, static const struct GNUNET_SERVER_MessageHandler handlers[] = { {&handle_start, NULL, GNUNET_MESSAGE_TYPE_NAMESTORE_START, sizeof (struct StartMessage)}, + {&handle_stop, NULL, + GNUNET_MESSAGE_TYPE_NAMESTORE_DISCONNECT, sizeof (struct DisconnectMessage)}, {&handle_lookup_name, NULL, GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME, 0}, {&handle_record_put, NULL, diff --git a/src/namestore/namestore.h b/src/namestore/namestore.h index e079e62ce..a70d3a62c 100644 --- a/src/namestore/namestore.h +++ b/src/namestore/namestore.h @@ -43,6 +43,8 @@ #define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT 441 #define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP 442 +#define GNUNET_MESSAGE_TYPE_NAMESTORE_DISCONNECT 443 + struct GNUNET_CRYPTO_RsaSignature * GNUNET_NAMESTORE_create_signature (const struct GNUNET_CRYPTO_RsaPrivateKey *key, const char *name, struct GNUNET_NAMESTORE_RecordData *rd, unsigned int rd_count); @@ -102,6 +104,25 @@ struct StartMessage }; +/** + * Connect to namestore service. FIXME: UNNECESSARY. + */ +struct DisconnectMessage +{ + + /** + * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_DISCONNECT + */ + struct GNUNET_MessageHeader header; + + /** + * Drop namestore? + * GNUNET_YES or _NO in NBO + */ + uint32_t drop; +}; + + /** * Generic namestore message with op id */ @@ -262,9 +283,9 @@ struct RecordCreateResponseMessage /* Contenct starts here */ /** - * name length: GNUNET_NO (0) on error, GNUNET_OK (1) on success + * name length: GNUNET_NO already existsw, GNUNET_YES on success, GNUNET_SYSERR error */ - uint16_t op_result; + int16_t op_result; }; diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c index cd85a35eb..fa681c566 100644 --- a/src/namestore/namestore_api.c +++ b/src/namestore/namestore_api.c @@ -316,29 +316,30 @@ handle_record_create_response (struct GNUNET_NAMESTORE_QueueEntry *qe, "RECORD_CREATE_RESPONSE"); struct GNUNET_NAMESTORE_Handle *h = qe->nsh; - int res = GNUNET_OK; - if (ntohs (msg->op_result) == GNUNET_OK) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' %i\n", + "RECORD_CREATE_RESPONSE", ntohs (msg->op_result)); + if (ntohs (msg->op_result) == GNUNET_YES) { - res = GNUNET_OK; if (qe->cont != NULL) { - qe->cont (qe->cont_cls, res, _("Namestore added record successfully")); + qe->cont (qe->cont_cls, GNUNET_YES, _("Namestore added record successfully")); } } else if (ntohs (msg->op_result) == GNUNET_NO) { - res = GNUNET_SYSERR; if (qe->cont != NULL) { - qe->cont (qe->cont_cls, res, _("Namestore failed to add record")); + qe->cont (qe->cont_cls, GNUNET_NO, _("Namestore record already existed")); } } else { - GNUNET_break_op (0); - return; + if (qe->cont != NULL) + { + qe->cont (qe->cont_cls, GNUNET_SYSERR, _("Namestore failed to add record\n")); + } } /* Operation done, remove */ @@ -742,23 +743,21 @@ GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) return h; } +struct DisconnectContext +{ + struct GNUNET_NAMESTORE_Handle *h; + int drop; +}; -/** - * Disconnect from the namestore service (and free associated - * resources). - * - * @param h handle to the namestore - * @param drop set to GNUNET_YES to delete all data in namestore (!) - */ -void -GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h, int drop) +static void +clean_up_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PendingMessage *p; struct GNUNET_NAMESTORE_QueueEntry *q; struct GNUNET_NAMESTORE_ZoneIterator *z; - + struct GNUNET_NAMESTORE_Handle *h = cls; GNUNET_assert (h != NULL); - + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); while (NULL != (p = h->pending_head)) { GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p); @@ -790,6 +789,61 @@ GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h, int drop) } GNUNET_free(h); h = NULL; +}; + +static size_t +transmit_disconnect_to_namestore (void *cls, size_t size, void *buf) +{ + struct DisconnectContext * d_ctx = cls; + struct DisconnectMessage d_msg; + struct GNUNET_NAMESTORE_Handle *h = d_ctx->h; + int res; + + d_msg.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_DISCONNECT); + d_msg.header.size = htons (sizeof (struct DisconnectMessage)); + d_msg.drop = htonl (d_ctx->drop); + + h->th = NULL; + if ((size == 0) || (buf == NULL) || (size < sizeof (struct DisconnectMessage))) + { + GNUNET_break (0); + res = 0; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message to service \n", "NAMESTORE_DISCONNECT"); + memcpy (buf, &d_msg, sizeof (struct DisconnectMessage)); + res = sizeof (struct DisconnectMessage); + } + + GNUNET_SCHEDULER_add_now (&clean_up_task, h); + GNUNET_free (d_ctx); + return res; +} + +/** + * Disconnect from the namestore service (and free associated + * resources). + * + * @param h handle to the namestore + * @param drop set to GNUNET_YES to delete all data in namestore (!) + */ +void +GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h, int drop) +{ + if (h->th != NULL) + { + GNUNET_CLIENT_notify_transmit_ready_cancel(h->th); + } + + struct DisconnectContext *d_ctx = GNUNET_malloc (sizeof (struct DisconnectContext)); + d_ctx->h = h; + d_ctx->drop = drop; + + h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, sizeof (struct DisconnectMessage), + GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_NO, &transmit_disconnect_to_namestore, + d_ctx); } diff --git a/src/namestore/test_namestore_api_put.c b/src/namestore/test_namestore_api_put.c index f65b533b3..8aa149ad9 100644 --- a/src/namestore/test_namestore_api_put.c +++ b/src/namestore/test_namestore_api_put.c @@ -92,7 +92,6 @@ endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) if (NULL != arm) stop_arm(); - res = 1; } @@ -114,7 +113,7 @@ end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); nsh = NULL; - if (NULL != arm) + if (NULL != arm) stop_arm(); } -- 2.25.1