diff options
Diffstat (limited to 'src/social/gnunet-service-social.c')
-rw-r--r-- | src/social/gnunet-service-social.c | 461 |
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 | */ | ||
42 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
43 | |||
44 | /** | ||
45 | * Handle to the statistics service. | ||
46 | */ | ||
47 | static struct GNUNET_STATISTICS_Handle *stats; | ||
48 | |||
49 | /** | ||
50 | * Notification context, simplifies client broadcasts. | ||
51 | */ | ||
52 | static struct GNUNET_SERVER_NotificationContext *nc; | ||
53 | |||
54 | /** | ||
55 | * All connected hosts. | ||
56 | * Place's pub_key_hash -> struct Host | ||
57 | */ | ||
58 | static struct GNUNET_CONTAINER_MultiHashMap *hosts; | ||
59 | |||
60 | /** | ||
61 | * All connected guests. | ||
62 | * Place's pub_key_hash -> struct Guest | ||
63 | */ | ||
64 | static 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 | */ | ||
70 | static struct GNUNET_CONTAINER_MultiHashMap *place_guests; | ||
71 | |||
72 | |||
73 | /** | ||
74 | * Message in the transmission queue. | ||
75 | */ | ||
76 | struct 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 | */ | ||
105 | struct 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 | */ | ||
116 | struct 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 | */ | ||
144 | struct 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 | */ | ||
182 | struct 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 | |||
236 | static inline void | ||
237 | transmit_message (struct Place *pl); | ||
238 | |||
239 | |||
240 | /** | ||
241 | * Task run during shutdown. | ||
242 | * | ||
243 | * @param cls unused | ||
244 | * @param tc unused | ||
245 | */ | ||
246 | static void | ||
247 | shutdown_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 | */ | ||
265 | static void | ||
266 | cleanup_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 | */ | ||
280 | static void | ||
281 | cleanup_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 | */ | ||
311 | static void | ||
312 | cleanup_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 | */ | ||
328 | static void | ||
329 | client_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 | |||
375 | static void | ||
376 | client_home_enter (void *cls, struct GNUNET_SERVER_Client *client, | ||
377 | const struct GNUNET_MessageHeader *msg) | ||
378 | { | ||
379 | |||
380 | } | ||
381 | |||
382 | |||
383 | static void | ||
384 | client_place_enter (void *cls, struct GNUNET_SERVER_Client *client, | ||
385 | const struct GNUNET_MessageHeader *msg) | ||
386 | { | ||
387 | |||
388 | } | ||
389 | |||
390 | |||
391 | static void | ||
392 | client_join_decision (void *cls, struct GNUNET_SERVER_Client *client, | ||
393 | const struct GNUNET_MessageHeader *msg) | ||
394 | { | ||
395 | |||
396 | } | ||
397 | |||
398 | |||
399 | static void | ||
400 | client_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 | */ | ||
414 | static void | ||
415 | run (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 | */ | ||
452 | int | ||
453 | main (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 */ | ||