From 93ec40f34839a1d508ef633c8d09566c63319df2 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Sun, 29 Mar 2020 03:05:32 +0200 Subject: [PATCH] Code optimizations --- src/hasp_telnet.cpp | 224 ++++++++++++++++++++++++++------------------ src/hasp_telnet.h | 1 + 2 files changed, 134 insertions(+), 91 deletions(-) diff --git a/src/hasp_telnet.cpp b/src/hasp_telnet.cpp index f93c1244..8eb5558a 100644 --- a/src/hasp_telnet.cpp +++ b/src/hasp_telnet.cpp @@ -5,6 +5,7 @@ #include "ArduinoJson.h" #include "ArduinoLog.h" +#include "hasp_http.h" #include "hasp_debug.h" #include "hasp_config.h" #include "hasp_dispatch.h" @@ -21,21 +22,24 @@ #define TELNET_USERNAME_NOK 99 #define TELNET_AUTHENTICATED 255 +extern char httpUser[32]; +extern char httpPassword[32]; + uint8_t telnetLoginState = TELNET_UNAUTHENTICATED; -WiFiServer * telnetServer; //(23); -WiFiClient * telnetClient; -uint8_t telnetEnabled = true; // Enable telnet debug output -uint8_t telnetLoginAttempt = 0; // Initial attempt -uint8_t telnetInputIndex = 0; // Empty buffer +static WiFiServer * telnetServer; //= new WiFiServer(23); +static WiFiClient * telnetClient = new WiFiClient; +bool telnetInCommandMode = false; +uint8_t telnetEnabled = true; // Enable telnet debug output +uint8_t telnetLoginAttempt = 0; // Initial attempt +uint8_t telnetInputIndex = 0; // Empty buffer char telnetInputBuffer[128]; bool telnetExitCommand() { - char buffer[128]; - snprintf_P(buffer, sizeof(buffer), PSTR("exit")); - if(strcmp(telnetInputBuffer, buffer) == 0 || telnetLoginAttempt >= 3) { + if(strcmp_P(telnetInputBuffer, PSTR("exit")) == 0 || telnetLoginAttempt >= 3) { Log.notice(F("TELNET: Closing session from %s"), telnetClient->remoteIP().toString().c_str()); telnetClient->stop(); + Log.unregisterOutput(1); // telnetClient telnetLoginState = TELNET_UNAUTHENTICATED; telnetInputIndex = 0; // Empty buffer telnetLoginAttempt = 0; // Initial attempt @@ -48,107 +52,138 @@ bool telnetExitCommand() void telnetAcceptClient() { if(telnetClient) { - telnetClient->stop(); // client disconnected + telnetClient->stop(); // client disconnected + Log.unregisterOutput(1); // telnetClient } *telnetClient = telnetServer->available(); // ready for new client Log.notice(F("TELNET: Client connected from %s"), telnetClient->remoteIP().toString().c_str()); - char buffer[128]; - snprintf_P(buffer, sizeof(buffer), PSTR("\r\nUsername: ")); - telnetClient->print(buffer); + /* Avoid a buffer here */ + telnetClient->print(0xFF); // DO TERMINAL-TYPE + telnetClient->print(0xFD); + telnetClient->print(0x1B); + telnetClient->print(F("\r\nUsername: ")); telnetLoginState = TELNET_UNAUTHENTICATED; telnetInputIndex = 0; // reset input buffer index telnetLoginAttempt = 0; // Initial attempt } -void telnetProcessInput() +void telnetProcessCommand(char ch) { - char telnetInputByte = telnetClient->read(); // Read client byte - // debugPrintln(String("telnet in: 0x") + String(telnetInputByte, HEX)); - switch(telnetInputByte) { - case 0x01: - case 0x03: - case 0x05: - case 0xff: - case 0xfe: - case 0xfd: - case 0xfc: - case 0xfb: - case 0xf1: - case 0x1f: - case 10: - telnetInputIndex = 0; - break; - case 0x08: // Backspace - if(telnetInputIndex > 0) { - telnetInputIndex--; - } - break; - case 13: - telnetInputBuffer[telnetInputIndex] = 0; // null terminate our char array - switch(telnetLoginState) { - case TELNET_UNAUTHENTICATED: { - char buffer[128]; - snprintf_P(buffer, sizeof(buffer), PSTR("Password: %c%c%c"), 0xFF, 0xFB, 0x01); // Hide characters - telnetClient->print(buffer); - snprintf_P(buffer, sizeof(buffer), PSTR("admin")); - telnetLoginState = - strcmp(telnetInputBuffer, buffer) == 0 ? TELNET_USERNAME_OK : TELNET_USERNAME_NOK; - break; - } - case TELNET_USERNAME_OK: - case TELNET_USERNAME_NOK: { - char buffer[128]; - snprintf_P(buffer, sizeof(buffer), PSTR("%c%c%c"), 0xFF, 0xFC, 0x01); // Show characters - telnetClient->println(buffer); - snprintf_P(buffer, sizeof(buffer), PSTR("haspadmin")); - if(telnetLoginState == TELNET_USERNAME_OK && strcmp(telnetInputBuffer, buffer) == 0) { - telnetLoginState = TELNET_AUTHENTICATED; // User and Pass are correct - telnetLoginAttempt = 0; // Reset attempt counter - telnetClient->println(debugHaspHeader()); // Send version header - Log.notice(F("TELNET: Client login from %s"), telnetClient->remoteIP().toString().c_str()); - } else { - telnetLoginState = TELNET_UNAUTHENTICATED; - telnetLoginAttempt++; // Subsequent attempt - snprintf_P(buffer, sizeof(buffer), PSTR("Authorization failed!\r\n")); - telnetClient->println(buffer); - Log.warning(F("TELNET: Incorrect login attempt from %s"), - telnetClient->remoteIP().toString().c_str()); - if(telnetLoginAttempt >= 3) { - telnetExitCommand(); - } else { - snprintf_P(buffer, sizeof(buffer), PSTR("Username: ")); - telnetClient->print(buffer); - } - } - break; - } - default: - if(telnetInputIndex > 0 && !telnetExitCommand()) { - dispatchCommand(telnetInputBuffer); - } - } - telnetInputIndex = 0; // reset input buffer index - break; - default: - // If we have room left in our buffer add the current byte - if(telnetInputIndex < sizeof(telnetInputBuffer) - 1 && telnetInputByte >= 0x20) { - telnetInputBuffer[telnetInputIndex] = telnetInputByte; - telnetInputIndex++; + switch(ch) { + case 255: + if(telnetInCommandMode) { + telnetInCommandMode = true; } } } +void telnetProcessLine() +{ + telnetInputBuffer[telnetInputIndex] = 0; // null terminate our char array + + switch(telnetLoginState) { + case TELNET_UNAUTHENTICATED: { + telnetClient->printf(PSTR("Password: %c%c%c"), 0xFF, 0xFB, 0x01); // Hide characters + telnetLoginState = strcmp(telnetInputBuffer, httpUser) == 0 ? TELNET_USERNAME_OK : TELNET_USERNAME_NOK; + break; + } + case TELNET_USERNAME_OK: + case TELNET_USERNAME_NOK: { + telnetClient->printf(PSTR("%c%c%c\n"), 0xFF, 0xFC, 0x01); // Show characters + if(telnetLoginState == TELNET_USERNAME_OK && strcmp(telnetInputBuffer, httpPassword) == 0) { + telnetClient->println(); + telnetClient->println(debugHaspHeader().c_str()); // Send version header + telnetLoginState = TELNET_AUTHENTICATED; // User and Pass are correct + telnetLoginAttempt = 0; // Reset attempt counter + Log.notice(F("TELNET: Client login from %s"), + telnetClient->remoteIP().toString().c_str()); // Serial Only + + /* Echo locally as separate string */ + telnetClient->print(F("TELNET: Client login from ")); + telnetClient->println(telnetClient->remoteIP().toString().c_str()); + + /* Now register logger for telnet */ + Log.registerOutput(1, telnetClient, LOG_LEVEL_VERBOSE, true); + } else { + telnetLoginState = TELNET_UNAUTHENTICATED; + telnetLoginAttempt++; // Subsequent attempt + telnetClient->println(F("Authorization failed!\r\n")); + Log.warning(F("TELNET: Incorrect login attempt from %s"), telnetClient->remoteIP().toString().c_str()); + if(telnetLoginAttempt >= 3) { + telnetExitCommand(); + } else { + telnetClient->print(F("Username: ")); + } + } + break; + } + default: + if(telnetInputIndex > 0 && !telnetExitCommand()) { + dispatchCommand(telnetInputBuffer); + } + } + + telnetInputIndex = 0; // reset input buffer index +} + +void telnetProcessData(char ch) +{ + + switch(ch) { + case 0 ... 7: + case 9: + case 11 ... 12: + case 14 ... 31: + case 251 ... 255: + break; + case 10: + telnetInputIndex = 0; + break; + case 8: // Backspace + if(telnetInputIndex > 0) telnetInputIndex--; + break; + case 13: + telnetProcessLine(); + break; + default: + if(!isprint(ch)) { + telnetClient->printf(PSTR(" 0x%02x "), ch); + } + // If we have room left in our buffer add the current byte + if(telnetInputIndex < sizeof(telnetInputBuffer) - 1) { + telnetInputBuffer[telnetInputIndex++] = ch; + // telnetInputIndex++; + } + } +} + +void telnetProcessCharacter(char ch) +{ + // if(ch == (char)0xff || telnetInCommandMode) { + // telnetProcessCharacter(ch); + //} else { + telnetProcessData(ch); + //} +} + void telnetSetup(const JsonObject & settings) { - telnetSetConfig(settings); + // telnetSetConfig(settings); if(telnetEnabled) { // Setup telnet server for remote debug output - telnetServer = new WiFiServer(23); + if(!telnetServer) telnetServer = new WiFiServer(23); if(telnetServer) { - telnetClient = new WiFiClient; telnetServer->setNoDelay(true); telnetServer->begin(); + + if(!telnetClient) telnetClient = new WiFiClient; + if(!telnetClient) { + Log.error(F("TELNET: Failed to start telnet client")); + } else { + telnetClient->setNoDelay(true); + } + Log.notice(F("TELNET: Debug telnet console started")); } else { Log.error(F("TELNET: Failed to start telnet server")); @@ -156,7 +191,7 @@ void telnetSetup(const JsonObject & settings) } } -void telnetLoop() +void IRAM_ATTR telnetLoop() { // Basic telnet client handling code from: https://gist.github.com/tablatronix/4793677ca748f5f584c95ec4a2b10303 if(telnetServer && telnetServer->hasClient()) { // client is connected @@ -169,11 +204,12 @@ void telnetLoop() // Handle client input from telnet connection. if(telnetClient && telnetClient->connected() && telnetClient->available()) { - telnetProcessInput(); // client input processing + telnetProcessCharacter(telnetClient->read()); // client input processing } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* void telnetPrintln(const char * msg) { if(telnetEnabled && telnetClient && telnetClient->connected() && telnetLoginState == TELNET_AUTHENTICATED) { @@ -186,7 +222,13 @@ void telnetPrint(const char * msg) telnetClient->print(msg); } } - +void telnetPrint(const __FlashStringHelper * msg) +{ + if(telnetEnabled && telnetClient && telnetClient->connected() && telnetLoginState == TELNET_AUTHENTICATED) { + telnetClient->print(msg); + } +} +*/ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool telnetGetConfig(const JsonObject & settings) diff --git a/src/hasp_telnet.h b/src/hasp_telnet.h index 98d6b19e..e61c46e5 100644 --- a/src/hasp_telnet.h +++ b/src/hasp_telnet.h @@ -13,6 +13,7 @@ void telnetStop(void); void telnetPrint(const char * msg); void telnetPrintln(const char * msg); +void telnetPrint(const __FlashStringHelper * msg); bool telnetSetConfig(const JsonObject & settings); bool telnetGetConfig(const JsonObject & settings);