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());
173
    mAppConfig.cfg.outbound_proxy_cnt = 1;
174
    mAppConfig.cfg.outbound_proxy[0] = pj_str((char *)regUri.c_str());
175
    mAppConfig.cfg.max_calls = SIP_MAX_LINES;
176
 
177
    if (!TConfig::getSIPstun().empty())
178
    {
179
        mAppConfig.cfg.stun_srv_cnt = 1;
180
        mAppConfig.cfg.stun_srv[0] = pj_str((char *)TConfig::getSIPstun().c_str());
181
 
182
        if (TConfig::getSIPnetworkIPv6())
183
            mAppConfig.cfg.stun_try_ipv6 = PJ_TRUE;
184
    }
185
 
186
    string uAgent = string("TPanel v") + VERSION_STRING();
187
    mAppConfig.cfg.user_agent = pj_str((char *)uAgent.c_str());
188
 
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
    pjsua_config_default(&mAppConfig.cfg);
207
    mAppConfig.cfg.cb.on_incoming_call = &on_incoming_call;
208
    mAppConfig.cfg.cb.on_call_media_state = &on_call_media_state;
209
    mAppConfig.cfg.cb.on_call_state = &on_call_state;
210
    mAppConfig.cfg.cb.on_dtmf_digit2 = &call_on_dtmf_callback2;
211
    mAppConfig.cfg.cb.on_call_redirected = &call_on_redirected;
212
    mAppConfig.cfg.cb.on_call_transfer_status = &on_call_transfer_status;
213
    mAppConfig.cfg.cb.on_transport_state = &on_transport_state;
214
    mAppConfig.cfg.cb.on_ip_change_progress = &on_ip_change_progress;
123 andreas 215
 
135 andreas 216
    pjsua_logging_config_default(&log_cfg);
217
    log_cfg.console_level = 4;
218
    log_cfg.level = 5;
219
    log_cfg.decor = (PJ_LOG_HAS_SENDER);
220
    log_cfg.cb = &_log_call;
123 andreas 221
 
135 andreas 222
    pjsua_media_config_default(&mAppConfig.media_cfg);
223
 
224
    if (mAppConfig.capture_lat > 0)
225
        mAppConfig.media_cfg.snd_rec_latency = mAppConfig.capture_lat;
226
 
227
    if (mAppConfig.playback_lat)
228
        mAppConfig.media_cfg.snd_play_latency = mAppConfig.playback_lat;
229
 
230
    if (TConfig::getSIPfirewall() == TConfig::SIP_ICE)
231
        mAppConfig.media_cfg.enable_ice = true;
232
 
233
    if (!TConfig::getSIPstun().empty())
234
        mAppConfig.media_cfg.turn_server = pj_str((char *)TConfig::getSIPstun().c_str());
235
 
236
    if (pjsua_init(&mAppConfig.cfg, &log_cfg, &mAppConfig.media_cfg) != PJ_SUCCESS)
123 andreas 237
    {
135 andreas 238
        MSG_ERROR("Error in pjsua_init()");
239
        pj_pool_release(tmp_pool);
240
        pjsua_destroy();
241
        return false;
123 andreas 242
    }
135 andreas 243
 
244
    if (pjsip_endpt_register_module(pjsua_get_pjsip_endpt(), &mod_default_handler) != PJ_SUCCESS)
123 andreas 245
    {
135 andreas 246
        MSG_ERROR("Error registrating module handler!");
247
        pjsua_destroy();
123 andreas 248
        return false;
249
    }
250
 
135 andreas 251
    // Initialize calls data
252
    for (size_t i = 0; i < PJ_ARRAY_SIZE(mAppConfig.call_data); ++i)
253
    {
254
        mAppConfig.call_data[i].timer.id = PJSUA_INVALID_ID;
255
        mAppConfig.call_data[i].timer.cb = &call_timeout_callback;
256
    }
123 andreas 257
 
135 andreas 258
    /* Optionally registers WAV file */
259
    for (uint_t i = 0; i < mAppConfig.wav_count; ++i)
260
    {
261
        pjsua_player_id wav_id;
262
        uint_t play_options = 0;
123 andreas 263
 
135 andreas 264
        if (mAppConfig.auto_play_hangup)
265
            play_options |= PJMEDIA_FILE_NO_LOOP;
123 andreas 266
 
135 andreas 267
        status = pjsua_player_create(&mAppConfig.wav_files[i], play_options, &wav_id);
123 andreas 268
 
135 andreas 269
        if (status != PJ_SUCCESS)
270
        {
271
            MSG_ERROR("Error creating a player!");
272
            pj_pool_release(tmp_pool);
273
            pjsua_destroy();
274
            return false;
275
        }
123 andreas 276
 
135 andreas 277
        if (mAppConfig.wav_id == PJSUA_INVALID_ID)
278
        {
279
            mAppConfig.wav_id = wav_id;
280
            mAppConfig.wav_port = pjsua_player_get_conf_port(mAppConfig.wav_id);
123 andreas 281
 
135 andreas 282
            if (mAppConfig.auto_play_hangup)
283
            {
284
                pjmedia_port *port;
123 andreas 285
 
135 andreas 286
                pjsua_player_get_port(mAppConfig.wav_id, &port);
123 andreas 287
 
135 andreas 288
                if (pjmedia_wav_player_set_eof_cb2(port, NULL, &on_playfile_done) != PJ_SUCCESS)
289
                {
290
                    MSG_ERROR("Error setting callback function for player!");
291
                    pj_pool_release(tmp_pool);
292
                    pjsua_destroy();
293
                    return false;
294
                }
295
 
296
                pj_timer_entry_init(&mAppConfig.auto_hangup_timer, 0, NULL, &hangup_timeout_callback);
297
            }
298
        }
123 andreas 299
    }
300
 
135 andreas 301
    /* Register tone players */
302
    for (uint_t i = 0; i < mAppConfig.tone_count; ++i)
123 andreas 303
    {
135 andreas 304
        pjmedia_port *tport;
305
        char name[80];
306
        pj_str_t label;
307
        pj_status_t status2;
123 andreas 308
 
135 andreas 309
        pj_ansi_snprintf(name, sizeof(name), "tone-%d,%d",
310
                         mAppConfig.tones[i].freq1,
311
                         mAppConfig.tones[i].freq2);
312
        label = pj_str(name);
313
        status2 = pjmedia_tonegen_create2(mAppConfig.pool, &label,
314
                                          8000, 1, 160, 16,
315
                                          PJMEDIA_TONEGEN_LOOP,  &tport);
316
        if (status2 != PJ_SUCCESS)
317
        {
318
            MSG_ERROR("Unable to create tone generator! (" << status << ")");
319
            pj_pool_release(tmp_pool);
320
            pjsua_destroy();
321
            return false;
322
        }
123 andreas 323
 
135 andreas 324
        status2 = pjsua_conf_add_port(mAppConfig.pool, tport, &mAppConfig.tone_slots[i]);
325
        pj_assert(status2 == PJ_SUCCESS);
326
 
327
        status2 = pjmedia_tonegen_play(tport, 1, &mAppConfig.tones[i], 0);
328
        pj_assert(status2 == PJ_SUCCESS);
123 andreas 329
    }
330
 
135 andreas 331
    /* Create ringback tones */
332
    if (mAppConfig.no_tones == PJ_FALSE)
