⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 telnetd.c

📁 Embeded MCU Tcpip code.
💻 C
字号:
/* THIS SAMPLE CODE IS PROVIDED AS IS AND IS SUBJECT TO ALTERATIONS. FUJITSU */
/* MICROELECTRONICS ACCEPTS NO RESPONSIBILITY OR LIABILITY FOR ANY ERRORS OR */
/* ELIGIBILITY FOR ANY PURPOSES.                                             */
/*                 (C) Fujitsu Microelectronics Europe GmbH                  */
/*---------------------------------------------------------------------------
  Telnet server for OpenTCP stack  
  
  TELNETD.C

/*---------------------------------------------------------------------------*/

#include <stddef.h>
#include <stdio.h>
#include <string.h>

#include "../inet/datatypes.h"
#include "../inet/globalvariables.h"
#include "../inet/debug.h"
#include "../inet/system.h"
#include "../inet/tcp_ip.h"
#include "../inet/telnetd/telnetd.h"
#include "../inet/timers.h"

void (*telnetconnect)(UINT32, UINT32);      /* callback for client connect        */
void (*telnetcommand)(char*, UINT32);       /* callback for command arrival       */
void (*telnetdata)(char*, UINT32);          /* callback for data arrival          */
void (*telnetclose)(UINT32, UINT32);        /* callback for client close conn.    */

struct _tpacket TelnetPacketizer;           /* reserve memory for session data    */

INT8 telnetd_soch;                          /* Socket handler                     */
UINT8 telnetd_senddata;                     /* If set, data will be sent          */
INT8 dataack;                               /* Is set to 1 if no data is expected */
UINT8 timeout;

/*-----------------------------------------------------------------------------
 UINT8 telnetd_init()
 This function is called when the main thread installs socket processes.
 Return value: 1 - socket installed
-----------------------------------------------------------------------------*/
UINT8 telnetd_init()
{
  
  /* Allocate tcp socket */   
  telnetd_soch = tcp_getsocket(TCP_TYPE_SERVER, TCP_TOS_NORMAL, TCP_DEF_TOUT, telnetd_eventlistener);
        
  if( telnetd_soch < 0 )
  {
    printf("telnetd: server unable to get socket. Resetting!!!\r\n");
    RESET_SYSTEM();
  }
        
  /* Put it to listen on some port        */
  tcp_listen(telnetd_soch,TELNET_PORT);
        
  /* for now no data sending */
  telnetd_senddata=0;
  
  /* set packet structure items */
  TelnetPacketizer.sBufPtr = NULL;
  TelnetPacketizer.cBufPtr = NULL;
  TelnetPacketizer.tlen = 0;
  TelnetPacketizer.tpoint = 0;
  TelnetPacketizer.davail = 0;
  TelnetPacketizer.dack = 0;
  
  dataack = 1;
  
  timeout = get_timer();                     /* get a timer from the timer pool        */
  init_timer(timeout, 10*TIMERTIC);          /* set the timer alarm                    */

  /* Information message */
  printf("telnetd: socket registered\n");
  
  return(1);
}

/*-----------------------------------------------------------------------------
 INT8 telnetd_close(void)
 This function initiates the socket close process. 
 Return value: -2 - there is unacked data, try again later.
 			   -1 - there is an error
 			   >= 0 - ok, connection closing, return sochandler
-----------------------------------------------------------------------------*/
INT8 telnetd_close(void)
{
  
  return(tcp_close(telnetd_soch));
}

/*-----------------------------------------------------------------------------
 INT8 telnetd_getsock(void)
 This function simply returns the actual socket.
 Return value: actual socket handler >0
-----------------------------------------------------------------------------*/
INT8 telnetd_getsock(void)
{
  return(telnetd_soch);
}

