-service skeleton
[oweals/gnunet.git] / src / conversation / gnunet-service-conversation-new.c
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  * @file conversation/gnunet-service-conversation.c
22  * @brief conversation service implementation
23  * @author Simon Dieterle
24  * @author Andreas Fuchs
25  * @author Christian Grothoff
26  */
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_protocols.h"
30 #include "gnunet_applications.h"
31 #include "gnunet_constants.h"
32 #include "gnunet_mesh_service.h"
33 #include "gnunet_conversation_service.h"
34 #include "conversation.h"
35
36
37 /**
38  * The possible connection status
39  */
40 enum LineStatus
41 {
42   /**
43    * We are waiting for incoming calls.
44    */
45   LS_CALLEE_LISTEN,
46
47   /**
48    * Our phone is ringing, waiting for the client to pick up.
49    */
50   LS_CALLEE_RINGING,
51
52   /**
53    * We are talking!
54    */
55   LS_CALLEE_CONNECTED,
56
57   /**
58    * We are waiting for the phone to be picked up.
59    */
60   LS_CALLER_CALLING,
61
62   /**
63    * We are talking!
64    */
65   LS_CALLER_CONNECTED,
66
67   /**
68    * We're in shutdown, sending hangup messages before cleaning up.
69    */
70   LS_CALLER_SHUTDOWN
71 };
72
73
74 /**
75  * A line connects a local client with a mesh tunnel (or, if it is an
76  * open line, is waiting for a mesh tunnel).
77  */
78 struct Line
79 {
80   /**
81    * Kept in a DLL.
82    */
83   struct Line *next;
84
85   /**
86    * Kept in a DLL.
87    */
88   struct Line *prev;
89
90   /**
91    * Handle for the reliable tunnel (contol data)
92    */
93   struct GNUNET_MESH_Tunnel *tunnel_reliable;
94   
95   /**
96    * Handle for unreliable tunnel (audio data)
97    */
98   struct GNUNET_MESH_Tunnel *tunnel_unreliable;
99
100   /**
101    * Transmit handle for pending audio messages
102    */
103   struct GNUNET_MESH_TransmitHandle *mth;
104
105   /**
106    * Our line number.
107    */
108   uint32_t line;
109
110   /**
111    * Current status of this line.
112    */ 
113   enum LineStatus status;
114
115 };
116
117
118 /**
119  * Our configuration.
120  */
121 static const struct GNUNET_CONFIGURATION_Handle *cfg;
122
123 /**
124  * Notification context containing all connected clients.
125  */
126 static struct GNUNET_SERVER_NotificationContext *nc;
127
128 /**
129  * Handle for mesh
130  */
131 static struct GNUNET_MESH_Handle *mesh;
132
133 /**
134  * Head of DLL of active lines.
135  */
136 static struct Line *lines_head;
137
138 /**
139  * Tail of DLL of active lines.
140  */
141 static struct Line *lines_tail;
142
143
144 /**
145  * Function to register a phone.
146  *
147  * @param cls closure, NULL
148  * @param client the client from which the message is
149  * @param message the message from the client
150  */
151 static void
152 handle_client_register_message (void *cls,
153                                 struct GNUNET_SERVER_Client *client,
154                                 const struct GNUNET_MessageHeader *message)
155 {
156   const struct ClientPhoneRegisterMessage *msg;
157
158   msg = (struct ClientPhoneRegisterMessage *) message;
159   GNUNET_break (0); // FIXME
160   GNUNET_SERVER_receive_done (client, GNUNET_OK);
161 }
162
163
164 /**
165  * Function to handle a pickup request message from the client
166  *
167  * @param cls closure, NULL
168  * @param client the client from which the message is
169  * @param message the message from the client
170  */
171 static void
172 handle_client_pickup_message (void *cls,
173                               struct GNUNET_SERVER_Client *client,
174                               const struct GNUNET_MessageHeader *message)
175 {
176   const struct ClientPhonePickupMessage *msg;
177
178   msg = (struct ClientPhonePickupMessage *) message;
179   GNUNET_break (0); // FIXME
180   GNUNET_SERVER_receive_done (client, GNUNET_OK);
181 }
182
183
184 /**
185  * Function to handle a hangup request message from the client
186  *
187  * @param cls closure, NULL
188  * @param client the client from which the message is
189  * @param message the message from the client
190  */
191 static void
192 handle_client_hangup_message (void *cls,
193                               struct GNUNET_SERVER_Client *client,
194                               const struct GNUNET_MessageHeader *message)
195 {
196   const struct ClientPhoneHangupMessage *msg;
197
198   msg = (struct ClientPhoneHangupMessage *) message;
199   GNUNET_break (0); // FIXME
200   GNUNET_SERVER_receive_done (client, GNUNET_OK);
201 }
202
203
204 /**
205  * Function to handle call request the client
206  *
207  * @param cls closure, NULL
208  * @param client the client from which the message is
209  * @param message the message from the client
210  */
211 static void
212 handle_client_call_message (void *cls,
213                             struct GNUNET_SERVER_Client *client,
214                             const struct GNUNET_MessageHeader *message)
215 {
216   const struct ClientCallMessage *msg;
217
218   msg = (struct ClientCallMessage *) message;
219   GNUNET_break (0); // FIXME
220   GNUNET_SERVER_receive_done (client, GNUNET_OK);
221 }
222
223
224 /**
225  * Function to handle audio data from the client
226  *
227  * @param cls closure, NULL
228  * @param client the client from which the message is
229  * @param message the message from the client
230  */
231 static void
232 handle_client_audio_message (void *cls,
233                              struct GNUNET_SERVER_Client *client,
234                              const struct GNUNET_MessageHeader *message)
235 {
236   const struct ClientAudioMessage *msg;
237
238   msg = (struct ClientAudioMessage *) message;
239   GNUNET_break (0); // FIXME
240   GNUNET_SERVER_receive_done (client, GNUNET_OK);
241 }
242
243
244 /**
245  * Function to handle a ring message incoming over mesh
246  *
247  * @param cls closure, NULL
248  * @param tunnel the tunnel over which the message arrived
249  * @param tunnel_ctx the tunnel context, can be NULL
250  * @param message the incoming message
251  * @return #GNUNET_OK
252  */
253 static int
254 handle_mesh_ring_message (void *cls,
255                           struct GNUNET_MESH_Tunnel *tunnel,
256                           void **tunnel_ctx,
257                           const struct GNUNET_MessageHeader *message)
258 {
259   const struct MeshPhoneRingMessage *msg;
260   
261   msg = (const struct MeshPhoneRingMessage *) message;
262   GNUNET_break (0); // FIXME
263   return GNUNET_OK;
264 }
265
266
267 /**
268  * Function to handle a hangup message incoming over mesh
269  *
270  * @param cls closure, NULL
271  * @param tunnel the tunnel over which the message arrived
272  * @param tunnel_ctx the tunnel context, can be NULL
273  * @param message the incoming message
274  * @return #GNUNET_OK
275  */
276 static int
277 handle_mesh_hangup_message (void *cls,
278                             struct GNUNET_MESH_Tunnel *tunnel,
279                             void **tunnel_ctx,
280                             const struct GNUNET_MessageHeader *message)
281 {
282   const struct MeshPhoneHangupMessage *msg;
283   
284   msg = (const struct MeshPhoneHangupMessage *) message;
285   GNUNET_break (0); // FIXME
286   return GNUNET_OK;
287 }
288
289
290 /**
291  * Function to handle a pickup message incoming over mesh
292  *
293  * @param cls closure, NULL
294  * @param tunnel the tunnel over which the message arrived
295  * @param tunnel_ctx the tunnel context, can be NULL
296  * @param message the incoming message
297  * @return #GNUNET_OK
298  */
299 static int
300 handle_mesh_pickup_message (void *cls,
301                             struct GNUNET_MESH_Tunnel *tunnel,
302                             void **tunnel_ctx,
303                             const struct GNUNET_MessageHeader *message)
304 {
305   const struct MeshPhonePickupMessage *msg;
306   
307   msg = (const struct MeshPhonePickupMessage *) message;
308   GNUNET_break (0); // FIXME
309   return GNUNET_OK;
310 }
311
312
313 /**
314  * Function to handle a busy message incoming over mesh
315  *
316  * @param cls closure, NULL
317  * @param tunnel the tunnel over which the message arrived
318  * @param tunnel_ctx the tunnel context, can be NULL
319  * @param message the incoming message
320  * @return #GNUNET_OK
321  */
322 static int
323 handle_mesh_busy_message (void *cls,
324                           struct GNUNET_MESH_Tunnel *tunnel,
325                           void **tunnel_ctx,
326                           const struct GNUNET_MessageHeader *message)
327 {
328   const struct MeshPhoneBusyMessage *msg;
329   
330   msg = (const struct MeshPhoneBusyMessage *) message;
331   GNUNET_break (0); // FIXME
332   return GNUNET_OK;
333 }
334
335
336 /**
337  * Function to handle an audio message incoming over mesh
338  *
339  * @param cls closure, NULL
340  * @param tunnel the tunnel over which the message arrived
341  * @param tunnel_ctx the tunnel context, can be NULL
342  * @param message the incoming message
343  * @return #GNUNET_OK
344  */
345 static int
346 handle_mesh_audio_message (void *cls,
347                            struct GNUNET_MESH_Tunnel *tunnel,
348                            void **tunnel_ctx,
349                            const struct GNUNET_MessageHeader *message)
350 {
351   const struct MeshAudioMessage *msg;
352   
353   msg = (const struct MeshAudioMessage *) message;
354   GNUNET_break (0); // FIXME
355   return GNUNET_OK;
356 }
357
358
359 /**
360  * Method called whenever another peer has added us to a tunnel
361  * the other peer initiated.
362  *
363  * @param cls closure
364  * @param tunnel new handle to the tunnel
365  * @param initiator peer that started the tunnel
366  * @param port port
367  * @return initial tunnel context for the tunnel (can be NULL -- that's not an error)
368  */
369 static void *
370 inbound_tunnel (void *cls,
371                 struct GNUNET_MESH_Tunnel *tunnel,
372                 const struct GNUNET_PeerIdentity *initiator, 
373                 uint32_t port)
374 {
375   GNUNET_break (0); // FIXME
376   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
377               _("Received incoming tunnel on port %d\n"), port);
378   return NULL;
379 }
380
381
382 /**
383  * Function called whenever an inbound tunnel is destroyed.  Should clean up
384  * any associated state.
385  *
386  * @param cls closure (set from #GNUNET_MESH_connect)
387  * @param tunnel connection to the other end (henceforth invalid)
388  * @param tunnel_ctx place where local state associated
389  *                   with the tunnel is stored
390  */
391 static void
392 inbound_end (void *cls,
393              const struct GNUNET_MESH_Tunnel *tunnel,
394              void *tunnel_ctx)
395 {
396   GNUNET_break (0); // FIXME
397 }
398
399
400 /**
401  * A client disconnected.  Remove all of its data structure entries.
402  *
403  * @param cls closure, NULL
404  * @param client identification of the client
405  */
406 static void
407 handle_client_disconnect (void *cls, 
408                           struct GNUNET_SERVER_Client *cl)
409 {
410   GNUNET_break (0); // FIXME
411 }
412
413
414 /**
415  * Shutdown nicely
416  * 
417  * @param cls closure, NULL
418  * @param tc the task context
419  */
420 static void
421 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
422 {
423   GNUNET_break (0); // FIXME
424   if (NULL != mesh)
425   {
426     GNUNET_MESH_disconnect (mesh);
427     mesh = NULL;
428   }
429   if (NULL != nc)
430   {
431     GNUNET_SERVER_notification_context_destroy (nc);
432     nc = NULL;
433   }
434 }
435
436
437 /**
438  * Main function that will be run by the scheduler.
439  *
440  * @param cls closure
441  * @param server server handle
442  * @param c configuration
443  */
444 static void
445 run (void *cls, 
446      struct GNUNET_SERVER_Handle *server,
447      const struct GNUNET_CONFIGURATION_Handle *c)
448 {
449   static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
450     {&handle_client_register_message, NULL,
451      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_REGISTER,
452      sizeof (struct ClientPhoneRegisterMessage)},
453     {&handle_client_pickup_message, NULL,
454      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP,
455      0},
456     {&handle_client_hangup_message, NULL,
457      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP,
458      0},
459     {&handle_client_call_message, NULL,
460      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL,
461      0},
462     {&handle_client_audio_message, NULL,
463      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO,
464      0},
465     {NULL, NULL, 0, 0}
466   };
467   static struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
468     {&handle_mesh_ring_message,
469      GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_RING,
470      sizeof (struct MeshPhoneRingMessage)},
471     {&handle_mesh_hangup_message, 
472      GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_HANG_UP,
473      0},
474     {&handle_mesh_pickup_message, 
475      GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_PICK_UP,
476      0},
477     {&handle_mesh_busy_message, 
478      GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_BUSY,
479      sizeof (struct MeshPhoneBusyMessage)},
480     {&handle_mesh_audio_message, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_AUDIO,
481      0},
482     {NULL, 0, 0}
483   };
484   static uint32_t ports[] = { 
485     GNUNET_APPLICATION_TYPE_CONVERSATION_CONTROL,
486     GNUNET_APPLICATION_TYPE_CONVERSATION_AUDIO,
487     0 
488   };
489
490   cfg = c;
491   mesh = GNUNET_MESH_connect (cfg,
492                               NULL,
493                               &inbound_tunnel,
494                               &inbound_end, 
495                               mesh_handlers, 
496                               ports);
497
498   if (NULL == mesh)
499   {
500     GNUNET_break (0);
501     GNUNET_SCHEDULER_shutdown ();
502     return;
503   }
504   nc = GNUNET_SERVER_notification_context_create (server, 16);
505   GNUNET_SERVER_add_handlers (server, server_handlers);
506   GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
507   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, 
508                                 &do_shutdown,
509                                 NULL);
510 }
511
512
513 /**
514  * The main function for the conversation service.
515  *
516  * @param argc number of arguments from the command line
517  * @param argv command line arguments
518  * @return 0 ok, 1 on error
519  */
520 int
521 main (int argc, 
522       char *const *argv)
523 {
524   return (GNUNET_OK ==
525           GNUNET_SERVICE_run (argc, argv,
526                               "conversation", 
527                               GNUNET_SERVICE_OPTION_NONE,
528                               &run, NULL)) ? 0 : 1;
529 }
530
531 /* end of gnunet-service-conversation.c */