Subversion Repositories tpanel

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
123 andreas 1
/*
2
 * Copyright (C) 2022 by Andreas Theofilu <andreas@theosys.at>
3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software Foundation,
16
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
17
 */
18
#include <string>
19
#include <vector>
20
#include <iomanip>
21
#include <ctime>
135 andreas 22
#include <thread>
123 andreas 23
 
135 andreas 24
#ifdef __ANDROID__
25
#include <jni.h>
26
#endif
123 andreas 27
#include "tsipclient.h"
28
#include "tconfig.h"
29
#include "terror.h"
30
#include "tpagemanager.h"
31
 
129 andreas 32
#ifndef _NOSIP_
33
 
135 andreas 34
static pj_thread_desc _desc_;
35
static pj_thread_t *_thread_;
36
 
37
#define REGISTER_THREAD() \
38
if(!pj_thread_is_registered()) {\
39
    pj_thread_register(NULL, _desc_, &_thread_);\
40
}
41
 
141 andreas 42
#if __cplusplus < 201402L
43
#   error "This module requires at least C++14 standard!"
44
#else
45
#   if __cplusplus < 201703L
46
#       include <experimental/filesystem>
47
        namespace fs = std::experimental::filesystem;
48
#       warning "Support for C++14 and experimental filesystem will be removed in a future version!"
49
#   else
50
#       include <filesystem>
51
#       ifdef __ANDROID__
52
            namespace fs = std::__fs::filesystem;
53
#       else
54
            namespace fs = std::filesystem;
55
#       endif
56
#   endif
57
#endif
58
 
123 andreas 59
using std::string;
60
using std::vector;
61
using std::to_string;
135 andreas 62
using std::atomic;
141 andreas 63
using std::thread;
123 andreas 64
 
127 andreas 65
TSIPClient *TSIPClient::mMyself{nullptr};
135 andreas 66
TSIPClient::pjsua_app_config TSIPClient::mAppConfig;
67
pjsua_call_id TSIPClient::mCurrentCall{PJSUA_INVALID_ID};
68
atomic<bool> TSIPClient::mRefreshRun{false};
141 andreas 69
bool TSIPClient::mPhoneRingInit{false};
70
TSIPClient::ringtone_port_info_t TSIPClient::mRingtonePortInfo;
123 andreas 71
 
135 andreas 72
// The module instance.
73
pjsip_module TSIPClient::mod_default_handler =
74
{
75
    NULL, NULL,                             // prev, next.
76
    { (char *)"mod-default-handler", 19 },  // Name.
77
    -1,                                     // Id
78
    PJSIP_MOD_PRIORITY_APPLICATION+99,      // Priority
79
    NULL,                                   // load()
80
    NULL,                                   // start()
81
    NULL,                                   // stop()
82
    NULL,                                   // unload()
83
    &default_mod_on_rx_request,             // on_rx_request()
84
    NULL,                                   // on_rx_response()
85
    NULL,                                   // on_tx_request.
86
    NULL,                                   // on_tx_response()
87
    NULL,                                   // on_tsx_state()
88
};
89
 
123 andreas 90
extern TPageManager *gPageManager;
91
 
135 andreas 92
 
127 andreas 93
TSIPClient::TSIPClient()
123 andreas 94
{
95
    DECL_TRACER("TSIPClient::TSIPClient()");
96
 
135 andreas 97
    if (mMyself)
98
        return;
99
 
127 andreas 100
    mMyself = this;
138 andreas 101
    mLine = PJSUA_INVALID_ID;
102
    mCurrentCall = PJSUA_INVALID_ID;
123 andreas 103
 
138 andreas 104
    for (int i = 0; i < PJSUA_MAX_CALLS; ++i)
105
        mSIPState[i] = SIP_NONE;
127 andreas 106
 
107
    // Start the SIP client
123 andreas 108
    if (TConfig::getSIPstatus())    // Is SIP enabled?
109
    {                               // Yes, try to connect to SIP proxy
135 andreas 110
        if (!init())
123 andreas 111
            TError::setError();
112
    }
113
}
114
 
115
TSIPClient::~TSIPClient()
116
{
117
    DECL_TRACER("TSIPClient::~TSIPClient()");
118
 
135 andreas 119
    if (mMyself != this)
120
        return;
121
 
123 andreas 122
    cleanUp();
127 andreas 123
    mMyself = nullptr;
123 andreas 124
}
125
 
