sipvoiplink.cpp 83.3 KB
Newer Older
jpbl's avatar
jpbl committed
1
/*
2 3 4
 *  Copyright (C) 2004-2009 Savoir-Faire Linux inc.
 *
 *  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
5
 *  Author: Yun Liu <yun.liu@savoirfairelinux.com>
jpbl's avatar
jpbl committed
6 7 8
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
9
 *  the Free Software Foundation; either version 3 of the License, or
jpbl's avatar
jpbl committed
10 11 12 13 14 15 16 17 18 19 20
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
21

jpbl's avatar
jpbl committed
22 23
#include "sipvoiplink.h"
#include "eventthread.h"
yanmorin's avatar
yanmorin committed
24
#include "sipcall.h"
Emmanuel Milou's avatar
Emmanuel Milou committed
25
#include "sipaccount.h"
26
#include "audio/audiortp.h"
27
#include "pjsip/sip_endpoint.h"
28

29 30 31
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
32

33 34
#define CAN_REINVITE        1

pierre-luc's avatar
pierre-luc committed
35
static char * invitationStateMap[] = { 
36 37 38 39 40 41 42
(char*) "PJSIP_INV_STATE_NULL", 
(char*) "PJSIP_INV_STATE_CALLING", 
(char*) "PJSIP_INV_STATE_INCOMING", 
(char*) "PJSIP_INV_STATE_EARLY", 
(char*) "PJSIP_INV_STATE_CONNECTING", 
(char*) "PJSIP_INV_STATE_CONFIRMED", 
(char*) "PJSIP_INV_STATE_DISCONNECTED" 
pierre-luc's avatar
pierre-luc committed
43 44 45
};
                                       
static char * transactionStateMap[] = {
46 47 48 49 50 51 52 53 54
(char*) "PJSIP_TSX_STATE_NULL" ,	
(char*) "PJSIP_TSX_STATE_CALLING", 	
(char*) "PJSIP_TSX_STATE_TRYING", 	
(char*) "PJSIP_TSX_STATE_PROCEEDING", 	
(char*) "PJSIP_TSX_STATE_COMPLETED", 	
(char*) "PJSIP_TSX_STATE_CONFIRMED", 	
(char*) "PJSIP_TSX_STATE_TERMINATED", 	
(char*) "PJSIP_TSX_STATE_DESTROYED", 	
(char*) "PJSIP_TSX_STATE_MAX" 
pierre-luc's avatar
pierre-luc committed
55 56
};

57 58 59 60 61
struct result
{
    pj_status_t             status;
    pjsip_server_addresses  servers;
};
Alexandre Savard's avatar
Alexandre Savard committed
62

63
const pj_str_t STR_USER_AGENT = { (char*) "User-Agent", 10 };
64

65
/**************** EXTERN VARIABLES AND FUNCTIONS (callbacks) **************************/
jpbl's avatar
jpbl committed
66

67 68 69 70 71 72
/*
 * Retrieve the SDP of the peer contained in the offer
 *
 * @param rdata The request data
 * @param r_sdp The pjmedia_sdp_media to stock the remote SDP
 */
73
void get_remote_sdp_from_offer (pjsip_rx_data *rdata, pjmedia_sdp_session** r_sdp);
74

75 76
int getModId();

77
/**
78 79 80 81 82
 * Set audio (SDP) configuration for a call
 * localport, localip, localexternalport
 * @param call a SIPCall valid pointer
 * @return bool True
 */
83
bool setCallAudioLocal (SIPCall* call, std::string localIP, bool stun, std::string server);
84

85
void handle_incoming_options (pjsip_rx_data *rxdata);
86

87
std::string fetch_header_value (pjsip_msg *msg, std::string field);
88

89 90 91
/*
 *  The global pool factory
 */
92
pj_caching_pool _cp;
93 94 95 96

/*
 * The pool to allocate memory
 */
97
pj_pool_t *_pool;
98 99 100 101

/*
 *	The SIP endpoint
 */
102
pjsip_endpoint *_endpt;
103 104 105 106

/*
 *	The SIP module
 */
107
pjsip_module _mod_ua;
108 109 110 111

/*
 * Thread related
 */
112 113 114
pj_thread_t *thread;
pj_thread_desc desc;

115 116 117 118 119
/*
 * Url hook instance
 */
UrlHook *urlhook;

120 121 122
/**
 * Get the number of voicemail waiting in a SIP message
 */
123
void set_voicemail_info (AccountID account, pjsip_msg_body *body);
124

125
// Documentated from the PJSIP Developer's Guide, available on the pjsip website/
126

127 128 129 130 131 132 133
/*
 * Session callback
 * Called when the invite session state has changed.
 *
 * @param	inv	A pointer on a pjsip_inv_session structure
 * @param	e	A pointer on a pjsip_event structure
 */
134
void call_on_state_changed (pjsip_inv_session *inv, pjsip_event *e);
135 136 137 138 139 140 141 142

