blob: 033a2f2ae4137b33430a141049d0184c4fbed538 [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//
Benny Prijono0e2c6462008-02-14 13:39:24 +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
54
55//
56// Configure nameserver if DNS SRV is to be used with both SIP
57// or STUN (for STUN see other settings below)
58//
Nanang Izzuddin82f7a412008-12-17 11:36:22 +000059#define NAMESERVER NULL
60//#define NAMESERVER "192.168.0.2"
Benny Prijono897f9f82007-05-03 19:56:21 +000061
62//
63// STUN server
Benny Prijono684c0ad2008-01-03 18:50:27 +000064#if 0
Benny Prijono897f9f82007-05-03 19:56:21 +000065 // Use this to have the STUN server resolved normally
66# define STUN_DOMAIN NULL
Benny Prijono4b55e0a2008-12-18 13:22:52 +000067# define STUN_SERVER "stun.pjsip.org"
Benny Prijono897f9f82007-05-03 19:56:21 +000068#elif 0
69 // Use this to have the STUN server resolved with DNS SRV
Benny Prijono4b55e0a2008-12-18 13:22:52 +000070# define STUN_DOMAIN "pjsip.org"
Benny Prijono897f9f82007-05-03 19:56:21 +000071# define STUN_SERVER NULL
72#else
73 // Use this to disable STUN
74# define STUN_DOMAIN NULL
75# define STUN_SERVER NULL
76#endif
77
78//
79// Use ICE?
80//
Benny Prijono70c5ba02007-12-31 11:27:35 +000081#define USE_ICE 1
Benny Prijono72a81aa2007-05-02 23:06:11 +000082
Nanang Izzuddin6a6392f2008-06-02 18:30:15 +000083//
84// Use SRTP?
85//
86#define USE_SRTP PJSUA_DEFAULT_USE_SRTP
Benny Prijono72a81aa2007-05-02 23:06:11 +000087
Benny Prijonob2c96822007-05-03 13:31:21 +000088//
89// Globals
90//
91static pjsua_acc_id g_acc_id = PJSUA_INVALID_ID;
92static pjsua_call_id g_call_id = PJSUA_INVALID_ID;
93static pjsua_buddy_id g_buddy_id = PJSUA_INVALID_ID;
Benny Prijono72a81aa2007-05-02 23:06:11 +000094
Benny Prijonoba5926a2007-05-02 11:29:37 +000095
96/* Callback called by the library upon receiving incoming call */
97static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
98 pjsip_rx_data *rdata)
99{
100 pjsua_call_info ci;
101
102 PJ_UNUSED_ARG(acc_id);
103 PJ_UNUSED_ARG(rdata);
104
Benny Prijonob2c96822007-05-03 13:31:21 +0000105 if (g_call_id != PJSUA_INVALID_ID) {
106 pjsua_call_answer(call_id, PJSIP_SC_BUSY_HERE, NULL, NULL);
107 return;
108 }
109
Benny Prijonoba5926a2007-05-02 11:29:37 +0000110 pjsua_call_get_info(call_id, &ci);
111
112 PJ_LOG(3,(THIS_FILE, "Incoming call from %.*s!!",
113 (int)ci.remote_info.slen,
114 ci.remote_info.ptr));
115
Benny Prijonob2c96822007-05-03 13:31:21 +0000116 g_call_id = call_id;
117
Benny Prijono897f9f82007-05-03 19:56:21 +0000118 /* Automatically answer incoming calls with 180/Ringing */
119 pjsua_call_answer(call_id, 180, NULL, NULL);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000120}
121
122/* Callback called by the library when call's state has changed */
123static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
124{
125 pjsua_call_info ci;
126
127 PJ_UNUSED_ARG(e);
128
129 pjsua_call_get_info(call_id, &ci);
Benny Prijonob2c96822007-05-03 13:31:21 +0000130
131 if (ci.state == PJSIP_INV_STATE_DISCONNECTED) {
132 if (call_id == g_call_id)
133 g_call_id = PJSUA_INVALID_ID;
Benny Prijono897f9f82007-05-03 19:56:21 +0000134 } else if (ci.state != PJSIP_INV_STATE_INCOMING) {
Benny Prijonob2c96822007-05-03 13:31:21 +0000135 if (g_call_id == PJSUA_INVALID_ID)
136 g_call_id = call_id;
137 }
138
Benny Prijonoba5926a2007-05-02 11:29:37 +0000139 PJ_LOG(3,(THIS_FILE, "Call %d state=%.*s", call_id,
140 (int)ci.state_text.slen,
141 ci.state_text.ptr));
142}
143
144/* Callback called by the library when call's media state has changed */
145static void on_call_media_state(pjsua_call_id call_id)
146{
147 pjsua_call_info ci;
148
149 pjsua_call_get_info(call_id, &ci);
150
151 if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
152 // When media is active, connect call to sound device.
153 pjsua_conf_connect(ci.conf_slot, 0);
154 pjsua_conf_connect(0, ci.conf_slot);
155 }
156}
157
158
Benny Prijonob2c96822007-05-03 13:31:21 +0000159/* Handler on buddy state changed. */
160static void on_buddy_state(pjsua_buddy_id buddy_id)
161{
162 pjsua_buddy_info info;
163 pjsua_buddy_get_info(buddy_id, &info);
164
165 PJ_LOG(3,(THIS_FILE, "%.*s status is %.*s",
166 (int)info.uri.slen,
167 info.uri.ptr,
168 (int)info.status_text.slen,
169 info.status_text.ptr));
170}
171
172
173/* Incoming IM message (i.e. MESSAGE request)! */
174static void on_pager(pjsua_call_id call_id, const pj_str_t *from,
175 const pj_str_t *to, const pj_str_t *contact,
176 const pj_str_t *mime_type, const pj_str_t *text)
177{
178 /* Note: call index may be -1 */
179 PJ_UNUSED_ARG(call_id);
180 PJ_UNUSED_ARG(to);
181 PJ_UNUSED_ARG(contact);
182 PJ_UNUSED_ARG(mime_type);
183
184 PJ_LOG(3,(THIS_FILE,"MESSAGE from %.*s: %.*s",
185 (int)from->slen, from->ptr,
186 (int)text->slen, text->ptr));
187}
188
189
190/* Received typing indication */
191static void on_typing(pjsua_call_id call_id, const pj_str_t *from,
192 const pj_str_t *to, const pj_str_t *contact,
193 pj_bool_t is_typing)
194{
195 PJ_UNUSED_ARG(call_id);
196 PJ_UNUSED_ARG(to);
197 PJ_UNUSED_ARG(contact);
198
199 PJ_LOG(3,(THIS_FILE, "IM indication: %.*s %s",
200 (int)from->slen, from->ptr,
201 (is_typing?"is typing..":"has stopped typing")));
202}
203
204
205/* Call transfer request status. */
206static void on_call_transfer_status(pjsua_call_id call_id,
207 int status_code,
208 const pj_str_t *status_text,
209 pj_bool_t final,
210 pj_bool_t *p_cont)
211{
212 PJ_LOG(3,(THIS_FILE, "Call %d: transfer status=%d (%.*s) %s",
213 call_id, status_code,
214 (int)status_text->slen, status_text->ptr,
215 (final ? "[final]" : "")));
216
217 if (status_code/100 == 2) {
218 PJ_LOG(3,(THIS_FILE,
219 "Call %d: call transfered successfully, disconnecting call",
220 call_id));
221 pjsua_call_hangup(call_id, PJSIP_SC_GONE, NULL, NULL);
222 *p_cont = PJ_FALSE;
223 }
224}
225
226
Benny Prijonoaecabfc2007-10-26 05:35:42 +0000227/* NAT detection result */
228static void on_nat_detect(const pj_stun_nat_detect_result *res)
229{
230 if (res->status != PJ_SUCCESS) {
231 pjsua_perror(THIS_FILE, "NAT detection failed", res->status);
232 } else {
233 PJ_LOG(3, (THIS_FILE, "NAT detected as %s", res->nat_type_name));
234 }
235}
236
Benny Prijonob2c96822007-05-03 13:31:21 +0000237/* Notification that call is being replaced. */
238static void on_call_replaced(pjsua_call_id old_call_id,
239 pjsua_call_id new_call_id)
240{
241 pjsua_call_info old_ci, new_ci;
242
243 pjsua_call_get_info(old_call_id, &old_ci);
244 pjsua_call_get_info(new_call_id, &new_ci);
245
246 PJ_LOG(3,(THIS_FILE, "Call %d with %.*s is being replaced by "
247 "call %d with %.*s",
248 old_call_id,
249 (int)old_ci.remote_info.slen, old_ci.remote_info.ptr,
250 new_call_id,
251 (int)new_ci.remote_info.slen, new_ci.remote_info.ptr));
252}
253
254
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000255//#include<e32debug.h>
256
Benny Prijonoba5926a2007-05-02 11:29:37 +0000257/* Logging callback */
Benny Prijono797e3382007-12-01 09:10:07 +0000258static void log_writer(int level, const char *buf, int len)
Benny Prijonoba5926a2007-05-02 11:29:37 +0000259{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000260 static wchar_t buf16[PJ_LOG_MAX_SIZE];
Benny Prijonoba5926a2007-05-02 11:29:37 +0000261
262 PJ_UNUSED_ARG(level);
263
264 pj_ansi_to_unicode(buf, len, buf16, PJ_ARRAY_SIZE(buf16));
265
266 TPtrC16 aBuf((const TUint16*)buf16, (TInt)len);
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000267 //RDebug::Print(aBuf);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000268 console->Write(aBuf);
Benny Prijono797e3382007-12-01 09:10:07 +0000269
Benny Prijonoba5926a2007-05-02 11:29:37 +0000270}
271
272/*
273 * app_startup()
274 *
275 * url may contain URL to call.
276 */
Benny Prijonob2c96822007-05-03 13:31:21 +0000277static pj_status_t app_startup()
Benny Prijonoba5926a2007-05-02 11:29:37 +0000278{
Benny Prijonoba5926a2007-05-02 11:29:37 +0000279 pj_status_t status;
280
281 /* Redirect log before pjsua_init() */
Benny Prijono70c5ba02007-12-31 11:27:35 +0000282 pj_log_set_log_func(&log_writer);
283
284 /* Set log level */
Nanang Izzuddinda37ea32009-03-06 16:24:43 +0000285 pj_log_set_level(CON_LOG_LEVEL);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000286
287 /* Create pjsua first! */
288 status = pjsua_create();
289 if (status != PJ_SUCCESS) {
290 pjsua_perror(THIS_FILE, "pjsua_create() error", status);
291 return status;
292 }
293
Benny Prijonoba5926a2007-05-02 11:29:37 +0000294 /* Init pjsua */
Benny Prijonoc71ad432007-05-04 07:25:19 +0000295 pjsua_config cfg;
296 pjsua_logging_config log_cfg;
297 pjsua_media_config med_cfg;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000298
Benny Prijonoc71ad432007-05-04 07:25:19 +0000299 pjsua_config_default(&cfg);
300 cfg.max_calls = 2;
301 cfg.thread_cnt = 0; // Disable threading on Symbian
Nanang Izzuddin6a6392f2008-06-02 18:30:15 +0000302 cfg.use_srtp = USE_SRTP;
303 cfg.srtp_secure_signaling = 0;
304
Benny Prijonoc71ad432007-05-04 07:25:19 +0000305 cfg.cb.on_incoming_call = &on_incoming_call;
306 cfg.cb.on_call_media_state = &on_call_media_state;
307 cfg.cb.on_call_state = &on_call_state;
308 cfg.cb.on_buddy_state = &on_buddy_state;
309 cfg.cb.on_pager = &on_pager;
310 cfg.cb.on_typing = &on_typing;
311 cfg.cb.on_call_transfer_status = &on_call_transfer_status;
312 cfg.cb.on_call_replaced = &on_call_replaced;
Benny Prijonoaecabfc2007-10-26 05:35:42 +0000313 cfg.cb.on_nat_detect = &on_nat_detect;
314
Benny Prijonoc71ad432007-05-04 07:25:19 +0000315 if (SIP_PROXY) {
316 cfg.outbound_proxy_cnt = 1;
317 cfg.outbound_proxy[0] = pj_str(SIP_PROXY);
318 }
319
320 if (NAMESERVER) {
321 cfg.nameserver_count = 1;
322 cfg.nameserver[0] = pj_str(NAMESERVER);
323 }
324
325 if (NAMESERVER && STUN_DOMAIN) {
326 cfg.stun_domain = pj_str(STUN_DOMAIN);
327 } else if (STUN_SERVER) {
328 cfg.stun_host = pj_str(STUN_SERVER);
329 }
330
331
332 pjsua_logging_config_default(&log_cfg);
Nanang Izzuddinda37ea32009-03-06 16:24:43 +0000333 log_cfg.level = FILE_LOG_LEVEL;
334 log_cfg.console_level = CON_LOG_LEVEL;
Benny Prijonoc71ad432007-05-04 07:25:19 +0000335 log_cfg.cb = &log_writer;
Nanang Izzuddin83457d52009-02-16 16:29:05 +0000336 log_cfg.log_filename = pj_str("C:\\data\\symbian_ua.log");
Benny Prijonoba5926a2007-05-02 11:29:37 +0000337
Benny Prijonoc71ad432007-05-04 07:25:19 +0000338 pjsua_media_config_default(&med_cfg);
339 med_cfg.thread_cnt = 0; // Disable threading on Symbian
340 med_cfg.has_ioqueue = PJ_FALSE;
341 med_cfg.clock_rate = 8000;
Benny Prijono5df8bb62007-12-28 18:55:02 +0000342 med_cfg.audio_frame_ptime = 40;
Benny Prijonoc71ad432007-05-04 07:25:19 +0000343 med_cfg.ec_tail_len = 0;
344 med_cfg.enable_ice = USE_ICE;
Nanang Izzuddin81db8c72009-02-05 10:59:14 +0000345 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 +0000346 //med_cfg.no_vad = PJ_TRUE;
Benny Prijonoc71ad432007-05-04 07:25:19 +0000347
348 status = pjsua_init(&cfg, &log_cfg, &med_cfg);
349 if (status != PJ_SUCCESS) {
350 pjsua_perror(THIS_FILE, "pjsua_init() error", status);
351 pjsua_destroy();
352 return status;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000353 }
Nanang Izzuddin829ac022008-05-27 00:24:26 +0000354
355 /* Adjust Speex priority and enable only the narrowband */
356 {
357 pj_str_t codec_id = pj_str("speex/8000");
358 pjmedia_codec_mgr_set_codec_priority(
359 pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
360 &codec_id, PJMEDIA_CODEC_PRIO_NORMAL+1);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000361
Nanang Izzuddin829ac022008-05-27 00:24:26 +0000362 codec_id = pj_str("speex/16000");
363 pjmedia_codec_mgr_set_codec_priority(
364 pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
365 &codec_id, PJMEDIA_CODEC_PRIO_DISABLED);
366
367 codec_id = pj_str("speex/32000");
368 pjmedia_codec_mgr_set_codec_priority(
369 pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
370 &codec_id, PJMEDIA_CODEC_PRIO_DISABLED);
371 }
372
Benny Prijonoba5926a2007-05-02 11:29:37 +0000373 /* Add UDP transport. */
Benny Prijonoc71ad432007-05-04 07:25:19 +0000374 pjsua_transport_config tcfg;
375 pjsua_transport_id tid;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000376
Benny Prijonoc71ad432007-05-04 07:25:19 +0000377 pjsua_transport_config_default(&tcfg);
378 tcfg.port = SIP_PORT;
379 status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &tcfg, &tid);
380 if (status != PJ_SUCCESS) {
381 pjsua_perror(THIS_FILE, "Error creating transport", status);
382 pjsua_destroy();
383 return status;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000384 }
385
Benny Prijonoc71ad432007-05-04 07:25:19 +0000386 /* Add account for the transport */
387 pjsua_acc_add_local(tid, PJ_TRUE, &g_acc_id);
388
389
Benny Prijonoba5926a2007-05-02 11:29:37 +0000390 /* Initialization is done, now start pjsua */
391 status = pjsua_start();
392 if (status != PJ_SUCCESS) {
393 pjsua_perror(THIS_FILE, "Error starting pjsua", status);
394 pjsua_destroy();
395 return status;
396 }
397
398 /* Register to SIP server by creating SIP account. */
Benny Prijono72a81aa2007-05-02 23:06:11 +0000399 if (HAS_SIP_ACCOUNT) {
Benny Prijonoba5926a2007-05-02 11:29:37 +0000400 pjsua_acc_config cfg;
401
402 pjsua_acc_config_default(&cfg);
403 cfg.id = pj_str("sip:" SIP_USER "@" SIP_DOMAIN);
404 cfg.reg_uri = pj_str("sip:" SIP_DOMAIN);
405 cfg.cred_count = 1;
Benny Prijono0e2c6462008-02-14 13:39:24 +0000406 cfg.cred_info[0].realm = pj_str("*");
Benny Prijonoba5926a2007-05-02 11:29:37 +0000407 cfg.cred_info[0].scheme = pj_str("digest");
408 cfg.cred_info[0].username = pj_str(SIP_USER);
409 cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
410 cfg.cred_info[0].data = pj_str(SIP_PASSWD);
411
Benny Prijonob2c96822007-05-03 13:31:21 +0000412 status = pjsua_acc_add(&cfg, PJ_TRUE, &g_acc_id);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000413 if (status != PJ_SUCCESS) {
414 pjsua_perror(THIS_FILE, "Error adding account", status);
415 pjsua_destroy();
416 return status;
417 }
418 }
419
Benny Prijonob2c96822007-05-03 13:31:21 +0000420 if (SIP_DST_URI) {
421 pjsua_buddy_config bcfg;
422
423 pjsua_buddy_config_default(&bcfg);
424 bcfg.uri = pj_str(SIP_DST_URI);
425 bcfg.subscribe = PJ_FALSE;
426
427 pjsua_buddy_add(&bcfg, &g_buddy_id);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000428 }
Benny Prijonoba5926a2007-05-02 11:29:37 +0000429 return PJ_SUCCESS;
430}
431
432
433////////////////////////////////////////////////////////////////////////////
Benny Prijonoc71ad432007-05-04 07:25:19 +0000434/*
435 * The interractive console UI
436 */
Benny Prijonoba5926a2007-05-02 11:29:37 +0000437#include <e32base.h>
438
439class ConsoleUI : public CActive
440{
441public:
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000442 ConsoleUI(CConsoleBase *con);
Nanang Izzuddin90b83202009-03-02 15:48:45 +0000443 ~ConsoleUI();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000444
Benny Prijonoc71ad432007-05-04 07:25:19 +0000445 // Run console UI
446 void Run();
447
448 // Stop
449 void Stop();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000450
451protected:
Benny Prijonoc71ad432007-05-04 07:25:19 +0000452 // Cancel asynchronous read.
453 void DoCancel();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000454
Benny Prijonoc71ad432007-05-04 07:25:19 +0000455 // Implementation: called when read has completed.
456 void RunL();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000457
458private:
Benny Prijonoc71ad432007-05-04 07:25:19 +0000459 CConsoleBase *con_;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000460};
461
462
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000463ConsoleUI::ConsoleUI(CConsoleBase *con)
464: CActive(EPriorityStandard), con_(con)
Benny Prijonoba5926a2007-05-02 11:29:37 +0000465{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000466 CActiveScheduler::Add(this);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000467}
468
Nanang Izzuddin90b83202009-03-02 15:48:45 +0000469ConsoleUI::~ConsoleUI()
470{
471 Stop();
472}
473
Benny Prijonoba5926a2007-05-02 11:29:37 +0000474// Run console UI
475void ConsoleUI::Run()
476{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000477 con_->Read(iStatus);
478 SetActive();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000479}
480
481// Stop console UI
482void ConsoleUI::Stop()
483{
Nanang Izzuddin90b83202009-03-02 15:48:45 +0000484 Cancel();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000485}
486
487// Cancel asynchronous read.
488void ConsoleUI::DoCancel()
489{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000490 con_->ReadCancel();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000491}
492
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000493static void PrintMainMenu()
Benny Prijono72a81aa2007-05-02 23:06:11 +0000494{
Nanang Izzuddinda37ea32009-03-06 16:24:43 +0000495 const char *menu =
496 "\n\n"
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000497 "Main Menu:\n"
498 " d Enable/disable codecs\n"
Benny Prijono70c5ba02007-12-31 11:27:35 +0000499 " m Call " SIP_DST_URI "\n"
500 " a Answer call\n"
501 " g Hangup all calls\n"
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000502 " t Toggle audio route\n"
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000503#if !defined(PJMEDIA_CONF_USE_SWITCH_BOARD) || PJMEDIA_CONF_USE_SWITCH_BOARD==0
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000504 " j Toggle loopback audio\n"
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000505#endif
Nanang Izzuddin08694ea2009-03-10 15:03:04 +0000506 "up/dn Increase/decrease output volume\n"
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000507 " s Subscribe " SIP_DST_URI "\n"
Benny Prijonoc71ad432007-05-04 07:25:19 +0000508 " S Unsubscribe presence\n"
509 " o Set account online\n"
510 " O Set account offline\n"
Nanang Izzuddinda37ea32009-03-06 16:24:43 +0000511 " w Quit\n";
512
513 PJ_LOG(3, (THIS_FILE, menu));
Benny Prijono72a81aa2007-05-02 23:06:11 +0000514}
515
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000516static void PrintCodecMenu()
517{
Nanang Izzuddinda37ea32009-03-06 16:24:43 +0000518 const char *menu =
519 "\n\n"
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000520 "Codec Menu:\n"
521 " a Enable all codecs\n"
Nanang Izzuddina3775972009-03-03 18:25:55 +0000522#if PJMEDIA_HAS_PASSTHROUGH_CODEC_AMR
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000523 " d Enable only AMR\n"
Nanang Izzuddina3775972009-03-03 18:25:55 +0000524#endif
525#if PJMEDIA_HAS_PASSTHROUGH_CODEC_G729
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000526 " g Enable only G.729\n"
Nanang Izzuddina3775972009-03-03 18:25:55 +0000527#endif
528#if PJMEDIA_HAS_PASSTHROUGH_CODEC_ILBC
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000529 " j Enable only iLBC\n"
530#endif
531 " m Enable only Speex\n"
532 " p Enable only GSM\n"
533 " t Enable only PCMU\n"
Nanang Izzuddinda37ea32009-03-06 16:24:43 +0000534 " w Enable only PCMA\n";
535
536 PJ_LOG(3, (THIS_FILE, menu));
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000537}
538
539static void HandleMainMenu(TKeyCode kc) {
540 switch (kc) {
541
Nanang Izzuddin08694ea2009-03-10 15:03:04 +0000542 case EKeyUpArrow:
543 case EKeyDownArrow:
544 {
545 unsigned vol;
546 pj_status_t status;
547
548 status = pjsua_snd_get_setting(
549 PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING, &vol);
550 if (status == PJ_SUCCESS) {
551 if (kc == EKeyUpArrow)
552 vol = PJ_MIN(100, vol+10);
553 else
554 vol = (vol>=10 ? vol-10 : 0);
555 status = pjsua_snd_set_setting(
556 PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING,
557 &vol, PJ_TRUE);
558 }
559
560 if (status == PJ_SUCCESS) {
561 PJ_LOG(3,(THIS_FILE, "Output volume set to %d", vol));
562 } else {
563 pjsua_perror(THIS_FILE, "Error setting volume", status);
564 }
565 }
566 break;
567
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000568 case 't':
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000569 {
Nanang Izzuddinfcb92d02009-03-10 13:32:09 +0000570 pjmedia_aud_dev_route route;
571 pj_status_t status;
572
573 status = pjsua_snd_get_setting(PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE,
574 &route);
575
576 if (status == PJ_SUCCESS) {
577 if (route == PJMEDIA_AUD_DEV_ROUTE_LOUDSPEAKER)
578 route = PJMEDIA_AUD_DEV_ROUTE_EARPIECE;
579 else
580 route = PJMEDIA_AUD_DEV_ROUTE_LOUDSPEAKER;
Nanang Izzuddin452b66b2009-02-18 15:23:47 +0000581
Nanang Izzuddinfcb92d02009-03-10 13:32:09 +0000582 status = pjsua_snd_set_setting(
583 PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE,
584 &route, PJ_TRUE);
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000585 }
Nanang Izzuddinfcb92d02009-03-10 13:32:09 +0000586
587 if (status != PJ_SUCCESS)
588 pjsua_perror(THIS_FILE, "Error switch audio route", status);
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000589 }
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000590 break;
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000591
592 case 'j':
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000593 {
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000594 static pj_bool_t loopback_active = PJ_FALSE;
595 if (!loopback_active)
596 pjsua_conf_connect(0, 0);
597 else
598 pjsua_conf_disconnect(0, 0);
599 loopback_active = !loopback_active;
Nanang Izzuddin0cb3b022009-02-27 17:37:35 +0000600 }
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000601 break;
602
603 case 'm':
604 if (g_call_id != PJSUA_INVALID_ID) {
605 PJ_LOG(3,(THIS_FILE, "Another call is active"));
606 break;
607 }
608
609 if (pjsua_verify_sip_url(SIP_DST_URI) == PJ_SUCCESS) {
610 pj_str_t dst = pj_str(SIP_DST_URI);
611 pjsua_call_make_call(g_acc_id, &dst, 0, NULL,
612 NULL, &g_call_id);
613 } else {
614 PJ_LOG(3,(THIS_FILE, "Invalid SIP URI"));
615 }
616 break;
617 case 'a':
618 if (g_call_id != PJSUA_INVALID_ID)
619 pjsua_call_answer(g_call_id, 200, NULL, NULL);
620 break;
621 case 'g':
622 pjsua_call_hangup_all();
623 break;
624 case 's':
625 case 'S':
626 if (g_buddy_id != PJSUA_INVALID_ID)
627 pjsua_buddy_subscribe_pres(g_buddy_id, kc=='s');
628 break;
629 case 'o':
630 case 'O':
631 pjsua_acc_set_online_status(g_acc_id, kc=='o');
632 break;
633
634 default:
635 PJ_LOG(3,(THIS_FILE, "Keycode '%c' (%d) is pressed", kc, kc));
636 break;
637 }
638
639 PrintMainMenu();
640}
641
642static void HandleCodecMenu(TKeyCode kc) {
643 const pj_str_t ID_ALL = {"*", 1};
644 pj_str_t codec = {NULL, 0};
645
646 if (kc == 'a') {
647 pjsua_codec_set_priority(&ID_ALL, PJMEDIA_CODEC_PRIO_NORMAL);
648 PJ_LOG(3,(THIS_FILE, "All codecs activated"));
649 } else {
650 switch (kc) {
651 case 'd':
652 codec = pj_str("AMR");
653 break;
654 case 'g':
655 codec = pj_str("G729");
656 break;
657 case 'j':
658 codec = pj_str("ILBC");
659 break;
660 case 'm':
661 codec = pj_str("SPEEX/8000");
662 break;
663 case 'p':
664 codec = pj_str("GSM");
665 break;
666 case 't':
667 codec = pj_str("PCMU");
668 break;
669 case 'w':
670 codec = pj_str("PCMA");
671 break;
672 default:
673 PJ_LOG(3,(THIS_FILE, "Keycode '%c' (%d) is pressed", kc, kc));
674 break;
675 }
676
677 if (codec.slen) {
678 pj_status_t status;
679
680 pjsua_codec_set_priority(&ID_ALL, PJMEDIA_CODEC_PRIO_DISABLED);
681
682 status = pjsua_codec_set_priority(&codec,
683 PJMEDIA_CODEC_PRIO_NORMAL);
684 if (status == PJ_SUCCESS)
685 PJ_LOG(3,(THIS_FILE, "%s activated", codec.ptr));
686 else
687 PJ_LOG(3,(THIS_FILE, "Failed activating %s, err=%d",
688 codec.ptr, status));
689 }
690 }
Benny Prijonoba5926a2007-05-02 11:29:37 +0000691}
692
693// Implementation: called when read has completed.
694void ConsoleUI::RunL()
695{
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000696 enum {
697 MENU_TYPE_MAIN = 0,
698 MENU_TYPE_CODEC = 1
699 };
700 static int menu_type = MENU_TYPE_MAIN;
Benny Prijonoc71ad432007-05-04 07:25:19 +0000701 TKeyCode kc = con_->KeyCode();
702 pj_bool_t reschedule = PJ_TRUE;
703
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000704 if (menu_type == MENU_TYPE_MAIN) {
705 if (kc == 'w') {
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000706 CActiveScheduler::Stop();
Benny Prijonoc71ad432007-05-04 07:25:19 +0000707 reschedule = PJ_FALSE;
Nanang Izzuddin798bf452009-02-12 12:35:27 +0000708 } else if (kc == 'd') {
709 menu_type = MENU_TYPE_CODEC;
710 PrintCodecMenu();
711 } else {
712 HandleMainMenu(kc);
713 }
714 } else {
715 HandleCodecMenu(kc);
716
717 menu_type = MENU_TYPE_MAIN;
718 PrintMainMenu();
Benny Prijonoc71ad432007-05-04 07:25:19 +0000719 }
Benny Prijonoc71ad432007-05-04 07:25:19 +0000720
721 if (reschedule)
722 Run();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000723}
724
Benny Prijono70c5ba02007-12-31 11:27:35 +0000725#if 0
726// IP networking related testing
727static pj_status_t test_addr(void)
728{
729 int af;
730 unsigned i, count;
731 pj_addrinfo ai[8];
732 pj_sockaddr ifs[8];
733 const pj_str_t *hostname;
734 pj_hostent he;
735 pj_status_t status;
736
737 pj_log_set_log_func(&log_writer);
738
739 status = pj_init();
740 if (status != PJ_SUCCESS) {
741 pjsua_perror(THIS_FILE, "pj_init() error", status);
742 return status;
743 }
744
745 af = pj_AF_INET();
746
Benny Prijono684c0ad2008-01-03 18:50:27 +0000747#if 0
748 pj_in_addr in_addr;
749 pj_str_t aa = pj_str("1.1.1.1");
750 in_addr = pj_inet_addr(&aa);
751 char *the_addr = pj_inet_ntoa(in_addr);
752 PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
753
754 aa = pj_str("192.168.0.15");
755 in_addr = pj_inet_addr(&aa);
756 the_addr = pj_inet_ntoa(in_addr);
757 PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
758
759 aa = pj_str("2.2.2.2");
760 in_addr = pj_inet_addr(&aa);
761 the_addr = pj_inet_ntoa(in_addr);
762 PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
763
764 return -1;
765#endif
766
Benny Prijono70c5ba02007-12-31 11:27:35 +0000767 // Hostname
768 hostname = pj_gethostname();
769 if (hostname == NULL) {
770 status = PJ_ERESOLVE;
771 pjsua_perror(THIS_FILE, "pj_gethostname() error", status);
772 goto on_return;
773 }
774
775 PJ_LOG(3,(THIS_FILE, "Hostname: %.*s", hostname->slen, hostname->ptr));
776
777 // Gethostbyname
778 status = pj_gethostbyname(hostname, &he);
779 if (status != PJ_SUCCESS) {
780 pjsua_perror(THIS_FILE, "pj_gethostbyname() error", status);
781 } else {
782 PJ_LOG(3,(THIS_FILE, "gethostbyname: %s",
783 pj_inet_ntoa(*(pj_in_addr*)he.h_addr)));
784 }
785
786 // Getaddrinfo
787 count = PJ_ARRAY_SIZE(ai);
788 status = pj_getaddrinfo(af, hostname, &count, ai);
789 if (status != PJ_SUCCESS) {
790 pjsua_perror(THIS_FILE, "pj_getaddrinfo() error", status);
791 } else {
792 for (i=0; i<count; ++i) {
793 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
794 PJ_LOG(3,(THIS_FILE, "Addrinfo: %s",
795 pj_sockaddr_print(&ai[i].ai_addr, ipaddr, sizeof(ipaddr), 2)));
796 }
797 }
798
799 // Enum interface
800 count = PJ_ARRAY_SIZE(ifs);
801 status = pj_enum_ip_interface(af, &count, ifs);
802 if (status != PJ_SUCCESS) {
803 pjsua_perror(THIS_FILE, "pj_enum_ip_interface() error", status);
804 } else {
805 for (i=0; i<count; ++i) {
806 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
807 PJ_LOG(3,(THIS_FILE, "Interface: %s",
808 pj_sockaddr_print(&ifs[i], ipaddr, sizeof(ipaddr), 2)));
809 }
810 }
811
812 // Get default iinterface
813 status = pj_getdefaultipinterface(af, &ifs[0]);
814 if (status != PJ_SUCCESS) {
815 pjsua_perror(THIS_FILE, "pj_getdefaultipinterface() error", status);
816 } else {
817 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
818 PJ_LOG(3,(THIS_FILE, "Default IP: %s",
819 pj_sockaddr_print(&ifs[0], ipaddr, sizeof(ipaddr), 2)));
820 }
821
822 // Get default IP address
823 status = pj_gethostip(af, &ifs[0]);
824 if (status != PJ_SUCCESS) {
825 pjsua_perror(THIS_FILE, "pj_gethostip() error", status);
826 } else {
827 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
828 PJ_LOG(3,(THIS_FILE, "Host IP: %s",
829 pj_sockaddr_print(&ifs[0], ipaddr, sizeof(ipaddr), 2)));
830 }
831
832 status = -1;
833
834on_return:
835 pj_shutdown();
836 return status;
837}
838#endif
839
840
Benny Prijono6b3ccdf2008-01-14 11:54:21 +0000841#include <es_sock.h>
Benny Prijono897f9f82007-05-03 19:56:21 +0000842
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000843#if 0
844// Force network connection to use the first IAP,
845// this is useful for debugging on emulator without GUI.
846// Include commdb.lib & apengine.lib in symbian_ua.mmp file
847// if this is enabled.
848
849#include <apdatahandler.h>
850
851inline void ForceUseFirstIAP()
852{
853 TUint32 rank = 1;
854 TUint32 bearers;
855 TUint32 prompt;
856 TUint32 iap;
857
858 CCommsDatabase* commDb = CCommsDatabase::NewL(EDatabaseTypeIAP);
859 CleanupStack::PushL(commDb);
860
861 CApDataHandler* apDataHandler = CApDataHandler::NewLC(*commDb);
862
863 TCommDbConnectionDirection direction = ECommDbConnectionDirectionOutgoing;
864 apDataHandler->GetPreferredIfDbIapTypeL(rank, direction, bearers, prompt, iap);
865 prompt = ECommDbDialogPrefDoNotPrompt;
866 apDataHandler->SetPreferredIfDbIapTypeL(rank, direction, bearers, (TCommDbDialogPref)prompt, iap, ETrue);
867 CleanupStack::PopAndDestroy(2); // apDataHandler, commDb
868}
869
870static void SelectIAP()
871{
872 ForceUseFirstIAP();
873}
874
875#else
876
877static void SelectIAP()
878{
879}
880
881#endif
882
883
Nanang Izzuddin90b83202009-03-02 15:48:45 +0000884// Class CConnMon to monitor network connection (RConnection). Whenever
885// the connection is down, it will notify PJLIB and restart PJSUA-LIB.
886class CConnMon : public CActive {
887public:
888 static CConnMon* NewL(RConnection &conn, RSocketServ &sserver) {
889 CConnMon *self = new (ELeave) CConnMon(conn, sserver);
890 CleanupStack::PushL(self);
891 self->ConstructL();
892 CleanupStack::Pop(self);
893 return self;
894 }
895
896 void Start() {
897 conn_.ProgressNotification(nif_progress_, iStatus);
898 SetActive();
899 }
900
901 void Stop() {
902 Cancel();
903 }
904
905 ~CConnMon() { Stop(); }
906
907private:
908 CConnMon(RConnection &conn, RSocketServ &sserver) :
909 CActive(EPriorityHigh),
910 conn_(conn),
911 sserver_(sserver)
912 {
913 CActiveScheduler::Add(this);
914 }
915
916 void ConstructL() {}
917
918 void DoCancel() {
919 conn_.CancelProgressNotification();
920 }
921
922 void RunL() {
923 int stage = nif_progress_().iStage;
924
925 if (stage == KLinkLayerClosed) {
926 pj_status_t status;
927 TInt err;
928
929 // Tell pjlib that connection is down.
930 pj_symbianos_set_connection_status(PJ_FALSE);
931
932 PJ_LOG(3, (THIS_FILE, "RConnection closed, restarting PJSUA.."));
933
934 // Destroy pjsua
935 pjsua_destroy();
936 PJ_LOG(3, (THIS_FILE, "PJSUA destroyed."));
937
938 // Reopen the connection
939 err = conn_.Open(sserver_);
940 if (err == KErrNone)
941 err = conn_.Start();
942 if (err != KErrNone) {
943 CActiveScheduler::Stop();
944 return;
945 }
946
947 // Reinit Symbian OS param before pj_init()
948 pj_symbianos_params sym_params;
949 pj_bzero(&sym_params, sizeof(sym_params));
950 sym_params.rsocketserv = &sserver_;
951 sym_params.rconnection = &conn_;
952 pj_symbianos_set_params(&sym_params);
953
954 // Reinit pjsua
955 status = app_startup();
956 if (status != PJ_SUCCESS) {
957 pjsua_perror(THIS_FILE, "app_startup() error", status);
958 CActiveScheduler::Stop();
959 return;
960 }
961
962 PJ_LOG(3, (THIS_FILE, "PJSUA restarted."));
Benny Prijono9920dc32009-03-12 18:11:37 +0000963 PrintMainMenu();
Nanang Izzuddin90b83202009-03-02 15:48:45 +0000964 }
965
966 Start();
967 }
968
969 RConnection& conn_;
970 RSocketServ& sserver_;
971 TNifProgressBuf nif_progress_;
972};
973
Benny Prijonoba5926a2007-05-02 11:29:37 +0000974////////////////////////////////////////////////////////////////////////////
975int ua_main()
976{
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000977 RSocketServ aSocketServer;
978 RConnection aConn;
979 TInt err;
980 pj_symbianos_params sym_params;
Benny Prijonoc71ad432007-05-04 07:25:19 +0000981 pj_status_t status;
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000982
983 SelectIAP();
Benny Prijonoc71ad432007-05-04 07:25:19 +0000984
Benny Prijono70c5ba02007-12-31 11:27:35 +0000985 // Initialize RSocketServ
986 if ((err=aSocketServer.Connect()) != KErrNone)
987 return PJ_STATUS_FROM_OS(err);
988
989 // Open up a connection
990 if ((err=aConn.Open(aSocketServer)) != KErrNone) {
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000991 aSocketServer.Close();
992 return PJ_STATUS_FROM_OS(err);
Benny Prijono70c5ba02007-12-31 11:27:35 +0000993 }
994
995 if ((err=aConn.Start()) != KErrNone) {
996 aSocketServer.Close();
997 return PJ_STATUS_FROM_OS(err);
998 }
999
1000 // Set Symbian OS parameters in pjlib.
1001 // This must be done before pj_init() is called.
1002 pj_bzero(&sym_params, sizeof(sym_params));
1003 sym_params.rsocketserv = &aSocketServer;
1004 sym_params.rconnection = &aConn;
1005 pj_symbianos_set_params(&sym_params);
1006
Benny Prijonoc71ad432007-05-04 07:25:19 +00001007 // Initialize pjsua
1008 status = app_startup();
Benny Prijono70c5ba02007-12-31 11:27:35 +00001009 //status = test_addr();
1010 if (status != PJ_SUCCESS) {
1011 aConn.Close();
1012 aSocketServer.Close();
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001013 return status;
Benny Prijono70c5ba02007-12-31 11:27:35 +00001014 }
Benny Prijono897f9f82007-05-03 19:56:21 +00001015
Nanang Izzuddin90b83202009-03-02 15:48:45 +00001016
Benny Prijonoc71ad432007-05-04 07:25:19 +00001017 // Run the UI
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001018 ConsoleUI *con = new ConsoleUI(console);
Benny Prijonoc71ad432007-05-04 07:25:19 +00001019
1020 con->Run();
Nanang Izzuddin798bf452009-02-12 12:35:27 +00001021 PrintMainMenu();
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001022
Nanang Izzuddin90b83202009-03-02 15:48:45 +00001023 // Init & start connection monitor
1024 CConnMon *connmon = CConnMon::NewL(aConn, aSocketServer);
1025 connmon->Start();
1026
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001027 CActiveScheduler::Start();
Benny Prijonoc71ad432007-05-04 07:25:19 +00001028
Nanang Izzuddin90b83202009-03-02 15:48:45 +00001029 delete connmon;
Benny Prijonoc71ad432007-05-04 07:25:19 +00001030 delete con;
Benny Prijono684c0ad2008-01-03 18:50:27 +00001031
1032 // Dump memory statistics
1033 PJ_LOG(3,(THIS_FILE, "Max heap usage: %u.%03uMB",
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001034 pjsua_var.cp.peak_used_size / 1000000,
1035 (pjsua_var.cp.peak_used_size % 1000000)/1000));
Benny Prijonoc71ad432007-05-04 07:25:19 +00001036
Benny Prijono684c0ad2008-01-03 18:50:27 +00001037 // check max stack usage
1038#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
1039 pj_thread_t* this_thread = pj_thread_this();
1040 if (!this_thread)
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001041 return status;
Benny Prijono684c0ad2008-01-03 18:50:27 +00001042
1043 const char* max_stack_file;
1044 int max_stack_line;
1045 status = pj_thread_get_stack_info(this_thread, &max_stack_file, &max_stack_line);
1046
1047 PJ_LOG(3,(THIS_FILE, "Max stack usage: %u at %s:%d",
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001048 pj_thread_get_stack_max_usage(this_thread),
1049 max_stack_file, max_stack_line));
Benny Prijono684c0ad2008-01-03 18:50:27 +00001050#endif
1051
Benny Prijonoc71ad432007-05-04 07:25:19 +00001052 // Shutdown pjsua
1053 pjsua_destroy();
1054
Benny Prijono70c5ba02007-12-31 11:27:35 +00001055 // Close connection and socket server
1056 aConn.Close();
Nanang Izzuddin82f7a412008-12-17 11:36:22 +00001057 aSocketServer.Close();
Nanang Izzuddina940b362009-02-23 13:53:30 +00001058
Benny Prijono797e3382007-12-01 09:10:07 +00001059 return status;
Benny Prijonoba5926a2007-05-02 11:29:37 +00001060}
1061