135 andreas 126
bool TSIPClient::init()
123 andreas 127
{
135 andreas 128
    DECL_TRACER("TSIPClient::init()");
123 andreas 129
 
135 andreas 130
    if (mRegistered)
131
        return true;
132
 
133
    pj_status_t status;
134
    string sipProxy = TConfig::getSIPproxy();
135
    string sipDomain = TConfig::getSIPdomain();
136
 
137
    if (!sipProxy.empty() && sipDomain.empty())
138
        sipDomain = sipProxy;
139
    else if (sipProxy.empty() && !sipDomain.empty())
140
        sipProxy = sipDomain;
141
    else if (sipProxy.empty() && sipDomain.empty())
123 andreas 142
    {
135 andreas 143
        MSG_ERROR("No proxy server and no domain given!");
144
        return false;
123 andreas 145
    }
146
 
135 andreas 147
    // Initialize the library
148
    if (pj_init() != PJ_SUCCESS)
127 andreas 149
    {
135 andreas 150
        MSG_ERROR("Initialisation of PJSIP failed!");
151
        return false;
152
    }
123 andreas 153
 
135 andreas 154
    // Define the callback for logging
155
    pj_log_init();
156
    pj_log_set_log_func(&_log_call);
157
    pj_log_set_decor(PJ_LOG_HAS_SENDER);
158
    pj_log_set_level(4);
159
 
160
    /* Create pjsua first! */
161
    if (pjsua_create() != PJ_SUCCESS)
162
    {
163
        MSG_ERROR("Error in pjsua_create()");
164
        return false;
127 andreas 165
    }
166
 
135 andreas 167
    mAppConfig.pool = pjsua_pool_create("TPanel", 1000, 1000);
168
    pj_pool_t *tmp_pool = pjsua_pool_create("tmp-TPanel", 1000, 1000);
123 andreas 169
 
136 andreas 170
    // Global configuration
171
    string idUri = "sip:" + TConfig::getSIPuser() + "@" + sipProxy;
172
    string regUri = "sip:" + sipProxy + ":" + to_string(TConfig::getSIPport());
144 andreas 173
    pjsua_config_default(&mAppConfig.cfg);
136 andreas 174
    mAppConfig.cfg.outbound_proxy_cnt = 1;
175
    mAppConfig.cfg.outbound_proxy[0] = pj_str((char *)regUri.c_str());
176
    mAppConfig.cfg.max_calls = SIP_MAX_LINES;
177
 
178
    if (!TConfig::getSIPstun().empty())
179
    {
180
        mAppConfig.cfg.stun_srv_cnt = 1;
181
        mAppConfig.cfg.stun_srv[0] = pj_str((char *)TConfig::getSIPstun().c_str());
182
 
183
        if (TConfig::getSIPnetworkIPv6())
184
            mAppConfig.cfg.stun_try_ipv6 = PJ_TRUE;
185
    }
186
 
144 andreas 187
    string uAgent = string("TPanel v") + VERSION_STRING() + "/" + PJ_OS_NAME;
136 andreas 188
    mAppConfig.cfg.user_agent = pj_str((char *)uAgent.c_str());
135 andreas 189
    // Define main account
190
    mAppConfig.acc_cnt = 1;
191
    pjsua_acc_config_default(&mAppConfig.acc_cfg[0]);
192
    mAppConfig.acc_cfg[0].id = pj_str((char *)idUri.c_str());
193
    mAppConfig.acc_cfg[0].reg_uri = pj_str((char *)regUri.c_str());
136 andreas 194
    mAppConfig.acc_cfg[0].proxy_cnt = 1;
195
    mAppConfig.acc_cfg[0].proxy[0] = pj_str((char *)regUri.c_str());
135 andreas 196
    mAppConfig.acc_cfg[0].cred_count = 1;
197
    mAppConfig.acc_cfg[0].cred_info[0].scheme = pjsip_DIGEST_STR;
198
    mAppConfig.acc_cfg[0].cred_info[0].realm = pj_str((char *)"*");
199
    mAppConfig.acc_cfg[0].cred_info[0].username = pj_str((char *)TConfig::getSIPuser().c_str());
200
    mAppConfig.acc_cfg[0].cred_info[0].data_type = 0;
201
    mAppConfig.acc_cfg[0].cred_info[0].data = pj_str((char *)TConfig::getSIPpassword().c_str());
123 andreas 202
 
135 andreas 203
    /* Init pjsua */
204
    pjsua_logging_config log_cfg;
123 andreas 205
 
135 andreas 206
    mAppConfig.cfg.cb.on_incoming_call = &on_incoming_call;
207
    mAppConfig.cfg.cb.on_call_media_state = &on_call_media_state;
208
    mAppConfig.cfg.cb.on_call_state = &on_call_state;
209
    mAppConfig.cfg.cb.on_dtmf_digit2 = &call_on_dtmf_callback2;
210
    mAppConfig.cfg.cb.on_call_redirected = &call_on_redirected;
211
    mAppConfig.cfg.cb.on_call_transfer_status = &on_call_transfer_status;
212
    mAppConfig.cfg.cb.on_transport_state = &on_transport_state;
213
    mAppConfig.cfg.cb.on_ip_change_progress = &on_ip_change_progress;
144 andreas 214
    mAppConfig.cfg.cb.on_pager2 = &on_pager2;
215
    mAppConfig.cfg.cb.on_buddy_state = &on_buddy_state;
216
    mAppConfig.cfg.cb.on_buddy_evsub_state = &on_buddy_evsub_state;
217
    mAppConfig.cfg.cb.on_mwi_info = &on_mwi_info;
123 andreas 218
 
135 andreas 219
    pjsua_logging_config_default(&log_cfg);
220
    log_cfg.console_level = 4;
221
    log_cfg.level = 5;
222
    log_cfg.decor = (PJ_LOG_HAS_SENDER);
223
    log_cfg.cb = &_log_call;
123 andreas 224
 
135 andreas 225
    pjsua_media_config_default(&mAppConfig.media_cfg);
226
 
227
    if (mAppConfig.capture_lat > 0)
228
        mAppConfig.media_cfg.snd_rec_latency = mAppConfig.capture_lat;
229
 
230
    if (mAppConfig.playback_lat)
231
        mAppConfig.media_cfg.snd_play_latency = mAppConfig.playback_lat;
232
 
233
    if (TConfig::getSIPfirewall() == TConfig::SIP_ICE)
234
        mAppConfig.media_cfg.enable_ice = true;
235
 
236
    if (!TConfig::getSIPstun().empty())
237
        mAppConfig.media_cfg.turn_server = pj_str((char *)TConfig::getSIPstun().c_str());
238
 
239
    if (pjsua_init(&mAppConfig.cfg, &log_cfg, &mAppConfig.media_cfg) != PJ_SUCCESS)
123 andreas 240
    {
135 andreas 241
        MSG_ERROR("Error in pjsua_init()");
242
        pj_pool_release(tmp_pool);
243
        pjsua_destroy();
244
        return false;
123 andreas 245
    }
135 andreas 246
 
247
    if (pjsip_endpt_register_module(pjsua_get_pjsip_endpt(), &mod_default_handler) != PJ_SUCCESS)
123 andreas 248
    {
135 andreas 249
        MSG_ERROR("Error registrating module handler!");
250
        pjsua_destroy();
123 andreas 251
        return false;
252
    }
253
 
135 andreas 254
    // Initialize calls data
255
    for (size_t i = 0; i < PJ_ARRAY_SIZE(mAppConfig.call_data); ++i)
256
    {
257
        mAppConfig.call_data[i].timer.id = PJSUA_INVALID_ID;
258
        mAppConfig.call_data[i].timer.cb = &call_timeout_callback;
259
    }
123 andreas 260
 
135 andreas 261
    /* Optionally registers WAV file */
262
    for (uint_t i = 0; i < mAppConfig.wav_count; ++i)
263
    {
264
        pjsua_player_id wav_id;
265
        uint_t play_options = 0;
123 andreas 266
 
135 andreas 267
        if (mAppConfig.auto_play_hangup)
268
            play_options |= PJMEDIA_FILE_NO_LOOP;
123 andreas 269
 
135 andreas 270
        status = pjsua_player_create(&mAppConfig.wav_files[i], play_options, &wav_id);
123 andreas 271
 
135 andreas 272
        if (status != PJ_SUCCESS)
273
        {
274
            MSG_ERROR("Error creating a player!");
275
            pj_pool_release(tmp_pool);
276
            pjsua_destroy();
277
            return false;
278
        }
123 andreas 279
 
135 andreas 280
        if (mAppConfig.wav_id == PJSUA_INVALID_ID)
281
        {
282
            mAppConfig.wav_id = wav_id;
283
            mAppConfig.wav_port = pjsua_player_get_conf_port(mAppConfig.wav_id);
123 andreas 284
 
135 andreas 285
            if (mAppConfig.auto_play_hangup)
286
            {
287
                pjmedia_port *port;
123 andreas 288
 
135 andreas 289
                pjsua_player_get_port(mAppConfig.wav_id, &port);
123 andreas 290
 
135 andreas 291
                if (pjmedia_wav_player_set_eof_cb2(port, NULL, &on_playfile_done) != PJ_SUCCESS)
292
                {
293
                    MSG_ERROR("Error setting callback function for player!");
294
                    pj_pool_release(tmp_pool);
295
                    pjsua_destroy();
296
                    return false;
297
                }
298
 
299
                pj_timer_entry_init(&mAppConfig.auto_hangup_timer, 0, NULL, &hangup_timeout_callback);
300
            }
301
        }
123 andreas 302
    }
303
 
135 andreas 304
    /* Register tone players */
305
    for (uint_t i = 0; i < mAppConfig.tone_count; ++i)
123 andreas 306
    {
135 andreas 307
        pjmedia_port *tport;
308
        char name[80];
309
        pj_str_t label;
310
        pj_status_t status2;
123 andreas 311
 
135 andreas 312
        pj_ansi_snprintf(name, sizeof(name), "tone-%d,%d",
313
                         mAppConfig.tones[i].freq1,
314
                         mAppConfig.tones[i].freq2);
315
        label = pj_str(name);
316
        status2 = pjmedia_tonegen_create2(mAppConfig.pool, &label,
317
                                          8000, 1, 160, 16,
318
                                          PJMEDIA_TONEGEN_LOOP,  &tport);
319
        if (status2 != PJ_SUCCESS)
320
        {
321
            MSG_ERROR("Unable to create tone generator! (" << status << ")");
322
            pj_pool_release(tmp_pool);
323
            pjsua_destroy();
324
            return false;
325
        }
123 andreas 326
 
135 andreas 327
        status2 = pjsua_conf_add_port(mAppConfig.pool, tport, &mAppConfig.tone_slots[i]);
328
        pj_assert(status2 == PJ_SUCCESS);
329
 
330
        status2 = pjmedia_tonegen_play(tport, 1, &mAppConfig.tones[i], 0);
331
        pj_assert(status2 == PJ_SUCCESS);
123 andreas 332
    }
333
 
135 andreas 334
    /* Create ringback tones */
335
    if (mAppConfig.no_tones == PJ_FALSE)
336
    {
337
        uint_t samples_per_frame;
338
        pjmedia_tone_desc tone[RING_CNT+RINGBACK_CNT];
339
        pj_str_t name;
127 andreas 340
 
135 andreas 341
        samples_per_frame = mAppConfig.media_cfg.audio_frame_ptime *
342
        mAppConfig.media_cfg.clock_rate *
343
        mAppConfig.media_cfg.channel_count / 1000;
127 andreas 344
 
135 andreas 345
        /* Ringback tone (call is ringing) */
346
        name = pj_str((char *)"ringback");
347
        status = pjmedia_tonegen_create2(mAppConfig.pool, &name,
348
                                         mAppConfig.media_cfg.clock_rate,
349
                                         mAppConfig.media_cfg.channel_count,
350
                                         samples_per_frame,
351
                                         16, PJMEDIA_TONEGEN_LOOP,
352
                                         &mAppConfig.ringback_port);
353
        if (status != PJ_SUCCESS)
354
        {
355
            MSG_ERROR("Unable to create tone generator 2! (" << status << ")");
356
            pj_pool_release(tmp_pool);
357
            pjsua_destroy();
358
            return false;
359
        }
127 andreas 360
 
135 andreas 361
        pj_bzero(&tone, sizeof(tone));
124 andreas 362
 
135 andreas 363
        for (int i = 0; i < RINGBACK_CNT; ++i)
364
        {
365
            tone[i].freq1 = RINGBACK_FREQ1;
366
            tone[i].freq2 = RINGBACK_FREQ2;
367
            tone[i].on_msec = RINGBACK_ON;
368
            tone[i].off_msec = RINGBACK_OFF;
369
        }
370
 
371
        tone[RINGBACK_CNT-1].off_msec = RINGBACK_INTERVAL;
372
 
373
        pjmedia_tonegen_play(mAppConfig.ringback_port, RINGBACK_CNT, tone,
374
                             PJMEDIA_TONEGEN_LOOP);
375
 
376
 
377
        status = pjsua_conf_add_port(mAppConfig.pool, mAppConfig.ringback_port,
378
                                     &mAppConfig.ringback_slot);
379
        if (status != PJ_SUCCESS)
380
        {
381
            MSG_ERROR("Unable to add a port to tone generator! (" << status << ")");
382
            pj_pool_release(tmp_pool);
383
            pjsua_destroy();
384
            return false;
385
        }
386
 
387
        /* Ring (to alert incoming call) */
388
        name = pj_str((char *)"ring");
389
        status = pjmedia_tonegen_create2(mAppConfig.pool, &name,
390
                                         mAppConfig.media_cfg.clock_rate,
391
                                         mAppConfig.media_cfg.channel_count,
392
                                         samples_per_frame,
393
                                         16, PJMEDIA_TONEGEN_LOOP,
394
                                         &mAppConfig.ring_port);
395
        if (status != PJ_SUCCESS)
396
        {
397
            MSG_ERROR("Unable to create tone generator 2! (" << status << ")");
398
            pj_pool_release(tmp_pool);
399
            pjsua_destroy();
400
            return false;
401
        }
402
 
403
        for (int i = 0; i < RING_CNT; ++i)
404
        {
405
            tone[i].freq1 = RING_FREQ1;
406
            tone[i].freq2 = RING_FREQ2;
407
            tone[i].on_msec = RING_ON;
408
            tone[i].off_msec = RING_OFF;
409
        }
410
 
411
        tone[RING_CNT-1].off_msec = RING_INTERVAL;
412
 
413
        pjmedia_tonegen_play(mAppConfig.ring_port, RING_CNT, tone, PJMEDIA_TONEGEN_LOOP);
414
 
415
        status = pjsua_conf_add_port(mAppConfig.pool, mAppConfig.ring_port,
416
                                     &mAppConfig.ring_slot);
417
        if (status != PJ_SUCCESS)
418
        {
419
            MSG_ERROR("Unable to add a port to tone generator! (" << status << ")");
420
            pj_pool_release(tmp_pool);
421
            pjsua_destroy();
422
            return false;
423
        }
124 andreas 424
    }
127 andreas 425
 
135 andreas 426
    /* Add UDP transport. */
427
    pjsua_transport_id transport_id = -1;
428
    pjsua_transport_config tcp_cfg;
123 andreas 429
 
135 andreas 430
    if (!mAppConfig.no_udp && TConfig::getSIPnetworkIPv4())
123 andreas 431
    {
135 andreas 432
        pjsua_acc_id aid;
433
        pjsip_transport_type_e type = PJSIP_TRANSPORT_UDP;
434
 
435
        status = pjsua_transport_create(type,
436
                                        &mAppConfig.udp_cfg,
437
                                        &transport_id);
438
        if (status != PJ_SUCCESS)
439
        {
440
            MSG_ERROR("Unable to create transport! (" << status << ")");
441
            pj_pool_release(tmp_pool);
442
            pjsua_destroy();
443
            return false;
444
        }
445
 
446
        /* Add local account */
447
        pjsua_acc_add_local(transport_id, PJ_TRUE, &aid);
448
        /* Adjust local account config based on pjsua app config */
449
        {
450
            pjsua_acc_config acc_cfg;
451
            pjsua_acc_get_config(aid, tmp_pool, &acc_cfg);
452
 
453
            acc_cfg.rtp_cfg = mAppConfig.rtp_cfg;
454
            pjsua_acc_modify(aid, &acc_cfg);
455
        }
456
 
457
        pjsua_acc_set_online_status(current_acc, PJ_TRUE);
458
        // Find a free port to listen on
459
        pjsua_transport_info ti;
460
        pj_sockaddr_in *a;
461
 
462
        pjsua_transport_get_info(transport_id, &ti);
463
        ti.local_addr.addr.sa_family = PJ_AF_INET;
464
        a = (pj_sockaddr_in*)&ti.local_addr;
465
        tcp_cfg.port = pj_ntohs(a->sin_port);
123 andreas 466
    }
467
 
135 andreas 468
    if (!mAppConfig.no_udp && TConfig::getSIPnetworkIPv6())
123 andreas 469
    {
135 andreas 470
        pjsua_acc_id aid;
471
        pjsip_transport_type_e type = PJSIP_TRANSPORT_UDP6;
472
        pjsua_transport_config udp_cfg;
123 andreas 473
 
135 andreas 474
        udp_cfg = mAppConfig.udp_cfg;
123 andreas 475
 
135 andreas 476
        if (udp_cfg.port == 0)
477
            udp_cfg.port = 5060;
478
        else
479
            udp_cfg.port += 10;
123 andreas 480
 
135 andreas 481
        status = pjsua_transport_create(type,
482
                                        &udp_cfg,
483
                                        &transport_id);
484
        if (status != PJ_SUCCESS)
485
        {
486
            MSG_ERROR("Unable to create IPv6 transport! (" << status << ")");
487
            pj_pool_release(tmp_pool);
488
            pjsua_destroy();
489
            return false;
490
        }
123 andreas 491
 
135 andreas 492
        /* Add local account */
493
        pjsua_acc_add_local(transport_id, PJ_TRUE, &aid);
494
        /* Adjust local account config based on pjsua app config */
495
        {
496
            pjsua_acc_config acc_cfg;
497
            pjsua_acc_get_config(aid, tmp_pool, &acc_cfg);
123 andreas 498
 
135 andreas 499
            acc_cfg.rtp_cfg = mAppConfig.rtp_cfg;
500
            acc_cfg.ipv6_media_use = PJSUA_IPV6_ENABLED;
501
            pjsua_acc_modify(aid, &acc_cfg);
502
        }
123 andreas 503
 
135 andreas 504
        //pjsua_acc_set_transport(aid, transport_id);
505
        pjsua_acc_set_online_status(current_acc, PJ_TRUE);
127 andreas 506
 
135 andreas 507
        if (mAppConfig.udp_cfg.port == 0)
508
        {
509
            pjsua_transport_info ti;
127 andreas 510
 
135 andreas 511
            pjsua_transport_get_info(transport_id, &ti);
512
            tcp_cfg.port = pj_sockaddr_get_port(&ti.local_addr);
513
        }
123 andreas 514
    }
135 andreas 515
 
516
    /* Add TCP transport unless it's disabled */
517
    if (!mAppConfig.no_tcp && TConfig::getSIPnetworkIPv4())
123 andreas 518
    {
135 andreas 519
        pjsua_acc_id aid;
123 andreas 520
 
135 andreas 521
        status = pjsua_transport_create(PJSIP_TRANSPORT_TCP,
522
                                        &tcp_cfg,
523
                                        &transport_id);
524
        if (status != PJ_SUCCESS)
525
        {
526
            MSG_ERROR("Unable to create TCP transport! (" << status << ")");
527
            pj_pool_release(tmp_pool);
528
            pjsua_destroy();
529
            return false;
530
        }
123 andreas 531
 
135 andreas 532
        /* Add local account */
533
        pjsua_acc_add_local(transport_id, PJ_TRUE, &aid);
127 andreas 534
 
135 andreas 535
        /* Adjust local account config based on pjsua app config */
536
        {
537
            pjsua_acc_config acc_cfg;
538
            pjsua_acc_get_config(aid, tmp_pool, &acc_cfg);
127 andreas 539
 
135 andreas 540
            acc_cfg.rtp_cfg = mAppConfig.rtp_cfg;
541
            pjsua_acc_modify(aid, &acc_cfg);
542
        }
543
 
544
        pjsua_acc_set_online_status(current_acc, PJ_TRUE);
545
    }
546
 
547
    /* Add TCP IPv6 transport unless it's disabled. */
548
    if (!mAppConfig.no_tcp && TConfig::getSIPnetworkIPv6())
127 andreas 549
    {
135 andreas 550
        pjsua_acc_id aid;
551
        pjsip_transport_type_e type = PJSIP_TRANSPORT_TCP6;
552
 
553
        tcp_cfg.port += 10;
554
 
555
        status = pjsua_transport_create(type,
556
                                        &tcp_cfg,
557
                                        &transport_id);
558
        if (status != PJ_SUCCESS)
127 andreas 559
        {
135 andreas 560
            MSG_ERROR("Unable to create TCP IPv6 transport! (" << status << ")");
561
            pj_pool_release(tmp_pool);
562
            pjsua_destroy();
563
            return false;
564
        }
127 andreas 565
 
135 andreas 566
        /* Add local account */
567
        pjsua_acc_add_local(transport_id, PJ_TRUE, &aid);
127 andreas 568
 
135 andreas 569
        /* Adjust local account config based on pjsua app config */
570
        {
571
            pjsua_acc_config acc_cfg;
572
            pjsua_acc_get_config(aid, tmp_pool, &acc_cfg);
573
 
574
            acc_cfg.rtp_cfg = mAppConfig.rtp_cfg;
575
            acc_cfg.ipv6_media_use = PJSUA_IPV6_ENABLED;
576
            pjsua_acc_modify(aid, &acc_cfg);
127 andreas 577
        }
578
 
135 andreas 579
        //pjsua_acc_set_transport(aid, transport_id);
580
        pjsua_acc_set_online_status(current_acc, PJ_TRUE);
127 andreas 581
    }
582
 
135 andreas 583
    if (transport_id == -1)
584
    {
585
        MSG_ERROR("Transport couldn't be configured!");
586
        pj_pool_release(tmp_pool);
587
        pjsua_destroy();
588
        return false;
589
    }
127 andreas 590
 
135 andreas 591
    /* Add accounts */
592
    for (uint_t i = 0; i < mAppConfig.acc_cnt; ++i)
127 andreas 593
    {
135 andreas 594
        mAppConfig.acc_cfg[i].rtp_cfg = mAppConfig.rtp_cfg;
595
        mAppConfig.acc_cfg[i].reg_retry_interval = 300;
596
        mAppConfig.acc_cfg[i].reg_first_retry_interval = 60;
597
 
598
        status = pjsua_acc_add(&mAppConfig.acc_cfg[i], PJ_TRUE, NULL);
599
 
600
        if (status != PJ_SUCCESS)
601
        {
602
            MSG_ERROR("Unable to add an account! (" << status << ")");
603
            pj_pool_release(tmp_pool);
604
            pjsua_destroy();
605
            return false;
606
        }
607
 
608
        pjsua_acc_set_online_status(current_acc, PJ_TRUE);
127 andreas 609
    }
610
 
144 andreas 611
    // Boddy for IM
612
    mAppConfig.buddy_cnt = 1;
613
    pjsua_buddy_config_default(mAppConfig.buddy_cfg);
614
    mAppConfig.buddy_cfg->uri = pj_str((char *)idUri.c_str());
615
    mAppConfig.buddy_cfg->subscribe = PJ_FALSE;
616
    pjsua_buddy_id bid;
617
 
618
    if (pjsua_buddy_add(mAppConfig.buddy_cfg, &bid) != PJ_SUCCESS)
619
    {
620
        MSG_ERROR("Couldn't create a new buddy for IM (SMS)!");
621
        mAppConfig.buddy_cnt = 0;
622
    }
623
 
135 andreas 624
    /* Init call setting */
625
    pjsua_call_setting call_opt;
626
    pjsua_call_setting_default(&call_opt);
627
    call_opt.aud_cnt = mAppConfig.aud_cnt;
628
    call_opt.vid_cnt = 0;
127 andreas 629
 
135 andreas 630
#if defined(PJSIP_HAS_TLS_TRANSPORT) && PJSIP_HAS_TLS_TRANSPORT!=0
631
    /* Wipe out TLS key settings in transport configs */
632
    pjsip_tls_setting_wipe_keys(&mAppConfig.udp_cfg.tls_setting);
633
#endif
634
 
635
    pj_pool_release(tmp_pool);
636
 
637
    /* Initialization is done, now start pjsua */
638
    status = pjsua_start();
639
 
640
    if (status != PJ_SUCCESS)
641
    {
642
        MSG_ERROR("Error starting pjsua");
643
        pjsua_destroy();
644
        return false;
645
    }
646
 
647
    mRegistered = true;
123 andreas 648
    return true;
649
}
650
 
