~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to sflphone-common/src/iax/iaxvoiplink.cpp

  • Committer: Package Import Robot
  • Author(s): Francois Marier
  • Date: 2011-11-25 13:24:12 UTC
  • mfrom: (4.1.10 sid)
  • Revision ID: package-import@ubuntu.com-20111125132412-dc4qvhyosk74cd42
Tags: 1.0.1-4
Don't assume that arch:all packages will get built (closes: #649726)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
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>
5
 
 *
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.
10
 
 *
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.
15
 
 *
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.
19
 
 *
20
 
 *  Additional permission under GNU GPL version 3 section 7:
21
 
 *
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.
30
 
 */
31
 
#include "iaxvoiplink.h"
32
 
#include "iaxcall.h"
33
 
#include "eventthread.h"
34
 
#include "iaxaccount.h"
35
 
#include "manager.h"
36
 
#include "audio/audiolayer.h"
37
 
 
38
 
#include <math.h>
39
 
#include <dlfcn.h>
40
 
 
41
 
#define IAX_BLOCKING    1
42
 
#define IAX_NONBLOCKING 0
43
 
 
44
 
#define IAX_SUCCESS  0
45
 
#define IAX_FAILURE -1
46
 
 
47
 
#define RANDOM_IAX_PORT   rand() % 64000 + 1024
48
 
 
49
 
#define MUSIC_ONHOLD true
50
 
 
51
 
#define CHK_VALID_CALL   if (call == NULL) { _debug("IAX: Call doesn't exists"); \
52
 
        return false; }
53
 
 
54
 
IAXVoIPLink::IAXVoIPLink (const AccountID& accountID) : VoIPLink (accountID)
55
 
    , _evThread (NULL)
56
 
    , _regSession (NULL)
57
 
    , _nextRefreshStamp (0)
58
 
    , audiolayer (NULL)
59
 
    , micData (NULL)
60
 
    , micDataConverted (NULL)
61
 
    , micDataEncoded (NULL)
62
 
    , spkrDataDecoded (NULL)
63
 
    , spkrDataConverted (NULL)
64
 
    , converter (NULL)
65
 
    , converterSamplingRate (NULL)
66
 
    , urlhook (NULL)
67
 
{
68
 
    _evThread = new EventThread (this);
69
 
 
70
 
    // to get random number for RANDOM_PORT
71
 
    srand (time (NULL));
72
 
 
73
 
    converter = new SamplerateConverter (44100, 20);
74
 
 
75
 
    // int nbSamplesMax = (int) (converter->getFrequence() * converter->getFramesize() / 1000);
76
 
    int nbSamplesMax = (44100 * 20) / 1000;
77
 
 
78
 
    micData = new SFLDataFormat[nbSamplesMax];
79
 
    micDataConverted = new SFLDataFormat[nbSamplesMax];
80
 
    micDataEncoded = new unsigned char[nbSamplesMax];
81
 
 
82
 
    spkrDataConverted = new SFLDataFormat[nbSamplesMax];
83
 
    spkrDataDecoded = new SFLDataFormat[nbSamplesMax];
84
 
 
85
 
    urlhook = new UrlHook ();
86
 
}
87
 
 
88
 
 
89
 
IAXVoIPLink::~IAXVoIPLink()
90
 
{
91
 
    if (_evThread) {
92
 
        delete _evThread;
93
 
        _evThread = NULL;
94
 
    }
95
 
 
96
 
    _regSession = NULL; // shall not delete it
97
 
    terminate();
98
 
 
99
 
    audiolayer = NULL;
100
 
 
101
 
    if (converter) {
102
 
        delete converter;
103
 
        converter = NULL;
104
 
    }
105
 
 
106
 
    if (micData) {
107
 
        delete [] micData;
108
 
        micData = NULL;
109
 
    }
110
 
 
111
 
    if (micDataConverted) {
112
 
        delete [] micDataConverted;
113
 
        micDataConverted = NULL;
114
 
    }
115
 
 
116
 
    if (micDataEncoded) {
117
 
        delete [] micDataEncoded;
118
 
        micDataEncoded = NULL;
119
 
    }
120
 
 
121
 
    if (spkrDataDecoded) {
122
 
        delete [] spkrDataDecoded;
123
 
        spkrDataDecoded = NULL;
124
 
    }
125
 
 
126
 
    if (spkrDataConverted) {
127
 
        delete [] spkrDataConverted;
128
 
        spkrDataConverted = NULL;
129
 
    }
130
 
 
131
 
}
132
 
 
133
 
bool
134
 
IAXVoIPLink::init()
135
 