333
    {
334
        uint_t samples_per_frame;
335
        pjmedia_tone_desc tone[RING_CNT+RINGBACK_CNT];
336
        pj_str_t name;
127 andreas 337
 
135 andreas 338
        samples_per_frame = mAppConfig.media_cfg.audio_frame_ptime *
339
        mAppConfig.media_cfg.clock_rate *
340
        mAppConfig.media_cfg.channel_count / 1000;
127 andreas 341
 
135 andreas 342
        /* Ringback tone (call is ringing) */
343
        name = pj_str((char *)"ringback");
344
        status = pjmedia_tonegen_create2(mAppConfig.pool, &name,
345
                                         mAppConfig.media_cfg.clock_rate,
346
                                         mAppConfig.media_cfg.channel_count,
347
                                         samples_per_frame,
348
                                         16, PJMEDIA_TONEGEN_LOOP,
349
                                         &mAppConfig.ringback_port);
350
        if (status != PJ_SUCCESS)
351
        {
352
            MSG_ERROR("Unable to create tone generator 2! (" << status << ")");
353
            pj_pool_release(tmp_pool);
354
            pjsua_destroy();
355
            return false;
356
        }
127 andreas 357
 
135 andreas 358
        pj_bzero(&tone, sizeof(tone));
124 andreas 359
 
135 andreas 360
        for (int i = 0; i < RINGBACK_CNT; ++i)
361
        {
362
            tone[i].freq1 = RINGBACK_FREQ1;
363
            tone[i].freq2 = RINGBACK_FREQ2;
364
            tone[i].on_msec = RINGBACK_ON;
365
            tone[i].off_msec = RINGBACK_OFF;
366
        }
367
 
368
        tone[RINGBACK_CNT-1].off_msec = RINGBACK_INTERVAL;
369
 
370
        pjmedia_tonegen_play(mAppConfig.ringback_port, RINGBACK_CNT, tone,
371
                             PJMEDIA_TONEGEN_LOOP);
372
 
373
 
374
        status = pjsua_conf_add_port(mAppConfig.pool, mAppConfig.ringback_port,
375
                                     &mAppConfig.ringback_slot);
376
        if (status != PJ_SUCCESS)
377
        {
378
            MSG_ERROR("Unable to add a port to tone generator! (" << status << ")");
379
            pj_pool_release(tmp_pool);
380
            pjsua_destroy();
381
            return false;
382
        }
383
 
384
        /* Ring (to alert incoming call) */
385
        name = pj_str((char *)"ring");
386
        status = pjmedia_tonegen_create2(mAppConfig.pool, &name,
387
                                         mAppConfig.media_cfg.clock_rate,
388
                                         mAppConfig.media_cfg.channel_count,
389
                                         samples_per_frame,
390
                                         16, PJMEDIA_TONEGEN_LOOP,
391
                                         &mAppConfig.ring_port);
392
        if (status != PJ_SUCCESS)
393
        {
394
            MSG_ERROR("Unable to create tone generator 2! (" << status << ")");
395
            pj_pool_release(tmp_pool);
396
            pjsua_destroy();
397
            return false;
398
        }
399
 
400
        for (int i = 0; i < RING_CNT; ++i)
401
        {
402
            tone[i].freq1 = RING_FREQ1;
403
            tone[i].freq2 = RING_FREQ2;
404
            tone[i].on_msec = RING_ON;
405
            tone[i].off_msec = RING_OFF;
406
        }
407
 
408
        tone[RING_CNT-1].off_msec = RING_INTERVAL;
409
 
410
        pjmedia_tonegen_play(mAppConfig.ring_port, RING_CNT, tone, PJMEDIA_TONEGEN_LOOP);
411
 
412
        status = pjsua_conf_add_port(mAppConfig.pool, mAppConfig.ring_port,
413
                                     &mAppConfig.ring_slot);
414
        if (status != PJ_SUCCESS)
415
        {
416
            MSG_ERROR("Unable to add a port to tone generator! (" << status << ")");
417
            pj_pool_release(tmp_pool);
418
            pjsua_destroy();
419
            return false;
420
        }
124 andreas 421
    }
127 andreas 422
 
135 andreas 423
    /* Add UDP transport. */
424
    pjsua_transport_id transport_id = -1;
425
    pjsua_transport_config tcp_cfg;
123 andreas 426
 
135 andreas 427
    if (!mAppConfig.no_udp && TConfig::getSIPnetworkIPv4())
123 andreas 428
    {
135 andreas 429
        pjsua_acc_id aid;
430
        pjsip_transport_type_e type = PJSIP_TRANSPORT_UDP;
431
 
432
        status = pjsua_transport_create(type,
433
                                        &mAppConfig.udp_cfg,
434
                                        &transport_id);
435
        if (status != PJ_SUCCESS)
436
        {
437
            MSG_ERROR("Unable to create transport! (" << status << ")");
438
            pj_pool_release(tmp_pool);
439
            pjsua_destroy();
440
            return false;
441
        }
442
 
443
        /* Add local account */
444
        pjsua_acc_add_local(transport_id, PJ_TRUE, &aid);
445
        /* Adjust local account config based on pjsua app config */
446
        {
447
            pjsua_acc_config acc_cfg;
448
            pjsua_acc_get_config(aid, tmp_pool, &acc_cfg);
449
 
450
            acc_cfg.rtp_cfg = mAppConfig.rtp_cfg;
451
            pjsua_acc_modify(aid, &acc_cfg);
452
        }
453
 
454
        pjsua_acc_set_online_status(current_acc, PJ_TRUE);
455
        // Find a free port to listen on
456
        pjsua_transport_info ti;
457
        pj_sockaddr_in *a;
458
 
459
        pjsua_transport_get_info(transport_id, &ti);
460
        ti.local_addr.addr.sa_family = PJ_AF_INET;
461
        a = (pj_sockaddr_in*)&ti.local_addr;
462
        tcp_cfg.port = pj_ntohs(a->sin_port);
123 andreas 463
    }
464
 
135 andreas 465
    if (!mAppConfig.no_udp && TConfig::getSIPnetworkIPv6())
123 andreas 466
    {
135 andreas 467
        pjsua_acc_id aid;
468
        pjsip_transport_type_e type = PJSIP_TRANSPORT_UDP6;
469
        pjsua_transport_config udp_cfg;
123 andreas 470
 
135 andreas 471
        udp_cfg = mAppConfig.udp_cfg;
123 andreas 472
 
135 andreas 473
        if (udp_cfg.port == 0)
474
            udp_cfg.port = 5060;
475
        else
476
            udp_cfg.port += 10;
123 andreas 477
 
135 andreas 478
        status = pjsua_transport_create(type,
479
                                        &udp_cfg,
480
                                        &transport_id);
481
        if (status != PJ_SUCCESS)
482
        {
483
            MSG_ERROR("Unable to create IPv6 transport! (" << status << ")");
484
            pj_pool_release(tmp_pool);
485
            pjsua_destroy();
486
            return false;
487
        }
123 andreas 488
 
135 andreas 489
        /* Add local account */
490
        pjsua_acc_add_local(transport_id, PJ_TRUE, &aid);
491
        /* Adjust local account config based on pjsua app config */
492
        {
493
            pjsua_acc_config acc_cfg;
494
            pjsua_acc_get_config(aid, tmp_pool, &acc_cfg);
123 andreas 495
 
135 andreas 496
            acc_cfg.rtp_cfg = mAppConfig.rtp_cfg;
497
            acc_cfg.ipv6_media_use = PJSUA_IPV6_ENABLED;
498
            pjsua_acc_modify(aid, &acc_cfg);
499
        }
123 andreas 500
 
135 andreas 501
        //pjsua_acc_set_transport(aid, transport_id);
502
        pjsua_acc_set_online_status(current_acc, PJ_TRUE);
127 andreas 503
 
135 andreas 504
        if (mAppConfig.udp_cfg.port == 0)
505
        {
506
            pjsua_transport_info ti;
127 andreas 507
 
135 andreas 508
            pjsua_transport_get_info(transport_id, &ti);
509
            tcp_cfg.port = pj_sockaddr_get_port(&ti.local_addr);
510
        }
123 andreas 511
    }
135 andreas 512
 
513
    /* Add TCP transport unless it's disabled */
514
    if (!mAppConfig.no_tcp && TConfig::getSIPnetworkIPv4())
123 andreas 515
    {
135 andreas 516
        pjsua_acc_id aid;
123 andreas 517
 
135 andreas 518
        status = pjsua_transport_create(PJSIP_TRANSPORT_TCP,
519
                                        &tcp_cfg,
520
                                        &transport_id);
521
        if (status != PJ_SUCCESS)
522
        {
523
            MSG_ERROR("Unable to create TCP transport! (" << status << ")");
524
            pj_pool_release(tmp_pool);
525
            pjsua_destroy();
526
            return false;
527
        }
123 andreas 528
 
135 andreas 529
        /* Add local account */
530
        pjsua_acc_add_local(transport_id, PJ_TRUE, &aid);
127 andreas 531
 
135 andreas 532
        /* Adjust local account config based on pjsua app config */
533
        {
534
            pjsua_acc_config acc_cfg;
535
            pjsua_acc_get_config(aid, tmp_pool, &acc_cfg);
127 andreas 536
 
135 andreas 537
            acc_cfg.rtp_cfg = mAppConfig.rtp_cfg;
538
            pjsua_acc_modify(aid, &acc_cfg);
539
        }
540
 
541
        pjsua_acc_set_online_status(current_acc, PJ_TRUE);
542
    }
543
 
544
    /* Add TCP IPv6 transport unless it's disabled. */
545
    if (!mAppConfig.no_tcp && TConfig::getSIPnetworkIPv6())
127 andreas 546
    {
135 andreas 547
        pjsua_acc_id aid;
548
        pjsip_transport_type_e type = PJSIP_TRANSPORT_TCP6;
549
 
550
        tcp_cfg.port += 10;
551
 
552
        status = pjsua_transport_create(type,
553
                                        &tcp_cfg,
554
                                        &transport_id);
555
        if (status != PJ_SUCCESS)
127 andreas 556
        {
135 andreas 557
            MSG_ERROR("Unable to create TCP IPv6 transport! (" << status << ")");
558
            pj_pool_release(tmp_pool);
559
            pjsua_destroy();
560
            return false;
561
        }
127 andreas 562
 
135 andreas 563
        /* Add local account */
564
        pjsua_acc_add_local(transport_id, PJ_TRUE, &aid);
127 andreas 565
 
135 andreas 566
        /* Adjust local account config based on pjsua app config */
567
        {
568
            pjsua_acc_config acc_cfg;
569
            pjsua_acc_get_config(aid, tmp_pool, &acc_cfg);
570
 
571
            acc_cfg.rtp_cfg = mAppConfig.rtp_cfg;
572
            acc_cfg.ipv6_media_use = PJSUA_IPV6_ENABLED;
573
            pjsua_acc_modify(aid, &acc_cfg);
127 andreas 574
        }
575
 
135 andreas 576
        //pjsua_acc_set_transport(aid, transport_id);
577
        pjsua_acc_set_online_status(current_acc, PJ_TRUE);
127 andreas 578
    }
