diff options
Diffstat (limited to 'src/conversation/gnunet-service-conversation.c')
-rw-r--r-- | src/conversation/gnunet-service-conversation.c | 1381 |
1 files changed, 0 insertions, 1381 deletions
diff --git a/src/conversation/gnunet-service-conversation.c b/src/conversation/gnunet-service-conversation.c deleted file mode 100644 index a69c95a80..000000000 --- a/src/conversation/gnunet-service-conversation.c +++ /dev/null | |||
@@ -1,1381 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013, 2016, 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your 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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file conversation/gnunet-service-conversation.c | ||
22 | * @brief conversation service implementation | ||
23 | * @author Simon Dieterle | ||
24 | * @author Andreas Fuchs | ||
25 | * @author Christian Grothoff | ||
26 | */ | ||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_protocols.h" | ||
30 | #include "gnunet_applications.h" | ||
31 | #include "gnunet_constants.h" | ||
32 | #include "gnunet_signatures.h" | ||
33 | #include "gnunet_cadet_service.h" | ||
34 | #include "gnunet_conversation_service.h" | ||
35 | #include "conversation.h" | ||
36 | |||
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 | ||
44 | |||
45 | |||
46 | /** | ||
47 | * A line connects a local client with a cadet channel (or, if it is an | ||
48 | * open line, is waiting for a cadet channel). | ||
49 | */ | ||
50 | struct Line; | ||
51 | |||
52 | /** | ||
53 | * The possible connection status | ||
54 | */ | ||
55 | enum ChannelStatus | ||
56 | { | ||
57 | /** | ||
58 | * We just got the connection, but no introduction yet. | ||
59 | */ | ||
60 | CS_CALLEE_INIT, | ||
61 | |||
62 | /** | ||
63 | * Our phone is ringing, waiting for the client to pick up. | ||
64 | */ | ||
65 | CS_CALLEE_RINGING, | ||
66 | |||
67 | /** | ||
68 | * We are talking! | ||
69 | */ | ||
70 | CS_CALLEE_CONNECTED, | ||
71 | |||
72 | /** | ||
73 | * We're in shutdown, sending hangup messages before cleaning up. | ||
74 | */ | ||
75 | CS_CALLEE_SHUTDOWN, | ||
76 | |||
77 | /** | ||
78 | * We are waiting for the phone to be picked up. | ||
79 | */ | ||
80 | CS_CALLER_CALLING, | ||
81 | |||
82 | /** | ||
83 | * We are talking! | ||
84 | */ | ||
85 | CS_CALLER_CONNECTED, | ||
86 | |||
87 | /** | ||
88 | * We're in shutdown, sending hangup messages before cleaning up. | ||
89 | */ | ||
90 | CS_CALLER_SHUTDOWN | ||
91 | }; | ||
92 | |||
93 | |||
94 | /** | ||
95 | * A `struct Channel` represents a cadet channel, which is a P2P | ||
96 | * connection to another conversation service. Multiple channels can | ||
97 | * be attached the the same `struct Line`, which represents a local | ||
98 | * client. We keep them in a linked list. | ||
99 | */ | ||
100 | struct Channel | ||
101 | { | ||
102 | /** | ||
103 | * This is a DLL. | ||
104 | */ | ||
105 | struct Channel *next; | ||
106 | |||
107 | /** | ||
108 | * This is a DLL. | ||
109 | */ | ||
110 | struct Channel *prev; | ||
111 | |||
112 | /** | ||
113 | * Line associated with the channel. | ||
114 | */ | ||
115 | struct Line *line; | ||
116 | |||
117 | /** | ||
118 | * Handle for the channel. | ||
119 | */ | ||
120 | struct GNUNET_CADET_Channel *channel; | ||
121 | |||
122 | /** | ||
123 | * Message queue for control messages | ||
124 | */ | ||
125 | struct GNUNET_MQ_Handle *mq; | ||
126 | |||
127 | /** | ||
128 | * Temporary buffer for audio data in the @e mq. | ||
129 | */ | ||
130 | struct GNUNET_MQ_Envelope *env; | ||
131 | |||
132 | /** | ||
133 | * Channel identifier we use for this call with the client. | ||
134 | */ | ||
135 | uint32_t cid; | ||
136 | |||
137 | /** | ||
138 | * Current status of this line. | ||
139 | */ | ||
140 | enum ChannelStatus status; | ||
141 | |||
142 | /** | ||
143 | * #GNUNET_YES if the channel was suspended by the other peer. | ||
144 | */ | ||
145 | int8_t suspended_remote; | ||
146 | |||
147 | /** | ||
148 | * #GNUNET_YES if the channel was suspended by the local client. | ||
149 | */ | ||
150 | int8_t suspended_local; | ||
151 | }; | ||
152 | |||
153 | |||
154 | /** | ||
155 | * A `struct Line` connects a local client with cadet channels. | ||
156 | */ | ||
157 | struct Line | ||
158 | { | ||
159 | /** | ||
160 | * This is a DLL. | ||
161 | */ | ||
162 | struct Channel *channel_head; | ||
163 | |||
164 | /** | ||
165 | * This is a DLL. | ||
166 | */ | ||
167 | struct Channel *channel_tail; | ||
168 | |||
169 | /** | ||
170 | * Handle to the line client. | ||
171 | */ | ||
172 | struct GNUNET_SERVICE_Client *client; | ||
173 | |||
174 | /** | ||
175 | * Message queue for @e client. | ||
176 | */ | ||
177 | struct GNUNET_MQ_Handle *mq; | ||
178 | |||
179 | /** | ||
180 | * Our open port. | ||
181 | */ | ||
182 | struct GNUNET_CADET_Port *port; | ||
183 | |||
184 | /** | ||
185 | * Port number we are listening on (to verify signatures). | ||
186 | * Only valid if @e port is non-NULL. | ||
187 | */ | ||
188 | struct GNUNET_HashCode line_port; | ||
189 | |||
190 | /** | ||
191 | * Generator for channel IDs. | ||
192 | */ | ||
193 | uint32_t cid_gen; | ||
194 | }; | ||
195 | |||
196 | |||
197 | /** | ||
198 | * Our configuration. | ||
199 | */ | ||
200 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
201 | |||
202 | /** | ||
203 | * Handle for cadet | ||
204 | */ | ||
205 | static struct GNUNET_CADET_Handle *cadet; | ||
206 | |||
207 | /** | ||
208 | * Identity of this peer. | ||
209 | */ | ||
210 | static struct GNUNET_PeerIdentity my_identity; | ||
211 | |||
212 | |||
213 | /** | ||
214 | * Given a @a cid, find the corresponding channel given | ||
215 | * a @a line. | ||
216 | * | ||
217 | * @param line a line to search | ||
218 | * @param cid what to search for | ||
219 | * @return NULL for not found | ||
220 | */ | ||
221 | static struct Channel * | ||
222 | find_channel_by_line (struct Line *line, uint32_t cid) | ||
223 | { | ||
224 | for (struct Channel *ch = line->channel_head; NULL != ch; ch = ch->next) | ||
225 | if (cid == ch->cid) | ||
226 | return ch; | ||
227 | return NULL; | ||
228 | } | ||
229 | |||
230 | |||
231 | /** | ||
232 | * Function to handle a pickup request message from the client | ||
233 | * | ||
234 | * @param cls the `struct Line` of the client from which the message is | ||
235 | * @param msg the message from the client | ||
236 | */ | ||
237 | static void | ||
238 | handle_client_pickup_message (void *cls, | ||
239 | const struct ClientPhonePickupMessage *msg) | ||
240 | { | ||
241 | struct Line *line = cls; | ||
242 | struct CadetPhonePickupMessage *mppm; | ||
243 | struct GNUNET_MQ_Envelope *env; | ||
244 | struct Channel *ch; | ||
245 | |||
246 | if (NULL == line->port) | ||
247 | { | ||
248 | /* we never opened the port, bad client! */ | ||
249 | GNUNET_break_op (0); | ||
250 | GNUNET_SERVICE_client_drop (line->client); | ||
251 | return; | ||
252 | } | ||
253 | for (ch = line->channel_head; NULL != ch; ch = ch->next) | ||
254 | if (msg->cid == ch->cid) | ||
255 | break; | ||
256 | if (NULL == ch) | ||
257 | { | ||
258 | /* could have been destroyed asynchronously, ignore message */ | ||
259 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Channel %u not found\n", msg->cid); | ||
260 | GNUNET_SERVICE_client_continue (line->client); | ||
261 | return; | ||
262 | } | ||
263 | switch (ch->status) | ||
264 | { | ||
265 | case CS_CALLEE_INIT: | ||
266 | GNUNET_break (0); | ||
267 | GNUNET_SERVICE_client_drop (line->client); | ||
268 | return; | ||
269 | |||
270 | case CS_CALLEE_RINGING: | ||
271 | ch->status = CS_CALLEE_CONNECTED; | ||
272 | break; | ||
273 | |||
274 | case CS_CALLEE_CONNECTED: | ||
275 | GNUNET_break (0); | ||
276 | GNUNET_SERVICE_client_drop (line->client); | ||
277 | return; | ||
278 | |||
279 | case CS_CALLEE_SHUTDOWN: | ||
280 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
281 | "Ignoring client's PICKUP message, line is in SHUTDOWN\n"); | ||
282 | break; | ||
283 | |||
284 | case CS_CALLER_CALLING: | ||
285 | case CS_CALLER_CONNECTED: | ||
286 | case CS_CALLER_SHUTDOWN: | ||
287 | GNUNET_break (0); | ||
288 | GNUNET_SERVICE_client_drop (line->client); | ||
289 | return; | ||
290 | } | ||
291 | GNUNET_break (CS_CALLEE_CONNECTED == ch->status); | ||
292 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending PICK_UP message to cadet\n"); | ||
293 | env = | ||
294 | GNUNET_MQ_msg (mppm, GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_PICK_UP); | ||
295 | GNUNET_MQ_send (ch->mq, env); | ||
296 | GNUNET_SERVICE_client_continue (line->client); | ||
297 | } | ||
298 | |||
299 | |||
300 | /** | ||
301 | * Channel went down, notify client and free data | ||
302 | * structure. | ||
303 | * | ||
304 | * @param ch channel that went down | ||
305 | */ | ||
306 | static void | ||
307 | clean_up_channel (struct Channel *ch) | ||
308 | { | ||
309 | struct Line *line = ch->line; | ||
310 | struct GNUNET_MQ_Envelope *env; | ||
311 | struct ClientPhoneHangupMessage *hup; | ||
312 | |||
313 | switch (ch->status) | ||
314 | { | ||
315 | case CS_CALLEE_INIT: | ||
316 | case CS_CALLEE_SHUTDOWN: | ||
317 | case CS_CALLER_SHUTDOWN: | ||
318 | break; | ||
319 | |||
320 | case CS_CALLEE_RINGING: | ||
321 | case CS_CALLEE_CONNECTED: | ||
322 | case CS_CALLER_CALLING: | ||
323 | case CS_CALLER_CONNECTED: | ||
324 | if (NULL != line) | ||
325 | { | ||
326 | env = | ||
327 | GNUNET_MQ_msg (hup, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP); | ||
328 | hup->cid = ch->cid; | ||
329 | GNUNET_MQ_send (line->mq, env); | ||
330 | } | ||
331 | break; | ||
332 | } | ||
333 | if (NULL != line) | ||
334 | GNUNET_CONTAINER_DLL_remove (line->channel_head, line->channel_tail, ch); | ||
335 | GNUNET_free (ch); | ||
336 | } | ||
337 | |||
338 | |||
339 | /** | ||
340 | * Destroy a channel. | ||
341 | * | ||
342 | * @param ch channel to destroy. | ||
343 | */ | ||
344 | static void | ||
345 | destroy_line_cadet_channels (struct Channel *ch) | ||
346 | { | ||
347 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Destroying cadet channels\n"); | ||
348 | if (NULL != ch->channel) | ||
349 | { | ||
350 | GNUNET_CADET_channel_destroy (ch->channel); | ||
351 | ch->channel = NULL; | ||
352 | } | ||
353 | clean_up_channel (ch); | ||
354 | } | ||
355 | |||
356 | |||
357 | /** | ||
358 | * We are done signalling shutdown to the other peer. Close down | ||
359 | * the channel. | ||
360 | * | ||
361 | * @param cls the `struct Channel` to reset/terminate | ||
362 | */ | ||
363 | static void | ||
364 | mq_done_finish_caller_shutdown (void *cls) | ||
365 | { | ||
366 | struct Channel *ch = cls; | ||
367 | |||
368 | switch (ch->status) | ||
369 | { | ||
370 | case CS_CALLEE_INIT: | ||
371 | GNUNET_break (0); | ||
372 | break; | ||
373 | |||
374 | case CS_CALLEE_RINGING: | ||
375 | GNUNET_break (0); | ||
376 | break; | ||
377 | |||
378 | case CS_CALLEE_CONNECTED: | ||
379 | GNUNET_break (0); | ||
380 | break; | ||
381 | |||
382 | case CS_CALLEE_SHUTDOWN: | ||
383 | destroy_line_cadet_channels (ch); | ||
384 | break; | ||
385 | |||
386 | case CS_CALLER_CALLING: | ||
387 | GNUNET_break (0); | ||
388 | break; | ||
389 | |||
390 | case CS_CALLER_CONNECTED: | ||
391 | GNUNET_break (0); | ||
392 | break; | ||
393 | |||
394 | case CS_CALLER_SHUTDOWN: | ||
395 | destroy_line_cadet_channels (ch); | ||
396 | break; | ||
397 | } | ||
398 | } | ||
399 | |||
400 | |||
401 | /** | ||
402 | * Function to handle a hangup request message from the client | ||
403 | * | ||
404 | * @param cls the `struct Line` the hangup is for | ||
405 | * @param msg the message from the client | ||
406 | */ | ||
407 | static void | ||
408 | handle_client_hangup_message (void *cls, | ||
409 | const struct ClientPhoneHangupMessage *msg) | ||
410 | { | ||
411 | struct Line *line = cls; | ||
412 | struct GNUNET_MQ_Envelope *e; | ||
413 | struct CadetPhoneHangupMessage *mhum; | ||
414 | struct Channel *ch; | ||
415 | |||
416 | for (ch = line->channel_head; NULL != ch; ch = ch->next) | ||
417 | if (msg->cid == ch->cid) | ||
418 | break; | ||
419 | if (NULL == ch) | ||
420 | { | ||
421 | /* could have been destroyed asynchronously, ignore message */ | ||
422 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Channel %u not found\n", msg->cid); | ||
423 | GNUNET_SERVICE_client_continue (line->client); | ||
424 | return; | ||
425 | } | ||
426 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
427 | "Received HANGUP for channel %u which is in state %d\n", | ||
428 | msg->cid, | ||
429 | ch->status); | ||
430 | switch (ch->status) | ||
431 | { | ||
432 | case CS_CALLEE_INIT: | ||
433 | GNUNET_break (0); | ||
434 | GNUNET_SERVICE_client_drop (line->client); | ||
435 | return; | ||
436 | |||
437 | case CS_CALLEE_RINGING: | ||
438 | ch->status = CS_CALLEE_SHUTDOWN; | ||
439 | break; | ||
440 | |||
441 | case CS_CALLEE_CONNECTED: | ||
442 | ch->status = CS_CALLEE_SHUTDOWN; | ||
443 | break; | ||
444 | |||
445 | case CS_CALLEE_SHUTDOWN: | ||
446 | /* maybe the other peer closed asynchronously... */ | ||
447 | GNUNET_SERVICE_client_continue (line->client); | ||
448 | return; | ||
449 | |||
450 | case CS_CALLER_CALLING: | ||
451 | ch->status = CS_CALLER_SHUTDOWN; | ||
452 | break; | ||
453 | |||
454 | case CS_CALLER_CONNECTED: | ||
455 | ch->status = CS_CALLER_SHUTDOWN; | ||
456 | break; | ||
457 | |||
458 | case CS_CALLER_SHUTDOWN: | ||
459 | /* maybe the other peer closed asynchronously... */ | ||
460 | GNUNET_SERVICE_client_continue (line->client); | ||
461 | return; | ||
462 | } | ||
463 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending HANG_UP message via cadet\n"); | ||
464 | e = | ||
465 | GNUNET_MQ_msg (mhum, GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_HANG_UP); | ||
466 | GNUNET_MQ_notify_sent (e, &mq_done_finish_caller_shutdown, ch); | ||
467 | GNUNET_MQ_send (ch->mq, e); | ||
468 | GNUNET_SERVICE_client_continue (line->client); | ||
469 | } | ||
470 | |||
471 | |||
472 | /** | ||
473 | * Function to handle a suspend request message from the client | ||
474 | * | ||
475 | * @param cls the `struct Line` the message is about | ||
476 | * @param msg the message from the client | ||
477 | */ | ||
478 | static void | ||
479 | handle_client_suspend_message (void *cls, | ||
480 | const struct ClientPhoneSuspendMessage *msg) | ||
481 | { | ||
482 | struct Line *line = cls; | ||
483 | struct GNUNET_MQ_Envelope *e; | ||
484 | struct CadetPhoneSuspendMessage *mhum; | ||
485 | struct Channel *ch; | ||
486 | |||
487 | for (ch = line->channel_head; NULL != ch; ch = ch->next) | ||
488 | if (msg->cid == ch->cid) | ||
489 | break; | ||
490 | if (NULL == ch) | ||
491 | { | ||
492 | /* could have been destroyed asynchronously, ignore message */ | ||
493 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Channel %u not found\n", msg->cid); | ||
494 | GNUNET_SERVICE_client_continue (line->client); | ||
495 | return; | ||
496 | } | ||
497 | if (GNUNET_YES == ch->suspended_local) | ||
498 | { | ||
499 | GNUNET_break (0); | ||
500 | GNUNET_SERVICE_client_drop (line->client); | ||
501 | return; | ||
502 | } | ||
503 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
504 | "Received SUSPEND for channel %u which is in state %d\n", | ||
505 | msg->cid, | ||
506 | ch->status); | ||
507 | switch (ch->status) | ||
508 | { | ||
509 | case CS_CALLEE_INIT: | ||
510 | GNUNET_break (0); | ||
511 | GNUNET_SERVICE_client_drop (line->client); | ||
512 | return; | ||
513 | |||
514 | case CS_CALLEE_RINGING: | ||
515 | GNUNET_break (0); | ||
516 | GNUNET_SERVICE_client_drop (line->client); | ||
517 | return; | ||
518 | |||
519 | case CS_CALLEE_CONNECTED: | ||
520 | ch->suspended_local = GNUNET_YES; | ||
521 | break; | ||
522 | |||
523 | case CS_CALLEE_SHUTDOWN: | ||
524 | /* maybe the other peer closed asynchronously... */ | ||
525 | GNUNET_SERVICE_client_continue (line->client); | ||
526 | return; | ||
527 | |||
528 | case CS_CALLER_CALLING: | ||
529 | GNUNET_break (0); | ||
530 | GNUNET_SERVICE_client_drop (line->client); | ||
531 | return; | ||
532 | |||
533 | case CS_CALLER_CONNECTED: | ||
534 | ch->suspended_local = GNUNET_YES; | ||
535 | break; | ||
536 | |||
537 | case CS_CALLER_SHUTDOWN: | ||
538 | /* maybe the other peer closed asynchronously... */ | ||
539 | GNUNET_SERVICE_client_continue (line->client); | ||
540 | return; | ||
541 | } | ||
542 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUSPEND message via cadet\n"); | ||
543 | e = | ||
544 | GNUNET_MQ_msg (mhum, GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_SUSPEND); | ||
545 | GNUNET_MQ_send (ch->mq, e); | ||
546 | GNUNET_SERVICE_client_continue (line->client); | ||
547 | } | ||
548 | |||
549 | |||
550 | /** | ||
551 | * Function to handle a resume request message from the client | ||
552 | * | ||
553 | * @param cls the `struct Line` the message is about | ||
554 | * @param msg the message from the client | ||
555 | */ | ||
556 | static void | ||
557 | handle_client_resume_message (void *cls, | ||
558 | const struct ClientPhoneResumeMessage *msg) | ||
559 | { | ||
560 | struct Line *line = cls; | ||
561 | struct GNUNET_MQ_Envelope *e; | ||
562 | struct CadetPhoneResumeMessage *mhum; | ||
563 | struct Channel *ch; | ||
564 | |||
565 | for (ch = line->channel_head; NULL != ch; ch = ch->next) | ||
566 | if (msg->cid == ch->cid) | ||
567 | break; | ||
568 | if (NULL == ch) | ||
569 | { | ||
570 | /* could have been destroyed asynchronously, ignore message */ | ||
571 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Channel %u not found\n", msg->cid); | ||
572 | GNUNET_SERVICE_client_continue (line->client); | ||
573 | return; | ||
574 | } | ||
575 | if (GNUNET_YES != ch->suspended_local) | ||
576 | { | ||
577 | GNUNET_break (0); | ||
578 | GNUNET_SERVICE_client_drop (line->client); | ||
579 | return; | ||
580 | } | ||
581 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
582 | "Received RESUME for channel %u which is in state %d\n", | ||
583 | msg->cid, | ||
584 | ch->status); | ||
585 | switch (ch->status) | ||
586 | { | ||
587 | case CS_CALLEE_INIT: | ||
588 | GNUNET_break (0); | ||
589 | GNUNET_SERVICE_client_drop (line->client); | ||
590 | return; | ||
591 | |||
592 | case CS_CALLEE_RINGING: | ||
593 | GNUNET_break (0); | ||
594 | GNUNET_SERVICE_client_drop (line->client); | ||
595 | return; | ||
596 | |||
597 | case CS_CALLEE_CONNECTED: | ||
598 | ch->suspended_local = GNUNET_NO; | ||
599 | break; | ||
600 | |||
601 | case CS_CALLEE_SHUTDOWN: | ||
602 | /* maybe the other peer closed asynchronously... */ | ||
603 | GNUNET_SERVICE_client_continue (line->client); | ||
604 | return; | ||
605 | |||
606 | case CS_CALLER_CALLING: | ||
607 | GNUNET_break (0); | ||
608 | GNUNET_SERVICE_client_drop (line->client); | ||
609 | return; | ||
610 | |||
611 | case CS_CALLER_CONNECTED: | ||
612 | ch->suspended_local = GNUNET_NO; | ||
613 | break; | ||
614 | |||
615 | case CS_CALLER_SHUTDOWN: | ||
616 | /* maybe the other peer closed asynchronously... */ | ||
617 | GNUNET_SERVICE_client_drop (line->client); | ||
618 | return; | ||
619 | } | ||
620 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending RESUME message via cadet\n"); | ||
621 | e = GNUNET_MQ_msg (mhum, GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RESUME); | ||
622 | GNUNET_MQ_send (ch->mq, e); | ||
623 | GNUNET_SERVICE_client_continue (line->client); | ||
624 | } | ||
625 | |||
626 | |||
627 | /** | ||
628 | * Transmission of audio data via cadet channel finished. | ||
629 | * | ||
630 | * @param cls the `struct Channel` we are transmitting for | ||
631 | */ | ||
632 | static void | ||
633 | channel_audio_sent_notify (void *cls) | ||
634 | { | ||
635 | struct Channel *ch = cls; | ||
636 | |||
637 | ch->env = NULL; | ||
638 | } | ||
639 | |||
640 | |||
641 | /** | ||
642 | * Function to check audio data from the client | ||
643 | * | ||
644 | * @param cls the `struct Line` the message is about | ||
645 | * @param msg the message from the client | ||
646 | * @return #GNUNET_OK (any data is ok) | ||
647 | */ | ||
648 | static int | ||
649 | check_client_audio_message (void *cls, const struct ClientAudioMessage *msg) | ||
650 | { | ||
651 | (void) cls; | ||
652 | (void) msg; | ||
653 | return GNUNET_OK; | ||
654 | } | ||
655 | |||
656 | |||
657 | /** | ||
658 | * Function to handle audio data from the client | ||
659 | * | ||
660 | * @param cls the `struct Line` the message is about | ||
661 | * @param msg the message from the client | ||
662 | */ | ||
663 | static void | ||
664 | handle_client_audio_message (void *cls, const struct ClientAudioMessage *msg) | ||
665 | { | ||
666 | struct Line *line = cls; | ||
667 | struct CadetAudioMessage *mam; | ||
668 | struct Channel *ch; | ||
669 | size_t size; | ||
670 | |||
671 | size = ntohs (msg->header.size) - sizeof(struct ClientAudioMessage); | ||
672 | ch = find_channel_by_line (line, msg->cid); | ||
673 | if (NULL == ch) | ||
674 | { | ||
675 | /* could have been destroyed asynchronously, ignore message */ | ||
676 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Channel %u not found\n", msg->cid); | ||
677 | GNUNET_SERVICE_client_continue (line->client); | ||
678 | return; | ||
679 | } | ||
680 | |||
681 | switch (ch->status) | ||
682 | { | ||
683 | case CS_CALLEE_INIT: | ||
684 | case CS_CALLEE_RINGING: | ||
685 | case CS_CALLER_CALLING: | ||
686 | GNUNET_break (0); | ||
687 | GNUNET_SERVICE_client_drop (line->client); | ||
688 | return; | ||
689 | |||
690 | case CS_CALLEE_CONNECTED: | ||
691 | case CS_CALLER_CONNECTED: | ||
692 | /* common case, handled below */ | ||
693 | break; | ||
694 | |||
695 | case CS_CALLEE_SHUTDOWN: | ||
696 | case CS_CALLER_SHUTDOWN: | ||
697 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, | ||
698 | "Cadet audio channel in shutdown; audio data dropped\n"); | ||
699 | GNUNET_SERVICE_client_continue (line->client); | ||
700 | return; | ||
701 | } | ||
702 | if (GNUNET_YES == ch->suspended_local) | ||
703 | { | ||
704 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
705 | "This channel is suspended locally\n"); | ||
706 | GNUNET_SERVICE_client_drop (line->client); | ||
707 | return; | ||
708 | } | ||
709 | if (NULL != ch->env) | ||
710 | { | ||
711 | /* NOTE: we may want to not do this and instead combine the data */ | ||
712 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
713 | "Bandwidth insufficient; dropping previous audio data segment\n"); | ||
714 | GNUNET_MQ_send_cancel (ch->env); | ||
715 | ch->env = NULL; | ||
716 | } | ||
717 | |||
718 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
719 | "Received %u bytes of AUDIO data from client CID %u\n", | ||
720 | (unsigned int) size, | ||
721 | msg->cid); | ||
722 | ch->env = GNUNET_MQ_msg_extra (mam, | ||
723 | size, | ||
724 | GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_AUDIO); | ||
725 | GNUNET_memcpy (&mam[1], &msg[1], size); | ||
726 | /* FIXME: set options for unreliable transmission */ | ||
727 | GNUNET_MQ_notify_sent (ch->env, &channel_audio_sent_notify, ch); | ||
728 | GNUNET_MQ_send (ch->mq, ch->env); | ||
729 | GNUNET_SERVICE_client_continue (line->client); | ||
730 | } | ||
731 | |||
732 | |||
733 | /** | ||
734 | * Function to handle a ring message incoming over cadet | ||
735 | * | ||
736 | * @param cls closure, NULL | ||
737 | * @param msg the incoming message | ||
738 | */ | ||
739 | static void | ||
740 | handle_cadet_ring_message (void *cls, const struct CadetPhoneRingMessage *msg) | ||
741 | { | ||
742 | struct Channel *ch = cls; | ||
743 | struct Line *line = ch->line; | ||
744 | struct GNUNET_MQ_Envelope *env; | ||
745 | struct ClientPhoneRingMessage *cring; | ||
746 | struct CadetPhoneRingInfoPS rs; | ||
747 | |||
748 | rs.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING); | ||
749 | rs.purpose.size = htonl (sizeof(struct CadetPhoneRingInfoPS)); | ||
750 | rs.line_port = line->line_port; | ||
751 | rs.target_peer = my_identity; | ||
752 | rs.expiration_time = msg->expiration_time; | ||
753 | |||
754 | if (GNUNET_OK != | ||
755 | GNUNET_IDENTITY_signature_verify ( | ||
756 | GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING, | ||
757 | &rs, | ||
758 | &msg->signature, | ||
759 | &msg->caller_id)) | ||
760 | { | ||
761 | GNUNET_break_op (0); | ||
762 | destroy_line_cadet_channels (ch); | ||
763 | return; | ||
764 | } | ||
765 | if (0 == GNUNET_TIME_absolute_get_remaining ( | ||
766 | GNUNET_TIME_absolute_ntoh (msg->expiration_time)) | ||
767 | .rel_value_us) | ||
768 | { | ||
769 | /* ancient call, replay? */ | ||
770 | GNUNET_break_op (0); | ||
771 | /* Note that our reliance on time here is awkward; better would be | ||
772 | to use a more complex challenge-response protocol against | ||
773 | replay attacks. Left for future work ;-). */ | ||
774 | destroy_line_cadet_channels (ch); | ||
775 | return; | ||
776 | } | ||
777 | if (CS_CALLEE_INIT != ch->status) | ||
778 | { | ||
779 | GNUNET_break_op (0); | ||
780 | destroy_line_cadet_channels (ch); | ||
781 | return; | ||
782 | } | ||
783 | GNUNET_CADET_receive_done (ch->channel); | ||
784 | ch->status = CS_CALLEE_RINGING; | ||
785 | env = GNUNET_MQ_msg (cring, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RING); | ||
786 | cring->cid = ch->cid; | ||
787 | cring->caller_id = msg->caller_id; | ||
788 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
789 | "Sending RING message to client. CID is %u\n", | ||
790 | (unsigned int) ch->cid); | ||
791 | GNUNET_MQ_send (line->mq, env); | ||
792 | } | ||
793 | |||
794 | |||
795 | /** | ||
796 | * Function to handle a hangup message incoming over cadet | ||
797 | * | ||
798 | * @param cls closure, our `struct Channel *` | ||
799 | * @param message the incoming message | ||
800 | */ | ||
801 | static void | ||
802 | handle_cadet_hangup_message (void *cls, | ||
803 | const struct CadetPhoneHangupMessage *message) | ||
804 | { | ||
805 | struct Channel *ch = cls; | ||
806 | struct Line *line = ch->line; | ||
807 | struct GNUNET_MQ_Envelope *env; | ||
808 | struct ClientPhoneHangupMessage *hup; | ||
809 | enum ChannelStatus status; | ||
810 | uint32_t cid; | ||
811 | |||
812 | (void) message; | ||
813 | GNUNET_CADET_receive_done (ch->channel); | ||
814 | cid = ch->cid; | ||
815 | status = ch->status; | ||
816 | destroy_line_cadet_channels (ch); | ||
817 | switch (status) | ||
818 | { | ||
819 | case CS_CALLEE_INIT: | ||
820 | GNUNET_break_op (0); | ||
821 | return; | ||
822 | |||
823 | case CS_CALLEE_RINGING: | ||
824 | case CS_CALLEE_CONNECTED: | ||
825 | break; | ||
826 | |||
827 | case CS_CALLEE_SHUTDOWN: | ||
828 | return; | ||
829 | |||
830 | case CS_CALLER_CALLING: | ||
831 | case CS_CALLER_CONNECTED: | ||
832 | break; | ||
833 | |||
834 | case CS_CALLER_SHUTDOWN: | ||
835 | return; | ||
836 | } | ||
837 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending HANG UP message to client\n"); | ||
838 | env = GNUNET_MQ_msg (hup, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP); | ||
839 | hup->cid = cid; | ||
840 | GNUNET_MQ_send (line->mq, env); | ||
841 | } | ||
842 | |||
843 | |||
844 | /** | ||
845 | * Function to handle a pickup message incoming over cadet | ||
846 | * | ||
847 | * @param cls closure, our `struct Channel *` | ||
848 | * @param message the incoming message | ||
849 | */ | ||
850 | static void | ||
851 | handle_cadet_pickup_message (void *cls, | ||
852 | const struct CadetPhonePickupMessage *message) | ||
853 | { | ||
854 | struct Channel *ch = cls; | ||
855 | struct Line *line = ch->line; | ||
856 | struct GNUNET_MQ_Envelope *env; | ||
857 | struct ClientPhonePickedupMessage *pick; | ||
858 | |||
859 | (void) message; | ||
860 | GNUNET_CADET_receive_done (ch->channel); | ||
861 | switch (ch->status) | ||
862 | { | ||
863 | case CS_CALLEE_INIT: | ||
864 | case CS_CALLEE_RINGING: | ||
865 | case CS_CALLEE_CONNECTED: | ||
866 | GNUNET_break_op (0); | ||
867 | destroy_line_cadet_channels (ch); | ||
868 | return; | ||
869 | |||
870 | case CS_CALLEE_SHUTDOWN: | ||
871 | GNUNET_break_op (0); | ||
872 | destroy_line_cadet_channels (ch); | ||
873 | return; | ||
874 | |||
875 | case CS_CALLER_CALLING: | ||
876 | ch->status = CS_CALLER_CONNECTED; | ||
877 | break; | ||
878 | |||
879 | case CS_CALLER_CONNECTED: | ||
880 | GNUNET_break_op (0); | ||
881 | return; | ||
882 | |||
883 | case CS_CALLER_SHUTDOWN: | ||
884 | GNUNET_break_op (0); | ||
885 | mq_done_finish_caller_shutdown (ch); | ||
886 | return; | ||
887 | } | ||
888 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending PICKED UP message to client\n"); | ||
889 | env = | ||
890 | GNUNET_MQ_msg (pick, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICKED_UP); | ||
891 | pick->cid = ch->cid; | ||
892 | GNUNET_MQ_send (line->mq, env); | ||
893 | } | ||
894 | |||
895 | |||
896 | /** | ||
897 | * Function to handle a suspend message incoming over cadet | ||
898 | * | ||
899 | * @param cls closure, our `struct Channel *` | ||
900 | * @param message the incoming message | ||
901 | */ | ||
902 | static void | ||
903 | handle_cadet_suspend_message (void *cls, | ||
904 | const struct CadetPhoneSuspendMessage *message) | ||
905 | { | ||
906 | struct Channel *ch = cls; | ||
907 | struct Line *line = ch->line; | ||
908 | struct GNUNET_MQ_Envelope *env; | ||
909 | struct ClientPhoneSuspendMessage *suspend; | ||
910 | |||
911 | (void) message; | ||
912 | GNUNET_CADET_receive_done (ch->channel); | ||
913 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Suspending channel CID: %u\n", ch->cid); | ||
914 | switch (ch->status) | ||
915 | { | ||
916 | case CS_CALLEE_INIT: | ||
917 | GNUNET_break_op (0); | ||
918 | break; | ||
919 | |||
920 | case CS_CALLEE_RINGING: | ||
921 | GNUNET_break_op (0); | ||
922 | break; | ||
923 | |||
924 | case CS_CALLEE_CONNECTED: | ||
925 | ch->suspended_remote = GNUNET_YES; | ||
926 | break; | ||
927 | |||
928 | case CS_CALLEE_SHUTDOWN: | ||
929 | return; | ||
930 | |||
931 | case CS_CALLER_CALLING: | ||
932 | GNUNET_break_op (0); | ||
933 | break; | ||
934 | |||
935 | case CS_CALLER_CONNECTED: | ||
936 | ch->suspended_remote = GNUNET_YES; | ||
937 | break; | ||
938 | |||
939 | case CS_CALLER_SHUTDOWN: | ||
940 | return; | ||
941 | } | ||
942 | env = | ||
943 | GNUNET_MQ_msg (suspend, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND); | ||
944 | suspend->cid = ch->cid; | ||
945 | GNUNET_MQ_send (line->mq, env); | ||
946 | } | ||
947 | |||
948 | |||
949 | /** | ||
950 | * Function to handle a resume message incoming over cadet | ||
951 | * | ||
952 | * @param cls closure, our `struct Channel *` | ||
953 | * @param msg the incoming message | ||
954 | */ | ||
955 | static void | ||
956 | handle_cadet_resume_message (void *cls, | ||
957 | const struct CadetPhoneResumeMessage *msg) | ||
958 | { | ||
959 | struct Channel *ch = cls; | ||
960 | struct Line *line; | ||
961 | struct GNUNET_MQ_Envelope *env; | ||
962 | struct ClientPhoneResumeMessage *resume; | ||
963 | |||
964 | (void) msg; | ||
965 | line = ch->line; | ||
966 | GNUNET_CADET_receive_done (ch->channel); | ||
967 | if (GNUNET_YES != ch->suspended_remote) | ||
968 | { | ||
969 | GNUNET_log ( | ||
970 | GNUNET_ERROR_TYPE_DEBUG, | ||
971 | "RESUME message received for non-suspended channel, dropping channel.\n"); | ||
972 | destroy_line_cadet_channels (ch); | ||
973 | return; | ||
974 | } | ||
975 | switch (ch->status) | ||
976 | { | ||
977 | case CS_CALLEE_INIT: | ||
978 | GNUNET_break (0); | ||
979 | break; | ||
980 | |||
981 | case CS_CALLEE_RINGING: | ||
982 | GNUNET_break (0); | ||
983 | break; | ||
984 | |||
985 | case CS_CALLEE_CONNECTED: | ||
986 | ch->suspended_remote = GNUNET_NO; | ||
987 | break; | ||
988 | |||
989 | case CS_CALLEE_SHUTDOWN: | ||
990 | return; | ||
991 | |||
992 | case CS_CALLER_CALLING: | ||
993 | GNUNET_break (0); | ||
994 | break; | ||
995 | |||
996 | case CS_CALLER_CONNECTED: | ||
997 | ch->suspended_remote = GNUNET_NO; | ||
998 | break; | ||
999 | |||
1000 | case CS_CALLER_SHUTDOWN: | ||
1001 | return; | ||
1002 | } | ||
1003 | env = | ||
1004 | GNUNET_MQ_msg (resume, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME); | ||
1005 | resume->cid = ch->cid; | ||
1006 | GNUNET_MQ_send (line->mq, env); | ||
1007 | } | ||
1008 | |||
1009 | |||
1010 | /** | ||
1011 | * Function to check an audio message incoming over cadet | ||
1012 | * | ||
1013 | * @param cls closure, our `struct Channel *` | ||
1014 | * @param msg the incoming message | ||
1015 | * @return #GNUNET_OK (always) | ||
1016 | */ | ||
1017 | static int | ||
1018 | check_cadet_audio_message (void *cls, const struct CadetAudioMessage *msg) | ||
1019 | { | ||
1020 | (void) cls; | ||
1021 | (void) msg; | ||
1022 | return GNUNET_OK; /* any payload is fine */ | ||
1023 | } | ||
1024 | |||
1025 | |||
1026 | /** | ||
1027 | * Function to handle an audio message incoming over cadet | ||
1028 | * | ||
1029 | * @param cls closure, our `struct Channel *` | ||
1030 | * @param msg the incoming message | ||
1031 | */ | ||
1032 | static void | ||
1033 | handle_cadet_audio_message (void *cls, const struct CadetAudioMessage *msg) | ||
1034 | { | ||
1035 | struct Channel *ch = cls; | ||
1036 | size_t msize = ntohs (msg->header.size) - sizeof(struct CadetAudioMessage); | ||
1037 | struct GNUNET_MQ_Envelope *env; | ||
1038 | struct ClientAudioMessage *cam; | ||
1039 | |||
1040 | GNUNET_CADET_receive_done (ch->channel); | ||
1041 | if ((GNUNET_YES == ch->suspended_local) || | ||
1042 | (GNUNET_YES == ch->suspended_remote)) | ||
1043 | { | ||
1044 | GNUNET_log ( | ||
1045 | GNUNET_ERROR_TYPE_DEBUG, | ||
1046 | "Received %u bytes of AUDIO data on suspended channel CID %u; dropping\n", | ||
1047 | (unsigned int) msize, | ||
1048 | ch->cid); | ||
1049 | return; | ||
1050 | } | ||
1051 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1052 | "Forwarding %u bytes of AUDIO data to client CID %u\n", | ||
1053 | (unsigned int) msize, | ||
1054 | ch->cid); | ||
1055 | env = | ||
1056 | GNUNET_MQ_msg_extra (cam, msize, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO); | ||
1057 | cam->cid = ch->cid; | ||
1058 | GNUNET_memcpy (&cam[1], &msg[1], msize); | ||
1059 | GNUNET_MQ_send (ch->line->mq, env); | ||
1060 | } | ||
1061 | |||
1062 | |||
1063 | /** | ||
1064 | * Function called whenever an inbound channel is destroyed. Should clean up | ||
1065 | * any associated state. | ||
1066 | * | ||
1067 | * @param cls closure (set from #GNUNET_CADET_connect) | ||
1068 | * @param channel connection to the other end (henceforth invalid) | ||
1069 | */ | ||
1070 | static void | ||
1071 | inbound_end (void *cls, const struct GNUNET_CADET_Channel *channel) | ||
1072 | { | ||
1073 | struct Channel *ch = cls; | ||
1074 | |||
1075 | GNUNET_assert (channel == ch->channel); | ||
1076 | ch->channel = NULL; | ||
1077 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1078 | "Channel destroyed by CADET in state %d\n", | ||
1079 | ch->status); | ||
1080 | clean_up_channel (ch); | ||
1081 | } | ||
1082 | |||
1083 | |||
1084 | /** | ||
1085 | * Function to handle call request from the client | ||
1086 | * | ||
1087 | * @param cls the `struct Line` the message is about | ||
1088 | * @param msg the message from the client | ||
1089 | */ | ||
1090 | static void | ||
1091 | handle_client_call_message (void *cls, const struct ClientCallMessage *msg) | ||
1092 | { | ||
1093 | struct Line *line = cls; | ||
1094 | struct Channel *ch = GNUNET_new (struct Channel); | ||
1095 | struct GNUNET_MQ_MessageHandler cadet_handlers[] = | ||
1096 | { GNUNET_MQ_hd_fixed_size (cadet_hangup_message, | ||
1097 | GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_HANG_UP, | ||
1098 | struct CadetPhoneHangupMessage, | ||
1099 | ch), | ||
1100 | GNUNET_MQ_hd_fixed_size (cadet_pickup_message, | ||
1101 | GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_PICK_UP, | ||
1102 | struct CadetPhonePickupMessage, | ||
1103 | ch), | ||
1104 | GNUNET_MQ_hd_fixed_size (cadet_suspend_message, | ||
1105 | GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_SUSPEND, | ||
1106 | struct CadetPhoneSuspendMessage, | ||
1107 | ch), | ||
1108 | GNUNET_MQ_hd_fixed_size (cadet_resume_message, | ||
1109 | GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RESUME, | ||
1110 | struct CadetPhoneResumeMessage, | ||
1111 | ch), | ||
1112 | GNUNET_MQ_hd_var_size (cadet_audio_message, | ||
1113 | GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_AUDIO, | ||
1114 | struct CadetAudioMessage, | ||
1115 | ch), | ||
1116 | GNUNET_MQ_handler_end () }; | ||
1117 | struct GNUNET_MQ_Envelope *e; | ||
1118 | struct CadetPhoneRingMessage *ring; | ||
1119 | struct CadetPhoneRingInfoPS rs; | ||
1120 | |||
1121 | line->line_port = msg->line_port; | ||
1122 | rs.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING); | ||
1123 | rs.purpose.size = htonl (sizeof(struct CadetPhoneRingInfoPS)); | ||
1124 | rs.line_port = line->line_port; | ||
1125 | rs.target_peer = msg->target; | ||
1126 | rs.expiration_time = | ||
1127 | GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (RING_TIMEOUT)); | ||
1128 | ch->line = line; | ||
1129 | GNUNET_CONTAINER_DLL_insert (line->channel_head, line->channel_tail, ch); | ||
1130 | ch->status = CS_CALLER_CALLING; | ||
1131 | ch->channel = GNUNET_CADET_channel_create (cadet, | ||
1132 | ch, | ||
1133 | &msg->target, | ||
1134 | &msg->line_port, | ||
1135 | NULL, | ||
1136 | &inbound_end, | ||
1137 | cadet_handlers); | ||
1138 | ch->mq = GNUNET_CADET_get_mq (ch->channel); | ||
1139 | e = GNUNET_MQ_msg (ring, GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RING); | ||
1140 | GNUNET_IDENTITY_key_get_public (&msg->caller_id, &ring->caller_id); | ||
1141 | ring->expiration_time = rs.expiration_time; | ||
1142 | GNUNET_IDENTITY_sign (&msg->caller_id, &rs, &ring->signature); | ||
1143 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending RING message via CADET\n"); | ||
1144 | GNUNET_MQ_send (ch->mq, e); | ||
1145 | GNUNET_SERVICE_client_continue (line->client); | ||
1146 | } | ||
1147 | |||
1148 | |||
1149 | /** | ||
1150 | * Method called whenever another peer has added us to a channel | ||
1151 | * the other peer initiated. | ||
1152 | * | ||
1153 | * @param cls the `struct Line` receiving a connection | ||
1154 | * @param channel new handle to the channel | ||
1155 | * @param initiator peer that started the channel | ||
1156 | * @return initial channel context for the channel | ||
1157 | */ | ||
1158 | static void * | ||
1159 | inbound_channel (void *cls, | ||
1160 | struct GNUNET_CADET_Channel *channel, | ||
1161 | const struct GNUNET_PeerIdentity *initiator) | ||
1162 | { | ||
1163 | struct Line *line = cls; | ||
1164 | struct Channel *ch; | ||
1165 | |||
1166 | (void) initiator; | ||
1167 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1168 | "Received incoming cadet channel on line %p\n", | ||
1169 | line); | ||
1170 | ch = GNUNET_new (struct Channel); | ||
1171 | ch->status = CS_CALLEE_INIT; | ||
1172 | ch->line = line; | ||
1173 | ch->channel = channel; | ||
1174 | ch->mq = GNUNET_CADET_get_mq (ch->channel); | ||
1175 | ch->cid = line->cid_gen++; | ||
1176 | GNUNET_CONTAINER_DLL_insert (line->channel_head, line->channel_tail, ch); | ||
1177 | return ch; | ||
1178 | } | ||
1179 | |||
1180 | |||
1181 | /** | ||
1182 | * A client connected. Initialize the `struct Line` data structure. | ||
1183 | * | ||
1184 | * @param cls closure, NULL | ||
1185 | * @param client identification of the client | ||
1186 | * @param mq message queue for @a client | ||
1187 | * @return the `struct Line` for the client | ||
1188 | */ | ||
1189 | static void * | ||
1190 | client_connect_cb (void *cls, | ||
1191 | struct GNUNET_SERVICE_Client *client, | ||
1192 | struct GNUNET_MQ_Handle *mq) | ||
1193 | { | ||
1194 | struct Line *line; | ||
1195 | |||
1196 | (void) cls; | ||
1197 | line = GNUNET_new (struct Line); | ||
1198 | line->client = client; | ||
1199 | line->mq = mq; | ||
1200 | return line; | ||
1201 | } | ||
1202 | |||
1203 | |||
1204 | /** | ||
1205 | * A client disconnected. Remove all of its data structure entries. | ||
1206 | * | ||
1207 | * @param cls closure, NULL | ||
1208 | * @param client identification of the client | ||
1209 | * @param app_ctx our `struct Line *` for @a client | ||
1210 | */ | ||
1211 | static void | ||
1212 | client_disconnect_cb (void *cls, | ||
1213 | struct GNUNET_SERVICE_Client *client, | ||
1214 | void *app_ctx) | ||
1215 | { | ||
1216 | struct Line *line = app_ctx; | ||
1217 | struct Channel *chn; | ||
1218 | |||
1219 | (void) cls; | ||
1220 | (void) client; | ||
1221 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client disconnected, closing line\n"); | ||
1222 | if (NULL != line->port) | ||
1223 | { | ||
1224 | GNUNET_CADET_close_port (line->port); | ||
1225 | line->port = NULL; | ||
1226 | } | ||
1227 | for (struct Channel *ch = line->channel_head; NULL != ch; ch = chn) | ||
1228 | { | ||
1229 | chn = ch->next; | ||
1230 | ch->line = NULL; | ||
1231 | destroy_line_cadet_channels (ch); | ||
1232 | } | ||
1233 | GNUNET_free (line); | ||
1234 | } | ||
1235 | |||
1236 | |||
1237 | /** | ||
1238 | * Function to register a phone. | ||
1239 | * | ||
1240 | * @param cls the `struct Line` of the client from which the message is | ||
1241 | * @param msg the message from the client | ||
1242 | */ | ||
1243 | static void | ||
1244 | handle_client_register_message (void *cls, | ||
1245 | const struct ClientPhoneRegisterMessage *msg) | ||
1246 | { | ||
1247 | struct Line *line = cls; | ||
1248 | struct GNUNET_MQ_MessageHandler cadet_handlers[] = | ||
1249 | { GNUNET_MQ_hd_fixed_size (cadet_ring_message, | ||
1250 | GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RING, | ||
1251 | struct CadetPhoneRingMessage, | ||
1252 | NULL), | ||
1253 | GNUNET_MQ_hd_fixed_size (cadet_hangup_message, | ||
1254 | GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_HANG_UP, | ||
1255 | struct CadetPhoneHangupMessage, | ||
1256 | NULL), | ||
1257 | GNUNET_MQ_hd_fixed_size (cadet_pickup_message, | ||
1258 | GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_PICK_UP, | ||
1259 | struct CadetPhonePickupMessage, | ||
1260 | NULL), | ||
1261 | GNUNET_MQ_hd_fixed_size (cadet_suspend_message, | ||
1262 | GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_SUSPEND, | ||
1263 | struct CadetPhoneSuspendMessage, | ||
1264 | NULL), | ||
1265 | GNUNET_MQ_hd_fixed_size (cadet_resume_message, | ||
1266 | GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RESUME, | ||
1267 | struct CadetPhoneResumeMessage, | ||
1268 | NULL), | ||
1269 | GNUNET_MQ_hd_var_size (cadet_audio_message, | ||
1270 | GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_AUDIO, | ||
1271 | struct CadetAudioMessage, | ||
1272 | NULL), | ||
1273 | GNUNET_MQ_handler_end () }; | ||
1274 | |||
1275 | line->line_port = msg->line_port; | ||
1276 | line->port = GNUNET_CADET_open_port (cadet, | ||
1277 | &msg->line_port, | ||
1278 | &inbound_channel, | ||
1279 | line, | ||
1280 | NULL, | ||
1281 | &inbound_end, | ||
1282 | cadet_handlers); | ||
1283 | if (NULL == line->port) | ||
1284 | { | ||
1285 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1286 | _ ("Could not open line, port %s already in use!\n"), | ||
1287 | GNUNET_h2s (&msg->line_port)); | ||
1288 | GNUNET_SERVICE_client_drop (line->client); | ||
1289 | return; | ||
1290 | } | ||
1291 | GNUNET_SERVICE_client_continue (line->client); | ||
1292 | } | ||
1293 | |||
1294 | |||
1295 | /** | ||
1296 | * Shutdown nicely | ||
1297 | * | ||
1298 | * @param cls closure, NULL | ||
1299 | */ | ||
1300 | static void | ||
1301 | do_shutdown (void *cls) | ||
1302 | { | ||
1303 | (void) cls; | ||
1304 | if (NULL != cadet) | ||
1305 | { | ||
1306 | GNUNET_CADET_disconnect (cadet); | ||
1307 | cadet = NULL; | ||
1308 | } | ||
1309 | } | ||
1310 | |||
1311 | |||
1312 | /** | ||
1313 | * Main function that will be run by the scheduler. | ||
1314 | * | ||
1315 | * @param cls closure | ||
1316 | * @param c configuration | ||
1317 | * @param service service handle | ||
1318 | */ | ||
1319 | static void | ||
1320 | run (void *cls, | ||
1321 | const struct GNUNET_CONFIGURATION_Handle *c, | ||
1322 | struct GNUNET_SERVICE_Handle *service) | ||
1323 | { | ||
1324 | (void) cls; | ||
1325 | (void) service; | ||
1326 | cfg = c; | ||
1327 | GNUNET_assert (GNUNET_OK == | ||
1328 | GNUNET_CRYPTO_get_peer_identity (cfg, &my_identity)); | ||
1329 | cadet = GNUNET_CADET_connect (cfg); | ||
1330 | if (NULL == cadet) | ||
1331 | { | ||
1332 | GNUNET_break (0); | ||
1333 | GNUNET_SCHEDULER_shutdown (); | ||
1334 | return; | ||
1335 | } | ||
1336 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); | ||
1337 | } | ||
1338 | |||
1339 | |||
1340 | /** | ||
1341 | * Define "main" method using service macro. | ||
1342 | */ | ||
1343 | GNUNET_SERVICE_MAIN ( | ||
1344 | "conversation", | ||
1345 | GNUNET_SERVICE_OPTION_NONE, | ||
1346 | &run, | ||
1347 | &client_connect_cb, | ||
1348 | &client_disconnect_cb, | ||
1349 | NULL, | ||
1350 | GNUNET_MQ_hd_fixed_size (client_register_message, | ||
1351 | GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_REGISTER, | ||
1352 | struct ClientPhoneRegisterMessage, | ||
1353 | NULL), | ||
1354 | GNUNET_MQ_hd_fixed_size (client_pickup_message, | ||
1355 | GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP, | ||
1356 | struct ClientPhonePickupMessage, | ||
1357 | NULL), | ||
1358 | GNUNET_MQ_hd_fixed_size (client_suspend_message, | ||
1359 | GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND, | ||
1360 | struct ClientPhoneSuspendMessage, | ||
1361 | NULL), | ||
1362 | GNUNET_MQ_hd_fixed_size (client_resume_message, | ||
1363 | GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME, | ||
1364 | struct ClientPhoneResumeMessage, | ||
1365 | NULL), | ||
1366 | GNUNET_MQ_hd_fixed_size (client_hangup_message, | ||
1367 | GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP, | ||
1368 | struct ClientPhoneHangupMessage, | ||
1369 | NULL), | ||
1370 | GNUNET_MQ_hd_fixed_size (client_call_message, | ||
1371 | GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL, | ||
1372 | struct ClientCallMessage, | ||
1373 | NULL), | ||
1374 | GNUNET_MQ_hd_var_size (client_audio_message, | ||
1375 | GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO, | ||
1376 | struct ClientAudioMessage, | ||
1377 | NULL), | ||
1378 | GNUNET_MQ_handler_end ()); | ||
1379 | |||
1380 | |||
1381 | /* end of gnunet-service-conversation.c */ | ||