/*
 * Session callback
 * Called after SDP offer/answer session has completed.
 *
 * @param	inv	A pointer on a pjsip_inv_session structure
 * @param	status	A pj_status_t structure
 */
143
void call_on_media_update (pjsip_inv_session *inv UNUSED, pj_status_t status UNUSED);
144 145

/*
146
 * Called when the invite usage module has created a new dialog and invite
147 148 149 150 151
 * because of forked outgoing request.
 *
 * @param	inv	A pointer on a pjsip_inv_session structure
 * @param	e	A pointer on a pjsip_event structure
 */
152
void call_on_forked (pjsip_inv_session *inv, pjsip_event *e);
153 154 155 156 157 158 159 160 161 162

/*
 * Session callback
 * Called whenever any transactions within the session has changed their state.
 * Useful to monitor the progress of an outgoing request.
 *
 * @param	inv	A pointer on a pjsip_inv_session structure
 * @param	tsx	A pointer on a pjsip_transaction structure
 * @param	e	A pointer on a pjsip_event structure
 */
163
void call_on_tsx_changed (pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_event *e);
164

165
void on_rx_offer (pjsip_inv_session *inv, const pjmedia_sdp_session *offer);
166

167 168 169
/*
 * Registration callback
 */
170
void regc_cb (struct pjsip_regc_cbparam *param);
171

172 173 174 175 176
/*
 * DNS Callback used in workaround for bug #1852
 */
static void dns_cb(pj_status_t status, void *token, const struct pjsip_server_addresses *addr);

177 178 179 180 181
/*
 * Called to handle incoming requests outside dialogs
 * @param   rdata
 * @return  pj_bool_t
 */
182
pj_bool_t mod_on_rx_request (pjsip_rx_data *rdata);
183 184 185 186 187 188

/*
 * Called to handle incoming response
 * @param	rdata
 * @return	pj_bool_t
 */
189
pj_bool_t mod_on_rx_response (pjsip_rx_data *rdata UNUSED) ;
190 191 192 193

/*
 * Transfer callbacks
 */
194 195 196
void xfer_func_cb (pjsip_evsub *sub, pjsip_event *event);
void xfer_svr_cb (pjsip_evsub *sub, pjsip_event *event);
void onCallTransfered (pjsip_inv_session *inv, pjsip_rx_data *rdata);
197 198 199 200 201

/*************************************************************************************************/

SIPVoIPLink* SIPVoIPLink::_instance = NULL;

202

203 204 205 206 207 208 209 210 211 212
SIPVoIPLink::SIPVoIPLink (const AccountID& accountID)
        : VoIPLink (accountID)
        , _nbTryListenAddr (2)   // number of times to try to start SIP listener
        , _stunServer ("")
        , _localExternAddress ("")
        , _localExternPort (0)
        , _audiortp (new AudioRtp())
        ,_regPort (DEFAULT_SIP_PORT)
        , _useStun (false)
        , _clients (0)
jpbl's avatar
jpbl committed
213
{
214 215
    // to get random number for RANDOM_PORT
    srand (time (NULL));
216

217
    urlhook = new UrlHook ();
218

219 220
    /* Start pjsip initialization step */
    init();
yanmorin's avatar
yanmorin committed
221
}
jpbl's avatar
jpbl committed
222

yanmorin's avatar
yanmorin committed
223 224
SIPVoIPLink::~SIPVoIPLink()
{
225
    terminate();
226 227
}

228
SIPVoIPLink* SIPVoIPLink::instance (const AccountID& id)
229 230
{

231 232 233
    if (!_instance) {
        _instance = new SIPVoIPLink (id);
    }
234

235
    return _instance;
yanmorin's avatar
yanmorin committed
236 237
}

238
void SIPVoIPLink::decrementClients (void)
239
{
240 241 242 243 244 245
    _clients--;

    if (_clients == 0) {
        terminate();
        SIPVoIPLink::_instance=NULL;
    }
246
}
247 248

bool SIPVoIPLink::init()
yanmorin's avatar
yanmorin committed
249
{
250 251 252
    if (initDone())
        return false;

253 254
    _regPort = Manager::instance().getSipPort();
    
255 256
    /* Instanciate the C++ thread */
    _evThread = new EventThread (this);
257

258 259
    /* Initialize the pjsip library */
    pjsip_init();
260

261
    initDone (true);
262

263
    return true;
jpbl's avatar
jpbl committed
264 265
}

266
void
yanmorin's avatar
yanmorin committed
267 268
SIPVoIPLink::terminate()
{
269 270 271 272 273
    if (_evThread) {
        delete _evThread;
        _evThread = NULL;
    }

274

275 276 277 278
    /* Clean shutdown of pjsip library */
    if (initDone()) {
        pjsip_shutdown();
    }
279

280
    initDone (false);
jpbl's avatar
jpbl committed
281 282
}