579
 
135 andreas 580
    if (transport_id == -1)
581
    {
582
        MSG_ERROR("Transport couldn't be configured!");
583
        pj_pool_release(tmp_pool);
584
        pjsua_destroy();
585
        return false;
586
    }
127 andreas 587
 
135 andreas 588
    /* Add accounts */
589
    for (uint_t i = 0; i < mAppConfig.acc_cnt; ++i)
127 andreas 590
    {
135 andreas 591
        mAppConfig.acc_cfg[i].rtp_cfg = mAppConfig.rtp_cfg;
592
        mAppConfig.acc_cfg[i].reg_retry_interval = 300;
593
        mAppConfig.acc_cfg[i].reg_first_retry_interval = 60;
594
 
595
        status = pjsua_acc_add(&mAppConfig.acc_cfg[i], PJ_TRUE, NULL);
596
 
597
        if (status != PJ_SUCCESS)
598
        {
599
            MSG_ERROR("Unable to add an account! (" << status << ")");
600
            pj_pool_release(tmp_pool);
601
            pjsua_destroy();
602
            return false;
603
        }
604
 
605
        pjsua_acc_set_online_status(current_acc, PJ_TRUE);
127 andreas 606
    }
607
 
135 andreas 608
    /* Init call setting */
609
    pjsua_call_setting call_opt;
610
    pjsua_call_setting_default(&call_opt);
611
    call_opt.aud_cnt = mAppConfig.aud_cnt;
612
    call_opt.vid_cnt = 0;
127 andreas 613
 
135 andreas 614
#if defined(PJSIP_HAS_TLS_TRANSPORT) && PJSIP_HAS_TLS_TRANSPORT!=0
615
    /* Wipe out TLS key settings in transport configs */
616
    pjsip_tls_setting_wipe_keys(&mAppConfig.udp_cfg.tls_setting);
617
#endif
618
 
619
    pj_pool_release(tmp_pool);
620
 
621
    /* Initialization is done, now start pjsua */
622
    status = pjsua_start();
623
 
624
    if (status != PJ_SUCCESS)
625
    {
626
        MSG_ERROR("Error starting pjsua");
627
        pjsua_destroy();
628
        return false;
629
    }
630
 
631
    mRegistered = true;
123 andreas 632
    return true;
633
}
634
 
135 andreas 635
void TSIPClient::cleanUp()
636
{
637
    DECL_TRACER("TSIPClient::cleanUp()");
638
 
141 andreas 639
    if (mPhoneRingInit && mRingtonePortInfo.pool)
640
    {
641
        pj_pool_release(mRingtonePortInfo.pool);
642
        mRingtonePortInfo.pool = nullptr;
643
        mPhoneRingInit = false;
644
    }
645
 
135 andreas 646
    pjsua_destroy();
647
    mAccountID = 0;
138 andreas 648
    mLine = PJSUA_INVALID_ID;
649
    mCurrentCall = PJSUA_INVALID_ID;
135 andreas 650
 
138 andreas 651
    for (int i = 0; i < PJSUA_MAX_CALLS; ++i)
652
        mSIPState[i] = SIP_NONE;
135 andreas 653
 
654
    mRegistered = false;
655
}
656
 
123 andreas 657
bool TSIPClient::call(const string& dest)
658
{
127 andreas 659
    DECL_TRACER("TSIPClient::call(const string& dest, int)");
123 andreas 660
 
135 andreas 661
    if (dest.empty())
662
    {
663
        MSG_ERROR("No destination defined!");
123 andreas 664
        return false;
135 andreas 665
    }
123 andreas 666
 
135 andreas 667
    if (!mRegistered)
668
    {
669
        MSG_ERROR("Phone core is not registered!");
670
        return false;
671
    }
672
 
127 andreas 673
    int numCalls = getNumberCalls();
123 andreas 674
 
127 andreas 675
    if (numCalls >= 2)
123 andreas 676
    {
127 andreas 677
        MSG_ERROR("There are already " << numCalls << " active!");
678
        return false;
679
    }
680
 
135 andreas 681
    string sUri;
127 andreas 682
 
135 andreas 683
    if (dest.find("sip:") == string::npos)
684
        sUri = "sip:";
685
 
686
    sUri += dest;
141 andreas 687
 
688
    if (sUri.find("@") == string::npos)
689
        sUri += "@" + TConfig::getSIPproxy();
690
 
135 andreas 691
    pj_str_t uri = pj_str((char *)sUri.c_str());
692
    REGISTER_THREAD();
693
    pjsua_call_id cid = PJSUA_INVALID_ID;
694
    pjsua_call_setting call_opt;
695
 
696
    pjsua_call_setting_default(&call_opt);
697
    call_opt.vid_cnt = 0;
698
    mAccountID = pjsua_acc_get_default();
699
 
700
    if (pjsua_call_make_call(mAccountID, &uri, &call_opt, NULL, NULL, &cid) != PJ_SUCCESS)
127 andreas 701
    {
135 andreas 702
        MSG_ERROR("Error calling " << dest << "!");
140 andreas 703
        sendConnectionStatus(SIP_ERROR, cid);
123 andreas 704
        return false;
705
    }
706
 
138 andreas 707
    mLine = cid;
708
    mLastCall = dest;
135 andreas 709
    return true;
123 andreas 710
}
711
 
135 andreas 712
bool TSIPClient::pickup(pjsua_call_id call)
123 andreas 713
{
127 andreas 714
    DECL_TRACER("TSIPClient::pickup(LinphoneCall *call, int)");
123 andreas 715
 
135 andreas 716
    pjsua_call_info ci;
128 andreas 717
 
135 andreas 718
    REGISTER_THREAD();
719
    pjsua_call_get_info(call, &ci);
720
 
721
    if (ci.remote_info.slen > 0)
722
    {
723
        MSG_DEBUG("Incoming call from " << ci.remote_info.ptr);
724
    }
127 andreas 725
    else
125 andreas 726
    {
135 andreas 727
        MSG_DEBUG("Incoming call (" << ci.id << ")");
728
    }
124 andreas 729
 
135 andreas 730
    if (pjsua_call_answer(call, 200, NULL, NULL) != PJ_SUCCESS)
731
    {
732
        MSG_ERROR("Couldn't answer with call ID " << call);
140 andreas 733
        sendConnectionStatus(SIP_ERROR, call);
135 andreas 734
        return false;
125 andreas 735
    }
736
 
138 andreas 737
    mLine = call;
135 andreas 738
    return true;
123 andreas 739
}
740
 
127 andreas 741
bool TSIPClient::terminate(int id)
123 andreas 742
{
127 andreas 743
    DECL_TRACER("TSIPClient::terminate(int)");
123 andreas 744
 
138 andreas 745
    pjsua_call_id cid = id;
746
    REGISTER_THREAD();
128 andreas 747
 
138 andreas 748
    if (!pjsua_call_is_active(cid))
749
    {
750
        MSG_ERROR("No active call at call ID " << id << "!");
123 andreas 751
        return false;
138 andreas 752
    }
123 andreas 753
 
135 andreas 754
    if (pjsua_call_hangup(cid, 200, NULL, NULL) != PJ_SUCCESS)
755
    {
756
        MSG_ERROR("The call " << id << " can't be ended successfull!");
140 andreas 757
        sendConnectionStatus(SIP_ERROR, cid);
135 andreas 758
        return false;
759
    }
760
 
140 andreas 761
    sendConnectionStatus(SIP_DISCONNECTED, cid);
138 andreas 762
    mLine = PJSUA_INVALID_ID;
123 andreas 763
    return true;
764
}
765
 
127 andreas 766
bool TSIPClient::hold(int id)
124 andreas 767
{
127 andreas 768
    DECL_TRACER("TSIPClient::hold(int id)");
124 andreas 769
 
138 andreas 770
    pjsua_call_id cid = id;
771
    REGISTER_THREAD();
135 andreas 772
 
138 andreas 773
    if (!pjsua_call_is_active(cid))
774
    {
775
        MSG_ERROR("No active call at call ID " << id << "!");
128 andreas 776
        return false;
138 andreas 777
    }
128 andreas 778
 
135 andreas 779
    if (pjsua_call_set_hold(cid, NULL) != PJ_SUCCESS)
124 andreas 780
    {
135 andreas 781
        MSG_ERROR("Error setting line " << id << " on hold!");
140 andreas 782
        sendConnectionStatus(SIP_ERROR, cid);
135 andreas 783
        return false;
124 andreas 784
    }
785
 
138 andreas 786
    sendConnectionStatus(SIP_HOLD, cid);
787
    mLine = id;
124 andreas 788
    return false;
789
}
790
 
