/************************************************************************ * NAME: fapp_init * * DESCRIPTION: FNET Application initialization. ************************************************************************/ void fapp_init(void) { static fnet_uint8_t stack_heap[FNET_CFG_HEAP_SIZE]; struct fnet_init_params init_params; struct fnet_shell_params shell_params; /* Input parameters for FNET stack initialization */ init_params.netheap_ptr = stack_heap; init_params.netheap_size = FNET_CFG_HEAP_SIZE; /* Add event handler on duplicated IP address */ #if FNET_CFG_IP4 fnet_netif_dupip_handler_init (fapp_dup_ip_handler); #endif /* Init FNET stack */ if(fnet_init(&init_params) != FNET_ERR) { #if FAPP_CFG_PARAMS_READ_FLASH /* During bootup, the most recently stored customer configuration data will be read and used to configure the interfaces.*/ if(fapp_params_from_flash() == FNET_OK) { fnet_printf(FAPP_PARAMS_LOAD_STR); } #endif if(fnet_netif_get_default() == FNET_NULL) { fnet_printf(FAPP_NET_ERR); } #if (FAPP_CFG_EXP_CMD && FNET_CFG_FS) || (FAPP_CFG_HTTP_CMD && FNET_CFG_HTTP) fapp_fs_mount(); /* Init FS and mount FS Image. */ #endif /* Init main shell. */ shell_params.shell = &fapp_shell; shell_params.cmd_line_buffer = fapp_cmd_line_buffer; shell_params.cmd_line_buffer_size = sizeof(fapp_cmd_line_buffer); shell_params.stream = FNET_SERIAL_STREAM_DEFAULT; shell_params.echo = FNET_TRUE; if((fapp_shell_desc = fnet_shell_init(&shell_params)) != FNET_ERR) { fapp_boot(fapp_shell_desc); } else { fnet_printf(FAPP_INIT_ERR, "Shell"); } } else { fnet_printf(FAPP_INIT_ERR, "FNET"); } }
/************************************************************************ * NAME: fnet_telnet_state_machine * * DESCRIPTION: Telnet server state machine. ************************************************************************/ static void fnet_telnet_state_machine( void *telnet_if_p ) { struct sockaddr foreign_addr; int res; struct fnet_telnet_if *telnet = (struct fnet_telnet_if *)telnet_if_p; char rx_data[1]; int len; int i; struct fnet_telnet_session_if *session; for(i=0; i<FNET_CFG_TELNET_SESSION_MAX; i++) { session = &telnet->session[i]; telnet->session_active = session; do { switch(session->state) { /*---- LISTENING ------------------------------------------------*/ case FNET_TELNET_STATE_LISTENING: len = sizeof(foreign_addr); session->socket_foreign = accept(telnet->socket_listen, (struct sockaddr *) &foreign_addr, &len); if(session->socket_foreign != SOCKET_INVALID) { #if FNET_CFG_DEBUG_TELNET { char ip_str[FNET_IP_ADDR_STR_SIZE]; fnet_inet_ntop(foreign_addr.sa_family, foreign_addr.sa_data, ip_str, sizeof(ip_str)); FNET_DEBUG_TELNET("\nTELNET: New connection: %s; Port: %d.", ip_str, fnet_ntohs(foreign_addr.sa_port)); } #endif /* Init Shell. */ session->shell_descriptor = fnet_shell_init(&session->shell_params); if(session->shell_descriptor == FNET_ERR) { session->shell_descriptor = 0; FNET_DEBUG_TELNET("TELNET: Shell Service registration error."); session->state = FNET_TELNET_STATE_CLOSING; /*=> CLOSING */ } else { listen(telnet->socket_listen, --telnet->backlog); /* Ignor other connections.*/ /* Reset TX timeout. */ session->state = FNET_TELNET_STATE_RECEIVING; /* => WAITING data */ } } break; /*---- NORMAL -----------------------------------------------*/ case FNET_TELNET_STATE_RECEIVING: if(rx_buffer_free_space(session)>0) { res = recv(session->socket_foreign, rx_data, 1, 0); if(res == 1) { if(rx_data[0] == FNET_TELNET_CMD_IAC ) { session->state = FNET_TELNET_STATE_IAC; /*=> Handle IAC */ } else { rx_buffer_write (session, rx_data[0]); } } else if (res == SOCKET_ERROR) { session->state = FNET_TELNET_STATE_CLOSING; /*=> CLOSING */ } } break; /*---- IAC -----------------------------------------------*/ case FNET_TELNET_STATE_IAC: FNET_DEBUG_TELNET("TELNET: STATE_IAC"); if((res = recv(session->socket_foreign, rx_data, 1, 0) )!= SOCKET_ERROR) { if(res) { switch(rx_data[0]) { case FNET_TELNET_CMD_WILL: session->state = FNET_TELNET_STATE_DONT; break; case FNET_TELNET_CMD_DO: session->state = FNET_TELNET_STATE_WONT; break; case FNET_TELNET_CMD_WONT: case FNET_TELNET_CMD_DONT: session->state = FNET_TELNET_STATE_SKIP ; break; case FNET_TELNET_CMD_IAC: /* the IAC need be doubled to be sent as data, and the other 255 codes may be passed transparently. */ rx_buffer_write (session, rx_data[0]); default: session->state = FNET_TELNET_STATE_RECEIVING; /*=> Ignore commands */ } } } else { session->state = FNET_TELNET_STATE_CLOSING; /*=> CLOSING */ } break; /*---- DONT & WONT -----------------------------------------------*/ case FNET_TELNET_STATE_DONT: case FNET_TELNET_STATE_WONT: { char command; if(session->state == FNET_TELNET_STATE_DONT) { FNET_DEBUG_TELNET("TELNET: STATE_DONT"); command = FNET_TELNET_CMD_DONT; } else { FNET_DEBUG_TELNET("TELNET: STATE_WONT"); command = FNET_TELNET_CMD_WONT; } if(tx_buffer_free_space(session) >= 3) { res = recv(session->socket_foreign, rx_data, 1, 0); if(res == 1) { /* Send command. */ fnet_telnet_send_cmd(session, command, rx_data[0]); session->state = FNET_TELNET_STATE_RECEIVING; } else if (res == SOCKET_ERROR) { session->state = FNET_TELNET_STATE_CLOSING; /*=> CLOSING */ } } } break; /*---- SKIP -----------------------------------------------*/ case FNET_TELNET_STATE_SKIP: FNET_DEBUG_TELNET("TELNET: STATE_SKIP"); res = recv(session->socket_foreign, rx_data, 1, 0); if(res == 1) { session->state = FNET_TELNET_STATE_RECEIVING; } else if (res == SOCKET_ERROR) { session->state = FNET_TELNET_STATE_CLOSING; /*=> CLOSING */ } break; /*---- CLOSING --------------------------------------------*/ case FNET_TELNET_STATE_CLOSING: FNET_DEBUG_TELNET("TELNET: STATE_CLOSING"); if(session->shell_descriptor) { fnet_shell_release(session->shell_descriptor); session->shell_descriptor = 0; } session->rx_buffer_head = session->rx_buffer; session->rx_buffer_tail = session->rx_buffer; closesocket(session->socket_foreign); session->socket_foreign = SOCKET_INVALID; listen(telnet->socket_listen, ++telnet->backlog); /* Allow connection.*/ session->state = FNET_TELNET_STATE_LISTENING; /*=> LISTENING */ break; default: break; } } while(session->state == FNET_TELNET_STATE_CLOSING); } }