blob: a59b95a921684d83cee3b09e48ad94fe43a12ea6 [file] [log] [blame]
Benny Prijonoba5926a2007-05-02 11:29:37 +00001/* $Id$ */
2/*
Benny Prijono844653c2008-12-23 17:27:53 +00003 * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
Benny Prijonoba5926a2007-05-02 11:29:37 +00005 *
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.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
Benny Prijonoba5926a2007-05-02 11:29:37 +000020#include <pjsua-lib/pjsua.h>
Benny Prijono72a81aa2007-05-02 23:06:11 +000021#include <pjsua-lib/pjsua_internal.h>
Nanang Izzuddina940b362009-02-23 13:53:30 +000022//#include <pjmedia/symbian_sound_aps.h>
Benny Prijonoba5926a2007-05-02 11:29:37 +000023#include "ua.h"
24
25#define THIS_FILE "symbian_ua.cpp"
Nanang Izzuddinda37ea32009-03-06 16:24:43 +000026#define CON_LOG_LEVEL 3 // console log level
27#define FILE_LOG_LEVEL 4 // logfile log level
Benny Prijonoba5926a2007-05-02 11:29:37 +000028
Benny Prijono72a81aa2007-05-02 23:06:11 +000029//
Benny Prijonoc71ad432007-05-04 07:25:19 +000030// Basic config.
31//
32#define SIP_PORT 5060
33
34
35//
Benny Prijonob2c96822007-05-03 13:31:21 +000036// Destination URI (to make call, or to subscribe presence)
37//
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +000038#define SIP_DST_URI "<sip:100@pjsip.lab>"
Benny Prijonob2c96822007-05-03 13:31:21 +000039
40//
Benny Prijono72a81aa2007-05-02 23:06:11 +000041// Account
42//
Nanang Izzuddin82f7a412008-12-17 11:36:22 +000043#define HAS_SIP_ACCOUNT 0 // 1 to enable registration
Benny Prijono0e2c6462008-02-14 13:39:24 +000044#define SIP_DOMAIN "pjsip.lab"
45#define SIP_USER "400"
46#define SIP_PASSWD "400"
Benny Prijonoba5926a2007-05-02 11:29:37 +000047
Benny Prijono72a81aa2007-05-02 23:06:11 +000048//
49// Outbound proxy for all accounts
50//
51#define SIP_PROXY NULL
Benny Prijono4b55e0a2008-12-18 13:22:52 +000052//#define SIP_PROXY "<sip:192.168.0.8;lr>"
Benny Prijono897f9f82007-05-03 19:56:21 +000053
Nanang Izzuddin940d3f62009-06-22 14:06:40 +000054//
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +000055// SIP transports
Nanang Izzuddin940d3f62009-06-22 14:06:40 +000056//
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +000057#define ENABLE_SIP_UDP 1
58#define ENABLE_SIP_TCP 0 // experimental
59#define ENABLE_SIP_TLS 0 // experimental
Benny Prijono897f9f82007-05-03 19:56:21 +000060
Benny Prijono28efe812009-11-09 09:52:23 +000061#define TLS_SRV_NAME "pjsip.org" // TLS servername (required for
62 // TLS transport)
63
Benny Prijono897f9f82007-05-03 19:56:21 +000064//
65// Configure nameserver if DNS SRV is to be used with both SIP
66// or STUN (for STUN see other settings below)
67//
Nanang Izzuddin82f7a412008-12-17 11:36:22 +000068#define NAMESERVER NULL
69//#define NAMESERVER "192.168.0.2"
Benny Prijono897f9f82007-05-03 19:56:21 +000070
71//
72// STUN server
Benny Prijono684c0ad2008-01-03 18:50:27 +000073#if 0
Benny Prijono897f9f82007-05-03 19:56:21 +000074 // Use this to have the STUN server resolved normally
75# define STUN_DOMAIN NULL
Benny Prijono4b55e0a2008-12-18 13:22:52 +000076# define STUN_SERVER "stun.pjsip.org"
Benny Prijono897f9f82007-05-03 19:56:21 +000077#elif 0
78 // Use this to have the STUN server resolved with DNS SRV
Benny Prijono4b55e0a2008-12-18 13:22:52 +000079# define STUN_DOMAIN "pjsip.org"
Benny Prijono897f9f82007-05-03 19:56:21 +000080# define STUN_SERVER NULL
81#else
82 // Use this to disable STUN
83# define STUN_DOMAIN NULL
84# define STUN_SERVER NULL
85#endif
86
87//
88// Use ICE?
89//
Benny Prijono70c5ba02007-12-31 11:27:35 +000090#define USE_ICE 1
Benny Prijono72a81aa2007-05-02 23:06:11 +000091
Nanang Izzuddin6a6392f2008-06-02 18:30:15 +000092//
93// Use SRTP?
94//
95#define USE_SRTP PJSUA_DEFAULT_USE_SRTP
Benny Prijono72a81aa2007-05-02 23:06:11 +000096
Benny Prijonob2c96822007-05-03 13:31:21 +000097//
Benny Prijonoa25bc9d2009-11-09 08:51:34 +000098// Set QoS on transports? Yes!
99// As an example, we set SIP transports DSCP value to CS3 (DSCP
100// value 24 or 0x18), for no reason, and tag RTP/RTCP packets
101// with VOICE type.
102//
103#define SIP_QOS_DSCP 0x18
104#define RTP_QOS_TYPE PJ_QOS_TYPE_VOICE
105
106
107//
Benny Prijonob2c96822007-05-03 13:31:21 +0000108// Globals
109//
110static pjsua_acc_id g_acc_id = PJSUA_INVALID_ID;
111static pjsua_call_id g_call_id = PJSUA_INVALID_ID;
112static pjsua_buddy_id g_buddy_id = PJSUA_INVALID_ID;
Benny Prijono72a81aa2007-05-02 23:06:11 +0000113
Benny Prijonoba5926a2007-05-02 11:29:37 +0000114
115/* Callback called by the library upon receiving incoming call */
116static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
117 pjsip_rx_data *rdata)
118{
119 pjsua_call_info ci;
120
121 PJ_UNUSED_ARG(acc_id);
122 PJ_UNUSED_ARG(rdata);
123
Benny Prijonob2c96822007-05-03 13:31:21 +0000124 if (g_call_id != PJSUA_INVALID_ID) {
125 pjsua_call_answer(call_id, PJSIP_SC_BUSY_HERE, NULL, NULL);
126 return;
127 }
128
Benny Prijonoba5926a2007-05-02 11:29:37 +0000129 pjsua_call_get_info(call_id, &ci);
130
131 PJ_LOG(3,(THIS_FILE, "Incoming call from %.*s!!",
132 (int)ci.remote_info.slen,
133 ci.remote_info.ptr));
134
Benny Prijonob2c96822007-05-03 13:31:21 +0000135 g_call_id = call_id;
136
Benny Prijono897f9f82007-05-03 19:56:21 +0000137 /* Automatically answer incoming calls with 180/Ringing */
138 pjsua_call_answer(call_id, 180, NULL, NULL);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000139}
140
141/* Callback called by the library when call's state has changed */
142static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
143{
144 pjsua_call_info ci;
145
146 PJ_UNUSED_ARG(e);
147
148 pjsua_call_get_info(call_id, &ci);
Benny Prijonob2c96822007-05-03 13:31:21 +0000149
150 if (ci.state == PJSIP_INV_STATE_DISCONNECTED) {
151 if (call_id == g_call_id)
152 g_call_id = PJSUA_INVALID_ID;
Benny Prijono897f9f82007-05-03 19:56:21 +0000153 } else if (ci.state != PJSIP_INV_STATE_INCOMING) {
Benny Prijonob2c96822007-05-03 13:31:21 +0000154 if (g_call_id == PJSUA_INVALID_ID)
155 g_call_id = call_id;
156 }
157
Benny Prijonoba5926a2007-05-02 11:29:37 +0000158 PJ_LOG(3,(THIS_FILE, "Call %d state=%.*s", call_id,
159 (int)ci.state_text.slen,
160 ci.state_text.ptr));
161}
162
163/* Callback called by the library when call's media state has changed */
164static void on_call_media_state(pjsua_call_id call_id)
165{
166 pjsua_call_info ci;
167
168 pjsua_call_get_info(call_id, &ci);
169
170 if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
171 // When media is active, connect call to sound device.
172 pjsua_conf_connect(ci.conf_slot, 0);
173 pjsua_conf_connect(0, ci.conf_slot);
174 }
175}
176
177
Benny Prijonob2c96822007-05-03 13:31:21 +0000178/* Handler on buddy state changed. */
179static void on_buddy_state(pjsua_buddy_id buddy_id)
180{
181 pjsua_buddy_info info;
182 pjsua_buddy_get_info(buddy_id, &info);
183
184 PJ_LOG(3,(THIS_FILE, "%.*s status is %.*s",
185 (int)info.uri.slen,
186 info.uri.ptr,
187 (int)info.status_text.slen,
188 info.status_text.ptr));
189}
190
191
192/* Incoming IM message (i.e. MESSAGE request)! */
193static void on_pager(pjsua_call_id call_id, const pj_str_t *from,
194 const pj_str_t *to, const pj_str_t *contact,
195 const pj_str_t *mime_type, const pj_str_t *text)
196{
197 /* Note: call index may be -1 */
198 PJ_UNUSED_ARG(call_id);
199 PJ_UNUSED_ARG(to);
200 PJ_UNUSED_ARG(contact);
201 PJ_UNUSED_ARG(mime_type);
202
203 PJ_LOG(3,(THIS_FILE,"MESSAGE from %.*s: %.*s",
204 (int)from->slen, from->ptr,
205 (int)text->slen, text->ptr));
206}
207
208
209/* Received typing indication */
210static void on_typing(pjsua_call_id call_id, const pj_str_t *from,
211 const pj_str_t *to, const pj_str_t *contact,
212 pj_bool_t is_typing)
213{
214 PJ_UNUSED_ARG(call_id);
215 PJ_UNUSED_ARG(to);
216 PJ_UNUSED_ARG(contact);
217
218 PJ_LOG(3,(THIS_FILE, "IM indication: %.*s %s",
219 (int)from->slen, from->ptr,
220 (is_typing?"is typing..":"has stopped typing")));
221}
222
223
224/* Call transfer request status. */
225static void on_call_transfer_status(pjsua_call_id call_id,
226 int status_code,
227 const pj_str_t *status_text,
228 pj_bool_t final,
229 pj_bool_t *p_cont)
230{
231 PJ_LOG(3,(THIS_FILE, "Call %d: transfer status=%d (%.*s) %s",
232 call_id, status_code,
233 (int)status_text->slen, status_text->ptr,
234 (final ? "[final]" : "")));
235
236 if (status_code/100 == 2) {
237 PJ_LOG(3,(THIS_FILE,
238 "Call %d: call transfered successfully, disconnecting call",
239 call_id));
240 pjsua_call_hangup(call_id, PJSIP_SC_GONE, NULL, NULL);
241 *p_cont = PJ_FALSE;
242 }
243}
244
245
Benny Prijonoaecabfc2007-10-26 05:35:42 +0000246/* NAT detection result */
247static void on_nat_detect(const pj_stun_nat_detect_result *res)
248{
249 if (res->status != PJ_SUCCESS) {
250 pjsua_perror(THIS_FILE, "NAT detection failed", res->status);
251 } else {
252 PJ_LOG(3, (THIS_FILE, "NAT detected as %s", res->nat_type_name));
253 }
254}
255
Benny Prijonob2c96822007-05-03 13:31:21 +0000256/* Notification that call is being replaced. */
257static void on_call_replaced(pjsua_call_id old_call_id,
258 pjsua_call_id new_call_id)
259{
260 pjsua_call_info old_ci, new_ci;
261
262 pjsua_call_get_info(old_call_id, &old_ci);
263 pjsua_call_get_info(new_call_id, &new_ci);
264
265 PJ_LOG(3,(THIS_FILE, "Call %d with %.*s is being replaced by "
266 "call %d with %.*s",
267 old_call_id,
268 (int)old_ci.remote_info.slen, old_ci.remote_info.ptr,
269 new_call_id,
270 (int)new_ci.remote_info.slen, new_ci.remote_info.ptr));
271}
272
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000273/*
274 * Transport status notification
275 */
Nanang Izzuddin5e69da52010-02-25 11:58:19 +0000276static void on_transport_state(pjsip_transport *tp,
277 pjsip_transport_state state,
278 const pjsip_transport_state_info *info)
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000279{
280 char host_port[128];
281
282 pj_ansi_snprintf(host_port, sizeof(host_port), "[%.*s:%d]",
283 (int)tp->remote_name.host.slen,
284 tp->remote_name.host.ptr,
285 tp->remote_name.port);
286
Nanang Izzuddin5e69da52010-02-25 11:58:19 +0000287 switch (state) {
288 case PJSIP_TP_STATE_CONNECTED:
289 {
290 PJ_LOG(3,(THIS_FILE, "SIP transport %s is connected to %s",
291 tp->type_name, host_port));
292 }
293 break;
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000294
Nanang Izzuddin5e69da52010-02-25 11:58:19 +0000295 case PJSIP_TP_STATE_DISCONNECTED:
296 {
297 char buf[100];
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000298
Nanang Izzuddin5e69da52010-02-25 11:58:19 +0000299 snprintf(buf, sizeof(buf), "SIP transport %s is disconnected from %s",
300 tp->type_name, host_port);
301 pjsua_perror(THIS_FILE, buf, info->status);
302 }
303 break;
304
305 default:
306 break;
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000307 }
308
309#if defined(PJSIP_HAS_TLS_TRANSPORT) && PJSIP_HAS_TLS_TRANSPORT!=0
310
311 if (!pj_ansi_stricmp(tp->type_name, "tls") && info->ext_info &&
Nanang Izzuddin5e69da52010-02-25 11:58:19 +0000312 state == PJSIP_TP_STATE_CONNECTED)
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000313 {
314 pjsip_tls_state_info *tls_info = (pjsip_tls_state_info*)info->ext_info;
315 pj_ssl_sock_info *ssl_sock_info = (pj_ssl_sock_info*)
316 tls_info->ssl_sock_info;
317 char buf[2048];
318
319 /* Dump server TLS certificate */
320 pj_ssl_cert_info_dump(ssl_sock_info->remote_cert_info, " ",
321 buf, sizeof(buf));
322 PJ_LOG(4,(THIS_FILE, "TLS cert info of %s:\n%s", host_port, buf));
323 }
324
325#endif
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000326}
327
Benny Prijonob2c96822007-05-03 13:31:21 +0000328
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000329//#include<e32debug.h>
330
Benny Prijonoba5926a2007-05-02 11:29:37 +0000331/* Logging callback */
Benny Prijono797e3382007-12-01 09:10:07 +0000332static void log_writer(int level, const char *buf, int len)
Benny Prijonoba5926a2007-05-02 11:29:37 +0000333{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000334 static wchar_t buf16[PJ_LOG_MAX_SIZE];
Benny Prijonoba5926a2007-05-02 11:29:37 +0000335
336 PJ_UNUSED_ARG(level);
337
338 pj_ansi_to_unicode(buf, len, buf16, PJ_ARRAY_SIZE(buf16));
339
340 TPtrC16 aBuf((const TUint16*)buf16, (TInt)len);
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000341 //RDebug::Print(aBuf);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000342 console->Write(aBuf);
Benny Prijono797e3382007-12-01 09:10:07 +0000343
Benny Prijonoba5926a2007-05-02 11:29:37 +0000344}
345
346/*
347 * app_startup()
348 *
349 * url may contain URL to call.
350 */
Benny Prijonob2c96822007-05-03 13:31:21 +0000351static pj_status_t app_startup()
Benny Prijonoba5926a2007-05-02 11:29:37 +0000352{
Benny Prijonoba5926a2007-05-02 11:29:37 +0000353 pj_status_t status;
354
355 /* Redirect log before pjsua_init() */
Benny Prijono70c5ba02007-12-31 11:27:35 +0000356 pj_log_set_log_func(&log_writer);
357
358 /* Set log level */
Nanang Izzuddinda37ea32009-03-06 16:24:43 +0000359 pj_log_set_level(CON_LOG_LEVEL);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000360
361 /* Create pjsua first! */
362 status = pjsua_create();
363 if (status != PJ_SUCCESS) {
364 pjsua_perror(THIS_FILE, "pjsua_create() error", status);
365 return status;
366 }
367
Benny Prijonoba5926a2007-05-02 11:29:37 +0000368 /* Init pjsua */
Benny Prijonoc71ad432007-05-04 07:25:19 +0000369 pjsua_config cfg;
370 pjsua_logging_config log_cfg;
371 pjsua_media_config med_cfg;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000372
Benny Prijonoc71ad432007-05-04 07:25:19 +0000373 pjsua_config_default(&cfg);
374 cfg.max_calls = 2;
375 cfg.thread_cnt = 0; // Disable threading on Symbian
Nanang Izzuddin6a6392f2008-06-02 18:30:15 +0000376 cfg.use_srtp = USE_SRTP;
377 cfg.srtp_secure_signaling = 0;
378
Benny Prijonoc71ad432007-05-04 07:25:19 +0000379 cfg.cb.on_incoming_call = &on_incoming_call;
380 cfg.cb.on_call_media_state = &on_call_media_state;
381 cfg.cb.on_call_state = &on_call_state;
382 cfg.cb.on_buddy_state = &on_buddy_state;
383 cfg.cb.on_pager = &on_pager;
384 cfg.cb.on_typing = &on_typing;
385 cfg.cb.on_call_transfer_status = &on_call_transfer_status;
386 cfg.cb.on_call_replaced = &on_call_replaced;
Benny Prijonoaecabfc2007-10-26 05:35:42 +0000387 cfg.cb.on_nat_detect = &on_nat_detect;
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000388 cfg.cb.on_transport_state = &on_transport_state;
Benny Prijonoaecabfc2007-10-26 05:35:42 +0000389
Benny Prijonoc71ad432007-05-04 07:25:19 +0000390 if (SIP_PROXY) {
391 cfg.outbound_proxy_cnt = 1;
392 cfg.outbound_proxy[0] = pj_str(SIP_PROXY);
393 }
394
395 if (NAMESERVER) {
396 cfg.nameserver_count = 1;
397 cfg.nameserver[0] = pj_str(NAMESERVER);
398 }
399
400 if (NAMESERVER && STUN_DOMAIN) {
401 cfg.stun_domain = pj_str(STUN_DOMAIN);
402 } else if (STUN_SERVER) {
403 cfg.stun_host = pj_str(STUN_SERVER);
404 }
405
406
407 pjsua_logging_config_default(&log_cfg);
Nanang Izzuddinda37ea32009-03-06 16:24:43 +0000408 log_cfg.level = FILE_LOG_LEVEL;
409 log_cfg.console_level = CON_LOG_LEVEL;
Benny Prijonoc71ad432007-05-04 07:25:19 +0000410 log_cfg.cb = &log_writer;
Nanang Izzuddin83457d52009-02-16 16:29:05 +0000411 log_cfg.log_filename = pj_str("C:\\data\\symbian_ua.log");
Benny Prijonoba5926a2007-05-02 11:29:37 +0000412
Benny Prijonoc71ad432007-05-04 07:25:19 +0000413 pjsua_media_config_default(&med_cfg);
414 med_cfg.thread_cnt = 0; // Disable threading on Symbian
415 med_cfg.has_ioqueue = PJ_FALSE;
416 med_cfg.clock_rate = 8000;
Benny Prijono5df8bb62007-12-28 18:55:02 +0000417 med_cfg.audio_frame_ptime = 40;
Benny Prijonoc71ad432007-05-04 07:25:19 +0000418 med_cfg.ec_tail_len = 0;
419 med_cfg.enable_ice = USE_ICE;
Nanang Izzuddin81db8c72009-02-05 10:59:14 +0000420 med_cfg.snd_auto_close_time = 0; // wait for 0 seconds idle before sound dev get auto-closed
Nanang Izzuddina3775972009-03-03 18:25:55 +0000421 //med_cfg.no_vad = PJ_TRUE;
Benny Prijonoc71ad432007-05-04 07:25:19 +0000422
423 status = pjsua_init(&cfg, &log_cfg, &med_cfg);
424 if (status != PJ_SUCCESS) {
425 pjsua_perror(THIS_FILE, "pjsua_init() error", status);
426 pjsua_destroy();
427 return status;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000428 }
Nanang Izzuddin829ac022008-05-27 00:24:26 +0000429
430 /* Adjust Speex priority and enable only the narrowband */
431 {
432 pj_str_t codec_id = pj_str("speex/8000");
433 pjmedia_codec_mgr_set_codec_priority(
434 pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
435 &codec_id, PJMEDIA_CODEC_PRIO_NORMAL+1);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000436
Nanang Izzuddin829ac022008-05-27 00:24:26 +0000437 codec_id = pj_str("speex/16000");
438 pjmedia_codec_mgr_set_codec_priority(
439 pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
440 &codec_id, PJMEDIA_CODEC_PRIO_DISABLED);
441
442 codec_id = pj_str("speex/32000");
443 pjmedia_codec_mgr_set_codec_priority(
444 pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
445 &codec_id, PJMEDIA_CODEC_PRIO_DISABLED);
446 }
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000447
Nanang Izzuddin829ac022008-05-27 00:24:26 +0000448
Benny Prijonoc71ad432007-05-04 07:25:19 +0000449 pjsua_transport_config tcfg;
450 pjsua_transport_id tid;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000451
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000452#if ENABLE_SIP_UDP
453 /* Add UDP transport. */
Benny Prijonoc71ad432007-05-04 07:25:19 +0000454 pjsua_transport_config_default(&tcfg);
455 tcfg.port = SIP_PORT;
Benny Prijonoa25bc9d2009-11-09 08:51:34 +0000456 if (SIP_QOS_DSCP) {
457 tcfg.qos_params.flags |= PJ_QOS_PARAM_HAS_DSCP;
458 tcfg.qos_params.dscp_val = SIP_QOS_DSCP;
459 }
Benny Prijonoc71ad432007-05-04 07:25:19 +0000460 status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &tcfg, &tid);
461 if (status != PJ_SUCCESS) {
Nanang Izzuddin940d3f62009-06-22 14:06:40 +0000462 pjsua_perror(THIS_FILE, "Error creating UDP transport", status);
Benny Prijonoc71ad432007-05-04 07:25:19 +0000463 pjsua_destroy();
464 return status;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000465 }
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000466#endif
467
Nanang Izzuddin940d3f62009-06-22 14:06:40 +0000468#if ENABLE_SIP_TCP
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000469 /* Add TCP transport */
Nanang Izzuddin940d3f62009-06-22 14:06:40 +0000470 pjsua_transport_config_default(&tcfg);
471 tcfg.port = SIP_PORT;
Benny Prijonoa25bc9d2009-11-09 08:51:34 +0000472 if (SIP_QOS_DSCP) {
473 tcfg.qos_params.flags |= PJ_QOS_PARAM_HAS_DSCP;
474 tcfg.qos_params.dscp_val = SIP_QOS_DSCP;
475 }
Nanang Izzuddin940d3f62009-06-22 14:06:40 +0000476 status = pjsua_transport_create(PJSIP_TRANSPORT_TCP, &tcfg, &tid);
477 if (status != PJ_SUCCESS) {
478 pjsua_perror(THIS_FILE, "Error creating TCP transport", status);
479 pjsua_destroy();
480 return status;
481 }
482#endif
483
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000484#if ENABLE_SIP_TLS
485 /* Add TLS transport */
486 pjsua_transport_config_default(&tcfg);
487 tcfg.port = SIP_PORT + 1;
Benny Prijonoa25bc9d2009-11-09 08:51:34 +0000488 if (SIP_QOS_DSCP) {
489 tcfg.qos_params.flags |= PJ_QOS_PARAM_HAS_DSCP;
490 tcfg.qos_params.dscp_val = SIP_QOS_DSCP;
491 tcfg.tls_setting.qos_params = tcfg.qos_params;
492 }
Benny Prijono28efe812009-11-09 09:52:23 +0000493 tcfg.tls_setting.server_name = pj_str(TLS_SRV_NAME);
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000494 status = pjsua_transport_create(PJSIP_TRANSPORT_TLS, &tcfg, &tid);
495 if (status != PJ_SUCCESS) {
496 pjsua_perror(THIS_FILE, "Error creating TLS transport", status);
497 pjsua_destroy();
498 return status;
499 }
500#endif
501
Benny Prijonoc71ad432007-05-04 07:25:19 +0000502 /* Add account for the transport */
503 pjsua_acc_add_local(tid, PJ_TRUE, &g_acc_id);
504
Benny Prijonoa25bc9d2009-11-09 08:51:34 +0000505 /* Create media transports */
506 pjsua_transport_config mtcfg;
507 pjsua_transport_config_default(&mtcfg);
508 mtcfg.port = 4000;
509 mtcfg.qos_type = RTP_QOS_TYPE;
510 status = pjsua_media_transports_create(&mtcfg);
511 if (status != PJ_SUCCESS) {
512 pjsua_perror(THIS_FILE, "Error creating media transports", status);
513 pjsua_destroy();
514 return status;
515 }
516
Benny Prijonoba5926a2007-05-02 11:29:37 +0000517 /* Initialization is done, now start pjsua */
518 status = pjsua_start();
519 if (status != PJ_SUCCESS) {
520 pjsua_perror(THIS_FILE, "Error starting pjsua", status);
521 pjsua_destroy();
522 return status;
523 }
524
525 /* Register to SIP server by creating SIP account. */
Benny Prijono72a81aa2007-05-02 23:06:11 +0000526 if (HAS_SIP_ACCOUNT) {
Benny Prijonoba5926a2007-05-02 11:29:37 +0000527 pjsua_acc_config cfg;
528
529 pjsua_acc_config_default(&cfg);
530 cfg.id = pj_str("sip:" SIP_USER "@" SIP_DOMAIN);
531 cfg.reg_uri = pj_str("sip:" SIP_DOMAIN);
532 cfg.cred_count = 1;
Benny Prijono0e2c6462008-02-14 13:39:24 +0000533 cfg.cred_info[0].realm = pj_str("*");
Benny Prijonoba5926a2007-05-02 11:29:37 +0000534 cfg.cred_info[0].scheme = pj_str("digest");
535 cfg.cred_info[0].username = pj_str(SIP_USER);
536 cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
537 cfg.cred_info[0].data = pj_str(SIP_PASSWD);
538
Benny Prijonob2c96822007-05-03 13:31:21 +0000539 status = pjsua_acc_add(&cfg, PJ_TRUE, &g_acc_id);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000540 if (status != PJ_SUCCESS) {
541 pjsua_perror(THIS_FILE, "Error adding account", status);
542 pjsua_destroy();
543 return status;
544 }
545 }
546
Benny Prijonob2c96822007-05-03 13:31:21 +0000547 if (SIP_DST_URI) {
548 pjsua_buddy_config bcfg;
549
550 pjsua_buddy_config_default(&bcfg);
551 bcfg.uri = pj_str(SIP_DST_URI);
552 bcfg.subscribe = PJ_FALSE;
553
554 pjsua_buddy_add(&bcfg, &g_buddy_id);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000555 }
Benny Prijonoba5926a2007-05-02 11:29:37 +0000556 return PJ_SUCCESS;
557}
558
559
560////////////////////////////////////////////////////////////////////////////
Benny Prijonoc71ad432007-05-04 07:25:19 +0000561/*
562 * The interractive console UI
563 */
Benny Prijonoba5926a2007-05-02 11:29:37 +0000564#include <e32base.h>
565
566class ConsoleUI : public CActive
567{
568public:
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000569 ConsoleUI(CConsoleBase *con);
Nanang Izzuddin90b83202009-03-02 15:48:45 +0000570 ~ConsoleUI();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000571
Benny Prijonoc71ad432007-05-04 07:25:19 +0000572 // Run console UI
573 void Run();
574
575 // Stop
576 void Stop();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000577
578protected:
Benny Prijonoc71ad432007-05-04 07:25:19 +0000579 // Cancel asynchronous read.
580 void DoCancel();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000581
Benny Prijonoc71ad432007-05-04 07:25:19 +0000582 // Implementation: called when read has completed.
583 void RunL();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000584
585private:
Benny Prijonoc71ad432007-05-04 07:25:19 +0000586 CConsoleBase *con_;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000587};
588
589
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000590ConsoleUI::ConsoleUI(CConsoleBase *con)
591: CActive(EPriorityStandard), con_(con)
Benny Prijonoba5926a2007-05-02 11:29:37 +0000592{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000593 CActiveScheduler::Add(this);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000594}
595
Nanang Izzuddin90b83202009-03-02 15:48:45 +0000596ConsoleUI::~ConsoleUI()
597{
598 Stop();
599}
600
Benny Prijonoba5926a2007-05-02 11:29:37 +0000601// Run console UI
602void ConsoleUI::Run()
603{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000604 con_->Read(iStatus);
605 SetActive();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000606}
607
608// Stop console UI
609void ConsoleUI::Stop()
610{
Nanang Izzuddin90b83202009-03-02 15:48:45 +0000611 Cancel();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000612}
613
614// Cancel asynchronous read.
615void ConsoleUI::DoCancel()
616{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000617 con_->ReadCancel();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000618}
619
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000620static void PrintMainMenu()
Benny Prijono72a81aa2007-05-02 23:06:11 +0000621{
Nanang Izzuddinda37ea32009-03-06 16:24:43 +0000622 const char *menu =
623 "\n\n"
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000624 "Main Menu:\n"
625 " d Enable/disable codecs\n"
Benny Prijono70c5ba02007-12-31 11:27:35 +0000626 " m Call " SIP_DST_URI "\n"
627 " a Answer call\n"
628 " g Hangup all calls\n"
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000629 " t Toggle audio route\n"
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000630#if !defined(PJMEDIA_CONF_USE_SWITCH_BOARD) || PJMEDIA_CONF_USE_SWITCH_BOARD==0
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000631 " j Toggle loopback audio\n"
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000632#endif
Nanang Izzuddin08694ea2009-03-10 15:03:04 +0000633 "up/dn Increase/decrease output volume\n"
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000634 " s Subscribe " SIP_DST_URI "\n"
Benny Prijonoc71ad432007-05-04 07:25:19 +0000635 " S Unsubscribe presence\n"
636 " o Set account online\n"
637 " O Set account offline\n"
Nanang Izzuddinda37ea32009-03-06 16:24:43 +0000638 " w Quit\n";
639
640 PJ_LOG(3, (THIS_FILE, menu));
Benny Prijono72a81aa2007-05-02 23:06:11 +0000641}
642
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000643static void PrintCodecMenu()
644{
Nanang Izzuddinda37ea32009-03-06 16:24:43 +0000645 const char *menu =
646 "\n\n"
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000647 "Codec Menu:\n"
648 " a Enable all codecs\n"
Nanang Izzuddin9608db42010-08-06 03:24:15 +0000649#if PJMEDIA_HAS_PASSTHROUGH_CODECS && PJMEDIA_HAS_PASSTHROUGH_CODEC_AMR
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000650 " d Enable only AMR\n"
Nanang Izzuddina3775972009-03-03 18:25:55 +0000651#endif
Nanang Izzuddin9608db42010-08-06 03:24:15 +0000652#if PJMEDIA_HAS_PASSTHROUGH_CODECS && PJMEDIA_HAS_PASSTHROUGH_CODEC_G729
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000653 " g Enable only G.729\n"
Nanang Izzuddina3775972009-03-03 18:25:55 +0000654#endif
Nanang Izzuddin9608db42010-08-06 03:24:15 +0000655#if PJMEDIA_HAS_PASSTHROUGH_CODECS && PJMEDIA_HAS_PASSTHROUGH_CODEC_ILBC
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000656 " j Enable only iLBC\n"
657#endif
658 " m Enable only Speex\n"
659 " p Enable only GSM\n"
660 " t Enable only PCMU\n"
Nanang Izzuddinda37ea32009-03-06 16:24:43 +0000661 " w Enable only PCMA\n";
662
663 PJ_LOG(3, (THIS_FILE, menu));
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000664}
665
666static void HandleMainMenu(TKeyCode kc) {
667 switch (kc) {
668
Nanang Izzuddin08694ea2009-03-10 15:03:04 +0000669 case EKeyUpArrow:
670 case EKeyDownArrow:
671 {
672 unsigned vol;
673 pj_status_t status;
674
675 status = pjsua_snd_get_setting(
676 PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING, &vol);
677 if (status == PJ_SUCCESS) {
678 if (kc == EKeyUpArrow)
679 vol = PJ_MIN(100, vol+10);
680 else
681 vol = (vol>=10 ? vol-10 : 0);
682 status = pjsua_snd_set_setting(
683 PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING,
684 &vol, PJ_TRUE);
685 }
686
687 if (status == PJ_SUCCESS) {
688 PJ_LOG(3,(THIS_FILE, "Output volume set to %d", vol));
689 } else {
690 pjsua_perror(THIS_FILE, "Error setting volume", status);
691 }
692 }
693 break;
694
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000695 case 't':
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000696 {
Nanang Izzuddinfcb92d02009-03-10 13:32:09 +0000697 pjmedia_aud_dev_route route;
698 pj_status_t status;
699
700 status = pjsua_snd_get_setting(PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE,
701 &route);
702
703 if (status == PJ_SUCCESS) {
704 if (route == PJMEDIA_AUD_DEV_ROUTE_LOUDSPEAKER)
705 route = PJMEDIA_AUD_DEV_ROUTE_EARPIECE;
706 else
707 route = PJMEDIA_AUD_DEV_ROUTE_LOUDSPEAKER;
Nanang Izzuddin452b66b2009-02-18 15:23:47 +0000708
Nanang Izzuddinfcb92d02009-03-10 13:32:09 +0000709 status = pjsua_snd_set_setting(
710 PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE,
711 &route, PJ_TRUE);
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000712 }
Nanang Izzuddinfcb92d02009-03-10 13:32:09 +0000713
714 if (status != PJ_SUCCESS)
715 pjsua_perror(THIS_FILE, "Error switch audio route", status);
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000716 }
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000717 break;
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000718
719 case 'j':
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000720 {
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000721 static pj_bool_t loopback_active = PJ_FALSE;
722 if (!loopback_active)
723 pjsua_conf_connect(0, 0);
724 else
725 pjsua_conf_disconnect(0, 0);
726 loopback_active = !loopback_active;
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000727 }
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000728 break;
729
730 case 'm':
731 if (g_call_id != PJSUA_INVALID_ID) {
732 PJ_LOG(3,(THIS_FILE, "Another call is active"));
733 break;
734 }
735
Benny Prijonoc7545782010-09-28 07:43:18 +0000736 if (pjsua_verify_url(SIP_DST_URI) == PJ_SUCCESS) {
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000737 pj_str_t dst = pj_str(SIP_DST_URI);
738 pjsua_call_make_call(g_acc_id, &dst, 0, NULL,
739 NULL, &g_call_id);
740 } else {
741 PJ_LOG(3,(THIS_FILE, "Invalid SIP URI"));
742 }
743 break;
744 case 'a':
745 if (g_call_id != PJSUA_INVALID_ID)
746 pjsua_call_answer(g_call_id, 200, NULL, NULL);
747 break;
748 case 'g':
749 pjsua_call_hangup_all();
750 break;
751 case 's':
752 case 'S':
753 if (g_buddy_id != PJSUA_INVALID_ID)
754 pjsua_buddy_subscribe_pres(g_buddy_id, kc=='s');
755 break;
756 case 'o':
757 case 'O':
758 pjsua_acc_set_online_status(g_acc_id, kc=='o');
759 break;
760
761 default:
762 PJ_LOG(3,(THIS_FILE, "Keycode '%c' (%d) is pressed", kc, kc));
763 break;
764 }
765
766 PrintMainMenu();
767}
768
769static void HandleCodecMenu(TKeyCode kc) {
770 const pj_str_t ID_ALL = {"*", 1};
771 pj_str_t codec = {NULL, 0};
772
773 if (kc == 'a') {
774 pjsua_codec_set_priority(&ID_ALL, PJMEDIA_CODEC_PRIO_NORMAL);
775 PJ_LOG(3,(THIS_FILE, "All codecs activated"));
776 } else {
777 switch (kc) {
778 case 'd':
779 codec = pj_str("AMR");
780 break;
781 case 'g':
782 codec = pj_str("G729");
783 break;
784 case 'j':
785 codec = pj_str("ILBC");
786 break;
787 case 'm':
788 codec = pj_str("SPEEX/8000");
789 break;
790 case 'p':
791 codec = pj_str("GSM");
792 break;
793 case 't':
794 codec = pj_str("PCMU");
795 break;
796 case 'w':
797 codec = pj_str("PCMA");
798 break;
799 default:
800 PJ_LOG(3,(THIS_FILE, "Keycode '%c' (%d) is pressed", kc, kc));
801 break;
802 }
803
804 if (codec.slen) {
805 pj_status_t status;
806
807 pjsua_codec_set_priority(&ID_ALL, PJMEDIA_CODEC_PRIO_DISABLED);
808
809 status = pjsua_codec_set_priority(&codec,
810 PJMEDIA_CODEC_PRIO_NORMAL);
811 if (status == PJ_SUCCESS)
812 PJ_LOG(3,(THIS_FILE, "%s activated", codec.ptr));
813 else
814 PJ_LOG(3,(THIS_FILE, "Failed activating %s, err=%d",
815 codec.ptr, status));
816 }
817 }
Benny Prijonoba5926a2007-05-02 11:29:37 +0000818}
819
820// Implementation: called when read has completed.
821void ConsoleUI::RunL()
822{
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000823 enum {
824 MENU_TYPE_MAIN = 0,
825 MENU_TYPE_CODEC = 1
826 };
827 static int menu_type = MENU_TYPE_MAIN;
Benny Prijonoc71ad432007-05-04 07:25:19 +0000828 TKeyCode kc = con_->KeyCode();
829 pj_bool_t reschedule = PJ_TRUE;
830
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000831 if (menu_type == MENU_TYPE_MAIN) {
832 if (kc == 'w') {
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000833 CActiveScheduler::Stop();
Benny Prijonoc71ad432007-05-04 07:25:19 +0000834 reschedule = PJ_FALSE;
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000835 } else if (kc == 'd') {
836 menu_type = MENU_TYPE_CODEC;
837 PrintCodecMenu();
838 } else {
839 HandleMainMenu(kc);
840 }
841 } else {
842 HandleCodecMenu(kc);
843
844 menu_type = MENU_TYPE_MAIN;
845 PrintMainMenu();
Benny Prijonoc71ad432007-05-04 07:25:19 +0000846 }
Benny Prijonoc71ad432007-05-04 07:25:19 +0000847
848 if (reschedule)
849 Run();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000850}
851
Benny Prijono70c5ba02007-12-31 11:27:35 +0000852#if 0
853// IP networking related testing
854static pj_status_t test_addr(void)
855{
856 int af;
857 unsigned i, count;
858 pj_addrinfo ai[8];
859 pj_sockaddr ifs[8];
860 const pj_str_t *hostname;
861 pj_hostent he;
862 pj_status_t status;
863
864 pj_log_set_log_func(&log_writer);
865
866 status = pj_init();
867 if (status != PJ_SUCCESS) {
868 pjsua_perror(THIS_FILE, "pj_init() error", status);
869 return status;
870 }
871
872 af = pj_AF_INET();
873
Benny Prijono684c0ad2008-01-03 18:50:27 +0000874#if 0
875 pj_in_addr in_addr;
876 pj_str_t aa = pj_str("1.1.1.1");
877 in_addr = pj_inet_addr(&aa);
878 char *the_addr = pj_inet_ntoa(in_addr);
879 PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
880
881 aa = pj_str("192.168.0.15");
882 in_addr = pj_inet_addr(&aa);
883 the_addr = pj_inet_ntoa(in_addr);
884 PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
885
886 aa = pj_str("2.2.2.2");
887 in_addr = pj_inet_addr(&aa);
888 the_addr = pj_inet_ntoa(in_addr);
889 PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
890
891 return -1;
892#endif
893
Benny Prijono70c5ba02007-12-31 11:27:35 +0000894 // Hostname
895 hostname = pj_gethostname();
896 if (hostname == NULL) {
897 status = PJ_ERESOLVE;
898 pjsua_perror(THIS_FILE, "pj_gethostname() error", status);
899 goto on_return;
900 }
901
902 PJ_LOG(3,(THIS_FILE, "Hostname: %.*s", hostname->slen, hostname->ptr));
903
904 // Gethostbyname
905 status = pj_gethostbyname(hostname, &he);
906 if (status != PJ_SUCCESS) {
907 pjsua_perror(THIS_FILE, "pj_gethostbyname() error", status);
908 } else {
909 PJ_LOG(3,(THIS_FILE, "gethostbyname: %s",
910 pj_inet_ntoa(*(pj_in_addr*)he.h_addr)));
911 }
912
913 // Getaddrinfo
914 count = PJ_ARRAY_SIZE(ai);
915 status = pj_getaddrinfo(af, hostname, &count, ai);
916 if (status != PJ_SUCCESS) {
917 pjsua_perror(THIS_FILE, "pj_getaddrinfo() error", status);
918 } else {
919 for (i=0; i<count; ++i) {
920 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
921 PJ_LOG(3,(THIS_FILE, "Addrinfo: %s",
922 pj_sockaddr_print(&ai[i].ai_addr, ipaddr, sizeof(ipaddr), 2)));
923 }
924 }
925
926 // Enum interface
927 count = PJ_ARRAY_SIZE(ifs);
928 status = pj_enum_ip_interface(af, &count, ifs);
929 if (status != PJ_SUCCESS) {
930 pjsua_perror(THIS_FILE, "pj_enum_ip_interface() error", status);
931 } else {
932 for (i=0; i<count; ++i) {
933 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
934 PJ_LOG(3,(THIS_FILE, "Interface: %s",
935 pj_sockaddr_print(&ifs[i], ipaddr, sizeof(ipaddr), 2)));
936 }
937 }
938
939 // Get default iinterface
940 status = pj_getdefaultipinterface(af, &ifs[0]);
941 if (status != PJ_SUCCESS) {
942 pjsua_perror(THIS_FILE, "pj_getdefaultipinterface() error", status);
943 } else {
944 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
945 PJ_LOG(3,(THIS_FILE, "Default IP: %s",
946 pj_sockaddr_print(&ifs[0], ipaddr, sizeof(ipaddr), 2)));
947 }
948
949 // Get default IP address
950 status = pj_gethostip(af, &ifs[0]);
951 if (status != PJ_SUCCESS) {
952 pjsua_perror(THIS_FILE, "pj_gethostip() error", status);
953 } else {
954 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
955 PJ_LOG(3,(THIS_FILE, "Host IP: %s",
956 pj_sockaddr_print(&ifs[0], ipaddr, sizeof(ipaddr), 2)));
957 }
958
959 status = -1;
960
961on_return:
962 pj_shutdown();
963 return status;
964}
965#endif
966
967
Benny Prijono6b3ccdf2008-01-14 11:54:21 +0000968#include <es_sock.h>
Benny Prijono897f9f82007-05-03 19:56:21 +0000969
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000970#if 0
971// Force network connection to use the first IAP,
972// this is useful for debugging on emulator without GUI.
973// Include commdb.lib & apengine.lib in symbian_ua.mmp file
974// if this is enabled.
975
976#include <apdatahandler.h>
977
978inline void ForceUseFirstIAP()
979{
980 TUint32 rank = 1;
981 TUint32 bearers;
982 TUint32 prompt;
983 TUint32 iap;
984
985 CCommsDatabase* commDb = CCommsDatabase::NewL(EDatabaseTypeIAP);
986 CleanupStack::PushL(commDb);
987
988 CApDataHandler* apDataHandler = CApDataHandler::NewLC(*commDb);
989
990 TCommDbConnectionDirection direction = ECommDbConnectionDirectionOutgoing;
991 apDataHandler->GetPreferredIfDbIapTypeL(rank, direction, bearers, prompt, iap);
992 prompt = ECommDbDialogPrefDoNotPrompt;
993 apDataHandler->SetPreferredIfDbIapTypeL(rank, direction, bearers, (TCommDbDialogPref)prompt, iap, ETrue);
994 CleanupStack::PopAndDestroy(2); // apDataHandler, commDb
995}
996
997static void SelectIAP()
998{
999 ForceUseFirstIAP();
1000}
1001
1002#else
1003
1004static void SelectIAP()
1005{
1006}
1007
1008#endif
1009
1010
Nanang Izzuddin90b83202009-03-02 15:48:45 +00001011// Class CConnMon to monitor network connection (RConnection). Whenever
1012// the connection is down, it will notify PJLIB and restart PJSUA-LIB.
1013class CConnMon : public CActive {
1014public:
1015 static CConnMon* NewL(RConnection &conn, RSocketServ &sserver) {
1016 CConnMon *self = new (ELeave) CConnMon(conn, sserver);
1017 CleanupStack::PushL(self);
1018 self->ConstructL();
1019 CleanupStack::Pop(self);
1020 return self;
1021 }
1022
1023 void Start() {
1024 conn_.ProgressNotification(nif_progress_, iStatus);
1025 SetActive();
1026 }
1027
1028 void Stop() {
1029 Cancel();
1030 }
1031
1032 ~CConnMon() { Stop(); }
1033
1034private:
1035 CConnMon(RConnection &conn, RSocketServ &sserver) :
1036 CActive(EPriorityHigh),
1037 conn_(conn),
1038 sserver_(sserver)
1039 {
1040 CActiveScheduler::Add(this);
1041 }
1042
1043 void ConstructL() {}
1044
1045 void DoCancel() {
1046 conn_.CancelProgressNotification();
1047 }
1048
1049 void RunL() {
1050 int stage = nif_progress_().iStage;
1051
1052 if (stage == KLinkLayerClosed) {
1053 pj_status_t status;
1054 TInt err;
1055
1056 // Tell pjlib that connection is down.
1057 pj_symbianos_set_connection_status(PJ_FALSE);
1058
1059 PJ_LOG(3, (THIS_FILE, "RConnection closed, restarting PJSUA.."));
1060
1061 // Destroy pjsua
1062 pjsua_destroy();
1063 PJ_LOG(3, (THIS_FILE, "PJSUA destroyed."));
1064
1065 // Reopen the connection
1066 err = conn_.Open(sserver_);
1067 if (err == KErrNone)
1068 err = conn_.Start();
1069 if (err != KErrNone) {
1070 CActiveScheduler::Stop();
1071 return;
1072 }
1073
1074 // Reinit Symbian OS param before pj_init()
1075 pj_symbianos_params sym_params;
1076 pj_bzero(&sym_params, sizeof(sym_params));
1077 sym_params.rsocketserv = &sserver_;
1078 sym_params.rconnection = &conn_;
1079 pj_symbianos_set_params(&sym_params);
1080
1081 // Reinit pjsua
1082 status = app_startup();
1083 if (status != PJ_SUCCESS) {
1084 pjsua_perror(THIS_FILE, "app_startup() error", status);
1085 CActiveScheduler::Stop();
1086 return;
1087 }
1088
1089 PJ_LOG(3, (THIS_FILE, "PJSUA restarted."));
Benny Prijono9920dc32009-03-12 18:11:37 +00001090 PrintMainMenu();
Nanang Izzuddin90b83202009-03-02 15:48:45 +00001091 }
1092
1093 Start();
1094 }
1095
1096 RConnection& conn_;
1097 RSocketServ& sserver_;
1098 TNifProgressBuf nif_progress_;
1099};
1100
Benny Prijonoba5926a2007-05-02 11:29:37 +00001101////////////////////////////////////////////////////////////////////////////
1102int ua_main()
1103{
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001104 RSocketServ aSocketServer;
1105 RConnection aConn;
1106 TInt err;
1107 pj_symbianos_params sym_params;
Benny Prijonoc71ad432007-05-04 07:25:19 +00001108 pj_status_t status;
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001109
1110 SelectIAP();
Benny Prijonoc71ad432007-05-04 07:25:19 +00001111
Benny Prijono70c5ba02007-12-31 11:27:35 +00001112 // Initialize RSocketServ
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +00001113 if ((err=aSocketServer.Connect(32)) != KErrNone)
Benny Prijono70c5ba02007-12-31 11:27:35 +00001114 return PJ_STATUS_FROM_OS(err);
1115
1116 // Open up a connection
1117 if ((err=aConn.Open(aSocketServer)) != KErrNone) {
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001118 aSocketServer.Close();
1119 return PJ_STATUS_FROM_OS(err);
Benny Prijono70c5ba02007-12-31 11:27:35 +00001120 }
1121
1122 if ((err=aConn.Start()) != KErrNone) {
1123 aSocketServer.Close();
1124 return PJ_STATUS_FROM_OS(err);
1125 }
1126
1127 // Set Symbian OS parameters in pjlib.
1128 // This must be done before pj_init() is called.
1129 pj_bzero(&sym_params, sizeof(sym_params));
1130 sym_params.rsocketserv = &aSocketServer;
1131 sym_params.rconnection = &aConn;
1132 pj_symbianos_set_params(&sym_params);
1133
Benny Prijonoc71ad432007-05-04 07:25:19 +00001134 // Initialize pjsua
1135 status = app_startup();
Benny Prijono70c5ba02007-12-31 11:27:35 +00001136 //status = test_addr();
1137 if (status != PJ_SUCCESS) {
1138 aConn.Close();
1139 aSocketServer.Close();
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001140 return status;
Benny Prijono70c5ba02007-12-31 11:27:35 +00001141 }
Benny Prijono897f9f82007-05-03 19:56:21 +00001142
Nanang Izzuddin90b83202009-03-02 15:48:45 +00001143
Benny Prijonoc71ad432007-05-04 07:25:19 +00001144 // Run the UI
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001145 ConsoleUI *con = new ConsoleUI(console);
Benny Prijonoc71ad432007-05-04 07:25:19 +00001146
1147 con->Run();
Nanang Izzuddin798bf452009-02-12 12:35:27 +00001148 PrintMainMenu();
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001149
Nanang Izzuddin90b83202009-03-02 15:48:45 +00001150 // Init & start connection monitor
1151 CConnMon *connmon = CConnMon::NewL(aConn, aSocketServer);
1152 connmon->Start();
1153
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001154 CActiveScheduler::Start();
Benny Prijonoc71ad432007-05-04 07:25:19 +00001155
Nanang Izzuddin90b83202009-03-02 15:48:45 +00001156 delete connmon;
Benny Prijonoc71ad432007-05-04 07:25:19 +00001157 delete con;
Benny Prijono684c0ad2008-01-03 18:50:27 +00001158
1159 // Dump memory statistics
1160 PJ_LOG(3,(THIS_FILE, "Max heap usage: %u.%03uMB",
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001161 pjsua_var.cp.peak_used_size / 1000000,
1162 (pjsua_var.cp.peak_used_size % 1000000)/1000));
Benny Prijonoc71ad432007-05-04 07:25:19 +00001163
Benny Prijono684c0ad2008-01-03 18:50:27 +00001164 // check max stack usage
1165#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
1166 pj_thread_t* this_thread = pj_thread_this();
1167 if (!this_thread)
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001168 return status;
Benny Prijono684c0ad2008-01-03 18:50:27 +00001169
1170 const char* max_stack_file;
1171 int max_stack_line;
1172 status = pj_thread_get_stack_info(this_thread, &max_stack_file, &max_stack_line);
1173
1174 PJ_LOG(3,(THIS_FILE, "Max stack usage: %u at %s:%d",
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001175 pj_thread_get_stack_max_usage(this_thread),
1176 max_stack_file, max_stack_line));
Benny Prijono684c0ad2008-01-03 18:50:27 +00001177#endif
1178
Benny Prijonoc71ad432007-05-04 07:25:19 +00001179 // Shutdown pjsua
1180 pjsua_destroy();
1181
Benny Prijono70c5ba02007-12-31 11:27:35 +00001182 // Close connection and socket server
1183 aConn.Close();
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001184 aSocketServer.Close();
Nanang Izzuddina940b362009-02-23 13:53:30 +00001185
Benny Prijono797e3382007-12-01 09:10:07 +00001186 return status;
Benny Prijonoba5926a2007-05-02 11:29:37 +00001187}
1188