135 andreas 651
void TSIPClient::cleanUp()
652
{
653
    DECL_TRACER("TSIPClient::cleanUp()");
654
 
141 andreas 655
    if (mPhoneRingInit && mRingtonePortInfo.pool)
656
    {
657
        pj_pool_release(mRingtonePortInfo.pool);
658
        mRingtonePortInfo.pool = nullptr;
659
        mPhoneRingInit = false;
660
    }
661
 
135 andreas 662
    pjsua_destroy();
663
    mAccountID = 0;
138 andreas 664
    mLine = PJSUA_INVALID_ID;
665
    mCurrentCall = PJSUA_INVALID_ID;
135 andreas 666
 
138 andreas 667
    for (int i = 0; i < PJSUA_MAX_CALLS; ++i)
668
        mSIPState[i] = SIP_NONE;
135 andreas 669
 
670
    mRegistered = false;
671
}
672
 
123 andreas 673
bool TSIPClient::call(const string& dest)
674
{
127 andreas 675
    DECL_TRACER("TSIPClient::call(const string& dest, int)");
123 andreas 676
 
135 andreas 677
    if (dest.empty())
678
    {
679
        MSG_ERROR("No destination defined!");
123 andreas 680
        return false;
135 andreas 681
    }
123 andreas 682
 
135 andreas 683
    if (!mRegistered)
684
    {
685
        MSG_ERROR("Phone core is not registered!");
686
        return false;
687
    }
688
 
127 andreas 689
    int numCalls = getNumberCalls();
123 andreas 690
 
127 andreas 691
    if (numCalls >= 2)
123 andreas 692
    {
127 andreas 693
        MSG_ERROR("There are already " << numCalls << " active!");
694
        return false;
695
    }
696
 
135 andreas 697
    string sUri;
127 andreas 698
 
135 andreas 699
    if (dest.find("sip:") == string::npos)
700
        sUri = "sip:";
701
 
702
    sUri += dest;
141 andreas 703
 
704
    if (sUri.find("@") == string::npos)
705
        sUri += "@" + TConfig::getSIPproxy();
706
 
135 andreas 707
    pj_str_t uri = pj_str((char *)sUri.c_str());
708
    REGISTER_THREAD();
709
    pjsua_call_id cid = PJSUA_INVALID_ID;
710
    pjsua_call_setting call_opt;
711
 
712
    pjsua_call_setting_default(&call_opt);
713
    call_opt.vid_cnt = 0;
714
    mAccountID = pjsua_acc_get_default();
715
 
716
    if (pjsua_call_make_call(mAccountID, &uri, &call_opt, NULL, NULL, &cid) != PJ_SUCCESS)
127 andreas 717
    {
135 andreas 718
        MSG_ERROR("Error calling " << dest << "!");
140 andreas 719
        sendConnectionStatus(SIP_ERROR, cid);
123 andreas 720
        return false;
721
    }
722
 
138 andreas 723
    mLine = cid;
724
    mLastCall = dest;
135 andreas 725
    return true;
123 andreas 726
}
727
 
135 andreas 728
bool TSIPClient::pickup(pjsua_call_id call)
123 andreas 729
{
127 andreas 730
    DECL_TRACER("TSIPClient::pickup(LinphoneCall *call, int)");
123 andreas 731
 
135 andreas 732
    pjsua_call_info ci;
128 andreas 733
 
135 andreas 734
    REGISTER_THREAD();
735
    pjsua_call_get_info(call, &ci);
736
 
737
    if (ci.remote_info.slen > 0)
738
    {
739
        MSG_DEBUG("Incoming call from " << ci.remote_info.ptr);
740
    }
127 andreas 741
    else
125 andreas 742
    {
135 andreas 743
        MSG_DEBUG("Incoming call (" << ci.id << ")");
744
    }
124 andreas 745
 
135 andreas 746
    if (pjsua_call_answer(call, 200, NULL, NULL) != PJ_SUCCESS)
747
    {
748
        MSG_ERROR("Couldn't answer with call ID " << call);
140 andreas 749
        sendConnectionStatus(SIP_ERROR, call);
135 andreas 750
        return false;
125 andreas 751
    }
752
 
138 andreas 753
    mLine = call;
135 andreas 754
    return true;
123 andreas 755
}
756
 
127 andreas 757
bool TSIPClient::terminate(int id)
123 andreas 758
{
127 andreas 759
    DECL_TRACER("TSIPClient::terminate(int)");
123 andreas 760
 
138 andreas 761
    pjsua_call_id cid = id;
762
    REGISTER_THREAD();
128 andreas 763
 
138 andreas 764
    if (!pjsua_call_is_active(cid))
765
    {
766
        MSG_ERROR("No active call at call ID " << id << "!");
123 andreas 767
        return false;
138 andreas 768
    }
123 andreas 769
 
135 andreas 770
    if (pjsua_call_hangup(cid, 200, NULL, NULL) != PJ_SUCCESS)
771
    {
772
        MSG_ERROR("The call " << id << " can't be ended successfull!");
140 andreas 773
        sendConnectionStatus(SIP_ERROR, cid);
135 andreas 774
        return false;
775
    }
776
 
140 andreas 777
    sendConnectionStatus(SIP_DISCONNECTED, cid);
138 andreas 778
    mLine = PJSUA_INVALID_ID;
123 andreas 779
    return true;
780
}
781
 
127 andreas 782
bool TSIPClient::hold(int id)
124 andreas 783
{
127 andreas 784
    DECL_TRACER("TSIPClient::hold(int id)");
124 andreas 785
 
138 andreas 786
    pjsua_call_id cid = id;
787
    REGISTER_THREAD();
135 andreas 788
 
138 andreas 789
    if (!pjsua_call_is_active(cid))
790
    {
791
        MSG_ERROR("No active call at call ID " << id << "!");
128 andreas 792
        return false;
138 andreas 793
    }
128 andreas 794
 
135 andreas 795
    if (pjsua_call_set_hold(cid, NULL) != PJ_SUCCESS)
124 andreas 796
    {
135 andreas 797
        MSG_ERROR("Error setting line " << id << " on hold!");
140 andreas 798
        sendConnectionStatus(SIP_ERROR, cid);
135 andreas 799
        return false;
124 andreas 800
    }
801
 
138 andreas 802
    sendConnectionStatus(SIP_HOLD, cid);
803
    mLine = id;
124 andreas 804
    return false;
805
}
806
 
