diff --git a/YSFGateway/APRSWriter.cpp b/YSFGateway/APRSWriter.cpp index 9598456..8ec15ad 100644 --- a/YSFGateway/APRSWriter.cpp +++ b/YSFGateway/APRSWriter.cpp @@ -37,7 +37,7 @@ m_height(0), m_desc(), m_suffix(suffix), m_aprsAddr(), -m_aprsAddrLen(), +m_aprsAddrLen(0U), m_aprsSocket() #if defined(USE_GPSD) ,m_gpsdEnabled(false), @@ -55,7 +55,8 @@ m_gpsdData() m_callsign.append(rptSuffix.substr(0U, 1U)); } - CUDPSocket::lookup(address, port, m_aprsAddr, m_aprsAddrLen); + if (CUDPSocket::lookup(address, port, m_aprsAddr, m_aprsAddrLen) != 0) + m_aprsAddrLen = 0U; } CAPRSWriter::~CAPRSWriter() @@ -90,6 +91,11 @@ void CAPRSWriter::setGPSDLocation(const std::string& address, const std::string& bool CAPRSWriter::open() { + if (m_aprsAddrLen == 0U) { + LogError("Unable to lookup the adress of the APRS-IS server"); + return false; + } + #if defined(USE_GPSD) if (m_gpsdEnabled) { int ret = ::gps_open(m_gpsdAddress.c_str(), m_gpsdPort.c_str(), &m_gpsdData); @@ -103,7 +109,7 @@ bool CAPRSWriter::open() LogMessage("Connected to GPSD"); } #endif - bool ret = m_aprsSocket.open(); + bool ret = m_aprsSocket.open(m_aprsAddr); if (!ret) return false; diff --git a/YSFGateway/Conf.cpp b/YSFGateway/Conf.cpp index eb5b2b4..2efaf7e 100644 --- a/YSFGateway/Conf.cpp +++ b/YSFGateway/Conf.cpp @@ -70,6 +70,7 @@ m_aprsPort(0U), m_aprsSuffix(), m_aprsDescription(), m_networkStartup(), +m_networkOptions(), m_networkInactivityTimeout(0U), m_networkRevert(false), m_networkDebug(false), @@ -102,49 +103,69 @@ CConf::~CConf() bool CConf::read() { - FILE* fp = ::fopen(m_file.c_str(), "rt"); - if (fp == NULL) { - ::fprintf(stderr, "Couldn't open the .ini file - %s\n", m_file.c_str()); - return false; - } - - SECTION section = SECTION_NONE; - - char buffer[BUFFER_SIZE]; - while (::fgets(buffer, BUFFER_SIZE, fp) != NULL) { - if (buffer[0U] == '#') - continue; - - if (buffer[0U] == '[') { - if (::strncmp(buffer, "[General]", 9U) == 0) - section = SECTION_GENERAL; - else if (::strncmp(buffer, "[Info]", 6U) == 0) - section = SECTION_INFO; - else if (::strncmp(buffer, "[Log]", 5U) == 0) - section = SECTION_LOG; - else if (::strncmp(buffer, "[APRS]", 6U) == 0) - section = SECTION_APRS; - else if (::strncmp(buffer, "[Network]", 9U) == 0) - section = SECTION_NETWORK; - else if (::strncmp(buffer, "[YSF Network]", 13U) == 0) - section = SECTION_YSF_NETWORK; - else if (::strncmp(buffer, "[FCS Network]", 13U) == 0) - section = SECTION_FCS_NETWORK; - else if (::strncmp(buffer, "[GPSD]", 6U) == 0) - section = SECTION_GPSD; - else if (::strncmp(buffer, "[Remote Commands]", 17U) == 0) - section = SECTION_REMOTE_COMMANDS; - else - section = SECTION_NONE; - - continue; + FILE* fp = ::fopen(m_file.c_str(), "rt"); + if (fp == NULL) { + ::fprintf(stderr, "Couldn't open the .ini file - %s\n", m_file.c_str()); + return false; } - char* key = ::strtok(buffer, " \t=\r\n"); - if (key == NULL) - continue; + SECTION section = SECTION_NONE; + + char buffer[BUFFER_SIZE]; + while (::fgets(buffer, BUFFER_SIZE, fp) != NULL) { + if (buffer[0U] == '#') + continue; + + if (buffer[0U] == '[') { + if (::strncmp(buffer, "[General]", 9U) == 0) + section = SECTION_GENERAL; + else if (::strncmp(buffer, "[Info]", 6U) == 0) + section = SECTION_INFO; + else if (::strncmp(buffer, "[Log]", 5U) == 0) + section = SECTION_LOG; + else if (::strncmp(buffer, "[APRS]", 6U) == 0) + section = SECTION_APRS; + else if (::strncmp(buffer, "[Network]", 9U) == 0) + section = SECTION_NETWORK; + else if (::strncmp(buffer, "[YSF Network]", 13U) == 0) + section = SECTION_YSF_NETWORK; + else if (::strncmp(buffer, "[FCS Network]", 13U) == 0) + section = SECTION_FCS_NETWORK; + else if (::strncmp(buffer, "[GPSD]", 6U) == 0) + section = SECTION_GPSD; + else if (::strncmp(buffer, "[Remote Commands]", 17U) == 0) + section = SECTION_REMOTE_COMMANDS; + else + section = SECTION_NONE; + + continue; + } + + char* key = ::strtok(buffer, " \t=\r\n"); + if (key == NULL) + continue; + + char* value = ::strtok(NULL, "\r\n"); + if (value == NULL) + continue; + + // Remove quotes from the value + size_t len = ::strlen(value); + if (len > 1U && *value == '"' && value[len - 1U] == '"') { + value[len - 1U] = '\0'; + value++; + } else { + char *p; + + // if value is not quoted, remove after # (to make comment) + if ((p = strchr(value, '#')) != NULL) + *p = '\0'; + + // remove trailing tab/space + for (p = value + strlen(value) - 1U; p >= value && (*p == '\t' || *p == ' '); p--) + *p = '\0'; + } - char* value = ::strtok(NULL, "\r\n"); if (section == SECTION_GENERAL) { if (::strcmp(key, "Callsign") == 0) { // Convert the callsign to upper case @@ -214,6 +235,8 @@ bool CConf::read() } else if (section == SECTION_NETWORK) { if (::strcmp(key, "Startup") == 0) m_networkStartup = value; + else if (::strcmp(key, "Options") == 0) + m_networkOptions = value; else if (::strcmp(key, "InactivityTimeout") == 0) m_networkInactivityTimeout = (unsigned int)::atoi(value); else if (::strcmp(key, "Revert") == 0) @@ -379,12 +402,12 @@ unsigned int CConf::getLogFileLevel() const std::string CConf::getLogFilePath() const { - return m_logFilePath; + return m_logFilePath; } std::string CConf::getLogFileRoot() const { - return m_logFileRoot; + return m_logFileRoot; } bool CConf::getAPRSEnabled() const @@ -417,6 +440,11 @@ std::string CConf::getNetworkStartup() const return m_networkStartup; } +std::string CConf::getNetworkOptions() const +{ + return m_networkOptions; +} + unsigned int CConf::getNetworkInactivityTimeout() const { return m_networkInactivityTimeout; @@ -439,7 +467,7 @@ bool CConf::getYSFNetworkEnabled() const unsigned int CConf::getYSFNetworkPort() const { - return m_ysfNetworkPort; + return m_ysfNetworkPort; } std::string CConf::getYSFNetworkHosts() const diff --git a/YSFGateway/Conf.h b/YSFGateway/Conf.h index 7f07a9c..e050599 100644 --- a/YSFGateway/Conf.h +++ b/YSFGateway/Conf.h @@ -67,6 +67,7 @@ public: // The Network section std::string getNetworkStartup() const; + std::string getNetworkOptions() const; unsigned int getNetworkInactivityTimeout() const; bool getNetworkRevert() const; bool getNetworkDebug() const; @@ -134,6 +135,7 @@ private: std::string m_aprsDescription; std::string m_networkStartup; + std::string m_networkOptions; unsigned int m_networkInactivityTimeout; bool m_networkRevert; bool m_networkDebug; diff --git a/YSFGateway/FCSNetwork.cpp b/YSFGateway/FCSNetwork.cpp index 940955c..a01cd6c 100644 --- a/YSFGateway/FCSNetwork.cpp +++ b/YSFGateway/FCSNetwork.cpp @@ -35,6 +35,8 @@ m_debug(debug), m_addr(), m_addrLen(), m_ping(NULL), +m_options(NULL), +m_opt(), m_info(NULL), m_reflector(), m_print(), @@ -53,60 +55,33 @@ m_state(FCS_UNLINKED) ::memset(m_ping + 4U, ' ', 6U); ::memcpy(m_ping + 4U, callsign.c_str(), callsign.size()); ::memset(m_ping + 10U, 0x00U, 15U); + + m_options = new unsigned char[50U]; + ::memcpy(m_options + 0U, "FCSO", 4U); + ::memset(m_options + 4U, ' ', 46U); + ::memcpy(m_options + 4U, callsign.c_str(), callsign.size()); } CFCSNetwork::~CFCSNetwork() { delete[] m_info; delete[] m_ping; + delete[] m_options; } bool CFCSNetwork::open() { - LogMessage("Resolving FCS00x addresses"); + LogMessage("Resolving FCS999 address"); sockaddr_storage addr; unsigned int addrLen; - - CUDPSocket::lookup("fcs001.xreflector.net", FCS_PORT, addr, addrLen); - std::pair entry = std::make_pair(addr, addrLen); - m_addresses["FCS001"] = entry; - - CUDPSocket::lookup("fcs002.xreflector.net", FCS_PORT, addr, addrLen); - entry = std::make_pair(addr, addrLen); - m_addresses["FCS002"] = entry; - - CUDPSocket::lookup("fcs003.xreflector.net", FCS_PORT, addr, addrLen); - entry = std::make_pair(addr, addrLen); - m_addresses["FCS003"] = entry; - - CUDPSocket::lookup("fcs004.xreflector.net", FCS_PORT, addr, addrLen); - entry = std::make_pair(addr, addrLen); - m_addresses["FCS004"] = entry; - - CUDPSocket::lookup("fcs005.xreflector.net", FCS_PORT, addr, addrLen); - entry = std::make_pair(addr, addrLen); - m_addresses["FCS005"] = entry; - - CUDPSocket::lookup("fcs222.xreflector.net", FCS_PORT, addr, addrLen); - entry = std::make_pair(addr, addrLen); - m_addresses["FCS222"] = entry; - - CUDPSocket::lookup("fcs224.xreflector.net", FCS_PORT, addr, addrLen); - entry = std::make_pair(addr, addrLen); - m_addresses["FCS224"] = entry; - - CUDPSocket::lookup("fcs232.xreflector.net", FCS_PORT, addr, addrLen); - entry = std::make_pair(addr, addrLen); - m_addresses["FCS232"] = entry; - - CUDPSocket::lookup("fcs260.xreflector.net", FCS_PORT, addr, addrLen); - entry = std::make_pair(addr, addrLen); - m_addresses["FCS260"] = entry; - - CUDPSocket::lookup("fcs262.xreflector.net", FCS_PORT, addr, addrLen); - entry = std::make_pair(addr, addrLen); - m_addresses["FCS262"] = entry; + if (CUDPSocket::lookup("fcs999.xreflector.net", FCS_PORT, addr, addrLen) != 0) { + LogWarning("Unable to lookup the address for FCS999"); + return false; + } else { + std::pair entry = std::make_pair(addr, addrLen); + m_addresses["FCS999"] = entry; + } LogMessage("Opening FCS network connection"); @@ -131,6 +106,7 @@ void CFCSNetwork::write(const unsigned char* data) unsigned char buffer[130U]; ::memset(buffer + 0U, ' ', 130U); ::memcpy(buffer + 0U, data + 35U, 120U); + ::memcpy(buffer + 120U, data + 34U, 1U); ::memcpy(buffer + 121U, m_reflector.c_str(), 8U); if (m_debug) @@ -143,14 +119,20 @@ bool CFCSNetwork::writeLink(const std::string& reflector) { if (m_state != FCS_LINKED) { std::string name = reflector.substr(0U, 6U); - if (m_addresses.count(name) == 0U) { - LogError("Unknown FCS reflector - %s", name.c_str()); - return false; - } - - std::pair entry = m_addresses[name]; - m_addr = entry.first; - m_addrLen = entry.second; + + if (m_addresses.count(name) == 0U) { + char url[30U]; + ::sprintf(url, "%s.xreflector.net", name.c_str()); + + if (CUDPSocket::lookup(url, FCS_PORT, m_addr, m_addrLen) != 0) { + LogWarning("Unknown FCS reflector - %s", name.c_str()); + return false; + } + } else { + std::pair entry = m_addresses[name]; + m_addr = entry.first; + m_addrLen = entry.second; + } } m_reflector = reflector; @@ -167,6 +149,11 @@ bool CFCSNetwork::writeLink(const std::string& reflector) return true; } +void CFCSNetwork::setOptions(const std::string& options) +{ + m_opt = options; +} + void CFCSNetwork::writeUnlink(unsigned int count) { if (m_state != FCS_LINKED) @@ -212,12 +199,14 @@ void CFCSNetwork::clock(unsigned int ms) LogMessage("Linked to %s", m_print.c_str()); m_state = FCS_LINKED; writeInfo(); + writeOptions(); } if (length == 10 && m_state == FCS_LINKING) { LogMessage("Linked to %s", m_print.c_str()); m_state = FCS_LINKED; writeInfo(); + writeOptions(); } if (length == 7 || length == 10 || length == 130) { @@ -294,3 +283,20 @@ void CFCSNetwork::writePing() m_socket.write(m_ping, 25U, m_addr, m_addrLen); } + +void CFCSNetwork::writeOptions() +{ + if (m_state != FCS_LINKED) + return; + + if (m_opt.size() < 1) + return; + + ::memset(m_options + 14U, 0x20U, 36U); + ::memcpy(m_options + 14U, m_opt.c_str(), m_opt.size()); + + if (m_debug) + CUtils::dump(1U, "FCS Network Options Sent", m_options, 50U); + + m_socket.write(m_options, 50U, m_addr, m_addrLen); +} diff --git a/YSFGateway/FCSNetwork.h b/YSFGateway/FCSNetwork.h index b4b7f05..7dc0c03 100644 --- a/YSFGateway/FCSNetwork.h +++ b/YSFGateway/FCSNetwork.h @@ -41,6 +41,8 @@ public: bool open(); + void setOptions(const std::string& options); + void clearDestination(); void write(const unsigned char* data); @@ -61,6 +63,8 @@ private: sockaddr_storage m_addr; unsigned int m_addrLen; unsigned char* m_ping; + unsigned char* m_options; + std::string m_opt; unsigned char* m_info; std::string m_reflector; std::string m_print; @@ -71,6 +75,7 @@ private: CTimer m_resetTimer; FCS_STATE m_state; + void writeOptions(); void writeInfo(); void writePing(); }; diff --git a/YSFGateway/UDPSocket.cpp b/YSFGateway/UDPSocket.cpp index 659d816..fb4eb16 100644 --- a/YSFGateway/UDPSocket.cpp +++ b/YSFGateway/UDPSocket.cpp @@ -96,47 +96,66 @@ int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_ return 0; } -bool CUDPSocket::match(const sockaddr_storage& addr1, const sockaddr_storage& addr2) +bool CUDPSocket::match(const sockaddr_storage& addr1, const sockaddr_storage& addr2, IPMATCHTYPE type) { if (addr1.ss_family != addr2.ss_family) return false; - switch (addr1.ss_family) { - case AF_INET: - struct sockaddr_in *in_1, *in_2; - in_1 = (struct sockaddr_in*)&addr1; - in_2 = (struct sockaddr_in*)&addr2; - return ((in_1->sin_addr.s_addr == in_2->sin_addr.s_addr) && (in_1->sin_port == in_2->sin_port)); - case AF_INET6: - struct sockaddr_in6 *in6_1, *in6_2; - in6_1 = (struct sockaddr_in6*)&addr1; - in6_2 = (struct sockaddr_in6*)&addr2; - return (IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr) && (in6_1->sin6_port == in6_2->sin6_port)); - default: + if (type == IMT_ADDRESS_AND_PORT) { + switch (addr1.ss_family) { + case AF_INET: + struct sockaddr_in *in_1, *in_2; + in_1 = (struct sockaddr_in*)&addr1; + in_2 = (struct sockaddr_in*)&addr2; + return (in_1->sin_addr.s_addr == in_2->sin_addr.s_addr) && (in_1->sin_port == in_2->sin_port); + case AF_INET6: + struct sockaddr_in6 *in6_1, *in6_2; + in6_1 = (struct sockaddr_in6*)&addr1; + in6_2 = (struct sockaddr_in6*)&addr2; + return IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr) && (in6_1->sin6_port == in6_2->sin6_port); + default: + return false; + } + } else if (type == IMT_ADDRESS_ONLY) { + switch (addr1.ss_family) { + case AF_INET: + struct sockaddr_in *in_1, *in_2; + in_1 = (struct sockaddr_in*)&addr1; + in_2 = (struct sockaddr_in*)&addr2; + return in_1->sin_addr.s_addr == in_2->sin_addr.s_addr; + case AF_INET6: + struct sockaddr_in6 *in6_1, *in6_2; + in6_1 = (struct sockaddr_in6*)&addr1; + in6_2 = (struct sockaddr_in6*)&addr2; + return IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr); + default: + return false; + } + } else { return false; } } -bool CUDPSocket::isnone(const sockaddr_storage& addr) +bool CUDPSocket::isNone(const sockaddr_storage& addr) { struct sockaddr_in *in = (struct sockaddr_in *)&addr; return ((addr.ss_family == AF_INET) && (in->sin_addr.s_addr == htonl(INADDR_NONE))); } -bool CUDPSocket::open() +bool CUDPSocket::open(const sockaddr_storage& address) { - return open(AF_UNSPEC); + return open(address.ss_family); } -bool CUDPSocket::open(const unsigned int af) +bool CUDPSocket::open(unsigned int af) { sockaddr_storage addr; unsigned int addrlen; struct addrinfo hints; ::memset(&hints, 0, sizeof(hints)); - hints.ai_flags = AI_PASSIVE; + hints.ai_flags = AI_PASSIVE; hints.ai_family = af; /* to determine protocol family, call lookup() first. */ @@ -235,6 +254,7 @@ int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storag } address_length = size; + return len; } diff --git a/YSFGateway/UDPSocket.h b/YSFGateway/UDPSocket.h index 386f059..b169641 100644 --- a/YSFGateway/UDPSocket.h +++ b/YSFGateway/UDPSocket.h @@ -35,14 +35,19 @@ #include #endif +enum IPMATCHTYPE { + IMT_ADDRESS_AND_PORT, + IMT_ADDRESS_ONLY +}; + class CUDPSocket { public: CUDPSocket(const std::string& address, unsigned int port = 0U); CUDPSocket(unsigned int port = 0U); ~CUDPSocket(); - bool open(); - bool open(const unsigned int af); + bool open(unsigned int af = AF_UNSPEC); + bool open(const sockaddr_storage& address); int read(unsigned char* buffer, unsigned int length, sockaddr_storage& address, unsigned int &address_length); bool write(const unsigned char* buffer, unsigned int length, const sockaddr_storage& address, unsigned int address_length); @@ -51,8 +56,10 @@ public: static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage& address, unsigned int& address_length); static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage& address, unsigned int& address_length, struct addrinfo& hints); - static bool match(const sockaddr_storage& addr1, const sockaddr_storage& addr2); - static bool isnone(const sockaddr_storage& addr); + + static bool match(const sockaddr_storage& addr1, const sockaddr_storage& addr2, IPMATCHTYPE type = IMT_ADDRESS_AND_PORT); + + static bool isNone(const sockaddr_storage& addr); private: std::string m_address; @@ -61,3 +68,4 @@ private: }; #endif + diff --git a/YSFGateway/Version.h b/YSFGateway/Version.h index ff2325e..facbd36 100644 --- a/YSFGateway/Version.h +++ b/YSFGateway/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20200903"; +const char* VERSION = "20200905"; #endif diff --git a/YSFGateway/YSFGateway.cpp b/YSFGateway/YSFGateway.cpp index 0231835..c89c6fb 100644 --- a/YSFGateway/YSFGateway.cpp +++ b/YSFGateway/YSFGateway.cpp @@ -89,6 +89,7 @@ m_fcsNetwork(NULL), m_linkType(LINK_NONE), m_current(), m_startup(), +m_options(), m_exclude(false), m_inactivityTimer(1000U), m_lostTimer(1000U, 120U), @@ -187,7 +188,10 @@ int CYSFGateway::run() bool debug = m_conf.getNetworkDebug(); sockaddr_storage rptAddr; unsigned int rptAddrLen; - CUDPSocket::lookup(m_conf.getRptAddress(), m_conf.getRptPort(), rptAddr, rptAddrLen); + if (CUDPSocket::lookup(m_conf.getRptAddress(), m_conf.getRptPort(), rptAddr, rptAddrLen) != 0) { + ::fprintf(stderr, "YSFGateway: cannot find the address of the MMDVM Host"); + return 1; + } std::string myAddress = m_conf.getMyAddress(); unsigned int myPort = m_conf.getMyPort(); @@ -256,6 +260,7 @@ int CYSFGateway::run() } m_startup = m_conf.getNetworkStartup(); + m_options = m_conf.getNetworkOptions(); bool revert = m_conf.getNetworkRevert(); bool wiresXCommandPassthrough = m_conf.getWiresXCommandPassthrough(); @@ -805,6 +810,8 @@ void CYSFGateway::startupLinking() m_linkType = LINK_NONE; bool ok = m_fcsNetwork->writeLink(m_startup); + m_fcsNetwork->setOptions(m_options); + if (ok) { LogMessage("Automatic (re-)connection to %s", m_startup.c_str()); @@ -825,6 +832,8 @@ void CYSFGateway::startupLinking() if (reflector != NULL) { LogMessage("Automatic (re-)connection to %5.5s - \"%s\"", reflector->m_id.c_str(), reflector->m_name.c_str()); + m_ysfNetwork->setOptions(m_options); + m_wiresX->setReflector(reflector); m_ysfNetwork->setDestination(reflector->m_name, reflector->m_addr, reflector->m_addrLen); diff --git a/YSFGateway/YSFGateway.h b/YSFGateway/YSFGateway.h index b74db45..c0d75ce 100644 --- a/YSFGateway/YSFGateway.h +++ b/YSFGateway/YSFGateway.h @@ -59,6 +59,7 @@ private: LINK_TYPE m_linkType; std::string m_current; std::string m_startup; + std::string m_options; bool m_exclude; CTimer m_inactivityTimer; CTimer m_lostTimer; diff --git a/YSFGateway/YSFGateway.ini b/YSFGateway/YSFGateway.ini index 104909b..c3376c8 100644 --- a/YSFGateway/YSFGateway.ini +++ b/YSFGateway/YSFGateway.ini @@ -39,6 +39,8 @@ Suffix=Y [Network] # Startup=FCS00120 # Startup=Alabama-Link +# book DG-ID for Reflector +# Options=20;21; InactivityTimeout=10 Revert=0 Debug=0 diff --git a/YSFGateway/YSFNetwork.cpp b/YSFGateway/YSFNetwork.cpp index 7a9bccb..52453ae 100644 --- a/YSFGateway/YSFNetwork.cpp +++ b/YSFGateway/YSFNetwork.cpp @@ -33,6 +33,7 @@ m_debug(debug), m_addr(), m_addrLen(0U), m_poll(NULL), +m_options(NULL), m_unlink(NULL), m_buffer(1000U, "YSF Network Buffer"), m_pollTimer(1000U, 5U), @@ -45,12 +46,16 @@ m_linked(false) m_unlink = new unsigned char[14U]; ::memcpy(m_unlink + 0U, "YSFU", 4U); + m_options = new unsigned char[50U]; + ::memcpy(m_options + 0U, "YSFO", 4U); + std::string node = callsign; node.resize(YSF_CALLSIGN_LENGTH, ' '); for (unsigned int i = 0U; i < YSF_CALLSIGN_LENGTH; i++) { m_poll[i + 4U] = node.at(i); m_unlink[i + 4U] = node.at(i); + m_options[i + 4U] = node.at(i); } } @@ -60,9 +65,12 @@ m_debug(debug), m_addr(), m_addrLen(0U), m_poll(NULL), +m_options(NULL), m_unlink(NULL), m_buffer(1000U, "YSF Network Buffer"), -m_pollTimer(1000U, 5U) +m_pollTimer(1000U, 5U), +m_name(), +m_linked(false) { m_poll = new unsigned char[14U]; ::memcpy(m_poll + 0U, "YSFP", 4U); @@ -70,12 +78,16 @@ m_pollTimer(1000U, 5U) m_unlink = new unsigned char[14U]; ::memcpy(m_unlink + 0U, "YSFU", 4U); + m_options = new unsigned char[50U]; + ::memcpy(m_options + 0U, "YSFO", 4U); + std::string node = callsign; node.resize(YSF_CALLSIGN_LENGTH, ' '); for (unsigned int i = 0U; i < YSF_CALLSIGN_LENGTH; i++) { m_poll[i + 4U] = node.at(i); m_unlink[i + 4U] = node.at(i); + m_options[i + 4U] = node.at(i); } } @@ -129,6 +141,22 @@ void CYSFNetwork::writePoll(unsigned int count) for (unsigned int i = 0U; i < count; i++) m_socket.write(m_poll, 14U, m_addr, m_addrLen); + + if (m_options != NULL) + m_socket.write(m_options, 50U, m_addr, m_addrLen); +} + +void CYSFNetwork::setOptions(const std::string& options) +{ + std::string opt = options; + + if (opt.size() < 1) + return; + + opt.resize(50, ' '); + + for (unsigned int i = 0U; i < (50 - 4 - YSF_CALLSIGN_LENGTH); i++) + m_options[i + 4U + YSF_CALLSIGN_LENGTH] = opt.at(i); } void CYSFNetwork::writeUnlink(unsigned int count) @@ -170,6 +198,9 @@ void CYSFNetwork::clock(unsigned int ms) LogMessage("Linked to %s", m_name.c_str()); m_linked = true; + + if (m_options != NULL) + m_socket.write(m_options, 50U, m_addr, m_addrLen); } if (m_debug) diff --git a/YSFGateway/YSFNetwork.h b/YSFGateway/YSFNetwork.h index 1125c72..3411aa8 100644 --- a/YSFGateway/YSFNetwork.h +++ b/YSFGateway/YSFNetwork.h @@ -41,6 +41,7 @@ public: void write(const unsigned char* data); void writePoll(unsigned int count = 1U); + void setOptions(const std::string& options = NULL); void writeUnlink(unsigned int count = 1U); unsigned int read(unsigned char* data); @@ -55,6 +56,7 @@ private: sockaddr_storage m_addr; unsigned int m_addrLen; unsigned char* m_poll; + unsigned char* m_options; unsigned char* m_unlink; CRingBuffer m_buffer; CTimer m_pollTimer; diff --git a/YSFGateway/YSFReflectors.cpp b/YSFGateway/YSFReflectors.cpp index f4b5198..8345d01 100644 --- a/YSFGateway/YSFReflectors.cpp +++ b/YSFGateway/YSFReflectors.cpp @@ -1,5 +1,5 @@ /* -* Copyright (C) 2016-2019 by Jonathan Naylor G4KLX +* Copyright (C) 2016-2020 by Jonathan Naylor G4KLX * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -130,21 +130,27 @@ bool CYSFReflectors::load() std::string host = std::string(p4); unsigned int port = (unsigned int)::atoi(p5); - CYSFReflector* refl = new CYSFReflector; - - CUDPSocket::lookup(host, port, refl->m_addr, refl->m_addrLen); - - refl->m_id = std::string(p1); - refl->m_name = std::string(p2); - refl->m_desc = std::string(p3); - refl->m_count = std::string(p6); - refl->m_type = YT_YSF; - refl->m_wiresX = (refl->m_name.compare(0, 3, "XLX") == 0); - - refl->m_name.resize(16U, ' '); - refl->m_desc.resize(14U, ' '); - - m_newReflectors.push_back(refl); + sockaddr_storage addr; + unsigned int addrLen; + if (CUDPSocket::lookup(host, port, addr, addrLen) == 0) { + CYSFReflector* refl = new CYSFReflector; + + refl->m_id = std::string(p1); + refl->m_name = std::string(p2); + refl->m_desc = std::string(p3); + refl->m_addr = addr; + refl->m_addrLen = addrLen; + refl->m_count = std::string(p6); + refl->m_type = YT_YSF; + refl->m_wiresX = (refl->m_name.compare(0, 3, "XLX") == 0); + + refl->m_name.resize(16U, ' '); + refl->m_desc.resize(14U, ' '); + + m_newReflectors.push_back(refl); + } else { + LogWarning("Unable to resolve the address of YSF reflector - %s", p2); + } } } @@ -156,66 +162,94 @@ bool CYSFReflectors::load() // Add the Parrot entry if (m_parrotPort > 0U) { - CYSFReflector* refl = new CYSFReflector; - refl->m_id = "00001"; - refl->m_name = "ZZ Parrot "; - refl->m_desc = "Parrot "; - CUDPSocket::lookup(m_parrotAddress, m_parrotPort, refl->m_addr, refl->m_addrLen); - refl->m_count = "000"; - refl->m_type = YT_YSF; - refl->m_wiresX = false; - - m_newReflectors.push_back(refl); - - LogInfo("Loaded YSF parrot"); + sockaddr_storage addr; + unsigned int addrLen; + if (CUDPSocket::lookup(m_parrotAddress, m_parrotPort, addr, addrLen) == 0) { + CYSFReflector* refl = new CYSFReflector; + refl->m_id = "00001"; + refl->m_name = "ZZ Parrot "; + refl->m_desc = "Parrot "; + refl->m_addr = addr; + refl->m_addrLen = addrLen; + refl->m_count = "000"; + refl->m_type = YT_YSF; + refl->m_wiresX = false; + + m_newReflectors.push_back(refl); + + LogInfo("Loaded YSF parrot"); + } else { + LogWarning("Unable to resolve the address of the YSF Parrot"); + } } // Add the YSF2DMR entry if (m_YSF2DMRPort > 0U) { - CYSFReflector* refl = new CYSFReflector; - refl->m_id = "00002"; - refl->m_name = "YSF2DMR "; - refl->m_desc = "Link YSF2DMR "; - CUDPSocket::lookup(m_YSF2DMRAddress, m_YSF2DMRPort, refl->m_addr, refl->m_addrLen); - refl->m_count = "000"; - refl->m_type = YT_YSF; - refl->m_wiresX = true; - - m_newReflectors.push_back(refl); - - LogInfo("Loaded YSF2DMR"); + sockaddr_storage addr; + unsigned int addrLen; + if (CUDPSocket::lookup(m_YSF2DMRAddress, m_YSF2DMRPort, addr, addrLen) == 0) { + CYSFReflector* refl = new CYSFReflector; + refl->m_id = "00002"; + refl->m_name = "YSF2DMR "; + refl->m_desc = "Link YSF2DMR "; + refl->m_addr = addr; + refl->m_addrLen = addrLen; + refl->m_count = "000"; + refl->m_type = YT_YSF; + refl->m_wiresX = true; + + m_newReflectors.push_back(refl); + + LogInfo("Loaded YSF2DMR"); + } else { + LogWarning("Unable to resolve the address of YSF2DMR"); + } } // Add the YSF2NXDN entry if (m_YSF2NXDNPort > 0U) { - CYSFReflector* refl = new CYSFReflector; - refl->m_id = "00003"; - refl->m_name = "YSF2NXDN "; - refl->m_desc = "Link YSF2NXDN "; - CUDPSocket::lookup(m_YSF2NXDNAddress, m_YSF2NXDNPort, refl->m_addr, refl->m_addrLen); - refl->m_count = "000"; - refl->m_type = YT_YSF; - refl->m_wiresX = true; - - m_newReflectors.push_back(refl); - - LogInfo("Loaded YSF2NXDN"); + sockaddr_storage addr; + unsigned int addrLen; + if (CUDPSocket::lookup(m_YSF2NXDNAddress, m_YSF2NXDNPort, addr, addrLen) == 0) { + CYSFReflector* refl = new CYSFReflector; + refl->m_id = "00003"; + refl->m_name = "YSF2NXDN "; + refl->m_desc = "Link YSF2NXDN "; + refl->m_addr = addr; + refl->m_addrLen = addrLen; + refl->m_count = "000"; + refl->m_type = YT_YSF; + refl->m_wiresX = true; + + m_newReflectors.push_back(refl); + + LogInfo("Loaded YSF2NXDN"); + } else { + LogWarning("Unable to resolve the address of YSF2NXDN"); + } } // Add the YSF2P25 entry if (m_YSF2P25Port > 0U) { - CYSFReflector* refl = new CYSFReflector; - refl->m_id = "00004"; - refl->m_name = "YSF2P25 "; - refl->m_desc = "Link YSF2P25 "; - CUDPSocket::lookup(m_YSF2P25Address, m_YSF2P25Port, refl->m_addr, refl->m_addrLen); - refl->m_count = "000"; - refl->m_type = YT_YSF; - refl->m_wiresX = true; - - m_newReflectors.push_back(refl); - - LogInfo("Loaded YSF2P25"); + sockaddr_storage addr; + unsigned int addrLen; + if (CUDPSocket::lookup(m_YSF2P25Address, m_YSF2P25Port, addr, addrLen) == 0) { + CYSFReflector* refl = new CYSFReflector; + refl->m_id = "00004"; + refl->m_name = "YSF2P25 "; + refl->m_desc = "Link YSF2P25 "; + refl->m_addr = addr; + refl->m_addrLen = addrLen; + refl->m_count = "000"; + refl->m_type = YT_YSF; + refl->m_wiresX = true; + + m_newReflectors.push_back(refl); + + LogInfo("Loaded YSF2P25"); + } else { + LogWarning("Unable to resolve the address of YSF2P25"); + } } unsigned int id = 10U; diff --git a/YSFParrot/UDPSocket.cpp b/YSFParrot/UDPSocket.cpp index aa1770c..3e2ac45 100644 --- a/YSFParrot/UDPSocket.cpp +++ b/YSFParrot/UDPSocket.cpp @@ -95,40 +95,56 @@ int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_ return 0; } -bool CUDPSocket::match(const sockaddr_storage &addr1, const sockaddr_storage &addr2) +bool CUDPSocket::match(const sockaddr_storage& addr1, const sockaddr_storage& addr2, IPMATCHTYPE type) { if (addr1.ss_family != addr2.ss_family) return false; - switch (addr1.ss_family) { - case AF_INET: - struct sockaddr_in *in_1, *in_2; - in_1 = (struct sockaddr_in *)&addr1; - in_2 = (struct sockaddr_in *)&addr2; - return ( (in_1->sin_addr.s_addr == in_2->sin_addr.s_addr) && - (in_1->sin_port == in_2->sin_port) ); - case AF_INET6: - struct sockaddr_in6 *in6_1, *in6_2; - in6_1 = (struct sockaddr_in6 *)&addr1; - in6_2 = (struct sockaddr_in6 *)&addr2; - return ( IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr) && - (in6_1->sin6_port == in6_2->sin6_port) ); - default: + if (type == IMT_ADDRESS_AND_PORT) { + switch (addr1.ss_family) { + case AF_INET: + struct sockaddr_in *in_1, *in_2; + in_1 = (struct sockaddr_in*)&addr1; + in_2 = (struct sockaddr_in*)&addr2; + return (in_1->sin_addr.s_addr == in_2->sin_addr.s_addr) && (in_1->sin_port == in_2->sin_port); + case AF_INET6: + struct sockaddr_in6 *in6_1, *in6_2; + in6_1 = (struct sockaddr_in6*)&addr1; + in6_2 = (struct sockaddr_in6*)&addr2; + return IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr) && (in6_1->sin6_port == in6_2->sin6_port); + default: + return false; + } + } else if (type == IMT_ADDRESS_ONLY) { + switch (addr1.ss_family) { + case AF_INET: + struct sockaddr_in *in_1, *in_2; + in_1 = (struct sockaddr_in*)&addr1; + in_2 = (struct sockaddr_in*)&addr2; + return in_1->sin_addr.s_addr == in_2->sin_addr.s_addr; + case AF_INET6: + struct sockaddr_in6 *in6_1, *in6_2; + in6_1 = (struct sockaddr_in6*)&addr1; + in6_2 = (struct sockaddr_in6*)&addr2; + return IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr); + default: + return false; + } + } else { return false; } } -bool CUDPSocket::isnone(const sockaddr_storage &addr) +bool CUDPSocket::isNone(const sockaddr_storage& addr) { struct sockaddr_in *in = (struct sockaddr_in *)&addr; - return ( (addr.ss_family == AF_INET) && - (in->sin_addr.s_addr == htonl(INADDR_NONE)) ); + return ((addr.ss_family == AF_INET) && (in->sin_addr.s_addr == htonl(INADDR_NONE))); } -bool CUDPSocket::open() +bool CUDPSocket::open(const sockaddr_storage& address) { - return open(AF_UNSPEC); + return open(address.ss_family); } bool CUDPSocket::open(const unsigned int af) diff --git a/YSFParrot/UDPSocket.h b/YSFParrot/UDPSocket.h index 46b2370..8dac4d0 100644 --- a/YSFParrot/UDPSocket.h +++ b/YSFParrot/UDPSocket.h @@ -35,14 +35,19 @@ #include #endif +enum IPMATCHTYPE { + IMT_ADDRESS_AND_PORT, + IMT_ADDRESS_ONLY +}; + class CUDPSocket { public: CUDPSocket(const std::string& address, unsigned int port = 0U); CUDPSocket(unsigned int port = 0U); ~CUDPSocket(); - bool open(); - bool open(const unsigned int af); + bool open(const sockaddr_storage& addr); + bool open(const unsigned int af = AF_UNSPEC); int read(unsigned char* buffer, unsigned int length, sockaddr_storage& address, unsigned int &address_length); bool write(const unsigned char* buffer, unsigned int length, const sockaddr_storage& address, unsigned int address_length); @@ -51,8 +56,11 @@ public: static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage &address, unsigned int &address_length); static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage &address, unsigned int &address_length, struct addrinfo &hints); - static bool match(const sockaddr_storage &addr1, const sockaddr_storage &addr2); - static bool isnone(const sockaddr_storage &addr); + + static bool match(const sockaddr_storage& addr1, const sockaddr_storage& addr2, IPMATCHTYPE type = IMT_ADDRESS_AND_PORT); + + static bool isNone(const sockaddr_storage& addr); + private: std::string m_address; diff --git a/YSFParrot/Version.h b/YSFParrot/Version.h index 601aa02..cf9d8b9 100644 --- a/YSFParrot/Version.h +++ b/YSFParrot/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20200903"; +const char* VERSION = "20200905"; #endif diff --git a/YSFReflector/Conf.cpp b/YSFReflector/Conf.cpp index a4e1f21..277fed1 100644 --- a/YSFReflector/Conf.cpp +++ b/YSFReflector/Conf.cpp @@ -88,6 +88,26 @@ bool CConf::read() continue; char* value = ::strtok(NULL, "\r\n"); + if (value == NULL) + continue; + + // Remove quotes from the value + size_t len = ::strlen(value); + if (len > 1U && *value == '"' && value[len - 1U] == '"') { + value[len - 1U] = '\0'; + value++; + } else { + char *p; + + // if value is not quoted, remove after # (to make comment) + if ((p = strchr(value, '#')) != NULL) + *p = '\0'; + + // remove trailing tab/space + for (p = value + strlen(value) - 1U; p >= value && (*p == '\t' || *p == ' '); p--) + *p = '\0'; + } + if (section == SECTION_GENERAL) { if (::strcmp(key, "Daemon") == 0) m_daemon = ::atoi(value) == 1; @@ -152,12 +172,12 @@ unsigned int CConf::getLogFileLevel() const std::string CConf::getLogFilePath() const { - return m_logFilePath; + return m_logFilePath; } std::string CConf::getLogFileRoot() const { - return m_logFileRoot; + return m_logFileRoot; } unsigned int CConf::getNetworkPort() const diff --git a/YSFReflector/UDPSocket.cpp b/YSFReflector/UDPSocket.cpp index 659d816..fb4eb16 100644 --- a/YSFReflector/UDPSocket.cpp +++ b/YSFReflector/UDPSocket.cpp @@ -96,47 +96,66 @@ int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_ return 0; } -bool CUDPSocket::match(const sockaddr_storage& addr1, const sockaddr_storage& addr2) +bool CUDPSocket::match(const sockaddr_storage& addr1, const sockaddr_storage& addr2, IPMATCHTYPE type) { if (addr1.ss_family != addr2.ss_family) return false; - switch (addr1.ss_family) { - case AF_INET: - struct sockaddr_in *in_1, *in_2; - in_1 = (struct sockaddr_in*)&addr1; - in_2 = (struct sockaddr_in*)&addr2; - return ((in_1->sin_addr.s_addr == in_2->sin_addr.s_addr) && (in_1->sin_port == in_2->sin_port)); - case AF_INET6: - struct sockaddr_in6 *in6_1, *in6_2; - in6_1 = (struct sockaddr_in6*)&addr1; - in6_2 = (struct sockaddr_in6*)&addr2; - return (IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr) && (in6_1->sin6_port == in6_2->sin6_port)); - default: + if (type == IMT_ADDRESS_AND_PORT) { + switch (addr1.ss_family) { + case AF_INET: + struct sockaddr_in *in_1, *in_2; + in_1 = (struct sockaddr_in*)&addr1; + in_2 = (struct sockaddr_in*)&addr2; + return (in_1->sin_addr.s_addr == in_2->sin_addr.s_addr) && (in_1->sin_port == in_2->sin_port); + case AF_INET6: + struct sockaddr_in6 *in6_1, *in6_2; + in6_1 = (struct sockaddr_in6*)&addr1; + in6_2 = (struct sockaddr_in6*)&addr2; + return IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr) && (in6_1->sin6_port == in6_2->sin6_port); + default: + return false; + } + } else if (type == IMT_ADDRESS_ONLY) { + switch (addr1.ss_family) { + case AF_INET: + struct sockaddr_in *in_1, *in_2; + in_1 = (struct sockaddr_in*)&addr1; + in_2 = (struct sockaddr_in*)&addr2; + return in_1->sin_addr.s_addr == in_2->sin_addr.s_addr; + case AF_INET6: + struct sockaddr_in6 *in6_1, *in6_2; + in6_1 = (struct sockaddr_in6*)&addr1; + in6_2 = (struct sockaddr_in6*)&addr2; + return IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr); + default: + return false; + } + } else { return false; } } -bool CUDPSocket::isnone(const sockaddr_storage& addr) +bool CUDPSocket::isNone(const sockaddr_storage& addr) { struct sockaddr_in *in = (struct sockaddr_in *)&addr; return ((addr.ss_family == AF_INET) && (in->sin_addr.s_addr == htonl(INADDR_NONE))); } -bool CUDPSocket::open() +bool CUDPSocket::open(const sockaddr_storage& address) { - return open(AF_UNSPEC); + return open(address.ss_family); } -bool CUDPSocket::open(const unsigned int af) +bool CUDPSocket::open(unsigned int af) { sockaddr_storage addr; unsigned int addrlen; struct addrinfo hints; ::memset(&hints, 0, sizeof(hints)); - hints.ai_flags = AI_PASSIVE; + hints.ai_flags = AI_PASSIVE; hints.ai_family = af; /* to determine protocol family, call lookup() first. */ @@ -235,6 +254,7 @@ int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storag } address_length = size; + return len; } diff --git a/YSFReflector/UDPSocket.h b/YSFReflector/UDPSocket.h index 386f059..b169641 100644 --- a/YSFReflector/UDPSocket.h +++ b/YSFReflector/UDPSocket.h @@ -35,14 +35,19 @@ #include #endif +enum IPMATCHTYPE { + IMT_ADDRESS_AND_PORT, + IMT_ADDRESS_ONLY +}; + class CUDPSocket { public: CUDPSocket(const std::string& address, unsigned int port = 0U); CUDPSocket(unsigned int port = 0U); ~CUDPSocket(); - bool open(); - bool open(const unsigned int af); + bool open(unsigned int af = AF_UNSPEC); + bool open(const sockaddr_storage& address); int read(unsigned char* buffer, unsigned int length, sockaddr_storage& address, unsigned int &address_length); bool write(const unsigned char* buffer, unsigned int length, const sockaddr_storage& address, unsigned int address_length); @@ -51,8 +56,10 @@ public: static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage& address, unsigned int& address_length); static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage& address, unsigned int& address_length, struct addrinfo& hints); - static bool match(const sockaddr_storage& addr1, const sockaddr_storage& addr2); - static bool isnone(const sockaddr_storage& addr); + + static bool match(const sockaddr_storage& addr1, const sockaddr_storage& addr2, IPMATCHTYPE type = IMT_ADDRESS_AND_PORT); + + static bool isNone(const sockaddr_storage& addr); private: std::string m_address; @@ -61,3 +68,4 @@ private: }; #endif + diff --git a/YSFReflector/Version.h b/YSFReflector/Version.h index 601aa02..cf9d8b9 100644 --- a/YSFReflector/Version.h +++ b/YSFReflector/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20200903"; +const char* VERSION = "20200905"; #endif