127 andreas 791
bool TSIPClient::resume(int id)
124 andreas 792
{
127 andreas 793
    DECL_TRACER("TSIPClient::resume(int)");
124 andreas 794
 
138 andreas 795
    pjsua_call_id cid = id;
135 andreas 796
    REGISTER_THREAD();
138 andreas 797
 
798
    if (!pjsua_call_is_active(cid))
799
    {
800
        MSG_ERROR("No active call at call ID " << id << "!");
801
        return false;
802
    }
803
 
804
    if (pjsua_call_set_hold2(cid, PJSUA_CALL_UNHOLD, NULL) != PJ_SUCCESS)
805
    {
806
        MSG_ERROR("Call couldn't be resumed!");
140 andreas 807
        sendConnectionStatus(SIP_ERROR, cid);
138 andreas 808
        return false;
809
    }
810
 
811
    mLine = id;
812
    return true;
124 andreas 813
}
814
 
127 andreas 815
bool TSIPClient::sendDTMF(string& dtmf)
816
{
817
    DECL_TRACER("TSIPClient::sendDTMF(string& dtmf, int id)");
818
 
135 andreas 819
    REGISTER_THREAD();
138 andreas 820
 
821
    if (!pjsua_call_get_count())    // Is there no call active?
822
    {                               // Yes, then treat dtmf as a phone number and call
823
        pj_str_t s = pj_str((char *)dtmf.c_str());
824
 
825
        if (pjsua_call_dial_dtmf(0, &s) != PJ_SUCCESS)
826
        {
827
            MSG_ERROR("Error calling DTMF number " << dtmf << "!");
828
            return false;
829
        }
830
 
831
        sendConnectionStatus(SIP_TRYING, 0);
832
        mLine = 0;
833
        return true;
834
    }
835
 
836
    mLine = getActiveCall();
837
 
838
    pjsua_call_send_dtmf_param d;
839
    d.duration = mDTMFduration;
840
    d.method = PJSUA_DTMF_METHOD_RFC2833;
841
    d.digits = pj_str((char *)dtmf.c_str());
842
 
843
    if (pjsua_call_send_dtmf(mLine, &d) != PJ_SUCCESS)
844
    {
845
        MSG_ERROR("Error sendig DTMF sequence " << dtmf << "!");
846
        return false;
847
    }
848
 
849
    return true;
127 andreas 850
}
851
 
128 andreas 852
bool TSIPClient::sendLinestate()
853
{
854
    DECL_TRACER("TSIPClient::sendLinestate()");
855
 
138 andreas 856
    uint_t maxCalls = pjsua_call_get_max_count();
128 andreas 857
    vector<string> cmds;
858
    cmds.push_back("LINESTATE");
859
 
138 andreas 860
    for (uint_t i = 0; i < maxCalls; ++i)
128 andreas 861
    {
138 andreas 862
        cmds.push_back(to_string(i));
863
 
864
        if (pjsua_call_is_active(i))
865
            cmds.push_back("CONNECTED");
866
        else
867
            cmds.push_back("IDLE");
128 andreas 868
    }
869
 
138 andreas 870
    if (gPageManager)
871
        gPageManager->sendPHN(cmds);
128 andreas 872
 
873
    return true;
874
}
875
 
876
bool TSIPClient::sendPrivate(bool state)
877
{
878
    DECL_TRACER("TSIPClient::sendPrivate(bool state)");
879
 
138 andreas 880
    // FIXME: Enter code to set privacy (DND - do not disturb)
128 andreas 881
    vector<string> cmds;
882
    cmds.push_back("PRIVACY");
883
 
884
    if (state)
885
        cmds.push_back("1");
886
    else
887
        cmds.push_back("0");
888
 
889
    gPageManager->sendPHN(cmds);
138 andreas 890
    mDoNotDisturb = state;
128 andreas 891
    return true;
892
}
893
 
894
bool TSIPClient::redial()
895
{
896
    DECL_TRACER("TSIPClient::redial()");
897
 
138 andreas 898
    if (mLastCall.empty())
899
        return false;
900
 
901
    return call(mLastCall);
135 andreas 902
}
128 andreas 903
 
135 andreas 904
bool TSIPClient::transfer(int id, const string& num)
905
{
906
    DECL_TRACER("TSIPClient::transfer(int id, const string& num)");
907
 
908
    REGISTER_THREAD();
138 andreas 909
 
910
    if (id == PJSUA_INVALID_ID || !pjsua_call_is_active(id))
911
    {
912
        MSG_ERROR("Call ID " << id << " is not an active call!");
913
        return false;
914
    }
915
 
916
    pj_str_t s = pj_str((char *)num.c_str());
917
 
918
    if (pjsua_call_xfer(id, &s, NULL) != PJ_SUCCESS)
919
    {
920
        MSG_ERROR("Call ID " << id << " couldn't be transferred to " << num << "!");
140 andreas 921
        sendConnectionStatus(SIP_ERROR, id);
138 andreas 922
        return false;
923
    }
924
 
140 andreas 925
    sendConnectionStatus(SIP_IDLE, id);
138 andreas 926
    return true;
135 andreas 927
}
928
 
138 andreas 929
bool TSIPClient::setDTMFduration(uint_t ms)
930
{
931
    DECL_TRACER("TSIPClient::setDTMFduration(uint_t ms)");
932
 
933
    if (ms >= 100 && ms <= 3000)
934
        mDTMFduration = ms;
935
 
936
    return true;
937
}
938
 
135 andreas 939
int TSIPClient::getNumberCalls()
940
{
941
    DECL_TRACER("TSIPClient::getNumberCalls()");
942
 
138 andreas 943
    return pjsua_call_get_count();
135 andreas 944
}
945
 
138 andreas 946
pjsua_call_id TSIPClient::getActiveCall()
947
{
948
    DECL_TRACER("TSIPClient::getActiveCall()");
949
 
950
    uint_t maxCalls = pjsua_call_get_max_count();
951
 
952
    for (uint_t i = 0; i < maxCalls; ++i)
953
    {
954
        if (pjsua_call_is_active(i))
955
            return i;
956
    }
957
 
958
    return PJSUA_INVALID_ID;
959
}
960
 
135 andreas 961
void TSIPClient::sendConnectionStatus(SIP_STATE_t state, int id)
962
{
963
    DECL_TRACER("TSIPClient::sendConnectionStatus(SIP_STATE_t state)");
964
 
138 andreas 965
    mMyself->setSIPState(state, id);
966
 
135 andreas 967
    if (!gPageManager)
968
        return;
969
 
140 andreas 970
    if (state == SIP_RINGING && TConfig::getSIPiphone() && gPageManager->getShowPhoneDialog())
141 andreas 971
    {
972
        pjsua_call_info ci;
973
 
140 andreas 974
        gPageManager->getShowPhoneDialog()(true);
141 andreas 975
        pjsua_call_get_info(id, &ci);
976
        string number;
977
        number.assign(ci.remote_info.ptr, ci.remote_info.slen);
978
        size_t pos;
140 andreas 979
 
141 andreas 980
        if ((pos = number.find("\"")) != string::npos)
981
        {
982
            size_t pos2 = number.find("\"", pos + 1);
983
 
984
            if (pos2 != string::npos)
985
                number = number.substr(pos + 1, pos2 - pos - 1);
986
            else
987
                number = number.substr(pos + 1);
988
        }
989
        else if ((pos = number.find("sip:")) != string::npos)
990
        {
991
            size_t pos2 = number.find("@");
992
 
993
            if (pos2 != string::npos && pos2 > pos)
994
                number = number.substr(pos + 4, pos2 - (pos + 4));
995
            else
996
                number = number.substr(pos + 4);
997
        }
998
 
999
        gPageManager->getSetPhoneNumber()(number);
1000
        gPageManager->getSetPhoneState()(SIP_RINGING, id);
1001
    }
1002
 
135 andreas 1003
    vector<string> cmds;
1004
    cmds.push_back("CALL");
1005
 
1006
    switch(state)
128 andreas 1007
    {
135 andreas 1008
        case SIP_CONNECTED:     cmds.push_back("CONNECTED"); break;
1009
        case SIP_DISCONNECTED:  cmds.push_back("DISCONNECTED"); break;
1010
        case SIP_HOLD:          cmds.push_back("HOLD"); break;
1011
        case SIP_RINGING:       cmds.push_back("RINGING"); break;
1012
        case SIP_TRYING:        cmds.push_back("TRYING"); break;
140 andreas 1013
        case SIP_IDLE:          cmds.push_back("IDLE"); break;
135 andreas 1014
 
1015
        default:
140 andreas 1016
            if (gPageManager->getSetPhoneState())
1017
                gPageManager->getSetPhoneState()(state, id);
1018
 
135 andreas 1019
            return;
128 andreas 1020
    }
1021
 
135 andreas 1022
    cmds.push_back(to_string(id));
1023
    gPageManager->sendPHN(cmds);
140 andreas 1024
 
1025
    if (gPageManager->getSetPhoneState())
1026
        gPageManager->getSetPhoneState()(state, id);
135 andreas 1027
}
1028
 