127 andreas 807
bool TSIPClient::resume(int id)
124 andreas 808
{
127 andreas 809
    DECL_TRACER("TSIPClient::resume(int)");
124 andreas 810
 
138 andreas 811
    pjsua_call_id cid = id;
135 andreas 812
    REGISTER_THREAD();
138 andreas 813
 
814
    if (!pjsua_call_is_active(cid))
815
    {
816
        MSG_ERROR("No active call at call ID " << id << "!");
817
        return false;
818
    }
819
 
820
    if (pjsua_call_set_hold2(cid, PJSUA_CALL_UNHOLD, NULL) != PJ_SUCCESS)
821
    {
822
        MSG_ERROR("Call couldn't be resumed!");
140 andreas 823
        sendConnectionStatus(SIP_ERROR, cid);
138 andreas 824
        return false;
825
    }
826
 
827
    mLine = id;
828
    return true;
124 andreas 829
}
830
 
127 andreas 831
bool TSIPClient::sendDTMF(string& dtmf)
832
{
833
    DECL_TRACER("TSIPClient::sendDTMF(string& dtmf, int id)");
834
 
135 andreas 835
    REGISTER_THREAD();
138 andreas 836
 
837
    if (!pjsua_call_get_count())    // Is there no call active?
838
    {                               // Yes, then treat dtmf as a phone number and call
839
        pj_str_t s = pj_str((char *)dtmf.c_str());
840
 
841
        if (pjsua_call_dial_dtmf(0, &s) != PJ_SUCCESS)
842
        {
843
            MSG_ERROR("Error calling DTMF number " << dtmf << "!");
844
            return false;
845
        }
846
 
847
        sendConnectionStatus(SIP_TRYING, 0);
848
        mLine = 0;
849
        return true;
850
    }
851
 
852
    mLine = getActiveCall();
853
 
854
    pjsua_call_send_dtmf_param d;
855
    d.duration = mDTMFduration;
856
    d.method = PJSUA_DTMF_METHOD_RFC2833;
857
    d.digits = pj_str((char *)dtmf.c_str());
858
 
859
    if (pjsua_call_send_dtmf(mLine, &d) != PJ_SUCCESS)
860
    {
861
        MSG_ERROR("Error sendig DTMF sequence " << dtmf << "!");
862
        return false;
863
    }
864
 
865
    return true;
127 andreas 866
}
867
 
128 andreas 868
bool TSIPClient::sendLinestate()
869
{
870
    DECL_TRACER("TSIPClient::sendLinestate()");
871
 
138 andreas 872
    uint_t maxCalls = pjsua_call_get_max_count();
128 andreas 873
    vector<string> cmds;
874
    cmds.push_back("LINESTATE");
875
 
138 andreas 876
    for (uint_t i = 0; i < maxCalls; ++i)
128 andreas 877
    {
138 andreas 878
        cmds.push_back(to_string(i));
879
 
880
        if (pjsua_call_is_active(i))
881
            cmds.push_back("CONNECTED");
882
        else
883
            cmds.push_back("IDLE");
128 andreas 884
    }
885
 
138 andreas 886
    if (gPageManager)
887
        gPageManager->sendPHN(cmds);
128 andreas 888
 
889
    return true;
890
}
891
 
892
bool TSIPClient::sendPrivate(bool state)
893
{
894
    DECL_TRACER("TSIPClient::sendPrivate(bool state)");
895
 
138 andreas 896
    // FIXME: Enter code to set privacy (DND - do not disturb)
128 andreas 897
    vector<string> cmds;
898
    cmds.push_back("PRIVACY");
899
 
900
    if (state)
901
        cmds.push_back("1");
902
    else
903
        cmds.push_back("0");
904
 
905
    gPageManager->sendPHN(cmds);
138 andreas 906
    mDoNotDisturb = state;
128 andreas 907
    return true;
908
}
909
 
910
bool TSIPClient::redial()
911
{
912
    DECL_TRACER("TSIPClient::redial()");
913
 
138 andreas 914
    if (mLastCall.empty())
915
        return false;
916
 
917
    return call(mLastCall);
135 andreas 918
}
128 andreas 919
 
135 andreas 920
bool TSIPClient::transfer(int id, const string& num)
921
{
922
    DECL_TRACER("TSIPClient::transfer(int id, const string& num)");
923
 
924
    REGISTER_THREAD();
138 andreas 925
 
926
    if (id == PJSUA_INVALID_ID || !pjsua_call_is_active(id))
927
    {
928
        MSG_ERROR("Call ID " << id << " is not an active call!");
929
        return false;
930
    }
931
 
932
    pj_str_t s = pj_str((char *)num.c_str());
933
 
934
    if (pjsua_call_xfer(id, &s, NULL) != PJ_SUCCESS)
935
    {
936
        MSG_ERROR("Call ID " << id << " couldn't be transferred to " << num << "!");
140 andreas 937
        sendConnectionStatus(SIP_ERROR, id);
138 andreas 938
        return false;
939
    }
940
 
140 andreas 941
    sendConnectionStatus(SIP_IDLE, id);
138 andreas 942
    return true;
135 andreas 943
}
944
 
138 andreas 945
bool TSIPClient::setDTMFduration(uint_t ms)
946
{
947
    DECL_TRACER("TSIPClient::setDTMFduration(uint_t ms)");
948
 
949
    if (ms >= 100 && ms <= 3000)
950
        mDTMFduration = ms;
951
 
952
    return true;
953
}
954
 
144 andreas 955
bool TSIPClient::sendIM(const string& target, const string& msg)
956
{
957
    DECL_TRACER("TSIPClient::sendIM(const string& target, const string& msg)");
958
 
959
    pj_str_t mime = pj_str((char *)"text/plain");
960
    pj_str_t to, content;
961
    pjsua_acc_id aid = PJSUA_INVALID_ID;
962
    REGISTER_THREAD();
963
 
964
    if (!target.empty() && !msg.empty())
965
    {
966
        to = pj_str((char *)target.c_str());
967
        content = pj_str((char *)msg.c_str());
968
        MSG_DEBUG("Sending instant message to: " << to.ptr << " [" << content.ptr << "]");
969
 
970
        if ((aid = pjsua_acc_find_for_outgoing(&to)) == PJSUA_INVALID_ID)
971
        {
972
            MSG_ERROR("No account found to send a message from!");
973
            return false;
974
        }
975
    }
976
    else if (!msg.empty())
977
    {
978
        pjsua_call_id cid = getActiveCall();
979
 
980
        if (cid == PJSUA_INVALID_ID)
981
        {
982
            MSG_ERROR("No active call. Can not send a messge!");
983
            return false;
984
        }
985
 
986
        pjsua_call_info cinfo;
987
 
988
        if (pjsua_call_get_info(cid, &cinfo) != PJ_SUCCESS)
989
        {
990
            MSG_ERROR("Error getting call information!");
991
            return false;
992
        }
993
 
994
        aid = cinfo.acc_id;
995
        content = pj_str((char *)msg.c_str());
996
        to = cinfo.remote_info;
997
    }
998
    else
999
        return false;
1000
 
1001
    if (pjsua_im_send(aid, &to, &mime, &content, NULL, NULL) != PJ_SUCCESS)
1002
    {
1003
        MSG_ERROR("Couldn't send a message to " << to.ptr << " (" << msg << ")");
1004
        return false;
1005
    }
1006
 
1007
    return true;
1008
}
1009
 
135 andreas 1010
int TSIPClient::getNumberCalls()
1011
{
1012
    DECL_TRACER("TSIPClient::getNumberCalls()");
1013
 
138 andreas 1014
    return pjsua_call_get_count();
135 andreas 1015
}
1016
 
138 andreas 1017
pjsua_call_id TSIPClient::getActiveCall()
1018
{
1019
    DECL_TRACER("TSIPClient::getActiveCall()");
1020
 
1021
    uint_t maxCalls = pjsua_call_get_max_count();
1022
 
1023
    for (uint_t i = 0; i < maxCalls; ++i)
1024
    {
1025
        if (pjsua_call_is_active(i))
1026
            return i;
1027
    }
1028
 
1029
    return PJSUA_INVALID_ID;
1030
}
1031
 
135 andreas 1032
void TSIPClient::sendConnectionStatus(SIP_STATE_t state, int id)
1033
{
1034
    DECL_TRACER("TSIPClient::sendConnectionStatus(SIP_STATE_t state)");
1035
 
138 andreas 1036
    mMyself->setSIPState(state, id);
1037
 
135 andreas 1038
    if (!gPageManager)
1039
        return;
1040
 
144 andreas 1041
    // If there is an incoming call and the internal phone is activated, this
1042
    // opens the phone dialog and shows the state.
140 andreas 1043
    if (state == SIP_RINGING && TConfig::getSIPiphone() && gPageManager->getShowPhoneDialog())
141 andreas 1044
    {
1045
        pjsua_call_info ci;
1046
 
140 andreas 1047
        gPageManager->getShowPhoneDialog()(true);
141 andreas 1048
        pjsua_call_get_info(id, &ci);
1049
        string number;
1050
        number.assign(ci.remote_info.ptr, ci.remote_info.slen);
1051
        size_t pos;
140 andreas 1052
 
141 andreas 1053
        if ((pos = number.find("\"")) != string::npos)
1054
        {
1055
            size_t pos2 = number.find("\"", pos + 1);
1056
 
1057
            if (pos2 != string::npos)
1058
                number = number.substr(pos + 1, pos2 - pos - 1);
1059
            else
1060
                number = number.substr(pos + 1);
1061
        }
1062
        else if ((pos = number.find("sip:")) != string::npos)
1063
        {
1064
            size_t pos2 = number.find("@");
1065
 
1066
            if (pos2 != string::npos && pos2 > pos)
1067
                number = number.substr(pos + 4, pos2 - (pos + 4));
1068
            else
1069
                number = number.substr(pos + 4);
1070
        }
1071
 
1072
        gPageManager->getSetPhoneNumber()(number);
1073
        gPageManager->getSetPhoneState()(SIP_RINGING, id);
1074
    }
1075
 
144 andreas 1076
    // Here we set the actual state. This is send to the controller, if there
1077
    // is one configured.
135 andreas 1078
    vector<string> cmds;
1079
    cmds.push_back("CALL");
1080
 
1081
    switch(state)
128 andreas 1082
    {
135 andreas 1083
        case SIP_CONNECTED:     cmds.push_back("CONNECTED"); break;
1084
        case SIP_DISCONNECTED:  cmds.push_back("DISCONNECTED"); break;
1085
        case SIP_HOLD:          cmds.push_back("HOLD"); break;
1086
        case SIP_RINGING:       cmds.push_back("RINGING"); break;
1087
        case SIP_TRYING:        cmds.push_back("TRYING"); break;
140 andreas 1088
        case SIP_IDLE:          cmds.push_back("IDLE"); break;
135 andreas 1089
 
1090
        default:
140 andreas 1091
            if (gPageManager->getSetPhoneState())
1092
                gPageManager->getSetPhoneState()(state, id);
1093
 
135 andreas 1094
            return;
128 andreas 1095
    }
1096
 
135 andreas 1097
    cmds.push_back(to_string(id));
1098
    gPageManager->sendPHN(cmds);
140 andreas 1099
 
1100
    if (gPageManager->getSetPhoneState())
1101
        gPageManager->getSetPhoneState()(state, id);
135 andreas 1102
}
1103
 