/*-----------------------------------------------------------------------------
 void telnetd_run(void)
 This is the telnet daemon thread. It handles the data sending queue. Because
 there is no os who manages processes, telnetd jumps back into the main after
 every stack use. That is why the stack must have an ACK before sending new 
 packets.
 Return value: none
-----------------------------------------------------------------------------*/
void telnetd_run(void)
{
  int pCount;
  
  /* Let's check if data is waiting or available and stack has acknowledged data*/
  if(TelnetPacketizer.davail && dataack)
  {
    if(TelnetPacketizer.dack == 1)
    {
        /* Ok, we copy our data in the stack buffer */
        for(pCount = 0; pCount < (TelnetPacketizer.tlen - TelnetPacketizer.tpoint); pCount++)
        {
          if(pCount >= 512)
          {
            /* Store stream position in fpoint */
            TelnetPacketizer.tpoint = pCount;
            TelnetPacketizer.dack = 0;
            break;
          }
          
          if(TelnetPacketizer.cBufPtr == NULL)
            net_buf[TCP_APP_OFFSET+pCount] = *(TelnetPacketizer.sBufPtr+pCount);
          else
            net_buf[TCP_APP_OFFSET+pCount] = *(TelnetPacketizer.cBufPtr+pCount);
        }
      
      TelnetPacketizer.tpoint += pCount;
      TelnetPacketizer.plen = pCount;
      TelnetPacketizer.dack = 0;
    }
    
    /* Ok, lets send data and check if it is successful */
    if(telnetd_send()!=-1)
    {
      /* Ok, it is successfull, set dack to 1 for next data ready */
      TelnetPacketizer.dack = 1;
      
      /* If tlen and tpoint are equal, our buffer is empty, all data is sent */
      if(TelnetPacketizer.tlen == TelnetPacketizer.tpoint)
      {
        TelnetPacketizer.davail = 0;
      }
    } 
  } 
  
  /* Reset tcp timeout to hold the connection open */
  if((tcp_getstate(telnetd_soch) == TCP_STATE_CONNECTED) && !check_timer(timeout)) 
  {
    UINT8 telnet_noop[2] = { 255, 241 };
      
    net_buf[TCP_APP_OFFSET+0] = telnet_noop[0];
    net_buf[TCP_APP_OFFSET+1] = telnet_noop[1];
    
    /* set length of command packet */
    TelnetPacketizer.plen = 2;
      
    if(telnetd_send() != -1)
    {
      init_timer(timeout, 3*TIMERTIC);
      return;
    }
    
    return;
  }

  
}

/*-----------------------------------------------------------------------------
 INT8 telnetd_sendstring(const char *tbuf)
 You can use this function to send a string over an active socket to the 
 client. But beware of calling telnetd_sendstring twice or more! After 
 every send you must jump back to main, because the stack waits for the ACK.
 Return value: 1 - ok, string accepted and written into the sending queue.
              -1 - sending queue full, try again later.
-----------------------------------------------------------------------------*/
INT8 telnetd_sendstring(const char *tbuf)
{
  
  if(!TelnetPacketizer.davail)
  {
    /* Copy pointer, not data */
    TelnetPacketizer.sBufPtr = (char*) tbuf;
    
    /* Set command pointer to zero because we send data */
    TelnetPacketizer.cBufPtr = NULL;
  
    /* Store complete length in structure */
    TelnetPacketizer.tlen = strlen(tbuf);
  
    /* Set seek pointer to zero */
    TelnetPacketizer.tpoint = 0;
  
    /* Make data available to telnetd_run() */
    TelnetPacketizer.davail = 1;
    
    /* No new packages are transmitted */
    TelnetPacketizer.dack = 1;
  
    return(1);
  }
  
  /* telnetd is still sending data */
  return(-1);
  
}

/*-----------------------------------------------------------------------------
 INT8 telnetd_sendcommand(const unsigned char *tbufc, UINT8 tlenc)
 You can use this function to send a command over an active socket to the 
 client. But beware of calling telnetd_sendcommand twice or more! After 
 every send you must jump back to main, because the stack waits for the ACK.
 Return value: 1 - ok, command accepted and written into the sending queue.
              -1 - sending queue full, try again later.
-----------------------------------------------------------------------------*/
INT8 telnetd_sendcommand(const unsigned char *tbufc, UINT8 tlenc)
{
  
  if(!TelnetPacketizer.davail)
  {
    /* Copy pointer, not data */
    TelnetPacketizer.cBufPtr = (unsigned char*) tbufc;
    
    /* Set data pointer to zero because we send commands */
    TelnetPacketizer.sBufPtr = NULL;
  
    /* Store complete length in structure */
    TelnetPacketizer.tlen = tlenc;
  
    /* Set seek pointer to zero */
    TelnetPacketizer.tpoint = 0;
  
    /* Make data available to telnetd_run() */
    TelnetPacketizer.davail = 1;
    
    /* No new packages are transmitted */
    TelnetPacketizer.dack = 1;
  
    return(1);
  }
  
  /* telnetd is still sending data */
  return(-1);
  
}

/*-----------------------------------------------------------------------------
 void telnetd_registershell(void (*shconnect)(UINT32, UINT32), void (*shcommand)(char*, UINT32), void (*shdata)(char*, UINT32), void (*shclose)(UINT32, UINT32))
 This function installs the callback functions for the shell. You must call this in your
 shell_init function.
 Return value: none
-----------------------------------------------------------------------------*/
void telnetd_registershell(void (*shconnect)(UINT32, UINT32), void (*shcommand)(char*, UINT32), void (*shdata)(char*, UINT32), void (*shclose)(UINT32, UINT32))
{
  /* register shell callbacks*/
  telnetconnect = shconnect;
  telnetcommand = shcommand;
  telnetdata = shdata;
  telnetclose = shclose;
}

