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 * Have we gotten the #GNUNET_MESSAGE_TYPE_CORE_INIT message
93 * from this client already?
98 * Number of types of incoming messages this client
99 * specifically cares about. Size of the @e types array.
109 struct GNUNET_PeerIdentity GSC_my_identity;
114 const struct GNUNET_CONFIGURATION_Handle *GSC_cfg;
117 * For creating statistics.
119 struct GNUNET_STATISTICS_Handle *GSC_stats;
122 * Big "or" of all client options.
124 static uint32_t all_client_options;
127 * Head of linked list of our clients.
129 static struct GSC_Client *client_head;
132 * Tail of linked list of our clients.
134 static struct GSC_Client *client_tail;
138 * Test if the client is interested in messages of the given type.
140 * @param type message type
141 * @param c client to test
142 * @return #GNUNET_YES if @a c is interested, #GNUNET_NO if not.
145 type_match (uint16_t type,
146 struct GSC_Client *c)
148 if ( (0 == c->tcnt) &&
150 return GNUNET_YES; /* peer without handlers and inbound/outbond
151 callbacks matches ALL */
152 if (NULL == c->types)
154 for (unsigned int i = 0; i < c->tcnt; i++)
155 if (type == c->types[i])
162 * Check #GNUNET_MESSAGE_TYPE_CORE_INIT request.
164 * @param cls client that sent #GNUNET_MESSAGE_TYPE_CORE_INIT
165 * @param im the `struct InitMessage`
166 * @return #GNUNET_OK if @a im is well-formed
169 check_client_init (void *cls,
170 const struct InitMessage *im)
177 * Handle #GNUNET_MESSAGE_TYPE_CORE_INIT request.
179 * @param cls client that sent #GNUNET_MESSAGE_TYPE_CORE_INIT
180 * @param im the `struct InitMessage`
183 handle_client_init (void *cls,
184 const struct InitMessage *im)
186 struct GSC_Client *c = cls;
187 struct GNUNET_MQ_Envelope *env;
188 struct InitReplyMessage *irm;
190 const uint16_t *types;
192 /* check that we don't have an entry already */
193 msize = ntohs (im->header.size) - sizeof (struct InitMessage);
194 types = (const uint16_t *) &im[1];
195 c->tcnt = msize / sizeof (uint16_t);
196 c->options = ntohl (im->options);
197 c->got_init = GNUNET_YES;
198 all_client_options |= c->options;
199 c->types = GNUNET_malloc (msize);
200 GNUNET_assert (GNUNET_YES ==
201 GNUNET_CONTAINER_multipeermap_put (c->connectmap,
204 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
205 for (unsigned int i = 0; i < c->tcnt; i++)
206 c->types[i] = ntohs (types[i]);
207 GSC_TYPEMAP_add (c->types,
209 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
210 "Client connecting to core service is interested in %u message types\n",
211 (unsigned int) c->tcnt);
212 /* send init reply message */
213 env = GNUNET_MQ_msg (irm,
214 GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY);
215 irm->reserved = htonl (0);
216 irm->my_identity = GSC_my_identity;
217 GNUNET_MQ_send (c->mq,
219 GSC_SESSIONS_notify_client_about_sessions (c);
220 GNUNET_SERVICE_client_continue (c->client);
225 * We will never be ready to transmit the given message in (disconnect
226 * or invalid request). Frees resources associated with @a car. We
227 * don't explicitly tell the client, he'll learn with the disconnect
228 * (or violated the protocol).
230 * @param car request that now permanently failed; the
231 * responsibility for the handle is now returned
232 * to CLIENTS (SESSIONS is done with it).
233 * @param drop_client #GNUNET_YES if the client violated the protocol
234 * and we should thus drop the connection
237 GSC_CLIENTS_reject_request (struct GSC_ClientActiveRequest *car,
240 GNUNET_assert (GNUNET_YES ==
241 GNUNET_CONTAINER_multipeermap_remove (car->
242 client_handle->requests,
245 if (GNUNET_YES == drop_client)
246 GNUNET_SERVICE_client_drop (car->client_handle->client);
252 * Tell a client that we are ready to receive the message.
254 * @param car request that is now ready; the responsibility
255 * for the handle remains shared between CLIENTS
256 * and SESSIONS after this call.
259 GSC_CLIENTS_solicit_request (struct GSC_ClientActiveRequest *car)
261 struct GSC_Client *c;
262 struct GNUNET_MQ_Envelope *env;
263 struct SendMessageReady *smr;
264 struct GNUNET_TIME_Relative delay;
265 struct GNUNET_TIME_Relative left;
267 c = car->client_handle;
269 GNUNET_CONTAINER_multipeermap_contains (c->connectmap,
272 /* connection has gone down since, drop request */
274 memcmp (&car->target,
276 sizeof (struct GNUNET_PeerIdentity)));
277 GSC_SESSIONS_dequeue_request (car);
278 GSC_CLIENTS_reject_request (car,
282 delay = GNUNET_TIME_absolute_get_duration (car->received_time);
283 left = GNUNET_TIME_absolute_get_duration (car->deadline);
284 if (delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
285 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
286 "Client waited %s for permission to transmit to `%s'%s (priority %u)\n",
287 GNUNET_STRINGS_relative_time_to_string (delay,
289 GNUNET_i2s (&car->target),
290 (0 == left.rel_value_us)
294 env = GNUNET_MQ_msg (smr,
295 GNUNET_MESSAGE_TYPE_CORE_SEND_READY);
296 smr->size = htons (car->msize);
297 smr->smr_id = car->smr_id;
298 smr->peer = car->target;
299 GNUNET_MQ_send (c->mq,
305 * Handle #GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST message.
307 * @param cls client that sent a #GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST
308 * @param req the `struct SendMessageRequest`
311 handle_client_send_request (void *cls,
312 const struct SendMessageRequest *req)
314 struct GSC_Client *c = cls;
315 struct GSC_ClientActiveRequest *car;
318 if (NULL == c->requests)
319 c->requests = GNUNET_CONTAINER_multipeermap_create (16,
321 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
322 "Client asked for transmission to `%s'\n",
323 GNUNET_i2s (&req->peer));
328 sizeof (struct GNUNET_PeerIdentity)));
329 if ((! is_loopback) &&
331 GNUNET_CONTAINER_multipeermap_contains (c->connectmap,
334 /* neighbour must have disconnected since request was issued,
335 * ignore (client will realize it once it processes the
336 * disconnect notification) */
337 GNUNET_STATISTICS_update (GSC_stats,
339 ("# send requests dropped (disconnected)"), 1,
341 GNUNET_SERVICE_client_continue (c->client);
345 car = GNUNET_CONTAINER_multipeermap_get (c->requests,
349 /* create new entry */
350 car = GNUNET_new (struct GSC_ClientActiveRequest);
351 GNUNET_assert (GNUNET_OK ==
352 GNUNET_CONTAINER_multipeermap_put (c->requests,
355 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
356 car->client_handle = c;
360 /* dequeue and recycle memory from pending request, there can only
361 be at most one per client and peer */
362 GNUNET_STATISTICS_update (GSC_stats,
363 gettext_noop ("# dequeuing CAR (duplicate request)"),
366 GSC_SESSIONS_dequeue_request (car);
367 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
368 "Transmission request to `%s' was a duplicate!\n",
369 GNUNET_i2s (&req->peer));
371 car->target = req->peer;
372 car->received_time = GNUNET_TIME_absolute_get ();
373 car->deadline = GNUNET_TIME_absolute_ntoh (req->deadline);
374 car->priority = (enum GNUNET_CORE_Priority) ntohl (req->priority);
375 car->msize = ntohs (req->size);
376 car->smr_id = req->smr_id;
377 car->was_solicited = GNUNET_NO;
378 GNUNET_SERVICE_client_continue (c->client);
381 /* loopback, satisfy immediately */
382 GSC_CLIENTS_solicit_request (car);
385 GSC_SESSIONS_queue_request (car);
390 * Closure for the #client_tokenizer_callback().
392 struct TokenizerContext
396 * Active request handle for the message.
398 struct GSC_ClientActiveRequest *car;
401 * How important is this message.
403 enum GNUNET_CORE_Priority priority;
406 * Is corking allowed (set only once we have the real message).
414 * Functions with this signature are called whenever a complete
415 * message is received by the tokenizer. Used by
416 * #handle_client_send() for dispatching messages from clients to
417 * either the SESSION subsystem or other CLIENT (for loopback).
419 * @param cls reservation request (`struct TokenizerContext`)
420 * @param message the actual message
423 tokenized_cb (void *cls,
424 const struct GNUNET_MessageHeader *message)
426 struct TokenizerContext *tc = cls;
427 struct GSC_ClientActiveRequest *car = tc->car;
430 GNUNET_snprintf (buf,
432 gettext_noop ("# bytes of messages of type %u received"),
433 (unsigned int) ntohs (message->type));
434 GNUNET_STATISTICS_update (GSC_stats,
436 ntohs (message->size),
439 memcmp (&car->target,
441 sizeof (struct GNUNET_PeerIdentity)))
443 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
444 "Delivering message of type %u to myself\n",
445 ntohs (message->type));
446 GSC_CLIENTS_deliver_message (&GSC_my_identity,
448 ntohs (message->size),
449 GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND);
450 GSC_CLIENTS_deliver_message (&GSC_my_identity,
452 sizeof (struct GNUNET_MessageHeader),
453 GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND);
454 GSC_CLIENTS_deliver_message (&GSC_my_identity,
456 ntohs (message->size),
457 GNUNET_CORE_OPTION_SEND_FULL_INBOUND);
458 GSC_CLIENTS_deliver_message (&GSC_my_identity,
460 sizeof (struct GNUNET_MessageHeader),
461 GNUNET_CORE_OPTION_SEND_HDR_INBOUND);
465 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
466 "Delivering message of type %u and size %u to %s\n",
467 ntohs (message->type),
468 ntohs (message->size),
469 GNUNET_i2s (&car->target));
470 GSC_CLIENTS_deliver_message (&car->target,
472 ntohs (message->size),
473 GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND);
474 GSC_CLIENTS_deliver_message (&car->target,
476 sizeof (struct GNUNET_MessageHeader),
477 GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND);
478 GSC_SESSIONS_transmit (car,
488 * Check #GNUNET_MESSAGE_TYPE_CORE_SEND request.
490 * @param cls the `struct GSC_Client`
491 * @param sm the `struct SendMessage`
492 * @return #GNUNET_OK if @a sm is well-formed
495 check_client_send (void *cls,
496 const struct SendMessage *sm)
503 * Handle #GNUNET_MESSAGE_TYPE_CORE_SEND request.
505 * @param cls the `struct GSC_Client`
506 * @param sm the `struct SendMessage`
509 handle_client_send (void *cls,
510 const struct SendMessage *sm)
512 struct GSC_Client *c = cls;
513 struct TokenizerContext tc;
515 struct GNUNET_TIME_Relative delay;
516 struct GNUNET_MessageStreamTokenizer *mst;
518 msize = ntohs (sm->header.size) - sizeof (struct SendMessage);
519 GNUNET_break (0 == ntohl (sm->reserved));
520 tc.car = GNUNET_CONTAINER_multipeermap_get (c->requests,
524 /* Must have been that we first approved the request, then got disconnected
525 * (which triggered removal of the 'car') and now the client gives us a message
526 * just *before* the client learns about the disconnect. Theoretically, we
527 * might also now be *again* connected. So this can happen (but should be
528 * rare). If it does happen, the message is discarded. */
529 GNUNET_STATISTICS_update (GSC_stats,
530 gettext_noop ("# messages discarded (session disconnected)"),
533 GNUNET_SERVICE_client_continue (c->client);
536 delay = GNUNET_TIME_absolute_get_duration (tc.car->received_time);
537 tc.cork = ntohl (sm->cork);
538 tc.priority = (enum GNUNET_CORE_Priority) ntohl (sm->priority);
539 if (delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
540 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
541 "Client waited %s for transmission of %u bytes to `%s'%s\n",
542 GNUNET_STRINGS_relative_time_to_string (delay,
545 GNUNET_i2s (&sm->peer),
546 tc.cork ? " (cork)" : " (uncorked)");
548 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
549 "Client waited %s for transmission of %u bytes to `%s'%s\n",
550 GNUNET_STRINGS_relative_time_to_string (delay,
553 GNUNET_i2s (&sm->peer),
554 tc.cork ? " (cork)" : " (uncorked)");
556 GNUNET_assert (GNUNET_YES ==
557 GNUNET_CONTAINER_multipeermap_remove (c->requests,
560 mst = GNUNET_MST_create (&tokenized_cb,
562 GNUNET_MST_from_buffer (mst,
563 (const char *) &sm[1],
567 GNUNET_MST_destroy (mst);
568 GSC_SESSIONS_dequeue_request (tc.car);
569 GNUNET_free (tc.car);
570 GNUNET_SERVICE_client_continue (c->client);
575 * Free client request records.
578 * @param key identity of peer for which this is an active request
579 * @param value the `struct GSC_ClientActiveRequest` to free
580 * @return #GNUNET_YES (continue iteration)
583 destroy_active_client_request (void *cls,
584 const struct GNUNET_PeerIdentity *key,
587 struct GSC_ClientActiveRequest *car = value;
589 GNUNET_assert (GNUNET_YES ==
590 GNUNET_CONTAINER_multipeermap_remove (car->
591 client_handle->requests,
594 GSC_SESSIONS_dequeue_request (car);
601 * A client connected, set up.
604 * @param client identification of the client
605 * @param mq message queue to talk to @a client
606 * @return our client handle
609 client_connect_cb (void *cls,
610 struct GNUNET_SERVICE_Client *client,
611 struct GNUNET_MQ_Handle *mq)
613 struct GSC_Client *c;
615 c = GNUNET_new (struct GSC_Client);
618 c->connectmap = GNUNET_CONTAINER_multipeermap_create (16,
620 GNUNET_CONTAINER_DLL_insert (client_head,
628 * A client disconnected, clean up.
631 * @param client identification of the client
632 * @param app_ctx our `struct GST_Client` for @a client
635 client_disconnect_cb (void *cls,
636 struct GNUNET_SERVICE_Client *client,
639 struct GSC_Client *c = app_ctx;
641 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
642 "Client %p has disconnected from core service.\n",
644 GNUNET_CONTAINER_DLL_remove (client_head,
647 if (NULL != c->requests)
649 GNUNET_CONTAINER_multipeermap_iterate (c->requests,
650 &destroy_active_client_request,
652 GNUNET_CONTAINER_multipeermap_destroy (c->requests);
654 GNUNET_CONTAINER_multipeermap_destroy (c->connectmap);
655 c->connectmap = NULL;
656 if (NULL != c->types)
658 GSC_TYPEMAP_remove (c->types,
660 GNUNET_free (c->types);
664 /* recalculate 'all_client_options' */
665 all_client_options = 0;
666 for (c = client_head; NULL != c ; c = c->next)
667 all_client_options |= c->options;
672 * Notify a particular client about a change to existing connection to
673 * one of our neighbours (check if the client is interested). Called
674 * from #GSC_SESSIONS_notify_client_about_sessions().
676 * @param client client to notify
677 * @param neighbour identity of the neighbour that changed status
678 * @param tmap_old previous type map for the neighbour, NULL for connect
679 * @param tmap_new updated type map for the neighbour, NULL for disconnect
682 GSC_CLIENTS_notify_client_about_neighbour (struct GSC_Client *client,
683 const struct GNUNET_PeerIdentity *neighbour,
684 const struct GSC_TypeMap *tmap_old,
685 const struct GSC_TypeMap *tmap_new)
687 struct GNUNET_MQ_Envelope *env;
691 if (GNUNET_YES != client->got_init)
693 old_match = GSC_TYPEMAP_test_match (tmap_old,
696 new_match = GSC_TYPEMAP_test_match (tmap_new,
699 if (old_match == new_match)
701 GNUNET_assert (old_match ==
702 GNUNET_CONTAINER_multipeermap_contains (client->connectmap,
704 return; /* no change */
706 if (GNUNET_NO == old_match)
708 struct ConnectNotifyMessage *cnm;
711 GNUNET_assert (GNUNET_NO ==
712 GNUNET_CONTAINER_multipeermap_contains (client->connectmap,
714 GNUNET_assert (GNUNET_YES ==
715 GNUNET_CONTAINER_multipeermap_put (client->connectmap,
718 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
719 env = GNUNET_MQ_msg (cnm,
720 GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
721 cnm->reserved = htonl (0);
722 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
723 "Sending NOTIFY_CONNECT message to client.\n");
724 cnm->peer = *neighbour;
725 GNUNET_MQ_send (client->mq,
730 struct DisconnectNotifyMessage *dcm;
732 /* send disconnect */
733 GNUNET_assert (GNUNET_YES ==
734 GNUNET_CONTAINER_multipeermap_contains (client->connectmap,
736 GNUNET_assert (GNUNET_YES ==
737 GNUNET_CONTAINER_multipeermap_remove (client->connectmap,
740 env = GNUNET_MQ_msg (dcm,
741 GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT);
742 dcm->reserved = htonl (0);
743 dcm->peer = *neighbour;
744 GNUNET_MQ_send (client->mq,
751 * Notify all clients about a change to existing session.
752 * Called from SESSIONS whenever there is a change in sessions
753 * or types processed by the respective peer.
755 * @param neighbour identity of the neighbour that changed status
756 * @param tmap_old previous type map for the neighbour, NULL for connect
757 * @param tmap_new updated type map for the neighbour, NULL for disconnect
760 GSC_CLIENTS_notify_clients_about_neighbour (const struct GNUNET_PeerIdentity *neighbour,
761 const struct GSC_TypeMap *tmap_old,
762 const struct GSC_TypeMap *tmap_new)
764 struct GSC_Client *c;
766 for (c = client_head; NULL != c; c = c->next)
767 GSC_CLIENTS_notify_client_about_neighbour (c,
775 * Deliver P2P message to interested clients. Caller must have checked
776 * that the sending peer actually lists the given message type as one
779 * @param sender peer who sent us the message
780 * @param msg the message
781 * @param msize number of bytes to transmit
782 * @param options options for checking which clients should
783 * receive the message
786 GSC_CLIENTS_deliver_message (const struct GNUNET_PeerIdentity *sender,
787 const struct GNUNET_MessageHeader *msg,
791 size_t size = msize + sizeof (struct NotifyTrafficMessage);
793 if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
798 if (! ( (0 != (all_client_options & options)) ||
799 (0 != (options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) ))
800 return; /* no client cares about this message notification */
801 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
802 "Core service passes message from `%s' of type %u to client.\n",
804 (unsigned int) ntohs (msg->type));
805 GSC_SESSIONS_add_to_typemap (sender,
808 for (struct GSC_Client *c = client_head; NULL != c; c = c->next)
810 struct GNUNET_MQ_Envelope *env;
811 struct NotifyTrafficMessage *ntm;
815 tm = type_match (ntohs (msg->type),
817 if (! ( (0 != (c->options & options)) ||
818 ( (0 != (options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) &&
819 (GNUNET_YES == tm) ) ) )
820 continue; /* neither options nor type match permit the message */
821 if ( (0 != (options & GNUNET_CORE_OPTION_SEND_HDR_INBOUND)) &&
822 ( (0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) ||
823 (GNUNET_YES == tm) ) )
825 if ( (0 != (options & GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND)) &&
826 (0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND)) )
828 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
829 "Sending %u message with %u bytes to client interested in messages of type %u.\n",
832 (unsigned int) ntohs (msg->type));
834 if (0 != (options & (GNUNET_CORE_OPTION_SEND_FULL_INBOUND | GNUNET_CORE_OPTION_SEND_HDR_INBOUND)))
835 mtype = GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND;
837 mtype = GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND;
838 env = GNUNET_MQ_msg_extra (ntm,
842 GNUNET_memcpy (&ntm[1],
846 GNUNET_assert ( (0 == (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) ||
847 (GNUNET_YES != tm) ||
849 GNUNET_CONTAINER_multipeermap_contains (c->connectmap,
851 GNUNET_MQ_send (c->mq,
858 * Last task run during shutdown. Disconnects us from
861 * @param cls NULL, unused
864 shutdown_task (void *cls)
866 struct GSC_Client *c;
868 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
869 "Core service shutting down.\n");
870 while (NULL != (c = client_head))
871 GNUNET_SERVICE_client_drop (c->client);
872 GSC_SESSIONS_done ();
875 if (NULL != GSC_stats)
877 GNUNET_STATISTICS_destroy (GSC_stats,
886 * Handle #GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request. For this
887 * request type, the client does not have to have transmitted an INIT
888 * request. All current peers are returned, regardless of which
889 * message types they accept.
891 * @param cls client sending the iteration request
892 * @param message iteration request message
895 handle_client_monitor_peers (void *cls,
896 const struct GNUNET_MessageHeader *message)
898 struct GSC_Client *c = cls;
900 GNUNET_SERVICE_client_continue (c->client);
901 GSC_KX_handle_client_monitor_peers (c->mq);
906 * Initiate core service.
909 * @param c configuration to use
910 * @param service the initialized service
914 const struct GNUNET_CONFIGURATION_Handle *c,
915 struct GNUNET_SERVICE_Handle *service)
917 struct GNUNET_CRYPTO_EddsaPrivateKey *pk;
922 GNUNET_CONFIGURATION_get_value_filename (GSC_cfg,
927 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
928 _("Core service is lacking HOSTKEY configuration setting. Exiting.\n"));
929 GNUNET_SCHEDULER_shutdown ();
932 GSC_stats = GNUNET_STATISTICS_create ("core",
934 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
936 GNUNET_SERVICE_suspend (service);
938 pk = GNUNET_CRYPTO_eddsa_key_create_from_file (keyfile);
939 GNUNET_free (keyfile);
940 GNUNET_assert (NULL != pk);
941 if (GNUNET_OK != GSC_KX_init (pk))
943 GNUNET_SCHEDULER_shutdown ();
946 GSC_SESSIONS_init ();
947 GNUNET_SERVICE_resume (service);
948 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
949 _("Core service of `%s' ready.\n"),
950 GNUNET_i2s (&GSC_my_identity));
955 * Define "main" method using service macro.
959 GNUNET_SERVICE_OPTION_NONE,
962 &client_disconnect_cb,
964 GNUNET_MQ_hd_var_size (client_init,
965 GNUNET_MESSAGE_TYPE_CORE_INIT,
968 GNUNET_MQ_hd_fixed_size (client_monitor_peers,
969 GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS,
970 struct GNUNET_MessageHeader,
972 GNUNET_MQ_hd_fixed_size (client_send_request,
973 GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST,
974 struct SendMessageRequest,
976 GNUNET_MQ_hd_var_size (client_send,
977 GNUNET_MESSAGE_TYPE_CORE_SEND,
980 GNUNET_MQ_handler_end ());
983 /* end of gnunet-service-core.c */