{
136
 
    // If it was done, don't do it again, until we call terminate()
137
 
    if (initDone())
138
 
        return false;
139
 
 
140
 
    bool returnValue = false;
141
 
 
142
 
    // _localAddress = "127.0.0.1";
143
 
    // port 0 is default
144
 
    //  iax_enable_debug(); have to enable debug when compiling iax...
145
 
    int port = IAX_DEFAULT_PORTNO;
146
 
 
147
 
    int last_port = 0;
148
 
 
149
 
    int nbTry = 3;
150
 
 
151
 
    while (port != IAX_FAILURE && nbTry) {
152
 
        last_port = port;
153
 
        port = iax_init (port);
154
 
 
155
 
        if (port < 0) {
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;
161
 
        } else {
162
 
            _debug ("IAX Info: listening on port %d", last_port);
163
 
            _localPort = last_port;
164
 
            returnValue = true;
165
 
            _evThread->start();
166
 
 
167
 
            audiolayer = Manager::instance().getAudioDriver();
168
 
 
169
 
            // may be different than one already setted
170
 
            converterSamplingRate = audiolayer->getMainBuffer()->getInternalSamplingRate();
171
 
 
172
 
            break;
173
 
        }
174
 
 
175
 
        nbTry--;
176
 
 
177
 
        initDone (true);
178
 
    }
179
 
 
180
 
    if (port == IAX_FAILURE || nbTry==0) {
181
 
        _debug ("Fail to initialize iax");
182
 
 
183
 
        initDone (false);
184
 
    }
185
 
 
186
 
    return returnValue;
187
 
}
188
 
 
189
 
void
190
 
IAXVoIPLink::terminate()
191
 
{
192
 
    // If it was done, don't do it again, until we call init()
193
 
    if (!initDone())
194
 
        return;
195
 
 
196
 
    // iaxc_shutdown();
197
 
 
198
 
    // Hangup all calls
199
 
    terminateIAXCall();
200
 
 
201
 
    initDone (false);
202
 
}
203
 
 
204
 
void
205
 
IAXVoIPLink::terminateIAXCall()
206
 
{
207
 
    std::string reason = "Dumped Call";
208
 
    ost::MutexLock m (_callMapMutex);
209
 
    CallMap::iterator iter = _callMap.begin();
210
 
    IAXCall *call;
211
 
 
212
 
    while (iter != _callMap.end()) {
213
 
        call = dynamic_cast<IAXCall*> (iter->second);
214
 
 
215
 
        if (call) {
216
 
            _mutexIAX.enterMutex();
217
 
            iax_hangup (call->getSession(), (char*) reason.c_str());
218
 
            _mutexIAX.leaveMutex();
219
 
            call->setSession (NULL);
220
 
            delete call;
221
 
            call = NULL;
222
 
        }
223
 
 
224
 
        iter++;
225
 
    }
226
 
 
227
 
    _callMap.clear();
228
 
}
229
 
 
230
 
void IAXVoIPLink::terminateCall (const CallID& id)
231
 
{
232
 
    IAXCall* call = getIAXCall (id);
233
 
 
234
 
    if (call) {
235
 
        _debug ("IAXVoIPLink: Terminate call");
236
 
        delete call;
237
 
        call = 0;
238
 
    }
239
 
}
240
 
 
241
 
 
242
 
 
243
 
void
244
 
IAXVoIPLink::getEvent()
245
 
{
246
 
    IAXCall* call = NULL;
247
 
 
248
 
    // Manager::instance().getAudioLayerMutex()->enter();
249
 
 
250
 
    // lock iax_ stuff..
251
 
    _mutexIAX.enterMutex();
252
 
    iax_event* event = NULL;
253
 
 
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) {
257
 
            continue;
258
 
        }
259
 
 
260
 
        //_debug ("Receive IAX Event: %d (0x%x)", event->etype, event->etype);
261
 
 
262
 
        call = iaxFindCallBySession (event->session);
263
 
 
264
 
        if (call) {
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);
271
 
        } else {
272
 
            // We've got an event before it's associated with any call
273
 
            iaxHandlePrecallEvent (event);
274
 
        }
275
 
 
276
 
        // _debug("IAXVoIPLink::getEvent() : timestamp %i ",event->ts);
277
 
 
278
 
        iax_event_free (event);
279
 
    }
280
 
 
281
 
    _mutexIAX.leaveMutex();
282
 
 
283
 
    sendAudioFromMic();
284
 
 
285
 
    // Manager::instance().getAudioLayerMutex()->leave();
286
 
 
287
 
    // Do the doodle-moodle to send audio from the microphone to the IAX channel.
288
 
    // sendAudioFromMic();
289
 
 
290
 
    // Refresh registration.
291
 
    if (_nextRefreshStamp && _nextRefreshStamp - 2 < time (NULL)) {
292
 
        sendRegister ("");
293
 
    }
294
 
 
295
 
    // thread wait 3 millisecond
296
 
    _evThread->sleep (3);
297
 
 
298
 
    free (event);
299
 
}
300
 
 
301
 
void
302
 
IAXVoIPLink::sendAudioFromMic (void)
303
 
