diff --git a/YSFGateway/WiresX.cpp b/YSFGateway/WiresX.cpp index d547535..b49f77b 100644 --- a/YSFGateway/WiresX.cpp +++ b/YSFGateway/WiresX.cpp @@ -239,7 +239,7 @@ WX_STATUS CWiresX::process(const unsigned char* data, const unsigned char* sourc CUtils::dump(1U, "Received Wires-X command", m_command, cmd_len); - // If we are using WiresX Passthrough (we already know we are on a YSF2xxx room from YSFGateway + // YSFGateway.cpp is telling us to pass the command to the network, so do not process locally unless it's a disconnect if (wiresXCommandPassthrough) { if (::memcmp(m_command + 1U, DX_REQ, 3U) == 0) { return WX_STATUS::NONE; @@ -375,8 +375,10 @@ WX_STATUS CWiresX::processConnect(const unsigned char* source, const unsigned ch std::string id = std::string((char*)data, 5U); m_reflector = m_reflectors.findById(id); - if (m_reflector == nullptr) + if (m_reflector == nullptr) { + sendConnectFailedReply(); return WX_STATUS::NONE; + } m_status = WXSI_STATUS::CONNECT; m_timer.start(); @@ -472,11 +474,11 @@ void CWiresX::createReply(const unsigned char* data, unsigned int length, CYSFNe assert(data != nullptr); assert(length > 0U); - bool isYSF2XX = true; + bool sendWiresXtoNetwork = true; // If we don't explicitly pass a network, use the default one. if (network == nullptr) { - isYSF2XX = false; + sendWiresXtoNetwork = false; network = m_network; } @@ -521,7 +523,7 @@ void CWiresX::createReply(const unsigned char* data, unsigned int length, CYSFNe buffer[34U] = seqNo; seqNo += 2U; - writeData(buffer, network, isYSF2XX); + writeData(buffer, network, sendWiresXtoNetwork); fich.setFI(YSF_FI_COMMUNICATIONS); @@ -568,7 +570,7 @@ void CWiresX::createReply(const unsigned char* data, unsigned int length, CYSFNe buffer[34U] = seqNo; seqNo += 2U; - writeData(buffer, network, isYSF2XX); + writeData(buffer, network, sendWiresXtoNetwork); fn++; if (fn >= 8U) { @@ -588,13 +590,13 @@ void CWiresX::createReply(const unsigned char* data, unsigned int length, CYSFNe buffer[34U] = seqNo | 0x01U; - writeData(buffer, network, isYSF2XX); + writeData(buffer, network, sendWiresXtoNetwork); } -void CWiresX::writeData(const unsigned char* buffer, CYSFNetwork* network, bool isYSF2XX) +void CWiresX::writeData(const unsigned char* buffer, CYSFNetwork* network, bool sendWiresXtoNetwork) { - if (isYSF2XX) { - // Send YSF2XXX Wires-X reply directly to the network + if (sendWiresXtoNetwork) { + // Send WiresX directly to the network network->write(buffer); } else { // Send host Wires-X reply using ring buffer @@ -644,15 +646,15 @@ void CWiresX::sendDXReply() data[i + 20U] = m_name.at(i); if (m_reflector == nullptr) { - data[34U] = '1'; - data[35U] = '2'; + data[34U] = '1'; // 0,1,2 seem Valid + data[35U] = '2'; // 0 = Offline 1 = Busy 2 = Disconnect 3 = Normal data[57U] = '0'; data[58U] = '0'; data[59U] = '0'; } else { - data[34U] = '1'; - data[35U] = '5'; + data[34U] = '1'; // 0,1,2 seem Valid + data[35U] = '3'; // 0 = Offline 1 = Busy 2 = Disconnect 3 = Normal for (unsigned int i = 0U; i < 5U; i++) data[i + 36U] = m_reflector->m_id.at(i); @@ -739,11 +741,11 @@ void CWiresX::sendConnectReply() for (unsigned int i = 0U; i < 14U; i++) data[i + 20U] = m_name.at(i); - data[34U] = '1'; - data[35U] = '5'; + data[34U] = '1'; // 0,1,2 seem Valid + data[35U] = '3'; // 0 = Offline 1 = Busy 2 = Disconnect 3 = Normal for (unsigned int i = 0U; i < 5U; i++) - data[i + 36U] = m_reflector->m_id.at(i); + data[i + 36U] = m_reflector->m_id.at(i); for (unsigned int i = 0U; i < 16U; i++) data[i + 41U] = m_reflector->m_name.at(i); @@ -770,6 +772,43 @@ void CWiresX::sendConnectReply() m_seqNo++; } +void CWiresX::sendConnectFailedReply() +{ + unsigned char data[110U]; + ::memset(data, 0x00U, 110U); + ::memset(data, ' ', 90U); + + data[0U] = m_seqNo; + + for (unsigned int i = 0U; i < 4U; i++) + data[i + 1U] = CONN_RESP[i]; + + for (unsigned int i = 0U; i < 5U; i++) + data[i + 5U] = m_id.at(i); + + for (unsigned int i = 0U; i < 10U; i++) + data[i + 10U] = m_node.at(i); + + for (unsigned int i = 0U; i < 14U; i++) + data[i + 20U] = m_name.at(i); + + data[34U] = '1'; // 0,1,2 seem Valid + data[35U] = '0'; // 0 = Offline 1 = Busy 2 = Disconnect 3 = Normal + + data[57U] = '0'; + data[58U] = '0'; + data[59U] = '0'; + + data[89U] = 0x03U; // End of data marker + data[90U] = CCRC::addCRC(data, 90U); + + CUtils::dump(1U, "Connect Failed Reply", data, 91U); + + createReply(data, 91U); + + m_seqNo++; +} + void CWiresX::sendDisconnectReply() { unsigned char data[110U]; @@ -790,8 +829,8 @@ void CWiresX::sendDisconnectReply() for (unsigned int i = 0U; i < 14U; i++) data[i + 20U] = m_name.at(i); - data[34U] = '1'; - data[35U] = '2'; + data[34U] = '1'; // 0,1,2 seem Valid + data[35U] = '2'; // 0 = Offline 1 = Busy 2 = Disconnect 3 = Normal data[57U] = '0'; data[58U] = '0'; diff --git a/YSFGateway/WiresX.h b/YSFGateway/WiresX.h index bcaad5a..7dd6ec2 100644 --- a/YSFGateway/WiresX.h +++ b/YSFGateway/WiresX.h @@ -106,6 +106,7 @@ private: void sendDXReply(); void sendConnectReply(); + void sendConnectFailedReply(); void sendDisconnectReply(); void sendAllReply(); void sendSearchReply(); @@ -113,7 +114,7 @@ private: void sendCategoryReply(); void createReply(const unsigned char* data, unsigned int length, CYSFNetwork* network = nullptr); - void writeData(const unsigned char* data, CYSFNetwork* network, bool isYSF2XX); + void writeData(const unsigned char* data, CYSFNetwork* network, bool sendWiresXtoNetwork); unsigned char calculateFT(unsigned int length, unsigned int offset) const; }; diff --git a/YSFGateway/YSFGateway.cpp b/YSFGateway/YSFGateway.cpp index bbdc5c5..5d4097b 100644 --- a/YSFGateway/YSFGateway.cpp +++ b/YSFGateway/YSFGateway.cpp @@ -323,14 +323,14 @@ int CYSFGateway::run() unsigned char dt = fich.getDT(); CYSFReflector* reflector = m_wiresX->getReflector(); - if (m_ysfNetwork != nullptr && m_linkType == LINK_TYPE::YSF && wiresXCommandPassthrough && reflector->m_wiresX) { + if (m_ysfNetwork != nullptr && m_linkType == LINK_TYPE::YSF && wiresXCommandPassthrough && reflector != nullptr && reflector->m_wiresX) { processDTMF(buffer, dt); - processWiresX(buffer, fich, true, wiresXCommandPassthrough); + processWiresX(buffer, fich, reflector->m_wiresX, wiresXCommandPassthrough); // Honour reflector->m_wiresX status } else { processDTMF(buffer, dt); - processWiresX(buffer, fich, false, wiresXCommandPassthrough); - reflector = m_wiresX->getReflector(); //reflector may have changed - if (m_ysfNetwork != nullptr && m_linkType == LINK_TYPE::YSF && reflector->m_wiresX) + processWiresX(buffer, fich, false, wiresXCommandPassthrough); // Remove the assumption that wiresXCommandPassthrough is set + reflector = m_wiresX->getReflector(); // reflector may have changed + if (m_ysfNetwork != nullptr && m_linkType == LINK_TYPE::YSF && reflector != nullptr && reflector->m_wiresX) m_exclude = (dt == YSF_DT_DATA_FR_MODE); } @@ -560,11 +560,17 @@ void CYSFGateway::createWiresX(CYSFNetwork* rptNetwork) m_wiresX->start(); } -void CYSFGateway::processWiresX(const unsigned char* buffer, const CYSFFICH& fich, bool dontProcessWiresXLocal, bool wiresXCommandPassthrough) +void CYSFGateway::processWiresX(const unsigned char* buffer, const CYSFFICH& fich, bool wiresXEnabledReflector, bool wiresXCommandPassthrough) { assert(buffer != nullptr); - WX_STATUS status = m_wiresX->process(buffer + 35U, buffer + 14U, fich, dontProcessWiresXLocal); + WX_STATUS status; + if (wiresXEnabledReflector && wiresXCommandPassthrough) { // If these are BOTH true, then we ignore anything but a WiresX disconnect + status = m_wiresX->process(buffer + 35U, buffer + 14U, fich, true); + } else { // Otherwise process all WiresX commands locally + status = m_wiresX->process(buffer + 35U, buffer + 14U, fich, false); + } + switch (status) { case WX_STATUS::CONNECT_YSF: { if (m_linkType == LINK_TYPE::YSF) @@ -626,8 +632,9 @@ void CYSFGateway::processWiresX(const unsigned char* buffer, const CYSFFICH& fic case WX_STATUS::DISCONNECT: if (m_linkType == LINK_TYPE::YSF) { LogMessage("Disconnect has been requested by %10.10s", buffer + 14U); - if ( (wiresXCommandPassthrough) && (::memcmp(buffer + 0U, "YSFD", 4U) == 0) ) { + if ( (wiresXEnabledReflector && wiresXCommandPassthrough) && (::memcmp(buffer + 0U, "YSFD", 4U) == 0) ) { // Send the disconnect to the YSF2xxx gateway too + LogMessage("Forward WiresX Disconnect to Network"); m_ysfNetwork->write(buffer); } diff --git a/YSFGateway/YSFGateway.h b/YSFGateway/YSFGateway.h index 60e9f9c..29cab5d 100644 --- a/YSFGateway/YSFGateway.h +++ b/YSFGateway/YSFGateway.h @@ -71,7 +71,7 @@ private: void reconnectReflector(const std::string& nameOrId); void disconnectCurrentReflector(); std::string calculateLocator(); - void processWiresX(const unsigned char* buffer, const CYSFFICH& fich, bool dontProcessWiresXLocal, bool wiresXCommandPassthrough); + void processWiresX(const unsigned char* buffer, const CYSFFICH& fich, bool wiresXEnabledReflector, bool wiresXCommandPassthrough); void processDTMF(unsigned char* buffer, unsigned char dt); void createWiresX(CYSFNetwork* rptNetwork); void createGPS(); diff --git a/YSFGateway/YSFReflectors.cpp b/YSFGateway/YSFReflectors.cpp index dd618a8..f7e5384 100644 --- a/YSFGateway/YSFReflectors.cpp +++ b/YSFGateway/YSFReflectors.cpp @@ -142,8 +142,7 @@ bool CYSFReflectors::load() refl->m_addrLen = addrLen; refl->m_count = std::string(p6); refl->m_type = YSF_TYPE::YSF; - refl->m_wiresX = (refl->m_name.compare(0, 3, "XLX") == 0); - + refl->m_wiresX = ( refl->m_name.compare(0, 3, "XLX") == 0 || refl->m_name.compare(2, 4, "-XLX") == 0 ); refl->m_name.resize(16U, ' '); refl->m_desc.resize(14U, ' ');