141 andreas 1029
void TSIPClient::runRinger()
1030
{
1031
    DECL_TRACER("TSIPClient::runRinger()");
1032
 
1033
    init_ringtone_player();
1034
 
1035
    if (start_ring_tone() != PJ_SUCCESS)
1036
    {
1037
        //FIXME:: Add code to free the pool
1038
        return;
1039
    }
1040
}
1041
 
1042
void TSIPClient::init_ringtone_player()
1043
{
1044
    DECL_TRACER("TSIPClient::init_ringtone_player()");
1045
 
1046
    int file_slot;
1047
    pj_pool_t *pool;
1048
    pjmedia_port *file_port;
1049
    pj_status_t status;
1050
 
1051
    if (mPhoneRingInit)
1052
        return;
1053
 
1054
    string tone = TConfig::getProjectPath() + "/__system/graphics/sounds/ringtone.wav";
1055
    MSG_DEBUG("Testing for sound file: " << tone);
1056
 
1057
    if (!fs::exists(tone))
1058
    {
1059
        tone = TConfig::getProjectPath() + "/sounds/ringtone.wav";
1060
        MSG_DEBUG("Testing for sound file: " << tone);
1061
 
1062
        if (!fs::exists(tone))
1063
        {
1064
            MSG_ERROR("Couldn't find any ringtone sound file!");
1065
            return;
1066
        }
1067
    }
1068
 
1069
    pool = pjsua_pool_create("wav", 4000, 4000);
1070
    status = pjmedia_wav_player_port_create(pool, tone.c_str(), 0, 0, 0, &file_port);
1071
 
1072
    if (status != PJ_SUCCESS)
1073
    {
1074
        MSG_ERROR("Error creating WAV player port: " << status);
1075
        return;
1076
    }
1077
 
1078
    status = pjsua_conf_add_port(pool, file_port, &file_slot);
1079
 
1080
    if (status != PJ_SUCCESS) {
1081
        MSG_ERROR("Error adding port to conference: " << status);
1082
        return;
1083
    }
1084
 
1085
    mRingtonePortInfo.ring_on = PJ_FALSE;
1086
    mRingtonePortInfo.ring_slot = file_slot;
1087
    mRingtonePortInfo.ring_port = file_port;
1088
    mRingtonePortInfo.pool = pool;
1089
    mPhoneRingInit = true;
1090
}
1091
 
1092
pj_status_t TSIPClient::start_ring_tone()
1093
{
1094
    DECL_TRACER("TSIPClient::start_ring_tone() ");
1095
 
1096
    pj_status_t status;
1097
 
1098
    if (mRingtonePortInfo.ring_on)
1099
    {
1100
        MSG_DEBUG("Ringtone port already connected");
1101
        return PJ_SUCCESS;
1102
    }
1103
 
1104
    MSG_DEBUG("Starting ringtone");
1105
    status = pjsua_conf_connect(mRingtonePortInfo.ring_slot, 0);
1106
    mRingtonePortInfo.ring_on = PJ_TRUE;
1107
 
1108
    if (status != PJ_SUCCESS)
1109
    {
1110
        MSG_ERROR("Error connecting ringtone port: " << status);
1111
    }
1112
 
1113
    return status;
1114
}
1115
 
1116
pj_status_t TSIPClient::stop_ring_tone()
1117
{
1118
    DECL_TRACER("TSIPClient::stop_ring_tone()");
1119
 
1120
    pj_status_t status;
1121
 
1122
    if (!mRingtonePortInfo.ring_on)
1123
    {
1124
        MSG_DEBUG("Ringtone port already disconnected");
1125
        return PJ_SUCCESS;
1126
    }
1127
 
1128
    MSG_DEBUG("Stopping ringtone");
1129
    status = pjsua_conf_disconnect(mRingtonePortInfo.ring_slot, 0);
1130
    mRingtonePortInfo.ring_on = PJ_FALSE;
1131
 
1132
    if (status != PJ_SUCCESS)
1133
    {
1134
        MSG_ERROR("Error disconnecting ringtone port" << status);
1135
    }
1136
 
1137
    return status;
1138
}
1139
 
135 andreas 1140
/*******************************************************************************
1141
 * All the following functions are static callback functions.
1142
 * The following functions are called by the PJSUA-library for different
1143
 * events.
1144
 ******************************************************************************/
1145
 
1146
void TSIPClient::_log_call(int level, const char *data, int len)
1147
{
1148
    string msg;
1149
    msg.assign(data, len);
1150
 
1151
    switch(level)
128 andreas 1152
    {
135 andreas 1153
        case 0: MSG_ERROR("FATAL:" << msg); break;
1154
        case 1: MSG_ERROR(msg); break;
1155
        case 2: MSG_WARNING(msg); break;
1156
        case 3: MSG_INFO(msg); break;
1157
        default:
1158
            MSG_DEBUG(msg);
1159
    }
1160
}
128 andreas 1161
 
135 andreas 1162
void TSIPClient::ringback_start(pjsua_call_id call_id)
1163
{
1164
    DECL_TRACER("TSIPClient::ringback_start(pjsua_call_id call_id)");
128 andreas 1165
 
135 andreas 1166
    if (mAppConfig.call_data[call_id].ringback_on)
1167
        return;
1168
 
1169
    mAppConfig.call_data[call_id].ringback_on = PJ_TRUE;
1170
 
141 andreas 1171
    if (++mAppConfig.ringback_cnt == 1 && mAppConfig.ringback_slot != PJSUA_INVALID_ID)
135 andreas 1172
    {
1173
        pjsua_conf_connect(mAppConfig.ringback_slot, 0);
128 andreas 1174
    }
135 andreas 1175
}
128 andreas 1176
 
135 andreas 1177
void TSIPClient::ring_stop(pjsua_call_id call_id)
1178
{
1179
    DECL_TRACER("TSIPClient::ring_stop(pjsua_call_id call_id)");
1180
 
1181
    if (mAppConfig.no_tones)
1182
        return;
1183
 
1184
    if (mAppConfig.call_data[call_id].ringback_on)
128 andreas 1185
    {
135 andreas 1186
        mAppConfig.call_data[call_id].ringback_on = PJ_FALSE;
1187
 
1188
        pj_assert(mAppConfig.ringback_cnt > 0);
1189
 
1190
        if (--mAppConfig.ringback_cnt == 0 && mAppConfig.ringback_slot != PJSUA_INVALID_ID)
1191
        {
1192
            pjsua_conf_disconnect(mAppConfig.ringback_slot, 0);
1193
            pjmedia_tonegen_rewind(mAppConfig.ringback_port);
1194
        }
128 andreas 1195
    }
1196
 
135 andreas 1197
    if (mAppConfig.call_data[call_id].ring_on)
1198
    {
1199
        mAppConfig.call_data[call_id].ring_on = PJ_FALSE;
128 andreas 1200
 
141 andreas 1201
        pj_assert(mAppConfig.ring_cnt > 0);
135 andreas 1202
 
1203
        if (--mAppConfig.ring_cnt == 0 && mAppConfig.ring_slot != PJSUA_INVALID_ID)
1204
        {
1205
            pjsua_conf_disconnect(mAppConfig.ring_slot, 0);
1206
            pjmedia_tonegen_rewind(mAppConfig.ring_port);
1207
        }
1208
    }
1209
}
1210
 
1211
void TSIPClient::ring_start(pjsua_call_id call_id)
1212
{
1213
    DECL_TRACER("TSIPClient::ring_start(pjsua_call_id call_id)");
1214
 
1215
    if (mAppConfig.no_tones)
1216
        return;
1217
 
1218
    if (mAppConfig.call_data[call_id].ring_on)
1219
        return;
1220
 
1221
    mAppConfig.call_data[call_id].ring_on = PJ_TRUE;
1222
 
141 andreas 1223
    if (++mAppConfig.ring_cnt == 1 && mAppConfig.ring_slot != PJSUA_INVALID_ID)
128 andreas 1224
    {
135 andreas 1225
        pjsua_conf_connect(mAppConfig.ring_slot, 0);
128 andreas 1226
    }
135 andreas 1227
}
128 andreas 1228
 
135 andreas 1229
pj_bool_t TSIPClient::find_next_call(void)
1230
{
1231
    int i, max;
128 andreas 1232
 
135 andreas 1233
    max = pjsua_call_get_max_count();
1234
 
1235
    for (i = mCurrentCall + 1; i < max; ++i)
128 andreas 1236
    {
135 andreas 1237
        if (pjsua_call_is_active(i))
1238
        {
1239
            mCurrentCall = i;
1240
            return PJ_TRUE;
1241
        }
128 andreas 1242
    }
1243
 
135 andreas 1244
    for (i = 0; i < mCurrentCall; ++i)
1245
    {
1246
        if (pjsua_call_is_active(i))
1247
        {
1248
            mCurrentCall = i;
1249
            return PJ_TRUE;
1250
        }
1251
    }
1252
 
1253
    mCurrentCall = PJSUA_INVALID_ID;
1254
    return PJ_FALSE;
128 andreas 1255
}
1256
 