{
304
 
 
305
 
    int maxBytesToGet, availBytesFromMic, bytesAvail, compSize;
306
 
    AudioCodec *ac;
307
 
    IAXCall *currentCall;
308
 
 
309
 
    // We have to update the audio layer type in case we switched
310
 
    // TODO Find out a better way to do it
311
 
    updateAudiolayer();
312
 
 
313
 
    // do not use the current ID in Manager (it may refer to a conference also)
314
 
    // currentCall = getIAXCall (Manager::instance().getCurrentCallId());
315
 
 
316
 
    CallMap::iterator iter_call = _callMap.begin();
317
 
 
318
 
    while (iter_call != _callMap.end()) {
319
 
 
320
 
        currentCall = (IAXCall*) iter_call->second;
321
 
 
322
 
        iter_call++;
323
 
 
324
 
        if (currentCall) {
325
 
 
326
 
            // bool sessionIsConnected = (currentCall->getConnectionState() == Call::Connected);
327
 
            bool callIsActive = (currentCall->getState() == Call::Active);
328
 
 
329
 
            // if (sessionIsConnected || callIsActive) {
330
 
 
331
 
            if (callIsActive) {
332
 
 
333
 
                ac = currentCall->getCodecMap().getCodec (currentCall->getAudioCodec());
334
 
 
335
 
                // Send sound here
336
 
 
337
 
                if (ac && audiolayer) {
338
 
 
339
 
                    // _debug("Send sound");
340
 
                    // audiolayer->getMainBuffer()->flush(currentCall->getCallId());
341
 
 
342
 
                    audiolayer->getMainBuffer()->setInternalSamplingRate (ac->getClockRate());
343
 
 
344
 
                    int _mainBufferSampleRate = audiolayer->getMainBuffer()->getInternalSamplingRate();
345
 
 
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);
349
 
 
350
 
                    // available bytes inside ringbuffer
351
 
                    availBytesFromMic = audiolayer->getMainBuffer()->availForGet (currentCall->getCallId());
352
 
                    // We need packets full!
353
 
 
354
 
                    if (availBytesFromMic > maxBytesToGet) {
355
 
 
356
 
                        // take the lowest
357
 
                        bytesAvail = (availBytesFromMic < maxBytesToGet) ? availBytesFromMic : maxBytesToGet;
358
 
 
359
 
                        // Get bytes from micRingBuffer to data_from_mic
360
 
                        nbSample_ = audiolayer->getMainBuffer()->getData (micData, bytesAvail, 100, currentCall->getCallId()) / sizeof (SFLDataFormat);
361
 
 
362
 
 
363
 
                        // Store the number of samples for recording
364
 
                        nbSampleForRec_ = nbSample_;
365
 
 
366
 
 
367
 
                        if (ac->getClockRate() && (ac->getClockRate() != _mainBufferSampleRate)) {
368
 
 
369
 
                            // resample
370
 
                            nbSample_ = converter->downsampleData (micData , micDataConverted , (int) ac->getClockRate(), _mainBufferSampleRate, nbSample_);
371
 
 
372
 
                            // for the mono: range = 0 to IAX_FRAME2SEND * sizeof(int16)
373
 
                            compSize = ac->codecEncode (micDataEncoded, micDataConverted , nbSample_*sizeof (int16));
374
 
 
375
 
                        } else {
376
 
 
377
 
                            // for the mono: range = 0 to IAX_FRAME2SEND * sizeof(int16)
378
 
                            compSize = ac->codecEncode (micDataEncoded, micData, nbSample_*sizeof (int16));
379
 
 
380
 
                        }
381
 
 
382
 
                        // Send it out!
383
 
                        _mutexIAX.enterMutex();
384
 
 
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.");
389
 
                            }
390
 
                        }
391
 
 
392
 
                        _mutexIAX.leaveMutex();
393
 
 
394
 
                    }
395
 
                }
396
 
 
397
 
            }
398
 
 
399
 
        }
400
 
 
401
 
    }
402
 
}
403
 
 
404
 
 
405
 
IAXCall*
406
 
IAXVoIPLink::getIAXCall (const CallID& id)
407
 
{
408
 
    Call* call = getCall (id);
409
 
 
410
 
    if (call) {
411
 
        return dynamic_cast<IAXCall*> (call);
412
 
    }
413
 
 
414
 
    return NULL;
415
 
}
416
 
 
417
 
 
418
 
void
419
 
IAXVoIPLink::sendRegister (AccountID id UNUSED) throw(VoipLinkException)
420
 
{
421
 
    _debug ("IAX: Sending registration");
422
 
 
423
 
    IAXAccount *account = dynamic_cast<IAXAccount *> (getAccountPtr());
424
 
 
425
 
    if (!account) {
426
 
        throw VoipLinkException("Account is NULL in send register");
427
 
    }
428
 
 
429
 
    if (account->getHostname().empty()) {
430
 
        throw VoipLinkException("Account hostname is empty");
431
 
    }
432
 
 
433
 
    if (account->getUsername().empty()) {
434
 
        throw VoipLinkException("Account username is empty");
435
 
    }
436
 
 
437
 
    // lock
438
 
    _mutexIAX.enterMutex();
439
 
 
440
 
    // Always use a brand new session
441
 
    if (_regSession) {
442
 
        iax_destroy (_regSession);
443
 
    }
444
 
 
445
 
    _regSession = iax_session_new();
446
 
 
447
 
    if (!_regSession) {
448
 
        _debug ("IAX: Error when generating new session for register");
449
 
    } else {
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;
456
 
 
457
 
        account->setRegistrationState (Trying);
458
 
    }
459
 
 
460
 
    // unlock
461
 
    _mutexIAX.leaveMutex();
462
 
}
463
 
 
464
 
void
465
 
IAXVoIPLink::sendUnregister (AccountID id UNUSED) throw(VoipLinkException)
466
 