/*
 * Event listener invoked when TCP/IP stack receives TCP data for
 * a given socket. Parameters:
 * - cbhandle - handle of the socket this packet is intended for. Check it
 *      just to be sure, but in general case not needed
 * - event - event that is notified. For TCP there are quite a few possible
 *      events, check switch structure below for more information
 * - par1, par2 - parameters whose use depends on the event that is notified
 */
INT32 telnetd_eventlistener(INT8 cbhandle, UINT8 event, UINT32 par1, UINT32 par2)
{
/* This function is called by TCP stack to inform about events  */
  char receivedchars[32];
        
  if( cbhandle != telnetd_soch)         /* Not our handle       */
    return(-1);
        
  switch( event )
  {
    /* Connection request event. Used by TCP/IP stack to inform
     * the application someone is trying to establish a connection.
     * Server can decide, based on provided IP address and port number,
     * whether to allow or not connection establishment.
     * Parameters:
     *  - par1 - remote hosts IP address
     *  - par2 - remote hosts port number
     * 
     * Return values from event listener:
     * -1 - do not allow connection to be established (send reset)
     * -2 - do not send any response for now to the SYN packet (let's
     *              think a little before answering)
     * 1  - allow connection to be established
     */
    case TCP_EVENT_CONREQ:
      /* Enable all connections       */
      return(1);
      break;
                        
    /* Connection abort event. Connection on a given socket is being 
     * aborted for some reason (usually retransmissions are used up or 
     * some abnormal situation in communication happened).
     * Parameters:
     *  - par1 - remote hosts IP address
     *  - par2 - remote hosts port number
     */
    case TCP_EVENT_ABORT:
      (*telnetclose)(par1, par2);
      break;

    /* Connection established event - three-way handshaking performed
     * OK and connection is established.
     * Parameters:
     *  - par1 - remote hosts IP address
     *  - par2 - remote hosts port number
     */
    case TCP_EVENT_CONNECTED:
      (*telnetconnect)(par1, par2);
      break;

    /* Connection closing event. Happens when TCP connection is
     * intentionally closed by some side calling close function and
     * initializing proper TCP connection close procedure.
     * Parameters:
     *  - par1 - remote hosts IP address
     *  - par2 - remote hosts port number
     */
    case TCP_EVENT_CLOSE:
      (*telnetclose)(par1, par2);
      break;

    /* Data acknowledgment event. Happens when data that was
     * previously sent gets acknowledged. This means we can now
     * send some more data! :-)
     * Parameters:
     *  - par1 - remote hosts IP address
     *  - par2 - remote hosts port number
     */
    case TCP_EVENT_ACK:
      /* if more data should be sent, adjust variables and
       * set tcps_demo_senddata variable */
      dataack = 1;
      break;
                
    /* Data received event. Happens when we receive some data over the
     * TCP connection.
     * Parameters:
     *  - par1 - number of data bytes received
     *  - par2 = 0
     */
    case TCP_EVENT_DATA:
      if((par1 != 0) && (par1 < 32))
      {
        RECEIVE_NETWORK_BUF(receivedchars, par1);

        /* choose data or control path */
        if ((receivedchars[0] != 0xFF) && (receivedchars[0] != 0x00))
        {
          /* Ok, there is data, calling the shell... */
          (*telnetdata)(receivedchars, par1);
        }
        else if (receivedchars[0] == 0x00)
        {
           // No OP
        }
        else
        {
          /* Ok, here we have telnet option commands */
          (*telnetcommand)(receivedchars, par1);
        }
      }
      break;

    /* Regenerate data event. Happens when data needs to be
     * retransmitted because of possible loss on the network.
     * Note that THE SAME DATA must be sent over and over again
     * until TCP_EVENT_ACK is generated (for that data)! 
     * Parameters:
     *  - par1 - amount of data to regenerate (usually all)
     *  - par2 = 0
     */
    case TCP_EVENT_REGENERATE:
      telnetd_send();
      break;

    default:
      return(-1);
  }

  return 0;
}

/*-----------------------------------------------------------------------------
 INT16 telnetd_send(void)
 This function checks if the stack is ready for assembling packets and calls
 tcp_send. 
 Return value: >0 - ok, return number of bytes sent.
               -1 - there is an error sending.
-----------------------------------------------------------------------------*/
INT16 telnetd_send(void) 
{
        /* first check if data sending is possible (it may be that
         * previously sent data is not yet acknowledged)
         */
  if(tcp_checksend(telnetd_soch) < 0 )
  {
  /* Not yet */
    return -1;
  }
  
  /* Set dataack to zero, we should wait for the ACK */      
  dataack = 0;
  return tcp_send(telnetd_soch, &net_buf[TCP_APP_OFFSET], NETWORK_TX_BUFFER_SIZE - TCP_APP_OFFSET, TelnetPacketizer.plen);

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -