diff options
Diffstat (limited to 'src/namestore/gnunet-service-namestore.c')
-rw-r--r-- | src/namestore/gnunet-service-namestore.c | 845 |
1 files changed, 845 insertions, 0 deletions
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c new file mode 100644 index 0000000..92eb218 --- /dev/null +++ b/src/namestore/gnunet-service-namestore.c @@ -0,0 +1,845 @@ +/* + This file is part of GNUnet. + (C) 2009 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 License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file namestore/gnunet-service-namestore.c + * @brief namestore for the GNUnet naming system + * @author Matthias Wachs + */ +#include "platform.h" +#include "gnunet_getopt_lib.h" +#include "gnunet_service_lib.h" +#include "gnunet_namestore_service.h" +#include "gnunet_namestore_plugin.h" +#include "namestore.h" + + + +/** + * A namestore operation. + */ +struct GNUNET_NAMESTORE_ZoneIteration +{ + struct GNUNET_NAMESTORE_ZoneIteration *next; + struct GNUNET_NAMESTORE_ZoneIteration *prev; + + struct GNUNET_NAMESTORE_Client * client; + + GNUNET_HashCode zone; + + uint64_t op_id; + uint32_t offset; + +}; + + +/** + * A namestore client + */ +struct GNUNET_NAMESTORE_Client +{ + struct GNUNET_NAMESTORE_Client *next; + struct GNUNET_NAMESTORE_Client *prev; + + struct GNUNET_SERVER_Client * client; + + struct GNUNET_NAMESTORE_ZoneIteration *op_head; + struct GNUNET_NAMESTORE_ZoneIteration *op_tail; +}; + + + +/** + * Configuration handle. + */ +const struct GNUNET_CONFIGURATION_Handle *GSN_cfg; + +static struct GNUNET_NAMESTORE_PluginFunctions *GSN_database; + +/** + * Our notification context. + */ +static struct GNUNET_SERVER_NotificationContext *snc; + +static char *db_lib_name; + +static struct GNUNET_NAMESTORE_Client *client_head; +static struct GNUNET_NAMESTORE_Client *client_tail; + + +/** + * Task run during shutdown. + * + * @param cls unused + * @param tc unused + */ +static void +cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n"); + + struct GNUNET_NAMESTORE_ZoneIteration * no; + struct GNUNET_NAMESTORE_ZoneIteration * tmp; + struct GNUNET_NAMESTORE_Client * nc; + struct GNUNET_NAMESTORE_Client * next; + + for (nc = client_head; nc != NULL; nc = next) + { + next = nc->next; + for (no = nc->op_head; no != NULL; no = tmp) + { + GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no); + tmp = no->next; + GNUNET_free (no); + } + + GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc); + GNUNET_free (nc); + + } + + GNUNET_SERVER_notification_context_destroy (snc); + snc = NULL; + + GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database)); + GNUNET_free (db_lib_name); +} + +static struct GNUNET_NAMESTORE_Client * +client_lookup (struct GNUNET_SERVER_Client *client) +{ + struct GNUNET_NAMESTORE_Client * nc; + + GNUNET_assert (NULL != client); + + for (nc = client_head; nc != NULL; nc = nc->next) + { + if (client == nc->client) + break; + } + return nc; +} + + +/** + * Called whenever a client is disconnected. Frees our + * resources associated with that client. + * + * @param cls closure + * @param client identification of the client + */ +static void +client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client) +{ + struct GNUNET_NAMESTORE_ZoneIteration * no; + struct GNUNET_NAMESTORE_Client * nc; + if (NULL == client) + return; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected \n", client); + + nc = client_lookup (client); + + if ((NULL == client) || (NULL == nc)) + 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); + } + + GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc); + GNUNET_free (nc); +} + +static void handle_start (void *cls, + struct GNUNET_SERVER_Client * client, + const struct GNUNET_MessageHeader * message) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client); + + struct GNUNET_NAMESTORE_Client * nc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Client)); + nc->client = client; + GNUNET_SERVER_notification_context_add (snc, client); + GNUNET_CONTAINER_DLL_insert(client_head, client_tail, nc); + + GNUNET_SERVER_receive_done (client, GNUNET_OK); +} + +struct LookupNameContext +{ + struct GNUNET_NAMESTORE_Client *nc; + uint32_t id; + uint32_t record_type; +}; + + + + +static void +handle_lookup_name_it (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, + struct GNUNET_TIME_Absolute expire, + const char *name, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + /* send response */ + struct LookupNameContext *lnc = cls; + struct LookupNameResponseMessage *lnr_msg; + + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key_tmp; + struct GNUNET_NAMESTORE_RecordData * rd_tmp; + char *name_tmp; + struct GNUNET_CRYPTO_RsaSignature *signature_tmp; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "NAMESTORE_LOOKUP_NAME_RESPONSE"); + + size_t r_size = 0; + + size_t name_len = 0; + if (NULL != name) + name_len = strlen(name) + 1; + + int copied_elements = 0; + int contains_signature = 0; + int c; + + /* count records to copy */ + if (rd_count != 0) + { + if (lnc->record_type != 0) + { + /* special record type needed */ + for (c = 0; c < rd_count; c ++) + if (rd[c].record_type == lnc->record_type) + copied_elements++; /* found matching record */ + } + else + copied_elements = rd_count; + } + + if ((copied_elements == rd_count) && (signature != NULL)) + contains_signature = GNUNET_YES; + + r_size = sizeof (struct LookupNameResponseMessage) + + sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + + name_len + + copied_elements * sizeof (struct GNUNET_NAMESTORE_RecordData) + + contains_signature * sizeof (struct GNUNET_CRYPTO_RsaSignature); + + lnr_msg = GNUNET_malloc (r_size); + + lnr_msg->header.type = ntohs (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE); + lnr_msg->header.size = ntohs (r_size); + lnr_msg->op_id = htonl (lnc->id); + lnr_msg->rc_count = htonl (copied_elements); + lnr_msg->name_len = htons (name_len); + lnr_msg->expire = GNUNET_TIME_absolute_hton(expire); + lnr_msg->contains_sig = htons (contains_signature); + + + zone_key_tmp = (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) &lnr_msg[1]; + name_tmp = (char *) &zone_key_tmp[1]; + rd_tmp = (struct GNUNET_NAMESTORE_RecordData *) &name_tmp[name_len]; + signature_tmp = (struct GNUNET_CRYPTO_RsaSignature *) &rd_tmp[copied_elements]; + + if (zone_key != NULL) + memcpy (zone_key_tmp, zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); + else + { + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded dummy; + memset (&dummy, '0', sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); + memcpy (zone_key_tmp, &dummy, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); + } + memcpy (name_tmp, name, name_len); + /* copy records */ + copied_elements = 0; + if (rd_count != 0) + { + if (lnc->record_type != 0) + { + /* special record type needed */ + for (c = 0; c < rd_count; c ++) + if (rd[c].record_type == lnc->record_type) + { + /* found matching record */ + memcpy (&rd_tmp[copied_elements], &rd[c], rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData)); + copied_elements++; + } + } + else + memcpy (rd_tmp, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData)); + } + + if (GNUNET_YES == contains_signature) + memcpy (signature_tmp, signature, sizeof (struct GNUNET_CRYPTO_RsaSignature)); + GNUNET_SERVER_notification_context_unicast (snc, lnc->nc->client, (const struct GNUNET_MessageHeader *) lnr_msg, GNUNET_NO); + + GNUNET_free (lnr_msg); +} + +static void handle_lookup_name (void *cls, + struct GNUNET_SERVER_Client * client, + const struct GNUNET_MessageHeader * message) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_LOOKUP_NAME"); + struct LookupNameContext lnc; + struct GNUNET_NAMESTORE_Client *nc; + GNUNET_HashCode name_hash; + size_t name_len; + char * name; + uint32_t id = 0; + uint32_t type = 0; + + + if (ntohs (message->size) < sizeof (struct LookupNameMessage)) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + nc = client_lookup(client); + if (nc == NULL) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + struct LookupNameMessage * ln_msg = (struct LookupNameMessage *) message; + id = ntohl (ln_msg->op_id); + name_len = ntohl (ln_msg->name_len); + type = ntohl (ln_msg->record_type); + + if ((name_len == 0) || (name_len > 256)) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + name = GNUNET_malloc (name_len); + memcpy (name, &ln_msg[1], name_len); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up record for name `%s'\n", name); + GNUNET_CRYPTO_hash(name, name_len-1, &name_hash); + GNUNET_free (name); + + /* do the actual lookup */ + lnc.id = id; + lnc.nc = nc; + lnc.record_type = type; + GSN_database->iterate_records(GSN_database->cls, &ln_msg->zone, &ln_msg->zone, 0, &handle_lookup_name_it, &lnc); + + GNUNET_SERVER_receive_done (client, GNUNET_OK); +} + +static void handle_record_put (void *cls, + struct GNUNET_SERVER_Client * client, + const struct GNUNET_MessageHeader * message) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_PUT"); + struct GNUNET_NAMESTORE_Client *nc; + struct GNUNET_TIME_Absolute expire; + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key; + struct GNUNET_NAMESTORE_RecordData *rd; + struct GNUNET_CRYPTO_RsaSignature *signature; + struct RecordPutResponseMessage rpr_msg; + size_t name_len; + size_t msg_size; + size_t msg_size_exp; + char * name; + char * rd_ser; + uint32_t id = 0; + uint32_t rd_ser_len; + uint32_t rd_count; + int res = GNUNET_SYSERR; + + if (ntohs (message->size) < sizeof (struct RecordPutMessage)) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + nc = client_lookup (client); + if (nc == NULL) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + struct RecordPutMessage * rp_msg = (struct RecordPutMessage *) message; + id = ntohl (rp_msg->op_id); + name_len = ntohs (rp_msg->name_len); + rd_ser_len = ntohs(rp_msg->rd_len); + msg_size = ntohs (message->size); + msg_size_exp = sizeof (struct RecordPutMessage) + sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + name_len + rd_ser_len; + + if (msg_size != msg_size_exp) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size); + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + + if ((name_len == 0) || (name_len > 256)) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + zone_key = (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) &rp_msg[1]; + name = (char *) &zone_key[1]; + expire = GNUNET_TIME_absolute_ntoh(rp_msg->expire); + signature = (struct GNUNET_CRYPTO_RsaSignature *) &rp_msg->signature; + rd_ser = &name[name_len]; + rd_count = GNUNET_NAMESTORE_records_deserialize(&rd, rd_ser, rd_ser_len); + + /* Database operation */ + res = GSN_database->put_records(GSN_database->cls, + zone_key, + expire, + name, + rd_count, rd, + signature); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting record for name `%s': %s\n", + name, (res == GNUNET_OK) ? "OK" : "FAIL"); + + /* Send response */ + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_PUT_RESPONSE"); + rpr_msg.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE); + rpr_msg.op_id = rp_msg->op_id; + rpr_msg.header.size = htons (sizeof (struct RecordPutResponseMessage)); + if (GNUNET_OK == res) + rpr_msg.op_result = htons (GNUNET_OK); + else + rpr_msg.op_result = htons (GNUNET_NO); + GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rpr_msg, GNUNET_NO); + + GNUNET_SERVER_receive_done (client, GNUNET_OK); +} + + +static void handle_record_create (void *cls, + struct GNUNET_SERVER_Client * client, + const struct GNUNET_MessageHeader * message) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_CREATE"); + struct GNUNET_NAMESTORE_Client *nc; + struct RecordCreateResponseMessage rcr_msg; + size_t name_len; + size_t msg_size; + size_t msg_size_exp; + uint32_t id = 0; + + int res = GNUNET_SYSERR; + + if (ntohs (message->size) < sizeof (struct RecordCreateMessage)) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + nc = client_lookup(client); + if (nc == NULL) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + struct RecordCreateMessage * rp_msg = (struct RecordCreateMessage *) message; + id = ntohl (rp_msg->op_id); + name_len = ntohs (rp_msg->name_len); + msg_size = ntohs (message->size); + msg_size_exp = sizeof (struct RecordCreateMessage) + name_len + sizeof (struct GNUNET_NAMESTORE_RecordData); + + if (msg_size != msg_size_exp) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size); + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + + if ((name_len == 0) || (name_len > 256)) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + /* DO WORK HERE */ + + /* Send response */ + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_CREATE_RESPONSE"); + rcr_msg.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE); + rcr_msg.op_id = rp_msg->op_id; + rcr_msg.header.size = htons (sizeof (struct RecordCreateResponseMessage)); + if (GNUNET_OK == res) + rcr_msg.op_result = htons (GNUNET_OK); + else + rcr_msg.op_result = htons (GNUNET_NO); + GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rcr_msg, GNUNET_NO); + + GNUNET_SERVER_receive_done (client, GNUNET_OK); +} + +static void handle_record_remove (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 GNUNET_NAMESTORE_Client *nc; + struct RecordRemoveResponseMessage rrr_msg; + size_t name_len; + size_t msg_size; + size_t msg_size_exp; + uint32_t id = 0; + + int res = GNUNET_SYSERR; + + if (ntohs (message->size) < sizeof (struct RecordRemoveMessage)) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + nc = client_lookup(client); + if (nc == NULL) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + struct RecordRemoveMessage * rp_msg = (struct RecordRemoveMessage *) message; + id = ntohl (rp_msg->op_id); + name_len = ntohs (rp_msg->name_len); + msg_size = ntohs (message->size); + msg_size_exp = sizeof (struct RecordRemoveMessage) + name_len + sizeof (struct GNUNET_NAMESTORE_RecordData); + + if (msg_size != msg_size_exp) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size); + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + + if ((name_len == 0) || (name_len > 256)) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + /* DO WORK HERE */ + + /* Send response */ + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_REMOVE_RESPONSE"); + rrr_msg.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE); + rrr_msg.op_id = rp_msg->op_id; + rrr_msg.header.size = htons (sizeof (struct RecordRemoveResponseMessage)); + if (GNUNET_OK == res) + rrr_msg.op_result = htons (GNUNET_OK); + else + rrr_msg.op_result = htons (GNUNET_NO); + GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rrr_msg, GNUNET_NO); + + GNUNET_SERVER_receive_done (client, GNUNET_OK); +} + +struct ZoneIterationProcResult +{ + int have_zone_key; + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded zone_key; + + int have_signature; + struct GNUNET_CRYPTO_RsaSignature signature; + struct GNUNET_TIME_Absolute expire; + + int have_name; + char name[256]; + + unsigned int rd_count; + char *rd_ser; +}; + + +void zone_iteration_proc (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, + struct GNUNET_TIME_Absolute expire, + const char *name, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + struct ZoneIterationProcResult *zipr = cls; + size_t len; + if (zone_key != NULL) + { + zipr->zone_key = *zone_key; + zipr->have_zone_key = GNUNET_YES; + } + else + zipr->have_zone_key = GNUNET_NO; + + zipr->expire = expire; + + if (name != NULL) + { + memcpy (zipr->name, name, strlen(name) + 1); + zipr->have_name = GNUNET_YES; + } + else + zipr->have_name = GNUNET_NO; + + zipr->rd_count = rd_count; + + if (signature != NULL) + { + zipr->signature = *signature; + zipr->have_signature = GNUNET_YES; + } + else + zipr->have_signature = GNUNET_NO; + + if ((rd_count > 0) && (rd != NULL)) + { + len = GNUNET_NAMESTORE_records_serialize (&zipr->rd_ser, rd_count, rd); + } +} + +static void handle_iteration_start (void *cls, + struct GNUNET_SERVER_Client * client, + const struct GNUNET_MessageHeader * message) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_START"); + + struct ZoneIterationStartMessage * zis_msg = (struct ZoneIterationStartMessage *) message; + struct GNUNET_NAMESTORE_Client *nc; + struct GNUNET_NAMESTORE_ZoneIteration *zi; + struct ZoneIterationResponseMessage zir_msg; + struct ZoneIterationProcResult zipr; + int res; + + nc = client_lookup(client); + if (nc == NULL) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + zi = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIteration)); + zi->op_id = ntohl (zis_msg->op_id); + zi->offset = 0; + zi->client = nc; + zi->zone = zis_msg->zone; + + GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi); + + res = GSN_database->iterate_records (GSN_database->cls, &zis_msg->zone, NULL, zi->offset , &zone_iteration_proc, &zipr); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "ZONE_ITERATION_RESPONSE"); + zir_msg.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE); + zir_msg.op_id = htonl(zi->op_id); + zir_msg.header.size = htons (sizeof (struct ZoneIterationResponseMessage)); + + GNUNET_SERVER_notification_context_unicast (snc, zi->client->client, (const struct GNUNET_MessageHeader *) &zir_msg, GNUNET_NO); + + + GNUNET_SERVER_receive_done (client, GNUNET_OK); +} + +static void handle_iteration_stop (void *cls, + struct GNUNET_SERVER_Client * client, + const struct GNUNET_MessageHeader * message) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_STOP"); + + struct GNUNET_NAMESTORE_Client *nc; + struct GNUNET_NAMESTORE_ZoneIteration *zi; + struct ZoneIterationStopMessage * zis_msg = (struct ZoneIterationStopMessage *) message; + uint32_t id; + + nc = client_lookup(client); + if (nc == NULL) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + id = ntohl (zis_msg->op_id); + for (zi = nc->op_head; zi != NULL; zi = zi->next) + { + if (zi->op_id == id) + break; + } + if (zi == NULL) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + GNUNET_CONTAINER_DLL_remove(nc->op_head, nc->op_tail, zi); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopped zone iteration for zone `%s'\n", GNUNET_h2s (&zi->zone)); + GNUNET_free (zi); + + GNUNET_SERVER_receive_done (client, GNUNET_OK); +} + +static void handle_iteration_next (void *cls, + struct GNUNET_SERVER_Client * client, + const struct GNUNET_MessageHeader * message) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_NEXT"); + + struct GNUNET_NAMESTORE_Client *nc; + struct GNUNET_NAMESTORE_ZoneIteration *zi; + struct ZoneIterationStopMessage * zis_msg = (struct ZoneIterationStopMessage *) message; + uint32_t id; + int res; + + nc = client_lookup(client); + if (nc == NULL) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + id = ntohl (zis_msg->op_id); + for (zi = nc->op_head; zi != NULL; zi = zi->next) + { + if (zi->op_id == id) + break; + } + if (zi == NULL) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + zi->offset++; + res = GSN_database->iterate_records (GSN_database->cls, &zi->zone, NULL, zi->offset , &zone_iteration_proc, zi); +} + + + +/** + * Process template requests. + * + * @param cls closure + * @param server the initialized server + * @param cfg configuration to use + */ +static void +run (void *cls, struct GNUNET_SERVER_Handle *server, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + char * database; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n"); + + static const struct GNUNET_SERVER_MessageHandler handlers[] = { + {&handle_start, NULL, + GNUNET_MESSAGE_TYPE_NAMESTORE_START, sizeof (struct StartMessage)}, + {&handle_lookup_name, NULL, + GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME, 0}, + {&handle_record_put, NULL, + GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT, 0}, + {&handle_record_create, NULL, + GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE, 0}, + {&handle_record_remove, NULL, + GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE, 0}, + {&handle_iteration_start, NULL, + GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START, sizeof (struct ZoneIterationStartMessage)}, + {&handle_iteration_stop, NULL, + GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP, sizeof (struct ZoneIterationStopMessage)}, + {&handle_iteration_next, NULL, + GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT, 0}, + {NULL, NULL, 0, 0} + }; + + GSN_cfg = cfg; + + /* Loading database plugin */ + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, "namestore", "database", + &database)) + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n"); + + GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database); + GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg); + if (GSN_database == NULL) + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load database backend `%s'\n", + db_lib_name); + GNUNET_free (database); + + /* Configuring server handles */ + GNUNET_SERVER_add_handlers (server, handlers); + snc = GNUNET_SERVER_notification_context_create (server, 16); + GNUNET_SERVER_disconnect_notify (server, + &client_disconnect_notification, + NULL); + + GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task, + NULL); + +} + + +/** + * The main function for the template service. + * + * @param argc number of arguments from the command line + * @param argv command line arguments + * @return 0 ok, 1 on error + */ +int +main (int argc, char *const *argv) +{ + return (GNUNET_OK == + GNUNET_SERVICE_run (argc, argv, "namestore", + GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; +} + +/* end of gnunet-service-namestore.c */ |