- Timestamp:
- Apr 5, 2013 3:02:19 AM (12 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 5 added
- 3 deleted
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/build.symbian/pjlib_util.mmp
r3087 r4461 33 33 // 34 34 SOURCE base64.c 35 SOURCE cli.c 36 SOURCE cli_console.c 37 SOURCE cli_telnet.c 35 38 SOURCE crc32.c 36 39 SOURCE dns.c -
pjproject/trunk/pjlib-util/include/pjlib-util.h
r3553 r4461 64 64 #include <pjlib-util/http_client.h> 65 65 66 /** CLI Telnet **/ 67 #include <pjlib-util/cli_telnet.h> 68 66 69 #endif /* __PJLIB_UTIL_H__ */ -
pjproject/trunk/pjlib-util/include/pjlib-util/cli_telnet.h
r4440 r4461 35 35 */ 36 36 37 /** 38 * This structure contains the information about the telnet. 39 * Application will get updated information each time the telnet is started/ 40 * restarted. 41 */ 42 typedef struct pj_cli_telnet_info 43 { 44 /** 45 * The telnet's ip address. 46 */ 47 pj_str_t ip_address; 48 49 /** 50 * The telnet's port number. 51 */ 52 pj_uint16_t port; 53 } pj_cli_telnet_info; 54 55 /** 56 * This specifies the callback called when telnet is started 57 * 58 * @param telnet_info The telnet runtime information. 59 * 60 */ 61 typedef void (*pj_cli_telnet_on_started)(pj_cli_telnet_info *telnet_info); 37 62 38 63 /** … … 86 111 pj_str_t prompt_str; 87 112 113 /** 114 * Specify the pj_cli_telnet_on_started callback. 115 * 116 * Default: empty 117 */ 118 pj_cli_telnet_on_started on_started; 119 88 120 } pj_cli_telnet_cfg; 89 90 121 91 122 /** -
pjproject/trunk/pjlib-util/include/pjlib-util/config.h
r4440 r4461 292 292 */ 293 293 #ifndef PJ_CLI_MAX_CMDBUF 294 # define PJ_CLI_MAX_CMDBUF 120294 # define PJ_CLI_MAX_CMDBUF 512 295 295 #endif 296 296 -
pjproject/trunk/pjlib-util/src/pjlib-util/cli_telnet.c
r4440 r4461 30 30 #include <pjlib-util/errno.h> 31 31 #include <pjlib-util/scanner.h> 32 #include <pj/addr_resolv.h> 33 #include <pj/compat/socket.h> 34 35 #if (defined(PJ_WIN32) && PJ_WIN32!=0) || \ 36 (defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE!=0) 37 38 #define EADDRINUSE WSAEADDRINUSE 39 40 #endif 32 41 33 42 #define CLI_TELNET_BUF_SIZE 256 … … 45 54 46 55 #define MAX_CLI_TELNET_OPTIONS 256 56 /** Maximum retry on Telnet Restart **/ 57 #define MAX_RETRY_ON_TELNET_RESTART 100 58 /** Minimum number of millisecond to wait before retrying to re-bind on 59 * telnet restart **/ 60 #define MIN_WAIT_ON_TELNET_RESTART 20 61 /** Maximum number of millisecod to wait before retrying to re-bind on 62 * telnet restart **/ 63 #define MAX_WAIT_ON_TELNET_RESTART 1000 47 64 48 65 /** … … 262 279 } cli_telnet_sess; 263 280 264 struct cli_telnet_fe281 typedef struct cli_telnet_fe 265 282 { 266 283 pj_cli_front_end base; … … 273 290 pj_thread_t *worker_thread; 274 291 pj_bool_t is_quitting; 275 pj_mutex_t *mutex; 276 } ;292 pj_mutex_t *mutex; 293 } cli_telnet_fe; 277 294 278 295 /* Forward Declaration */ … … 282 299 static pj_status_t telnet_sess_send(cli_telnet_sess *sess, 283 300 const pj_str_t *str); 301 302 static pj_status_t telnet_start(cli_telnet_fe *fe); 303 static pj_status_t telnet_restart(cli_telnet_fe *tfe); 284 304 285 305 /** … … 646 666 pj_str_t send_data; 647 667 char data_str[128]; 648 struct cli_telnet_fe *fe = (structcli_telnet_fe *)sess->base.fe;668 cli_telnet_fe *fe = (cli_telnet_fe *)sess->base.fe; 649 669 650 670 send_data.ptr = &data_str[0]; … … 670 690 unsigned len; 671 691 unsigned i; 672 struct cli_telnet_fe *fe = (structcli_telnet_fe *)sess->base.fe;692 cli_telnet_fe *fe = (cli_telnet_fe *)sess->base.fe; 673 693 674 694 send_data.ptr = &data_str[0]; … … 744 764 pj_str_t send_data; 745 765 char data[1028]; 746 struct cli_telnet_fe *fe = (structcli_telnet_fe *)sess->base.fe;766 cli_telnet_fe *fe = (cli_telnet_fe *)sess->base.fe; 747 767 const pj_cli_hint_info *hint = info->hint; 748 768 out_parse_state parse_state = OP_NORMAL; … … 1319 1339 { 1320 1340 cli_telnet_sess *tsess = (cli_telnet_sess *)sess; 1321 pj_mutex_t *mutex = (( structcli_telnet_fe *)sess->fe)->mutex;1341 pj_mutex_t *mutex = ((cli_telnet_fe *)sess->fe)->mutex; 1322 1342 1323 1343 pj_mutex_lock(mutex); … … 1335 1355 const char *data, int len) 1336 1356 { 1337 struct cli_telnet_fe * tfe = (structcli_telnet_fe *)fe;1357 cli_telnet_fe *tfe = (cli_telnet_fe *)fe; 1338 1358 pj_cli_sess *sess; 1339 1359 … … 1358 1378 static void telnet_fe_destroy(pj_cli_front_end *fe) 1359 1379 { 1360 struct cli_telnet_fe *tfe = (structcli_telnet_fe *)fe;1380 cli_telnet_fe *tfe = (cli_telnet_fe *)fe; 1361 1381 pj_cli_sess *sess; 1362 1382 … … 1392 1412 static int poll_worker_thread(void *p) 1393 1413 { 1394 struct cli_telnet_fe *fe = (structcli_telnet_fe *)p;1414 cli_telnet_fe *fe = (cli_telnet_fe *)p; 1395 1415 1396 1416 while (!fe->is_quitting) { … … 1409 1429 pj_activesock_get_user_data(asock); 1410 1430 1411 PJ_UNUSED_ARG(op_key); 1431 PJ_UNUSED_ARG(op_key); 1412 1432 1413 1433 if (sent <= 0) { 1434 TRACE_((THIS_FILE, "Error On data send")); 1414 1435 pj_cli_sess_end_session(&sess->base); 1415 1436 return PJ_FALSE; … … 1442 1463 cli_telnet_sess *sess = (cli_telnet_sess *) 1443 1464 pj_activesock_get_user_data(asock); 1444 struct cli_telnet_fe *tfe = (structcli_telnet_fe *)sess->base.fe;1465 cli_telnet_fe *tfe = (cli_telnet_fe *)sess->base.fe; 1445 1466 unsigned char *cdata = (unsigned char*)data; 1446 1467 pj_status_t is_valid = PJ_TRUE; … … 1449 1470 PJ_UNUSED_ARG(remainder); 1450 1471 1451 if (status != PJ_SUCCESS && status != PJ_EPENDING) {1452 pj_cli_sess_end_session(&sess->base);1453 return PJ_FALSE;1454 }1455 1456 1472 if (tfe->is_quitting) 1457 1473 return PJ_FALSE; 1474 1475 if (status != PJ_SUCCESS && status != PJ_EPENDING) { 1476 TRACE_((THIS_FILE, "Error on data read %d", status)); 1477 return PJ_FALSE; 1478 } 1458 1479 1459 1480 pj_mutex_lock(sess->smutex); … … 1552 1573 pj_sock_t newsock, 1553 1574 const pj_sockaddr_t *src_addr, 1554 int src_addr_len) 1555 { 1556 struct cli_telnet_fe *fe = (struct cli_telnet_fe *) 1557 pj_activesock_get_user_data(asock); 1575 int src_addr_len, 1576 pj_status_t status) 1577 { 1578 cli_telnet_fe *fe = (cli_telnet_fe *) pj_activesock_get_user_data(asock); 1579 1558 1580 pj_status_t sstatus; 1559 1581 pj_pool_t *pool; 1560 cli_telnet_sess *sess ;1582 cli_telnet_sess *sess = NULL; 1561 1583 pj_activesock_cb asock_cb; 1562 1584 … … 1566 1588 if (fe->is_quitting) 1567 1589 return PJ_FALSE; 1590 1591 if (status != PJ_SUCCESS && status != PJ_EPENDING) { 1592 TRACE_((THIS_FILE, "Error on data accept %d", status)); 1593 if (status == PJ_ESOCKETSTOP) 1594 telnet_restart(fe); 1595 1596 return PJ_FALSE; 1597 } 1568 1598 1569 1599 /* An incoming connection is accepted, create a new session */ … … 1658 1688 pj_cli_front_end **p_fe) 1659 1689 { 1660 structcli_telnet_fe *fe;1690 cli_telnet_fe *fe; 1661 1691 pj_pool_t *pool; 1662 pj_sock_t sock = PJ_INVALID_SOCKET; 1663 pj_activesock_cb asock_cb; 1664 pj_sockaddr_in addr; 1665 pj_status_t sstatus; 1692 pj_status_t status; 1666 1693 1667 1694 PJ_ASSERT_RETURN(cli, PJ_EINVAL); … … 1670 1697 PJ_CLI_TELNET_POOL_SIZE, PJ_CLI_TELNET_POOL_INC, 1671 1698 NULL); 1672 fe = PJ_POOL_ZALLOC_T(pool, structcli_telnet_fe);1699 fe = PJ_POOL_ZALLOC_T(pool, cli_telnet_fe); 1673 1700 if (!fe) 1674 1701 return PJ_ENOMEM; … … 1688 1715 fe->pool = pool; 1689 1716 1690 if (!fe->cfg.ioqueue) { 1717 if (!fe->cfg.ioqueue) { 1691 1718 /* Create own ioqueue if application doesn't supply one */ 1692 s status = pj_ioqueue_create(pool, 8, &fe->cfg.ioqueue);1693 if (s status != PJ_SUCCESS)1719 status = pj_ioqueue_create(pool, 8, &fe->cfg.ioqueue); 1720 if (status != PJ_SUCCESS) 1694 1721 goto on_exit; 1695 1722 fe->own_ioqueue = PJ_TRUE; 1696 1723 } 1697 1724 1698 s status = pj_mutex_create_recursive(pool, "mutex_telnet_fe", &fe->mutex);1699 if (s status != PJ_SUCCESS)1725 status = pj_mutex_create_recursive(pool, "mutex_telnet_fe", &fe->mutex); 1726 if (status != PJ_SUCCESS) 1700 1727 goto on_exit; 1701 1728 1702 1729 /* Start telnet daemon */ 1703 sstatus = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, 1704 &sock); 1705 if (sstatus != PJ_SUCCESS) 1730 telnet_start(fe); 1731 1732 pj_cli_register_front_end(cli, &fe->base); 1733 1734 if (p_fe) 1735 *p_fe = &fe->base; 1736 1737 return PJ_SUCCESS; 1738 1739 on_exit: 1740 if (fe->own_ioqueue) 1741 pj_ioqueue_destroy(fe->cfg.ioqueue); 1742 1743 if (fe->mutex) 1744 pj_mutex_destroy(fe->mutex); 1745 1746 pj_pool_release(pool); 1747 return status; 1748 } 1749 1750 static pj_status_t telnet_start(cli_telnet_fe *fe) 1751 { 1752 pj_sock_t sock = PJ_INVALID_SOCKET; 1753 pj_activesock_cb asock_cb; 1754 pj_sockaddr_in addr; 1755 pj_status_t status; 1756 int val; 1757 int restart_retry; 1758 unsigned msec; 1759 1760 /* Start telnet daemon */ 1761 status = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, &sock); 1762 1763 if (status != PJ_SUCCESS) 1706 1764 goto on_exit; 1707 1765 1708 1766 pj_sockaddr_in_init(&addr, NULL, fe->cfg.port); 1709 1767 1710 sstatus = pj_sock_bind(sock, &addr, sizeof(addr)); 1711 if (sstatus == PJ_SUCCESS) { 1712 pj_sockaddr_in addr; 1713 int addr_len = sizeof(addr); 1714 1715 sstatus = pj_sock_getsockname(sock, &addr, &addr_len); 1716 if (sstatus != PJ_SUCCESS) 1768 val = 1; 1769 status = pj_sock_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, 1770 &val, sizeof(val)); 1771 1772 if (status != PJ_SUCCESS) 1773 goto on_exit; 1774 1775 /* The loop is silly, but what else can we do? */ 1776 for (msec=MIN_WAIT_ON_TELNET_RESTART, restart_retry=0; 1777 restart_retry < MAX_RETRY_ON_TELNET_RESTART; 1778 ++restart_retry, msec=(msec<MAX_WAIT_ON_TELNET_RESTART? 1779 msec*2 : MAX_WAIT_ON_TELNET_RESTART)) 1780 { 1781 status = pj_sock_bind(sock, &addr, sizeof(addr)); 1782 if (status != PJ_STATUS_FROM_OS(EADDRINUSE)) 1783 break; 1784 PJ_LOG(4,(THIS_FILE, "Address is still in use, retrying..")); 1785 pj_thread_sleep(msec); 1786 } 1787 1788 if (status == PJ_SUCCESS) { 1789 int addr_len = sizeof(addr); 1790 1791 status = pj_sock_getsockname(sock, &addr, &addr_len); 1792 if (status != PJ_SUCCESS) 1717 1793 goto on_exit; 1718 1794 1719 fe->cfg.port = pj_sockaddr_in_get_port(&addr); 1720 if (param) 1721 param->port = fe->cfg.port; 1722 1723 PJ_LOG(3, (THIS_FILE, "CLI telnet daemon listening at port %d", 1724 fe->cfg.port)); 1725 1795 fe->cfg.port = pj_sockaddr_in_get_port(&addr); 1796 1726 1797 if (fe->cfg.prompt_str.slen == 0) { 1727 1798 pj_str_t prompt_sign = {"> ", 2}; … … 1738 1809 } 1739 1810 1740 s status = pj_sock_listen(sock, 4);1741 if (s status != PJ_SUCCESS)1811 status = pj_sock_listen(sock, 4); 1812 if (status != PJ_SUCCESS) 1742 1813 goto on_exit; 1743 1814 1744 1815 pj_bzero(&asock_cb, sizeof(asock_cb)); 1745 asock_cb.on_accept_complete = &telnet_fe_on_accept;1746 s status = pj_activesock_create(pool, sock, pj_SOCK_STREAM(),1747 1748 1749 if (s status != PJ_SUCCESS)1816 asock_cb.on_accept_complete2 = &telnet_fe_on_accept; 1817 status = pj_activesock_create(fe->pool, sock, pj_SOCK_STREAM(), 1818 NULL, fe->cfg.ioqueue, 1819 &asock_cb, fe, &fe->asock); 1820 if (status != PJ_SUCCESS) 1750 1821 goto on_exit; 1751 1822 1752 s status = pj_activesock_start_accept(fe->asock,pool);1753 if (s status != PJ_SUCCESS)1823 status = pj_activesock_start_accept(fe->asock, fe->pool); 1824 if (status != PJ_SUCCESS) 1754 1825 goto on_exit; 1755 1826 1756 1827 if (fe->own_ioqueue) { 1757 1828 /* Create our own worker thread */ 1758 s status = pj_thread_create(pool, "worker_telnet_fe",1759 1760 1761 if (s status != PJ_SUCCESS)1829 status = pj_thread_create(fe->pool, "worker_telnet_fe", 1830 &poll_worker_thread, fe, 0, 0, 1831 &fe->worker_thread); 1832 if (status != PJ_SUCCESS) 1762 1833 goto on_exit; 1763 1834 } 1764 1835 1765 pj_cli_register_front_end(cli, &fe->base); 1766 1767 if (p_fe) 1768 *p_fe = &fe->base; 1836 /** Fill telnet information and call pj_cli_telnet_on_started callback */ 1837 if (fe->cfg.on_started) { 1838 char ip_addr[32]; 1839 pj_cli_telnet_info telnet_info; 1840 pj_sockaddr hostip; 1841 1842 telnet_info.ip_address.ptr = ip_addr; 1843 telnet_info.ip_address.slen = 0; 1844 1845 status = pj_gethostip(pj_AF_INET(), &hostip); 1846 if (status != PJ_SUCCESS) 1847 goto on_exit; 1848 1849 pj_strcpy2(&telnet_info.ip_address, 1850 pj_inet_ntoa(hostip.ipv4.sin_addr)); 1851 1852 telnet_info.port = fe->cfg.port; 1853 1854 (*fe->cfg.on_started)(&telnet_info); 1855 } 1769 1856 1770 1857 return PJ_SUCCESS; … … 1782 1869 pj_mutex_destroy(fe->mutex); 1783 1870 1784 pj_pool_release(pool); 1785 return sstatus; 1786 } 1871 pj_pool_release(fe->pool); 1872 return status; 1873 } 1874 1875 static pj_status_t telnet_restart(cli_telnet_fe *fe) 1876 { 1877 pj_status_t status; 1878 pj_cli_sess *sess; 1879 1880 fe->is_quitting = PJ_TRUE; 1881 if (fe->worker_thread) { 1882 pj_thread_join(fe->worker_thread); 1883 } 1884 1885 pj_mutex_lock(fe->mutex); 1886 1887 /* Destroy all the sessions */ 1888 sess = fe->sess_head.next; 1889 while (sess != &fe->sess_head) { 1890 (*sess->op->destroy)(sess); 1891 sess = fe->sess_head.next; 1892 } 1893 1894 pj_mutex_unlock(fe->mutex); 1895 1896 /** Close existing activesock **/ 1897 status = pj_activesock_close(fe->asock); 1898 if (status != PJ_SUCCESS) 1899 goto on_exit; 1900 1901 if (fe->worker_thread) { 1902 pj_thread_destroy(fe->worker_thread); 1903 fe->worker_thread = NULL; 1904 } 1905 1906 fe->is_quitting = PJ_FALSE; 1907 1908 /** Start Telnet **/ 1909 status = telnet_start(fe); 1910 if (status == PJ_SUCCESS) 1911 TRACE_((THIS_FILE, "Telnet Restarted")); 1912 1913 on_exit: 1914 return status; 1915 } -
pjproject/trunk/pjlib/include/pj/activesock.h
r4359 r4461 133 133 /** 134 134 * This callback is called when new connection arrives as the result 135 * of pj_activesock_start_accept(). 135 * of pj_activesock_start_accept(). If the status of accept operation is 136 * needed use on_accept_complete2 instead of this callback. 136 137 * 137 138 * @param asock The active socket. … … 149 150 const pj_sockaddr_t *src_addr, 150 151 int src_addr_len); 152 153 /** 154 * This callback is called when new connection arrives as the result 155 * of pj_activesock_start_accept(). 156 * 157 * @param asock The active socket. 158 * @param newsock The new incoming socket. 159 * @param src_addr The source address of the connection. 160 * @param addr_len Length of the source address. 161 * @param status The status of the accept operation. This may contain 162 * non-PJ_SUCCESS for example when the TCP listener is in 163 * bad state for example on iOS platform after the 164 * application waking up from background. 165 * 166 * @return PJ_TRUE if further accept() is desired, and PJ_FALSE 167 * when application no longer wants to accept incoming 168 * connection. Application may destroy the active socket 169 * in the callback and return PJ_FALSE here. 170 */ 171 pj_bool_t (*on_accept_complete2)(pj_activesock_t *asock, 172 pj_sock_t newsock, 173 const pj_sockaddr_t *src_addr, 174 int src_addr_len, 175 pj_status_t status); 151 176 152 177 /** -
pjproject/trunk/pjlib/include/pj/errno.h
r4359 r4461 428 428 */ 429 429 #define PJ_EGONE (PJ_ERRNO_START_STATUS + 23)/* 70023 */ 430 /** 431 * @hideinitializer 432 * Socket is stopped 433 */ 434 #define PJ_ESOCKETSTOP (PJ_ERRNO_START_STATUS + 24)/* 70024 */ 430 435 431 436 /** @} */ /* pj_errnum */ -
pjproject/trunk/pjlib/src/pj/activesock.c
r4359 r4461 844 844 " operation, stopping further ioqueue accepts.", 845 845 asock->err_counter, asock->last_err)); 846 847 if ((status == PJ_STATUS_FROM_OS(OSERR_EWOULDBLOCK)) && 848 (asock->cb.on_accept_complete2)) 849 { 850 (*asock->cb.on_accept_complete2)(asock, 851 accept_op->new_sock, 852 &accept_op->rem_addr, 853 accept_op->rem_addr_len, 854 PJ_ESOCKETSTOP); 855 } 846 856 return; 847 857 } … … 851 861 } 852 862 853 if (status==PJ_SUCCESS && asock->cb.on_accept_complete) { 863 if (status==PJ_SUCCESS && (asock->cb.on_accept_complete2 || 864 asock->cb.on_accept_complete)) { 854 865 pj_bool_t ret; 855 866 856 867 /* Notify callback */ 857 ret = (*asock->cb.on_accept_complete)(asock, accept_op->new_sock, 858 &accept_op->rem_addr, 859 accept_op->rem_addr_len); 868 if (asock->cb.on_accept_complete2) { 869 ret = (*asock->cb.on_accept_complete2)(asock, 870 accept_op->new_sock, 871 &accept_op->rem_addr, 872 accept_op->rem_addr_len, 873 status); 874 } else { 875 ret = (*asock->cb.on_accept_complete)(asock, 876 accept_op->new_sock, 877 &accept_op->rem_addr, 878 accept_op->rem_addr_len); 879 } 860 880 861 881 /* If callback returns false, we have been destroyed! */ -
pjproject/trunk/pjlib/src/pj/errno.c
r4359 r4461 79 79 PJ_BUILD_ERR(PJ_EIPV6NOTSUP, "IPv6 is not supported"), 80 80 PJ_BUILD_ERR(PJ_EAFNOTSUP, "Unsupported address family"), 81 PJ_BUILD_ERR(PJ_EGONE, "Object no longer exists") 81 PJ_BUILD_ERR(PJ_EGONE, "Object no longer exists"), 82 PJ_BUILD_ERR(PJ_ESOCKETSTOP, "Socket is in bad state") 82 83 }; 83 84 #endif /* PJ_HAS_ERROR_STRING */ -
pjproject/trunk/pjsip-apps/build/Makefile
r4440 r4461 34 34 export PJSUA_SRCDIR = ../src/pjsua 35 35 export PJSUA_OBJS += $(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \ 36 main.o pjsua_app.o pjsua_cmd.o pjsua_cli_cmd.o pjsua_ui_cmd.o 36 main.o pjsua_app.o pjsua_cli.o pjsua_cli_cmd.o pjsua_common.o \ 37 pjsua_config.o pjsua_legacy.o 37 38 export PJSUA_CFLAGS += $(_CFLAGS) 38 39 export PJSUA_LDFLAGS += $(APP_LDFLAGS) $(APP_LDLIBS) $(LDFLAGS) -
pjproject/trunk/pjsip-apps/build/pjsua.vcproj
r4440 r4461 3621 3621 </File> 3622 3622 <File 3623 RelativePath="..\src\pjsua\pjsua_cli.c" 3624 > 3625 </File> 3626 <File 3623 3627 RelativePath="..\src\pjsua\pjsua_cli_cmd.c" 3624 3628 > … … 4003 4007 </File> 4004 4008 <File 4005 RelativePath="..\src\pjsua\pjsua_c md.c"4009 RelativePath="..\src\pjsua\pjsua_common.c" 4006 4010 > 4007 <FileConfiguration4008 Name="Release|Win32"4009 >4010 <Tool4011 Name="VCCLCompilerTool"4012 AdditionalIncludeDirectories=""4013 PreprocessorDefinitions=""4014 />4015 </FileConfiguration>4016 <FileConfiguration4017 Name="Release|Pocket PC 2003 (ARMV4)"4018 >4019 <Tool4020 Name="VCCLCompilerTool"4021 AdditionalIncludeDirectories=""4022 PreprocessorDefinitions=""4023 />4024 </FileConfiguration>4025 <FileConfiguration4026 Name="Release|Smartphone 2003 (ARMV4)"4027 >4028 <Tool4029 Name="VCCLCompilerTool"4030 AdditionalIncludeDirectories=""4031 PreprocessorDefinitions=""4032 />4033 </FileConfiguration>4034 <FileConfiguration4035 Name="Debug|Win32"4036 >4037 <Tool4038 Name="VCCLCompilerTool"4039 AdditionalIncludeDirectories=""4040 PreprocessorDefinitions=""4041 />4042 </FileConfiguration>4043 <FileConfiguration4044 Name="Debug|Pocket PC 2003 (ARMV4)"4045 >4046 <Tool4047 Name="VCCLCompilerTool"4048 AdditionalIncludeDirectories=""4049 PreprocessorDefinitions=""4050 />4051 </FileConfiguration>4052 <FileConfiguration4053 Name="Debug|Smartphone 2003 (ARMV4)"4054 >4055 <Tool4056 Name="VCCLCompilerTool"4057 AdditionalIncludeDirectories=""4058 PreprocessorDefinitions=""4059 />4060 </FileConfiguration>4061 <FileConfiguration4062 Name="Debug-Static|Win32"4063 >4064 <Tool4065 Name="VCCLCompilerTool"4066 AdditionalIncludeDirectories=""4067 PreprocessorDefinitions=""4068 />4069 </FileConfiguration>4070 <FileConfiguration4071 Name="Debug-Static|Pocket PC 2003 (ARMV4)"4072 >4073 <Tool4074 Name="VCCLCompilerTool"4075 AdditionalIncludeDirectories=""4076 PreprocessorDefinitions=""4077 />4078 </FileConfiguration>4079 <FileConfiguration4080 Name="Debug-Static|Smartphone 2003 (ARMV4)"4081 >4082 <Tool4083 Name="VCCLCompilerTool"4084 AdditionalIncludeDirectories=""4085 PreprocessorDefinitions=""4086 />4087 </FileConfiguration>4088 <FileConfiguration4089 Name="Release-Dynamic|Win32"4090 >4091 <Tool4092 Name="VCCLCompilerTool"4093 AdditionalIncludeDirectories=""4094 PreprocessorDefinitions=""4095 />4096 </FileConfiguration>4097 <FileConfiguration4098 Name="Release-Dynamic|Pocket PC 2003 (ARMV4)"4099 >4100 <Tool4101 Name="VCCLCompilerTool"4102 AdditionalIncludeDirectories=""4103 PreprocessorDefinitions=""4104 />4105 </FileConfiguration>4106 <FileConfiguration4107 Name="Release-Dynamic|Smartphone 2003 (ARMV4)"4108 >4109 <Tool4110 Name="VCCLCompilerTool"4111 AdditionalIncludeDirectories=""4112 PreprocessorDefinitions=""4113 />4114 </FileConfiguration>4115 <FileConfiguration4116 Name="Debug-Dynamic|Win32"4117 >4118 <Tool4119 Name="VCCLCompilerTool"4120 AdditionalIncludeDirectories=""4121 PreprocessorDefinitions=""4122 />4123 </FileConfiguration>4124 <FileConfiguration4125 Name="Debug-Dynamic|Pocket PC 2003 (ARMV4)"4126 >4127 <Tool4128 Name="VCCLCompilerTool"4129 AdditionalIncludeDirectories=""4130 PreprocessorDefinitions=""4131 />4132 </FileConfiguration>4133 <FileConfiguration4134 Name="Debug-Dynamic|Smartphone 2003 (ARMV4)"4135 >4136 <Tool4137 Name="VCCLCompilerTool"4138 AdditionalIncludeDirectories=""4139 PreprocessorDefinitions=""4140 />4141 </FileConfiguration>4142 <FileConfiguration4143 Name="Release-Static|Win32"4144 >4145 <Tool4146 Name="VCCLCompilerTool"4147 AdditionalIncludeDirectories=""4148 PreprocessorDefinitions=""4149 />4150 </FileConfiguration>4151 <FileConfiguration4152 Name="Release-Static|Pocket PC 2003 (ARMV4)"4153 >4154 <Tool4155 Name="VCCLCompilerTool"4156 AdditionalIncludeDirectories=""4157 PreprocessorDefinitions=""4158 />4159 </FileConfiguration>4160 <FileConfiguration4161 Name="Release-Static|Smartphone 2003 (ARMV4)"4162 >4163 <Tool4164 Name="VCCLCompilerTool"4165 AdditionalIncludeDirectories=""4166 PreprocessorDefinitions=""4167 />4168 </FileConfiguration>4169 <FileConfiguration4170 Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)"4171 >4172 <Tool4173 Name="VCCLCompilerTool"4174 AdditionalIncludeDirectories=""4175 PreprocessorDefinitions=""4176 />4177 </FileConfiguration>4178 <FileConfiguration4179 Name="Release|Windows Mobile 6 Professional SDK (ARMV4I)"4180 >4181 <Tool4182 Name="VCCLCompilerTool"4183 AdditionalIncludeDirectories=""4184 PreprocessorDefinitions=""4185 />4186 </FileConfiguration>4187 <FileConfiguration4188 Name="Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"4189 >4190 <Tool4191 Name="VCCLCompilerTool"4192 AdditionalIncludeDirectories=""4193 PreprocessorDefinitions=""4194 />4195 </FileConfiguration>4196 <FileConfiguration4197 Name="Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"4198 >4199 <Tool4200 Name="VCCLCompilerTool"4201 AdditionalIncludeDirectories=""4202 PreprocessorDefinitions=""4203 />4204 </FileConfiguration>4205 <FileConfiguration4206 Name="Debug|Windows Mobile 6 Standard SDK (ARMV4I)"4207 >4208 <Tool4209 Name="VCCLCompilerTool"4210 AdditionalIncludeDirectories=""4211 PreprocessorDefinitions=""4212 />4213 </FileConfiguration>4214 <FileConfiguration4215 Name="Debug|Windows Mobile 6 Professional SDK (ARMV4I)"4216 >4217 <Tool4218 Name="VCCLCompilerTool"4219 AdditionalIncludeDirectories=""4220 PreprocessorDefinitions=""4221 />4222 </FileConfiguration>4223 <FileConfiguration4224 Name="Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"4225 >4226 <Tool4227 Name="VCCLCompilerTool"4228 AdditionalIncludeDirectories=""4229 PreprocessorDefinitions=""4230 />4231 </FileConfiguration>4232 <FileConfiguration4233 Name="Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"4234 >4235 <Tool4236 Name="VCCLCompilerTool"4237 AdditionalIncludeDirectories=""4238 PreprocessorDefinitions=""4239 />4240 </FileConfiguration>4241 <FileConfiguration4242 Name="Debug-Static|Windows Mobile 6 Standard SDK (ARMV4I)"4243 >4244 <Tool4245 Name="VCCLCompilerTool"4246 AdditionalIncludeDirectories=""4247 PreprocessorDefinitions=""4248 />4249 </FileConfiguration>4250 <FileConfiguration4251 Name="Debug-Static|Windows Mobile 6 Professional SDK (ARMV4I)"4252 >4253 <Tool4254 Name="VCCLCompilerTool"4255 AdditionalIncludeDirectories=""4256 PreprocessorDefinitions=""4257 />4258 </FileConfiguration>4259 <FileConfiguration4260 Name="Debug-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"4261 >4262 <Tool4263 Name="VCCLCompilerTool"4264 AdditionalIncludeDirectories=""4265 PreprocessorDefinitions=""4266 />4267 </FileConfiguration>4268 <FileConfiguration4269 Name="Debug-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"4270 >4271 <Tool4272 Name="VCCLCompilerTool"4273 AdditionalIncludeDirectories=""4274 PreprocessorDefinitions=""4275 />4276 </FileConfiguration>4277 <FileConfiguration4278 Name="Release-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"4279 >4280 <Tool4281 Name="VCCLCompilerTool"4282 AdditionalIncludeDirectories=""4283 PreprocessorDefinitions=""4284 />4285 </FileConfiguration>4286 <FileConfiguration4287 Name="Release-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"4288 >4289 <Tool4290 Name="VCCLCompilerTool"4291 AdditionalIncludeDirectories=""4292 PreprocessorDefinitions=""4293 />4294 </FileConfiguration>4295 <FileConfiguration4296 Name="Release-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"4297 >4298 <Tool4299 Name="VCCLCompilerTool"4300 AdditionalIncludeDirectories=""4301 PreprocessorDefinitions=""4302 />4303 </FileConfiguration>4304 <FileConfiguration4305 Name="Release-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"4306 >4307 <Tool4308 Name="VCCLCompilerTool"4309 AdditionalIncludeDirectories=""4310 PreprocessorDefinitions=""4311 />4312 </FileConfiguration>4313 <FileConfiguration4314 Name="Debug-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"4315 >4316 <Tool4317 Name="VCCLCompilerTool"4318 AdditionalIncludeDirectories=""4319 PreprocessorDefinitions=""4320 />4321 </FileConfiguration>4322 <FileConfiguration4323 Name="Debug-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"4324 >4325 <Tool4326 Name="VCCLCompilerTool"4327 AdditionalIncludeDirectories=""4328 PreprocessorDefinitions=""4329 />4330 </FileConfiguration>4331 <FileConfiguration4332 Name="Debug-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"4333 >4334 <Tool4335 Name="VCCLCompilerTool"4336 AdditionalIncludeDirectories=""4337 PreprocessorDefinitions=""4338 />4339 </FileConfiguration>4340 <FileConfiguration4341 Name="Debug-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"4342 >4343 <Tool4344 Name="VCCLCompilerTool"4345 AdditionalIncludeDirectories=""4346 PreprocessorDefinitions=""4347 />4348 </FileConfiguration>4349 <FileConfiguration4350 Name="Release-Static|Windows Mobile 6 Standard SDK (ARMV4I)"4351 >4352 <Tool4353 Name="VCCLCompilerTool"4354 AdditionalIncludeDirectories=""4355 PreprocessorDefinitions=""4356 />4357 </FileConfiguration>4358 <FileConfiguration4359 Name="Release-Static|Windows Mobile 6 Professional SDK (ARMV4I)"4360 >4361 <Tool4362 Name="VCCLCompilerTool"4363 AdditionalIncludeDirectories=""4364 PreprocessorDefinitions=""4365 />4366 </FileConfiguration>4367 <FileConfiguration4368 Name="Release-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"4369 >4370 <Tool4371 Name="VCCLCompilerTool"4372 AdditionalIncludeDirectories=""4373 PreprocessorDefinitions=""4374 />4375 </FileConfiguration>4376 <FileConfiguration4377 Name="Release-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"4378 >4379 <Tool4380 Name="VCCLCompilerTool"4381 AdditionalIncludeDirectories=""4382 PreprocessorDefinitions=""4383 />4384 </FileConfiguration>4385 4011 </File> 4386 4012 <File 4387 RelativePath="..\src\pjsua\pjsua_ ui_cmd.c"4013 RelativePath="..\src\pjsua\pjsua_config.c" 4388 4014 > 4389 <FileConfiguration 4390 Name="Release|Win32" 4391 > 4392 <Tool 4393 Name="VCCLCompilerTool" 4394 AdditionalIncludeDirectories="" 4395 PreprocessorDefinitions="" 4396 /> 4397 </FileConfiguration> 4398 <FileConfiguration 4399 Name="Release|Pocket PC 2003 (ARMV4)" 4400 > 4401 <Tool 4402 Name="VCCLCompilerTool" 4403 AdditionalIncludeDirectories="" 4404 PreprocessorDefinitions="" 4405 /> 4406 </FileConfiguration> 4407 <FileConfiguration 4408 Name="Release|Smartphone 2003 (ARMV4)" 4409 > 4410 <Tool 4411 Name="VCCLCompilerTool" 4412 AdditionalIncludeDirectories="" 4413 PreprocessorDefinitions="" 4414 /> 4415 </FileConfiguration> 4416 <FileConfiguration 4417 Name="Debug|Win32" 4418 > 4419 <Tool 4420 Name="VCCLCompilerTool" 4421 AdditionalIncludeDirectories="" 4422 PreprocessorDefinitions="" 4423 /> 4424 </FileConfiguration> 4425 <FileConfiguration 4426 Name="Debug|Pocket PC 2003 (ARMV4)" 4427 > 4428 <Tool 4429 Name="VCCLCompilerTool" 4430 AdditionalIncludeDirectories="" 4431 PreprocessorDefinitions="" 4432 /> 4433 </FileConfiguration> 4434 <FileConfiguration 4435 Name="Debug|Smartphone 2003 (ARMV4)" 4436 > 4437 <Tool 4438 Name="VCCLCompilerTool" 4439 AdditionalIncludeDirectories="" 4440 PreprocessorDefinitions="" 4441 /> 4442 </FileConfiguration> 4443 <FileConfiguration 4444 Name="Debug-Static|Win32" 4445 > 4446 <Tool 4447 Name="VCCLCompilerTool" 4448 AdditionalIncludeDirectories="" 4449 PreprocessorDefinitions="" 4450 /> 4451 </FileConfiguration> 4452 <FileConfiguration 4453 Name="Debug-Static|Pocket PC 2003 (ARMV4)" 4454 > 4455 <Tool 4456 Name="VCCLCompilerTool" 4457 AdditionalIncludeDirectories="" 4458 PreprocessorDefinitions="" 4459 /> 4460 </FileConfiguration> 4461 <FileConfiguration 4462 Name="Debug-Static|Smartphone 2003 (ARMV4)" 4463 > 4464 <Tool 4465 Name="VCCLCompilerTool" 4466 AdditionalIncludeDirectories="" 4467 PreprocessorDefinitions="" 4468 /> 4469 </FileConfiguration> 4470 <FileConfiguration 4471 Name="Release-Dynamic|Win32" 4472 > 4473 <Tool 4474 Name="VCCLCompilerTool" 4475 AdditionalIncludeDirectories="" 4476 PreprocessorDefinitions="" 4477 /> 4478 </FileConfiguration> 4479 <FileConfiguration 4480 Name="Release-Dynamic|Pocket PC 2003 (ARMV4)" 4481 > 4482 <Tool 4483 Name="VCCLCompilerTool" 4484 AdditionalIncludeDirectories="" 4485 PreprocessorDefinitions="" 4486 /> 4487 </FileConfiguration> 4488 <FileConfiguration 4489 Name="Release-Dynamic|Smartphone 2003 (ARMV4)" 4490 > 4491 <Tool 4492 Name="VCCLCompilerTool" 4493 AdditionalIncludeDirectories="" 4494 PreprocessorDefinitions="" 4495 /> 4496 </FileConfiguration> 4497 <FileConfiguration 4498 Name="Debug-Dynamic|Win32" 4499 > 4500 <Tool 4501 Name="VCCLCompilerTool" 4502 AdditionalIncludeDirectories="" 4503 PreprocessorDefinitions="" 4504 /> 4505 </FileConfiguration> 4506 <FileConfiguration 4507 Name="Debug-Dynamic|Pocket PC 2003 (ARMV4)" 4508 > 4509 <Tool 4510 Name="VCCLCompilerTool" 4511 AdditionalIncludeDirectories="" 4512 PreprocessorDefinitions="" 4513 /> 4514 </FileConfiguration> 4515 <FileConfiguration 4516 Name="Debug-Dynamic|Smartphone 2003 (ARMV4)" 4517 > 4518 <Tool 4519 Name="VCCLCompilerTool" 4520 AdditionalIncludeDirectories="" 4521 PreprocessorDefinitions="" 4522 /> 4523 </FileConfiguration> 4524 <FileConfiguration 4525 Name="Release-Static|Win32" 4526 > 4527 <Tool 4528 Name="VCCLCompilerTool" 4529 AdditionalIncludeDirectories="" 4530 PreprocessorDefinitions="" 4531 /> 4532 </FileConfiguration> 4533 <FileConfiguration 4534 Name="Release-Static|Pocket PC 2003 (ARMV4)" 4535 > 4536 <Tool 4537 Name="VCCLCompilerTool" 4538 AdditionalIncludeDirectories="" 4539 PreprocessorDefinitions="" 4540 /> 4541 </FileConfiguration> 4542 <FileConfiguration 4543 Name="Release-Static|Smartphone 2003 (ARMV4)" 4544 > 4545 <Tool 4546 Name="VCCLCompilerTool" 4547 AdditionalIncludeDirectories="" 4548 PreprocessorDefinitions="" 4549 /> 4550 </FileConfiguration> 4551 <FileConfiguration 4552 Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)" 4553 > 4554 <Tool 4555 Name="VCCLCompilerTool" 4556 AdditionalIncludeDirectories="" 4557 PreprocessorDefinitions="" 4558 /> 4559 </FileConfiguration> 4560 <FileConfiguration 4561 Name="Release|Windows Mobile 6 Professional SDK (ARMV4I)" 4562 > 4563 <Tool 4564 Name="VCCLCompilerTool" 4565 AdditionalIncludeDirectories="" 4566 PreprocessorDefinitions="" 4567 /> 4568 </FileConfiguration> 4569 <FileConfiguration 4570 Name="Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)" 4571 > 4572 <Tool 4573 Name="VCCLCompilerTool" 4574 AdditionalIncludeDirectories="" 4575 PreprocessorDefinitions="" 4576 /> 4577 </FileConfiguration> 4578 <FileConfiguration 4579 Name="Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)" 4580 > 4581 <Tool 4582 Name="VCCLCompilerTool" 4583 AdditionalIncludeDirectories="" 4584 PreprocessorDefinitions="" 4585 /> 4586 </FileConfiguration> 4587 <FileConfiguration 4588 Name="Debug|Windows Mobile 6 Standard SDK (ARMV4I)" 4589 > 4590 <Tool 4591 Name="VCCLCompilerTool" 4592 AdditionalIncludeDirectories="" 4593 PreprocessorDefinitions="" 4594 /> 4595 </FileConfiguration> 4596 <FileConfiguration 4597 Name="Debug|Windows Mobile 6 Professional SDK (ARMV4I)" 4598 > 4599 <Tool 4600 Name="VCCLCompilerTool" 4601 AdditionalIncludeDirectories="" 4602 PreprocessorDefinitions="" 4603 /> 4604 </FileConfiguration> 4605 <FileConfiguration 4606 Name="Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)" 4607 > 4608 <Tool 4609 Name="VCCLCompilerTool" 4610 AdditionalIncludeDirectories="" 4611 PreprocessorDefinitions="" 4612 /> 4613 </FileConfiguration> 4614 <FileConfiguration 4615 Name="Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)" 4616 > 4617 <Tool 4618 Name="VCCLCompilerTool" 4619 AdditionalIncludeDirectories="" 4620 PreprocessorDefinitions="" 4621 /> 4622 </FileConfiguration> 4623 <FileConfiguration 4624 Name="Debug-Static|Windows Mobile 6 Standard SDK (ARMV4I)" 4625 > 4626 <Tool 4627 Name="VCCLCompilerTool" 4628 AdditionalIncludeDirectories="" 4629 PreprocessorDefinitions="" 4630 /> 4631 </FileConfiguration> 4632 <FileConfiguration 4633 Name="Debug-Static|Windows Mobile 6 Professional SDK (ARMV4I)" 4634 > 4635 <Tool 4636 Name="VCCLCompilerTool" 4637 AdditionalIncludeDirectories="" 4638 PreprocessorDefinitions="" 4639 /> 4640 </FileConfiguration> 4641 <FileConfiguration 4642 Name="Debug-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)" 4643 > 4644 <Tool 4645 Name="VCCLCompilerTool" 4646 AdditionalIncludeDirectories="" 4647 PreprocessorDefinitions="" 4648 /> 4649 </FileConfiguration> 4650 <FileConfiguration 4651 Name="Debug-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)" 4652 > 4653 <Tool 4654 Name="VCCLCompilerTool" 4655 AdditionalIncludeDirectories="" 4656 PreprocessorDefinitions="" 4657 /> 4658 </FileConfiguration> 4659 <FileConfiguration 4660 Name="Release-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)" 4661 > 4662 <Tool 4663 Name="VCCLCompilerTool" 4664 AdditionalIncludeDirectories="" 4665 PreprocessorDefinitions="" 4666 /> 4667 </FileConfiguration> 4668 <FileConfiguration 4669 Name="Release-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)" 4670 > 4671 <Tool 4672 Name="VCCLCompilerTool" 4673 AdditionalIncludeDirectories="" 4674 PreprocessorDefinitions="" 4675 /> 4676 </FileConfiguration> 4677 <FileConfiguration 4678 Name="Release-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)" 4679 > 4680 <Tool 4681 Name="VCCLCompilerTool" 4682 AdditionalIncludeDirectories="" 4683 PreprocessorDefinitions="" 4684 /> 4685 </FileConfiguration> 4686 <FileConfiguration 4687 Name="Release-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)" 4688 > 4689 <Tool 4690 Name="VCCLCompilerTool" 4691 AdditionalIncludeDirectories="" 4692 PreprocessorDefinitions="" 4693 /> 4694 </FileConfiguration> 4695 <FileConfiguration 4696 Name="Debug-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)" 4697 > 4698 <Tool 4699 Name="VCCLCompilerTool" 4700 AdditionalIncludeDirectories="" 4701 PreprocessorDefinitions="" 4702 /> 4703 </FileConfiguration> 4704 <FileConfiguration 4705 Name="Debug-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)" 4706 > 4707 <Tool 4708 Name="VCCLCompilerTool" 4709 AdditionalIncludeDirectories="" 4710 PreprocessorDefinitions="" 4711 /> 4712 </FileConfiguration> 4713 <FileConfiguration 4714 Name="Debug-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)" 4715 > 4716 <Tool 4717 Name="VCCLCompilerTool" 4718 AdditionalIncludeDirectories="" 4719 PreprocessorDefinitions="" 4720 /> 4721 </FileConfiguration> 4722 <FileConfiguration 4723 Name="Debug-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)" 4724 > 4725 <Tool 4726 Name="VCCLCompilerTool" 4727 AdditionalIncludeDirectories="" 4728 PreprocessorDefinitions="" 4729 /> 4730 </FileConfiguration> 4731 <FileConfiguration 4732 Name="Release-Static|Windows Mobile 6 Standard SDK (ARMV4I)" 4733 > 4734 <Tool 4735 Name="VCCLCompilerTool" 4736 AdditionalIncludeDirectories="" 4737 PreprocessorDefinitions="" 4738 /> 4739 </FileConfiguration> 4740 <FileConfiguration 4741 Name="Release-Static|Windows Mobile 6 Professional SDK (ARMV4I)" 4742 > 4743 <Tool 4744 Name="VCCLCompilerTool" 4745 AdditionalIncludeDirectories="" 4746 PreprocessorDefinitions="" 4747 /> 4748 </FileConfiguration> 4749 <FileConfiguration 4750 Name="Release-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)" 4751 > 4752 <Tool 4753 Name="VCCLCompilerTool" 4754 AdditionalIncludeDirectories="" 4755 PreprocessorDefinitions="" 4756 /> 4757 </FileConfiguration> 4758 <FileConfiguration 4759 Name="Release-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)" 4760 > 4761 <Tool 4762 Name="VCCLCompilerTool" 4763 AdditionalIncludeDirectories="" 4764 PreprocessorDefinitions="" 4765 /> 4766 </FileConfiguration> 4015 </File> 4016 <File 4017 RelativePath="..\src\pjsua\pjsua_legacy.c" 4018 > 4767 4019 </File> 4768 4020 </Filter> … … 4772 4024 > 4773 4025 <File 4774 RelativePath="..\src\pjsua\pjsua_c md.h"4026 RelativePath="..\src\pjsua\pjsua_common.h" 4775 4027 > 4776 4028 </File> -
pjproject/trunk/pjsip-apps/src/pjsua/main.c
r4440 r4461 27 27 * These are defined in pjsua_app.c. 28 28 */ 29 extern pj_bool_t app_restart; 30 pj_status_t app_init(int argc, char *argv[]); 31 pj_status_t app_main(void); 32 pj_status_t app_destroy(); 33 pj_status_t receive_end_sig; 34 pj_thread_t *sig_thread; 35 36 #if defined(PJ_WIN32) && PJ_WIN32!=0 37 #include <windows.h> 38 39 static pj_thread_desc handler_desc; 40 41 static BOOL WINAPI CtrlHandler(DWORD fdwCtrlType) 42 { 43 switch (fdwCtrlType) 44 { 45 // Handle the CTRL+C signal. 46 47 case CTRL_C_EVENT: 48 case CTRL_CLOSE_EVENT: 49 case CTRL_BREAK_EVENT: 50 case CTRL_LOGOFF_EVENT: 51 case CTRL_SHUTDOWN_EVENT: 52 pj_thread_register("ctrlhandler", handler_desc, &sig_thread); 53 PJ_LOG(3,(THIS_FILE, "Ctrl-C detected, quitting..")); 54 receive_end_sig = PJ_TRUE; 55 app_destroy(); 56 ExitProcess(1); 57 PJ_UNREACHED(return TRUE;) 58 59 default: 60 61 return FALSE; 62 } 63 } 64 65 static void setup_signal_handler(void) 66 { 67 SetConsoleCtrlHandler(&CtrlHandler, TRUE); 68 } 69 70 static void setup_socket_signal() 71 { 72 } 73 74 #else 75 #include <signal.h> 76 77 static void setup_signal_handler(void) 78 { 79 } 80 81 static void setup_socket_signal() 82 { 83 signal(SIGPIPE, SIG_IGN); 84 } 85 86 #endif 87 88 static int main_func(int argc, char *argv[]) 89 { 90 receive_end_sig = PJ_FALSE; 91 setup_socket_signal(); 92 93 do { 94 app_restart = PJ_FALSE; 95 96 if (app_init(argc, argv) != PJ_SUCCESS) 97 return 1; 98 99 setup_signal_handler(); 100 101 app_main(); 102 if (!receive_end_sig) { 103 app_destroy(); 104 105 /* This is on purpose */ 106 app_destroy(); 107 } else { 108 pj_thread_join(sig_thread); 109 } 110 } while (app_restart); 111 112 return 0; 113 } 29 int main_func(int argc, char *argv[]); 114 30 115 31 int main(int argc, char *argv[]) -
pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c
r4440 r4461 18 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 19 */ 20 #include "pjsua_c md.h"20 #include "pjsua_common.h" 21 21 #include "gui.h" 22 22 … … 44 44 #define current_acc pjsua_acc_get_default() 45 45 46 static pj_str_t uri_arg;47 48 46 #ifdef STEREO_DEMO 49 47 static void stereo_demo(); … … 51 49 52 50 pj_status_t app_destroy(void); 51 53 52 static void ringback_start(pjsua_call_id call_id); 54 53 static void ring_start(pjsua_call_id call_id); 55 54 static void ring_stop(pjsua_call_id call_id); 56 55 57 pj_bool_t app_restart; 58 pj_log_func *log_cb = NULL; 59 static const char *stdout_refresh_text = "STDOUT_REFRESH"; 56 static pj_status_t receive_end_sig; 57 static pj_thread_t *sig_thread; 58 pj_str_t uri_arg; 59 pj_bool_t app_restart; 60 pj_bool_t app_running = PJ_FALSE; 61 pj_log_func *log_cb = NULL; 60 62 61 63 /** Forward declaration **/ 62 void console_app_main(const pj_str_t *uri_to_call, pj_bool_t *app_restart); 63 64 void cli_console_app_main(const pj_str_t *uri_to_call, pj_bool_t *app_restart); 64 /** Defined in pjsua_common.c **/ 65 65 void app_config_init_video(pjsua_acc_config *acc_cfg); 66 pj_status_t setup_cli(); 67 void destroy_cli(); 66 /** Defined in pjsua_legacy.c **/ 67 void start_ui_main(pj_str_t *uri_to_call, pj_bool_t *app_restart); 68 /** Defined in pjsua_cli.c **/ 69 void start_cli_main(pj_str_t *uri_to_call, pj_bool_t *app_restart); 70 pj_status_t setup_cli(pj_bool_t with_console, pj_bool_t with_telnet, 71 pj_uint16_t telnet_port, 72 pj_cli_telnet_on_started on_started_cb, 73 pj_cli_on_quit on_quit_cb, 74 pj_cli_on_destroy on_destroy_cb, 75 pj_cli_on_restart_pjsua on_restart_pjsua_cb); 76 void destroy_cli(pj_bool_t app_restart); 68 77 69 78 /***************************************************************************** … … 92 101 #endif 93 102 94 /* Show usage */95 static void usage(void)96 {97 puts ("Usage:");98 puts (" pjsua [options] [SIP URL to call]");99 puts ("");100 puts ("General options:");101 puts (" --config-file=file Read the config/arguments from file.");102 puts (" --help Display this help screen");103 puts (" --version Display version info");104 puts ("");105 puts ("Logging options:");106 puts (" --log-file=fname Log to filename (default stderr)");107 puts (" --log-level=N Set log max level to N (0(none) to 6(trace)) (default=5)");108 puts (" --app-log-level=N Set log max level for stdout display (default=4)");109 puts (" --log-append Append instead of overwrite existing log file.\n");110 puts (" --color Use colorful logging (default yes on Win32)");111 puts (" --no-color Disable colorful logging");112 puts (" --light-bg Use dark colors for light background (default is dark bg)");113 puts (" --no-stderr Disable stderr");114 115 puts ("");116 puts ("SIP Account options:");117 puts (" --registrar=url Set the URL of registrar server");118 puts (" --id=url Set the URL of local ID (used in From header)");119 puts (" --realm=string Set realm");120 puts (" --username=string Set authentication username");121 puts (" --password=string Set authentication password");122 puts (" --contact=url Optionally override the Contact information");123 puts (" --contact-params=S Append the specified parameters S in Contact header");124 puts (" --contact-uri-params=S Append the specified parameters S in Contact URI");125 puts (" --proxy=url Optional URL of proxy server to visit");126 puts (" May be specified multiple times");127 printf(" --reg-timeout=SEC Optional registration interval (default %d)\n",128 PJSUA_REG_INTERVAL);129 printf(" --rereg-delay=SEC Optional auto retry registration interval (default %d)\n",130 PJSUA_REG_RETRY_INTERVAL);131 puts (" --reg-use-proxy=N Control the use of proxy settings in REGISTER.");132 puts (" 0=no proxy, 1=outbound only, 2=acc only, 3=all (default)");133 puts (" --publish Send presence PUBLISH for this account");134 puts (" --mwi Subscribe to message summary/waiting indication");135 puts (" --use-ims Enable 3GPP/IMS related settings on this account");136 #if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)137 puts (" --use-srtp=N Use SRTP? 0:disabled, 1:optional, 2:mandatory,");138 puts (" 3:optional by duplicating media offer (def:0)");139 puts (" --srtp-secure=N SRTP require secure SIP? 0:no, 1:tls, 2:sips (def:1)");140 #endif141 puts (" --use-100rel Require reliable provisional response (100rel)");142 puts (" --use-timer=N Use SIP session timers? (default=1)");143 puts (" 0:inactive, 1:optional, 2:mandatory, 3:always");144 printf(" --timer-se=N Session timers expiration period, in secs (def:%d)\n",145 PJSIP_SESS_TIMER_DEF_SE);146 puts (" --timer-min-se=N Session timers minimum expiration period, in secs (def:90)");147 puts (" --outb-rid=string Set SIP outbound reg-id (default:1)");148 puts (" --auto-update-nat=N Where N is 0 or 1 to enable/disable SIP traversal behind");149 puts (" symmetric NAT (default 1)");150 puts (" --disable-stun Disable STUN for this account");151 puts (" --next-cred Add another credentials");152 puts ("");153 puts ("SIP Account Control:");154 puts (" --next-account Add more account");155 puts ("");156 puts ("Transport Options:");157 #if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6158 puts (" --ipv6 Use IPv6 instead for SIP and media.");159 #endif160 puts (" --set-qos Enable QoS tagging for SIP and media.");161 puts (" --local-port=port Set TCP/UDP port. This implicitly enables both ");162 puts (" TCP and UDP transports on the specified port, unless");163 puts (" if TCP or UDP is disabled.");164 puts (" --ip-addr=IP Use the specifed address as SIP and RTP addresses.");165 puts (" (Hint: the IP may be the public IP of the NAT/router)");166 puts (" --bound-addr=IP Bind transports to this IP interface");167 puts (" --no-tcp Disable TCP transport.");168 puts (" --no-udp Disable UDP transport.");169 puts (" --nameserver=NS Add the specified nameserver to enable SRV resolution");170 puts (" This option can be specified multiple times.");171 puts (" --outbound=url Set the URL of global outbound proxy server");172 puts (" May be specified multiple times");173 puts (" --stun-srv=FORMAT Set STUN server host or domain. This option may be");174 puts (" specified more than once. FORMAT is hostdom[:PORT]");175 176 #if defined(PJSIP_HAS_TLS_TRANSPORT) && (PJSIP_HAS_TLS_TRANSPORT != 0)177 puts ("");178 puts ("TLS Options:");179 puts (" --use-tls Enable TLS transport (default=no)");180 puts (" --tls-ca-file Specify TLS CA file (default=none)");181 puts (" --tls-cert-file Specify TLS certificate file (default=none)");182 puts (" --tls-privkey-file Specify TLS private key file (default=none)");183 puts (" --tls-password Specify TLS password to private key file (default=none)");184 puts (" --tls-verify-server Verify server's certificate (default=no)");185 puts (" --tls-verify-client Verify client's certificate (default=no)");186 puts (" --tls-neg-timeout Specify TLS negotiation timeout (default=no)");187 puts (" --tls-srv-name Specify TLS server name for multihosting server");188 puts (" --tls-cipher Specify prefered TLS cipher (optional).");189 puts (" May be specified multiple times");190 #endif191 192 puts ("");193 puts ("Audio Options:");194 puts (" --add-codec=name Manually add codec (default is to enable all)");195 puts (" --dis-codec=name Disable codec (can be specified multiple times)");196 puts (" --clock-rate=N Override conference bridge clock rate");197 puts (" --snd-clock-rate=N Override sound device clock rate");198 puts (" --stereo Audio device and conference bridge opened in stereo mode");199 puts (" --null-audio Use NULL audio device");200 puts (" --play-file=file Register WAV file in conference bridge.");201 puts (" This can be specified multiple times.");202 puts (" --play-tone=FORMAT Register tone to the conference bridge.");203 puts (" FORMAT is 'F1,F2,ON,OFF', where F1,F2 are");204 puts (" frequencies, and ON,OFF=on/off duration in msec.");205 puts (" This can be specified multiple times.");206 puts (" --auto-play Automatically play the file (to incoming calls only)");207 puts (" --auto-loop Automatically loop incoming RTP to outgoing RTP");208 puts (" --auto-conf Automatically put calls in conference with others");209 puts (" --rec-file=file Open file recorder (extension can be .wav or .mp3");210 puts (" --auto-rec Automatically record conversation");211 puts (" --quality=N Specify media quality (0-10, default=6)");212 puts (" --ptime=MSEC Override codec ptime to MSEC (default=specific)");213 puts (" --no-vad Disable VAD/silence detector (default=vad enabled)");214 puts (" --ec-tail=MSEC Set echo canceller tail length (default=256)");215 puts (" --ec-opt=OPT Select echo canceller algorithm (0=default, ");216 puts (" 1=speex, 2=suppressor)");217 puts (" --ilbc-mode=MODE Set iLBC codec mode (20 or 30, default is 30)");218 puts (" --capture-dev=id Audio capture device ID (default=-1)");219 puts (" --playback-dev=id Audio playback device ID (default=-1)");220 puts (" --capture-lat=N Audio capture latency, in ms (default=100)");221 puts (" --playback-lat=N Audio playback latency, in ms (default=100)");222 puts (" --snd-auto-close=N Auto close audio device when idle for N secs (default=1)");223 puts (" Specify N=-1 to disable this feature.");224 puts (" Specify N=0 for instant close when unused.");225 puts (" --no-tones Disable audible tones");226 puts (" --jb-max-size Specify jitter buffer maximum size, in frames (default=-1)");227 puts (" --extra-audio Add one more audio stream");228 229 #if PJSUA_HAS_VIDEO230 puts ("");231 puts ("Video Options:");232 puts (" --video Enable video");233 puts (" --vcapture-dev=id Video capture device ID (default=-1)");234 puts (" --vrender-dev=id Video render device ID (default=-2)");235 puts (" --play-avi=FILE Load this AVI as virtual capture device");236 puts (" --auto-play-avi Automatically play the AVI media to call");237 #endif238 239 puts ("");240 puts ("Media Transport Options:");241 puts (" --use-ice Enable ICE (default:no)");242 puts (" --ice-regular Use ICE regular nomination (default: aggressive)");243 puts (" --ice-max-hosts=N Set maximum number of ICE host candidates");244 puts (" --ice-no-rtcp Disable RTCP component in ICE (default: no)");245 puts (" --rtp-port=N Base port to try for RTP (default=4000)");246 puts (" --rx-drop-pct=PCT Drop PCT percent of RX RTP (for pkt lost sim, default: 0)");247 puts (" --tx-drop-pct=PCT Drop PCT percent of TX RTP (for pkt lost sim, default: 0)");248 puts (" --use-turn Enable TURN relay with ICE (default:no)");249 puts (" --turn-srv Domain or host name of TURN server (\"NAME:PORT\" format)");250 puts (" --turn-tcp Use TCP connection to TURN server (default no)");251 puts (" --turn-user TURN username");252 puts (" --turn-passwd TURN password");253 254 puts ("");255 puts ("Buddy List (can be more than one):");256 puts (" --add-buddy url Add the specified URL to the buddy list.");257 puts ("");258 puts ("User Agent options:");259 puts (" --auto-answer=code Automatically answer incoming calls with code (e.g. 200)");260 puts (" --max-calls=N Maximum number of concurrent calls (default:4, max:255)");261 puts (" --thread-cnt=N Number of worker threads (default:1)");262 puts (" --duration=SEC Set maximum call duration (default:no limit)");263 puts (" --norefersub Suppress event subscription when transfering calls");264 puts (" --use-compact-form Minimize SIP message size");265 puts (" --no-force-lr Allow strict-route to be used (i.e. do not force lr)");266 puts (" --accept-redirect=N Specify how to handle call redirect (3xx) response.");267 puts (" 0: reject, 1: follow automatically,");268 puts (" 2: follow + replace To header (default), 3: ask");269 270 puts ("");271 puts ("CLI options:");272 puts (" --use-cli Use CLI as user interface");273 puts (" --cli-telnet-port=N CLI telnet port");274 puts ("");275 276 puts ("");277 puts ("When URL is specified, pjsua will immediately initiate call to that URL");278 puts ("");279 280 fflush(stdout);281 }282 283 static int stdout_refresh_proc(void *arg)284 {285 PJ_UNUSED_ARG(arg);286 287 /* Set thread to lowest priority so that it doesn't clobber288 * stdout output289 */290 pj_thread_set_prio(pj_thread_this(),291 pj_thread_get_prio_min(pj_thread_this()));292 293 while (!stdout_refresh_quit) {294 pj_thread_sleep(stdout_refresh * 1000);295 puts(stdout_refresh_text);296 fflush(stdout);297 }298 299 return 0;300 }301 302 /* Set default config. */303 static void default_config(pjsua_app_config *cfg)304 {305 char tmp[80];306 unsigned i;307 308 pjsua_config_default(&cfg->cfg);309 pj_ansi_sprintf(tmp, "PJSUA v%s %s", pj_get_version(),310 pj_get_sys_info()->info.ptr);311 pj_strdup2_with_null(app_config.pool, &cfg->cfg.user_agent, tmp);312 313 pjsua_logging_config_default(&cfg->log_cfg);314 pjsua_media_config_default(&cfg->media_cfg);315 pjsua_transport_config_default(&cfg->udp_cfg);316 cfg->udp_cfg.port = 5060;317 pjsua_transport_config_default(&cfg->rtp_cfg);318 cfg->rtp_cfg.port = 4000;319 cfg->redir_op = PJSIP_REDIRECT_ACCEPT_REPLACE;320 cfg->duration = NO_LIMIT_DURATION;321 cfg->wav_id = PJSUA_INVALID_ID;322 cfg->rec_id = PJSUA_INVALID_ID;323 cfg->wav_port = PJSUA_INVALID_ID;324 cfg->rec_port = PJSUA_INVALID_ID;325 cfg->mic_level = cfg->speaker_level = 1.0;326 cfg->capture_dev = PJSUA_INVALID_ID;327 cfg->playback_dev = PJSUA_INVALID_ID;328 cfg->capture_lat = PJMEDIA_SND_DEFAULT_REC_LATENCY;329 cfg->playback_lat = PJMEDIA_SND_DEFAULT_PLAY_LATENCY;330 cfg->ringback_slot = PJSUA_INVALID_ID;331 cfg->ring_slot = PJSUA_INVALID_ID;332 333 for (i=0; i<PJ_ARRAY_SIZE(cfg->acc_cfg); ++i)334 pjsua_acc_config_default(&cfg->acc_cfg[i]);335 336 for (i=0; i<PJ_ARRAY_SIZE(cfg->buddy_cfg); ++i)337 pjsua_buddy_config_default(&cfg->buddy_cfg[i]);338 339 cfg->vid.vcapture_dev = PJMEDIA_VID_DEFAULT_CAPTURE_DEV;340 cfg->vid.vrender_dev = PJMEDIA_VID_DEFAULT_RENDER_DEV;341 cfg->aud_cnt = 1;342 343 cfg->avi_def_idx = PJSUA_INVALID_ID;344 345 cfg->use_cli = PJ_FALSE;346 cfg->cli_telnet_port = 0;347 }348 349 /*350 * Read command arguments from config file.351 */352 static int read_config_file(pj_pool_t *pool, const char *filename,353 int *app_argc, char ***app_argv)354 {355 int i;356 FILE *fhnd;357 char line[200];358 int argc = 0;359 char **argv;360 enum { MAX_ARGS = 128 };361 362 /* Allocate MAX_ARGS+1 (argv needs to be terminated with NULL argument) */363 argv = pj_pool_calloc(pool, MAX_ARGS+1, sizeof(char*));364 argv[argc++] = *app_argv[0];365 366 /* Open config file. */367 fhnd = fopen(filename, "rt");368 if (!fhnd) {369 PJ_LOG(1,(THIS_FILE, "Unable to open config file %s", filename));370 fflush(stdout);371 return -1;372 }373 374 /* Scan tokens in the file. */375 while (argc < MAX_ARGS && !feof(fhnd)) {376 char *token;377 char *p;378 const char *whitespace = " \t\r\n";379 char cDelimiter;380 int len, token_len;381 382 pj_bzero(line, sizeof(line));383 if (fgets(line, sizeof(line), fhnd) == NULL) break;384 385 // Trim ending newlines386 len = strlen(line);387 if (line[len-1]=='\n')388 line[--len] = '\0';389 if (line[len-1]=='\r')390 line[--len] = '\0';391 392 if (len==0) continue;393 394 for (p = line; *p != '\0' && argc < MAX_ARGS; p++) {395 // first, scan whitespaces396 while (*p != '\0' && strchr(whitespace, *p) != NULL) p++;397 398 if (*p == '\0') // are we done yet?399 break;400 401 if (*p == '"' || *p == '\'') { // is token a quoted string402 cDelimiter = *p++; // save quote delimiter403 token = p;404 405 while (*p != '\0' && *p != cDelimiter) p++;406 407 if (*p == '\0') // found end of the line, but,408 cDelimiter = '\0'; // didn't find a matching quote409 410 } else { // token's not a quoted string411 token = p;412 413 while (*p != '\0' && strchr(whitespace, *p) == NULL) p++;414 415 cDelimiter = *p;416 }417 418 *p = '\0';419 token_len = p-token;420 421 if (token_len > 0) {422 if (*token == '#')423 break; // ignore remainder of line424 425 argv[argc] = pj_pool_alloc(pool, token_len + 1);426 pj_memcpy(argv[argc], token, token_len + 1);427 ++argc;428 }429 430 *p = cDelimiter;431 }432 }433 434 /* Copy arguments from command line */435 for (i=1; i<*app_argc && argc < MAX_ARGS; ++i)436 argv[argc++] = (*app_argv)[i];437 438 if (argc == MAX_ARGS && (i!=*app_argc || !feof(fhnd))) {439 PJ_LOG(1,(THIS_FILE,440 "Too many arguments specified in cmd line/config file"));441 fflush(stdout);442 fclose(fhnd);443 return -1;444 }445 446 fclose(fhnd);447 448 /* Assign the new command line back to the original command line. */449 *app_argc = argc;450 *app_argv = argv;451 return 0;452 }453 454 /* Parse arguments. */455 static pj_status_t parse_args(int argc, char *argv[],456 pjsua_app_config *cfg,457 pj_str_t *uri_to_call)458 {459 int c;460 int option_index;461 enum { OPT_CONFIG_FILE=127, OPT_LOG_FILE, OPT_LOG_LEVEL, OPT_APP_LOG_LEVEL,462 OPT_LOG_APPEND, OPT_COLOR, OPT_NO_COLOR, OPT_LIGHT_BG, OPT_NO_STDERR,463 OPT_HELP, OPT_VERSION, OPT_NULL_AUDIO, OPT_SND_AUTO_CLOSE,464 OPT_LOCAL_PORT, OPT_IP_ADDR, OPT_PROXY, OPT_OUTBOUND_PROXY,465 OPT_REGISTRAR, OPT_REG_TIMEOUT, OPT_PUBLISH, OPT_ID, OPT_CONTACT,466 OPT_BOUND_ADDR, OPT_CONTACT_PARAMS, OPT_CONTACT_URI_PARAMS,467 OPT_100REL, OPT_USE_IMS, OPT_REALM, OPT_USERNAME, OPT_PASSWORD,468 OPT_REG_RETRY_INTERVAL, OPT_REG_USE_PROXY,469 OPT_MWI, OPT_NAMESERVER, OPT_STUN_SRV, OPT_OUTB_RID,470 OPT_ADD_BUDDY, OPT_OFFER_X_MS_MSG, OPT_NO_PRESENCE,471 OPT_AUTO_ANSWER, OPT_AUTO_PLAY, OPT_AUTO_PLAY_HANGUP, OPT_AUTO_LOOP,472 OPT_AUTO_CONF, OPT_CLOCK_RATE, OPT_SND_CLOCK_RATE, OPT_STEREO,473 OPT_USE_ICE, OPT_ICE_REGULAR, OPT_USE_SRTP, OPT_SRTP_SECURE,474 OPT_USE_TURN, OPT_ICE_MAX_HOSTS, OPT_ICE_NO_RTCP, OPT_TURN_SRV,475 OPT_TURN_TCP, OPT_TURN_USER, OPT_TURN_PASSWD,476 OPT_PLAY_FILE, OPT_PLAY_TONE, OPT_RTP_PORT, OPT_ADD_CODEC,477 OPT_ILBC_MODE, OPT_REC_FILE, OPT_AUTO_REC,478 OPT_COMPLEXITY, OPT_QUALITY, OPT_PTIME, OPT_NO_VAD,479 OPT_RX_DROP_PCT, OPT_TX_DROP_PCT, OPT_EC_TAIL, OPT_EC_OPT,480 OPT_NEXT_ACCOUNT, OPT_NEXT_CRED, OPT_MAX_CALLS,481 OPT_DURATION, OPT_NO_TCP, OPT_NO_UDP, OPT_THREAD_CNT,482 OPT_NOREFERSUB, OPT_ACCEPT_REDIRECT,483 OPT_USE_TLS, OPT_TLS_CA_FILE, OPT_TLS_CERT_FILE, OPT_TLS_PRIV_FILE,484 OPT_TLS_PASSWORD, OPT_TLS_VERIFY_SERVER, OPT_TLS_VERIFY_CLIENT,485 OPT_TLS_NEG_TIMEOUT, OPT_TLS_CIPHER,486 OPT_CAPTURE_DEV, OPT_PLAYBACK_DEV,487 OPT_CAPTURE_LAT, OPT_PLAYBACK_LAT, OPT_NO_TONES, OPT_JB_MAX_SIZE,488 OPT_STDOUT_REFRESH, OPT_STDOUT_REFRESH_TEXT, OPT_IPV6, OPT_QOS,489 #ifdef _IONBF490 OPT_STDOUT_NO_BUF,491 #endif492 OPT_AUTO_UPDATE_NAT,OPT_USE_COMPACT_FORM,OPT_DIS_CODEC,493 OPT_DISABLE_STUN, OPT_NO_FORCE_LR,494 OPT_TIMER, OPT_TIMER_SE, OPT_TIMER_MIN_SE,495 OPT_VIDEO, OPT_EXTRA_AUDIO,496 OPT_VCAPTURE_DEV, OPT_VRENDER_DEV, OPT_PLAY_AVI, OPT_AUTO_PLAY_AVI,497 OPT_USE_CLI, OPT_CLI_TELNET_PORT498 };499 struct pj_getopt_option long_options[] = {500 { "config-file",1, 0, OPT_CONFIG_FILE},501 { "log-file", 1, 0, OPT_LOG_FILE},502 { "log-level", 1, 0, OPT_LOG_LEVEL},503 { "app-log-level",1,0,OPT_APP_LOG_LEVEL},504 { "log-append", 0, 0, OPT_LOG_APPEND},505 { "color", 0, 0, OPT_COLOR},506 { "no-color", 0, 0, OPT_NO_COLOR},507 { "light-bg", 0, 0, OPT_LIGHT_BG},508 { "no-stderr", 0, 0, OPT_NO_STDERR},509 { "help", 0, 0, OPT_HELP},510 { "version", 0, 0, OPT_VERSION},511 { "clock-rate", 1, 0, OPT_CLOCK_RATE},512 { "snd-clock-rate", 1, 0, OPT_SND_CLOCK_RATE},513 { "stereo", 0, 0, OPT_STEREO},514 { "null-audio", 0, 0, OPT_NULL_AUDIO},515 { "local-port", 1, 0, OPT_LOCAL_PORT},516 { "ip-addr", 1, 0, OPT_IP_ADDR},517 { "bound-addr", 1, 0, OPT_BOUND_ADDR},518 { "no-tcp", 0, 0, OPT_NO_TCP},519 { "no-udp", 0, 0, OPT_NO_UDP},520 { "norefersub", 0, 0, OPT_NOREFERSUB},521 { "proxy", 1, 0, OPT_PROXY},522 { "outbound", 1, 0, OPT_OUTBOUND_PROXY},523 { "registrar", 1, 0, OPT_REGISTRAR},524 { "reg-timeout",1, 0, OPT_REG_TIMEOUT},525 { "publish", 0, 0, OPT_PUBLISH},526 { "mwi", 0, 0, OPT_MWI},527 { "use-100rel", 0, 0, OPT_100REL},528 { "use-ims", 0, 0, OPT_USE_IMS},529 { "id", 1, 0, OPT_ID},530 { "contact", 1, 0, OPT_CONTACT},531 { "contact-params",1,0, OPT_CONTACT_PARAMS},532 { "contact-uri-params",1,0, OPT_CONTACT_URI_PARAMS},533 { "auto-update-nat", 1, 0, OPT_AUTO_UPDATE_NAT},534 { "disable-stun",0,0, OPT_DISABLE_STUN},535 { "use-compact-form", 0, 0, OPT_USE_COMPACT_FORM},536 { "accept-redirect", 1, 0, OPT_ACCEPT_REDIRECT},537 { "no-force-lr",0, 0, OPT_NO_FORCE_LR},538 { "realm", 1, 0, OPT_REALM},539 { "username", 1, 0, OPT_USERNAME},540 { "password", 1, 0, OPT_PASSWORD},541 { "rereg-delay",1, 0, OPT_REG_RETRY_INTERVAL},542 { "reg-use-proxy", 1, 0, OPT_REG_USE_PROXY},543 { "nameserver", 1, 0, OPT_NAMESERVER},544 { "stun-srv", 1, 0, OPT_STUN_SRV},545 { "add-buddy", 1, 0, OPT_ADD_BUDDY},546 { "offer-x-ms-msg",0,0,OPT_OFFER_X_MS_MSG},547 { "no-presence", 0, 0, OPT_NO_PRESENCE},548 { "auto-answer",1, 0, OPT_AUTO_ANSWER},549 { "auto-play", 0, 0, OPT_AUTO_PLAY},550 { "auto-play-hangup",0, 0, OPT_AUTO_PLAY_HANGUP},551 { "auto-rec", 0, 0, OPT_AUTO_REC},552 { "auto-loop", 0, 0, OPT_AUTO_LOOP},553 { "auto-conf", 0, 0, OPT_AUTO_CONF},554 { "play-file", 1, 0, OPT_PLAY_FILE},555 { "play-tone", 1, 0, OPT_PLAY_TONE},556 { "rec-file", 1, 0, OPT_REC_FILE},557 { "rtp-port", 1, 0, OPT_RTP_PORT},558 559 { "use-ice", 0, 0, OPT_USE_ICE},560 { "ice-regular",0, 0, OPT_ICE_REGULAR},561 { "use-turn", 0, 0, OPT_USE_TURN},562 { "ice-max-hosts",1, 0, OPT_ICE_MAX_HOSTS},563 { "ice-no-rtcp",0, 0, OPT_ICE_NO_RTCP},564 { "turn-srv", 1, 0, OPT_TURN_SRV},565 { "turn-tcp", 0, 0, OPT_TURN_TCP},566 { "turn-user", 1, 0, OPT_TURN_USER},567 { "turn-passwd",1, 0, OPT_TURN_PASSWD},568 569 #if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)570 { "use-srtp", 1, 0, OPT_USE_SRTP},571 { "srtp-secure",1, 0, OPT_SRTP_SECURE},572 #endif573 { "add-codec", 1, 0, OPT_ADD_CODEC},574 { "dis-codec", 1, 0, OPT_DIS_CODEC},575 { "complexity", 1, 0, OPT_COMPLEXITY},576 { "quality", 1, 0, OPT_QUALITY},577 { "ptime", 1, 0, OPT_PTIME},578 { "no-vad", 0, 0, OPT_NO_VAD},579 { "ec-tail", 1, 0, OPT_EC_TAIL},580 { "ec-opt", 1, 0, OPT_EC_OPT},581 { "ilbc-mode", 1, 0, OPT_ILBC_MODE},582 { "rx-drop-pct",1, 0, OPT_RX_DROP_PCT},583 { "tx-drop-pct",1, 0, OPT_TX_DROP_PCT},584 { "next-account",0,0, OPT_NEXT_ACCOUNT},585 { "next-cred", 0, 0, OPT_NEXT_CRED},586 { "max-calls", 1, 0, OPT_MAX_CALLS},587 { "duration", 1, 0, OPT_DURATION},588 { "thread-cnt", 1, 0, OPT_THREAD_CNT},589 #if defined(PJSIP_HAS_TLS_TRANSPORT) && (PJSIP_HAS_TLS_TRANSPORT != 0)590 { "use-tls", 0, 0, OPT_USE_TLS},591 { "tls-ca-file",1, 0, OPT_TLS_CA_FILE},592 { "tls-cert-file",1,0, OPT_TLS_CERT_FILE},593 { "tls-privkey-file",1,0, OPT_TLS_PRIV_FILE},594 { "tls-password",1,0, OPT_TLS_PASSWORD},595 { "tls-verify-server", 0, 0, OPT_TLS_VERIFY_SERVER},596 { "tls-verify-client", 0, 0, OPT_TLS_VERIFY_CLIENT},597 { "tls-neg-timeout", 1, 0, OPT_TLS_NEG_TIMEOUT},598 { "tls-cipher", 1, 0, OPT_TLS_CIPHER},599 #endif600 { "capture-dev", 1, 0, OPT_CAPTURE_DEV},601 { "playback-dev", 1, 0, OPT_PLAYBACK_DEV},602 { "capture-lat", 1, 0, OPT_CAPTURE_LAT},603 { "playback-lat", 1, 0, OPT_PLAYBACK_LAT},604 { "stdout-refresh", 1, 0, OPT_STDOUT_REFRESH},605 { "stdout-refresh-text", 1, 0, OPT_STDOUT_REFRESH_TEXT},606 #ifdef _IONBF607 { "stdout-no-buf", 0, 0, OPT_STDOUT_NO_BUF },608 #endif609 { "snd-auto-close", 1, 0, OPT_SND_AUTO_CLOSE},610 { "no-tones", 0, 0, OPT_NO_TONES},611 { "jb-max-size", 1, 0, OPT_JB_MAX_SIZE},612 #if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6613 { "ipv6", 0, 0, OPT_IPV6},614 #endif615 { "set-qos", 0, 0, OPT_QOS},616 { "use-timer", 1, 0, OPT_TIMER},617 { "timer-se", 1, 0, OPT_TIMER_SE},618 { "timer-min-se", 1, 0, OPT_TIMER_MIN_SE},619 { "outb-rid", 1, 0, OPT_OUTB_RID},620 { "video", 0, 0, OPT_VIDEO},621 { "extra-audio",0, 0, OPT_EXTRA_AUDIO},622 { "vcapture-dev", 1, 0, OPT_VCAPTURE_DEV},623 { "vrender-dev", 1, 0, OPT_VRENDER_DEV},624 { "play-avi", 1, 0, OPT_PLAY_AVI},625 { "auto-play-avi", 0, 0, OPT_AUTO_PLAY_AVI},626 { "use-cli", 0, 0, OPT_USE_CLI},627 { "cli-telnet-port", 1, 0, OPT_CLI_TELNET_PORT},628 { NULL, 0, 0, 0}629 };630 pj_status_t status;631 pjsua_acc_config *cur_acc;632 char *config_file = NULL;633 unsigned i;634 635 /* Run pj_getopt once to see if user specifies config file to read. */636 pj_optind = 0;637 while ((c=pj_getopt_long(argc, argv, "", long_options,638 &option_index)) != -1)639 {640 switch (c) {641 case OPT_CONFIG_FILE:642 config_file = pj_optarg;643 break;644 }645 if (config_file)646 break;647 }648 649 if (config_file) {650 status = read_config_file(cfg->pool, config_file, &argc, &argv);651 if (status != 0)652 return status;653 }654 655 cfg->acc_cnt = 0;656 cur_acc = &cfg->acc_cfg[0];657 658 659 /* Reinitialize and re-run pj_getopt again, possibly with new arguments660 * read from config file.661 */662 pj_optind = 0;663 while((c=pj_getopt_long(argc,argv, "", long_options,&option_index))!=-1) {664 pj_str_t tmp;665 long lval;666 667 switch (c) {668 669 case OPT_CONFIG_FILE:670 /* Ignore as this has been processed before */671 break;672 673 case OPT_LOG_FILE:674 cfg->log_cfg.log_filename = pj_str(pj_optarg);675 break;676 677 case OPT_LOG_LEVEL:678 c = pj_strtoul(pj_cstr(&tmp, pj_optarg));679 if (c < 0 || c > 6) {680 PJ_LOG(1,(THIS_FILE,681 "Error: expecting integer value 0-6 "682 "for --log-level"));683 return PJ_EINVAL;684 }685 cfg->log_cfg.level = c;686 pj_log_set_level( c );687 break;688 689 case OPT_APP_LOG_LEVEL:690 cfg->log_cfg.console_level = pj_strtoul(pj_cstr(&tmp, pj_optarg));691 if (cfg->log_cfg.console_level < 0 || cfg->log_cfg.console_level > 6) {692 PJ_LOG(1,(THIS_FILE,693 "Error: expecting integer value 0-6 "694 "for --app-log-level"));695 return PJ_EINVAL;696 }697 break;698 699 case OPT_LOG_APPEND:700 cfg->log_cfg.log_file_flags |= PJ_O_APPEND;701 break;702 703 case OPT_COLOR:704 cfg->log_cfg.decor |= PJ_LOG_HAS_COLOR;705 break;706 707 case OPT_NO_COLOR:708 cfg->log_cfg.decor &= ~PJ_LOG_HAS_COLOR;709 break;710 711 case OPT_LIGHT_BG:712 pj_log_set_color(1, PJ_TERM_COLOR_R);713 pj_log_set_color(2, PJ_TERM_COLOR_R | PJ_TERM_COLOR_G);714 pj_log_set_color(3, PJ_TERM_COLOR_B | PJ_TERM_COLOR_G);715 pj_log_set_color(4, 0);716 pj_log_set_color(5, 0);717 pj_log_set_color(77, 0);718 break;719 720 case OPT_NO_STDERR:721 freopen("/dev/null", "w", stderr);722 break;723 724 case OPT_HELP:725 usage();726 return PJ_EINVAL;727 728 case OPT_VERSION: /* version */729 pj_dump_config();730 return PJ_EINVAL;731 732 case OPT_NULL_AUDIO:733 cfg->null_audio = PJ_TRUE;734 break;735 736 case OPT_CLOCK_RATE:737 lval = pj_strtoul(pj_cstr(&tmp, pj_optarg));738 if (lval < 8000 || lval > 192000) {739 PJ_LOG(1,(THIS_FILE, "Error: expecting value between "740 "8000-192000 for conference clock rate"));741 return PJ_EINVAL;742 }743 cfg->media_cfg.clock_rate = lval;744 break;745 746 case OPT_SND_CLOCK_RATE:747 lval = pj_strtoul(pj_cstr(&tmp, pj_optarg));748 if (lval < 8000 || lval > 192000) {749 PJ_LOG(1,(THIS_FILE, "Error: expecting value between "750 "8000-192000 for sound device clock rate"));751 return PJ_EINVAL;752 }753 cfg->media_cfg.snd_clock_rate = lval;754 break;755 756 case OPT_STEREO:757 cfg->media_cfg.channel_count = 2;758 break;759 760 case OPT_LOCAL_PORT: /* local-port */761 lval = pj_strtoul(pj_cstr(&tmp, pj_optarg));762 if (lval < 0 || lval > 65535) {763 PJ_LOG(1,(THIS_FILE,764 "Error: expecting integer value for "765 "--local-port"));766 return PJ_EINVAL;767 }768 cfg->udp_cfg.port = (pj_uint16_t)lval;769 break;770 771 case OPT_IP_ADDR: /* ip-addr */772 cfg->udp_cfg.public_addr = pj_str(pj_optarg);773 cfg->rtp_cfg.public_addr = pj_str(pj_optarg);774 break;775 776 case OPT_BOUND_ADDR: /* bound-addr */777 cfg->udp_cfg.bound_addr = pj_str(pj_optarg);778 cfg->rtp_cfg.bound_addr = pj_str(pj_optarg);779 break;780 781 case OPT_NO_UDP: /* no-udp */782 if (cfg->no_tcp && !cfg->use_tls) {783 PJ_LOG(1,(THIS_FILE,"Error: cannot disable both TCP and UDP"));784 return PJ_EINVAL;785 }786 787 cfg->no_udp = PJ_TRUE;788 break;789 790 case OPT_NOREFERSUB: /* norefersub */791 cfg->no_refersub = PJ_TRUE;792 break;793 794 case OPT_NO_TCP: /* no-tcp */795 if (cfg->no_udp && !cfg->use_tls) {796 PJ_LOG(1,(THIS_FILE,"Error: cannot disable both TCP and UDP"));797 return PJ_EINVAL;798 }799 800 cfg->no_tcp = PJ_TRUE;801 break;802 803 case OPT_PROXY: /* proxy */804 if (pjsua_verify_sip_url(pj_optarg) != 0) {805 PJ_LOG(1,(THIS_FILE,806 "Error: invalid SIP URL '%s' "807 "in proxy argument", pj_optarg));808 return PJ_EINVAL;809 }810 cur_acc->proxy[cur_acc->proxy_cnt++] = pj_str(pj_optarg);811 break;812 813 case OPT_OUTBOUND_PROXY: /* outbound proxy */814 if (pjsua_verify_sip_url(pj_optarg) != 0) {815 PJ_LOG(1,(THIS_FILE,816 "Error: invalid SIP URL '%s' "817 "in outbound proxy argument", pj_optarg));818 return PJ_EINVAL;819 }820 cfg->cfg.outbound_proxy[cfg->cfg.outbound_proxy_cnt++] = pj_str(pj_optarg);821 break;822 823 case OPT_REGISTRAR: /* registrar */824 if (pjsua_verify_sip_url(pj_optarg) != 0) {825 PJ_LOG(1,(THIS_FILE,826 "Error: invalid SIP URL '%s' in "827 "registrar argument", pj_optarg));828 return PJ_EINVAL;829 }830 cur_acc->reg_uri = pj_str(pj_optarg);831 break;832 833 case OPT_REG_TIMEOUT: /* reg-timeout */834 cur_acc->reg_timeout = pj_strtoul(pj_cstr(&tmp,pj_optarg));835 if (cur_acc->reg_timeout < 1 || cur_acc->reg_timeout > 3600) {836 PJ_LOG(1,(THIS_FILE,837 "Error: invalid value for --reg-timeout "838 "(expecting 1-3600)"));839 return PJ_EINVAL;840 }841 break;842 843 case OPT_PUBLISH: /* publish */844 cur_acc->publish_enabled = PJ_TRUE;845 break;846 847 case OPT_MWI: /* mwi */848 cur_acc->mwi_enabled = PJ_TRUE;849 break;850 851 case OPT_100REL: /** 100rel */852 cur_acc->require_100rel = PJSUA_100REL_MANDATORY;853 cfg->cfg.require_100rel = PJSUA_100REL_MANDATORY;854 break;855 856 case OPT_TIMER: /** session timer */857 lval = pj_strtoul(pj_cstr(&tmp, pj_optarg));858 if (lval < 0 || lval > 3) {859 PJ_LOG(1,(THIS_FILE,860 "Error: expecting integer value 0-3 for --use-timer"));861 return PJ_EINVAL;862 }863 cur_acc->use_timer = lval;864 cfg->cfg.use_timer = lval;865 break;866 867 case OPT_TIMER_SE: /** session timer session expiration */868 cur_acc->timer_setting.sess_expires = pj_strtoul(pj_cstr(&tmp, pj_optarg));869 if (cur_acc->timer_setting.sess_expires < 90) {870 PJ_LOG(1,(THIS_FILE,871 "Error: invalid value for --timer-se "872 "(expecting higher than 90)"));873 return PJ_EINVAL;874 }875 cfg->cfg.timer_setting.sess_expires = cur_acc->timer_setting.sess_expires;876 break;877 878 case OPT_TIMER_MIN_SE: /** session timer minimum session expiration */879 cur_acc->timer_setting.min_se = pj_strtoul(pj_cstr(&tmp, pj_optarg));880 if (cur_acc->timer_setting.min_se < 90) {881 PJ_LOG(1,(THIS_FILE,882 "Error: invalid value for --timer-min-se "883 "(expecting higher than 90)"));884 return PJ_EINVAL;885 }886 cfg->cfg.timer_setting.min_se = cur_acc->timer_setting.min_se;887 break;888 889 case OPT_OUTB_RID: /* Outbound reg-id */890 cur_acc->rfc5626_reg_id = pj_str(pj_optarg);891 break;892 893 case OPT_USE_IMS: /* Activate IMS settings */894 cur_acc->auth_pref.initial_auth = PJ_TRUE;895 break;896 897 case OPT_ID: /* id */898 if (pjsua_verify_url(pj_optarg) != 0) {899 PJ_LOG(1,(THIS_FILE,900 "Error: invalid SIP URL '%s' "901 "in local id argument", pj_optarg));902 return PJ_EINVAL;903 }904 cur_acc->id = pj_str(pj_optarg);905 break;906 907 case OPT_CONTACT: /* contact */908 if (pjsua_verify_sip_url(pj_optarg) != 0) {909 PJ_LOG(1,(THIS_FILE,910 "Error: invalid SIP URL '%s' "911 "in contact argument", pj_optarg));912 return PJ_EINVAL;913 }914 cur_acc->force_contact = pj_str(pj_optarg);915 break;916 917 case OPT_CONTACT_PARAMS:918 cur_acc->contact_params = pj_str(pj_optarg);919 break;920 921 case OPT_CONTACT_URI_PARAMS:922 cur_acc->contact_uri_params = pj_str(pj_optarg);923 break;924 925 case OPT_AUTO_UPDATE_NAT: /* OPT_AUTO_UPDATE_NAT */926 cur_acc->allow_contact_rewrite = pj_strtoul(pj_cstr(&tmp, pj_optarg));927 break;928 929 case OPT_DISABLE_STUN:930 cur_acc->sip_stun_use = PJSUA_STUN_USE_DISABLED;931 cur_acc->media_stun_use = PJSUA_STUN_USE_DISABLED;932 break;933 934 case OPT_USE_COMPACT_FORM:935 /* enable compact form - from Ticket #342 */936 {937 extern pj_bool_t pjsip_use_compact_form;938 extern pj_bool_t pjsip_include_allow_hdr_in_dlg;939 extern pj_bool_t pjmedia_add_rtpmap_for_static_pt;940 941 pjsip_use_compact_form = PJ_TRUE;942 /* do not transmit Allow header */943 pjsip_include_allow_hdr_in_dlg = PJ_FALSE;944 /* Do not include rtpmap for static payload types (<96) */945 pjmedia_add_rtpmap_for_static_pt = PJ_FALSE;946 }947 break;948 949 case OPT_ACCEPT_REDIRECT:950 cfg->redir_op = my_atoi(pj_optarg);951 if (cfg->redir_op<0 || cfg->redir_op>PJSIP_REDIRECT_STOP) {952 PJ_LOG(1,(THIS_FILE,953 "Error: accept-redirect value '%s' ", pj_optarg));954 return PJ_EINVAL;955 }956 break;957 958 case OPT_NO_FORCE_LR:959 cfg->cfg.force_lr = PJ_FALSE;960 break;961 962 case OPT_NEXT_ACCOUNT: /* Add more account. */963 cfg->acc_cnt++;964 cur_acc = &cfg->acc_cfg[cfg->acc_cnt];965 break;966 967 case OPT_USERNAME: /* Default authentication user */968 cur_acc->cred_info[cur_acc->cred_count].username = pj_str(pj_optarg);969 cur_acc->cred_info[cur_acc->cred_count].scheme = pj_str("Digest");970 break;971 972 case OPT_REALM: /* Default authentication realm. */973 cur_acc->cred_info[cur_acc->cred_count].realm = pj_str(pj_optarg);974 break;975 976 case OPT_PASSWORD: /* authentication password */977 cur_acc->cred_info[cur_acc->cred_count].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;978 cur_acc->cred_info[cur_acc->cred_count].data = pj_str(pj_optarg);979 #if PJSIP_HAS_DIGEST_AKA_AUTH980 cur_acc->cred_info[cur_acc->cred_count].data_type |= PJSIP_CRED_DATA_EXT_AKA;981 cur_acc->cred_info[cur_acc->cred_count].ext.aka.k = pj_str(pj_optarg);982 cur_acc->cred_info[cur_acc->cred_count].ext.aka.cb = &pjsip_auth_create_aka_response;983 #endif984 break;985 986 case OPT_REG_RETRY_INTERVAL:987 cur_acc->reg_retry_interval = pj_strtoul(pj_cstr(&tmp, pj_optarg));988 break;989 990 case OPT_REG_USE_PROXY:991 cur_acc->reg_use_proxy = (unsigned)pj_strtoul(pj_cstr(&tmp, pj_optarg));992 if (cur_acc->reg_use_proxy > 3) {993 PJ_LOG(1,(THIS_FILE, "Error: invalid --reg-use-proxy value '%s'",994 pj_optarg));995 return PJ_EINVAL;996 }997 break;998 999 case OPT_NEXT_CRED: /* next credential */1000 cur_acc->cred_count++;1001 break;1002 1003 case OPT_NAMESERVER: /* nameserver */1004 cfg->cfg.nameserver[cfg->cfg.nameserver_count++] = pj_str(pj_optarg);1005 if (cfg->cfg.nameserver_count > PJ_ARRAY_SIZE(cfg->cfg.nameserver)) {1006 PJ_LOG(1,(THIS_FILE, "Error: too many nameservers"));1007 return PJ_ETOOMANY;1008 }1009 break;1010 1011 case OPT_STUN_SRV: /* STUN server */1012 cfg->cfg.stun_host = pj_str(pj_optarg);1013 if (cfg->cfg.stun_srv_cnt==PJ_ARRAY_SIZE(cfg->cfg.stun_srv)) {1014 PJ_LOG(1,(THIS_FILE, "Error: too many STUN servers"));1015 return PJ_ETOOMANY;1016 }1017 cfg->cfg.stun_srv[cfg->cfg.stun_srv_cnt++] = pj_str(pj_optarg);1018 break;1019 1020 case OPT_ADD_BUDDY: /* Add to buddy list. */1021 if (pjsua_verify_url(pj_optarg) != 0) {1022 PJ_LOG(1,(THIS_FILE,1023 "Error: invalid URL '%s' in "1024 "--add-buddy option", pj_optarg));1025 return -1;1026 }1027 if (cfg->buddy_cnt == PJ_ARRAY_SIZE(cfg->buddy_cfg)) {1028 PJ_LOG(1,(THIS_FILE,1029 "Error: too many buddies in buddy list."));1030 return -1;1031 }1032 cfg->buddy_cfg[cfg->buddy_cnt].uri = pj_str(pj_optarg);1033 cfg->buddy_cnt++;1034 break;1035 1036 case OPT_AUTO_PLAY:1037 cfg->auto_play = 1;1038 break;1039 1040 case OPT_AUTO_PLAY_HANGUP:1041 cfg->auto_play_hangup = 1;1042 break;1043 1044 case OPT_AUTO_REC:1045 cfg->auto_rec = 1;1046 break;1047 1048 case OPT_AUTO_LOOP:1049 cfg->auto_loop = 1;1050 break;1051 1052 case OPT_AUTO_CONF:1053 cfg->auto_conf = 1;1054 break;1055 1056 case OPT_PLAY_FILE:1057 cfg->wav_files[cfg->wav_count++] = pj_str(pj_optarg);1058 break;1059 1060 case OPT_PLAY_TONE:1061 {1062 int f1, f2, on, off;1063 int n;1064 1065 n = sscanf(pj_optarg, "%d,%d,%d,%d", &f1, &f2, &on, &off);1066 if (n != 4) {1067 puts("Expecting f1,f2,on,off in --play-tone");1068 return -1;1069 }1070 1071 cfg->tones[cfg->tone_count].freq1 = (short)f1;1072 cfg->tones[cfg->tone_count].freq2 = (short)f2;1073 cfg->tones[cfg->tone_count].on_msec = (short)on;1074 cfg->tones[cfg->tone_count].off_msec = (short)off;1075 ++cfg->tone_count;1076 }1077 break;1078 1079 case OPT_REC_FILE:1080 cfg->rec_file = pj_str(pj_optarg);1081 break;1082 1083 case OPT_USE_ICE:1084 cfg->media_cfg.enable_ice =1085 cur_acc->ice_cfg.enable_ice = PJ_TRUE;1086 break;1087 1088 case OPT_ICE_REGULAR:1089 cfg->media_cfg.ice_opt.aggressive =1090 cur_acc->ice_cfg.ice_opt.aggressive = PJ_FALSE;1091 break;1092 1093 case OPT_USE_TURN:1094 cfg->media_cfg.enable_turn =1095 cur_acc->turn_cfg.enable_turn = PJ_TRUE;1096 break;1097 1098 case OPT_ICE_MAX_HOSTS:1099 cfg->media_cfg.ice_max_host_cands =1100 cur_acc->ice_cfg.ice_max_host_cands = my_atoi(pj_optarg);1101 break;1102 1103 case OPT_ICE_NO_RTCP:1104 cfg->media_cfg.ice_no_rtcp =1105 cur_acc->ice_cfg.ice_no_rtcp = PJ_TRUE;1106 break;1107 1108 case OPT_TURN_SRV:1109 cfg->media_cfg.turn_server =1110 cur_acc->turn_cfg.turn_server = pj_str(pj_optarg);1111 break;1112 1113 case OPT_TURN_TCP:1114 cfg->media_cfg.turn_conn_type =1115 cur_acc->turn_cfg.turn_conn_type = PJ_TURN_TP_TCP;1116 break;1117 1118 case OPT_TURN_USER:1119 cfg->media_cfg.turn_auth_cred.type =1120 cur_acc->turn_cfg.turn_auth_cred.type = PJ_STUN_AUTH_CRED_STATIC;1121 cfg->media_cfg.turn_auth_cred.data.static_cred.realm =1122 cur_acc->turn_cfg.turn_auth_cred.data.static_cred.realm = pj_str("*");1123 cfg->media_cfg.turn_auth_cred.data.static_cred.username =1124 cur_acc->turn_cfg.turn_auth_cred.data.static_cred.username = pj_str(pj_optarg);1125 break;1126 1127 case OPT_TURN_PASSWD:1128 cfg->media_cfg.turn_auth_cred.data.static_cred.data_type =1129 cur_acc->turn_cfg.turn_auth_cred.data.static_cred.data_type = PJ_STUN_PASSWD_PLAIN;1130 cfg->media_cfg.turn_auth_cred.data.static_cred.data =1131 cur_acc->turn_cfg.turn_auth_cred.data.static_cred.data = pj_str(pj_optarg);1132 break;1133 1134 #if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)1135 case OPT_USE_SRTP:1136 app_config.cfg.use_srtp = my_atoi(pj_optarg);1137 if (!pj_isdigit(*pj_optarg) || app_config.cfg.use_srtp > 3) {1138 PJ_LOG(1,(THIS_FILE, "Invalid value for --use-srtp option"));1139 return -1;1140 }1141 if ((int)app_config.cfg.use_srtp == 3) {1142 /* SRTP optional mode with duplicated media offer */1143 app_config.cfg.use_srtp = PJMEDIA_SRTP_OPTIONAL;1144 app_config.cfg.srtp_optional_dup_offer = PJ_TRUE;1145 cur_acc->srtp_optional_dup_offer = PJ_TRUE;1146 }1147 cur_acc->use_srtp = app_config.cfg.use_srtp;1148 break;1149 case OPT_SRTP_SECURE:1150 app_config.cfg.srtp_secure_signaling = my_atoi(pj_optarg);1151 if (!pj_isdigit(*pj_optarg) ||1152 app_config.cfg.srtp_secure_signaling > 2)1153 {1154 PJ_LOG(1,(THIS_FILE, "Invalid value for --srtp-secure option"));1155 return -1;1156 }1157 cur_acc->srtp_secure_signaling = app_config.cfg.srtp_secure_signaling;1158 break;1159 #endif1160 1161 case OPT_RTP_PORT:1162 cfg->rtp_cfg.port = my_atoi(pj_optarg);1163 if (cfg->rtp_cfg.port == 0) {1164 enum { START_PORT=4000 };1165 unsigned range;1166 1167 range = (65535-START_PORT-PJSUA_MAX_CALLS*2);1168 cfg->rtp_cfg.port = START_PORT +1169 ((pj_rand() % range) & 0xFFFE);1170 }1171 1172 if (cfg->rtp_cfg.port < 1 || cfg->rtp_cfg.port > 65535) {1173 PJ_LOG(1,(THIS_FILE,1174 "Error: rtp-port argument value "1175 "(expecting 1-65535"));1176 return -1;1177 }1178 break;1179 1180 case OPT_DIS_CODEC:1181 cfg->codec_dis[cfg->codec_dis_cnt++] = pj_str(pj_optarg);1182 break;1183 1184 case OPT_ADD_CODEC:1185 cfg->codec_arg[cfg->codec_cnt++] = pj_str(pj_optarg);1186 break;1187 1188 /* These options were no longer valid after new pjsua */1189 /*1190 case OPT_COMPLEXITY:1191 cfg->complexity = my_atoi(pj_optarg);1192 if (cfg->complexity < 0 || cfg->complexity > 10) {1193 PJ_LOG(1,(THIS_FILE,1194 "Error: invalid --complexity (expecting 0-10"));1195 return -1;1196 }1197 break;1198 */1199 1200 case OPT_DURATION:1201 cfg->duration = my_atoi(pj_optarg);1202 break;1203 1204 case OPT_THREAD_CNT:1205 cfg->cfg.thread_cnt = my_atoi(pj_optarg);1206 if (cfg->cfg.thread_cnt > 128) {1207 PJ_LOG(1,(THIS_FILE,1208 "Error: invalid --thread-cnt option"));1209 return -1;1210 }1211 break;1212 1213 case OPT_PTIME:1214 cfg->media_cfg.ptime = my_atoi(pj_optarg);1215 if (cfg->media_cfg.ptime < 10 || cfg->media_cfg.ptime > 1000) {1216 PJ_LOG(1,(THIS_FILE,1217 "Error: invalid --ptime option"));1218 return -1;1219 }1220 break;1221 1222 case OPT_NO_VAD:1223 cfg->media_cfg.no_vad = PJ_TRUE;1224 break;1225 1226 case OPT_EC_TAIL:1227 cfg->media_cfg.ec_tail_len = my_atoi(pj_optarg);1228 if (cfg->media_cfg.ec_tail_len > 1000) {1229 PJ_LOG(1,(THIS_FILE, "I think the ec-tail length setting "1230 "is too big"));1231 return -1;1232 }1233 break;1234 1235 case OPT_EC_OPT:1236 cfg->media_cfg.ec_options = my_atoi(pj_optarg);1237 break;1238 1239 case OPT_QUALITY:1240 cfg->media_cfg.quality = my_atoi(pj_optarg);1241 if (cfg->media_cfg.quality < 0 || cfg->media_cfg.quality > 10) {1242 PJ_LOG(1,(THIS_FILE,1243 "Error: invalid --quality (expecting 0-10"));1244 return -1;1245 }1246 break;1247 1248 case OPT_ILBC_MODE:1249 cfg->media_cfg.ilbc_mode = my_atoi(pj_optarg);1250 if (cfg->media_cfg.ilbc_mode!=20 && cfg->media_cfg.ilbc_mode!=30) {1251 PJ_LOG(1,(THIS_FILE,1252 "Error: invalid --ilbc-mode (expecting 20 or 30"));1253 return -1;1254 }1255 break;1256 1257 case OPT_RX_DROP_PCT:1258 cfg->media_cfg.rx_drop_pct = my_atoi(pj_optarg);1259 if (cfg->media_cfg.rx_drop_pct > 100) {1260 PJ_LOG(1,(THIS_FILE,1261 "Error: invalid --rx-drop-pct (expecting <= 100"));1262 return -1;1263 }1264 break;1265 1266 case OPT_TX_DROP_PCT:1267 cfg->media_cfg.tx_drop_pct = my_atoi(pj_optarg);1268 if (cfg->media_cfg.tx_drop_pct > 100) {1269 PJ_LOG(1,(THIS_FILE,1270 "Error: invalid --tx-drop-pct (expecting <= 100"));1271 return -1;1272 }1273 break;1274 1275 case OPT_AUTO_ANSWER:1276 cfg->auto_answer = my_atoi(pj_optarg);1277 if (cfg->auto_answer < 100 || cfg->auto_answer > 699) {1278 PJ_LOG(1,(THIS_FILE,1279 "Error: invalid code in --auto-answer "1280 "(expecting 100-699"));1281 return -1;1282 }1283 break;1284 1285 case OPT_MAX_CALLS:1286 cfg->cfg.max_calls = my_atoi(pj_optarg);1287 if (cfg->cfg.max_calls < 1 || cfg->cfg.max_calls > PJSUA_MAX_CALLS) {1288 PJ_LOG(1,(THIS_FILE,"Error: maximum call setting exceeds "1289 "compile time limit (PJSUA_MAX_CALLS=%d)",1290 PJSUA_MAX_CALLS));1291 return -1;1292 }1293 break;1294 1295 #if defined(PJSIP_HAS_TLS_TRANSPORT) && (PJSIP_HAS_TLS_TRANSPORT != 0)1296 case OPT_USE_TLS:1297 cfg->use_tls = PJ_TRUE;1298 break;1299 1300 case OPT_TLS_CA_FILE:1301 cfg->udp_cfg.tls_setting.ca_list_file = pj_str(pj_optarg);1302 break;1303 1304 case OPT_TLS_CERT_FILE:1305 cfg->udp_cfg.tls_setting.cert_file = pj_str(pj_optarg);1306 break;1307 1308 case OPT_TLS_PRIV_FILE:1309 cfg->udp_cfg.tls_setting.privkey_file = pj_str(pj_optarg);1310 break;1311 1312 case OPT_TLS_PASSWORD:1313 cfg->udp_cfg.tls_setting.password = pj_str(pj_optarg);1314 break;1315 1316 case OPT_TLS_VERIFY_SERVER:1317 cfg->udp_cfg.tls_setting.verify_server = PJ_TRUE;1318 break;1319 1320 case OPT_TLS_VERIFY_CLIENT:1321 cfg->udp_cfg.tls_setting.verify_client = PJ_TRUE;1322 cfg->udp_cfg.tls_setting.require_client_cert = PJ_TRUE;1323 break;1324 1325 case OPT_TLS_NEG_TIMEOUT:1326 cfg->udp_cfg.tls_setting.timeout.sec = atoi(pj_optarg);1327 break;1328 1329 case OPT_TLS_CIPHER:1330 {1331 pj_ssl_cipher cipher;1332 1333 if (pj_ansi_strnicmp(pj_optarg, "0x", 2) == 0) {1334 pj_str_t cipher_st = pj_str(pj_optarg + 2);1335 cipher = pj_strtoul2(&cipher_st, NULL, 16);1336 } else {1337 cipher = atoi(pj_optarg);1338 }1339 1340 if (pj_ssl_cipher_is_supported(cipher)) {1341 static pj_ssl_cipher tls_ciphers[128];1342 1343 tls_ciphers[cfg->udp_cfg.tls_setting.ciphers_num++] = cipher;1344 cfg->udp_cfg.tls_setting.ciphers = tls_ciphers;1345 } else {1346 pj_ssl_cipher ciphers[128];1347 unsigned j, ciphers_cnt;1348 1349 ciphers_cnt = PJ_ARRAY_SIZE(ciphers);1350 pj_ssl_cipher_get_availables(ciphers, &ciphers_cnt);1351 1352 PJ_LOG(1,(THIS_FILE, "Cipher \"%s\" is not supported by "1353 "TLS/SSL backend.", pj_optarg));1354 printf("Available TLS/SSL ciphers (%d):\n", ciphers_cnt);1355 for (j=0; j<ciphers_cnt; ++j)1356 printf("- 0x%06X: %s\n", ciphers[j], pj_ssl_cipher_name(ciphers[j]));1357 return -1;1358 }1359 }1360 break;1361 #endif /* PJSIP_HAS_TLS_TRANSPORT */1362 1363 case OPT_CAPTURE_DEV:1364 cfg->capture_dev = atoi(pj_optarg);1365 break;1366 1367 case OPT_PLAYBACK_DEV:1368 cfg->playback_dev = atoi(pj_optarg);1369 break;1370 1371 case OPT_STDOUT_REFRESH:1372 stdout_refresh = atoi(pj_optarg);1373 break;1374 1375 case OPT_STDOUT_REFRESH_TEXT:1376 stdout_refresh_text = pj_optarg;1377 break;1378 1379 #ifdef _IONBF1380 case OPT_STDOUT_NO_BUF:1381 setvbuf(stdout, NULL, _IONBF, 0);1382 break;1383 #endif1384 1385 case OPT_CAPTURE_LAT:1386 cfg->capture_lat = atoi(pj_optarg);1387 break;1388 1389 case OPT_PLAYBACK_LAT:1390 cfg->playback_lat = atoi(pj_optarg);1391 break;1392 1393 case OPT_SND_AUTO_CLOSE:1394 cfg->media_cfg.snd_auto_close_time = atoi(pj_optarg);1395 break;1396 1397 case OPT_NO_TONES:1398 cfg->no_tones = PJ_TRUE;1399 break;1400 1401 case OPT_JB_MAX_SIZE:1402 cfg->media_cfg.jb_max = atoi(pj_optarg);1403 break;1404 1405 #if defined(PJ_HAS_IPV6) && PJ_HAS_IPV61406 case OPT_IPV6:1407 cfg->ipv6 = PJ_TRUE;1408 break;1409 #endif1410 case OPT_QOS:1411 cfg->enable_qos = PJ_TRUE;1412 /* Set RTP traffic type to Voice */1413 cfg->rtp_cfg.qos_type = PJ_QOS_TYPE_VOICE;1414 /* Directly apply DSCP value to SIP traffic. Say lets1415 * set it to CS3 (DSCP 011000). Note that this will not1416 * work on all platforms.1417 */1418 cfg->udp_cfg.qos_params.flags = PJ_QOS_PARAM_HAS_DSCP;1419 cfg->udp_cfg.qos_params.dscp_val = 0x18;1420 break;1421 case OPT_VIDEO:1422 cfg->vid.vid_cnt = 1;1423 cfg->vid.in_auto_show = PJ_TRUE;1424 cfg->vid.out_auto_transmit = PJ_TRUE;1425 break;1426 case OPT_EXTRA_AUDIO:1427 cfg->aud_cnt++;1428 break;1429 1430 case OPT_VCAPTURE_DEV:1431 cfg->vid.vcapture_dev = atoi(pj_optarg);1432 cur_acc->vid_cap_dev = cfg->vid.vcapture_dev;1433 break;1434 1435 case OPT_VRENDER_DEV:1436 cfg->vid.vrender_dev = atoi(pj_optarg);1437 cur_acc->vid_rend_dev = cfg->vid.vrender_dev;1438 break;1439 1440 case OPT_PLAY_AVI:1441 if (app_config.avi_cnt >= MAX_AVI) {1442 PJ_LOG(1,(THIS_FILE, "Too many AVIs"));1443 return -1;1444 }1445 app_config.avi[app_config.avi_cnt++].path = pj_str(pj_optarg);1446 break;1447 1448 case OPT_AUTO_PLAY_AVI:1449 app_config.avi_auto_play = PJ_TRUE;1450 break;1451 1452 case OPT_USE_CLI:1453 cfg->use_cli = PJ_TRUE;1454 break;1455 1456 case OPT_CLI_TELNET_PORT:1457 cfg->cli_telnet_port = atoi(pj_optarg);1458 break;1459 1460 default:1461 PJ_LOG(1,(THIS_FILE,1462 "Argument \"%s\" is not valid. Use --help to see help",1463 argv[pj_optind-1]));1464 return -1;1465 }1466 }1467 1468 if (pj_optind != argc) {1469 pj_str_t uri_arg;1470 1471 if (pjsua_verify_url(argv[pj_optind]) != PJ_SUCCESS) {1472 PJ_LOG(1,(THIS_FILE, "Invalid SIP URI %s", argv[pj_optind]));1473 return -1;1474 }1475 uri_arg = pj_str(argv[pj_optind]);1476 if (uri_to_call)1477 *uri_to_call = uri_arg;1478 pj_optind++;1479 1480 /* Add URI to call to buddy list if it's not already there */1481 for (i=0; i<cfg->buddy_cnt; ++i) {1482 if (pj_stricmp(&cfg->buddy_cfg[i].uri, &uri_arg)==0)1483 break;1484 }1485 if (i == cfg->buddy_cnt && cfg->buddy_cnt < PJSUA_MAX_BUDDIES) {1486 cfg->buddy_cfg[cfg->buddy_cnt++].uri = uri_arg;1487 }1488 1489 } else {1490 if (uri_to_call)1491 uri_to_call->slen = 0;1492 }1493 1494 if (pj_optind != argc) {1495 PJ_LOG(1,(THIS_FILE, "Error: unknown options %s", argv[pj_optind]));1496 return PJ_EINVAL;1497 }1498 1499 if (cfg->acc_cfg[cfg->acc_cnt].id.slen)1500 cfg->acc_cnt++;1501 1502 for (i=0; i<cfg->acc_cnt; ++i) {1503 pjsua_acc_config *acfg = &cfg->acc_cfg[i];1504 1505 if (acfg->cred_info[acfg->cred_count].username.slen)1506 {1507 acfg->cred_count++;1508 }1509 1510 if (acfg->ice_cfg.enable_ice) {1511 acfg->ice_cfg_use = PJSUA_ICE_CONFIG_USE_CUSTOM;1512 }1513 if (acfg->turn_cfg.enable_turn) {1514 acfg->turn_cfg_use = PJSUA_TURN_CONFIG_USE_CUSTOM;1515 }1516 1517 /* When IMS mode is enabled for the account, verify that settings1518 * are okay.1519 */1520 /* For now we check if IMS mode is activated by looking if1521 * initial_auth is set.1522 */1523 if (acfg->auth_pref.initial_auth && acfg->cred_count) {1524 /* Realm must point to the real domain */1525 if (*acfg->cred_info[0].realm.ptr=='*') {1526 PJ_LOG(1,(THIS_FILE,1527 "Error: cannot use '*' as realm with IMS"));1528 return PJ_EINVAL;1529 }1530 1531 /* Username for authentication must be in a@b format */1532 if (strchr(acfg->cred_info[0].username.ptr, '@')==0) {1533 PJ_LOG(1,(THIS_FILE,1534 "Error: Username for authentication must "1535 "be in user@domain format with IMS"));1536 return PJ_EINVAL;1537 }1538 }1539 }1540 return PJ_SUCCESS;1541 }1542 1543 103 /***************************************************************************** 1544 * C onsole application104 * Callback 1545 105 */ 1546 106 static void ringback_start(pjsua_call_id call_id) … … 1659 219 /* Cancel duration timer, if any */ 1660 220 if (app_config.call_data[call_id].timer.id != PJSUA_INVALID_ID) { 1661 structcall_data *cd = &app_config.call_data[call_id];221 app_call_data *cd = &app_config.call_data[call_id]; 1662 222 pjsip_endpoint *endpt = pjsua_get_pjsip_endpt(); 1663 223 … … 1696 256 { 1697 257 /* Schedule timer to hangup call after the specified duration */ 1698 structcall_data *cd = &app_config.call_data[call_id];258 app_call_data *cd = &app_config.call_data[call_id]; 1699 259 pjsip_endpoint *endpt = pjsua_get_pjsip_endpt(); 1700 260 pj_time_val delay; … … 1810 370 } 1811 371 } 1812 1813 372 1814 373 /* … … 2690 1249 }; 2691 1250 1251 #if defined(PJ_WIN32) && PJ_WIN32!=0 1252 #include <windows.h> 1253 1254 static pj_thread_desc handler_desc; 1255 1256 static BOOL WINAPI CtrlHandler(DWORD fdwCtrlType) 1257 { 1258 switch (fdwCtrlType) 1259 { 1260 // Handle the CTRL+C signal. 1261 1262 case CTRL_C_EVENT: 1263 case CTRL_CLOSE_EVENT: 1264 case CTRL_BREAK_EVENT: 1265 case CTRL_LOGOFF_EVENT: 1266 case CTRL_SHUTDOWN_EVENT: 1267 pj_thread_register("ctrlhandler", handler_desc, &sig_thread); 1268 PJ_LOG(3,(THIS_FILE, "Ctrl-C detected, quitting..")); 1269 receive_end_sig = PJ_TRUE; 1270 app_destroy(); 1271 ExitProcess(1); 1272 PJ_UNREACHED(return TRUE;) 1273 1274 default: 1275 1276 return FALSE; 1277 } 1278 } 1279 1280 static void setup_socket_signal() 1281 { 1282 } 1283 1284 #else 1285 #include <signal.h> 1286 1287 static void setup_socket_signal() 1288 { 1289 signal(SIGPIPE, SIG_IGN); 1290 } 1291 1292 #endif 1293 1294 static pj_status_t setup_pjsua() 1295 { 1296 pj_status_t status = pjsua_destroy(); 1297 if (status != PJ_SUCCESS) 1298 return status; 1299 1300 /* Create pjsua */ 1301 status = pjsua_create(); 1302 if (status != PJ_SUCCESS) 1303 return status; 1304 1305 /* Create pool for application */ 1306 app_config.pool = pjsua_pool_create("pjsua-app", 1000, 1000); 1307 1308 return status; 1309 } 1310 2692 1311 /***************************************************************************** 2693 1312 * Public API 2694 1313 */ 2695 1314 2696 pj_status_t app_init(int argc, char *argv[]) 1315 #if defined(PJ_WIN32) && PJ_WIN32!=0 1316 PJ_DEF(void) setup_signal_handler(void) 1317 { 1318 SetConsoleCtrlHandler(&CtrlHandler, TRUE); 1319 } 1320 #else 1321 PJ_DEF(void) setup_signal_handler(void) 1322 { 1323 } 1324 #endif 1325 1326 int stdout_refresh_proc(void *arg) 1327 { 1328 extern char *stdout_refresh_text; 1329 1330 PJ_UNUSED_ARG(arg); 1331 1332 /* Set thread to lowest priority so that it doesn't clobber 1333 * stdout output 1334 */ 1335 pj_thread_set_prio(pj_thread_this(), 1336 pj_thread_get_prio_min(pj_thread_this())); 1337 1338 while (!stdout_refresh_quit) { 1339 pj_thread_sleep(stdout_refresh * 1000); 1340 puts(stdout_refresh_text); 1341 fflush(stdout); 1342 } 1343 1344 return 0; 1345 } 1346 1347 PJ_DEF(pj_status_t) app_init(pj_cli_telnet_on_started on_started_cb, 1348 pj_cli_on_quit on_quit_cb, 1349 pj_cli_on_destroy on_destroy_cb, 1350 pj_cli_on_restart_pjsua on_restart_pjsua_cb) 2697 1351 { 2698 1352 pjsua_transport_id transport_id = -1; … … 2701 1355 pj_status_t status; 2702 1356 2703 app_restart = PJ_FALSE; 2704 2705 /* Create pjsua */ 2706 status = pjsua_create(); 1357 /** Setup pjsua **/ 1358 status = setup_pjsua(); 2707 1359 if (status != PJ_SUCCESS) 2708 1360 return status; 2709 1361 2710 /* Create pool for application */ 2711 app_config.pool = pjsua_pool_create("pjsua-app", 1000, 1000); 2712 2713 /* Initialize default config */ 2714 default_config(&app_config); 2715 2716 /* Parse the arguments */ 2717 status = parse_args(argc, argv, &app_config, &uri_arg); 1362 /** Load config **/ 1363 status = load_config(&app_config, &uri_arg, app_running); 2718 1364 if (status != PJ_SUCCESS) 2719 return status; 1365 return status; 1366 1367 #if defined(PJ_SYMBIAN) && PJ_SYMBIAN!=0 1368 /* Disable threading on Symbian */ 1369 app_config.cfg.thread_cnt = 0; 1370 app_config.media_cfg.thread_cnt = 0; 1371 app_config.media_cfg.has_ioqueue = PJ_FALSE; 1372 #endif 2720 1373 2721 1374 /* Initialize application callbacks */ … … 3237 1890 } 3238 1891 1892 /* Init call setting */ 1893 pjsua_call_setting_default(&call_opt); 1894 call_opt.aud_cnt = app_config.aud_cnt; 1895 call_opt.vid_cnt = app_config.vid.vid_cnt; 1896 1897 /* Init CLI if configured */ 3239 1898 if (app_config.use_cli) { 3240 /*3241 * Init CLI3242 */3243 status = setup_cli();3244 if (status != PJ_SUCCESS)3245 goto on_error;3246 3247 PJ_LOG(3,(THIS_FILE, "CLI telnet daemon listening at port %d",3248 app_config.cli_telnet_port));1899 if (app_restart) { 1900 pj_uint16_t port = (pj_uint16_t)app_config.cli_telnet_port; 1901 status = setup_cli(!app_config.disable_cli_console, 1902 app_config.cli_telnet_port >= 0, port, 1903 on_started_cb, on_quit_cb, on_destroy_cb, 1904 on_restart_pjsua_cb); 1905 if (status != PJ_SUCCESS) 1906 goto on_error; 1907 } 3249 1908 } 3250 1909 … … 3252 1911 3253 1912 on_error: 1913 app_restart = PJ_FALSE; 3254 1914 app_destroy(); 3255 1915 return status; … … 3259 1919 { 3260 1920 pj_thread_t *stdout_refresh_thread = NULL; 3261 pj_status_t status;3262 3263 /* Start pjsua */3264 status = pjsua_start();3265 if (status != PJ_SUCCESS) {3266 app_destroy();3267 return status;3268 }3269 1921 3270 1922 /* Start console refresh thread */ … … 3275 1927 3276 1928 if (app_config.use_cli) 3277 cli_console_app_main(&uri_arg, &app_restart);3278 else 3279 console_app_main(&uri_arg, &app_restart);1929 start_cli_main(&uri_arg, &app_restart); 1930 else 1931 start_ui_main(&uri_arg, &app_restart); 3280 1932 3281 1933 if (stdout_refresh_thread) { … … 3288 1940 } 3289 1941 3290 pj_status_t app_destroy( void)1942 pj_status_t app_destroy() 3291 1943 { 3292 1944 pj_status_t status; … … 3344 1996 3345 1997 if (app_config.use_cli) { 3346 destroy_cli( );1998 destroy_cli(app_restart); 3347 1999 } 3348 2000 … … 3351 2003 app_config.pool = NULL; 3352 2004 } 3353 2005 3354 2006 status = pjsua_destroy(); 3355 3356 pj_bzero(&app_config, sizeof(app_config)); 3357 2007 2008 if (!app_restart) 2009 pj_bzero(&app_config, sizeof(app_config)); 2010 3358 2011 return status; 3359 2012 } 3360 2013 2014 /** === CLI Callback == **/ 2015 2016 static void cli_telnet_started(pj_cli_telnet_info *telnet_info) 2017 { 2018 PJ_LOG(3,(THIS_FILE, "Telnet daemon listening at %.*s:%d", 2019 telnet_info->ip_address.slen, telnet_info->ip_address.ptr, 2020 telnet_info->port)); 2021 } 2022 2023 static void cli_on_quit (pj_bool_t is_restarted) 2024 { 2025 PJ_LOG(3,(THIS_FILE, "CLI quit, restart(%d)", is_restarted)); 2026 } 2027 2028 static void cli_on_destroy(void) 2029 { 2030 PJ_LOG(3,(THIS_FILE, "CLI destroyed")); 2031 } 2032 2033 static void cli_on_restart_pjsua(void) 2034 { 2035 PJ_LOG(3,(THIS_FILE, "Restart pjsua")); 2036 } 2037 2038 /** ======================= **/ 2039 2040 int main_func(int argc, char *argv[]) 2041 { 2042 pj_status_t status; 2043 2044 setup_socket_signal(); 2045 2046 receive_end_sig = PJ_FALSE; 2047 app_restart = PJ_TRUE; 2048 2049 add_startup_config(argc, argv); 2050 2051 do { 2052 if (app_restart) { 2053 status = app_init(cli_telnet_started, cli_on_quit, 2054 cli_on_destroy, cli_on_restart_pjsua); 2055 if (status != PJ_SUCCESS) 2056 return 1; 2057 } 2058 2059 app_running = PJ_TRUE; 2060 2061 app_main(); 2062 if (!receive_end_sig) { 2063 app_destroy(); 2064 2065 /* This is on purpose */ 2066 app_destroy(); 2067 } else { 2068 pj_thread_join(sig_thread); 2069 } 2070 } while (app_restart); 2071 return 0; 2072 } 3361 2073 3362 2074 #ifdef STEREO_DEMO … … 3431 2143 } 3432 2144 #endif 3433 -
pjproject/trunk/pjsip-apps/src/pjsua/pjsua_cli_cmd.c
r4459 r4461 19 19 */ 20 20 21 #include "pjsua_c md.h"21 #include "pjsua_common.h" 22 22 #include <pjlib-util/cli.h> 23 23 #include <pjlib-util/cli_imp.h> 24 24 #include <pjlib-util/cli_console.h> 25 25 #include <pjlib-util/cli_telnet.h> 26 #include <pjlib-util/scanner.h> 26 27 27 28 #define THIS_FILE "pjsua_cli_cmd.c" 29 30 #define CHECK_PJSUA_RUNNING() if (pjsua_get_state()!=PJSUA_STATE_RUNNING) \ 31 return PJ_EINVALIDOP 28 32 29 33 /* CLI command id */ … … 39 43 #define CMD_NETWORK 900 40 44 #define CMD_QUIT 110 45 #define CMD_RESTART 120 46 #define CMD_RELOAD 130 41 47 42 48 /* call level 2 command */ … … 144 150 #define DYN_CHOICE_ADDED_BUDDY_ID (DYN_CHOICE_START)+12 145 151 146 static pj_cli_cfg cli_cfg;147 static pj_cli_telnet_cfg telnet_cfg;148 static pj_cli_t *cli = NULL;149 static pj_cli_sess *sess = NULL;150 static pj_cli_console_cfg console_cfg;151 152 152 /* Get input URL */ 153 153 static void get_input_url(char *buf, 154 154 int len, 155 155 pj_cli_cmd_val *cval, 156 struct input_result *result)156 struct input_result *result) 157 157 { 158 158 static const pj_str_t err_invalid_input = {"Invalid input\n", 15}; … … 203 203 204 204 pj_cli_sess_write_msg(cval->sess, err_invalid_input.ptr, 205 err_invalid_input.slen);205 err_invalid_input.slen); 206 206 result->nb_result = NO_NB; 207 207 return; … … 616 616 default: 617 617 param->cnt = 0; 618 } 619 } 620 621 void cli_console_app_main(const pj_str_t *uri_to_call, pj_bool_t *app_restart) 622 { 623 pjsua_call_setting_default(&call_opt); 624 call_opt.aud_cnt = app_config.aud_cnt; 625 call_opt.vid_cnt = app_config.vid.vid_cnt; 626 627 /* If user specifies URI to call, then call the URI */ 628 if (uri_to_call->slen) { 629 pjsua_call_make_call(current_acc, uri_to_call, &call_opt, NULL, 630 NULL, NULL); 631 } 632 633 /* 634 * Main loop. 635 */ 636 for (;;) { 637 char cmdline[PJ_CLI_MAX_CMDBUF]; 638 pj_status_t status; 639 640 status = pj_cli_console_process(sess, &cmdline[0], sizeof(cmdline)); 641 642 if (status == PJ_CLI_EEXIT) { 643 /* exit is called */ 644 break; 645 } else if (status != PJ_SUCCESS) { 646 /* Something wrong with the cmdline */ 647 PJ_PERROR(1,(THIS_FILE, status, "Exec error")); 648 } 649 } 650 *app_restart = pj_cli_is_restarting(cli); 618 break; 619 } 651 620 } 652 621 … … 795 764 { 796 765 pj_status_t status = PJ_SUCCESS; 766 767 CHECK_PJSUA_RUNNING(); 797 768 798 769 switch(pj_cli_get_cmd_id(cval->cmd)) { … … 1065 1036 pj_status_t status = PJ_SUCCESS; 1066 1037 1038 CHECK_PJSUA_RUNNING(); 1039 1067 1040 switch(pj_cli_get_cmd_id(cval->cmd)) { 1068 1041 case CMD_PRESENCE_ADD_BUDDY: … … 1107 1080 1108 1081 for (i=0; i<count; ++i) { 1109 char out_str[ PJSUA_MAX_CALLS*6];1110 char txlist[ PJSUA_MAX_CALLS*4+10];1082 char out_str[128]; 1083 char txlist[16]; 1111 1084 unsigned j; 1112 1085 pjsua_conf_port_info info; … … 1224 1197 pj_status_t status = PJ_SUCCESS; 1225 1198 1199 CHECK_PJSUA_RUNNING(); 1200 1226 1201 switch(pj_cli_get_cmd_id(cval->cmd)) { 1227 1202 case CMD_MEDIA_LIST: … … 1306 1281 { 1307 1282 pj_status_t status = PJ_SUCCESS; 1283 1284 CHECK_PJSUA_RUNNING(); 1308 1285 1309 1286 switch(pj_cli_get_cmd_id(cval->cmd)) { … … 1524 1501 { 1525 1502 if (current_call != PJSUA_INVALID_ID) { 1526 call_opt.flag |= PJSUA_CALL_UNHOLD;1527 1503 pjsua_call_update2(current_call, &call_opt, NULL); 1528 1504 } else { … … 1923 1899 pj_cli_cmd_id cmd_id = pj_cli_get_cmd_id(cval->cmd); 1924 1900 1901 CHECK_PJSUA_RUNNING(); 1902 1925 1903 switch(cmd_id) { 1926 1904 case CMD_CALL_NEW: … … 2012 1990 pjsua_acc_config acc_cfg; 2013 1991 pj_cli_cmd_id cmd_id = pj_cli_get_cmd_id(cval->cmd); 1992 1993 CHECK_PJSUA_RUNNING(); 2014 1994 2015 1995 pjsua_acc_get_config(current_acc, &acc_cfg); … … 2322 2302 pj_cli_cmd_id cmd_id = pj_cli_get_cmd_id(cval->cmd); 2323 2303 2304 CHECK_PJSUA_RUNNING(); 2305 2324 2306 switch(cmd_id) { 2325 2307 case CMD_VIDEO_ENABLE: … … 2415 2397 { 2416 2398 pj_status_t status = PJ_SUCCESS; 2417 PJ_UNUSED_ARG(cval); 2399 PJ_UNUSED_ARG(cval); 2400 2401 CHECK_PJSUA_RUNNING(); 2402 2418 2403 status = pjsua_detect_nat_type(); 2419 2404 if (status != PJ_SUCCESS) … … 2425 2410 static pj_status_t cmd_quit_handler(pj_cli_cmd_val *cval) 2426 2411 { 2412 extern pj_cli_on_quit cli_on_quit_cb; 2427 2413 PJ_LOG(3,(THIS_FILE, "Quitting app..")); 2428 pj_cli_quit(cval->sess->fe->cli, cval->sess, PJ_FALSE); 2414 pj_cli_quit(cval->sess->fe->cli, cval->sess, PJ_FALSE); 2415 /** Call pj_cli_on_quit callback **/ 2416 if (cli_on_quit_cb) 2417 (*cli_on_quit_cb)(PJ_FALSE); 2418 2429 2419 return PJ_SUCCESS; 2430 2420 } … … 2432 2422 static pj_status_t cmd_restart_handler(pj_cli_cmd_val *cval) 2433 2423 { 2424 extern pj_cli_on_quit cli_on_quit_cb; 2434 2425 PJ_LOG(3,(THIS_FILE, "Restarting app..")); 2435 pj_cli_quit(cval->sess->fe->cli, cval->sess, PJ_TRUE); 2426 pj_cli_quit(cval->sess->fe->cli, cval->sess, PJ_TRUE); 2427 /** Call pj_cli_on_quit callback **/ 2428 if (cli_on_quit_cb) 2429 (*cli_on_quit_cb)(PJ_TRUE); 2430 2431 return PJ_SUCCESS; 2432 } 2433 2434 /* 2435 * Syntax error handler for parser. 2436 */ 2437 static void on_syntax_error(pj_scanner *scanner) 2438 { 2439 PJ_UNUSED_ARG(scanner); 2440 PJ_THROW(PJ_EINVAL); 2441 } 2442 2443 static pj_status_t get_options(pj_str_t *options, unsigned *cmd_count) 2444 { 2445 pj_scanner scanner; 2446 pj_str_t str; 2447 2448 PJ_USE_EXCEPTION; 2449 2450 if (!options) 2451 return PJ_SUCCESS; 2452 2453 pj_scan_init(&scanner, options->ptr, options->slen, PJ_SCAN_AUTOSKIP_WS, 2454 &on_syntax_error); 2455 PJ_TRY { 2456 while (!pj_scan_is_eof(&scanner)) { 2457 ++(*cmd_count); 2458 pj_scan_get_until_chr(&scanner, " \t\r\n", &str); 2459 /** Store to command arguments **/ 2460 add_reload_config(*cmd_count, &str); 2461 } 2462 } 2463 PJ_CATCH_ANY { 2464 pj_scan_fini(&scanner); 2465 return PJ_GET_EXCEPTION(); 2466 } 2467 PJ_END; 2468 return PJ_SUCCESS; 2469 } 2470 2471 static pj_status_t cmd_reload_handler(pj_cli_cmd_val *cval) 2472 { 2473 int i; 2474 unsigned cmd_count = 0; 2475 extern pj_bool_t pjsua_restarted; 2476 extern pj_cli_on_restart_pjsua cli_on_restart_pjsua_cb; 2477 2478 PJ_LOG(3,(THIS_FILE, "Reloading Pjsua..")); 2479 /** Get the pjsua option **/ 2480 2481 for (i=1;i<cval->argc;i++) { 2482 get_options(&cval->argv[i], &cmd_count); 2483 } 2484 pjsua_restarted = PJ_TRUE; 2485 2486 if (cli_on_restart_pjsua_cb) 2487 (*cli_on_restart_pjsua_cb)(); 2488 2436 2489 return PJ_SUCCESS; 2437 2490 } … … 2832 2885 "<CMD name='restart' id='120' desc='Restart application'/>"; 2833 2886 2887 char* reload_command = 2888 "<CMD name='reload' id='130' desc='Reload pjsua'>" 2889 " <ARG name='options1' type='string' desc='Options' optional='1'/>" 2890 " <ARG name='options2' type='string' desc='Options' optional='1'/>" 2891 " <ARG name='options3' type='string' desc='Options' optional='1'/>" 2892 " <ARG name='options4' type='string' desc='Options' optional='1'/>" 2893 "</CMD>"; 2894 2834 2895 pj_status_t status; 2835 2896 pj_str_t sleep_xml = pj_str(sleep_command); … … 2837 2898 pj_str_t shutdown_xml = pj_str(shutdown_command); 2838 2899 pj_str_t restart_xml = pj_str(restart_command); 2900 pj_str_t reload_xml = pj_str(reload_command); 2839 2901 2840 2902 status = pj_cli_add_cmd_from_xml(cli, NULL, … … 2860 2922 &restart_xml, cmd_restart_handler, 2861 2923 NULL, NULL); 2924 if (status != PJ_SUCCESS) 2925 return status; 2926 2927 status = pj_cli_add_cmd_from_xml(cli, NULL, 2928 &reload_xml, cmd_reload_handler, 2929 NULL, NULL); 2862 2930 2863 2931 return status; 2864 2932 } 2865 2933 2866 static pj_status_t setup_command()2934 pj_status_t setup_command(pj_cli_t *cli) 2867 2935 { 2868 2936 pj_status_t status; … … 2898 2966 return status; 2899 2967 } 2900 2901 static void log_writer(int level, const char *buffer, int len)2902 {2903 if (cli)2904 pj_cli_write_log(cli, level, buffer, len);2905 }2906 2907 pj_status_t setup_cli()2908 {2909 pj_status_t status;2910 pj_cli_cfg_default(&cli_cfg);2911 cli_cfg.pf = app_config.pool->factory;2912 cli_cfg.name = pj_str("pjsua_cli");2913 cli_cfg.title = pj_str("Pjsua CLI Application");2914 2915 status = pj_cli_create(&cli_cfg, &cli);2916 if (status != PJ_SUCCESS)2917 return status;2918 2919 status = setup_command();2920 if (status != PJ_SUCCESS)2921 return status;2922 2923 pj_log_set_log_func(&log_writer);2924 2925 /*2926 * Init telnet2927 */2928 pj_cli_telnet_cfg_default(&telnet_cfg);2929 telnet_cfg.log_level = 5;2930 if (app_config.cli_telnet_port)2931 telnet_cfg.port = (pj_uint16_t)app_config.cli_telnet_port;2932 2933 status = pj_cli_telnet_create(cli, &telnet_cfg, NULL);2934 if (status != PJ_SUCCESS)2935 return status;2936 2937 app_config.cli_telnet_port = telnet_cfg.port;;2938 2939 /*2940 * Init console2941 */2942 pj_cli_console_cfg_default(&console_cfg);2943 console_cfg.quit_command = pj_str("shutdown");2944 status = pj_cli_console_create(cli, &console_cfg, &sess, NULL);2945 return status;2946 }2947 2948 void destroy_cli()2949 {2950 pj_log_set_log_func(&pj_log_write);2951 pj_cli_destroy(cli);2952 cli = NULL;2953 }2954
Note: See TracChangeset
for help on using the changeset viewer.