Changeset 4461


Ignore:
Timestamp:
Apr 5, 2013 3:02:19 AM (6 years ago)
Author:
riza
Message:

Re #1643: Code restructure+add callback to support symbian gui app

Location:
pjproject/trunk
Files:
5 added
3 deleted
14 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/build.symbian/pjlib_util.mmp

    r3087 r4461  
    3333// 
    3434SOURCE  base64.c 
     35SOURCE  cli.c 
     36SOURCE  cli_console.c 
     37SOURCE  cli_telnet.c 
    3538SOURCE  crc32.c 
    3639SOURCE  dns.c 
  • pjproject/trunk/pjlib-util/include/pjlib-util.h

    r3553 r4461  
    6464#include <pjlib-util/http_client.h> 
    6565 
     66/** CLI Telnet **/ 
     67#include <pjlib-util/cli_telnet.h> 
     68 
    6669#endif  /* __PJLIB_UTIL_H__ */ 
  • pjproject/trunk/pjlib-util/include/pjlib-util/cli_telnet.h

    r4440 r4461  
    3535 */ 
    3636 
     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 */ 
     42typedef 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 */ 
     61typedef void (*pj_cli_telnet_on_started)(pj_cli_telnet_info *telnet_info); 
    3762 
    3863/** 
     
    86111    pj_str_t prompt_str; 
    87112 
     113    /** 
     114     * Specify the pj_cli_telnet_on_started callback. 
     115     * 
     116     * Default: empty 
     117     */ 
     118    pj_cli_telnet_on_started on_started; 
     119 
    88120} pj_cli_telnet_cfg; 
    89  
    90121 
    91122/** 
  • pjproject/trunk/pjlib-util/include/pjlib-util/config.h

    r4440 r4461  
    292292 */ 
    293293#ifndef PJ_CLI_MAX_CMDBUF 
    294 #   define PJ_CLI_MAX_CMDBUF            120 
     294#   define PJ_CLI_MAX_CMDBUF            512 
    295295#endif 
    296296 
  • pjproject/trunk/pjlib-util/src/pjlib-util/cli_telnet.c

    r4440 r4461  
    3030#include <pjlib-util/errno.h> 
    3131#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 
    3241 
    3342#define CLI_TELNET_BUF_SIZE 256 
     
    4554 
    4655#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 
    4764 
    4865/** 
     
    262279} cli_telnet_sess; 
    263280 
    264 struct cli_telnet_fe 
     281typedef struct cli_telnet_fe 
    265282{ 
    266283    pj_cli_front_end        base; 
     
    273290    pj_thread_t            *worker_thread; 
    274291    pj_bool_t               is_quitting; 
    275     pj_mutex_t             *mutex; 
    276 }; 
     292    pj_mutex_t             *mutex;     
     293} cli_telnet_fe; 
    277294 
    278295/* Forward Declaration */ 
     
    282299static pj_status_t telnet_sess_send(cli_telnet_sess *sess, 
    283300                                    const pj_str_t *str); 
     301 
     302static pj_status_t telnet_start(cli_telnet_fe *fe); 
     303static pj_status_t telnet_restart(cli_telnet_fe *tfe); 
    284304 
    285305/** 
     
    646666    pj_str_t send_data; 
    647667    char data_str[128]; 
    648     struct cli_telnet_fe *fe = (struct cli_telnet_fe *)sess->base.fe; 
     668    cli_telnet_fe *fe = (cli_telnet_fe *)sess->base.fe; 
    649669 
    650670    send_data.ptr = &data_str[0]; 
     
    670690    unsigned len; 
    671691    unsigned i; 
    672     struct cli_telnet_fe *fe = (struct cli_telnet_fe *)sess->base.fe; 
     692    cli_telnet_fe *fe = (cli_telnet_fe *)sess->base.fe; 
    673693 
    674694    send_data.ptr = &data_str[0]; 
     
    744764    pj_str_t send_data; 
    745765    char data[1028]; 
    746     struct cli_telnet_fe *fe = (struct cli_telnet_fe *)sess->base.fe; 
     766    cli_telnet_fe *fe = (cli_telnet_fe *)sess->base.fe; 
    747767    const pj_cli_hint_info *hint = info->hint; 
    748768    out_parse_state parse_state = OP_NORMAL; 
     
    13191339{ 
    13201340    cli_telnet_sess *tsess = (cli_telnet_sess *)sess; 
    1321     pj_mutex_t *mutex = ((struct cli_telnet_fe *)sess->fe)->mutex; 
     1341    pj_mutex_t *mutex = ((cli_telnet_fe *)sess->fe)->mutex; 
    13221342 
    13231343    pj_mutex_lock(mutex); 
     
    13351355                                const char *data, int len) 
    13361356{ 
    1337     struct cli_telnet_fe * tfe = (struct cli_telnet_fe *)fe; 
     1357    cli_telnet_fe *tfe = (cli_telnet_fe *)fe; 
    13381358    pj_cli_sess *sess;     
    13391359 
     
    13581378static void telnet_fe_destroy(pj_cli_front_end *fe) 
    13591379{ 
    1360     struct cli_telnet_fe *tfe = (struct cli_telnet_fe *)fe; 
     1380    cli_telnet_fe *tfe = (cli_telnet_fe *)fe; 
    13611381    pj_cli_sess *sess; 
    13621382 
     
    13921412static int poll_worker_thread(void *p) 
    13931413{ 
    1394     struct cli_telnet_fe *fe = (struct cli_telnet_fe *)p; 
     1414    cli_telnet_fe *fe = (cli_telnet_fe *)p; 
    13951415 
    13961416    while (!fe->is_quitting) { 
     
    14091429                            pj_activesock_get_user_data(asock); 
    14101430 
    1411     PJ_UNUSED_ARG(op_key); 
     1431    PJ_UNUSED_ARG(op_key);     
    14121432 
    14131433    if (sent <= 0) { 
     1434        TRACE_((THIS_FILE, "Error On data send")); 
    14141435        pj_cli_sess_end_session(&sess->base); 
    14151436        return PJ_FALSE; 
     
    14421463    cli_telnet_sess *sess = (cli_telnet_sess *) 
    14431464                            pj_activesock_get_user_data(asock); 
    1444     struct cli_telnet_fe *tfe = (struct cli_telnet_fe *)sess->base.fe; 
     1465    cli_telnet_fe *tfe = (cli_telnet_fe *)sess->base.fe; 
    14451466    unsigned char *cdata = (unsigned char*)data;     
    14461467    pj_status_t is_valid = PJ_TRUE; 
     
    14491470    PJ_UNUSED_ARG(remainder); 
    14501471 
    1451     if (status != PJ_SUCCESS && status != PJ_EPENDING) { 
    1452         pj_cli_sess_end_session(&sess->base); 
    1453         return PJ_FALSE; 
    1454     } 
    1455  
    14561472    if (tfe->is_quitting) 
    14571473        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    }     
    14581479 
    14591480    pj_mutex_lock(sess->smutex); 
     
    15521573                                     pj_sock_t newsock, 
    15531574                                     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 
    15581580    pj_status_t sstatus; 
    15591581    pj_pool_t *pool; 
    1560     cli_telnet_sess *sess; 
     1582    cli_telnet_sess *sess = NULL; 
    15611583    pj_activesock_cb asock_cb; 
    15621584 
     
    15661588    if (fe->is_quitting) 
    15671589        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    }     
    15681598 
    15691599    /* An incoming connection is accepted, create a new session */ 
     
    16581688                                         pj_cli_front_end **p_fe) 
    16591689{ 
    1660     struct cli_telnet_fe *fe; 
     1690    cli_telnet_fe *fe; 
    16611691    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;    
    16661693 
    16671694    PJ_ASSERT_RETURN(cli, PJ_EINVAL); 
     
    16701697                          PJ_CLI_TELNET_POOL_SIZE, PJ_CLI_TELNET_POOL_INC, 
    16711698                          NULL); 
    1672     fe = PJ_POOL_ZALLOC_T(pool, struct cli_telnet_fe); 
     1699    fe = PJ_POOL_ZALLOC_T(pool, cli_telnet_fe); 
    16731700    if (!fe) 
    16741701        return PJ_ENOMEM; 
     
    16881715    fe->pool = pool; 
    16891716 
    1690     if (!fe->cfg.ioqueue) { 
     1717    if (!fe->cfg.ioqueue) {      
    16911718        /* Create own ioqueue if application doesn't supply one */ 
    1692         sstatus = pj_ioqueue_create(pool, 8, &fe->cfg.ioqueue); 
    1693         if (sstatus != PJ_SUCCESS) 
     1719        status = pj_ioqueue_create(pool, 8, &fe->cfg.ioqueue); 
     1720        if (status != PJ_SUCCESS) 
    16941721            goto on_exit; 
    16951722        fe->own_ioqueue = PJ_TRUE; 
    16961723    } 
    16971724 
    1698     sstatus = pj_mutex_create_recursive(pool, "mutex_telnet_fe", &fe->mutex); 
    1699     if (sstatus != PJ_SUCCESS) 
     1725    status = pj_mutex_create_recursive(pool, "mutex_telnet_fe", &fe->mutex); 
     1726    if (status != PJ_SUCCESS) 
    17001727        goto on_exit; 
    17011728 
    17021729    /* 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 
     1739on_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 
     1750static 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) 
    17061764        goto on_exit; 
    17071765 
    17081766    pj_sockaddr_in_init(&addr, NULL, fe->cfg.port); 
    17091767 
    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) 
    17171793            goto on_exit; 
    17181794             
    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 
    17261797        if (fe->cfg.prompt_str.slen == 0) { 
    17271798            pj_str_t prompt_sign = {"> ", 2}; 
     
    17381809    } 
    17391810 
    1740     sstatus = pj_sock_listen(sock, 4); 
    1741     if (sstatus != PJ_SUCCESS) 
     1811    status = pj_sock_listen(sock, 4); 
     1812    if (status != PJ_SUCCESS) 
    17421813        goto on_exit; 
    17431814 
    17441815    pj_bzero(&asock_cb, sizeof(asock_cb)); 
    1745     asock_cb.on_accept_complete = &telnet_fe_on_accept; 
    1746     sstatus = pj_activesock_create(pool, sock, pj_SOCK_STREAM(), 
    1747                                    NULL, fe->cfg.ioqueue, 
    1748                                    &asock_cb, fe, &fe->asock); 
    1749     if (sstatus != 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) 
    17501821        goto on_exit; 
    17511822 
    1752     sstatus = pj_activesock_start_accept(fe->asock, pool); 
    1753     if (sstatus != PJ_SUCCESS) 
     1823    status = pj_activesock_start_accept(fe->asock, fe->pool); 
     1824    if (status != PJ_SUCCESS) 
    17541825        goto on_exit; 
    17551826 
    17561827    if (fe->own_ioqueue) { 
    17571828        /* Create our own worker thread */ 
    1758         sstatus = pj_thread_create(pool, "worker_telnet_fe", 
    1759                                    &poll_worker_thread, fe, 0, 0, 
    1760                                    &fe->worker_thread); 
    1761         if (sstatus != 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) 
    17621833            goto on_exit; 
    17631834    } 
    17641835 
    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    } 
    17691856 
    17701857    return PJ_SUCCESS; 
     
    17821869        pj_mutex_destroy(fe->mutex); 
    17831870 
    1784     pj_pool_release(pool); 
    1785     return sstatus; 
    1786 } 
     1871    pj_pool_release(fe->pool); 
     1872    return status; 
     1873} 
     1874 
     1875static 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     
     1913on_exit: 
     1914    return status; 
     1915} 
  • pjproject/trunk/pjlib/include/pj/activesock.h

    r4359 r4461  
    133133    /** 
    134134     * 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. 
    136137     * 
    137138     * @param asock     The active socket. 
     
    149150                                    const pj_sockaddr_t *src_addr, 
    150151                                    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); 
    151176 
    152177    /** 
  • pjproject/trunk/pjlib/include/pj/errno.h

    r4359 r4461  
    428428 */ 
    429429#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 */ 
    430435 
    431436/** @} */   /* pj_errnum */ 
  • pjproject/trunk/pjlib/src/pj/activesock.c

    r4359 r4461  
    844844                               " operation, stopping further ioqueue accepts.", 
    845845                               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                } 
    846856                return; 
    847857            } 
     
    851861        } 
    852862 
    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)) { 
    854865            pj_bool_t ret; 
    855866 
    856867            /* 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            } 
    860880 
    861881            /* If callback returns false, we have been destroyed! */ 
  • pjproject/trunk/pjlib/src/pj/errno.c

    r4359 r4461  
    7979    PJ_BUILD_ERR(PJ_EIPV6NOTSUP,   "IPv6 is not supported"), 
    8080    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") 
    8283}; 
    8384#endif  /* PJ_HAS_ERROR_STRING */ 
  • pjproject/trunk/pjsip-apps/build/Makefile

    r4440 r4461  
    3434export PJSUA_SRCDIR = ../src/pjsua 
    3535export 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 
    3738export PJSUA_CFLAGS += $(_CFLAGS) 
    3839export PJSUA_LDFLAGS += $(APP_LDFLAGS) $(APP_LDLIBS) $(LDFLAGS) 
  • pjproject/trunk/pjsip-apps/build/pjsua.vcproj

    r4440 r4461  
    36213621                        </File> 
    36223622                        <File 
     3623                                RelativePath="..\src\pjsua\pjsua_cli.c" 
     3624                                > 
     3625                        </File> 
     3626                        <File 
    36233627                                RelativePath="..\src\pjsua\pjsua_cli_cmd.c" 
    36243628                                > 
     
    40034007                        </File> 
    40044008                        <File 
    4005                                 RelativePath="..\src\pjsua\pjsua_cmd.c" 
     4009                                RelativePath="..\src\pjsua\pjsua_common.c" 
    40064010                                > 
    4007                                 <FileConfiguration 
    4008                                         Name="Release|Win32" 
    4009                                         > 
    4010                                         <Tool 
    4011                                                 Name="VCCLCompilerTool" 
    4012                                                 AdditionalIncludeDirectories="" 
    4013                                                 PreprocessorDefinitions="" 
    4014                                         /> 
    4015                                 </FileConfiguration> 
    4016                                 <FileConfiguration 
    4017                                         Name="Release|Pocket PC 2003 (ARMV4)" 
    4018                                         > 
    4019                                         <Tool 
    4020                                                 Name="VCCLCompilerTool" 
    4021                                                 AdditionalIncludeDirectories="" 
    4022                                                 PreprocessorDefinitions="" 
    4023                                         /> 
    4024                                 </FileConfiguration> 
    4025                                 <FileConfiguration 
    4026                                         Name="Release|Smartphone 2003 (ARMV4)" 
    4027                                         > 
    4028                                         <Tool 
    4029                                                 Name="VCCLCompilerTool" 
    4030                                                 AdditionalIncludeDirectories="" 
    4031                                                 PreprocessorDefinitions="" 
    4032                                         /> 
    4033                                 </FileConfiguration> 
    4034                                 <FileConfiguration 
    4035                                         Name="Debug|Win32" 
    4036                                         > 
    4037                                         <Tool 
    4038                                                 Name="VCCLCompilerTool" 
    4039                                                 AdditionalIncludeDirectories="" 
    4040                                                 PreprocessorDefinitions="" 
    4041                                         /> 
    4042                                 </FileConfiguration> 
    4043                                 <FileConfiguration 
    4044                                         Name="Debug|Pocket PC 2003 (ARMV4)" 
    4045                                         > 
    4046                                         <Tool 
    4047                                                 Name="VCCLCompilerTool" 
    4048                                                 AdditionalIncludeDirectories="" 
    4049                                                 PreprocessorDefinitions="" 
    4050                                         /> 
    4051                                 </FileConfiguration> 
    4052                                 <FileConfiguration 
    4053                                         Name="Debug|Smartphone 2003 (ARMV4)" 
    4054                                         > 
    4055                                         <Tool 
    4056                                                 Name="VCCLCompilerTool" 
    4057                                                 AdditionalIncludeDirectories="" 
    4058                                                 PreprocessorDefinitions="" 
    4059                                         /> 
    4060                                 </FileConfiguration> 
    4061                                 <FileConfiguration 
    4062                                         Name="Debug-Static|Win32" 
    4063                                         > 
    4064                                         <Tool 
    4065                                                 Name="VCCLCompilerTool" 
    4066                                                 AdditionalIncludeDirectories="" 
    4067                                                 PreprocessorDefinitions="" 
    4068                                         /> 
    4069                                 </FileConfiguration> 
    4070                                 <FileConfiguration 
    4071                                         Name="Debug-Static|Pocket PC 2003 (ARMV4)" 
    4072                                         > 
    4073                                         <Tool 
    4074                                                 Name="VCCLCompilerTool" 
    4075                                                 AdditionalIncludeDirectories="" 
    4076                                                 PreprocessorDefinitions="" 
    4077                                         /> 
    4078                                 </FileConfiguration> 
    4079                                 <FileConfiguration 
    4080                                         Name="Debug-Static|Smartphone 2003 (ARMV4)" 
    4081                                         > 
    4082                                         <Tool 
    4083                                                 Name="VCCLCompilerTool" 
    4084                                                 AdditionalIncludeDirectories="" 
    4085                                                 PreprocessorDefinitions="" 
    4086                                         /> 
    4087                                 </FileConfiguration> 
    4088                                 <FileConfiguration 
    4089                                         Name="Release-Dynamic|Win32" 
    4090                                         > 
    4091                                         <Tool 
    4092                                                 Name="VCCLCompilerTool" 
    4093                                                 AdditionalIncludeDirectories="" 
    4094                                                 PreprocessorDefinitions="" 
    4095                                         /> 
    4096                                 </FileConfiguration> 
    4097                                 <FileConfiguration 
    4098                                         Name="Release-Dynamic|Pocket PC 2003 (ARMV4)" 
    4099                                         > 
    4100                                         <Tool 
    4101                                                 Name="VCCLCompilerTool" 
    4102                                                 AdditionalIncludeDirectories="" 
    4103                                                 PreprocessorDefinitions="" 
    4104                                         /> 
    4105                                 </FileConfiguration> 
    4106                                 <FileConfiguration 
    4107                                         Name="Release-Dynamic|Smartphone 2003 (ARMV4)" 
    4108                                         > 
    4109                                         <Tool 
    4110                                                 Name="VCCLCompilerTool" 
    4111                                                 AdditionalIncludeDirectories="" 
    4112                                                 PreprocessorDefinitions="" 
    4113                                         /> 
    4114                                 </FileConfiguration> 
    4115                                 <FileConfiguration 
    4116                                         Name="Debug-Dynamic|Win32" 
    4117                                         > 
    4118                                         <Tool 
    4119                                                 Name="VCCLCompilerTool" 
    4120                                                 AdditionalIncludeDirectories="" 
    4121                                                 PreprocessorDefinitions="" 
    4122                                         /> 
    4123                                 </FileConfiguration> 
    4124                                 <FileConfiguration 
    4125                                         Name="Debug-Dynamic|Pocket PC 2003 (ARMV4)" 
    4126                                         > 
    4127                                         <Tool 
    4128                                                 Name="VCCLCompilerTool" 
    4129                                                 AdditionalIncludeDirectories="" 
    4130                                                 PreprocessorDefinitions="" 
    4131                                         /> 
    4132                                 </FileConfiguration> 
    4133                                 <FileConfiguration 
    4134                                         Name="Debug-Dynamic|Smartphone 2003 (ARMV4)" 
    4135                                         > 
    4136                                         <Tool 
    4137                                                 Name="VCCLCompilerTool" 
    4138                                                 AdditionalIncludeDirectories="" 
    4139                                                 PreprocessorDefinitions="" 
    4140                                         /> 
    4141                                 </FileConfiguration> 
    4142                                 <FileConfiguration 
    4143                                         Name="Release-Static|Win32" 
    4144                                         > 
    4145                                         <Tool 
    4146                                                 Name="VCCLCompilerTool" 
    4147                                                 AdditionalIncludeDirectories="" 
    4148                                                 PreprocessorDefinitions="" 
    4149                                         /> 
    4150                                 </FileConfiguration> 
    4151                                 <FileConfiguration 
    4152                                         Name="Release-Static|Pocket PC 2003 (ARMV4)" 
    4153                                         > 
    4154                                         <Tool 
    4155                                                 Name="VCCLCompilerTool" 
    4156                                                 AdditionalIncludeDirectories="" 
    4157                                                 PreprocessorDefinitions="" 
    4158                                         /> 
    4159                                 </FileConfiguration> 
    4160                                 <FileConfiguration 
    4161                                         Name="Release-Static|Smartphone 2003 (ARMV4)" 
    4162                                         > 
    4163                                         <Tool 
    4164                                                 Name="VCCLCompilerTool" 
    4165                                                 AdditionalIncludeDirectories="" 
    4166                                                 PreprocessorDefinitions="" 
    4167                                         /> 
    4168                                 </FileConfiguration> 
    4169                                 <FileConfiguration 
    4170                                         Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)" 
    4171                                         > 
    4172                                         <Tool 
    4173                                                 Name="VCCLCompilerTool" 
    4174                                                 AdditionalIncludeDirectories="" 
    4175                                                 PreprocessorDefinitions="" 
    4176                                         /> 
    4177                                 </FileConfiguration> 
    4178                                 <FileConfiguration 
    4179                                         Name="Release|Windows Mobile 6 Professional SDK (ARMV4I)" 
    4180                                         > 
    4181                                         <Tool 
    4182                                                 Name="VCCLCompilerTool" 
    4183                                                 AdditionalIncludeDirectories="" 
    4184                                                 PreprocessorDefinitions="" 
    4185                                         /> 
    4186                                 </FileConfiguration> 
    4187                                 <FileConfiguration 
    4188                                         Name="Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)" 
    4189                                         > 
    4190                                         <Tool 
    4191                                                 Name="VCCLCompilerTool" 
    4192                                                 AdditionalIncludeDirectories="" 
    4193                                                 PreprocessorDefinitions="" 
    4194                                         /> 
    4195                                 </FileConfiguration> 
    4196                                 <FileConfiguration 
    4197                                         Name="Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)" 
    4198                                         > 
    4199                                         <Tool 
    4200                                                 Name="VCCLCompilerTool" 
    4201                                                 AdditionalIncludeDirectories="" 
    4202                                                 PreprocessorDefinitions="" 
    4203                                         /> 
    4204                                 </FileConfiguration> 
    4205                                 <FileConfiguration 
    4206                                         Name="Debug|Windows Mobile 6 Standard SDK (ARMV4I)" 
    4207                                         > 
    4208                                         <Tool 
    4209                                                 Name="VCCLCompilerTool" 
    4210                                                 AdditionalIncludeDirectories="" 
    4211                                                 PreprocessorDefinitions="" 
    4212                                         /> 
    4213                                 </FileConfiguration> 
    4214                                 <FileConfiguration 
    4215                                         Name="Debug|Windows Mobile 6 Professional SDK (ARMV4I)" 
    4216                                         > 
    4217                                         <Tool 
    4218                                                 Name="VCCLCompilerTool" 
    4219                                                 AdditionalIncludeDirectories="" 
    4220                                                 PreprocessorDefinitions="" 
    4221                                         /> 
    4222                                 </FileConfiguration> 
    4223                                 <FileConfiguration 
    4224                                         Name="Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)" 
    4225                                         > 
    4226                                         <Tool 
    4227                                                 Name="VCCLCompilerTool" 
    4228                                                 AdditionalIncludeDirectories="" 
    4229                                                 PreprocessorDefinitions="" 
    4230                                         /> 
    4231                                 </FileConfiguration> 
    4232                                 <FileConfiguration 
    4233                                         Name="Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)" 
    4234                                         > 
    4235                                         <Tool 
    4236                                                 Name="VCCLCompilerTool" 
    4237                                                 AdditionalIncludeDirectories="" 
    4238                                                 PreprocessorDefinitions="" 
    4239                                         /> 
    4240                                 </FileConfiguration> 
    4241                                 <FileConfiguration 
    4242                                         Name="Debug-Static|Windows Mobile 6 Standard SDK (ARMV4I)" 
    4243                                         > 
    4244                                         <Tool 
    4245                                                 Name="VCCLCompilerTool" 
    4246                                                 AdditionalIncludeDirectories="" 
    4247                                                 PreprocessorDefinitions="" 
    4248                                         /> 
    4249                                 </FileConfiguration> 
    4250                                 <FileConfiguration 
    4251                                         Name="Debug-Static|Windows Mobile 6 Professional SDK (ARMV4I)" 
    4252                                         > 
    4253                                         <Tool 
    4254                                                 Name="VCCLCompilerTool" 
    4255                                                 AdditionalIncludeDirectories="" 
    4256                                                 PreprocessorDefinitions="" 
    4257                                         /> 
    4258                                 </FileConfiguration> 
    4259                                 <FileConfiguration 
    4260                                         Name="Debug-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)" 
    4261                                         > 
    4262                                         <Tool 
    4263                                                 Name="VCCLCompilerTool" 
    4264                                                 AdditionalIncludeDirectories="" 
    4265                                                 PreprocessorDefinitions="" 
    4266                                         /> 
    4267                                 </FileConfiguration> 
    4268                                 <FileConfiguration 
    4269                                         Name="Debug-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)" 
    4270                                         > 
    4271                                         <Tool 
    4272                                                 Name="VCCLCompilerTool" 
    4273                                                 AdditionalIncludeDirectories="" 
    4274                                                 PreprocessorDefinitions="" 
    4275                                         /> 
    4276                                 </FileConfiguration> 
    4277                                 <FileConfiguration 
    4278                                         Name="Release-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)" 
    4279                                         > 
    4280                                         <Tool 
    4281                                                 Name="VCCLCompilerTool" 
    4282                                                 AdditionalIncludeDirectories="" 
    4283                                                 PreprocessorDefinitions="" 
    4284                                         /> 
    4285                                 </FileConfiguration> 
    4286                                 <FileConfiguration 
    4287                                         Name="Release-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)" 
    4288                                         > 
    4289                                         <Tool 
    4290                                                 Name="VCCLCompilerTool" 
    4291                                                 AdditionalIncludeDirectories="" 
    4292                                                 PreprocessorDefinitions="" 
    4293                                         /> 
    4294                                 </FileConfiguration> 
    4295                                 <FileConfiguration 
    4296                                         Name="Release-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)" 
    4297                                         > 
    4298                                         <Tool 
    4299                                                 Name="VCCLCompilerTool" 
    4300                                                 AdditionalIncludeDirectories="" 
    4301                                                 PreprocessorDefinitions="" 
    4302                                         /> 
    4303                                 </FileConfiguration> 
    4304                                 <FileConfiguration 
    4305                                         Name="Release-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)" 
    4306                                         > 
    4307                                         <Tool 
    4308                                                 Name="VCCLCompilerTool" 
    4309                                                 AdditionalIncludeDirectories="" 
    4310                                                 PreprocessorDefinitions="" 
    4311                                         /> 
    4312                                 </FileConfiguration> 
    4313                                 <FileConfiguration 
    4314                                         Name="Debug-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)" 
    4315                                         > 
    4316                                         <Tool 
    4317                                                 Name="VCCLCompilerTool" 
    4318                                                 AdditionalIncludeDirectories="" 
    4319                                                 PreprocessorDefinitions="" 
    4320                                         /> 
    4321                                 </FileConfiguration> 
    4322                                 <FileConfiguration 
    4323                                         Name="Debug-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)" 
    4324                                         > 
    4325                                         <Tool 
    4326                                                 Name="VCCLCompilerTool" 
    4327                                                 AdditionalIncludeDirectories="" 
    4328                                                 PreprocessorDefinitions="" 
    4329                                         /> 
    4330                                 </FileConfiguration> 
    4331                                 <FileConfiguration 
    4332                                         Name="Debug-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)" 
    4333                                         > 
    4334                                         <Tool 
    4335                                                 Name="VCCLCompilerTool" 
    4336                                                 AdditionalIncludeDirectories="" 
    4337                                                 PreprocessorDefinitions="" 
    4338                                         /> 
    4339                                 </FileConfiguration> 
    4340                                 <FileConfiguration 
    4341                                         Name="Debug-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)" 
    4342                                         > 
    4343                                         <Tool 
    4344                                                 Name="VCCLCompilerTool" 
    4345                                                 AdditionalIncludeDirectories="" 
    4346                                                 PreprocessorDefinitions="" 
    4347                                         /> 
    4348                                 </FileConfiguration> 
    4349                                 <FileConfiguration 
    4350                                         Name="Release-Static|Windows Mobile 6 Standard SDK (ARMV4I)" 
    4351                                         > 
    4352                                         <Tool 
    4353                                                 Name="VCCLCompilerTool" 
    4354                                                 AdditionalIncludeDirectories="" 
    4355                                                 PreprocessorDefinitions="" 
    4356                                         /> 
    4357                                 </FileConfiguration> 
    4358                                 <FileConfiguration 
    4359                                         Name="Release-Static|Windows Mobile 6 Professional SDK (ARMV4I)" 
    4360                                         > 
    4361                                         <Tool 
    4362                                                 Name="VCCLCompilerTool" 
    4363                                                 AdditionalIncludeDirectories="" 
    4364                                                 PreprocessorDefinitions="" 
    4365                                         /> 
    4366                                 </FileConfiguration> 
    4367                                 <FileConfiguration 
    4368                                         Name="Release-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)" 
    4369                                         > 
    4370                                         <Tool 
    4371                                                 Name="VCCLCompilerTool" 
    4372                                                 AdditionalIncludeDirectories="" 
    4373                                                 PreprocessorDefinitions="" 
    4374                                         /> 
    4375                                 </FileConfiguration> 
    4376                                 <FileConfiguration 
    4377                                         Name="Release-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)" 
    4378                                         > 
    4379                                         <Tool 
    4380                                                 Name="VCCLCompilerTool" 
    4381                                                 AdditionalIncludeDirectories="" 
    4382                                                 PreprocessorDefinitions="" 
    4383                                         /> 
    4384                                 </FileConfiguration> 
    43854011                        </File> 
    43864012                        <File 
    4387                                 RelativePath="..\src\pjsua\pjsua_ui_cmd.c" 
     4013                                RelativePath="..\src\pjsua\pjsua_config.c" 
    43884014                                > 
    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                                > 
    47674019                        </File> 
    47684020                </Filter> 
     
    47724024                        > 
    47734025                        <File 
    4774                                 RelativePath="..\src\pjsua\pjsua_cmd.h" 
     4026                                RelativePath="..\src\pjsua\pjsua_common.h" 
    47754027                                > 
    47764028                        </File> 
  • pjproject/trunk/pjsip-apps/src/pjsua/main.c

    r4440 r4461  
    2727 * These are defined in pjsua_app.c. 
    2828 */ 
    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 } 
     29int main_func(int argc, char *argv[]); 
    11430 
    11531int main(int argc, char *argv[]) 
  • pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c

    r4440 r4461  
    1818 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  
    1919 */ 
    20 #include "pjsua_cmd.h" 
     20#include "pjsua_common.h" 
    2121#include "gui.h" 
    2222 
     
    4444#define current_acc     pjsua_acc_get_default() 
    4545 
    46 static pj_str_t         uri_arg; 
    47  
    4846#ifdef STEREO_DEMO 
    4947static void stereo_demo(); 
     
    5149 
    5250pj_status_t app_destroy(void); 
     51 
    5352static void ringback_start(pjsua_call_id call_id); 
    5453static void ring_start(pjsua_call_id call_id); 
    5554static void ring_stop(pjsua_call_id call_id); 
    5655 
    57 pj_bool_t       app_restart; 
    58 pj_log_func     *log_cb = NULL; 
    59 static const char      *stdout_refresh_text = "STDOUT_REFRESH"; 
     56static pj_status_t          receive_end_sig; 
     57static pj_thread_t          *sig_thread; 
     58pj_str_t                    uri_arg; 
     59pj_bool_t                   app_restart; 
     60pj_bool_t                   app_running = PJ_FALSE; 
     61pj_log_func                 *log_cb = NULL; 
    6062 
    6163/** 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 **/ 
    6565void 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 **/ 
     67void start_ui_main(pj_str_t *uri_to_call, pj_bool_t *app_restart); 
     68/** Defined in pjsua_cli.c **/ 
     69void start_cli_main(pj_str_t *uri_to_call, pj_bool_t *app_restart); 
     70pj_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); 
     76void destroy_cli(pj_bool_t app_restart); 
    6877 
    6978/***************************************************************************** 
     
    92101#endif 
    93102 
    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 #endif 
    141     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_IPV6 
    158     puts  ("  --ipv6              Use IPv6 instead for SIP and media."); 
    159 #endif 
    160     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 #endif 
    191  
    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_VIDEO 
    230     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 #endif 
    238  
    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 clobber 
    288      * stdout output 
    289      */ 
    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 newlines 
    386         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 whitespaces 
    396             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 string 
    402                 cDelimiter = *p++;          // save quote delimiter 
    403                 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 quote 
    409  
    410             } else {                    // token's not a quoted string 
    411                 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 line 
    424                  
    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 _IONBF 
    490            OPT_STDOUT_NO_BUF, 
    491 #endif 
    492            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_PORT 
    498     }; 
    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 #endif 
    573         { "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 #endif 
    600         { "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 _IONBF 
    607         { "stdout-no-buf",  0, 0, OPT_STDOUT_NO_BUF }, 
    608 #endif 
    609         { "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_IPV6 
    613         { "ipv6",        0, 0, OPT_IPV6}, 
    614 #endif 
    615         { "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 arguments 
    660      * 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_AUTH 
    980             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 #endif 
    984             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 #endif 
    1160  
    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 _IONBF 
    1380         case OPT_STDOUT_NO_BUF: 
    1381             setvbuf(stdout, NULL, _IONBF, 0); 
    1382             break; 
    1383 #endif 
    1384  
    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_IPV6 
    1406         case OPT_IPV6: 
    1407             cfg->ipv6 = PJ_TRUE; 
    1408             break; 
    1409 #endif 
    1410         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 lets 
    1415              * set it to CS3 (DSCP 011000). Note that this will not  
    1416              * 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 settings 
    1518          * are okay. 
    1519          */ 
    1520         /* For now we check if IMS mode is activated by looking if 
    1521          * 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  
    1543103/***************************************************************************** 
    1544  * Console application 
     104 * Callback  
    1545105 */ 
    1546106static void ringback_start(pjsua_call_id call_id) 
     
    1659219        /* Cancel duration timer, if any */ 
    1660220        if (app_config.call_data[call_id].timer.id != PJSUA_INVALID_ID) { 
    1661             struct call_data *cd = &app_config.call_data[call_id]; 
     221            app_call_data *cd = &app_config.call_data[call_id]; 
    1662222            pjsip_endpoint *endpt = pjsua_get_pjsip_endpt(); 
    1663223 
     
    1696256        { 
    1697257            /* Schedule timer to hangup call after the specified duration */ 
    1698             struct call_data *cd = &app_config.call_data[call_id]; 
     258            app_call_data *cd = &app_config.call_data[call_id]; 
    1699259            pjsip_endpoint *endpt = pjsua_get_pjsip_endpt(); 
    1700260            pj_time_val delay; 
     
    1810370    } 
    1811371} 
    1812  
    1813372 
    1814373/* 
     
    26901249}; 
    26911250 
     1251#if defined(PJ_WIN32) && PJ_WIN32!=0 
     1252#include <windows.h> 
     1253 
     1254static pj_thread_desc handler_desc; 
     1255 
     1256static 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 
     1280static void setup_socket_signal() 
     1281{ 
     1282} 
     1283 
     1284#else 
     1285#include <signal.h> 
     1286 
     1287static void setup_socket_signal() 
     1288{ 
     1289    signal(SIGPIPE, SIG_IGN); 
     1290} 
     1291 
     1292#endif 
     1293 
     1294static 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 
    26921311/***************************************************************************** 
    26931312 * Public API 
    26941313 */ 
    26951314 
    2696 pj_status_t app_init(int argc, char *argv[]) 
     1315#if defined(PJ_WIN32) && PJ_WIN32!=0 
     1316PJ_DEF(void) setup_signal_handler(void) 
     1317{ 
     1318    SetConsoleCtrlHandler(&CtrlHandler, TRUE); 
     1319} 
     1320#else 
     1321PJ_DEF(void) setup_signal_handler(void) 
     1322{ 
     1323} 
     1324#endif 
     1325 
     1326int 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 
     1347PJ_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) 
    26971351{ 
    26981352    pjsua_transport_id transport_id = -1; 
     
    27011355    pj_status_t status; 
    27021356 
    2703     app_restart = PJ_FALSE; 
    2704  
    2705     /* Create pjsua */ 
    2706     status = pjsua_create(); 
     1357    /** Setup pjsua **/ 
     1358    status = setup_pjsua(); 
    27071359    if (status != PJ_SUCCESS) 
    27081360        return status; 
    27091361 
    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); 
    27181364    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 
    27201373 
    27211374    /* Initialize application callbacks */ 
     
    32371890    } 
    32381891 
     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 */     
    32391898    if (app_config.use_cli) { 
    3240         /* 
    3241          * Init CLI 
    3242          */     
    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        } 
    32491908    } 
    32501909 
     
    32521911 
    32531912on_error: 
     1913    app_restart = PJ_FALSE; 
    32541914    app_destroy(); 
    32551915    return status; 
     
    32591919{ 
    32601920    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     } 
    32691921 
    32701922    /* Start console refresh thread */ 
     
    32751927 
    32761928    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); 
    32801932 
    32811933    if (stdout_refresh_thread) { 
     
    32881940} 
    32891941 
    3290 pj_status_t app_destroy(void) 
     1942pj_status_t app_destroy() 
    32911943{ 
    32921944    pj_status_t status; 
     
    33441996 
    33451997    if (app_config.use_cli) {    
    3346         destroy_cli(); 
     1998        destroy_cli(app_restart); 
    33471999    } 
    33482000 
     
    33512003        app_config.pool = NULL; 
    33522004    } 
    3353  
     2005     
    33542006    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     
    33582011    return status; 
    33592012} 
    33602013 
     2014/** === CLI Callback == **/ 
     2015 
     2016static 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 
     2023static void cli_on_quit (pj_bool_t is_restarted) 
     2024{ 
     2025    PJ_LOG(3,(THIS_FILE, "CLI quit, restart(%d)", is_restarted)); 
     2026} 
     2027 
     2028static void cli_on_destroy(void) 
     2029{ 
     2030    PJ_LOG(3,(THIS_FILE, "CLI destroyed")); 
     2031} 
     2032 
     2033static void cli_on_restart_pjsua(void) 
     2034{ 
     2035    PJ_LOG(3,(THIS_FILE, "Restart pjsua")); 
     2036} 
     2037 
     2038/** ======================= **/ 
     2039 
     2040int 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} 
    33612073 
    33622074#ifdef STEREO_DEMO 
     
    34312143} 
    34322144#endif 
    3433  
  • pjproject/trunk/pjsip-apps/src/pjsua/pjsua_cli_cmd.c

    r4459 r4461  
    1919 */ 
    2020 
    21 #include "pjsua_cmd.h" 
     21#include "pjsua_common.h" 
    2222#include <pjlib-util/cli.h> 
    2323#include <pjlib-util/cli_imp.h> 
    2424#include <pjlib-util/cli_console.h> 
    2525#include <pjlib-util/cli_telnet.h> 
     26#include <pjlib-util/scanner.h> 
    2627 
    2728#define THIS_FILE       "pjsua_cli_cmd.c" 
     29 
     30#define CHECK_PJSUA_RUNNING() if (pjsua_get_state()!=PJSUA_STATE_RUNNING) \ 
     31                                  return PJ_EINVALIDOP 
    2832 
    2933/* CLI command id */ 
     
    3943#define CMD_NETWORK                 900 
    4044#define CMD_QUIT                    110 
     45#define CMD_RESTART                 120 
     46#define CMD_RELOAD                  130 
    4147 
    4248/* call level 2 command */ 
     
    144150#define DYN_CHOICE_ADDED_BUDDY_ID   (DYN_CHOICE_START)+12 
    145151 
    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  
    152152/* Get input URL */ 
    153153static void get_input_url(char *buf,  
    154154                          int len, 
    155155                          pj_cli_cmd_val *cval, 
    156 struct input_result *result) 
     156                          struct input_result *result) 
    157157{ 
    158158    static const pj_str_t err_invalid_input = {"Invalid input\n", 15}; 
     
    203203 
    204204        pj_cli_sess_write_msg(cval->sess, err_invalid_input.ptr,  
    205             err_invalid_input.slen); 
     205                              err_invalid_input.slen); 
    206206        result->nb_result = NO_NB; 
    207207        return; 
     
    616616    default: 
    617617        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    } 
    651620} 
    652621 
     
    795764{     
    796765    pj_status_t status = PJ_SUCCESS; 
     766 
     767    CHECK_PJSUA_RUNNING(); 
    797768 
    798769    switch(pj_cli_get_cmd_id(cval->cmd)) { 
     
    10651036    pj_status_t status = PJ_SUCCESS; 
    10661037 
     1038    CHECK_PJSUA_RUNNING(); 
     1039 
    10671040    switch(pj_cli_get_cmd_id(cval->cmd)) { 
    10681041    case CMD_PRESENCE_ADD_BUDDY: 
     
    11071080 
    11081081    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]; 
    11111084        unsigned j; 
    11121085        pjsua_conf_port_info info; 
     
    12241197    pj_status_t status = PJ_SUCCESS; 
    12251198 
     1199    CHECK_PJSUA_RUNNING(); 
     1200 
    12261201    switch(pj_cli_get_cmd_id(cval->cmd)) { 
    12271202    case CMD_MEDIA_LIST: 
     
    13061281{ 
    13071282    pj_status_t status = PJ_SUCCESS; 
     1283 
     1284    CHECK_PJSUA_RUNNING(); 
    13081285 
    13091286    switch(pj_cli_get_cmd_id(cval->cmd)) { 
     
    15241501{ 
    15251502    if (current_call != PJSUA_INVALID_ID) { 
    1526         call_opt.flag |= PJSUA_CALL_UNHOLD; 
    15271503        pjsua_call_update2(current_call, &call_opt, NULL); 
    15281504    } else { 
     
    19231899    pj_cli_cmd_id cmd_id = pj_cli_get_cmd_id(cval->cmd); 
    19241900 
     1901    CHECK_PJSUA_RUNNING(); 
     1902 
    19251903    switch(cmd_id) { 
    19261904    case CMD_CALL_NEW: 
     
    20121990    pjsua_acc_config acc_cfg; 
    20131991    pj_cli_cmd_id cmd_id = pj_cli_get_cmd_id(cval->cmd); 
     1992 
     1993    CHECK_PJSUA_RUNNING(); 
    20141994 
    20151995    pjsua_acc_get_config(current_acc, &acc_cfg); 
     
    23222302    pj_cli_cmd_id cmd_id = pj_cli_get_cmd_id(cval->cmd);     
    23232303 
     2304    CHECK_PJSUA_RUNNING(); 
     2305 
    23242306    switch(cmd_id) { 
    23252307    case CMD_VIDEO_ENABLE: 
     
    24152397{ 
    24162398    pj_status_t status = PJ_SUCCESS; 
    2417     PJ_UNUSED_ARG(cval);     
     2399    PJ_UNUSED_ARG(cval); 
     2400 
     2401    CHECK_PJSUA_RUNNING(); 
     2402     
    24182403    status = pjsua_detect_nat_type(); 
    24192404    if (status != PJ_SUCCESS) 
     
    24252410static pj_status_t cmd_quit_handler(pj_cli_cmd_val *cval) 
    24262411{ 
     2412    extern pj_cli_on_quit cli_on_quit_cb; 
    24272413    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 
    24292419    return PJ_SUCCESS; 
    24302420} 
     
    24322422static pj_status_t cmd_restart_handler(pj_cli_cmd_val *cval) 
    24332423{ 
     2424    extern pj_cli_on_quit cli_on_quit_cb; 
    24342425    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 */ 
     2437static void on_syntax_error(pj_scanner *scanner) 
     2438{ 
     2439    PJ_UNUSED_ARG(scanner); 
     2440    PJ_THROW(PJ_EINVAL); 
     2441} 
     2442 
     2443static 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 
     2471static 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 
    24362489    return PJ_SUCCESS; 
    24372490} 
     
    28322885        "<CMD name='restart' id='120' desc='Restart application'/>"; 
    28332886 
     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 
    28342895    pj_status_t status; 
    28352896    pj_str_t sleep_xml = pj_str(sleep_command);     
     
    28372898    pj_str_t shutdown_xml = pj_str(shutdown_command); 
    28382899    pj_str_t restart_xml = pj_str(restart_command); 
     2900    pj_str_t reload_xml = pj_str(reload_command); 
    28392901 
    28402902    status = pj_cli_add_cmd_from_xml(cli, NULL,  
     
    28602922                                     &restart_xml, cmd_restart_handler,  
    28612923                                     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); 
    28622930 
    28632931    return status; 
    28642932} 
    28652933 
    2866 static pj_status_t setup_command() 
     2934pj_status_t setup_command(pj_cli_t *cli) 
    28672935{ 
    28682936    pj_status_t status; 
     
    28982966    return status; 
    28992967} 
    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 telnet 
    2927     */  
    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 console 
    2941     */  
    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.