Changeset 4461 for pjproject/trunk/pjlib-util/src/pjlib-util/cli_telnet.c
- Timestamp:
- Apr 5, 2013 3:02:19 AM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjlib-util/src/pjlib-util/cli_telnet.c
r4440 r4461 30 30 #include <pjlib-util/errno.h> 31 31 #include <pjlib-util/scanner.h> 32 #include <pj/addr_resolv.h> 33 #include <pj/compat/socket.h> 34 35 #if (defined(PJ_WIN32) && PJ_WIN32!=0) || \ 36 (defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE!=0) 37 38 #define EADDRINUSE WSAEADDRINUSE 39 40 #endif 32 41 33 42 #define CLI_TELNET_BUF_SIZE 256 … … 45 54 46 55 #define MAX_CLI_TELNET_OPTIONS 256 56 /** Maximum retry on Telnet Restart **/ 57 #define MAX_RETRY_ON_TELNET_RESTART 100 58 /** Minimum number of millisecond to wait before retrying to re-bind on 59 * telnet restart **/ 60 #define MIN_WAIT_ON_TELNET_RESTART 20 61 /** Maximum number of millisecod to wait before retrying to re-bind on 62 * telnet restart **/ 63 #define MAX_WAIT_ON_TELNET_RESTART 1000 47 64 48 65 /** … … 262 279 } cli_telnet_sess; 263 280 264 struct cli_telnet_fe281 typedef struct cli_telnet_fe 265 282 { 266 283 pj_cli_front_end base; … … 273 290 pj_thread_t *worker_thread; 274 291 pj_bool_t is_quitting; 275 pj_mutex_t *mutex; 276 } ;292 pj_mutex_t *mutex; 293 } cli_telnet_fe; 277 294 278 295 /* Forward Declaration */ … … 282 299 static pj_status_t telnet_sess_send(cli_telnet_sess *sess, 283 300 const pj_str_t *str); 301 302 static pj_status_t telnet_start(cli_telnet_fe *fe); 303 static pj_status_t telnet_restart(cli_telnet_fe *tfe); 284 304 285 305 /** … … 646 666 pj_str_t send_data; 647 667 char data_str[128]; 648 struct cli_telnet_fe *fe = (structcli_telnet_fe *)sess->base.fe;668 cli_telnet_fe *fe = (cli_telnet_fe *)sess->base.fe; 649 669 650 670 send_data.ptr = &data_str[0]; … … 670 690 unsigned len; 671 691 unsigned i; 672 struct cli_telnet_fe *fe = (structcli_telnet_fe *)sess->base.fe;692 cli_telnet_fe *fe = (cli_telnet_fe *)sess->base.fe; 673 693 674 694 send_data.ptr = &data_str[0]; … … 744 764 pj_str_t send_data; 745 765 char data[1028]; 746 struct cli_telnet_fe *fe = (structcli_telnet_fe *)sess->base.fe;766 cli_telnet_fe *fe = (cli_telnet_fe *)sess->base.fe; 747 767 const pj_cli_hint_info *hint = info->hint; 748 768 out_parse_state parse_state = OP_NORMAL; … … 1319 1339 { 1320 1340 cli_telnet_sess *tsess = (cli_telnet_sess *)sess; 1321 pj_mutex_t *mutex = (( structcli_telnet_fe *)sess->fe)->mutex;1341 pj_mutex_t *mutex = ((cli_telnet_fe *)sess->fe)->mutex; 1322 1342 1323 1343 pj_mutex_lock(mutex); … … 1335 1355 const char *data, int len) 1336 1356 { 1337 struct cli_telnet_fe * tfe = (structcli_telnet_fe *)fe;1357 cli_telnet_fe *tfe = (cli_telnet_fe *)fe; 1338 1358 pj_cli_sess *sess; 1339 1359 … … 1358 1378 static void telnet_fe_destroy(pj_cli_front_end *fe) 1359 1379 { 1360 struct cli_telnet_fe *tfe = (structcli_telnet_fe *)fe;1380 cli_telnet_fe *tfe = (cli_telnet_fe *)fe; 1361 1381 pj_cli_sess *sess; 1362 1382 … … 1392 1412 static int poll_worker_thread(void *p) 1393 1413 { 1394 struct cli_telnet_fe *fe = (structcli_telnet_fe *)p;1414 cli_telnet_fe *fe = (cli_telnet_fe *)p; 1395 1415 1396 1416 while (!fe->is_quitting) { … … 1409 1429 pj_activesock_get_user_data(asock); 1410 1430 1411 PJ_UNUSED_ARG(op_key); 1431 PJ_UNUSED_ARG(op_key); 1412 1432 1413 1433 if (sent <= 0) { 1434 TRACE_((THIS_FILE, "Error On data send")); 1414 1435 pj_cli_sess_end_session(&sess->base); 1415 1436 return PJ_FALSE; … … 1442 1463 cli_telnet_sess *sess = (cli_telnet_sess *) 1443 1464 pj_activesock_get_user_data(asock); 1444 struct cli_telnet_fe *tfe = (structcli_telnet_fe *)sess->base.fe;1465 cli_telnet_fe *tfe = (cli_telnet_fe *)sess->base.fe; 1445 1466 unsigned char *cdata = (unsigned char*)data; 1446 1467 pj_status_t is_valid = PJ_TRUE; … … 1449 1470 PJ_UNUSED_ARG(remainder); 1450 1471 1451 if (status != PJ_SUCCESS && status != PJ_EPENDING) {1452 pj_cli_sess_end_session(&sess->base);1453 return PJ_FALSE;1454 }1455 1456 1472 if (tfe->is_quitting) 1457 1473 return PJ_FALSE; 1474 1475 if (status != PJ_SUCCESS && status != PJ_EPENDING) { 1476 TRACE_((THIS_FILE, "Error on data read %d", status)); 1477 return PJ_FALSE; 1478 } 1458 1479 1459 1480 pj_mutex_lock(sess->smutex); … … 1552 1573 pj_sock_t newsock, 1553 1574 const pj_sockaddr_t *src_addr, 1554 int src_addr_len) 1555 { 1556 struct cli_telnet_fe *fe = (struct cli_telnet_fe *) 1557 pj_activesock_get_user_data(asock); 1575 int src_addr_len, 1576 pj_status_t status) 1577 { 1578 cli_telnet_fe *fe = (cli_telnet_fe *) pj_activesock_get_user_data(asock); 1579 1558 1580 pj_status_t sstatus; 1559 1581 pj_pool_t *pool; 1560 cli_telnet_sess *sess ;1582 cli_telnet_sess *sess = NULL; 1561 1583 pj_activesock_cb asock_cb; 1562 1584 … … 1566 1588 if (fe->is_quitting) 1567 1589 return PJ_FALSE; 1590 1591 if (status != PJ_SUCCESS && status != PJ_EPENDING) { 1592 TRACE_((THIS_FILE, "Error on data accept %d", status)); 1593 if (status == PJ_ESOCKETSTOP) 1594 telnet_restart(fe); 1595 1596 return PJ_FALSE; 1597 } 1568 1598 1569 1599 /* An incoming connection is accepted, create a new session */ … … 1658 1688 pj_cli_front_end **p_fe) 1659 1689 { 1660 structcli_telnet_fe *fe;1690 cli_telnet_fe *fe; 1661 1691 pj_pool_t *pool; 1662 pj_sock_t sock = PJ_INVALID_SOCKET; 1663 pj_activesock_cb asock_cb; 1664 pj_sockaddr_in addr; 1665 pj_status_t sstatus; 1692 pj_status_t status; 1666 1693 1667 1694 PJ_ASSERT_RETURN(cli, PJ_EINVAL); … … 1670 1697 PJ_CLI_TELNET_POOL_SIZE, PJ_CLI_TELNET_POOL_INC, 1671 1698 NULL); 1672 fe = PJ_POOL_ZALLOC_T(pool, structcli_telnet_fe);1699 fe = PJ_POOL_ZALLOC_T(pool, cli_telnet_fe); 1673 1700 if (!fe) 1674 1701 return PJ_ENOMEM; … … 1688 1715 fe->pool = pool; 1689 1716 1690 if (!fe->cfg.ioqueue) { 1717 if (!fe->cfg.ioqueue) { 1691 1718 /* Create own ioqueue if application doesn't supply one */ 1692 s status = pj_ioqueue_create(pool, 8, &fe->cfg.ioqueue);1693 if (s status != PJ_SUCCESS)1719 status = pj_ioqueue_create(pool, 8, &fe->cfg.ioqueue); 1720 if (status != PJ_SUCCESS) 1694 1721 goto on_exit; 1695 1722 fe->own_ioqueue = PJ_TRUE; 1696 1723 } 1697 1724 1698 s status = pj_mutex_create_recursive(pool, "mutex_telnet_fe", &fe->mutex);1699 if (s status != PJ_SUCCESS)1725 status = pj_mutex_create_recursive(pool, "mutex_telnet_fe", &fe->mutex); 1726 if (status != PJ_SUCCESS) 1700 1727 goto on_exit; 1701 1728 1702 1729 /* Start telnet daemon */ 1703 sstatus = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, 1704 &sock); 1705 if (sstatus != PJ_SUCCESS) 1730 telnet_start(fe); 1731 1732 pj_cli_register_front_end(cli, &fe->base); 1733 1734 if (p_fe) 1735 *p_fe = &fe->base; 1736 1737 return PJ_SUCCESS; 1738 1739 on_exit: 1740 if (fe->own_ioqueue) 1741 pj_ioqueue_destroy(fe->cfg.ioqueue); 1742 1743 if (fe->mutex) 1744 pj_mutex_destroy(fe->mutex); 1745 1746 pj_pool_release(pool); 1747 return status; 1748 } 1749 1750 static pj_status_t telnet_start(cli_telnet_fe *fe) 1751 { 1752 pj_sock_t sock = PJ_INVALID_SOCKET; 1753 pj_activesock_cb asock_cb; 1754 pj_sockaddr_in addr; 1755 pj_status_t status; 1756 int val; 1757 int restart_retry; 1758 unsigned msec; 1759 1760 /* Start telnet daemon */ 1761 status = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, &sock); 1762 1763 if (status != PJ_SUCCESS) 1706 1764 goto on_exit; 1707 1765 1708 1766 pj_sockaddr_in_init(&addr, NULL, fe->cfg.port); 1709 1767 1710 sstatus = pj_sock_bind(sock, &addr, sizeof(addr)); 1711 if (sstatus == PJ_SUCCESS) { 1712 pj_sockaddr_in addr; 1713 int addr_len = sizeof(addr); 1714 1715 sstatus = pj_sock_getsockname(sock, &addr, &addr_len); 1716 if (sstatus != PJ_SUCCESS) 1768 val = 1; 1769 status = pj_sock_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, 1770 &val, sizeof(val)); 1771 1772 if (status != PJ_SUCCESS) 1773 goto on_exit; 1774 1775 /* The loop is silly, but what else can we do? */ 1776 for (msec=MIN_WAIT_ON_TELNET_RESTART, restart_retry=0; 1777 restart_retry < MAX_RETRY_ON_TELNET_RESTART; 1778 ++restart_retry, msec=(msec<MAX_WAIT_ON_TELNET_RESTART? 1779 msec*2 : MAX_WAIT_ON_TELNET_RESTART)) 1780 { 1781 status = pj_sock_bind(sock, &addr, sizeof(addr)); 1782 if (status != PJ_STATUS_FROM_OS(EADDRINUSE)) 1783 break; 1784 PJ_LOG(4,(THIS_FILE, "Address is still in use, retrying..")); 1785 pj_thread_sleep(msec); 1786 } 1787 1788 if (status == PJ_SUCCESS) { 1789 int addr_len = sizeof(addr); 1790 1791 status = pj_sock_getsockname(sock, &addr, &addr_len); 1792 if (status != PJ_SUCCESS) 1717 1793 goto on_exit; 1718 1794 1719 fe->cfg.port = pj_sockaddr_in_get_port(&addr); 1720 if (param) 1721 param->port = fe->cfg.port; 1722 1723 PJ_LOG(3, (THIS_FILE, "CLI telnet daemon listening at port %d", 1724 fe->cfg.port)); 1725 1795 fe->cfg.port = pj_sockaddr_in_get_port(&addr); 1796 1726 1797 if (fe->cfg.prompt_str.slen == 0) { 1727 1798 pj_str_t prompt_sign = {"> ", 2}; … … 1738 1809 } 1739 1810 1740 s status = pj_sock_listen(sock, 4);1741 if (s status != PJ_SUCCESS)1811 status = pj_sock_listen(sock, 4); 1812 if (status != PJ_SUCCESS) 1742 1813 goto on_exit; 1743 1814 1744 1815 pj_bzero(&asock_cb, sizeof(asock_cb)); 1745 asock_cb.on_accept_complete = &telnet_fe_on_accept;1746 s status = pj_activesock_create(pool, sock, pj_SOCK_STREAM(),1747 1748 1749 if (s status != PJ_SUCCESS)1816 asock_cb.on_accept_complete2 = &telnet_fe_on_accept; 1817 status = pj_activesock_create(fe->pool, sock, pj_SOCK_STREAM(), 1818 NULL, fe->cfg.ioqueue, 1819 &asock_cb, fe, &fe->asock); 1820 if (status != PJ_SUCCESS) 1750 1821 goto on_exit; 1751 1822 1752 s status = pj_activesock_start_accept(fe->asock,pool);1753 if (s status != PJ_SUCCESS)1823 status = pj_activesock_start_accept(fe->asock, fe->pool); 1824 if (status != PJ_SUCCESS) 1754 1825 goto on_exit; 1755 1826 1756 1827 if (fe->own_ioqueue) { 1757 1828 /* Create our own worker thread */ 1758 s status = pj_thread_create(pool, "worker_telnet_fe",1759 1760 1761 if (s status != PJ_SUCCESS)1829 status = pj_thread_create(fe->pool, "worker_telnet_fe", 1830 &poll_worker_thread, fe, 0, 0, 1831 &fe->worker_thread); 1832 if (status != PJ_SUCCESS) 1762 1833 goto on_exit; 1763 1834 } 1764 1835 1765 pj_cli_register_front_end(cli, &fe->base); 1766 1767 if (p_fe) 1768 *p_fe = &fe->base; 1836 /** Fill telnet information and call pj_cli_telnet_on_started callback */ 1837 if (fe->cfg.on_started) { 1838 char ip_addr[32]; 1839 pj_cli_telnet_info telnet_info; 1840 pj_sockaddr hostip; 1841 1842 telnet_info.ip_address.ptr = ip_addr; 1843 telnet_info.ip_address.slen = 0; 1844 1845 status = pj_gethostip(pj_AF_INET(), &hostip); 1846 if (status != PJ_SUCCESS) 1847 goto on_exit; 1848 1849 pj_strcpy2(&telnet_info.ip_address, 1850 pj_inet_ntoa(hostip.ipv4.sin_addr)); 1851 1852 telnet_info.port = fe->cfg.port; 1853 1854 (*fe->cfg.on_started)(&telnet_info); 1855 } 1769 1856 1770 1857 return PJ_SUCCESS; … … 1782 1869 pj_mutex_destroy(fe->mutex); 1783 1870 1784 pj_pool_release(pool); 1785 return sstatus; 1786 } 1871 pj_pool_release(fe->pool); 1872 return status; 1873 } 1874 1875 static pj_status_t telnet_restart(cli_telnet_fe *fe) 1876 { 1877 pj_status_t status; 1878 pj_cli_sess *sess; 1879 1880 fe->is_quitting = PJ_TRUE; 1881 if (fe->worker_thread) { 1882 pj_thread_join(fe->worker_thread); 1883 } 1884 1885 pj_mutex_lock(fe->mutex); 1886 1887 /* Destroy all the sessions */ 1888 sess = fe->sess_head.next; 1889 while (sess != &fe->sess_head) { 1890 (*sess->op->destroy)(sess); 1891 sess = fe->sess_head.next; 1892 } 1893 1894 pj_mutex_unlock(fe->mutex); 1895 1896 /** Close existing activesock **/ 1897 status = pj_activesock_close(fe->asock); 1898 if (status != PJ_SUCCESS) 1899 goto on_exit; 1900 1901 if (fe->worker_thread) { 1902 pj_thread_destroy(fe->worker_thread); 1903 fe->worker_thread = NULL; 1904 } 1905 1906 fe->is_quitting = PJ_FALSE; 1907 1908 /** Start Telnet **/ 1909 status = telnet_start(fe); 1910 if (status == PJ_SUCCESS) 1911 TRACE_((THIS_FILE, "Telnet Restarted")); 1912 1913 on_exit: 1914 return status; 1915 }
Note: See TracChangeset
for help on using the changeset viewer.