141 andreas 1104
void TSIPClient::runRinger()
1105
{
1106
    DECL_TRACER("TSIPClient::runRinger()");
1107
 
1108
    init_ringtone_player();
1109
 
1110
    if (start_ring_tone() != PJ_SUCCESS)
1111
    {
1112
        //FIXME:: Add code to free the pool
144 andreas 1113
        pj_pool_release(mRingtonePortInfo.pool);
1114
        mRingtonePortInfo.pool = nullptr;
1115
        mPhoneRingInit = false;
141 andreas 1116
        return;
1117
    }
1118
}
1119
 
1120
void TSIPClient::init_ringtone_player()
1121
{
1122
    DECL_TRACER("TSIPClient::init_ringtone_player()");
1123
 
1124
    int file_slot;
1125
    pj_pool_t *pool;
1126
    pjmedia_port *file_port;
1127
    pj_status_t status;
1128
 
1129
    if (mPhoneRingInit)
1130
        return;
1131
 
1132
    string tone = TConfig::getProjectPath() + "/__system/graphics/sounds/ringtone.wav";
1133
    MSG_DEBUG("Testing for sound file: " << tone);
1134
 
1135
    if (!fs::exists(tone))
1136
    {
1137
        tone = TConfig::getProjectPath() + "/sounds/ringtone.wav";
1138
        MSG_DEBUG("Testing for sound file: " << tone);
1139
 
1140
        if (!fs::exists(tone))
1141
        {
1142
            MSG_ERROR("Couldn't find any ringtone sound file!");
1143
            return;
1144
        }
1145
    }
1146
 
1147
    pool = pjsua_pool_create("wav", 4000, 4000);
1148
    status = pjmedia_wav_player_port_create(pool, tone.c_str(), 0, 0, 0, &file_port);
1149
 
1150
    if (status != PJ_SUCCESS)
1151
    {
1152
        MSG_ERROR("Error creating WAV player port: " << status);
1153
        return;
1154
    }
1155
 
1156
    status = pjsua_conf_add_port(pool, file_port, &file_slot);
1157
 
1158
    if (status != PJ_SUCCESS) {
1159
        MSG_ERROR("Error adding port to conference: " << status);
1160
        return;
1161
    }
1162
 
1163
    mRingtonePortInfo.ring_on = PJ_FALSE;
1164
    mRingtonePortInfo.ring_slot = file_slot;
1165
    mRingtonePortInfo.ring_port = file_port;
144 andreas 1166
 
1167
    if (mRingtonePortInfo.pool)
1168
        pj_pool_release(mRingtonePortInfo.pool);
1169
 
141 andreas 1170
    mRingtonePortInfo.pool = pool;
1171
    mPhoneRingInit = true;
1172
}
1173
 
1174
pj_status_t TSIPClient::start_ring_tone()
1175
{
1176
    DECL_TRACER("TSIPClient::start_ring_tone() ");
1177
 
1178
    pj_status_t status;
1179
 
1180
    if (mRingtonePortInfo.ring_on)
1181
    {
1182
        MSG_DEBUG("Ringtone port already connected");
1183
        return PJ_SUCCESS;
1184
    }
1185
 
1186
    MSG_DEBUG("Starting ringtone");
1187
    status = pjsua_conf_connect(mRingtonePortInfo.ring_slot, 0);
1188
    mRingtonePortInfo.ring_on = PJ_TRUE;
1189
 
1190
    if (status != PJ_SUCCESS)
1191
    {
1192
        MSG_ERROR("Error connecting ringtone port: " << status);
1193
    }
1194
 
1195
    return status;
1196
}
1197
 
1198
pj_status_t TSIPClient::stop_ring_tone()
1199
{
1200
    DECL_TRACER("TSIPClient::stop_ring_tone()");
1201
 
1202
    pj_status_t status;
1203
 
1204
    if (!mRingtonePortInfo.ring_on)
1205
    {
1206
        MSG_DEBUG("Ringtone port already disconnected");
1207
        return PJ_SUCCESS;
1208
    }
1209
 
1210
    MSG_DEBUG("Stopping ringtone");
1211
    status = pjsua_conf_disconnect(mRingtonePortInfo.ring_slot, 0);
1212
    mRingtonePortInfo.ring_on = PJ_FALSE;
1213
 
1214
    if (status != PJ_SUCCESS)
1215
    {
1216
        MSG_ERROR("Error disconnecting ringtone port" << status);
1217
    }
1218
 
1219
    return status;
1220
}
1221
 
144 andreas 1222
pjsua_buddy_id TSIPClient::addBuddy(const string& rsipurl)
1223
{
1224
    DECL_TRACER("TSIPClient::addBuddy(const string& rsipurl)");
1225
 
1226
    // Boddy for IM
1227
    uint_t bcnt = mAppConfig.buddy_cnt + 1;
1228
 
1229
    if (bcnt >= PJSUA_MAX_BUDDIES)
1230
        return PJSUA_INVALID_ID;
1231
 
1232
    pj_str_t uri = pj_str((char *)rsipurl.c_str());
1233
 
1234
    if (pjsua_verify_sip_url(rsipurl.c_str()) != PJ_SUCCESS)
1235
    {
1236
        MSG_ERROR("Invalid SIP URI: " << rsipurl);
1237
        return PJSUA_INVALID_ID;
1238
    }
1239
 
1240
    pjsua_buddy_config *cfg = &mAppConfig.buddy_cfg[bcnt];
1241
    pjsua_buddy_config_default(cfg);
1242
    cfg->uri = uri;
1243
    cfg->subscribe = PJ_FALSE;
1244
    pjsua_buddy_id bid;
1245
 
1246
    if (pjsua_buddy_add(mAppConfig.buddy_cfg, &bid) != PJ_SUCCESS)
1247
    {
1248
        MSG_ERROR("Couldn't create a new buddy for URL " << rsipurl << "!");
1249
        return PJSUA_INVALID_ID;
1250
    }
1251
 
1252
    mAppConfig.buddy_cnt = bcnt;
1253
    return bid;
1254
}
1255
 
1256
TSIPClient::_uri_t TSIPClient::parseUri(const string& uri)
1257
{
1258
    DECL_TRACER("TSIPClient::parseUri(const string& uri)");
1259
 
1260
    size_t pos1, pos2;
1261
    _uri_t u;
1262
 
1263
    pos1 = uri.find("\"");
1264
 
1265
    if (pos1 != string::npos)
1266
    {
1267
        pos2 = uri.find("\"", pos1 + 1);
1268
 
1269
        if (pos2 != string::npos)
1270
            u.name = uri.substr(pos1 + 1, pos2 - pos1 - 1);
1271
    }
1272
 
1273
    pos1 = uri.find("<");
1274
 
1275
    if (pos1 != string::npos)
1276
    {
1277
        pos2 = uri.find(":");
1278
 
1279
        if (pos2 != string::npos)
1280
            u.scheme = uri.substr(pos1 + 1, pos2 - pos1 - 1);
1281
        else
1282
        {
1283
            pos2 = uri.find("@");
1284
 
1285
            if (pos2 != string::npos)
1286
                u.user = uri.substr(pos1 + 1, pos2 - pos1 - 1);
1287
            else
1288
            {
1289
                pos2 = uri.find(">");
1290
 
1291
                if (pos2 != string::npos)
1292
                    u.server = uri.substr(pos1, pos2 - pos1 - 1);
1293
 
1294
                return u;
1295
            }
1296
 
1297
            return u;
1298
        }
1299
 
1300
        pos1 = pos2;
1301
        pos2 = uri.find("@");
1302
 
1303
        if (pos2 != string::npos)
1304
            u.user = uri.substr(pos1 + 1, pos2 - pos1 - 1);
1305
        else
1306
        {
1307
            pos2 = uri.find(">");
1308
 
1309
            if (pos2 != string::npos)
1310
                u.server = uri.substr(pos1, pos2 - pos1 - 1);
1311
            else
1312
                return u;
1313
        }
1314
 
1315
        pos1 = pos2;
1316
        pos2 = uri.find(">");
1317
 
1318
        if (pos2 != string::npos)
1319
            u.server = uri.substr(pos1 + 1, pos2 - pos1 - 1);
1320
        else
1321
            u.server = uri.substr(pos1 + 1);
1322
    }
1323
 
1324
    return u;
1325
}
1326
 
135 andreas 1327
/*******************************************************************************
1328
 * All the following functions are static callback functions.
1329
 * The following functions are called by the PJSUA-library for different
1330
 * events.
1331
 ******************************************************************************/
1332
 
1333
void TSIPClient::_log_call(int level, const char *data, int len)
1334
{
1335
    string msg;
1336
    msg.assign(data, len);
1337
 
1338
    switch(level)
128 andreas 1339
    {
135 andreas 1340
        case 0: MSG_ERROR("FATAL:" << msg); break;
1341
        case 1: MSG_ERROR(msg); break;
1342
        case 2: MSG_WARNING(msg); break;
1343
        case 3: MSG_INFO(msg); break;
1344
        default:
1345
            MSG_DEBUG(msg);
1346
    }
1347
}
128 andreas 1348
 
135 andreas 1349
void TSIPClient::ringback_start(pjsua_call_id call_id)
1350
{
1351
    DECL_TRACER("TSIPClient::ringback_start(pjsua_call_id call_id)");
128 andreas 1352
 
135 andreas 1353
    if (mAppConfig.call_data[call_id].ringback_on)
1354
        return;
1355
 
1356
    mAppConfig.call_data[call_id].ringback_on = PJ_TRUE;
1357
 
141 andreas 1358
    if (++mAppConfig.ringback_cnt == 1 && mAppConfig.ringback_slot != PJSUA_INVALID_ID)
135 andreas 1359
    {
1360
        pjsua_conf_connect(mAppConfig.ringback_slot, 0);
128 andreas 1361
    }
135 andreas 1362
}
128 andreas 1363
 
135 andreas 1364
void TSIPClient::ring_stop(pjsua_call_id call_id)
1365
{
1366
    DECL_TRACER("TSIPClient::ring_stop(pjsua_call_id call_id)");
1367
 
1368
    if (mAppConfig.no_tones)
1369
        return;
1370
 
1371
    if (mAppConfig.call_data[call_id].ringback_on)
128 andreas 1372
    {
135 andreas 1373
        mAppConfig.call_data[call_id].ringback_on = PJ_FALSE;
1374
 
1375
        pj_assert(mAppConfig.ringback_cnt > 0);
1376
 
1377
        if (--mAppConfig.ringback_cnt == 0 && mAppConfig.ringback_slot != PJSUA_INVALID_ID)
1378
        {
1379
            pjsua_conf_disconnect(mAppConfig.ringback_slot, 0);
1380
            pjmedia_tonegen_rewind(mAppConfig.ringback_port);
1381
        }
128 andreas 1382
    }
1383
 
135 andreas 1384
    if (mAppConfig.call_data[call_id].ring_on)
1385
    {
1386
        mAppConfig.call_data[call_id].ring_on = PJ_FALSE;
128 andreas 1387
 
141 andreas 1388
        pj_assert(mAppConfig.ring_cnt > 0);
135 andreas 1389
 
1390
        if (--mAppConfig.ring_cnt == 0 && mAppConfig.ring_slot != PJSUA_INVALID_ID)
1391
        {
1392
            pjsua_conf_disconnect(mAppConfig.ring_slot, 0);
1393
            pjmedia_tonegen_rewind(mAppConfig.ring_port);
1394
        }
1395
    }
1396
}
1397
 
1398
void TSIPClient::ring_start(pjsua_call_id call_id)
1399
{
1400
    DECL_TRACER("TSIPClient::ring_start(pjsua_call_id call_id)");
1401
 
1402
    if (mAppConfig.no_tones)
1403
        return;
1404
 
1405
    if (mAppConfig.call_data[call_id].ring_on)
1406
        return;
1407
 
1408
    mAppConfig.call_data[call_id].ring_on = PJ_TRUE;
1409
 
141 andreas 1410
    if (++mAppConfig.ring_cnt == 1 && mAppConfig.ring_slot != PJSUA_INVALID_ID)
128 andreas 1411
    {
135 andreas 1412
        pjsua_conf_connect(mAppConfig.ring_slot, 0);
128 andreas 1413
    }
135 andreas 1414
}
128 andreas 1415
 
