summaryrefslogtreecommitdiff
path: root/src/namestore/gnunet-service-namestore.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/namestore/gnunet-service-namestore.c')
-rw-r--r--src/namestore/gnunet-service-namestore.c358
1 files changed, 154 insertions, 204 deletions
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c
index 869be75d5..40a7ac790 100644
--- a/src/namestore/gnunet-service-namestore.c
+++ b/src/namestore/gnunet-service-namestore.c
@@ -27,6 +27,7 @@
27#include "platform.h" 27#include "platform.h"
28#include "gnunet_util_lib.h" 28#include "gnunet_util_lib.h"
29#include "gnunet_dnsparser_lib.h" 29#include "gnunet_dnsparser_lib.h"
30#include "gnunet_namecache_service.h"
30#include "gnunet_namestore_service.h" 31#include "gnunet_namestore_service.h"
31#include "gnunet_namestore_plugin.h" 32#include "gnunet_namestore_plugin.h"
32#include "gnunet_signatures.h" 33#include "gnunet_signatures.h"
@@ -165,11 +166,49 @@ struct ZoneMonitor
165 166
166 167
167/** 168/**
169 * Pending operation on the namecache.
170 */
171struct CacheOperation
172{
173
174 /**
175 * Kept in a DLL.
176 */
177 struct CacheOperation *prev;
178
179 /**
180 * Kept in a DLL.
181 */
182 struct CacheOperation *next;
183
184 /**
185 * Handle to namecache queue.
186 */
187 struct GNUNET_NAMECACHE_QueueEntry *qe;
188
189 /**
190 * Client to notify about the result.
191 */
192 struct GNUNET_SERVER_Client *client;
193
194 /**
195 * Client's request ID.
196 */
197 uint32_t rid;
198};
199
200
201/**
168 * Configuration handle. 202 * Configuration handle.
169 */ 203 */
170static const struct GNUNET_CONFIGURATION_Handle *GSN_cfg; 204static const struct GNUNET_CONFIGURATION_Handle *GSN_cfg;
171 205
172/** 206/**
207 * Namecache handle.
208 */
209static struct GNUNET_NAMECACHE_Handle *namecache;
210
211/**
173 * Database handle 212 * Database handle
174 */ 213 */
175static struct GNUNET_NAMESTORE_PluginFunctions *GSN_database; 214static struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
@@ -195,6 +234,16 @@ static struct NamestoreClient *client_head;
195static struct NamestoreClient *client_tail; 234static struct NamestoreClient *client_tail;
196 235
197/** 236/**
237 * Head of cop DLL.
238 */
239static struct CacheOperation *cop_head;
240
241/**
242 * Tail of cop DLL.
243 */
244static struct CacheOperation *cop_tail;
245
246/**
198 * First active zone monitor. 247 * First active zone monitor.
199 */ 248 */
200static struct ZoneMonitor *monitor_head; 249static struct ZoneMonitor *monitor_head;
@@ -222,6 +271,7 @@ cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
222{ 271{
223 struct ZoneIteration *no; 272 struct ZoneIteration *no;
224 struct NamestoreClient *nc; 273 struct NamestoreClient *nc;
274 struct CacheOperation *cop;
225 275
226 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 276 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
227 "Stopping namestore service\n"); 277 "Stopping namestore service\n");
@@ -230,6 +280,16 @@ cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
230 GNUNET_SERVER_notification_context_destroy (snc); 280 GNUNET_SERVER_notification_context_destroy (snc);
231 snc = NULL; 281 snc = NULL;
232 } 282 }
283 while (NULL != (cop = cop_head))
284 {
285 GNUNET_NAMECACHE_cancel (cop->qe);
286 GNUNET_CONTAINER_DLL_remove (cop_head,
287 cop_tail,
288 cop);
289 GNUNET_free (cop);
290 }
291 GNUNET_NAMECACHE_disconnect (namecache);
292 namecache = NULL;
233 while (NULL != (nc = client_head)) 293 while (NULL != (nc = client_head))
234 { 294 {
235 while (NULL != (no = nc->op_head)) 295 while (NULL != (no = nc->op_head))
@@ -266,6 +326,7 @@ client_disconnect_notification (void *cls,
266 struct ZoneIteration *no; 326 struct ZoneIteration *no;
267 struct NamestoreClient *nc; 327 struct NamestoreClient *nc;
268 struct ZoneMonitor *zm; 328 struct ZoneMonitor *zm;
329 struct CacheOperation *cop;
269 330
270 if (NULL == client) 331 if (NULL == client)
271 return; 332 return;
@@ -297,6 +358,9 @@ client_disconnect_notification (void *cls,
297 break; 358 break;
298 } 359 }
299 } 360 }
361 for (cop = cop_head; NULL != cop; cop = cop->next)
362 if (client == cop->client)
363 cop->client = NULL;
300} 364}
301 365
302 366
@@ -328,175 +392,6 @@ client_lookup (struct GNUNET_SERVER_Client *client)
328 392
329 393
330/** 394/**
331 * Context for name lookups passed from #handle_lookup_block to
332 * #handle_lookup_block_it as closure
333 */
334struct LookupBlockContext
335{
336 /**
337 * The client to send the response to
338 */
339 struct NamestoreClient *nc;
340
341 /**
342 * Operation id for the name lookup
343 */
344 uint32_t request_id;
345
346};
347
348
349/**
350 * A #GNUNET_GNSRECORD_BlockCallback for name lookups in #handle_lookup_block
351 *
352 * @param cls a `struct LookupNameContext *` with information about the request
353 * @param block the block
354 */
355static void
356handle_lookup_block_it (void *cls,
357 const struct GNUNET_GNSRECORD_Block *block)
358{
359 struct LookupBlockContext *lnc = cls;
360 struct LookupBlockResponseMessage *r;
361 size_t esize;
362
363 esize = ntohl (block->purpose.size)
364 - sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose)
365 - sizeof (struct GNUNET_TIME_AbsoluteNBO);
366 r = GNUNET_malloc (sizeof (struct LookupBlockResponseMessage) + esize);
367 r->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_BLOCK_RESPONSE);
368 r->gns_header.header.size = htons (sizeof (struct LookupBlockResponseMessage) + esize);
369 r->gns_header.r_id = htonl (lnc->request_id);
370 r->expire = block->expiration_time;
371 r->signature = block->signature;
372 r->derived_key = block->derived_key;
373 memcpy (&r[1], &block[1], esize);
374 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
375 "Sending `%s' message with expiration time %s\n",
376 "NAMESTORE_LOOKUP_BLOCK_RESPONSE",
377 GNUNET_STRINGS_absolute_time_to_string (GNUNET_TIME_absolute_ntoh (r->expire)));
378 GNUNET_SERVER_notification_context_unicast (snc,
379 lnc->nc->client,
380 &r->gns_header.header,
381 GNUNET_NO);
382 GNUNET_free (r);
383}
384
385
386/**
387 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_BLOCK message
388 *
389 * @param cls unused
390 * @param client client sending the message
391 * @param message message of type 'struct LookupNameMessage'
392 */
393static void
394handle_lookup_block (void *cls,
395 struct GNUNET_SERVER_Client *client,
396 const struct GNUNET_MessageHeader *message)
397{
398 const struct LookupBlockMessage *ln_msg;
399 struct LookupBlockContext lnc;
400 struct NamestoreClient *nc;
401 struct LookupBlockResponseMessage zir_end;
402 int ret;
403
404 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
405 "Received `%s' message\n",
406 "NAMESTORE_LOOKUP_BLOCK");
407 nc = client_lookup(client);
408 ln_msg = (const struct LookupBlockMessage *) message;
409 lnc.request_id = ntohl (ln_msg->gns_header.r_id);
410 lnc.nc = nc;
411 if (GNUNET_SYSERR ==
412 (ret = GSN_database->lookup_block (GSN_database->cls,
413 &ln_msg->query,
414 &handle_lookup_block_it, &lnc)))
415 {
416 /* internal error (in database plugin); might be best to just hang up on
417 plugin rather than to signal that there are 'no' results, which
418 might also be false... */
419 GNUNET_break (0);
420 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
421 return;
422 }
423 if (0 == ret)
424 {
425 /* no records match at all, generate empty response */
426 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
427 "Sending empty `%s' message\n",
428 "NAMESTORE_LOOKUP_BLOCK_RESPONSE");
429 memset (&zir_end, 0, sizeof (zir_end));
430 zir_end.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_BLOCK_RESPONSE);
431 zir_end.gns_header.header.size = htons (sizeof (struct LookupBlockResponseMessage));
432 zir_end.gns_header.r_id = ln_msg->gns_header.r_id;
433 GNUNET_SERVER_notification_context_unicast (snc,
434 client,
435 &zir_end.gns_header.header,
436 GNUNET_NO);
437
438 }
439 GNUNET_SERVER_receive_done (client, GNUNET_OK);
440}
441
442
443/**
444 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_BLOCK_CACHE message
445 *
446 * @param cls unused
447 * @param client client sending the message
448 * @param message message of type 'struct BlockCacheMessage'
449 */
450static void
451handle_block_cache (void *cls,
452 struct GNUNET_SERVER_Client *client,
453 const struct GNUNET_MessageHeader *message)
454{
455 struct NamestoreClient *nc;
456 const struct BlockCacheMessage *rp_msg;
457 struct BlockCacheResponseMessage rpr_msg;
458 struct GNUNET_GNSRECORD_Block *block;
459 size_t esize;
460 int res;
461
462 nc = client_lookup (client);
463 if (ntohs (message->size) < sizeof (struct BlockCacheMessage))
464 {
465 GNUNET_break (0);
466 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
467 return;
468 }
469 rp_msg = (const struct BlockCacheMessage *) message;
470 esize = ntohs (rp_msg->gns_header.header.size) - sizeof (struct BlockCacheMessage);
471 block = GNUNET_malloc (sizeof (struct GNUNET_GNSRECORD_Block) + esize);
472 block->signature = rp_msg->signature;
473 block->derived_key = rp_msg->derived_key;
474 block->purpose.size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
475 sizeof (struct GNUNET_TIME_AbsoluteNBO) +
476 esize);
477 block->expiration_time = rp_msg->expire;
478 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
479 "Received `%s' message with expiration time %s\n",
480 "NAMESTORE_BLOCK_CACHE",
481 GNUNET_STRINGS_absolute_time_to_string (GNUNET_TIME_absolute_ntoh (block->expiration_time)));
482 memcpy (&block[1], &rp_msg[1], esize);
483 res = GSN_database->cache_block (GSN_database->cls,
484 block);
485 GNUNET_free (block);
486
487 rpr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_BLOCK_CACHE_RESPONSE);
488 rpr_msg.gns_header.header.size = htons (sizeof (struct BlockCacheResponseMessage));
489 rpr_msg.gns_header.r_id = rp_msg->gns_header.r_id;
490 rpr_msg.op_result = htonl (res);
491 GNUNET_SERVER_notification_context_unicast (snc,
492 nc->client,
493 &rpr_msg.gns_header.header,
494 GNUNET_NO);
495 GNUNET_SERVER_receive_done (client, GNUNET_OK);
496}
497
498
499/**
500 * Generate a 'struct LookupNameResponseMessage' and send it to the 395 * Generate a 'struct LookupNameResponseMessage' and send it to the
501 * given client using the given notification context. 396 * given client using the given notification context.
502 * 397 *
@@ -554,21 +449,84 @@ send_lookup_response (struct GNUNET_SERVER_NotificationContext *nc,
554 449
555 450
556/** 451/**
452 * Send response to the store request to the client.
453 *
454 * @param client client to talk to
455 * @param res status of the operation
456 * @param rid client's request ID
457 */
458static void
459send_store_response (struct GNUNET_SERVER_Client *client,
460 int res,
461 uint32_t rid)
462{
463 struct RecordStoreResponseMessage rcr_msg;
464
465 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
466 "Sending `%s' message\n",
467 "RECORD_STORE_RESPONSE");
468 rcr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE);
469 rcr_msg.gns_header.header.size = htons (sizeof (struct RecordStoreResponseMessage));
470 rcr_msg.gns_header.r_id = htonl (rid);
471 rcr_msg.op_result = htonl (res);
472 GNUNET_SERVER_notification_context_unicast (snc, client,
473 &rcr_msg.gns_header.header,
474 GNUNET_NO);
475
476}
477
478
479/**
480 * Cache operation complete, clean up.
481 *
482 * @param cls the `struct CacheOperation`
483 */
484static void
485finish_cache_operation (void *cls,
486 int32_t success,
487 const char *emsg)
488{
489 struct CacheOperation *cop = cls;
490
491 if (NULL != emsg)
492 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
493 _("Failed to replicate block in namecache: %s\n"),
494 emsg);
495 else
496 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
497 "CACHE operation completed\n");
498 GNUNET_CONTAINER_DLL_remove (cop_head,
499 cop_tail,
500 cop);
501 if (NULL != cop->client)
502 send_store_response (cop->client,
503 success,
504 cop->rid);
505 GNUNET_free (cop);
506}
507
508
509/**
557 * We just touched the plaintext information about a name in our zone; 510 * We just touched the plaintext information about a name in our zone;
558 * refresh the corresponding (encrypted) block in the namestore. 511 * refresh the corresponding (encrypted) block in the namestore.
559 * 512 *
513 * @param client client responsible for the request
514 * @param rid request ID of the client
560 * @param zone_key private key of the zone 515 * @param zone_key private key of the zone
561 * @param name label for the records 516 * @param name label for the records
562 * @param rd_count number of records 517 * @param rd_count number of records
563 * @param rd records stored under the given @a name 518 * @param rd records stored under the given @a name
564 */ 519 */
565static void 520static void
566refresh_block (const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, 521refresh_block (struct GNUNET_SERVER_Client *client,
522 uint32_t rid,
523 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
567 const char *name, 524 const char *name,
568 unsigned int rd_count, 525 unsigned int rd_count,
569 const struct GNUNET_GNSRECORD_Data *rd) 526 const struct GNUNET_GNSRECORD_Data *rd)
570{ 527{
571 struct GNUNET_GNSRECORD_Block *block; 528 struct GNUNET_GNSRECORD_Block *block;
529 struct CacheOperation *cop;
572 530
573 if (0 == rd_count) 531 if (0 == rd_count)
574 block = GNUNET_GNSRECORD_block_create (zone_key, 532 block = GNUNET_GNSRECORD_block_create (zone_key,
@@ -581,13 +539,17 @@ refresh_block (const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
581 rd), 539 rd),
582 name, 540 name,
583 rd, rd_count); 541 rd, rd_count);
584 if (GNUNET_OK != 542
585 GSN_database->cache_block (GSN_database->cls, 543 cop = GNUNET_new (struct CacheOperation);
586 block)) 544 cop->client = client;
587 { 545 cop->rid = rid;
588 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 546 GNUNET_CONTAINER_DLL_insert (cop_head,
589 _("Failed to cache encrypted block of my own zone!\n")); 547 cop_tail,
590 } 548 cop);
549 cop->qe = GNUNET_NAMECACHE_block_cache (namecache,
550 block,
551 &finish_cache_operation,
552 cop);
591 GNUNET_free (block); 553 GNUNET_free (block);
592} 554}
593 555
@@ -601,12 +563,10 @@ refresh_block (const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
601 */ 563 */
602static void 564static void
603handle_record_store (void *cls, 565handle_record_store (void *cls,
604 struct GNUNET_SERVER_Client *client, 566 struct GNUNET_SERVER_Client *client,
605 const struct GNUNET_MessageHeader *message) 567 const struct GNUNET_MessageHeader *message)
606{ 568{
607 struct NamestoreClient *nc;
608 const struct RecordStoreMessage *rp_msg; 569 const struct RecordStoreMessage *rp_msg;
609 struct RecordStoreResponseMessage rcr_msg;
610 size_t name_len; 570 size_t name_len;
611 size_t msg_size; 571 size_t msg_size;
612 size_t msg_size_exp; 572 size_t msg_size_exp;
@@ -629,7 +589,6 @@ handle_record_store (void *cls,
629 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 589 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
630 return; 590 return;
631 } 591 }
632 nc = client_lookup (client);
633 rp_msg = (const struct RecordStoreMessage *) message; 592 rp_msg = (const struct RecordStoreMessage *) message;
634 rid = ntohl (rp_msg->gns_header.r_id); 593 rid = ntohl (rp_msg->gns_header.r_id);
635 name_len = ntohs (rp_msg->name_len); 594 name_len = ntohs (rp_msg->name_len);
@@ -705,10 +664,6 @@ handle_record_store (void *cls,
705 rd_count, rd); 664 rd_count, rd);
706 if (GNUNET_OK == res) 665 if (GNUNET_OK == res)
707 { 666 {
708 refresh_block (&rp_msg->private_key,
709 conv_name,
710 rd_count, rd);
711
712 for (zm = monitor_head; NULL != zm; zm = zm->next) 667 for (zm = monitor_head; NULL != zm; zm = zm->next)
713 if (0 == memcmp (&rp_msg->private_key, &zm->zone, 668 if (0 == memcmp (&rp_msg->private_key, &zm->zone,
714 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) 669 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
@@ -721,19 +676,17 @@ handle_record_store (void *cls,
721 } 676 }
722 GNUNET_free (conv_name); 677 GNUNET_free (conv_name);
723 } 678 }
679 if (GNUNET_OK == res)
680 {
681 refresh_block (client, rid,
682 &rp_msg->private_key,
683 conv_name,
684 rd_count, rd);
685 GNUNET_SERVER_receive_done (client, GNUNET_OK);
686 return;
687 }
724 } 688 }
725 689 send_store_response (client, res, rid);
726 /* Send response */
727 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
728 "Sending `%s' message\n",
729 "RECORD_STORE_RESPONSE");
730 rcr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE);
731 rcr_msg.gns_header.header.size = htons (sizeof (struct RecordStoreResponseMessage));
732 rcr_msg.gns_header.r_id = htonl (rid);
733 rcr_msg.op_result = htonl (res);
734 GNUNET_SERVER_notification_context_unicast (snc, nc->client,
735 &rcr_msg.gns_header.header,
736 GNUNET_NO);
737 GNUNET_SERVER_receive_done (client, GNUNET_OK); 690 GNUNET_SERVER_receive_done (client, GNUNET_OK);
738} 691}
739 692
@@ -976,7 +929,8 @@ zone_iteraterate_proc (void *cls,
976 break; 929 break;
977 } 930 }
978 if (GNUNET_YES == do_refresh_block) 931 if (GNUNET_YES == do_refresh_block)
979 refresh_block (zone_key, 932 refresh_block (NULL, 0,
933 zone_key,
980 name, 934 name,
981 rd_count, 935 rd_count,
982 rd); 936 rd);
@@ -1299,10 +1253,6 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
1299 const struct GNUNET_CONFIGURATION_Handle *cfg) 1253 const struct GNUNET_CONFIGURATION_Handle *cfg)
1300{ 1254{
1301 static const struct GNUNET_SERVER_MessageHandler handlers[] = { 1255 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
1302 {&handle_lookup_block, NULL,
1303 GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_BLOCK, sizeof (struct LookupBlockMessage)},
1304 {&handle_block_cache, NULL,
1305 GNUNET_MESSAGE_TYPE_NAMESTORE_BLOCK_CACHE, 0},
1306 {&handle_record_store, NULL, 1256 {&handle_record_store, NULL,
1307 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE, 0}, 1257 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE, 0},
1308 {&handle_zone_to_name, NULL, 1258 {&handle_zone_to_name, NULL,
@@ -1322,7 +1272,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
1322 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n"); 1272 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
1323 GSN_cfg = cfg; 1273 GSN_cfg = cfg;
1324 monitor_nc = GNUNET_SERVER_notification_context_create (server, 1); 1274 monitor_nc = GNUNET_SERVER_notification_context_create (server, 1);
1325 1275 namecache = GNUNET_NAMECACHE_connect (cfg);
1326 /* Loading database plugin */ 1276 /* Loading database plugin */
1327 if (GNUNET_OK != 1277 if (GNUNET_OK !=
1328 GNUNET_CONFIGURATION_get_value_string (cfg, "namestore", "database", 1278 GNUNET_CONFIGURATION_get_value_string (cfg, "namestore", "database",