{
467
 
    _debug ("IAXVoipLink: Send unregister");
468
 
 
469
 
    IAXAccount *account = dynamic_cast<IAXAccount*> (getAccountPtr());
470
 
 
471
 
    if (!account) {
472
 
        throw VoipLinkException("Account is NULL in send unregister");
473
 
    }
474
 
 
475
 
    _mutexIAX.enterMutex();
476
 
 
477
 
    if (_regSession) {
478
 
        /** @todo Should send a REGREL in sendUnregister()... */
479
 
        //iax_send_regrel(); doesn't exist yet :)
480
 
        iax_destroy (_regSession);
481
 
        _regSession = NULL;
482
 
    }
483
 
 
484
 
    _mutexIAX.leaveMutex();
485
 
 
486
 
    _nextRefreshStamp = 0;
487
 
 
488
 
    account->setRegistrationState (Unregistered);
489
 
}
490
 
 
491
 
Call*
492
 
IAXVoIPLink::newOutgoingCall (const CallID& id, const std::string& toUrl) throw(VoipLinkException)
493
 
{
494
 
    IAXCall* call = new IAXCall (id, Call::Outgoing);
495
 
    call->setCodecMap (Manager::instance().getCodecDescriptorMap());
496
 
 
497
 
    if (call) {
498
 
        call->setPeerNumber (toUrl);
499
 
        call->initRecFileName (toUrl);
500
 
 
501
 
        if (iaxOutgoingInvite (call)) {
502
 
            call->setConnectionState (Call::Progressing);
503
 
            call->setState (Call::Active);
504
 
            addCall (call);
505
 
        } else {
506
 
            delete call;
507
 
            call = NULL;
508
 
        }
509
 
    }
510
 
 
511
 
    return call;
512
 
}
513
 
 
514
 
 
515
 
bool
516
 
IAXVoIPLink::answer (const CallID& id)
517
 
{
518
 
    IAXCall* call = getIAXCall (id);
519
 
    call->setCodecMap (Manager::instance().getCodecDescriptorMap());
520
 
 
521
 
    Manager::instance().addStream (call->getCallId());
522
 
 
523
 
    CHK_VALID_CALL;
524
 
 
525
 
    _mutexIAX.enterMutex();
526
 
    iax_answer (call->getSession());
527
 
    _mutexIAX.leaveMutex();
528
 
 
529
 
    call->setState (Call::Active);
530
 
    call->setConnectionState (Call::Connected);
531
 
 
532
 
    // Flush main buffer
533
 
    audiolayer->flushMain();
534
 
 
535
 
    return true;
536
 
}
537
 
 
538
 
bool
539
 
IAXVoIPLink::hangup (const CallID& id)
540
 
{
541
 
    _debug ("IAXVoIPLink: Hangup");
542
 
    IAXCall* call = getIAXCall (id);
543
 
    std::string reason = "Dumped Call";
544
 
    CHK_VALID_CALL;
545
 
 
546
 
    audiolayer->getMainBuffer()->unBindAll (call->getCallId());
547
 
 
548
 
    _mutexIAX.enterMutex();
549
 
 
550
 
    iax_hangup (call->getSession(), (char*) reason.c_str());
551
 
    _mutexIAX.leaveMutex();
552
 
    call->setSession (NULL);
553
 
 
554
 
    if (Manager::instance().isCurrentCall (id)) {
555
 
        // stop audio
556
 
        // audiolayer->stopStream();
557
 
    }
558
 
 
559
 
    removeCall (id);
560
 
    return true;
561
 
}
562
 
 
563
 
 
564
 
bool
565
 
IAXVoIPLink::peerHungup (const CallID& id)
566
 
{
567
 
    _debug ("IAXVoIPLink: Peer hung up");
568
 
    IAXCall* call = getIAXCall (id);
569
 
    std::string reason = "Dumped Call";
570
 
    CHK_VALID_CALL;
571
 
 
572
 
    audiolayer->getMainBuffer()->unBindAll (call->getCallId());
573
 
 
574
 
    _mutexIAX.enterMutex();
575
 
 
576
 
    _mutexIAX.leaveMutex();
577
 
    call->setSession (NULL);
578
 
 
579
 
    if (Manager::instance().isCurrentCall (id)) {
580
 
        // stop audio
581
 
        // audiolayer->stopStream();
582
 
    }
583
 
 
584
 
    removeCall (id);
585
 
    return true;
586
 
}
587
 
 
588
 
 
589
 
 
590
 
bool
591
 
IAXVoIPLink::onhold (const CallID& id)
592
 
{
593
 
    IAXCall* call = getIAXCall (id);
594
 
 
595
 
    CHK_VALID_CALL;
596
 
 
597
 
    audiolayer->getMainBuffer()->unBindAll (call->getCallId());
598
 
 
599
 
    //if (call->getState() == Call::Hold) { _debug("Call is already on hold"); return false; }
600
 
 
601
 
    _mutexIAX.enterMutex();
602
 
    iax_quelch_moh (call->getSession() , MUSIC_ONHOLD);
603
 
    _mutexIAX.leaveMutex();
604
 
 
605
 
    call->setState (Call::Hold);
606
 
    return true;
607
 
}
608
 
 
609
 
