blob: 79e91aeb5c7e2b4765283e1b63a03ad3701d2799 [file] [log] [blame]
Benny Prijonoba5926a2007-05-02 11:29:37 +00001/* $Id$ */
2/*
3 * Copyright (C) 2003-2007 Benny Prijono <benny@prijono.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
Benny Prijonoba5926a2007-05-02 11:29:37 +000019#include <pjsua-lib/pjsua.h>
Benny Prijono72a81aa2007-05-02 23:06:11 +000020#include <pjsua-lib/pjsua_internal.h>
Benny Prijonoba5926a2007-05-02 11:29:37 +000021#include "ua.h"
22
23#define THIS_FILE "symbian_ua.cpp"
Benny Prijono684c0ad2008-01-03 18:50:27 +000024#define LOG_LEVEL 3
Benny Prijonoba5926a2007-05-02 11:29:37 +000025
Benny Prijono72a81aa2007-05-02 23:06:11 +000026//
Benny Prijonoc71ad432007-05-04 07:25:19 +000027// Basic config.
28//
29#define SIP_PORT 5060
30
31
32//
Benny Prijonob2c96822007-05-03 13:31:21 +000033// Destination URI (to make call, or to subscribe presence)
34//
Benny Prijono0e2c6462008-02-14 13:39:24 +000035#define SIP_DST_URI "sip:100@pjsip.lab"
Benny Prijonob2c96822007-05-03 13:31:21 +000036
37//
Benny Prijono72a81aa2007-05-02 23:06:11 +000038// Account
39//
Nanang Izzuddin82f7a412008-12-17 11:36:22 +000040#define HAS_SIP_ACCOUNT 0 // 1 to enable registration
Benny Prijono0e2c6462008-02-14 13:39:24 +000041#define SIP_DOMAIN "pjsip.lab"
42#define SIP_USER "400"
43#define SIP_PASSWD "400"
Benny Prijonoba5926a2007-05-02 11:29:37 +000044
Benny Prijono72a81aa2007-05-02 23:06:11 +000045//
46// Outbound proxy for all accounts
47//
48#define SIP_PROXY NULL
Benny Prijono4b55e0a2008-12-18 13:22:52 +000049//#define SIP_PROXY "<sip:192.168.0.8;lr>"
Benny Prijono897f9f82007-05-03 19:56:21 +000050
51
52//
53// Configure nameserver if DNS SRV is to be used with both SIP
54// or STUN (for STUN see other settings below)
55//
Nanang Izzuddin82f7a412008-12-17 11:36:22 +000056#define NAMESERVER NULL
57//#define NAMESERVER "192.168.0.2"
Benny Prijono897f9f82007-05-03 19:56:21 +000058
59//
60// STUN server
Benny Prijono684c0ad2008-01-03 18:50:27 +000061#if 0
Benny Prijono897f9f82007-05-03 19:56:21 +000062 // Use this to have the STUN server resolved normally
63# define STUN_DOMAIN NULL
Benny Prijono4b55e0a2008-12-18 13:22:52 +000064# define STUN_SERVER "stun.pjsip.org"
Benny Prijono897f9f82007-05-03 19:56:21 +000065#elif 0
66 // Use this to have the STUN server resolved with DNS SRV
Benny Prijono4b55e0a2008-12-18 13:22:52 +000067# define STUN_DOMAIN "pjsip.org"
Benny Prijono897f9f82007-05-03 19:56:21 +000068# define STUN_SERVER NULL
69#else
70 // Use this to disable STUN
71# define STUN_DOMAIN NULL
72# define STUN_SERVER NULL
73#endif
74
75//
76// Use ICE?
77//
Benny Prijono70c5ba02007-12-31 11:27:35 +000078#define USE_ICE 1
Benny Prijono72a81aa2007-05-02 23:06:11 +000079
Nanang Izzuddin6a6392f2008-06-02 18:30:15 +000080//
81// Use SRTP?
82//
83#define USE_SRTP PJSUA_DEFAULT_USE_SRTP
Benny Prijono72a81aa2007-05-02 23:06:11 +000084
Benny Prijonob2c96822007-05-03 13:31:21 +000085//
86// Globals
87//
88static pjsua_acc_id g_acc_id = PJSUA_INVALID_ID;
89static pjsua_call_id g_call_id = PJSUA_INVALID_ID;
90static pjsua_buddy_id g_buddy_id = PJSUA_INVALID_ID;
Benny Prijono72a81aa2007-05-02 23:06:11 +000091
Benny Prijonoba5926a2007-05-02 11:29:37 +000092
93/* Callback called by the library upon receiving incoming call */
94static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
95 pjsip_rx_data *rdata)
96{
97 pjsua_call_info ci;
98
99 PJ_UNUSED_ARG(acc_id);
100 PJ_UNUSED_ARG(rdata);
101
Benny Prijonob2c96822007-05-03 13:31:21 +0000102 if (g_call_id != PJSUA_INVALID_ID) {
103 pjsua_call_answer(call_id, PJSIP_SC_BUSY_HERE, NULL, NULL);
104 return;
105 }
106
Benny Prijonoba5926a2007-05-02 11:29:37 +0000107 pjsua_call_get_info(call_id, &ci);
108
109 PJ_LOG(3,(THIS_FILE, "Incoming call from %.*s!!",
110 (int)ci.remote_info.slen,
111 ci.remote_info.ptr));
112
Benny Prijonob2c96822007-05-03 13:31:21 +0000113 g_call_id = call_id;
114
Benny Prijono897f9f82007-05-03 19:56:21 +0000115 /* Automatically answer incoming calls with 180/Ringing */
116 pjsua_call_answer(call_id, 180, NULL, NULL);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000117}
118
119/* Callback called by the library when call's state has changed */
120static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
121{
122 pjsua_call_info ci;
123
124 PJ_UNUSED_ARG(e);
125
126 pjsua_call_get_info(call_id, &ci);
Benny Prijonob2c96822007-05-03 13:31:21 +0000127
128 if (ci.state == PJSIP_INV_STATE_DISCONNECTED) {
129 if (call_id == g_call_id)
130 g_call_id = PJSUA_INVALID_ID;
Benny Prijono897f9f82007-05-03 19:56:21 +0000131 } else if (ci.state != PJSIP_INV_STATE_INCOMING) {
Benny Prijonob2c96822007-05-03 13:31:21 +0000132 if (g_call_id == PJSUA_INVALID_ID)
133 g_call_id = call_id;
134 }
135
Benny Prijonoba5926a2007-05-02 11:29:37 +0000136 PJ_LOG(3,(THIS_FILE, "Call %d state=%.*s", call_id,
137 (int)ci.state_text.slen,
138 ci.state_text.ptr));
139}
140
141/* Callback called by the library when call's media state has changed */
142static void on_call_media_state(pjsua_call_id call_id)
143{
144 pjsua_call_info ci;
145
146 pjsua_call_get_info(call_id, &ci);
147
148 if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
149 // When media is active, connect call to sound device.
150 pjsua_conf_connect(ci.conf_slot, 0);
151 pjsua_conf_connect(0, ci.conf_slot);
152 }
153}
154
155
Benny Prijonob2c96822007-05-03 13:31:21 +0000156/* Handler on buddy state changed. */
157static void on_buddy_state(pjsua_buddy_id buddy_id)
158{
159 pjsua_buddy_info info;
160 pjsua_buddy_get_info(buddy_id, &info);
161
162 PJ_LOG(3,(THIS_FILE, "%.*s status is %.*s",
163 (int)info.uri.slen,
164 info.uri.ptr,
165 (int)info.status_text.slen,
166 info.status_text.ptr));
167}
168
169
170/* Incoming IM message (i.e. MESSAGE request)! */
171static void on_pager(pjsua_call_id call_id, const pj_str_t *from,
172 const pj_str_t *to, const pj_str_t *contact,
173 const pj_str_t *mime_type, const pj_str_t *text)
174{
175 /* Note: call index may be -1 */
176 PJ_UNUSED_ARG(call_id);
177 PJ_UNUSED_ARG(to);
178 PJ_UNUSED_ARG(contact);
179 PJ_UNUSED_ARG(mime_type);
180
181 PJ_LOG(3,(THIS_FILE,"MESSAGE from %.*s: %.*s",
182 (int)from->slen, from->ptr,
183 (int)text->slen, text->ptr));
184}
185
186
187/* Received typing indication */
188static void on_typing(pjsua_call_id call_id, const pj_str_t *from,
189 const pj_str_t *to, const pj_str_t *contact,
190 pj_bool_t is_typing)
191{
192 PJ_UNUSED_ARG(call_id);
193 PJ_UNUSED_ARG(to);
194 PJ_UNUSED_ARG(contact);
195
196 PJ_LOG(3,(THIS_FILE, "IM indication: %.*s %s",
197 (int)from->slen, from->ptr,
198 (is_typing?"is typing..":"has stopped typing")));
199}
200
201
202/* Call transfer request status. */
203static void on_call_transfer_status(pjsua_call_id call_id,
204 int status_code,
205 const pj_str_t *status_text,
206 pj_bool_t final,
207 pj_bool_t *p_cont)
208{
209 PJ_LOG(3,(THIS_FILE, "Call %d: transfer status=%d (%.*s) %s",
210 call_id, status_code,
211 (int)status_text->slen, status_text->ptr,
212 (final ? "[final]" : "")));
213
214 if (status_code/100 == 2) {
215 PJ_LOG(3,(THIS_FILE,
216 "Call %d: call transfered successfully, disconnecting call",
217 call_id));
218 pjsua_call_hangup(call_id, PJSIP_SC_GONE, NULL, NULL);
219 *p_cont = PJ_FALSE;
220 }
221}
222
223
Benny Prijonoaecabfc2007-10-26 05:35:42 +0000224/* NAT detection result */
225static void on_nat_detect(const pj_stun_nat_detect_result *res)
226{
227 if (res->status != PJ_SUCCESS) {
228 pjsua_perror(THIS_FILE, "NAT detection failed", res->status);
229 } else {
230 PJ_LOG(3, (THIS_FILE, "NAT detected as %s", res->nat_type_name));
231 }
232}
233
Benny Prijonob2c96822007-05-03 13:31:21 +0000234/* Notification that call is being replaced. */
235static void on_call_replaced(pjsua_call_id old_call_id,
236 pjsua_call_id new_call_id)
237{
238 pjsua_call_info old_ci, new_ci;
239
240 pjsua_call_get_info(old_call_id, &old_ci);
241 pjsua_call_get_info(new_call_id, &new_ci);
242
243 PJ_LOG(3,(THIS_FILE, "Call %d with %.*s is being replaced by "
244 "call %d with %.*s",
245 old_call_id,
246 (int)old_ci.remote_info.slen, old_ci.remote_info.ptr,
247 new_call_id,
248 (int)new_ci.remote_info.slen, new_ci.remote_info.ptr));
249}
250
251
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000252//#include<e32debug.h>
253
Benny Prijonoba5926a2007-05-02 11:29:37 +0000254/* Logging callback */
Benny Prijono797e3382007-12-01 09:10:07 +0000255static void log_writer(int level, const char *buf, int len)
Benny Prijonoba5926a2007-05-02 11:29:37 +0000256{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000257 static wchar_t buf16[PJ_LOG_MAX_SIZE];
Benny Prijonoba5926a2007-05-02 11:29:37 +0000258
259 PJ_UNUSED_ARG(level);
260
261 pj_ansi_to_unicode(buf, len, buf16, PJ_ARRAY_SIZE(buf16));
262
263 TPtrC16 aBuf((const TUint16*)buf16, (TInt)len);
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000264 //RDebug::Print(aBuf);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000265 console->Write(aBuf);
Benny Prijono797e3382007-12-01 09:10:07 +0000266
Benny Prijonoba5926a2007-05-02 11:29:37 +0000267}
268
269/*
270 * app_startup()
271 *
272 * url may contain URL to call.
273 */
Benny Prijonob2c96822007-05-03 13:31:21 +0000274static pj_status_t app_startup()
Benny Prijonoba5926a2007-05-02 11:29:37 +0000275{
Benny Prijonoba5926a2007-05-02 11:29:37 +0000276 pj_status_t status;
277
278 /* Redirect log before pjsua_init() */
Benny Prijono70c5ba02007-12-31 11:27:35 +0000279 pj_log_set_log_func(&log_writer);
280
281 /* Set log level */
282 pj_log_set_level(LOG_LEVEL);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000283
284 /* Create pjsua first! */
285 status = pjsua_create();
286 if (status != PJ_SUCCESS) {
287 pjsua_perror(THIS_FILE, "pjsua_create() error", status);
288 return status;
289 }
290
Benny Prijonoba5926a2007-05-02 11:29:37 +0000291 /* Init pjsua */
Benny Prijonoc71ad432007-05-04 07:25:19 +0000292 pjsua_config cfg;
293 pjsua_logging_config log_cfg;
294 pjsua_media_config med_cfg;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000295
Benny Prijonoc71ad432007-05-04 07:25:19 +0000296 pjsua_config_default(&cfg);
297 cfg.max_calls = 2;
298 cfg.thread_cnt = 0; // Disable threading on Symbian
Nanang Izzuddin6a6392f2008-06-02 18:30:15 +0000299 cfg.use_srtp = USE_SRTP;
300 cfg.srtp_secure_signaling = 0;
301
Benny Prijonoc71ad432007-05-04 07:25:19 +0000302 cfg.cb.on_incoming_call = &on_incoming_call;
303 cfg.cb.on_call_media_state = &on_call_media_state;
304 cfg.cb.on_call_state = &on_call_state;
305 cfg.cb.on_buddy_state = &on_buddy_state;
306 cfg.cb.on_pager = &on_pager;
307 cfg.cb.on_typing = &on_typing;
308 cfg.cb.on_call_transfer_status = &on_call_transfer_status;
309 cfg.cb.on_call_replaced = &on_call_replaced;
Benny Prijonoaecabfc2007-10-26 05:35:42 +0000310 cfg.cb.on_nat_detect = &on_nat_detect;
311
Benny Prijonoc71ad432007-05-04 07:25:19 +0000312 if (SIP_PROXY) {
313 cfg.outbound_proxy_cnt = 1;
314 cfg.outbound_proxy[0] = pj_str(SIP_PROXY);
315 }
316
317 if (NAMESERVER) {
318 cfg.nameserver_count = 1;
319 cfg.nameserver[0] = pj_str(NAMESERVER);
320 }
321
322 if (NAMESERVER && STUN_DOMAIN) {
323 cfg.stun_domain = pj_str(STUN_DOMAIN);
324 } else if (STUN_SERVER) {
325 cfg.stun_host = pj_str(STUN_SERVER);
326 }
327
328
329 pjsua_logging_config_default(&log_cfg);
Benny Prijono4b55e0a2008-12-18 13:22:52 +0000330 log_cfg.level = LOG_LEVEL;
331 log_cfg.console_level = LOG_LEVEL;
Benny Prijonoc71ad432007-05-04 07:25:19 +0000332 log_cfg.cb = &log_writer;
Nanang Izzuddincb2789a2008-07-24 15:30:44 +0000333 //log_cfg.log_filename = pj_str("C:\\data\\symbian_ua.log");
Benny Prijonoba5926a2007-05-02 11:29:37 +0000334
Benny Prijonoc71ad432007-05-04 07:25:19 +0000335 pjsua_media_config_default(&med_cfg);
336 med_cfg.thread_cnt = 0; // Disable threading on Symbian
337 med_cfg.has_ioqueue = PJ_FALSE;
338 med_cfg.clock_rate = 8000;
Nanang Izzuddincb2789a2008-07-24 15:30:44 +0000339#if defined(PJMEDIA_SYM_SND_USE_APS) && (PJMEDIA_SYM_SND_USE_APS==1)
340 med_cfg.audio_frame_ptime = 20;
341#else
Benny Prijono5df8bb62007-12-28 18:55:02 +0000342 med_cfg.audio_frame_ptime = 40;
Nanang Izzuddincb2789a2008-07-24 15:30:44 +0000343#endif
Benny Prijonoc71ad432007-05-04 07:25:19 +0000344 med_cfg.ec_tail_len = 0;
345 med_cfg.enable_ice = USE_ICE;
Nanang Izzuddin68559c32008-06-13 17:01:46 +0000346 med_cfg.snd_auto_close_time = 5; // wait for 5 seconds idle before sound dev get auto-closed
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);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000443
Benny Prijonoc71ad432007-05-04 07:25:19 +0000444 // Run console UI
445 void Run();
446
447 // Stop
448 void Stop();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000449
450protected:
Benny Prijonoc71ad432007-05-04 07:25:19 +0000451 // Cancel asynchronous read.
452 void DoCancel();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000453
Benny Prijonoc71ad432007-05-04 07:25:19 +0000454 // Implementation: called when read has completed.
455 void RunL();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000456
457private:
Benny Prijonoc71ad432007-05-04 07:25:19 +0000458 CConsoleBase *con_;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000459};
460
461
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000462ConsoleUI::ConsoleUI(CConsoleBase *con)
463: CActive(EPriorityStandard), con_(con)
Benny Prijonoba5926a2007-05-02 11:29:37 +0000464{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000465 CActiveScheduler::Add(this);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000466}
467
468// Run console UI
469void ConsoleUI::Run()
470{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000471 con_->Read(iStatus);
472 SetActive();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000473}
474
475// Stop console UI
476void ConsoleUI::Stop()
477{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000478 DoCancel();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000479}
480
481// Cancel asynchronous read.
482void ConsoleUI::DoCancel()
483{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000484 con_->ReadCancel();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000485}
486
Benny Prijono72a81aa2007-05-02 23:06:11 +0000487static void PrintMenu()
488{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000489 PJ_LOG(3, (THIS_FILE, "\n\n"
490 "Menu:\n"
491 " d Dump states\n"
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000492 " D Dump states detail\n"
Benny Prijonoc71ad432007-05-04 07:25:19 +0000493 " P Dump pool factory\n"
Benny Prijono5df8bb62007-12-28 18:55:02 +0000494 " l Start loopback audio device\n"
495 " L Stop loopback audio device\n"
Benny Prijono70c5ba02007-12-31 11:27:35 +0000496 " m Call " SIP_DST_URI "\n"
497 " a Answer call\n"
498 " g Hangup all calls\n"
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000499 " s Subscribe " SIP_DST_URI "\n"
Benny Prijonoc71ad432007-05-04 07:25:19 +0000500 " S Unsubscribe presence\n"
501 " o Set account online\n"
502 " O Set account offline\n"
Benny Prijono70c5ba02007-12-31 11:27:35 +0000503 " w Quit\n"));
Benny Prijono72a81aa2007-05-02 23:06:11 +0000504}
505
Benny Prijonoba5926a2007-05-02 11:29:37 +0000506// Implementation: called when read has completed.
507void ConsoleUI::RunL()
508{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000509 TKeyCode kc = con_->KeyCode();
510 pj_bool_t reschedule = PJ_TRUE;
511
512 switch (kc) {
Benny Prijono70c5ba02007-12-31 11:27:35 +0000513 case 'w':
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000514 CActiveScheduler::Stop();
Benny Prijonoc71ad432007-05-04 07:25:19 +0000515 reschedule = PJ_FALSE;
516 break;
517 case 'D':
518 case 'd':
519 pjsua_dump(kc == 'D');
520 break;
521 case 'p':
522 case 'P':
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000523 pj_pool_factory_dump(pjsua_get_pool_factory(), PJ_TRUE);
Benny Prijonoc71ad432007-05-04 07:25:19 +0000524 break;
Benny Prijono5df8bb62007-12-28 18:55:02 +0000525 case 'l':
526 pjsua_conf_connect(0, 0);
527 break;
528 case 'L':
529 pjsua_conf_disconnect(0, 0);
530 break;
Benny Prijono70c5ba02007-12-31 11:27:35 +0000531 case 'm':
Benny Prijonoc71ad432007-05-04 07:25:19 +0000532 if (g_call_id != PJSUA_INVALID_ID) {
533 PJ_LOG(3,(THIS_FILE, "Another call is active"));
534 break;
535 }
536
537 if (pjsua_verify_sip_url(SIP_DST_URI) == PJ_SUCCESS) {
538 pj_str_t dst = pj_str(SIP_DST_URI);
539 pjsua_call_make_call(g_acc_id, &dst, 0, NULL,
540 NULL, &g_call_id);
541 } else {
542 PJ_LOG(3,(THIS_FILE, "Invalid SIP URI"));
543 }
544 break;
Benny Prijono70c5ba02007-12-31 11:27:35 +0000545 case 'a':
Benny Prijonoc71ad432007-05-04 07:25:19 +0000546 if (g_call_id != PJSUA_INVALID_ID)
547 pjsua_call_answer(g_call_id, 200, NULL, NULL);
548 break;
Benny Prijono70c5ba02007-12-31 11:27:35 +0000549 case 'g':
Benny Prijonoc71ad432007-05-04 07:25:19 +0000550 pjsua_call_hangup_all();
551 break;
552 case 's':
553 case 'S':
554 if (g_buddy_id != PJSUA_INVALID_ID)
555 pjsua_buddy_subscribe_pres(g_buddy_id, kc=='s');
556 break;
557 case 'o':
558 case 'O':
559 pjsua_acc_set_online_status(g_acc_id, kc=='o');
560 break;
561 default:
562 PJ_LOG(3,(THIS_FILE, "Keycode '%c' (%d) is pressed",
563 kc, kc));
564 break;
565 }
Benny Prijono72a81aa2007-05-02 23:06:11 +0000566
Benny Prijonoc71ad432007-05-04 07:25:19 +0000567 PrintMenu();
568
569 if (reschedule)
570 Run();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000571}
572
Benny Prijono70c5ba02007-12-31 11:27:35 +0000573#if 0
574// IP networking related testing
575static pj_status_t test_addr(void)
576{
577 int af;
578 unsigned i, count;
579 pj_addrinfo ai[8];
580 pj_sockaddr ifs[8];
581 const pj_str_t *hostname;
582 pj_hostent he;
583 pj_status_t status;
584
585 pj_log_set_log_func(&log_writer);
586
587 status = pj_init();
588 if (status != PJ_SUCCESS) {
589 pjsua_perror(THIS_FILE, "pj_init() error", status);
590 return status;
591 }
592
593 af = pj_AF_INET();
594
Benny Prijono684c0ad2008-01-03 18:50:27 +0000595#if 0
596 pj_in_addr in_addr;
597 pj_str_t aa = pj_str("1.1.1.1");
598 in_addr = pj_inet_addr(&aa);
599 char *the_addr = pj_inet_ntoa(in_addr);
600 PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
601
602 aa = pj_str("192.168.0.15");
603 in_addr = pj_inet_addr(&aa);
604 the_addr = pj_inet_ntoa(in_addr);
605 PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
606
607 aa = pj_str("2.2.2.2");
608 in_addr = pj_inet_addr(&aa);
609 the_addr = pj_inet_ntoa(in_addr);
610 PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
611
612 return -1;
613#endif
614
Benny Prijono70c5ba02007-12-31 11:27:35 +0000615 // Hostname
616 hostname = pj_gethostname();
617 if (hostname == NULL) {
618 status = PJ_ERESOLVE;
619 pjsua_perror(THIS_FILE, "pj_gethostname() error", status);
620 goto on_return;
621 }
622
623 PJ_LOG(3,(THIS_FILE, "Hostname: %.*s", hostname->slen, hostname->ptr));
624
625 // Gethostbyname
626 status = pj_gethostbyname(hostname, &he);
627 if (status != PJ_SUCCESS) {
628 pjsua_perror(THIS_FILE, "pj_gethostbyname() error", status);
629 } else {
630 PJ_LOG(3,(THIS_FILE, "gethostbyname: %s",
631 pj_inet_ntoa(*(pj_in_addr*)he.h_addr)));
632 }
633
634 // Getaddrinfo
635 count = PJ_ARRAY_SIZE(ai);
636 status = pj_getaddrinfo(af, hostname, &count, ai);
637 if (status != PJ_SUCCESS) {
638 pjsua_perror(THIS_FILE, "pj_getaddrinfo() error", status);
639 } else {
640 for (i=0; i<count; ++i) {
641 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
642 PJ_LOG(3,(THIS_FILE, "Addrinfo: %s",
643 pj_sockaddr_print(&ai[i].ai_addr, ipaddr, sizeof(ipaddr), 2)));
644 }
645 }
646
647 // Enum interface
648 count = PJ_ARRAY_SIZE(ifs);
649 status = pj_enum_ip_interface(af, &count, ifs);
650 if (status != PJ_SUCCESS) {
651 pjsua_perror(THIS_FILE, "pj_enum_ip_interface() error", status);
652 } else {
653 for (i=0; i<count; ++i) {
654 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
655 PJ_LOG(3,(THIS_FILE, "Interface: %s",
656 pj_sockaddr_print(&ifs[i], ipaddr, sizeof(ipaddr), 2)));
657 }
658 }
659
660 // Get default iinterface
661 status = pj_getdefaultipinterface(af, &ifs[0]);
662 if (status != PJ_SUCCESS) {
663 pjsua_perror(THIS_FILE, "pj_getdefaultipinterface() error", status);
664 } else {
665 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
666 PJ_LOG(3,(THIS_FILE, "Default IP: %s",
667 pj_sockaddr_print(&ifs[0], ipaddr, sizeof(ipaddr), 2)));
668 }
669
670 // Get default IP address
671 status = pj_gethostip(af, &ifs[0]);
672 if (status != PJ_SUCCESS) {
673 pjsua_perror(THIS_FILE, "pj_gethostip() error", status);
674 } else {
675 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
676 PJ_LOG(3,(THIS_FILE, "Host IP: %s",
677 pj_sockaddr_print(&ifs[0], ipaddr, sizeof(ipaddr), 2)));
678 }
679
680 status = -1;
681
682on_return:
683 pj_shutdown();
684 return status;
685}
686#endif
687
688
Benny Prijono6b3ccdf2008-01-14 11:54:21 +0000689#include <es_sock.h>
Benny Prijono897f9f82007-05-03 19:56:21 +0000690
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000691#if 0
692// Force network connection to use the first IAP,
693// this is useful for debugging on emulator without GUI.
694// Include commdb.lib & apengine.lib in symbian_ua.mmp file
695// if this is enabled.
696
697#include <apdatahandler.h>
698
699inline void ForceUseFirstIAP()
700{
701 TUint32 rank = 1;
702 TUint32 bearers;
703 TUint32 prompt;
704 TUint32 iap;
705
706 CCommsDatabase* commDb = CCommsDatabase::NewL(EDatabaseTypeIAP);
707 CleanupStack::PushL(commDb);
708
709 CApDataHandler* apDataHandler = CApDataHandler::NewLC(*commDb);
710
711 TCommDbConnectionDirection direction = ECommDbConnectionDirectionOutgoing;
712 apDataHandler->GetPreferredIfDbIapTypeL(rank, direction, bearers, prompt, iap);
713 prompt = ECommDbDialogPrefDoNotPrompt;
714 apDataHandler->SetPreferredIfDbIapTypeL(rank, direction, bearers, (TCommDbDialogPref)prompt, iap, ETrue);
715 CleanupStack::PopAndDestroy(2); // apDataHandler, commDb
716}
717
718static void SelectIAP()
719{
720 ForceUseFirstIAP();
721}
722
723#else
724
725static void SelectIAP()
726{
727}
728
729#endif
730
731
Benny Prijonoba5926a2007-05-02 11:29:37 +0000732////////////////////////////////////////////////////////////////////////////
733int ua_main()
734{
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000735 RSocketServ aSocketServer;
736 RConnection aConn;
737 TInt err;
738 pj_symbianos_params sym_params;
Benny Prijonoc71ad432007-05-04 07:25:19 +0000739 pj_status_t status;
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000740
741 SelectIAP();
Benny Prijonoc71ad432007-05-04 07:25:19 +0000742
Benny Prijono70c5ba02007-12-31 11:27:35 +0000743 // Initialize RSocketServ
744 if ((err=aSocketServer.Connect()) != KErrNone)
745 return PJ_STATUS_FROM_OS(err);
746
747 // Open up a connection
748 if ((err=aConn.Open(aSocketServer)) != KErrNone) {
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000749 aSocketServer.Close();
750 return PJ_STATUS_FROM_OS(err);
Benny Prijono70c5ba02007-12-31 11:27:35 +0000751 }
752
753 if ((err=aConn.Start()) != KErrNone) {
754 aSocketServer.Close();
755 return PJ_STATUS_FROM_OS(err);
756 }
757
758 // Set Symbian OS parameters in pjlib.
759 // This must be done before pj_init() is called.
760 pj_bzero(&sym_params, sizeof(sym_params));
761 sym_params.rsocketserv = &aSocketServer;
762 sym_params.rconnection = &aConn;
763 pj_symbianos_set_params(&sym_params);
764
Benny Prijonoc71ad432007-05-04 07:25:19 +0000765 // Initialize pjsua
766 status = app_startup();
Benny Prijono70c5ba02007-12-31 11:27:35 +0000767 //status = test_addr();
768 if (status != PJ_SUCCESS) {
769 aConn.Close();
770 aSocketServer.Close();
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000771 return status;
Benny Prijono70c5ba02007-12-31 11:27:35 +0000772 }
Benny Prijono897f9f82007-05-03 19:56:21 +0000773
Benny Prijonoc71ad432007-05-04 07:25:19 +0000774 // Run the UI
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000775 ConsoleUI *con = new ConsoleUI(console);
Benny Prijonoc71ad432007-05-04 07:25:19 +0000776
777 con->Run();
Benny Prijonoc71ad432007-05-04 07:25:19 +0000778 PrintMenu();
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000779
780 CActiveScheduler::Start();
Benny Prijonoc71ad432007-05-04 07:25:19 +0000781
782 delete con;
Benny Prijono684c0ad2008-01-03 18:50:27 +0000783
784 // Dump memory statistics
785 PJ_LOG(3,(THIS_FILE, "Max heap usage: %u.%03uMB",
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000786 pjsua_var.cp.peak_used_size / 1000000,
787 (pjsua_var.cp.peak_used_size % 1000000)/1000));
Benny Prijonoc71ad432007-05-04 07:25:19 +0000788
Benny Prijono684c0ad2008-01-03 18:50:27 +0000789 // check max stack usage
790#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
791 pj_thread_t* this_thread = pj_thread_this();
792 if (!this_thread)
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000793 return status;
Benny Prijono684c0ad2008-01-03 18:50:27 +0000794
795 const char* max_stack_file;
796 int max_stack_line;
797 status = pj_thread_get_stack_info(this_thread, &max_stack_file, &max_stack_line);
798
799 PJ_LOG(3,(THIS_FILE, "Max stack usage: %u at %s:%d",
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000800 pj_thread_get_stack_max_usage(this_thread),
801 max_stack_file, max_stack_line));
Benny Prijono684c0ad2008-01-03 18:50:27 +0000802#endif
803
Benny Prijonoc71ad432007-05-04 07:25:19 +0000804 // Shutdown pjsua
805 pjsua_destroy();
806
Benny Prijono70c5ba02007-12-31 11:27:35 +0000807 // Close connection and socket server
808 aConn.Close();
Nanang Izzuddin82f7a412008-12-17 11:36:22 +0000809 aSocketServer.Close();
Benny Prijono70c5ba02007-12-31 11:27:35 +0000810
Benny Prijono797e3382007-12-01 09:10:07 +0000811 return status;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000812}
813