GNUnet 0.21.1
conversation_api_call.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013, 2016 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
28#include "platform.h"
31#include "gnunet_gns_service.h"
32#include "conversation.h"
33
34
39{
44
49
54
59
64
69
74};
75
76
81{
86
91
95 char *callee;
96
101
106
111
116
121
126
131
136
141};
142
143
149static void
151
152
160static void
162 size_t data_size,
163 const void *data)
164{
165 struct GNUNET_CONVERSATION_Call *call = cls;
166 struct GNUNET_MQ_Envelope *e;
167 struct ClientAudioMessage *am;
168
170 e = GNUNET_MQ_msg_extra (am,
171 data_size,
173 GNUNET_memcpy (&am[1],
174 data,
175 data_size);
177 e);
178}
179
180
187static void
189 const struct ClientPhoneSuspendMessage *msg)
190{
191 struct GNUNET_CONVERSATION_Call *call = cls;
192
193 (void) msg;
194 switch (call->state)
195 {
196 case CS_LOOKUP:
197 GNUNET_break (0);
198 fail_call (call);
199 break;
200
201 case CS_RINGING:
202 GNUNET_break_op (0);
203 fail_call (call);
204 break;
205
210 break;
211
214 GNUNET_break_op (0);
215 break;
216
217 case CS_ACTIVE:
223 break;
224
225 case CS_SHUTDOWN:
227 break;
228 }
229}
230
231
238static void
240 const struct ClientPhoneResumeMessage *msg)
241{
242 struct GNUNET_CONVERSATION_Call *call = cls;
243
244 (void) msg;
245 switch (call->state)
246 {
247 case CS_LOOKUP:
248 GNUNET_break (0);
249 fail_call (call);
250 break;
251
252 case CS_RINGING:
253 GNUNET_break_op (0);
254 fail_call (call);
255 break;
256
258 GNUNET_break_op (0);
259 break;
260
266 call);
269 break;
270
275 break;
276
277 case CS_ACTIVE:
278 GNUNET_break_op (0);
279 break;
280
281 case CS_SHUTDOWN:
283 break;
284 }
285}
286
287
294static void
296 const struct ClientPhonePickedupMessage *msg)
297{
298 struct GNUNET_CONVERSATION_Call *call = cls;
299
300 (void) msg;
301 switch (call->state)
302 {
303 case CS_LOOKUP:
304 GNUNET_break (0);
305 fail_call (call);
306 break;
307
308 case CS_RINGING:
313 call);
316 break;
317
321 case CS_ACTIVE:
322 GNUNET_break (0);
323 fail_call (call);
324 break;
325
326 case CS_SHUTDOWN:
328 break;
329 }
330}
331
332
339static void
341 const struct ClientPhoneHangupMessage *msg)
342{
343 struct GNUNET_CONVERSATION_Call *call = cls;
345 void *eh_cls;
346
347 (void) msg;
348 switch (call->state)
349 {
350 case CS_LOOKUP:
351 GNUNET_break (0);
352 fail_call (call);
353 break;
354
355 case CS_RINGING:
359 case CS_ACTIVE:
360 eh = call->event_handler;
361 eh_cls = call->event_handler_cls;
363 eh (eh_cls,
365 return;
366
367 case CS_SHUTDOWN:
369 break;
370 }
371}
372
373
381static int
383 const struct ClientAudioMessage *am)
384{
385 (void) cls;
386 (void) am;
387 /* any payload is OK */
388 return GNUNET_OK;
389}
390
391
398static void
400 const struct ClientAudioMessage *am)
401{
402 struct GNUNET_CONVERSATION_Call *call = cls;
403
404 switch (call->state)
405 {
406 case CS_LOOKUP:
407 GNUNET_break (0);
408 fail_call (call);
409 break;
410
411 case CS_RINGING:
412 GNUNET_break (0);
413 fail_call (call);
414 break;
415
417 /* can happen: we suspended, other peer did not yet
418 learn about this. */
419 break;
420
423 /* can (rarely) also happen: other peer suspended, but cadet might
424 have had delayed data on the unreliable channel */
425 break;
426
427 case CS_ACTIVE:
429 ntohs (am->header.size) - sizeof(struct
431 &am[1]);
432 break;
433
434 case CS_SHUTDOWN:
436 break;
437 }
438}
439
440
449static void
451 int was_gns,
452 uint32_t rd_count,
453 const struct GNUNET_GNSRECORD_Data *rd)
454{
455 struct GNUNET_CONVERSATION_Call *call = cls;
456 struct GNUNET_MQ_Envelope *e;
457 struct ClientCallMessage *ccm;
458 const struct GNUNET_CRYPTO_PrivateKey *caller_id;
459 size_t key_len;
460
461 (void) was_gns;
462 GNUNET_break (NULL != call->gns_lookup);
464 call->gns_lookup = NULL;
465 for (uint32_t i = 0; i < rd_count; i++)
466 {
467 if (GNUNET_GNSRECORD_TYPE_PHONE == rd[i].record_type)
468 {
469 if (rd[i].data_size != sizeof(struct GNUNET_CONVERSATION_PhoneRecord))
470 {
471 GNUNET_break_op (0);
472 continue;
473 }
475 rd[i].data,
476 rd[i].data_size);
478 key_len = GNUNET_CRYPTO_private_key_get_length (caller_id);
479 e = GNUNET_MQ_msg_extra (ccm, key_len,
484 &ccm[1], key_len);
485 ccm->key_len = htonl (key_len);
487 e);
491 return;
492 }
493 }
494 /* not found */
498}
499
500
507static void
509 enum GNUNET_MQ_Error error)
510{
511 struct GNUNET_CONVERSATION_Call *call = cls;
512
513 (void) error;
514 if (CS_SHUTDOWN == call->state)
515 {
517 return;
518 }
520 _ (
521 "Connection to conversation service lost, trying to reconnect\n"));
522 fail_call (call);
523}
524
525
531static void
533{
534 if (CS_ACTIVE == call->state)
535 {
538 }
539 if (NULL != call->mq)
540 {
542 call->mq = NULL;
543 }
548}
549
550
569 const char *callee,
574 void *event_handler_cls)
575{
579 GNUNET_MQ_hd_fixed_size (call_suspend,
582 call),
583 GNUNET_MQ_hd_fixed_size (call_resume,
586 call),
587 GNUNET_MQ_hd_fixed_size (call_picked_up,
590 call),
591 GNUNET_MQ_hd_fixed_size (call_hangup,
594 call),
595 GNUNET_MQ_hd_var_size (call_audio,
597 struct ClientAudioMessage,
598 call),
600 };
601
603 "conversation",
604 handlers,
606 call);
607 if (NULL == call->mq)
608 {
609 GNUNET_break (0);
611 return NULL;
612 }
613 call->cfg = cfg;
614 call->caller_id = caller_id;
615 call->callee = GNUNET_strdup (callee);
617 call->mic = mic;
618 call->event_handler = event_handler;
619 call->event_handler_cls = event_handler_cls;
621 if (NULL == call->gns)
622 {
624 return NULL;
625 }
628 call->callee,
632 call);
633 if (NULL == call->gns_lookup)
634 {
636 return NULL;
637 }
638 return call;
639}
640
641
647void
649{
650 if ((NULL != call->speaker) &&
651 (CS_ACTIVE == call->state))
653 if ((NULL != call->mic) &&
654 (CS_ACTIVE == call->state))
656 if (CS_SHUTDOWN != call->state)
657 {
659 }
660 if (NULL != call->mq)
661 {
663 call->mq = NULL;
664 }
665 if (NULL != call->gns_lookup)
666 {
668 call->gns_lookup = NULL;
669 }
670 if (NULL != call->gns)
671 {
673 call->gns = NULL;
674 }
677}
678
679
686void
688{
689 struct GNUNET_MQ_Envelope *e;
690 struct ClientPhoneSuspendMessage *suspend;
691
693 (CS_ACTIVE == call->state));
694 if (CS_ACTIVE == call->state)
695 {
698 }
699 call->speaker = NULL;
700 call->mic = NULL;
701 e = GNUNET_MQ_msg (suspend,
704 e);
707 else
709}
710
711
720void
724{
725 struct GNUNET_MQ_Envelope *e;
726 struct ClientPhoneResumeMessage *resume;
727
731 GNUNET_MQ_send (call->mq, e);
733 call->mic = mic;
735 {
740 call);
741 }
742 else
743 {
745 }
746}
747
748
749/* end of conversation_api_call.c */
struct GNUNET_MQ_MessageHandlers handlers[]
Definition: 003.c:1
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
constants for network protocols
static void fail_call(struct GNUNET_CONVERSATION_Call *call)
The call got disconnected, reconnect to the service.
static void handle_call_audio(void *cls, const struct ClientAudioMessage *am)
We received a struct ClientAudioMessage
static int check_call_audio(void *cls, const struct ClientAudioMessage *am)
We received a struct ClientAudioMessage, check it is well-formed.
static void handle_call_picked_up(void *cls, const struct ClientPhonePickedupMessage *msg)
We received a GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICKED_UP.
static void handle_call_hangup(void *cls, const struct ClientPhoneHangupMessage *msg)
We received a #GNUNET_MESSAGE_TYPE_CONVERSATION_CS_HANG_UP.
static void handle_gns_response(void *cls, int was_gns, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Iterator called on obtained result for a GNS lookup.
static void transmit_call_audio(void *cls, size_t data_size, const void *data)
Process recorded audio data.
CallState
Possible states of the phone.
@ CS_LOOKUP
We still need to lookup the callee.
@ CS_SUSPENDED_CALLEE
The call was suspended by the callee.
@ CS_SHUTDOWN
The call is in termination.
@ CS_SUSPENDED_CALLER
The call was suspended by the caller.
@ CS_SUSPENDED_BOTH
The call was suspended by both caller and callee.
@ CS_ACTIVE
The call is in an active conversation.
@ CS_RINGING
The call is ringing.
static void handle_call_resume(void *cls, const struct ClientPhoneResumeMessage *msg)
We received a GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME.
static void handle_call_suspend(void *cls, const struct ClientPhoneSuspendMessage *msg)
We received a GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND.
static void call_error_handler(void *cls, enum GNUNET_MQ_Error error)
We encountered an error talking with the conversation service.
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:109
static struct GNUNET_SPEAKER_Handle * speaker
Handle to the speaker.
static struct GNUNET_CONVERSATION_Call * call
Call handle (for active outgoing call).
static struct GNUNET_MICROPHONE_Handle * mic
Our microphone.
static char * data
The data to insert into the dht.
static unsigned int rd_count
Number of records for currently parsed set.
static struct GNUNET_GNSRECORD_Data rd[50]
The record data under a single label.
static size_t data_size
Number of bytes in data.
API to the conversation service.
API to the GNS service.
API that can be used to manipulate GNS record data.
struct GNUNET_MQ_Handle * GNUNET_CLIENT_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *service_name, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *error_handler_cls)
Create a message queue to connect to a GNUnet service.
Definition: client.c:1057
void GNUNET_CONVERSATION_call_suspend(struct GNUNET_CONVERSATION_Call *call)
Pause a call.
void GNUNET_CONVERSATION_call_resume(struct GNUNET_CONVERSATION_Call *call, struct GNUNET_SPEAKER_Handle *speaker, struct GNUNET_MICROPHONE_Handle *mic)
Resumes a call after GNUNET_CONVERSATION_call_suspend.
struct GNUNET_CONVERSATION_Call * GNUNET_CONVERSATION_call_start(const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_IDENTITY_Ego *caller_id, const char *callee, struct GNUNET_SPEAKER_Handle *speaker, struct GNUNET_MICROPHONE_Handle *mic, GNUNET_CONVERSATION_CallEventHandler event_handler, void *event_handler_cls)
Call the phone of another user.
void GNUNET_CONVERSATION_call_stop(struct GNUNET_CONVERSATION_Call *call)
Terminate a call.
void(* GNUNET_CONVERSATION_CallEventHandler)(void *cls, enum GNUNET_CONVERSATION_CallEventCode code)
Function called with an event emitted for a call.
@ GNUNET_CONVERSATION_EC_CALL_SUSPENDED
We are the caller and the callee suspended the call.
@ GNUNET_CONVERSATION_EC_CALL_GNS_FAIL
We are the caller and failed to locate a phone record in GNS.
@ GNUNET_CONVERSATION_EC_CALL_PICKED_UP
We are the caller and are now ready to talk as the callee picked up.
@ GNUNET_CONVERSATION_EC_CALL_RESUMED
We are the caller and the callee suspended the call.
@ GNUNET_CONVERSATION_EC_CALL_RINGING
We are the caller and are now ringing the other party (GNS lookup succeeded).
@ GNUNET_CONVERSATION_EC_CALL_ERROR
We had an error handing the call, and are now restarting it (back to lookup).
@ GNUNET_CONVERSATION_EC_CALL_HUNG_UP
We are the caller and the callee called GNUNET_CONVERSATION_caller_hang_up.
void GNUNET_GNS_disconnect(struct GNUNET_GNS_Handle *handle)
Shutdown connection with the GNS service.
Definition: gns_api.c:289
struct GNUNET_GNS_LookupWithTldRequest * GNUNET_GNS_lookup_with_tld(struct GNUNET_GNS_Handle *handle, const char *name, uint32_t type, enum GNUNET_GNS_LocalOptions options, GNUNET_GNS_LookupResultProcessor2 proc, void *proc_cls)
Perform an asynchronous lookup operation on the GNS, determining the zone using the TLD of the given ...
Definition: gns_tld_api.c:240
void * GNUNET_GNS_lookup_with_tld_cancel(struct GNUNET_GNS_LookupWithTldRequest *ltr)
Cancel pending lookup request.
Definition: gns_tld_api.c:331
struct GNUNET_GNS_Handle * GNUNET_GNS_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Initialize the connection with the GNS service.
Definition: gns_api.c:267
@ GNUNET_GNS_LO_DEFAULT
Defaults, look in cache, then in DHT.
const struct GNUNET_CRYPTO_PrivateKey * GNUNET_IDENTITY_ego_get_private_key(const struct GNUNET_IDENTITY_Ego *ego)
Obtain the ECC key associated with a ego.
Definition: identity_api.c:517
#define GNUNET_log(kind,...)
ssize_t GNUNET_CRYPTO_private_key_get_length(const struct GNUNET_CRYPTO_PrivateKey *key)
Get the compacted length of a GNUNET_CRYPTO_PrivateKey.
Definition: crypto_pkey.c:47
ssize_t GNUNET_CRYPTO_write_private_key_to_buffer(const struct GNUNET_CRYPTO_PrivateKey *key, void *buffer, size_t len)
Writes a GNUNET_CRYPTO_PrivateKey to a compact buffer.
Definition: crypto_pkey.c:171
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_OK
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_WARNING
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
GNUNET_MQ_Error
Error codes for the queue.
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:304
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
Definition: gnunet_mq_lib.h:63
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:78
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:683
#define GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME
Client <-> Server message to resume connection.
#define GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND
Client <-> Server message to suspend connection.
#define GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICKED_UP
Service -> Client message to notify that phone was picked up.
#define GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP
Client -> Server message to reject/hangup a call.
#define GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO
Client <-> Server message to send audio data.
#define GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL
Client <- Server message to indicate a ringing phone.
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
#define GNUNET_GNSRECORD_TYPE_PHONE
Endpoint for conversation.
Message Client <-> Service to transmit the audio.
Definition: conversation.h:195
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO.
Definition: conversation.h:199
Client -> Service message to call a phone.
Definition: conversation.h:215
struct GNUNET_HashCode line_port
Which phone line to call at the peer?
Definition: conversation.h:234
struct GNUNET_PeerIdentity target
Which peer is hosting the line?
Definition: conversation.h:229
uint32_t key_len
The identity key length.
Definition: conversation.h:239
Client <-> Service hang up phone that may or may not be ringing.
Definition: conversation.h:177
Service -> Client: other peer has picked up the phone, we are now talking.
Definition: conversation.h:252
Service <-> Client message for phone was resumed.
Definition: conversation.h:140
Service <-> Client message for phone was suspended.
Definition: conversation.h:122
Handle for an outgoing call.
void * event_handler_cls
Closure for event_handler.
char * callee
Target callee as a GNS address/name.
struct GNUNET_GNS_LookupWithTldRequest * gns_lookup
Active GNS lookup (or NULL).
struct GNUNET_GNS_Handle * gns
Connection to GNS (can be NULL).
struct GNUNET_MICROPHONE_Handle * mic
Our microphone.
enum CallState state
State machine for the call.
struct GNUNET_MQ_Handle * mq
Handle for transmitting to the CONVERSATION service.
struct GNUNET_SPEAKER_Handle * speaker
Our speaker.
struct GNUNET_CONVERSATION_PhoneRecord phone_record
Target phone record, only valid after the lookup is done.
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
GNUNET_CONVERSATION_CallEventHandler event_handler
Function to call with events.
struct GNUNET_IDENTITY_Ego * caller_id
Our caller identity.
A phone record specifies which peer is hosting a given user and may also specify the phone line that ...
struct GNUNET_HashCode line_port
Phone line (CADET port) to connect to.
struct GNUNET_PeerIdentity peer
Identity of the peer hosting the phone service.
A private key for an identity as per LSD0001.
const void * data
Binary value stored in the DNS record.
size_t data_size
Number of bytes in data.
Connection to the GNS service.
Definition: gns_api.h:36
Handle to a lookup request.
Definition: gns_tld_api.c:44
Handle for an ego.
Definition: identity.h:37
A microphone is a device that can capture or otherwise produce audio data.
void * cls
Closure for the callbacks.
GNUNET_MICROPHONE_DisableCallback disable_microphone
Turn the microphone off.
GNUNET_MICROPHONE_EnableCallback enable_microphone
Turn on the microphone.
Handle to a message queue.
Definition: mq.c:87
Message handler for a specific message type.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
A speaker is a device that can play or record audio data.
void * cls
Closure for the callbacks.
GNUNET_SPEAKER_PlayCallback play
Play audio.
GNUNET_SPEAKER_EnableCallback enable_speaker
Turn on the speaker.
GNUNET_SPEAKER_DisableCallback disable_speaker
Turn the speaker off.