283
void
yanmorin's avatar
yanmorin committed
284
SIPVoIPLink::terminateSIPCall()
jpbl's avatar
jpbl committed
285
{
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
    ost::MutexLock m (_callMapMutex);
    CallMap::iterator iter = _callMap.begin();
    SIPCall *call;

    while (iter != _callMap.end()) {
        call = dynamic_cast<SIPCall*> (iter->second);

        if (call) {
            // terminate the sip call
            delete call;
            call = 0;
        }

        iter++;
    }

    _callMap.clear();
jpbl's avatar
jpbl committed
303 304
}

305
void
306
SIPVoIPLink::terminateOneCall (const CallID& id)
Emmanuel Milou's avatar
Emmanuel Milou committed
307
{
308

309 310 311 312 313 314 315
    SIPCall *call = getSIPCall (id);

    if (call) {
        // terminate the sip call
        delete call;
        call = 0;
    }
Emmanuel Milou's avatar
Emmanuel Milou committed
316 317
}

318
void get_remote_sdp_from_offer (pjsip_rx_data *rdata, pjmedia_sdp_session** r_sdp)
319
{
320

321 322 323 324 325 326 327 328
    pjmedia_sdp_session *sdp;
    pjsip_msg *msg;
    pjsip_msg_body *body;

    // Get the message
    msg = rdata->msg_info.msg;
    // Get the body message
    body = msg->body;
329

330
    // Parse the remote request to get the sdp session
331

332 333 334 335
    if (body) {
        pjmedia_sdp_parse (rdata->tp_info.pool, (char*) body->data, body->len, &sdp);
        *r_sdp = sdp;
    }
336

337 338
    else
        *r_sdp = NULL;
339
}
Emmanuel Milou's avatar
Emmanuel Milou committed
340

341

342
std::string SIPVoIPLink::get_useragent_name (void)
343
{
344 345 346
    std::ostringstream  useragent;
    useragent << PROGNAME << "/" << SFLPHONED_VERSION;
    return useragent.str();
347 348
}

349
void
yanmorin's avatar
yanmorin committed
350
SIPVoIPLink::getEvent()
jpbl's avatar
jpbl committed
351
{
352 353 354
    // We have to register the external thread so it could access the pjsip framework
    if (!pj_thread_is_registered())
        pj_thread_register (NULL, desc, &thread);
yanmorin's avatar
yanmorin committed
355

356 357 358 359
    // PJSIP polling
    pj_time_val timeout = {0, 10};

    pjsip_endpt_handle_events (_endpt, &timeout);
360

361
}
362

363
int SIPVoIPLink::sendRegister (AccountID id)
364
{
365 366
    int expire_value;
    char contactTmp[256];
367 368
    
    pj_status_t status;
369 370
    pj_str_t svr, aor, contact, useragent;
    pjsip_tx_data *tdata;
371 372
    pjsip_host_info destination;
    
373
    std::string tmp, hostname, username, password;
374
    SIPAccount *account = NULL;
375 376 377
    pjsip_regc *regc;
    pjsip_generic_string_hdr *h;
    pjsip_hdr hdr_list;
378

379
    account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (id));
380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
    if(account == NULL) {
        _debug("In sendRegister: account is null");
        return false; 
    }
    
    if(account->isResolveOnce()) {
        struct result result;
        destination.type = PJSIP_TRANSPORT_UNSPECIFIED;
        destination.flag = pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_UNSPECIFIED);    
        destination.addr.host = pj_str(const_cast<char*> ((account->getHostname()).c_str()));
        destination.addr.port = 0;
        
        result.status = 0x12345678;
        
        pjsip_endpt_resolve(_endpt, _pool, &destination, &result, &dns_cb);
        
        /* The following magic number and construct are inspired from dns_test.c
         * in test-pjsip directory.
         */
        while (result.status == 0x12345678) {
            pj_time_val timeout = { 1, 0 };
            pjsip_endpt_handle_events(_endpt, &timeout);
            _debug("status : %d\n", result.status);	
        }
        
        if(result.status != PJ_SUCCESS) {
            _debug("Failed to resolve hostname only once."
                   " Default resolver will be used on"
                   " hostname for all requests.\n");
        } else {
            _debug("%d servers where obtained from name resolution.\n", result.servers.count);
            char addr_buf[80];
            
            pj_sockaddr_print((pj_sockaddr_t*) &result.servers.entry[0].addr, addr_buf, sizeof(addr_buf), 3);
            account->setHostname(addr_buf);
        }
    } 
    
418 419
    hostname = account->getHostname();
    username = account->getUsername();
420 421
    password = account->getPassword(); 
    
422
    _mutexSIP.enterMutex();
423

424 425 426 427 428 429 430 431
    /* Get the client registration information for this particular account */
    regc = account->getRegistrationInfo();
    /* TODO If the registration already exists, delete it */
    /*if(regc) {
        status = pjsip_regc_destroy(regc);
        regc = NULL;
        PJ_ASSERT_RETURN( status == PJ_SUCCESS, 1 );
    }*/
432

433
    account->setRegister (true);
434

435
    /* Set the expire value of the message from the config file */
