aboutsummaryrefslogtreecommitdiff
path: root/src/conversation/conversation_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/conversation/conversation_api.c')
-rw-r--r--src/conversation/conversation_api.c871
1 files changed, 0 insertions, 871 deletions
diff --git a/src/conversation/conversation_api.c b/src/conversation/conversation_api.c
deleted file mode 100644
index 1984abdd6..000000000
--- a/src/conversation/conversation_api.c
+++ /dev/null
@@ -1,871 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013, 2014 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/**
22 * @file conversation/conversation_api.c
23 * @brief phone and caller API to the conversation service
24 * @author Simon Dieterle
25 * @author Andreas Fuchs
26 * @author Christian Grothoff
27 */
28#include "platform.h"
29#include "gnunet_conversation_service.h"
30#include "conversation.h"
31
32
33/**
34 * Possible states of a caller.
35 */
36enum CallerState
37{
38 /**
39 * The phone is ringing (user knows about incoming call).
40 */
41 CS_RINGING,
42
43 /**
44 * The phone is in an active conversation.
45 */
46 CS_ACTIVE,
47
48 /**
49 * We suspended the conversation.
50 */
51 CS_CALLEE_SUSPENDED,
52
53 /**
54 * Caller suspended the conversation.
55 */
56 CS_CALLER_SUSPENDED,
57
58 /**
59 * Both sides suspended the conversation.
60 */
61 CS_BOTH_SUSPENDED
62};
63
64
65/**
66 * A caller is the handle we have for an incoming call.
67 */
68struct GNUNET_CONVERSATION_Caller
69{
70 /**
71 * We keep all callers in a DLL.
72 */
73 struct GNUNET_CONVERSATION_Caller *next;
74
75 /**
76 * We keep all callers in a DLL.
77 */
78 struct GNUNET_CONVERSATION_Caller *prev;
79
80 /**
81 * Our phone.
82 */
83 struct GNUNET_CONVERSATION_Phone *phone;
84
85 /**
86 * Function to call for phone events.
87 */
88 GNUNET_CONVERSATION_CallerEventHandler event_handler;
89
90 /**
91 * Closure for @e event_handler
92 */
93 void *event_handler_cls;
94
95 /**
96 * Speaker, or NULL if none is attached.
97 */
98 struct GNUNET_SPEAKER_Handle *speaker;
99
100 /**
101 * Microphone, or NULL if none is attached.
102 */
103 struct GNUNET_MICROPHONE_Handle *mic;
104
105 /**
106 * Identity of the person calling us.
107 */
108 struct GNUNET_IDENTITY_PublicKey caller_id;
109
110 /**
111 * Internal handle to identify the caller with the service.
112 */
113 uint32_t cid;
114
115 /**
116 * State machine for the phone.
117 */
118 enum CallerState state;
119};
120
121
122/**
123 * Possible states of a phone.
124 */
125enum PhoneState
126{
127 /**
128 * We still need to register the phone.
129 */
130 PS_REGISTER = 0,
131
132 /**
133 * We are waiting for calls.
134 */
135 PS_READY
136};
137
138
139/**
140 * A phone is a device that can ring to signal an incoming call and
141 * that you can pick up to answer the call and hang up to terminate
142 * the call. You can also hang up a ringing phone immediately
143 * (without picking it up) to stop it from ringing. Phones have
144 * caller ID. You can ask the phone for its record and make that
145 * record available (via GNS) to enable others to call you.
146 * Multiple phones maybe connected to the same line (the line is
147 * something rather internal to a phone and not obvious from it).
148 * You can only have one conversation per phone at any time.
149 */
150struct GNUNET_CONVERSATION_Phone
151{
152 /**
153 * Our configuration.
154 */
155 const struct GNUNET_CONFIGURATION_Handle *cfg;
156
157 /**
158 * We keep all callers in a DLL.
159 */
160 struct GNUNET_CONVERSATION_Caller *caller_head;
161
162 /**
163 * We keep all callers in a DLL.
164 */
165 struct GNUNET_CONVERSATION_Caller *caller_tail;
166
167 /**
168 * Function to call for phone events.
169 */
170 GNUNET_CONVERSATION_PhoneEventHandler event_handler;
171
172 /**
173 * Closure for @e event_handler
174 */
175 void *event_handler_cls;
176
177 /**
178 * Connection to NAMESTORE (for reverse lookup).
179 */
180 struct GNUNET_NAMESTORE_Handle *ns;
181
182 /**
183 * Handle for transmitting to the CONVERSATION service.
184 */
185 struct GNUNET_MQ_Handle *mq;
186
187 /**
188 * This phone's record.
189 */
190 struct GNUNET_CONVERSATION_PhoneRecord my_record;
191
192 /**
193 * My GNS zone.
194 */
195 struct GNUNET_IDENTITY_PrivateKey my_zone;
196
197 /**
198 * State machine for the phone.
199 */
200 enum PhoneState state;
201};
202
203
204/**
205 * The phone got disconnected, reconnect to the service.
206 *
207 * @param phone phone to reconnect
208 */
209static void
210reconnect_phone (struct GNUNET_CONVERSATION_Phone *phone);
211
212
213/**
214 * Process recorded audio data.
215 *
216 * @param cls closure with the `struct GNUNET_CONVERSATION_Caller`
217 * @param data_size number of bytes in @a data
218 * @param data audio data to play
219 */
220static void
221transmit_phone_audio (void *cls,
222 size_t data_size,
223 const void *data)
224{
225 struct GNUNET_CONVERSATION_Caller *caller = cls;
226 struct GNUNET_CONVERSATION_Phone *phone = caller->phone;
227 struct GNUNET_MQ_Envelope *e;
228 struct ClientAudioMessage *am;
229
230 e = GNUNET_MQ_msg_extra (am,
231 data_size,
232 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO);
233 am->cid = caller->cid;
234 GNUNET_memcpy (&am[1],
235 data,
236 data_size);
237 GNUNET_MQ_send (phone->mq,
238 e);
239}
240
241
242/**
243 * We received a `struct ClientPhoneRingMessage`
244 *
245 * @param cls the `struct GNUNET_CONVERSATION_Phone`
246 * @param ring the message
247 */
248static void
249handle_phone_ring (void *cls,
250 const struct ClientPhoneRingMessage *ring)
251{
252 struct GNUNET_CONVERSATION_Phone *phone = cls;
253 struct GNUNET_CONVERSATION_Caller *caller;
254
255 switch (phone->state)
256 {
257 case PS_REGISTER:
258 GNUNET_assert (0);
259 break;
260
261 case PS_READY:
262 caller = GNUNET_new (struct GNUNET_CONVERSATION_Caller);
263 caller->phone = phone;
264 GNUNET_CONTAINER_DLL_insert (phone->caller_head,
265 phone->caller_tail,
266 caller);
267 caller->caller_id = ring->caller_id;
268 caller->cid = ring->cid;
269 caller->state = CS_RINGING;
270 phone->event_handler (phone->event_handler_cls,
271 GNUNET_CONVERSATION_EC_PHONE_RING,
272 caller,
273 &caller->caller_id);
274 break;
275 }
276}
277
278
279/**
280 * Find the record of the caller matching the @a cid
281 *
282 * @param phone phone to search
283 * @param cid caller ID to search for (in NBO)
284 * @return NULL if @a cid was not found
285 */
286static struct GNUNET_CONVERSATION_Caller *
287find_caller (struct GNUNET_CONVERSATION_Phone *phone,
288 uint32_t cid)
289{
290 struct GNUNET_CONVERSATION_Caller *caller;
291
292 for (caller = phone->caller_head; NULL != caller; caller = caller->next)
293 if (cid == caller->cid)
294 return caller;
295 return NULL;
296}
297
298
299/**
300 * We received a `struct ClientPhoneHangupMessage`.
301 *
302 * @param cls the `struct GNUNET_CONVERSATION_Phone *`
303 * @param msg the message
304 */
305static void
306handle_phone_hangup (void *cls,
307 const struct ClientPhoneHangupMessage *hang)
308{
309 struct GNUNET_CONVERSATION_Phone *phone = cls;
310 struct GNUNET_CONVERSATION_Caller *caller;
311
312 caller = find_caller (phone,
313 hang->cid);
314 if (NULL == caller)
315 {
316 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
317 "Received HANG_UP message for unknown caller ID %u\n",
318 (unsigned int) hang->cid);
319 return;
320 }
321
322 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
323 "Received HANG_UP message, terminating call with `%s'\n",
324 GNUNET_GNSRECORD_pkey_to_zkey (&caller->caller_id));
325 switch (caller->state)
326 {
327 case CS_RINGING:
328 phone->event_handler (phone->event_handler_cls,
329 GNUNET_CONVERSATION_EC_PHONE_HUNG_UP,
330 caller,
331 &caller->caller_id);
332 break;
333
334 case CS_ACTIVE:
335 caller->speaker->disable_speaker (caller->speaker->cls);
336 caller->mic->disable_microphone (caller->mic->cls);
337 phone->event_handler (phone->event_handler_cls,
338 GNUNET_CONVERSATION_EC_PHONE_HUNG_UP,
339 caller,
340 &caller->caller_id);
341 break;
342
343 case CS_CALLEE_SUSPENDED:
344 case CS_CALLER_SUSPENDED:
345 case CS_BOTH_SUSPENDED:
346 phone->event_handler (phone->event_handler_cls,
347 GNUNET_CONVERSATION_EC_PHONE_HUNG_UP,
348 caller,
349 &caller->caller_id);
350 break;
351 }
352 GNUNET_CONTAINER_DLL_remove (phone->caller_head,
353 phone->caller_tail,
354 caller);
355 GNUNET_free (caller);
356}
357
358
359/**
360 * We received a `struct ClientPhoneSuspendMessage`.
361 *
362 * @param cls the `struct GNUNET_CONVERSATION_Phone`
363 * @param suspend the message
364 */
365static void
366handle_phone_suspend (void *cls,
367 const struct ClientPhoneSuspendMessage *suspend)
368{
369 struct GNUNET_CONVERSATION_Phone *phone = cls;
370 struct GNUNET_CONVERSATION_Caller *caller;
371
372 caller = find_caller (phone,
373 suspend->cid);
374 if (NULL == caller)
375 return;
376 switch (caller->state)
377 {
378 case CS_RINGING:
379 GNUNET_break_op (0);
380 break;
381
382 case CS_ACTIVE:
383 caller->state = CS_CALLER_SUSPENDED;
384 caller->speaker->disable_speaker (caller->speaker->cls);
385 caller->mic->disable_microphone (caller->mic->cls);
386 caller->event_handler (caller->event_handler_cls,
387 GNUNET_CONVERSATION_EC_CALLER_SUSPEND);
388 break;
389
390 case CS_CALLEE_SUSPENDED:
391 caller->state = CS_BOTH_SUSPENDED;
392 caller->event_handler (caller->event_handler_cls,
393 GNUNET_CONVERSATION_EC_CALLER_SUSPEND);
394 break;
395
396 case CS_CALLER_SUSPENDED:
397 case CS_BOTH_SUSPENDED:
398 GNUNET_break_op (0);
399 break;
400 }
401}
402
403
404/**
405 * We received a `struct ClientPhoneResumeMessage`.
406 *
407 * @param cls the `struct GNUNET_CONVERSATION_Phone`
408 * @param resume the message
409 */
410static void
411handle_phone_resume (void *cls,
412 const struct ClientPhoneResumeMessage *resume)
413{
414 struct GNUNET_CONVERSATION_Phone *phone = cls;
415 struct GNUNET_CONVERSATION_Caller *caller;
416
417 caller = find_caller (phone,
418 resume->cid);
419 if (NULL == caller)
420 return;
421 switch (caller->state)
422 {
423 case CS_RINGING:
424 GNUNET_break_op (0);
425 break;
426
427 case CS_ACTIVE:
428 case CS_CALLEE_SUSPENDED:
429 GNUNET_break_op (0);
430 break;
431
432 case CS_CALLER_SUSPENDED:
433 caller->state = CS_ACTIVE;
434 caller->speaker->enable_speaker (caller->speaker->cls);
435 caller->mic->enable_microphone (caller->mic->cls,
436 &transmit_phone_audio,
437 caller);
438 caller->event_handler (caller->event_handler_cls,
439 GNUNET_CONVERSATION_EC_CALLER_RESUME);
440 break;
441
442 case CS_BOTH_SUSPENDED:
443 caller->state = CS_CALLEE_SUSPENDED;
444 caller->event_handler (caller->event_handler_cls,
445 GNUNET_CONVERSATION_EC_CALLER_RESUME);
446 break;
447 }
448}
449
450
451/**
452 * We received a `struct ClientAudioMessage`, check it is well-formed.
453 *
454 * @param cls the `struct GNUNET_CONVERSATION_Phone`
455 * @param am the message
456 * @return #GNUNET_OK if @a am is well-formed
457 */
458static int
459check_phone_audio (void *cls,
460 const struct ClientAudioMessage *am)
461{
462 (void) cls;
463 (void) am;
464
465 /* any variable-size payload is OK */
466 return GNUNET_OK;
467}
468
469
470/**
471 * We received a `struct ClientAudioMessage`
472 *
473 * @param cls the `struct GNUNET_CONVERSATION_Phone`
474 * @param am the message
475 */
476static void
477handle_phone_audio (void *cls,
478 const struct ClientAudioMessage *am)
479{
480 struct GNUNET_CONVERSATION_Phone *phone = cls;
481 struct GNUNET_CONVERSATION_Caller *caller;
482
483 caller = find_caller (phone,
484 am->cid);
485 if (NULL == caller)
486 return;
487 switch (caller->state)
488 {
489 case CS_RINGING:
490 GNUNET_break_op (0);
491 break;
492
493 case CS_ACTIVE:
494 caller->speaker->play (caller->speaker->cls,
495 ntohs (am->header.size) - sizeof(struct
496 ClientAudioMessage),
497 &am[1]);
498 break;
499
500 case CS_CALLEE_SUSPENDED:
501 case CS_CALLER_SUSPENDED:
502 case CS_BOTH_SUSPENDED:
503 break;
504 }
505}
506
507
508/**
509 * We encountered an error talking with the conversation service.
510 *
511 * @param cls the `struct GNUNET_CONVERSATION_Phone`
512 * @param error details about the error
513 */
514static void
515phone_error_handler (void *cls,
516 enum GNUNET_MQ_Error error)
517{
518 struct GNUNET_CONVERSATION_Phone *phone = cls;
519
520 (void) error;
521 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
522 _ (
523 "Connection to conversation service lost, trying to reconnect\n"));
524 reconnect_phone (phone);
525}
526
527
528/**
529 * Clean up all callers of the given phone.
530 *
531 * @param phone phone to clean up callers for
532 */
533static void
534clean_up_callers (struct GNUNET_CONVERSATION_Phone *phone)
535{
536 struct GNUNET_CONVERSATION_Caller *caller;
537
538 while (NULL != (caller = phone->caller_head))
539 {
540 /* make sure mic/speaker are disabled *before* callback */
541 if (CS_ACTIVE == caller->state)
542 {
543 caller->speaker->disable_speaker (caller->speaker->cls);
544 caller->mic->disable_microphone (caller->mic->cls);
545 caller->state = CS_CALLER_SUSPENDED;
546 }
547 phone->event_handler (phone->event_handler_cls,
548 GNUNET_CONVERSATION_EC_PHONE_HUNG_UP,
549 caller,
550 &caller->caller_id);
551 GNUNET_CONVERSATION_caller_hang_up (caller);
552 }
553}
554
555
556/**
557 * The phone got disconnected, reconnect to the service.
558 *
559 * @param phone phone to reconnect
560 */
561static void
562reconnect_phone (struct GNUNET_CONVERSATION_Phone *phone)
563{
564 struct GNUNET_MQ_MessageHandler handlers[] = {
565 GNUNET_MQ_hd_fixed_size (phone_ring,
566 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RING,
567 struct ClientPhoneRingMessage,
568 phone),
569 GNUNET_MQ_hd_fixed_size (phone_hangup,
570 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP,
571 struct ClientPhoneHangupMessage,
572 phone),
573 GNUNET_MQ_hd_fixed_size (phone_suspend,
574 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND,
575 struct ClientPhoneSuspendMessage,
576 phone),
577 GNUNET_MQ_hd_fixed_size (phone_resume,
578 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME,
579 struct ClientPhoneResumeMessage,
580 phone),
581 GNUNET_MQ_hd_var_size (phone_audio,
582 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO,
583 struct ClientAudioMessage,
584 phone),
585 GNUNET_MQ_handler_end ()
586 };
587 struct GNUNET_MQ_Envelope *e;
588 struct ClientPhoneRegisterMessage *reg;
589
590 clean_up_callers (phone);
591 if (NULL != phone->mq)
592 {
593 GNUNET_MQ_destroy (phone->mq);
594 phone->mq = NULL;
595 }
596 phone->state = PS_REGISTER;
597 phone->mq = GNUNET_CLIENT_connect (phone->cfg,
598 "conversation",
599 handlers,
600 &phone_error_handler,
601 phone);
602 if (NULL == phone->mq)
603 return;
604 e = GNUNET_MQ_msg (reg,
605 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_REGISTER);
606 reg->line_port = phone->my_record.line_port;
607 GNUNET_MQ_send (phone->mq,
608 e);
609 phone->state = PS_READY;
610}
611
612
613/**
614 * Create a new phone.
615 *
616 * @param cfg configuration for the phone; specifies the phone service and
617 * which line the phone is to be connected to
618 * @param ego ego to use for name resolution (when determining caller ID)
619 * @param event_handler how to notify the owner of the phone about events
620 * @param event_handler_cls closure for @a event_handler
621 * @return NULL on error (no valid line configured)
622 */
623struct GNUNET_CONVERSATION_Phone *
624GNUNET_CONVERSATION_phone_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
625 const struct GNUNET_IDENTITY_Ego *ego,
626 GNUNET_CONVERSATION_PhoneEventHandler
627 event_handler,
628 void *event_handler_cls)
629{
630 struct GNUNET_CONVERSATION_Phone *phone;
631 char *line;
632 struct GNUNET_HashCode line_port;
633
634 if (GNUNET_OK !=
635 GNUNET_CONFIGURATION_get_value_string (cfg,
636 "CONVERSATION",
637 "LINE",
638 &line))
639 {
640 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
641 "CONVERSATION",
642 "LINE");
643 return NULL;
644 }
645 GNUNET_CRYPTO_hash (line,
646 strlen (line),
647 &line_port);
648 GNUNET_free (line);
649 phone = GNUNET_new (struct GNUNET_CONVERSATION_Phone);
650 if (GNUNET_OK !=
651 GNUNET_CRYPTO_get_peer_identity (cfg,
652 &phone->my_record.peer))
653 {
654 GNUNET_break (0);
655 GNUNET_free (phone);
656 return NULL;
657 }
658 phone->cfg = cfg;
659 phone->my_zone = *GNUNET_IDENTITY_ego_get_private_key (ego);
660 phone->event_handler = event_handler;
661 phone->event_handler_cls = event_handler_cls;
662 phone->ns = GNUNET_NAMESTORE_connect (cfg);
663 phone->my_record.version = htonl (1);
664 phone->my_record.reserved = htonl (0);
665 phone->my_record.line_port = line_port;
666 reconnect_phone (phone);
667 if ((NULL == phone->mq) ||
668 (NULL == phone->ns))
669 {
670 GNUNET_break (0);
671 GNUNET_CONVERSATION_phone_destroy (phone);
672 return NULL;
673 }
674 return phone;
675}
676
677
678/**
679 * Fill in a namestore record with the contact information
680 * for this phone. Note that the filled in "data" value
681 * is only valid until the phone is destroyed.
682 *
683 * @param phone phone to create a record for
684 * @param rd namestore record to fill in
685 */
686void
687GNUNET_CONVERSATION_phone_get_record (struct GNUNET_CONVERSATION_Phone *phone,
688 struct GNUNET_GNSRECORD_Data *rd)
689{
690 rd->data = &phone->my_record;
691 rd->expiration_time = 0;
692 rd->data_size = sizeof(struct GNUNET_CONVERSATION_PhoneRecord);
693 rd->record_type = GNUNET_GNSRECORD_TYPE_PHONE;
694 rd->flags = GNUNET_GNSRECORD_RF_NONE;
695}
696
697
698/**
699 * Picks up a (ringing) phone. This will connect the speaker
700 * to the microphone of the other party, and vice versa.
701 *
702 * @param caller handle that identifies which caller should be answered
703 * @param event_handler how to notify about events by the caller
704 * @param event_handler_cls closure for @a event_handler
705 * @param speaker speaker to use
706 * @param mic microphone to use
707 */
708void
709GNUNET_CONVERSATION_caller_pick_up (struct GNUNET_CONVERSATION_Caller *caller,
710 GNUNET_CONVERSATION_CallerEventHandler
711 event_handler,
712 void *event_handler_cls,
713 struct GNUNET_SPEAKER_Handle *speaker,
714 struct GNUNET_MICROPHONE_Handle *mic)
715{
716 struct GNUNET_CONVERSATION_Phone *phone = caller->phone;
717 struct GNUNET_MQ_Envelope *e;
718 struct ClientPhonePickupMessage *pick;
719
720 GNUNET_assert (CS_RINGING == caller->state);
721 caller->speaker = speaker;
722 caller->mic = mic;
723 e = GNUNET_MQ_msg (pick,
724 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP);
725 pick->cid = caller->cid;
726 GNUNET_MQ_send (phone->mq,
727 e);
728 caller->state = CS_ACTIVE;
729 caller->event_handler = event_handler;
730 caller->event_handler_cls = event_handler_cls;
731 caller->speaker->enable_speaker (caller->speaker->cls);
732 caller->mic->enable_microphone (caller->mic->cls,
733 &transmit_phone_audio,
734 caller);
735}
736
737
738/**
739 * Hang up up a (possibly ringing) phone. This will notify the other
740 * party that we are no longer interested in talking with them.
741 *
742 * @param caller conversation to hang up on
743 */
744void
745GNUNET_CONVERSATION_caller_hang_up (struct GNUNET_CONVERSATION_Caller *caller)
746{
747 struct GNUNET_CONVERSATION_Phone *phone = caller->phone;
748 struct GNUNET_MQ_Envelope *e;
749 struct ClientPhoneHangupMessage *hang;
750
751 switch (caller->state)
752 {
753 case CS_ACTIVE:
754 caller->speaker->disable_speaker (caller->speaker->cls);
755 caller->mic->disable_microphone (caller->mic->cls);
756 break;
757
758 default:
759 break;
760 }
761 GNUNET_CONTAINER_DLL_remove (phone->caller_head,
762 phone->caller_tail,
763 caller);
764 e = GNUNET_MQ_msg (hang,
765 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP);
766 hang->cid = caller->cid;
767 GNUNET_MQ_send (phone->mq,
768 e);
769 GNUNET_free (caller);
770}
771
772
773/**
774 * Destroys a phone.
775 *
776 * @param phone phone to destroy
777 */
778void
779GNUNET_CONVERSATION_phone_destroy (struct GNUNET_CONVERSATION_Phone *phone)
780{
781 clean_up_callers (phone);
782 if (NULL != phone->ns)
783 {
784 GNUNET_NAMESTORE_disconnect (phone->ns);
785 phone->ns = NULL;
786 }
787 if (NULL != phone->mq)
788 {
789 GNUNET_MQ_destroy (phone->mq);
790 phone->mq = NULL;
791 }
792 GNUNET_free (phone);
793}
794
795
796/**
797 * Pause conversation of an active call. This will disconnect the speaker
798 * and the microphone. The call can later be resumed with
799 * #GNUNET_CONVERSATION_caller_resume.
800 *
801 * @param caller call to suspend
802 */
803void
804GNUNET_CONVERSATION_caller_suspend (struct GNUNET_CONVERSATION_Caller *caller)
805{
806 struct GNUNET_CONVERSATION_Phone *phone = caller->phone;
807 struct GNUNET_MQ_Envelope *e;
808 struct ClientPhoneSuspendMessage *suspend;
809
810 GNUNET_assert ((CS_ACTIVE == caller->state) ||
811 (CS_CALLER_SUSPENDED == caller->state));
812 if (CS_ACTIVE == caller->state)
813 {
814 caller->speaker->disable_speaker (caller->speaker->cls);
815 caller->mic->disable_microphone (caller->mic->cls);
816 }
817 caller->speaker = NULL;
818 caller->mic = NULL;
819 e = GNUNET_MQ_msg (suspend,
820 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND);
821 suspend->cid = caller->cid;
822 GNUNET_MQ_send (phone->mq,
823 e);
824 if (CS_ACTIVE == caller->state)
825 caller->state = CS_CALLEE_SUSPENDED;
826 else
827 caller->state = CS_BOTH_SUSPENDED;
828}
829
830
831/**
832 * Resume suspended conversation of a phone.
833 *
834 * @param caller call to resume
835 * @param speaker speaker to use
836 * @param mic microphone to use
837 */
838void
839GNUNET_CONVERSATION_caller_resume (struct GNUNET_CONVERSATION_Caller *caller,
840 struct GNUNET_SPEAKER_Handle *speaker,
841 struct GNUNET_MICROPHONE_Handle *mic)
842{
843 struct GNUNET_CONVERSATION_Phone *phone = caller->phone;
844 struct GNUNET_MQ_Envelope *e;
845 struct ClientPhoneResumeMessage *resume;
846
847 GNUNET_assert ((CS_CALLEE_SUSPENDED == caller->state) ||
848 (CS_BOTH_SUSPENDED == caller->state));
849 caller->speaker = speaker;
850 caller->mic = mic;
851 e = GNUNET_MQ_msg (resume,
852 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME);
853 resume->cid = caller->cid;
854 GNUNET_MQ_send (phone->mq,
855 e);
856 if (CS_CALLEE_SUSPENDED == caller->state)
857 {
858 caller->state = CS_ACTIVE;
859 caller->speaker->enable_speaker (caller->speaker->cls);
860 caller->mic->enable_microphone (caller->mic->cls,
861 &transmit_phone_audio,
862 caller);
863 }
864 else
865 {
866 caller->state = CS_CALLER_SUSPENDED;
867 }
868}
869
870
871/* end of conversation_api.c */