You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
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;
|
|
}
|
|
|
|
|