Versão atual 13-12-2013.

Dependencies:   EthernetInterface mbed-rtos mbed

Codes/TelnetServer.cpp

Committer:
rebonatto
Date:
2013-12-13
Revision:
0:65c41a68b49a

File content as of revision 0:65c41a68b49a:

/*
    Original autor: Francisco
    Modificacao do uso da rede: rebonatto
*/


#include "TelnetServer.h"

#include "Split.h"

#define OPT_WILL    251
#define OPT_WONT    252
#define OPT_DO      253
#define OPT_DONT    254

char* welcome_msg = "Protegemed - welcome to telnet\r\nType 'help' for a list of commands\r\n";
char* prompt_msg = "\r\n$ ";
char iac_will_echo[] = {0xFF,0xFB,0x01};
char erase_cmd[] = { 0x1B,0x5B,0x44,0x1B,0x5B,0x4B};

const struct telnet_cmd_handler TelnetServer::cmds[] = {
        {"exit",(cmd_function)-1},
        {"help",TelnetServer::HelpCommand},
        {"reset",TelnetServer::ResetCommand},
        {"remove",TelnetServer::RemoveCommand},
        {"listparam",TelnetServer::ListParamCommand},
        {"getparam",TelnetServer::GetParamCommand},
        {"setparam",TelnetServer::SetParamCommand},
        {"version",TelnetServer::VersionCommand},
        {"update",TelnetServer::UpdateCommand},
        {"",(cmd_function)0}
};

void TelnetServer::TelnetServer_Thread(void const* arg)
{
    int r=0;
    printf("Telnet Thread starting... \r\nCommands up to 100 chars\n");
    
    TCPSocketServer server;                     
    
    server.bind(23);
    server.listen();
    
    while(1)
    {
        TCPSocketConnection* conn ;
        TCPSocketConnection aux;
        r = server.accept(aux);
        conn = &aux;
        printf("Aceitou conexao \n");
        if (r != 0){
            printf("Error in connection\n");
            exit(1);
        }            
        
        TelnetSession(conn);
        printf("Fechou\n");
        conn->close();
    }
}

void TelnetServer::TelnetSession(TCPSocketConnection *conn)
{
    int r;
    int buffer_ptr=0;   

    printf("Connected to %s:%d\n",conn->get_address(),conn->get_port());            
    
    conn->send(welcome_msg,strlen(welcome_msg));
    conn->send(prompt_msg,strlen(prompt_msg));
    
    conn->set_blocking(true);
    
    while(1)
    {
        char buf_rec[260];
        unsigned char buf[260];
        char buffer[260];             
        
        //printf("Vai recevber\n");
        r = conn->receive(buf_rec, strlen(buf_rec) );
        
        /* need memcpy becouse commands are ready to unsigned char and tcp receive char */
        memcpy(buf, buf_rec, r);
        
        //printf("Receive %d\n", r);
        
        if(r == -1)
        {
            printf("Error %d %s\n", r, buf);
            break;
        }
        
        if (r > 120){
            printf("Max command length = 100 chars\n");
            //send
            break;        
        }                
                
        //printf("Got Here\n");        
        
        for(int i=0;i<r;i++)
        {
            //check if it is a printable or any of the line control chars
            if((buf[i]>31 && buf[i] < 128) || buf[i]=='\r' || buf[i]=='\n' || buf[i]=='\t')
            {
                //append to the buffer                
                buffer[buffer_ptr] = buf[i];
                buffer_ptr++;
            }
            else if(buf[i] == '\b')  //backspace
            {
                //erases the character from the command buffer
                if(buffer_ptr > 0)
                {
                    buffer_ptr--;
                }
                //resets m variable state (will not cause error on the next block of code
                
            }
            else if((int)buf[i] == 255)   //IAC - Interpret As Command
            {
                if((int)buf[i+1] >= 251)
                {
                    option_negotiator(conn,buf[i+1],buf[i+2]);
                    i+=2;
                }
                else
                    i+=1;
            }
        }                
        
        //detect a carriage return and line feed sequence. Trigger command processor
        if(buffer_ptr >= 2)
        {
            if(buffer[buffer_ptr-1] == '\n' && buffer[buffer_ptr-2] == '\r')
            {
                char **command;
                int command_count;

                buffer[buffer_ptr-2] = '\0';
                command_count = split((char*)buffer," ",&command);
                
                printf("Command found: %s\n", command[0]);

                //must find a function in the table and then execute it, passing the command array as an argument
                for(int i=0;cmds[i].pfn != 0;i++)
                {
                    if(!strcasecmp(command[0],cmds[i].command_name))
                    {
                        if((int)cmds[i].pfn == -1)//exit cmd
                        {
                            //delete buffer;                            
                            return;
                        }
                        else
                        {
                            cmds[i].pfn(conn,command,command_count);
                            break;
                        }
                    }
                }

                //write the prompt
                conn->send(prompt_msg,strlen(prompt_msg));
                buffer_ptr=0;
            }
        }
    }
    //delete buffer;
}

void TelnetServer::option_negotiator(TCPSocketConnection *conn,unsigned char opt_cmd,unsigned char opt_param)
{
    char opt[3]={0,0,0};    

    if(opt_param == 1 && (opt_cmd == OPT_DO || opt_cmd == OPT_DONT))    //response for our will echo
    {
        printf("HERE");
        return;
    }
    if(opt_cmd == OPT_DO)   //every other option that it will ask to us to do, we won't
    {
        opt[0] = 255;
        opt[1] = OPT_WONT;
        opt[2] = opt_param;
        conn->send(opt,3);
    }
    else if(opt_cmd == OPT_WILL && opt_param==3)    //OK to supperss go ahead
    {
        opt[0] = 255;
        opt[1] = OPT_DO;
        opt[2] = opt_param;
        conn->send(opt,3);
    }
    else if(opt_cmd == OPT_WILL)    //every other option that it will ask do, we don't
    {
        opt[0] = 255;
        opt[1] = OPT_DONT;
        opt[2] = opt_param;
        conn->send(opt,3);
        
    }

}