bool
610
 
IAXVoIPLink::offhold (const CallID& id)
611
 
{
612
 
    IAXCall* call = getIAXCall (id);
613
 
 
614
 
    CHK_VALID_CALL;
615
 
 
616
 
    Manager::instance().addStream (call->getCallId());
617
 
 
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);
624
 
    return true;
625
 
}
626
 
 
627
 
bool
628
 
IAXVoIPLink::transfer (const CallID& id, const std::string& to)
629
 
{
630
 
    IAXCall* call = getIAXCall (id);
631
 
 
632
 
    CHK_VALID_CALL;
633
 
 
634
 
    char callto[to.length() +1];
635
 
    strcpy (callto, to.c_str());
636
 
 
637
 
    _mutexIAX.enterMutex();
638
 
    iax_transfer (call->getSession(), callto);
639
 
    _mutexIAX.leaveMutex();
640
 
 
641
 
    return true;
642
 
 
643
 
    // should we remove it?
644
 
    // removeCall(id);
645
 
}
646
 
 
647
 
bool
648
 
IAXVoIPLink::attendedTransfer(const CallID& transferID, const CallID& targetID)
649
 
{
650
 
        // TODO implement attended transfer for IAX
651
 
        return false;
652
 
}
653
 
 
654
 
bool
655
 
IAXVoIPLink::refuse (const CallID& id)
656
 
{
657
 
    IAXCall* call = getIAXCall (id);
658
 
    std::string reason = "Call rejected manually.";
659
 
 
660
 
    CHK_VALID_CALL;
661
 
 
662
 
    _mutexIAX.enterMutex();
663
 
    iax_reject (call->getSession(), (char*) reason.c_str());
664
 
    _mutexIAX.leaveMutex();
665
 
 
666
 
    removeCall (id);
667
 
 
668
 
    return true;
669
 
}
670
 
 
671
 
 
672
 
bool
673
 
IAXVoIPLink::carryingDTMFdigits (const CallID& id, char code)
674
 
{
675
 
    IAXCall* call = getIAXCall (id);
676
 
 
677
 
    CHK_VALID_CALL;
678
 
 
679
 
    _mutexIAX.enterMutex();
680
 
    iax_send_dtmf (call->getSession(), code);
681
 
    _mutexIAX.leaveMutex();
682
 
 
683
 
    return true;
684
 
}
685
 
 
686
 
bool
687
 
IAXVoIPLink::sendTextMessage (sfl::InstantMessaging *module, const std::string& callID, const std::string& message, const std::string& from)
688
 
{
689
 
    IAXCall* call = getIAXCall (callID);
690
 
 
691
 
    CHK_VALID_CALL;
692
 
 
693
 
    // Must active the mutex for this session
694
 
    _mutexIAX.enterMutex();
695
 
 
696
 
    module->send_iax_message (call->getSession(), callID, message.c_str());
697
 
 
698
 
    // iax_send_text (call->getSession(), message.c_str());
699
 
    _mutexIAX.leaveMutex();
700
 
 
701
 
    return true;
702
 
}
703
 
 
704
 
 
705
 
std::string
706
 
IAXVoIPLink::getCurrentCodecName()
707
 
{
708
 
    IAXCall *call = NULL;
709
 
    AudioCodec *ac = NULL;
710
 
    std::string name = "";
711
 
 
712
 
    call = getIAXCall (Manager::instance().getCurrentCallId());
713
 
 
714
 
    if (call)
715
 
        ac = call->getCodecMap().getCodec (call->getAudioCodec());
716
 
 
717
 
    if (ac)
718
 
        name = ac->getCodecName();
719
 
 
720
 
    return name;
721
 
}
722
 
 
723
 
 
724
 
bool
725
 
IAXVoIPLink::iaxOutgoingInvite (IAXCall* call)
726
 
{
727
 
 
728
 
    struct iax_session *newsession;
729
 
    ost::MutexLock m (_mutexIAX);
730
 
    std::string username, strNum;
731
 
    char *lang=NULL;
732
 
    int wait, audio_format_preferred, audio_format_capability;
733
 
    IAXAccount *account;
734
 
 
735
 
    newsession = iax_session_new();
736
 
 
737
 
    if (!newsession) {
738
 
        _debug ("IAX Error: Can't make new session for a new call");
739
 
        return false;
740
 
    }
741
 
 
742
 
    call->setSession (newsession);
743
 
 
744
 
    account = dynamic_cast<IAXAccount*> (getAccountPtr());
745
 
    username = account->getUsername();
746
 
    strNum = username + ":" + account->getPassword() + "@" + account->getHostname() + "/" + call->getPeerNumber();
747
 
 
748
 
    wait = 0;
749
 
    /** @todo Make preference dynamic, and configurable */
750
 
    audio_format_preferred =  call->getFirstMatchingFormat (call->getSupportedFormat (getAccountID ()), getAccountID ());
751
 
    audio_format_capability = call->getSupportedFormat (getAccountID ());
752
 
 
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);
755
 
 
756
 
    return true;
757
 
}
758
 
 
759
 
 
760
 
IAXCall*
761
 
IAXVoIPLink::iaxFindCallBySession (struct iax_session* session)
762
 