436 437 438 439 440
    istringstream stream(account->getRegistrationExpire());
    stream >> expire_value;
    if(!expire_value) {
        expire_value = PJSIP_REGC_EXPIRATION_NOT_SPECIFIED;
    }
441

442 443
    /* Update the state of the voip link */
    account->setRegistrationState (Trying);
444

445 446 447 448 449 450
    if (!validStunServer) {
        account->setRegistrationState (ErrorExistStun);
        account->setRegister (false);
        _mutexSIP.leaveMutex();
        return false;
    }
451

452 453
    /* Create the registration according to the account ID */
    status = pjsip_regc_create (_endpt, (void*) account, &regc_cb, &regc);
Alexandre Savard's avatar
Alexandre Savard committed
454

455 456 457 458 459
    if (status != PJ_SUCCESS) {
        _debug ("UserAgent: Unable to create regc.\n");
        _mutexSIP.leaveMutex();
        return false;
    }
460

461
    tmp = "sip:" + hostname;
Alexandre Savard's avatar
Alexandre Savard committed
462

463
    pj_strdup2 (_pool, &svr, tmp.data());
464

465 466 467
    // tmp = "<sip:" + username + "@" + hostname + ";transport=tls>";
    tmp = "<sip:" + username + "@" + hostname + ">";
    pj_strdup2 (_pool, &aor, tmp.data());
468

469 470 471 472
    _debug ("<sip:%s@%s:%d>\n", username.data(), _localExternAddress.data(), _localExternPort);
    sprintf (contactTmp, "<sip:%s@%s:%d>", username.data(), _localExternAddress.data(), _localExternPort);
    pj_strdup2 (_pool, &contact, contactTmp);
    account->setContact (contactTmp);
473

474
    status = pjsip_regc_init (regc, &svr, &aor, &aor, 1, &contact, expire_value);   //timeout);
475

476 477 478 479 480
    if (status != PJ_SUCCESS) {
        _debug ("UserAgent: Unable to initialize regc. %d\n", status);   //, regc->str_srv_url.ptr);
        _mutexSIP.leaveMutex();
        return false;
    }
481

482
    pjsip_cred_info *cred = account->getCredInfo();
483

484 485
    if (!cred)
        cred = new pjsip_cred_info();
486

487
    pj_bzero (cred, sizeof (pjsip_cred_info));
488

489
    pj_strdup2 (_pool, &cred->username, username.data());
490

491
    cred->data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
492

493
    pj_strdup2 (_pool, &cred->data, password.data());
494

495
    pj_strdup2 (_pool, &cred->realm, "*");
496

497
    pj_strdup2 (_pool, &cred->scheme, "digest");
498

499
    pjsip_regc_set_credentials (regc, 1, cred);
500

501
    account->setCredInfo (cred);
502

503 504
    // Add User-Agent Header
    pj_list_init (&hdr_list);
jpbl's avatar
jpbl committed
505

506
    useragent = pj_str ( (char*) get_useragent_name ().c_str());
507

508
    h = pjsip_generic_string_hdr_create (_pool, &STR_USER_AGENT, &useragent);
509

510
    pj_list_push_back (&hdr_list, (pjsip_hdr*) h);
511

512
    pjsip_regc_add_headers (regc, &hdr_list);
yanmorin's avatar
yanmorin committed
513

514
    status = pjsip_regc_register (regc, PJ_TRUE, &tdata);
jpbl's avatar
jpbl committed
515

516 517 518 519 520 521 522
    if (status != PJ_SUCCESS) {
        _debug ("UserAgent: Unable to register regc.\n");
        _mutexSIP.leaveMutex();
        return false;
    }

    status = pjsip_regc_send (regc, tdata);
523

524 525 526 527 528
    if (status != PJ_SUCCESS) {
        _debug ("UserAgent: Unable to send regc request.\n");
        _mutexSIP.leaveMutex();
        return false;
    }
529

530
    _mutexSIP.leaveMutex();
531

532
    account->setRegistrationInfo (regc);
533

534
    return true;
535 536
}

537 538
int
SIPVoIPLink::sendUnregister (AccountID id)
539
{
540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561
    pj_status_t status = 0;
    pjsip_tx_data *tdata = NULL;
    SIPAccount *account;
    pjsip_regc *regc;

    account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (id));
    regc = account->getRegistrationInfo();

    if (!account->isRegister()) {
        account->setRegistrationState (Unregistered);
        return true;
    }

    if (regc) {
        status = pjsip_regc_unregister (regc, &tdata);

        if (status != PJ_SUCCESS) {
            _debug ("UserAgent: Unable to unregister regc.\n");
            return false;
        }

        status = pjsip_regc_send (regc, tdata);
562

563 564 565 566 567 568 569 570
        if (status != PJ_SUCCESS) {
            _debug ("UserAgent: Unable to send regc request.\n");
            return false;
        }
    } else {
        _debug ("UserAgent: regc is null!\n");
        return false;
    }
571

572 573
    //account->setRegistrationInfo(regc);
    account->setRegister (false);