135 andreas 1416
pj_bool_t TSIPClient::find_next_call(void)
1417
{
1418
    int i, max;
128 andreas 1419
 
135 andreas 1420
    max = pjsua_call_get_max_count();
1421
 
1422
    for (i = mCurrentCall + 1; i < max; ++i)
128 andreas 1423
    {
135 andreas 1424
        if (pjsua_call_is_active(i))
1425
        {
1426
            mCurrentCall = i;
1427
            return PJ_TRUE;
1428
        }
128 andreas 1429
    }
1430
 
135 andreas 1431
    for (i = 0; i < mCurrentCall; ++i)
1432
    {
1433
        if (pjsua_call_is_active(i))
1434
        {
1435
            mCurrentCall = i;
1436
            return PJ_TRUE;
1437
        }
1438
    }
1439
 
1440
    mCurrentCall = PJSUA_INVALID_ID;
1441
    return PJ_FALSE;
128 andreas 1442
}
1443
 
135 andreas 1444
void TSIPClient::call_timeout_callback(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)
128 andreas 1445
{
135 andreas 1446
    DECL_TRACER("TSIPClient::call_timeout_callback(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)");
128 andreas 1447
 
135 andreas 1448
    pjsua_call_id call_id = entry->id;
1449
    pjsua_msg_data msg_data_;
1450
    pjsip_generic_string_hdr warn;
1451
    pj_str_t hname = pj_str((char *)"Warning");
1452
    pj_str_t hvalue = pj_str((char *)"399 pjsua \"Call duration exceeded\"");
128 andreas 1453
 
135 andreas 1454
    PJ_UNUSED_ARG(timer_heap);
128 andreas 1455
 
135 andreas 1456
    if (call_id == PJSUA_INVALID_ID)
128 andreas 1457
    {
135 andreas 1458
        MSG_WARNING("Invalid call ID in timer callback");
1459
        return;
128 andreas 1460
    }
1461
 
135 andreas 1462
    /* Add warning header */
1463
    pjsua_msg_data_init(&msg_data_);
1464
    pjsip_generic_string_hdr_init2(&warn, &hname, &hvalue);
1465
    pj_list_push_back(&msg_data_.hdr_list, &warn);
1466
 
1467
    /* Call duration has been exceeded; disconnect the call */
1468
    MSG_WARNING("Duration (" << mAppConfig.duration << " seconds) has been exceeded for call " << call_id << ", disconnecting the call,");
1469
    entry->id = PJSUA_INVALID_ID;
1470
    pjsua_call_hangup(call_id, 200, NULL, &msg_data_);
1471
    sendConnectionStatus(SIP_DISCONNECTED, call_id);
128 andreas 1472
}
1473
 
135 andreas 1474
void TSIPClient::on_playfile_done(pjmedia_port *port, void *usr_data)
123 andreas 1475
{
135 andreas 1476
    DECL_TRACER("TSIPClient::on_playfile_done(pjmedia_port *port, void *usr_data)");
123 andreas 1477
 
135 andreas 1478
    pj_time_val delay;
123 andreas 1479
 
135 andreas 1480
    PJ_UNUSED_ARG(port);
1481
    PJ_UNUSED_ARG(usr_data);
123 andreas 1482
 
135 andreas 1483
    /* Just rewind WAV when it is played outside of call */
138 andreas 1484
    if (pjsua_call_get_count() == 0)
1485
    {
135 andreas 1486
        pjsua_player_set_pos(mAppConfig.wav_id, 0);
1487
    }
1488
 
1489
    /* Timer is already active */
1490
    if (mAppConfig.auto_hangup_timer.id == 1)
1491
        return;
1492
 
1493
    mAppConfig.auto_hangup_timer.id = 1;
1494
    delay.sec = 0;
1495
    delay.msec = 200; /* Give 200 ms before hangup */
1496
    pjsip_endpt_schedule_timer(pjsua_get_pjsip_endpt(), &mAppConfig.auto_hangup_timer, &delay);
123 andreas 1497
}
1498
 
135 andreas 1499
void TSIPClient::hangup_timeout_callback(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)
123 andreas 1500
{
135 andreas 1501
    DECL_TRACER("TSIPClient::hangup_timeout_callback(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)");
123 andreas 1502
 
135 andreas 1503
    PJ_UNUSED_ARG(timer_heap);
1504
    PJ_UNUSED_ARG(entry);
123 andreas 1505
 
135 andreas 1506
    mAppConfig.auto_hangup_timer.id = 0;
1507
    pjsua_call_hangup_all();
1508
}
123 andreas 1509
 
135 andreas 1510
/* Callback called by the library upon receiving incoming call */
1511
void TSIPClient::on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_rx_data *rdata)
1512
{
1513
    DECL_TRACER("on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_rx_data *rdata)");
1514
 
1515
    pjsua_call_info ci;
1516
 
1517
    PJ_UNUSED_ARG(acc_id);
1518
    PJ_UNUSED_ARG(rdata);
1519
 
1520
    pjsua_call_get_info(call_id, &ci);
1521
 
1522
    MSG_DEBUG("Incoming call from " << ci.remote_info.ptr);
138 andreas 1523
    sendConnectionStatus(SIP_RINGING, call_id);
135 andreas 1524
 
1525
    if (gPageManager && gPageManager->getPHNautoanswer() && mMyself)
144 andreas 1526
        mMyself->pickup(call_id);   // Automatically answer incoming calls with 200/OK
141 andreas 1527
    else if (mMyself)
144 andreas 1528
        mMyself->runRinger();       // Start the ring tone
123 andreas 1529
}
1530
 
135 andreas 1531
/* Callback called by the library when call's state has changed */
1532
void TSIPClient::on_call_state(pjsua_call_id call_id, pjsip_event *e)
127 andreas 1533
{
135 andreas 1534
    DECL_TRACER("on_call_state(pjsua_call_id call_id, pjsip_event *e)");
127 andreas 1535
 
135 andreas 1536
    pjsua_call_info ci;
127 andreas 1537
 
135 andreas 1538
    pjsua_call_get_info(call_id, &ci);
127 andreas 1539
 
135 andreas 1540
    if (ci.state == PJSIP_INV_STATE_DISCONNECTED)
1541
    {
1542
        /* Stop all ringback for this call */
1543
        ring_stop(call_id);
127 andreas 1544
 
141 andreas 1545
        if (mPhoneRingInit)
1546
            stop_ring_tone();
1547
 
135 andreas 1548
        /* Cancel duration timer, if any */
1549
        if (mAppConfig.call_data[call_id].timer.id != PJSUA_INVALID_ID)
1550
        {
1551
            app_call_data *cd = &mAppConfig.call_data[call_id];
1552
            pjsip_endpoint *endpt = pjsua_get_pjsip_endpt();
1553
 
1554
            cd->timer.id = PJSUA_INVALID_ID;
1555
            pjsip_endpt_cancel_timer(endpt, &cd->timer);
1556
        }
1557
 
1558
        /* Rewind play file when hangup automatically,
1559
         * since file is not looped
1560
         */
1561
        if (mAppConfig.auto_play_hangup)
1562
            pjsua_player_set_pos(mAppConfig.wav_id, 0);
1563
 
1564
        string dbgMsg;
1565
 
1566
        if (ci.last_status_text.slen > 0)
1567
            dbgMsg.assign(ci.last_status_text.ptr, ci.last_status_text.slen);
1568
 
1569
        MSG_DEBUG("Call " << call_id << " disconnected [reason: " << ci.last_status << " (" << dbgMsg << ")]");
138 andreas 1570
        sendConnectionStatus(SIP_DISCONNECTED, call_id);
135 andreas 1571
 
1572
        if (call_id == mCurrentCall)
1573
        {
1574
            find_next_call();
1575
        }
1576
    }
1577
    else
127 andreas 1578
    {
135 andreas 1579
        if (mAppConfig.duration != PJSUA_APP_NO_LIMIT_DURATION && ci.state == PJSIP_INV_STATE_CONFIRMED)
127 andreas 1580
        {
135 andreas 1581
            /* Schedule timer to hangup call after the specified duration */
1582
            app_call_data *cd = &mAppConfig.call_data[call_id];
1583
            pjsip_endpoint *endpt = pjsua_get_pjsip_endpt();
1584
            pj_time_val delay;
1585
 
1586
            cd->timer.id = call_id;
1587
            delay.sec = mAppConfig.duration;
1588
            delay.msec = 0;
1589
            pjsip_endpt_schedule_timer(endpt, &cd->timer, &delay);
127 andreas 1590
        }
1591
 
135 andreas 1592
        if (ci.state == PJSIP_INV_STATE_EARLY)
1593
        {
1594
            int code;
1595
            pj_str_t reason;
1596
            pjsip_msg *msg;
1597
 
1598
            /* This can only occur because of TX or RX message */
1599
            pj_assert(e->type == PJSIP_EVENT_TSX_STATE);
1600
 
138 andreas 1601
            if (e->body.tsx_state.type == PJSIP_EVENT_RX_MSG)
1602
            {
135 andreas 1603
                msg = e->body.tsx_state.src.rdata->msg_info.msg;
138 andreas 1604
            }
1605
            else
1606
            {
135 andreas 1607
                msg = e->body.tsx_state.src.tdata->msg;
1608
            }
1609
 
1610
            code = msg->line.status.code;
1611
            reason = msg->line.status.reason;
1612
 
1613
            /* Start ringback for 180 for UAC unless there's SDP in 180 */
1614
            if (ci.role == PJSIP_ROLE_UAC && code == 180 && msg->body == NULL && ci.media_status == PJSUA_CALL_MEDIA_NONE)
1615
            {
1616
                ringback_start(call_id);
1617
            }
1618
 
1619
            string dbgMsg;
1620
            string dbgCode;
1621
 
1622
            if (ci.state_text.slen > 0)
1623
                dbgMsg.assign(ci.state_text.ptr, ci.state_text.slen);
1624
 
1625
            if (reason.slen > 0)
1626
                dbgCode.assign(reason.ptr, reason.slen);
1627
 
1628
            MSG_DEBUG("Call " << call_id << " state changed to " << dbgMsg << " (" << code << " " << dbgCode << ")");
1629
        }
1630
        else
1631
        {
1632
            string dbgMsg;
1633
 
1634
            if (ci.state_text.slen > 0)
1635
                dbgMsg.assign(ci.state_text.ptr, ci.state_text.slen);
1636
 
1637
            MSG_DEBUG("Call " << call_id << " state changed to " << dbgMsg);
141 andreas 1638
 
1639
            if (ci.state == PJSIP_INV_STATE_CONNECTING || ci.state == PJSIP_INV_STATE_CALLING)
1640
                sendConnectionStatus(SIP_TRYING, call_id);
1641
            else if (ci.state == PJSIP_INV_STATE_INCOMING)
1642
                sendConnectionStatus(SIP_RINGING, call_id);
1643
            else if (ci.state == PJSIP_INV_STATE_CONFIRMED)
1644
            {
1645
                ring_stop(call_id);
1646
 
1647
                if (mPhoneRingInit)
1648
                    stop_ring_tone();
1649
 
1650
                sendConnectionStatus(SIP_CONNECTED, call_id);
1651
            }
135 andreas 1652
        }
1653
 
1654
        if (mCurrentCall == PJSUA_INVALID_ID)
1655
            mCurrentCall = call_id;
127 andreas 1656
    }
1657
}
1658
 
