blob: 5396bc720b2f9f774f25460854b4d7883941c9fa [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;
Nanang Izzuddin68559c32008-06-13 17:01:46 +0000337 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 +0000338
339 status = pjsua_init(&cfg, &log_cfg, &med_cfg);
340 if (status != PJ_SUCCESS) {
341 pjsua_perror(THIS_FILE, "pjsua_init() error", status);
342 pjsua_destroy();
343 return status;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000344 }
Nanang Izzuddin829ac022008-05-27 00:24:26 +0000345
346 /* Adjust Speex priority and enable only the narrowband */
347 {
348 pj_str_t codec_id = pj_str("speex/8000");
349 pjmedia_codec_mgr_set_codec_priority(
350 pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
351 &codec_id, PJMEDIA_CODEC_PRIO_NORMAL+1);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000352
Nanang Izzuddin829ac022008-05-27 00:24:26 +0000353 codec_id = pj_str("speex/16000");
354 pjmedia_codec_mgr_set_codec_priority(
355 pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
356 &codec_id, PJMEDIA_CODEC_PRIO_DISABLED);
357
358 codec_id = pj_str("speex/32000");
359 pjmedia_codec_mgr_set_codec_priority(
360 pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
361 &codec_id, PJMEDIA_CODEC_PRIO_DISABLED);
362 }
363
Benny Prijonoba5926a2007-05-02 11:29:37 +0000364 /* Add UDP transport. */
Benny Prijonoc71ad432007-05-04 07:25:19 +0000365 pjsua_transport_config tcfg;
366 pjsua_transport_id tid;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000367
Benny Prijonoc71ad432007-05-04 07:25:19 +0000368 pjsua_transport_config_default(&tcfg);
369 tcfg.port = SIP_PORT;
370 status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &tcfg, &tid);
371 if (status != PJ_SUCCESS) {
372 pjsua_perror(THIS_FILE, "Error creating transport", status);
373 pjsua_destroy();
374 return status;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000375 }
376
Benny Prijonoc71ad432007-05-04 07:25:19 +0000377 /* Add account for the transport */
378 pjsua_acc_add_local(tid, PJ_TRUE, &g_acc_id);
379
380
Benny Prijonoba5926a2007-05-02 11:29:37 +0000381 /* Initialization is done, now start pjsua */
382 status = pjsua_start();
383 if (status != PJ_SUCCESS) {
384 pjsua_perror(THIS_FILE, "Error starting pjsua", status);
385 pjsua_destroy();
386 return status;
387 }
388
389 /* Register to SIP server by creating SIP account. */
Benny Prijono72a81aa2007-05-02 23:06:11 +0000390 if (HAS_SIP_ACCOUNT) {
Benny Prijonoba5926a2007-05-02 11:29:37 +0000391 pjsua_acc_config cfg;
392
393 pjsua_acc_config_default(&cfg);
394 cfg.id = pj_str("sip:" SIP_USER "@" SIP_DOMAIN);
395 cfg.reg_uri = pj_str("sip:" SIP_DOMAIN);
396 cfg.cred_count = 1;
Benny Prijono0e2c6462008-02-14 13:39:24 +0000397 cfg.cred_info[0].realm = pj_str("*");
Benny Prijonoba5926a2007-05-02 11:29:37 +0000398 cfg.cred_info[0].scheme = pj_str("digest");
399 cfg.cred_info[0].username = pj_str(SIP_USER);
400 cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
401 cfg.cred_info[0].data = pj_str(SIP_PASSWD);
402
Benny Prijonob2c96822007-05-03 13:31:21 +0000403 status = pjsua_acc_add(&cfg, PJ_TRUE, &g_acc_id);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000404 if (status != PJ_SUCCESS) {
405 pjsua_perror(THIS_FILE, "Error adding account", status);
406 pjsua_destroy();
407 return status;
408 }
409 }
410
Benny Prijonob2c96822007-05-03 13:31:21 +0000411 if (SIP_DST_URI) {
412 pjsua_buddy_config bcfg;
413
414 pjsua_buddy_config_default(&bcfg);
415 bcfg.uri = pj_str(SIP_DST_URI);
416 bcfg.subscribe = PJ_FALSE;
417
418 pjsua_buddy_add(&bcfg, &g_buddy_id);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000419 }
Benny Prijonoba5926a2007-05-02 11:29:37 +0000420 return PJ_SUCCESS;
421}
422
423
424////////////////////////////////////////////////////////////////////////////
Benny Prijonoc71ad432007-05-04 07:25:19 +0000425/*
426 * The interractive console UI
427 */
Benny Prijonoba5926a2007-05-02 11:29:37 +0000428#include <e32base.h>
429
430class ConsoleUI : public CActive
431{
432public:
Benny Prijonoc71ad432007-05-04 07:25:19 +0000433 ConsoleUI(CActiveSchedulerWait *asw, CConsoleBase *con);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000434
Benny Prijonoc71ad432007-05-04 07:25:19 +0000435 // Run console UI
436 void Run();
437
438 // Stop
439 void Stop();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000440
441protected:
Benny Prijonoc71ad432007-05-04 07:25:19 +0000442 // Cancel asynchronous read.
443 void DoCancel();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000444
Benny Prijonoc71ad432007-05-04 07:25:19 +0000445 // Implementation: called when read has completed.
446 void RunL();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000447
448private:
Benny Prijonoc71ad432007-05-04 07:25:19 +0000449 CActiveSchedulerWait *asw_;
450 CConsoleBase *con_;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000451};
452
453
454ConsoleUI::ConsoleUI(CActiveSchedulerWait *asw, CConsoleBase *con)
455: CActive(EPriorityStandard), asw_(asw), con_(con)
456{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000457 CActiveScheduler::Add(this);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000458}
459
460// Run console UI
461void ConsoleUI::Run()
462{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000463 con_->Read(iStatus);
464 SetActive();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000465}
466
467// Stop console UI
468void ConsoleUI::Stop()
469{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000470 DoCancel();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000471}
472
473// Cancel asynchronous read.
474void ConsoleUI::DoCancel()
475{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000476 con_->ReadCancel();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000477}
478
Benny Prijono72a81aa2007-05-02 23:06:11 +0000479static void PrintMenu()
480{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000481 PJ_LOG(3, (THIS_FILE, "\n\n"
482 "Menu:\n"
483 " d Dump states\n"
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000484 " D Dump states detail\n"
Benny Prijonoc71ad432007-05-04 07:25:19 +0000485 " P Dump pool factory\n"
Benny Prijono5df8bb62007-12-28 18:55:02 +0000486 " l Start loopback audio device\n"
487 " L Stop loopback audio device\n"
Benny Prijono70c5ba02007-12-31 11:27:35 +0000488 " m Call " SIP_DST_URI "\n"
489 " a Answer call\n"
490 " g Hangup all calls\n"
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000491 " s Subscribe " SIP_DST_URI "\n"
Benny Prijonoc71ad432007-05-04 07:25:19 +0000492 " S Unsubscribe presence\n"
493 " o Set account online\n"
494 " O Set account offline\n"
Benny Prijono70c5ba02007-12-31 11:27:35 +0000495 " w Quit\n"));
Benny Prijono72a81aa2007-05-02 23:06:11 +0000496}
497
Benny Prijonoba5926a2007-05-02 11:29:37 +0000498// Implementation: called when read has completed.
499void ConsoleUI::RunL()
500{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000501 TKeyCode kc = con_->KeyCode();
502 pj_bool_t reschedule = PJ_TRUE;
503
504 switch (kc) {
Benny Prijono70c5ba02007-12-31 11:27:35 +0000505 case 'w':
Benny Prijonoc71ad432007-05-04 07:25:19 +0000506 asw_->AsyncStop();
507 reschedule = PJ_FALSE;
508 break;
509 case 'D':
510 case 'd':
511 pjsua_dump(kc == 'D');
512 break;
513 case 'p':
514 case 'P':
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000515 pj_pool_factory_dump(pjsua_get_pool_factory(), PJ_TRUE);
Benny Prijonoc71ad432007-05-04 07:25:19 +0000516 break;
Benny Prijono5df8bb62007-12-28 18:55:02 +0000517 case 'l':
518 pjsua_conf_connect(0, 0);
519 break;
520 case 'L':
521 pjsua_conf_disconnect(0, 0);
522 break;
Benny Prijono70c5ba02007-12-31 11:27:35 +0000523 case 'm':
Benny Prijonoc71ad432007-05-04 07:25:19 +0000524 if (g_call_id != PJSUA_INVALID_ID) {
525 PJ_LOG(3,(THIS_FILE, "Another call is active"));
526 break;
527 }
528
529 if (pjsua_verify_sip_url(SIP_DST_URI) == PJ_SUCCESS) {
530 pj_str_t dst = pj_str(SIP_DST_URI);
531 pjsua_call_make_call(g_acc_id, &dst, 0, NULL,
532 NULL, &g_call_id);
533 } else {
534 PJ_LOG(3,(THIS_FILE, "Invalid SIP URI"));
535 }
536 break;
Benny Prijono70c5ba02007-12-31 11:27:35 +0000537 case 'a':
Benny Prijonoc71ad432007-05-04 07:25:19 +0000538 if (g_call_id != PJSUA_INVALID_ID)
539 pjsua_call_answer(g_call_id, 200, NULL, NULL);
540 break;
Benny Prijono70c5ba02007-12-31 11:27:35 +0000541 case 'g':
Benny Prijonoc71ad432007-05-04 07:25:19 +0000542 pjsua_call_hangup_all();
543 break;
544 case 's':
545 case 'S':
546 if (g_buddy_id != PJSUA_INVALID_ID)
547 pjsua_buddy_subscribe_pres(g_buddy_id, kc=='s');
548 break;
549 case 'o':
550 case 'O':
551 pjsua_acc_set_online_status(g_acc_id, kc=='o');
552 break;
553 default:
554 PJ_LOG(3,(THIS_FILE, "Keycode '%c' (%d) is pressed",
555 kc, kc));
556 break;
557 }
Benny Prijono72a81aa2007-05-02 23:06:11 +0000558
Benny Prijonoc71ad432007-05-04 07:25:19 +0000559 PrintMenu();
560
561 if (reschedule)
562 Run();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000563}
564
Benny Prijono70c5ba02007-12-31 11:27:35 +0000565#if 0
566// IP networking related testing
567static pj_status_t test_addr(void)
568{
569 int af;
570 unsigned i, count;
571 pj_addrinfo ai[8];
572 pj_sockaddr ifs[8];
573 const pj_str_t *hostname;
574 pj_hostent he;
575 pj_status_t status;
576
577 pj_log_set_log_func(&log_writer);
578
579 status = pj_init();
580 if (status != PJ_SUCCESS) {
581 pjsua_perror(THIS_FILE, "pj_init() error", status);
582 return status;
583 }
584
585 af = pj_AF_INET();
586
Benny Prijono684c0ad2008-01-03 18:50:27 +0000587#if 0
588 pj_in_addr in_addr;
589 pj_str_t aa = pj_str("1.1.1.1");
590 in_addr = pj_inet_addr(&aa);
591 char *the_addr = pj_inet_ntoa(in_addr);
592 PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
593
594 aa = pj_str("192.168.0.15");
595 in_addr = pj_inet_addr(&aa);
596 the_addr = pj_inet_ntoa(in_addr);
597 PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
598
599 aa = pj_str("2.2.2.2");
600 in_addr = pj_inet_addr(&aa);
601 the_addr = pj_inet_ntoa(in_addr);
602 PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
603
604 return -1;
605#endif
606
Benny Prijono70c5ba02007-12-31 11:27:35 +0000607 // Hostname
608 hostname = pj_gethostname();
609 if (hostname == NULL) {
610 status = PJ_ERESOLVE;
611 pjsua_perror(THIS_FILE, "pj_gethostname() error", status);
612 goto on_return;
613 }
614
615 PJ_LOG(3,(THIS_FILE, "Hostname: %.*s", hostname->slen, hostname->ptr));
616
617 // Gethostbyname
618 status = pj_gethostbyname(hostname, &he);
619 if (status != PJ_SUCCESS) {
620 pjsua_perror(THIS_FILE, "pj_gethostbyname() error", status);
621 } else {
622 PJ_LOG(3,(THIS_FILE, "gethostbyname: %s",
623 pj_inet_ntoa(*(pj_in_addr*)he.h_addr)));
624 }
625
626 // Getaddrinfo
627 count = PJ_ARRAY_SIZE(ai);
628 status = pj_getaddrinfo(af, hostname, &count, ai);
629 if (status != PJ_SUCCESS) {
630 pjsua_perror(THIS_FILE, "pj_getaddrinfo() error", status);
631 } else {
632 for (i=0; i<count; ++i) {
633 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
634 PJ_LOG(3,(THIS_FILE, "Addrinfo: %s",
635 pj_sockaddr_print(&ai[i].ai_addr, ipaddr, sizeof(ipaddr), 2)));
636 }
637 }
638
639 // Enum interface
640 count = PJ_ARRAY_SIZE(ifs);
641 status = pj_enum_ip_interface(af, &count, ifs);
642 if (status != PJ_SUCCESS) {
643 pjsua_perror(THIS_FILE, "pj_enum_ip_interface() error", status);
644 } else {
645 for (i=0; i<count; ++i) {
646 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
647 PJ_LOG(3,(THIS_FILE, "Interface: %s",
648 pj_sockaddr_print(&ifs[i], ipaddr, sizeof(ipaddr), 2)));
649 }
650 }
651
652 // Get default iinterface
653 status = pj_getdefaultipinterface(af, &ifs[0]);
654 if (status != PJ_SUCCESS) {
655 pjsua_perror(THIS_FILE, "pj_getdefaultipinterface() error", status);
656 } else {
657 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
658 PJ_LOG(3,(THIS_FILE, "Default IP: %s",
659 pj_sockaddr_print(&ifs[0], ipaddr, sizeof(ipaddr), 2)));
660 }
661
662 // Get default IP address
663 status = pj_gethostip(af, &ifs[0]);
664 if (status != PJ_SUCCESS) {
665 pjsua_perror(THIS_FILE, "pj_gethostip() error", status);
666 } else {
667 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
668 PJ_LOG(3,(THIS_FILE, "Host IP: %s",
669 pj_sockaddr_print(&ifs[0], ipaddr, sizeof(ipaddr), 2)));
670 }
671
672 status = -1;
673
674on_return:
675 pj_shutdown();
676 return status;
677}
678#endif
679
680
Benny Prijono6b3ccdf2008-01-14 11:54:21 +0000681#include <es_sock.h>
Benny Prijono897f9f82007-05-03 19:56:21 +0000682
Benny Prijonoba5926a2007-05-02 11:29:37 +0000683////////////////////////////////////////////////////////////////////////////
684int ua_main()
685{
Benny Prijono70c5ba02007-12-31 11:27:35 +0000686 RSocketServ aSocketServer;
687 RConnection aConn;
688 TInt err;
689 pj_symbianos_params sym_params;
Benny Prijonoc71ad432007-05-04 07:25:19 +0000690 pj_status_t status;
691
Benny Prijono70c5ba02007-12-31 11:27:35 +0000692 // Initialize RSocketServ
693 if ((err=aSocketServer.Connect()) != KErrNone)
694 return PJ_STATUS_FROM_OS(err);
695
696 // Open up a connection
697 if ((err=aConn.Open(aSocketServer)) != KErrNone) {
698 aSocketServer.Close();
699 return PJ_STATUS_FROM_OS(err);
700 }
701
702 if ((err=aConn.Start()) != KErrNone) {
703 aSocketServer.Close();
704 return PJ_STATUS_FROM_OS(err);
705 }
706
707 // Set Symbian OS parameters in pjlib.
708 // This must be done before pj_init() is called.
709 pj_bzero(&sym_params, sizeof(sym_params));
710 sym_params.rsocketserv = &aSocketServer;
711 sym_params.rconnection = &aConn;
712 pj_symbianos_set_params(&sym_params);
713
Benny Prijonoc71ad432007-05-04 07:25:19 +0000714 // Initialize pjsua
715 status = app_startup();
Benny Prijono70c5ba02007-12-31 11:27:35 +0000716 //status = test_addr();
717 if (status != PJ_SUCCESS) {
718 aConn.Close();
719 aSocketServer.Close();
Benny Prijonoc71ad432007-05-04 07:25:19 +0000720 return status;
Benny Prijono70c5ba02007-12-31 11:27:35 +0000721 }
Benny Prijono897f9f82007-05-03 19:56:21 +0000722
Benny Prijonoc71ad432007-05-04 07:25:19 +0000723 // Run the UI
724 CActiveSchedulerWait *asw = new CActiveSchedulerWait;
725 ConsoleUI *con = new ConsoleUI(asw, console);
726
727 con->Run();
728
729 PrintMenu();
730 asw->Start();
731
732 delete con;
733 delete asw;
Benny Prijono684c0ad2008-01-03 18:50:27 +0000734
735 // Dump memory statistics
736 PJ_LOG(3,(THIS_FILE, "Max heap usage: %u.%03uMB",
737 pjsua_var.cp.peak_used_size / 1000000,
738 (pjsua_var.cp.peak_used_size % 1000000)/1000));
Benny Prijonoc71ad432007-05-04 07:25:19 +0000739
Benny Prijono684c0ad2008-01-03 18:50:27 +0000740 // check max stack usage
741#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
742 pj_thread_t* this_thread = pj_thread_this();
743 if (!this_thread)
744 return status;
745
746 const char* max_stack_file;
747 int max_stack_line;
748 status = pj_thread_get_stack_info(this_thread, &max_stack_file, &max_stack_line);
749
750 PJ_LOG(3,(THIS_FILE, "Max stack usage: %u at %s:%d",
751 pj_thread_get_stack_max_usage(this_thread),
752 max_stack_file, max_stack_line));
753#endif
754
Benny Prijonoc71ad432007-05-04 07:25:19 +0000755 // Shutdown pjsua
756 pjsua_destroy();
757
Benny Prijono70c5ba02007-12-31 11:27:35 +0000758 // Close connection and socket server
759 aConn.Close();
760 aSocketServer.Close();
761
Benny Prijono797e3382007-12-01 09:10:07 +0000762 return status;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000763}
764