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