Beispiel #1
0
/************************************************************************
* NAME: fnet_telnet_send_cmd
*
* DESCRIPTION: Wrie command to the TX buffer.
************************************************************************/
static void fnet_telnet_send_cmd(struct fnet_telnet_session_if *session, char command, char option )
{
    tx_buffer_write(session, (char)FNET_TELNET_CMD_IAC);
    tx_buffer_write(session, command);
    tx_buffer_write(session, option);
    
    /* Send the command.*/
    fnet_telnet_send(session);
    
    FNET_DEBUG_TELNET("TELNET: Send option = %d", option);
}
Beispiel #2
0
/************************************************************************
* DESCRIPTION:
************************************************************************/
static void fnet_telnet_send(struct fnet_telnet_session_if *session)
{
    fnet_int32_t    res;
    fnet_index_t    tx_buffer_tail_index = 0u;
    fnet_time_t     timeout = fnet_timer_get_ticks();

    /* Send all data in the buffer.*/
    while((tx_buffer_tail_index != session->tx_buffer_head_index) && (session->state != FNET_TELNET_STATE_CLOSING))
    {
        if((res = fnet_socket_send(session->socket_foreign, &session->tx_buffer[tx_buffer_tail_index], (fnet_size_t)session->tx_buffer_head_index - tx_buffer_tail_index, 0u)) != FNET_ERR)
        {
            if(res) /* >0 */
            {
                /* Update buffer pointers. */
                tx_buffer_tail_index += (fnet_index_t)res;

                /* Reset timeout. */
                timeout = fnet_timer_get_ticks();
            }
            else if( fnet_timer_get_interval(timeout, fnet_timer_get_ticks())
                     > (FNET_TELNET_WAIT_SEND_MS / FNET_TIMER_PERIOD_MS) ) /* Check timeout */
            {
                FNET_DEBUG_TELNET("TELNET:Send timeout.");
                break; /* Time-out. */
            }
            else
            {}
        }
        else /* Error.*/
        {
            FNET_DEBUG_TELNET("TELNET:Send error.");
            session->state = FNET_TELNET_STATE_CLOSING; /*=> CLOSING */
        }
    }

    /* Reset TX buffer index. */
    session->tx_buffer_head_index = 0u;
}
Beispiel #3
0
/************************************************************************
* NAME: fnet_telnet_send
*
* DESCRIPTION: 
************************************************************************/
static void fnet_telnet_send(struct fnet_telnet_session_if *session)
{
    int             res;
    int             tx_buffer_tail_index = 0;
    unsigned long   timeout = fnet_timer_ticks();
    
    /* Send all data in the buffer.*/
    while(tx_buffer_tail_index != session->tx_buffer_head_index)
    {
        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)
        {
            if(res) /* >0 */
            {
                /* Update buffer pointers. */
                tx_buffer_tail_index += res;

                /* Reset timeout. */
                timeout = fnet_timer_ticks();           
            }
            else if( fnet_timer_get_interval(timeout, fnet_timer_ticks())
                         > (FNET_TELNET_WAIT_SEND_MS / FNET_TIMER_PERIOD_MS) ) /* Check timeout */
            {
                FNET_DEBUG_TELNET("TELNET:Send timeout.");
                break; /* Time-out. */
            }
        }
        else /* Error.*/
        {
            FNET_DEBUG_TELNET("TELNET:Send error.");
            session->state = FNET_TELNET_STATE_CLOSING; /*=> CLOSING */
            break; 
        }
    }
    
    /* Reset TX buffer index. */ 
    session->tx_buffer_head_index = 0;
}
Beispiel #4
0
/************************************************************************
* NAME: fnet_telnet_init
*
* DESCRIPTION: Initialization of the Telnet server.
*************************************************************************/
fnet_telnet_desc_t fnet_telnet_init( struct fnet_telnet_params *params )
{
    struct sockaddr         local_addr;
    struct fnet_telnet_if   *telnet_if = 0;
    
    /* Socket options. */
    const struct linger     linger_option ={1, /*l_onoff*/
                                        4  /*l_linger*/};
    const unsigned long     bufsize_option = FNET_CFG_TELNET_SOCKET_BUF_SIZE;
    const int               keepalive_option = 1;
    const int               keepcnt_option = FNET_TELNET_TCP_KEEPCNT;
    const int               keepintvl_option = FNET_TELNET_TCP_KEEPINTVL;
    const int               keepidle_option = FNET_TELNET_TCP_KEEPIDLE;
    int                     i;
    
    if(params == 0 )
    {
        FNET_DEBUG_TELNET("TELNET: Wrong init parameters.");
        goto ERROR_1;
    }

    /* Try to find free Telnet server descriptor. */
#if (FNET_CFG_TELNET_MAX > 1)
    {
        int i;
        for(i=0; i<FNET_CFG_TELNET_MAX; i++)
        {
            if(telnet_if_list[i].enabled == FNET_FALSE)
            {
                telnet_if = &telnet_if_list[i];
                break; 
            }
        }
    }
#else
    if(telnet_if_list[0].enabled == FNET_FALSE)
        telnet_if = &telnet_if_list[0];
#endif

    /* No free Telnet server descriptor. */
    if(telnet_if == 0)
    {
        FNET_DEBUG_TELNET("TELNET: No free Telnet Server.");
        goto ERROR_1;
    }
   
    local_addr = params->address;
    
    if(local_addr.sa_port == 0)
        local_addr.sa_port = FNET_CFG_TELNET_PORT;  /* Aply the default port. */
    
    if(local_addr.sa_family == AF_UNSPEC)
        local_addr.sa_family = AF_SUPPORTED;   /* Asign supported families.*/
    
     /* Create listen socket */
    if((telnet_if->socket_listen = socket(local_addr.sa_family, SOCK_STREAM, 0)) == SOCKET_INVALID)
    {
        FNET_DEBUG_TELNET("TELNET: Socket creation error.");
        goto ERROR_1;
    }   

    if(bind(telnet_if->socket_listen, (struct sockaddr *)(&local_addr), sizeof(local_addr)) == SOCKET_ERROR)
    {
        FNET_DEBUG_TELNET("TELNET: Socket bind error.");
        goto ERROR_2;
    }
    
    /* Set socket options. */    
    if( /* Setup linger option. */
        (setsockopt (telnet_if->socket_listen, SOL_SOCKET, SO_LINGER, (char *)&linger_option, sizeof(linger_option)) == SOCKET_ERROR) ||
         /* Set socket buffer size. */
        (setsockopt(telnet_if->socket_listen, SOL_SOCKET, SO_RCVBUF, (char *) &bufsize_option, sizeof(bufsize_option))== SOCKET_ERROR) ||
        (setsockopt(telnet_if->socket_listen, SOL_SOCKET, SO_SNDBUF, (char *) &bufsize_option, sizeof(bufsize_option))== SOCKET_ERROR) ||
        /* Enable keepalive_option option. */
        (setsockopt (telnet_if->socket_listen, SOL_SOCKET, SO_KEEPALIVE, (char *)&keepalive_option, sizeof(keepalive_option)) == SOCKET_ERROR) ||
        /* Keepalive probe retransmit limit. */
        (setsockopt (telnet_if->socket_listen, IPPROTO_TCP, TCP_KEEPCNT, (char *)&keepcnt_option, sizeof(keepcnt_option)) == SOCKET_ERROR) ||
        /* Keepalive retransmit interval.*/
        (setsockopt (telnet_if->socket_listen, IPPROTO_TCP, TCP_KEEPINTVL, (char *)&keepintvl_option, sizeof(keepintvl_option)) == SOCKET_ERROR) ||
        /* Time between keepalive probes.*/
        (setsockopt (telnet_if->socket_listen, IPPROTO_TCP, TCP_KEEPIDLE, (char *)&keepidle_option, sizeof(keepidle_option)) == SOCKET_ERROR)
    )
    {
        FNET_DEBUG_TELNET("TELNET: Socket setsockopt() error.");
        goto ERROR_2;
    }

    telnet_if->backlog = FNET_CFG_TELNET_SESSION_MAX;
        
    if(listen(telnet_if->socket_listen, telnet_if->backlog) == SOCKET_ERROR)
    {
        FNET_DEBUG_TELNET("TELNET: Socket listen error.");
        goto ERROR_2;
    }
    
    /* Register service. */
    telnet_if->service_descriptor = fnet_poll_service_register(fnet_telnet_state_machine, (void *) telnet_if);
    
    if(telnet_if->service_descriptor == (fnet_poll_desc_t)FNET_ERR)
    {
        FNET_DEBUG_TELNET("TELNET: Service registration error.");
        goto ERROR_2;
    }
  
    for(i=0; i<FNET_CFG_TELNET_SESSION_MAX; i++) 
    {
        struct fnet_telnet_session_if   *session = &telnet_if->session[i];
         
        /* Reset buffer pointers. Move it to init state. */ 
        session->tx_buffer_head_index = 0;
        session->rx_buffer_head = session->rx_buffer;
        session->rx_buffer_tail = session->rx_buffer; 
        session->rx_buffer_end = &session->rx_buffer[FNET_TELNET_RX_BUFFER_SIZE]; 

        /* Setup stream. */
        session->stream.id = (long)(session);
        session->stream.putchar = fnet_telnet_putchar;
        session->stream.getchar = fnet_telnet_getchar;
        session->stream.flush = fnet_telnet_flush;
        
        /* Init shell. */
        session->shell_params.shell = params->shell;
        session->shell_params.cmd_line_buffer = session->cmd_line_buffer;
        session->shell_params.cmd_line_buffer_size = sizeof(session->cmd_line_buffer);
        session->shell_params.stream = &session->stream;
        session->shell_params.echo = FNET_CFG_TELNET_SHELL_ECHO;

        session->socket_foreign = SOCKET_INVALID;
                
        session->state = FNET_TELNET_STATE_LISTENING;
    }
    
    
    telnet_if->session_active = FNET_NULL;
    telnet_if->enabled = FNET_TRUE;
    
    return (fnet_telnet_desc_t)telnet_if;

ERROR_2:
    closesocket(telnet_if->socket_listen);

ERROR_1:
    return (fnet_telnet_desc_t)FNET_ERR;
}
Beispiel #5
0
/************************************************************************
* 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);
    }
}