{
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();
768
 
 
769
 
    while (iter != _callMap.end()) {
770
 
        call = dynamic_cast<IAXCall*> (iter->second);
771
 
 
772
 
        if (call && call->getSession() == session) {
773
 
            return call;
774
 
        }
775
 
 
776
 
        iter++;
777
 
    }
778
 
 
779
 
    return NULL; // not found
780
 
}
781
 
 
782
 
void
783
 
IAXVoIPLink::iaxHandleCallEvent (iax_event* event, IAXCall* call)
784
 
{
785
 
    // call should not be 0
786
 
    // note activity?
787
 
    //
788
 
    CallID id = call->getCallId();
789
 
 
790
 
    switch (event->etype) {
791
 
 
792
 
        case IAX_EVENT_HANGUP:
793
 
 
794
 
            if (Manager::instance().isCurrentCall (id)) {
795
 
                // stop audio
796
 
                // audiolayer->stopStream();
797
 
            }
798
 
 
799
 
            Manager::instance().peerHungupCall (id);
800
 
 
801
 
            /*
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();
809
 
             */
810
 
            removeCall (id);
811
 
            break;
812
 
 
813
 
        case IAX_EVENT_REJECT:
814
 
            //Manager::instance().peerHungupCall(id);
815
 
 
816
 
            if (Manager::instance().isCurrentCall (id)) {
817
 
                // stop audio
818
 
                // audiolayer->stopStream();
819
 
            }
820
 
 
821
 
            call->setConnectionState (Call::Connected);
822
 
 
823
 
            call->setState (Call::Error);
824
 
            Manager::instance().callFailure (id);
825
 
            removeCall (id);
826
 
            break;
827
 
 
828
 
        case IAX_EVENT_ACCEPT:
829
 
 
830
 
            // Call accepted over there by the computer, not the user yet.
831
 
            _debug ("IAX_EVENT_ACCEPT: codec format: ");
832
 
 
833
 
            if (event->ies.format) {
834
 
                printf ("%i", event->ies.format);
835
 
                call->setFormat (event->ies.format);
836
 
            } else {
837
 
                printf ("no codec format");
838
 
            }
839
 
 
840
 
            break;
841
 
 
842
 
        case IAX_EVENT_ANSWER:
843
 
 
844
 
            if (call->getConnectionState() != Call::Connected) {
845
 
 
846
 
                Manager::instance().addStream (call->getCallId());
847
 
 
848
 
                call->setConnectionState (Call::Connected);
849
 
                call->setState (Call::Active);
850
 
                // audiolayer->startStream();
851
 
 
852
 
                _debug ("IAX_EVENT_ANSWER: codec format: ");
853
 
 
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);
858
 
                }
859
 
 
860
 
                {
861
 
                    printf ("no codec format");
862
 
                }
863
 
 
864
 
                Manager::instance().peerAnsweredCall (id);
865
 
 
866
 
                // start audio here?
867
 
                audiolayer->startStream();
868
 
                audiolayer->flushMain();
869
 
            } else {
870
 
                // deja connecté ?
871
 
            }
872
 
 
873
 
            break;
874
 
 
875
 
        case IAX_EVENT_BUSY:
876
 
            call->setConnectionState (Call::Connected);
877
 
            call->setState (Call::Busy);
878
 
            Manager::instance().callBusy (id);
879
 
            removeCall (id);
880
 
            break;
881
 
 
882
 
        case IAX_EVENT_VOICE:
883
 
            //if (!audiolayer->isCaptureActive ())
884
 
            //  audiolayer->startStream ();
885
 
            // _debug("IAX_EVENT_VOICE: ");
886
 
            iaxHandleVoiceEvent (event, call);
887
 
            break;
888
 
 
889
 
        case IAX_EVENT_TEXT:
890
 
            Manager::instance ().incomingMessage (call->getCallId (), call->getPeerNumber(), std::string ( (const char*) event->data));
891
 
            break;
892
 
 
893
 
        case IAX_EVENT_RINGA:
894
 
            call->setConnectionState (Call::Ringing);
895
 
            Manager::instance().peerRingingCall (call->getCallId());
896
 
            break;
897
 
 
898
 
        case IAX_IE_MSGCOUNT:
899
 
            break;
900
 
 
901
 
        case IAX_EVENT_PONG:
902
 
            break;
903
 
 
904
 
        case IAX_EVENT_URL:
905
 
 
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));
910
 
                }
911
 
            }
912
 
 
913
 
            break;
914
 
 
915
 
        case IAX_EVENT_TIMEOUT:
916
 
            break;
917
 
 
918
 
        case IAX_EVENT_TRANSFER:
919
 
            _debug ("IAX_EVENT_TRANSFER");
920
 
 
921
 
            if (call->getConnectionState() != Call::Connected) {
922
 
 
923
 
                Manager::instance().addStream (call->getCallId());
924
 
 
925
 
                call->setConnectionState (Call::Connected);
926
 
                call->setState (Call::Active);
927
 
                // audiolayer->startStream();
928
 
 
929
 
                _debug ("IAX_EVENT_ANSWER: codec format: ");
930
 
 
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);
935
 
                }