135 andreas 1257
void TSIPClient::call_timeout_callback(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)
128 andreas 1258
{
135 andreas 1259
    DECL_TRACER("TSIPClient::call_timeout_callback(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)");
128 andreas 1260
 
135 andreas 1261
    pjsua_call_id call_id = entry->id;
1262
    pjsua_msg_data msg_data_;
1263
    pjsip_generic_string_hdr warn;
1264
    pj_str_t hname = pj_str((char *)"Warning");
1265
    pj_str_t hvalue = pj_str((char *)"399 pjsua \"Call duration exceeded\"");
128 andreas 1266
 
135 andreas 1267
    PJ_UNUSED_ARG(timer_heap);
128 andreas 1268
 
135 andreas 1269
    if (call_id == PJSUA_INVALID_ID)
128 andreas 1270
    {
135 andreas 1271
        MSG_WARNING("Invalid call ID in timer callback");
1272
        return;
128 andreas 1273
    }
1274
 
135 andreas 1275
    /* Add warning header */
1276
    pjsua_msg_data_init(&msg_data_);
1277
    pjsip_generic_string_hdr_init2(&warn, &hname, &hvalue);
1278
    pj_list_push_back(&msg_data_.hdr_list, &warn);
1279
 
1280
    /* Call duration has been exceeded; disconnect the call */
1281
    MSG_WARNING("Duration (" << mAppConfig.duration << " seconds) has been exceeded for call " << call_id << ", disconnecting the call,");
1282
    entry->id = PJSUA_INVALID_ID;
1283
    pjsua_call_hangup(call_id, 200, NULL, &msg_data_);
1284
    sendConnectionStatus(SIP_DISCONNECTED, call_id);
128 andreas 1285
}
1286
 
135 andreas 1287
void TSIPClient::on_playfile_done(pjmedia_port *port, void *usr_data)
123 andreas 1288
{
135 andreas 1289
    DECL_TRACER("TSIPClient::on_playfile_done(pjmedia_port *port, void *usr_data)");
123 andreas 1290
 
135 andreas 1291
    pj_time_val delay;
123 andreas 1292
 
135 andreas 1293
    PJ_UNUSED_ARG(port);
1294
    PJ_UNUSED_ARG(usr_data);
123 andreas 1295
 
135 andreas 1296
    /* Just rewind WAV when it is played outside of call */
138 andreas 1297
    if (pjsua_call_get_count() == 0)
1298
    {
135 andreas 1299
        pjsua_player_set_pos(mAppConfig.wav_id, 0);
1300
    }
1301
 
1302
    /* Timer is already active */
1303
    if (mAppConfig.auto_hangup_timer.id == 1)
1304
        return;
1305
 
1306
    mAppConfig.auto_hangup_timer.id = 1;
1307
    delay.sec = 0;
1308
    delay.msec = 200; /* Give 200 ms before hangup */
1309
    pjsip_endpt_schedule_timer(pjsua_get_pjsip_endpt(), &mAppConfig.auto_hangup_timer, &delay);
123 andreas 1310
}
1311
 
135 andreas 1312
void TSIPClient::hangup_timeout_callback(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)
123 andreas 1313
{
135 andreas 1314
    DECL_TRACER("TSIPClient::hangup_timeout_callback(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)");
123 andreas 1315
 
135 andreas 1316
    PJ_UNUSED_ARG(timer_heap);
1317
    PJ_UNUSED_ARG(entry);
123 andreas 1318
 
135 andreas 1319
    mAppConfig.auto_hangup_timer.id = 0;
1320
    pjsua_call_hangup_all();
1321
}
123 andreas 1322
 
135 andreas 1323
/* Callback called by the library upon receiving incoming call */
1324
void TSIPClient::on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_rx_data *rdata)
1325
{
1326
    DECL_TRACER("on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_rx_data *rdata)");
1327
 
1328
    pjsua_call_info ci;
1329
 
1330
    PJ_UNUSED_ARG(acc_id);
1331
    PJ_UNUSED_ARG(rdata);
1332
 
1333
    pjsua_call_get_info(call_id, &ci);
1334
 
1335
    MSG_DEBUG("Incoming call from " << ci.remote_info.ptr);
138 andreas 1336
    sendConnectionStatus(SIP_RINGING, call_id);
135 andreas 1337
 
1338
    /* Automatically answer incoming calls with 200/OK */
1339
    if (gPageManager && gPageManager->getPHNautoanswer() && mMyself)
1340
        mMyself->pickup(call_id);
141 andreas 1341
    else if (mMyself)
1342
        mMyself->runRinger();
123 andreas 1343
}
1344
 
135 andreas 1345
/* Callback called by the library when call's state has changed */
1346
void TSIPClient::on_call_state(pjsua_call_id call_id, pjsip_event *e)
127 andreas 1347
{
135 andreas 1348
    DECL_TRACER("on_call_state(pjsua_call_id call_id, pjsip_event *e)");
127 andreas 1349
 
135 andreas 1350
    pjsua_call_info ci;
127 andreas 1351
 
135 andreas 1352
    pjsua_call_get_info(call_id, &ci);
127 andreas 1353
 
135 andreas 1354
    if (ci.state == PJSIP_INV_STATE_DISCONNECTED)
1355
    {
1356
        /* Stop all ringback for this call */
1357
        ring_stop(call_id);
127 andreas 1358
 
141 andreas 1359
        if (mPhoneRingInit)
1360
            stop_ring_tone();
1361
 
135 andreas 1362
        /* Cancel duration timer, if any */
1363
        if (mAppConfig.call_data[call_id].timer.id != PJSUA_INVALID_ID)
1364
        {
1365
            app_call_data *cd = &mAppConfig.call_data[call_id];
1366
            pjsip_endpoint *endpt = pjsua_get_pjsip_endpt();
1367
 
1368
            cd->timer.id = PJSUA_INVALID_ID;
1369
            pjsip_endpt_cancel_timer(endpt, &cd->timer);
1370
        }
1371
 
1372
        /* Rewind play file when hangup automatically,
1373
         * since file is not looped
1374
         */
1375
        if (mAppConfig.auto_play_hangup)
1376
            pjsua_player_set_pos(mAppConfig.wav_id, 0);
1377
 
1378
        string dbgMsg;
1379
 
1380
        if (ci.last_status_text.slen > 0)
1381
            dbgMsg.assign(ci.last_status_text.ptr, ci.last_status_text.slen);
1382
 
1383
        MSG_DEBUG("Call " << call_id << " disconnected [reason: " << ci.last_status << " (" << dbgMsg << ")]");
138 andreas 1384
        sendConnectionStatus(SIP_DISCONNECTED, call_id);
135 andreas 1385
 
1386
        if (call_id == mCurrentCall)
1387
        {
1388
            find_next_call();
1389
        }
1390
    }
1391
    else
127 andreas 1392
    {
135 andreas 1393
        if (mAppConfig.duration != PJSUA_APP_NO_LIMIT_DURATION && ci.state == PJSIP_INV_STATE_CONFIRMED)
127 andreas 1394
        {
135 andreas 1395
            /* Schedule timer to hangup call after the specified duration */
1396
            app_call_data *cd = &mAppConfig.call_data[call_id];
1397
            pjsip_endpoint *endpt = pjsua_get_pjsip_endpt();
1398
            pj_time_val delay;
1399
 
1400
            cd->timer.id = call_id;
1401
            delay.sec = mAppConfig.duration;
1402
            delay.msec = 0;
1403
            pjsip_endpt_schedule_timer(endpt, &cd->timer, &delay);
127 andreas 1404
        }
1405
 
135 andreas 1406
        if (ci.state == PJSIP_INV_STATE_EARLY)
1407
        {
1408
            int code;
1409
            pj_str_t reason;
1410
            pjsip_msg *msg;
1411
 
1412
            /* This can only occur because of TX or RX message */
1413
            pj_assert(e->type == PJSIP_EVENT_TSX_STATE);
1414
 
138 andreas 1415
            if (e->body.tsx_state.type == PJSIP_EVENT_RX_MSG)
1416
            {
135 andreas 1417
                msg = e->body.tsx_state.src.rdata->msg_info.msg;
138 andreas 1418
            }
1419
            else
1420
            {
135 andreas 1421
                msg = e->body.tsx_state.src.tdata->msg;
1422
            }
1423
 
1424
            code = msg->line.status.code;
1425
            reason = msg->line.status.reason;
1426
 
1427
            /* Start ringback for 180 for UAC unless there's SDP in 180 */
1428
            if (ci.role == PJSIP_ROLE_UAC && code == 180 && msg->body == NULL && ci.media_status == PJSUA_CALL_MEDIA_NONE)
1429
            {
1430
                ringback_start(call_id);
1431
            }
1432
 
1433
            string dbgMsg;
1434
            string dbgCode;
1435
 
1436
            if (ci.state_text.slen > 0)
1437
                dbgMsg.assign(ci.state_text.ptr, ci.state_text.slen);
1438
 
1439
            if (reason.slen > 0)
1440
                dbgCode.assign(reason.ptr, reason.slen);
1441
 
1442
            MSG_DEBUG("Call " << call_id << " state changed to " << dbgMsg << " (" << code << " " << dbgCode << ")");
1443
        }
1444
        else
1445
        {
1446
            string dbgMsg;
1447
 
1448
            if (ci.state_text.slen > 0)
1449
                dbgMsg.assign(ci.state_text.ptr, ci.state_text.slen);
1450
 
1451
            MSG_DEBUG("Call " << call_id << " state changed to " << dbgMsg);
141 andreas 1452
 
1453
            if (ci.state == PJSIP_INV_STATE_CONNECTING || ci.state == PJSIP_INV_STATE_CALLING)
1454
                sendConnectionStatus(SIP_TRYING, call_id);
1455
            else if (ci.state == PJSIP_INV_STATE_INCOMING)
1456
                sendConnectionStatus(SIP_RINGING, call_id);
1457
            else if (ci.state == PJSIP_INV_STATE_CONFIRMED)
1458
            {
1459
                ring_stop(call_id);
1460
 
1461
                if (mPhoneRingInit)
1462
                    stop_ring_tone();
1463
 
1464
                sendConnectionStatus(SIP_CONNECTED, call_id);
1465
            }
135 andreas 1466
        }
1467
 
1468
        if (mCurrentCall == PJSUA_INVALID_ID)
1469
            mCurrentCall = call_id;
127 andreas 1470
    }
1471
}
1472
 
