aboutsummaryrefslogtreecommitdiff
path: root/src/testbed/gnunet-service-testbed.c
diff options
context:
space:
mode:
authorSree Harsha Totakura <totakura@in.tum.de>2013-04-21 20:01:34 +0000
committerSree Harsha Totakura <totakura@in.tum.de>2013-04-21 20:01:34 +0000
commitda683835112d7510461269a81363dcaf23af4b9b (patch)
tree5c4e530a304c315f132a18e0f9d938d04b9e94de /src/testbed/gnunet-service-testbed.c
parente823f8b9a57844dc90afed91076117eea7cb85ea (diff)
downloadgnunet-da683835112d7510461269a81363dcaf23af4b9b.tar.gz
gnunet-da683835112d7510461269a81363dcaf23af4b9b.zip
fix #2666: Implement service sharing among peers
Diffstat (limited to 'src/testbed/gnunet-service-testbed.c')
-rw-r--r--src/testbed/gnunet-service-testbed.c209
1 files changed, 75 insertions, 134 deletions
diff --git a/src/testbed/gnunet-service-testbed.c b/src/testbed/gnunet-service-testbed.c
index d9a2a6c13..6bca3d9cd 100644
--- a/src/testbed/gnunet-service-testbed.c
+++ b/src/testbed/gnunet-service-testbed.c
@@ -127,10 +127,6 @@ static struct MessageQueue *mq_head;
127 */ 127 */
128static struct MessageQueue *mq_tail; 128static struct MessageQueue *mq_tail;
129 129
130/**
131 * The hashmap of shared services
132 */
133static struct GNUNET_CONTAINER_MultiHashMap *ss_map;
134 130
135/** 131/**
136 * The shutdown task handle 132 * The shutdown task handle
@@ -235,19 +231,6 @@ host_list_add (struct GNUNET_TESTBED_Host *host)
235 231
236 232
237/** 233/**
238 * Routes message to a host given its host_id
239 *
240 * @param host_id the id of the destination host
241 * @param msg the message to be routed
242 */
243static void
244route_message (uint32_t host_id, const struct GNUNET_MessageHeader *msg)
245{
246 GNUNET_break (0);
247}
248
249
250/**
251 * Send operation failure message to client 234 * Send operation failure message to client
252 * 235 *
253 * @param client the client to which the failure message has to be sent to 236 * @param client the client to which the failure message has to be sent to
@@ -440,6 +423,57 @@ GST_forwarded_operation_timeout (void *cls,
440 423
441 424
442/** 425/**
426 * Parse service sharing specification line.
427 * Format is "[<service:share>] [<service:share>] ..."
428 *
429 * @param ss_str the spec string to be parsed
430 * @param cfg the configuration to use for shared services
431 * @return an array suitable to pass to GNUNET_TESTING_system_create(). NULL
432 * upon empty service sharing specification.
433 */
434static struct GNUNET_TESTING_SharedService *
435parse_shared_services (char *ss_str, struct GNUNET_CONFIGURATION_Handle *cfg)
436{
437 struct GNUNET_TESTING_SharedService ss;
438 struct GNUNET_TESTING_SharedService *slist;
439 char service[256];
440 char *arg;
441 unsigned int n;
442#define GROW_SS \
443 do { \
444 GNUNET_array_grow (slist, n, n+1); \
445 (void) memcpy (&slist[n - 1], &ss, \
446 sizeof (struct GNUNET_TESTING_SharedService)); \
447 } while (0)
448
449 slist = NULL;
450 n = 0;
451 ss.cfg = cfg;
452 for (; NULL != (arg = strtok (ss_str, " ")); ss_str = NULL)
453 {
454 ss.service = NULL;
455 ss.share = 0;
456 if (2 != sscanf (arg, "%255s:%u", service, &ss.share))
457 {
458 LOG (GNUNET_ERROR_TYPE_WARNING, "Ignoring shared service spec: %s", arg);
459 continue;
460 }
461 LOG_DEBUG ("Will be sharing %s service among %u peers\n", service, ss.share);
462 ss.service = GNUNET_strdup (service);
463 GROW_SS;
464 }
465 if (NULL != slist)
466 {
467 /* Add trailing NULL block */
468 (void) memset (&ss, 0, sizeof (struct GNUNET_TESTING_SharedService));
469 GROW_SS;
470 }
471 return slist;
472#undef GROW_SS
473}
474
475
476/**
443 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_INIT messages 477 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_INIT messages
444 * 478 *
445 * @param cls NULL 479 * @param cls NULL
@@ -453,6 +487,9 @@ handle_init (void *cls, struct GNUNET_SERVER_Client *client,
453 const struct GNUNET_TESTBED_InitMessage *msg; 487 const struct GNUNET_TESTBED_InitMessage *msg;
454 struct GNUNET_TESTBED_Host *host; 488 struct GNUNET_TESTBED_Host *host;
455 const char *controller_hostname; 489 const char *controller_hostname;
490 char *ss_str;
491 struct GNUNET_TESTING_SharedService *ss;
492 unsigned int cnt;
456 uint16_t msize; 493 uint16_t msize;
457 494
458 if (NULL != GST_context) 495 if (NULL != GST_context)
@@ -477,6 +514,16 @@ handle_init (void *cls, struct GNUNET_SERVER_Client *client,
477 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 514 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
478 return; 515 return;
479 } 516 }
517 ss_str = NULL;
518 ss = NULL;
519 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (our_config, "TESTBED",
520 "SHARED_SERVICES",
521 &ss_str))
522 {
523 ss = parse_shared_services (ss_str, our_config);
524 GNUNET_free (ss_str);
525 ss_str = NULL;
526 }
480 GST_context = GNUNET_malloc (sizeof (struct Context)); 527 GST_context = GNUNET_malloc (sizeof (struct Context));
481 GNUNET_SERVER_client_keep (client); 528 GNUNET_SERVER_client_keep (client);
482 GST_context->client = client; 529 GST_context->client = client;
@@ -485,7 +532,17 @@ handle_init (void *cls, struct GNUNET_SERVER_Client *client,
485 LOG_DEBUG ("Our IP: %s\n", GST_context->master_ip); 532 LOG_DEBUG ("Our IP: %s\n", GST_context->master_ip);
486 GST_context->system = 533 GST_context->system =
487 GNUNET_TESTING_system_create ("testbed", GST_context->master_ip, 534 GNUNET_TESTING_system_create ("testbed", GST_context->master_ip,
488 hostname, NULL); 535 hostname, ss);
536 if (NULL != ss)
537 {
538 for (cnt = 0; NULL != ss[cnt].service; cnt++)
539 {
540 ss_str = (char *) ss[cnt].service;
541 GNUNET_free (ss_str);
542 }
543 GNUNET_free (ss);
544 ss = NULL;
545 }
489 host = 546 host =
490 GNUNET_TESTBED_host_create_with_id (GST_context->host_id, 547 GNUNET_TESTBED_host_create_with_id (GST_context->host_id,
491 GST_context->master_ip, NULL, 548 GST_context->master_ip, NULL,
@@ -614,93 +671,6 @@ handle_add_host (void *cls, struct GNUNET_SERVER_Client *client,
614 671
615 672
616/** 673/**
617 * Iterator over hash map entries.
618 *
619 * @param cls closure
620 * @param key current key code
621 * @param value value in the hash map
622 * @return GNUNET_YES if we should continue to
623 * iterate,
624 * GNUNET_NO if not.
625 */
626int
627ss_exists_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
628{
629 struct SharedService *queried_ss = cls;
630 struct SharedService *ss = value;
631
632 if (0 == strcmp (ss->name, queried_ss->name))
633 return GNUNET_NO;
634 else
635 return GNUNET_YES;
636}
637
638
639/**
640 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
641 *
642 * @param cls NULL
643 * @param client identification of the client
644 * @param message the actual message
645 */
646static void
647handle_configure_shared_service (void *cls, struct GNUNET_SERVER_Client *client,
648 const struct GNUNET_MessageHeader *message)
649{
650 const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg;
651 struct SharedService *ss;
652 char *service_name;
653 struct GNUNET_HashCode hash;
654 uint16_t msg_size;
655 uint16_t service_name_size;
656
657 msg = (const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *) message;
658 msg_size = ntohs (message->size);
659 if (msg_size <= sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage))
660 {
661 GNUNET_break (0);
662 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
663 return;
664 }
665 service_name_size =
666 msg_size - sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage);
667 service_name = (char *) &msg[1];
668 if ('\0' != service_name[service_name_size - 1])
669 {
670 GNUNET_break (0);
671 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
672 return;
673 }
674 LOG_DEBUG ("Received service sharing request for %s, with %d peers\n",
675 service_name, ntohl (msg->num_peers));
676 if (ntohl (msg->host_id) != GST_context->host_id)
677 {
678 route_message (ntohl (msg->host_id), message);
679 GNUNET_SERVER_receive_done (client, GNUNET_OK);
680 return;
681 }
682 GNUNET_SERVER_receive_done (client, GNUNET_OK);
683 ss = GNUNET_malloc (sizeof (struct SharedService));
684 ss->name = strdup (service_name);
685 ss->num_shared = ntohl (msg->num_peers);
686 GNUNET_CRYPTO_hash (ss->name, service_name_size, &hash);
687 if (GNUNET_SYSERR ==
688 GNUNET_CONTAINER_multihashmap_get_multiple (ss_map, &hash,
689 &ss_exists_iterator, ss))
690 {
691 LOG (GNUNET_ERROR_TYPE_WARNING,
692 "Service %s already configured as a shared service. "
693 "Ignoring service sharing request \n", ss->name);
694 GNUNET_free (ss->name);
695 GNUNET_free (ss);
696 return;
697 }
698 GNUNET_CONTAINER_multihashmap_put (ss_map, &hash, ss,
699 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
700}
701
702
703/**
704 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG messages 674 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG messages
705 * 675 *
706 * @param cls NULL 676 * @param cls NULL
@@ -802,29 +772,6 @@ GST_clear_fopcq ()
802 772
803 773
804/** 774/**
805 * Iterator over hash map entries.
806 *
807 * @param cls closure
808 * @param key current key code
809 * @param value value in the hash map
810 * @return GNUNET_YES if we should continue to
811 * iterate,
812 * GNUNET_NO if not.
813 */
814static int
815ss_map_free_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
816{
817 struct SharedService *ss = value;
818
819 GNUNET_assert (GNUNET_YES ==
820 GNUNET_CONTAINER_multihashmap_remove (ss_map, key, value));
821 GNUNET_free (ss->name);
822 GNUNET_free (ss);
823 return GNUNET_YES;
824}
825
826
827/**
828 * Task to clean up and shutdown nicely 775 * Task to clean up and shutdown nicely
829 * 776 *
830 * @param cls NULL 777 * @param cls NULL
@@ -838,9 +785,6 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
838 785
839 shutdown_task_id = GNUNET_SCHEDULER_NO_TASK; 786 shutdown_task_id = GNUNET_SCHEDULER_NO_TASK;
840 LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down testbed service\n"); 787 LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down testbed service\n");
841 (void) GNUNET_CONTAINER_multihashmap_iterate (ss_map, &ss_map_free_iterator,
842 NULL);
843 GNUNET_CONTAINER_multihashmap_destroy (ss_map);
844 /* cleanup any remaining forwarded operations */ 788 /* cleanup any remaining forwarded operations */
845 GST_clear_fopcq (); 789 GST_clear_fopcq ();
846 GST_free_lcfq (); 790 GST_free_lcfq ();
@@ -926,8 +870,6 @@ testbed_run (void *cls, struct GNUNET_SERVER_Handle *server,
926 static const struct GNUNET_SERVER_MessageHandler message_handlers[] = { 870 static const struct GNUNET_SERVER_MessageHandler message_handlers[] = {
927 {&handle_init, NULL, GNUNET_MESSAGE_TYPE_TESTBED_INIT, 0}, 871 {&handle_init, NULL, GNUNET_MESSAGE_TYPE_TESTBED_INIT, 0},
928 {&handle_add_host, NULL, GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST, 0}, 872 {&handle_add_host, NULL, GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST, 0},
929 {&handle_configure_shared_service, NULL,
930 GNUNET_MESSAGE_TYPE_TESTBED_SHARE_SERVICE, 0},
931 {&GST_handle_link_controllers, NULL, 873 {&GST_handle_link_controllers, NULL,
932 GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS, 874 GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS,
933 sizeof (struct GNUNET_TESTBED_ControllerLinkRequest)}, 875 sizeof (struct GNUNET_TESTBED_ControllerLinkRequest)},
@@ -985,7 +927,6 @@ testbed_run (void *cls, struct GNUNET_SERVER_Handle *server,
985 our_config = GNUNET_CONFIGURATION_dup (cfg); 927 our_config = GNUNET_CONFIGURATION_dup (cfg);
986 GNUNET_SERVER_add_handlers (server, message_handlers); 928 GNUNET_SERVER_add_handlers (server, message_handlers);
987 GNUNET_SERVER_disconnect_notify (server, &client_disconnect_cb, NULL); 929 GNUNET_SERVER_disconnect_notify (server, &client_disconnect_cb, NULL);
988 ss_map = GNUNET_CONTAINER_multihashmap_create (5, GNUNET_NO);
989 shutdown_task_id = 930 shutdown_task_id =
990 GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_UNIT_FOREVER_REL, 931 GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_UNIT_FOREVER_REL,
991 GNUNET_SCHEDULER_PRIORITY_IDLE, 932 GNUNET_SCHEDULER_PRIORITY_IDLE,