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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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} 
Note: See TracChangeset for help on using the changeset viewer.