blob: 620e75a74b695a45dbde8fe433a090af0e269886 [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 */
276static pj_bool_t on_transport_state(pjsip_transport *tp, pj_uint32_t state,
277 const pjsip_transport_state_info *info)
278{
279 char host_port[128];
280
281 pj_ansi_snprintf(host_port, sizeof(host_port), "[%.*s:%d]",
282 (int)tp->remote_name.host.slen,
283 tp->remote_name.host.ptr,
284 tp->remote_name.port);
285
286 if (state & PJSIP_TP_STATE_CONNECTED) {
287 PJ_LOG(3,(THIS_FILE, "SIP transport %s is connected to %s",
288 tp->type_name, host_port));
289 }
290 else if (state & PJSIP_TP_STATE_ACCEPTED) {
291 PJ_LOG(3,(THIS_FILE, "SIP transport %s accepted %s",
292 tp->type_name, host_port));
293 }
294 else if (state & PJSIP_TP_STATE_DISCONNECTED) {
295 char buf[100];
296
297 snprintf(buf, sizeof(buf), "SIP transport %s is disconnected from %s",
298 tp->type_name, host_port);
299 pjsua_perror(THIS_FILE, buf, info->status);
300 }
301 else if (state & PJSIP_TP_STATE_REJECTED) {
302 char buf[100];
303
304 snprintf(buf, sizeof(buf), "SIP transport %s rejected %s",
305 tp->type_name, host_port);
306 pjsua_perror(THIS_FILE, buf, info->status);
307 }
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 &&
312 (state == PJSIP_TP_STATE_CONNECTED ||
313 (state & PJSIP_TP_STATE_TLS_VERIF_ERROR)))
314 {
315 pjsip_tls_state_info *tls_info = (pjsip_tls_state_info*)info->ext_info;
316 pj_ssl_sock_info *ssl_sock_info = (pj_ssl_sock_info*)
317 tls_info->ssl_sock_info;
318 char buf[2048];
319
320 /* Dump server TLS certificate */
321 pj_ssl_cert_info_dump(ssl_sock_info->remote_cert_info, " ",
322 buf, sizeof(buf));
323 PJ_LOG(4,(THIS_FILE, "TLS cert info of %s:\n%s", host_port, buf));
324 }
325
326#endif
327 return PJ_TRUE;
328}
329
Benny Prijonob2c96822007-05-03 13:31:21 +0000330
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000331//#include<e32debug.h>
332
Benny Prijonoba5926a2007-05-02 11:29:37 +0000333/* Logging callback */
Benny Prijono797e3382007-12-01 09:10:07 +0000334static void log_writer(int level, const char *buf, int len)
Benny Prijonoba5926a2007-05-02 11:29:37 +0000335{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000336 static wchar_t buf16[PJ_LOG_MAX_SIZE];
Benny Prijonoba5926a2007-05-02 11:29:37 +0000337
338 PJ_UNUSED_ARG(level);
339
340 pj_ansi_to_unicode(buf, len, buf16, PJ_ARRAY_SIZE(buf16));
341
342 TPtrC16 aBuf((const TUint16*)buf16, (TInt)len);
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000343 //RDebug::Print(aBuf);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000344 console->Write(aBuf);
Benny Prijono797e3382007-12-01 09:10:07 +0000345
Benny Prijonoba5926a2007-05-02 11:29:37 +0000346}
347
348/*
349 * app_startup()
350 *
351 * url may contain URL to call.
352 */
Benny Prijonob2c96822007-05-03 13:31:21 +0000353static pj_status_t app_startup()
Benny Prijonoba5926a2007-05-02 11:29:37 +0000354{
Benny Prijonoba5926a2007-05-02 11:29:37 +0000355 pj_status_t status;
356
357 /* Redirect log before pjsua_init() */
Benny Prijono70c5ba02007-12-31 11:27:35 +0000358 pj_log_set_log_func(&log_writer);
359
360 /* Set log level */
Nanang Izzuddinda37ea32009-03-06 16:24:43 +0000361 pj_log_set_level(CON_LOG_LEVEL);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000362
363 /* Create pjsua first! */
364 status = pjsua_create();
365 if (status != PJ_SUCCESS) {
366 pjsua_perror(THIS_FILE, "pjsua_create() error", status);
367 return status;
368 }
369
Benny Prijonoba5926a2007-05-02 11:29:37 +0000370 /* Init pjsua */
Benny Prijonoc71ad432007-05-04 07:25:19 +0000371 pjsua_config cfg;
372 pjsua_logging_config log_cfg;
373 pjsua_media_config med_cfg;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000374
Benny Prijonoc71ad432007-05-04 07:25:19 +0000375 pjsua_config_default(&cfg);
376 cfg.max_calls = 2;
377 cfg.thread_cnt = 0; // Disable threading on Symbian
Nanang Izzuddin6a6392f2008-06-02 18:30:15 +0000378 cfg.use_srtp = USE_SRTP;
379 cfg.srtp_secure_signaling = 0;
380
Benny Prijonoc71ad432007-05-04 07:25:19 +0000381 cfg.cb.on_incoming_call = &on_incoming_call;
382 cfg.cb.on_call_media_state = &on_call_media_state;
383 cfg.cb.on_call_state = &on_call_state;
384 cfg.cb.on_buddy_state = &on_buddy_state;
385 cfg.cb.on_pager = &on_pager;
386 cfg.cb.on_typing = &on_typing;
387 cfg.cb.on_call_transfer_status = &on_call_transfer_status;
388 cfg.cb.on_call_replaced = &on_call_replaced;
Benny Prijonoaecabfc2007-10-26 05:35:42 +0000389 cfg.cb.on_nat_detect = &on_nat_detect;
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000390 cfg.cb.on_transport_state = &on_transport_state;
Benny Prijonoaecabfc2007-10-26 05:35:42 +0000391
Benny Prijonoc71ad432007-05-04 07:25:19 +0000392 if (SIP_PROXY) {
393 cfg.outbound_proxy_cnt = 1;
394 cfg.outbound_proxy[0] = pj_str(SIP_PROXY);
395 }
396
397 if (NAMESERVER) {
398 cfg.nameserver_count = 1;
399 cfg.nameserver[0] = pj_str(NAMESERVER);
400 }
401
402 if (NAMESERVER && STUN_DOMAIN) {
403 cfg.stun_domain = pj_str(STUN_DOMAIN);
404 } else if (STUN_SERVER) {
405 cfg.stun_host = pj_str(STUN_SERVER);
406 }
407
408
409 pjsua_logging_config_default(&log_cfg);
Nanang Izzuddinda37ea32009-03-06 16:24:43 +0000410 log_cfg.level = FILE_LOG_LEVEL;
411 log_cfg.console_level = CON_LOG_LEVEL;
Benny Prijonoc71ad432007-05-04 07:25:19 +0000412 log_cfg.cb = &log_writer;
Nanang Izzuddin83457d52009-02-16 16:29:05 +0000413 log_cfg.log_filename = pj_str("C:\\data\\symbian_ua.log");
Benny Prijonoba5926a2007-05-02 11:29:37 +0000414
Benny Prijonoc71ad432007-05-04 07:25:19 +0000415 pjsua_media_config_default(&med_cfg);
416 med_cfg.thread_cnt = 0; // Disable threading on Symbian
417 med_cfg.has_ioqueue = PJ_FALSE;
418 med_cfg.clock_rate = 8000;
Benny Prijono5df8bb62007-12-28 18:55:02 +0000419 med_cfg.audio_frame_ptime = 40;
Benny Prijonoc71ad432007-05-04 07:25:19 +0000420 med_cfg.ec_tail_len = 0;
421 med_cfg.enable_ice = USE_ICE;
Nanang Izzuddin81db8c72009-02-05 10:59:14 +0000422 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 +0000423 //med_cfg.no_vad = PJ_TRUE;
Benny Prijonoc71ad432007-05-04 07:25:19 +0000424
425 status = pjsua_init(&cfg, &log_cfg, &med_cfg);
426 if (status != PJ_SUCCESS) {
427 pjsua_perror(THIS_FILE, "pjsua_init() error", status);
428 pjsua_destroy();
429 return status;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000430 }
Nanang Izzuddin829ac022008-05-27 00:24:26 +0000431
432 /* Adjust Speex priority and enable only the narrowband */
433 {
434 pj_str_t codec_id = pj_str("speex/8000");
435 pjmedia_codec_mgr_set_codec_priority(
436 pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
437 &codec_id, PJMEDIA_CODEC_PRIO_NORMAL+1);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000438
Nanang Izzuddin829ac022008-05-27 00:24:26 +0000439 codec_id = pj_str("speex/16000");
440 pjmedia_codec_mgr_set_codec_priority(
441 pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
442 &codec_id, PJMEDIA_CODEC_PRIO_DISABLED);
443
444 codec_id = pj_str("speex/32000");
445 pjmedia_codec_mgr_set_codec_priority(
446 pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
447 &codec_id, PJMEDIA_CODEC_PRIO_DISABLED);
448 }
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000449
Nanang Izzuddin829ac022008-05-27 00:24:26 +0000450
Benny Prijonoc71ad432007-05-04 07:25:19 +0000451 pjsua_transport_config tcfg;
452 pjsua_transport_id tid;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000453
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000454#if ENABLE_SIP_UDP
455 /* Add UDP transport. */
Benny Prijonoc71ad432007-05-04 07:25:19 +0000456 pjsua_transport_config_default(&tcfg);
457 tcfg.port = SIP_PORT;
Benny Prijonoa25bc9d2009-11-09 08:51:34 +0000458 if (SIP_QOS_DSCP) {
459 tcfg.qos_params.flags |= PJ_QOS_PARAM_HAS_DSCP;
460 tcfg.qos_params.dscp_val = SIP_QOS_DSCP;
461 }
Benny Prijonoc71ad432007-05-04 07:25:19 +0000462 status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &tcfg, &tid);
463 if (status != PJ_SUCCESS) {
Nanang Izzuddin940d3f62009-06-22 14:06:40 +0000464 pjsua_perror(THIS_FILE, "Error creating UDP transport", status);
Benny Prijonoc71ad432007-05-04 07:25:19 +0000465 pjsua_destroy();
466 return status;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000467 }
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000468#endif
469
Nanang Izzuddin940d3f62009-06-22 14:06:40 +0000470#if ENABLE_SIP_TCP
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000471 /* Add TCP transport */
Nanang Izzuddin940d3f62009-06-22 14:06:40 +0000472 pjsua_transport_config_default(&tcfg);
473 tcfg.port = SIP_PORT;
Benny Prijonoa25bc9d2009-11-09 08:51:34 +0000474 if (SIP_QOS_DSCP) {
475 tcfg.qos_params.flags |= PJ_QOS_PARAM_HAS_DSCP;
476 tcfg.qos_params.dscp_val = SIP_QOS_DSCP;
477 }
Nanang Izzuddin940d3f62009-06-22 14:06:40 +0000478 status = pjsua_transport_create(PJSIP_TRANSPORT_TCP, &tcfg, &tid);
479 if (status != PJ_SUCCESS) {
480 pjsua_perror(THIS_FILE, "Error creating TCP transport", status);
481 pjsua_destroy();
482 return status;
483 }
484#endif
485
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000486#if ENABLE_SIP_TLS
487 /* Add TLS transport */
488 pjsua_transport_config_default(&tcfg);
489 tcfg.port = SIP_PORT + 1;
Benny Prijonoa25bc9d2009-11-09 08:51:34 +0000490 if (SIP_QOS_DSCP) {
491 tcfg.qos_params.flags |= PJ_QOS_PARAM_HAS_DSCP;
492 tcfg.qos_params.dscp_val = SIP_QOS_DSCP;
493 tcfg.tls_setting.qos_params = tcfg.qos_params;
494 }
Benny Prijono28efe812009-11-09 09:52:23 +0000495 tcfg.tls_setting.server_name = pj_str(TLS_SRV_NAME);
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000496 status = pjsua_transport_create(PJSIP_TRANSPORT_TLS, &tcfg, &tid);
497 if (status != PJ_SUCCESS) {
498 pjsua_perror(THIS_FILE, "Error creating TLS transport", status);
499 pjsua_destroy();
500 return status;
501 }
502#endif
503
Benny Prijonoc71ad432007-05-04 07:25:19 +0000504 /* Add account for the transport */
505 pjsua_acc_add_local(tid, PJ_TRUE, &g_acc_id);
506
Benny Prijonoa25bc9d2009-11-09 08:51:34 +0000507 /* Create media transports */
508 pjsua_transport_config mtcfg;
509 pjsua_transport_config_default(&mtcfg);
510 mtcfg.port = 4000;
511 mtcfg.qos_type = RTP_QOS_TYPE;
512 status = pjsua_media_transports_create(&mtcfg);
513 if (status != PJ_SUCCESS) {
514 pjsua_perror(THIS_FILE, "Error creating media transports", status);
515 pjsua_destroy();
516 return status;
517 }
518
Benny Prijonoba5926a2007-05-02 11:29:37 +0000519 /* Initialization is done, now start pjsua */
520 status = pjsua_start();
521 if (status != PJ_SUCCESS) {
522 pjsua_perror(THIS_FILE, "Error starting pjsua", status);
523 pjsua_destroy();
524 return status;
525 }
526
527 /* Register to SIP server by creating SIP account. */
Benny Prijono72a81aa2007-05-02 23:06:11 +0000528 if (HAS_SIP_ACCOUNT) {
Benny Prijonoba5926a2007-05-02 11:29:37 +0000529 pjsua_acc_config cfg;
530
531 pjsua_acc_config_default(&cfg);
532 cfg.id = pj_str("sip:" SIP_USER "@" SIP_DOMAIN);
533 cfg.reg_uri = pj_str("sip:" SIP_DOMAIN);
534 cfg.cred_count = 1;
Benny Prijono0e2c6462008-02-14 13:39:24 +0000535 cfg.cred_info[0].realm = pj_str("*");
Benny Prijonoba5926a2007-05-02 11:29:37 +0000536 cfg.cred_info[0].scheme = pj_str("digest");
537 cfg.cred_info[0].username = pj_str(SIP_USER);
538 cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
539 cfg.cred_info[0].data = pj_str(SIP_PASSWD);
540
Benny Prijonob2c96822007-05-03 13:31:21 +0000541 status = pjsua_acc_add(&cfg, PJ_TRUE, &g_acc_id);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000542 if (status != PJ_SUCCESS) {
543 pjsua_perror(THIS_FILE, "Error adding account", status);
544 pjsua_destroy();
545 return status;
546 }
547 }
548
Benny Prijonob2c96822007-05-03 13:31:21 +0000549 if (SIP_DST_URI) {
550 pjsua_buddy_config bcfg;
551
552 pjsua_buddy_config_default(&bcfg);
553 bcfg.uri = pj_str(SIP_DST_URI);
554 bcfg.subscribe = PJ_FALSE;
555
556 pjsua_buddy_add(&bcfg, &g_buddy_id);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000557 }
Benny Prijonoba5926a2007-05-02 11:29:37 +0000558 return PJ_SUCCESS;
559}
560
561
562////////////////////////////////////////////////////////////////////////////
Benny Prijonoc71ad432007-05-04 07:25:19 +0000563/*
564 * The interractive console UI
565 */
Benny Prijonoba5926a2007-05-02 11:29:37 +0000566#include <e32base.h>
567
568class ConsoleUI : public CActive
569{
570public:
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000571 ConsoleUI(CConsoleBase *con);
Nanang Izzuddin90b83202009-03-02 15:48:45 +0000572 ~ConsoleUI();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000573
Benny Prijonoc71ad432007-05-04 07:25:19 +0000574 // Run console UI
575 void Run();
576
577 // Stop
578 void Stop();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000579
580protected:
Benny Prijonoc71ad432007-05-04 07:25:19 +0000581 // Cancel asynchronous read.
582 void DoCancel();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000583
Benny Prijonoc71ad432007-05-04 07:25:19 +0000584 // Implementation: called when read has completed.
585 void RunL();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000586
587private:
Benny Prijonoc71ad432007-05-04 07:25:19 +0000588 CConsoleBase *con_;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000589};
590
591
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000592ConsoleUI::ConsoleUI(CConsoleBase *con)
593: CActive(EPriorityStandard), con_(con)
Benny Prijonoba5926a2007-05-02 11:29:37 +0000594{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000595 CActiveScheduler::Add(this);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000596}
597
Nanang Izzuddin90b83202009-03-02 15:48:45 +0000598ConsoleUI::~ConsoleUI()
599{
600 Stop();
601}
602
Benny Prijonoba5926a2007-05-02 11:29:37 +0000603// Run console UI
604void ConsoleUI::Run()
605{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000606 con_->Read(iStatus);
607 SetActive();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000608}
609
610// Stop console UI
611void ConsoleUI::Stop()
612{
Nanang Izzuddin90b83202009-03-02 15:48:45 +0000613 Cancel();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000614}
615
616// Cancel asynchronous read.
617void ConsoleUI::DoCancel()
618{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000619 con_->ReadCancel();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000620}
621
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000622static void PrintMainMenu()
Benny Prijono72a81aa2007-05-02 23:06:11 +0000623{
Nanang Izzuddinda37ea32009-03-06 16:24:43 +0000624 const char *menu =
625 "\n\n"
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000626 "Main Menu:\n"
627 " d Enable/disable codecs\n"
Benny Prijono70c5ba02007-12-31 11:27:35 +0000628 " m Call " SIP_DST_URI "\n"
629 " a Answer call\n"
630 " g Hangup all calls\n"
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000631 " t Toggle audio route\n"
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000632#if !defined(PJMEDIA_CONF_USE_SWITCH_BOARD) || PJMEDIA_CONF_USE_SWITCH_BOARD==0
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000633 " j Toggle loopback audio\n"
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000634#endif
Nanang Izzuddin08694ea2009-03-10 15:03:04 +0000635 "up/dn Increase/decrease output volume\n"
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000636 " s Subscribe " SIP_DST_URI "\n"
Benny Prijonoc71ad432007-05-04 07:25:19 +0000637 " S Unsubscribe presence\n"
638 " o Set account online\n"
639 " O Set account offline\n"
Nanang Izzuddinda37ea32009-03-06 16:24:43 +0000640 " w Quit\n";
641
642 PJ_LOG(3, (THIS_FILE, menu));
Benny Prijono72a81aa2007-05-02 23:06:11 +0000643}
644
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000645static void PrintCodecMenu()
646{
Nanang Izzuddinda37ea32009-03-06 16:24:43 +0000647 const char *menu =
648 "\n\n"
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000649 "Codec Menu:\n"
650 " a Enable all codecs\n"
Nanang Izzuddina3775972009-03-03 18:25:55 +0000651#if PJMEDIA_HAS_PASSTHROUGH_CODEC_AMR
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000652 " d Enable only AMR\n"
Nanang Izzuddina3775972009-03-03 18:25:55 +0000653#endif
654#if PJMEDIA_HAS_PASSTHROUGH_CODEC_G729
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000655 " g Enable only G.729\n"
Nanang Izzuddina3775972009-03-03 18:25:55 +0000656#endif
657#if PJMEDIA_HAS_PASSTHROUGH_CODEC_ILBC
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000658 " j Enable only iLBC\n"
659#endif
660 " m Enable only Speex\n"
661 " p Enable only GSM\n"
662 " t Enable only PCMU\n"
Nanang Izzuddinda37ea32009-03-06 16:24:43 +0000663 " w Enable only PCMA\n";
664
665 PJ_LOG(3, (THIS_FILE, menu));
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000666}
667
668static void HandleMainMenu(TKeyCode kc) {
669 switch (kc) {
670
Nanang Izzuddin08694ea2009-03-10 15:03:04 +0000671 case EKeyUpArrow:
672 case EKeyDownArrow:
673 {
674 unsigned vol;
675 pj_status_t status;
676
677 status = pjsua_snd_get_setting(
678 PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING, &vol);
679 if (status == PJ_SUCCESS) {
680 if (kc == EKeyUpArrow)
681 vol = PJ_MIN(100, vol+10);
682 else
683 vol = (vol>=10 ? vol-10 : 0);
684 status = pjsua_snd_set_setting(
685 PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING,
686 &vol, PJ_TRUE);
687 }
688
689 if (status == PJ_SUCCESS) {
690 PJ_LOG(3,(THIS_FILE, "Output volume set to %d", vol));
691 } else {
692 pjsua_perror(THIS_FILE, "Error setting volume", status);
693 }
694 }
695 break;
696
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000697 case 't':
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000698 {
Nanang Izzuddinfcb92d02009-03-10 13:32:09 +0000699 pjmedia_aud_dev_route route;
700 pj_status_t status;
701
702 status = pjsua_snd_get_setting(PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE,
703 &route);
704
705 if (status == PJ_SUCCESS) {
706 if (route == PJMEDIA_AUD_DEV_ROUTE_LOUDSPEAKER)
707 route = PJMEDIA_AUD_DEV_ROUTE_EARPIECE;
708 else
709 route = PJMEDIA_AUD_DEV_ROUTE_LOUDSPEAKER;
Nanang Izzuddin452b66b2009-02-18 15:23:47 +0000710
Nanang Izzuddinfcb92d02009-03-10 13:32:09 +0000711 status = pjsua_snd_set_setting(
712 PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE,
713 &route, PJ_TRUE);
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000714 }
Nanang Izzuddinfcb92d02009-03-10 13:32:09 +0000715
716 if (status != PJ_SUCCESS)
717 pjsua_perror(THIS_FILE, "Error switch audio route", status);
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000718 }
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000719 break;
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000720
721 case 'j':
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000722 {
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000723 static pj_bool_t loopback_active = PJ_FALSE;
724 if (!loopback_active)
725 pjsua_conf_connect(0, 0);
726 else
727 pjsua_conf_disconnect(0, 0);
728 loopback_active = !loopback_active;
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000729 }
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000730 break;
731
732 case 'm':
733 if (g_call_id != PJSUA_INVALID_ID) {
734 PJ_LOG(3,(THIS_FILE, "Another call is active"));
735 break;
736 }
737
738 if (pjsua_verify_sip_url(SIP_DST_URI) == PJ_SUCCESS) {
739 pj_str_t dst = pj_str(SIP_DST_URI);
740 pjsua_call_make_call(g_acc_id, &dst, 0, NULL,
741 NULL, &g_call_id);
742 } else {
743 PJ_LOG(3,(THIS_FILE, "Invalid SIP URI"));
744 }
745 break;
746 case 'a':
747 if (g_call_id != PJSUA_INVALID_ID)
748 pjsua_call_answer(g_call_id, 200, NULL, NULL);
749 break;
750 case 'g':
751 pjsua_call_hangup_all();
752 break;
753 case 's':
754 case 'S':
755 if (g_buddy_id != PJSUA_INVALID_ID)
756 pjsua_buddy_subscribe_pres(g_buddy_id, kc=='s');
757 break;
758 case 'o':
759 case 'O':
760 pjsua_acc_set_online_status(g_acc_id, kc=='o');
761 break;
762
763 default:
764 PJ_LOG(3,(THIS_FILE, "Keycode '%c' (%d) is pressed", kc, kc));
765 break;
766 }
767
768 PrintMainMenu();
769}
770
771static void HandleCodecMenu(TKeyCode kc) {
772 const pj_str_t ID_ALL = {"*", 1};
773 pj_str_t codec = {NULL, 0};
774
775 if (kc == 'a') {
776 pjsua_codec_set_priority(&ID_ALL, PJMEDIA_CODEC_PRIO_NORMAL);
777 PJ_LOG(3,(THIS_FILE, "All codecs activated"));
778 } else {
779 switch (kc) {
780 case 'd':
781 codec = pj_str("AMR");
782 break;
783 case 'g':
784 codec = pj_str("G729");
785 break;
786 case 'j':
787 codec = pj_str("ILBC");
788 break;
789 case 'm':
790 codec = pj_str("SPEEX/8000");
791 break;
792 case 'p':
793 codec = pj_str("GSM");
794 break;
795 case 't':
796 codec = pj_str("PCMU");
797 break;
798 case 'w':
799 codec = pj_str("PCMA");
800 break;
801 default:
802 PJ_LOG(3,(THIS_FILE, "Keycode '%c' (%d) is pressed", kc, kc));
803 break;
804 }
805
806 if (codec.slen) {
807 pj_status_t status;
808
809 pjsua_codec_set_priority(&ID_ALL, PJMEDIA_CODEC_PRIO_DISABLED);
810
811 status = pjsua_codec_set_priority(&codec,
812 PJMEDIA_CODEC_PRIO_NORMAL);
813 if (status == PJ_SUCCESS)
814 PJ_LOG(3,(THIS_FILE, "%s activated", codec.ptr));
815 else
816 PJ_LOG(3,(THIS_FILE, "Failed activating %s, err=%d",
817 codec.ptr, status));
818 }
819 }
Benny Prijonoba5926a2007-05-02 11:29:37 +0000820}
821
822// Implementation: called when read has completed.
823void ConsoleUI::RunL()
824{
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000825 enum {
826 MENU_TYPE_MAIN = 0,
827 MENU_TYPE_CODEC = 1
828 };
829 static int menu_type = MENU_TYPE_MAIN;
Benny Prijonoc71ad432007-05-04 07:25:19 +0000830 TKeyCode kc = con_->KeyCode();
831 pj_bool_t reschedule = PJ_TRUE;
832
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000833 if (menu_type == MENU_TYPE_MAIN) {
834 if (kc == 'w') {
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000835 CActiveScheduler::Stop();
Benny Prijonoc71ad432007-05-04 07:25:19 +0000836 reschedule = PJ_FALSE;
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000837 } else if (kc == 'd') {
838 menu_type = MENU_TYPE_CODEC;
839 PrintCodecMenu();
840 } else {
841 HandleMainMenu(kc);
842 }
843 } else {
844 HandleCodecMenu(kc);
845
846 menu_type = MENU_TYPE_MAIN;
847 PrintMainMenu();
Benny Prijonoc71ad432007-05-04 07:25:19 +0000848 }
Benny Prijonoc71ad432007-05-04 07:25:19 +0000849
850 if (reschedule)
851 Run();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000852}
853
Benny Prijono70c5ba02007-12-31 11:27:35 +0000854#if 0
855// IP networking related testing
856static pj_status_t test_addr(void)
857{
858 int af;
859 unsigned i, count;
860 pj_addrinfo ai[8];
861 pj_sockaddr ifs[8];
862 const pj_str_t *hostname;
863 pj_hostent he;
864 pj_status_t status;
865
866 pj_log_set_log_func(&log_writer);
867
868 status = pj_init();
869 if (status != PJ_SUCCESS) {
870 pjsua_perror(THIS_FILE, "pj_init() error", status);
871 return status;
872 }
873
874 af = pj_AF_INET();
875
Benny Prijono684c0ad2008-01-03 18:50:27 +0000876#if 0
877 pj_in_addr in_addr;
878 pj_str_t aa = pj_str("1.1.1.1");
879 in_addr = pj_inet_addr(&aa);
880 char *the_addr = pj_inet_ntoa(in_addr);
881 PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
882
883 aa = pj_str("192.168.0.15");
884 in_addr = pj_inet_addr(&aa);
885 the_addr = pj_inet_ntoa(in_addr);
886 PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
887
888 aa = pj_str("2.2.2.2");
889 in_addr = pj_inet_addr(&aa);
890 the_addr = pj_inet_ntoa(in_addr);
891 PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
892
893 return -1;
894#endif
895
Benny Prijono70c5ba02007-12-31 11:27:35 +0000896 // Hostname
897 hostname = pj_gethostname();
898 if (hostname == NULL) {
899 status = PJ_ERESOLVE;
900 pjsua_perror(THIS_FILE, "pj_gethostname() error", status);
901 goto on_return;
902 }
903
904 PJ_LOG(3,(THIS_FILE, "Hostname: %.*s", hostname->slen, hostname->ptr));
905
906 // Gethostbyname
907 status = pj_gethostbyname(hostname, &he);
908 if (status != PJ_SUCCESS) {
909 pjsua_perror(THIS_FILE, "pj_gethostbyname() error", status);
910 } else {
911 PJ_LOG(3,(THIS_FILE, "gethostbyname: %s",
912 pj_inet_ntoa(*(pj_in_addr*)he.h_addr)));
913 }
914
915 // Getaddrinfo
916 count = PJ_ARRAY_SIZE(ai);
917 status = pj_getaddrinfo(af, hostname, &count, ai);
918 if (status != PJ_SUCCESS) {
919 pjsua_perror(THIS_FILE, "pj_getaddrinfo() error", status);
920 } else {
921 for (i=0; i<count; ++i) {
922 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
923 PJ_LOG(3,(THIS_FILE, "Addrinfo: %s",
924 pj_sockaddr_print(&ai[i].ai_addr, ipaddr, sizeof(ipaddr), 2)));
925 }
926 }
927
928 // Enum interface
929 count = PJ_ARRAY_SIZE(ifs);
930 status = pj_enum_ip_interface(af, &count, ifs);
931 if (status != PJ_SUCCESS) {
932 pjsua_perror(THIS_FILE, "pj_enum_ip_interface() error", status);
933 } else {
934 for (i=0; i<count; ++i) {
935 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
936 PJ_LOG(3,(THIS_FILE, "Interface: %s",
937 pj_sockaddr_print(&ifs[i], ipaddr, sizeof(ipaddr), 2)));
938 }
939 }
940
941 // Get default iinterface
942 status = pj_getdefaultipinterface(af, &ifs[0]);
943 if (status != PJ_SUCCESS) {
944 pjsua_perror(THIS_FILE, "pj_getdefaultipinterface() error", status);
945 } else {
946 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
947 PJ_LOG(3,(THIS_FILE, "Default IP: %s",
948 pj_sockaddr_print(&ifs[0], ipaddr, sizeof(ipaddr), 2)));
949 }
950
951 // Get default IP address
952 status = pj_gethostip(af, &ifs[0]);
953 if (status != PJ_SUCCESS) {
954 pjsua_perror(THIS_FILE, "pj_gethostip() error", status);
955 } else {
956 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
957 PJ_LOG(3,(THIS_FILE, "Host IP: %s",
958 pj_sockaddr_print(&ifs[0], ipaddr, sizeof(ipaddr), 2)));
959 }
960
961 status = -1;
962
963on_return:
964 pj_shutdown();
965 return status;
966}
967#endif
968
969
Benny Prijono6b3ccdf2008-01-14 11:54:21 +0000970#include <es_sock.h>
Benny Prijono897f9f82007-05-03 19:56:21 +0000971
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000972#if 0
973// Force network connection to use the first IAP,
974// this is useful for debugging on emulator without GUI.
975// Include commdb.lib & apengine.lib in symbian_ua.mmp file
976// if this is enabled.
977
978#include <apdatahandler.h>
979
980inline void ForceUseFirstIAP()
981{
982 TUint32 rank = 1;
983 TUint32 bearers;
984 TUint32 prompt;
985 TUint32 iap;
986
987 CCommsDatabase* commDb = CCommsDatabase::NewL(EDatabaseTypeIAP);
988 CleanupStack::PushL(commDb);
989
990 CApDataHandler* apDataHandler = CApDataHandler::NewLC(*commDb);
991
992 TCommDbConnectionDirection direction = ECommDbConnectionDirectionOutgoing;
993 apDataHandler->GetPreferredIfDbIapTypeL(rank, direction, bearers, prompt, iap);
994 prompt = ECommDbDialogPrefDoNotPrompt;
995 apDataHandler->SetPreferredIfDbIapTypeL(rank, direction, bearers, (TCommDbDialogPref)prompt, iap, ETrue);
996 CleanupStack::PopAndDestroy(2); // apDataHandler, commDb
997}
998
999static void SelectIAP()
1000{
1001 ForceUseFirstIAP();
1002}
1003
1004#else
1005
1006static void SelectIAP()
1007{
1008}
1009
1010#endif
1011
1012
Nanang Izzuddin90b83202009-03-02 15:48:45 +00001013// Class CConnMon to monitor network connection (RConnection). Whenever
1014// the connection is down, it will notify PJLIB and restart PJSUA-LIB.
1015class CConnMon : public CActive {
1016public:
1017 static CConnMon* NewL(RConnection &conn, RSocketServ &sserver) {
1018 CConnMon *self = new (ELeave) CConnMon(conn, sserver);
1019 CleanupStack::PushL(self);
1020 self->ConstructL();
1021 CleanupStack::Pop(self);
1022 return self;
1023 }
1024
1025 void Start() {
1026 conn_.ProgressNotification(nif_progress_, iStatus);
1027 SetActive();
1028 }
1029
1030 void Stop() {
1031 Cancel();
1032 }
1033
1034 ~CConnMon() { Stop(); }
1035
1036private:
1037 CConnMon(RConnection &conn, RSocketServ &sserver) :
1038 CActive(EPriorityHigh),
1039 conn_(conn),
1040 sserver_(sserver)
1041 {
1042 CActiveScheduler::Add(this);
1043 }
1044
1045 void ConstructL() {}
1046
1047 void DoCancel() {
1048 conn_.CancelProgressNotification();
1049 }
1050
1051 void RunL() {
1052 int stage = nif_progress_().iStage;
1053
1054 if (stage == KLinkLayerClosed) {
1055 pj_status_t status;
1056 TInt err;
1057
1058 // Tell pjlib that connection is down.
1059 pj_symbianos_set_connection_status(PJ_FALSE);
1060
1061 PJ_LOG(3, (THIS_FILE, "RConnection closed, restarting PJSUA.."));
1062
1063 // Destroy pjsua
1064 pjsua_destroy();
1065 PJ_LOG(3, (THIS_FILE, "PJSUA destroyed."));
1066
1067 // Reopen the connection
1068 err = conn_.Open(sserver_);
1069 if (err == KErrNone)
1070 err = conn_.Start();
1071 if (err != KErrNone) {
1072 CActiveScheduler::Stop();
1073 return;
1074 }
1075
1076 // Reinit Symbian OS param before pj_init()
1077 pj_symbianos_params sym_params;
1078 pj_bzero(&sym_params, sizeof(sym_params));
1079 sym_params.rsocketserv = &sserver_;
1080 sym_params.rconnection = &conn_;
1081 pj_symbianos_set_params(&sym_params);
1082
1083 // Reinit pjsua
1084 status = app_startup();
1085 if (status != PJ_SUCCESS) {
1086 pjsua_perror(THIS_FILE, "app_startup() error", status);
1087 CActiveScheduler::Stop();
1088 return;
1089 }
1090
1091 PJ_LOG(3, (THIS_FILE, "PJSUA restarted."));
Benny Prijono9920dc32009-03-12 18:11:37 +00001092 PrintMainMenu();
Nanang Izzuddin90b83202009-03-02 15:48:45 +00001093 }
1094
1095 Start();
1096 }
1097
1098 RConnection& conn_;
1099 RSocketServ& sserver_;
1100 TNifProgressBuf nif_progress_;
1101};
1102
Benny Prijonoba5926a2007-05-02 11:29:37 +00001103////////////////////////////////////////////////////////////////////////////
1104int ua_main()
1105{
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001106 RSocketServ aSocketServer;
1107 RConnection aConn;
1108 TInt err;
1109 pj_symbianos_params sym_params;
Benny Prijonoc71ad432007-05-04 07:25:19 +00001110 pj_status_t status;
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001111
1112 SelectIAP();
Benny Prijonoc71ad432007-05-04 07:25:19 +00001113
Benny Prijono70c5ba02007-12-31 11:27:35 +00001114 // Initialize RSocketServ
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +00001115 if ((err=aSocketServer.Connect(32)) != KErrNone)
Benny Prijono70c5ba02007-12-31 11:27:35 +00001116 return PJ_STATUS_FROM_OS(err);
1117
1118 // Open up a connection
1119 if ((err=aConn.Open(aSocketServer)) != KErrNone) {
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001120 aSocketServer.Close();
1121 return PJ_STATUS_FROM_OS(err);
Benny Prijono70c5ba02007-12-31 11:27:35 +00001122 }
1123
1124 if ((err=aConn.Start()) != KErrNone) {
1125 aSocketServer.Close();
1126 return PJ_STATUS_FROM_OS(err);
1127 }
1128
1129 // Set Symbian OS parameters in pjlib.
1130 // This must be done before pj_init() is called.
1131 pj_bzero(&sym_params, sizeof(sym_params));
1132 sym_params.rsocketserv = &aSocketServer;
1133 sym_params.rconnection = &aConn;
1134 pj_symbianos_set_params(&sym_params);
1135
Benny Prijonoc71ad432007-05-04 07:25:19 +00001136 // Initialize pjsua
1137 status = app_startup();
Benny Prijono70c5ba02007-12-31 11:27:35 +00001138 //status = test_addr();
1139 if (status != PJ_SUCCESS) {
1140 aConn.Close();
1141 aSocketServer.Close();
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001142 return status;
Benny Prijono70c5ba02007-12-31 11:27:35 +00001143 }
Benny Prijono897f9f82007-05-03 19:56:21 +00001144
Nanang Izzuddin90b83202009-03-02 15:48:45 +00001145
Benny Prijonoc71ad432007-05-04 07:25:19 +00001146 // Run the UI
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001147 ConsoleUI *con = new ConsoleUI(console);
Benny Prijonoc71ad432007-05-04 07:25:19 +00001148
1149 con->Run();
Nanang Izzuddin798bf452009-02-12 12:35:27 +00001150 PrintMainMenu();
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001151
Nanang Izzuddin90b83202009-03-02 15:48:45 +00001152 // Init & start connection monitor
1153 CConnMon *connmon = CConnMon::NewL(aConn, aSocketServer);
1154 connmon->Start();
1155
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001156 CActiveScheduler::Start();
Benny Prijonoc71ad432007-05-04 07:25:19 +00001157
Nanang Izzuddin90b83202009-03-02 15:48:45 +00001158 delete connmon;
Benny Prijonoc71ad432007-05-04 07:25:19 +00001159 delete con;
Benny Prijono684c0ad2008-01-03 18:50:27 +00001160
1161 // Dump memory statistics
1162 PJ_LOG(3,(THIS_FILE, "Max heap usage: %u.%03uMB",
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001163 pjsua_var.cp.peak_used_size / 1000000,
1164 (pjsua_var.cp.peak_used_size % 1000000)/1000));
Benny Prijonoc71ad432007-05-04 07:25:19 +00001165
Benny Prijono684c0ad2008-01-03 18:50:27 +00001166 // check max stack usage
1167#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
1168 pj_thread_t* this_thread = pj_thread_this();
1169 if (!this_thread)
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001170 return status;
Benny Prijono684c0ad2008-01-03 18:50:27 +00001171
1172 const char* max_stack_file;
1173 int max_stack_line;
1174 status = pj_thread_get_stack_info(this_thread, &max_stack_file, &max_stack_line);
1175
1176 PJ_LOG(3,(THIS_FILE, "Max stack usage: %u at %s:%d",
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001177 pj_thread_get_stack_max_usage(this_thread),
1178 max_stack_file, max_stack_line));
Benny Prijono684c0ad2008-01-03 18:50:27 +00001179#endif
1180
Benny Prijonoc71ad432007-05-04 07:25:19 +00001181 // Shutdown pjsua
1182 pjsua_destroy();
1183
Benny Prijono70c5ba02007-12-31 11:27:35 +00001184 // Close connection and socket server
1185 aConn.Close();
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001186 aSocketServer.Close();
Nanang Izzuddina940b362009-02-23 13:53:30 +00001187
Benny Prijono797e3382007-12-01 09:10:07 +00001188 return status;
Benny Prijonoba5926a2007-05-02 11:29:37 +00001189}
1190