From 2e506ced93f80d250673d4df1bb85f094d5dd9f1 Mon Sep 17 00:00:00 2001 From: Andy CA6JAU Date: Sun, 5 Aug 2018 18:04:35 -0400 Subject: [PATCH] Add Wires-X categories support --- YSFGateway/WiresX.cpp | 114 ++++++++++++++++++++++++++++++++++- YSFGateway/WiresX.h | 6 +- YSFGateway/YSFReflectors.cpp | 2 +- 3 files changed, 118 insertions(+), 4 deletions(-) diff --git a/YSFGateway/WiresX.cpp b/YSFGateway/WiresX.cpp index 8013f7a..db7cc52 100644 --- a/YSFGateway/WiresX.cpp +++ b/YSFGateway/WiresX.cpp @@ -32,6 +32,7 @@ const unsigned char DX_REQ[] = {0x5DU, 0x71U, 0x5FU}; const unsigned char CONN_REQ[] = {0x5DU, 0x23U, 0x5FU}; const unsigned char DISC_REQ[] = {0x5DU, 0x2AU, 0x5FU}; const unsigned char ALL_REQ[] = {0x5DU, 0x66U, 0x5FU}; +const unsigned char CAT_REQ[] = {0x5DU, 0x67U, 0x5FU}; const unsigned char DX_RESP[] = {0x5DU, 0x51U, 0x5FU, 0x26U}; const unsigned char CONN_RESP[] = {0x5DU, 0x41U, 0x5FU, 0x26U}; @@ -237,6 +238,9 @@ WX_STATUS CWiresX::process(const unsigned char* data, const unsigned char* sourc } else if (::memcmp(m_command + 1U, DISC_REQ, 3U) == 0) { processDisconnect(source); return WXS_DISCONNECT; + } else if (::memcmp(m_command + 1U, CAT_REQ, 3U) == 0) { + processCategory(source, m_command + 5U); + return WXS_NONE; } else { CUtils::dump("Unknown Wires-X command", m_command, cmd_len); return WXS_NONE; @@ -264,6 +268,39 @@ void CWiresX::processDX(const unsigned char* source) m_timer.start(); } +void CWiresX::processCategory(const unsigned char* source, const unsigned char* data) +{ + ::LogDebug("Received CATEGORY request from %10.10s", source); + + char buffer[6U]; + ::memcpy(buffer, data + 5U, 2U); + buffer[3U] = 0x00U; + + unsigned int len = atoi(buffer); + + if (len == 0U) + return; + + if (len > 20U) + return; + + m_category.clear(); + + for (unsigned int j = 0U; j < len; j++) { + ::memcpy(buffer, data + 7U + j * 5U, 5U); + buffer[5U] = 0x00U; + + std::string id = std::string(buffer, 5U); + + CYSFReflector* refl = m_reflectors.findById(id); + if (refl) + m_category.push_back(refl); + } + + m_status = WXSI_CATEGORY; + m_timer.start(); +} + void CWiresX::processAll(const unsigned char* source, const unsigned char* data) { if (data[0U] == '0' && data[1] == '1') { @@ -355,6 +392,9 @@ void CWiresX::clock(unsigned int ms) case WXSI_DISCONNECT: sendDisconnectReply(); break; + case WXSI_CATEGORY: + sendCategoryReply(); + break; default: break; } @@ -725,9 +765,9 @@ void CWiresX::sendAllReply() unsigned int k = 1029U - offset; for(unsigned int i = 0U; i < k; i++) data[i + offset] = 0x20U; - + offset += k; - + data[offset + 0U] = 0x03U; // End of data marker data[offset + 1U] = CCRC::addCRC(data, offset + 1U); @@ -853,3 +893,73 @@ void CWiresX::sendSearchNotFoundReply() m_seqNo++; } + +void CWiresX::sendCategoryReply() +{ + unsigned char data[1100U]; + ::memset(data, 0x00U, 1100U); + + data[0U] = m_seqNo; + + for (unsigned int i = 0U; i < 4U; i++) + data[i + 1U] = ALL_RESP[i]; + + data[5U] = '2'; + data[6U] = '1'; + + for (unsigned int i = 0U; i < 5U; i++) + data[i + 7U] = m_id.at(i); + + for (unsigned int i = 0U; i < 10U; i++) + data[i + 12U] = m_node.at(i); + + unsigned int n = m_category.size(); + if (n > 20U) + n = 20U; + + ::sprintf((char*)(data + 22U), "%03u%03u", n, n); + + data[28U] = 0x0DU; + + unsigned int offset = 29U; + for (unsigned int j = 0U; j < n; j++, offset += 50U) { + CYSFReflector* refl = m_category.at(j); + + ::memset(data + offset, ' ', 50U); + + data[offset + 0U] = '5'; + + for (unsigned int i = 0U; i < 5U; i++) + data[i + offset + 1U] = refl->m_id.at(i); + + for (unsigned int i = 0U; i < 16U; i++) + data[i + offset + 6U] = refl->m_name.at(i); + + for (unsigned int i = 0U; i < 3U; i++) + data[i + offset + 22U] = refl->m_count.at(i); + + for (unsigned int i = 0U; i < 10U; i++) + data[i + offset + 25U] = ' '; + + for (unsigned int i = 0U; i < 14U; i++) + data[i + offset + 35U] = refl->m_desc.at(i); + + data[offset + 49U] = 0x0DU; + } + + unsigned int k = 1029U - offset; + for(unsigned int i = 0U; i < k; i++) + data[i + offset] = 0x20U; + + offset += k; + + data[offset + 0U] = 0x03U; // End of data marker + data[offset + 1U] = CCRC::addCRC(data, offset + 1U); + + CUtils::dump(1U, "CATEGORY Reply", data, offset + 2U); + + createReply(data, offset + 2U); + + m_seqNo++; +} + diff --git a/YSFGateway/WiresX.h b/YSFGateway/WiresX.h index 83987c1..0116762 100644 --- a/YSFGateway/WiresX.h +++ b/YSFGateway/WiresX.h @@ -38,7 +38,8 @@ enum WXSI_STATUS { WXSI_CONNECT, WXSI_DISCONNECT, WXSI_ALL, - WXSI_SEARCH + WXSI_SEARCH, + WXSI_CATEGORY }; class CWiresX { @@ -85,10 +86,12 @@ private: WXSI_STATUS m_status; unsigned int m_start; std::string m_search; + std::vector m_category; WX_STATUS processConnect(const unsigned char* source, const unsigned char* data); void processDX(const unsigned char* source); void processAll(const unsigned char* source, const unsigned char* data); + void processCategory(const unsigned char* source, const unsigned char* data); void sendDXReply(); void sendConnectReply(); @@ -96,6 +99,7 @@ private: void sendAllReply(); void sendSearchReply(); void sendSearchNotFoundReply(); + void sendCategoryReply(); void createReply(const unsigned char* data, unsigned int length); unsigned char calculateFT(unsigned int length, unsigned int offset) const; diff --git a/YSFGateway/YSFReflectors.cpp b/YSFGateway/YSFReflectors.cpp index a263760..5325fab 100644 --- a/YSFGateway/YSFReflectors.cpp +++ b/YSFGateway/YSFReflectors.cpp @@ -136,7 +136,7 @@ bool CYSFReflectors::load() refl->m_desc = std::string(p3); refl->m_address = address; refl->m_port = (unsigned int)::atoi(p5); - refl->m_count = std::string(p6);; + refl->m_count = std::string(p6); refl->m_type = YT_YSF; refl->m_name.resize(16U, ' ');