From 6cd887f91abcf89fbc3ecb09580f9d33323ddb9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Nidecki?= Date: Sat, 21 Aug 2021 22:35:52 +0200 Subject: [PATCH] TNC: recognize and ignore non data frames --- lib/KISS_TO_TNC2/KISS_TO_TNC2.cpp | 259 ++++++++++++++++-------------- lib/KISS_TO_TNC2/KISS_TO_TNC2.h | 2 +- src/taskTNC.cpp | 23 +-- 3 files changed, 152 insertions(+), 132 deletions(-) diff --git a/lib/KISS_TO_TNC2/KISS_TO_TNC2.cpp b/lib/KISS_TO_TNC2/KISS_TO_TNC2.cpp index b429a81..77aac79 100644 --- a/lib/KISS_TO_TNC2/KISS_TO_TNC2.cpp +++ b/lib/KISS_TO_TNC2/KISS_TO_TNC2.cpp @@ -7,7 +7,7 @@ String decode_address_ax25(const String &ax25Address, bool &isLast, bool isRelay bool validateKISSFrame(const String &kissFormattedFrame); -String decapsulateKISS(const String& frame); +String decapsulateKISS(const String &frame); /* * https://ham.zmailer.org/oh2mqk/aprx/PROTOCOLS @@ -33,100 +33,112 @@ String decapsulateKISS(const String& frame); */ -String encode_kiss(const String& tnc2FormattedFrame) { - String ax25Frame = ""; +String encode_kiss(const String &tnc2FormattedFrame) { + String ax25Frame = ""; - if (validateTNC2Frame(tnc2FormattedFrame)){ - String address = ""; - bool dst_addres_written = false; - for (int p=0;p<=tnc2FormattedFrame.indexOf(':');p++){ - char currentChar = tnc2FormattedFrame.charAt(p); - if (currentChar == ':' || currentChar == '>' || currentChar == ','){ - if (!dst_addres_written && (currentChar == ',' || currentChar == ':')){ - // ax25 frame DST SRC - // tnc2 frame SRC DST - ax25Frame = encode_address_ax25(address) + ax25Frame; - dst_addres_written = true; - } else { - ax25Frame += encode_address_ax25(address); - } - address = ""; - } else { - address += currentChar; - } + if (validateTNC2Frame(tnc2FormattedFrame)) { + String address = ""; + bool dst_addres_written = false; + for (int p = 0; p <= tnc2FormattedFrame.indexOf(':'); p++) { + char currentChar = tnc2FormattedFrame.charAt(p); + if (currentChar == ':' || currentChar == '>' || currentChar == ',') { + if (!dst_addres_written && (currentChar == ',' || currentChar == ':')) { + // ax25 frame DST SRC + // tnc2 frame SRC DST + ax25Frame = encode_address_ax25(address) + ax25Frame; + dst_addres_written = true; + } else { + ax25Frame += encode_address_ax25(address); } - auto lastAddressChar = (uint8_t)ax25Frame.charAt(ax25Frame.length() - 1); - ax25Frame.setCharAt(ax25Frame.length() - 1, (char)(lastAddressChar | IS_LAST_ADDRESS_POSITION_MASK)); - ax25Frame += (char)APRS_CONTROL_FIELD; - ax25Frame += (char)APRS_INFORMATION_FIELD; - ax25Frame += tnc2FormattedFrame.substring(tnc2FormattedFrame.indexOf(':')+1); + address = ""; + } else { + address += currentChar; + } } + auto lastAddressChar = (uint8_t) ax25Frame.charAt(ax25Frame.length() - 1); + ax25Frame.setCharAt(ax25Frame.length() - 1, (char) (lastAddressChar | IS_LAST_ADDRESS_POSITION_MASK)); + ax25Frame += (char) APRS_CONTROL_FIELD; + ax25Frame += (char) APRS_INFORMATION_FIELD; + ax25Frame += tnc2FormattedFrame.substring(tnc2FormattedFrame.indexOf(':') + 1); + } - String kissFrame = encapsulateKISS(ax25Frame, CMD_DATA); - return kissFrame; + String kissFrame = encapsulateKISS(ax25Frame, CMD_DATA); + return kissFrame; } String encapsulateKISS(const String &ax25Frame, uint8_t TNCCmd) { - String kissFrame = ""; - kissFrame += (char)FEND; // start of frame - kissFrame += (char)(0x0f & TNCCmd); // TNC0, cmd - for (int i = 0; i < ax25Frame.length(); ++i) { - char currentChar = ax25Frame.charAt(i); - if (currentChar == (char)FEND){ - kissFrame += (char)FESC; - kissFrame += (char)TFEND; - } else if (currentChar == (char)FESC){ - kissFrame += (char)FESC; - kissFrame += (char)TFESC; - } else { - kissFrame += currentChar; - } + String kissFrame = ""; + kissFrame += (char) FEND; // start of frame + kissFrame += (char) (0x0f & TNCCmd); // TNC0, cmd + for (int i = 0; i < ax25Frame.length(); ++i) { + char currentChar = ax25Frame.charAt(i); + if (currentChar == (char) FEND) { + kissFrame += (char) FESC; + kissFrame += (char) TFEND; + } else if (currentChar == (char) FESC) { + kissFrame += (char) FESC; + kissFrame += (char) TFESC; + } else { + kissFrame += currentChar; } - kissFrame += (char)FEND; // end of frame - return kissFrame; + } + kissFrame += (char) FEND; // end of frame + return kissFrame; } -String decapsulateKISS(const String& frame) { - String ax25Frame = ""; - for (int i = 2; i < frame.length() - 1; ++i) { - char currentChar = frame.charAt(i); - if (currentChar == (char)FESC){ - char nextChar = frame.charAt(i+1); - if (nextChar == (char)TFEND){ - ax25Frame += (char)FEND; - } else if (nextChar == (char)TFESC){ - ax25Frame += (char)FESC; - } - i++; - } else { - ax25Frame += currentChar; - } +String decapsulateKISS(const String &frame) { + String ax25Frame = ""; + for (int i = 2; i < frame.length() - 1; ++i) { + char currentChar = frame.charAt(i); + if (currentChar == (char) FESC) { + char nextChar = frame.charAt(i + 1); + if (nextChar == (char) TFEND) { + ax25Frame += (char) FEND; + } else if (nextChar == (char) TFESC) { + ax25Frame += (char) FESC; + } + i++; + } else { + ax25Frame += currentChar; } + } - return ax25Frame; + return ax25Frame; } -String decode_kiss(const String& kissFormattedFrame) { - String TNC2Frame = ""; +/** + * + * @param inputKISSTNCFrame + * @param dataFrame + * @return Decapsulated TNC2KISS APRS data frame, or raw command data frame + */ +String decode_kiss(const String &inputKISSTNCFrame, bool &dataFrame) { + String TNC2Frame = ""; - if (validateKISSFrame(kissFormattedFrame)){ - String ax25Frame = decapsulateKISS(kissFormattedFrame); - bool isLast = false; - String dst_addr = decode_address_ax25(ax25Frame.substring(0, 7), isLast, false); - String src_addr = decode_address_ax25(ax25Frame.substring(7, 14), isLast, false); - TNC2Frame = src_addr + ">" + dst_addr; - int digi_info_index = 14; - while (!isLast && digi_info_index + 7 < ax25Frame.length()){ - String digi_addr = decode_address_ax25(ax25Frame.substring(digi_info_index, digi_info_index + 7), isLast, true); - TNC2Frame += ',' + digi_addr; - digi_info_index += 7; - } - TNC2Frame += ':'; - TNC2Frame += ax25Frame.substring(digi_info_index + 2); + if (validateKISSFrame(inputKISSTNCFrame)) { + dataFrame = inputKISSTNCFrame.charAt(1) == CMD_DATA; + if (dataFrame){ + String ax25Frame = decapsulateKISS(inputKISSTNCFrame); + bool isLast = false; + String dst_addr = decode_address_ax25(ax25Frame.substring(0, 7), isLast, false); + String src_addr = decode_address_ax25(ax25Frame.substring(7, 14), isLast, false); + TNC2Frame = src_addr + ">" + dst_addr; + int digi_info_index = 14; + while (!isLast && digi_info_index + 7 < ax25Frame.length()) { + String digi_addr = decode_address_ax25(ax25Frame.substring(digi_info_index, digi_info_index + 7), isLast, true); + TNC2Frame += ',' + digi_addr; + digi_info_index += 7; + } + TNC2Frame += ':'; + TNC2Frame += ax25Frame.substring(digi_info_index + 2); + } else { + // command frame, currently ignored + TNC2Frame += inputKISSTNCFrame; } + } - return TNC2Frame; + return TNC2Frame; } /** @@ -135,32 +147,32 @@ String decode_kiss(const String& kissFormattedFrame) { * @return */ String encode_address_ax25(String tnc2Address) { - bool hasBeenDigipited = tnc2Address.indexOf('*') != -1; + bool hasBeenDigipited = tnc2Address.indexOf('*') != -1; - if (tnc2Address.indexOf('-') == -1){ - if (hasBeenDigipited){ - // ex. TCPIP* in tnc2Address - // so we skip last char - tnc2Address = tnc2Address.substring(0, tnc2Address.length()-1); - } - tnc2Address += "-0"; + if (tnc2Address.indexOf('-') == -1) { + if (hasBeenDigipited) { + // ex. TCPIP* in tnc2Address + // so we skip last char + tnc2Address = tnc2Address.substring(0, tnc2Address.length() - 1); } + tnc2Address += "-0"; + } - int separatorIndex = tnc2Address.indexOf('-'); - int ssid = tnc2Address.substring(separatorIndex + 1).toInt(); - // TODO: SSID should not be > 16 - String kissAddress = ""; - for (int i = 0; i < 6; ++i) { - char addressChar; - if (tnc2Address.length() > i && i < separatorIndex){ - addressChar = tnc2Address.charAt(i); - } else { - addressChar = ' '; - } - kissAddress += (char)(addressChar << 1); + int separatorIndex = tnc2Address.indexOf('-'); + int ssid = tnc2Address.substring(separatorIndex + 1).toInt(); + // TODO: SSID should not be > 16 + String kissAddress = ""; + for (int i = 0; i < 6; ++i) { + char addressChar; + if (tnc2Address.length() > i && i < separatorIndex) { + addressChar = tnc2Address.charAt(i); + } else { + addressChar = ' '; } - kissAddress += (char)((ssid << 1) | 0b01100000 | (hasBeenDigipited ? HAS_BEEN_DIGIPITED_MASK : 0)); - return kissAddress; + kissAddress += (char) (addressChar << 1); + } + kissAddress += (char) ((ssid << 1) | 0b01100000 | (hasBeenDigipited ? HAS_BEEN_DIGIPITED_MASK : 0)); + return kissAddress; } /** @@ -169,30 +181,35 @@ String encode_address_ax25(String tnc2Address) { * @return */ String decode_address_ax25(const String &ax25Address, bool &isLast, bool isRelay) { - String TNCAddress = ""; - for (int i = 0; i < 6; ++i) { - uint8_t currentCharacter = ax25Address.charAt(i); - currentCharacter >>= 1; - if (currentCharacter != ' '){ - TNCAddress += (char)currentCharacter; - } + String TNCAddress = ""; + for (int i = 0; i < 6; ++i) { + uint8_t currentCharacter = ax25Address.charAt(i); + currentCharacter >>= 1; + if (currentCharacter != ' ') { + TNCAddress += (char) currentCharacter; } - auto ssid_char = (uint8_t) ax25Address.charAt(6); - bool hasBeenDigipited = ssid_char & HAS_BEEN_DIGIPITED_MASK; - isLast = ssid_char & IS_LAST_ADDRESS_POSITION_MASK; - ssid_char >>= 1; + } + auto ssid_char = (uint8_t) ax25Address.charAt(6); + bool hasBeenDigipited = ssid_char & HAS_BEEN_DIGIPITED_MASK; + isLast = ssid_char & IS_LAST_ADDRESS_POSITION_MASK; + ssid_char >>= 1; - int ssid = 0b1111 & ssid_char; - if (ssid){ - TNCAddress += '-'; - TNCAddress += ssid; - } - if (isRelay && hasBeenDigipited){ - TNCAddress += '*'; - } - return TNCAddress; + int ssid = 0b1111 & ssid_char; + if (ssid) { + TNCAddress += '-'; + TNCAddress += ssid; + } + if (isRelay && hasBeenDigipited) { + TNCAddress += '*'; + } + return TNCAddress; } -bool validateTNC2Frame(const String &tnc2FormattedFrame) { return (tnc2FormattedFrame.indexOf(':') != -1) && (tnc2FormattedFrame.indexOf('>') != -1); } +bool validateTNC2Frame(const String &tnc2FormattedFrame) { + return (tnc2FormattedFrame.indexOf(':') != -1) && (tnc2FormattedFrame.indexOf('>') != -1); +} -bool validateKISSFrame(const String &kissFormattedFrame) { return kissFormattedFrame.charAt(0) == (char)FEND && kissFormattedFrame.charAt(kissFormattedFrame.length() - 1) == (char)FEND; } +bool validateKISSFrame(const String &kissFormattedFrame) { + return kissFormattedFrame.charAt(0) == (char) FEND && + kissFormattedFrame.charAt(kissFormattedFrame.length() - 1) == (char) FEND; +} diff --git a/lib/KISS_TO_TNC2/KISS_TO_TNC2.h b/lib/KISS_TO_TNC2/KISS_TO_TNC2.h index ecf447a..87aa7a9 100644 --- a/lib/KISS_TO_TNC2/KISS_TO_TNC2.h +++ b/lib/KISS_TO_TNC2/KISS_TO_TNC2.h @@ -8,6 +8,6 @@ #define IS_LAST_ADDRESS_POSITION_MASK 0b1 String encode_kiss(const String& tnc2FormattedFrame); -String decode_kiss(const String& kissFormattedFrame); +String decode_kiss(const String &inputKISSTNCFrame, bool &dataFrame); String encapsulateKISS(const String &ax25Frame, uint8_t TNCCmd); \ No newline at end of file diff --git a/src/taskTNC.cpp b/src/taskTNC.cpp index c77e334..8bc495b 100644 --- a/src/taskTNC.cpp +++ b/src/taskTNC.cpp @@ -33,28 +33,31 @@ void handleKISSData(char character, int bufferIndex) { } inTNCData->concat(character); if (character == (char) FEND && inTNCData->length() > 3) { - const String &TNC2DataFrame = decode_kiss(*inTNCData); + bool isDataFrame = false; + const String &TNC2DataFrame = decode_kiss(*inTNCData, isDataFrame); - #ifdef LOCAL_KISS_ECHO + if (isDataFrame) { + #ifdef LOCAL_KISS_ECHO Serial.print(inTNCData); - #ifdef ENABLE_BLUETOOTH + #ifdef ENABLE_BLUETOOTH if (SerialBT.hasClient()) { SerialBT.print(inTNCData); } - #endif - #ifdef ENABLE_WIFI + #endif + #ifdef ENABLE_WIFI iterateWifiClients([](WiFiClient *client, const String *data){ if (client->connected()){ client->print(*data); client->flush(); } }, &inTNCData, clients, MAX_WIFI_CLIENTS); + #endif #endif - #endif - auto *buffer = new String(); - buffer->concat(TNC2DataFrame); - if (xQueueSend(tncToSendQueue, &buffer, (1000 / portTICK_PERIOD_MS)) != pdPASS){ - delete buffer; + auto *buffer = new String(); + buffer->concat(TNC2DataFrame); + if (xQueueSend(tncToSendQueue, &buffer, (1000 / portTICK_PERIOD_MS)) != pdPASS) { + delete buffer; + } } inTNCData->clear(); }