135 andreas 1659
/* Callback called by the library when call's media state has changed */
1660
void TSIPClient::on_call_media_state(pjsua_call_id call_id)
127 andreas 1661
{
135 andreas 1662
    DECL_TRACER("on_call_media_state(pjsua_call_id call_id)");
127 andreas 1663
 
135 andreas 1664
    pjsua_call_info ci;
127 andreas 1665
 
135 andreas 1666
    pjsua_call_get_info(call_id, &ci);
127 andreas 1667
 
135 andreas 1668
    if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE)
1669
    {
1670
        // When media is active, connect call to sound device.
1671
        pjsua_conf_connect(ci.conf_slot, 0);
1672
        pjsua_conf_connect(0, ci.conf_slot);
1673
    }
1674
}
127 andreas 1675
 
135 andreas 1676
void TSIPClient::call_on_dtmf_callback2(pjsua_call_id call_id, const pjsua_dtmf_info *info)
1677
{
1678
    DECL_TRACER("TSIPClient::call_on_dtmf_callback2(pjsua_call_id call_id, const pjsua_dtmf_info *info)");
127 andreas 1679
 
135 andreas 1680
    char duration[16];
1681
    char method[16];
1682
 
1683
    duration[0] = '\0';
1684
 
1685
    switch (info->method)
127 andreas 1686
    {
135 andreas 1687
        case PJSUA_DTMF_METHOD_RFC2833:
1688
            pj_ansi_snprintf(method, sizeof(method), "RFC2833");
1689
        break;
127 andreas 1690
 
135 andreas 1691
        case PJSUA_DTMF_METHOD_SIP_INFO:
1692
            pj_ansi_snprintf(method, sizeof(method), "SIP INFO");
1693
            pj_ansi_snprintf(duration, sizeof(duration), ":duration(%d)", info->duration);
1694
        break;
127 andreas 1695
    }
1696
 
135 andreas 1697
    MSG_DEBUG("Incoming DTMF on call " << call_id << ": " << info->digit << duration << ", using " << method << " method.");
127 andreas 1698
}
1699
 
135 andreas 1700
pjsip_redirect_op TSIPClient::call_on_redirected(pjsua_call_id call_id, const pjsip_uri *target, const pjsip_event *e)
127 andreas 1701
{
135 andreas 1702
    DECL_TRACER("TSIPClient::call_on_redirected(pjsua_call_id call_id, const pjsip_uri *target, const pjsip_event *e)");
127 andreas 1703
 
135 andreas 1704
    PJ_UNUSED_ARG(e);
127 andreas 1705
 
135 andreas 1706
    if (mAppConfig.redir_op == PJSIP_REDIRECT_PENDING)
1707
    {
1708
        char uristr[PJSIP_MAX_URL_SIZE];
1709
        int len;
127 andreas 1710
 
135 andreas 1711
        len = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, target, uristr, sizeof(uristr));
127 andreas 1712
 
135 andreas 1713
        if (len < 1)
1714
        {
1715
            pj_ansi_strcpy(uristr, "--URI too long--");
1716
        }
1717
 
1718
        string dbgMsg;
1719
 
1720
        if (len > 0)
1721
            dbgMsg.assign(uristr, len);
1722
 
1723
        MSG_DEBUG("Call " << call_id << " is being redirected to " << dbgMsg << ".");
138 andreas 1724
 
1725
        if (gPageManager)
140 andreas 1726
        {
1727
            vector<string>cmds;
1728
            cmds.push_back("TRANSFERRED");
1729
            cmds.push_back(to_string(call_id));
138 andreas 1730
            gPageManager->sendPHN(cmds);
140 andreas 1731
            sendConnectionStatus(SIP_IDLE, call_id);
1732
        }
127 andreas 1733
    }
1734
 
135 andreas 1735
    return mAppConfig.redir_op;
127 andreas 1736
}
1737
 
135 andreas 1738
void TSIPClient::on_call_transfer_status(pjsua_call_id call_id, int status_code, const pj_str_t *status_text, pj_bool_t final, pj_bool_t *p_cont)
123 andreas 1739
{
135 andreas 1740
    DECL_TRACER("TSIPClient::on_call_transfer_status(pjsua_call_id call_id, int status_code, const pj_str_t *status_text, pj_bool_t final, pj_bool_t *p_cont)");
123 andreas 1741
 
135 andreas 1742
    string dbgMsg;
123 andreas 1743
 
135 andreas 1744
    if (status_text->slen > 0)
1745
        dbgMsg.assign(status_text->ptr, status_text->slen);
123 andreas 1746
 
135 andreas 1747
    MSG_DEBUG("Call " << call_id << ": transfer status: " << status_code << " (" << dbgMsg << ") " << (final ? "[final]" : ""));
1748
 
1749
    if ((status_code / 100) == 2)
1750
    {
1751
        MSG_DEBUG("Call " << call_id << ": Call transferred successfully, disconnecting call.");
1752
        pjsua_call_hangup(call_id, PJSIP_SC_GONE, NULL, NULL);
1753
        *p_cont = PJ_FALSE;
1754
 
1755
        if (gPageManager)
1756
        {
1757
            vector<string> cmds;
1758
            cmds.push_back("TRANSFERRED");
1759
            cmds.push_back(to_string(call_id));
1760
            gPageManager->sendPHN(cmds);
138 andreas 1761
            cmds.clear();
1762
            cmds.push_back("DISCONNECTED");
1763
            cmds.push_back(to_string(call_id));
1764
            gPageManager->sendPHN(cmds);
135 andreas 1765
        }
1766
    }
123 andreas 1767
}
1768
 
135 andreas 1769
void TSIPClient::on_transport_state(pjsip_transport *tp, pjsip_transport_state state, const pjsip_transport_state_info *info)
123 andreas 1770
{
135 andreas 1771
    DECL_TRACER("TSIPClient::on_transport_state(pjsip_transport *tp, pjsip_transport_state state, const pjsip_transport_state_info *info)");
123 andreas 1772
 
135 andreas 1773
    char host_port[128];
1774
 
1775
    pj_addr_str_print(&tp->remote_name.host, tp->remote_name.port, host_port, sizeof(host_port), 1);
1776
 
1777
    switch (state)
123 andreas 1778
    {
135 andreas 1779
        case PJSIP_TP_STATE_CONNECTED:
1780
            MSG_DEBUG("SIP " << tp->type_name << " transport is connected to " << host_port);
1781
        break;
123 andreas 1782
 
135 andreas 1783
        case PJSIP_TP_STATE_DISCONNECTED:
1784
        {
1785
            char buf[100];
1786
            size_t len;
124 andreas 1787
 
135 andreas 1788
            len = pj_ansi_snprintf(buf, sizeof(buf), "SIP %s transport is disconnected from %s", tp->type_name, host_port);
1789
            PJ_CHECK_TRUNC_STR(len, buf, sizeof(buf));
1790
            MSG_ERROR(buf << " (" << info->status << ")");
1791
        }
1792
        break;
1793
 
1794
        default:
1795
            break;
124 andreas 1796
    }
135 andreas 1797
}
124 andreas 1798
 
135 andreas 1799
void TSIPClient::on_ip_change_progress(pjsua_ip_change_op op, pj_status_t status, const pjsua_ip_change_op_info *info)
1800
{
1801
    DECL_TRACER("TSIPClient::on_ip_change_progress(pjsua_ip_change_op op, pj_status_t status, const pjsua_ip_change_op_info *info)");
123 andreas 1802
 
135 andreas 1803
    char info_str[128];
1804
    pjsua_acc_info acc_info;
1805
    pjsua_transport_info tp_info;
1806
 
1807
    if (status == PJ_SUCCESS)
123 andreas 1808
    {
135 andreas 1809
        switch (op)
1810
        {
1811
            case PJSUA_IP_CHANGE_OP_RESTART_LIS:
1812
                pjsua_transport_get_info(info->lis_restart.transport_id, &tp_info);
1813
                pj_ansi_snprintf(info_str, sizeof(info_str),
1814
                                 "restart transport %.*s",
1815
                                 (int)tp_info.info.slen, tp_info.info.ptr);
1816
            break;
124 andreas 1817
 
135 andreas 1818
            case PJSUA_IP_CHANGE_OP_ACC_SHUTDOWN_TP:
1819
                pjsua_acc_get_info(info->acc_shutdown_tp.acc_id, &acc_info);
127 andreas 1820
 
135 andreas 1821
                pj_ansi_snprintf(info_str, sizeof(info_str),
1822
                                 "transport shutdown for account %.*s",
1823
                                 (int)acc_info.acc_uri.slen,
1824
                                 acc_info.acc_uri.ptr);
1825
            break;
127 andreas 1826
 
135 andreas 1827
            case PJSUA_IP_CHANGE_OP_ACC_UPDATE_CONTACT:
1828
                pjsua_acc_get_info(info->acc_shutdown_tp.acc_id, &acc_info);
1829
                if (info->acc_update_contact.code) {
1830
                    pj_ansi_snprintf(info_str, sizeof(info_str),
1831
                                     "update contact for account %.*s, code[%d]",
1832
                                     (int)acc_info.acc_uri.slen,
1833
                                     acc_info.acc_uri.ptr,
1834
                                     info->acc_update_contact.code);
1835
                } else {
1836
                    pj_ansi_snprintf(info_str, sizeof(info_str),
1837
                                     "update contact for account %.*s",
1838
                                     (int)acc_info.acc_uri.slen,
1839
                                     acc_info.acc_uri.ptr);
1840
                }
1841
            break;
127 andreas 1842
 
135 andreas 1843
            case PJSUA_IP_CHANGE_OP_ACC_HANGUP_CALLS:
1844
                pjsua_acc_get_info(info->acc_shutdown_tp.acc_id, &acc_info);
1845
                pj_ansi_snprintf(info_str, sizeof(info_str),
1846
                                 "hangup call for account %.*s, call_id[%d]",
1847
                                 (int)acc_info.acc_uri.slen, acc_info.acc_uri.ptr,
1848
                                 info->acc_hangup_calls.call_id);
1849
            break;
123 andreas 1850
 
135 andreas 1851
            case PJSUA_IP_CHANGE_OP_ACC_REINVITE_CALLS:
1852
                pjsua_acc_get_info(info->acc_shutdown_tp.acc_id, &acc_info);
1853
                pj_ansi_snprintf(info_str, sizeof(info_str),
1854
                                 "reinvite call for account %.*s, call_id[%d]",
1855
                                 (int)acc_info.acc_uri.slen, acc_info.acc_uri.ptr,
1856
                                 info->acc_reinvite_calls.call_id);
1857
            break;
127 andreas 1858
 
135 andreas 1859
            case PJSUA_IP_CHANGE_OP_COMPLETED:
1860
                pj_ansi_snprintf(info_str, sizeof(info_str), "done");
123 andreas 1861
 
135 andreas 1862
            default:
1863
                break;
1864
        }
123 andreas 1865
 
135 andreas 1866
        MSG_DEBUG("IP change progress report: " << info_str);
1867
    }
1868
    else
1869
    {
1870
        MSG_ERROR("IP change progress failed (" << status << ")");
1871
    }
1872
}
124 andreas 1873
 