574

575
    return true;
jpbl's avatar
jpbl committed
576 577
}

578 579
Call*
SIPVoIPLink::newOutgoingCall (const CallID& id, const std::string& toUrl)
jpbl's avatar
jpbl committed
580
{
581 582
    Account* account;
    pj_status_t status;
jpbl's avatar
jpbl committed
583

584
    SIPCall* call = new SIPCall (id, Call::Outgoing, _pool);
585

586 587
    if (call) {
        account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (Manager::instance().getAccountFromCall (id)));
588

589 590 591 592 593 594 595 596
        if (!account) {
            _debug ("Error retrieving the account to the make the call with\n");
            call->setConnectionState (Call::Disconnected);
            call->setState (Call::Error);
            delete call;
            call=0;
            return call;
        }
597

598
        call->setPeerNumber (getSipTo (toUrl, account->getHostname()));
599

600
        setCallAudioLocal (call, getLocalIPAddress(), useStun(), getStunServer());
601

602
        try {
pierre-luc's avatar
pierre-luc committed
603
            _debug ("Creating new rtp session in newOutgoingCall\n");
604 605 606 607 608 609
            _audiortp->createNewSession (call);
        } catch (...) {
            _debug ("Failed to create rtp thread from newOutGoingCall\n");
        }

        call->initRecFileName();
610

611 612 613 614
        _debug ("Try to make a call to: %s with call ID: %s\n", toUrl.data(), id.data());
        // Building the local SDP offer
        call->getLocalSDP()->set_ip_address (getLocalIP());
        status = call->getLocalSDP()->create_initial_offer();
615

616 617 618 619 620
        if (status != PJ_SUCCESS) {
            delete call;
            call=0;
            return call;
        }
621

622 623 624 625 626 627 628 629 630
        if (SIPOutgoingInvite (call)) {
            call->setConnectionState (Call::Progressing);
            call->setState (Call::Active);
            addCall (call);
        } else {
            delete call;
            call = 0;
        }
    }
jpbl's avatar
jpbl committed
631

632 633
    return call;
}
634

635
bool
636
SIPVoIPLink::answer (const CallID& id)
jpbl's avatar
jpbl committed
637
{
638 639 640 641 642
    SIPCall *call;
    pj_status_t status;
    pjsip_tx_data *tdata;
    Sdp *local_sdp;
    pjsip_inv_session *inv_session;
jpbl's avatar
jpbl committed
643

644
    _debug ("SIPVoIPLink::answer: start answering \n");
645

646
    call = getSIPCall (id);
647

648 649 650 651
    if (call==0) {
        _debug ("! SIP Failure: SIPCall doesn't exists\n");
        return false;
    }
652

653
    local_sdp = call->getLocalSDP();
654

655 656 657 658 659
    try {
        _audiortp->createNewSession (call);
    } catch (...) {
        _debug ("Failed to create rtp thread from answer\n");
    }
660

661
    inv_session = call->getInvSession();
662

663
    status = local_sdp->start_negociation ();
jpbl's avatar
jpbl committed
664

665
    if (status == PJ_SUCCESS) {
jpbl's avatar
jpbl committed
666

667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690
        _debug ("SIPVoIPLink::answer:UserAgent: Negociation success! : call %s \n", call->getCallId().c_str());
        // Create and send a 200(OK) response
        status = pjsip_inv_answer (inv_session, PJSIP_SC_OK, NULL, NULL, &tdata);
        PJ_ASSERT_RETURN (status == PJ_SUCCESS, 1);
        status = pjsip_inv_send_msg (inv_session, tdata);
        PJ_ASSERT_RETURN (status == PJ_SUCCESS, 1);

        call->setConnectionState (Call::Connected);
        call->setState (Call::Active);

        return true;
    } else {
        // Create and send a 488/Not acceptable here
        // because the SDP negociation failed
        status = pjsip_inv_answer (inv_session, PJSIP_SC_NOT_ACCEPTABLE_HERE, NULL, NULL,
                                   &tdata);
        PJ_ASSERT_RETURN (status == PJ_SUCCESS, 1);
        status = pjsip_inv_send_msg (inv_session, tdata);
        PJ_ASSERT_RETURN (status == PJ_SUCCESS, 1);

        // Terminate the call
        _debug ("SIPVoIPLink::answer: fail terminate call %s \n",call->getCallId().c_str());
        terminateOneCall (call->getCallId());
        removeCall (call->getCallId());
691
        _audiortp->closeRtpSession ();
692 693
        return false;
    }
694 695
}

