PageRenderTime 61ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 1ms

/platform/FNET/fnet_stack/services/telnet/fnet_telnet.c

https://gitlab.com/fuggles/ucos
C | 753 lines | 469 code | 104 blank | 180 comment | 83 complexity | 6db96c8f2353023eea52e4a413dcf623 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0
  1. /**************************************************************************
  2. *
  3. * Copyright 2011-2015 by Andrey Butok. FNET Community.
  4. * Copyright 2008-2010 by Andrey Butok. Freescale Semiconductor, Inc.
  5. *
  6. ***************************************************************************
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU Lesser General Public License Version 3
  9. * or later (the "LGPL").
  10. *
  11. * As a special exception, the copyright holders of the FNET project give you
  12. * permission to link the FNET sources with independent modules to produce an
  13. * executable, regardless of the license terms of these independent modules,
  14. * and to copy and distribute the resulting executable under terms of your
  15. * choice, provided that you also meet, for each linked independent module,
  16. * the terms and conditions of the license of that module.
  17. * An independent module is a module which is not derived from or based
  18. * on this library.
  19. * If you modify the FNET sources, you may extend this exception
  20. * to your version of the FNET sources, but you are not obligated
  21. * to do so. If you do not wish to do so, delete this
  22. * exception statement from your version.
  23. *
  24. * This program is distributed in the hope that it will be useful,
  25. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  26. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  27. *
  28. * You should have received a copy of the GNU General Public License
  29. * and the GNU Lesser General Public License along with this program.
  30. * If not, see <http://www.gnu.org/licenses/>.
  31. *
  32. **********************************************************************/ /*!
  33. *
  34. * @file fnet_telnet.c
  35. *
  36. * @author Andrey Butok
  37. *
  38. * @brief FNET Telnet Server implementation.
  39. *
  40. ***************************************************************************/
  41. #include "fnet.h"
  42. #if FNET_CFG_TELNET
  43. /************************************************************************
  44. * Definitions
  45. ************************************************************************/
  46. #if FNET_CFG_DEBUG_TELNET
  47. #define FNET_DEBUG_TELNET FNET_DEBUG
  48. #else
  49. #define FNET_DEBUG_TELNET(...)
  50. #endif
  51. #define FNET_TELNET_WAIT_SEND_MS (2000) /* ms*/
  52. #define FNET_TELNET_TX_BUFFER_SIZE FNET_CFG_TELNET_SOCKET_BUF_SIZE
  53. #define FNET_TELNET_RX_BUFFER_SIZE (10)
  54. #if FNET_TELNET_TX_BUFFER_SIZE > 90 /* Check maximum value for TX application/stream buffer (optional check).*/
  55. #undef FNET_TELNET_TX_BUFFER_SIZE
  56. #define FNET_TELNET_TX_BUFFER_SIZE (90)
  57. #endif
  58. #if (FNET_TELNET_TX_BUFFER_SIZE < 5) /* Check minimum value for TX application/stream buffer.*/
  59. error "FNET_TELNET_TX_BUFFER_SIZE must be > 4"
  60. #endif
  61. /* Keepalive probe retransmit limit.*/
  62. #define FNET_TELNET_TCP_KEEPCNT (2)
  63. /* Keepalive retransmit interval.*/
  64. #define FNET_TELNET_TCP_KEEPINTVL (4) /*sec*/
  65. /* Time between keepalive probes.*/
  66. #define FNET_TELNET_TCP_KEEPIDLE (7) /*sec*/
  67. /* RFC:
  68. * All TELNET commands consist of at least a two byte sequence: the
  69. * "Interpret as Command" (IAC) escape character followed by the code
  70. * for the command. The commands dealing with option negotiation are
  71. * three byte sequences, the third byte being the code for the option
  72. * referenced.
  73. */
  74. /* RFC:
  75. * Since the NVT is what is left when no options are enabled, the DON’T and
  76. * WON’T responses are guaranteed to leave the connection in a state
  77. * which both ends can handle. Thus, all hosts may implement their
  78. * TELNET processes to be totally unaware of options that are not
  79. * supported, simply returning a rejection to (i.e., refusing) any
  80. * option request that cannot be understood.
  81. *
  82. * The Network Virtual Terminal (NVT) is a bi-directional character
  83. * device.
  84. */
  85. #define FNET_TELNET_CMD_IAC ((char)255) /* "Interpret as Command" (IAC) escape character followed by the code for the command. */
  86. #define FNET_TELNET_CMD_WILL ((char)251) /* Indicates the desire to begin performing, or confirmation that
  87. * you are now performing, the indicated option.*/
  88. #define FNET_TELNET_CMD_WONT ((char)252) /* Indicates the refusal to perform, or continue performing, the
  89. * indicated option. */
  90. #define FNET_TELNET_CMD_DO ((char)253) /* Indicates the request that the other party perform, or
  91. * confirmation that you are expecting the other party to perform, the
  92. * indicated option. */
  93. #define FNET_TELNET_CMD_DONT ((char)254) /* Indicates the demand that the other party stop performing,
  94. * or confirmation that you are no longer expecting the other party
  95. * to perform, the indicated option. */
  96. /*****************************************************************************
  97. * Telnet server states.
  98. ******************************************************************************/
  99. typedef enum
  100. {
  101. FNET_TELNET_STATE_DISABLED = 0, /* Telnet server service is
  102. * not initialized.
  103. */
  104. FNET_TELNET_STATE_LISTENING, /* Telnet server is listening
  105. * for client socket.
  106. */
  107. FNET_TELNET_STATE_RECEIVING, /* Ready to receive data from a Telnet client. */
  108. FNET_TELNET_STATE_IAC, /* Received IAC symbol. */
  109. FNET_TELNET_STATE_DONT , /* Prepare to send DON'T. */
  110. FNET_TELNET_STATE_WONT , /* Prepare to send WON'T. */
  111. FNET_TELNET_STATE_SKIP , /* Ignore next received character.*/
  112. FNET_TELNET_STATE_CLOSING /* Closing Telnet session.*/
  113. } fnet_telnet_state_t;
  114. /************************************************************************
  115. * Telnet interface control structure.
  116. *************************************************************************/
  117. struct fnet_telnet_session_if
  118. {
  119. fnet_telnet_state_t state; /* Current state.*/
  120. SOCKET socket_foreign; /* Foreign socket.*/
  121. char tx_buffer[FNET_TELNET_TX_BUFFER_SIZE]; /* Transmit liner buffer. */
  122. int tx_buffer_head_index; /* TX buffer index (write place).*/
  123. char rx_buffer[FNET_TELNET_RX_BUFFER_SIZE]; /* RX circular buffer */
  124. char *rx_buffer_head; /* The RX circular buffer write pointer. */
  125. char *rx_buffer_tail; /* The RX circular buffer read pointer. */
  126. char *rx_buffer_end; /* Pointer to the end of the Rx circular buffer. */
  127. fnet_shell_desc_t shell_descriptor;
  128. struct fnet_shell_params shell_params;
  129. char cmd_line_buffer[FNET_CFG_TELNET_CMD_LINE_BUF_SIZE];
  130. struct fnet_serial_stream stream;
  131. };
  132. /************************************************************************
  133. * Telnet interface control structure.
  134. *************************************************************************/
  135. struct fnet_telnet_if
  136. {
  137. SOCKET socket_listen; /* Listening socket.*/
  138. fnet_poll_desc_t service_descriptor; /* Descriptor of polling service.*/
  139. int enabled;
  140. int backlog;
  141. struct fnet_telnet_session_if *session_active;
  142. struct fnet_telnet_session_if session[FNET_CFG_TELNET_SESSION_MAX];
  143. };
  144. /* The Telnet interface */
  145. static struct fnet_telnet_if telnet_if_list[FNET_CFG_TELNET_MAX];
  146. /************************************************************************
  147. * Function Prototypes
  148. *************************************************************************/
  149. static void fnet_telnet_send(struct fnet_telnet_session_if *session);
  150. static void tx_buffer_write(struct fnet_telnet_session_if *session, char data);
  151. static int tx_buffer_free_space(struct fnet_telnet_session_if *session);
  152. static void rx_buffer_write (struct fnet_telnet_session_if *session, char data);
  153. static char rx_buffer_read(struct fnet_telnet_session_if *session);
  154. static int rx_buffer_free_space(struct fnet_telnet_session_if *session);
  155. static void fnet_telnet_putchar(long id, int character);
  156. static int fnet_telnet_getchar(long id);
  157. static void fnet_telnet_flush(long id);
  158. static void fnet_telnet_send_cmd(struct fnet_telnet_session_if *session, char command, char option);
  159. static void fnet_telnet_state_machine(void *telnet_if_p);
  160. /************************************************************************
  161. * Buffer functions.
  162. ************************************************************************/
  163. /* Write to Tx liner buffer. */
  164. /* It's posible to write FNET_TELNET_TX_BUFFER_SIZE-1 characters. */
  165. static void tx_buffer_write (struct fnet_telnet_session_if *session, char data)
  166. {
  167. session->tx_buffer[session->tx_buffer_head_index] = data;
  168. session->tx_buffer_head_index++;
  169. }
  170. /* Free space in Tx Liner buffer. */
  171. static int tx_buffer_free_space(struct fnet_telnet_session_if *session)
  172. {
  173. return(FNET_TELNET_TX_BUFFER_SIZE - session->tx_buffer_head_index);
  174. }
  175. /* Write to Rx circular buffer. */
  176. /* It's posible to write FNET_TELNET_RX_BUFFER_SIZE-1 characters. */
  177. static void rx_buffer_write (struct fnet_telnet_session_if *session, char data)
  178. {
  179. *session->rx_buffer_head = data;
  180. if(++session->rx_buffer_head==session->rx_buffer_end)
  181. session->rx_buffer_head=session->rx_buffer;
  182. }
  183. /* Read from Rx circular buffer. */
  184. static char rx_buffer_read (struct fnet_telnet_session_if *session)
  185. {
  186. char data = *session->rx_buffer_tail;
  187. if(++session->rx_buffer_tail==session->rx_buffer_end)
  188. session->rx_buffer_tail=session->rx_buffer;
  189. return data;
  190. }
  191. /* Free space in Rx circular buffer. */
  192. static int rx_buffer_free_space(struct fnet_telnet_session_if *session)
  193. {
  194. int space = session->rx_buffer_tail - session->rx_buffer_head;
  195. if (space<=0)
  196. space += FNET_TELNET_RX_BUFFER_SIZE;
  197. return (space-1);
  198. }
  199. /************************************************************************
  200. * NAME: fnet_telnet_putchar
  201. *
  202. * DESCRIPTION:
  203. ************************************************************************/
  204. static void fnet_telnet_putchar(long id, int character)
  205. {
  206. struct fnet_telnet_session_if *session = (struct fnet_telnet_session_if *)id;
  207. if(session->state != FNET_TELNET_STATE_CLOSING)
  208. {
  209. tx_buffer_write(session, (char)character);
  210. if(tx_buffer_free_space(session) < 1) /* Buffer is full => flush. */
  211. {
  212. fnet_telnet_send(session);
  213. }
  214. }
  215. }
  216. /************************************************************************
  217. * NAME: fnet_telnet_getchar
  218. *
  219. * DESCRIPTION:
  220. ************************************************************************/
  221. static int fnet_telnet_getchar(long id)
  222. {
  223. struct fnet_telnet_session_if *session = (struct fnet_telnet_session_if *)id;
  224. if(session->rx_buffer_tail != session->rx_buffer_head) /* If there is something. */
  225. {
  226. return rx_buffer_read (session);
  227. }
  228. else
  229. return FNET_ERR;
  230. }
  231. /************************************************************************
  232. * NAME: fnet_telnet_flush
  233. *
  234. * DESCRIPTION:
  235. ************************************************************************/
  236. static void fnet_telnet_flush(long id)
  237. {
  238. struct fnet_telnet_session_if *session = (struct fnet_telnet_session_if *)id;
  239. fnet_telnet_send(session);
  240. }
  241. /************************************************************************
  242. * NAME: fnet_telnet_send
  243. *
  244. * DESCRIPTION:
  245. ************************************************************************/
  246. static void fnet_telnet_send(struct fnet_telnet_session_if *session)
  247. {
  248. int res;
  249. int tx_buffer_tail_index = 0;
  250. unsigned long timeout = fnet_timer_ticks();
  251. /* Send all data in the buffer.*/
  252. while(tx_buffer_tail_index != session->tx_buffer_head_index)
  253. {
  254. if((res = send(session->socket_foreign, &session->tx_buffer[tx_buffer_tail_index], session->tx_buffer_head_index - tx_buffer_tail_index, 0)) != SOCKET_ERROR)
  255. {
  256. if(res) /* >0 */
  257. {
  258. /* Update buffer pointers. */
  259. tx_buffer_tail_index += res;
  260. /* Reset timeout. */
  261. timeout = fnet_timer_ticks();
  262. }
  263. else if( fnet_timer_get_interval(timeout, fnet_timer_ticks())
  264. > (FNET_TELNET_WAIT_SEND_MS / FNET_TIMER_PERIOD_MS) ) /* Check timeout */
  265. {
  266. FNET_DEBUG_TELNET("TELNET:Send timeout.");
  267. break; /* Time-out. */
  268. }
  269. }
  270. else /* Error.*/
  271. {
  272. FNET_DEBUG_TELNET("TELNET:Send error.");
  273. session->state = FNET_TELNET_STATE_CLOSING; /*=> CLOSING */
  274. break;
  275. }
  276. }
  277. /* Reset TX buffer index. */
  278. session->tx_buffer_head_index = 0;
  279. }
  280. /************************************************************************
  281. * NAME: fnet_telnet_send_cmd
  282. *
  283. * DESCRIPTION: Wrie command to the TX buffer.
  284. ************************************************************************/
  285. static void fnet_telnet_send_cmd(struct fnet_telnet_session_if *session, char command, char option )
  286. {
  287. tx_buffer_write(session, (char)FNET_TELNET_CMD_IAC);
  288. tx_buffer_write(session, command);
  289. tx_buffer_write(session, option);
  290. /* Send the command.*/
  291. fnet_telnet_send(session);
  292. FNET_DEBUG_TELNET("TELNET: Send option = %d", option);
  293. }
  294. /************************************************************************
  295. * NAME: fnet_telnet_state_machine
  296. *
  297. * DESCRIPTION: Telnet server state machine.
  298. ************************************************************************/
  299. static void fnet_telnet_state_machine( void *telnet_if_p )
  300. {
  301. struct sockaddr foreign_addr;
  302. int res;
  303. struct fnet_telnet_if *telnet = (struct fnet_telnet_if *)telnet_if_p;
  304. char rx_data[1];
  305. unsigned int len;
  306. int i;
  307. struct fnet_telnet_session_if *session;
  308. for(i=0; i<FNET_CFG_TELNET_SESSION_MAX; i++)
  309. {
  310. session = &telnet->session[i];
  311. telnet->session_active = session;
  312. do
  313. {
  314. switch(session->state)
  315. {
  316. /*---- LISTENING ------------------------------------------------*/
  317. case FNET_TELNET_STATE_LISTENING:
  318. len = sizeof(foreign_addr);
  319. session->socket_foreign = accept(telnet->socket_listen, (struct sockaddr *) &foreign_addr, &len);
  320. if(session->socket_foreign != SOCKET_INVALID)
  321. {
  322. #if FNET_CFG_DEBUG_TELNET
  323. {
  324. char ip_str[FNET_IP_ADDR_STR_SIZE];
  325. fnet_inet_ntop(foreign_addr.sa_family, foreign_addr.sa_data, ip_str, sizeof(ip_str));
  326. FNET_DEBUG_TELNET("\nTELNET: New connection: %s; Port: %d.", ip_str, fnet_ntohs(foreign_addr.sa_port));
  327. }
  328. #endif
  329. /* Init Shell. */
  330. session->shell_descriptor = fnet_shell_init(&session->shell_params);
  331. if(session->shell_descriptor == FNET_ERR)
  332. {
  333. session->shell_descriptor = 0;
  334. FNET_DEBUG_TELNET("TELNET: Shell Service registration error.");
  335. session->state = FNET_TELNET_STATE_CLOSING; /*=> CLOSING */
  336. }
  337. else
  338. {
  339. listen(telnet->socket_listen, --telnet->backlog); /* Ignor other connections.*/
  340. /* Reset TX timeout. */
  341. session->state = FNET_TELNET_STATE_RECEIVING; /* => WAITING data */
  342. }
  343. }
  344. break;
  345. /*---- NORMAL -----------------------------------------------*/
  346. case FNET_TELNET_STATE_RECEIVING:
  347. if(rx_buffer_free_space(session)>0)
  348. {
  349. res = recv(session->socket_foreign, rx_data, 1, 0);
  350. if(res == 1)
  351. {
  352. if(rx_data[0] == FNET_TELNET_CMD_IAC )
  353. {
  354. session->state = FNET_TELNET_STATE_IAC; /*=> Handle IAC */
  355. }
  356. else
  357. {
  358. rx_buffer_write (session, rx_data[0]);
  359. }
  360. }
  361. else if (res == SOCKET_ERROR)
  362. {
  363. session->state = FNET_TELNET_STATE_CLOSING; /*=> CLOSING */
  364. }
  365. }
  366. break;
  367. /*---- IAC -----------------------------------------------*/
  368. case FNET_TELNET_STATE_IAC:
  369. FNET_DEBUG_TELNET("TELNET: STATE_IAC");
  370. if((res = recv(session->socket_foreign, rx_data, 1, 0) )!= SOCKET_ERROR)
  371. {
  372. if(res)
  373. {
  374. switch(rx_data[0])
  375. {
  376. case FNET_TELNET_CMD_WILL:
  377. session->state = FNET_TELNET_STATE_DONT;
  378. break;
  379. case FNET_TELNET_CMD_DO:
  380. session->state = FNET_TELNET_STATE_WONT;
  381. break;
  382. case FNET_TELNET_CMD_WONT:
  383. case FNET_TELNET_CMD_DONT:
  384. session->state = FNET_TELNET_STATE_SKIP ;
  385. break;
  386. case FNET_TELNET_CMD_IAC:
  387. /*
  388. the IAC need be doubled to be sent as data, and
  389. the other 255 codes may be passed transparently.
  390. */
  391. rx_buffer_write (session, rx_data[0]);
  392. default:
  393. session->state = FNET_TELNET_STATE_RECEIVING; /*=> Ignore commands */
  394. }
  395. }
  396. }
  397. else
  398. {
  399. session->state = FNET_TELNET_STATE_CLOSING; /*=> CLOSING */
  400. }
  401. break;
  402. /*---- DONT & WONT -----------------------------------------------*/
  403. case FNET_TELNET_STATE_DONT:
  404. case FNET_TELNET_STATE_WONT:
  405. {
  406. char command;
  407. if(session->state == FNET_TELNET_STATE_DONT)
  408. {
  409. FNET_DEBUG_TELNET("TELNET: STATE_DONT");
  410. command = FNET_TELNET_CMD_DONT;
  411. }
  412. else
  413. {
  414. FNET_DEBUG_TELNET("TELNET: STATE_WONT");
  415. command = FNET_TELNET_CMD_WONT;
  416. }
  417. if(tx_buffer_free_space(session) >= 3)
  418. {
  419. res = recv(session->socket_foreign, rx_data, 1, 0);
  420. if(res == 1)
  421. {
  422. /* Send command. */
  423. fnet_telnet_send_cmd(session, command, rx_data[0]);
  424. session->state = FNET_TELNET_STATE_RECEIVING;
  425. }
  426. else if (res == SOCKET_ERROR)
  427. {
  428. session->state = FNET_TELNET_STATE_CLOSING; /*=> CLOSING */
  429. }
  430. }
  431. }
  432. break;
  433. /*---- SKIP -----------------------------------------------*/
  434. case FNET_TELNET_STATE_SKIP:
  435. FNET_DEBUG_TELNET("TELNET: STATE_SKIP");
  436. res = recv(session->socket_foreign, rx_data, 1, 0);
  437. if(res == 1)
  438. {
  439. session->state = FNET_TELNET_STATE_RECEIVING;
  440. }
  441. else if (res == SOCKET_ERROR)
  442. {
  443. session->state = FNET_TELNET_STATE_CLOSING; /*=> CLOSING */
  444. }
  445. break;
  446. /*---- CLOSING --------------------------------------------*/
  447. case FNET_TELNET_STATE_CLOSING:
  448. FNET_DEBUG_TELNET("TELNET: STATE_CLOSING");
  449. if(session->shell_descriptor)
  450. {
  451. fnet_shell_release(session->shell_descriptor);
  452. session->shell_descriptor = 0;
  453. }
  454. session->rx_buffer_head = session->rx_buffer;
  455. session->rx_buffer_tail = session->rx_buffer;
  456. closesocket(session->socket_foreign);
  457. session->socket_foreign = SOCKET_INVALID;
  458. listen(telnet->socket_listen, ++telnet->backlog); /* Allow connection.*/
  459. session->state = FNET_TELNET_STATE_LISTENING; /*=> LISTENING */
  460. break;
  461. default:
  462. break;
  463. }
  464. }
  465. while(session->state == FNET_TELNET_STATE_CLOSING);
  466. }
  467. }
  468. /************************************************************************
  469. * NAME: fnet_telnet_init
  470. *
  471. * DESCRIPTION: Initialization of the Telnet server.
  472. *************************************************************************/
  473. fnet_telnet_desc_t fnet_telnet_init( struct fnet_telnet_params *params )
  474. {
  475. struct sockaddr local_addr;
  476. struct fnet_telnet_if *telnet_if = 0;
  477. /* Socket options. */
  478. const struct linger linger_option ={1, /*l_onoff*/
  479. 4 /*l_linger*/};
  480. const unsigned long bufsize_option = FNET_CFG_TELNET_SOCKET_BUF_SIZE;
  481. const int keepalive_option = 1;
  482. const int keepcnt_option = FNET_TELNET_TCP_KEEPCNT;
  483. const int keepintvl_option = FNET_TELNET_TCP_KEEPINTVL;
  484. const int keepidle_option = FNET_TELNET_TCP_KEEPIDLE;
  485. int i;
  486. if(params == 0 )
  487. {
  488. FNET_DEBUG_TELNET("TELNET: Wrong init parameters.");
  489. goto ERROR_1;
  490. }
  491. /* Try to find free Telnet server descriptor. */
  492. #if (FNET_CFG_TELNET_MAX > 1)
  493. {
  494. int i;
  495. for(i=0; i<FNET_CFG_TELNET_MAX; i++)
  496. {
  497. if(telnet_if_list[i].enabled == FNET_FALSE)
  498. {
  499. telnet_if = &telnet_if_list[i];
  500. break;
  501. }
  502. }
  503. }
  504. #else
  505. if(telnet_if_list[0].enabled == FNET_FALSE)
  506. telnet_if = &telnet_if_list[0];
  507. #endif
  508. /* No free Telnet server descriptor. */
  509. if(telnet_if == 0)
  510. {
  511. FNET_DEBUG_TELNET("TELNET: No free Telnet Server.");
  512. goto ERROR_1;
  513. }
  514. local_addr = params->address;
  515. if(local_addr.sa_port == 0)
  516. local_addr.sa_port = FNET_CFG_TELNET_PORT; /* Aply the default port. */
  517. if(local_addr.sa_family == AF_UNSPEC)
  518. local_addr.sa_family = AF_SUPPORTED; /* Asign supported families.*/
  519. /* Create listen socket */
  520. if((telnet_if->socket_listen = socket(local_addr.sa_family, SOCK_STREAM, 0)) == SOCKET_INVALID)
  521. {
  522. FNET_DEBUG_TELNET("TELNET: Socket creation error.");
  523. goto ERROR_1;
  524. }
  525. if(bind(telnet_if->socket_listen, (struct sockaddr *)(&local_addr), sizeof(local_addr)) == SOCKET_ERROR)
  526. {
  527. FNET_DEBUG_TELNET("TELNET: Socket bind error.");
  528. goto ERROR_2;
  529. }
  530. /* Set socket options. */
  531. if( /* Setup linger option. */
  532. (setsockopt (telnet_if->socket_listen, SOL_SOCKET, SO_LINGER, (char *)&linger_option, sizeof(linger_option)) == SOCKET_ERROR) ||
  533. /* Set socket buffer size. */
  534. (setsockopt(telnet_if->socket_listen, SOL_SOCKET, SO_RCVBUF, (char *) &bufsize_option, sizeof(bufsize_option))== SOCKET_ERROR) ||
  535. (setsockopt(telnet_if->socket_listen, SOL_SOCKET, SO_SNDBUF, (char *) &bufsize_option, sizeof(bufsize_option))== SOCKET_ERROR) ||
  536. /* Enable keepalive_option option. */
  537. (setsockopt (telnet_if->socket_listen, SOL_SOCKET, SO_KEEPALIVE, (char *)&keepalive_option, sizeof(keepalive_option)) == SOCKET_ERROR) ||
  538. /* Keepalive probe retransmit limit. */
  539. (setsockopt (telnet_if->socket_listen, IPPROTO_TCP, TCP_KEEPCNT, (char *)&keepcnt_option, sizeof(keepcnt_option)) == SOCKET_ERROR) ||
  540. /* Keepalive retransmit interval.*/
  541. (setsockopt (telnet_if->socket_listen, IPPROTO_TCP, TCP_KEEPINTVL, (char *)&keepintvl_option, sizeof(keepintvl_option)) == SOCKET_ERROR) ||
  542. /* Time between keepalive probes.*/
  543. (setsockopt (telnet_if->socket_listen, IPPROTO_TCP, TCP_KEEPIDLE, (char *)&keepidle_option, sizeof(keepidle_option)) == SOCKET_ERROR)
  544. )
  545. {
  546. FNET_DEBUG_TELNET("TELNET: Socket setsockopt() error.");
  547. goto ERROR_2;
  548. }
  549. telnet_if->backlog = FNET_CFG_TELNET_SESSION_MAX;
  550. if(listen(telnet_if->socket_listen, telnet_if->backlog) == SOCKET_ERROR)
  551. {
  552. FNET_DEBUG_TELNET("TELNET: Socket listen error.");
  553. goto ERROR_2;
  554. }
  555. /* Register service. */
  556. telnet_if->service_descriptor = fnet_poll_service_register(fnet_telnet_state_machine, (void *) telnet_if);
  557. if(telnet_if->service_descriptor == (fnet_poll_desc_t)FNET_ERR)
  558. {
  559. FNET_DEBUG_TELNET("TELNET: Service registration error.");
  560. goto ERROR_2;
  561. }
  562. for(i=0; i<FNET_CFG_TELNET_SESSION_MAX; i++)
  563. {
  564. struct fnet_telnet_session_if *session = &telnet_if->session[i];
  565. /* Reset buffer pointers. Move it to init state. */
  566. session->tx_buffer_head_index = 0;
  567. session->rx_buffer_head = session->rx_buffer;
  568. session->rx_buffer_tail = session->rx_buffer;
  569. session->rx_buffer_end = &session->rx_buffer[FNET_TELNET_RX_BUFFER_SIZE];
  570. /* Setup stream. */
  571. session->stream.id = (long)(session);
  572. session->stream.putchar = fnet_telnet_putchar;
  573. session->stream.getchar = fnet_telnet_getchar;
  574. session->stream.flush = fnet_telnet_flush;
  575. /* Init shell. */
  576. session->shell_params.shell = params->shell;
  577. session->shell_params.cmd_line_buffer = session->cmd_line_buffer;
  578. session->shell_params.cmd_line_buffer_size = sizeof(session->cmd_line_buffer);
  579. session->shell_params.stream = &session->stream;
  580. session->shell_params.echo = FNET_CFG_TELNET_SHELL_ECHO;
  581. session->socket_foreign = SOCKET_INVALID;
  582. session->state = FNET_TELNET_STATE_LISTENING;
  583. }
  584. telnet_if->session_active = FNET_NULL;
  585. telnet_if->enabled = FNET_TRUE;
  586. return (fnet_telnet_desc_t)telnet_if;
  587. ERROR_2:
  588. closesocket(telnet_if->socket_listen);
  589. ERROR_1:
  590. return (fnet_telnet_desc_t)FNET_ERR;
  591. }
  592. /************************************************************************
  593. * NAME: fnet_telnet_release
  594. *
  595. * DESCRIPTION: Telnet server release.
  596. ************************************************************************/
  597. void fnet_telnet_release(fnet_telnet_desc_t desc)
  598. {
  599. struct fnet_telnet_if *telnet_if = (struct fnet_telnet_if *) desc;
  600. int i;
  601. if(telnet_if && (telnet_if->enabled == FNET_TRUE))
  602. {
  603. for(i=0; i<FNET_CFG_TELNET_SESSION_MAX; i++)
  604. {
  605. struct fnet_telnet_session_if *session = &telnet_if->session[i];
  606. closesocket(session->socket_foreign);
  607. session->socket_foreign = SOCKET_INVALID;
  608. if(session->shell_descriptor)
  609. {
  610. fnet_shell_release(session->shell_descriptor);
  611. session->shell_descriptor = 0;
  612. }
  613. session->state = FNET_TELNET_STATE_DISABLED;
  614. }
  615. closesocket(telnet_if->socket_listen);
  616. fnet_poll_service_unregister(telnet_if->service_descriptor); /* Delete service.*/
  617. telnet_if->enabled = FNET_FALSE;
  618. }
  619. }
  620. /************************************************************************
  621. * NAME: fnet_telnet_close_session
  622. *
  623. * DESCRIPTION: Close current Telnet server session.
  624. ************************************************************************/
  625. void fnet_telnet_close_session(fnet_telnet_desc_t desc)
  626. {
  627. struct fnet_telnet_if *telnet_if = (struct fnet_telnet_if *) desc;
  628. if(telnet_if && (telnet_if->enabled == FNET_TRUE) && telnet_if->session_active)
  629. {
  630. telnet_if->session_active->state = FNET_TELNET_STATE_CLOSING;
  631. }
  632. }
  633. /************************************************************************
  634. * NAME: fnet_telnet_enabled
  635. *
  636. * DESCRIPTION: This function returns FNET_TRUE if the Telnet server
  637. * is enabled/initialised.
  638. ************************************************************************/
  639. int fnet_telnet_enabled(fnet_telnet_desc_t desc)
  640. {
  641. struct fnet_telnet_if *telnet_if = (struct fnet_telnet_if *) desc;
  642. int result;
  643. if(telnet_if)
  644. result = telnet_if->enabled;
  645. else
  646. result = FNET_FALSE;
  647. return result;
  648. }
  649. #endif /* FNET_CFG_TELNET */