144 andreas 1874
void TSIPClient::on_pager2(pjsua_call_id call_id, const pj_str_t* from, const pj_str_t* to, const pj_str_t* contact, const pj_str_t* mime_type, const pj_str_t* body, pjsip_rx_data* rdata, pjsua_acc_id acc_id)
1875
{
1876
    DECL_TRACER("TSIPClient::on_pager2(pjsua_call_id call_id, const pj_str_t* from, const pj_str_t* to, const pj_str_t* contact, const pj_str_t* mime_type, const pj_str_t* body, pjsip_rx_data* rdata, pjsua_acc_id acc_id)");
1877
 
1878
    PJ_UNUSED_ARG(contact);
1879
    PJ_UNUSED_ARG(rdata);
1880
 
1881
    string sFrom(from->ptr, from->slen);
1882
    string sTo(to->ptr, to->slen);
1883
    string mime(mime_type->ptr, mime_type->slen);
1884
    string bdy(body->ptr, body->slen);
1885
 
1886
    MSG_DEBUG("Received message for ID " << call_id << " from " << sFrom << ", to " << sTo << " (" << acc_id << ") with mime type " << mime << ": " << bdy);
1887
 
1888
    if (acc_id == PJSUA_INVALID_ID)
1889
    {
1890
        MSG_ERROR("Invalid account ID: " << acc_id);
1891
        return;
1892
    }
1893
 
1894
    if (mime != "text/plain")
1895
    {
1896
        MSG_ERROR("Unknown mime type " << mime);
1897
        return;
1898
    }
1899
 
1900
    _uri_t u = parseUri(from->ptr);
1901
 
1902
    vector<string> cmds;
1903
    cmds.push_back("IM");
1904
    cmds.push_back(u.user + "@" + u.server);
1905
 
1906
    if (bdy.length() > 256)
1907
        bdy = bdy.substr(0, 256);
1908
 
1909
    cmds.push_back(bdy);
1910
 
1911
    if (gPageManager)
1912
        gPageManager->sendPHN(cmds);
1913
}
1914
 
1915
void TSIPClient::on_buddy_state(pjsua_buddy_id buddy_id)
1916
{
1917
    DECL_TRACER("TSIPClient::on_buddy_state(pjsua_buddy_id buddy_id)");
1918
 
1919
    pjsua_buddy_info binfo;
1920
 
1921
    if (pjsua_buddy_get_info(buddy_id, &binfo) != PJ_SUCCESS)
1922
    {
1923
        MSG_ERROR("Error retrieving buddy information for buddy ID " << buddy_id);
1924
        return;
1925
    }
1926
 
1927
    switch(binfo.status)
1928
    {
1929
        case PJSUA_BUDDY_STATUS_ONLINE:
1930
            MSG_DEBUG("Buddy " << buddy_id << ": " << binfo.contact.ptr << " is online.");
1931
        break;
1932
 
1933
        case PJSUA_BUDDY_STATUS_OFFLINE:
1934
            MSG_DEBUG("Buddy " << buddy_id << ": " << binfo.contact.ptr << " is offline.");
1935
        break;
1936
 
1937
        default:
1938
            MSG_DEBUG("Buddy " << buddy_id << ": " << binfo.contact.ptr << " is unknown.");
1939
    }
1940
}
1941
void TSIPClient::on_buddy_evsub_state(pjsua_buddy_id buddy_id, pjsip_evsub* sub, pjsip_event* event)
1942
{
1943
    DECL_TRACER("TSIPClient::on_buddy_evsub_state(pjsua_buddy_id buddy_id, pjsip_evsub* sub, pjsip_event* event)");
1944
 
1945
    char event_info[80];
1946
 
1947
    if (event->type == PJSIP_EVENT_RX_MSG)
1948
    {
1949
        pjsip_rx_data *rdata = event->body.tsx_state.src.rdata;
1950
        snprintf(event_info, sizeof(event_info), " (RX %s)", pjsip_rx_data_get_info(rdata));
1951
        MSG_DEBUG("Budyy event for ID " << buddy_id << ":" << event_info);
1952
    }
1953
    else
1954
        event_info[0] = 0;
1955
 
1956
    MSG_DEBUG("Buddy " << buddy_id << ": subscription state: " << pjsip_evsub_get_state_name(sub) << " (event: " << pjsip_event_str(event->type) << event_info << ")");
1957
}
1958
 
1959
void TSIPClient::on_mwi_info(pjsua_acc_id acc_id, pjsua_mwi_info* mwi_info)
1960
{
1961
    DECL_TRACER("TSIPClient::on_mwi_info(pjsua_acc_id acc_id, pjsua_mwi_info* mwi_info)");
1962
 
1963
    MSG_INFO("Received MWI for acc " << acc_id);
1964
    vector<string>cmds;
1965
    cmds.push_back("IM");
1966
 
1967
    if (mwi_info->rdata->msg_info.ctype)
1968
    {
1969
        const pjsip_ctype_hdr *ctype = mwi_info->rdata->msg_info.ctype;
1970
        string msg(ctype->media.subtype.ptr, ctype->media.subtype.slen);
1971
        MSG_INFO("Content-Type: " << ctype->media.type.ptr << "/" << msg);
1972
        const pjsip_from_hdr *from = mwi_info->rdata->msg_info.from;
1973
 
1974
        cmds.push_back((char *)pjsip_uri_get_uri(from->uri));
1975
    }
1976
    else
1977
        cmds.push_back("sip:?@" + TConfig::getSIPproxy());
1978
 
1979
    if (!mwi_info->rdata->msg_info.msg->body)
1980
    {
1981
        MSG_INFO("No message body!");
1982
        return;
1983
    }
1984
 
1985
    string body((char *)mwi_info->rdata->msg_info.msg->body->data, mwi_info->rdata->msg_info.msg->body->len);
1986
 
1987
    if (body.length() > 256)
1988
        cmds.push_back(body.substr(0, 256));
1989
    else
1990
        cmds.push_back(body);
1991
 
1992
    MSG_INFO("Body:" << std::endl << body);
1993
 
1994
    if (gPageManager)
1995
        gPageManager->sendPHN(cmds);
1996
}
1997
 
135 andreas 1998
/*
1999
 * A simple registrar, invoked by default_mod_on_rx_request()
2000
 */
2001
void TSIPClient::simple_registrar(pjsip_rx_data *rdata)
2002
{
144 andreas 2003
    DECL_TRACER("TSIPClient::simple_registrar(pjsip_rx_data *rdata)");
2004
 
135 andreas 2005
    pjsip_tx_data *tdata;
2006
    const pjsip_expires_hdr *exp;
2007
    const pjsip_hdr *h;
2008
    unsigned cnt = 0;
2009
    pjsip_generic_string_hdr *srv;
2010
    pj_status_t status;
123 andreas 2011
 
135 andreas 2012
    status = pjsip_endpt_create_response(pjsua_get_pjsip_endpt(), rdata, 200, NULL, &tdata);
123 andreas 2013
 
135 andreas 2014
    if (status != PJ_SUCCESS)
2015
        return;
123 andreas 2016
 
135 andreas 2017
    exp = (pjsip_expires_hdr *)pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, NULL);
2018
 
2019
    h = rdata->msg_info.msg->hdr.next;
2020
 
2021
    while (h != &rdata->msg_info.msg->hdr)
2022
    {
2023
        if (h->type == PJSIP_H_CONTACT)
128 andreas 2024
        {
135 andreas 2025
            const pjsip_contact_hdr *c = (const pjsip_contact_hdr*)h;
2026
            unsigned e = c->expires;
123 andreas 2027
 
135 andreas 2028
            if (e != PJSIP_EXPIRES_NOT_SPECIFIED)
128 andreas 2029
            {
135 andreas 2030
                if (exp)
2031
                    e = exp->ivalue;
2032
                else
2033
                    e = 3600;
128 andreas 2034
            }
2035
 
135 andreas 2036
            if (e > 0)
2037
            {
2038
                pjsip_contact_hdr *nc = (pjsip_contact_hdr *)pjsip_hdr_clone(tdata->pool, h);
2039
                nc->expires = e;
2040
                pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)nc);
2041
                ++cnt;
2042
            }
128 andreas 2043
        }
123 andreas 2044
 
135 andreas 2045
        h = h->next;
123 andreas 2046
    }
2047
 
135 andreas 2048
    srv = pjsip_generic_string_hdr_create(tdata->pool, NULL, NULL);
2049
    srv->name = pj_str((char *)"Server");
2050
    srv->hvalue = pj_str((char *)"pjsua simple registrar");
2051
    pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)srv);
2052
 
2053
    status = pjsip_endpt_send_response2(pjsua_get_pjsip_endpt(), rdata, tdata, NULL, NULL);
2054
 
2055
    if (status != PJ_SUCCESS)
2056
        pjsip_tx_data_dec_ref(tdata);
123 andreas 2057
}
124 andreas 2058
 
135 andreas 2059
/*****************************************************************************
2060
 * A simple module to handle otherwise unhandled request. We will register
2061
 * this with the lowest priority.
2062
 */
2063
 
2064
/* Notification on incoming request */
2065
pj_bool_t TSIPClient::default_mod_on_rx_request(pjsip_rx_data *rdata)
124 andreas 2066
{
144 andreas 2067
    DECL_TRACER("TSIPClient::default_mod_on_rx_request(pjsip_rx_data *rdata)");
2068
 
135 andreas 2069
    pjsip_tx_data *tdata;
2070
    pjsip_status_code status_code;
2071
    pj_status_t status;
124 andreas 2072
 
135 andreas 2073
    /* Don't respond to ACK! */
2074
    if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_ack_method) == 0)
2075
        return PJ_TRUE;
124 andreas 2076
 
135 andreas 2077
    /* Simple registrar */
2078
    if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_register_method) == 0)
2079
    {
2080
        simple_registrar(rdata);
2081
        return PJ_TRUE;
2082
    }
124 andreas 2083
 
135 andreas 2084
    /* Create basic response. */
2085
    if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_notify_method) == 0)
2086
    {
2087
        /* Unsolicited NOTIFY's, send with Bad Request */
2088
        status_code = PJSIP_SC_BAD_REQUEST;
2089
    }
2090
    else
2091
    {
2092
        /* Probably unknown method */
2093
        status_code = PJSIP_SC_METHOD_NOT_ALLOWED;
2094
    }
124 andreas 2095
 
135 andreas 2096
    status = pjsip_endpt_create_response(pjsua_get_pjsip_endpt(), rdata, status_code, NULL, &tdata);
124 andreas 2097
 
135 andreas 2098
    if (status != PJ_SUCCESS)
2099
    {
2100
        MSG_ERROR("Unable to create response");
2101
        return PJ_TRUE;
2102
    }
124 andreas 2103
 
135 andreas 2104
    /* Add Allow if we're responding with 405 */
2105
    if (status_code == PJSIP_SC_METHOD_NOT_ALLOWED)
2106
    {
2107
        const pjsip_hdr *cap_hdr;
2108
        cap_hdr = pjsip_endpt_get_capability(pjsua_get_pjsip_endpt(), PJSIP_H_ALLOW, NULL);
2109
 
2110
        if (cap_hdr)
2111
        {
2112
            pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)pjsip_hdr_clone(tdata->pool, cap_hdr));
2113
        }
2114
    }
2115
 
2116
    /* Add User-Agent header */
2117
    {
2118
        pj_str_t user_agent;
2119
        char tmp[80];
2120
        const pj_str_t USER_AGENT = { (char *)"User-Agent", 10};
2121
        pjsip_hdr *h;
2122
 
144 andreas 2123
//        pj_ansi_snprintf(tmp, sizeof(tmp), "PJSUA v%s/%s", pj_get_version(), PJ_OS_NAME);
2124
        pj_ansi_snprintf(tmp, sizeof(tmp), "TPanel v%s/%s", VERSION_STRING(), PJ_OS_NAME);
135 andreas 2125
        pj_strdup2_with_null(tdata->pool, &user_agent, tmp);
2126
 
2127
        h = (pjsip_hdr*) pjsip_generic_string_hdr_create(tdata->pool, &USER_AGENT, &user_agent);
2128
        pjsip_msg_add_hdr(tdata->msg, h);
2129
    }
2130
 
2131
    status = pjsip_endpt_send_response2(pjsua_get_pjsip_endpt(), rdata, tdata, NULL, NULL);
2132
 
144 andreas 2133
    if (status != PJ_SUCCESS)
2134
        pjsip_tx_data_dec_ref(tdata);
2135
 
135 andreas 2136
    return PJ_TRUE;
124 andreas 2137
}
2138
 
129 andreas 2139
#endif  // _NOSIP_