From f8b0accafb6d88046fd41ea64ff89173b979a2a8 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 29 Sep 2016 19:56:27 +0100 Subject: [PATCH] Alter format of hosts file ready for network reloading. --- YSFGateway/Conf.cpp | 14 +- YSFGateway/Conf.h | 4 +- YSFGateway/Hosts.cpp | 79 ---------- YSFGateway/Hosts.h | 45 ------ YSFGateway/Makefile | 2 +- YSFGateway/Makefile.Solaris | 2 +- YSFGateway/Reflectors.cpp | 129 ++++++---------- YSFGateway/Reflectors.h | 10 +- YSFGateway/WiresX.cpp | 5 +- YSFGateway/WiresX.h | 2 +- YSFGateway/YSFGateway.cpp | 4 +- YSFGateway/YSFGateway.ini | 2 +- YSFGateway/YSFGateway.vcxproj | 2 - YSFGateway/YSFGateway.vcxproj.filters | 6 - YSFGateway/YSFHosts.txt | 210 +++++--------------------- 15 files changed, 106 insertions(+), 410 deletions(-) delete mode 100644 YSFGateway/Hosts.cpp delete mode 100644 YSFGateway/Hosts.h diff --git a/YSFGateway/Conf.cpp b/YSFGateway/Conf.cpp index 0c7fd3f..aff8c4c 100644 --- a/YSFGateway/Conf.cpp +++ b/YSFGateway/Conf.cpp @@ -62,8 +62,8 @@ m_aprsPort(0U), m_aprsPassword(), m_networkEnabled(false), m_networkDataPort(0U), -m_networkStatusPort(0U), m_networkHosts(), +m_networkReloadTime(0U), m_networkStartup(), m_networkDebug(false) { @@ -171,10 +171,10 @@ bool CConf::read() m_networkEnabled = ::atoi(value) == 1; else if (::strcmp(key, "DataPort") == 0) m_networkDataPort = (unsigned int)::atoi(value); - else if (::strcmp(key, "StatusPort") == 0) - m_networkStatusPort = (unsigned int)::atoi(value); else if (::strcmp(key, "Hosts") == 0) m_networkHosts = value; + else if (::strcmp(key, "ReloadTime") == 0) + m_networkReloadTime = (unsigned int)::atoi(value); else if (::strcmp(key, "Startup") == 0) m_networkStartup = value; else if (::strcmp(key, "Debug") == 0) @@ -312,14 +312,14 @@ unsigned int CConf::getNetworkDataPort() const return m_networkDataPort; } -unsigned int CConf::getNetworkStatusPort() const +std::string CConf::getNetworkHosts() const { - return m_networkStatusPort; + return m_networkHosts; } -std::string CConf::getNetworkHosts() const +unsigned int CConf::getNetworkReloadTime() const { - return m_networkHosts; + return m_networkReloadTime; } std::string CConf::getNetworkStartup() const diff --git a/YSFGateway/Conf.h b/YSFGateway/Conf.h index 24d0349..b8a70f7 100644 --- a/YSFGateway/Conf.h +++ b/YSFGateway/Conf.h @@ -64,8 +64,8 @@ public: // The Network section bool getNetworkEnabled() const; unsigned int getNetworkDataPort() const; - unsigned int getNetworkStatusPort() const; std::string getNetworkHosts() const; + unsigned int getNetworkReloadTime() const; std::string getNetworkStartup() const; bool getNetworkDebug() const; @@ -100,8 +100,8 @@ private: bool m_networkEnabled; unsigned int m_networkDataPort; - unsigned int m_networkStatusPort; std::string m_networkHosts; + unsigned int m_networkReloadTime; std::string m_networkStartup; bool m_networkDebug; }; diff --git a/YSFGateway/Hosts.cpp b/YSFGateway/Hosts.cpp deleted file mode 100644 index a55faed..0000000 --- a/YSFGateway/Hosts.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* -* Copyright (C) 2016 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 -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "Hosts.h" -#include "Log.h" - -#include -#include -#include -#include - -CHosts::CHosts(const std::string& filename) : -m_filename(filename), -m_hosts() -{ -} - -CHosts::~CHosts() -{ -} - -bool CHosts::read() -{ - FILE* fp = ::fopen(m_filename.c_str(), "rt"); - if (fp == NULL) { - LogWarning("Cannot open the YSF Hosts file - %s", m_filename.c_str()); - return false; - } - - char buffer[100U]; - while (::fgets(buffer, 100U, fp) != NULL) { - if (buffer[0U] == '#') - continue; - - char* p1 = ::strtok(buffer, " \t\r\n"); - char* p2 = ::strtok(NULL, " \t\r\n"); - - if (p1 != NULL && p2 != NULL) { - std::string address = std::string(p1); - unsigned int port = (unsigned int)::atoi(p2); - - CYSFHost* host = new CYSFHost; - host->m_address = address; - host->m_port = port; - - m_hosts.push_back(host); - } - } - - ::fclose(fp); - - size_t size = m_hosts.size(); - if (size == 0U) - return false; - - LogInfo("Loaded %u YSF reflectors", size); - - return true; -} - -std::vector& CHosts::list() -{ - return m_hosts; -} diff --git a/YSFGateway/Hosts.h b/YSFGateway/Hosts.h deleted file mode 100644 index 2d76c14..0000000 --- a/YSFGateway/Hosts.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -* Copyright (C) 2016 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 -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifndef Hosts_H -#define Hosts_H - -#include -#include - -class CYSFHost { -public: - std::string m_address; - unsigned int m_port; -}; - -class CHosts { -public: - CHosts(const std::string& filename); - ~CHosts(); - - bool read(); - - std::vector& list(); - -private: - std::string m_filename; - std::vector m_hosts; -}; - -#endif diff --git a/YSFGateway/Makefile b/YSFGateway/Makefile index 50aca69..2c25ec8 100644 --- a/YSFGateway/Makefile +++ b/YSFGateway/Makefile @@ -4,7 +4,7 @@ CFLAGS = -g -O3 -Wall -std=c++0x -pthread LIBS = -lm -lpthread LDFLAGS = -g -OBJECTS = APRSWriterThread.o APRSWriter.o Conf.o CRC.o Golay24128.o GPS.o Hosts.o Log.o Network.o Reflectors.o StopWatch.o Sync.o TCPSocket.o Thread.o Timer.o \ +OBJECTS = APRSWriterThread.o APRSWriter.o Conf.o CRC.o Golay24128.o GPS.o Log.o Network.o Reflectors.o StopWatch.o Sync.o TCPSocket.o Thread.o Timer.o \ UDPSocket.o Utils.o WiresX.o YSFConvolution.o YSFFICH.o YSFGateway.o YSFPayload.o all: YSFGateway diff --git a/YSFGateway/Makefile.Solaris b/YSFGateway/Makefile.Solaris index 4862eec..b458fd6 100644 --- a/YSFGateway/Makefile.Solaris +++ b/YSFGateway/Makefile.Solaris @@ -4,7 +4,7 @@ CFLAGS = -g -O3 -Wall -std=c++0x -pthread LIBS = -lm -lpthread -lsocket LDFLAGS = -g -OBJECTS = APRSWriterThread.o APRSWriter.o Conf.o CRC.o Golay24128.o GPS.o Hosts.o Log.o Network.o Reflectors.o StopWatch.o Sync.o TCPSocket.o Thread.o Timer.o \ +OBJECTS = APRSWriterThread.o APRSWriter.o Conf.o CRC.o Golay24128.o GPS.o Log.o Network.o Reflectors.o StopWatch.o Sync.o TCPSocket.o Thread.o Timer.o \ UDPSocket.o Utils.o WiresX.o YSFConvolution.o YSFFICH.o YSFGateway.o YSFPayload.o all: YSFGateway diff --git a/YSFGateway/Reflectors.cpp b/YSFGateway/Reflectors.cpp index 4d8f582..f32a274 100644 --- a/YSFGateway/Reflectors.cpp +++ b/YSFGateway/Reflectors.cpp @@ -17,7 +17,6 @@ */ #include "Reflectors.h" -#include "Hosts.h" #include "Log.h" #include @@ -27,16 +26,15 @@ #include #include -CReflectors::CReflectors(const std::string& hostsFile, unsigned int statusPort) : +CReflectors::CReflectors(const std::string& hostsFile, unsigned int reloadTime) : m_hostsFile(hostsFile), -m_socket(statusPort), m_reflectors(), -m_it(), m_current(), m_search(), -m_timer(1000U, 30U) +m_timer(1000U, reloadTime * 60U) { - assert(statusPort > 0U); + if (reloadTime > 0U) + m_timer.start(); } CReflectors::~CReflectors() @@ -47,43 +45,53 @@ CReflectors::~CReflectors() bool CReflectors::load() { - bool ret = m_socket.open(); - if (!ret) - return false; - - CHosts hosts(m_hostsFile); - ret = hosts.read(); - if (!ret) + FILE* fp = ::fopen(m_hostsFile.c_str(), "rt"); + if (fp == NULL) { + LogWarning("Cannot open the YSF Hosts file - %s", m_hostsFile.c_str()); return false; + } - std::vector& hostList = hosts.list(); + // Clear out the old reflector list + for (std::vector::iterator it = m_reflectors.begin(); it != m_reflectors.end(); ++it) + delete *it; - for (std::vector::const_iterator it = hostList.begin(); it != hostList.end(); ++it) { - in_addr address = CUDPSocket::lookup((*it)->m_address); + char buffer[100U]; + while (::fgets(buffer, 100U, fp) != NULL) { + if (buffer[0U] == '#') + continue; - if (address.s_addr != INADDR_NONE) { - CYSFReflector* reflector = new CYSFReflector; - reflector->m_address = address; - reflector->m_port = (*it)->m_port; - m_reflectors.push_back(reflector); + char* p1 = ::strtok(buffer, " \t\r\n"); + char* p2 = ::strtok(NULL, " \t\r\n"); + char* p3 = ::strtok(NULL, " \t\r\n"); + char* p4 = ::strtok(NULL, " \t\r\n"); + char* p5 = ::strtok(NULL, " \t\r\n"); + char* p6 = ::strtok(NULL, " \t\r\n"); + + if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL && p6 != NULL) { + std::string host = std::string(p4); + + in_addr address = CUDPSocket::lookup(host); + if (address.s_addr != INADDR_NONE) { + CYSFReflector* refl = new CYSFReflector; + refl->m_id = std::string(p1); + refl->m_name = std::string(p2); + refl->m_desc = std::string(p3); + refl->m_address = address; + refl->m_port = (unsigned int)::atoi(p5); + refl->m_count = std::string(p6);; + + m_reflectors.push_back(refl); + } } } - m_it = m_reflectors.begin(); - - // Make the polling time based on the number of reflectors within limits - unsigned int nReflectors = m_reflectors.size(); - if (nReflectors > 0U) { - unsigned int t = 600U / nReflectors; - if (t > 30U) - t = 30U; - else if (t < 15U) - t = 15U; + ::fclose(fp); - m_timer.setTimeout(t); - } + size_t size = m_reflectors.size(); + if (size == 0U) + return false; - m_timer.start(); + LogInfo("Loaded %u YSF reflectors", size); return true; } @@ -121,10 +129,8 @@ std::vector& CReflectors::current() { m_current.clear(); - for (std::vector::iterator it = m_reflectors.begin(); it != m_reflectors.end(); ++it) { - if ((*it)->m_seen) - m_current.push_back(*it); - } + for (std::vector::iterator it = m_reflectors.begin(); it != m_reflectors.end(); ++it) + m_current.push_back(*it); std::sort(m_current.begin(), m_current.end(), refComparison); @@ -142,9 +148,6 @@ std::vector& CReflectors::search(const std::string& name) unsigned int len = trimmed.size(); for (std::vector::iterator it = m_reflectors.begin(); it != m_reflectors.end(); ++it) { - if (!(*it)->m_seen) - continue; - std::string reflector = (*it)->m_name; reflector.erase(std::find_if(reflector.rbegin(), reflector.rend(), std::not1(std::ptr_fun(std::isspace))).base(), reflector.end()); std::transform(reflector.begin(), reflector.end(), reflector.begin(), ::toupper); @@ -160,50 +163,10 @@ std::vector& CReflectors::search(const std::string& name) void CReflectors::clock(unsigned int ms) { - // Nothing to do, avoid crashes - if (m_reflectors.size() == 0U) - return; - m_timer.clock(ms); - if (m_timer.isRunning() && m_timer.hasExpired()) { - m_socket.write((unsigned char*)"YSFS", 4U, (*m_it)->m_address, (*m_it)->m_port); - - ++m_it; - if (m_it == m_reflectors.end()) - m_it = m_reflectors.begin(); + if (m_timer.isRunning() && m_timer.hasExpired()) { + load(); m_timer.start(); } - - in_addr address; - unsigned int port; - unsigned char buffer[200U]; - int ret = m_socket.read(buffer, 200U, address, port); - - if (ret > 0) { - if (::memcmp(buffer + 0U, "YSFS", 4U) == 0) { - buffer[42U] = 0x00U; - - std::string id = std::string((char*)(buffer + 4U), 5U); - std::string name = std::string((char*)(buffer + 9U), 16U); - std::string desc = std::string((char*)(buffer + 25U), 14U); - std::string cnt = std::string((char*)(buffer + 39U), 3U); - - LogDebug("Have reflector status reply from %s/%s/%s/%s", id.c_str(), name.c_str(), desc.c_str(), cnt.c_str()); - - for (std::vector::iterator it = m_reflectors.begin(); it != m_reflectors.end(); ++it) { - in_addr itAddr = (*it)->m_address; - unsigned int itPort = (*it)->m_port; - - if (itAddr.s_addr == address.s_addr && itPort == port) { - (*it)->m_id = id; - (*it)->m_name = name; - (*it)->m_desc = desc; - (*it)->m_count = cnt; - (*it)->m_seen = true; - break; - } - } - } - } } diff --git a/YSFGateway/Reflectors.h b/YSFGateway/Reflectors.h index 2f14b46..c0ddd0d 100644 --- a/YSFGateway/Reflectors.h +++ b/YSFGateway/Reflectors.h @@ -21,8 +21,8 @@ #include "UDPSocket.h" #include "Timer.h" -#include "Hosts.h" +#include #include class CYSFReflector { @@ -33,8 +33,7 @@ public: m_desc(), m_count("000"), m_address(), - m_port(0U), - m_seen(false) + m_port(0U) { } @@ -44,12 +43,11 @@ public: std::string m_count; in_addr m_address; unsigned int m_port; - bool m_seen; }; class CReflectors { public: - CReflectors(const std::string& hostsFile, unsigned int statusPort); + CReflectors(const std::string& hostsFile, unsigned int reloadTime); ~CReflectors(); bool load(); @@ -64,9 +62,7 @@ public: private: std::string m_hostsFile; - CUDPSocket m_socket; std::vector m_reflectors; - std::vector ::iterator m_it; std::vector m_current; std::vector m_search; CTimer m_timer; diff --git a/YSFGateway/WiresX.cpp b/YSFGateway/WiresX.cpp index 14c2944..cede4ca 100644 --- a/YSFGateway/WiresX.cpp +++ b/YSFGateway/WiresX.cpp @@ -42,11 +42,11 @@ const unsigned char DEFAULT_FICH[] = {0x20U, 0x00U, 0x01U, 0x00U}; const unsigned char NET_HEADER[] = "YSFD ALL "; -CWiresX::CWiresX(const std::string& callsign, const std::string& suffix, CNetwork* network, const std::string& hostsFile, unsigned int statusPort) : +CWiresX::CWiresX(const std::string& callsign, const std::string& suffix, CNetwork* network, const std::string& hostsFile, unsigned int reloadTime) : m_callsign(callsign), m_node(), m_network(network), -m_reflectors(hostsFile, statusPort), +m_reflectors(hostsFile, reloadTime), m_reflector(NULL), m_id(), m_name(), @@ -64,7 +64,6 @@ m_start(0U), m_search() { assert(network != NULL); - assert(statusPort > 0U); m_node = callsign; if (suffix.size() > 0U) { diff --git a/YSFGateway/WiresX.h b/YSFGateway/WiresX.h index 9f703a0..85946fc 100644 --- a/YSFGateway/WiresX.h +++ b/YSFGateway/WiresX.h @@ -42,7 +42,7 @@ enum WXSI_STATUS { class CWiresX { public: - CWiresX(const std::string& callsign, const std::string& suffix, CNetwork* network, const std::string& hostsFile, unsigned int statusPort); + CWiresX(const std::string& callsign, const std::string& suffix, CNetwork* network, const std::string& hostsFile, unsigned int reloadTime); ~CWiresX(); void setInfo(const std::string& name, unsigned int txFrequency, unsigned int rxFrequency); diff --git a/YSFGateway/YSFGateway.cpp b/YSFGateway/YSFGateway.cpp index ec4af2d..4e7139b 100644 --- a/YSFGateway/YSFGateway.cpp +++ b/YSFGateway/YSFGateway.cpp @@ -195,9 +195,9 @@ int CYSFGateway::run() bool networkEnabled = m_conf.getNetworkEnabled(); if (networkEnabled) { std::string fileName = m_conf.getNetworkHosts(); - unsigned int port = m_conf.getNetworkStatusPort(); + unsigned int reloadTime = m_conf.getNetworkReloadTime(); - m_wiresX = new CWiresX(m_callsign, m_suffix, &rptNetwork, fileName, port); + m_wiresX = new CWiresX(m_callsign, m_suffix, &rptNetwork, fileName, reloadTime); std::string name = m_conf.getName(); unsigned int txFrequency = m_conf.getTxFrequency(); diff --git a/YSFGateway/YSFGateway.ini b/YSFGateway/YSFGateway.ini index 06c0cd1..b68f3eb 100644 --- a/YSFGateway/YSFGateway.ini +++ b/YSFGateway/YSFGateway.ini @@ -35,7 +35,7 @@ Password=9999 [Network] Enable=1 DataPort=42000 -StatusPort=42001 Hosts=./YSFHosts.txt +ReloadTime=60 # Startup= Debug=0 diff --git a/YSFGateway/YSFGateway.vcxproj b/YSFGateway/YSFGateway.vcxproj index 03a7dd8..d4386bc 100644 --- a/YSFGateway/YSFGateway.vcxproj +++ b/YSFGateway/YSFGateway.vcxproj @@ -152,7 +152,6 @@ - @@ -179,7 +178,6 @@ - diff --git a/YSFGateway/YSFGateway.vcxproj.filters b/YSFGateway/YSFGateway.vcxproj.filters index 62c9df0..9bbd27c 100644 --- a/YSFGateway/YSFGateway.vcxproj.filters +++ b/YSFGateway/YSFGateway.vcxproj.filters @@ -38,9 +38,6 @@ Header Files - - Header Files - Header Files @@ -106,9 +103,6 @@ Source Files - - Source Files - Source Files diff --git a/YSFGateway/YSFHosts.txt b/YSFGateway/YSFHosts.txt index 1ccece8..91eeffb 100644 --- a/YSFGateway/YSFHosts.txt +++ b/YSFGateway/YSFHosts.txt @@ -1,170 +1,40 @@ -# -# These are the allowed hosts for this node -# -# The format is
-# -# To get your own YSFReflector into this list, -# please register it at: -# https://register.ysfreflector.de -# -# It is also possible to export this file by -# yourself via wget, curl or something else: -# https://register.ysfreflector.de/export.php -# - -# Alabama Link / Alabama Link -ysf.c4fm.se 42000 - -# Arizona USA / MARA C4FM -199.66.168.97 42000 - -# AU AUYSF001 / 1st World YSFR -64.137.181.152 42000 - -# AU FUSION2 / AU Reflector2 -aufusion2.ysfreflector.net 42000 - -# BM TG-2148 / BM TG-2148 -c4fm.ea3hkb.com 42108 - -# CA YSF005 / QC Fusion -ysf.ve2mrc.com 42000 - -# CT WIRESCAT / C4FM Catalunya -c4fm.ea3hkb.com 42000 - -# CZ Czech / TG2300 DCS019V -80.250.3.114 42000 - -# DE Germany / TG26208 -c4fm.ysfreflector.de 42000 - -# DE Germany2 / no bridge -c4fm.ysfreflector.de 42001 - -# DK Denmark / YSF012 C4FM Re -oz2ree.dk 42000 - -# ES YSF004 EDT / C4FM Reflector -c4fm.sustrai.org 42000 - -# ES YSF906 / ED7ZAK -xrf906.radioclubveleta.es 42000 - -# FON-Gateway / AllModes-GW -ysf-fon.f1tzo.com 42000 - -# FR YSF-France / Fusion France -m55.evxonline.net 42000 - -# FUSION-ITALY / Italy YSFR -c4fm-it.selfip.com 42000 - -# FUSIONBE2 / FusionBelgium -ysf.on4top.be 42000 - -# GB Fusion Kernow / Fusion SW UK -mb6cc.dyndns.org 43000 - -# GB Scotland / Scottish YSF -c4fm.gb7de.co.uk 42000 - -# GR YSF202 / Fusion Greece -ysf202.dv4gr.eu 42000 - -# IT Roma / Roma YSF Ref -romaroom.ddns.net 42000 - -# IT YRF003 CISAR / www.cisar.it -xrf003.iw0red.it 42000 - -# IT YSF027 / Zone_1_Italy -194.116.29.78 42000 - -# NETDA / FusioNET -ysf423.netda.us 42000 - -# NL Central / CENTRAL NL -c4fm.pa7lim.nl 42000 - -# NL YSF444 / Dutch Refl. -ysf444.pa3dfn.nl 42000 - -# PA Panama Link / Enlace Panama -69.164.201.29 42000 - -# PL POLAND / DMR 260042 -ysf260.ham-dmr.pl 42026 - -# PL YSF016 / SR8UWD Wlodawa -ysf016.wiresx.pl 42000 - -# PL YSF088 / Bedzin -83.142.218.188 42088 - -# Poland 21 / DMR TG260021 -ysf021.ham-dmr.pl 42021 - -# Poland 22 / DMR TG260022 -ysf022.ham-dmr.pl 42022 - -# PT YSF009 / C4FM-Portugal -c4fm.from-ct.com 42000 - -# RO YSF226 / C4FM Romania -xrf226.hamnet.ro 42000 - -# SE YSF699 / Tekniksnack -ysf.tekniksnack.se 42000 - -# SK OMO0OUE / Slovakia -88.212.32.147 42000 - -# SP EmCom / EmCom TG260023 -ysf023.ham-dmr.pl 42023 - -# TechTalk24 / Engineers talk -ysf024.ham-dmr.pl 42024 - -# TH nakhonthai / C4FM -office.nakhonthai.net 42000 - -# UK DVMEGA / DVMEGA CHAT -c4fm.pa7lim.nl 42001 - -# UK_YSF_BM_UK / UK_Ref_DN_ONLY -bm-dmr.uk 42000 - -# US EPA Exp / WB0YLE Test -www.wb0yle.com 42000 - -# US ILLINOIS / IL REFLECTOR -ilysf.ddns.net 42000 - -# US Michigan-MI5 / Michigan MI5 -c4fm-mi5.kb8zgl.net 42000 - -# US Nationwide / United States -174.36.222.36 42000 - -# US NJ PA Asteris / Link to BM 313 -ysf.njpaasterisk.org 42000 - -# US WMTG / WMTG Fusion -ysf.wmtg.me 42000 - -# US YSF008 USA / DVSwitch Test -ysfreflector.dvswitch.org 42000 - -# US-YSF587MiFL / YSF-QNetBridge -ysfqbridge.noip.us 42000 - -# YSF006 NORWAY / 24299+XLX404D -ysf.hamlabs.no 42000 - -# YSF017 / YSFLatino TG-9 -ysf-latino.ddns.net 42000 - -# ZZ Parrot / Parrot -127.0.0.1 42000 - +Alabama Link;Alabama Link;ysf.c4fm.se;42000;000 +AU AUYSF001;1st World YSFR;64.137.181.152;42000;000 +AU FUSION2;AU Reflector2;aufusion2.ysfreflector.net;42000;000 +CA YSF005;QC Fusion;ysf.ve2mrc.com;42000;000 +CT WIRESCAT;C4FM Catalunya;c4fm.ea3hkb.com;42000;000 +CZ Czech;TG2300 DCS019V;80.250.3.114;42000;000 +DE Germany;TG26208;c4fm.ysfreflector.de;42000;000 +DE Germany2;no bridge;c4fm.ysfreflector.de;42001;000 +1;ES YSF004 EDT;C4FM Reflector;c4fm.sustrai.org;42000;000 +2;FON-Gateway;AllModes-GW;ysf-fon.f1tzo.com;42000;000 +3;FR YSF-France;Fusion France;m55.evxonline.net;42000;000 +4;FUSION-ITALY;Italy YSFR;c4fm-it.selfip.com;42000;000 +5;FUSIONBE2;FusionBelgium;ysf.on4top.be;42000;000 +6;GB Fusion Kernow;Fusion SW UK;mb6cc.dyndns.org;43000;000 +7;GR YSF202;Fusion Greece;ysf202.dv4gr.eu;42000;000 +8;IT Roma;Roma YSF Ref;romaroom.ddns.net;42000;000 +9;IT YRF003 CISAR;www.cisar.it;xrf003.iw0red.it;42000;000 +10;NL Central;CENTRAL NL;c4fm.pa7lim.nl;42000;000 +11;NL YSF444;Dutch Refl.;ysf444.pa3dfn.nl;42000;000 +12;PL POLAND;DMR TG260;ysf260.ham-dmr.pl;42026;000 +13;PL YSF016;SR8UWD Wlodawa;ysf016.wiresx.pl;42000;000 +14;Poland 21;DMR TG260021;ysf021.ham-dmr.pl;42021;000 +15;Poland 22;DMR TG260022;ysf022.ham-dmr.pl;42022;000 +16;PT YSF009;C4FM-Portugal;c4fm.from-ct.com;42000;000 +17;RO YSF226;C4FM Romania;xrf226.hamnet.ro;42000;000 +18;SE YSF699;Tekniksnack;ysf.tekniksnack.se;42000;000 +19;SP EmCom;EmCom TG260023;ysf023.ham-dmr.pl;42023;000 +20;TechTalk24;Engineers talk;ysf024.ham-dmr.pl;42024;000 +21;UK DVMEGA;DVMEGA CHAT;c4fm.pa7lim.nl;42001;000 +22;UK Scotland;Scottish YSF;c4fm.gb7de.co.uk;42000;000 +23;UK_YSF_BM_UK;UK_Ref_DN_ONLY;bm-dmr.uk;42000;000 +24;US Nationwide;United States;174.36.222.36;42000;000 +25;US NJ PA Asteris;Link to BM 313;ysf.njpaasterisk.org;42000;000 +26;US WMTG;WMTG Fusion;ysf.wmtg.me;42000;000 +27;US YSF008 USA;DVSwitch Test;ysfreflector.dvswitch.org;42000;000 +28;US-YSF587MiFL;YSF-QNetBridge;ysfqbridge.noip.us;42000;000 +29;YSF004 MI5 SW2;Crossconnect t;c4fm-mi5.kb8zgl.net;42000;000 +30;YSF006 NORWAY;24299+XLX404D;ysf.hamlabs.no;42000;000 +31;YSF017;YSFLatino TG-9;ysf-latino.ddns.net;42000;000 +99;ZZ Parrot;Parrot;127.0.0.1;42000;000