936
 
 
937
 
                {
938
 
                    printf ("no codec format");
939
 
                }
940
 
 
941
 
                Manager::instance().peerAnsweredCall (id);
942
 
 
943
 
                // start audio here?
944
 
                audiolayer->startStream();
945
 
                audiolayer->flushMain();
946
 
            } else {
947
 
                // deja connecté ?
948
 
            }
949
 
 
950
 
            break;
951
 
 
952
 
        default:
953
 
            _debug ("iaxHandleCallEvent: Unknown event type (in call event): %d", event->etype);
954
 
 
955
 
    }
956
 
}
957
 
 
958
 
 
959
 
/* Handle audio event, VOICE packet received */
960
 
void
961
 
IAXVoIPLink::iaxHandleVoiceEvent (iax_event* event, IAXCall* call)
962
 
{
963
 
 
964
 
    unsigned char *data;
965
 
    unsigned int size, max, nbInt16;
966
 
    int expandedSize, nbSample_;
967
 
    AudioCodec *ac;
968
 
 
969
 
    if (!call)
970
 
        return;
971
 
 
972
 
    if (!event->datalen) {
973
 
        // Skip this empty packet.
974
 
        //_debug("IAX: Skipping empty jitter-buffer interpolated packet");
975
 
        return;
976
 
    }
977
 
 
978
 
    ac = call->getCodecMap ().getCodec (call->getAudioCodec ());
979
 
 
980
 
    if (!ac)
981
 
        return;
982
 
 
983
 
    if (audiolayer) {
984
 
 
985
 
        audiolayer->getMainBuffer ()->setInternalSamplingRate (ac->getClockRate ());
986
 
 
987
 
        // If we receive datalen == 0, some things of the jitter buffer in libiax2/iax.c
988
 
        // were triggered
989
 
 
990
 
        int _mainBufferSampleRate = audiolayer->getMainBuffer()->getInternalSamplingRate();
991
 
 
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.
995
 
 
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);
999
 
        }
1000
 
 
1001
 
        //_debug("Receive: len=%d, format=%d, _receiveDataDecoded=%p", event->datalen, call->getFormat(), _receiveDataDecoded);
1002
 
        // ac = call->getCodecMap().getCodec (call -> getAudioCodec());
1003
 
 
1004
 
        data = (unsigned char*) event->data;
1005
 
 
1006
 
        size   = event->datalen;
1007
 
 
1008
 
        // Decode data with relevant codec
1009
 
        max = (int) (ac->getClockRate() * audiolayer->getFrameSize() / 1000);
1010
 
 
1011
 
        if (size > max) {
1012
 
            _debug ("The size %d is bigger than expected %d. Packet cropped. Ouch!", size, max);
1013
 
            size = max;
1014
 
        }
1015
 
 
1016
 
        expandedSize = ac->codecDecode (spkrDataDecoded , data , size);
1017
 
 
1018
 
        nbInt16      = expandedSize/sizeof (int16);
1019
 
 
1020
 
        if (nbInt16 > max) {
1021
 
            _debug ("We have decoded an IAX VOICE packet larger than expected: %i VS %i. Cropping.", nbInt16, max);
1022
 
            nbInt16 = max;
1023
 
        }
1024
 
 
1025
 
        nbSample_ = nbInt16;
1026
 
 
1027
 
        // test if resampling is required
1028
 
 
1029
 
        if (ac->getClockRate() && (ac->getClockRate() != _mainBufferSampleRate)) {
1030
 
 
1031
 
            // resample
1032
 
            nbInt16 = converter->upsampleData (spkrDataDecoded, spkrDataConverted, ac->getClockRate(), _mainBufferSampleRate, nbSample_);
1033
 
 
1034
 
            /* Write the data to the mic ring buffer */
1035
 
            audiolayer->getMainBuffer()->putData (spkrDataConverted, nbInt16 * sizeof (SFLDataFormat), 100, call->getCallId());
1036
 
 
1037
 
        } else {
1038
 
 
1039
 
            /* Write the data to the mic ring buffer */
1040
 
            audiolayer->getMainBuffer()->putData (spkrDataDecoded, nbInt16 * sizeof (SFLDataFormat), 100, call->getCallId());
1041
 
 
1042
 
        }
1043
 
 
1044
 
    } else {
1045
 
        _debug ("IAX: incoming audio, but no sound card open");
1046
 
    }
1047
 
 
1048
 
}
1049
 
 
1050
 
/**
1051
 
 * Handle the registration process
1052
 
 */
1053
 
void
1054
 
IAXVoIPLink::iaxHandleRegReply (iax_event* event)
1055
 
{
1056
 
 
1057
 
    std::string account_id;
1058
 
    IAXAccount *account;
1059
 
 
1060
 
    account_id = getAccountID();
1061
 
    account = dynamic_cast<IAXAccount *> (Manager::instance().getAccount (account_id));
1062
 
 
1063
 
    if (event->etype == IAX_EVENT_REGREJ) {
1064
 
        /* Authentication failed! */
1065
 
        _mutexIAX.enterMutex();
1066
 
        iax_destroy (_regSession);
1067
 
        _mutexIAX.leaveMutex();
1068
 
        _regSession = NULL;
1069
 
        // Update the account registration state
1070
 
        account->setRegistrationState (ErrorAuth);
1071
 
    }
1072
 
 
1073
 
    else if (event->etype == IAX_EVENT_REGACK) {
1074
 
        /* Authentication succeeded */
1075
 
        _mutexIAX.enterMutex();
1076
 
 
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);
1084
 
 
1085
 
        iax_destroy (_regSession);
1086
 
        _mutexIAX.leaveMutex();
1087
 
        _regSession = NULL;
1088
 
 
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);
1093
 
    }
