aboutsummaryrefslogtreecommitdiff
path: root/src/conversation/gnunet-service-conversation.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-10-05 13:10:53 +0000
committerChristian Grothoff <christian@grothoff.org>2013-10-05 13:10:53 +0000
commitac3a1c494fd48fc1d01fcc4eafa0b3f4878f5441 (patch)
treea21b54452171f582444a199e70426b4c4266152b /src/conversation/gnunet-service-conversation.c
parent45c9ba99503eaf130b3d298062c612e281893d6a (diff)
downloadgnunet-ac3a1c494fd48fc1d01fcc4eafa0b3f4878f5441.tar.gz
gnunet-ac3a1c494fd48fc1d01fcc4eafa0b3f4878f5441.zip
-rename fest: new to default
Diffstat (limited to 'src/conversation/gnunet-service-conversation.c')
-rw-r--r--src/conversation/gnunet-service-conversation.c2485
1 files changed, 940 insertions, 1545 deletions
diff --git a/src/conversation/gnunet-service-conversation.c b/src/conversation/gnunet-service-conversation.c
index 4c4bdc133..d379931f7 100644
--- a/src/conversation/gnunet-service-conversation.c
+++ b/src/conversation/gnunet-service-conversation.c
@@ -22,56 +22,140 @@
22 * @brief conversation service implementation 22 * @brief conversation service implementation
23 * @author Simon Dieterle 23 * @author Simon Dieterle
24 * @author Andreas Fuchs 24 * @author Andreas Fuchs
25 * STRUCTURE: 25 * @author Christian Grothoff
26 * - Variables
27 * - AUXILIARY FUNCTIONS
28 * - SENDING FUNCTIONS CL -> SERVER
29 * - RECEIVE FUNCTIONS CL -> SERVER
30 * - SENDING FUNCTIONS MESH
31 * - RECEIVE FUNCTIONS MESH
32 * - HELPER
33 * - TUNNEL HANDLING
34 * - CLIENT HANDLING
35 */ 26 */
36#include "platform.h" 27#include "platform.h"
37#include "gnunet_util_lib.h" 28#include "gnunet_util_lib.h"
38#include "gnunet_protocols.h" 29#include "gnunet_protocols.h"
30#include "gnunet_applications.h"
39#include "gnunet_constants.h" 31#include "gnunet_constants.h"
32#include "gnunet_signatures.h"
40#include "gnunet_mesh_service.h" 33#include "gnunet_mesh_service.h"
41#include "gnunet_conversation_service.h" 34#include "gnunet_conversation_service.h"
42#include "conversation.h" 35#include "conversation.h"
43 36
44 37
38/**
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.
42 */
43#define RING_TIMEOUT GNUNET_TIME_UNIT_DAYS
45 44
46/* 45
47* The possible connection status 46/**
48*/ 47 * The possible connection status
49enum connection_status 48 */
49enum LineStatus
50{ 50{
51 LISTEN, 51 /**
52 CALLER, 52 * We are waiting for incoming calls.
53 CALLEE, 53 */
54 CONNECTED 54 LS_CALLEE_LISTEN,
55
56 /**
57 * Our phone is ringing, waiting for the client to pick up.
58 */
59 LS_CALLEE_RINGING,
60
61 /**
62 * We are talking!
63 */
64 LS_CALLEE_CONNECTED,
65
66 /**
67 * We're in shutdown, sending hangup messages before cleaning up.
68 */
69 LS_CALLEE_SHUTDOWN,
70
71 /**
72 * We are waiting for the phone to be picked up.
73 */
74 LS_CALLER_CALLING,
75
76 /**
77 * We are talking!
78 */
79 LS_CALLER_CONNECTED,
80
81 /**
82 * We're in shutdown, sending hangup messages before cleaning up.
83 */
84 LS_CALLER_SHUTDOWN
55}; 85};
56 86
57 87
58/******************************************************** 88/**
59 * Ugly hack because of not working MESH API 89 * A line connects a local client with a mesh tunnel (or, if it is an
60*/ 90 * open line, is waiting for a mesh tunnel).
61typedef uint32_t MESH_TunnelNumber; 91 */
62struct GNUNET_MESH_Tunnel 92struct Line
63{ 93{
64 struct GNUNET_MESH_Tunnel *next; 94 /**
65 struct GNUNET_MESH_Tunnel *prev; 95 * Kept in a DLL.
66 struct GNUNET_MESH_Handle *mesh; 96 */
67 MESH_TunnelNumber tid; 97 struct Line *next;
68 uint32_t port; 98
69 GNUNET_PEER_Id peer; 99 /**
70 void *ctx; 100 * Kept in a DLL.
71 unsigned int packet_size; 101 */
72 int buffering; 102 struct Line *prev;
73 int reliable; 103
74 int allow_send; 104 /**
105 * Handle for the reliable tunnel (contol data)
106 */
107 struct GNUNET_MESH_Tunnel *tunnel_reliable;
108
109 /**
110 * Handle for unreliable tunnel (audio data)
111 */
112 struct GNUNET_MESH_Tunnel *tunnel_unreliable;
113
114 /**
115 * Transmit handle for pending audio messages
116 */
117 struct GNUNET_MESH_TransmitHandle *unreliable_mth;
118
119 /**
120 * Message queue for control messages
121 */
122 struct GNUNET_MQ_Handle *reliable_mq;
123
124 /**
125 * Handle to the line client.
126 */
127 struct GNUNET_SERVER_Client *client;
128
129 /**
130 * Target of the line, if we are the caller.
131 */
132 struct GNUNET_PeerIdentity target;
133
134 /**
135 * Temporary buffer for audio data.
136 */
137 void *audio_data;
138
139 /**
140 * Number of bytes in @e audio_data.
141 */
142 size_t audio_size;
143
144 /**
145 * Our line number.
146 */
147 uint32_t local_line;
148
149 /**
150 * Remote line number.
151 */
152 uint32_t remote_line;
153
154 /**
155 * Current status of this line.
156 */
157 enum LineStatus status;
158
75}; 159};
76 160
77 161
@@ -81,1421 +165,831 @@ struct GNUNET_MESH_Tunnel
81static const struct GNUNET_CONFIGURATION_Handle *cfg; 165static const struct GNUNET_CONFIGURATION_Handle *cfg;
82 166
83/** 167/**
84 * Head of the list of current clients.
85 */
86static struct GNUNET_CONTAINER_SList *clients;
87
88/**
89 * Notification context containing all connected clients. 168 * Notification context containing all connected clients.
90 */ 169 */
91struct GNUNET_SERVER_NotificationContext *nc = NULL; 170static struct GNUNET_SERVER_NotificationContext *nc;
92
93/**
94* The connection status
95*/
96static struct ConnectionStatus connection;
97 171
98/** 172/**
99* Handle for the record helper 173 * Handle for mesh
100*/
101static struct GNUNET_HELPER_Handle *record_helper;
102
103/** Handle for the playback handler
104*
105*/
106static struct GNUNET_HELPER_Handle *playback_helper;
107
108/**
109* Handle for mesh
110*/
111static struct GNUNET_MESH_Handle *mesh;
112
113/**
114* Transmit handle for audio messages
115*/
116static struct GNUNET_MESH_TransmitHandle *mth = NULL;
117
118/**
119* Handle for the reliable tunnel (contol data)
120*/
121static struct GNUNET_MESH_Tunnel *tunnel_reliable;
122
123/**
124* Handle for unreliable tunnel (audio data)
125*/
126static struct GNUNET_MESH_Tunnel *tunnel_unreliable;
127
128/**
129* List for missed calls
130*/
131static struct GNUNET_CONTAINER_SList *missed_calls;
132
133/**
134* List for peers to notify that we are available again
135*/
136static struct GNUNET_CONTAINER_SList *peers_to_notify;
137
138/**
139* Audio buffer (outgoing)
140*/
141static struct GNUNET_CONTAINER_SList *audio_buffer;
142
143/**
144* The pointer to the task for sending audio
145*/
146static GNUNET_SCHEDULER_TaskIdentifier audio_task;
147
148/**
149* The pointer to the task for checking timeouts an calling a peer
150*/
151static GNUNET_SCHEDULER_TaskIdentifier timeout_task;
152
153/**
154 * Timestamp for call statistics
155 */
156static struct GNUNET_TIME_Absolute start_time;
157
158/**
159 * Number of payload packes sent
160 */ 174 */
161static int data_sent; 175static struct GNUNET_MESH_Handle *mesh;
162static int data_sent_size;
163 176
164/** 177/**
165 * Number of payload packets received 178 * Identity of this peer.
166 */ 179 */
167static int data_received; 180static struct GNUNET_PeerIdentity my_identity;
168static int data_received_size;
169
170 181
171/** 182/**
172* Transmit a mesh message 183 * Head of DLL of active lines.
173 * @param cls closure, NULL
174 * @param size number of bytes available in buf
175 * @param buf where the callee should write the error message
176 * @return number of bytes written to buf
177 */ 184 */
178static size_t transmit_mesh_message (void *cls, size_t size, void *buf); 185static struct Line *lines_head;
179 186
180/** 187/**
181 * Function called to send a peer no answer message to the client. 188 * Tail of DLL of active lines.
182 * "buf" will be NULL and "size" zero if the socket was closed for writing in
183 * the meantime.
184 *
185 * @param cls closure, NULL
186 * @param size number of bytes available in buf
187 * @param buf where the callee should write the peer no answer message
188 * @return number of bytes written to buf
189 */ 189 */
190static size_t 190static struct Line *lines_tail;
191transmit_server_no_answer_message (void *cls, size_t size, void *buf);
192 191
193/** 192/**
194 * Task to schedule a audio transmission. 193 * Counter for generating local line numbers.
195 * 194 * FIXME: randomize generation in the future
196 * @param cls Closure. 195 * to eliminate information leakage.
197 * @param tc Task Context.
198 */ 196 */
199static void 197static uint32_t local_line_cnt;
200transmit_audio_task (void *cls,
201 const struct GNUNET_SCHEDULER_TaskContext *tc);
202 198
203/**
204* Start the audio helpers
205*/
206int start_helpers (void);
207 199
208/** 200/**
209* Stop the audio helpers 201 * Function to register a phone.
210*/
211void stop_helpers (void);
212
213
214
215/******************************************************************************/
216/*********************** AUXILIARY FUNCTIONS *************************/
217/******************************************************************************/
218
219/**
220* Function which displays some call stats
221*/
222static void
223show_end_data (void)
224{
225 static struct GNUNET_TIME_Absolute end_time;
226 static struct GNUNET_TIME_Relative total_time;
227
228 end_time = GNUNET_TIME_absolute_get ();
229 total_time = GNUNET_TIME_absolute_get_difference (start_time, end_time);
230 FPRINTF (stderr, "\nResults of send\n");
231 FPRINTF (stderr, "Test time %s\n",
232 GNUNET_STRINGS_relative_time_to_string (total_time,
233 GNUNET_NO));
234 FPRINTF (stderr, "Test total packets: %d\n",
235 data_sent);
236 FPRINTF (stderr, "Test bandwidth: %f kb/s\n",
237 data_sent_size * 1000.0 / (total_time.rel_value_us + 1)); // 4bytes * us
238 FPRINTF (stderr, "Test throughput: %f packets/s\n\n",
239 data_sent * 1000000.0 / (total_time.rel_value_us + 1)); // packets * us
240
241 FPRINTF (stderr, "\nResults of recv\n");
242 FPRINTF (stderr, "Test time %s\n",
243 GNUNET_STRINGS_relative_time_to_string (total_time,
244 GNUNET_NO));
245 FPRINTF (stderr, "Test total packets: %d\n",
246 data_received);
247 FPRINTF (stderr, "Test bandwidth: %f kb/s\n",
248 data_received_size * 1000.0 / (total_time.rel_value_us + 1)); // 4bytes * us
249 FPRINTF (stderr, "Test throughput: %f packets/s\n\n",
250 data_received * 1000000.0 / (total_time.rel_value_us + 1)); // packets * us
251}
252
253/**
254* Function which sets the connection state to LISTEN
255*/
256static void
257status_to_listen (void)
258{
259
260 if (CONNECTED == connection.status)
261 {
262 show_end_data ();
263 }
264
265 if (timeout_task != GNUNET_SCHEDULER_NO_TASK)
266 {
267 GNUNET_SCHEDULER_cancel (timeout_task);
268 timeout_task = GNUNET_SCHEDULER_NO_TASK;
269 }
270
271 stop_helpers ();
272
273 connection.status = LISTEN;
274 connection.client = NULL;
275
276 data_sent = 0;
277 data_sent_size = 0;
278 data_received = 0;
279 data_received_size = 0;
280
281 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %s\n"),
282 "LISTEN");
283}
284
285/**
286* Function to terminate the active call
287*/
288static void
289terminate_call ()
290{
291 size_t msg_size;
292 msg_size = sizeof (struct MeshSessionTerminateMessage);
293 struct MeshSessionTerminateMessage *message_mesh_terminate =
294 (struct MeshSessionTerminateMessage *) GNUNET_malloc (msg_size);
295
296 if (NULL == message_mesh_terminate)
297 {
298 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
299 _("Could not create MeshSessionTerminateMessage\n"));
300 status_to_listen ();
301
302 return;
303 }
304
305 message_mesh_terminate->header.size = htons (msg_size);
306 message_mesh_terminate->header.type =
307 htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_TERMINATE);
308
309 if (NULL ==
310 GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
311 MAX_TRANSMIT_DELAY, msg_size,
312 &transmit_mesh_message,
313 (void *) message_mesh_terminate))
314 {
315 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
316 _("Could not queue MeshSessionTerminateMessage\n"));
317 GNUNET_free (message_mesh_terminate);
318 status_to_listen ();
319 }
320}
321
322/**
323* Function to reject a call
324*
325* @param tunnel the tunnel where to reject the incoming call
326* @param reason te reson why the call is rejected
327*/
328static void
329reject_call (struct GNUNET_MESH_Tunnel *tunnel, int reason)
330{
331 size_t msg_size;
332 msg_size = sizeof (struct MeshSessionRejectMessage);
333 struct MeshSessionRejectMessage *message_mesh_reject =
334 (struct MeshSessionRejectMessage *) GNUNET_malloc (msg_size);
335
336 if (NULL == message_mesh_reject)
337 {
338 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
339 _("Could not create MeshSessionRejectMessage\n"));
340 status_to_listen ();
341
342 return;
343 }
344
345 message_mesh_reject->header.size = htons (msg_size);
346 message_mesh_reject->header.type =
347 htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_REJECT);
348 message_mesh_reject->reason = htons (reason);
349
350 if (NULL ==
351 GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
352 MAX_TRANSMIT_DELAY, msg_size,
353 &transmit_mesh_message,
354 (void *) message_mesh_reject))
355 {
356 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
357 _("Could not queue MeshSessionRejectMessage\n"));
358 GNUNET_free (message_mesh_reject);
359 status_to_listen ();
360 }
361}
362
363/**
364 * Check for timeout when calling a peer
365 * 202 *
366 * @param cls closure, NULL 203 * @param cls closure, NULL
367 * @param tc the task context (can be NULL) 204 * @param client the client from which the message is
205 * @param message the message from the client
368 */ 206 */
369static void 207static void
370check_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 208handle_client_register_message (void *cls,
371{ 209 struct GNUNET_SERVER_Client *client,
372 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Call timeout\n"); 210 const struct GNUNET_MessageHeader *message)
373
374 if (NULL ==
375 GNUNET_SERVER_notify_transmit_ready (connection.client,
376 sizeof (struct
377 ServerClientNoAnswerMessage),
378 MAX_TRANSMIT_DELAY,
379 &transmit_server_no_answer_message,
380 NULL))
381 {
382 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
383 _("Could not queue ServerClientNoAnswerMessage\n"));
384 }
385
386 terminate_call ();
387}
388
389/******************************************************************************/
390/*********************** SENDING FUNCTIONS CL -> SERVER *******************/
391/******************************************************************************/
392
393/**
394 * Function called to send a session initiate message to the client.
395 * "buf" will be NULL and "size" zero if the socket was closed for writing in
396 * the meantime.
397 *
398 * @param cls closure, NULL
399 * @param size number of bytes available in buf
400 * @param buf where the callee should write the initiate message
401 * @return number of bytes written to buf
402 */
403static size_t
404transmit_server_initiate_message (void *cls, size_t size, void *buf)
405{
406 struct ServerClientSessionInitiateMessage *msg;
407 size_t msg_size;
408
409 msg_size = sizeof (struct ServerClientSessionInitiateMessage);
410
411 GNUNET_assert (size >= msg_size);
412
413 msg = (struct ServerClientSessionInitiateMessage *) buf;
414 msg->header.size = htons (msg_size);
415 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_INITIATE);
416 memcpy (&(msg->peer), (struct GNUNET_PeerIdentity *) cls,
417 sizeof (struct GNUNET_PeerIdentity));
418
419 return msg_size;
420}
421
422/**
423 * Function called to send a session accept message to the client.
424 * "buf" will be NULL and "size" zero if the socket was closed for writing in
425 * the meantime.
426 *
427 * @param cls closure, NULL
428 * @param size number of bytes available in buf
429 * @param buf where the callee should write the accept message
430 * @return number of bytes written to buf
431 */
432static size_t
433transmit_server_accept_message (void *cls, size_t size, void *buf)
434{ 211{
435 struct ServerClientSessionAcceptMessage *msg; 212 const struct ClientPhoneRegisterMessage *msg;
436 size_t msg_size; 213 struct Line *line;
437 214
438 msg_size = sizeof (struct ServerClientSessionAcceptMessage); 215 msg = (struct ClientPhoneRegisterMessage *) message;
439 216 line = GNUNET_SERVER_client_get_user_context (client, struct Line);
440 GNUNET_assert (size >= msg_size); 217 if (NULL != line)
441 218 {
442 msg = (struct ServerClientSessionAcceptMessage *) buf; 219 GNUNET_break (0);
443 msg->header.size = htons (msg_size); 220 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
444 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_ACCEPT); 221 return;
445 222 }
446 return msg_size; 223 line = GNUNET_new (struct Line);
224 line->client = client;
225 GNUNET_SERVER_notification_context_add (nc, client);
226 GNUNET_CONTAINER_DLL_insert (lines_head,
227 lines_tail,
228 line);
229 line->local_line = ntohl (msg->line);
230 GNUNET_SERVER_client_set_user_context (client, line);
231 GNUNET_SERVER_receive_done (client, GNUNET_OK);
447} 232}
448 233
449/**
450 * Function called to send a session reject message to the client.
451 * "buf" will be NULL and "size" zero if the socket was closed for writing in
452 * the meantime.
453 *
454 * @param cls closure, NULL
455 * @param size number of bytes available in buf
456 * @param buf where the callee should write the reject message
457 * @return number of bytes written to buf
458 */
459static size_t
460transmit_server_reject_message (void *cls, size_t size, void *buf)
461{
462 struct ServerClientSessionRejectMessage *msg;
463 size_t msg_size;
464
465 msg_size = sizeof (struct ServerClientSessionRejectMessage);
466
467 GNUNET_assert (size >= msg_size);
468
469 msg = (struct ServerClientSessionRejectMessage *) buf;
470 msg->header.size = htons (msg_size);
471 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_REJECT);
472
473 if (NULL == cls)
474 {
475 msg->reason = htons (GNUNET_CONVERSATION_REJECT_REASON_NOT_AVAILABLE);
476 }
477 else
478 {
479 msg->reason = ((struct MeshSessionRejectMessage *) cls)->reason;
480 }
481
482 return msg_size;
483}
484 234
485/** 235/**
486 * Function called to send a session terminate message to the client. 236 * Function to handle a pickup request message from the client
487 * "buf" will be NULL and "size" zero if the socket was closed for writing in
488 * the meantime.
489 * 237 *
490 * @param cls closure, NULL 238 * @param cls closure, NULL
491 * @param size number of bytes available in buf 239 * @param client the client from which the message is
492 * @param buf where the callee should write the terminate message 240 * @param message the message from the client
493 * @return number of bytes written to buf
494 */ 241 */
495static size_t 242static void
496transmit_server_terminate_message (void *cls, size_t size, void *buf) 243handle_client_pickup_message (void *cls,
244 struct GNUNET_SERVER_Client *client,
245 const struct GNUNET_MessageHeader *message)
497{ 246{
498 struct ServerClientSessionTerminateMessage *msg; 247 const struct ClientPhonePickupMessage *msg;
499 size_t msg_size; 248 struct GNUNET_MQ_Envelope *e;
500 249 struct MeshPhonePickupMessage *mppm;
501 msg_size = sizeof (struct ServerClientSessionTerminateMessage); 250 const char *meta;
502 251 struct Line *line;
503 GNUNET_assert (size >= msg_size); 252 size_t len;
504 253
505 msg = (struct ServerClientSessionTerminateMessage *) buf; 254 msg = (struct ClientPhonePickupMessage *) message;
506 msg->header.size = htons (msg_size); 255 meta = (const char *) &msg[1];
507 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_TERMINATE); 256 len = ntohs (msg->header.size) - sizeof (struct ClientPhonePickupMessage);
508 257 if ( (0 == len) ||
509 return msg_size; 258 ('\0' != meta[len - 1]) )
259 {
260 meta = NULL;
261 len = 0;
262 }
263 line = GNUNET_SERVER_client_get_user_context (client, struct Line);
264 if (NULL == line)
265 {
266 GNUNET_break (0);
267 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
268 return;
269 }
270 switch (line->status)
271 {
272 case LS_CALLEE_LISTEN:
273 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
274 "Ignoring client's PICKUP message, caller has HUNG UP already\n");
275 GNUNET_SERVER_receive_done (client, GNUNET_OK);
276 break;
277 case LS_CALLEE_RINGING:
278 line->status = LS_CALLEE_CONNECTED;
279 break;
280 case LS_CALLEE_CONNECTED:
281 GNUNET_break (0);
282 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
283 return;
284 case LS_CALLEE_SHUTDOWN:
285 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
286 "Ignoring client's PICKUP message, line is in SHUTDOWN\n");
287 GNUNET_SERVER_receive_done (client, GNUNET_OK);
288 break;
289 case LS_CALLER_CALLING:
290 case LS_CALLER_CONNECTED:
291 case LS_CALLER_SHUTDOWN:
292 GNUNET_break (0);
293 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
294 return;
295 }
296 line->status = LS_CALLEE_CONNECTED;
297 e = GNUNET_MQ_msg_extra (mppm,
298 len,
299 GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_PICK_UP);
300 memcpy (&mppm[1], meta, len);
301 GNUNET_MQ_send (line->reliable_mq, e);
302 GNUNET_SERVER_receive_done (client, GNUNET_OK);
510} 303}
511 304
512/**
513 * Function called to send a missed call message to the client.
514 * "buf" will be NULL and "size" zero if the socket was closed for writing in
515 * the meantime.
516 *
517 * @param cls closure, NULL
518 * @param size number of bytes available in buf
519 * @param buf where the callee should write the missed call message
520 * @return number of bytes written to buf
521 */
522static size_t
523transmit_server_missed_call_message (void *cls, size_t size, void *buf)
524{
525 struct ServerClientMissedCallMessage *msg;
526 msg = (struct ServerClientMissedCallMessage *) cls;
527
528 memcpy (buf, msg, size);
529 GNUNET_free (msg);
530
531 return size;
532}
533 305
534/** 306/**
535 * Function called to send a service blocked message to the client. 307 * Destroy the mesh tunnels of a line.
536 * "buf" will be NULL and "size" zero if the socket was closed for writing in
537 * the meantime.
538 * 308 *
539 * @param cls closure, NULL 309 * @param line line to shutdown tunnels of
540 * @param size number of bytes available in buf
541 * @param buf where the callee should write the service blocked message
542 * @return number of bytes written to buf
543 */ 310 */
544static size_t 311static void
545transmit_server_service_blocked_message (void *cls, size_t size, void *buf) 312destroy_line_mesh_tunnels (struct Line *line)
546{ 313{
547 struct ServerClientServiceBlockedMessage *msg; 314 if (NULL != line->reliable_mq)
548 size_t msg_size; 315 {
549 316 GNUNET_MQ_destroy (line->reliable_mq);
550 msg_size = sizeof (struct ServerClientServiceBlockedMessage); 317 line->reliable_mq = NULL;
551 318 }
552 GNUNET_assert (size >= msg_size); 319 if (NULL != line->unreliable_mth)
553 320 {
554 msg = (struct ServerClientServiceBlockedMessage *) buf; 321 GNUNET_MESH_notify_transmit_ready_cancel (line->unreliable_mth);
555 msg->header.size = htons (msg_size); 322 line->unreliable_mth = NULL;
556 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SERVICE_BLOCKED); 323 }
557 324 if (NULL != line->tunnel_unreliable)
558 return msg_size; 325 {
326 GNUNET_MESH_tunnel_destroy (line->tunnel_unreliable);
327 line->tunnel_unreliable = NULL;
328 }
329 if (NULL != line->tunnel_reliable)
330 {
331 GNUNET_MESH_tunnel_destroy (line->tunnel_reliable);
332 line->tunnel_reliable = NULL;
333 }
559} 334}
560 335
561/**
562 * Function called to send a peer not connected message to the client.
563 * "buf" will be NULL and "size" zero if the socket was closed for writing in
564 * the meantime.
565 *
566 * @param cls closure, NULL
567 * @param size number of bytes available in buf
568 * @param buf where the callee should write the peer not connected message
569 * @return number of bytes written to buf
570 */
571static size_t
572transmit_server_peer_not_connected_message (void *cls, size_t size, void *buf)
573{
574 struct ServerClientPeerNotConnectedMessage *msg;
575 size_t msg_size;
576
577 msg_size = sizeof (struct ServerClientPeerNotConnectedMessage);
578
579 GNUNET_assert (size >= msg_size);
580
581 msg = (struct ServerClientPeerNotConnectedMessage *) buf;
582 msg->header.size = htons (msg_size);
583 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_PEER_NOT_CONNECTED);
584
585 return msg_size;
586}
587 336
588/** 337/**
589 * Function called to send a peer no answer message to the client. 338 * We are done signalling shutdown to the other peer. Close down
590 * "buf" will be NULL and "size" zero if the socket was closed for writing in 339 * (or reset) the line.
591 * the meantime.
592 * 340 *
593 * @param cls closure, NULL 341 * @param cls the `struct Line` to reset/terminate
594 * @param size number of bytes available in buf
595 * @param buf where the callee should write the peer no answer message
596 * @return number of bytes written to buf
597 */ 342 */
598static size_t 343static void
599transmit_server_no_answer_message (void *cls, size_t size, void *buf) 344mq_done_finish_caller_shutdown (void *cls)
600{
601 struct ServerClientNoAnswerMessage *msg;
602 size_t msg_size;
603
604 msg_size = sizeof (struct ServerClientNoAnswerMessage);
605
606 GNUNET_assert (size >= msg_size);
607
608 msg = (struct ServerClientNoAnswerMessage *) buf;
609 msg->header.size = htons (msg_size);
610 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_NO_ANSWER);
611
612 return msg_size;
613}
614
615/**
616 * Function called to send a error message to the client.
617 * "buf" will be NULL and "size" zero if the socket was closed for writing in
618 * the meantime.
619 *
620 * @param cls closure, NULL
621 * @param size number of bytes available in buf
622 * @param buf where the callee should write the error message
623 * @return number of bytes written to buf
624 */
625static size_t
626transmit_server_error_message (void *cls, size_t size, void *buf)
627{ 345{
628 struct ServerClientErrorMessage *msg; 346 struct Line *line = cls;
629 size_t msg_size; 347
630 348 switch (line->status)
631 msg_size = sizeof (struct ServerClientErrorMessage); 349 {
632 350 case LS_CALLEE_LISTEN:
633 GNUNET_assert (size >= msg_size); 351 GNUNET_break (0);
634 352 break;
635 msg = (struct ServerClientErrorMessage *) buf; 353 case LS_CALLEE_RINGING:
636 msg->header.size = htons (msg_size); 354 GNUNET_break (0);
637 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_ERROR); 355 break;
638 356 case LS_CALLEE_CONNECTED:
639 return msg_size; 357 GNUNET_break (0);
358 break;
359 case LS_CALLEE_SHUTDOWN:
360 line->status = LS_CALLEE_LISTEN;
361 destroy_line_mesh_tunnels (line);
362 return;
363 case LS_CALLER_CALLING:
364 line->status = LS_CALLER_SHUTDOWN;
365 break;
366 case LS_CALLER_CONNECTED:
367 line->status = LS_CALLER_SHUTDOWN;
368 break;
369 case LS_CALLER_SHUTDOWN:
370 destroy_line_mesh_tunnels (line);
371 GNUNET_CONTAINER_DLL_remove (lines_head,
372 lines_tail,
373 line);
374 GNUNET_free_non_null (line->audio_data);
375 GNUNET_free (line);
376 break;
377 }
640} 378}
641 379
642/******************************************************************************/
643/*********************** RECEIVE FUNCTIONS CL -> SERVER ********************/
644/******************************************************************************/
645 380
646/** 381/**
647 * Function to handle a session initiate message from the client 382 * Function to handle a hangup request message from the client
648 * 383 *
649 * @param cls closure, NULL 384 * @param cls closure, NULL
650 * @param client the client from which the message is 385 * @param client the client from which the message is
651 * @param message the message from the client 386 * @param message the message from the client
652*/ 387 */
653static void 388static void
654handle_session_initiate_message (void *cls, 389handle_client_hangup_message (void *cls,
655 struct GNUNET_SERVER_Client *client, 390 struct GNUNET_SERVER_Client *client,
656 const struct GNUNET_MessageHeader *message) 391 const struct GNUNET_MessageHeader *message)
657{ 392{
658 static uint32_t port = 50002; 393 const struct ClientPhoneHangupMessage *msg;
659 size_t msg_size; 394 struct GNUNET_MQ_Envelope *e;
660 struct ClientServerSessionInitiateMessage *msg = 395 struct MeshPhoneHangupMessage *mhum;
661 (struct ClientServerSessionInitiateMessage *) message; 396 const char *meta;
662 struct GNUNET_PeerIdentity *peer = &(msg->peer); 397 struct Line *line;
663 398 size_t len;
399
400 msg = (struct ClientPhoneHangupMessage *) message;
401 meta = (const char *) &msg[1];
402 len = ntohs (msg->header.size) - sizeof (struct ClientPhoneHangupMessage);
403 if ( (0 == len) ||
404 ('\0' != meta[len - 1]) )
405 {
406 meta = NULL;
407 len = 0;
408 }
409 line = GNUNET_SERVER_client_get_user_context (client, struct Line);
410 if (NULL == line)
411 {
412 GNUNET_break (0);
413 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
414 return;
415 }
416 switch (line->status)
417 {
418 case LS_CALLEE_LISTEN:
419 GNUNET_break (0);
420 GNUNET_SERVER_receive_done (client, GNUNET_OK);
421 return;
422 case LS_CALLEE_RINGING:
423 line->status = LS_CALLEE_SHUTDOWN;
424 break;
425 case LS_CALLEE_CONNECTED:
426 line->status = LS_CALLEE_SHUTDOWN;
427 break;
428 case LS_CALLEE_SHUTDOWN:
429 GNUNET_break (0);
430 GNUNET_SERVER_receive_done (client, GNUNET_OK);
431 return;
432 case LS_CALLER_CALLING:
433 line->status = LS_CALLER_SHUTDOWN;
434 break;
435 case LS_CALLER_CONNECTED:
436 line->status = LS_CALLER_SHUTDOWN;
437 break;
438 case LS_CALLER_SHUTDOWN:
439 GNUNET_break (0);
440 GNUNET_SERVER_receive_done (client, GNUNET_OK);
441 return;
442 }
443 e = GNUNET_MQ_msg_extra (mhum,
444 len,
445 GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_HANG_UP);
446 memcpy (&mhum[1], meta, len);
447 GNUNET_MQ_notify_sent (e,
448 &mq_done_finish_caller_shutdown,
449 line);
450 GNUNET_MQ_send (line->reliable_mq, e);
664 GNUNET_SERVER_receive_done (client, GNUNET_OK); 451 GNUNET_SERVER_receive_done (client, GNUNET_OK);
665
666 if (NULL != connection.client)
667 {
668 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
669 _("There is already a peer in interaction\n"));
670 GNUNET_SERVER_notify_transmit_ready (client,
671 sizeof (struct
672 ServerClientServiceBlockedMessage),
673 MAX_TRANSMIT_DELAY,
674 &transmit_server_service_blocked_message,
675 NULL);
676
677 return;
678 }
679
680 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Creating tunnel to: %s\n"),
681 GNUNET_i2s_full (peer));
682 tunnel_reliable =
683 GNUNET_MESH_tunnel_create (mesh, NULL, peer, port, GNUNET_NO, GNUNET_NO);
684 if (NULL == tunnel_reliable)
685 {
686 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
687 _("Could not create reliable tunnel\n"));
688 GNUNET_SERVER_notify_transmit_ready (client,
689 sizeof (struct
690 ServerClientPeerNotConnectedMessage),
691 MAX_TRANSMIT_DELAY,
692 &transmit_server_peer_not_connected_message,
693 NULL);
694
695 return;
696 }
697
698 msg_size = sizeof (struct MeshSessionInitiateMessage);
699 struct MeshSessionInitiateMessage *message_mesh_initiate =
700 (struct MeshSessionInitiateMessage *) GNUNET_malloc (msg_size);
701
702 if (NULL == message_mesh_initiate)
703 {
704 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
705 _("Could not create MeshSessionInitiateMessage\n"));
706 GNUNET_MESH_tunnel_destroy (tunnel_reliable);
707 tunnel_reliable = NULL;
708 GNUNET_SERVER_notify_transmit_ready (client,
709 sizeof (struct
710 ServerClientErrorMessage),
711 MAX_TRANSMIT_DELAY,
712 &transmit_server_error_message,
713 NULL);
714
715 return;
716 }
717
718 message_mesh_initiate->header.size = htons (msg_size);
719 message_mesh_initiate->header.type =
720 htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_INITIATE);
721
722 if (NULL ==
723 GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
724 MAX_TRANSMIT_DELAY, msg_size,
725 &transmit_mesh_message,
726 (void *) message_mesh_initiate))
727 {
728 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
729 _("Could not queue MeshSessionInitiateMessage\n"));
730 GNUNET_MESH_tunnel_destroy (tunnel_reliable);
731 tunnel_reliable = NULL;
732 GNUNET_free (message_mesh_initiate);
733 GNUNET_SERVER_notify_transmit_ready (client,
734 sizeof (struct
735 ServerClientErrorMessage),
736 MAX_TRANSMIT_DELAY,
737 &transmit_server_error_message,
738 NULL);
739
740 return;
741 }
742
743 connection.status = CALLER;
744 connection.client = client;
745 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"),
746 connection.status);
747 memcpy (&(connection.peer), peer, sizeof (struct GNUNET_PeerIdentity));
748
749 return;
750} 452}
751 453
454
752/** 455/**
753 * Function to handle a session accept message from the client 456 * Function to handle call request the client
754 * 457 *
755 * @param cls closure, NULL 458 * @param cls closure, NULL
756 * @param client the client from which the message is 459 * @param client the client from which the message is
757 * @param message the message from the client 460 * @param message the message from the client
758*/ 461 */
759static void 462static void
760handle_session_accept_message (void *cls, struct GNUNET_SERVER_Client *client, 463handle_client_call_message (void *cls,
761 const struct GNUNET_MessageHeader *message) 464 struct GNUNET_SERVER_Client *client,
465 const struct GNUNET_MessageHeader *message)
762{ 466{
763 size_t msg_size; 467 const struct ClientCallMessage *msg;
764 468 struct Line *line;
469 struct GNUNET_MQ_Envelope *e;
470 struct MeshPhoneRingMessage *ring;
471
472 msg = (struct ClientCallMessage *) message;
473 line = GNUNET_SERVER_client_get_user_context (client, struct Line);
474 if (NULL != line)
475 {
476 GNUNET_break (0);
477 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
478 return;
479 }
480 line = GNUNET_new (struct Line);
481 line->target = msg->target;
482 GNUNET_CONTAINER_DLL_insert (lines_head,
483 lines_tail,
484 line);
485 line->remote_line = ntohl (msg->line);
486 line->status = LS_CALLER_CALLING;
487 line->tunnel_reliable = GNUNET_MESH_tunnel_create (mesh,
488 line,
489 &msg->target,
490 GNUNET_APPLICATION_TYPE_CONVERSATION_CONTROL,
491 GNUNET_NO,
492 GNUNET_YES);
493 line->reliable_mq = GNUNET_MESH_mq_create (line->tunnel_reliable);
494 line->local_line = local_line_cnt++;
495 e = GNUNET_MQ_msg (ring, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_RING);
496 ring->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING);
497 ring->purpose.size = htonl (sizeof (struct GNUNET_PeerIdentity) * 2 +
498 sizeof (struct GNUNET_TIME_AbsoluteNBO) +
499 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
500 sizeof (struct GNUNET_CRYPTO_EccPublicSignKey));
501 GNUNET_CRYPTO_ecc_key_get_public_for_signature (&msg->caller_id,
502 &ring->caller_id);
503 ring->remote_line = msg->line;
504 ring->source_line = line->local_line;
505 ring->target = msg->target;
506 ring->source = my_identity;
507 ring->expiration_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (RING_TIMEOUT));
508 GNUNET_CRYPTO_ecc_sign (&msg->caller_id,
509 &ring->purpose,
510 &ring->signature);
511 GNUNET_MQ_send (line->reliable_mq, e);
512 GNUNET_SERVER_client_set_user_context (client, line);
765 GNUNET_SERVER_receive_done (client, GNUNET_OK); 513 GNUNET_SERVER_receive_done (client, GNUNET_OK);
766
767 if (connection.status != CALLEE)
768 {
769 // TODO send illegal command
770 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
771 _
772 ("handle_session_accept_message called when not allowed\n"));
773 return;
774 }
775
776 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Accepting the call of: %s\n"),
777 GNUNET_i2s_full (&(connection.peer)));
778
779 msg_size = sizeof (struct MeshSessionAcceptMessage);
780 struct MeshSessionAcceptMessage *message_mesh_accept =
781 (struct MeshSessionAcceptMessage *) GNUNET_malloc (msg_size);
782
783 if (NULL == message_mesh_accept)
784 {
785 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
786 _("Could not create MeshSessionAcceptMessage\n"));
787 return;
788 }
789
790 message_mesh_accept->header.size = htons (msg_size);
791 message_mesh_accept->header.type =
792 htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_ACCEPT);
793
794 if (NULL ==
795 GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
796 MAX_TRANSMIT_DELAY, msg_size,
797 &transmit_mesh_message,
798 (void *) message_mesh_accept))
799 {
800 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
801 _("Could not queue MeshSessionAcceptMessage\n"));
802 GNUNET_free (message_mesh_accept);
803 return;
804 }
805
806 connection.status = CONNECTED;
807 connection.client = client;
808 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"),
809 connection.status);
810
811 return;
812} 514}
813 515
516
814/** 517/**
815 * Function to handle a session reject message from the client 518 * Transmit audio data via unreliable mesh channel.
816 * 519 *
817 * @param cls closure, NULL 520 * @param cls the `struct Line` we are transmitting for
818 * @param client the client from which the message is 521 * @param size number of bytes available in @a buf
819 * @param message the message from the client 522 * @param buf where to copy the data
820*/ 523 * @return number of bytes copied to @buf
821static void 524 */
822handle_session_reject_message (void *cls, struct GNUNET_SERVER_Client *client, 525static size_t
823 const struct GNUNET_MessageHeader *message) 526transmit_line_audio (void *cls,
527 size_t size,
528 void *buf)
824{ 529{
825 struct ClientServerSessionRejectMessage *message_received; 530 struct Line *line = cls;
826 531 struct MeshAudioMessage *mam = buf;
827 GNUNET_SERVER_receive_done (client, GNUNET_OK); 532
828 533 line->unreliable_mth = NULL;
829 if (connection.status != CALLEE) 534 if ( (NULL == buf) ||
535 (size < sizeof (struct MeshAudioMessage) + line->audio_size) )
830 { 536 {
831 // TODO send illegal command 537 /* eh, other error handling? */
832 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 538 return 0;
833 _ 539 }
834 ("handle_session_reject_message called when not allowed\n")); 540 mam->header.size = htons (sizeof (struct MeshAudioMessage) + line->audio_size);
835 return; 541 mam->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_AUDIO);
836 } 542 mam->remote_line = htonl (line->remote_line);
837 543 memcpy (&mam[1], line->audio_data, line->audio_size);
838 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Rejecting the call of: %s\n"), 544 GNUNET_free (line->audio_data);
839 GNUNET_i2s_full (&(connection.peer))); 545 line->audio_data = NULL;
840 message_received = (struct ClientServerSessionRejectMessage *) message; 546 return sizeof (struct MeshAudioMessage) + line->audio_size;
841 reject_call (tunnel_reliable, ntohs (message_received->reason));
842
843 return;
844} 547}
845 548
549
846/** 550/**
847 * Function to handle a session terminate message from the client 551 * Function to handle audio data from the client
848 * 552 *
849 * @param cls closure, NULL 553 * @param cls closure, NULL
850 * @param client the client from which the message is 554 * @param client the client from which the message is
851 * @param message the message from the client 555 * @param message the message from the client
852*/ 556 */
853static void 557static void
854handle_session_terminate_message (void *cls, 558handle_client_audio_message (void *cls,
855 struct GNUNET_SERVER_Client *client, 559 struct GNUNET_SERVER_Client *client,
856 const struct GNUNET_MessageHeader *message) 560 const struct GNUNET_MessageHeader *message)
857{ 561{
562 const struct ClientAudioMessage *msg;
563 struct Line *line;
564 size_t size;
565
566 size = ntohs (message->size) - sizeof (struct ClientAudioMessage);
567 msg = (struct ClientAudioMessage *) message;
568 line = GNUNET_SERVER_client_get_user_context (client, struct Line);
569 if (NULL == line)
570 {
571 GNUNET_break (0);
572 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
573 return;
574 }
575 switch (line->status)
576 {
577 case LS_CALLEE_LISTEN:
578 case LS_CALLEE_RINGING:
579 case LS_CALLER_CALLING:
580 GNUNET_break (0);
581 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
582 return;
583 case LS_CALLEE_CONNECTED:
584 case LS_CALLER_CONNECTED:
585 /* common case, handled below */
586 break;
587 case LS_CALLEE_SHUTDOWN:
588 case LS_CALLER_SHUTDOWN:
589 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
590 "Mesh audio channel in shutdown; audio data dropped\n");
591 GNUNET_SERVER_receive_done (client, GNUNET_OK);
592 return;
593 }
594 if (NULL == line->tunnel_unreliable)
595 {
596 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
597 _("Mesh audio channel not ready; audio data dropped\n"));
598 GNUNET_SERVER_receive_done (client, GNUNET_OK);
599 return;
600 }
601 if (NULL != line->unreliable_mth)
602 {
603 /* NOTE: we may want to not do this and instead combine the data */
604 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
605 "Dropping previous audio data segment with %u bytes\n",
606 line->audio_size);
607 GNUNET_MESH_notify_transmit_ready_cancel (line->unreliable_mth);
608 GNUNET_free (line->audio_data);
609 }
610 line->audio_size = size;
611 line->audio_data = GNUNET_malloc (line->audio_size);
612 memcpy (line->audio_data,
613 &msg[1],
614 size);
615 line->unreliable_mth = GNUNET_MESH_notify_transmit_ready (line->tunnel_unreliable,
616 GNUNET_NO,
617 GNUNET_TIME_UNIT_FOREVER_REL,
618 sizeof (struct MeshAudioMessage)
619 + line->audio_size,
620 &transmit_line_audio,
621 line);
858 GNUNET_SERVER_receive_done (client, GNUNET_OK); 622 GNUNET_SERVER_receive_done (client, GNUNET_OK);
859
860 if (connection.client == NULL || connection.status == CALLEE)
861 {
862 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
863 _
864 ("handle_session_terminate_message called when not allowed\n"));
865 return;
866 }
867
868 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Terminating the call with: %s\n"),
869 GNUNET_i2s_full (&(connection.peer)));
870 terminate_call ();
871} 623}
872 624
873/******************************************************************************/
874/*********************** SENDING FUNCTIONS MESH *******************/
875/******************************************************************************/
876 625
877/** 626/**
878* Transmit a mesh message 627 * We are done signalling shutdown to the other peer.
879 * @param cls closure, NULL 628 * Destroy the tunnel.
880 * @param size number of bytes available in buf 629 *
881 * @param buf where the callee should write the message 630 * @param cls the `struct GNUNET_MESH_tunnel` to destroy
882 * @return number of bytes written to buf
883 */
884static size_t
885transmit_mesh_message (void *cls, size_t size, void *buf)
886{
887 struct VoIPMeshMessageHeader *msg_header =
888 (struct VoIPMeshMessageHeader *) cls;
889
890 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transmitting message over mesh\n"));
891
892 memcpy (buf, cls, size);
893 // Check if this is correct
894
895
896 if ((GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_TERMINATE ==
897 ntohs (msg_header->header.type))
898 || (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_REJECT ==
899 ntohs (msg_header->header.type)))
900 {
901 status_to_listen ();
902 }
903 else if (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_INITIATE ==
904 ntohs (msg_header->header.type))
905 {
906 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting timeout task.\n"));
907 timeout_task =
908 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
909 (GNUNET_TIME_UNIT_SECONDS, 30),
910 &check_timeout, NULL);
911 }
912
913 GNUNET_free (cls);
914
915 return size;
916}
917
918/**
919* Transmit a audo message over mesh
920 * @param cls closure, NULL
921 * @param size number of bytes available in buf
922 * @param buf where the callee should write the message
923 * @return number of bytes written to buf
924 */
925static size_t
926transmit_mesh_audio_message (void *cls, size_t size, void *buf)
927{
928 struct AudioMessage *message = (struct AudioMessage *) cls;
929
930 if (size < sizeof (struct AudioMessage) || NULL == buf)
931 {
932 GNUNET_break (0);
933 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
934 "size %u, buf %p, data_sent %u, data_received %u\n",
935 size, buf, data_sent, data_received);
936 return 0;
937 }
938
939 memcpy (buf, message, size);
940
941 data_sent++;
942 data_sent_size += size;
943
944 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " Sent packet %d\n", data_sent);
945
946 audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL);
947
948 return size;
949}
950
951/**
952 * Task to schedule a audio transmission.
953 *
954 * @param cls Closure.
955 * @param tc Task Context.
956 */ 631 */
957static void 632static void
958transmit_audio_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 633mq_done_destroy_tunnel (void *cls)
959{ 634{
960 struct GNUNET_CONTAINER_SList_Iterator iterator; 635 struct GNUNET_MESH_Tunnel *tunnel = cls;
961 struct AudioMessage *msg; 636
962 int ab_length = GNUNET_CONTAINER_slist_count (audio_buffer); 637 GNUNET_MESH_tunnel_destroy (tunnel);
963
964 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "We have %d packets.\n", ab_length);
965
966 if (NULL == cls)
967 {
968 if (0 == ab_length && CONNECTED == connection.status)
969 {
970 audio_task =
971 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
972 (GNUNET_TIME_UNIT_MILLISECONDS, 10),
973 &transmit_audio_task, NULL);
974 return;
975 }
976
977 iterator = GNUNET_CONTAINER_slist_begin (audio_buffer);
978 msg =
979 (struct AudioMessage *) GNUNET_CONTAINER_slist_get (&iterator, NULL);
980 GNUNET_CONTAINER_slist_erase (&iterator);
981 GNUNET_CONTAINER_slist_iter_destroy (&iterator);
982 }
983 else
984 {
985 msg = (struct AudioMessage *) cls;
986 }
987
988 if (NULL == tunnel_unreliable)
989 {
990 GNUNET_CONTAINER_slist_clear (audio_buffer);
991 return;
992 }
993
994 mth = GNUNET_MESH_notify_transmit_ready (tunnel_unreliable, GNUNET_NO,
995 MAX_TRANSMIT_DELAY,
996 sizeof (struct AudioMessage),
997 &transmit_mesh_audio_message,
998 (void *) msg);
999
1000 if (NULL == mth)
1001 {
1002 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1003 "Need to retransmit audio packet\n");
1004 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " in 1 ms\n");
1005 audio_task =
1006 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
1007 &transmit_audio_task, (void *) msg);
1008 }
1009} 638}
1010 639
1011/******************************************************************************/
1012/*********************** RECEIVE FUNCTIONS MESH ********************/
1013/******************************************************************************/
1014 640
1015/** 641/**
1016* Function to handle a initiation messaage incoming over mesh 642 * Function to handle a ring message incoming over mesh
643 *
1017 * @param cls closure, NULL 644 * @param cls closure, NULL
1018 * @param tunnel the tunnel over which the message arrived 645 * @param tunnel the tunnel over which the message arrived
1019 * @param tunnel_ctx the tunnel context, can be NULL 646 * @param tunnel_ctx the tunnel context, can be NULL
1020 * @param message the incoming message 647 * @param message the incoming message
1021 * 648 * @return #GNUNET_OK
1022 * @return GNUNET_OK 649 */
1023*/ 650static int
1024int 651handle_mesh_ring_message (void *cls,
1025handle_mesh_initiate_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel, 652 struct GNUNET_MESH_Tunnel *tunnel,
1026 void **tunnel_ctx, 653 void **tunnel_ctx,
1027 const struct GNUNET_MessageHeader *message) 654 const struct GNUNET_MessageHeader *message)
1028{ 655{
1029 int reject_reason; 656 const struct MeshPhoneRingMessage *msg;
1030 //struct GNUNET_PeerIdentity *peer = (GNUNET_MESH_tunnel_get_info(tunnel, GNUNET_MESH_OPTION_PEER))->peer; 657 struct Line *line;
1031 const struct GNUNET_PeerIdentity *peer = 658 struct GNUNET_MQ_Envelope *e;
1032 GNUNET_PEER_resolve2 (tunnel->peer); 659 struct MeshPhoneBusyMessage *busy;
1033 660 struct ClientPhoneRingMessage cring;
1034 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 661
1035 _("Handling MeshSessionInitiateMessage from peer: %s\n"), 662 msg = (const struct MeshPhoneRingMessage *) message;
1036 GNUNET_i2s_full (peer)); 663 if ( (msg->purpose.size != htonl (sizeof (struct GNUNET_PeerIdentity) * 2 +
664 sizeof (struct GNUNET_TIME_AbsoluteNBO) +
665 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
666 sizeof (struct GNUNET_CRYPTO_EccPublicSignKey))) ||
667 (GNUNET_OK !=
668 GNUNET_CRYPTO_ecc_verify (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING,
669 &msg->purpose,
670 &msg->signature,
671 &msg->caller_id)) )
672 {
673 GNUNET_break_op (0);
674 return GNUNET_SYSERR;
675 }
676 for (line = lines_head; NULL != line; line = line->next)
677 if ( (line->local_line == ntohl (msg->remote_line)) &&
678 (LS_CALLEE_LISTEN == line->status) )
679 break;
680 if (NULL == line)
681 {
682 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
683 _("No available phone for incoming call on line %u, sending BUSY signal\n"),
684 ntohl (msg->remote_line));
685 e = GNUNET_MQ_msg (busy, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_BUSY);
686 GNUNET_MQ_notify_sent (e,
687 &mq_done_destroy_tunnel,
688 tunnel);
689 GNUNET_MQ_send (line->reliable_mq, e);
690 GNUNET_MESH_receive_done (tunnel); /* needed? */
691 return GNUNET_OK;
692 }
693 line->status = LS_CALLEE_RINGING;
694 line->remote_line = ntohl (msg->source_line);
695 line->tunnel_reliable = tunnel;
696 line->reliable_mq = GNUNET_MESH_mq_create (line->tunnel_reliable);
697 *tunnel_ctx = line;
698 cring.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RING);
699 cring.header.size = htons (sizeof (cring));
700 cring.reserved = htonl (0);
701 cring.caller_id = msg->caller_id;
702 GNUNET_SERVER_notification_context_unicast (nc,
703 line->client,
704 &cring.header,
705 GNUNET_NO);
1037 GNUNET_MESH_receive_done (tunnel); 706 GNUNET_MESH_receive_done (tunnel);
1038
1039 if (LISTEN != connection.status
1040 || 1 > GNUNET_CONTAINER_slist_count (clients))
1041 {
1042
1043 if (CONNECTED == connection.status)
1044 {
1045 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1046 _
1047 ("Rejected call from %s because there is an active call"),
1048 GNUNET_i2s_full (peer));
1049 reject_reason = htons (GNUNET_CONVERSATION_REJECT_REASON_ACTIVE_CALL);
1050
1051 // Notifying client about missed call
1052 size_t msg_size =
1053 sizeof (struct ServerClientMissedCallMessage) +
1054 sizeof (struct MissedCall);
1055 struct ServerClientMissedCallMessage *message =
1056 GNUNET_malloc (msg_size);
1057
1058 message->header.size = htons (msg_size);
1059 message->header.type =
1060 htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_MISSED_CALL);
1061 message->number = 1;
1062
1063 memcpy (&(message->missed_call->peer), peer,
1064 sizeof (struct GNUNET_PeerIdentity));
1065 message->missed_call->time = GNUNET_TIME_absolute_get ();
1066
1067 if (NULL ==
1068 GNUNET_SERVER_notify_transmit_ready (connection.client,
1069 sizeof (struct
1070 ServerClientMissedCallMessage),
1071 MAX_TRANSMIT_DELAY,
1072 &transmit_server_missed_call_message,
1073 (void *) message))
1074 {
1075 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1076 _
1077 ("Could not queue ServerClientMissedCallMessage\n"));
1078 GNUNET_free (message);
1079 }
1080 }
1081
1082 if (1 > GNUNET_CONTAINER_slist_count (clients))
1083 {
1084 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1085 _("Got a call from %s while no client connected.\n"),
1086 GNUNET_i2s_full (peer));
1087 reject_reason = htons (GNUNET_CONVERSATION_REJECT_REASON_NO_CLIENT);
1088 // Store missed calls
1089 struct MissedCall call;
1090 memcpy (&(call.peer), peer, sizeof (struct GNUNET_PeerIdentity));
1091 call.time = GNUNET_TIME_absolute_get ();
1092 GNUNET_CONTAINER_slist_add_end (missed_calls,
1093 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1094 &call, sizeof (struct MissedCall));
1095
1096 }
1097
1098 reject_call (tunnel, reject_reason);
1099 }
1100 else
1101 {
1102 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Initiated call from: %s\n"),
1103 GNUNET_i2s_full (peer));
1104 tunnel_reliable = tunnel;
1105 connection.status = CALLEE;
1106 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1107 _("Changed connection status to %d\n"), connection.status);
1108 memcpy (&(connection.peer), peer, sizeof (struct GNUNET_PeerIdentity));
1109
1110 struct GNUNET_CONTAINER_SList_Iterator iterator =
1111 GNUNET_CONTAINER_slist_begin (clients);
1112 do
1113 {
1114 struct VoipClient *conversation_client =
1115 (struct VoipClient *) GNUNET_CONTAINER_slist_get (&iterator,
1116 NULL);
1117 struct GNUNET_SERVER_Client *client = conversation_client->client;
1118 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Client found: %p\n"),
1119 client);
1120
1121 if (NULL ==
1122 GNUNET_SERVER_notify_transmit_ready (client,
1123 sizeof (struct
1124 ServerClientSessionInitiateMessage),
1125 MAX_TRANSMIT_DELAY,
1126 &transmit_server_initiate_message,
1127 (void *) peer))
1128 {
1129 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1130 _
1131 ("Could not queue ServerClientSessionInitiateMessage\n"));
1132 }
1133
1134 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Client notified.\n"));
1135 }
1136 while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator));
1137
1138 GNUNET_CONTAINER_slist_iter_destroy (&iterator);
1139
1140 }
1141
1142 return GNUNET_OK; 707 return GNUNET_OK;
1143} 708}
1144 709
710
1145/** 711/**
1146* Function to handle an accept messaage incoming over mesh 712 * Function to handle a hangup message incoming over mesh
713 *
1147 * @param cls closure, NULL 714 * @param cls closure, NULL
1148 * @param tunnel the tunnel over which the message arrived 715 * @param tunnel the tunnel over which the message arrived
1149 * @param tunnel_ctx the tunnel context, can be NULL 716 * @param tunnel_ctx the tunnel context, can be NULL
1150 * @param message the incoming message 717 * @param message the incoming message
1151 * 718 * @return #GNUNET_OK
1152 * @return GNUNET_OK 719 */
1153*/ 720static int
1154int 721handle_mesh_hangup_message (void *cls,
1155handle_mesh_accept_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel, 722 struct GNUNET_MESH_Tunnel *tunnel,
1156 void **tunnel_ctx, 723 void **tunnel_ctx,
1157 const struct GNUNET_MessageHeader *message) 724 const struct GNUNET_MessageHeader *message)
1158{ 725{
1159 static uint32_t port = 50003; 726 struct Line *line = *tunnel_ctx;
1160 //struct GNUNET_PeerIdentity *peer = (GNUNET_MESH_tunnel_get_info(tunnel, GNUNET_MESH_OPTION_PEER))->peer; 727 const struct MeshPhoneHangupMessage *msg;
1161 const struct GNUNET_PeerIdentity *peer = 728 const char *reason;
1162 GNUNET_PEER_resolve2 (tunnel->peer); 729 size_t len = ntohs (message->size) - sizeof (struct MeshPhoneHangupMessage);
1163 730 char buf[len + sizeof (struct ClientPhoneHangupMessage)];
1164 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 731 struct ClientPhoneHangupMessage *hup;
1165 _ 732
1166 ("Handling MeshSessionAccpetMessage from peer: %s (connection.peer: %s)\n"), 733 msg = (const struct MeshPhoneHangupMessage *) message;
1167 GNUNET_i2s_full (peer), GNUNET_i2s_full (&(connection.peer))); 734 len = ntohs (msg->header.size) - sizeof (struct MeshPhoneHangupMessage);
735 reason = (const char *) &msg[1];
736 if ( (0 == len) ||
737 ('\0' != reason[len - 1]) )
738 {
739 reason = NULL;
740 len = 0;
741 }
742 if (NULL == line)
743 {
744 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
745 "HANGUP message received for non-existing line, dropping tunnel.\n");
746 return GNUNET_SYSERR;
747 }
748 *tunnel_ctx = NULL;
749 switch (line->status)
750 {
751 case LS_CALLEE_LISTEN:
752 GNUNET_break (0);
753 return GNUNET_SYSERR;
754 case LS_CALLEE_RINGING:
755 line->status = LS_CALLEE_LISTEN;
756 destroy_line_mesh_tunnels (line);
757 break;
758 case LS_CALLEE_CONNECTED:
759 line->status = LS_CALLEE_LISTEN;
760 destroy_line_mesh_tunnels (line);
761 break;
762 case LS_CALLEE_SHUTDOWN:
763 line->status = LS_CALLEE_LISTEN;
764 destroy_line_mesh_tunnels (line);
765 return GNUNET_OK;
766 case LS_CALLER_CALLING:
767 line->status = LS_CALLER_SHUTDOWN;
768 mq_done_finish_caller_shutdown (line);
769 break;
770 case LS_CALLER_CONNECTED:
771 line->status = LS_CALLER_SHUTDOWN;
772 mq_done_finish_caller_shutdown (line);
773 break;
774 case LS_CALLER_SHUTDOWN:
775 mq_done_finish_caller_shutdown (line);
776 return GNUNET_OK;
777 }
778 hup = (struct ClientPhoneHangupMessage *) buf;
779 hup->header.size = sizeof (buf);
780 hup->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP);
781 memcpy (&hup[1], reason, len);
782 GNUNET_SERVER_notification_context_unicast (nc,
783 line->client,
784 &hup->header,
785 GNUNET_NO);
1168 GNUNET_MESH_receive_done (tunnel); 786 GNUNET_MESH_receive_done (tunnel);
1169
1170 if (0 ==
1171 memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity))
1172 && connection.status == CALLER)
1173 {
1174 tunnel_unreliable =
1175 GNUNET_MESH_tunnel_create (mesh, NULL, peer, port, GNUNET_NO,
1176 GNUNET_NO);
1177 if (NULL == tunnel_unreliable)
1178 {
1179 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1180 _("Could not create unreliable tunnel\n"));
1181
1182 status_to_listen ();
1183
1184 GNUNET_SERVER_notify_transmit_ready (connection.client,
1185 sizeof (struct
1186 ServerClientSessionRejectMessage),
1187 MAX_TRANSMIT_DELAY,
1188 &transmit_server_reject_message,
1189 NULL);
1190 return GNUNET_SYSERR;
1191 }
1192
1193 if (timeout_task != GNUNET_SCHEDULER_NO_TASK)
1194 {
1195 GNUNET_SCHEDULER_cancel (timeout_task);
1196 timeout_task = GNUNET_SCHEDULER_NO_TASK;
1197 }
1198
1199 connection.status = CONNECTED;
1200 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1201 _("Changed connection status to %d\n"), connection.status);
1202
1203 if (NULL ==
1204 GNUNET_SERVER_notify_transmit_ready (connection.client,
1205 sizeof (struct
1206 ServerClientSessionAcceptMessage),
1207 MAX_TRANSMIT_DELAY,
1208 &transmit_server_accept_message,
1209 (void *) message))
1210 {
1211 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1212 _
1213 ("Could not queue ServerClientSessionAcceptMessage\n"));
1214 return GNUNET_SYSERR;
1215 }
1216
1217 start_time = GNUNET_TIME_absolute_get ();
1218 start_helpers ();
1219 audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL);
1220 }
1221
1222 return GNUNET_OK; 787 return GNUNET_OK;
1223} 788}
1224 789
790
1225/** 791/**
1226* Function to handle a reject messaage incoming over mesh 792 * Function to handle a pickup message incoming over mesh
793 *
1227 * @param cls closure, NULL 794 * @param cls closure, NULL
1228 * @param tunnel the tunnel over which the message arrived 795 * @param tunnel the tunnel over which the message arrived
1229 * @param tunnel_ctx the tunnel context, can be NULL 796 * @param tunnel_ctx the tunnel context, can be NULL
1230 * @param message the incoming message 797 * @param message the incoming message
1231 * 798 * @return #GNUNET_OK
1232 * @return GNUNET_OK 799 */
1233*/ 800static int
1234int 801handle_mesh_pickup_message (void *cls,
1235handle_mesh_reject_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel, 802 struct GNUNET_MESH_Tunnel *tunnel,
1236 void **tunnel_ctx, 803 void **tunnel_ctx,
1237 const struct GNUNET_MessageHeader *message) 804 const struct GNUNET_MessageHeader *message)
1238{ 805{
1239 //struct GNUNET_PeerIdentity *peer = (GNUNET_MESH_tunnel_get_info(tunnel, GNUNET_MESH_OPTION_PEER))->peer; 806 const struct MeshPhonePickupMessage *msg;
1240 const struct GNUNET_PeerIdentity *peer = 807 struct Line *line = *tunnel_ctx;
1241 GNUNET_PEER_resolve2 (tunnel->peer); 808 const char *metadata;
1242 809 size_t len = ntohs (message->size) - sizeof (struct MeshPhonePickupMessage);
1243 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 810 char buf[len + sizeof (struct ClientPhonePickupMessage)];
1244 _ 811 struct ClientPhonePickupMessage *pick;
1245 ("Handling MeshSessionRejectMessage from peer: %s (connection.peer: %s)\n"), 812
1246 GNUNET_i2s_full (peer), GNUNET_i2s_full (&(connection.peer))); 813 msg = (const struct MeshPhonePickupMessage *) message;
814 len = ntohs (msg->header.size) - sizeof (struct MeshPhonePickupMessage);
815 metadata = (const char *) &msg[1];
816 if ( (0 == len) ||
817 ('\0' != metadata[len - 1]) )
818 {
819 metadata = NULL;
820 len = 0;
821 }
822 if (NULL == line)
823 {
824 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
825 "PICKUP message received for non-existing line, dropping tunnel.\n");
826 return GNUNET_SYSERR;
827 }
1247 GNUNET_MESH_receive_done (tunnel); 828 GNUNET_MESH_receive_done (tunnel);
1248 829 switch (line->status)
1249 if (0 == 830 {
1250 memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity)) 831 case LS_CALLEE_LISTEN:
1251 && connection.status == CALLER) 832 GNUNET_break (0);
1252 { 833 return GNUNET_SYSERR;
1253 if (NULL == 834 case LS_CALLEE_RINGING:
1254 GNUNET_SERVER_notify_transmit_ready (connection.client, 835 case LS_CALLEE_CONNECTED:
1255 sizeof (struct 836 GNUNET_break_op (0);
1256 ServerClientSessionRejectMessage), 837 destroy_line_mesh_tunnels (line);
1257 MAX_TRANSMIT_DELAY, 838 line->status = LS_CALLEE_LISTEN;
1258 &transmit_server_reject_message, 839 return GNUNET_SYSERR;
1259 (void *) message)) 840 case LS_CALLEE_SHUTDOWN:
1260 { 841 GNUNET_break_op (0);
1261 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 842 line->status = LS_CALLEE_LISTEN;
1262 _ 843 destroy_line_mesh_tunnels (line);
1263 ("Could not queue ServerClientSessionRejectMessage\n")); 844 break;
1264 } 845 case LS_CALLER_CALLING:
1265 846 line->status = LS_CALLER_CONNECTED;
1266 status_to_listen (); 847 break;
1267 848 case LS_CALLER_CONNECTED:
1268 if (NULL != tunnel_reliable) 849 GNUNET_break_op (0);
1269 { 850 return GNUNET_OK;
1270 GNUNET_MESH_tunnel_destroy (tunnel_reliable); 851 case LS_CALLER_SHUTDOWN:
1271 tunnel_reliable = NULL; 852 GNUNET_break_op (0);
1272 } 853 mq_done_finish_caller_shutdown (line);
1273 } 854 return GNUNET_SYSERR;
1274 855 }
856 pick = (struct ClientPhonePickupMessage *) buf;
857 pick->header.size = sizeof (buf);
858 pick->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP);
859 memcpy (&pick[1], metadata, len);
860 GNUNET_SERVER_notification_context_unicast (nc,
861 line->client,
862 &pick->header,
863 GNUNET_NO);
864 line->tunnel_unreliable = GNUNET_MESH_tunnel_create (mesh,
865 line,
866 &line->target,
867 GNUNET_APPLICATION_TYPE_CONVERSATION_AUDIO,
868 GNUNET_YES,
869 GNUNET_NO);
1275 return GNUNET_OK; 870 return GNUNET_OK;
1276} 871}
1277 872
873
1278/** 874/**
1279* Function to handle a terminate messaage incoming over mesh 875 * Function to handle a busy message incoming over mesh
876 *
1280 * @param cls closure, NULL 877 * @param cls closure, NULL
1281 * @param tunnel the tunnel over which the message arrived 878 * @param tunnel the tunnel over which the message arrived
1282 * @param tunnel_ctx the tunnel context, can be NULL 879 * @param tunnel_ctx the tunnel context, can be NULL
1283 * @param message the incoming message 880 * @param message the incoming message
1284 * 881 * @return #GNUNET_OK
1285 * @return GNUNET_OK 882 */
1286*/ 883static int
1287int 884handle_mesh_busy_message (void *cls,
1288handle_mesh_terminate_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel, 885 struct GNUNET_MESH_Tunnel *tunnel,
1289 void **tunnel_ctx, 886 void **tunnel_ctx,
1290 const struct GNUNET_MessageHeader *message) 887 const struct GNUNET_MessageHeader *message)
1291{ 888{
1292 //struct GNUNET_PeerIdentity *peer = (GNUNET_MESH_tunnel_get_info(tunnel, GNUNET_MESH_OPTION_PEER))->peer; 889 struct Line *line = *tunnel_ctx;
1293 const struct GNUNET_PeerIdentity *peer = 890 struct ClientPhoneBusyMessage busy;
1294 GNUNET_PEER_resolve2 (tunnel->peer); 891
1295 892 if (NULL == line)
1296 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 893 {
1297 _ 894 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1298 ("Handling MeshSessionTerminateMessage from peer: %s (connection.peer: %s)\n"), 895 "HANGUP message received for non-existing line, dropping tunnel.\n");
1299 GNUNET_i2s_full (peer), GNUNET_i2s_full (&(connection.peer))); 896 return GNUNET_SYSERR;
897 }
898 busy.header.size = sizeof (busy);
899 busy.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_BUSY);
900 GNUNET_SERVER_notification_context_unicast (nc,
901 line->client,
902 &busy.header,
903 GNUNET_NO);
1300 GNUNET_MESH_receive_done (tunnel); 904 GNUNET_MESH_receive_done (tunnel);
1301 905 *tunnel_ctx = NULL;
1302 if (!memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity)) 906 switch (line->status)
1303 && (connection.status == CONNECTED || connection.status == CALLEE)) 907 {
1304 { 908 case LS_CALLEE_LISTEN:
1305 status_to_listen (); 909 GNUNET_break (0);
1306 910 return GNUNET_SYSERR;
1307 if (NULL != tunnel_unreliable) 911 case LS_CALLEE_RINGING:
1308 { 912 GNUNET_break_op (0);
1309 GNUNET_MESH_tunnel_destroy (tunnel_unreliable); 913 break;
1310 tunnel_unreliable = NULL; 914 case LS_CALLEE_CONNECTED:
1311 } 915 GNUNET_break_op (0);
1312 916 break;
1313 if (NULL != tunnel_reliable) 917 case LS_CALLEE_SHUTDOWN:
1314 { 918 GNUNET_break_op (0);
1315 GNUNET_MESH_tunnel_destroy (tunnel_reliable); 919 break;
1316 tunnel_reliable = NULL; 920 case LS_CALLER_CALLING:
1317 } 921 line->status = LS_CALLER_SHUTDOWN;
1318 } 922 mq_done_finish_caller_shutdown (line);
1319 923 break;
924 case LS_CALLER_CONNECTED:
925 line->status = LS_CALLER_SHUTDOWN;
926 mq_done_finish_caller_shutdown (line);
927 break;
928 case LS_CALLER_SHUTDOWN:
929 mq_done_finish_caller_shutdown (line);
930 break;
931 }
1320 return GNUNET_OK; 932 return GNUNET_OK;
1321} 933}
1322 934
935
1323/** 936/**
1324* Function to handle a audio messaage incoming over mesh 937 * Function to handle an audio message incoming over mesh
938 *
1325 * @param cls closure, NULL 939 * @param cls closure, NULL
1326 * @param tunnel the tunnel over which the message arrived 940 * @param tunnel the tunnel over which the message arrived
1327 * @param tunnel_ctx the tunnel context, can be NULL 941 * @param tunnel_ctx the tunnel context, can be NULL
1328 * @param message the incoming message 942 * @param message the incoming message
1329 * 943 * @return #GNUNET_OK
1330 * @return GNUNET_OK 944 */
1331*/
1332int
1333handle_mesh_audio_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1334 void **tunnel_ctx,
1335 const struct GNUNET_MessageHeader *message)
1336{
1337 const struct AudioMessage *audio;
1338 audio = (const struct AudioMessage *) message;
1339
1340 GNUNET_MESH_receive_done (tunnel);
1341 if (CONNECTED != connection.status)
1342 return GNUNET_OK;
1343 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1344 "[RECV] %dbytes\n",
1345 ntohs (audio->header.size));
1346 if (NULL == playback_helper)
1347 return GNUNET_OK;
1348 (void) GNUNET_HELPER_send (playback_helper,
1349 message, GNUNET_YES, NULL, NULL);
1350 return GNUNET_OK;
1351}
1352
1353/******************************************************************************/
1354/*********************** HELPER *******************/
1355/******************************************************************************/
1356
1357/**
1358* Function to process the audio from the record helper
1359 * @param cls closure, NULL
1360 * @param client NULL
1361 * @param msg the message from the helper
1362 *
1363 * @return GNUNET_OK
1364*/
1365static int 945static int
1366process_record_messages (void *cls GNUNET_UNUSED, void *client, 946handle_mesh_audio_message (void *cls,
1367 const struct GNUNET_MessageHeader *msg) 947 struct GNUNET_MESH_Tunnel *tunnel,
948 void **tunnel_ctx,
949 const struct GNUNET_MessageHeader *message)
1368{ 950{
1369 const struct AudioMessage *message = (const struct AudioMessage *) msg; 951 const struct MeshAudioMessage *msg;
1370 952 struct Line *line = *tunnel_ctx;
1371 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 953 struct GNUNET_PeerIdentity sender;
1372 " [REC] %dbyte\n", 954 size_t msize = ntohs (message->size) - sizeof (struct MeshAudioMessage);
1373 ntohs (message->header.size)); 955 char buf[msize + sizeof (struct ClientAudioMessage)];
1374 GNUNET_CONTAINER_slist_add_end (audio_buffer, 956 struct ClientAudioMessage *cam;
1375 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, 957
1376 message, ntohs (message->header.size)); 958 msg = (const struct MeshAudioMessage *) message;
1377 959 if (NULL == line)
1378 return GNUNET_OK; 960 {
1379} 961 sender = *GNUNET_MESH_tunnel_get_info (tunnel,
1380 962 GNUNET_MESH_OPTION_PEER)->peer;
1381/** 963 for (line = lines_head; NULL != line; line = line->next)
1382* Function to to start the playback helper 964 if ( (line->local_line == ntohl (msg->remote_line)) &&
1383 * 965 (LS_CALLEE_CONNECTED == line->status) &&
1384 * @return 0 ok, 1 on error 966 (0 == memcmp (&line->target,
1385*/ 967 &sender,
1386int 968 sizeof (struct GNUNET_PeerIdentity))) &&
1387start_playback_helper (void) 969 (NULL == line->tunnel_unreliable) )
1388{ 970 break;
1389 static char *playback_helper_argv[1]; 971 if (NULL == line)
1390 int success = 1;
1391
1392 playback_helper_argv[0] = "gnunet-helper-audio-playback";
1393 playback_helper = GNUNET_HELPER_start (GNUNET_NO,
1394 "gnunet-helper-audio-playback",
1395 playback_helper_argv,
1396 NULL, NULL, NULL);
1397
1398 if (NULL == playback_helper)
1399 {
1400 success = 0;
1401 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1402 _("Could not start playback audio helper.\n"));
1403 }
1404
1405 return success;
1406}
1407
1408/**
1409* Function to to start the record helper
1410 *
1411 * @return 0 ok, 1 on error
1412*/
1413int
1414start_record_helper (void)
1415{
1416 static char *record_helper_argv[1];
1417 int success = 1;
1418
1419 record_helper_argv[0] = "gnunet-helper-audio-record";
1420 record_helper = GNUNET_HELPER_start (GNUNET_NO,
1421 "gnunet-helper-audio-record",
1422 record_helper_argv,
1423 &process_record_messages, NULL, NULL);
1424
1425 if (NULL == record_helper)
1426 {
1427 success = 0;
1428 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1429 _("Could not start record audio helper\n"));
1430 }
1431
1432 return success;
1433}
1434
1435
1436/**
1437* Function to to start both helpers
1438 *
1439 * @return 0 ok, 1 on error
1440*/
1441int
1442start_helpers (void)
1443{
1444
1445 if (0 == start_playback_helper () || 0 == start_record_helper ())
1446 {
1447 stop_helpers ();
1448 return 0;
1449 }
1450
1451 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Started helpers\n"));
1452
1453 return 1;
1454}
1455
1456/**
1457* Function to to stop the playback helper
1458*/
1459void
1460stop_playback_helper (void)
1461{
1462 if (NULL != playback_helper)
1463 {
1464 GNUNET_HELPER_stop (playback_helper, GNUNET_NO);
1465 playback_helper = NULL;
1466
1467 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Stopped playback helper\n"));
1468 }
1469}
1470
1471/**
1472* Function to to stop the record helper
1473*/
1474void
1475stop_record_helper (void)
1476{
1477 if (NULL != record_helper)
1478 { 972 {
1479 GNUNET_HELPER_stop (record_helper, GNUNET_NO); 973 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1480 record_helper = NULL; 974 "Received AUDIO data for non-existing line %u, dropping.\n",
1481 975 ntohl (msg->remote_line));
1482 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Stopped record helper\n")); 976 return GNUNET_SYSERR;
1483 } 977 }
978 line->tunnel_unreliable = tunnel;
979 *tunnel_ctx = line;
980 }
981 cam = (struct ClientAudioMessage *) buf;
982 cam->header.size = htons (sizeof (buf));
983 cam->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO);
984 memcpy (&cam[1], &msg[1], msize);
985 GNUNET_SERVER_notification_context_unicast (nc,
986 line->client,
987 &cam->header,
988 GNUNET_YES);
989 GNUNET_MESH_receive_done (tunnel);
990 return GNUNET_OK;
1484} 991}
1485 992
1486/**
1487* Function to stop both audio helpers
1488*/
1489void
1490stop_helpers (void)
1491{
1492 stop_playback_helper ();
1493 stop_record_helper ();
1494}
1495
1496/******************************************************************************/
1497/*********************** TUNNEL HANDLING *******************/
1498/******************************************************************************/
1499 993
1500/** 994/**
1501 * Method called whenever another peer has added us to a tunnel 995 * Method called whenever another peer has added us to a tunnel
@@ -1508,21 +1002,14 @@ stop_helpers (void)
1508 * @return initial tunnel context for the tunnel (can be NULL -- that's not an error) 1002 * @return initial tunnel context for the tunnel (can be NULL -- that's not an error)
1509 */ 1003 */
1510static void * 1004static void *
1511inbound_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel, 1005inbound_tunnel (void *cls,
1512 const struct GNUNET_PeerIdentity *initiator, uint32_t port) 1006 struct GNUNET_MESH_Tunnel *tunnel,
1007 const struct GNUNET_PeerIdentity *initiator,
1008 uint32_t port)
1513{ 1009{
1514 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1010 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1515 _("Received incoming tunnel on port %d\n"), port); 1011 _("Received incoming tunnel on port %d\n"),
1516 if (50003 == port) 1012 port);
1517 {
1518 tunnel_unreliable = tunnel;
1519
1520 start_time = GNUNET_TIME_absolute_get ();
1521
1522 start_helpers ();
1523 audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL);
1524 }
1525
1526 return NULL; 1013 return NULL;
1527} 1014}
1528 1015
@@ -1531,115 +1018,68 @@ inbound_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1531 * Function called whenever an inbound tunnel is destroyed. Should clean up 1018 * Function called whenever an inbound tunnel is destroyed. Should clean up
1532 * any associated state. 1019 * any associated state.
1533 * 1020 *
1534 * @param cls closure (set from GNUNET_MESH_connect) 1021 * @param cls closure (set from #GNUNET_MESH_connect)
1535 * @param tunnel connection to the other end (henceforth invalid) 1022 * @param tunnel connection to the other end (henceforth invalid)
1536 * @param tunnel_ctx place where local state associated 1023 * @param tunnel_ctx place where local state associated
1537 * with the tunnel is stored 1024 * with the tunnel is stored
1538 */ 1025 */
1539static void 1026static void
1540inbound_end (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, 1027inbound_end (void *cls,
1028 const struct GNUNET_MESH_Tunnel *tunnel,
1541 void *tunnel_ctx) 1029 void *tunnel_ctx)
1542{ 1030{
1543 if (tunnel == tunnel_unreliable) 1031 struct Line *line = tunnel_ctx;
1544 { 1032 struct ClientPhoneHangupMessage hup;
1545 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Tunnel closed: audio\n"); 1033
1546 1034 if (NULL == line)
1547 stop_helpers (); 1035 return;
1548 tunnel_unreliable = NULL; 1036 if (line->tunnel_unreliable == tunnel)
1549 } 1037 {
1550 1038 line->tunnel_unreliable = NULL;
1551 if (tunnel == tunnel_reliable) 1039 return;
1552 { 1040 }
1553 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Tunnel closed: control\n"); 1041 hup.header.size = sizeof (hup);
1554 1042 hup.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP);
1555 if (LISTEN != connection.status && NULL != connection.client) 1043 switch (line->status)
1556 { 1044 {
1557 if (NULL == 1045 case LS_CALLEE_LISTEN:
1558 GNUNET_SERVER_notify_transmit_ready (connection.client, 1046 GNUNET_break (0);
1559 sizeof (struct 1047 return;
1560 ServerClientSessionTerminateMessage), 1048 case LS_CALLEE_RINGING:
1561 MAX_TRANSMIT_DELAY, 1049 case LS_CALLEE_CONNECTED:
1562 &transmit_server_terminate_message, 1050 GNUNET_SERVER_notification_context_unicast (nc,
1563 NULL)) 1051 line->client,
1564 { 1052 &hup.header,
1565 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1053 GNUNET_NO);
1566 _ 1054 line->status = LS_CALLEE_LISTEN;
1567 ("Could not queue ServerClientSessionTerminateMessage\n")); 1055 break;
1568 } 1056 case LS_CALLEE_SHUTDOWN:
1569 } 1057 line->status = LS_CALLEE_LISTEN;
1570 1058 destroy_line_mesh_tunnels (line);
1571 status_to_listen (); 1059 break;
1572 } 1060 case LS_CALLER_CALLING:
1061 case LS_CALLER_CONNECTED:
1062 GNUNET_SERVER_notification_context_unicast (nc,
1063 line->client,
1064 &hup.header,
1065 GNUNET_NO);
1066 destroy_line_mesh_tunnels (line);
1067 GNUNET_CONTAINER_DLL_remove (lines_head,
1068 lines_tail,
1069 line);
1070 GNUNET_free_non_null (line->audio_data);
1071 GNUNET_free (line);
1072 break;
1073 case LS_CALLER_SHUTDOWN:
1074 destroy_line_mesh_tunnels (line);
1075 GNUNET_CONTAINER_DLL_remove (lines_head,
1076 lines_tail,
1077 line);
1078 GNUNET_free (line);
1079 break;
1080 }
1573} 1081}
1574 1082
1575/******************************************************************************/
1576/*********************** CLIENT HANDLING *******************/
1577/******************************************************************************/
1578
1579/**
1580 * A client connected.
1581 *
1582 * @param cls closure, NULL
1583 * @param client identification of the client
1584 */
1585
1586static void
1587handle_client_connect (void *cls, struct GNUNET_SERVER_Client *cl)
1588{
1589 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client connected\n");
1590 struct ServerClientMissedCallMessage *message;
1591 size_t msg_size;
1592 struct VoipClient c;
1593 c.client = cl;
1594
1595 GNUNET_CONTAINER_slist_add_end (clients,
1596 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1597 &c, sizeof (struct VoipClient));
1598 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Client added: %p\n"), cl);
1599
1600 if (0 < GNUNET_CONTAINER_slist_count (missed_calls))
1601 {
1602 int i = 0;
1603 msg_size =
1604 sizeof (struct ServerClientMissedCallMessage) +
1605 GNUNET_CONTAINER_slist_count (missed_calls) *
1606 sizeof (struct MissedCall);
1607 message =
1608 (struct ServerClientMissedCallMessage *) GNUNET_malloc (msg_size);
1609
1610 message->header.size = htons (msg_size);
1611 message->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_MISSED_CALL);
1612 message->number = GNUNET_CONTAINER_slist_count (missed_calls);
1613
1614 struct GNUNET_CONTAINER_SList_Iterator iterator =
1615 GNUNET_CONTAINER_slist_begin (missed_calls);
1616 do
1617 {
1618 memcpy (&(message->missed_call[i]),
1619 GNUNET_CONTAINER_slist_get (&iterator, NULL),
1620 sizeof (struct MissedCall));
1621 i++;
1622 }
1623 while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator));
1624
1625 GNUNET_CONTAINER_slist_iter_destroy (&iterator);
1626 GNUNET_CONTAINER_slist_clear (missed_calls);
1627
1628
1629 if (NULL ==
1630 GNUNET_SERVER_notify_transmit_ready (cl, msg_size,
1631 MAX_TRANSMIT_DELAY,
1632 &transmit_server_missed_call_message,
1633 (void *) message))
1634 {
1635 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1636 _("Could not queue ServerClientMissedCallMessage\n"));
1637 GNUNET_free (message);
1638 }
1639 }
1640
1641 return;
1642}
1643 1083
1644/** 1084/**
1645 * A client disconnected. Remove all of its data structure entries. 1085 * A client disconnected. Remove all of its data structure entries.
@@ -1648,42 +1088,21 @@ handle_client_connect (void *cls, struct GNUNET_SERVER_Client *cl)
1648 * @param client identification of the client 1088 * @param client identification of the client
1649 */ 1089 */
1650static void 1090static void
1651handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *cl) 1091handle_client_disconnect (void *cls,
1092 struct GNUNET_SERVER_Client *client)
1652{ 1093{
1653 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client disconnected\n"); 1094 struct Line *line;
1654 1095
1655 if (connection.client == cl) 1096 line = GNUNET_SERVER_client_get_user_context (client, struct Line);
1656 { 1097 if (NULL == line)
1657 if (CONNECTED == connection.status) 1098 return;
1658 { 1099 GNUNET_CONTAINER_DLL_remove (lines_head,
1659 terminate_call (); 1100 lines_tail,
1660 } 1101 line);
1661 else 1102 GNUNET_free (line);
1662 { 1103 GNUNET_SERVER_client_set_user_context (client, NULL);
1663 status_to_listen ();
1664 }
1665 }
1666
1667 struct GNUNET_CONTAINER_SList_Iterator iterator =
1668 GNUNET_CONTAINER_slist_begin (clients);
1669 do
1670 {
1671 if (((struct VoipClient *)
1672 GNUNET_CONTAINER_slist_get (&iterator, NULL))->client == cl)
1673 {
1674 GNUNET_CONTAINER_slist_erase (&iterator);
1675 }
1676 }
1677 while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator));
1678
1679 GNUNET_CONTAINER_slist_iter_destroy (&iterator);
1680
1681 return;
1682} 1104}
1683 1105
1684/******************************************************************************/
1685/*********************** SERVICE *******************/
1686/******************************************************************************/
1687 1106
1688/** 1107/**
1689 * Shutdown nicely 1108 * Shutdown nicely
@@ -1692,60 +1111,23 @@ handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *cl)
1692 * @param tc the task context 1111 * @param tc the task context
1693 */ 1112 */
1694static void 1113static void
1695do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 1114do_shutdown (void *cls,
1115 const struct GNUNET_SCHEDULER_TaskContext *tc)
1696{ 1116{
1697 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutdown\n");
1698
1699 stop_helpers ();
1700
1701 if (NULL != tunnel_reliable)
1702 {
1703 GNUNET_MESH_tunnel_destroy (tunnel_reliable);
1704 }
1705
1706 if (NULL != tunnel_unreliable)
1707 {
1708 GNUNET_MESH_tunnel_destroy (tunnel_unreliable);
1709 }
1710
1711 if (NULL != mesh) 1117 if (NULL != mesh)
1712 { 1118 {
1713 GNUNET_MESH_disconnect (mesh); 1119 GNUNET_MESH_disconnect (mesh);
1714 } 1120 mesh = NULL;
1715 1121 }
1716 if (NULL != nc) 1122 if (NULL != nc)
1717 { 1123 {
1718 GNUNET_SERVER_notification_context_destroy (nc); 1124 GNUNET_SERVER_notification_context_destroy (nc);
1719 nc = NULL; 1125 nc = NULL;
1720 } 1126 }
1721
1722 GNUNET_CONTAINER_slist_destroy (audio_buffer);
1723 GNUNET_CONTAINER_slist_destroy (clients);
1724 GNUNET_CONTAINER_slist_destroy (missed_calls);
1725 GNUNET_CONTAINER_slist_destroy (peers_to_notify);
1726} 1127}
1727 1128
1728 1129
1729/** 1130/**
1730 * Handler array for traffic received
1731 */
1732static struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
1733 {&handle_mesh_initiate_message,
1734 GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_INITIATE,
1735 sizeof (struct MeshSessionInitiateMessage)},
1736 {&handle_mesh_accept_message, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_ACCEPT,
1737 sizeof (struct MeshSessionAcceptMessage)},
1738 {&handle_mesh_reject_message, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_REJECT,
1739 sizeof (struct MeshSessionRejectMessage)},
1740 {&handle_mesh_terminate_message,
1741 GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_TERMINATE,
1742 sizeof (struct MeshSessionTerminateMessage)},
1743 {&handle_mesh_audio_message, GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO,
1744 sizeof (struct AudioMessage)},
1745 {NULL, 0, 0}
1746};
1747
1748/**
1749 * Main function that will be run by the scheduler. 1131 * Main function that will be run by the scheduler.
1750 * 1132 *
1751 * @param cls closure 1133 * @param cls closure
@@ -1753,67 +1135,77 @@ static struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
1753 * @param c configuration 1135 * @param c configuration
1754 */ 1136 */
1755static void 1137static void
1756run (void *cls, struct GNUNET_SERVER_Handle *server, 1138run (void *cls,
1139 struct GNUNET_SERVER_Handle *server,
1757 const struct GNUNET_CONFIGURATION_Handle *c) 1140 const struct GNUNET_CONFIGURATION_Handle *c)
1758{ 1141{
1142 static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
1143 {&handle_client_register_message, NULL,
1144 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_REGISTER,
1145 sizeof (struct ClientPhoneRegisterMessage)},
1146 {&handle_client_pickup_message, NULL,
1147 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP,
1148 0},
1149 {&handle_client_hangup_message, NULL,
1150 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP,
1151 0},
1152 {&handle_client_call_message, NULL,
1153 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL,
1154 0},
1155 {&handle_client_audio_message, NULL,
1156 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO,
1157 0},
1158 {NULL, NULL, 0, 0}
1159 };
1160 static struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
1161 {&handle_mesh_ring_message,
1162 GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_RING,
1163 sizeof (struct MeshPhoneRingMessage)},
1164 {&handle_mesh_hangup_message,
1165 GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_HANG_UP,
1166 0},
1167 {&handle_mesh_pickup_message,
1168 GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_PICK_UP,
1169 0},
1170 {&handle_mesh_busy_message,
1171 GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_BUSY,
1172 sizeof (struct MeshPhoneBusyMessage)},
1173 {&handle_mesh_audio_message, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_AUDIO,
1174 0},
1175 {NULL, 0, 0}
1176 };
1177 static uint32_t ports[] = {
1178 GNUNET_APPLICATION_TYPE_CONVERSATION_CONTROL,
1179 GNUNET_APPLICATION_TYPE_CONVERSATION_AUDIO,
1180 0
1181 };
1759 1182
1760 static uint32_t ports[] = { 50002, 50003, 0 };
1761 cfg = c; 1183 cfg = c;
1762 1184 GNUNET_assert (GNUNET_OK ==
1185 GNUNET_CRYPTO_get_host_identity (cfg,
1186 &my_identity));
1763 mesh = GNUNET_MESH_connect (cfg, 1187 mesh = GNUNET_MESH_connect (cfg,
1764 NULL, 1188 NULL,
1765 &inbound_tunnel, 1189 &inbound_tunnel,
1766 &inbound_end, mesh_handlers, ports); 1190 &inbound_end,
1191 mesh_handlers,
1192 ports);
1767 1193
1768 if (NULL == mesh) 1194 if (NULL == mesh)
1769 { 1195 {
1770 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Couldn't connect to mesh\n"); 1196 GNUNET_break (0);
1771 return; 1197 GNUNET_SCHEDULER_shutdown ();
1772 } 1198 return;
1773 else 1199 }
1774 {
1775 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connected to mesh\n");
1776 }
1777
1778 static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
1779 {&handle_session_initiate_message, NULL,
1780 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_INITIATE,
1781 sizeof (struct ClientServerSessionInitiateMessage)},
1782 {&handle_session_accept_message, NULL,
1783 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_ACCEPT,
1784 sizeof (struct ClientServerSessionAcceptMessage)},
1785 {&handle_session_reject_message, NULL,
1786 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_REJECT,
1787 sizeof (struct ClientServerSessionRejectMessage)},
1788 {&handle_session_terminate_message, NULL,
1789 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_TERMINATE,
1790 sizeof (struct ClientServerSessionTerminateMessage)},
1791 {NULL, NULL, 0, 0}
1792 };
1793
1794 connection.status = LISTEN;
1795
1796 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"),
1797 connection.status);
1798
1799 nc = GNUNET_SERVER_notification_context_create (server, 16); 1200 nc = GNUNET_SERVER_notification_context_create (server, 16);
1800
1801 GNUNET_SERVER_add_handlers (server, server_handlers); 1201 GNUNET_SERVER_add_handlers (server, server_handlers);
1802 GNUNET_SERVER_connect_notify (server, &handle_client_connect, NULL);
1803 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL); 1202 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
1804 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, 1203 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
1204 &do_shutdown,
1805 NULL); 1205 NULL);
1806
1807 clients = GNUNET_CONTAINER_slist_create ();
1808
1809 // Missed calls
1810 missed_calls = GNUNET_CONTAINER_slist_create ();
1811 peers_to_notify = GNUNET_CONTAINER_slist_create ();
1812 audio_buffer = GNUNET_CONTAINER_slist_create ();
1813
1814 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Voip service running\n"));
1815} 1206}
1816 1207
1208
1817/** 1209/**
1818 * The main function for the conversation service. 1210 * The main function for the conversation service.
1819 * 1211 *
@@ -1822,10 +1214,13 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
1822 * @return 0 ok, 1 on error 1214 * @return 0 ok, 1 on error
1823 */ 1215 */
1824int 1216int
1825main (int argc, char *const *argv) 1217main (int argc,
1218 char *const *argv)
1826{ 1219{
1827 return (GNUNET_OK == 1220 return (GNUNET_OK ==
1828 GNUNET_SERVICE_run (argc, argv, "conversation", GNUNET_SERVICE_OPTION_NONE, 1221 GNUNET_SERVICE_run (argc, argv,
1222 "conversation",
1223 GNUNET_SERVICE_OPTION_NONE,
1829 &run, NULL)) ? 0 : 1; 1224 &run, NULL)) ? 0 : 1;
1830} 1225}
1831 1226