1
/* $Id: ua.cpp 3999 2012-03-30 07:10:13Z bennylp $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
#include <pjsua-lib/pjsua.h>
21
#include <pjsua-lib/pjsua_internal.h>
22
//#include <pjmedia/symbian_sound_aps.h>
25
#define THIS_FILE "symbian_ua.cpp"
26
#define CON_LOG_LEVEL 3 // console log level
27
#define FILE_LOG_LEVEL 4 // logfile log level
36
// Destination URI (to make call, or to subscribe presence)
38
#define SIP_DST_URI "<sip:100@pjsip.lab>"
43
#define HAS_SIP_ACCOUNT 0 // 1 to enable registration
44
#define SIP_DOMAIN "pjsip.lab"
45
#define SIP_USER "400"
46
#define SIP_PASSWD "400"
49
// Outbound proxy for all accounts
51
#define SIP_PROXY NULL
52
//#define SIP_PROXY "<sip:192.168.0.8;lr>"
57
#define ENABLE_SIP_UDP 1
58
#define ENABLE_SIP_TCP 0 // experimental
59
#define ENABLE_SIP_TLS 0 // experimental
62
// Configure nameserver if DNS SRV is to be used with both SIP
63
// or STUN (for STUN see other settings below)
65
#define NAMESERVER NULL
66
//#define NAMESERVER "192.168.0.2"
71
// Use this to have the STUN server resolved normally
72
# define STUN_DOMAIN NULL
73
# define STUN_SERVER "stun.pjsip.org"
75
// Use this to have the STUN server resolved with DNS SRV
76
# define STUN_DOMAIN "pjsip.org"
77
# define STUN_SERVER NULL
79
// Use this to disable STUN
80
# define STUN_DOMAIN NULL
81
# define STUN_SERVER NULL
92
#define USE_SRTP PJSUA_DEFAULT_USE_SRTP
95
// Set QoS on transports? Yes!
96
// As an example, we set SIP transports DSCP value to CS3 (DSCP
97
// value 24 or 0x18), for no reason, and tag RTP/RTCP packets
100
#define SIP_QOS_DSCP 0x18
101
#define RTP_QOS_TYPE PJ_QOS_TYPE_VOICE
107
static pjsua_acc_id g_acc_id = PJSUA_INVALID_ID;
108
static pjsua_call_id g_call_id = PJSUA_INVALID_ID;
109
static pjsua_buddy_id g_buddy_id = PJSUA_INVALID_ID;
112
/* Callback called by the library upon receiving incoming call */
113
static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
114
pjsip_rx_data *rdata)
118
PJ_UNUSED_ARG(acc_id);
119
PJ_UNUSED_ARG(rdata);
121
if (g_call_id != PJSUA_INVALID_ID) {
122
pjsua_call_answer(call_id, PJSIP_SC_BUSY_HERE, NULL, NULL);
126
pjsua_call_get_info(call_id, &ci);
128
PJ_LOG(3,(THIS_FILE, "Incoming call from %.*s!!",
129
(int)ci.remote_info.slen,
130
ci.remote_info.ptr));
134
/* Automatically answer incoming calls with 180/Ringing */
135
pjsua_call_answer(call_id, 180, NULL, NULL);
138
/* Callback called by the library when call's state has changed */
139
static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
145
pjsua_call_get_info(call_id, &ci);
147
if (ci.state == PJSIP_INV_STATE_DISCONNECTED) {
148
if (call_id == g_call_id)
149
g_call_id = PJSUA_INVALID_ID;
150
} else if (ci.state != PJSIP_INV_STATE_INCOMING) {
151
if (g_call_id == PJSUA_INVALID_ID)
155
PJ_LOG(3,(THIS_FILE, "Call %d state=%.*s", call_id,
156
(int)ci.state_text.slen,
160
/* Callback called by the library when call's media state has changed */
161
static void on_call_media_state(pjsua_call_id call_id)
165
pjsua_call_get_info(call_id, &ci);
167
if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
168
// When media is active, connect call to sound device.
169
pjsua_conf_connect(ci.conf_slot, 0);
170
pjsua_conf_connect(0, ci.conf_slot);
175
/* Handler on buddy state changed. */
176
static void on_buddy_state(pjsua_buddy_id buddy_id)
178
pjsua_buddy_info info;
179
pjsua_buddy_get_info(buddy_id, &info);
181
PJ_LOG(3,(THIS_FILE, "%.*s status is %.*s",
184
(int)info.status_text.slen,
185
info.status_text.ptr));
189
/* Incoming IM message (i.e. MESSAGE request)! */
190
static void on_pager(pjsua_call_id call_id, const pj_str_t *from,
191
const pj_str_t *to, const pj_str_t *contact,
192
const pj_str_t *mime_type, const pj_str_t *text)
194
/* Note: call index may be -1 */
195
PJ_UNUSED_ARG(call_id);
197
PJ_UNUSED_ARG(contact);
198
PJ_UNUSED_ARG(mime_type);
200
PJ_LOG(3,(THIS_FILE,"MESSAGE from %.*s: %.*s",
201
(int)from->slen, from->ptr,
202
(int)text->slen, text->ptr));
206
/* Received typing indication */
207
static void on_typing(pjsua_call_id call_id, const pj_str_t *from,
208
const pj_str_t *to, const pj_str_t *contact,
211
PJ_UNUSED_ARG(call_id);
213
PJ_UNUSED_ARG(contact);
215
PJ_LOG(3,(THIS_FILE, "IM indication: %.*s %s",
216
(int)from->slen, from->ptr,
217
(is_typing?"is typing..":"has stopped typing")));
221
/* Call transfer request status. */
222
static void on_call_transfer_status(pjsua_call_id call_id,
224
const pj_str_t *status_text,
228
PJ_LOG(3,(THIS_FILE, "Call %d: transfer status=%d (%.*s) %s",
229
call_id, status_code,
230
(int)status_text->slen, status_text->ptr,
231
(final ? "[final]" : "")));
233
if (status_code/100 == 2) {
235
"Call %d: call transfered successfully, disconnecting call",
237
pjsua_call_hangup(call_id, PJSIP_SC_GONE, NULL, NULL);
243
/* NAT detection result */
244
static void on_nat_detect(const pj_stun_nat_detect_result *res)
246
if (res->status != PJ_SUCCESS) {
247
pjsua_perror(THIS_FILE, "NAT detection failed", res->status);
249
PJ_LOG(3, (THIS_FILE, "NAT detected as %s", res->nat_type_name));
253
/* Notification that call is being replaced. */
254
static void on_call_replaced(pjsua_call_id old_call_id,
255
pjsua_call_id new_call_id)
257
pjsua_call_info old_ci, new_ci;
259
pjsua_call_get_info(old_call_id, &old_ci);
260
pjsua_call_get_info(new_call_id, &new_ci);
262
PJ_LOG(3,(THIS_FILE, "Call %d with %.*s is being replaced by "
265
(int)old_ci.remote_info.slen, old_ci.remote_info.ptr,
267
(int)new_ci.remote_info.slen, new_ci.remote_info.ptr));
271
* Transport status notification
273
static void on_transport_state(pjsip_transport *tp,
274
pjsip_transport_state state,
275
const pjsip_transport_state_info *info)
279
pj_ansi_snprintf(host_port, sizeof(host_port), "[%.*s:%d]",
280
(int)tp->remote_name.host.slen,
281
tp->remote_name.host.ptr,
282
tp->remote_name.port);
285
case PJSIP_TP_STATE_CONNECTED:
287
PJ_LOG(3,(THIS_FILE, "SIP transport %s is connected to %s",
288
tp->type_name, host_port));
292
case PJSIP_TP_STATE_DISCONNECTED:
296
snprintf(buf, sizeof(buf), "SIP transport %s is disconnected from %s",
297
tp->type_name, host_port);
298
pjsua_perror(THIS_FILE, buf, info->status);
306
#if defined(PJSIP_HAS_TLS_TRANSPORT) && PJSIP_HAS_TLS_TRANSPORT!=0
308
if (!pj_ansi_stricmp(tp->type_name, "tls") && info->ext_info &&
309
state == PJSIP_TP_STATE_CONNECTED)
311
pjsip_tls_state_info *tls_info = (pjsip_tls_state_info*)info->ext_info;
312
pj_ssl_sock_info *ssl_sock_info = (pj_ssl_sock_info*)
313
tls_info->ssl_sock_info;
316
/* Dump server TLS certificate */
317
pj_ssl_cert_info_dump(ssl_sock_info->remote_cert_info, " ",
319
PJ_LOG(4,(THIS_FILE, "TLS cert info of %s:\n%s", host_port, buf));
326
//#include<e32debug.h>
328
/* Logging callback */
329
static void log_writer(int level, const char *buf, int len)
331
static wchar_t buf16[PJ_LOG_MAX_SIZE];
333
PJ_UNUSED_ARG(level);
335
pj_ansi_to_unicode(buf, len, buf16, PJ_ARRAY_SIZE(buf16));
337
TPtrC16 aBuf((const TUint16*)buf16, (TInt)len);
338
//RDebug::Print(aBuf);
339
console->Write(aBuf);
346
* url may contain URL to call.
348
static pj_status_t app_startup()
352
/* Redirect log before pjsua_init() */
353
pj_log_set_log_func(&log_writer);
356
pj_log_set_level(CON_LOG_LEVEL);
358
/* Create pjsua first! */
359
status = pjsua_create();
360
if (status != PJ_SUCCESS) {
361
pjsua_perror(THIS_FILE, "pjsua_create() error", status);
367
pjsua_logging_config log_cfg;
368
pjsua_media_config med_cfg;
370
pjsua_config_default(&cfg);
372
cfg.thread_cnt = 0; // Disable threading on Symbian
373
cfg.use_srtp = USE_SRTP;
374
cfg.srtp_secure_signaling = 0;
376
cfg.cb.on_incoming_call = &on_incoming_call;
377
cfg.cb.on_call_media_state = &on_call_media_state;
378
cfg.cb.on_call_state = &on_call_state;
379
cfg.cb.on_buddy_state = &on_buddy_state;
380
cfg.cb.on_pager = &on_pager;
381
cfg.cb.on_typing = &on_typing;
382
cfg.cb.on_call_transfer_status = &on_call_transfer_status;
383
cfg.cb.on_call_replaced = &on_call_replaced;
384
cfg.cb.on_nat_detect = &on_nat_detect;
385
cfg.cb.on_transport_state = &on_transport_state;
388
cfg.outbound_proxy_cnt = 1;
389
cfg.outbound_proxy[0] = pj_str(SIP_PROXY);
393
cfg.nameserver_count = 1;
394
cfg.nameserver[0] = pj_str(NAMESERVER);
397
if (NAMESERVER && STUN_DOMAIN) {
398
cfg.stun_domain = pj_str(STUN_DOMAIN);
399
} else if (STUN_SERVER) {
400
cfg.stun_host = pj_str(STUN_SERVER);
404
pjsua_logging_config_default(&log_cfg);
405
log_cfg.level = FILE_LOG_LEVEL;
406
log_cfg.console_level = CON_LOG_LEVEL;
407
log_cfg.cb = &log_writer;
408
log_cfg.log_filename = pj_str("C:\\data\\symbian_ua.log");
410
pjsua_media_config_default(&med_cfg);
411
med_cfg.thread_cnt = 0; // Disable threading on Symbian
412
med_cfg.has_ioqueue = PJ_FALSE;
413
med_cfg.clock_rate = 8000;
414
med_cfg.audio_frame_ptime = 40;
415
med_cfg.ec_tail_len = 0;
416
med_cfg.enable_ice = USE_ICE;
417
med_cfg.snd_auto_close_time = 0; // wait for 0 seconds idle before sound dev get auto-closed
418
//med_cfg.no_vad = PJ_TRUE;
420
status = pjsua_init(&cfg, &log_cfg, &med_cfg);
421
if (status != PJ_SUCCESS) {
422
pjsua_perror(THIS_FILE, "pjsua_init() error", status);
427
/* Adjust Speex priority and enable only the narrowband */
429
pj_str_t codec_id = pj_str("speex/8000");
430
pjmedia_codec_mgr_set_codec_priority(
431
pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
432
&codec_id, PJMEDIA_CODEC_PRIO_NORMAL+1);
434
codec_id = pj_str("speex/16000");
435
pjmedia_codec_mgr_set_codec_priority(
436
pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
437
&codec_id, PJMEDIA_CODEC_PRIO_DISABLED);
439
codec_id = pj_str("speex/32000");
440
pjmedia_codec_mgr_set_codec_priority(
441
pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
442
&codec_id, PJMEDIA_CODEC_PRIO_DISABLED);
446
pjsua_transport_config tcfg;
447
pjsua_transport_id tid;
450
/* Add UDP transport. */
451
pjsua_transport_config_default(&tcfg);
452
tcfg.port = SIP_PORT;
454
tcfg.qos_params.flags |= PJ_QOS_PARAM_HAS_DSCP;
455
tcfg.qos_params.dscp_val = SIP_QOS_DSCP;
457
status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &tcfg, &tid);
458
if (status != PJ_SUCCESS) {
459
pjsua_perror(THIS_FILE, "Error creating UDP transport", status);
466
/* Add TCP transport */
467
pjsua_transport_config_default(&tcfg);
468
tcfg.port = SIP_PORT;
470
tcfg.qos_params.flags |= PJ_QOS_PARAM_HAS_DSCP;
471
tcfg.qos_params.dscp_val = SIP_QOS_DSCP;
473
status = pjsua_transport_create(PJSIP_TRANSPORT_TCP, &tcfg, &tid);
474
if (status != PJ_SUCCESS) {
475
pjsua_perror(THIS_FILE, "Error creating TCP transport", status);
482
/* Add TLS transport */
483
pjsua_transport_config_default(&tcfg);
484
tcfg.port = SIP_PORT + 1;
486
tcfg.qos_params.flags |= PJ_QOS_PARAM_HAS_DSCP;
487
tcfg.qos_params.dscp_val = SIP_QOS_DSCP;
488
tcfg.tls_setting.qos_params = tcfg.qos_params;
490
status = pjsua_transport_create(PJSIP_TRANSPORT_TLS, &tcfg, &tid);
491
if (status != PJ_SUCCESS) {
492
pjsua_perror(THIS_FILE, "Error creating TLS transport", status);
498
/* Add account for the transport */
499
pjsua_acc_add_local(tid, PJ_TRUE, &g_acc_id);
501
#if DISABLED_FOR_TICKET_1185
502
/* Create media transports */
503
pjsua_transport_config mtcfg;
504
pjsua_transport_config_default(&mtcfg);
506
mtcfg.qos_type = RTP_QOS_TYPE;
507
status = pjsua_media_transports_create(&mtcfg);
508
if (status != PJ_SUCCESS) {
509
pjsua_perror(THIS_FILE, "Error creating media transports", status);
515
/* Initialization is done, now start pjsua */
516
status = pjsua_start();
517
if (status != PJ_SUCCESS) {
518
pjsua_perror(THIS_FILE, "Error starting pjsua", status);
523
/* Register to SIP server by creating SIP account. */
524
if (HAS_SIP_ACCOUNT) {
525
pjsua_acc_config cfg;
527
pjsua_acc_config_default(&cfg);
528
cfg.id = pj_str("sip:" SIP_USER "@" SIP_DOMAIN);
529
cfg.reg_uri = pj_str("sip:" SIP_DOMAIN);
531
cfg.cred_info[0].realm = pj_str("*");
532
cfg.cred_info[0].scheme = pj_str("digest");
533
cfg.cred_info[0].username = pj_str(SIP_USER);
534
cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
535
cfg.cred_info[0].data = pj_str(SIP_PASSWD);
537
status = pjsua_acc_add(&cfg, PJ_TRUE, &g_acc_id);
538
if (status != PJ_SUCCESS) {
539
pjsua_perror(THIS_FILE, "Error adding account", status);
546
pjsua_buddy_config bcfg;
548
pjsua_buddy_config_default(&bcfg);
549
bcfg.uri = pj_str(SIP_DST_URI);
550
bcfg.subscribe = PJ_FALSE;
552
pjsua_buddy_add(&bcfg, &g_buddy_id);
558
////////////////////////////////////////////////////////////////////////////
560
* The interractive console UI
564
class ConsoleUI : public CActive
567
ConsoleUI(CConsoleBase *con);
577
// Cancel asynchronous read.
580
// Implementation: called when read has completed.
588
ConsoleUI::ConsoleUI(CConsoleBase *con)
589
: CActive(EPriorityStandard), con_(con)
591
CActiveScheduler::Add(this);
594
ConsoleUI::~ConsoleUI()
600
void ConsoleUI::Run()
607
void ConsoleUI::Stop()
612
// Cancel asynchronous read.
613
void ConsoleUI::DoCancel()
618
static void PrintMainMenu()
623
" d Enable/disable codecs\n"
624
" m Call " SIP_DST_URI "\n"
626
" g Hangup all calls\n"
627
" t Toggle audio route\n"
628
#if !defined(PJMEDIA_CONF_USE_SWITCH_BOARD) || PJMEDIA_CONF_USE_SWITCH_BOARD==0
629
" j Toggle loopback audio\n"
631
"up/dn Increase/decrease output volume\n"
632
" s Subscribe " SIP_DST_URI "\n"
633
" S Unsubscribe presence\n"
634
" o Set account online\n"
635
" O Set account offline\n"
638
PJ_LOG(3, (THIS_FILE, menu));
641
static void PrintCodecMenu()
646
" a Enable all codecs\n"
647
#if PJMEDIA_HAS_PASSTHROUGH_CODECS && PJMEDIA_HAS_PASSTHROUGH_CODEC_AMR
648
" d Enable only AMR\n"
650
#if PJMEDIA_HAS_PASSTHROUGH_CODECS && PJMEDIA_HAS_PASSTHROUGH_CODEC_G729
651
" g Enable only G.729\n"
653
#if PJMEDIA_HAS_PASSTHROUGH_CODECS && PJMEDIA_HAS_PASSTHROUGH_CODEC_ILBC
654
" j Enable only iLBC\n"
656
" m Enable only Speex\n"
657
" p Enable only GSM\n"
658
" t Enable only PCMU\n"
659
" w Enable only PCMA\n";
661
PJ_LOG(3, (THIS_FILE, menu));
664
static void HandleMainMenu(TKeyCode kc) {
673
status = pjsua_snd_get_setting(
674
PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING, &vol);
675
if (status == PJ_SUCCESS) {
676
if (kc == EKeyUpArrow)
677
vol = PJ_MIN(100, vol+10);
679
vol = (vol>=10 ? vol-10 : 0);
680
status = pjsua_snd_set_setting(
681
PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING,
685
if (status == PJ_SUCCESS) {
686
PJ_LOG(3,(THIS_FILE, "Output volume set to %d", vol));
688
pjsua_perror(THIS_FILE, "Error setting volume", status);
695
pjmedia_aud_dev_route route;
698
status = pjsua_snd_get_setting(PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE,
701
if (status == PJ_SUCCESS) {
702
if (route == PJMEDIA_AUD_DEV_ROUTE_LOUDSPEAKER)
703
route = PJMEDIA_AUD_DEV_ROUTE_EARPIECE;
705
route = PJMEDIA_AUD_DEV_ROUTE_LOUDSPEAKER;
707
status = pjsua_snd_set_setting(
708
PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE,
712
if (status != PJ_SUCCESS)
713
pjsua_perror(THIS_FILE, "Error switch audio route", status);
719
static pj_bool_t loopback_active = PJ_FALSE;
720
if (!loopback_active)
721
pjsua_conf_connect(0, 0);
723
pjsua_conf_disconnect(0, 0);
724
loopback_active = !loopback_active;
729
if (g_call_id != PJSUA_INVALID_ID) {
730
PJ_LOG(3,(THIS_FILE, "Another call is active"));
734
if (pjsua_verify_url(SIP_DST_URI) == PJ_SUCCESS) {
735
pj_str_t dst = pj_str(SIP_DST_URI);
736
pjsua_call_make_call(g_acc_id, &dst, 0, NULL,
739
PJ_LOG(3,(THIS_FILE, "Invalid SIP URI"));
743
if (g_call_id != PJSUA_INVALID_ID)
744
pjsua_call_answer(g_call_id, 200, NULL, NULL);
747
pjsua_call_hangup_all();
751
if (g_buddy_id != PJSUA_INVALID_ID)
752
pjsua_buddy_subscribe_pres(g_buddy_id, kc=='s');
756
pjsua_acc_set_online_status(g_acc_id, kc=='o');
760
PJ_LOG(3,(THIS_FILE, "Keycode '%c' (%d) is pressed", kc, kc));
767
static void HandleCodecMenu(TKeyCode kc) {
768
const pj_str_t ID_ALL = {"*", 1};
769
pj_str_t codec = {NULL, 0};
772
pjsua_codec_set_priority(&ID_ALL, PJMEDIA_CODEC_PRIO_NORMAL);
773
PJ_LOG(3,(THIS_FILE, "All codecs activated"));
777
codec = pj_str("AMR");
780
codec = pj_str("G729");
783
codec = pj_str("ILBC");
786
codec = pj_str("SPEEX/8000");
789
codec = pj_str("GSM");
792
codec = pj_str("PCMU");
795
codec = pj_str("PCMA");
798
PJ_LOG(3,(THIS_FILE, "Keycode '%c' (%d) is pressed", kc, kc));
805
pjsua_codec_set_priority(&ID_ALL, PJMEDIA_CODEC_PRIO_DISABLED);
807
status = pjsua_codec_set_priority(&codec,
808
PJMEDIA_CODEC_PRIO_NORMAL);
809
if (status == PJ_SUCCESS)
810
PJ_LOG(3,(THIS_FILE, "%s activated", codec.ptr));
812
PJ_LOG(3,(THIS_FILE, "Failed activating %s, err=%d",
818
// Implementation: called when read has completed.
819
void ConsoleUI::RunL()
825
static int menu_type = MENU_TYPE_MAIN;
826
TKeyCode kc = con_->KeyCode();
827
pj_bool_t reschedule = PJ_TRUE;
829
if (menu_type == MENU_TYPE_MAIN) {
831
CActiveScheduler::Stop();
832
reschedule = PJ_FALSE;
833
} else if (kc == 'd') {
834
menu_type = MENU_TYPE_CODEC;
842
menu_type = MENU_TYPE_MAIN;
851
// IP networking related testing
852
static pj_status_t test_addr(void)
858
const pj_str_t *hostname;
862
pj_log_set_log_func(&log_writer);
865
if (status != PJ_SUCCESS) {
866
pjsua_perror(THIS_FILE, "pj_init() error", status);
874
pj_str_t aa = pj_str("1.1.1.1");
875
in_addr = pj_inet_addr(&aa);
876
char *the_addr = pj_inet_ntoa(in_addr);
877
PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
879
aa = pj_str("192.168.0.15");
880
in_addr = pj_inet_addr(&aa);
881
the_addr = pj_inet_ntoa(in_addr);
882
PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
884
aa = pj_str("2.2.2.2");
885
in_addr = pj_inet_addr(&aa);
886
the_addr = pj_inet_ntoa(in_addr);
887
PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
893
hostname = pj_gethostname();
894
if (hostname == NULL) {
895
status = PJ_ERESOLVE;
896
pjsua_perror(THIS_FILE, "pj_gethostname() error", status);
900
PJ_LOG(3,(THIS_FILE, "Hostname: %.*s", hostname->slen, hostname->ptr));
903
status = pj_gethostbyname(hostname, &he);
904
if (status != PJ_SUCCESS) {
905
pjsua_perror(THIS_FILE, "pj_gethostbyname() error", status);
907
PJ_LOG(3,(THIS_FILE, "gethostbyname: %s",
908
pj_inet_ntoa(*(pj_in_addr*)he.h_addr)));
912
count = PJ_ARRAY_SIZE(ai);
913
status = pj_getaddrinfo(af, hostname, &count, ai);
914
if (status != PJ_SUCCESS) {
915
pjsua_perror(THIS_FILE, "pj_getaddrinfo() error", status);
917
for (i=0; i<count; ++i) {
918
char ipaddr[PJ_INET6_ADDRSTRLEN+2];
919
PJ_LOG(3,(THIS_FILE, "Addrinfo: %s",
920
pj_sockaddr_print(&ai[i].ai_addr, ipaddr, sizeof(ipaddr), 2)));
925
count = PJ_ARRAY_SIZE(ifs);
926
status = pj_enum_ip_interface(af, &count, ifs);
927
if (status != PJ_SUCCESS) {
928
pjsua_perror(THIS_FILE, "pj_enum_ip_interface() error", status);
930
for (i=0; i<count; ++i) {
931
char ipaddr[PJ_INET6_ADDRSTRLEN+2];
932
PJ_LOG(3,(THIS_FILE, "Interface: %s",
933
pj_sockaddr_print(&ifs[i], ipaddr, sizeof(ipaddr), 2)));
937
// Get default iinterface
938
status = pj_getdefaultipinterface(af, &ifs[0]);
939
if (status != PJ_SUCCESS) {
940
pjsua_perror(THIS_FILE, "pj_getdefaultipinterface() error", status);
942
char ipaddr[PJ_INET6_ADDRSTRLEN+2];
943
PJ_LOG(3,(THIS_FILE, "Default IP: %s",
944
pj_sockaddr_print(&ifs[0], ipaddr, sizeof(ipaddr), 2)));
947
// Get default IP address
948
status = pj_gethostip(af, &ifs[0]);
949
if (status != PJ_SUCCESS) {
950
pjsua_perror(THIS_FILE, "pj_gethostip() error", status);
952
char ipaddr[PJ_INET6_ADDRSTRLEN+2];
953
PJ_LOG(3,(THIS_FILE, "Host IP: %s",
954
pj_sockaddr_print(&ifs[0], ipaddr, sizeof(ipaddr), 2)));
969
// Force network connection to use the first IAP,
970
// this is useful for debugging on emulator without GUI.
971
// Include commdb.lib & apengine.lib in symbian_ua.mmp file
972
// if this is enabled.
974
#include <apdatahandler.h>
976
inline void ForceUseFirstIAP()
983
CCommsDatabase* commDb = CCommsDatabase::NewL(EDatabaseTypeIAP);
984
CleanupStack::PushL(commDb);
986
CApDataHandler* apDataHandler = CApDataHandler::NewLC(*commDb);
988
TCommDbConnectionDirection direction = ECommDbConnectionDirectionOutgoing;
989
apDataHandler->GetPreferredIfDbIapTypeL(rank, direction, bearers, prompt, iap);
990
prompt = ECommDbDialogPrefDoNotPrompt;
991
apDataHandler->SetPreferredIfDbIapTypeL(rank, direction, bearers, (TCommDbDialogPref)prompt, iap, ETrue);
992
CleanupStack::PopAndDestroy(2); // apDataHandler, commDb
995
static void SelectIAP()
1002
static void SelectIAP()
1009
// Class CConnMon to monitor network connection (RConnection). Whenever
1010
// the connection is down, it will notify PJLIB and restart PJSUA-LIB.
1011
class CConnMon : public CActive {
1013
static CConnMon* NewL(RConnection &conn, RSocketServ &sserver) {
1014
CConnMon *self = new (ELeave) CConnMon(conn, sserver);
1015
CleanupStack::PushL(self);
1017
CleanupStack::Pop(self);
1022
conn_.ProgressNotification(nif_progress_, iStatus);
1030
~CConnMon() { Stop(); }
1033
CConnMon(RConnection &conn, RSocketServ &sserver) :
1034
CActive(EPriorityHigh),
1038
CActiveScheduler::Add(this);
1041
void ConstructL() {}
1044
conn_.CancelProgressNotification();
1048
int stage = nif_progress_().iStage;
1050
if (stage == KLinkLayerClosed) {
1054
// Tell pjlib that connection is down.
1055
pj_symbianos_set_connection_status(PJ_FALSE);
1057
PJ_LOG(3, (THIS_FILE, "RConnection closed, restarting PJSUA.."));
1061
PJ_LOG(3, (THIS_FILE, "PJSUA destroyed."));
1063
// Reopen the connection
1064
err = conn_.Open(sserver_);
1065
if (err == KErrNone)
1066
err = conn_.Start();
1067
if (err != KErrNone) {
1068
CActiveScheduler::Stop();
1072
// Reinit Symbian OS param before pj_init()
1073
pj_symbianos_params sym_params;
1074
pj_bzero(&sym_params, sizeof(sym_params));
1075
sym_params.rsocketserv = &sserver_;
1076
sym_params.rconnection = &conn_;
1077
pj_symbianos_set_params(&sym_params);
1080
status = app_startup();
1081
if (status != PJ_SUCCESS) {
1082
pjsua_perror(THIS_FILE, "app_startup() error", status);
1083
CActiveScheduler::Stop();
1087
PJ_LOG(3, (THIS_FILE, "PJSUA restarted."));
1095
RSocketServ& sserver_;
1096
TNifProgressBuf nif_progress_;
1099
////////////////////////////////////////////////////////////////////////////
1102
RSocketServ aSocketServer;
1105
pj_symbianos_params sym_params;
1110
// Initialize RSocketServ
1111
if ((err=aSocketServer.Connect(32)) != KErrNone)
1112
return PJ_STATUS_FROM_OS(err);
1114
// Open up a connection
1115
if ((err=aConn.Open(aSocketServer)) != KErrNone) {
1116
aSocketServer.Close();
1117
return PJ_STATUS_FROM_OS(err);
1120
if ((err=aConn.Start()) != KErrNone) {
1121
aSocketServer.Close();
1122
return PJ_STATUS_FROM_OS(err);
1125
// Set Symbian OS parameters in pjlib.
1126
// This must be done before pj_init() is called.
1127
pj_bzero(&sym_params, sizeof(sym_params));
1128
sym_params.rsocketserv = &aSocketServer;
1129
sym_params.rconnection = &aConn;
1130
pj_symbianos_set_params(&sym_params);
1133
status = app_startup();
1134
//status = test_addr();
1135
if (status != PJ_SUCCESS) {
1137
aSocketServer.Close();
1143
ConsoleUI *con = new ConsoleUI(console);
1148
// Init & start connection monitor
1149
CConnMon *connmon = CConnMon::NewL(aConn, aSocketServer);
1152
CActiveScheduler::Start();
1157
// Dump memory statistics
1158
PJ_LOG(3,(THIS_FILE, "Max heap usage: %u.%03uMB",
1159
pjsua_var.cp.peak_used_size / 1000000,
1160
(pjsua_var.cp.peak_used_size % 1000000)/1000));
1162
// check max stack usage
1163
#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
1164
pj_thread_t* this_thread = pj_thread_this();
1168
const char* max_stack_file;
1170
status = pj_thread_get_stack_info(this_thread, &max_stack_file, &max_stack_line);
1172
PJ_LOG(3,(THIS_FILE, "Max stack usage: %u at %s:%d",
1173
pj_thread_get_stack_max_usage(this_thread),
1174
max_stack_file, max_stack_line));
1180
// Close connection and socket server
1182
aSocketServer.Close();