135 andreas 1473
/* Callback called by the library when call's media state has changed */
1474
void TSIPClient::on_call_media_state(pjsua_call_id call_id)
127 andreas 1475
{
135 andreas 1476
    DECL_TRACER("on_call_media_state(pjsua_call_id call_id)");
127 andreas 1477
 
135 andreas 1478
    pjsua_call_info ci;
127 andreas 1479
 
135 andreas 1480
    pjsua_call_get_info(call_id, &ci);
127 andreas 1481
 
135 andreas 1482
    if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE)
1483
    {
1484
        // When media is active, connect call to sound device.
1485
        pjsua_conf_connect(ci.conf_slot, 0);
1486
        pjsua_conf_connect(0, ci.conf_slot);
1487
    }
1488
}
127 andreas 1489
 
135 andreas 1490
void TSIPClient::call_on_dtmf_callback2(pjsua_call_id call_id, const pjsua_dtmf_info *info)
1491
{
1492
    DECL_TRACER("TSIPClient::call_on_dtmf_callback2(pjsua_call_id call_id, const pjsua_dtmf_info *info)");
127 andreas 1493
 
135 andreas 1494
    char duration[16];
1495
    char method[16];
1496
 
1497
    duration[0] = '\0';
1498
 
1499
    switch (info->method)
127 andreas 1500
    {
135 andreas 1501
        case PJSUA_DTMF_METHOD_RFC2833:
1502
            pj_ansi_snprintf(method, sizeof(method), "RFC2833");
1503
        break;
127 andreas 1504
 
135 andreas 1505
        case PJSUA_DTMF_METHOD_SIP_INFO:
1506
            pj_ansi_snprintf(method, sizeof(method), "SIP INFO");
1507
            pj_ansi_snprintf(duration, sizeof(duration), ":duration(%d)", info->duration);
1508
        break;
127 andreas 1509
    }
1510
 
135 andreas 1511
    MSG_DEBUG("Incoming DTMF on call " << call_id << ": " << info->digit << duration << ", using " << method << " method.");
127 andreas 1512
}
1513
 
135 andreas 1514
pjsip_redirect_op TSIPClient::call_on_redirected(pjsua_call_id call_id, const pjsip_uri *target, const pjsip_event *e)
127 andreas 1515
{
135 andreas 1516
    DECL_TRACER("TSIPClient::call_on_redirected(pjsua_call_id call_id, const pjsip_uri *target, const pjsip_event *e)");
127 andreas 1517
 
135 andreas 1518
    PJ_UNUSED_ARG(e);
127 andreas 1519
 
135 andreas 1520
    if (mAppConfig.redir_op == PJSIP_REDIRECT_PENDING)
1521
    {
1522
        char uristr[PJSIP_MAX_URL_SIZE];
1523
        int len;
127 andreas 1524
 
135 andreas 1525
        len = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, target, uristr, sizeof(uristr));
127 andreas 1526
 
135 andreas 1527
        if (len < 1)
1528
        {
1529
            pj_ansi_strcpy(uristr, "--URI too long--");
1530
        }
1531
 
1532
        string dbgMsg;
1533
 
1534
        if (len > 0)
1535
            dbgMsg.assign(uristr, len);
1536
 
1537
        MSG_DEBUG("Call " << call_id << " is being redirected to " << dbgMsg << ".");
138 andreas 1538
 
1539
        if (gPageManager)
140 andreas 1540
        {
1541
            vector<string>cmds;
1542
            cmds.push_back("TRANSFERRED");
1543
            cmds.push_back(to_string(call_id));
138 andreas 1544
            gPageManager->sendPHN(cmds);
140 andreas 1545
            sendConnectionStatus(SIP_IDLE, call_id);
1546
        }
127 andreas 1547
    }
1548
 
135 andreas 1549
    return mAppConfig.redir_op;
127 andreas 1550
}
1551
 
135 andreas 1552
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 1553
{
135 andreas 1554
    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 1555
 
135 andreas 1556
    string dbgMsg;
123 andreas 1557
 
135 andreas 1558
    if (status_text->slen > 0)
1559
        dbgMsg.assign(status_text->ptr, status_text->slen);
123 andreas 1560
 
135 andreas 1561
    MSG_DEBUG("Call " << call_id << ": transfer status: " << status_code << " (" << dbgMsg << ") " << (final ? "[final]" : ""));
1562
 
1563
    if ((status_code / 100) == 2)
1564
    {
1565
        MSG_DEBUG("Call " << call_id << ": Call transferred successfully, disconnecting call.");
1566
        pjsua_call_hangup(call_id, PJSIP_SC_GONE, NULL, NULL);
1567
        *p_cont = PJ_FALSE;
1568
 
1569
        if (gPageManager)
1570
        {
1571
            vector<string> cmds;
1572
            cmds.push_back("TRANSFERRED");
1573
            cmds.push_back(to_string(call_id));
1574
            gPageManager->sendPHN(cmds);
138 andreas 1575
            cmds.clear();
1576
            cmds.push_back("DISCONNECTED");
1577
            cmds.push_back(to_string(call_id));
1578
            gPageManager->sendPHN(cmds);
135 andreas 1579
        }
1580
    }
123 andreas 1581
}
1582
 
135 andreas 1583
void TSIPClient::on_transport_state(pjsip_transport *tp, pjsip_transport_state state, const pjsip_transport_state_info *info)
123 andreas 1584
{
135 andreas 1585
    DECL_TRACER("TSIPClient::on_transport_state(pjsip_transport *tp, pjsip_transport_state state, const pjsip_transport_state_info *info)");
123 andreas 1586
 
135 andreas 1587
    char host_port[128];
1588
 
1589
    pj_addr_str_print(&tp->remote_name.host, tp->remote_name.port, host_port, sizeof(host_port), 1);
1590
 
1591
    switch (state)
123 andreas 1592
    {
135 andreas 1593
        case PJSIP_TP_STATE_CONNECTED:
1594
            MSG_DEBUG("SIP " << tp->type_name << " transport is connected to " << host_port);
1595
        break;
123 andreas 1596
 
135 andreas 1597
        case PJSIP_TP_STATE_DISCONNECTED:
1598
        {
1599
            char buf[100];
1600
            size_t len;
124 andreas 1601
 
135 andreas 1602
            len = pj_ansi_snprintf(buf, sizeof(buf), "SIP %s transport is disconnected from %s", tp->type_name, host_port);
1603
            PJ_CHECK_TRUNC_STR(len, buf, sizeof(buf));
1604
            MSG_ERROR(buf << " (" << info->status << ")");
1605
        }
1606
        break;
1607
 
1608
        default:
1609
            break;
124 andreas 1610
    }
135 andreas 1611
}
124 andreas 1612
 
