381 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			381 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * telnet.c
 | 
						|
 *
 | 
						|
 *  Created on: 30 íîÿá. 2018 ã.
 | 
						|
 *      Author: maxx
 | 
						|
 */
 | 
						|
#include <stdio.h>
 | 
						|
#include "telnet.h"
 | 
						|
#include "socket.h"
 | 
						|
#include "wizchip_conf.h"
 | 
						|
 | 
						|
#define GREETING_MSG 		 "Well done guys! Welcome to the IoT world.\r\nType <Help> or <Q> to exit.\r\n"
 | 
						|
#define PASS_MSG 		 	 "\r\n> pass: "
 | 
						|
#define BYE_MSG				 "\r\nBye-bye!\r\n"
 | 
						|
 | 
						|
#define _passcode				 "1234" //Pass for authorization telnet session
 | 
						|
 | 
						|
//Command processor exec command from telnet server
 | 
						|
void processCommand(char *command, char *answer)
 | 
						|
{
 | 
						|
    //Loopback mode
 | 
						|
	//sprintf_P(answer,PSTR("\r\n> %s\r\n"), command);
 | 
						|
 | 
						|
	if((strcasestr_P(command, PSTR("HELP")) != 0) ||\
 | 
						|
		(strncmp_P(command, PSTR("?"), 1) == 0)	)
 | 
						|
	{
 | 
						|
		sprintf_P(answer,PSTR("\r\nAvailable commands:\r\n"\
 | 
						|
				"Help/Echo xyz/FreeRAM/Uptime/LED_(ON/OFF/TGL)\r\n"));
 | 
						|
 | 
						|
	}
 | 
						|
	else if(strcasestr_P(command, PSTR("ECHO ")) != 0)
 | 
						|
	{
 | 
						|
		sprintf_P(answer,PSTR("\r\n> %s\r\n"), (char *)(command+5));
 | 
						|
	}
 | 
						|
	else if(strcasestr_P(command, PSTR("Uptime")) != 0)
 | 
						|
	{
 | 
						|
		sprintf_P(answer,PSTR("\r\nServer uptime: %lu sec\r\n"), millis()/1000);
 | 
						|
	}
 | 
						|
	else if(strcasestr_P(command, PSTR("FreeRAM")) != 0)
 | 
						|
	{
 | 
						|
		sprintf_P(answer,PSTR("\r\nRAM free: %u bytes\r\n"), freeRam());
 | 
						|
	}
 | 
						|
	else if(strcasestr_P(command, PSTR("LED_ON")) != 0)
 | 
						|
	{
 | 
						|
		led1_high();
 | 
						|
		sprintf_P(answer,PSTR("\r\n> LED: %s\r\n"), (led1_read()? "ON": "OFF"));
 | 
						|
	}
 | 
						|
	else if(strcasestr_P(command, PSTR("LED_OFF")) != 0)
 | 
						|
	{
 | 
						|
		led1_low();
 | 
						|
		sprintf_P(answer,PSTR("\r\n> LED: %s\r\n"), (led1_read()? "ON": "OFF"));
 | 
						|
	}
 | 
						|
	else if(strcasestr_P(command, PSTR("LED_TGL")) != 0)
 | 
						|
	{
 | 
						|
		led1_tgl();
 | 
						|
		sprintf_P(answer,PSTR("\r\n> LED: %s\r\n"), (led1_read()? "ON": "OFF"));
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		sprintf_P(answer,PSTR("\r\n??Unknown command: <%s>\r\nTry <Help>\r\n"), command);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
int32_t telnet_srv(uint8_t sn, uint8_t* buf, uint16_t port)
 | 
						|
{
 | 
						|
   int32_t ret;
 | 
						|
   uint16_t size = 0;
 | 
						|
 | 
						|
    static char cmd_buffer[TELNET_BUF_SIZE] = "\0";
 | 
						|
	static uint8_t cmd_buffer_len;
 | 
						|
	static char msg_answer[128] = "\0";
 | 
						|
 | 
						|
#ifdef _TELNET_DEBUG_
 | 
						|
   uint8_t destip[4];
 | 
						|
   uint16_t destport;
 | 
						|
#endif
 | 
						|
 | 
						|
   switch(getSn_SR(sn))
 | 
						|
   {
 | 
						|
      case SOCK_ESTABLISHED :
 | 
						|
         if(getSn_IR(sn) & Sn_IR_CON)
 | 
						|
         {
 | 
						|
        	//Open connection
 | 
						|
#ifdef _TELNET_DEBUG_
 | 
						|
			getSn_DIPR(sn, destip);
 | 
						|
			destport = getSn_DPORT(sn);
 | 
						|
 | 
						|
			printf("%d telnet:Connected - %d.%d.%d.%d : %u\r\n",sn, destip[0], destip[1], destip[2], destip[3], destport);
 | 
						|
#endif
 | 
						|
			setSn_IR(sn,Sn_IR_CON);
 | 
						|
			cmd_buffer_len = 0;
 | 
						|
			//Send welcome message to client
 | 
						|
			ret = send(sn, GREETING_MSG, strlen(GREETING_MSG));
 | 
						|
			if(ret < 0)
 | 
						|
			{
 | 
						|
				close(sn);
 | 
						|
				return ret;
 | 
						|
			}
 | 
						|
         }
 | 
						|
		 if((size = getSn_RX_RSR(sn)) > 0) // Don't need to check SOCKERR_BUSY because it doesn't not occur.
 | 
						|
         {
 | 
						|
			//Here when receive message from client
 | 
						|
			if(size > TELNET_BUF_SIZE) size = TELNET_BUF_SIZE;
 | 
						|
			ret = recv(sn, buf, size); //receive message
 | 
						|
 | 
						|
			if(ret <= 0) return ret;      // check SOCKERR_BUSY & SOCKERR_XXX. For showing the occurrence of SOCKERR_BUSY.
 | 
						|
			size = (uint16_t) ret;
 | 
						|
 | 
						|
			//Parse <Q> to quit session
 | 
						|
			if(buf[0] == 'Q')
 | 
						|
			{
 | 
						|
				//Send welcome message to client
 | 
						|
				ret = send(sn, BYE_MSG, strlen(BYE_MSG));
 | 
						|
				//Disconnect
 | 
						|
				disconnect(sn);
 | 
						|
				close(sn);
 | 
						|
				return ret;
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{
 | 
						|
				//Loop-back received back, just for test!!!
 | 
						|
				/*
 | 
						|
				ret = send(sn, buf, size);
 | 
						|
				if(ret < 0)
 | 
						|
				{
 | 
						|
					close(sn);
 | 
						|
					return ret;
 | 
						|
				}
 | 
						|
				*/
 | 
						|
 | 
						|
				//Parse received message from telnet client
 | 
						|
				buf[size] = 0x0; //Insert null-terminate symbol (for string parse)
 | 
						|
 | 
						|
				//Print out command from telnet client
 | 
						|
				//PRINTF(">> %s\r\n", msg_receive);
 | 
						|
 | 
						|
				//Fill cmd_buffer until '\n' (NEW LINE) received
 | 
						|
				//some bulletproof for overflow protection
 | 
						|
				if(size > TELNET_BUF_SIZE) size = TELNET_BUF_SIZE;
 | 
						|
				for(int32_t i = 0; i < size; i++)
 | 
						|
				{
 | 
						|
					if(buf[i] == '\n') //PARSE '\n'(0x0A NEW LINE)
 | 
						|
					{
 | 
						|
						cmd_buffer[cmd_buffer_len++] = 0x0; //Received EOL,so process command
 | 
						|
						//Clear commnad buffe
 | 
						|
						cmd_buffer_len = 0;
 | 
						|
						//Exec process command
 | 
						|
						processCommand(cmd_buffer, msg_answer);
 | 
						|
						//Send answer to telnet client
 | 
						|
						send(sn, msg_answer, strlen(msg_answer));
 | 
						|
 | 
						|
					}
 | 
						|
					else if(buf[i] == '\r') //PARSE '\r'(0x0D RETURN LINE)
 | 
						|
					{
 | 
						|
						//Suppress CR symbol
 | 
						|
					}
 | 
						|
					else
 | 
						|
					{
 | 
						|
						// Any other symbol, fill input buffer
 | 
						|
						cmd_buffer[cmd_buffer_len++] = buf[i];
 | 
						|
					}
 | 
						|
 | 
						|
				}
 | 
						|
			}
 | 
						|
         }
 | 
						|
         break;
 | 
						|
      case SOCK_CLOSE_WAIT :
 | 
						|
#ifdef _TELNET_DEBUG_
 | 
						|
         //printf("%d:CloseWait\r\n",sn);
 | 
						|
#endif
 | 
						|
         if((ret = disconnect(sn)) != SOCK_OK) return ret;
 | 
						|
#ifdef _TELNET_DEBUG_
 | 
						|
         printf("%d telnet:Socket Closed\r\n", sn);
 | 
						|
#endif
 | 
						|
         break;
 | 
						|
      case SOCK_INIT :
 | 
						|
#ifdef _TELNET_DEBUG_
 | 
						|
    	 printf("%d telnet:Listen, TELNET server, port [%u]\r\n", sn, port);
 | 
						|
#endif
 | 
						|
         if( (ret = listen(sn)) != SOCK_OK) return ret;
 | 
						|
         break;
 | 
						|
      case SOCK_CLOSED:
 | 
						|
#ifdef _TELNET_DEBUG_
 | 
						|
         //printf("%d:TCP server loopback start\r\n",sn);
 | 
						|
#endif
 | 
						|
         if((ret = socket(sn, Sn_MR_TCP, port, 0x00)) != sn) return ret;
 | 
						|
#ifdef _TELNET_DEBUG_
 | 
						|
         //printf("%d:Socket opened\r\n",sn);
 | 
						|
#endif
 | 
						|
         break;
 | 
						|
      default:
 | 
						|
         break;
 | 
						|
   }
 | 
						|
   return 1;
 | 
						|
}
 | 
						|
 | 
						|
//Command processor authorization
 | 
						|
uint8_t processAuth(char * pass)
 | 
						|
{
 | 
						|
	if(strstr_P(pass, PSTR(_passcode)) != 0)
 | 
						|
	{
 | 
						|
		//PASS OK
 | 
						|
		return 1;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		//PASS ERROR
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
#define TELNET_STATE_BEGIN 0
 | 
						|
#define TELNET_STATE_AUTH 1
 | 
						|
#define TELNET_STATE_PROCESS 2
 | 
						|
 | 
						|
int32_t telnet_auth_srv(uint8_t sn, uint8_t* buf, uint16_t port)
 | 
						|
{
 | 
						|
   int32_t ret;
 | 
						|
   uint16_t size = 0;
 | 
						|
    static uint8_t tel_st = TELNET_STATE_BEGIN;
 | 
						|
	static char cmd_buffer[TELNET_BUF_SIZE] = "\0";
 | 
						|
	static uint8_t cmd_buffer_len;
 | 
						|
	static char msg_answer[128] = "\0";
 | 
						|
 | 
						|
#ifdef _TELNET_DEBUG_
 | 
						|
   uint8_t destip[4];
 | 
						|
   uint16_t destport;
 | 
						|
#endif
 | 
						|
 | 
						|
   switch(getSn_SR(sn))
 | 
						|
   {
 | 
						|
      case SOCK_ESTABLISHED :
 | 
						|
         if(getSn_IR(sn) & Sn_IR_CON)
 | 
						|
         {
 | 
						|
        	//Open connection
 | 
						|
#ifdef _TELNET_DEBUG_
 | 
						|
			getSn_DIPR(sn, destip);
 | 
						|
			destport = getSn_DPORT(sn);
 | 
						|
 | 
						|
			printf("%d telnet_auth:Connected - %d.%d.%d.%d : %u\r\n",sn, destip[0], destip[1], destip[2], destip[3], destport);
 | 
						|
#endif
 | 
						|
			setSn_IR(sn,Sn_IR_CON);
 | 
						|
			cmd_buffer_len = 0;
 | 
						|
			//Send pass message to client
 | 
						|
			ret = send(sn, PASS_MSG, strlen(PASS_MSG));
 | 
						|
			if(ret < 0)
 | 
						|
			{
 | 
						|
				close(sn);
 | 
						|
				return ret;
 | 
						|
			}
 | 
						|
			tel_st = TELNET_STATE_AUTH;
 | 
						|
         }
 | 
						|
		 if((size = getSn_RX_RSR(sn)) > 0) // Don't need to check SOCKERR_BUSY because it doesn't not occur.
 | 
						|
         {
 | 
						|
			//Here when receive message from client
 | 
						|
			if(size > TELNET_BUF_SIZE) size = TELNET_BUF_SIZE;
 | 
						|
			ret = recv(sn, buf, size); //receive message
 | 
						|
 | 
						|
			if(ret <= 0) return ret;      // check SOCKERR_BUSY & SOCKERR_XXX. For showing the occurrence of SOCKERR_BUSY.
 | 
						|
			size = (uint16_t) ret;
 | 
						|
 | 
						|
			//Parse <Q> to quit session
 | 
						|
			if(buf[0] == 'Q')
 | 
						|
			{
 | 
						|
				//Send welcome message to client
 | 
						|
				ret = send(sn, BYE_MSG, strlen(BYE_MSG));
 | 
						|
				//Disconnect
 | 
						|
				disconnect(sn);
 | 
						|
				close(sn);
 | 
						|
				return ret;
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{
 | 
						|
				//Loop-back received back, just for test
 | 
						|
				/*
 | 
						|
				ret = send(sn, buf, size);
 | 
						|
				if(ret < 0)
 | 
						|
				{
 | 
						|
					close(sn);
 | 
						|
					return ret;
 | 
						|
				}
 | 
						|
				*/
 | 
						|
 | 
						|
				//Parse received message from telnet client
 | 
						|
				buf[size] = 0x0; //Insert null-terminate symbol (for string parse)
 | 
						|
 | 
						|
				//Print out command from telnet client
 | 
						|
				//PRINTF(">> %s\r\n", msg_receive);
 | 
						|
 | 
						|
				//Fill cmd_buffer until '\n' (NEW LINE) received
 | 
						|
				//some bulletproof for overflow protection
 | 
						|
				if(size > TELNET_BUF_SIZE) size = TELNET_BUF_SIZE;
 | 
						|
				for(int32_t i = 0; i < size; i++)
 | 
						|
				{
 | 
						|
					if(buf[i] == '\n') //PARSE '\n'(0x0A NEW LINE)
 | 
						|
					{
 | 
						|
						cmd_buffer[cmd_buffer_len++] = 0x0; //Received EOL,so process command
 | 
						|
						//Clear commnad buffe
 | 
						|
						cmd_buffer_len = 0;
 | 
						|
						//String to command done
 | 
						|
						//Check state session (authorization done or not)
 | 
						|
						if(tel_st == TELNET_STATE_AUTH)
 | 
						|
						{
 | 
						|
							//Authorization required
 | 
						|
							if (processAuth(cmd_buffer))
 | 
						|
							{
 | 
						|
								//Authorization OK
 | 
						|
								tel_st = TELNET_STATE_PROCESS;
 | 
						|
								//Send greetings message to client
 | 
						|
								ret = send(sn, GREETING_MSG, strlen(GREETING_MSG));
 | 
						|
							}
 | 
						|
							else
 | 
						|
							{
 | 
						|
								//Authorization ERROR
 | 
						|
								tel_st = TELNET_STATE_BEGIN;
 | 
						|
								//Send bye message to client
 | 
						|
								ret = send(sn, BYE_MSG, strlen(BYE_MSG));
 | 
						|
								//Disconnect
 | 
						|
								disconnect(sn);
 | 
						|
								close(sn);
 | 
						|
								return ret;
 | 
						|
							}
 | 
						|
						}
 | 
						|
						else
 | 
						|
						{
 | 
						|
							//Authorization done
 | 
						|
							//Exec process command
 | 
						|
							processCommand(cmd_buffer, msg_answer);
 | 
						|
							//Send answer to telnet client
 | 
						|
							send(sn, msg_answer, strlen(msg_answer));
 | 
						|
						}
 | 
						|
					}
 | 
						|
					else if(buf[i] == '\r') //PARSE '\r'(0x0D RETURN LINE)
 | 
						|
					{
 | 
						|
						//Suppress CR symbol
 | 
						|
					}
 | 
						|
					else
 | 
						|
					{
 | 
						|
						// Any other symbol, fill input buffer
 | 
						|
						cmd_buffer[cmd_buffer_len++] = buf[i];
 | 
						|
					}
 | 
						|
 | 
						|
				}
 | 
						|
			}
 | 
						|
         }
 | 
						|
         break;
 | 
						|
      case SOCK_CLOSE_WAIT :
 | 
						|
#ifdef _TELNET_DEBUG_
 | 
						|
         //printf("%d:CloseWait\r\n",sn);
 | 
						|
#endif
 | 
						|
         tel_st = TELNET_STATE_BEGIN;
 | 
						|
         if((ret = disconnect(sn)) != SOCK_OK) return ret;
 | 
						|
#ifdef _TELNET_DEBUG_
 | 
						|
         printf("%d telnet_auth:Socket Closed\r\n", sn);
 | 
						|
#endif
 | 
						|
         break;
 | 
						|
      case SOCK_INIT :
 | 
						|
#ifdef _TELNET_DEBUG_
 | 
						|
    	 printf("%d telnet_auth:Listen, TELNET_AUTH server, port [%u]\r\n", sn, port);
 | 
						|
#endif
 | 
						|
         tel_st = TELNET_STATE_BEGIN;
 | 
						|
    	 if( (ret = listen(sn)) != SOCK_OK) return ret;
 | 
						|
         break;
 | 
						|
      case SOCK_CLOSED:
 | 
						|
#ifdef _TELNET_DEBUG_
 | 
						|
         //printf("%d:TCP server loopback start\r\n",sn);
 | 
						|
#endif
 | 
						|
         if((ret = socket(sn, Sn_MR_TCP, port, 0x00)) != sn) return ret;
 | 
						|
#ifdef _TELNET_DEBUG_
 | 
						|
         //printf("%d:Socket opened\r\n",sn);
 | 
						|
#endif
 | 
						|
         tel_st = TELNET_STATE_BEGIN;
 | 
						|
         break;
 | 
						|
      default:
 | 
						|
         break;
 | 
						|
   }
 | 
						|
   return 1;
 | 
						|
}
 | 
						|
 | 
						|
 |