696
bool
697
SIPVoIPLink::hangup (const CallID& id)
jpbl's avatar
jpbl committed
698
{
699 700 701
    pj_status_t status;
    pjsip_tx_data *tdata = NULL;
    SIPCall* call;
702

703
    call = getSIPCall (id);
704

705 706 707 708
    if (call==0) {
        _debug ("! SIP Error: Call doesn't exist\n");
        return false;
    }
yanmorin's avatar
yanmorin committed
709

710 711
    // User hangup current call. Notify peer
    status = pjsip_inv_end_session (call->getInvSession(), 404, NULL, &tdata);
yanmorin's avatar
yanmorin committed
712

713 714
    if (status != PJ_SUCCESS)
        return false;
715

716

717 718
    if (tdata == NULL)
        return true;
719

720
    // _debug("Some tdata info: %",);
721

722 723 724 725 726 727 728
    status = pjsip_inv_send_msg (call->getInvSession(), tdata);

    if (status != PJ_SUCCESS)
        return false;


    call->getInvSession()->mod_data[getModId() ] = NULL;
jpbl's avatar
jpbl committed
729

730

731 732 733 734 735 736 737
    // Release RTP thread
    if (Manager::instance().isCurrentCall (id)) {
        _debug ("* SIP Info: Stopping AudioRTP for hangup\n");
        _audiortp->closeRtpSession();
    }

    terminateOneCall (id);
738

739 740 741
    removeCall (id);

    return true;
742 743
}

744
bool
745
SIPVoIPLink::peerHungup (const CallID& id)
746
{
747 748 749
    pj_status_t status;
    pjsip_tx_data *tdata = NULL;
    SIPCall* call;
750

751
    call = getSIPCall (id);
Alexandre Savard's avatar
Alexandre Savard committed
752

753 754 755 756
    if (call==0) {
        _debug ("! SIP Error: Call doesn't exist\n");
        return false;
    }
Alexandre Savard's avatar
Alexandre Savard committed
757

758 759
    // User hangup current call. Notify peer
    status = pjsip_inv_end_session (call->getInvSession(), 404, NULL, &tdata);
760

761 762
    if (status != PJ_SUCCESS)
        return false;
763

764 765
    if (tdata == NULL)
        return true;
766

767
    status = pjsip_inv_send_msg (call->getInvSession(), tdata);
768

769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784
    if (status != PJ_SUCCESS)
        return false;

    call->getInvSession()->mod_data[getModId() ] = NULL;

    // Release RTP thread
    if (Manager::instance().isCurrentCall (id)) {
        _debug ("* SIP Info: Stopping AudioRTP for hangup\n");
        _audiortp->closeRtpSession();
    }

    terminateOneCall (id);

    removeCall (id);

    return true;
785 786 787
}

bool
788
SIPVoIPLink::cancel (const CallID& id)
789
{
790
    SIPCall* call = getSIPCall (id);
791

792 793 794 795 796 797 798 799 800 801 802
    if (call==0) {
        _debug ("! SIP Error: Call doesn't exist\n");
        return false;
    }

    _debug ("- SIP Action: Cancel call %s [cid: %3d]\n", id.data(), call->getCid());

    terminateOneCall (id);
    removeCall (id);

    return true;
803 804 805
}

bool
806
SIPVoIPLink::onhold (const CallID& id)
807 808
{

809 810
    pj_status_t status;
    SIPCall* call;
811

812 813 814 815 816 817 818 819 820 821 822 823
    call = getSIPCall (id);

    if (call==0) {
        _debug ("! SIP Error: call doesn't exist\n");
        return false;
    }


    // Stop sound
    call->setAudioStart (false);

    call->setState (Call::Hold);
824

825
    _debug ("* SIP Info: Stopping AudioRTP for onhold action\n");
826

827
    _audiortp->closeRtpSession();
828

829 830 831 832 833 834 835
    /* Create re-INVITE with new offer */
    status = inv_session_reinvite (call, "sendonly");

    if (status != PJ_SUCCESS)
        return false;

    return true;
836 837
}

838
int SIPVoIPLink::inv_session_reinvite (SIPCall *call, std::string direction)
839 840
{

841 842 843 844
    pj_status_t status;
    pjsip_tx_data *tdata;
    pjmedia_sdp_session *local_sdp;
    pjmedia_sdp_attr *attr;
845

846
    local_sdp = call->getLocalSDP()->get_local_sdp_session();
847

848 849 850 851 852 853 854 855
    if (local_sdp == NULL) {
        _debug ("! SIP Failure: unable to find local_sdp\n");
        return !PJ_SUCCESS;
    }

    // reinvite only if connected
    // Build the local SDP offer
    status = call->getLocalSDP()->create_initial_offer();
856

857 858
    if (status != PJ_SUCCESS)
        return 1;   // !PJ_SUCCESS
859

860
    pjmedia_sdp_media_remove_all_attr (local_sdp->media[0], "sendrecv");
861

862
    attr = pjmedia_sdp_attr_create (_pool, direction.c_str(), NULL);
863

864
    pjmedia_sdp_media_add_attr (local_sdp->media[0], attr);
865

866
    // Build the reinvite request
867

868 869
    status = pjsip_inv_reinvite (call->getInvSession(), NULL,
                                 local_sdp, &tdata);
870

871 872
    if (status != PJ_SUCCESS)
        return 1;   // !PJ_SUCCESS
873

874 875
    // Send it
    status = pjsip_inv_send_msg (call->getInvSession(), tdata);
876

877 878
    if (status != PJ_SUCCESS)
        return 1;   // !PJ_SUCCESS
879

880
    return PJ_SUCCESS;
881 882 883
}


