2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011, 2016 GNUnet e.V.
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
22 * @file core/gnunet-service-core.c
23 * @brief high-level P2P messaging
24 * @author Christian Grothoff
28 #include "gnunet_util_lib.h"
29 #include "gnunet-service-core.h"
30 #include "gnunet-service-core_kx.h"
31 #include "gnunet-service-core_sessions.h"
32 #include "gnunet-service-core_typemap.h"
35 * How many messages do we queue up at most for optional
36 * notifications to a client? (this can cause notifications
37 * about outgoing messages to be dropped).
39 #define MAX_NOTIFY_QUEUE 1024
43 * Data structure for each client connected to the CORE service.
48 * Clients are kept in a linked list.
50 struct GSC_Client *next;
53 * Clients are kept in a linked list.
55 struct GSC_Client *prev;
58 * Handle for the client with the server API.
60 struct GNUNET_SERVICE_Client *client;
63 * Message queue to talk to @e client.
65 struct GNUNET_MQ_Handle *mq;
68 * Array of the types of messages this peer cares
69 * about (with @e tcnt entries). Allocated as part
70 * of this client struct, do not free!
75 * Map of peer identities to active transmission requests of this
76 * client to the peer (of type `struct GSC_ClientActiveRequest`).
78 struct GNUNET_CONTAINER_MultiPeerMap *requests;
81 * Map containing all peers that this client knows we're connected to.
83 struct GNUNET_CONTAINER_MultiPeerMap *connectmap;
86 * Options for messages this client cares about,
87 * see GNUNET_CORE_OPTION_ values.
92 * Number of types of incoming messages this client
93 * specifically cares about. Size of the @e types array.
103 struct GNUNET_PeerIdentity GSC_my_identity;
108 const struct GNUNET_CONFIGURATION_Handle *GSC_cfg;
111 * For creating statistics.
113 struct GNUNET_STATISTICS_Handle *GSC_stats;
116 * Big "or" of all client options.
118 static uint32_t all_client_options;
121 * Head of linked list of our clients.
123 static struct GSC_Client *client_head;
126 * Tail of linked list of our clients.
128 static struct GSC_Client *client_tail;
132 * Test if the client is interested in messages of the given type.
134 * @param type message type
135 * @param c client to test
136 * @return #GNUNET_YES if @a c is interested, #GNUNET_NO if not.
139 type_match (uint16_t type,
140 struct GSC_Client *c)
142 if ( (0 == c->tcnt) &&
144 return GNUNET_YES; /* peer without handlers and inbound/outbond
145 callbacks matches ALL */
146 if (NULL == c->types)
148 for (unsigned int i = 0; i < c->tcnt; i++)
149 if (type == c->types[i])
156 * Check #GNUNET_MESSAGE_TYPE_CORE_INIT request.
158 * @param cls client that sent #GNUNET_MESSAGE_TYPE_CORE_INIT
159 * @param im the `struct InitMessage`
160 * @return #GNUNET_OK if @a im is well-formed
163 check_client_init (void *cls,
164 const struct InitMessage *im)
171 * Handle #GNUNET_MESSAGE_TYPE_CORE_INIT request.
173 * @param cls client that sent #GNUNET_MESSAGE_TYPE_CORE_INIT
174 * @param im the `struct InitMessage`
177 handle_client_init (void *cls,
178 const struct InitMessage *im)
180 struct GSC_Client *c = cls;
181 struct GNUNET_MQ_Envelope *env;
182 struct InitReplyMessage *irm;
184 const uint16_t *types;
186 /* check that we don't have an entry already */
187 msize = ntohs (im->header.size) - sizeof (struct InitMessage);
188 types = (const uint16_t *) &im[1];
189 c->tcnt = msize / sizeof (uint16_t);
190 c->options = ntohl (im->options);
191 all_client_options |= c->options;
192 c->types = GNUNET_malloc (msize);
193 GNUNET_assert (GNUNET_YES ==
194 GNUNET_CONTAINER_multipeermap_put (c->connectmap,
197 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
198 for (unsigned int i = 0; i < c->tcnt; i++)
199 c->types[i] = ntohs (types[i]);
200 GSC_TYPEMAP_add (c->types,
202 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
203 "Client connecting to core service is interested in %u message types\n",
204 (unsigned int) c->tcnt);
205 /* send init reply message */
206 env = GNUNET_MQ_msg (irm,
207 GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY);
208 irm->reserved = htonl (0);
209 irm->my_identity = GSC_my_identity;
210 GNUNET_MQ_send (c->mq,
212 GSC_SESSIONS_notify_client_about_sessions (c);
213 GNUNET_SERVICE_client_continue (c->client);
218 * We will never be ready to transmit the given message in (disconnect
219 * or invalid request). Frees resources associated with @a car. We
220 * don't explicitly tell the client, he'll learn with the disconnect
221 * (or violated the protocol).
223 * @param car request that now permanently failed; the
224 * responsibility for the handle is now returned
225 * to CLIENTS (SESSIONS is done with it).
226 * @param drop_client #GNUNET_YES if the client violated the protocol
227 * and we should thus drop the connection
230 GSC_CLIENTS_reject_request (struct GSC_ClientActiveRequest *car,
233 GNUNET_assert (GNUNET_YES ==
234 GNUNET_CONTAINER_multipeermap_remove (car->
235 client_handle->requests,
238 if (GNUNET_YES == drop_client)
239 GNUNET_SERVICE_client_drop (car->client_handle->client);
245 * Tell a client that we are ready to receive the message.
247 * @param car request that is now ready; the responsibility
248 * for the handle remains shared between CLIENTS
249 * and SESSIONS after this call.
252 GSC_CLIENTS_solicit_request (struct GSC_ClientActiveRequest *car)
254 struct GSC_Client *c;
255 struct GNUNET_MQ_Envelope *env;
256 struct SendMessageReady *smr;
257 struct GNUNET_TIME_Relative delay;
258 struct GNUNET_TIME_Relative left;
260 c = car->client_handle;
262 GNUNET_CONTAINER_multipeermap_contains (c->connectmap,
265 /* connection has gone down since, drop request */
267 memcmp (&car->target,
269 sizeof (struct GNUNET_PeerIdentity)));
270 GSC_SESSIONS_dequeue_request (car);
271 GSC_CLIENTS_reject_request (car,
275 delay = GNUNET_TIME_absolute_get_duration (car->received_time);
276 left = GNUNET_TIME_absolute_get_duration (car->deadline);
277 if (delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
278 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
279 "Client waited %s for permission to transmit to `%s'%s (priority %u)\n",
280 GNUNET_STRINGS_relative_time_to_string (delay,
282 GNUNET_i2s (&car->target),
283 (0 == left.rel_value_us)
287 env = GNUNET_MQ_msg (smr,
288 GNUNET_MESSAGE_TYPE_CORE_SEND_READY);
289 smr->size = htons (car->msize);
290 smr->smr_id = car->smr_id;
291 smr->peer = car->target;
292 GNUNET_MQ_send (c->mq,
298 * Handle #GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST message.
300 * @param cls client that sent a #GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST
301 * @param req the `struct SendMessageRequest`
304 handle_client_send_request (void *cls,
305 const struct SendMessageRequest *req)
307 struct GSC_Client *c = cls;
308 struct GSC_ClientActiveRequest *car;
311 if (NULL == c->requests)
312 c->requests = GNUNET_CONTAINER_multipeermap_create (16,
314 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
315 "Client asked for transmission to `%s'\n",
316 GNUNET_i2s (&req->peer));
321 sizeof (struct GNUNET_PeerIdentity)));
322 if ((! is_loopback) &&
324 GNUNET_CONTAINER_multipeermap_contains (c->connectmap,
327 /* neighbour must have disconnected since request was issued,
328 * ignore (client will realize it once it processes the
329 * disconnect notification) */
330 GNUNET_STATISTICS_update (GSC_stats,
332 ("# send requests dropped (disconnected)"), 1,
334 GNUNET_SERVICE_client_continue (c->client);
338 car = GNUNET_CONTAINER_multipeermap_get (c->requests,
342 /* create new entry */
343 car = GNUNET_new (struct GSC_ClientActiveRequest);
344 GNUNET_assert (GNUNET_OK ==
345 GNUNET_CONTAINER_multipeermap_put (c->requests,
348 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
349 car->client_handle = c;
353 /* dequeue and recycle memory from pending request, there can only
354 be at most one per client and peer */
355 GNUNET_STATISTICS_update (GSC_stats,
356 gettext_noop ("# dequeuing CAR (duplicate request)"),
359 GSC_SESSIONS_dequeue_request (car);
360 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
361 "Transmission request to `%s' was a duplicate!\n",
362 GNUNET_i2s (&req->peer));
364 car->target = req->peer;
365 car->received_time = GNUNET_TIME_absolute_get ();
366 car->deadline = GNUNET_TIME_absolute_ntoh (req->deadline);
367 car->priority = (enum GNUNET_CORE_Priority) ntohl (req->priority);
368 car->msize = ntohs (req->size);
369 car->smr_id = req->smr_id;
370 car->was_solicited = GNUNET_NO;
371 GNUNET_SERVICE_client_continue (c->client);
374 /* loopback, satisfy immediately */
375 GSC_CLIENTS_solicit_request (car);
378 GSC_SESSIONS_queue_request (car);
383 * Closure for the #client_tokenizer_callback().
385 struct TokenizerContext
389 * Active request handle for the message.
391 struct GSC_ClientActiveRequest *car;
394 * How important is this message.
396 enum GNUNET_CORE_Priority priority;
399 * Is corking allowed (set only once we have the real message).
407 * Functions with this signature are called whenever a complete
408 * message is received by the tokenizer. Used by
409 * #handle_client_send() for dispatching messages from clients to
410 * either the SESSION subsystem or other CLIENT (for loopback).
412 * @param cls reservation request (`struct TokenizerContext`)
413 * @param message the actual message
416 tokenized_cb (void *cls,
417 const struct GNUNET_MessageHeader *message)
419 struct TokenizerContext *tc = cls;
420 struct GSC_ClientActiveRequest *car = tc->car;
423 GNUNET_snprintf (buf,
425 gettext_noop ("# bytes of messages of type %u received"),
426 (unsigned int) ntohs (message->type));
427 GNUNET_STATISTICS_update (GSC_stats,
429 ntohs (message->size),
432 memcmp (&car->target,
434 sizeof (struct GNUNET_PeerIdentity)))
436 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
437 "Delivering message of type %u to myself\n",
438 ntohs (message->type));
439 GSC_CLIENTS_deliver_message (&GSC_my_identity,
441 ntohs (message->size),
442 GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND);
443 GSC_CLIENTS_deliver_message (&GSC_my_identity,
445 sizeof (struct GNUNET_MessageHeader),
446 GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND);
447 GSC_CLIENTS_deliver_message (&GSC_my_identity,
449 ntohs (message->size),
450 GNUNET_CORE_OPTION_SEND_FULL_INBOUND);
451 GSC_CLIENTS_deliver_message (&GSC_my_identity,
453 sizeof (struct GNUNET_MessageHeader),
454 GNUNET_CORE_OPTION_SEND_HDR_INBOUND);
458 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
459 "Delivering message of type %u and size %u to %s\n",
460 ntohs (message->type),
461 ntohs (message->size),
462 GNUNET_i2s (&car->target));
463 GSC_CLIENTS_deliver_message (&car->target,
465 ntohs (message->size),
466 GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND);
467 GSC_CLIENTS_deliver_message (&car->target,
469 sizeof (struct GNUNET_MessageHeader),
470 GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND);
471 GSC_SESSIONS_transmit (car,
481 * Check #GNUNET_MESSAGE_TYPE_CORE_SEND request.
483 * @param cls the `struct GSC_Client`
484 * @param sm the `struct SendMessage`
485 * @return #GNUNET_OK if @a sm is well-formed
488 check_client_send (void *cls,
489 const struct SendMessage *sm)
496 * Handle #GNUNET_MESSAGE_TYPE_CORE_SEND request.
498 * @param cls the `struct GSC_Client`
499 * @param sm the `struct SendMessage`
502 handle_client_send (void *cls,
503 const struct SendMessage *sm)
505 struct GSC_Client *c = cls;
506 struct TokenizerContext tc;
508 struct GNUNET_TIME_Relative delay;
509 struct GNUNET_MessageStreamTokenizer *mst;
511 msize = ntohs (sm->header.size) - sizeof (struct SendMessage);
512 GNUNET_break (0 == ntohl (sm->reserved));
513 tc.car = GNUNET_CONTAINER_multipeermap_get (c->requests,
517 /* Must have been that we first approved the request, then got disconnected
518 * (which triggered removal of the 'car') and now the client gives us a message
519 * just *before* the client learns about the disconnect. Theoretically, we
520 * might also now be *again* connected. So this can happen (but should be
521 * rare). If it does happen, the message is discarded. */
522 GNUNET_STATISTICS_update (GSC_stats,
523 gettext_noop ("# messages discarded (session disconnected)"),
526 GNUNET_SERVICE_client_continue (c->client);
529 delay = GNUNET_TIME_absolute_get_duration (tc.car->received_time);
530 tc.cork = ntohl (sm->cork);
531 tc.priority = (enum GNUNET_CORE_Priority) ntohl (sm->priority);
532 if (delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
533 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
534 "Client waited %s for transmission of %u bytes to `%s'%s\n",
535 GNUNET_STRINGS_relative_time_to_string (delay,
538 GNUNET_i2s (&sm->peer),
539 tc.cork ? " (cork)" : " (uncorked)");
541 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
542 "Client waited %s for transmission of %u bytes to `%s'%s\n",
543 GNUNET_STRINGS_relative_time_to_string (delay,
546 GNUNET_i2s (&sm->peer),
547 tc.cork ? " (cork)" : " (uncorked)");
549 GNUNET_assert (GNUNET_YES ==
550 GNUNET_CONTAINER_multipeermap_remove (c->requests,
553 mst = GNUNET_MST_create (&tokenized_cb,
555 GNUNET_MST_from_buffer (mst,
556 (const char *) &sm[1],
560 GNUNET_MST_destroy (mst);
561 GSC_SESSIONS_dequeue_request (tc.car);
562 GNUNET_free (tc.car);
563 GNUNET_SERVICE_client_continue (c->client);
568 * Free client request records.
571 * @param key identity of peer for which this is an active request
572 * @param value the `struct GSC_ClientActiveRequest` to free
573 * @return #GNUNET_YES (continue iteration)
576 destroy_active_client_request (void *cls,
577 const struct GNUNET_PeerIdentity *key,
580 struct GSC_ClientActiveRequest *car = value;
582 GNUNET_assert (GNUNET_YES ==
583 GNUNET_CONTAINER_multipeermap_remove (car->
584 client_handle->requests,
587 GSC_SESSIONS_dequeue_request (car);
594 * A client connected, set up.
597 * @param client identification of the client
598 * @param mq message queue to talk to @a client
599 * @return our client handle
602 client_connect_cb (void *cls,
603 struct GNUNET_SERVICE_Client *client,
604 struct GNUNET_MQ_Handle *mq)
606 struct GSC_Client *c;
608 c = GNUNET_new (struct GSC_Client);
611 c->connectmap = GNUNET_CONTAINER_multipeermap_create (16,
613 GNUNET_CONTAINER_DLL_insert (client_head,
621 * A client disconnected, clean up.
624 * @param client identification of the client
625 * @param app_ctx our `struct GST_Client` for @a client
628 client_disconnect_cb (void *cls,
629 struct GNUNET_SERVICE_Client *client,
632 struct GSC_Client *c = app_ctx;
634 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
635 "Client %p has disconnected from core service.\n",
637 GNUNET_CONTAINER_DLL_remove (client_head,
640 if (NULL != c->requests)
642 GNUNET_CONTAINER_multipeermap_iterate (c->requests,
643 &destroy_active_client_request,
645 GNUNET_CONTAINER_multipeermap_destroy (c->requests);
647 GNUNET_CONTAINER_multipeermap_destroy (c->connectmap);
648 c->connectmap = NULL;
649 if (NULL != c->types)
651 GSC_TYPEMAP_remove (c->types,
653 GNUNET_free (c->types);
657 /* recalculate 'all_client_options' */
658 all_client_options = 0;
659 for (c = client_head; NULL != c ; c = c->next)
660 all_client_options |= c->options;
665 * Notify a particular client about a change to existing connection to
666 * one of our neighbours (check if the client is interested). Called
667 * from #GSC_SESSIONS_notify_client_about_sessions().
669 * @param client client to notify
670 * @param neighbour identity of the neighbour that changed status
671 * @param tmap_old previous type map for the neighbour, NULL for connect
672 * @param tmap_new updated type map for the neighbour, NULL for disconnect
675 GSC_CLIENTS_notify_client_about_neighbour (struct GSC_Client *client,
676 const struct GNUNET_PeerIdentity *neighbour,
677 const struct GSC_TypeMap *tmap_old,
678 const struct GSC_TypeMap *tmap_new)
680 struct GNUNET_MQ_Envelope *env;
684 old_match = GSC_TYPEMAP_test_match (tmap_old,
687 new_match = GSC_TYPEMAP_test_match (tmap_new,
690 if (old_match == new_match)
692 GNUNET_assert (old_match ==
693 GNUNET_CONTAINER_multipeermap_contains (client->connectmap,
695 return; /* no change */
697 if (GNUNET_NO == old_match)
699 struct ConnectNotifyMessage *cnm;
702 GNUNET_assert (GNUNET_NO ==
703 GNUNET_CONTAINER_multipeermap_contains (client->connectmap,
705 GNUNET_assert (GNUNET_YES ==
706 GNUNET_CONTAINER_multipeermap_put (client->connectmap,
709 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
710 env = GNUNET_MQ_msg (cnm,
711 GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
712 cnm->reserved = htonl (0);
713 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
714 "Sending NOTIFY_CONNECT message to client.\n");
715 cnm->peer = *neighbour;
716 GNUNET_MQ_send (client->mq,
721 struct DisconnectNotifyMessage *dcm;
723 /* send disconnect */
724 GNUNET_assert (GNUNET_YES ==
725 GNUNET_CONTAINER_multipeermap_contains (client->connectmap,
727 GNUNET_assert (GNUNET_YES ==
728 GNUNET_CONTAINER_multipeermap_remove (client->connectmap,
731 env = GNUNET_MQ_msg (dcm,
732 GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT);
733 dcm->reserved = htonl (0);
734 dcm->peer = *neighbour;
735 GNUNET_MQ_send (client->mq,
742 * Notify all clients about a change to existing session.
743 * Called from SESSIONS whenever there is a change in sessions
744 * or types processed by the respective peer.
746 * @param neighbour identity of the neighbour that changed status
747 * @param tmap_old previous type map for the neighbour, NULL for connect
748 * @param tmap_new updated type map for the neighbour, NULL for disconnect
751 GSC_CLIENTS_notify_clients_about_neighbour (const struct GNUNET_PeerIdentity *neighbour,
752 const struct GSC_TypeMap *tmap_old,
753 const struct GSC_TypeMap *tmap_new)
755 struct GSC_Client *c;
757 for (c = client_head; NULL != c; c = c->next)
758 GSC_CLIENTS_notify_client_about_neighbour (c,
766 * Deliver P2P message to interested clients. Caller must have checked
767 * that the sending peer actually lists the given message type as one
770 * @param sender peer who sent us the message
771 * @param msg the message
772 * @param msize number of bytes to transmit
773 * @param options options for checking which clients should
774 * receive the message
777 GSC_CLIENTS_deliver_message (const struct GNUNET_PeerIdentity *sender,
778 const struct GNUNET_MessageHeader *msg,
782 size_t size = msize + sizeof (struct NotifyTrafficMessage);
784 if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
789 if (! ( (0 != (all_client_options & options)) ||
790 (0 != (options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) ))
791 return; /* no client cares about this message notification */
792 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
793 "Core service passes message from `%s' of type %u to client.\n",
795 (unsigned int) ntohs (msg->type));
796 GSC_SESSIONS_add_to_typemap (sender,
799 for (struct GSC_Client *c = client_head; NULL != c; c = c->next)
801 struct GNUNET_MQ_Envelope *env;
802 struct NotifyTrafficMessage *ntm;
806 tm = type_match (ntohs (msg->type),
808 if (! ( (0 != (c->options & options)) ||
809 ( (0 != (options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) &&
810 (GNUNET_YES == tm) ) ) )
811 continue; /* neither options nor type match permit the message */
812 if ( (0 != (options & GNUNET_CORE_OPTION_SEND_HDR_INBOUND)) &&
813 ( (0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) ||
814 (GNUNET_YES == tm) ) )
816 if ( (0 != (options & GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND)) &&
817 (0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND)) )
819 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
820 "Sending %u message with %u bytes to client interested in messages of type %u.\n",
823 (unsigned int) ntohs (msg->type));
825 if (0 != (options & (GNUNET_CORE_OPTION_SEND_FULL_INBOUND | GNUNET_CORE_OPTION_SEND_HDR_INBOUND)))
826 mtype = GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND;
828 mtype = GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND;
829 env = GNUNET_MQ_msg_extra (ntm,
833 GNUNET_memcpy (&ntm[1],
837 GNUNET_assert ( (0 == (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) ||
838 (GNUNET_YES != tm) ||
840 GNUNET_CONTAINER_multipeermap_contains (c->connectmap,
842 GNUNET_MQ_send (c->mq,
849 * Last task run during shutdown. Disconnects us from
852 * @param cls NULL, unused
855 shutdown_task (void *cls)
857 struct GSC_Client *c;
859 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
860 "Core service shutting down.\n");
861 while (NULL != (c = client_head))
862 GNUNET_SERVICE_client_drop (c->client);
863 GSC_SESSIONS_done ();
866 if (NULL != GSC_stats)
868 GNUNET_STATISTICS_destroy (GSC_stats,
877 * Handle #GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request. For this
878 * request type, the client does not have to have transmitted an INIT
879 * request. All current peers are returned, regardless of which
880 * message types they accept.
882 * @param cls client sending the iteration request
883 * @param message iteration request message
886 handle_client_monitor_peers (void *cls,
887 const struct GNUNET_MessageHeader *message)
889 struct GSC_Client *c = cls;
891 GNUNET_SERVICE_client_continue (c->client);
892 GSC_KX_handle_client_monitor_peers (c->mq);
897 * Initiate core service.
900 * @param c configuration to use
901 * @param service the initialized service
905 const struct GNUNET_CONFIGURATION_Handle *c,
906 struct GNUNET_SERVICE_Handle *service)
908 struct GNUNET_CRYPTO_EddsaPrivateKey *pk;
913 GNUNET_CONFIGURATION_get_value_filename (GSC_cfg,
918 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
919 _("Core service is lacking HOSTKEY configuration setting. Exiting.\n"));
920 GNUNET_SCHEDULER_shutdown ();
923 GSC_stats = GNUNET_STATISTICS_create ("core",
925 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
927 GNUNET_SERVICE_suspend (service);
929 pk = GNUNET_CRYPTO_eddsa_key_create_from_file (keyfile);
930 GNUNET_free (keyfile);
931 GNUNET_assert (NULL != pk);
932 if (GNUNET_OK != GSC_KX_init (pk))
934 GNUNET_SCHEDULER_shutdown ();
937 GSC_SESSIONS_init ();
938 GNUNET_SERVICE_resume (service);
939 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
940 _("Core service of `%s' ready.\n"),
941 GNUNET_i2s (&GSC_my_identity));
946 * Define "main" method using service macro.
950 GNUNET_SERVICE_OPTION_NONE,
953 &client_disconnect_cb,
955 GNUNET_MQ_hd_var_size (client_init,
956 GNUNET_MESSAGE_TYPE_CORE_INIT,
959 GNUNET_MQ_hd_fixed_size (client_monitor_peers,
960 GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS,
961 struct GNUNET_MessageHeader,
963 GNUNET_MQ_hd_fixed_size (client_send_request,
964 GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST,
965 struct SendMessageRequest,
967 GNUNET_MQ_hd_var_size (client_send,
968 GNUNET_MESSAGE_TYPE_CORE_SEND,
971 GNUNET_MQ_handler_end ());
974 /* end of gnunet-service-core.c */