2
* Copyright (C) 2004, 2005, 2006, 2009, 2008, 2009, 2010, 2011 Savoir-Faire Linux Inc.
3
* Author: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com>
4
* Author: Yan Morin <yan.morin@savoirfairelinux.com>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 3 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
* Additional permission under GNU GPL version 3 section 7:
22
* If you modify this program, or any covered work, by linking or
23
* combining it with the OpenSSL project's OpenSSL library (or a
24
* modified version of that library), containing parts covered by the
25
* terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
26
* grants you additional permission to convey the resulting work.
27
* Corresponding Source for a non-source form of such a combination
28
* shall include the source code for the parts of OpenSSL used as well
29
* as that of the covered work.
31
#include "iaxvoiplink.h"
33
#include "eventthread.h"
34
#include "iaxaccount.h"
36
#include "audio/audiolayer.h"
41
#define IAX_BLOCKING 1
42
#define IAX_NONBLOCKING 0
45
#define IAX_FAILURE -1
47
#define RANDOM_IAX_PORT rand() % 64000 + 1024
49
#define MUSIC_ONHOLD true
51
#define CHK_VALID_CALL if (call == NULL) { _debug("IAX: Call doesn't exists"); \
54
IAXVoIPLink::IAXVoIPLink (const AccountID& accountID) : VoIPLink (accountID)
57
, _nextRefreshStamp (0)
60
, micDataConverted (NULL)
61
, micDataEncoded (NULL)
62
, spkrDataDecoded (NULL)
63
, spkrDataConverted (NULL)
65
, converterSamplingRate (NULL)
68
_evThread = new EventThread (this);
70
// to get random number for RANDOM_PORT
73
converter = new SamplerateConverter (44100, 20);
75
// int nbSamplesMax = (int) (converter->getFrequence() * converter->getFramesize() / 1000);
76
int nbSamplesMax = (44100 * 20) / 1000;
78
micData = new SFLDataFormat[nbSamplesMax];
79
micDataConverted = new SFLDataFormat[nbSamplesMax];
80
micDataEncoded = new unsigned char[nbSamplesMax];
82
spkrDataConverted = new SFLDataFormat[nbSamplesMax];
83
spkrDataDecoded = new SFLDataFormat[nbSamplesMax];
85
urlhook = new UrlHook ();
89
IAXVoIPLink::~IAXVoIPLink()
96
_regSession = NULL; // shall not delete it
111
if (micDataConverted) {
112
delete [] micDataConverted;
113
micDataConverted = NULL;
116
if (micDataEncoded) {
117
delete [] micDataEncoded;
118
micDataEncoded = NULL;
121
if (spkrDataDecoded) {
122
delete [] spkrDataDecoded;
123
spkrDataDecoded = NULL;
126
if (spkrDataConverted) {
127
delete [] spkrDataConverted;
128
spkrDataConverted = NULL;
136
// If it was done, don't do it again, until we call terminate()
140
bool returnValue = false;
142
// _localAddress = "127.0.0.1";
144
// iax_enable_debug(); have to enable debug when compiling iax...
145
int port = IAX_DEFAULT_PORTNO;
151
while (port != IAX_FAILURE && nbTry) {
153
port = iax_init (port);
156
_debug ("IAX Warning: already initialize on port %d", last_port);
157
port = RANDOM_IAX_PORT;
158
} else if (port == IAX_FAILURE) {
159
_debug ("IAX Fail to start on port %d", last_port);
160
port = RANDOM_IAX_PORT;
162
_debug ("IAX Info: listening on port %d", last_port);
163
_localPort = last_port;
167
audiolayer = Manager::instance().getAudioDriver();
169
// may be different than one already setted
170
converterSamplingRate = audiolayer->getMainBuffer()->getInternalSamplingRate();
180
if (port == IAX_FAILURE || nbTry==0) {
181
_debug ("Fail to initialize iax");
190
IAXVoIPLink::terminate()
192
// If it was done, don't do it again, until we call init()
205
IAXVoIPLink::terminateIAXCall()
207
std::string reason = "Dumped Call";
208
ost::MutexLock m (_callMapMutex);
209
CallMap::iterator iter = _callMap.begin();
212
while (iter != _callMap.end()) {
213
call = dynamic_cast<IAXCall*> (iter->second);
216
_mutexIAX.enterMutex();
217
iax_hangup (call->getSession(), (char*) reason.c_str());
218
_mutexIAX.leaveMutex();
219
call->setSession (NULL);
230
void IAXVoIPLink::terminateCall (const CallID& id)
232
IAXCall* call = getIAXCall (id);
235
_debug ("IAXVoIPLink: Terminate call");
244
IAXVoIPLink::getEvent()
246
IAXCall* call = NULL;
248
// Manager::instance().getAudioLayerMutex()->enter();
251
_mutexIAX.enterMutex();
252
iax_event* event = NULL;
254
while ( (event = iax_get_event (IAX_NONBLOCKING)) != NULL) {
255
// If we received an 'ACK', libiax2 tells apps to ignore them.
256
if (event->etype == IAX_EVENT_NULL) {
260
//_debug ("Receive IAX Event: %d (0x%x)", event->etype, event->etype);
262
call = iaxFindCallBySession (event->session);
265
// We know that call, deal with it
266
iaxHandleCallEvent (event, call);
267
//_audiocodec = Manager::instance().getCodecDescriptorMap().getCodec( call -> getAudioCodec() );
268
} else if (event->session && event->session == _regSession) {
269
// This is a registration session, deal with it
270
iaxHandleRegReply (event);
272
// We've got an event before it's associated with any call
273
iaxHandlePrecallEvent (event);
276
// _debug("IAXVoIPLink::getEvent() : timestamp %i ",event->ts);
278
iax_event_free (event);
281
_mutexIAX.leaveMutex();
285
// Manager::instance().getAudioLayerMutex()->leave();
287
// Do the doodle-moodle to send audio from the microphone to the IAX channel.
288
// sendAudioFromMic();
290
// Refresh registration.
291
if (_nextRefreshStamp && _nextRefreshStamp - 2 < time (NULL)) {
295
// thread wait 3 millisecond
296
_evThread->sleep (3);
302
IAXVoIPLink::sendAudioFromMic (void)
305
int maxBytesToGet, availBytesFromMic, bytesAvail, compSize;
307
IAXCall *currentCall;
309
// We have to update the audio layer type in case we switched
310
// TODO Find out a better way to do it
313
// do not use the current ID in Manager (it may refer to a conference also)
314
// currentCall = getIAXCall (Manager::instance().getCurrentCallId());
316
CallMap::iterator iter_call = _callMap.begin();
318
while (iter_call != _callMap.end()) {
320
currentCall = (IAXCall*) iter_call->second;
326
// bool sessionIsConnected = (currentCall->getConnectionState() == Call::Connected);
327
bool callIsActive = (currentCall->getState() == Call::Active);
329
// if (sessionIsConnected || callIsActive) {
333
ac = currentCall->getCodecMap().getCodec (currentCall->getAudioCodec());
337
if (ac && audiolayer) {
339
// _debug("Send sound");
340
// audiolayer->getMainBuffer()->flush(currentCall->getCallId());
342
audiolayer->getMainBuffer()->setInternalSamplingRate (ac->getClockRate());
344
int _mainBufferSampleRate = audiolayer->getMainBuffer()->getInternalSamplingRate();
346
// we have to get 20ms of data from the mic *20/1000 = /50
347
// rate/50 shall be lower than IAX__20S_48KHZ_MAX
348
maxBytesToGet = _mainBufferSampleRate * audiolayer->getFrameSize() / 1000 * sizeof (SFLDataFormat);
350
// available bytes inside ringbuffer
351
availBytesFromMic = audiolayer->getMainBuffer()->availForGet (currentCall->getCallId());
352
// We need packets full!
354
if (availBytesFromMic > maxBytesToGet) {
357
bytesAvail = (availBytesFromMic < maxBytesToGet) ? availBytesFromMic : maxBytesToGet;
359
// Get bytes from micRingBuffer to data_from_mic
360
nbSample_ = audiolayer->getMainBuffer()->getData (micData, bytesAvail, 100, currentCall->getCallId()) / sizeof (SFLDataFormat);
363
// Store the number of samples for recording
364
nbSampleForRec_ = nbSample_;
367
if (ac->getClockRate() && (ac->getClockRate() != _mainBufferSampleRate)) {
370
nbSample_ = converter->downsampleData (micData , micDataConverted , (int) ac->getClockRate(), _mainBufferSampleRate, nbSample_);
372
// for the mono: range = 0 to IAX_FRAME2SEND * sizeof(int16)
373
compSize = ac->codecEncode (micDataEncoded, micDataConverted , nbSample_*sizeof (int16));
377
// for the mono: range = 0 to IAX_FRAME2SEND * sizeof(int16)
378
compSize = ac->codecEncode (micDataEncoded, micData, nbSample_*sizeof (int16));
383
_mutexIAX.enterMutex();
385
// Make sure the session and the call still exists.
386
if (currentCall->getSession() && (micDataEncoded != NULL) && (nbSample_ > 0)) {
387
if (iax_send_voice (currentCall->getSession(), currentCall->getFormat(), micDataEncoded, compSize, nbSample_) == -1) {
388
_debug ("IAX: Error sending voice data.");
392
_mutexIAX.leaveMutex();
406
IAXVoIPLink::getIAXCall (const CallID& id)
408
Call* call = getCall (id);
411
return dynamic_cast<IAXCall*> (call);
419
IAXVoIPLink::sendRegister (AccountID id UNUSED) throw(VoipLinkException)
421
_debug ("IAX: Sending registration");
423
IAXAccount *account = dynamic_cast<IAXAccount *> (getAccountPtr());
426
throw VoipLinkException("Account is NULL in send register");
429
if (account->getHostname().empty()) {
430
throw VoipLinkException("Account hostname is empty");
433
if (account->getUsername().empty()) {
434
throw VoipLinkException("Account username is empty");
438
_mutexIAX.enterMutex();
440
// Always use a brand new session
442
iax_destroy (_regSession);
445
_regSession = iax_session_new();
448
_debug ("IAX: Error when generating new session for register");
450
_debug ("IAX: Sending registration to %s with user %s", account->getHostname().c_str() , account->getUsername().c_str());
451
int val = iax_register (_regSession, account->getHostname().data(), account->getUsername().data(), account->getPassword().data(), 120);
452
_debug ("IAX: Return value: %d", val);
453
// set the time-out to 15 seconds, after that, resend a registration request.
454
// until we unregister.
455
_nextRefreshStamp = time (NULL) + 10;
457
account->setRegistrationState (Trying);
461
_mutexIAX.leaveMutex();
465
IAXVoIPLink::sendUnregister (AccountID id UNUSED) throw(VoipLinkException)
467
_debug ("IAXVoipLink: Send unregister");
469
IAXAccount *account = dynamic_cast<IAXAccount*> (getAccountPtr());
472
throw VoipLinkException("Account is NULL in send unregister");
475
_mutexIAX.enterMutex();
478
/** @todo Should send a REGREL in sendUnregister()... */
479
//iax_send_regrel(); doesn't exist yet :)
480
iax_destroy (_regSession);
484
_mutexIAX.leaveMutex();
486
_nextRefreshStamp = 0;
488
account->setRegistrationState (Unregistered);
492
IAXVoIPLink::newOutgoingCall (const CallID& id, const std::string& toUrl) throw(VoipLinkException)
494
IAXCall* call = new IAXCall (id, Call::Outgoing);
495
call->setCodecMap (Manager::instance().getCodecDescriptorMap());
498
call->setPeerNumber (toUrl);
499
call->initRecFileName (toUrl);
501
if (iaxOutgoingInvite (call)) {
502
call->setConnectionState (Call::Progressing);
503
call->setState (Call::Active);
516
IAXVoIPLink::answer (const CallID& id)
518
IAXCall* call = getIAXCall (id);
519
call->setCodecMap (Manager::instance().getCodecDescriptorMap());
521
Manager::instance().addStream (call->getCallId());
525
_mutexIAX.enterMutex();
526
iax_answer (call->getSession());
527
_mutexIAX.leaveMutex();
529
call->setState (Call::Active);
530
call->setConnectionState (Call::Connected);
533
audiolayer->flushMain();
539
IAXVoIPLink::hangup (const CallID& id)
541
_debug ("IAXVoIPLink: Hangup");
542
IAXCall* call = getIAXCall (id);
543
std::string reason = "Dumped Call";
546
audiolayer->getMainBuffer()->unBindAll (call->getCallId());
548
_mutexIAX.enterMutex();
550
iax_hangup (call->getSession(), (char*) reason.c_str());
551
_mutexIAX.leaveMutex();
552
call->setSession (NULL);
554
if (Manager::instance().isCurrentCall (id)) {
556
// audiolayer->stopStream();
565
IAXVoIPLink::peerHungup (const CallID& id)
567
_debug ("IAXVoIPLink: Peer hung up");
568
IAXCall* call = getIAXCall (id);
569
std::string reason = "Dumped Call";
572
audiolayer->getMainBuffer()->unBindAll (call->getCallId());
574
_mutexIAX.enterMutex();
576
_mutexIAX.leaveMutex();
577
call->setSession (NULL);
579
if (Manager::instance().isCurrentCall (id)) {
581
// audiolayer->stopStream();
591
IAXVoIPLink::onhold (const CallID& id)
593
IAXCall* call = getIAXCall (id);
597
audiolayer->getMainBuffer()->unBindAll (call->getCallId());
599
//if (call->getState() == Call::Hold) { _debug("Call is already on hold"); return false; }
601
_mutexIAX.enterMutex();
602
iax_quelch_moh (call->getSession() , MUSIC_ONHOLD);
603
_mutexIAX.leaveMutex();
605
call->setState (Call::Hold);
610
IAXVoIPLink::offhold (const CallID& id)
612
IAXCall* call = getIAXCall (id);
616
Manager::instance().addStream (call->getCallId());
618
//if (call->getState() == Call::Active) { _debug("Call is already active"); return false; }
619
_mutexIAX.enterMutex();
620
iax_unquelch (call->getSession());
621
_mutexIAX.leaveMutex();
622
audiolayer->startStream();
623
call->setState (Call::Active);
628
IAXVoIPLink::transfer (const CallID& id, const std::string& to)
630
IAXCall* call = getIAXCall (id);
634
char callto[to.length() +1];
635
strcpy (callto, to.c_str());
637
_mutexIAX.enterMutex();
638
iax_transfer (call->getSession(), callto);
639
_mutexIAX.leaveMutex();
643
// should we remove it?
648
IAXVoIPLink::attendedTransfer(const CallID& transferID, const CallID& targetID)
650
// TODO implement attended transfer for IAX
655
IAXVoIPLink::refuse (const CallID& id)
657
IAXCall* call = getIAXCall (id);
658
std::string reason = "Call rejected manually.";
662
_mutexIAX.enterMutex();
663
iax_reject (call->getSession(), (char*) reason.c_str());
664
_mutexIAX.leaveMutex();
673
IAXVoIPLink::carryingDTMFdigits (const CallID& id, char code)
675
IAXCall* call = getIAXCall (id);
679
_mutexIAX.enterMutex();
680
iax_send_dtmf (call->getSession(), code);
681
_mutexIAX.leaveMutex();
687
IAXVoIPLink::sendTextMessage (sfl::InstantMessaging *module, const std::string& callID, const std::string& message, const std::string& from)
689
IAXCall* call = getIAXCall (callID);
693
// Must active the mutex for this session
694
_mutexIAX.enterMutex();
696
module->send_iax_message (call->getSession(), callID, message.c_str());
698
// iax_send_text (call->getSession(), message.c_str());
699
_mutexIAX.leaveMutex();
706
IAXVoIPLink::getCurrentCodecName()
708
IAXCall *call = NULL;
709
AudioCodec *ac = NULL;
710
std::string name = "";
712
call = getIAXCall (Manager::instance().getCurrentCallId());
715
ac = call->getCodecMap().getCodec (call->getAudioCodec());
718
name = ac->getCodecName();
725
IAXVoIPLink::iaxOutgoingInvite (IAXCall* call)
728
struct iax_session *newsession;
729
ost::MutexLock m (_mutexIAX);
730
std::string username, strNum;
732
int wait, audio_format_preferred, audio_format_capability;
735
newsession = iax_session_new();
738
_debug ("IAX Error: Can't make new session for a new call");
742
call->setSession (newsession);
744
account = dynamic_cast<IAXAccount*> (getAccountPtr());
745
username = account->getUsername();
746
strNum = username + ":" + account->getPassword() + "@" + account->getHostname() + "/" + call->getPeerNumber();
749
/** @todo Make preference dynamic, and configurable */
750
audio_format_preferred = call->getFirstMatchingFormat (call->getSupportedFormat (getAccountID ()), getAccountID ());
751
audio_format_capability = call->getSupportedFormat (getAccountID ());
753
_debug ("IAX New call: %s", strNum.c_str());
754
iax_call (newsession, username.c_str(), username.c_str(), strNum.c_str(), lang, wait, audio_format_preferred, audio_format_capability);
761
IAXVoIPLink::iaxFindCallBySession (struct iax_session* session)
763
// access to callMap shoud use that
764
// the code below is like findSIPCallWithCid()
765
ost::MutexLock m (_callMapMutex);
766
IAXCall* call = NULL;
767
CallMap::iterator iter = _callMap.begin();
769
while (iter != _callMap.end()) {
770
call = dynamic_cast<IAXCall*> (iter->second);
772
if (call && call->getSession() == session) {
779
return NULL; // not found
783
IAXVoIPLink::iaxHandleCallEvent (iax_event* event, IAXCall* call)
785
// call should not be 0
788
CallID id = call->getCallId();
790
switch (event->etype) {
792
case IAX_EVENT_HANGUP:
794
if (Manager::instance().isCurrentCall (id)) {
796
// audiolayer->stopStream();
799
Manager::instance().peerHungupCall (id);
802
_debug("IAXVoIPLink::iaxHandleCallEvent, peer hangup have been called");
803
std::string reason = "Dumped Call";
804
_mutexIAX.enterMutex();
805
iax_hangup(call->getSession(), (char*)reason.c_str());
806
_mutexIAX.leaveMutex();
807
call->setSession(NULL);
808
audiolayer->stopStream();
813
case IAX_EVENT_REJECT:
814
//Manager::instance().peerHungupCall(id);
816
if (Manager::instance().isCurrentCall (id)) {
818
// audiolayer->stopStream();
821
call->setConnectionState (Call::Connected);
823
call->setState (Call::Error);
824
Manager::instance().callFailure (id);
828
case IAX_EVENT_ACCEPT:
830
// Call accepted over there by the computer, not the user yet.
831
_debug ("IAX_EVENT_ACCEPT: codec format: ");
833
if (event->ies.format) {
834
printf ("%i", event->ies.format);
835
call->setFormat (event->ies.format);
837
printf ("no codec format");
842
case IAX_EVENT_ANSWER:
844
if (call->getConnectionState() != Call::Connected) {
846
Manager::instance().addStream (call->getCallId());
848
call->setConnectionState (Call::Connected);
849
call->setState (Call::Active);
850
// audiolayer->startStream();
852
_debug ("IAX_EVENT_ANSWER: codec format: ");
854
if (event->ies.format) {
855
// Should not get here, should have been set in EVENT_ACCEPT
856
printf ("%i", event->ies.format);
857
call->setFormat (event->ies.format);
861
printf ("no codec format");
864
Manager::instance().peerAnsweredCall (id);
867
audiolayer->startStream();
868
audiolayer->flushMain();
876
call->setConnectionState (Call::Connected);
877
call->setState (Call::Busy);
878
Manager::instance().callBusy (id);
882
case IAX_EVENT_VOICE:
883
//if (!audiolayer->isCaptureActive ())
884
// audiolayer->startStream ();
885
// _debug("IAX_EVENT_VOICE: ");
886
iaxHandleVoiceEvent (event, call);
890
Manager::instance ().incomingMessage (call->getCallId (), call->getPeerNumber(), std::string ( (const char*) event->data));
893
case IAX_EVENT_RINGA:
894
call->setConnectionState (Call::Ringing);
895
Manager::instance().peerRingingCall (call->getCallId());
898
case IAX_IE_MSGCOUNT:
906
if (Manager::instance().getConfigString (HOOKS, URLHOOK_IAX2_ENABLED) == "1") {
907
if (strcmp ( (char*) event->data, "") != 0) {
908
_debug ("> IAX_EVENT_URL received: %s", event->data);
909
urlhook->addAction ( (char*) event->data, Manager::instance().getConfigString (HOOKS, URLHOOK_COMMAND));
915
case IAX_EVENT_TIMEOUT:
918
case IAX_EVENT_TRANSFER:
919
_debug ("IAX_EVENT_TRANSFER");
921
if (call->getConnectionState() != Call::Connected) {
923
Manager::instance().addStream (call->getCallId());
925
call->setConnectionState (Call::Connected);
926
call->setState (Call::Active);
927
// audiolayer->startStream();
929
_debug ("IAX_EVENT_ANSWER: codec format: ");
931
if (event->ies.format) {
932
// Should not get here, should have been set in EVENT_ACCEPT
933
printf ("%i", event->ies.format);
934
call->setFormat (event->ies.format);
938
printf ("no codec format");
941
Manager::instance().peerAnsweredCall (id);
944
audiolayer->startStream();
945
audiolayer->flushMain();
953
_debug ("iaxHandleCallEvent: Unknown event type (in call event): %d", event->etype);
959
/* Handle audio event, VOICE packet received */
961
IAXVoIPLink::iaxHandleVoiceEvent (iax_event* event, IAXCall* call)
965
unsigned int size, max, nbInt16;
966
int expandedSize, nbSample_;
972
if (!event->datalen) {
973
// Skip this empty packet.
974
//_debug("IAX: Skipping empty jitter-buffer interpolated packet");
978
ac = call->getCodecMap ().getCodec (call->getAudioCodec ());
985
audiolayer->getMainBuffer ()->setInternalSamplingRate (ac->getClockRate ());
987
// If we receive datalen == 0, some things of the jitter buffer in libiax2/iax.c
990
int _mainBufferSampleRate = audiolayer->getMainBuffer()->getInternalSamplingRate();
992
// On-the-fly codec changing (normally, when we receive a full packet)
993
// as per http://tools.ietf.org/id/draft-guy-iax-03.txt
994
// - subclass holds the voiceformat property.
996
if (event->subclass && event->subclass != call->getFormat()) {
997
_debug ("iaxHandleVoiceEvent: no format found in call setting it to %i", event->subclass);
998
call->setFormat (event->subclass);
1001
//_debug("Receive: len=%d, format=%d, _receiveDataDecoded=%p", event->datalen, call->getFormat(), _receiveDataDecoded);
1002
// ac = call->getCodecMap().getCodec (call -> getAudioCodec());
1004
data = (unsigned char*) event->data;
1006
size = event->datalen;
1008
// Decode data with relevant codec
1009
max = (int) (ac->getClockRate() * audiolayer->getFrameSize() / 1000);
1012
_debug ("The size %d is bigger than expected %d. Packet cropped. Ouch!", size, max);
1016
expandedSize = ac->codecDecode (spkrDataDecoded , data , size);
1018
nbInt16 = expandedSize/sizeof (int16);
1020
if (nbInt16 > max) {
1021
_debug ("We have decoded an IAX VOICE packet larger than expected: %i VS %i. Cropping.", nbInt16, max);
1025
nbSample_ = nbInt16;
1027
// test if resampling is required
1029
if (ac->getClockRate() && (ac->getClockRate() != _mainBufferSampleRate)) {
1032
nbInt16 = converter->upsampleData (spkrDataDecoded, spkrDataConverted, ac->getClockRate(), _mainBufferSampleRate, nbSample_);
1034
/* Write the data to the mic ring buffer */
1035
audiolayer->getMainBuffer()->putData (spkrDataConverted, nbInt16 * sizeof (SFLDataFormat), 100, call->getCallId());
1039
/* Write the data to the mic ring buffer */
1040
audiolayer->getMainBuffer()->putData (spkrDataDecoded, nbInt16 * sizeof (SFLDataFormat), 100, call->getCallId());
1045
_debug ("IAX: incoming audio, but no sound card open");
1051
* Handle the registration process
1054
IAXVoIPLink::iaxHandleRegReply (iax_event* event)
1057
std::string account_id;
1058
IAXAccount *account;
1060
account_id = getAccountID();
1061
account = dynamic_cast<IAXAccount *> (Manager::instance().getAccount (account_id));
1063
if (event->etype == IAX_EVENT_REGREJ) {
1064
/* Authentication failed! */
1065
_mutexIAX.enterMutex();
1066
iax_destroy (_regSession);
1067
_mutexIAX.leaveMutex();
1069
// Update the account registration state
1070
account->setRegistrationState (ErrorAuth);
1073
else if (event->etype == IAX_EVENT_REGACK) {
1074
/* Authentication succeeded */
1075
_mutexIAX.enterMutex();
1077
// Looking for the voicemail information
1078
//if( event->ies != 0 )
1079
//new_voicemails = processIAXMsgCount(event->ies.msgcount);
1080
//_debug("iax voicemail number notification: %i", new_voicemails);
1081
// Notify the client if new voicemail waiting for the current account
1082
//account_id = getAccountID();
1083
//Manager::instance().startVoiceMessageNotification(account_id.c_str(), new_voicemails);
1085
iax_destroy (_regSession);
1086
_mutexIAX.leaveMutex();
1089
// I mean, save the timestamp, so that we re-register again in the REFRESH time.
1090
// Defaults to 60, as per draft-guy-iax-03.
1091
_nextRefreshStamp = time (NULL) + (event->ies.refresh ? event->ies.refresh : 60);
1092
account->setRegistrationState (Registered);
1096
int IAXVoIPLink::processIAXMsgCount (int msgcount)
1099
// IAX sends the message count under a specific format:
1101
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
1102
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1104
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1105
// | Old messages | New messages |
1106
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1108
// For now we just need the new messages informations.
1110
// 0 <= msgcount <= 255 => msgcount new messages, 0 old messages
1111
// msgcount >= 256 => msgcount/256 old messages , msgcount%256 new messages (RULES)
1113
return msgcount%256;
1119
IAXVoIPLink::iaxHandlePrecallEvent (iax_event* event)
1121
IAXCall* call = NULL;
1123
std::string reason = "Error ringing user.";
1125
switch (event->etype) {
1127
case IAX_EVENT_REGACK:
1129
case IAX_EVENT_REGREJ:
1130
_debug ("IAX Registration Event in a pre-call setup");
1133
case IAX_EVENT_REGREQ:
1134
// Received when someone wants to register to us!?!
1135
// Asterisk receives and answers to that, not us, we're a phone.
1136
_debug ("Registration by a peer, don't allow it");
1139
case IAX_EVENT_CONNECT:
1140
// We've got an incoming call! Yikes!
1141
_debug ("> IAX_EVENT_CONNECT (receive)");
1143
id = Manager::instance().getNewCallID();
1145
call = new IAXCall (id, Call::Incoming);
1148
_debug ("! IAX Failure: unable to create an incoming call");
1152
// Setup the new IAXCall
1153
// Associate the call to the session.
1154
call->setSession (event->session);
1156
// setCallAudioLocal(call);
1157
call->setCodecMap (Manager::instance().getCodecDescriptorMap());
1159
call->setConnectionState (Call::Progressing);
1162
if (event->ies.calling_number)
1163
call->setPeerNumber (std::string (event->ies.calling_number));
1165
if (event->ies.calling_name)
1166
call->setPeerName (std::string (event->ies.calling_name));
1168
// if peerNumber exist append it to the name string
1169
call->initRecFileName (std::string (event->ies.calling_number));
1171
if (Manager::instance().incomingCall (call, getAccountID())) {
1172
/** @todo Faudra considérer éventuellement le champ CODEC PREFS pour
1173
* l'établissement du codec de transmission */
1175
// Remote lists its capabilities
1176
int format = call->getFirstMatchingFormat (event->ies.capability, getAccountID ());
1177
// Remote asks for preferred codec voiceformat
1178
int pref_format = call->getFirstMatchingFormat (event->ies.format, getAccountID ());
1180
// Priority to remote's suggestion. In case it's a forwarding, no transcoding
1181
// will be needed from the server, thus less latency.
1184
format = pref_format;
1186
iax_accept (event->session, format);
1188
iax_ring_announce (event->session);
1192
// Set the audio codec now, to avoid non-set codec problem later
1193
call->setFormat (format);
1196
// reject call, unable to add it
1197
iax_reject (event->session, (char*) reason.c_str());
1205
case IAX_EVENT_HANGUP:
1206
// Remote peer hung up
1207
call = iaxFindCallBySession (event->session);
1208
id = call->getCallId();
1209
_debug ("IAXVoIPLink::hungup::iaxHandlePrecallEvent");
1210
Manager::instance().peerHungupCall (id);
1214
case IAX_EVENT_TIMEOUT: // timeout for an unknown session
1218
case IAX_IE_MSGCOUNT:
1222
_debug ("IAXVoIPLink::iaxHandlePrecallEvent: Unknown event type (in precall): %d", event->etype);
1227
void IAXVoIPLink::updateAudiolayer (void)
1229
_mutexIAX.enterMutex();
1231
audiolayer = Manager::instance().getAudioDriver();
1232
_mutexIAX.leaveMutex();