135 andreas 1613
void TSIPClient::on_ip_change_progress(pjsua_ip_change_op op, pj_status_t status, const pjsua_ip_change_op_info *info)
1614
{
1615
    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 1616
 
135 andreas 1617
    char info_str[128];
1618
    pjsua_acc_info acc_info;
1619
    pjsua_transport_info tp_info;
1620
 
1621
    if (status == PJ_SUCCESS)
123 andreas 1622
    {
135 andreas 1623
        switch (op)
1624
        {
1625
            case PJSUA_IP_CHANGE_OP_RESTART_LIS:
1626
                pjsua_transport_get_info(info->lis_restart.transport_id, &tp_info);
1627
                pj_ansi_snprintf(info_str, sizeof(info_str),
1628
                                 "restart transport %.*s",
1629
                                 (int)tp_info.info.slen, tp_info.info.ptr);
1630
            break;
124 andreas 1631
 
135 andreas 1632
            case PJSUA_IP_CHANGE_OP_ACC_SHUTDOWN_TP:
1633
                pjsua_acc_get_info(info->acc_shutdown_tp.acc_id, &acc_info);
127 andreas 1634
 
135 andreas 1635
                pj_ansi_snprintf(info_str, sizeof(info_str),
1636
                                 "transport shutdown for account %.*s",
1637
                                 (int)acc_info.acc_uri.slen,
1638
                                 acc_info.acc_uri.ptr);
1639
            break;
127 andreas 1640
 
135 andreas 1641
            case PJSUA_IP_CHANGE_OP_ACC_UPDATE_CONTACT:
1642
                pjsua_acc_get_info(info->acc_shutdown_tp.acc_id, &acc_info);
1643
                if (info->acc_update_contact.code) {
1644
                    pj_ansi_snprintf(info_str, sizeof(info_str),
1645
                                     "update contact for account %.*s, code[%d]",
1646
                                     (int)acc_info.acc_uri.slen,
1647
                                     acc_info.acc_uri.ptr,
1648
                                     info->acc_update_contact.code);
1649
                } else {
1650
                    pj_ansi_snprintf(info_str, sizeof(info_str),
1651
                                     "update contact for account %.*s",
1652
                                     (int)acc_info.acc_uri.slen,
1653
                                     acc_info.acc_uri.ptr);
1654
                }
1655
            break;
127 andreas 1656
 
135 andreas 1657
            case PJSUA_IP_CHANGE_OP_ACC_HANGUP_CALLS:
1658
                pjsua_acc_get_info(info->acc_shutdown_tp.acc_id, &acc_info);
1659
                pj_ansi_snprintf(info_str, sizeof(info_str),
1660
                                 "hangup call for account %.*s, call_id[%d]",
1661
                                 (int)acc_info.acc_uri.slen, acc_info.acc_uri.ptr,
1662
                                 info->acc_hangup_calls.call_id);
1663
            break;
123 andreas 1664
 
135 andreas 1665
            case PJSUA_IP_CHANGE_OP_ACC_REINVITE_CALLS:
1666
                pjsua_acc_get_info(info->acc_shutdown_tp.acc_id, &acc_info);
1667
                pj_ansi_snprintf(info_str, sizeof(info_str),
1668
                                 "reinvite call for account %.*s, call_id[%d]",
1669
                                 (int)acc_info.acc_uri.slen, acc_info.acc_uri.ptr,
1670
                                 info->acc_reinvite_calls.call_id);
1671
            break;
127 andreas 1672
 
135 andreas 1673
            case PJSUA_IP_CHANGE_OP_COMPLETED:
1674
                pj_ansi_snprintf(info_str, sizeof(info_str), "done");
123 andreas 1675
 
135 andreas 1676
            default:
1677
                break;
1678
        }
123 andreas 1679
 
135 andreas 1680
        MSG_DEBUG("IP change progress report: " << info_str);
1681
    }
1682
    else
1683
    {
1684
        MSG_ERROR("IP change progress failed (" << status << ")");
1685
    }
1686
}
124 andreas 1687
 
135 andreas 1688
/*
1689
 * A simple registrar, invoked by default_mod_on_rx_request()
1690
 */
1691
void TSIPClient::simple_registrar(pjsip_rx_data *rdata)
1692
{
1693
    pjsip_tx_data *tdata;
1694
    const pjsip_expires_hdr *exp;
1695
    const pjsip_hdr *h;
1696
    unsigned cnt = 0;
1697
    pjsip_generic_string_hdr *srv;
1698
    pj_status_t status;
123 andreas 1699
 
135 andreas 1700
    status = pjsip_endpt_create_response(pjsua_get_pjsip_endpt(), rdata, 200, NULL, &tdata);
123 andreas 1701
 
135 andreas 1702
    if (status != PJ_SUCCESS)
1703
        return;
123 andreas 1704
 
135 andreas 1705
    exp = (pjsip_expires_hdr *)pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, NULL);
1706
 
1707
    h = rdata->msg_info.msg->hdr.next;
1708
 
1709
    while (h != &rdata->msg_info.msg->hdr)
1710
    {
1711
        if (h->type == PJSIP_H_CONTACT)
128 andreas 1712
        {
135 andreas 1713
            const pjsip_contact_hdr *c = (const pjsip_contact_hdr*)h;
1714
            unsigned e = c->expires;
123 andreas 1715
 
135 andreas 1716
            if (e != PJSIP_EXPIRES_NOT_SPECIFIED)
128 andreas 1717
            {
135 andreas 1718
                if (exp)
1719
                    e = exp->ivalue;
1720
                else
1721
                    e = 3600;
128 andreas 1722
            }
1723
 
135 andreas 1724
            if (e > 0)
1725
            {
1726
                pjsip_contact_hdr *nc = (pjsip_contact_hdr *)pjsip_hdr_clone(tdata->pool, h);
1727
                nc->expires = e;
1728
                pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)nc);
1729
                ++cnt;
1730
            }
128 andreas 1731
        }
123 andreas 1732
 
135 andreas 1733
        h = h->next;
123 andreas 1734
    }
1735
 
135 andreas 1736
    srv = pjsip_generic_string_hdr_create(tdata->pool, NULL, NULL);
1737
    srv->name = pj_str((char *)"Server");
1738
    srv->hvalue = pj_str((char *)"pjsua simple registrar");
1739
    pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)srv);
1740
 
1741
    status = pjsip_endpt_send_response2(pjsua_get_pjsip_endpt(), rdata, tdata, NULL, NULL);
1742
 
1743
    if (status != PJ_SUCCESS)
1744
        pjsip_tx_data_dec_ref(tdata);
123 andreas 1745
}
124 andreas 1746
 
135 andreas 1747
/*****************************************************************************
1748
 * A simple module to handle otherwise unhandled request. We will register
1749
 * this with the lowest priority.
1750
 */
1751
 
1752
/* Notification on incoming request */
1753
pj_bool_t TSIPClient::default_mod_on_rx_request(pjsip_rx_data *rdata)
124 andreas 1754
{
135 andreas 1755
    pjsip_tx_data *tdata;
1756
    pjsip_status_code status_code;
1757
    pj_status_t status;
124 andreas 1758
 
135 andreas 1759
    /* Don't respond to ACK! */
1760
    if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_ack_method) == 0)
1761
        return PJ_TRUE;
124 andreas 1762
 
135 andreas 1763
    /* Simple registrar */
1764
    if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_register_method) == 0)
1765
    {
1766
        simple_registrar(rdata);
1767
        return PJ_TRUE;
1768
    }
124 andreas 1769
 
135 andreas 1770
    /* Create basic response. */
1771
    if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_notify_method) == 0)
1772
    {
1773
        /* Unsolicited NOTIFY's, send with Bad Request */
1774
        status_code = PJSIP_SC_BAD_REQUEST;
1775
    }
1776
    else
1777
    {
1778
        /* Probably unknown method */
1779
        status_code = PJSIP_SC_METHOD_NOT_ALLOWED;
1780
    }
124 andreas 1781
 
135 andreas 1782
    status = pjsip_endpt_create_response(pjsua_get_pjsip_endpt(), rdata, status_code, NULL, &tdata);
124 andreas 1783
 
135 andreas 1784
    if (status != PJ_SUCCESS)
1785
    {
1786
        MSG_ERROR("Unable to create response");
1787
        return PJ_TRUE;
1788
    }
124 andreas 1789
 
135 andreas 1790
    /* Add Allow if we're responding with 405 */
1791
    if (status_code == PJSIP_SC_METHOD_NOT_ALLOWED)
1792
    {
1793
        const pjsip_hdr *cap_hdr;
1794
        cap_hdr = pjsip_endpt_get_capability(pjsua_get_pjsip_endpt(), PJSIP_H_ALLOW, NULL);
1795
 
1796
        if (cap_hdr)
1797
        {
1798
            pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)pjsip_hdr_clone(tdata->pool, cap_hdr));
1799
        }
1800
    }
1801
 
1802
    /* Add User-Agent header */
1803
    {
1804
        pj_str_t user_agent;
1805
        char tmp[80];
1806
        const pj_str_t USER_AGENT = { (char *)"User-Agent", 10};
1807
        pjsip_hdr *h;
1808
 
1809
        pj_ansi_snprintf(tmp, sizeof(tmp), "PJSUA v%s/%s", pj_get_version(), PJ_OS_NAME);
1810
        pj_strdup2_with_null(tdata->pool, &user_agent, tmp);
1811
 
1812
        h = (pjsip_hdr*) pjsip_generic_string_hdr_create(tdata->pool, &USER_AGENT, &user_agent);
1813
        pjsip_msg_add_hdr(tdata->msg, h);
1814
    }
1815
 
1816
    status = pjsip_endpt_send_response2(pjsua_get_pjsip_endpt(), rdata, tdata, NULL, NULL);
1817
 
1818
    if (status != PJ_SUCCESS) pjsip_tx_data_dec_ref(tdata);
1819
    return PJ_TRUE;
124 andreas 1820
}
1821
 
129 andreas 1822
#endif  // _NOSIP_