diff options
author | Sree Harsha Totakura <totakura@in.tum.de> | 2013-04-21 20:01:34 +0000 |
---|---|---|
committer | Sree Harsha Totakura <totakura@in.tum.de> | 2013-04-21 20:01:34 +0000 |
commit | da683835112d7510461269a81363dcaf23af4b9b (patch) | |
tree | 5c4e530a304c315f132a18e0f9d938d04b9e94de /src/testbed/gnunet-service-testbed.c | |
parent | e823f8b9a57844dc90afed91076117eea7cb85ea (diff) | |
download | gnunet-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.c | 209 |
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 | */ |
128 | static struct MessageQueue *mq_tail; | 128 | static struct MessageQueue *mq_tail; |
129 | 129 | ||
130 | /** | ||
131 | * The hashmap of shared services | ||
132 | */ | ||
133 | static 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 | */ | ||
243 | static void | ||
244 | route_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 | */ | ||
434 | static struct GNUNET_TESTING_SharedService * | ||
435 | parse_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 | */ | ||
626 | int | ||
627 | ss_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 | */ | ||
646 | static void | ||
647 | handle_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 | */ | ||
814 | static int | ||
815 | ss_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, |