884 885
bool
SIPVoIPLink::offhold (const CallID& id)
886
{
887 888
    SIPCall *call;
    pj_status_t status;
889

890
    call = getSIPCall (id);
891

892 893 894 895
    if (call==0) {
        _debug ("! SIP Error: Call doesn't exist\n");
        return false;
    }
896

897 898 899 900 901
    try {
        _audiortp->createNewSession (call);
    } catch (...) {
        _debug ("! SIP Failure: Unable to create RTP Session (%s:%d)\n", __FILE__, __LINE__);
    }
902

903 904
    /* Create re-INVITE with new offer */
    status = inv_session_reinvite (call, "sendrecv");
905

906 907
    if (status != PJ_SUCCESS)
        return false;
908

909
    call->setState (Call::Active);
910

911 912
    return true;
}
913

914 915 916
bool
SIPVoIPLink::transfer (const CallID& id, const std::string& to)
{
917

918 919 920 921
    SIPCall *call;
    std::string tmp_to;
    pjsip_evsub *sub;
    pjsip_tx_data *tdata;
922

923 924 925 926 927
    struct pjsip_evsub_user xfer_cb;
    pj_status_t status;
    pj_str_t dest;
    AccountID account_id;
    Account* account;
928

929 930 931 932
    call = getSIPCall (id);
    call->stopRecording();
    account_id = Manager::instance().getAccountFromCall (id);
    account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (account_id));
933

934 935 936 937
    if (call==0) {
        _debug ("! SIP Failure: Call doesn't exist\n");
        return false;
    }
938

939
    tmp_to = SIPToHeader (to);
940

941 942 943 944 945
    if (account) {
        if (tmp_to.find ("@") == std::string::npos) {
            tmp_to = tmp_to + "@" + account->getHostname();
        }
    }
946

947
    else {
948

949
    }
950

951
    _debug ("In transfer, tmp_to is %s\n", tmp_to.data());
952

953
    pj_strdup2 (_pool, &dest, tmp_to.data());
954

955 956 957
    /* Create xfer client subscription. */
    pj_bzero (&xfer_cb, sizeof (xfer_cb));
    xfer_cb.on_evsub_state = &xfer_func_cb;
958

959
    status = pjsip_xfer_create_uac (call->getInvSession()->dlg, &xfer_cb, &sub);
960

961 962 963 964
    if (status != PJ_SUCCESS) {
        _debug ("UserAgent: Unable to create xfer -- %d\n", status);
        return false;
    }
965

966 967 968 969 970 971
    /* Associate this voiplink of call with the client subscription
     * We can not just associate call with the client subscription
     * because after this function, we can not find the cooresponding
     * voiplink from the call any more. But the voiplink is useful!
     */
    pjsip_evsub_set_mod_data (sub, getModId(), this);
972

973
    _debug ("SIP port listener = %i", _localExternPort);
974

975 976 977 978
    /*
     * Create REFER request.
     */
    status = pjsip_xfer_initiate (sub, &dest, &tdata);
979

980 981 982 983
    if (status != PJ_SUCCESS) {
        _debug ("UserAgent: Unable to create REFER request -- %d\n", status);
        return false;
    }
984

985 986
    /* Send. */
    status = pjsip_xfer_send_request (sub, tdata);
987

988 989 990 991
    if (status != PJ_SUCCESS) {
        _debug ("UserAgent: Unable to send REFER request -- %d\n", status);
        return false;
    }
992

993 994
    return true;
}
995

996 997 998 999
bool SIPVoIPLink::transferStep2()
{
    _audiortp->closeRtpSession();
    return true;
1000 1001
}

1002 1003
bool
SIPVoIPLink::refuse (const CallID& id)
1004
{
1005 1006 1007
    SIPCall *call;
    pj_status_t status;
    pjsip_tx_data *tdata;
1008 1009


1010
    call = getSIPCall (id);
1011

1012 1013 1014 1015 1016 1017 1018 1019 1020 1021
    if (call==0) {
        _debug ("Call doesn't exist\n");
        return false;
    }

    // can't refuse outgoing call or connected
    if (!call->isIncoming() || call->getConnectionState() == Call::Connected) {
        _debug ("It's not an incoming call, or it's already answered\n");
        return false;
    }
1022

1023 1024
    // User refuse current call. Notify peer
    status = pjsip_inv_end_session (call->getInvSession(), PJSIP_SC_DECLINE, NULL, &tdata);   //603
1025

1026 1027
    if (status != PJ_SUCCESS)
        return false;
1028

1029
    status = pjsip_inv_send_msg (call->getInvSession(), tdata);
1030

1031 1032
    if (status != PJ_SUCCESS)
        return false;
1033

1034
    call->getInvSession()->mod_data[getModId() ] = NULL;
1035

1036
    terminateOneCall (id);
1037

1038
    return true;
1039 1040
}