1094
 
}
1095
 
 
1096
 
int IAXVoIPLink::processIAXMsgCount (int msgcount)
1097
 
{
1098
 
 
1099
 
    // IAX sends the message count under a specific format:
1100
 
    //                       1
1101
 
    //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
1102
 
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1103
 
    //  |      0x18     |      0x02     |
1104
 
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1105
 
    //  |  Old messages |  New messages |
1106
 
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1107
 
 
1108
 
    // For now we just need the new messages informations.
1109
 
    // Thus:
1110
 
    // 0 <= msgcount <= 255   => msgcount new messages, 0 old messages
1111
 
    // msgcount >= 256        => msgcount/256 old messages , msgcount%256 new messages (RULES)
1112
 
 
1113
 
    return msgcount%256;
1114
 
 
1115
 
}
1116
 
 
1117
 
 
1118
 
void
1119
 
IAXVoIPLink::iaxHandlePrecallEvent (iax_event* event)
1120
 
{
1121
 
    IAXCall* call = NULL;
1122
 
    CallID   id;
1123
 
    std::string reason = "Error ringing user.";
1124
 
 
1125
 
    switch (event->etype) {
1126
 
 
1127
 
        case IAX_EVENT_REGACK:
1128
 
 
1129
 
        case IAX_EVENT_REGREJ:
1130
 
            _debug ("IAX Registration Event in a pre-call setup");
1131
 
            break;
1132
 
 
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");
1137
 
            break;
1138
 
 
1139
 
        case IAX_EVENT_CONNECT:
1140
 
            // We've got an incoming call! Yikes!
1141
 
            _debug ("> IAX_EVENT_CONNECT (receive)");
1142
 
 
1143
 
            id = Manager::instance().getNewCallID();
1144
 
 
1145
 
            call = new IAXCall (id, Call::Incoming);
1146
 
 
1147
 
            if (!call) {
1148
 
                _debug ("! IAX Failure: unable to create an incoming call");
1149
 
                return;
1150
 
            }
1151
 
 
1152
 
            // Setup the new IAXCall
1153
 
            // Associate the call to the session.
1154
 
            call->setSession (event->session);
1155
 
 
1156
 
            // setCallAudioLocal(call);
1157
 
            call->setCodecMap (Manager::instance().getCodecDescriptorMap());
1158
 
 
1159
 
            call->setConnectionState (Call::Progressing);
1160
 
 
1161
 
 
1162
 
            if (event->ies.calling_number)
1163
 
                call->setPeerNumber (std::string (event->ies.calling_number));
1164
 
 
1165
 
            if (event->ies.calling_name)
1166
 
                call->setPeerName (std::string (event->ies.calling_name));
1167
 
 
1168
 
            // if peerNumber exist append it to the name string
1169
 
            call->initRecFileName (std::string (event->ies.calling_number));
1170
 
 
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 */
1174
 
 
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 ());
1179
 
 
1180
 
                // Priority to remote's suggestion. In case it's a forwarding, no transcoding
1181
 
                // will be needed from the server, thus less latency.
1182
 
 
1183
 
                if (pref_format)
1184
 
                    format = pref_format;
1185
 
 
1186
 
                iax_accept (event->session, format);
1187
 
 
1188
 
                iax_ring_announce (event->session);
1189
 
 
1190
 
                addCall (call);
1191
 
 
1192
 
                // Set the audio codec now, to avoid non-set codec problem later
1193
 
                call->setFormat (format);
1194
 
 
1195
 
            } else {
1196
 
                // reject call, unable to add it
1197
 
                iax_reject (event->session, (char*) reason.c_str());
1198
 
 
1199
 
                delete call;
1200
 
                call = NULL;
1201
 
            }
1202
 
 
1203
 
            break;
1204
 
 
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);
1211
 
            removeCall (id);
1212
 
            break;
1213
 
 
1214
 
        case IAX_EVENT_TIMEOUT: // timeout for an unknown session
1215
 
 
1216
 
            break;
1217
 
 
1218
 
        case IAX_IE_MSGCOUNT:
1219
 
            break;
1220
 
 
1221
 
        default:
1222
 
            _debug ("IAXVoIPLink::iaxHandlePrecallEvent: Unknown event type (in precall): %d", event->etype);
1223
 
    }
1224
 
 
1225
 
}
1226
 
 
1227
 
void IAXVoIPLink::updateAudiolayer (void)
1228
 
{
1229
 
    _mutexIAX.enterMutex();
1230
 
    audiolayer = NULL;
1231
 
    audiolayer = Manager::instance().getAudioDriver();
1232
 
    _mutexIAX.leaveMutex();
1233
 
}
1234