blob: 64e49aee78629621744e9de11d589c8fe67c91ff [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
273
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000274//#include<e32debug.h>
275
Benny Prijonoba5926a2007-05-02 11:29:37 +0000276/* Logging callback */
Benny Prijono797e3382007-12-01 09:10:07 +0000277static void log_writer(int level, const char *buf, int len)
Benny Prijonoba5926a2007-05-02 11:29:37 +0000278{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000279 static wchar_t buf16[PJ_LOG_MAX_SIZE];
Benny Prijonoba5926a2007-05-02 11:29:37 +0000280
281 PJ_UNUSED_ARG(level);
282
283 pj_ansi_to_unicode(buf, len, buf16, PJ_ARRAY_SIZE(buf16));
284
285 TPtrC16 aBuf((const TUint16*)buf16, (TInt)len);
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000286 //RDebug::Print(aBuf);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000287 console->Write(aBuf);
Benny Prijono797e3382007-12-01 09:10:07 +0000288
Benny Prijonoba5926a2007-05-02 11:29:37 +0000289}
290
291/*
292 * app_startup()
293 *
294 * url may contain URL to call.
295 */
Benny Prijonob2c96822007-05-03 13:31:21 +0000296static pj_status_t app_startup()
Benny Prijonoba5926a2007-05-02 11:29:37 +0000297{
Benny Prijonoba5926a2007-05-02 11:29:37 +0000298 pj_status_t status;
299
300 /* Redirect log before pjsua_init() */
Benny Prijono70c5ba02007-12-31 11:27:35 +0000301 pj_log_set_log_func(&log_writer);
302
303 /* Set log level */
Nanang Izzuddinda37ea32009-03-06 16:24:43 +0000304 pj_log_set_level(CON_LOG_LEVEL);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000305
306 /* Create pjsua first! */
307 status = pjsua_create();
308 if (status != PJ_SUCCESS) {
309 pjsua_perror(THIS_FILE, "pjsua_create() error", status);
310 return status;
311 }
312
Benny Prijonoba5926a2007-05-02 11:29:37 +0000313 /* Init pjsua */
Benny Prijonoc71ad432007-05-04 07:25:19 +0000314 pjsua_config cfg;
315 pjsua_logging_config log_cfg;
316 pjsua_media_config med_cfg;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000317
Benny Prijonoc71ad432007-05-04 07:25:19 +0000318 pjsua_config_default(&cfg);
319 cfg.max_calls = 2;
320 cfg.thread_cnt = 0; // Disable threading on Symbian
Nanang Izzuddin6a6392f2008-06-02 18:30:15 +0000321 cfg.use_srtp = USE_SRTP;
322 cfg.srtp_secure_signaling = 0;
323
Benny Prijonoc71ad432007-05-04 07:25:19 +0000324 cfg.cb.on_incoming_call = &on_incoming_call;
325 cfg.cb.on_call_media_state = &on_call_media_state;
326 cfg.cb.on_call_state = &on_call_state;
327 cfg.cb.on_buddy_state = &on_buddy_state;
328 cfg.cb.on_pager = &on_pager;
329 cfg.cb.on_typing = &on_typing;
330 cfg.cb.on_call_transfer_status = &on_call_transfer_status;
331 cfg.cb.on_call_replaced = &on_call_replaced;
Benny Prijonoaecabfc2007-10-26 05:35:42 +0000332 cfg.cb.on_nat_detect = &on_nat_detect;
333
Benny Prijonoc71ad432007-05-04 07:25:19 +0000334 if (SIP_PROXY) {
335 cfg.outbound_proxy_cnt = 1;
336 cfg.outbound_proxy[0] = pj_str(SIP_PROXY);
337 }
338
339 if (NAMESERVER) {
340 cfg.nameserver_count = 1;
341 cfg.nameserver[0] = pj_str(NAMESERVER);
342 }
343
344 if (NAMESERVER && STUN_DOMAIN) {
345 cfg.stun_domain = pj_str(STUN_DOMAIN);
346 } else if (STUN_SERVER) {
347 cfg.stun_host = pj_str(STUN_SERVER);
348 }
349
350
351 pjsua_logging_config_default(&log_cfg);
Nanang Izzuddinda37ea32009-03-06 16:24:43 +0000352 log_cfg.level = FILE_LOG_LEVEL;
353 log_cfg.console_level = CON_LOG_LEVEL;
Benny Prijonoc71ad432007-05-04 07:25:19 +0000354 log_cfg.cb = &log_writer;
Nanang Izzuddin83457d52009-02-16 16:29:05 +0000355 log_cfg.log_filename = pj_str("C:\\data\\symbian_ua.log");
Benny Prijonoba5926a2007-05-02 11:29:37 +0000356
Benny Prijonoc71ad432007-05-04 07:25:19 +0000357 pjsua_media_config_default(&med_cfg);
358 med_cfg.thread_cnt = 0; // Disable threading on Symbian
359 med_cfg.has_ioqueue = PJ_FALSE;
360 med_cfg.clock_rate = 8000;
Benny Prijono5df8bb62007-12-28 18:55:02 +0000361 med_cfg.audio_frame_ptime = 40;
Benny Prijonoc71ad432007-05-04 07:25:19 +0000362 med_cfg.ec_tail_len = 0;
363 med_cfg.enable_ice = USE_ICE;
Nanang Izzuddin81db8c72009-02-05 10:59:14 +0000364 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 +0000365 //med_cfg.no_vad = PJ_TRUE;
Benny Prijonoc71ad432007-05-04 07:25:19 +0000366
367 status = pjsua_init(&cfg, &log_cfg, &med_cfg);
368 if (status != PJ_SUCCESS) {
369 pjsua_perror(THIS_FILE, "pjsua_init() error", status);
370 pjsua_destroy();
371 return status;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000372 }
Nanang Izzuddin829ac022008-05-27 00:24:26 +0000373
374 /* Adjust Speex priority and enable only the narrowband */
375 {
376 pj_str_t codec_id = pj_str("speex/8000");
377 pjmedia_codec_mgr_set_codec_priority(
378 pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
379 &codec_id, PJMEDIA_CODEC_PRIO_NORMAL+1);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000380
Nanang Izzuddin829ac022008-05-27 00:24:26 +0000381 codec_id = pj_str("speex/16000");
382 pjmedia_codec_mgr_set_codec_priority(
383 pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
384 &codec_id, PJMEDIA_CODEC_PRIO_DISABLED);
385
386 codec_id = pj_str("speex/32000");
387 pjmedia_codec_mgr_set_codec_priority(
388 pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
389 &codec_id, PJMEDIA_CODEC_PRIO_DISABLED);
390 }
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000391
Nanang Izzuddin829ac022008-05-27 00:24:26 +0000392
Benny Prijonoc71ad432007-05-04 07:25:19 +0000393 pjsua_transport_config tcfg;
394 pjsua_transport_id tid;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000395
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000396#if ENABLE_SIP_UDP
397 /* Add UDP transport. */
Benny Prijonoc71ad432007-05-04 07:25:19 +0000398 pjsua_transport_config_default(&tcfg);
399 tcfg.port = SIP_PORT;
Benny Prijonoa25bc9d2009-11-09 08:51:34 +0000400 if (SIP_QOS_DSCP) {
401 tcfg.qos_params.flags |= PJ_QOS_PARAM_HAS_DSCP;
402 tcfg.qos_params.dscp_val = SIP_QOS_DSCP;
403 }
Benny Prijonoc71ad432007-05-04 07:25:19 +0000404 status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &tcfg, &tid);
405 if (status != PJ_SUCCESS) {
Nanang Izzuddin940d3f62009-06-22 14:06:40 +0000406 pjsua_perror(THIS_FILE, "Error creating UDP transport", status);
Benny Prijonoc71ad432007-05-04 07:25:19 +0000407 pjsua_destroy();
408 return status;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000409 }
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000410#endif
411
Nanang Izzuddin940d3f62009-06-22 14:06:40 +0000412#if ENABLE_SIP_TCP
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000413 /* Add TCP transport */
Nanang Izzuddin940d3f62009-06-22 14:06:40 +0000414 pjsua_transport_config_default(&tcfg);
415 tcfg.port = SIP_PORT;
Benny Prijonoa25bc9d2009-11-09 08:51:34 +0000416 if (SIP_QOS_DSCP) {
417 tcfg.qos_params.flags |= PJ_QOS_PARAM_HAS_DSCP;
418 tcfg.qos_params.dscp_val = SIP_QOS_DSCP;
419 }
Nanang Izzuddin940d3f62009-06-22 14:06:40 +0000420 status = pjsua_transport_create(PJSIP_TRANSPORT_TCP, &tcfg, &tid);
421 if (status != PJ_SUCCESS) {
422 pjsua_perror(THIS_FILE, "Error creating TCP transport", status);
423 pjsua_destroy();
424 return status;
425 }
426#endif
427
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000428#if ENABLE_SIP_TLS
429 /* Add TLS transport */
430 pjsua_transport_config_default(&tcfg);
431 tcfg.port = SIP_PORT + 1;
Benny Prijonoa25bc9d2009-11-09 08:51:34 +0000432 if (SIP_QOS_DSCP) {
433 tcfg.qos_params.flags |= PJ_QOS_PARAM_HAS_DSCP;
434 tcfg.qos_params.dscp_val = SIP_QOS_DSCP;
435 tcfg.tls_setting.qos_params = tcfg.qos_params;
436 }
Benny Prijono28efe812009-11-09 09:52:23 +0000437 tcfg.tls_setting.server_name = pj_str(TLS_SRV_NAME);
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000438 status = pjsua_transport_create(PJSIP_TRANSPORT_TLS, &tcfg, &tid);
439 if (status != PJ_SUCCESS) {
440 pjsua_perror(THIS_FILE, "Error creating TLS transport", status);
441 pjsua_destroy();
442 return status;
443 }
444#endif
445
Benny Prijonoc71ad432007-05-04 07:25:19 +0000446 /* Add account for the transport */
447 pjsua_acc_add_local(tid, PJ_TRUE, &g_acc_id);
448
Benny Prijonoa25bc9d2009-11-09 08:51:34 +0000449 /* Create media transports */
450 pjsua_transport_config mtcfg;
451 pjsua_transport_config_default(&mtcfg);
452 mtcfg.port = 4000;
453 mtcfg.qos_type = RTP_QOS_TYPE;
454 status = pjsua_media_transports_create(&mtcfg);
455 if (status != PJ_SUCCESS) {
456 pjsua_perror(THIS_FILE, "Error creating media transports", status);
457 pjsua_destroy();
458 return status;
459 }
460
Benny Prijonoba5926a2007-05-02 11:29:37 +0000461 /* Initialization is done, now start pjsua */
462 status = pjsua_start();
463 if (status != PJ_SUCCESS) {
464 pjsua_perror(THIS_FILE, "Error starting pjsua", status);
465 pjsua_destroy();
466 return status;
467 }
468
469 /* Register to SIP server by creating SIP account. */
Benny Prijono72a81aa2007-05-02 23:06:11 +0000470 if (HAS_SIP_ACCOUNT) {
Benny Prijonoba5926a2007-05-02 11:29:37 +0000471 pjsua_acc_config cfg;
472
473 pjsua_acc_config_default(&cfg);
474 cfg.id = pj_str("sip:" SIP_USER "@" SIP_DOMAIN);
475 cfg.reg_uri = pj_str("sip:" SIP_DOMAIN);
476 cfg.cred_count = 1;
Benny Prijono0e2c6462008-02-14 13:39:24 +0000477 cfg.cred_info[0].realm = pj_str("*");
Benny Prijonoba5926a2007-05-02 11:29:37 +0000478 cfg.cred_info[0].scheme = pj_str("digest");
479 cfg.cred_info[0].username = pj_str(SIP_USER);
480 cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
481 cfg.cred_info[0].data = pj_str(SIP_PASSWD);
482
Benny Prijonob2c96822007-05-03 13:31:21 +0000483 status = pjsua_acc_add(&cfg, PJ_TRUE, &g_acc_id);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000484 if (status != PJ_SUCCESS) {
485 pjsua_perror(THIS_FILE, "Error adding account", status);
486 pjsua_destroy();
487 return status;
488 }
489 }
490
Benny Prijonob2c96822007-05-03 13:31:21 +0000491 if (SIP_DST_URI) {
492 pjsua_buddy_config bcfg;
493
494 pjsua_buddy_config_default(&bcfg);
495 bcfg.uri = pj_str(SIP_DST_URI);
496 bcfg.subscribe = PJ_FALSE;
497
498 pjsua_buddy_add(&bcfg, &g_buddy_id);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000499 }
Benny Prijonoba5926a2007-05-02 11:29:37 +0000500 return PJ_SUCCESS;
501}
502
503
504////////////////////////////////////////////////////////////////////////////
Benny Prijonoc71ad432007-05-04 07:25:19 +0000505/*
506 * The interractive console UI
507 */
Benny Prijonoba5926a2007-05-02 11:29:37 +0000508#include <e32base.h>
509
510class ConsoleUI : public CActive
511{
512public:
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000513 ConsoleUI(CConsoleBase *con);
Nanang Izzuddin90b83202009-03-02 15:48:45 +0000514 ~ConsoleUI();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000515
Benny Prijonoc71ad432007-05-04 07:25:19 +0000516 // Run console UI
517 void Run();
518
519 // Stop
520 void Stop();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000521
522protected:
Benny Prijonoc71ad432007-05-04 07:25:19 +0000523 // Cancel asynchronous read.
524 void DoCancel();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000525
Benny Prijonoc71ad432007-05-04 07:25:19 +0000526 // Implementation: called when read has completed.
527 void RunL();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000528
529private:
Benny Prijonoc71ad432007-05-04 07:25:19 +0000530 CConsoleBase *con_;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000531};
532
533
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000534ConsoleUI::ConsoleUI(CConsoleBase *con)
535: CActive(EPriorityStandard), con_(con)
Benny Prijonoba5926a2007-05-02 11:29:37 +0000536{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000537 CActiveScheduler::Add(this);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000538}
539
Nanang Izzuddin90b83202009-03-02 15:48:45 +0000540ConsoleUI::~ConsoleUI()
541{
542 Stop();
543}
544
Benny Prijonoba5926a2007-05-02 11:29:37 +0000545// Run console UI
546void ConsoleUI::Run()
547{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000548 con_->Read(iStatus);
549 SetActive();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000550}
551
552// Stop console UI
553void ConsoleUI::Stop()
554{
Nanang Izzuddin90b83202009-03-02 15:48:45 +0000555 Cancel();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000556}
557
558// Cancel asynchronous read.
559void ConsoleUI::DoCancel()
560{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000561 con_->ReadCancel();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000562}
563
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000564static void PrintMainMenu()
Benny Prijono72a81aa2007-05-02 23:06:11 +0000565{
Nanang Izzuddinda37ea32009-03-06 16:24:43 +0000566 const char *menu =
567 "\n\n"
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000568 "Main Menu:\n"
569 " d Enable/disable codecs\n"
Benny Prijono70c5ba02007-12-31 11:27:35 +0000570 " m Call " SIP_DST_URI "\n"
571 " a Answer call\n"
572 " g Hangup all calls\n"
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000573 " t Toggle audio route\n"
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000574#if !defined(PJMEDIA_CONF_USE_SWITCH_BOARD) || PJMEDIA_CONF_USE_SWITCH_BOARD==0
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000575 " j Toggle loopback audio\n"
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000576#endif
Nanang Izzuddin08694ea2009-03-10 15:03:04 +0000577 "up/dn Increase/decrease output volume\n"
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000578 " s Subscribe " SIP_DST_URI "\n"
Benny Prijonoc71ad432007-05-04 07:25:19 +0000579 " S Unsubscribe presence\n"
580 " o Set account online\n"
581 " O Set account offline\n"
Nanang Izzuddinda37ea32009-03-06 16:24:43 +0000582 " w Quit\n";
583
584 PJ_LOG(3, (THIS_FILE, menu));
Benny Prijono72a81aa2007-05-02 23:06:11 +0000585}
586
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000587static void PrintCodecMenu()
588{
Nanang Izzuddinda37ea32009-03-06 16:24:43 +0000589 const char *menu =
590 "\n\n"
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000591 "Codec Menu:\n"
592 " a Enable all codecs\n"
Nanang Izzuddina3775972009-03-03 18:25:55 +0000593#if PJMEDIA_HAS_PASSTHROUGH_CODEC_AMR
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000594 " d Enable only AMR\n"
Nanang Izzuddina3775972009-03-03 18:25:55 +0000595#endif
596#if PJMEDIA_HAS_PASSTHROUGH_CODEC_G729
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000597 " g Enable only G.729\n"
Nanang Izzuddina3775972009-03-03 18:25:55 +0000598#endif
599#if PJMEDIA_HAS_PASSTHROUGH_CODEC_ILBC
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000600 " j Enable only iLBC\n"
601#endif
602 " m Enable only Speex\n"
603 " p Enable only GSM\n"
604 " t Enable only PCMU\n"
Nanang Izzuddinda37ea32009-03-06 16:24:43 +0000605 " w Enable only PCMA\n";
606
607 PJ_LOG(3, (THIS_FILE, menu));
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000608}
609
610static void HandleMainMenu(TKeyCode kc) {
611 switch (kc) {
612
Nanang Izzuddin08694ea2009-03-10 15:03:04 +0000613 case EKeyUpArrow:
614 case EKeyDownArrow:
615 {
616 unsigned vol;
617 pj_status_t status;
618
619 status = pjsua_snd_get_setting(
620 PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING, &vol);
621 if (status == PJ_SUCCESS) {
622 if (kc == EKeyUpArrow)
623 vol = PJ_MIN(100, vol+10);
624 else
625 vol = (vol>=10 ? vol-10 : 0);
626 status = pjsua_snd_set_setting(
627 PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING,
628 &vol, PJ_TRUE);
629 }
630
631 if (status == PJ_SUCCESS) {
632 PJ_LOG(3,(THIS_FILE, "Output volume set to %d", vol));
633 } else {
634 pjsua_perror(THIS_FILE, "Error setting volume", status);
635 }
636 }
637 break;
638
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000639 case 't':
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000640 {
Nanang Izzuddinfcb92d02009-03-10 13:32:09 +0000641 pjmedia_aud_dev_route route;
642 pj_status_t status;
643
644 status = pjsua_snd_get_setting(PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE,
645 &route);
646
647 if (status == PJ_SUCCESS) {
648 if (route == PJMEDIA_AUD_DEV_ROUTE_LOUDSPEAKER)
649 route = PJMEDIA_AUD_DEV_ROUTE_EARPIECE;
650 else
651 route = PJMEDIA_AUD_DEV_ROUTE_LOUDSPEAKER;
Nanang Izzuddin452b66b2009-02-18 15:23:47 +0000652
Nanang Izzuddinfcb92d02009-03-10 13:32:09 +0000653 status = pjsua_snd_set_setting(
654 PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE,
655 &route, PJ_TRUE);
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000656 }
Nanang Izzuddinfcb92d02009-03-10 13:32:09 +0000657
658 if (status != PJ_SUCCESS)
659 pjsua_perror(THIS_FILE, "Error switch audio route", status);
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000660 }
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000661 break;
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000662
663 case 'j':
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000664 {
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000665 static pj_bool_t loopback_active = PJ_FALSE;
666 if (!loopback_active)
667 pjsua_conf_connect(0, 0);
668 else
669 pjsua_conf_disconnect(0, 0);
670 loopback_active = !loopback_active;
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000671 }
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000672 break;
673
674 case 'm':
675 if (g_call_id != PJSUA_INVALID_ID) {
676 PJ_LOG(3,(THIS_FILE, "Another call is active"));
677 break;
678 }
679
680 if (pjsua_verify_sip_url(SIP_DST_URI) == PJ_SUCCESS) {
681 pj_str_t dst = pj_str(SIP_DST_URI);
682 pjsua_call_make_call(g_acc_id, &dst, 0, NULL,
683 NULL, &g_call_id);
684 } else {
685 PJ_LOG(3,(THIS_FILE, "Invalid SIP URI"));
686 }
687 break;
688 case 'a':
689 if (g_call_id != PJSUA_INVALID_ID)
690 pjsua_call_answer(g_call_id, 200, NULL, NULL);
691 break;
692 case 'g':
693 pjsua_call_hangup_all();
694 break;
695 case 's':
696 case 'S':
697 if (g_buddy_id != PJSUA_INVALID_ID)
698 pjsua_buddy_subscribe_pres(g_buddy_id, kc=='s');
699 break;
700 case 'o':
701 case 'O':
702 pjsua_acc_set_online_status(g_acc_id, kc=='o');
703 break;
704
705 default:
706 PJ_LOG(3,(THIS_FILE, "Keycode '%c' (%d) is pressed", kc, kc));
707 break;
708 }
709
710 PrintMainMenu();
711}
712
713static void HandleCodecMenu(TKeyCode kc) {
714 const pj_str_t ID_ALL = {"*", 1};
715 pj_str_t codec = {NULL, 0};
716
717 if (kc == 'a') {
718 pjsua_codec_set_priority(&ID_ALL, PJMEDIA_CODEC_PRIO_NORMAL);
719 PJ_LOG(3,(THIS_FILE, "All codecs activated"));
720 } else {
721 switch (kc) {
722 case 'd':
723 codec = pj_str("AMR");
724 break;
725 case 'g':
726 codec = pj_str("G729");
727 break;
728 case 'j':
729 codec = pj_str("ILBC");
730 break;
731 case 'm':
732 codec = pj_str("SPEEX/8000");
733 break;
734 case 'p':
735 codec = pj_str("GSM");
736 break;
737 case 't':
738 codec = pj_str("PCMU");
739 break;
740 case 'w':
741 codec = pj_str("PCMA");
742 break;
743 default:
744 PJ_LOG(3,(THIS_FILE, "Keycode '%c' (%d) is pressed", kc, kc));
745 break;
746 }
747
748 if (codec.slen) {
749 pj_status_t status;
750
751 pjsua_codec_set_priority(&ID_ALL, PJMEDIA_CODEC_PRIO_DISABLED);
752
753 status = pjsua_codec_set_priority(&codec,
754 PJMEDIA_CODEC_PRIO_NORMAL);
755 if (status == PJ_SUCCESS)
756 PJ_LOG(3,(THIS_FILE, "%s activated", codec.ptr));
757 else
758 PJ_LOG(3,(THIS_FILE, "Failed activating %s, err=%d",
759 codec.ptr, status));
760 }
761 }
Benny Prijonoba5926a2007-05-02 11:29:37 +0000762}
763
764// Implementation: called when read has completed.
765void ConsoleUI::RunL()
766{
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000767 enum {
768 MENU_TYPE_MAIN = 0,
769 MENU_TYPE_CODEC = 1
770 };
771 static int menu_type = MENU_TYPE_MAIN;
Benny Prijonoc71ad432007-05-04 07:25:19 +0000772 TKeyCode kc = con_->KeyCode();
773 pj_bool_t reschedule = PJ_TRUE;
774
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000775 if (menu_type == MENU_TYPE_MAIN) {
776 if (kc == 'w') {
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000777 CActiveScheduler::Stop();
Benny Prijonoc71ad432007-05-04 07:25:19 +0000778 reschedule = PJ_FALSE;
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000779 } else if (kc == 'd') {
780 menu_type = MENU_TYPE_CODEC;
781 PrintCodecMenu();
782 } else {
783 HandleMainMenu(kc);
784 }
785 } else {
786 HandleCodecMenu(kc);
787
788 menu_type = MENU_TYPE_MAIN;
789 PrintMainMenu();
Benny Prijonoc71ad432007-05-04 07:25:19 +0000790 }
Benny Prijonoc71ad432007-05-04 07:25:19 +0000791
792 if (reschedule)
793 Run();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000794}
795
Benny Prijono70c5ba02007-12-31 11:27:35 +0000796#if 0
797// IP networking related testing
798static pj_status_t test_addr(void)
799{
800 int af;
801 unsigned i, count;
802 pj_addrinfo ai[8];
803 pj_sockaddr ifs[8];
804 const pj_str_t *hostname;
805 pj_hostent he;
806 pj_status_t status;
807
808 pj_log_set_log_func(&log_writer);
809
810 status = pj_init();
811 if (status != PJ_SUCCESS) {
812 pjsua_perror(THIS_FILE, "pj_init() error", status);
813 return status;
814 }
815
816 af = pj_AF_INET();
817
Benny Prijono684c0ad2008-01-03 18:50:27 +0000818#if 0
819 pj_in_addr in_addr;
820 pj_str_t aa = pj_str("1.1.1.1");
821 in_addr = pj_inet_addr(&aa);
822 char *the_addr = pj_inet_ntoa(in_addr);
823 PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
824
825 aa = pj_str("192.168.0.15");
826 in_addr = pj_inet_addr(&aa);
827 the_addr = pj_inet_ntoa(in_addr);
828 PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
829
830 aa = pj_str("2.2.2.2");
831 in_addr = pj_inet_addr(&aa);
832 the_addr = pj_inet_ntoa(in_addr);
833 PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
834
835 return -1;
836#endif
837
Benny Prijono70c5ba02007-12-31 11:27:35 +0000838 // Hostname
839 hostname = pj_gethostname();
840 if (hostname == NULL) {
841 status = PJ_ERESOLVE;
842 pjsua_perror(THIS_FILE, "pj_gethostname() error", status);
843 goto on_return;
844 }
845
846 PJ_LOG(3,(THIS_FILE, "Hostname: %.*s", hostname->slen, hostname->ptr));
847
848 // Gethostbyname
849 status = pj_gethostbyname(hostname, &he);
850 if (status != PJ_SUCCESS) {
851 pjsua_perror(THIS_FILE, "pj_gethostbyname() error", status);
852 } else {
853 PJ_LOG(3,(THIS_FILE, "gethostbyname: %s",
854 pj_inet_ntoa(*(pj_in_addr*)he.h_addr)));
855 }
856
857 // Getaddrinfo
858 count = PJ_ARRAY_SIZE(ai);
859 status = pj_getaddrinfo(af, hostname, &count, ai);
860 if (status != PJ_SUCCESS) {
861 pjsua_perror(THIS_FILE, "pj_getaddrinfo() error", status);
862 } else {
863 for (i=0; i<count; ++i) {
864 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
865 PJ_LOG(3,(THIS_FILE, "Addrinfo: %s",
866 pj_sockaddr_print(&ai[i].ai_addr, ipaddr, sizeof(ipaddr), 2)));
867 }
868 }
869
870 // Enum interface
871 count = PJ_ARRAY_SIZE(ifs);
872 status = pj_enum_ip_interface(af, &count, ifs);
873 if (status != PJ_SUCCESS) {
874 pjsua_perror(THIS_FILE, "pj_enum_ip_interface() error", status);
875 } else {
876 for (i=0; i<count; ++i) {
877 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
878 PJ_LOG(3,(THIS_FILE, "Interface: %s",
879 pj_sockaddr_print(&ifs[i], ipaddr, sizeof(ipaddr), 2)));
880 }
881 }
882
883 // Get default iinterface
884 status = pj_getdefaultipinterface(af, &ifs[0]);
885 if (status != PJ_SUCCESS) {
886 pjsua_perror(THIS_FILE, "pj_getdefaultipinterface() error", status);
887 } else {
888 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
889 PJ_LOG(3,(THIS_FILE, "Default IP: %s",
890 pj_sockaddr_print(&ifs[0], ipaddr, sizeof(ipaddr), 2)));
891 }
892
893 // Get default IP address
894 status = pj_gethostip(af, &ifs[0]);
895 if (status != PJ_SUCCESS) {
896 pjsua_perror(THIS_FILE, "pj_gethostip() error", status);
897 } else {
898 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
899 PJ_LOG(3,(THIS_FILE, "Host IP: %s",
900 pj_sockaddr_print(&ifs[0], ipaddr, sizeof(ipaddr), 2)));
901 }
902
903 status = -1;
904
905on_return:
906 pj_shutdown();
907 return status;
908}
909#endif
910
911
Benny Prijono6b3ccdf2008-01-14 11:54:21 +0000912#include <es_sock.h>
Benny Prijono897f9f82007-05-03 19:56:21 +0000913
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000914#if 0
915// Force network connection to use the first IAP,
916// this is useful for debugging on emulator without GUI.
917// Include commdb.lib & apengine.lib in symbian_ua.mmp file
918// if this is enabled.
919
920#include <apdatahandler.h>
921
922inline void ForceUseFirstIAP()
923{
924 TUint32 rank = 1;
925 TUint32 bearers;
926 TUint32 prompt;
927 TUint32 iap;
928
929 CCommsDatabase* commDb = CCommsDatabase::NewL(EDatabaseTypeIAP);
930 CleanupStack::PushL(commDb);
931
932 CApDataHandler* apDataHandler = CApDataHandler::NewLC(*commDb);
933
934 TCommDbConnectionDirection direction = ECommDbConnectionDirectionOutgoing;
935 apDataHandler->GetPreferredIfDbIapTypeL(rank, direction, bearers, prompt, iap);
936 prompt = ECommDbDialogPrefDoNotPrompt;
937 apDataHandler->SetPreferredIfDbIapTypeL(rank, direction, bearers, (TCommDbDialogPref)prompt, iap, ETrue);
938 CleanupStack::PopAndDestroy(2); // apDataHandler, commDb
939}
940
941static void SelectIAP()
942{
943 ForceUseFirstIAP();
944}
945
946#else
947
948static void SelectIAP()
949{
950}
951
952#endif
953
954
Nanang Izzuddin90b83202009-03-02 15:48:45 +0000955// Class CConnMon to monitor network connection (RConnection). Whenever
956// the connection is down, it will notify PJLIB and restart PJSUA-LIB.
957class CConnMon : public CActive {
958public:
959 static CConnMon* NewL(RConnection &conn, RSocketServ &sserver) {
960 CConnMon *self = new (ELeave) CConnMon(conn, sserver);
961 CleanupStack::PushL(self);
962 self->ConstructL();
963 CleanupStack::Pop(self);
964 return self;
965 }
966
967 void Start() {
968 conn_.ProgressNotification(nif_progress_, iStatus);
969 SetActive();
970 }
971
972 void Stop() {
973 Cancel();
974 }
975
976 ~CConnMon() { Stop(); }
977
978private:
979 CConnMon(RConnection &conn, RSocketServ &sserver) :
980 CActive(EPriorityHigh),
981 conn_(conn),
982 sserver_(sserver)
983 {
984 CActiveScheduler::Add(this);
985 }
986
987 void ConstructL() {}
988
989 void DoCancel() {
990 conn_.CancelProgressNotification();
991 }
992
993 void RunL() {
994 int stage = nif_progress_().iStage;
995
996 if (stage == KLinkLayerClosed) {
997 pj_status_t status;
998 TInt err;
999
1000 // Tell pjlib that connection is down.
1001 pj_symbianos_set_connection_status(PJ_FALSE);
1002
1003 PJ_LOG(3, (THIS_FILE, "RConnection closed, restarting PJSUA.."));
1004
1005 // Destroy pjsua
1006 pjsua_destroy();
1007 PJ_LOG(3, (THIS_FILE, "PJSUA destroyed."));
1008
1009 // Reopen the connection
1010 err = conn_.Open(sserver_);
1011 if (err == KErrNone)
1012 err = conn_.Start();
1013 if (err != KErrNone) {
1014 CActiveScheduler::Stop();
1015 return;
1016 }
1017
1018 // Reinit Symbian OS param before pj_init()
1019 pj_symbianos_params sym_params;
1020 pj_bzero(&sym_params, sizeof(sym_params));
1021 sym_params.rsocketserv = &sserver_;
1022 sym_params.rconnection = &conn_;
1023 pj_symbianos_set_params(&sym_params);
1024
1025 // Reinit pjsua
1026 status = app_startup();
1027 if (status != PJ_SUCCESS) {
1028 pjsua_perror(THIS_FILE, "app_startup() error", status);
1029 CActiveScheduler::Stop();
1030 return;
1031 }
1032
1033 PJ_LOG(3, (THIS_FILE, "PJSUA restarted."));
Benny Prijono9920dc32009-03-12 18:11:37 +00001034 PrintMainMenu();
Nanang Izzuddin90b83202009-03-02 15:48:45 +00001035 }
1036
1037 Start();
1038 }
1039
1040 RConnection& conn_;
1041 RSocketServ& sserver_;
1042 TNifProgressBuf nif_progress_;
1043};
1044
Benny Prijonoba5926a2007-05-02 11:29:37 +00001045////////////////////////////////////////////////////////////////////////////
1046int ua_main()
1047{
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001048 RSocketServ aSocketServer;
1049 RConnection aConn;
1050 TInt err;
1051 pj_symbianos_params sym_params;
Benny Prijonoc71ad432007-05-04 07:25:19 +00001052 pj_status_t status;
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001053
1054 SelectIAP();
Benny Prijonoc71ad432007-05-04 07:25:19 +00001055
Benny Prijono70c5ba02007-12-31 11:27:35 +00001056 // Initialize RSocketServ
1057 if ((err=aSocketServer.Connect()) != KErrNone)
1058 return PJ_STATUS_FROM_OS(err);
1059
1060 // Open up a connection
1061 if ((err=aConn.Open(aSocketServer)) != KErrNone) {
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001062 aSocketServer.Close();
1063 return PJ_STATUS_FROM_OS(err);
Benny Prijono70c5ba02007-12-31 11:27:35 +00001064 }
1065
1066 if ((err=aConn.Start()) != KErrNone) {
1067 aSocketServer.Close();
1068 return PJ_STATUS_FROM_OS(err);
1069 }
1070
1071 // Set Symbian OS parameters in pjlib.
1072 // This must be done before pj_init() is called.
1073 pj_bzero(&sym_params, sizeof(sym_params));
1074 sym_params.rsocketserv = &aSocketServer;
1075 sym_params.rconnection = &aConn;
1076 pj_symbianos_set_params(&sym_params);
1077
Benny Prijonoc71ad432007-05-04 07:25:19 +00001078 // Initialize pjsua
1079 status = app_startup();
Benny Prijono70c5ba02007-12-31 11:27:35 +00001080 //status = test_addr();
1081 if (status != PJ_SUCCESS) {
1082 aConn.Close();
1083 aSocketServer.Close();
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001084 return status;
Benny Prijono70c5ba02007-12-31 11:27:35 +00001085 }
Benny Prijono897f9f82007-05-03 19:56:21 +00001086
Nanang Izzuddin90b83202009-03-02 15:48:45 +00001087
Benny Prijonoc71ad432007-05-04 07:25:19 +00001088 // Run the UI
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001089 ConsoleUI *con = new ConsoleUI(console);
Benny Prijonoc71ad432007-05-04 07:25:19 +00001090
1091 con->Run();
Nanang Izzuddin798bf452009-02-12 12:35:27 +00001092 PrintMainMenu();
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001093
Nanang Izzuddin90b83202009-03-02 15:48:45 +00001094 // Init & start connection monitor
1095 CConnMon *connmon = CConnMon::NewL(aConn, aSocketServer);
1096 connmon->Start();
1097
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001098 CActiveScheduler::Start();
Benny Prijonoc71ad432007-05-04 07:25:19 +00001099
Nanang Izzuddin90b83202009-03-02 15:48:45 +00001100 delete connmon;
Benny Prijonoc71ad432007-05-04 07:25:19 +00001101 delete con;
Benny Prijono684c0ad2008-01-03 18:50:27 +00001102
1103 // Dump memory statistics
1104 PJ_LOG(3,(THIS_FILE, "Max heap usage: %u.%03uMB",
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001105 pjsua_var.cp.peak_used_size / 1000000,
1106 (pjsua_var.cp.peak_used_size % 1000000)/1000));
Benny Prijonoc71ad432007-05-04 07:25:19 +00001107
Benny Prijono684c0ad2008-01-03 18:50:27 +00001108 // check max stack usage
1109#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
1110 pj_thread_t* this_thread = pj_thread_this();
1111 if (!this_thread)
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001112 return status;
Benny Prijono684c0ad2008-01-03 18:50:27 +00001113
1114 const char* max_stack_file;
1115 int max_stack_line;
1116 status = pj_thread_get_stack_info(this_thread, &max_stack_file, &max_stack_line);
1117
1118 PJ_LOG(3,(THIS_FILE, "Max stack usage: %u at %s:%d",
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001119 pj_thread_get_stack_max_usage(this_thread),
1120 max_stack_file, max_stack_line));
Benny Prijono684c0ad2008-01-03 18:50:27 +00001121#endif
1122
Benny Prijonoc71ad432007-05-04 07:25:19 +00001123 // Shutdown pjsua
1124 pjsua_destroy();
1125
Benny Prijono70c5ba02007-12-31 11:27:35 +00001126 // Close connection and socket server
1127 aConn.Close();
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001128 aSocketServer.Close();
Nanang Izzuddina940b362009-02-23 13:53:30 +00001129
Benny Prijono797e3382007-12-01 09:10:07 +00001130 return status;
Benny Prijonoba5926a2007-05-02 11:29:37 +00001131}
1132