1041 1042
void
SIPVoIPLink::setRecording (const CallID& id)
1043
{
1044 1045 1046 1047 1048 1049
    SIPCall* call = getSIPCall (id);

    if (call)
        call->setRecording();

    // _audiortp->setRecording();
Alexandre Savard's avatar
Alexandre Savard committed
1050 1051
}

1052 1053
bool
SIPVoIPLink::isRecording (const CallID& id)
jpbl's avatar
jpbl committed
1054
{
1055 1056 1057 1058 1059 1060 1061 1062
    SIPCall* call = getSIPCall (id);
    _debug ("call->isRecording() %i \n",call->isRecording());

    if (call)
        return call->isRecording();
    else
        return false;
}
1063 1064


1065 1066 1067
std::string
SIPVoIPLink::getCurrentCodecName()
{
1068

1069 1070 1071
    SIPCall *call;
    AudioCodec *ac = NULL;
    std::string name = "";
1072

1073
    call = getSIPCall (Manager::instance().getCurrentCallId());
1074

1075 1076
    if (call)
        ac = call->getLocalSDP()->get_session_media();
1077

1078 1079
    if (ac)
        name = ac->getCodecName();
1080

1081
    return name;
1082 1083
}

1084 1085
bool
SIPVoIPLink::carryingDTMFdigits (const CallID& id, char code)
1086 1087
{

1088 1089 1090 1091 1092 1093 1094 1095 1096
    SIPCall *call;
    int duration;
    const int body_len = 1000;
    char *dtmf_body;
    pj_status_t status;
    pjsip_tx_data *tdata;
    pj_str_t methodName, content;
    pjsip_method method;
    pjsip_media_type ctype;
1097

1098
    call = getSIPCall (id);
1099

1100 1101 1102 1103
    if (call==0) {
        _debug ("Call doesn't exist\n");
        return false;
    }
1104

1105
    duration = Manager::instance().getConfigInt (SIGNALISATION, PULSE_LENGTH);
1106

1107
    dtmf_body = new char[body_len];
1108

1109
    snprintf (dtmf_body, body_len - 1, "Signal=%c\r\nDuration=%d\r\n", code, duration);
1110

1111 1112
    pj_strdup2 (_pool, &methodName, "INFO");
    pjsip_method_init_np (&method, &methodName);
1113

1114 1115
    /* Create request message. */
    status = pjsip_dlg_create_request (call->getInvSession()->dlg, &method, -1, &tdata);
1116

1117 1118 1119 1120
    if (status != PJ_SUCCESS) {
        _debug ("UserAgent: Unable to create INFO request -- %d\n", status);
        return false;
    }
1121

1122 1123
    /* Get MIME type */
    pj_strdup2 (_pool, &ctype.type, "application");
1124

1125
    pj_strdup2 (_pool, &ctype.subtype, "dtmf-relay");
1126

1127 1128
    /* Create "application/dtmf-relay" message body. */
    pj_strdup2 (_pool, &content, dtmf_body);
1129

1130
    tdata->msg->body = pjsip_msg_body_create (tdata->pool, &ctype.type, &ctype.subtype, &content);
1131

1132 1133 1134 1135 1136
    if (tdata->msg->body == NULL) {
        _debug ("UserAgent: Unable to create msg body!\n");
        pjsip_tx_data_dec_ref (tdata);
        return false;
    }
1137

1138 1139
    /* Send the request. */
    status = pjsip_dlg_send_request (call->getInvSession()->dlg, tdata, getModId(), NULL);
1140

1141 1142 1143 1144
    if (status != PJ_SUCCESS) {
        _debug ("UserAgent: Unable to send MESSAGE request -- %d\n", status);
        return false;
    }
1145

1146
    return true;
1147 1148
}

1149 1150
bool
SIPVoIPLink::SIPOutgoingInvite (SIPCall* call)
1151
{
1152 1153 1154 1155 1156 1157 1158
    // If no SIP proxy setting for direct call with only IP address
    if (!SIPStartCall (call, "")) {
        _debug ("! SIP Failure: call not started\n");
        return false;
    }

    return true;
1159 1160
}

1161 1162
bool
SIPVoIPLink::SIPStartCall (SIPCall* call, const std::string& subject UNUSED)
1163
{
1164 1165 1166 1167 1168 1169 1170 1171
    std::string strTo, strFrom;
    pj_status_t status;
    pjsip_dialog *dialog;
    pjsip_tx_data *tdata;
    pj_str_t from, to, contact;
    AccountID id;
    SIPAccount *account;
    pjsip_inv_session *inv;
1172

1173 1174
    if (!call)
        return false;
1175

1176
    id = Manager::instance().getAccountFromCall (call->getCallId());
1177

1178 1179
    // Get the basic information about the callee account
    account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (id));
1180

1181
    strTo = getSipTo (call->getPeerNumber(), account->getHostname());
1182