blob: 34935a1839c378c3b4ee3ca9bd36c980f9ca1cc2 [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//
Benny Prijono0e2c6462008-02-14 13:39:24 +000040#define HAS_SIP_ACCOUNT 1 // 0 to disable registration
41#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 Prijono897f9f82007-05-03 19:56:21 +000049//#define SIP_PROXY "sip:192.168.0.8"
50
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//
Benny Prijono0e2c6462008-02-14 13:39:24 +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 Prijono684c0ad2008-01-03 18:50:27 +000064# define STUN_SERVER "stun.xten.com"
Benny Prijono897f9f82007-05-03 19:56:21 +000065#elif 0
66 // Use this to have the STUN server resolved with DNS SRV
67# define STUN_DOMAIN "iptel.org"
68# 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
Benny Prijonoba5926a2007-05-02 11:29:37 +0000252/* Logging callback */
Benny Prijono797e3382007-12-01 09:10:07 +0000253static void log_writer(int level, const char *buf, int len)
Benny Prijonoba5926a2007-05-02 11:29:37 +0000254{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000255 static wchar_t buf16[PJ_LOG_MAX_SIZE];
Benny Prijonoba5926a2007-05-02 11:29:37 +0000256
257 PJ_UNUSED_ARG(level);
258
259 pj_ansi_to_unicode(buf, len, buf16, PJ_ARRAY_SIZE(buf16));
260
261 TPtrC16 aBuf((const TUint16*)buf16, (TInt)len);
262 console->Write(aBuf);
Benny Prijono797e3382007-12-01 09:10:07 +0000263
Benny Prijonoba5926a2007-05-02 11:29:37 +0000264}
265
266/*
267 * app_startup()
268 *
269 * url may contain URL to call.
270 */
Benny Prijonob2c96822007-05-03 13:31:21 +0000271static pj_status_t app_startup()
Benny Prijonoba5926a2007-05-02 11:29:37 +0000272{
Benny Prijonoba5926a2007-05-02 11:29:37 +0000273 pj_status_t status;
274
275 /* Redirect log before pjsua_init() */
Benny Prijono70c5ba02007-12-31 11:27:35 +0000276 pj_log_set_log_func(&log_writer);
277
278 /* Set log level */
279 pj_log_set_level(LOG_LEVEL);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000280
281 /* Create pjsua first! */
282 status = pjsua_create();
283 if (status != PJ_SUCCESS) {
284 pjsua_perror(THIS_FILE, "pjsua_create() error", status);
285 return status;
286 }
287
Benny Prijonoba5926a2007-05-02 11:29:37 +0000288 /* Init pjsua */
Benny Prijonoc71ad432007-05-04 07:25:19 +0000289 pjsua_config cfg;
290 pjsua_logging_config log_cfg;
291 pjsua_media_config med_cfg;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000292
Benny Prijonoc71ad432007-05-04 07:25:19 +0000293 pjsua_config_default(&cfg);
294 cfg.max_calls = 2;
295 cfg.thread_cnt = 0; // Disable threading on Symbian
Nanang Izzuddin6a6392f2008-06-02 18:30:15 +0000296 cfg.use_srtp = USE_SRTP;
297 cfg.srtp_secure_signaling = 0;
298
Benny Prijonoc71ad432007-05-04 07:25:19 +0000299 cfg.cb.on_incoming_call = &on_incoming_call;
300 cfg.cb.on_call_media_state = &on_call_media_state;
301 cfg.cb.on_call_state = &on_call_state;
302 cfg.cb.on_buddy_state = &on_buddy_state;
303 cfg.cb.on_pager = &on_pager;
304 cfg.cb.on_typing = &on_typing;
305 cfg.cb.on_call_transfer_status = &on_call_transfer_status;
306 cfg.cb.on_call_replaced = &on_call_replaced;
Benny Prijonoaecabfc2007-10-26 05:35:42 +0000307 cfg.cb.on_nat_detect = &on_nat_detect;
308
Benny Prijonoc71ad432007-05-04 07:25:19 +0000309 if (SIP_PROXY) {
310 cfg.outbound_proxy_cnt = 1;
311 cfg.outbound_proxy[0] = pj_str(SIP_PROXY);
312 }
313
314 if (NAMESERVER) {
315 cfg.nameserver_count = 1;
316 cfg.nameserver[0] = pj_str(NAMESERVER);
317 }
318
319 if (NAMESERVER && STUN_DOMAIN) {
320 cfg.stun_domain = pj_str(STUN_DOMAIN);
321 } else if (STUN_SERVER) {
322 cfg.stun_host = pj_str(STUN_SERVER);
323 }
324
325
326 pjsua_logging_config_default(&log_cfg);
327 log_cfg.console_level = 4;
328 log_cfg.cb = &log_writer;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000329
Benny Prijonoc71ad432007-05-04 07:25:19 +0000330 pjsua_media_config_default(&med_cfg);
331 med_cfg.thread_cnt = 0; // Disable threading on Symbian
332 med_cfg.has_ioqueue = PJ_FALSE;
333 med_cfg.clock_rate = 8000;
Benny Prijono5df8bb62007-12-28 18:55:02 +0000334 med_cfg.audio_frame_ptime = 40;
Benny Prijonoc71ad432007-05-04 07:25:19 +0000335 med_cfg.ec_tail_len = 0;
336 med_cfg.enable_ice = USE_ICE;
337
338 status = pjsua_init(&cfg, &log_cfg, &med_cfg);
339 if (status != PJ_SUCCESS) {
340 pjsua_perror(THIS_FILE, "pjsua_init() error", status);
341 pjsua_destroy();
342 return status;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000343 }
Nanang Izzuddin829ac022008-05-27 00:24:26 +0000344
345 /* Adjust Speex priority and enable only the narrowband */
346 {
347 pj_str_t codec_id = pj_str("speex/8000");
348 pjmedia_codec_mgr_set_codec_priority(
349 pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
350 &codec_id, PJMEDIA_CODEC_PRIO_NORMAL+1);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000351
Nanang Izzuddin829ac022008-05-27 00:24:26 +0000352 codec_id = pj_str("speex/16000");
353 pjmedia_codec_mgr_set_codec_priority(
354 pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
355 &codec_id, PJMEDIA_CODEC_PRIO_DISABLED);
356
357 codec_id = pj_str("speex/32000");
358 pjmedia_codec_mgr_set_codec_priority(
359 pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
360 &codec_id, PJMEDIA_CODEC_PRIO_DISABLED);
361 }
362
Benny Prijonoba5926a2007-05-02 11:29:37 +0000363 /* Add UDP transport. */
Benny Prijonoc71ad432007-05-04 07:25:19 +0000364 pjsua_transport_config tcfg;
365 pjsua_transport_id tid;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000366
Benny Prijonoc71ad432007-05-04 07:25:19 +0000367 pjsua_transport_config_default(&tcfg);
368 tcfg.port = SIP_PORT;
369 status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &tcfg, &tid);
370 if (status != PJ_SUCCESS) {
371 pjsua_perror(THIS_FILE, "Error creating transport", status);
372 pjsua_destroy();
373 return status;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000374 }
375
Benny Prijonoc71ad432007-05-04 07:25:19 +0000376 /* Add account for the transport */
377 pjsua_acc_add_local(tid, PJ_TRUE, &g_acc_id);
378
379
Benny Prijonoba5926a2007-05-02 11:29:37 +0000380 /* Initialization is done, now start pjsua */
381 status = pjsua_start();
382 if (status != PJ_SUCCESS) {
383 pjsua_perror(THIS_FILE, "Error starting pjsua", status);
384 pjsua_destroy();
385 return status;
386 }
387
388 /* Register to SIP server by creating SIP account. */
Benny Prijono72a81aa2007-05-02 23:06:11 +0000389 if (HAS_SIP_ACCOUNT) {
Benny Prijonoba5926a2007-05-02 11:29:37 +0000390 pjsua_acc_config cfg;
391
392 pjsua_acc_config_default(&cfg);
393 cfg.id = pj_str("sip:" SIP_USER "@" SIP_DOMAIN);
394 cfg.reg_uri = pj_str("sip:" SIP_DOMAIN);
395 cfg.cred_count = 1;
Benny Prijono0e2c6462008-02-14 13:39:24 +0000396 cfg.cred_info[0].realm = pj_str("*");
Benny Prijonoba5926a2007-05-02 11:29:37 +0000397 cfg.cred_info[0].scheme = pj_str("digest");
398 cfg.cred_info[0].username = pj_str(SIP_USER);
399 cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
400 cfg.cred_info[0].data = pj_str(SIP_PASSWD);
401
Benny Prijonob2c96822007-05-03 13:31:21 +0000402 status = pjsua_acc_add(&cfg, PJ_TRUE, &g_acc_id);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000403 if (status != PJ_SUCCESS) {
404 pjsua_perror(THIS_FILE, "Error adding account", status);
405 pjsua_destroy();
406 return status;
407 }
408 }
409
Benny Prijonob2c96822007-05-03 13:31:21 +0000410 if (SIP_DST_URI) {
411 pjsua_buddy_config bcfg;
412
413 pjsua_buddy_config_default(&bcfg);
414 bcfg.uri = pj_str(SIP_DST_URI);
415 bcfg.subscribe = PJ_FALSE;
416
417 pjsua_buddy_add(&bcfg, &g_buddy_id);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000418 }
Benny Prijonoba5926a2007-05-02 11:29:37 +0000419 return PJ_SUCCESS;
420}
421
422
423////////////////////////////////////////////////////////////////////////////
Benny Prijonoc71ad432007-05-04 07:25:19 +0000424/*
425 * The interractive console UI
426 */
Benny Prijonoba5926a2007-05-02 11:29:37 +0000427#include <e32base.h>
428
429class ConsoleUI : public CActive
430{
431public:
Benny Prijonoc71ad432007-05-04 07:25:19 +0000432 ConsoleUI(CActiveSchedulerWait *asw, CConsoleBase *con);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000433
Benny Prijonoc71ad432007-05-04 07:25:19 +0000434 // Run console UI
435 void Run();
436
437 // Stop
438 void Stop();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000439
440protected:
Benny Prijonoc71ad432007-05-04 07:25:19 +0000441 // Cancel asynchronous read.
442 void DoCancel();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000443
Benny Prijonoc71ad432007-05-04 07:25:19 +0000444 // Implementation: called when read has completed.
445 void RunL();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000446
447private:
Benny Prijonoc71ad432007-05-04 07:25:19 +0000448 CActiveSchedulerWait *asw_;
449 CConsoleBase *con_;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000450};
451
452
453ConsoleUI::ConsoleUI(CActiveSchedulerWait *asw, CConsoleBase *con)
454: CActive(EPriorityStandard), asw_(asw), con_(con)
455{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000456 CActiveScheduler::Add(this);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000457}
458
459// Run console UI
460void ConsoleUI::Run()
461{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000462 con_->Read(iStatus);
463 SetActive();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000464}
465
466// Stop console UI
467void ConsoleUI::Stop()
468{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000469 DoCancel();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000470}
471
472// Cancel asynchronous read.
473void ConsoleUI::DoCancel()
474{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000475 con_->ReadCancel();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000476}
477
Benny Prijono72a81aa2007-05-02 23:06:11 +0000478static void PrintMenu()
479{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000480 PJ_LOG(3, (THIS_FILE, "\n\n"
481 "Menu:\n"
482 " d Dump states\n"
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000483 " D Dump states detail\n"
Benny Prijonoc71ad432007-05-04 07:25:19 +0000484 " P Dump pool factory\n"
Benny Prijono5df8bb62007-12-28 18:55:02 +0000485 " l Start loopback audio device\n"
486 " L Stop loopback audio device\n"
Benny Prijono70c5ba02007-12-31 11:27:35 +0000487 " m Call " SIP_DST_URI "\n"
488 " a Answer call\n"
489 " g Hangup all calls\n"
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000490 " s Subscribe " SIP_DST_URI "\n"
Benny Prijonoc71ad432007-05-04 07:25:19 +0000491 " S Unsubscribe presence\n"
492 " o Set account online\n"
493 " O Set account offline\n"
Benny Prijono70c5ba02007-12-31 11:27:35 +0000494 " w Quit\n"));
Benny Prijono72a81aa2007-05-02 23:06:11 +0000495}
496
Benny Prijonoba5926a2007-05-02 11:29:37 +0000497// Implementation: called when read has completed.
498void ConsoleUI::RunL()
499{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000500 TKeyCode kc = con_->KeyCode();
501 pj_bool_t reschedule = PJ_TRUE;
502
503 switch (kc) {
Benny Prijono70c5ba02007-12-31 11:27:35 +0000504 case 'w':
Benny Prijonoc71ad432007-05-04 07:25:19 +0000505 asw_->AsyncStop();
506 reschedule = PJ_FALSE;
507 break;
508 case 'D':
509 case 'd':
510 pjsua_dump(kc == 'D');
511 break;
512 case 'p':
513 case 'P':
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000514 pj_pool_factory_dump(pjsua_get_pool_factory(), PJ_TRUE);
Benny Prijonoc71ad432007-05-04 07:25:19 +0000515 break;
Benny Prijono5df8bb62007-12-28 18:55:02 +0000516 case 'l':
517 pjsua_conf_connect(0, 0);
518 break;
519 case 'L':
520 pjsua_conf_disconnect(0, 0);
521 break;
Benny Prijono70c5ba02007-12-31 11:27:35 +0000522 case 'm':
Benny Prijonoc71ad432007-05-04 07:25:19 +0000523 if (g_call_id != PJSUA_INVALID_ID) {
524 PJ_LOG(3,(THIS_FILE, "Another call is active"));
525 break;
526 }
527
528 if (pjsua_verify_sip_url(SIP_DST_URI) == PJ_SUCCESS) {
529 pj_str_t dst = pj_str(SIP_DST_URI);
530 pjsua_call_make_call(g_acc_id, &dst, 0, NULL,
531 NULL, &g_call_id);
532 } else {
533 PJ_LOG(3,(THIS_FILE, "Invalid SIP URI"));
534 }
535 break;
Benny Prijono70c5ba02007-12-31 11:27:35 +0000536 case 'a':
Benny Prijonoc71ad432007-05-04 07:25:19 +0000537 if (g_call_id != PJSUA_INVALID_ID)
538 pjsua_call_answer(g_call_id, 200, NULL, NULL);
539 break;
Benny Prijono70c5ba02007-12-31 11:27:35 +0000540 case 'g':
Benny Prijonoc71ad432007-05-04 07:25:19 +0000541 pjsua_call_hangup_all();
542 break;
543 case 's':
544 case 'S':
545 if (g_buddy_id != PJSUA_INVALID_ID)
546 pjsua_buddy_subscribe_pres(g_buddy_id, kc=='s');
547 break;
548 case 'o':
549 case 'O':
550 pjsua_acc_set_online_status(g_acc_id, kc=='o');
551 break;
552 default:
553 PJ_LOG(3,(THIS_FILE, "Keycode '%c' (%d) is pressed",
554 kc, kc));
555 break;
556 }
Benny Prijono72a81aa2007-05-02 23:06:11 +0000557
Benny Prijonoc71ad432007-05-04 07:25:19 +0000558 PrintMenu();
559
560 if (reschedule)
561 Run();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000562}
563
Benny Prijono70c5ba02007-12-31 11:27:35 +0000564#if 0
565// IP networking related testing
566static pj_status_t test_addr(void)
567{
568 int af;
569 unsigned i, count;
570 pj_addrinfo ai[8];
571 pj_sockaddr ifs[8];
572 const pj_str_t *hostname;
573 pj_hostent he;
574 pj_status_t status;
575
576 pj_log_set_log_func(&log_writer);
577
578 status = pj_init();
579 if (status != PJ_SUCCESS) {
580 pjsua_perror(THIS_FILE, "pj_init() error", status);
581 return status;
582 }
583
584 af = pj_AF_INET();
585
Benny Prijono684c0ad2008-01-03 18:50:27 +0000586#if 0
587 pj_in_addr in_addr;
588 pj_str_t aa = pj_str("1.1.1.1");
589 in_addr = pj_inet_addr(&aa);
590 char *the_addr = pj_inet_ntoa(in_addr);
591 PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
592
593 aa = pj_str("192.168.0.15");
594 in_addr = pj_inet_addr(&aa);
595 the_addr = pj_inet_ntoa(in_addr);
596 PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
597
598 aa = pj_str("2.2.2.2");
599 in_addr = pj_inet_addr(&aa);
600 the_addr = pj_inet_ntoa(in_addr);
601 PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
602
603 return -1;
604#endif
605
Benny Prijono70c5ba02007-12-31 11:27:35 +0000606 // Hostname
607 hostname = pj_gethostname();
608 if (hostname == NULL) {
609 status = PJ_ERESOLVE;
610 pjsua_perror(THIS_FILE, "pj_gethostname() error", status);
611 goto on_return;
612 }
613
614 PJ_LOG(3,(THIS_FILE, "Hostname: %.*s", hostname->slen, hostname->ptr));
615
616 // Gethostbyname
617 status = pj_gethostbyname(hostname, &he);
618 if (status != PJ_SUCCESS) {
619 pjsua_perror(THIS_FILE, "pj_gethostbyname() error", status);
620 } else {
621 PJ_LOG(3,(THIS_FILE, "gethostbyname: %s",
622 pj_inet_ntoa(*(pj_in_addr*)he.h_addr)));
623 }
624
625 // Getaddrinfo
626 count = PJ_ARRAY_SIZE(ai);
627 status = pj_getaddrinfo(af, hostname, &count, ai);
628 if (status != PJ_SUCCESS) {
629 pjsua_perror(THIS_FILE, "pj_getaddrinfo() error", status);
630 } else {
631 for (i=0; i<count; ++i) {
632 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
633 PJ_LOG(3,(THIS_FILE, "Addrinfo: %s",
634 pj_sockaddr_print(&ai[i].ai_addr, ipaddr, sizeof(ipaddr), 2)));
635 }
636 }
637
638 // Enum interface
639 count = PJ_ARRAY_SIZE(ifs);
640 status = pj_enum_ip_interface(af, &count, ifs);
641 if (status != PJ_SUCCESS) {
642 pjsua_perror(THIS_FILE, "pj_enum_ip_interface() error", status);
643 } else {
644 for (i=0; i<count; ++i) {
645 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
646 PJ_LOG(3,(THIS_FILE, "Interface: %s",
647 pj_sockaddr_print(&ifs[i], ipaddr, sizeof(ipaddr), 2)));
648 }
649 }
650
651 // Get default iinterface
652 status = pj_getdefaultipinterface(af, &ifs[0]);
653 if (status != PJ_SUCCESS) {
654 pjsua_perror(THIS_FILE, "pj_getdefaultipinterface() error", status);
655 } else {
656 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
657 PJ_LOG(3,(THIS_FILE, "Default IP: %s",
658 pj_sockaddr_print(&ifs[0], ipaddr, sizeof(ipaddr), 2)));
659 }
660
661 // Get default IP address
662 status = pj_gethostip(af, &ifs[0]);
663 if (status != PJ_SUCCESS) {
664 pjsua_perror(THIS_FILE, "pj_gethostip() error", status);
665 } else {
666 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
667 PJ_LOG(3,(THIS_FILE, "Host IP: %s",
668 pj_sockaddr_print(&ifs[0], ipaddr, sizeof(ipaddr), 2)));
669 }
670
671 status = -1;
672
673on_return:
674 pj_shutdown();
675 return status;
676}
677#endif
678
679
Benny Prijono6b3ccdf2008-01-14 11:54:21 +0000680#include <es_sock.h>
Benny Prijono897f9f82007-05-03 19:56:21 +0000681
Benny Prijonoba5926a2007-05-02 11:29:37 +0000682////////////////////////////////////////////////////////////////////////////
683int ua_main()
684{
Benny Prijono70c5ba02007-12-31 11:27:35 +0000685 RSocketServ aSocketServer;
686 RConnection aConn;
687 TInt err;
688 pj_symbianos_params sym_params;
Benny Prijonoc71ad432007-05-04 07:25:19 +0000689 pj_status_t status;
690
Benny Prijono70c5ba02007-12-31 11:27:35 +0000691 // Initialize RSocketServ
692 if ((err=aSocketServer.Connect()) != KErrNone)
693 return PJ_STATUS_FROM_OS(err);
694
695 // Open up a connection
696 if ((err=aConn.Open(aSocketServer)) != KErrNone) {
697 aSocketServer.Close();
698 return PJ_STATUS_FROM_OS(err);
699 }
700
701 if ((err=aConn.Start()) != KErrNone) {
702 aSocketServer.Close();
703 return PJ_STATUS_FROM_OS(err);
704 }
705
706 // Set Symbian OS parameters in pjlib.
707 // This must be done before pj_init() is called.
708 pj_bzero(&sym_params, sizeof(sym_params));
709 sym_params.rsocketserv = &aSocketServer;
710 sym_params.rconnection = &aConn;
711 pj_symbianos_set_params(&sym_params);
712
Benny Prijonoc71ad432007-05-04 07:25:19 +0000713 // Initialize pjsua
714 status = app_startup();
Benny Prijono70c5ba02007-12-31 11:27:35 +0000715 //status = test_addr();
716 if (status != PJ_SUCCESS) {
717 aConn.Close();
718 aSocketServer.Close();
Benny Prijonoc71ad432007-05-04 07:25:19 +0000719 return status;
Benny Prijono70c5ba02007-12-31 11:27:35 +0000720 }
Benny Prijono897f9f82007-05-03 19:56:21 +0000721
Benny Prijonoc71ad432007-05-04 07:25:19 +0000722 // Run the UI
723 CActiveSchedulerWait *asw = new CActiveSchedulerWait;
724 ConsoleUI *con = new ConsoleUI(asw, console);
725
726 con->Run();
727
728 PrintMenu();
729 asw->Start();
730
731 delete con;
732 delete asw;
Benny Prijono684c0ad2008-01-03 18:50:27 +0000733
734 // Dump memory statistics
735 PJ_LOG(3,(THIS_FILE, "Max heap usage: %u.%03uMB",
736 pjsua_var.cp.peak_used_size / 1000000,
737 (pjsua_var.cp.peak_used_size % 1000000)/1000));
Benny Prijonoc71ad432007-05-04 07:25:19 +0000738
Benny Prijono684c0ad2008-01-03 18:50:27 +0000739 // check max stack usage
740#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
741 pj_thread_t* this_thread = pj_thread_this();
742 if (!this_thread)
743 return status;
744
745 const char* max_stack_file;
746 int max_stack_line;
747 status = pj_thread_get_stack_info(this_thread, &max_stack_file, &max_stack_line);
748
749 PJ_LOG(3,(THIS_FILE, "Max stack usage: %u at %s:%d",
750 pj_thread_get_stack_max_usage(this_thread),
751 max_stack_file, max_stack_line));
752#endif
753
Benny Prijonoc71ad432007-05-04 07:25:19 +0000754 // Shutdown pjsua
755 pjsua_destroy();
756
Benny Prijono70c5ba02007-12-31 11:27:35 +0000757 // Close connection and socket server
758 aConn.Close();
759 aSocketServer.Close();
760
Benny Prijono797e3382007-12-01 09:10:07 +0000761 return status;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000762}
763