/* * telnet.c * * Created on: 30 нояб. 2018 г. * Author: maxx */ #include #include "telnet.h" #include "socket.h" #include "wizchip_conf.h" #define GREETING_MSG "Well done guys! Welcome to the IoT world.\r\nType or 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 \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 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 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; }