aboutsummaryrefslogtreecommitdiff
path: root/src/social/gnunet-service-social.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/social/gnunet-service-social.c')
-rw-r--r--src/social/gnunet-service-social.c461
1 files changed, 461 insertions, 0 deletions
diff --git a/src/social/gnunet-service-social.c b/src/social/gnunet-service-social.c
new file mode 100644
index 000000000..db704898b
--- /dev/null
+++ b/src/social/gnunet-service-social.c
@@ -0,0 +1,461 @@
1/*
2 * This file is part of GNUnet
3 * (C) 2013 Christian Grothoff (and other contributing authors)
4 *
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.
9 *
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.
14 *
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.
19 */
20
21/**
22 * @file psyc/gnunet-service-social.c
23 * @brief Social service
24 * @author Gabor X Toth
25 */
26
27#include <inttypes.h>
28
29#include "platform.h"
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"
36#include "social.h"
37
38
39/**
40 * Handle to our current configuration.
41 */
42static const struct GNUNET_CONFIGURATION_Handle *cfg;
43
44/**
45 * Handle to the statistics service.
46 */
47static struct GNUNET_STATISTICS_Handle *stats;
48
49/**
50 * Notification context, simplifies client broadcasts.
51 */
52static struct GNUNET_SERVER_NotificationContext *nc;
53
54/**
55 * All connected hosts.
56 * Place's pub_key_hash -> struct Host
57 */
58static struct GNUNET_CONTAINER_MultiHashMap *hosts;
59
60/**
61 * All connected guests.
62 * Place's pub_key_hash -> struct Guest
63 */
64static struct GNUNET_CONTAINER_MultiHashMap *guests;
65
66/**
67 * Connected guests per place.
68 * Place's pub_key_hash -> Guest's pub_key -> struct Guest
69 */
70static struct GNUNET_CONTAINER_MultiHashMap *place_guests;
71
72
73/**
74 * Message in the transmission queue.
75 */
76struct TransmitMessage
77{
78 struct TransmitMessage *prev;
79 struct TransmitMessage *next;
80
81 struct GNUNET_SERVER_Client *client;
82
83 /**
84 * ID assigned to the message.
85 */
86 uint64_t id;
87
88 /**
89 * Size of @a buf
90 */
91 uint16_t size;
92
93 /**
94 * @see enum MessageState
95 */
96 uint8_t state;
97
98 /* Followed by message */
99};
100
101
102/**
103 * List of connected clients.
104 */
105struct ClientList
106{
107 struct ClientList *prev;
108 struct ClientList *next;
109 struct GNUNET_SERVER_Client *client;
110};
111
112
113/**
114 * Common part of the client context for both a host and guest.
115 */
116struct Place
117{
118 struct ClientList *clients_head;
119 struct ClientList *clients_tail;
120
121 struct TransmitMessage *tmit_head;
122 struct TransmitMessage *tmit_tail;
123
124 /**
125 * Public key of the channel.
126 */
127 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
128
129 /**
130 * Hash of @a pub_key.
131 */
132 struct GNUNET_HashCode pub_key_hash;
133
134 /**
135 * Is this a host (#GNUNET_YES), or guest (#GNUNET_NO)?
136 */
137 uint8_t is_host;
138};
139
140
141/**
142 * Client context for a host.
143 */
144struct Host
145{
146 /**
147 * Place struct common for Host and Guest
148 */
149 struct Place pl;
150
151 /**
152 * Private key of the channel.
153 */
154 struct GNUNET_CRYPTO_EddsaPrivateKey priv_key;
155
156 /**
157 * Handle for the multicast origin.
158 */
159 struct GNUNET_PSYC_Master *master;
160
161 /**
162 * Transmit handle for multicast.
163 */
164 struct GNUNET_PSYC_MasterTransmitHandle *tmit_handle;
165
166 /**
167 * Incoming join requests.
168 * guest_key -> struct GNUNET_PSYC_JoinHandle *
169 */
170 struct GNUNET_CONTAINER_MultiHashMap *join_reqs;
171
172 /**
173 * @see enum GNUNET_PSYC_Policy
174 */
175 enum GNUNET_PSYC_Policy policy;
176};
177
178
179/**
180 * Client context for a guest.
181 */
182struct Guest
183{
184 /**
185 * Place struct common for Host and Guest.
186 */
187 struct Place pl;
188
189 /**
190 * Private key of the slave.
191 */
192 struct GNUNET_CRYPTO_EddsaPrivateKey priv_key;
193
194 /**
195 * Public key of the slave.
196 */
197 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
198
199 /**
200 * Hash of @a pub_key.
201 */
202 struct GNUNET_HashCode pub_key_hash;
203
204 /**
205 * Handle for the PSYC slave.
206 */
207 struct GNUNET_PSYC_Slave *slave;
208
209 /**
210 * Transmit handle for multicast.
211 */
212 struct GNUNET_PSYC_SlaveTransmitHandle *tmit_handle;
213
214 /**
215 * Peer identity of the origin.
216 */
217 struct GNUNET_PeerIdentity origin;
218
219 /**
220 * Number of items in @a relays.
221 */
222 uint32_t relay_count;
223
224 /**
225 * Relays that multicast can use to connect.
226 */
227 struct GNUNET_PeerIdentity *relays;
228
229 /**
230 * Join request to be transmitted to the master on join.
231 */
232 struct GNUNET_MessageHeader *join_req;
233};
234
235
236static inline void
237transmit_message (struct Place *pl);
238
239
240/**
241 * Task run during shutdown.
242 *
243 * @param cls unused
244 * @param tc unused
245 */
246static void
247shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
248{
249 if (NULL != nc)
250 {
251 GNUNET_SERVER_notification_context_destroy (nc);
252 nc = NULL;
253 }
254 if (NULL != stats)
255 {
256 GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
257 stats = NULL;
258 }
259}
260
261
262/**
263 * Clean up host data structures after a client disconnected.
264 */
265static void
266cleanup_host (struct Host *hst)
267{
268 struct Place *pl = &hst->pl;
269
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);
274}
275
276
277/**
278 * Clean up guest data structures after a client disconnected.
279 */
280static void
281cleanup_guest (struct Guest *gst)
282{
283 struct Place *pl = &gst->pl;
284 struct GNUNET_CONTAINER_MultiHashMap *
285 pl_gst = GNUNET_CONTAINER_multihashmap_get (place_guests,
286 &pl->pub_key_hash);
287 GNUNET_assert (NULL != pl_gst);
288 GNUNET_CONTAINER_multihashmap_remove (pl_gst, &gst->pub_key_hash, gst);
289
290 if (0 == GNUNET_CONTAINER_multihashmap_size (pl_gst))
291 {
292 GNUNET_CONTAINER_multihashmap_remove (place_guests, &pl->pub_key_hash,
293 pl_gst);
294 GNUNET_CONTAINER_multihashmap_destroy (pl_gst);
295 }
296 GNUNET_CONTAINER_multihashmap_remove (guests, &pl->pub_key_hash, gst);
297
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);
305}
306
307
308/**
309 * Clean up place data structures after a client disconnected.
310 */
311static void
312cleanup_place (struct Place *pl)
313{
314 (GNUNET_YES == pl->is_host)
315 ? cleanup_host ((struct Host *) pl)
316 : cleanup_guest ((struct Guest *) pl);
317 GNUNET_free (pl);
318}
319
320
321/**
322 * Called whenever a client is disconnected.
323 * Frees our resources associated with that client.
324 *
325 * @param cls Closure.
326 * @param client Identification of the client.
327 */
328static void
329client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
330{
331 if (NULL == client)
332 return;
333
334 struct Place *
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));
340
341 if (NULL == pl)
342 {
343 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
344 "%p User context is NULL in client_disconnect()\n", pl);
345 GNUNET_break (0);
346 return;
347 }
348
349 struct ClientList *cl = pl->clients_head;
350 while (NULL != cl)
351 {
352 if (cl->client == client)
353 {
354 GNUNET_CONTAINER_DLL_remove (pl->clients_head, pl->clients_tail, cl);
355 GNUNET_free (cl);
356 break;
357 }
358 cl = cl->next;
359 }
360
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);
366 }
367 else
368 {
369 cleanup_place (pl);
370 }
371 }
372}
373
374
375static void
376client_home_enter (void *cls, struct GNUNET_SERVER_Client *client,
377 const struct GNUNET_MessageHeader *msg)
378{
379
380}
381
382
383static void
384client_place_enter (void *cls, struct GNUNET_SERVER_Client *client,
385 const struct GNUNET_MessageHeader *msg)
386{
387
388}
389
390
391static void
392client_join_decision (void *cls, struct GNUNET_SERVER_Client *client,
393 const struct GNUNET_MessageHeader *msg)
394{
395
396}
397
398
399static void
400client_psyc_message (void *cls, struct GNUNET_SERVER_Client *client,
401 const struct GNUNET_MessageHeader *msg)
402{
403
404}
405
406
407/**
408 * Initialize the PSYC service.
409 *
410 * @param cls Closure.
411 * @param server The initialized server.
412 * @param c Configuration to use.
413 */
414static void
415run (void *cls, struct GNUNET_SERVER_Handle *server,
416 const struct GNUNET_CONFIGURATION_Handle *c)
417{
418 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
419 { &client_home_enter, NULL,
420 GNUNET_MESSAGE_TYPE_SOCIAL_HOME_ENTER, 0 },
421
422 { &client_place_enter, NULL,
423 GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_ENTER, 0 },
424
425 { &client_join_decision, NULL,
426 GNUNET_MESSAGE_TYPE_SOCIAL_JOIN_DECISION, 0 },
427
428 { &client_psyc_message, NULL,
429 GNUNET_MESSAGE_TYPE_PSYC_MESSAGE, 0 }
430 };
431
432 cfg = c;
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);
442}
443
444
445/**
446 * The main function for the service.
447 *
448 * @param argc number of arguments from the command line
449 * @param argv command line arguments
450 * @return 0 ok, 1 on error
451 */
452int
453main (int argc, char *const *argv)
454{
455 return (GNUNET_OK ==
456 GNUNET_SERVICE_run (argc, argv, "social",
457 GNUNET_SERVICE_OPTION_NONE,
458 &run, NULL)) ? 0 : 1;
459}
460
461/* end of gnunet-service-social.c */