2 * This file is part of GNUnet
3 * (C) 2013 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
22 * @file social/gnunet-service-social.c
23 * @brief Social service
24 * @author Gabor X Toth
30 #include "gnunet_util_lib.h"
31 #include "gnunet_constants.h"
32 #include "gnunet_protocols.h"
33 #include "gnunet_statistics_service.h"
34 #include "gnunet_psyc_service.h"
35 #include "gnunet_social_service.h"
40 * Handle to our current configuration.
42 static const struct GNUNET_CONFIGURATION_Handle *cfg;
45 * Handle to the statistics service.
47 static struct GNUNET_STATISTICS_Handle *stats;
50 * Notification context, simplifies client broadcasts.
52 static struct GNUNET_SERVER_NotificationContext *nc;
55 * All connected hosts.
56 * Place's pub_key_hash -> struct Host
58 static struct GNUNET_CONTAINER_MultiHashMap *hosts;
61 * All connected guests.
62 * Place's pub_key_hash -> struct Guest
64 static struct GNUNET_CONTAINER_MultiHashMap *guests;
67 * Connected guests per place.
68 * Place's pub_key_hash -> Guest's pub_key -> struct Guest
70 static struct GNUNET_CONTAINER_MultiHashMap *place_guests;
74 * Message in the transmission queue.
76 struct TransmitMessage
78 struct TransmitMessage *prev;
79 struct TransmitMessage *next;
81 struct GNUNET_SERVER_Client *client;
84 * ID assigned to the message.
94 * @see enum MessageState
98 /* Followed by message */
103 * List of connected clients.
107 struct ClientList *prev;
108 struct ClientList *next;
109 struct GNUNET_SERVER_Client *client;
114 * Common part of the client context for both a host and guest.
118 struct ClientList *clients_head;
119 struct ClientList *clients_tail;
121 struct TransmitMessage *tmit_head;
122 struct TransmitMessage *tmit_tail;
125 * Public key of the channel.
127 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
130 * Hash of @a pub_key.
132 struct GNUNET_HashCode pub_key_hash;
135 * Is this a host (#GNUNET_YES), or guest (#GNUNET_NO)?
142 * Client context for a host.
147 * Place struct common for Host and Guest
152 * Private key of the channel.
154 struct GNUNET_CRYPTO_EddsaPrivateKey priv_key;
157 * Handle for the multicast origin.
159 struct GNUNET_PSYC_Master *master;
162 * Transmit handle for multicast.
164 struct GNUNET_PSYC_MasterTransmitHandle *tmit_handle;
167 * Incoming join requests.
168 * guest_key -> struct GNUNET_PSYC_JoinHandle *
170 struct GNUNET_CONTAINER_MultiHashMap *join_reqs;
173 * @see enum GNUNET_PSYC_Policy
175 enum GNUNET_PSYC_Policy policy;
180 * Client context for a guest.
185 * Place struct common for Host and Guest.
190 * Private key of the slave.
192 struct GNUNET_CRYPTO_EddsaPrivateKey priv_key;
195 * Public key of the slave.
197 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
200 * Hash of @a pub_key.
202 struct GNUNET_HashCode pub_key_hash;
205 * Handle for the PSYC slave.
207 struct GNUNET_PSYC_Slave *slave;
210 * Transmit handle for multicast.
212 struct GNUNET_PSYC_SlaveTransmitHandle *tmit_handle;
215 * Peer identity of the origin.
217 struct GNUNET_PeerIdentity origin;
220 * Number of items in @a relays.
222 uint32_t relay_count;
225 * Relays that multicast can use to connect.
227 struct GNUNET_PeerIdentity *relays;
230 * Join request to be transmitted to the master on join.
232 struct GNUNET_MessageHeader *join_req;
237 transmit_message (struct Place *pl);
241 * Task run during shutdown.
247 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
251 GNUNET_SERVER_notification_context_destroy (nc);
256 GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
263 * Clean up host data structures after a client disconnected.
266 cleanup_host (struct Host *hst)
268 struct Place *pl = &hst->pl;
270 if (NULL != hst->master)
271 GNUNET_PSYC_master_stop (hst->master);
272 GNUNET_CONTAINER_multihashmap_destroy (hst->join_reqs);
273 GNUNET_CONTAINER_multihashmap_remove (hosts, &pl->pub_key_hash, pl);
278 * Clean up guest data structures after a client disconnected.
281 cleanup_guest (struct Guest *gst)
283 struct Place *pl = &gst->pl;
284 struct GNUNET_CONTAINER_MultiHashMap *
285 pl_gst = GNUNET_CONTAINER_multihashmap_get (place_guests,
287 GNUNET_assert (NULL != pl_gst);
288 GNUNET_CONTAINER_multihashmap_remove (pl_gst, &gst->pub_key_hash, gst);
290 if (0 == GNUNET_CONTAINER_multihashmap_size (pl_gst))
292 GNUNET_CONTAINER_multihashmap_remove (place_guests, &pl->pub_key_hash,
294 GNUNET_CONTAINER_multihashmap_destroy (pl_gst);
296 GNUNET_CONTAINER_multihashmap_remove (guests, &pl->pub_key_hash, gst);
298 if (NULL != gst->join_req)
299 GNUNET_free (gst->join_req);
300 if (NULL != gst->relays)
301 GNUNET_free (gst->relays);
302 if (NULL != gst->slave)
303 GNUNET_PSYC_slave_part (gst->slave);
304 GNUNET_CONTAINER_multihashmap_remove (guests, &pl->pub_key_hash, pl);
309 * Clean up place data structures after a client disconnected.
312 cleanup_place (struct Place *pl)
314 (GNUNET_YES == pl->is_host)
315 ? cleanup_host ((struct Host *) pl)
316 : cleanup_guest ((struct Guest *) pl);
322 * Called whenever a client is disconnected.
323 * Frees our resources associated with that client.
325 * @param cls Closure.
326 * @param client Identification of the client.
329 client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
335 pl = GNUNET_SERVER_client_get_user_context (client, struct Place);
336 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
337 "%p Client (%s) disconnected from place %s\n",
338 pl, (GNUNET_YES == pl->is_host) ? "host" : "guest",
339 GNUNET_h2s (&pl->pub_key_hash));
343 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
344 "%p User context is NULL in client_disconnect()\n", pl);
349 struct ClientList *cl = pl->clients_head;
352 if (cl->client == client)
354 GNUNET_CONTAINER_DLL_remove (pl->clients_head, pl->clients_tail, cl);
361 if (NULL == pl->clients_head)
362 { /* Last client disconnected. */
363 if (NULL != pl->tmit_head)
364 { /* Send pending messages to PSYC before cleanup. */
365 //FIXME: transmit_message (pl);
376 client_home_enter (void *cls, struct GNUNET_SERVER_Client *client,
377 const struct GNUNET_MessageHeader *msg)
384 client_place_enter (void *cls, struct GNUNET_SERVER_Client *client,
385 const struct GNUNET_MessageHeader *msg)
392 client_join_decision (void *cls, struct GNUNET_SERVER_Client *client,
393 const struct GNUNET_MessageHeader *msg)
400 client_psyc_message (void *cls, struct GNUNET_SERVER_Client *client,
401 const struct GNUNET_MessageHeader *msg)
408 * Initialize the PSYC service.
410 * @param cls Closure.
411 * @param server The initialized server.
412 * @param c Configuration to use.
415 run (void *cls, struct GNUNET_SERVER_Handle *server,
416 const struct GNUNET_CONFIGURATION_Handle *c)
418 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
419 { &client_home_enter, NULL,
420 GNUNET_MESSAGE_TYPE_SOCIAL_HOME_ENTER, 0 },
422 { &client_place_enter, NULL,
423 GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_ENTER, 0 },
425 { &client_join_decision, NULL,
426 GNUNET_MESSAGE_TYPE_SOCIAL_JOIN_DECISION, 0 },
428 { &client_psyc_message, NULL,
429 GNUNET_MESSAGE_TYPE_PSYC_MESSAGE, 0 }
433 stats = GNUNET_STATISTICS_create ("social", cfg);
434 hosts = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
435 guests = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
436 place_guests = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
437 nc = GNUNET_SERVER_notification_context_create (server, 1);
438 GNUNET_SERVER_add_handlers (server, handlers);
439 GNUNET_SERVER_disconnect_notify (server, &client_disconnect, NULL);
440 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
441 &shutdown_task, NULL);
446 * The main function for the service.
448 * @param argc number of arguments from the command line
449 * @param argv command line arguments
450 * @return 0 ok, 1 on error
453 main (int argc, char *const *argv)
456 GNUNET_SERVICE_run (argc, argv, "social",
457 GNUNET_SERVICE_OPTION_NONE,
458 &run, NULL)) ? 0 : 1;
461 /* end of gnunet-service-social.c */