summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-04-22 19:52:39 +0000
committerChristian Grothoff <christian@grothoff.org>2012-04-22 19:52:39 +0000
commite2bf225a32bb93731b574ad698f20acbb92a5803 (patch)
treedc151b39eb6bb96eaa03c447a92205e8c4254b58
parent9ba0af50e8f41d40163bbac21003261928084c48 (diff)
downloadgnunet-e2bf225a32bb93731b574ad698f20acbb92a5803.tar.gz
gnunet-e2bf225a32bb93731b574ad698f20acbb92a5803.zip
introducing soft shutdown concept for services; during soft shutdown, services that are still managing non-monitor clients continue to run until those clients disconnect; however, the services do stop to accept new connections (will stop listening); soft shutdown is now used by ats, transport, peerinfo, namestore and most importantly statistics; this should fix #2197
-rw-r--r--src/arm/gnunet-service-arm.c3
-rw-r--r--src/ats/gnunet-service-ats.c2
-rw-r--r--src/include/gnunet_server_lib.h26
-rw-r--r--src/include/gnunet_service_lib.h38
-rw-r--r--src/namestore/gnunet-service-namestore.c2
-rw-r--r--src/peerinfo/gnunet-service-peerinfo.c3
-rw-r--r--src/statistics/gnunet-service-statistics.c3
-rw-r--r--src/transport/gnunet-service-transport.c4
-rw-r--r--src/transport/gnunet-service-transport_blacklist.c20
-rw-r--r--src/transport/gnunet-service-transport_clients.c19
-rw-r--r--src/transport/plugin_transport_tcp.c2
-rw-r--r--src/util/server.c104
-rw-r--r--src/util/service.c119
13 files changed, 218 insertions, 127 deletions
diff --git a/src/arm/gnunet-service-arm.c b/src/arm/gnunet-service-arm.c
index 459171ffb..ab9e7f281 100644
--- a/src/arm/gnunet-service-arm.c
+++ b/src/arm/gnunet-service-arm.c
@@ -1301,7 +1301,8 @@ main (int argc, char *const *argv)
1301 GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death); 1301 GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death);
1302 ret = 1302 ret =
1303 (GNUNET_OK == 1303 (GNUNET_OK ==
1304 GNUNET_SERVICE_run (argc, argv, "arm", GNUNET_YES, &run, NULL)) ? 0 : 1; 1304 GNUNET_SERVICE_run (argc, argv, "arm",
1305 GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN, &run, NULL)) ? 0 : 1;
1305 GNUNET_SIGNAL_handler_uninstall (shc_chld); 1306 GNUNET_SIGNAL_handler_uninstall (shc_chld);
1306 shc_chld = NULL; 1307 shc_chld = NULL;
1307 GNUNET_DISK_pipe_close (sigpipe); 1308 GNUNET_DISK_pipe_close (sigpipe);
diff --git a/src/ats/gnunet-service-ats.c b/src/ats/gnunet-service-ats.c
index 7deca0b62..a68ec416b 100644
--- a/src/ats/gnunet-service-ats.c
+++ b/src/ats/gnunet-service-ats.c
@@ -175,7 +175,7 @@ int
175main (int argc, char *const *argv) 175main (int argc, char *const *argv)
176{ 176{
177 return (GNUNET_OK == 177 return (GNUNET_OK ==
178 GNUNET_SERVICE_run (argc, argv, "ats", GNUNET_SERVICE_OPTION_NONE, 178 GNUNET_SERVICE_run (argc, argv, "ats", GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN,
179 &run, NULL)) ? 0 : 1; 179 &run, NULL)) ? 0 : 1;
180} 180}
181 181
diff --git a/src/include/gnunet_server_lib.h b/src/include/gnunet_server_lib.h
index 87c3a8f6c..c0a0a5cba 100644
--- a/src/include/gnunet_server_lib.h
+++ b/src/include/gnunet_server_lib.h
@@ -155,6 +155,16 @@ GNUNET_SERVER_create (GNUNET_CONNECTION_AccessCheck access, void *access_cls,
155 155
156 156
157/** 157/**
158 * Stop the listen socket and get ready to shutdown the server
159 * once only 'monitor' clients are left.
160 *
161 * @param server server to stop listening on
162 */
163void
164GNUNET_SERVER_stop_listening (struct GNUNET_SERVER_Handle *server);
165
166
167/**
158 * Free resources held by this server. 168 * Free resources held by this server.
159 * 169 *
160 * @param server server to destroy 170 * @param server server to destroy
@@ -215,6 +225,22 @@ GNUNET_SERVER_notify_transmit_ready_cancel (struct GNUNET_SERVER_TransmitHandle
215 225
216 226
217/** 227/**
228 * Set the 'monitor' flag on this client. Clients which have been
229 * marked as 'monitors' won't prevent the server from shutting down
230 * once 'GNUNET_SERVER_stop_listening' has been invoked. The idea is
231 * that for "normal" clients we likely want to allow them to process
232 * their requests; however, monitor-clients are likely to 'never'
233 * disconnect during shutdown and thus will not be considered when
234 * determining if the server should continue to exist after
235 * 'GNUNET_SERVER_destroy' has been called.
236 *
237 * @param client the client to set the 'monitor' flag on
238 */
239void
240GNUNET_SERVER_client_mark_monitor (struct GNUNET_SERVER_Client *client);
241
242
243/**
218 * Set the persistent flag on this client, used to setup client connection 244 * Set the persistent flag on this client, used to setup client connection
219 * to only be killed when the service it's connected to is actually dead. 245 * to only be killed when the service it's connected to is actually dead.
220 * 246 *
diff --git a/src/include/gnunet_service_lib.h b/src/include/gnunet_service_lib.h
index 1641e0f93..ec0c15e1b 100644
--- a/src/include/gnunet_service_lib.h
+++ b/src/include/gnunet_service_lib.h
@@ -85,16 +85,22 @@ typedef void (*GNUNET_SERVICE_Main) (void *cls,
85 */ 85 */
86enum GNUNET_SERVICE_Options 86enum GNUNET_SERVICE_Options
87{ 87{
88 /** 88 /**
89 * Use defaults. 89 * Use defaults.
90 */ 90 */
91 GNUNET_SERVICE_OPTION_NONE = 0, 91 GNUNET_SERVICE_OPTION_NONE = 0,
92 92
93 /** 93 /**
94 * Do not trigger server shutdown on signals, allow for the user 94 * Do not trigger server shutdown on signals, allow for the user
95 * to terminate the server explicitly when needed. 95 * to terminate the server explicitly when needed.
96 */ 96 */
97 GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN = 1 97 GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN = 1,
98
99 /**
100 * Trigger a SOFT server shutdown on signals, allowing active
101 * non-monitor clients to complete their transactions.
102 */
103 GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN = 2
98}; 104};
99 105
100 106
@@ -104,16 +110,16 @@ enum GNUNET_SERVICE_Options
104 * 110 *
105 * @param argc number of command line arguments 111 * @param argc number of command line arguments
106 * @param argv command line arguments 112 * @param argv command line arguments
107 * @param serviceName our service name 113 * @param service_name our service name
108 * @param opt service options 114 * @param options service options
109 * @param task main task of the service 115 * @param task main task of the service
110 * @param task_cls closure for task 116 * @param task_cls closure for task
111 * @return GNUNET_SYSERR on error, GNUNET_OK 117 * @return GNUNET_SYSERR on error, GNUNET_OK
112 * if we shutdown nicely 118 * if we shutdown nicely
113 */ 119 */
114int 120int
115GNUNET_SERVICE_run (int argc, char *const *argv, const char *serviceName, 121GNUNET_SERVICE_run (int argc, char *const *argv, const char *service_name,
116 enum GNUNET_SERVICE_Options opt, GNUNET_SERVICE_Main task, 122 enum GNUNET_SERVICE_Options options, GNUNET_SERVICE_Main task,
117 void *task_cls); 123 void *task_cls);
118 124
119 125
@@ -123,13 +129,15 @@ struct GNUNET_SERVICE_Context;
123 * Run a service startup sequence within an existing 129 * Run a service startup sequence within an existing
124 * initialized system. 130 * initialized system.
125 * 131 *
126 * @param serviceName our service name 132 * @param service_name our service name
127 * @param cfg configuration to use 133 * @param cfg configuration to use
134 * @param options service options
128 * @return NULL on error, service handle 135 * @return NULL on error, service handle
129 */ 136 */
130struct GNUNET_SERVICE_Context * 137struct GNUNET_SERVICE_Context *
131GNUNET_SERVICE_start (const char *serviceName, 138GNUNET_SERVICE_start (const char *service_name,
132 const struct GNUNET_CONFIGURATION_Handle *cfg); 139 const struct GNUNET_CONFIGURATION_Handle *cfg,
140 enum GNUNET_SERVICE_Options options);
133 141
134 142
135/** 143/**
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c
index 7facd5e39..aeeb9e589 100644
--- a/src/namestore/gnunet-service-namestore.c
+++ b/src/namestore/gnunet-service-namestore.c
@@ -1975,7 +1975,7 @@ main (int argc, char *const *argv)
1975{ 1975{
1976 return (GNUNET_OK == 1976 return (GNUNET_OK ==
1977 GNUNET_SERVICE_run (argc, argv, "namestore", 1977 GNUNET_SERVICE_run (argc, argv, "namestore",
1978 GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; 1978 GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN, &run, NULL)) ? 0 : 1;
1979} 1979}
1980 1980
1981/* end of gnunet-service-namestore.c */ 1981/* end of gnunet-service-namestore.c */
diff --git a/src/peerinfo/gnunet-service-peerinfo.c b/src/peerinfo/gnunet-service-peerinfo.c
index 2dbdc9f83..4155b1ebe 100644
--- a/src/peerinfo/gnunet-service-peerinfo.c
+++ b/src/peerinfo/gnunet-service-peerinfo.c
@@ -620,6 +620,7 @@ handle_notify (void *cls, struct GNUNET_SERVER_Client *client,
620 const struct GNUNET_MessageHeader *message) 620 const struct GNUNET_MessageHeader *message)
621{ 621{
622 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "`%s' message received\n", "NOTIFY"); 622 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "`%s' message received\n", "NOTIFY");
623 GNUNET_SERVER_client_mark_monitor (client);
623 GNUNET_SERVER_notification_context_add (notify_list, client); 624 GNUNET_SERVER_notification_context_add (notify_list, client);
624 GNUNET_CONTAINER_multihashmap_iterate (hostmap, &do_notify_entry, client); 625 GNUNET_CONTAINER_multihashmap_iterate (hostmap, &do_notify_entry, client);
625 GNUNET_SERVER_receive_done (client, GNUNET_OK); 626 GNUNET_SERVER_receive_done (client, GNUNET_OK);
@@ -728,7 +729,7 @@ main (int argc, char *const *argv)
728 729
729 ret = 730 ret =
730 (GNUNET_OK == 731 (GNUNET_OK ==
731 GNUNET_SERVICE_run (argc, argv, "peerinfo", GNUNET_SERVICE_OPTION_NONE, 732 GNUNET_SERVICE_run (argc, argv, "peerinfo", GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN,
732 &run, NULL)) ? 0 : 1; 733 &run, NULL)) ? 0 : 1;
733 GNUNET_free_non_null (networkIdDirectory); 734 GNUNET_free_non_null (networkIdDirectory);
734 return ret; 735 return ret;
diff --git a/src/statistics/gnunet-service-statistics.c b/src/statistics/gnunet-service-statistics.c
index 2b60d760b..5cced1426 100644
--- a/src/statistics/gnunet-service-statistics.c
+++ b/src/statistics/gnunet-service-statistics.c
@@ -651,6 +651,7 @@ handle_watch (void *cls, struct GNUNET_SERVER_Client *client,
651 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 651 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
652 return; 652 return;
653 } 653 }
654 GNUNET_SERVER_client_mark_monitor (client);
654 ce = make_client_entry (client); 655 ce = make_client_entry (client);
655 msize = ntohs (message->size); 656 msize = ntohs (message->size);
656 if (msize < sizeof (struct GNUNET_MessageHeader)) 657 if (msize < sizeof (struct GNUNET_MessageHeader))
@@ -844,7 +845,7 @@ main (int argc, char *const *argv)
844{ 845{
845 return (GNUNET_OK == 846 return (GNUNET_OK ==
846 GNUNET_SERVICE_run (argc, argv, "statistics", 847 GNUNET_SERVICE_run (argc, argv, "statistics",
847 GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; 848 GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN, &run, NULL)) ? 0 : 1;
848} 849}
849 850
850/* end of gnunet-service-statistics.c */ 851/* end of gnunet-service-statistics.c */
diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c
index d518a3bf7..33c92d6e5 100644
--- a/src/transport/gnunet-service-transport.c
+++ b/src/transport/gnunet-service-transport.c
@@ -642,7 +642,7 @@ main (int argc, char *const *argv)
642{ 642{
643 return (GNUNET_OK == 643 return (GNUNET_OK ==
644 GNUNET_SERVICE_run (argc, argv, "transport", 644 GNUNET_SERVICE_run (argc, argv, "transport",
645 GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; 645 GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN, &run, NULL)) ? 0 : 1;
646} 646}
647 647
648/* end of file gnunet-service-transport-new.c */ 648/* end of file gnunet-service-transport.c */
diff --git a/src/transport/gnunet-service-transport_blacklist.c b/src/transport/gnunet-service-transport_blacklist.c
index 44a029474..8c368886b 100644
--- a/src/transport/gnunet-service-transport_blacklist.c
+++ b/src/transport/gnunet-service-transport_blacklist.c
@@ -230,11 +230,9 @@ read_blacklist_file ()
230 GNUNET_CONFIGURATION_get_value_filename (GST_cfg, "TRANSPORT", 230 GNUNET_CONFIGURATION_get_value_filename (GST_cfg, "TRANSPORT",
231 "BLACKLIST_FILE", &fn)) 231 "BLACKLIST_FILE", &fn))
232 { 232 {
233#if DEBUG_TRANSPORT
234 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 233 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
235 "Option `%s' in section `%s' not specified!\n", 234 "Option `%s' in section `%s' not specified!\n",
236 "BLACKLIST_FILE", "TRANSPORT"); 235 "BLACKLIST_FILE", "TRANSPORT");
237#endif
238 return; 236 return;
239 } 237 }
240 if (GNUNET_OK != GNUNET_DISK_file_test (fn)) 238 if (GNUNET_OK != GNUNET_DISK_file_test (fn))
@@ -251,10 +249,8 @@ read_blacklist_file ()
251 } 249 }
252 if (fsize == 0) 250 if (fsize == 0)
253 { 251 {
254#if DEBUG_TRANSPORT
255 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Blacklist file `%s' is empty.\n"), 252 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Blacklist file `%s' is empty.\n"),
256 fn); 253 fn);
257#endif
258 GNUNET_free (fn); 254 GNUNET_free (fn);
259 return; 255 return;
260 } 256 }
@@ -322,11 +318,9 @@ read_blacklist_file ()
322 transport_name = GNUNET_malloc (tsize + 1); 318 transport_name = GNUNET_malloc (tsize + 1);
323 memcpy (transport_name, &data[pos], tsize); 319 memcpy (transport_name, &data[pos], tsize);
324 pos = colon_pos + 1; 320 pos = colon_pos + 1;
325#if DEBUG_TRANSPORT
326 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 321 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
327 "Read transport name `%s' in blacklist file.\n", 322 "Read transport name `%s' in blacklist file.\n",
328 transport_name); 323 transport_name);
329#endif
330 memcpy (&enc, &data[pos], sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)); 324 memcpy (&enc, &data[pos], sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded));
331 if (!isspace 325 if (!isspace
332 ((unsigned char) 326 ((unsigned char)
@@ -451,11 +445,9 @@ transmit_blacklist_message (void *cls, size_t size, void *buf)
451 GNUNET_i2s (&bc->peer)); 445 GNUNET_i2s (&bc->peer));
452 return 0; 446 return 0;
453 } 447 }
454#if DEBUG_TRANSPORT
455 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 448 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
456 "Sending blacklist test for peer `%s' to client\n", 449 "Sending blacklist test for peer `%s' to client\n",
457 GNUNET_i2s (&bc->peer)); 450 GNUNET_i2s (&bc->peer));
458#endif
459 bl = bc->bl_pos; 451 bl = bc->bl_pos;
460 bm.header.size = htons (sizeof (struct BlacklistMessage)); 452 bm.header.size = htons (sizeof (struct BlacklistMessage));
461 bm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY); 453 bm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY);
@@ -484,11 +476,9 @@ do_blacklist_check (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
484 bl = bc->bl_pos; 476 bl = bc->bl_pos;
485 if (bl == NULL) 477 if (bl == NULL)
486 { 478 {
487#if DEBUG_TRANSPORT
488 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 479 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
489 "No other blacklist clients active, will allow neighbour `%s'\n", 480 "No other blacklist clients active, will allow neighbour `%s'\n",
490 GNUNET_i2s (&bc->peer)); 481 GNUNET_i2s (&bc->peer));
491#endif
492 bc->cont (bc->cont_cls, &bc->peer, GNUNET_OK); 482 bc->cont (bc->cont_cls, &bc->peer, GNUNET_OK);
493 GNUNET_CONTAINER_DLL_remove(bc_head, bc_tail, bc); 483 GNUNET_CONTAINER_DLL_remove(bc_head, bc_tail, bc);
494 GNUNET_free (bc); 484 GNUNET_free (bc);
@@ -579,7 +569,6 @@ test_connection_ok (void *cls, const struct GNUNET_PeerIdentity *neighbour,
579} 569}
580 570
581 571
582
583/** 572/**
584 * Initialize a blacklisting client. We got a blacklist-init 573 * Initialize a blacklisting client. We got a blacklist-init
585 * message from this client, add him to the list of clients 574 * message from this client, add him to the list of clients
@@ -607,6 +596,7 @@ GST_blacklist_handle_init (void *cls, struct GNUNET_SERVER_Client *client,
607 } 596 }
608 bl = bl->next; 597 bl = bl->next;
609 } 598 }
599 GNUNET_SERVER_client_mark_monitor (client);
610 bl = GNUNET_malloc (sizeof (struct Blacklisters)); 600 bl = GNUNET_malloc (sizeof (struct Blacklisters));
611 bl->client = client; 601 bl->client = client;
612 GNUNET_SERVER_client_keep (client); 602 GNUNET_SERVER_client_keep (client);
@@ -640,9 +630,7 @@ GST_blacklist_handle_reply (void *cls, struct GNUNET_SERVER_Client *client,
640 bl = bl->next; 630 bl = bl->next;
641 if (bl == NULL) 631 if (bl == NULL)
642 { 632 {
643#if DEBUG_TRANSPORT
644 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Blacklist client disconnected\n"); 633 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Blacklist client disconnected\n");
645#endif
646 /* FIXME: other error handling here!? */ 634 /* FIXME: other error handling here!? */
647 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 635 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
648 return; 636 return;
@@ -656,20 +644,16 @@ GST_blacklist_handle_reply (void *cls, struct GNUNET_SERVER_Client *client,
656 * cancelled in the meantime... */ 644 * cancelled in the meantime... */
657 if (ntohl (msg->is_allowed) == GNUNET_SYSERR) 645 if (ntohl (msg->is_allowed) == GNUNET_SYSERR)
658 { 646 {
659#if DEBUG_TRANSPORT
660 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 647 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
661 "Blacklist check failed, peer not allowed\n"); 648 "Blacklist check failed, peer not allowed\n");
662#endif
663 bc->cont (bc->cont_cls, &bc->peer, GNUNET_NO); 649 bc->cont (bc->cont_cls, &bc->peer, GNUNET_NO);
664 GNUNET_CONTAINER_DLL_remove (bc_head, bc_tail, bc); 650 GNUNET_CONTAINER_DLL_remove (bc_head, bc_tail, bc);
665 GNUNET_free (bc); 651 GNUNET_free (bc);
666 } 652 }
667 else 653 else
668 { 654 {
669#if DEBUG_TRANSPORT
670 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 655 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
671 "Blacklist check succeeded, continuing with checks\n"); 656 "Blacklist check succeeded, continuing with checks\n");
672#endif
673 bc->bl_pos = bc->bl_pos->next; 657 bc->bl_pos = bc->bl_pos->next;
674 bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc); 658 bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc);
675 } 659 }
@@ -695,11 +679,9 @@ void
695GST_blacklist_add_peer (const struct GNUNET_PeerIdentity *peer, 679GST_blacklist_add_peer (const struct GNUNET_PeerIdentity *peer,
696 const char *transport_name) 680 const char *transport_name)
697{ 681{
698#if DEBUG_TRANSPORT
699 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 682 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
700 "Adding peer `%s' with plugin `%s' to blacklist\n", 683 "Adding peer `%s' with plugin `%s' to blacklist\n",
701 GNUNET_i2s (peer), transport_name); 684 GNUNET_i2s (peer), transport_name);
702#endif
703 if (blacklist == NULL) 685 if (blacklist == NULL)
704 blacklist = 686 blacklist =
705 GNUNET_CONTAINER_multihashmap_create (TRANSPORT_BLACKLIST_HT_SIZE); 687 GNUNET_CONTAINER_multihashmap_create (TRANSPORT_BLACKLIST_HT_SIZE);
diff --git a/src/transport/gnunet-service-transport_clients.c b/src/transport/gnunet-service-transport_clients.c
index f430ef91a..939f57b10 100644
--- a/src/transport/gnunet-service-transport_clients.c
+++ b/src/transport/gnunet-service-transport_clients.c
@@ -208,10 +208,7 @@ setup_client (struct GNUNET_SERVER_Client *client)
208 GNUNET_assert (lookup_client (client) == NULL); 208 GNUNET_assert (lookup_client (client) == NULL);
209 tc = GNUNET_malloc (sizeof (struct TransportClient)); 209 tc = GNUNET_malloc (sizeof (struct TransportClient));
210 tc->client = client; 210 tc->client = client;
211
212#if DEBUG_TRANSPORT
213 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", tc); 211 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", tc);
214#endif
215 return tc; 212 return tc;
216} 213}
217 214
@@ -293,10 +290,8 @@ transmit_to_client_callback (void *cls, size_t size, void *buf)
293 tc->th = NULL; 290 tc->th = NULL;
294 if (buf == NULL) 291 if (buf == NULL)
295 { 292 {
296#if DEBUG_TRANSPORT
297 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 293 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
298 "Transmission to client failed, closing connection.\n"); 294 "Transmission to client failed, closing connection.\n");
299#endif
300 return 0; 295 return 0;
301 } 296 }
302 cbuf = buf; 297 cbuf = buf;
@@ -307,11 +302,9 @@ transmit_to_client_callback (void *cls, size_t size, void *buf)
307 msize = ntohs (msg->size); 302 msize = ntohs (msg->size);
308 if (msize + tsize > size) 303 if (msize + tsize > size)
309 break; 304 break;
310#if DEBUG_TRANSPORT
311 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 305 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
312 "Transmitting message of type %u to client %p.\n", 306 "Transmitting message of type %u to client %p.\n",
313 ntohs (msg->type), tc); 307 ntohs (msg->type), tc);
314#endif
315 GNUNET_CONTAINER_DLL_remove (tc->message_queue_head, tc->message_queue_tail, 308 GNUNET_CONTAINER_DLL_remove (tc->message_queue_head, tc->message_queue_tail,
316 q); 309 q);
317 tc->message_count--; 310 tc->message_count--;
@@ -403,10 +396,8 @@ client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client)
403 tc = lookup_client (client); 396 tc = lookup_client (client);
404 if (tc == NULL) 397 if (tc == NULL)
405 return; 398 return;
406#if DEBUG_TRANSPORT
407 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, 399 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
408 "Client %p disconnected, cleaning up.\n", tc); 400 "Client %p disconnected, cleaning up.\n", tc);
409#endif
410 while (NULL != (mqe = tc->message_queue_head)) 401 while (NULL != (mqe = tc->message_queue_head))
411 { 402 {
412 GNUNET_CONTAINER_DLL_remove (tc->message_queue_head, tc->message_queue_tail, 403 GNUNET_CONTAINER_DLL_remove (tc->message_queue_head, tc->message_queue_tail,
@@ -481,18 +472,14 @@ clients_handle_start (void *cls, struct GNUNET_SERVER_Client *client,
481 472
482 tc = lookup_client (client); 473 tc = lookup_client (client);
483 474
484#if DEBUG_TRANSPORT
485 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, 475 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
486 "Client %p sent START\n", tc); 476 "Client %p sent START\n", tc);
487#endif
488 if (tc != NULL) 477 if (tc != NULL)
489 { 478 {
490 /* got 'start' twice from the same client, not allowed */ 479 /* got 'start' twice from the same client, not allowed */
491#if DEBUG_TRANSPORT
492 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, 480 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
493 "TransportClient %p ServerClient %p sent multiple START messages\n", 481 "TransportClient %p ServerClient %p sent multiple START messages\n",
494 tc, tc->client); 482 tc, tc->client);
495#endif
496 GNUNET_break (0); 483 GNUNET_break (0);
497 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 484 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
498 return; 485 return;
@@ -627,19 +614,15 @@ clients_handle_send (void *cls, struct GNUNET_SERVER_Client *client,
627 gettext_noop 614 gettext_noop
628 ("# bytes payload received for other peers"), msize, 615 ("# bytes payload received for other peers"), msize,
629 GNUNET_NO); 616 GNUNET_NO);
630#if DEBUG_TRANSPORT
631 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 617 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
632 "Received `%s' request from client with target `%4s' and first message of type %u and total size %u\n", 618 "Received `%s' request from client with target `%4s' and first message of type %u and total size %u\n",
633 "SEND", GNUNET_i2s (&obm->peer), ntohs (obmm->type), msize); 619 "SEND", GNUNET_i2s (&obm->peer), ntohs (obmm->type), msize);
634#endif
635 if (GNUNET_NO == GST_neighbours_test_connected (&obm->peer)) 620 if (GNUNET_NO == GST_neighbours_test_connected (&obm->peer))
636 { 621 {
637 /* not connected, not allowed to send; can happen due to asynchronous operations */ 622 /* not connected, not allowed to send; can happen due to asynchronous operations */
638#if DEBUG_TRANSPORT
639 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 623 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
640 "Could not send message to peer `%s': not connected\n", 624 "Could not send message to peer `%s': not connected\n",
641 GNUNET_i2s (&obm->peer)); 625 GNUNET_i2s (&obm->peer));
642#endif
643 GNUNET_STATISTICS_update (GST_stats, 626 GNUNET_STATISTICS_update (GST_stats,
644 gettext_noop 627 gettext_noop
645 ("# bytes payload dropped (other peer was not connected)"), 628 ("# bytes payload dropped (other peer was not connected)"),
@@ -695,11 +678,9 @@ clients_handle_request_connect (void *cls, struct GNUNET_SERVER_Client *client,
695 gettext_noop 678 gettext_noop
696 ("# REQUEST CONNECT messages received"), 1, 679 ("# REQUEST CONNECT messages received"), 1,
697 GNUNET_NO); 680 GNUNET_NO);
698#if DEBUG_TRANSPORT
699 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 681 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
700 "Received a request connect message for peer `%s'\n", 682 "Received a request connect message for peer `%s'\n",
701 GNUNET_i2s (&trcm->peer)); 683 GNUNET_i2s (&trcm->peer));
702#endif
703 (void) GST_blacklist_test_allowed (&trcm->peer, NULL, &try_connect_if_allowed, 684 (void) GST_blacklist_test_allowed (&trcm->peer, NULL, &try_connect_if_allowed,
704 NULL); 685 NULL);
705 GNUNET_SERVER_receive_done (client, GNUNET_OK); 686 GNUNET_SERVER_receive_done (client, GNUNET_OK);
diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c
index ea8b6ee08..54bcf16ef 100644
--- a/src/transport/plugin_transport_tcp.c
+++ b/src/transport/plugin_transport_tcp.c
@@ -2161,7 +2161,7 @@ libgnunet_plugin_transport_tcp_init (void *cls)
2161 aport = 0; 2161 aport = 0;
2162 if (bport != 0) 2162 if (bport != 0)
2163 { 2163 {
2164 service = GNUNET_SERVICE_start ("transport-tcp", env->cfg); 2164 service = GNUNET_SERVICE_start ("transport-tcp", env->cfg, GNUNET_SERVICE_OPTION_NONE);
2165 if (service == NULL) 2165 if (service == NULL)
2166 { 2166 {
2167 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "tcp", 2167 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "tcp",
diff --git a/src/util/server.c b/src/util/server.c
index 6a458b35b..4c7f62c17 100644
--- a/src/util/server.c
+++ b/src/util/server.c
@@ -133,12 +133,6 @@ struct GNUNET_SERVER_Handle
133 GNUNET_SCHEDULER_TaskIdentifier listen_task; 133 GNUNET_SCHEDULER_TaskIdentifier listen_task;
134 134
135 /** 135 /**
136 * Do we ignore messages of types that we do not understand or do we
137 * require that a handler is found (and if not kill the connection)?
138 */
139 int require_found;
140
141 /**
142 * Alternative function to create a MST instance. 136 * Alternative function to create a MST instance.
143 */ 137 */
144 GNUNET_SERVER_MstCreateCallback mst_create; 138 GNUNET_SERVER_MstCreateCallback mst_create;
@@ -157,6 +151,19 @@ struct GNUNET_SERVER_Handle
157 * Closure for 'mst_'-callbacks. 151 * Closure for 'mst_'-callbacks.
158 */ 152 */
159 void *mst_cls; 153 void *mst_cls;
154
155 /**
156 * Do we ignore messages of types that we do not understand or do we
157 * require that a handler is found (and if not kill the connection)?
158 */
159 int require_found;
160
161 /**
162 * Set to GNUNET_YES once we are in 'soft' shutdown where we wait for
163 * all non-monitor clients to disconnect before we call
164 * GNUNET_SERVER_destroy. See 'test_monitor_clients'.
165 */
166 int in_soft_shutdown;
160}; 167};
161 168
162 169
@@ -291,6 +298,13 @@ struct GNUNET_SERVER_Client
291 int persist; 298 int persist;
292 299
293 /** 300 /**
301 * Is this client a 'monitor' client that should not be counted
302 * when deciding on destroying the server during soft shutdown?
303 * (see also GNUNET_SERVICE_start)
304 */
305 int is_monitor;
306
307 /**
294 * Type of last message processed (for warn_no_receive_done). 308 * Type of last message processed (for warn_no_receive_done).
295 */ 309 */
296 uint16_t warn_type; 310 uint16_t warn_type;
@@ -558,6 +572,76 @@ GNUNET_SERVER_create (GNUNET_CONNECTION_AccessCheck access, void *access_cls,
558 572
559 573
560/** 574/**
575 * Set the 'monitor' flag on this client. Clients which have been
576 * marked as 'monitors' won't prevent the server from shutting down
577 * once 'GNUNET_SERVER_stop_listening' has been invoked. The idea is
578 * that for "normal" clients we likely want to allow them to process
579 * their requests; however, monitor-clients are likely to 'never'
580 * disconnect during shutdown and thus will not be considered when
581 * determining if the server should continue to exist after
582 * 'GNUNET_SERVER_destroy' has been called.
583 *
584 * @param client the client to set the 'monitor' flag on
585 */
586void
587GNUNET_SERVER_client_mark_monitor (struct GNUNET_SERVER_Client *client)
588{
589 client->is_monitor = GNUNET_YES;
590}
591
592
593/**
594 * Check if only 'monitor' clients are left. If so, destroy the
595 * server completely.
596 *
597 * @param server server to test for full shutdown
598 */
599static void
600test_monitor_clients (struct GNUNET_SERVER_Handle *server)
601{
602 struct GNUNET_SERVER_Client *client;
603
604 if (GNUNET_YES != server->in_soft_shutdown)
605 return;
606 for (client = server->clients; NULL != client; client = client->next)
607 if (GNUNET_NO == client->is_monitor)
608 return; /* not done yet */
609 GNUNET_SERVER_destroy (server);
610}
611
612
613/**
614 * Stop the listen socket and get ready to shutdown the server
615 * once only 'monitor' clients are left.
616 *
617 * @param server server to stop listening on
618 */
619void
620GNUNET_SERVER_stop_listening (struct GNUNET_SERVER_Handle *server)
621{
622 unsigned int i;
623
624 LOG (GNUNET_ERROR_TYPE_DEBUG, "Server in soft shutdown\n");
625 if (GNUNET_SCHEDULER_NO_TASK != server->listen_task)
626 {
627 GNUNET_SCHEDULER_cancel (server->listen_task);
628 server->listen_task = GNUNET_SCHEDULER_NO_TASK;
629 }
630 if (NULL != server->listen_sockets)
631 {
632 i = 0;
633 while (NULL != server->listen_sockets[i])
634 GNUNET_break (GNUNET_OK ==
635 GNUNET_NETWORK_socket_close (server->listen_sockets[i++]));
636 GNUNET_free (server->listen_sockets);
637 server->listen_sockets = NULL;
638 }
639 server->in_soft_shutdown = GNUNET_YES;
640 test_monitor_clients (server);
641}
642
643
644/**
561 * Free resources held by this server. 645 * Free resources held by this server.
562 * 646 *
563 * @param server server to destroy 647 * @param server server to destroy
@@ -1163,10 +1247,10 @@ GNUNET_SERVER_client_disconnect (struct GNUNET_SERVER_Client *client)
1163 GNUNET_CONNECTION_receive_cancel (client->connection); 1247 GNUNET_CONNECTION_receive_cancel (client->connection);
1164 client->receive_pending = GNUNET_NO; 1248 client->receive_pending = GNUNET_NO;
1165 } 1249 }
1250 server = client->server;
1166 rc = client->reference_count; 1251 rc = client->reference_count;
1167 if (GNUNET_YES != client->shutdown_now) 1252 if (GNUNET_YES != client->shutdown_now)
1168 { 1253 {
1169 server = client->server;
1170 client->shutdown_now = GNUNET_YES; 1254 client->shutdown_now = GNUNET_YES;
1171 prev = NULL; 1255 prev = NULL;
1172 pos = server->clients; 1256 pos = server->clients;
@@ -1212,11 +1296,13 @@ GNUNET_SERVER_client_disconnect (struct GNUNET_SERVER_Client *client)
1212 GNUNET_SERVER_notify_transmit_ready_cancel (&client->th); 1296 GNUNET_SERVER_notify_transmit_ready_cancel (&client->th);
1213 GNUNET_CONNECTION_destroy (client->connection); 1297 GNUNET_CONNECTION_destroy (client->connection);
1214 1298
1215 if (NULL != client->server->mst_destroy) 1299 if (NULL != server->mst_destroy)
1216 client->server->mst_destroy (client->server->mst_cls, client->mst); 1300 server->mst_destroy (server->mst_cls, client->mst);
1217 else 1301 else
1218 GNUNET_SERVER_mst_destroy (client->mst); 1302 GNUNET_SERVER_mst_destroy (client->mst);
1219 GNUNET_free (client); 1303 GNUNET_free (client);
1304 /* we might be in soft-shutdown, test if we're done */
1305 test_monitor_clients (server);
1220} 1306}
1221 1307
1222 1308
diff --git a/src/util/service.c b/src/util/service.c
index 4eb35d97a..3cddae69e 100644
--- a/src/util/service.c
+++ b/src/util/service.c
@@ -436,7 +436,7 @@ struct GNUNET_SERVICE_Context
436 /** 436 /**
437 * Name of our service. 437 * Name of our service.
438 */ 438 */
439 const char *serviceName; 439 const char *service_name;
440 440
441 /** 441 /**
442 * Main service-specific task to run. 442 * Main service-specific task to run.
@@ -697,7 +697,7 @@ check_access (void *cls, const struct GNUNET_CONNECTION_Credentials *uc,
697 LOG (GNUNET_ERROR_TYPE_WARNING, 697 LOG (GNUNET_ERROR_TYPE_WARNING,
698 _("Access from `%s' denied to service `%s'\n"), 698 _("Access from `%s' denied to service `%s'\n"),
699 GNUNET_a2s (addr, addrlen), 699 GNUNET_a2s (addr, addrlen),
700 sctx->serviceName); 700 sctx->service_name);
701 } 701 }
702 return ret; 702 return ret;
703} 703}
@@ -716,7 +716,7 @@ get_pid_file_name (struct GNUNET_SERVICE_Context *sctx)
716 char *pif; 716 char *pif;
717 717
718 if (GNUNET_OK != 718 if (GNUNET_OK !=
719 GNUNET_CONFIGURATION_get_value_filename (sctx->cfg, sctx->serviceName, 719 GNUNET_CONFIGURATION_get_value_filename (sctx->cfg, sctx->service_name,
720 "PIDFILE", &pif)) 720 "PIDFILE", &pif))
721 return NULL; 721 return NULL;
722 return pif; 722 return pif;
@@ -738,20 +738,20 @@ process_acl4 (struct IPv4NetworkSet **ret, struct GNUNET_SERVICE_Context *sctx,
738{ 738{
739 char *opt; 739 char *opt;
740 740
741 if (!GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->serviceName, option)) 741 if (!GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->service_name, option))
742 { 742 {
743 *ret = NULL; 743 *ret = NULL;
744 return GNUNET_OK; 744 return GNUNET_OK;
745 } 745 }
746 GNUNET_break (GNUNET_OK == 746 GNUNET_break (GNUNET_OK ==
747 GNUNET_CONFIGURATION_get_value_string (sctx->cfg, 747 GNUNET_CONFIGURATION_get_value_string (sctx->cfg,
748 sctx->serviceName, 748 sctx->service_name,
749 option, &opt)); 749 option, &opt));
750 if (NULL == (*ret = parse_ipv4_specification (opt))) 750 if (NULL == (*ret = parse_ipv4_specification (opt)))
751 { 751 {
752 LOG (GNUNET_ERROR_TYPE_WARNING, 752 LOG (GNUNET_ERROR_TYPE_WARNING,
753 _("Could not parse IPv4 network specification `%s' for `%s:%s'\n"), 753 _("Could not parse IPv4 network specification `%s' for `%s:%s'\n"),
754 opt, sctx->serviceName, option); 754 opt, sctx->service_name, option);
755 GNUNET_free (opt); 755 GNUNET_free (opt);
756 return GNUNET_SYSERR; 756 return GNUNET_SYSERR;
757 } 757 }
@@ -775,20 +775,20 @@ process_acl6 (struct IPv6NetworkSet **ret, struct GNUNET_SERVICE_Context *sctx,
775{ 775{
776 char *opt; 776 char *opt;
777 777
778 if (!GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->serviceName, option)) 778 if (!GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->service_name, option))
779 { 779 {
780 *ret = NULL; 780 *ret = NULL;
781 return GNUNET_OK; 781 return GNUNET_OK;
782 } 782 }
783 GNUNET_break (GNUNET_OK == 783 GNUNET_break (GNUNET_OK ==
784 GNUNET_CONFIGURATION_get_value_string (sctx->cfg, 784 GNUNET_CONFIGURATION_get_value_string (sctx->cfg,
785 sctx->serviceName, 785 sctx->service_name,
786 option, &opt)); 786 option, &opt));
787 if (NULL == (*ret = parse_ipv6_specification (opt))) 787 if (NULL == (*ret = parse_ipv6_specification (opt)))
788 { 788 {
789 LOG (GNUNET_ERROR_TYPE_WARNING, 789 LOG (GNUNET_ERROR_TYPE_WARNING,
790 _("Could not parse IPv6 network specification `%s' for `%s:%s'\n"), 790 _("Could not parse IPv6 network specification `%s' for `%s:%s'\n"),
791 opt, sctx->serviceName, option); 791 opt, sctx->service_name, option);
792 GNUNET_free (opt); 792 GNUNET_free (opt);
793 return GNUNET_SYSERR; 793 return GNUNET_SYSERR;
794 } 794 }
@@ -841,7 +841,7 @@ add_unixpath (struct sockaddr **saddrs, socklen_t * saddrlens,
841 * Get the list of addresses that a server for the given service 841 * Get the list of addresses that a server for the given service
842 * should bind to. 842 * should bind to.
843 * 843 *
844 * @param serviceName name of the service 844 * @param service_name name of the service
845 * @param cfg configuration (which specifies the addresses) 845 * @param cfg configuration (which specifies the addresses)
846 * @param addrs set (call by reference) to an array of pointers to the 846 * @param addrs set (call by reference) to an array of pointers to the
847 * addresses the server should bind to and listen on; the 847 * addresses the server should bind to and listen on; the
@@ -858,7 +858,7 @@ add_unixpath (struct sockaddr **saddrs, socklen_t * saddrlens,
858 * set to NULL). 858 * set to NULL).
859 */ 859 */
860int 860int
861GNUNET_SERVICE_get_server_addresses (const char *serviceName, 861GNUNET_SERVICE_get_server_addresses (const char *service_name,
862 const struct GNUNET_CONFIGURATION_Handle 862 const struct GNUNET_CONFIGURATION_Handle
863 *cfg, struct sockaddr ***addrs, 863 *cfg, struct sockaddr ***addrs,
864 socklen_t ** addr_lens) 864 socklen_t ** addr_lens)
@@ -881,11 +881,11 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName,
881 *addrs = NULL; 881 *addrs = NULL;
882 *addr_lens = NULL; 882 *addr_lens = NULL;
883 desc = NULL; 883 desc = NULL;
884 if (GNUNET_CONFIGURATION_have_value (cfg, serviceName, "DISABLEV6")) 884 if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "DISABLEV6"))
885 { 885 {
886 if (GNUNET_SYSERR == 886 if (GNUNET_SYSERR ==
887 (disablev6 = 887 (disablev6 =
888 GNUNET_CONFIGURATION_get_value_yesno (cfg, serviceName, "DISABLEV6"))) 888 GNUNET_CONFIGURATION_get_value_yesno (cfg, service_name, "DISABLEV6")))
889 return GNUNET_SYSERR; 889 return GNUNET_SYSERR;
890 } 890 }
891 else 891 else
@@ -906,7 +906,7 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName,
906 LOG (GNUNET_ERROR_TYPE_INFO, 906 LOG (GNUNET_ERROR_TYPE_INFO,
907 _ 907 _
908 ("Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"), 908 ("Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"),
909 serviceName, STRERROR (errno)); 909 service_name, STRERROR (errno));
910 disablev6 = GNUNET_YES; 910 disablev6 = GNUNET_YES;
911 } 911 }
912 else 912 else
@@ -917,24 +917,24 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName,
917 } 917 }
918 918
919 port = 0; 919 port = 0;
920 if (GNUNET_CONFIGURATION_have_value (cfg, serviceName, "PORT")) 920 if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT"))
921 { 921 {
922 GNUNET_break (GNUNET_OK == 922 GNUNET_break (GNUNET_OK ==
923 GNUNET_CONFIGURATION_get_value_number (cfg, serviceName, 923 GNUNET_CONFIGURATION_get_value_number (cfg, service_name,
924 "PORT", &port)); 924 "PORT", &port));
925 if (port > 65535) 925 if (port > 65535)
926 { 926 {
927 LOG (GNUNET_ERROR_TYPE_ERROR, 927 LOG (GNUNET_ERROR_TYPE_ERROR,
928 _("Require valid port number for service `%s' in configuration!\n"), 928 _("Require valid port number for service `%s' in configuration!\n"),
929 serviceName); 929 service_name);
930 return GNUNET_SYSERR; 930 return GNUNET_SYSERR;
931 } 931 }
932 } 932 }
933 933
934 if (GNUNET_CONFIGURATION_have_value (cfg, serviceName, "BINDTO")) 934 if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "BINDTO"))
935 { 935 {
936 GNUNET_break (GNUNET_OK == 936 GNUNET_break (GNUNET_OK ==
937 GNUNET_CONFIGURATION_get_value_string (cfg, serviceName, 937 GNUNET_CONFIGURATION_get_value_string (cfg, service_name,
938 "BINDTO", &hostname)); 938 "BINDTO", &hostname));
939 } 939 }
940 else 940 else
@@ -943,9 +943,9 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName,
943 unixpath = NULL; 943 unixpath = NULL;
944#ifdef AF_UNIX 944#ifdef AF_UNIX
945 if ((GNUNET_YES == 945 if ((GNUNET_YES ==
946 GNUNET_CONFIGURATION_have_value (cfg, serviceName, "UNIXPATH")) && 946 GNUNET_CONFIGURATION_have_value (cfg, service_name, "UNIXPATH")) &&
947 (GNUNET_OK == 947 (GNUNET_OK ==
948 GNUNET_CONFIGURATION_get_value_string (cfg, serviceName, "UNIXPATH", 948 GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "UNIXPATH",
949 &unixpath)) && 949 &unixpath)) &&
950 (0 < strlen (unixpath))) 950 (0 < strlen (unixpath)))
951 { 951 {
@@ -976,7 +976,7 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName,
976 LOG (GNUNET_ERROR_TYPE_INFO, 976 LOG (GNUNET_ERROR_TYPE_INFO,
977 _ 977 _
978 ("Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"), 978 ("Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
979 serviceName, STRERROR (errno)); 979 service_name, STRERROR (errno));
980 GNUNET_free (unixpath); 980 GNUNET_free (unixpath);
981 unixpath = NULL; 981 unixpath = NULL;
982 } 982 }
@@ -993,7 +993,7 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName,
993 LOG (GNUNET_ERROR_TYPE_ERROR, 993 LOG (GNUNET_ERROR_TYPE_ERROR,
994 _ 994 _
995 ("Have neither PORT nor UNIXPATH for service `%s', but one is required\n"), 995 ("Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
996 serviceName); 996 service_name);
997 GNUNET_free_non_null (hostname); 997 GNUNET_free_non_null (hostname);
998 return GNUNET_SYSERR; 998 return GNUNET_SYSERR;
999 } 999 }
@@ -1013,7 +1013,7 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName,
1013 { 1013 {
1014 LOG (GNUNET_ERROR_TYPE_DEBUG, 1014 LOG (GNUNET_ERROR_TYPE_DEBUG,
1015 "Resolving `%s' since that is where `%s' will bind to.\n", hostname, 1015 "Resolving `%s' since that is where `%s' will bind to.\n", hostname,
1016 serviceName); 1016 service_name);
1017 memset (&hints, 0, sizeof (struct addrinfo)); 1017 memset (&hints, 0, sizeof (struct addrinfo));
1018 if (disablev6) 1018 if (disablev6)
1019 hints.ai_family = AF_INET; 1019 hints.ai_family = AF_INET;
@@ -1066,7 +1066,7 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName,
1066 if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype)) 1066 if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
1067 continue; /* huh? */ 1067 continue; /* huh? */
1068 LOG (GNUNET_ERROR_TYPE_DEBUG, "Service `%s' will bind to `%s'\n", 1068 LOG (GNUNET_ERROR_TYPE_DEBUG, "Service `%s' will bind to `%s'\n",
1069 serviceName, GNUNET_a2s (pos->ai_addr, pos->ai_addrlen)); 1069 service_name, GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
1070 if (AF_INET == pos->ai_family) 1070 if (AF_INET == pos->ai_family)
1071 { 1071 {
1072 GNUNET_assert (sizeof (struct sockaddr_in) == pos->ai_addrlen); 1072 GNUNET_assert (sizeof (struct sockaddr_in) == pos->ai_addrlen);
@@ -1269,15 +1269,15 @@ setup_service (struct GNUNET_SERVICE_Context *sctx)
1269 int flags; 1269 int flags;
1270#endif 1270#endif
1271 1271
1272 if (GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->serviceName, "TIMEOUT")) 1272 if (GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->service_name, "TIMEOUT"))
1273 { 1273 {
1274 if (GNUNET_OK != 1274 if (GNUNET_OK !=
1275 GNUNET_CONFIGURATION_get_value_time (sctx->cfg, sctx->serviceName, 1275 GNUNET_CONFIGURATION_get_value_time (sctx->cfg, sctx->service_name,
1276 "TIMEOUT", &idleout)) 1276 "TIMEOUT", &idleout))
1277 { 1277 {
1278 LOG (GNUNET_ERROR_TYPE_ERROR, 1278 LOG (GNUNET_ERROR_TYPE_ERROR,
1279 _("Specified value for `%s' of service `%s' is invalid\n"), 1279 _("Specified value for `%s' of service `%s' is invalid\n"),
1280 "TIMEOUT", sctx->serviceName); 1280 "TIMEOUT", sctx->service_name);
1281 return GNUNET_SYSERR; 1281 return GNUNET_SYSERR;
1282 } 1282 }
1283 sctx->timeout = idleout; 1283 sctx->timeout = idleout;
@@ -1286,16 +1286,16 @@ setup_service (struct GNUNET_SERVICE_Context *sctx)
1286 sctx->timeout = GNUNET_TIME_UNIT_FOREVER_REL; 1286 sctx->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1287 1287
1288 if (GNUNET_CONFIGURATION_have_value 1288 if (GNUNET_CONFIGURATION_have_value
1289 (sctx->cfg, sctx->serviceName, "TOLERANT")) 1289 (sctx->cfg, sctx->service_name, "TOLERANT"))
1290 { 1290 {
1291 if (GNUNET_SYSERR == 1291 if (GNUNET_SYSERR ==
1292 (tolerant = 1292 (tolerant =
1293 GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg, sctx->serviceName, 1293 GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg, sctx->service_name,
1294 "TOLERANT"))) 1294 "TOLERANT")))
1295 { 1295 {
1296 LOG (GNUNET_ERROR_TYPE_ERROR, 1296 LOG (GNUNET_ERROR_TYPE_ERROR,
1297 _("Specified value for `%s' of service `%s' is invalid\n"), 1297 _("Specified value for `%s' of service `%s' is invalid\n"),
1298 "TOLERANT", sctx->serviceName); 1298 "TOLERANT", sctx->service_name);
1299 return GNUNET_SYSERR; 1299 return GNUNET_SYSERR;
1300 } 1300 }
1301 } 1301 }
@@ -1344,15 +1344,15 @@ setup_service (struct GNUNET_SERVICE_Context *sctx)
1344 1344
1345 if ((NULL == sctx->lsocks) && 1345 if ((NULL == sctx->lsocks) &&
1346 (GNUNET_SYSERR == 1346 (GNUNET_SYSERR ==
1347 GNUNET_SERVICE_get_server_addresses (sctx->serviceName, sctx->cfg, 1347 GNUNET_SERVICE_get_server_addresses (sctx->service_name, sctx->cfg,
1348 &sctx->addrs, &sctx->addrlens))) 1348 &sctx->addrs, &sctx->addrlens)))
1349 return GNUNET_SYSERR; 1349 return GNUNET_SYSERR;
1350 sctx->require_found = tolerant ? GNUNET_NO : GNUNET_YES; 1350 sctx->require_found = tolerant ? GNUNET_NO : GNUNET_YES;
1351 sctx->match_uid = 1351 sctx->match_uid =
1352 GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg, sctx->serviceName, 1352 GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg, sctx->service_name,
1353 "UNIX_MATCH_UID"); 1353 "UNIX_MATCH_UID");
1354 sctx->match_gid = 1354 sctx->match_gid =
1355 GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg, sctx->serviceName, 1355 GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg, sctx->service_name,
1356 "UNIX_MATCH_GID"); 1356 "UNIX_MATCH_GID");
1357 process_acl4 (&sctx->v4_denied, sctx, "REJECT_FROM"); 1357 process_acl4 (&sctx->v4_denied, sctx, "REJECT_FROM");
1358 process_acl4 (&sctx->v4_allowed, sctx, "ACCEPT_FROM"); 1358 process_acl4 (&sctx->v4_allowed, sctx, "ACCEPT_FROM");
@@ -1376,7 +1376,7 @@ get_user_name (struct GNUNET_SERVICE_Context *sctx)
1376 char *un; 1376 char *un;
1377 1377
1378 if (GNUNET_OK != 1378 if (GNUNET_OK !=
1379 GNUNET_CONFIGURATION_get_value_filename (sctx->cfg, sctx->serviceName, 1379 GNUNET_CONFIGURATION_get_value_filename (sctx->cfg, sctx->service_name,
1380 "USERNAME", &un)) 1380 "USERNAME", &un))
1381 return NULL; 1381 return NULL;
1382 return un; 1382 return un;
@@ -1443,19 +1443,21 @@ write_pid_file (struct GNUNET_SERVICE_Context *sctx, pid_t pid)
1443 1443
1444 1444
1445/** 1445/**
1446 * Task run during shutdown. 1446 * Task run during shutdown. Stops the server/service.
1447 * 1447 *
1448 * @param cls unused 1448 * @param cls the 'struct GNUNET_SERVICE_Context'
1449 * @param tc unused 1449 * @param tc unused
1450 */ 1450 */
1451static void 1451static void
1452shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 1452shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1453{ 1453{
1454 struct GNUNET_SERVER_Handle *server = cls; 1454 struct GNUNET_SERVICE_Context *service = cls;
1455 struct GNUNET_SERVER_Handle *server = service->server;
1455 1456
1456 // FIXME: we should not unconditionally destroy the server 1457 if (0 != (service->options & GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN))
1457 // here (often only stopping 'listening' would be better) 1458 GNUNET_SERVER_stop_listening (server);
1458 GNUNET_SERVER_destroy (server); 1459 else
1460 GNUNET_SERVER_destroy (server);
1459} 1461}
1460 1462
1461 1463
@@ -1488,7 +1490,7 @@ service_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1488 while (NULL != sctx->addrs[i]) 1490 while (NULL != sctx->addrs[i])
1489 { 1491 {
1490 LOG (GNUNET_ERROR_TYPE_INFO, _("Failed to start `%s' at `%s'\n"), 1492 LOG (GNUNET_ERROR_TYPE_INFO, _("Failed to start `%s' at `%s'\n"),
1491 sctx->serviceName, GNUNET_a2s (sctx->addrs[i], sctx->addrlens[i])); 1493 sctx->service_name, GNUNET_a2s (sctx->addrs[i], sctx->addrlens[i]));
1492 i++; 1494 i++;
1493 } 1495 }
1494 } 1496 }
@@ -1500,7 +1502,7 @@ service_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1500 /* install a task that will kill the server 1502 /* install a task that will kill the server
1501 * process if the scheduler ever gets a shutdown signal */ 1503 * process if the scheduler ever gets a shutdown signal */
1502 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, 1504 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
1503 sctx->server); 1505 sctx);
1504 } 1506 }
1505 sctx->my_handlers = GNUNET_malloc (sizeof (defhandlers)); 1507 sctx->my_handlers = GNUNET_malloc (sizeof (defhandlers));
1506 memcpy (sctx->my_handlers, defhandlers, sizeof (defhandlers)); 1508 memcpy (sctx->my_handlers, defhandlers, sizeof (defhandlers));
@@ -1521,7 +1523,7 @@ service_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1521 while (NULL != sctx->addrs[i]) 1523 while (NULL != sctx->addrs[i])
1522 { 1524 {
1523 LOG (GNUNET_ERROR_TYPE_INFO, _("Service `%s' runs at %s\n"), 1525 LOG (GNUNET_ERROR_TYPE_INFO, _("Service `%s' runs at %s\n"),
1524 sctx->serviceName, GNUNET_a2s (sctx->addrs[i], sctx->addrlens[i])); 1526 sctx->service_name, GNUNET_a2s (sctx->addrs[i], sctx->addrlens[i]));
1525 i++; 1527 i++;
1526 } 1528 }
1527 } 1529 }
@@ -1681,16 +1683,16 @@ pid_file_delete (struct GNUNET_SERVICE_Context *sctx)
1681 * 1683 *
1682 * @param argc number of command line arguments 1684 * @param argc number of command line arguments
1683 * @param argv command line arguments 1685 * @param argv command line arguments
1684 * @param serviceName our service name 1686 * @param service_name our service name
1685 * @param opt service options 1687 * @param options service options
1686 * @param task main task of the service 1688 * @param task main task of the service
1687 * @param task_cls closure for task 1689 * @param task_cls closure for task
1688 * @return GNUNET_SYSERR on error, GNUNET_OK 1690 * @return GNUNET_SYSERR on error, GNUNET_OK
1689 * if we shutdown nicely 1691 * if we shutdown nicely
1690 */ 1692 */
1691int 1693int
1692GNUNET_SERVICE_run (int argc, char *const *argv, const char *serviceName, 1694GNUNET_SERVICE_run (int argc, char *const *argv, const char *service_name,
1693 enum GNUNET_SERVICE_Options opt, GNUNET_SERVICE_Main task, 1695 enum GNUNET_SERVICE_Options options, GNUNET_SERVICE_Main task,
1694 void *task_cls) 1696 void *task_cls)
1695{ 1697{
1696#define HANDLE_ERROR do { GNUNET_break (0); goto shutdown; } while (0) 1698#define HANDLE_ERROR do { GNUNET_break (0); goto shutdown; } while (0)
@@ -1724,19 +1726,19 @@ GNUNET_SERVICE_run (int argc, char *const *argv, const char *serviceName,
1724 loglev = NULL; 1726 loglev = NULL;
1725 cfg_fn = GNUNET_strdup (GNUNET_DEFAULT_USER_CONFIG_FILE); 1727 cfg_fn = GNUNET_strdup (GNUNET_DEFAULT_USER_CONFIG_FILE);
1726 memset (&sctx, 0, sizeof (sctx)); 1728 memset (&sctx, 0, sizeof (sctx));
1727 sctx.options = opt; 1729 sctx.options = options;
1728 sctx.ready_confirm_fd = -1; 1730 sctx.ready_confirm_fd = -1;
1729 sctx.ret = GNUNET_OK; 1731 sctx.ret = GNUNET_OK;
1730 sctx.timeout = GNUNET_TIME_UNIT_FOREVER_REL; 1732 sctx.timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1731 sctx.task = task; 1733 sctx.task = task;
1732 sctx.task_cls = task_cls; 1734 sctx.task_cls = task_cls;
1733 sctx.serviceName = serviceName; 1735 sctx.service_name = service_name;
1734 sctx.cfg = cfg = GNUNET_CONFIGURATION_create (); 1736 sctx.cfg = cfg = GNUNET_CONFIGURATION_create ();
1735 /* setup subsystems */ 1737 /* setup subsystems */
1736 if (GNUNET_SYSERR == 1738 if (GNUNET_SYSERR ==
1737 GNUNET_GETOPT_run (serviceName, service_options, argc, argv)) 1739 GNUNET_GETOPT_run (service_name, service_options, argc, argv))
1738 goto shutdown; 1740 goto shutdown;
1739 if (GNUNET_OK != GNUNET_log_setup (serviceName, loglev, logfile)) 1741 if (GNUNET_OK != GNUNET_log_setup (service_name, loglev, logfile))
1740 HANDLE_ERROR; 1742 HANDLE_ERROR;
1741 if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfg_fn)) 1743 if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfg_fn))
1742 goto shutdown; 1744 goto shutdown;
@@ -1747,7 +1749,7 @@ GNUNET_SERVICE_run (int argc, char *const *argv, const char *serviceName,
1747 if (GNUNET_OK != set_user_id (&sctx)) 1749 if (GNUNET_OK != set_user_id (&sctx))
1748 goto shutdown; 1750 goto shutdown;
1749 LOG (GNUNET_ERROR_TYPE_DEBUG, 1751 LOG (GNUNET_ERROR_TYPE_DEBUG,
1750 "Service `%s' runs with configuration from `%s'\n", serviceName, cfg_fn); 1752 "Service `%s' runs with configuration from `%s'\n", service_name, cfg_fn);
1751 if ((GNUNET_OK == 1753 if ((GNUNET_OK ==
1752 GNUNET_CONFIGURATION_get_value_number (sctx.cfg, "TESTING", 1754 GNUNET_CONFIGURATION_get_value_number (sctx.cfg, "TESTING",
1753 "SKEW_OFFSET", &skew_offset)) && 1755 "SKEW_OFFSET", &skew_offset)) &&
@@ -1799,13 +1801,15 @@ shutdown:
1799 * Run a service startup sequence within an existing 1801 * Run a service startup sequence within an existing
1800 * initialized system. 1802 * initialized system.
1801 * 1803 *
1802 * @param serviceName our service name 1804 * @param service_name our service name
1803 * @param cfg configuration to use 1805 * @param cfg configuration to use
1806 * @param options service options
1804 * @return NULL on error, service handle 1807 * @return NULL on error, service handle
1805 */ 1808 */
1806struct GNUNET_SERVICE_Context * 1809struct GNUNET_SERVICE_Context *
1807GNUNET_SERVICE_start (const char *serviceName, 1810GNUNET_SERVICE_start (const char *service_name,
1808 const struct GNUNET_CONFIGURATION_Handle *cfg) 1811 const struct GNUNET_CONFIGURATION_Handle *cfg,
1812 enum GNUNET_SERVICE_Options options)
1809{ 1813{
1810 int i; 1814 int i;
1811 struct GNUNET_SERVICE_Context *sctx; 1815 struct GNUNET_SERVICE_Context *sctx;
@@ -1814,8 +1818,9 @@ GNUNET_SERVICE_start (const char *serviceName,
1814 sctx->ready_confirm_fd = -1; /* no daemonizing */ 1818 sctx->ready_confirm_fd = -1; /* no daemonizing */
1815 sctx->ret = GNUNET_OK; 1819 sctx->ret = GNUNET_OK;
1816 sctx->timeout = GNUNET_TIME_UNIT_FOREVER_REL; 1820 sctx->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1817 sctx->serviceName = serviceName; 1821 sctx->service_name = service_name;
1818 sctx->cfg = cfg; 1822 sctx->cfg = cfg;
1823 sctx->options = options;
1819 1824
1820 /* setup subsystems */ 1825 /* setup subsystems */
1821 if (GNUNET_OK != setup_service (sctx)) 1826 if (GNUNET_OK != setup_service (sctx))