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.
21 * @file conversation/gnunet-service-conversation.c
22 * @brief conversation service implementation
23 * @author Simon Dieterle
24 * @author Andreas Fuchs
25 * @author Christian Grothoff
28 #include "gnunet_util_lib.h"
29 #include "gnunet_protocols.h"
30 #include "gnunet_applications.h"
31 #include "gnunet_constants.h"
32 #include "gnunet_signatures.h"
33 #include "gnunet_mesh_service.h"
34 #include "gnunet_conversation_service.h"
35 #include "conversation.h"
39 * How long is our signature on a call valid? Needs to be long enough for time zone
40 * differences and network latency to not matter. No strong need for it to be short,
41 * but we simply like all signatures to eventually expire.
43 #define RING_TIMEOUT GNUNET_TIME_UNIT_DAYS
47 * The possible connection status
52 * We are waiting for incoming calls.
57 * Our phone is ringing, waiting for the client to pick up.
67 * We are waiting for the phone to be picked up.
77 * We're in shutdown, sending hangup messages before cleaning up.
84 * A line connects a local client with a mesh tunnel (or, if it is an
85 * open line, is waiting for a mesh tunnel).
100 * Handle for the reliable tunnel (contol data)
102 struct GNUNET_MESH_Tunnel *tunnel_reliable;
105 * Handle for unreliable tunnel (audio data)
107 struct GNUNET_MESH_Tunnel *tunnel_unreliable;
110 * Transmit handle for pending audio messages
112 struct GNUNET_MESH_TransmitHandle *unreliable_mth;
115 * Transmit handle for pending audio messages
117 struct GNUNET_MQ_Handle *reliable_mq;
125 * Current status of this line.
127 enum LineStatus status;
135 static const struct GNUNET_CONFIGURATION_Handle *cfg;
138 * Notification context containing all connected clients.
140 static struct GNUNET_SERVER_NotificationContext *nc;
145 static struct GNUNET_MESH_Handle *mesh;
148 * Identity of this peer.
150 static struct GNUNET_PeerIdentity my_identity;
153 * Head of DLL of active lines.
155 static struct Line *lines_head;
158 * Tail of DLL of active lines.
160 static struct Line *lines_tail;
164 * Function to register a phone.
166 * @param cls closure, NULL
167 * @param client the client from which the message is
168 * @param message the message from the client
171 handle_client_register_message (void *cls,
172 struct GNUNET_SERVER_Client *client,
173 const struct GNUNET_MessageHeader *message)
175 const struct ClientPhoneRegisterMessage *msg;
178 msg = (struct ClientPhoneRegisterMessage *) message;
179 line = GNUNET_SERVER_client_get_user_context (client, struct Line);
182 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
185 line = GNUNET_new (struct Line);
186 GNUNET_CONTAINER_DLL_insert (lines_head,
189 line->line = ntohl (msg->line);
190 GNUNET_SERVER_client_set_user_context (client, line);
191 GNUNET_SERVER_receive_done (client, GNUNET_OK);
196 * Function to handle a pickup request message from the client
198 * @param cls closure, NULL
199 * @param client the client from which the message is
200 * @param message the message from the client
203 handle_client_pickup_message (void *cls,
204 struct GNUNET_SERVER_Client *client,
205 const struct GNUNET_MessageHeader *message)
207 const struct ClientPhonePickupMessage *msg;
209 msg = (struct ClientPhonePickupMessage *) message;
210 GNUNET_break (0); // FIXME
211 GNUNET_SERVER_receive_done (client, GNUNET_OK);
216 * Function to handle a hangup request message from the client
218 * @param cls closure, NULL
219 * @param client the client from which the message is
220 * @param message the message from the client
223 handle_client_hangup_message (void *cls,
224 struct GNUNET_SERVER_Client *client,
225 const struct GNUNET_MessageHeader *message)
227 const struct ClientPhoneHangupMessage *msg;
229 msg = (struct ClientPhoneHangupMessage *) message;
230 GNUNET_break (0); // FIXME
231 GNUNET_SERVER_receive_done (client, GNUNET_OK);
236 * Function to handle call request the client
238 * @param cls closure, NULL
239 * @param client the client from which the message is
240 * @param message the message from the client
243 handle_client_call_message (void *cls,
244 struct GNUNET_SERVER_Client *client,
245 const struct GNUNET_MessageHeader *message)
247 const struct ClientCallMessage *msg;
249 struct GNUNET_MQ_Envelope *e;
250 struct MeshPhoneRingMessage *ring;
252 msg = (struct ClientCallMessage *) message;
253 line = GNUNET_SERVER_client_get_user_context (client, struct Line);
256 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
259 line = GNUNET_new (struct Line);
260 GNUNET_CONTAINER_DLL_insert (lines_head,
263 line->line = ntohl (msg->line);
264 line->status = LS_CALLER_CALLING;
265 line->tunnel_reliable = GNUNET_MESH_tunnel_create (mesh,
268 GNUNET_APPLICATION_TYPE_CONVERSATION_CONTROL,
271 line->tunnel_unreliable = GNUNET_MESH_tunnel_create (mesh,
274 GNUNET_APPLICATION_TYPE_CONVERSATION_AUDIO,
277 line->reliable_mq = GNUNET_MESH_mq_create (line->tunnel_reliable);
278 e = GNUNET_MQ_msg (ring, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_RING);
279 ring->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING);
280 ring->purpose.size = htonl (sizeof (struct GNUNET_PeerIdentity) * 2 +
281 sizeof (struct GNUNET_TIME_AbsoluteNBO) +
282 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
283 sizeof (struct GNUNET_CRYPTO_EccPublicSignKey));
284 GNUNET_CRYPTO_ecc_key_get_public_for_signature (&msg->caller_id,
286 ring->line = msg->line;
287 ring->target = msg->target;
288 ring->source = my_identity;
289 ring->expiration_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (RING_TIMEOUT));
290 GNUNET_CRYPTO_ecc_sign (&msg->caller_id,
293 GNUNET_MQ_send (line->reliable_mq, e);
294 GNUNET_SERVER_client_set_user_context (client, line);
295 GNUNET_SERVER_receive_done (client, GNUNET_OK);
300 * Function to handle audio data from the client
302 * @param cls closure, NULL
303 * @param client the client from which the message is
304 * @param message the message from the client
307 handle_client_audio_message (void *cls,
308 struct GNUNET_SERVER_Client *client,
309 const struct GNUNET_MessageHeader *message)
311 const struct ClientAudioMessage *msg;
313 msg = (struct ClientAudioMessage *) message;
314 GNUNET_break (0); // FIXME
315 GNUNET_SERVER_receive_done (client, GNUNET_OK);
320 * Function to handle a ring message incoming over mesh
322 * @param cls closure, NULL
323 * @param tunnel the tunnel over which the message arrived
324 * @param tunnel_ctx the tunnel context, can be NULL
325 * @param message the incoming message
329 handle_mesh_ring_message (void *cls,
330 struct GNUNET_MESH_Tunnel *tunnel,
332 const struct GNUNET_MessageHeader *message)
334 const struct MeshPhoneRingMessage *msg;
336 msg = (const struct MeshPhoneRingMessage *) message;
337 GNUNET_break (0); // FIXME
343 * Function to handle a hangup message incoming over mesh
345 * @param cls closure, NULL
346 * @param tunnel the tunnel over which the message arrived
347 * @param tunnel_ctx the tunnel context, can be NULL
348 * @param message the incoming message
352 handle_mesh_hangup_message (void *cls,
353 struct GNUNET_MESH_Tunnel *tunnel,
355 const struct GNUNET_MessageHeader *message)
357 const struct MeshPhoneHangupMessage *msg;
359 msg = (const struct MeshPhoneHangupMessage *) message;
360 GNUNET_break (0); // FIXME
366 * Function to handle a pickup message incoming over mesh
368 * @param cls closure, NULL
369 * @param tunnel the tunnel over which the message arrived
370 * @param tunnel_ctx the tunnel context, can be NULL
371 * @param message the incoming message
375 handle_mesh_pickup_message (void *cls,
376 struct GNUNET_MESH_Tunnel *tunnel,
378 const struct GNUNET_MessageHeader *message)
380 const struct MeshPhonePickupMessage *msg;
382 msg = (const struct MeshPhonePickupMessage *) message;
383 GNUNET_break (0); // FIXME
389 * Function to handle a busy message incoming over mesh
391 * @param cls closure, NULL
392 * @param tunnel the tunnel over which the message arrived
393 * @param tunnel_ctx the tunnel context, can be NULL
394 * @param message the incoming message
398 handle_mesh_busy_message (void *cls,
399 struct GNUNET_MESH_Tunnel *tunnel,
401 const struct GNUNET_MessageHeader *message)
403 const struct MeshPhoneBusyMessage *msg;
405 msg = (const struct MeshPhoneBusyMessage *) message;
406 GNUNET_break (0); // FIXME
412 * Function to handle an audio message incoming over mesh
414 * @param cls closure, NULL
415 * @param tunnel the tunnel over which the message arrived
416 * @param tunnel_ctx the tunnel context, can be NULL
417 * @param message the incoming message
421 handle_mesh_audio_message (void *cls,
422 struct GNUNET_MESH_Tunnel *tunnel,
424 const struct GNUNET_MessageHeader *message)
426 const struct MeshAudioMessage *msg;
428 msg = (const struct MeshAudioMessage *) message;
429 GNUNET_break (0); // FIXME
435 * Method called whenever another peer has added us to a tunnel
436 * the other peer initiated.
439 * @param tunnel new handle to the tunnel
440 * @param initiator peer that started the tunnel
442 * @return initial tunnel context for the tunnel (can be NULL -- that's not an error)
445 inbound_tunnel (void *cls,
446 struct GNUNET_MESH_Tunnel *tunnel,
447 const struct GNUNET_PeerIdentity *initiator,
451 GNUNET_break (0); // FIXME
452 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
453 _("Received incoming tunnel on port %d\n"), port);
459 * Function called whenever an inbound tunnel is destroyed. Should clean up
460 * any associated state.
462 * @param cls closure (set from #GNUNET_MESH_connect)
463 * @param tunnel connection to the other end (henceforth invalid)
464 * @param tunnel_ctx place where local state associated
465 * with the tunnel is stored
468 inbound_end (void *cls,
469 const struct GNUNET_MESH_Tunnel *tunnel,
472 GNUNET_break (0); // FIXME
477 * A client disconnected. Remove all of its data structure entries.
479 * @param cls closure, NULL
480 * @param client identification of the client
483 handle_client_disconnect (void *cls,
484 struct GNUNET_SERVER_Client *client)
488 line = GNUNET_SERVER_client_get_user_context (client, struct Line);
491 GNUNET_CONTAINER_DLL_remove (lines_head,
495 GNUNET_SERVER_client_set_user_context (client, NULL);
502 * @param cls closure, NULL
503 * @param tc the task context
506 do_shutdown (void *cls,
507 const struct GNUNET_SCHEDULER_TaskContext *tc)
509 GNUNET_break (0); // FIXME
512 GNUNET_MESH_disconnect (mesh);
517 GNUNET_SERVER_notification_context_destroy (nc);
524 * Main function that will be run by the scheduler.
527 * @param server server handle
528 * @param c configuration
532 struct GNUNET_SERVER_Handle *server,
533 const struct GNUNET_CONFIGURATION_Handle *c)
535 static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
536 {&handle_client_register_message, NULL,
537 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_REGISTER,
538 sizeof (struct ClientPhoneRegisterMessage)},
539 {&handle_client_pickup_message, NULL,
540 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP,
542 {&handle_client_hangup_message, NULL,
543 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP,
545 {&handle_client_call_message, NULL,
546 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL,
548 {&handle_client_audio_message, NULL,
549 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO,
553 static struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
554 {&handle_mesh_ring_message,
555 GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_RING,
556 sizeof (struct MeshPhoneRingMessage)},
557 {&handle_mesh_hangup_message,
558 GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_HANG_UP,
560 {&handle_mesh_pickup_message,
561 GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_PICK_UP,
563 {&handle_mesh_busy_message,
564 GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_BUSY,
565 sizeof (struct MeshPhoneBusyMessage)},
566 {&handle_mesh_audio_message, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_AUDIO,
570 static uint32_t ports[] = {
571 GNUNET_APPLICATION_TYPE_CONVERSATION_CONTROL,
572 GNUNET_APPLICATION_TYPE_CONVERSATION_AUDIO,
577 GNUNET_assert (GNUNET_OK ==
578 GNUNET_CRYPTO_get_host_identity (cfg,
580 mesh = GNUNET_MESH_connect (cfg,
590 GNUNET_SCHEDULER_shutdown ();
593 nc = GNUNET_SERVER_notification_context_create (server, 16);
594 GNUNET_SERVER_add_handlers (server, server_handlers);
595 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
596 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
603 * The main function for the conversation service.
605 * @param argc number of arguments from the command line
606 * @param argv command line arguments
607 * @return 0 ok, 1 on error
614 GNUNET_SERVICE_run (argc, argv,
616 GNUNET_SERVICE_OPTION_NONE,
617 &run, NULL)) ? 0 : 1;
620 /* end of gnunet-service-conversation.c */