2 This file is part of GNUnet
3 (C) 2013 Christian Grothoff (and other contributing authors)
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.
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.
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.
22 * @file conversation/conversation_api2.c
23 * @brief API to the conversation service
24 * @author Simon Dieterle
25 * @author Andreas Fuchs
26 * @author Christian Grothoff
29 #include "gnunet_conversation_service.h"
30 #include "gnunet_gns_service.h"
31 #include "conversation.h"
35 * A phone record specifies which peer is hosting a given user and
36 * may also specify the phone line that is used (typically zero).
37 * The version is also right now always zero.
43 * Version of the phone record, for now always zero. We may
44 * use other versions for anonymously hosted phone lines in
47 uint32_t version GNUNET_PACKED;
50 * Phone line to use at the peer.
52 uint32_t line GNUNET_PACKED;
55 * Identity of the peer hosting the phone service.
57 struct GNUNET_PeerIdentity peer;
63 * Possible states of the phone.
68 * We still need to register the phone.
73 * We are waiting for a call.
78 * The phone is ringing.
83 * The phone is in an active conversation.
90 * A phone is a device that can ring to signal an incoming call and
91 * that you can pick up to answer the call and hang up to terminate
92 * the call. You can also hang up a ringing phone immediately
93 * (without picking it up) to stop it from ringing. Phones have
94 * caller ID. You can ask the phone for its record and make that
95 * record available (via GNS) to enable others to call you.
96 * Multiple phones maybe connected to the same line (the line is
97 * something rather internal to a phone and not obvious from it).
98 * You can only have one conversation per phone at any time.
100 struct GNUNET_CONVERSATION_Phone
105 const struct GNUNET_CONFIGURATION_Handle *cfg;
108 * Handle to talk with CONVERSATION service.
110 struct GNUNET_CLIENT_Connection *client;
113 * Function to call for phone events.
115 GNUNET_CONVERSATION_EventHandler event_handler;
118 * Closure for @e event_handler
120 void *event_handler_cls;
123 * Speaker, or NULL if none is attached.
125 struct GNUNET_SPEAKER_Handle *speaker;
128 * Microphone, or NULL if none is attached.
130 struct GNUNET_MICROPHONE_Handle *mic;
133 * Connection to NAMESTORE (for reverse lookup).
135 struct GNUNET_NAMESTORE_Handle *ns;
138 * Active NAMESTORE lookup (or NULL).
140 struct GNUNET_NAMESTORE_QueueEntry *qe;
143 * Handle for transmitting to the CONVERSATION service.
145 struct GNUNET_MQ_Handle *mq;
148 * This phone's record.
150 struct PhoneRecord my_record;
155 struct GNUNET_CRYPTO_EccPrivateKey my_zone;
158 * Identity of the person calling us (valid while in state #PS_RINGING).
160 struct GNUNET_CRYPTO_EccPublicSignKey caller_id;
163 * State machine for the phone.
165 enum PhoneState state;
171 * The phone got disconnected, reconnect to the service.
173 * @param phone phone to reconnect
176 reconnect_phone (struct GNUNET_CONVERSATION_Phone *phone);
180 * We have resolved the caller ID using our name service.
182 * @param cls the `struct GNUNET_CONVERSATION_Phone`
183 * @param zone our zone used for resolution
184 * @param label name of the caller
185 * @param rd_count number of records we have in @a rd
186 * @param rd records we have for the caller's label
189 handle_caller_name (void *cls,
190 const struct GNUNET_CRYPTO_EccPrivateKey *zone,
192 unsigned int rd_count,
193 const struct GNUNET_NAMESTORE_RecordData *rd)
195 struct GNUNET_CONVERSATION_Phone *phone = cls;
200 name = GNUNET_strdup (GNUNET_NAMESTORE_pkey_to_zkey (&phone->caller_id));
202 GNUNET_asprintf (&name, "%.gnu", label);
203 phone->event_handler (phone->event_handler_cls,
204 GNUNET_CONVERSATION_EC_RING,
211 * We received a `struct ClientPhoneRingMessage`
213 * @param cls the `struct GNUNET_CONVERSATION_Phone`
214 * @param msg the message
217 handle_phone_ring (void *cls,
218 const struct GNUNET_MessageHeader *msg)
220 struct GNUNET_CONVERSATION_Phone *phone = cls;
221 const struct ClientPhoneRingMessage *ring;
223 ring = (const struct ClientPhoneRingMessage *) msg;
224 switch (phone->state)
230 phone->state = PS_RINGING;
231 phone->caller_id = ring->caller_id;
232 phone->qe = GNUNET_NAMESTORE_zone_to_name (phone->ns,
240 reconnect_phone (phone);
244 reconnect_phone (phone);
251 * We received a `struct ClientPhoneHangupMessage`.
253 * @param cls the `struct GNUNET_CONVERSATION_Phone`
254 * @param msg the message
257 handle_phone_hangup (void *cls,
258 const struct GNUNET_MessageHeader *msg)
260 struct GNUNET_CONVERSATION_Phone *phone = cls;
261 const struct ClientPhoneHangupMessage *hang;
265 hang = (const struct ClientPhoneHangupMessage *) msg;
266 reason = (const char *) &hang[1];
267 len = htons (hang->header.size) - sizeof (struct ClientPhoneHangupMessage);
269 ('\0' != reason[len-1]) )
272 reconnect_phone (phone);
275 switch (phone->state)
282 reconnect_phone (phone);
285 if (NULL != phone->qe)
287 GNUNET_NAMESTORE_cancel (phone->qe);
289 phone->state = PS_WAITING;
292 phone->state = PS_WAITING;
293 phone->event_handler (phone->event_handler_cls,
294 GNUNET_CONVERSATION_EC_TERMINATED,
298 GNUNET_break (NULL == phone->qe);
299 phone->state = PS_WAITING;
300 phone->event_handler (phone->event_handler_cls,
301 GNUNET_CONVERSATION_EC_TERMINATED,
309 * We received a `struct ClientAudioMessage`
311 * @param cls the `struct GNUNET_CONVERSATION_Phone`
312 * @param msg the message
315 handle_phone_audio_message (void *cls,
316 const struct GNUNET_MessageHeader *msg)
318 struct GNUNET_CONVERSATION_Phone *phone = cls;
319 const struct ClientAudioMessage *am;
321 am = (const struct ClientAudioMessage *) msg;
322 switch (phone->state)
329 reconnect_phone (phone);
333 reconnect_phone (phone);
336 phone->speaker->play (phone->speaker->cls,
337 ntohs (msg->size) - sizeof (struct ClientAudioMessage),
345 * We encountered an error talking with the conversation service.
347 * @param cls the `struct GNUNET_CONVERSATION_Phone`
348 * @param error details about the error
351 phone_error_handler (void *cls,
352 enum GNUNET_MQ_Error error)
354 struct GNUNET_CONVERSATION_Phone *phone = cls;
357 reconnect_phone (phone);
362 * The phone got disconnected, reconnect to the service.
364 * @param phone phone to reconnect
367 reconnect_phone (struct GNUNET_CONVERSATION_Phone *phone)
369 static struct GNUNET_MQ_MessageHandler handlers[] =
371 { &handle_phone_ring,
372 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RING,
373 sizeof (struct ClientPhoneRingMessage) },
374 { &handle_phone_hangup,
375 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP,
377 { &handle_phone_audio_message,
378 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO,
382 struct GNUNET_MQ_Envelope *e;
383 struct ClientPhoneRegisterMessage *reg;
385 if (NULL != phone->mq)
387 GNUNET_MQ_destroy (phone->mq);
390 if (NULL != phone->client)
392 GNUNET_CLIENT_disconnect (phone->client);
393 phone->client = NULL;
395 phone->state = PS_REGISTER;
396 phone->client = GNUNET_CLIENT_connect ("conversation", phone->cfg);
397 if (NULL == phone->client)
399 phone->mq = GNUNET_MQ_queue_for_connection_client (phone->client,
401 &phone_error_handler,
403 e = GNUNET_MQ_msg (reg, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_REGISTER);
404 reg->line = phone->my_record.line;
405 GNUNET_MQ_send (phone->mq, e);
406 phone->state = PS_WAITING;
411 * Create a new phone.
413 * @param cfg configuration for the phone; specifies the phone service and
414 * which line the phone is to be connected to
415 * @param ego ego to use for name resolution (when determining caller ID)
416 * @param event_handler how to notify the owner of the phone about events
417 * @param event_handler_cls closure for @a event_handler
419 struct GNUNET_CONVERSATION_Phone *
420 GNUNET_CONVERSATION_phone_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
421 const struct GNUNET_IDENTITY_Ego *ego,
422 GNUNET_CONVERSATION_EventHandler event_handler,
423 void *event_handler_cls)
425 struct GNUNET_CONVERSATION_Phone *phone;
426 unsigned long long line;
429 GNUNET_CONFIGURATION_get_value_number (cfg,
434 phone = GNUNET_new (struct GNUNET_CONVERSATION_Phone);
436 GNUNET_CRYPTO_get_host_identity (cfg,
437 &phone->my_record.peer))
444 phone->my_zone = *GNUNET_IDENTITY_ego_get_private_key (ego);
445 phone->event_handler = event_handler;
446 phone->event_handler_cls = event_handler_cls;
447 phone->ns = GNUNET_NAMESTORE_connect (cfg);
448 phone->my_record.line = htonl ((uint32_t) line);
449 phone->my_record.version = htonl (0);
450 reconnect_phone (phone);
451 if ( (NULL == phone->client) ||
452 (NULL == phone->ns) )
455 GNUNET_CONVERSATION_phone_destroy (phone);
463 * Fill in a namestore record with the contact information
464 * for this phone. Note that the filled in "data" value
465 * is only valid until the phone is destroyed.
467 * @param phone phone to create a record for
468 * @param rd namestore record to fill in
471 GNUNET_CONVERSATION_phone_get_record (struct GNUNET_CONVERSATION_Phone *phone,
472 struct GNUNET_NAMESTORE_RecordData *rd)
474 rd->data = &phone->my_record;
475 rd->expiration_time = 0;
476 rd->data_size = sizeof (struct PhoneRecord);
477 rd->record_type = GNUNET_NAMESTORE_TYPE_PHONE;
478 rd->flags = GNUNET_NAMESTORE_RF_NONE;
483 * Process recorded audio data.
485 * @param cls closure with the `struct GNUNET_CONVERSATION_Phone`
486 * @param data_size number of bytes in @a data
487 * @param data audio data to play
490 transmit_phone_audio (void *cls,
494 struct GNUNET_CONVERSATION_Phone *phone = cls;
495 struct GNUNET_MQ_Envelope *e;
496 struct ClientAudioMessage *am;
498 GNUNET_assert (PS_ACTIVE == phone->state);
499 e = GNUNET_MQ_msg_extra (am,
501 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO);
502 memcpy (&am[1], data, data_size);
503 GNUNET_MQ_send (phone->mq, e);
508 * Picks up a (ringing) phone. This will connect the speaker
509 * to the microphone of the other party, and vice versa.
511 * @param phone phone to pick up
512 * @param metadata meta data to give to the other user about the pick up event
513 * @param speaker speaker to use
514 * @param mic microphone to use
517 GNUNET_CONVERSATION_phone_pick_up (struct GNUNET_CONVERSATION_Phone *phone,
518 const char *metadata,
519 struct GNUNET_SPEAKER_Handle *speaker,
520 struct GNUNET_MICROPHONE_Handle *mic)
522 struct GNUNET_MQ_Envelope *e;
523 struct ClientPhonePickupMessage *pick;
526 GNUNET_assert (PS_RINGING == phone->state);
527 phone->speaker = speaker;
529 slen = strlen (metadata) + 1;
530 e = GNUNET_MQ_msg_extra (pick, slen, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP);
531 memcpy (&pick[1], metadata, slen);
532 GNUNET_MQ_send (phone->mq, e);
533 phone->state = PS_ACTIVE;
534 phone->speaker->enable_speaker (phone->speaker->cls);
535 phone->mic->enable_microphone (phone->mic->cls,
536 &transmit_phone_audio,
542 * Hang up up a (possibly ringing) phone. This will notify the other
543 * party that we are no longer interested in talking with them.
545 * @param phone phone to pick up
546 * @param reason text we give to the other party about why we terminated the conversation
549 GNUNET_CONVERSATION_phone_hang_up (struct GNUNET_CONVERSATION_Phone *phone,
552 struct GNUNET_MQ_Envelope *e;
553 struct ClientPhoneHangupMessage *hang;
556 GNUNET_assert ( (PS_RINGING == phone->state) ||
557 (PS_ACTIVE == phone->state) );
558 phone->speaker->disable_speaker (phone->speaker->cls);
559 phone->mic->disable_microphone (phone->mic->cls);
560 phone->speaker = NULL;
562 slen = strlen (reason) + 1;
563 e = GNUNET_MQ_msg_extra (hang, slen, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP);
564 memcpy (&hang[1], reason, slen);
565 GNUNET_MQ_send (phone->mq, e);
566 phone->state = PS_WAITING;
573 * @param phone phone to destroy
576 GNUNET_CONVERSATION_phone_destroy (struct GNUNET_CONVERSATION_Phone *phone)
578 if (NULL != phone->speaker)
580 phone->speaker->disable_speaker (phone->speaker->cls);
581 phone->speaker = NULL;
583 if (NULL != phone->mic)
585 phone->mic->disable_microphone (phone->mic->cls);
588 if (NULL != phone->qe)
590 GNUNET_NAMESTORE_cancel (phone->qe);
593 if (NULL != phone->ns)
595 GNUNET_NAMESTORE_disconnect (phone->ns);
598 if (NULL != phone->mq)
600 GNUNET_MQ_destroy (phone->mq);
603 if (NULL != phone->client)
605 GNUNET_CLIENT_disconnect (phone->client);
606 phone->client = NULL;
612 /* ******************************* Call API *************************** */
615 * Possible states of the phone.
620 * We still need to lookup the callee.
625 * The call is ringing.
630 * The call is in an active conversation.
635 * The call is in termination.
642 * Handle for an outgoing call.
644 struct GNUNET_CONVERSATION_Call
650 const struct GNUNET_CONFIGURATION_Handle *cfg;
653 * Handle to talk with CONVERSATION service.
655 struct GNUNET_CLIENT_Connection *client;
658 * Our caller identity.
660 struct GNUNET_IDENTITY_Ego *caller_id;
663 * Target callee as a GNS address/name.
670 struct GNUNET_SPEAKER_Handle *speaker;
675 struct GNUNET_MICROPHONE_Handle *mic;
678 * Function to call with events.
680 GNUNET_CONVERSATION_EventHandler event_handler;
683 * Closure for @e event_handler
685 void *event_handler_cls;
688 * Handle for transmitting to the CONVERSATION service.
690 struct GNUNET_MQ_Handle *mq;
693 * Connection to GNS (can be NULL).
695 struct GNUNET_GNS_Handle *gns;
698 * Active GNS lookup (or NULL).
700 struct GNUNET_GNS_LookupRequest *gns_lookup;
703 * Target phone record, only valid after the lookup is done.
705 struct PhoneRecord phone_record;
708 * State machine for the call.
710 enum CallState state;
716 * The call got disconnected, reconnect to the service.
718 * @param call call to reconnect
721 reconnect_call (struct GNUNET_CONVERSATION_Call *call);
725 * We received a `struct ClientPhoneBusyMessage`
727 * @param cls the `struct GNUNET_CONVERSATION_Call`
728 * @param msg the message
731 handle_call_busy (void *cls,
732 const struct GNUNET_MessageHeader *msg)
734 struct GNUNET_CONVERSATION_Call *call = cls;
740 reconnect_call (call);
743 call->event_handler (call->event_handler_cls,
744 GNUNET_CONVERSATION_EC_BUSY);
745 GNUNET_CONVERSATION_call_stop (call, NULL);
749 reconnect_call (call);
752 GNUNET_CONVERSATION_call_stop (call, NULL);
759 * Process recorded audio data.
761 * @param cls closure with the `struct GNUNET_CONVERSATION_Call`
762 * @param data_size number of bytes in @a data
763 * @param data audio data to play
766 transmit_call_audio (void *cls,
770 struct GNUNET_CONVERSATION_Call *call = cls;
771 struct GNUNET_MQ_Envelope *e;
772 struct ClientAudioMessage *am;
774 GNUNET_assert (CS_ACTIVE == call->state);
775 e = GNUNET_MQ_msg_extra (am,
777 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO);
778 memcpy (&am[1], data, data_size);
779 GNUNET_MQ_send (call->mq, e);
784 * We received a `struct ClientPhonePickedupMessage`
786 * @param cls the `struct GNUNET_CONVERSATION_Call`
787 * @param msg the message
790 handle_call_picked_up (void *cls,
791 const struct GNUNET_MessageHeader *msg)
793 struct GNUNET_CONVERSATION_Call *call = cls;
794 const struct ClientPhonePickedupMessage *am;
795 const char *metadata;
798 am = (const struct ClientPhonePickedupMessage *) msg;
799 size = ntohs (am->header.size) - sizeof (struct ClientPhonePickedupMessage);
800 metadata = (const char *) &am[1];
802 ('\0' != metadata[size - 1]) )
808 reconnect_call (call);
811 call->state = CS_ACTIVE;
812 call->event_handler (call->event_handler_cls,
813 GNUNET_CONVERSATION_EC_READY,
815 call->speaker->enable_speaker (call->speaker->cls);
816 call->mic->enable_microphone (call->mic->cls,
817 &transmit_call_audio,
822 reconnect_call (call);
825 GNUNET_CONVERSATION_call_stop (call, NULL);
832 * We received a `struct ClientPhoneHangupMessage`
834 * @param cls the `struct GNUNET_CONVERSATION_Call`
835 * @param msg the message
838 handle_call_hangup (void *cls,
839 const struct GNUNET_MessageHeader *msg)
841 struct GNUNET_CONVERSATION_Call *call = cls;
842 const struct ClientPhoneHangupMessage *am;
846 am = (const struct ClientPhoneHangupMessage *) msg;
847 size = ntohs (am->header.size) - sizeof (struct ClientPhoneHangupMessage);
848 reason = (const char *) &am[1];
850 ('\0' != reason[size - 1]) )
856 reconnect_call (call);
859 call->event_handler (call->event_handler_cls,
860 GNUNET_CONVERSATION_EC_TERMINATED,
862 GNUNET_CONVERSATION_call_stop (call, NULL);
865 call->event_handler (call->event_handler_cls,
866 GNUNET_CONVERSATION_EC_TERMINATED,
868 GNUNET_CONVERSATION_call_stop (call, NULL);
871 GNUNET_CONVERSATION_call_stop (call, NULL);
878 * We received a `struct ClientAudioMessage`
880 * @param cls the `struct GNUNET_CONVERSATION_Call`
881 * @param msg the message
884 handle_call_audio_message (void *cls,
885 const struct GNUNET_MessageHeader *msg)
887 struct GNUNET_CONVERSATION_Call *call = cls;
888 const struct ClientAudioMessage *am;
890 am = (const struct ClientAudioMessage *) msg;
895 reconnect_call (call);
899 reconnect_call (call);
902 call->speaker->play (call->speaker->cls,
903 ntohs (msg->size) - sizeof (struct ClientAudioMessage),
907 GNUNET_CONVERSATION_call_stop (call, NULL);
915 * Iterator called on obtained result for a GNS lookup.
917 * @param cls closure with the `struct GNUNET_CONVERSATION_Call`
918 * @param rd_count number of records in @a rd
919 * @param rd the records in reply
922 handle_gns_response (void *cls,
924 const struct GNUNET_NAMESTORE_RecordData *rd)
926 struct GNUNET_CONVERSATION_Call *call = cls;
928 struct GNUNET_MQ_Envelope *e;
929 struct ClientCallMessage *ccm;
931 for (i=0;i<rd_count;i++)
933 if (GNUNET_NAMESTORE_TYPE_PHONE == rd[i].record_type)
935 if (rd[i].data_size != sizeof (struct PhoneRecord))
940 memcpy (&call->phone_record,
943 e = GNUNET_MQ_msg (ccm, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL);
944 ccm->line = call->phone_record.line;
945 ccm->target = call->phone_record.peer;
946 ccm->caller_id = *GNUNET_IDENTITY_ego_get_private_key (call->caller_id);
947 GNUNET_MQ_send (call->mq, e);
948 call->state = CS_RINGING;
949 call->event_handler (call->event_handler_cls,
950 GNUNET_CONVERSATION_EC_RINGING);
955 call->event_handler (call->event_handler_cls,
956 GNUNET_CONVERSATION_EC_GNS_FAIL);
957 GNUNET_CONVERSATION_call_stop (call, NULL);
962 * We encountered an error talking with the conversation service.
964 * @param cls the `struct GNUNET_CONVERSATION_Call`
965 * @param error details about the error
968 call_error_handler (void *cls,
969 enum GNUNET_MQ_Error error)
971 struct GNUNET_CONVERSATION_Call *call = cls;
974 reconnect_call (call);
979 * The call got disconnected, reconnect to the service.
981 * @param call call to reconnect
984 reconnect_call (struct GNUNET_CONVERSATION_Call *call)
986 static struct GNUNET_MQ_MessageHandler handlers[] =
989 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_BUSY,
990 sizeof (struct ClientPhoneBusyMessage) },
991 { &handle_call_picked_up,
992 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICKED_UP,
994 { &handle_call_hangup,
995 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP,
997 { &handle_call_audio_message,
998 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO,
1002 if (NULL != call->mq)
1004 GNUNET_MQ_destroy (call->mq);
1007 if (NULL != call->client)
1009 GNUNET_CLIENT_disconnect (call->client);
1010 call->client = NULL;
1012 call->client = GNUNET_CLIENT_connect ("conversation", call->cfg);
1013 if (NULL == call->client)
1015 call->mq = GNUNET_MQ_queue_for_connection_client (call->client,
1017 &call_error_handler,
1023 * Call the phone of another user.
1025 * @param cfg configuration to use, specifies our phone service
1026 * @param caller_id identity of the caller
1027 * @param callee GNS name of the callee (used to locate the callee's record)
1028 * @param speaker speaker to use (will be used automatically immediately once the
1029 * #GNUNET_CONVERSATION_EC_READY event is generated); we will NOT generate
1030 * a ring tone on the speaker
1031 * @param mic microphone to use (will be used automatically immediately once the
1032 * #GNUNET_CONVERSATION_EC_READY event is generated)
1033 * @param event_handler how to notify the owner of the phone about events
1034 * @param event_handler_cls closure for @a event_handler
1036 struct GNUNET_CONVERSATION_Call *
1037 GNUNET_CONVERSATION_call_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
1038 struct GNUNET_IDENTITY_Ego *caller_id,
1040 struct GNUNET_SPEAKER_Handle *speaker,
1041 struct GNUNET_MICROPHONE_Handle *mic,
1042 GNUNET_CONVERSATION_EventHandler event_handler,
1043 void *event_handler_cls)
1045 struct GNUNET_CONVERSATION_Call *call;
1046 struct GNUNET_CRYPTO_EccPublicSignKey my_zone;
1048 GNUNET_IDENTITY_ego_get_public_key (caller_id,
1050 call = GNUNET_new (struct GNUNET_CONVERSATION_Call);
1052 call->caller_id = caller_id;
1053 call->callee = GNUNET_strdup (callee);
1054 call->speaker = speaker;
1056 call->event_handler = event_handler;
1057 call->event_handler_cls = event_handler_cls;
1058 call->gns = GNUNET_GNS_connect (cfg);
1059 reconnect_call (call);
1061 if ( (NULL == call->client) ||
1062 (NULL == call->gns) )
1064 GNUNET_CONVERSATION_call_stop (call, NULL);
1067 call->gns_lookup = GNUNET_GNS_lookup (call->gns, callee,
1069 GNUNET_NAMESTORE_TYPE_PHONE,
1071 NULL /* FIXME: add shortening support */,
1072 &handle_gns_response, call);
1073 GNUNET_assert (NULL != call->gns_lookup);
1079 * Terminate a call. The call may be ringing or ready at this time.
1081 * @param call call to terminate
1082 * @param reason if the call was active (ringing or ready) this will be the
1083 * reason given to the other user for why we hung up
1086 GNUNET_CONVERSATION_call_stop (struct GNUNET_CONVERSATION_Call *call,
1091 // FIXME: transmit reason to service... (not implemented!)
1095 if (NULL != call->speaker)
1097 if (CS_ACTIVE == call->state)
1098 call->speaker->disable_speaker (call->speaker->cls);
1099 call->speaker = NULL;
1101 if (NULL != call->mic)
1103 if (CS_ACTIVE == call->state)
1104 call->mic->disable_microphone (call->mic->cls);
1107 if (NULL != call->mq)
1109 GNUNET_MQ_destroy (call->mq);
1112 if (NULL != call->client)
1114 GNUNET_CLIENT_disconnect (call->client);
1115 call->client = NULL;
1117 if (NULL != call->gns_lookup)
1119 GNUNET_GNS_lookup_cancel (call->gns_lookup);
1120 call->gns_lookup = NULL;
1122 if (NULL != call->gns)
1124 GNUNET_GNS_disconnect (call->gns);
1132 /* end of conversation_api.c */