1
0
Fork 0

Beginnings of the DG-ID Gateway

ycs232-kbc
Jonathan Naylor 4 years ago
parent 66feacb19f
commit af2be04fc8

@ -0,0 +1,381 @@
/*
* Copyright (C) 2010-2014,2016,2017,2018,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
* 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 "APRSWriter.h"
#include "YSFDefines.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <cstring>
#include <cmath>
CAPRSWriter::CAPRSWriter(const std::string& callsign, const std::string& rptSuffix, const std::string& address, unsigned int port, const std::string& suffix, bool debug) :
m_idTimer(1000U),
m_callsign(callsign),
m_debug(debug),
m_txFrequency(0U),
m_rxFrequency(0U),
m_latitude(0.0F),
m_longitude(0.0F),
m_height(0),
m_desc(),
m_suffix(suffix),
m_aprsAddress(),
m_aprsPort(port),
m_aprsSocket()
#if defined(USE_GPSD)
,m_gpsdEnabled(false),
m_gpsdAddress(),
m_gpsdPort(),
m_gpsdData()
#endif
{
assert(!callsign.empty());
assert(!address.empty());
assert(port > 0U);
if (!rptSuffix.empty()) {
m_callsign.append("-");
m_callsign.append(rptSuffix.substr(0U, 1U));
}
m_aprsAddress = CUDPSocket::lookup(address);
}
CAPRSWriter::~CAPRSWriter()
{
}
void CAPRSWriter::setInfo(unsigned int txFrequency, unsigned int rxFrequency, const std::string& desc)
{
m_txFrequency = txFrequency;
m_rxFrequency = rxFrequency;
m_desc = desc;
}
void CAPRSWriter::setStaticLocation(float latitude, float longitude, int height)
{
m_latitude = latitude;
m_longitude = longitude;
m_height = height;
}
void CAPRSWriter::setGPSDLocation(const std::string& address, const std::string& port)
{
#if defined(USE_GPSD)
assert(!address.empty());
assert(!port.empty());
m_gpsdEnabled = true;
m_gpsdAddress = address;
m_gpsdPort = port;
#endif
}
bool CAPRSWriter::open()
{
#if defined(USE_GPSD)
if (m_gpsdEnabled) {
int ret = ::gps_open(m_gpsdAddress.c_str(), m_gpsdPort.c_str(), &m_gpsdData);
if (ret != 0) {
LogError("Error when opening access to gpsd - %d - %s", errno, ::gps_errstr(errno));
return false;
}
::gps_stream(&m_gpsdData, WATCH_ENABLE | WATCH_JSON, NULL);
LogMessage("Connected to GPSD");
}
#endif
bool ret = m_aprsSocket.open();
if (!ret)
return false;
LogMessage("Opened connection to the APRS Gateway");
m_idTimer.setTimeout(60U);
m_idTimer.start();
return true;
}
void CAPRSWriter::write(const unsigned char* source, const char* type, unsigned char radio, float fLatitude, float fLongitude)
{
assert(source != NULL);
assert(type != NULL);
char callsign[15U];
::memcpy(callsign, source, YSF_CALLSIGN_LENGTH);
callsign[YSF_CALLSIGN_LENGTH] = 0x00U;
size_t n = ::strspn(callsign, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
callsign[n] = 0x00U;
if (!m_suffix.empty()) {
::strcat(callsign, "-");
::strcat(callsign, m_suffix.substr(0U, 1U).c_str());
}
double tempLat = ::fabs(fLatitude);
double tempLong = ::fabs(fLongitude);
double latitude = ::floor(tempLat);
double longitude = ::floor(tempLong);
latitude = (tempLat - latitude) * 60.0 + latitude * 100.0;
longitude = (tempLong - longitude) * 60.0 + longitude * 100.0;
char lat[20U];
::sprintf(lat, "%07.2lf", latitude);
char lon[20U];
::sprintf(lon, "%08.2lf", longitude);
char symbol;
switch (radio) {
case 0x24U:
case 0x28U:
case 0x30U:
symbol = '[';
break;
case 0x25U:
case 0x29U:
symbol = '>';
break;
case 0x26U:
symbol = 'r';
break;
default:
symbol = '-';
break;
}
char output[300U];
::sprintf(output, "%s>APDPRS,C4FM*,qAR,%s:!%s%c/%s%c%c %s via MMDVM\r\n",
callsign, m_callsign.c_str(),
lat, (fLatitude < 0.0F) ? 'S' : 'N',
lon, (fLongitude < 0.0F) ? 'W' : 'E',
symbol, type);
if (m_debug)
LogDebug("APRS ==> %s", output);
m_aprsSocket.write((unsigned char*)output, (unsigned int)::strlen(output), m_aprsAddress, m_aprsPort);
}
void CAPRSWriter::clock(unsigned int ms)
{
m_idTimer.clock(ms);
#if defined(USE_GPSD)
if (m_gpsdEnabled) {
if (m_idTimer.hasExpired()) {
sendIdFrameMobile();
m_idTimer.start();
}
} else {
#endif
if (m_idTimer.hasExpired()) {
sendIdFrameFixed();
m_idTimer.setTimeout(20U * 60U);
m_idTimer.start();
}
#if defined(USE_GPSD)
}
#endif
}
void CAPRSWriter::close()
{
m_aprsSocket.close();
#if defined(USE_GPSD)
if (m_gpsdEnabled) {
::gps_stream(&m_gpsdData, WATCH_DISABLE, NULL);
::gps_close(&m_gpsdData);
}
#endif
}
void CAPRSWriter::sendIdFrameFixed()
{
// Default values aren't passed on
if (m_latitude == 0.0F && m_longitude == 0.0F)
return;
char desc[200U];
if (m_txFrequency != 0U) {
float offset = float(int(m_rxFrequency) - int(m_txFrequency)) / 1000000.0F;
::sprintf(desc, "MMDVM Voice %.5LfMHz %c%.4lfMHz%s%s",
(long double)(m_txFrequency) / 1000000.0F,
offset < 0.0F ? '-' : '+',
::fabs(offset), m_desc.empty() ? "" : ", ", m_desc.c_str());
} else {
::sprintf(desc, "MMDVM Voice%s%s", m_desc.empty() ? "" : ", ", m_desc.c_str());
}
const char* band = "4m";
if (m_txFrequency >= 1200000000U)
band = "1.2";
else if (m_txFrequency >= 420000000U)
band = "440";
else if (m_txFrequency >= 144000000U)
band = "2m";
else if (m_txFrequency >= 50000000U)
band = "6m";
else if (m_txFrequency >= 28000000U)
band = "10m";
double tempLat = ::fabs(m_latitude);
double tempLong = ::fabs(m_longitude);
double latitude = ::floor(tempLat);
double longitude = ::floor(tempLong);
latitude = (tempLat - latitude) * 60.0 + latitude * 100.0;
longitude = (tempLong - longitude) * 60.0 + longitude * 100.0;
char lat[20U];
::sprintf(lat, "%07.2lf", latitude);
char lon[20U];
::sprintf(lon, "%08.2lf", longitude);
std::string server = m_callsign;
size_t pos = server.find_first_of('-');
if (pos == std::string::npos)
server.append("-S");
else
server.append("S");
char output[500U];
::sprintf(output, "%s>APDG03,TCPIP*,qAC,%s:!%s%cD%s%c&/A=%06.0f%s %s\r\n",
m_callsign.c_str(), server.c_str(),
lat, (m_latitude < 0.0F) ? 'S' : 'N',
lon, (m_longitude < 0.0F) ? 'W' : 'E',
float(m_height) * 3.28F, band, desc);
if (m_debug)
LogDebug("APRS ==> %s", output);
m_aprsSocket.write((unsigned char*)output, (unsigned int)::strlen(output), m_aprsAddress, m_aprsPort);
}
#if defined(USE_GPSD)
void CAPRSWriter::sendIdFrameMobile()
{
if (!::gps_waiting(&m_gpsdData, 0))
return;
#if GPSD_API_MAJOR_VERSION >= 7
if (::gps_read(&m_gpsdData, NULL, 0) <= 0)
return;
#else
if (::gps_read(&m_gpsdData) <= 0)
return;
#endif
if (m_gpsdData.status != STATUS_FIX)
return;
bool latlonSet = (m_gpsdData.set & LATLON_SET) == LATLON_SET;
bool altitudeSet = (m_gpsdData.set & ALTITUDE_SET) == ALTITUDE_SET;
bool velocitySet = (m_gpsdData.set & SPEED_SET) == SPEED_SET;
bool bearingSet = (m_gpsdData.set & TRACK_SET) == TRACK_SET;
if (!latlonSet)
return;
float rawLatitude = float(m_gpsdData.fix.latitude);
float rawLongitude = float(m_gpsdData.fix.longitude);
#if GPSD_API_MAJOR_VERSION >= 9
float rawAltitude = float(m_gpsdData.fix.altMSL);
#else
float rawAltitude = float(m_gpsdData.fix.altitude);
#endif
float rawVelocity = float(m_gpsdData.fix.speed);
float rawBearing = float(m_gpsdData.fix.track);
char desc[200U];
if (m_txFrequency != 0U) {
float offset = float(int(m_rxFrequency) - int(m_txFrequency)) / 1000000.0F;
::sprintf(desc, "MMDVM Voice %.5LfMHz %c%.4lfMHz%s%s",
(long double)(m_txFrequency) / 1000000.0F,
offset < 0.0F ? '-' : '+',
::fabs(offset), m_desc.empty() ? "" : ", ", m_desc.c_str());
} else {
::sprintf(desc, "MMDVM Voice%s%s", m_desc.empty() ? "" : ", ", m_desc.c_str());
}
const char* band = "4m";
if (m_txFrequency >= 1200000000U)
band = "1.2";
else if (m_txFrequency >= 420000000U)
band = "440";
else if (m_txFrequency >= 144000000U)
band = "2m";
else if (m_txFrequency >= 50000000U)
band = "6m";
else if (m_txFrequency >= 28000000U)
band = "10m";
double tempLat = ::fabs(rawLatitude);
double tempLong = ::fabs(rawLongitude);
double latitude = ::floor(tempLat);
double longitude = ::floor(tempLong);
latitude = (tempLat - latitude) * 60.0 + latitude * 100.0;
longitude = (tempLong - longitude) * 60.0 + longitude * 100.0;
char lat[20U];
::sprintf(lat, "%07.2lf", latitude);
char lon[20U];
::sprintf(lon, "%08.2lf", longitude);
std::string server = m_callsign;
size_t pos = server.find_first_of('-');
if (pos == std::string::npos)
server.append("-S");
else
server.append("S");
char output[500U];
::sprintf(output, "%s>APDG03,TCPIP*,qAC,%s:!%s%cD%s%c&",
m_callsign.c_str(), server.c_str(),
lat, (rawLatitude < 0.0F) ? 'S' : 'N',
lon, (rawLongitude < 0.0F) ? 'W' : 'E');
if (bearingSet && velocitySet)
::sprintf(output + ::strlen(output), "%03.0f/%03.0f", rawBearing, rawVelocity * 0.539957F);
if (altitudeSet)
::sprintf(output + ::strlen(output), "/A=%06.0f", float(rawAltitude) * 3.28F);
::sprintf(output + ::strlen(output), "%s %s\r\n", band, desc);
if (m_debug)
LogDebug("APRS ==> %s", output);
m_aprsSocket.write((unsigned char*)output, (unsigned int)::strlen(output), m_aprsAddress, m_aprsPort);
}
#endif

@ -0,0 +1,87 @@
/*
* Copyright (C) 2010,2011,2012,2016,2017,2018,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
* 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 APRSWriter_H
#define APRSWriter_H
#include "UDPSocket.h"
#include "Timer.h"
#include <string>
#if !defined(_WIN32) && !defined(_WIN64)
#include <netdb.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#if defined(USE_GPSD)
#include <gps.h>
#endif
#else
#include <winsock.h>
#endif
class CAPRSWriter {
public:
CAPRSWriter(const std::string& callsign, const std::string& rptSuffix, const std::string& address, unsigned int port, const std::string& suffix, bool debug);
~CAPRSWriter();
bool open();
void setInfo(unsigned int txFrequency, unsigned int rxFrequency, const std::string& desc);
void setStaticLocation(float latitude, float longitude, int height);
void setGPSDLocation(const std::string& address, const std::string& port);
void write(const unsigned char* source, const char* type, unsigned char radio, float latitude, float longitude);
void clock(unsigned int ms);
void close();
private:
CTimer m_idTimer;
std::string m_callsign;
bool m_debug;
unsigned int m_txFrequency;
unsigned int m_rxFrequency;
float m_latitude;
float m_longitude;
int m_height;
std::string m_desc;
std::string m_suffix;
in_addr m_aprsAddress;
unsigned int m_aprsPort;
CUDPSocket m_aprsSocket;
#if defined(USE_GPSD)
bool m_gpsdEnabled;
std::string m_gpsdAddress;
std::string m_gpsdPort;
struct gps_data_t m_gpsdData;
#endif
void sendIdFrameFixed();
void sendIdFrameMobile();
};
#endif

@ -0,0 +1,115 @@
/*
* Copyright (C) 2015,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 "CRC.h"
#include "Utils.h"
#include "Log.h"
#include <cstdint>
#include <cstdio>
#include <cassert>
#include <cmath>
const uint16_t CCITT16_TABLE2[] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 };
void CCRC::addCCITT16(unsigned char *in, unsigned int length)
{
assert(in != NULL);
assert(length > 2U);
union {
uint16_t crc16;
uint8_t crc8[2U];
};
crc16 = 0U;
for (unsigned i = 0U; i < (length - 2U); i++)
crc16 = (uint16_t(crc8[0U]) << 8) ^ CCITT16_TABLE2[crc8[1U] ^ in[i]];
crc16 = ~crc16;
in[length - 1U] = crc8[0U];
in[length - 2U] = crc8[1U];
}
bool CCRC::checkCCITT16(const unsigned char *in, unsigned int length)
{
assert(in != NULL);
assert(length > 2U);
union {
uint16_t crc16;
uint8_t crc8[2U];
};
crc16 = 0U;
for (unsigned i = 0U; i < (length - 2U); i++)
crc16 = (uint16_t(crc8[0U]) << 8) ^ CCITT16_TABLE2[crc8[1U] ^ in[i]];
crc16 = ~crc16;
return crc8[0U] == in[length - 1U] && crc8[1U] == in[length - 2U];
}
unsigned char CCRC::addCRC(const unsigned char* in, unsigned int length)
{
assert(in != NULL);
unsigned char crc = 0U;
for (unsigned int i = 0U; i < length; i++)
crc += in[i];
return crc;
}

@ -0,0 +1,31 @@
/*
* Copyright (C) 2015,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.
*/
#if !defined(CRC_H)
#define CRC_H
class CCRC
{
public:
static void addCCITT16(unsigned char* in, unsigned int length);
static bool checkCCITT16(const unsigned char* in, unsigned int length);
static unsigned char addCRC(const unsigned char* in, unsigned int length);
};
#endif

@ -0,0 +1,430 @@
/*
* Copyright (C) 2015-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
* 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 "Conf.h"
#include "Log.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cassert>
const int BUFFER_SIZE = 500;
enum SECTION {
SECTION_NONE,
SECTION_GENERAL,
SECTION_INFO,
SECTION_LOG,
SECTION_APRS,
SECTION_YSF_NETWORK,
SECTION_FCS_NETWORK,
SECTION_DGID,
SECTION_GPSD
};
CConf::CConf(const std::string& file) :
m_file(file),
m_callsign(),
m_suffix(),
m_id(0U),
m_rptAddress(),
m_rptPort(0U),
m_myAddress(),
m_myPort(0U),
m_rfHangTime(60U),
m_netHangTime(60U),
m_debug(false),
m_daemon(false),
m_rxFrequency(0U),
m_txFrequency(0U),
m_power(0U),
m_latitude(0.0F),
m_longitude(0.0F),
m_height(0),
m_name(),
m_description(),
m_logDisplayLevel(0U),
m_logFileLevel(0U),
m_logFilePath(),
m_logFileRoot(),
m_aprsEnabled(false),
m_aprsAddress(),
m_aprsPort(0U),
m_aprsSuffix(),
m_aprsDescription(),
m_ysfNetHosts(),
m_ysfRFHangTime(60U),
m_ysfNetHangTime(60U),
m_ysfNetDebug(false),
m_fcsRFHangTime(60U),
m_fcsNetHangTime(60U),
m_fcsNetDebug(false),
m_dgIdData(),
m_gpsdEnabled(false),
m_gpsdAddress(),
m_gpsdPort()
{
}
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;
DGIdData* dgIdData = NULL;
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, "[YSF Network]", 13U) == 0)
section = SECTION_YSF_NETWORK;
else if (::strncmp(buffer, "[FCS Network]", 13U) == 0)
section = SECTION_FCS_NETWORK;
else if (::strncmp(buffer, "[DGId=", 6U) == 0) {
section = SECTION_DGID;
dgIdData = new DGIdData;
dgIdData->m_dgId = (unsigned int)::atoi(buffer + 6U);
m_dgIdData.push_back(dgIdData);
} else if (::strncmp(buffer, "[GPSD]", 6U) == 0)
section = SECTION_GPSD;
else
section = SECTION_NONE;
continue;
}
char* key = ::strtok(buffer, " \t=\r\n");
if (key == NULL)
continue;
char* value = ::strtok(NULL, "\r\n");
if (section == SECTION_GENERAL) {
if (::strcmp(key, "Callsign") == 0) {
// Convert the callsign to upper case
for (unsigned int i = 0U; value[i] != 0; i++)
value[i] = ::toupper(value[i]);
m_callsign = value;
} else if (::strcmp(key, "Suffix") == 0) {
// Convert the callsign to upper case
for (unsigned int i = 0U; value[i] != 0; i++)
value[i] = ::toupper(value[i]);
m_suffix = value;
} else if (::strcmp(key, "Id") == 0)
m_id = (unsigned int)::atoi(value);
else if (::strcmp(key, "RptAddress") == 0)
m_rptAddress = value;
else if (::strcmp(key, "RptPort") == 0)
m_rptPort = (unsigned int)::atoi(value);
else if (::strcmp(key, "LocalAddress") == 0)
m_myAddress = value;
else if (::strcmp(key, "LocalPort") == 0)
m_myPort = (unsigned int)::atoi(value);
else if (::strcmp(key, "RFHangTime") == 0)
m_ysfRFHangTime = m_fcsRFHangTime = m_rfHangTime = (unsigned int)::atoi(value);
else if (::strcmp(key, "NetHangTime") == 0)
m_ysfNetHangTime = m_fcsNetHangTime = m_netHangTime = (unsigned int)::atoi(value);
else if (::strcmp(key, "Debug") == 0)
m_debug = ::atoi(value) == 1;
else if (::strcmp(key, "Daemon") == 0)
m_daemon = ::atoi(value) == 1;
} else if (section == SECTION_INFO) {
if (::strcmp(key, "TXFrequency") == 0)
m_txFrequency = (unsigned int)::atoi(value);
else if (::strcmp(key, "RXFrequency") == 0)
m_rxFrequency = (unsigned int)::atoi(value);
else if (::strcmp(key, "Power") == 0)
m_power = (unsigned int)::atoi(value);
else if (::strcmp(key, "Latitude") == 0)
m_latitude = float(::atof(value));
else if (::strcmp(key, "Longitude") == 0)
m_longitude = float(::atof(value));
else if (::strcmp(key, "Height") == 0)
m_height = ::atoi(value);
else if (::strcmp(key, "Name") == 0)
m_name = value;
else if (::strcmp(key, "Description") == 0)
m_description = value;
} else if (section == SECTION_LOG) {
if (::strcmp(key, "FilePath") == 0)
m_logFilePath = value;
else if (::strcmp(key, "FileRoot") == 0)
m_logFileRoot = value;
else if (::strcmp(key, "FileLevel") == 0)
m_logFileLevel = (unsigned int)::atoi(value);
else if (::strcmp(key, "DisplayLevel") == 0)
m_logDisplayLevel = (unsigned int)::atoi(value);
} else if (section == SECTION_APRS) {
if (::strcmp(key, "Enable") == 0)
m_aprsEnabled = ::atoi(value) == 1;
else if (::strcmp(key, "Address") == 0)
m_aprsAddress = value;
else if (::strcmp(key, "Port") == 0)
m_aprsPort = (unsigned int)::atoi(value);
else if (::strcmp(key, "Suffix") == 0)
m_aprsSuffix = value;
else if (::strcmp(key, "Description") == 0)
m_aprsDescription = value;
} else if (section == SECTION_YSF_NETWORK) {
if (::strcmp(key, "Hosts") == 0)
m_ysfNetHosts = value;
else if (::strcmp(key, "RFHangTime") == 0)
m_ysfRFHangTime = (unsigned int)::atoi(value);
else if (::strcmp(key, "NetHangTime") == 0)
m_ysfNetHangTime = (unsigned int)::atoi(value);
else if (::strcmp(key, "Debug") == 0)
m_ysfNetDebug = ::atoi(value) == 1;
} else if (section == SECTION_FCS_NETWORK) {
if (::strcmp(key, "RFHangTime") == 0)
m_fcsRFHangTime = (unsigned int)::atoi(value);
else if (::strcmp(key, "NetHangTime") == 0)
m_fcsNetHangTime = (unsigned int)::atoi(value);
else if (::strcmp(key, "Debug") == 0)
m_fcsNetDebug = ::atoi(value) == 1;
} else if (section == SECTION_DGID) {
assert(dgIdData != NULL);
if (::strcmp(key, "Type") == 0) {
dgIdData->m_type = value;
dgIdData->m_static = false;
if (::strcmp(value, "YSF") == 0) {
dgIdData->m_rfHangTime = m_ysfRFHangTime;
dgIdData->m_netHangTime = m_ysfNetHangTime;
dgIdData->m_debug = m_ysfNetDebug;
} else if (::strcmp(value, "FCS") == 0) {
dgIdData->m_rfHangTime = m_fcsRFHangTime;
dgIdData->m_netHangTime = m_fcsNetHangTime;
dgIdData->m_debug = m_fcsNetDebug;
} else {
dgIdData->m_rfHangTime = m_rfHangTime;
dgIdData->m_netHangTime = m_netHangTime;
dgIdData->m_debug = false;
}
} else if (::strcmp(key, "RFHangTime") == 0)
dgIdData->m_rfHangTime = (unsigned int)::atoi(value);
else if (::strcmp(key, "NetHangTime") == 0)
dgIdData->m_netHangTime = (unsigned int)::atoi(value);
else if (::strcmp(key, "Static") == 0)
dgIdData->m_static = ::atoi(value) == 1;
else if (::strcmp(key, "Address") == 0)
dgIdData->m_address = value;
else if (::strcmp(key, "Name") == 0)
dgIdData->m_name = value;
else if (::strcmp(key, "Port") == 0)
dgIdData->m_port = (unsigned int)::atoi(value);
else if (::strcmp(key, "Local") == 0)
dgIdData->m_local = (unsigned int)::atoi(value);
else if (::strcmp(key, "Destination") == 0) {
char* p1 = ::strtok(value, ",");
char* p2 = ::strtok(NULL, "\r\n");
IMRSDestination* dest = new IMRSDestination;
dest->m_dgId = (unsigned int)::atoi(p1);
dest->m_address = p2;
dgIdData->m_destinations.push_back(dest);
} else if (::strcmp(key, "Debug") == 0)
dgIdData->m_debug = ::atoi(value) == 1;
} else if (section == SECTION_GPSD) {
if (::strcmp(key, "Enable") == 0)
m_gpsdEnabled = ::atoi(value) == 1;
else if (::strcmp(key, "Address") == 0)
m_gpsdAddress = value;
else if (::strcmp(key, "Port") == 0)
m_gpsdPort = value;
}
}
::fclose(fp);
return true;
}
std::string CConf::getCallsign() const
{
return m_callsign;
}
std::string CConf::getSuffix() const
{
return m_suffix;
}
unsigned int CConf::getId() const
{
return m_id;
}
std::string CConf::getRptAddress() const
{
return m_rptAddress;
}
unsigned int CConf::getRptPort() const
{
return m_rptPort;
}
std::string CConf::getMyAddress() const
{
return m_myAddress;
}
unsigned int CConf::getMyPort() const
{
return m_myPort;
}
bool CConf::getDebug() const
{
return m_debug;
}
bool CConf::getDaemon() const
{
return m_daemon;
}
unsigned int CConf::getRxFrequency() const
{
return m_rxFrequency;
}
unsigned int CConf::getTxFrequency() const
{
return m_txFrequency;
}
unsigned int CConf::getPower() const
{
return m_power;
}
float CConf::getLatitude() const
{
return m_latitude;
}
float CConf::getLongitude() const
{
return m_longitude;
}
int CConf::getHeight() const
{
return m_height;
}
std::string CConf::getName() const
{
return m_name;
}
std::string CConf::getDescription() const
{
return m_description;
}
unsigned int CConf::getLogDisplayLevel() const
{
return m_logDisplayLevel;
}
unsigned int CConf::getLogFileLevel() const
{
return m_logFileLevel;
}
std::string CConf::getLogFilePath() const
{
return m_logFilePath;
}
std::string CConf::getLogFileRoot() const
{
return m_logFileRoot;
}
bool CConf::getAPRSEnabled() const
{
return m_aprsEnabled;
}
std::string CConf::getAPRSAddress() const
{
return m_aprsAddress;
}
unsigned int CConf::getAPRSPort() const
{
return m_aprsPort;
}
std::string CConf::getAPRSSuffix() const
{
return m_aprsSuffix;
}
std::string CConf::getAPRSDescription() const
{
return m_aprsDescription;
}
std::string CConf::getYSFNetHosts() const
{
return m_ysfNetHosts;
}
std::vector<DGIdData*> CConf::getDGIdData() const
{
return m_dgIdData;
}
bool CConf::getGPSDEnabled() const
{
return m_gpsdEnabled;
}
std::string CConf::getGPSDAddress() const
{
return m_gpsdAddress;
}
std::string CConf::getGPSDPort() const
{
return m_gpsdPort;
}

@ -0,0 +1,147 @@
/*
* Copyright (C) 2015-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
* 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.
*/
#if !defined(CONF_H)
#define CONF_H
#include <string>
#include <vector>
struct IMRSDestination {
std::string m_address;
unsigned int m_dgId;
};
struct DGIdData {
unsigned int m_dgId;
std::string m_type;
bool m_static;
std::string m_name;
std::string m_address;
unsigned int m_port;
unsigned int m_local;
std::vector<IMRSDestination*> m_destinations;
unsigned int m_rfHangTime;
unsigned int m_netHangTime;
bool m_debug;
};
class CConf
{
public:
CConf(const std::string& file);
~CConf();
bool read();
// The General section
std::string getCallsign() const;
std::string getSuffix() const;
unsigned int getId() const;
std::string getRptAddress() const;
unsigned int getRptPort() const;
std::string getMyAddress() const;
unsigned int getMyPort() const;
bool getDebug() const;
bool getDaemon() const;
// The Info section
unsigned int getRxFrequency() const;
unsigned int getTxFrequency() const;
unsigned int getPower() const;
float getLatitude() const;
float getLongitude() const;
int getHeight() const;
std::string getName() const;
std::string getDescription() const;
// The Log section
unsigned int getLogDisplayLevel() const;
unsigned int getLogFileLevel() const;
std::string getLogFilePath() const;
std::string getLogFileRoot() const;
// The APRS section
bool getAPRSEnabled() const;
std::string getAPRSAddress() const;
unsigned int getAPRSPort() const;
std::string getAPRSSuffix() const;
std::string getAPRSDescription() const;
// The YSF Network section
std::string getYSFNetHosts() const;
// The DG-ID Section
std::vector<DGIdData*> getDGIdData() const;
// The GPSD section
bool getGPSDEnabled() const;
std::string getGPSDAddress() const;
std::string getGPSDPort() const;
private:
std::string m_file;
std::string m_callsign;
std::string m_suffix;
unsigned int m_id;
std::string m_rptAddress;
unsigned int m_rptPort;
std::string m_myAddress;
unsigned int m_myPort;
unsigned int m_rfHangTime;
unsigned int m_netHangTime;
bool m_debug;
bool m_daemon;
unsigned int m_rxFrequency;
unsigned int m_txFrequency;
unsigned int m_power;
float m_latitude;
float m_longitude;
int m_height;
std::string m_name;
std::string m_description;
unsigned int m_logDisplayLevel;
unsigned int m_logFileLevel;
std::string m_logFilePath;
std::string m_logFileRoot;
bool m_aprsEnabled;
std::string m_aprsAddress;
unsigned int m_aprsPort;
std::string m_aprsSuffix;
std::string m_aprsDescription;
std::string m_ysfNetHosts;
unsigned int m_ysfRFHangTime;
unsigned int m_ysfNetHangTime;
bool m_ysfNetDebug;
unsigned int m_fcsRFHangTime;
unsigned int m_fcsNetHangTime;
bool m_fcsNetDebug;
std::vector<DGIdData*> m_dgIdData;
bool m_gpsdEnabled;
std::string m_gpsdAddress;
std::string m_gpsdPort;
};
#endif

@ -0,0 +1,556 @@
/*
* 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
* 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 "YSFReflectors.h"
#include "DGIdGateway.h"
#include "DGIdNetwork.h"
#include "YSFNetwork.h"
#include "FCSNetwork.h"
#include "UDPSocket.h"
#include "StopWatch.h"
#include "Version.h"
#include "YSFFICH.h"
#include "Thread.h"
#include "Timer.h"
#include "Utils.h"
#include "Log.h"
#if defined(_WIN32) || defined(_WIN64)
#include <Windows.h>
#else
#include <sys/time.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <pwd.h>
#endif
#if defined(_WIN32) || defined(_WIN64)
const char* DEFAULT_INI_FILE = "DGIdGateway.ini";
#else
const char* DEFAULT_INI_FILE = "/etc/DGIdGateway.ini";
#endif
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <clocale>
#include <cmath>
int main(int argc, char** argv)
{
const char* iniFile = DEFAULT_INI_FILE;
if (argc > 1) {
for (int currentArg = 1; currentArg < argc; ++currentArg) {
std::string arg = argv[currentArg];
if ((arg == "-v") || (arg == "--version")) {
::fprintf(stdout, "DGIdGateway version %s\n", VERSION);
return 0;
} else if (arg.substr(0, 1) == "-") {
::fprintf(stderr, "Usage: DGIdGateway [-v|--version] [filename]\n");
return 1;
} else {
iniFile = argv[currentArg];
}
}
}
CDGIdGateway* gateway = new CDGIdGateway(std::string(iniFile));
int ret = gateway->run();
delete gateway;
return ret;
}
CDGIdGateway::CDGIdGateway(const std::string& configFile) :
m_callsign(),
m_suffix(),
m_conf(configFile),
m_writer(NULL),
m_gps(NULL)
{
}
CDGIdGateway::~CDGIdGateway()
{
}
int CDGIdGateway::run()
{
bool ret = m_conf.read();
if (!ret) {
::fprintf(stderr, "DGIdGateway: cannot read the .ini file\n");
return 1;
}
setlocale(LC_ALL, "C");
#if !defined(_WIN32) && !defined(_WIN64)
bool m_daemon = m_conf.getDaemon();
if (m_daemon) {
// Create new process
pid_t pid = ::fork();
if (pid == -1) {
::fprintf(stderr, "Couldn't fork() , exiting\n");
return -1;
}
else if (pid != 0) {
exit(EXIT_SUCCESS);
}
// Create new session and process group
if (::setsid() == -1) {
::fprintf(stderr, "Couldn't setsid(), exiting\n");
return -1;
}
// Set the working directory to the root directory
if (::chdir("/") == -1) {
::fprintf(stderr, "Couldn't cd /, exiting\n");
return -1;
}
// If we are currently root...
if (getuid() == 0) {
struct passwd* user = ::getpwnam("mmdvm");
if (user == NULL) {
::fprintf(stderr, "Could not get the mmdvm user, exiting\n");
return -1;
}
uid_t mmdvm_uid = user->pw_uid;
gid_t mmdvm_gid = user->pw_gid;
// Set user and group ID's to mmdvm:mmdvm
if (setgid(mmdvm_gid) != 0) {
::fprintf(stderr, "Could not set mmdvm GID, exiting\n");
return -1;
}
if (setuid(mmdvm_uid) != 0) {
::fprintf(stderr, "Could not set mmdvm UID, exiting\n");
return -1;
}
// Double check it worked (AKA Paranoia)
if (setuid(0) != -1) {
::fprintf(stderr, "It's possible to regain root - something is wrong!, exiting\n");
return -1;
}
}
}
#endif
ret = ::LogInitialise(m_conf.getLogFilePath(), m_conf.getLogFileRoot(), m_conf.getLogFileLevel(), m_conf.getLogDisplayLevel());
if (!ret) {
::fprintf(stderr, "DGIdGateway: unable to open the log file\n");
return 1;
}
#if !defined(_WIN32) && !defined(_WIN64)
if (m_daemon) {
::close(STDIN_FILENO);
::close(STDOUT_FILENO);
::close(STDERR_FILENO);
}
#endif
m_callsign = m_conf.getCallsign();
m_suffix = m_conf.getSuffix();
bool debug = m_conf.getDebug();
in_addr rptAddress = CUDPSocket::lookup(m_conf.getRptAddress());
unsigned int rptPort = m_conf.getRptPort();
std::string myAddress = m_conf.getMyAddress();
unsigned int myPort = m_conf.getMyPort();
CYSFNetwork rptNetwork(myAddress, myPort, m_callsign, debug);
rptNetwork.setDestination("MMDVM", rptAddress, rptPort);
ret = rptNetwork.open();
if (!ret) {
::LogError("Cannot open the repeater network port");
::LogFinalise();
return 1;
}
std::string fileName = m_conf.getYSFNetHosts();
CYSFReflectors* reflectors = new CYSFReflectors(fileName);
reflectors->load();
unsigned int currentDGId = 0U;
CDGIdNetwork* dgIdNetwork[100U];
for (unsigned int i = 0U; i < 100U; i++)
dgIdNetwork[i] = NULL;
std::vector<DGIdData*> dgIdData = m_conf.getDGIdData();
for (std::vector<DGIdData*>::const_iterator it = dgIdData.begin(); it != dgIdData.end(); ++it) {
unsigned int dgid = (*it)->m_dgId;
std::string type = (*it)->m_type;
bool statc = (*it)->m_static;
unsigned int rfHangTime = (*it)->m_rfHangTime;
unsigned int netHangTime = (*it)->m_netHangTime;
bool debug = (*it)->m_debug;
if (type == "FCS") {
std::string name = (*it)->m_name;
unsigned int local = (*it)->m_local;
unsigned int txFrequency = m_conf.getTxFrequency();
unsigned int rxFrequency = m_conf.getRxFrequency();
std::string locator = calculateLocator();
unsigned int id = m_conf.getId();
dgIdNetwork[dgid] = new CFCSNetwork(name, local, m_callsign, rxFrequency, txFrequency, locator, id, debug);
dgIdNetwork[dgid]->m_modes = YSF_DT_VD_MODE1 | YSF_DT_VD_MODE2 | YSF_DT_VOICE_FR_MODE | YSF_DT_DATA_FR_MODE;
dgIdNetwork[dgid]->m_static = statc;
dgIdNetwork[dgid]->m_rfHangTime = rfHangTime;
dgIdNetwork[dgid]->m_netHangTime = netHangTime;
} else if (type == "YSF") {
std::string name = (*it)->m_name;
unsigned int local = (*it)->m_local;
CYSFReflector* reflector = reflectors->findByName(name);
if (reflector != NULL) {
CYSFNetwork* ysf = new CYSFNetwork(local, m_callsign, debug);
ysf->setDestination(reflector->m_name, reflector->m_address, reflector->m_port);
dgIdNetwork[dgid] = ysf;
dgIdNetwork[dgid]->m_modes = YSF_DT_VD_MODE1 | YSF_DT_VD_MODE2 | YSF_DT_VOICE_FR_MODE | YSF_DT_DATA_FR_MODE;
dgIdNetwork[dgid]->m_static = statc;
dgIdNetwork[dgid]->m_rfHangTime = rfHangTime;
dgIdNetwork[dgid]->m_netHangTime = netHangTime;
}
/*
} else if (type == "IMRS") {
dgIdNetwork[dgid] = new CIMRSNetwork;
dgIdNetwork[dgid]->m_modes = YSF_DT_VD_MODE1 | YSF_DT_VD_MODE2 | YSF_DT_VOICE_FR_MODE | YSF_DT_DATA_FR_MODE;
dgIdNetwork[dgid]->m_static = statc;
dgIdNetwork[dgid]->m_rfHangTime = rfHangTime;
dgIdNetwork[dgid]->m_netHangTime = netHangTime;
*/
} else if (type == "Parrot") {
in_addr address = CUDPSocket::lookup((*it)->m_address);
unsigned int port = (*it)->m_port;
unsigned int local = (*it)->m_local;
if (address.s_addr != INADDR_NONE) {
CYSFNetwork* ysf = new CYSFNetwork(local, m_callsign, debug);
ysf->setDestination("PARROT", address, port);
dgIdNetwork[dgid] = ysf;
dgIdNetwork[dgid]->m_modes = YSF_DT_VD_MODE1 | YSF_DT_VD_MODE2 | YSF_DT_VOICE_FR_MODE | YSF_DT_DATA_FR_MODE;
dgIdNetwork[dgid]->m_static = statc;
dgIdNetwork[dgid]->m_rfHangTime = rfHangTime;
dgIdNetwork[dgid]->m_netHangTime = netHangTime;
}
} else if (type == "YSF2DMR") {
in_addr address = CUDPSocket::lookup((*it)->m_address);
unsigned int port = (*it)->m_port;
unsigned int local = (*it)->m_local;
if (address.s_addr != INADDR_NONE) {
CYSFNetwork* ysf = new CYSFNetwork(local, m_callsign, debug);
ysf->setDestination("YSF2DMR", address, port);
dgIdNetwork[dgid] = ysf;
dgIdNetwork[dgid]->m_modes = YSF_DT_VD_MODE1 | YSF_DT_VD_MODE2;
dgIdNetwork[dgid]->m_static = statc;
dgIdNetwork[dgid]->m_rfHangTime = rfHangTime;
dgIdNetwork[dgid]->m_netHangTime = netHangTime;
}
} else if (type == "YSF2NXDN") {
in_addr address = CUDPSocket::lookup((*it)->m_address);
unsigned int port = (*it)->m_port;
unsigned int local = (*it)->m_local;
if (address.s_addr != INADDR_NONE) {
CYSFNetwork* ysf = new CYSFNetwork(local, m_callsign, debug);
ysf->setDestination("YSF2NXDN", address, port);
dgIdNetwork[dgid] = ysf;
dgIdNetwork[dgid]->m_modes = YSF_DT_VD_MODE1 | YSF_DT_VD_MODE2;
dgIdNetwork[dgid]->m_static = statc;
dgIdNetwork[dgid]->m_rfHangTime = rfHangTime;
dgIdNetwork[dgid]->m_netHangTime = netHangTime;
}
} else if (type == "YSF2P25") {
in_addr address = CUDPSocket::lookup((*it)->m_address);
unsigned int port = (*it)->m_port;
unsigned int local = (*it)->m_local;
if (address.s_addr != INADDR_NONE) {
CYSFNetwork* ysf = new CYSFNetwork(local, m_callsign, debug);
ysf->setDestination("YSF2P25", address, port);
dgIdNetwork[dgid] = ysf;
dgIdNetwork[dgid]->m_modes = YSF_DT_VOICE_FR_MODE;
dgIdNetwork[dgid]->m_static = statc;
dgIdNetwork[dgid]->m_rfHangTime = rfHangTime;
dgIdNetwork[dgid]->m_netHangTime = netHangTime;
}
}
if (dgIdNetwork[dgid] != NULL) {
LogDebug("Loaded DG-ID %u", dgid);
bool ret = dgIdNetwork[dgid]->open();
if (!ret) {
delete dgIdNetwork[dgid];
dgIdNetwork[dgid] = NULL;
}
if (dgIdNetwork[dgid] != NULL && dgIdNetwork[dgid]->m_static) {
dgIdNetwork[dgid]->link();
dgIdNetwork[dgid]->link();
dgIdNetwork[dgid]->link();
}
}
}
createGPS();
CTimer inactivityTimer(1000U);
CStopWatch stopWatch;
stopWatch.start();
LogMessage("Starting DGIdGateway-%s", VERSION);
for (;;) {
unsigned char buffer[200U];
memset(buffer, 0U, 200U);
if (rptNetwork.read(0U, buffer) > 0U) {
if (::memcmp(buffer + 0U, "YSFD", 4U) == 0) {
CYSFFICH fich;
bool valid = fich.decode(buffer + 35U);
if (valid) {
unsigned char fi = fich.getFI();
unsigned char dt = fich.getDT();
unsigned char fn = fich.getFN();
unsigned char ft = fich.getFT();
unsigned char dgId = fich.getDGId();
if (dgId != 0U && dgId != currentDGId) {
if (dgIdNetwork[currentDGId] != NULL && !dgIdNetwork[currentDGId]->m_static) {
dgIdNetwork[currentDGId]->unlink();
dgIdNetwork[currentDGId]->unlink();
dgIdNetwork[currentDGId]->unlink();
}
if (dgIdNetwork[dgId] != NULL && !dgIdNetwork[dgId]->m_static) {
dgIdNetwork[dgId]->link();
dgIdNetwork[dgId]->link();
dgIdNetwork[dgId]->link();
}
LogDebug("DG-ID set to %u via RF", dgId);
currentDGId = dgId;
}
if (m_gps != NULL)
m_gps->data(buffer + 14U, buffer + 35U, fi, dt, fn, ft);
if (currentDGId != 0U && dgIdNetwork[currentDGId] != NULL) {
// Only allow the wanted modes through
if ((dgIdNetwork[currentDGId]->m_modes & dt) != 0U) {
dgIdNetwork[currentDGId]->write(currentDGId, buffer);
inactivityTimer.setTimeout(dgIdNetwork[currentDGId]->m_rfHangTime);
inactivityTimer.start();
}
}
}
if ((buffer[34U] & 0x01U) == 0x01U) {
if (m_gps != NULL)
m_gps->reset();
}
}
}
for (unsigned int i = 1U; i < 100U; i++) {
if (dgIdNetwork[i] != NULL) {
unsigned int len = dgIdNetwork[i]->read(i, buffer);
if (len > 0U && (i == currentDGId || currentDGId == 0U)) {
if (::memcmp(buffer + 0U, "YSFD", 4U) == 0) {
CYSFFICH fich;
bool valid = fich.decode(buffer + 35U);
if (valid) {
fich.setDGId(i);
fich.encode(buffer + 35U);
rptNetwork.write(0U, buffer);
inactivityTimer.setTimeout(dgIdNetwork[i]->m_netHangTime);
inactivityTimer.start();
if (currentDGId == 0U) {
LogDebug("DG-ID set to %u via Network", i);
currentDGId = i;
}
}
}
}
}
}
unsigned int ms = stopWatch.elapsed();
stopWatch.start();
rptNetwork.clock(ms);
for (unsigned int i = 0U; i < 100U; i++) {
if (dgIdNetwork[i] != NULL)
dgIdNetwork[i]->clock(ms);
}
if (m_writer != NULL)
m_writer->clock(ms);
inactivityTimer.clock(ms);
if (inactivityTimer.isRunning() && inactivityTimer.hasExpired()) {
if (dgIdNetwork[currentDGId] != NULL && !dgIdNetwork[currentDGId]->m_static) {
dgIdNetwork[currentDGId]->unlink();
dgIdNetwork[currentDGId]->unlink();
dgIdNetwork[currentDGId]->unlink();
}
}
LogDebug("DG-ID set to 0 via timeout");
currentDGId = 0U;
inactivityTimer.stop();
}
if (ms < 5U)
CThread::sleep(5U);
}
rptNetwork.close();
if (m_gps != NULL) {
m_writer->close();
delete m_writer;
delete m_gps;
}
for (unsigned int i = 1U; i < 100U; i++) {
if (dgIdNetwork[i] != NULL) {
dgIdNetwork[i]->unlink();
dgIdNetwork[i]->unlink();
dgIdNetwork[i]->unlink();
dgIdNetwork[i]->close();
delete dgIdNetwork[i];
}
}
::LogFinalise();
return 0;
}
void CDGIdGateway::createGPS()
{
if (!m_conf.getAPRSEnabled())
return;
std::string address = m_conf.getAPRSAddress();
unsigned int port = m_conf.getAPRSPort();
std::string suffix = m_conf.getAPRSSuffix();
bool debug = m_conf.getDebug();
m_writer = new CAPRSWriter(m_callsign, m_suffix, address, port, suffix, debug);
unsigned int txFrequency = m_conf.getTxFrequency();
unsigned int rxFrequency = m_conf.getRxFrequency();
std::string desc = m_conf.getAPRSDescription();
m_writer->setInfo(txFrequency, rxFrequency, desc);
bool enabled = m_conf.getGPSDEnabled();
if (enabled) {
std::string address = m_conf.getGPSDAddress();
std::string port = m_conf.getGPSDPort();
m_writer->setGPSDLocation(address, port);
} else {
float latitude = m_conf.getLatitude();
float longitude = m_conf.getLongitude();
int height = m_conf.getHeight();
m_writer->setStaticLocation(latitude, longitude, height);
}
bool ret = m_writer->open();
if (!ret) {
delete m_writer;
m_writer = NULL;
return;
}
m_gps = new CGPS(m_writer);
}
std::string CDGIdGateway::calculateLocator()
{
std::string locator;
float latitude = m_conf.getLatitude();
float longitude = m_conf.getLongitude();
if (latitude < -90.0F || latitude > 90.0F)
return "AA00AA";
if (longitude < -360.0F || longitude > 360.0F)
return "AA00AA";
latitude += 90.0F;
if (longitude > 180.0F)
longitude -= 360.0F;
if (longitude < -180.0F)
longitude += 360.0F;
longitude += 180.0F;
float lon = ::floor(longitude / 20.0F);
float lat = ::floor(latitude / 10.0F);
locator += 'A' + (unsigned int)lon;
locator += 'A' + (unsigned int)lat;
longitude -= lon * 20.0F;
latitude -= lat * 10.0F;
lon = ::floor(longitude / 2.0F);
lat = ::floor(latitude / 1.0F);
locator += '0' + (unsigned int)lon;
locator += '0' + (unsigned int)lat;
longitude -= lon * 2.0F;
latitude -= lat * 1.0F;
lon = ::floor(longitude / (2.0F / 24.0F));
lat = ::floor(latitude / (1.0F / 24.0F));
locator += 'A' + (unsigned int)lon;
locator += 'A' + (unsigned int)lat;
return locator;
}

@ -0,0 +1,152 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="RingBuffer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="StopWatch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Timer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="UDPSocket.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Version.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="YSFDefines.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Log.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="YSFGateway.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Conf.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="YSFFICH.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CRC.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Golay24128.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="YSFConvolution.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GPS.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="YSFPayload.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="WiresX.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Thread.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Sync.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Utils.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="APRSWriter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DTMF.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="YSFNetwork.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="YSFReflectors.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="FCSNetwork.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="StopWatch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Timer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="UDPSocket.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Log.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="YSFGateway.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Conf.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="YSFFICH.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CRC.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Golay24128.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="YSFConvolution.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GPS.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="YSFPayload.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="WiresX.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Thread.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Sync.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Utils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="APRSWriter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DTMF.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="YSFNetwork.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="YSFReflectors.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FCSNetwork.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

@ -0,0 +1,47 @@
/*
* Copyright (C) 2016,2017,2018,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
* 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.
*/
#if !defined(DGIdGateway_H)
#define DGIdGateway_H
#include "APRSWriter.h"
#include "Conf.h"
#include "GPS.h"
#include <string>
class CDGIdGateway
{
public:
CDGIdGateway(const std::string& configFile);
~CDGIdGateway();
int run();
private:
std::string m_callsign;
std::string m_suffix;
CConf m_conf;
CAPRSWriter* m_writer;
CGPS* m_gps;
std::string calculateLocator();
void createGPS();
};
#endif

@ -0,0 +1,138 @@
[General]
Callsign=G9BF
Suffix=RPT
# Suffix=ND
Id=1234567
RptAddress=127.0.0.1
RptPort=3200
LocalAddress=127.0.0.1
LocalPort=4200
RFHangTime=120
NetHangTime=120
Debug=0
Daemon=0
[Info]
RXFrequency=430475000
TXFrequency=439475000
Power=1
Latitude=0.0
Longitude=0.0
Height=0
Name=Nowhere
Description=Multi-Mode Repeater
[Log]
# Logging levels, 0=No logging
DisplayLevel=1
FileLevel=1
FilePath=.
FileRoot=DGIdGateway
[APRS]
Enable=0
Address=127.0.0.1
Port=8673
Description=APRS Description
Suffix=Y
[YSF Network]
Hosts=./YSFHosts.txt
RFHangTime=120
NetHangTime=60
Debug=0
[FCS Network]
RFHangTime=120
NetHangTime=60
Debug=0
[DGId=1]
# YSF Local Parrot
Type=Parrot
Static=1
Address=127.0.0.1
Port=42012
Local=42013
RFHangTime=30
NetHangTime=30
Debug=0
[DGId=10]
# Local YSF2DMR TG23590
Type=YSF2DMR
Static=1
Address=127.0.0.1
Port=42014
Local=42015
#RFHangTime=120
#NetHangTime=60
Debug=0
[DGId=11]
# Local YSF2DMR TG23510
Type=YSF2DMR
Static=1
Address=127.0.0.1
Port=42016
Local=42017
#RFHangTime=120
#NetHangTime=60
Debug=0
[DGId=20]
# Local YSF2NXDN TG65000
Type=YSF2NXDN
Static=1
Address=127.0.0.1
Port=42018
Local=42019
#RFHangTime=120
#NetHangTime=60
Debug=0
[DGId=30]
# Local YSF2P25 TG10200
Type=YSF2P25
Static=1
Address=127.0.0.1
Port=42020
Local=42021
#RFHangTime=120
#NetHangTime=60
Debug=0
[DGId=40]
# YSF Reflector CQ-UK
Type=YSF
Static=0
Name=0-0-CQ-UK-ROOM
Local=42023
#RFHangTime=120
#NetHangTime=60
Debug=0
[DGId=50]
# FCS Reflector FCS001-01
Type=FCS
Static=0
Name=FCS00101
Local=42025
#RFHangTime=120
#NetHangTime=60
Debug=0
[DGId=100]
# Local IMRS System Fusion Network
Type=IMRS
Destination=100,44.131.4.1
Destination=75,44.131.4.2
#RFHangTime=120
#NetHangTime=60
Debug=1
[GPSD]
Enable=0
Address=127.0.0.1
Port=2947

@ -0,0 +1,200 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{4F82857B-D2CC-48DC-91A8-6275BDD3081B}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>YSFGateway</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="APRSWriter.h" />
<ClInclude Include="Conf.h" />
<ClInclude Include="CRC.h" />
<ClInclude Include="DTMF.h" />
<ClInclude Include="FCSNetwork.h" />
<ClInclude Include="Golay24128.h" />
<ClInclude Include="GPS.h" />
<ClInclude Include="Log.h" />
<ClInclude Include="RingBuffer.h" />
<ClInclude Include="StopWatch.h" />
<ClInclude Include="Sync.h" />
<ClInclude Include="Thread.h" />
<ClInclude Include="Timer.h" />
<ClInclude Include="UDPSocket.h" />
<ClInclude Include="Utils.h" />
<ClInclude Include="Version.h" />
<ClInclude Include="WiresX.h" />
<ClInclude Include="YSFConvolution.h" />
<ClInclude Include="YSFDefines.h" />
<ClInclude Include="YSFFICH.h" />
<ClInclude Include="YSFGateway.h" />
<ClInclude Include="YSFNetwork.h" />
<ClInclude Include="YSFPayload.h" />
<ClInclude Include="YSFReflectors.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="APRSWriter.cpp" />
<ClCompile Include="Conf.cpp" />
<ClCompile Include="CRC.cpp" />
<ClCompile Include="DTMF.cpp" />
<ClCompile Include="FCSNetwork.cpp" />
<ClCompile Include="Golay24128.cpp" />
<ClCompile Include="GPS.cpp" />
<ClCompile Include="Log.cpp" />
<ClCompile Include="StopWatch.cpp" />
<ClCompile Include="Sync.cpp" />
<ClCompile Include="Thread.cpp" />
<ClCompile Include="Timer.cpp" />
<ClCompile Include="UDPSocket.cpp" />
<ClCompile Include="Utils.cpp" />
<ClCompile Include="WiresX.cpp" />
<ClCompile Include="YSFConvolution.cpp" />
<ClCompile Include="YSFFICH.cpp" />
<ClCompile Include="YSFGateway.cpp" />
<ClCompile Include="YSFNetwork.cpp" />
<ClCompile Include="YSFPayload.cpp" />
<ClCompile Include="YSFReflectors.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

@ -0,0 +1,25 @@
/*
* Copyright (C) 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
* 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 "DGIdNetwork.h"
CDGIdNetwork::~CDGIdNetwork()
{
}

@ -0,0 +1,52 @@
/*
* Copyright (C) 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
* 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 DGIdNetwork_H
#define DGIdNetwork_H
class CDGIdNetwork {
public:
virtual ~CDGIdNetwork() = 0;
virtual bool open() = 0;
virtual void link() = 0;
virtual void write(unsigned int dgId, const unsigned char* data) = 0;
virtual unsigned int read(unsigned int dgid, unsigned char* data) = 0;
virtual void clock(unsigned int ms) = 0;
virtual void unlink() = 0;
virtual void close() = 0;
// Allowed modes
unsigned char m_modes;
bool m_static;
unsigned int m_rfHangTime;
unsigned int m_netHangTime;
private:
};
#endif

@ -0,0 +1,252 @@
/*
* Copyright (C) 2009-2014,2016,2017,2018,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
* 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 "YSFDefines.h"
#include "FCSNetwork.h"
#include "Utils.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <cstring>
const char* FCS_VERSION = "MMDVM";
const unsigned int BUFFER_LENGTH = 200U;
CFCSNetwork::CFCSNetwork(const std::string& reflector, unsigned int port, const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, const std::string& locator, unsigned int id, bool debug) :
m_socket(port),
m_debug(debug),
m_address(),
m_ping(NULL),
m_info(NULL),
m_reflector(reflector),
m_print(),
m_buffer(1000U, "FCS Network Buffer"),
m_n(0U),
m_pingTimer(1000U, 0U, 800U),
m_resetTimer(1000U, 1U),
m_state(FCS_UNLINKED)
{
m_info = new unsigned char[100U];
::sprintf((char*)m_info, "%9u%9u%-6.6s%-12.12s%7u", rxFrequency, txFrequency, locator.c_str(), FCS_VERSION, id);
::memset(m_info + 43U, ' ', 57U);
m_ping = new unsigned char[25U];
::memcpy(m_ping + 0U, "PING", 4U);
::memset(m_ping + 4U, ' ', 6U);
::memcpy(m_ping + 4U, callsign.c_str(), callsign.size());
::memset(m_ping + 10U, 0x00U, 15U);
::memcpy(m_ping + 10U, reflector.c_str(), 8U);
}
CFCSNetwork::~CFCSNetwork()
{
delete[] m_info;
delete[] m_ping;
}
bool CFCSNetwork::open()
{
LogMessage("Resolving FCS00x addresses");
m_addresses["FCS001"] = CUDPSocket::lookup("fcs001.xreflector.net");
m_addresses["FCS002"] = CUDPSocket::lookup("fcs002.xreflector.net");
m_addresses["FCS003"] = CUDPSocket::lookup("fcs003.xreflector.net");
m_addresses["FCS004"] = CUDPSocket::lookup("fcs004.xreflector.net");
m_addresses["FCS005"] = CUDPSocket::lookup("fcs005.xreflector.net");
m_addresses["FCS222"] = CUDPSocket::lookup("fcs222.xreflector.net");
m_addresses["FCS224"] = CUDPSocket::lookup("fcs224.xreflector.net");
m_addresses["FCS232"] = CUDPSocket::lookup("fcs232.xreflector.net");
LogMessage("Opening FCS network connection");
return m_socket.open();
}
void CFCSNetwork::write(const unsigned char* data)
{
assert(data != NULL);
if (m_state != FCS_LINKED)
return;
unsigned char buffer[130U];
::memset(buffer + 0U, ' ', 130U);
::memcpy(buffer + 0U, data + 35U, 120U);
::memcpy(buffer + 121U, m_reflector.c_str(), 8U);
if (m_debug)
CUtils::dump(1U, "FCS Network Data Sent", buffer, 130U);
m_socket.write(buffer, 130U, m_address, FCS_PORT);
}
void CFCSNetwork::link()
{
if (m_state != FCS_LINKED) {
std::string name = m_reflector.substr(0U, 6U);
if (m_addresses.count(name) == 0U) {
LogError("Unknown FCS reflector - %s", name.c_str());
return;
}
m_address = m_addresses[name];
if (m_address.s_addr == INADDR_NONE) {
LogError("FCS reflector %s has no address", name.c_str());
return;
}
}
m_print = m_reflector.substr(0U, 6U) + "-" + m_reflector.substr(6U);
m_state = FCS_LINKING;
m_pingTimer.start();
writePing();
return true;
}
void CFCSNetwork::unlink()
{
if (m_state != FCS_LINKED)
return;
m_socket.write((unsigned char*)"CLOSE ", 11U, m_address, FCS_PORT);
}
void CFCSNetwork::clock(unsigned int ms)
{
m_pingTimer.clock(ms);
if (m_pingTimer.isRunning() && m_pingTimer.hasExpired()) {
writePing();
m_pingTimer.start();
}
m_resetTimer.clock(ms);
if (m_resetTimer.isRunning() && m_resetTimer.hasExpired()) {
m_n = 0U;
m_resetTimer.stop();
}
unsigned char buffer[BUFFER_LENGTH];
in_addr address;
unsigned int port;
int length = m_socket.read(buffer, BUFFER_LENGTH, address, port);
if (length <= 0)
return;
if (m_state == FCS_UNLINKED)
return;
if (address.s_addr != m_address.s_addr || port != FCS_PORT)
return;
if (m_debug)
CUtils::dump(1U, "FCS Network Data Received", buffer, length);
if (length == 7) {
if (m_state == FCS_LINKING)
LogMessage("Linked to %s", m_print.c_str());
m_state = FCS_LINKED;
writeInfo();
}
if (length == 10 && m_state == FCS_LINKING) {
LogMessage("Linked to %s", m_print.c_str());
m_state = FCS_LINKED;
writeInfo();
}
if (length == 7 || length == 10 || length == 130) {
unsigned char len = length;
m_buffer.addData(&len, 1U);
m_buffer.addData(buffer, len);
}
}
unsigned int CFCSNetwork::read(unsigned char* data)
{
assert(data != NULL);
if (m_buffer.isEmpty())
return 0U;
unsigned char len = 0U;
m_buffer.getData(&len, 1U);
// Pass pings up to the gateway to reset the lost timer.
if (len != 130U) {
m_buffer.getData(data, len);
::memset(data + 0U, ' ', 14U);
::memcpy(data + 0U, "YSFP", 4U);
::memcpy(data + 4U, m_print.c_str(), 8U);
return 14U;
}
m_resetTimer.start();
unsigned char buffer[130U];
m_buffer.getData(buffer, len);
::memset(data + 0U, ' ', 35U);
::memcpy(data + 0U, "YSFD", 4U);
::memcpy(data + 35U, buffer, 120U);
// Put the reflector name as the via callsign.
::memcpy(data + 4U, m_print.c_str(), 9U);
data[34U] = m_n;
m_n += 2U;
return 155U;
}
void CFCSNetwork::close()
{
m_socket.close();
LogMessage("Closing FCS network connection");
}
void CFCSNetwork::writeInfo()
{
if (m_state != FCS_LINKED)
return;
if (m_debug)
CUtils::dump(1U, "FCS Network Data Sent", m_info, 100U);
m_socket.write(m_info, 100U, m_address, FCS_PORT);
}
void CFCSNetwork::writePing()
{
if (m_state == FCS_UNLINKED)
return;
if (m_debug)
CUtils::dump(1U, "FCS Network Data Sent", m_ping, 25U);
m_socket.write(m_ping, 25U, m_address, FCS_PORT);
}

@ -0,0 +1,76 @@
/*
* Copyright (C) 2009-2014,2016,2017,2018,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
* 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 FCSNetwork_H
#define FCSNetwork_H
#include "DGIdNetwork.h"
#include "YSFDefines.h"
#include "UDPSocket.h"
#include "RingBuffer.h"
#include "Timer.h"
#include <cstdint>
#include <string>
#include <map>
enum FCS_STATE {
FCS_UNLINKED,
FCS_LINKING,
FCS_LINKED
};
class CFCSNetwork : public CDGIdNetwork {
public:
CFCSNetwork(const std::string& reflector, unsigned int port, const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, const std::string& locator, unsigned int id, bool debug);
virtual ~CFCSNetwork();
virtual bool open();
virtual void link();
virtual void write(unsigned int dgId, const unsigned char* data);
virtual unsigned int read(unsigned int dgId, unsigned char* data);
virtual void clock(unsigned int ms);
virtual void unlink();
virtual void close();
private:
CUDPSocket m_socket;
bool m_debug;
in_addr m_address;
unsigned char* m_ping;
unsigned char* m_info;
std::string m_reflector;
std::string m_print;
CRingBuffer<unsigned char> m_buffer;
std::map<std::string, in_addr> m_addresses;
unsigned char m_n;
CTimer m_pingTimer;
CTimer m_resetTimer;
FCS_STATE m_state;
void writeInfo();
void writePing();
};
#endif

@ -0,0 +1,678 @@
# FCS_Hosts.txt downloaded from http://www.pistar.uk/downloads/FCS_Hosts.txt
# Sourced from PiStar.UK Update Server
# File created at Tuesday 8th of May 2018 01:20:49 AM BST
FCS00100;Repeater;FCS001 - Repeater;;;
FCS00101;Deutschland;FCS001 - Deutschland;;;
FCS00102;World Wide ;FCS001 - World Wide ;;;
FCS00103;Switzerland;FCS001 - Switzerland;;;
FCS00104;Denmark;FCS001 - Denmark;;;
FCS00105;Great Britain;FCS001 - Great Britain;;;
FCS00106;United States of America;FCS001 - United States of America;;;
FCS00107;Netherlands;FCS001 - Netherlands;;;
FCS00108;South korea;FCS001 - South korea;;;
FCS00109;Austria;FCS001 - Austria;;;
FCS00110;Sweden;FCS001 - Sweden;;;
FCS00111;Belgium;FCS001 - Belgium;;;
FCS00112;Portugal;FCS001 - Portugal;;;
FCS00113;Norway;FCS001 - Norway;;;
FCS00114;Australia;FCS001 - Australia;;;
FCS00115;Test System;FCS001 - Test System;;;
FCS00116;Brazil;FCS001 - Brazil;;;
FCS00117;Canada;FCS001 - Canada;;;
FCS00118;Spain;FCS001 - Spain;;;
FCS00119;Czech;FCS001 - Czech;;;
FCS00120;Slovakia;FCS001 - Slovakia;;;
FCS00121;Japan;FCS001 - Japan;;;
FCS00122;THAILAND;FCS001 - THAILAND;;;
FCS00123;Bulgaria;FCS001 - Bulgaria;;;
FCS00124; United States of America2;FCS001 - United States of America2;;;
FCS00125;Hungary;FCS001 - Hungary;;;
FCS00126;Polen;FCS001 - Polen;;;
FCS00127;Italy2;FCS001 - Italy2;;;
FCS00128;Australia;FCS001 - Australia;;;
FCS00129;Canada;FCS001 - Canada;;;
FCS00130;Iwate001jp-net;FCS001 - Iwate001jp-net;;;
FCS00131;Hessen;FCS001 - Hessen;;;
FCS00132;Luxembourg;FCS001 - Luxembourg;;;
FCS00133;Franc;FCS001 - Franc;;;
FCS00134;Greece;FCS001 - Greece;;;
FCS00135;Mecklenburg-Vorpommern;FCS001 - Mecklenburg-Vorpommern;;;
FCS00136;Sendai;FCS001 - Sendai;;;
FCS00139;China;FCS001 - China;;;
FCS00140;Spain2;FCS001 - Spain2;;;
FCS00141;HB9DR;FCS001 - HB9DR;;;
FCS00142;Repeater Schweiz;FCS001 - Repeater Schweiz;;;
FCS00143;GL/GR Room Schweiz;FCS001 - GL/GR Room Schweiz;;;
FCS00144;Zuerich/Schweiz;FCS001 - Zuerich/Schweiz;;;
FCS00146;DL-NORDWEST;FCS001 - DL-NORDWEST;;;
FCS00147;Kurpfalz;FCS001 - Kurpfalz;;;
FCS00150;Canada;FCS001 - Canada;;;
FCS00156;Elbe-Weser;FCS001 - Elbe-Weser;;;
FCS00160;CATALUNYA;FCS001 - CATALUNYA;;;
FCS00166;Nord-Ostsee-Link;FCS001 - Nord-Ostsee-Link;;;
FCS00167;Baden-Pfalz;FCS001 - Baden-Pfalz;;;
FCS00169;Italy;FCS001 - Italy;;;
FCS00170;SoCal Link Society;FCS001 - SoCal Link Society;;;
FCS00171;ARGENTINA LINK;FCS001 - ARGENTINA LINK;;;
FCS00173;phillipines;FCS001 - phillipines;;;
FCS00180;Schleswig-Holstein;FCS001 - Schleswig-Holstein;;;
FCS00186;GAUCHOS DEL SUR;FCS001 - GAUCHOS DEL SUR;;;
FCS00187;Rhein-Main / Wetterau;FCS001 - Rhein-Main / Wetterau;;;
FCS00188;TIROLER OBERLAND;FCS001 - TIROLER OBERLAND;;;
FCS00189;OE9/Vorarlberg;FCS001 - OE9/Vorarlberg;;;
FCS00192;Dongle User OE;FCS001 - Dongle User OE;;;
FCS00198;C4FM OE8;FCS001 - C4FM OE8;;;
FCS00199;ECHO;FCS001 - ECHO;;;
FCS00200;TALK USA1;FCS002 - TALK USA1;;;
FCS00201;TALK USA2;FCS002 - TALK USA2;;;
FCS00202;Alabama;FCS002 - Alabama;;;
FCS00203;Alaska;FCS002 - Alaska;;;
FCS00204;Arizona;FCS002 - Arizona;;;
FCS00205;Arkansas;FCS002 - Arkansas;;;
FCS00206;California;FCS002 - California;;;
FCS00207;Colorado;FCS002 - Colorado;;;
FCS00208;Connecticut;FCS002 - Connecticut;;;
FCS00209;Delaware;FCS002 - Delaware;;;
FCS00210;Florida;FCS002 - Florida;;;
FCS00211;Georgia;FCS002 - Georgia;;;
FCS00212;Hawaii;FCS002 - Hawaii;;;
FCS00213;Idaho;FCS002 - Idaho;;;
FCS00214;Illinois;FCS002 - Illinois;;;
FCS00215;Indiana;FCS002 - Indiana;;;
FCS00216;Iowa;FCS002 - Iowa;;;
FCS00217;Kansas;FCS002 - Kansas;;;
FCS00218;Louisiana;FCS002 - Louisiana;;;
FCS00219;Maine;FCS002 - Maine;;;
FCS00220;Maryland;FCS002 - Maryland;;;
FCS00221;Massachusetts;FCS002 - Massachusetts;;;
FCS00222;Michigan;FCS002 - Michigan;;;
FCS00223;Minnesota;FCS002 - Minnesota;;;
FCS00224;Mississippi;FCS002 - Mississippi;;;
FCS00225;Missouri;FCS002 - Missouri;;;
FCS00226;Montana;FCS002 - Montana;;;
FCS00227;Nebraska;FCS002 - Nebraska;;;
FCS00228;Nevada;FCS002 - Nevada;;;
FCS00229;New Hampshire;FCS002 - New Hampshire;;;
FCS00230;New Jersey;FCS002 - New Jersey;;;
FCS00231;New Mexico;FCS002 - New Mexico;;;
FCS00232;New York;FCS002 - New York;;;
FCS00233;North Carolina;FCS002 - North Carolina;;;
FCS00234;North Dakota;FCS002 - North Dakota;;;
FCS00235;Ohio;FCS002 - Ohio;;;
FCS00236;Oklahoma;FCS002 - Oklahoma;;;
FCS00237;Oregon;FCS002 - Oregon;;;
FCS00238;Pennsylvania;FCS002 - Pennsylvania;;;
FCS00239;Rhode Island;FCS002 - Rhode Island;;;
FCS00240;South Carolina;FCS002 - South Carolina;;;
FCS00241;South Dakota;FCS002 - South Dakota;;;
FCS00242;Tennessee;FCS002 - Tennessee;;;
FCS00243;Texas;FCS002 - Texas;;;
FCS00244;Utah;FCS002 - Utah;;;
FCS00245;Vermont;FCS002 - Vermont;;;
FCS00246;Virginia;FCS002 - Virginia;;;
FCS00247;Washington;FCS002 - Washington;;;
FCS00248;West Virginia;FCS002 - West Virginia;;;
FCS00249;Wisconsin;FCS002 - Wisconsin;;;
FCS00250;Wyoming;FCS002 - Wyoming;;;
FCS00251;AREC;FCS002 - AREC;;;
FCS00253;Puerto Rico;FCS002 - Puerto Rico;;;
FCS00255;Central Alabama;FCS002 - Central Alabama;;;
FCS00256;Northeast Florida;FCS002 - Northeast Florida;;;
FCS00259;Public Safety ARG;FCS002 - Public Safety ARG;;;
FCS00260;AB2BH-AZ;FCS002 - AB2BH-AZ;;;
FCS00261;Belfast;FCS002 - Belfast;;;
FCS00269;Illinois Link;FCS002 - Illinois Link;;;
FCS00270;SoCal Link Society;FCS002 - SoCal Link Society;;;
FCS00271;SoCal Link Society;FCS002 - SoCal Link Society;;;
FCS00275;Wires-X Spain;FCS002 - Wires-X Spain;;;
FCS00280;Canada english;FCS002 - Canada english;;;
FCS00281;Canada francais;FCS002 - Canada francais;;;
FCS00284;NJ-NY RGNL;FCS002 - NJ-NY RGNL;;;
FCS00285;America-Ragchew (Wires-X);FCS002 - America-Ragchew (Wires-X);;;
FCS00288;KK4GAF;FCS002 - KK4GAF;;;
FCS00290;America Link WIRES-X;FCS002 - America Link WIRES-X;;;
FCS00291;CQ-UK WIRES-X;FCS002 - CQ-UK WIRES-X;;;
FCS00298;Software Test;FCS002 - Software Test;;;
FCS00299;ECHO;FCS002 - ECHO;;;
FCS00300;Group SYSOP chat ROOM;FCS003 - Group SYSOP chat ROOM;;;
FCS00301;FUSION-CANADA-FR;FCS003 - FUSION-CANADA-FR;;;
FCS00302;FUSION-QUEBEC-EN;FCS003 - FUSION-QUEBEC-EN;;;
FCS00303;Newfoundland and Labrador;FCS003 - Newfoundland and Labrador;;;
FCS00304;PEI;FCS003 - PEI;;;
FCS00305;New Brunswick;FCS003 - New Brunswick;;;
FCS00306;Ontario;FCS003 - Ontario;;;
FCS00307;Manitoba;FCS003 - Manitoba;;;
FCS00308;Saskatchewan;FCS003 - Saskatchewan;;;
FCS00309;Alberta;FCS003 - Alberta;;;
FCS00310;British Columbia;FCS003 - British Columbia;;;
FCS00311;Yukon / NWT / Nunavut;FCS003 - Yukon / NWT / Nunavut;;;
FCS00312;New England USA-East;FCS003 - New England USA-East;;;
FCS00314;NILECOMM;FCS003 - NILECOMM;;;
FCS00315;PA-Fl Link Society;FCS003 - PA-Fl Link Society;;;
FCS00316;San Diego;FCS003 - San Diego;;;
FCS00317;VA7GH Test Room;FCS003 - VA7GH Test Room;;;
FCS00318;ALOHA-HAWAII Wires-X;FCS003 - ALOHA-HAWAII Wires-X;;;
FCS00320;Irish Group;FCS003 - Irish Group;;;
FCS00321;CARS Nevada;FCS003 - CARS Nevada;;;
FCS00325;D.A.R.N.;FCS003 - D.A.R.N.;;;
FCS00328;SouthEast Mississippi;FCS003 - SouthEast Mississippi;;;
FCS00330;TeXaS-I35;FCS003 - TeXaS-I35;;;
FCS00333;Carolina Link;FCS003 - Carolina Link;;;
FCS00334;TEXAS - NEXUS;FCS003 - TEXAS - NEXUS;;;
FCS00335;Ohio NET;FCS003 - Ohio NET;;;
FCS00346;SAT-DRC;FCS003 - SAT-DRC;;;
FCS00350;LEO-ARC;FCS003 - LEO-ARC;;;
FCS00355;WINSCONSIN LINK;FCS003 - WINSCONSIN LINK;;;
FCS00358;Alabama Link;FCS003 - Alabama Link;;;
FCS00369;Midwest Hub;FCS003 - Midwest Hub;;;
FCS00370;SoCal Link Network;FCS003 - SoCal Link Network;;;
FCS00371;SoCal Link Society Café;FCS003 - SoCal Link Society Café;;;
FCS00372;ND6C-OpenSPOT Network;FCS003 - ND6C-OpenSPOT Network;;;
FCS00373;PINOYHAMS;FCS003 - PINOYHAMS;;;
FCS00376;Montivilliers C4FM / F4ETA;FCS003 - Montivilliers C4FM / F4ETA;;;
FCS00377;WXCTAC;FCS003 - WXCTAC;;;
FCS00385;Haïti System Fusion - HH2MJF;FCS003 - Haïti System Fusion - HH2MJF;;;
FCS00390;America Link Wires-X;FCS003 - America Link Wires-X;;;
FCS00397;DV4Home Test ROOM;FCS003 - DV4Home Test ROOM;;;
FCS00398;DV4mini Test ROOM;FCS003 - DV4mini Test ROOM;;;
FCS00399;ECHO;FCS003 - ECHO;;;
FCS00400;La-Espanola;FCS004 - La-Espanola;;;
FCS00401;EA-DISTRITO-1;FCS004 - EA-DISTRITO-1;;;
FCS00402;EA-DISTRITO-2;FCS004 - EA-DISTRITO-2;;;
FCS00403;EA-DISTRITO-3;FCS004 - EA-DISTRITO-3;;;
FCS00404;EA-DISTRITO-4;FCS004 - EA-DISTRITO-4;;;
FCS00405;EA-DISTRITO-5;FCS004 - EA-DISTRITO-5;;;
FCS00406;EA-DISTRITO-6;FCS004 - EA-DISTRITO-6;;;
FCS00407;EA-DISTRITO-7;FCS004 - EA-DISTRITO-7;;;
FCS00408;EA-DISTRITO-8;FCS004 - EA-DISTRITO-8;;;
FCS00409;EA-DISTRITO-9;FCS004 - EA-DISTRITO-9;;;
FCS00410;Republica Dominicana;FCS004 - Republica Dominicana;;;
FCS00411;DMR-TG314233-WiresX;FCS004 - DMR-TG314233-WiresX;;;
FCS00412;DVMEGA-WiresX-UK;FCS004 - DVMEGA-WiresX-UK;;;
FCS00413;HP-Panama-HUB;FCS004 - HP-Panama-HUB;;;
FCS00414;Guatemala;FCS004 - Guatemala;;;
FCS00415;Great-Britain;FCS004 - Great-Britain;;;
FCS00416;Miami-Latino;FCS004 - Miami-Latino;;;
FCS00417;Southern-Germany;FCS004 - Southern-Germany;;;
FCS00418;DCS018-Test;FCS004 - DCS018-Test;;;
FCS00419;Middle-Germany;FCS004 - Middle-Germany;;;
FCS00420;CQ-UK-WiresX-Room;FCS004 - CQ-UK-WiresX-Room;;;
FCS00421;Campania;FCS004 - Campania;;;
FCS00422;America-Ragchew-WiresX;FCS004 - America-Ragchew-WiresX;;;
FCS00423;Hertfordshire-RAYNET;FCS004 - Hertfordshire-RAYNET;;;
FCS00424;Fusion-Latina-WiresX-41067;FCS004 - Fusion-Latina-WiresX-41067;;;
FCS00425;Scotland;FCS004 - Scotland;;;
FCS00426;Oost-Nederland-Room;FCS004 - Oost-Nederland-Room;;;
FCS00427;Scout&Guide-JOTA;FCS004 - Scout&Guide-JOTA;;;
FCS00428;NWFG;FCS004 - NWFG;;;
FCS00429;D.A.R.C-USA;FCS004 - D.A.R.C-USA;;;
FCS00430;Irish-Scottish-Link;FCS004 - Irish-Scottish-Link;;;
FCS00431;UKHUB;FCS004 - UKHUB;;;
FCS00432;LincsLink;FCS004 - LincsLink;;;
FCS00433;Stockport-Room;FCS004 - Stockport-Room;;;
FCS00434;N8UKF-Repeater-Group;FCS004 - N8UKF-Repeater-Group;;;
FCS00435;WW-DX-Link-System;FCS004 - WW-DX-Link-System;;;
FCS00436;Essex-UK;FCS004 - Essex-UK;;;
FCS00437;Palmac;FCS004 - Palmac;;;
FCS00438;CQ-South-Wales;FCS004 - CQ-South-Wales;;;
FCS00439;Indiana-Link-SO;FCS004 - Indiana-Link-SO;;;
FCS00440;USA;FCS004 - USA;;;
FCS00441;Sevilla-TG21441;FCS004 - Sevilla-TG21441;;;
FCS00442;Eglisau-Amateur-Radio-Group;FCS004 - Eglisau-Amateur-Radio-Group;;;
FCS00443;Greenwich-Link-London;FCS004 - Greenwich-Link-London;;;
FCS00444;DMR-CHIRIQUi-TG7144;FCS004 - DMR-CHIRIQUi-TG7144;;;
FCS00445;NORTHSTAR;FCS004 - NORTHSTAR;;;
FCS00446;Kuwait-R;FCS004 - Kuwait-R;;;
FCS00447;Digital-Radio-Group-NZ;FCS004 - Digital-Radio-Group-NZ;;;
FCS00448;New-Zealand;FCS004 - New-Zealand;;;
FCS00449;MI5DAW;FCS004 - MI5DAW;;;
FCS00450;LEO-ARC;FCS004 - LEO-ARC;;;
FCS00451;RFIT;FCS004 - RFIT;;;
FCS00452;Seccion-Local-URE-Caceres;FCS004 - Seccion-Local-URE-Caceres;;;
FCS00453;Alaska-Last-Frontier;FCS004 - Alaska-Last-Frontier;;;
FCS00454;QSO-America;FCS004 - QSO-America;;;
FCS00455;Oldham-Radio-Club-Fusion-Group;FCS004 - Oldham-Radio-Club-Fusion-Group;;;
FCS00456;Nashville-HUB;FCS004 - Nashville-HUB;;;
FCS00457;Kapihan;FCS004 - Kapihan;;;
FCS00458;Catalina-Amateur-Repeater-Ass;FCS004 - Catalina-Amateur-Repeater-Ass;;;
FCS00459;Rhode-Island-Digital-Link;FCS004 - Rhode-Island-Digital-Link;;;
FCS00460;United-Kingdom-NET-WiresX;FCS004 - United-Kingdom-NET-WiresX;;;
FCS00461;21461BM-XLX051F-DSTAR-10302-NXDN-YSF-EA-SPAIN;FCS004 - 21461BM-XLX051F-DSTAR-10302-NXDN-YSF-EA-SPAIN;;;
FCS00462;Mabuhay-Canada-Link;FCS004 - Mabuhay-Canada-Link;;;
FCS00463;Uruguay-Link;FCS004 - Uruguay-Link;;;
FCS00464;WiresX 27464;FCS004 - WiresX 27464;;;
FCS00465;ADER;FCS004 - ADER;;;
FCS00466;nn;FCS004 - nn;;;
FCS00467;Minnesota-Nice;FCS004 - Minnesota-Nice;;;
FCS00468;GoldRunCa-Fusion-Group;FCS004 - GoldRunCa-Fusion-Group;;;
FCS00469;SE-Mississippi;FCS004 - SE-Mississippi;;;
FCS00470;DMR+-4370-Test;FCS004 - DMR+-4370-Test;;;
FCS00471;nn;FCS004 - nn;;;
FCS00472;nn;FCS004 - nn;;;
FCS00473;SOTA;FCS004 - SOTA;;;
FCS00474;DMR+-4374-Test;FCS004 - DMR+-4374-Test;;;
FCS00475;21369-KJ4VO-WORK-RM;FCS004 - 21369-KJ4VO-WORK-RM;;;
FCS00476;nn;FCS004 - nn;;;
FCS00477;HUBNet;FCS004 - HUBNet;;;
FCS00478;nn;FCS004 - nn;;;
FCS00479;CQ-California-Reflector;FCS004 - CQ-California-Reflector;;;
FCS00480;XLX925F;FCS004 - XLX925F;;;
FCS00481;nn;FCS004 - nn;;;
FCS00482;Netherlands;FCS004 - Netherlands;;;
FCS00483;CW-Ops;FCS004 - CW-Ops;;;
FCS00484;OMISS;FCS004 - OMISS;;;
FCS00485;XLX925E;FCS004 - XLX925E;;;
FCS00486;Argentina-Link;FCS004 - Argentina-Link;;;
FCS00487;URE-Salamanca;FCS004 - URE-Salamanca;;;
FCS00488;Philippine-Link;FCS004 - Philippine-Link;;;
FCS00489;Pinoy-Tambayan;FCS004 - Pinoy-Tambayan;;;
FCS00490;JOTA-SPAIN-2018;FCS004 - JOTA-SPAIN-2018;;;
FCS00491;SierraNorCal;FCS004 - SierraNorCal;;;
FCS00492;nn;FCS004 - nn;;;
FCS00493;nn;FCS004 - nn;;;
FCS00494;Almeria;FCS004 - Almeria;;;
FCS00495;Entrelaces-Latinos;FCS004 - Entrelaces-Latinos;;;
FCS00496;RC-Veleta;FCS004 - RC-Veleta;;;
FCS00497;APRS-Room;FCS004 - APRS-Room;;;
FCS00498;Hotspot-Test;FCS004 - Hotspot-Test;;;
FCS00499;ECHO;FCS004 - ECHO;;;
FCS00500;nn;FCS005 - nn;;;
FCS00501;nn;FCS005 - nn;;;
FCS00502;nn;FCS005 - nn;;;
FCS00503;nn;FCS005 - nn;;;
FCS00504;nn;FCS005 - nn;;;
FCS00505;nn;FCS005 - nn;;;
FCS00506;nn;FCS005 - nn;;;
FCS00507;nn;FCS005 - nn;;;
FCS00508;nn;FCS005 - nn;;;
FCS00509;nn;FCS005 - nn;;;
FCS00510;nn;FCS005 - nn;;;
FCS00511;nn;FCS005 - nn;;;
FCS00512;nn;FCS005 - nn;;;
FCS00513;nn;FCS005 - nn;;;
FCS00514;nn;FCS005 - nn;;;
FCS00515;DL-MultiNet-Bridge;FCS005 - DL-MultiNet-Bridge;;;
FCS00516;nn;FCS005 - nn;;;
FCS00517;nn;FCS005 - nn;;;
FCS00518;nn;FCS005 - nn;;;
FCS00519;nn;FCS005 - nn;;;
FCS00520;nn;FCS005 - nn;;;
FCS00521;nn;FCS005 - nn;;;
FCS00522;nn;FCS005 - nn;;;
FCS00523;nn;FCS005 - nn;;;
FCS00524;nn;FCS005 - nn;;;
FCS00525;nn;FCS005 - nn;;;
FCS00526;nn;FCS005 - nn;;;
FCS00527;nn;FCS005 - nn;;;
FCS00528;nn;FCS005 - nn;;;
FCS00529;nn;FCS005 - nn;;;
FCS00530;nn;FCS005 - nn;;;
FCS00531;nn;FCS005 - nn;;;
FCS00532;nn;FCS005 - nn;;;
FCS00533;nn;FCS005 - nn;;;
FCS00534;nn;FCS005 - nn;;;
FCS00535;nn;FCS005 - nn;;;
FCS00536;nn;FCS005 - nn;;;
FCS00537;nn;FCS005 - nn;;;
FCS00538;Niedersachsen;FCS005 - Niedersachsen;;;
FCS00539;nn;FCS005 - nn;;;
FCS00540;nn;FCS005 - nn;;;
FCS00541;nn;FCS005 - nn;;;
FCS00542;nn;FCS005 - nn;;;
FCS00543;nn;FCS005 - nn;;;
FCS00544;Pacific-Intertie-Net;FCS005 - Pacific-Intertie-Net;;;
FCS00545;nn;FCS005 - nn;;;
FCS00546;nn;FCS005 - nn;;;
FCS00547;nn;FCS005 - nn;;;
FCS00548;nn;FCS005 - nn;;;
FCS00549;nn;FCS005 - nn;;;
FCS00550;nn;FCS005 - nn;;;
FCS00551;nn;FCS005 - nn;;;
FCS00552;nn;FCS005 - nn;;;
FCS00553;nn;FCS005 - nn;;;
FCS00554;nn;FCS005 - nn;;;
FCS00555;nn;FCS005 - nn;;;
FCS00556;nn;FCS005 - nn;;;
FCS00557;nn;FCS005 - nn;;;
FCS00558;nn;FCS005 - nn;;;
FCS00559;nn;FCS005 - nn;;;
FCS00560;nn;FCS005 - nn;;;
FCS00561;nn;FCS005 - nn;;;
FCS00562;nn;FCS005 - nn;;;
FCS00563;nn;FCS005 - nn;;;
FCS00564;nn;FCS005 - nn;;;
FCS00565;nn;FCS005 - nn;;;
FCS00566;nn;FCS005 - nn;;;
FCS00567;nn;FCS005 - nn;;;
FCS00568;nn;FCS005 - nn;;;
FCS00569;nn;FCS005 - nn;;;
FCS00570;nn;FCS005 - nn;;;
FCS00571;nn;FCS005 - nn;;;
FCS00572;nn;FCS005 - nn;;;
FCS00573;nn;FCS005 - nn;;;
FCS00574;nn;FCS005 - nn;;;
FCS00575;nn;FCS005 - nn;;;
FCS00576;nn;FCS005 - nn;;;
FCS00577;nn;FCS005 - nn;;;
FCS00578;nn;FCS005 - nn;;;
FCS00579;nn;FCS005 - nn;;;
FCS00580;nn;FCS005 - nn;;;
FCS00581;nn;FCS005 - nn;;;
FCS00582;nn;FCS005 - nn;;;
FCS00583;nn;FCS005 - nn;;;
FCS00584;nn;FCS005 - nn;;;
FCS00585;nn;FCS005 - nn;;;
FCS00586;nn;FCS005 - nn;;;
FCS00587;nn;FCS005 - nn;;;
FCS00588;nn;FCS005 - nn;;;
FCS00589;nn;FCS005 - nn;;;
FCS00590;DMRplus-Chat;FCS005 - DMRplus-Chat;;;
FCS00591;nn;FCS005 - nn;;;
FCS00592;nn;FCS005 - nn;;;
FCS00593;nn;FCS005 - nn;;;
FCS00594;nn;FCS005 - nn;;;
FCS00595;nn;FCS005 - nn;;;
FCS00596;nn;FCS005 - nn;;;
FCS00597;nn;FCS005 - nn;;;
FCS00598;nn;FCS005 - nn;;;
FCS00599;ECHO;FCS005 - ECHO;;;
FCS22200;nn;FCS222 - nn;;;
FCS22201;nn;FCS222 - nn;;;
FCS22202;nn;FCS222 - nn;;;
FCS22203;nn;FCS222 - nn;;;
FCS22204;nn;FCS222 - nn;;;
FCS22205;nn;FCS222 - nn;;;
FCS22206;nn;FCS222 - nn;;;
FCS22207;nn;FCS222 - nn;;;
FCS22208;nn;FCS222 - nn;;;
FCS22209;nn;FCS222 - nn;;;
FCS22210;nn;FCS222 - nn;;;
FCS22211;nn;FCS222 - nn;;;
FCS22212;nn;FCS222 - nn;;;
FCS22213;nn;FCS222 - nn;;;
FCS22214;nn;FCS222 - nn;;;
FCS22215;nn;FCS222 - nn;;;
FCS22216;nn;FCS222 - nn;;;
FCS22217;Netherlands;FCS222 - Netherlands;;;
FCS22218;nn;FCS222 - nn;;;
FCS22219;nn;FCS222 - nn;;;
FCS22220;D-A-CH;FCS222 - D-A-CH;;;
FCS22221;nn;FCS222 - nn;;;
FCS22222;Italy;FCS222 - Italy;;;
FCS22223;nn;FCS222 - nn;;;
FCS22224;Spain;FCS222 - Spain;;;
FCS22225;nn;FCS222 - nn;;;
FCS22226;Poland;FCS222 - Poland;;;
FCS22227;nn;FCS222 - nn;;;
FCS22228;Switzerland;FCS222 - Switzerland;;;
FCS22229;nn;FCS222 - nn;;;
FCS22230;nn;FCS222 - nn;;;
FCS22231;nn;FCS222 - nn;;;
FCS22232;Austria;FCS222 - Austria;;;
FCS22233;nn;FCS222 - nn;;;
FCS22234;nn;FCS222 - nn;;;
FCS22235;nn;FCS222 - nn;;;
FCS22236;nn;FCS222 - nn;;;
FCS22237;nn;FCS222 - nn;;;
FCS22238;nn;FCS222 - nn;;;
FCS22239;nn;FCS222 - nn;;;
FCS22240;nn;FCS222 - nn;;;
FCS22241;nn;FCS222 - nn;;;
FCS22242;nn;FCS222 - nn;;;
FCS22243;nn;FCS222 - nn;;;
FCS22244;nn;FCS222 - nn;;;
FCS22245;nn;FCS222 - nn;;;
FCS22246;nn;FCS222 - nn;;;
FCS22247;nn;FCS222 - nn;;;
FCS22248;nn;FCS222 - nn;;;
FCS22249;nn;FCS222 - nn;;;
FCS22250;nn;FCS222 - nn;;;
FCS22251;nn;FCS222 - nn;;;
FCS22252;nn;FCS222 - nn;;;
FCS22253;nn;FCS222 - nn;;;
FCS22254;nn;FCS222 - nn;;;
FCS22255;nn;FCS222 - nn;;;
FCS22256;nn;FCS222 - nn;;;
FCS22257;nn;FCS222 - nn;;;
FCS22258;nn;FCS222 - nn;;;
FCS22259;nn;FCS222 - nn;;;
FCS22260;nn;FCS222 - nn;;;
FCS22261;nn;FCS222 - nn;;;
FCS22262;Germany;FCS222 - Germany;;;
FCS22263;nn;FCS222 - nn;;;
FCS22264;nn;FCS222 - nn;;;
FCS22265;nn;FCS222 - nn;;;
FCS22266;nn;FCS222 - nn;;;
FCS22267;nn;FCS222 - nn;;;
FCS22268;nn;FCS222 - nn;;;
FCS22269;nn;FCS222 - nn;;;
FCS22270;nn;FCS222 - nn;;;
FCS22271;nn;FCS222 - nn;;;
FCS22272;nn;FCS222 - nn;;;
FCS22273;nn;FCS222 - nn;;;
FCS22274;nn;FCS222 - nn;;;
FCS22275;nn;FCS222 - nn;;;
FCS22276;nn;FCS222 - nn;;;
FCS22277;nn;FCS222 - nn;;;
FCS22278;nn;FCS222 - nn;;;
FCS22279;nn;FCS222 - nn;;;
FCS22280;nn;FCS222 - nn;;;
FCS22281;nn;FCS222 - nn;;;
FCS22282;nn;FCS222 - nn;;;
FCS22283;nn;FCS222 - nn;;;
FCS22284;nn;FCS222 - nn;;;
FCS22285;nn;FCS222 - nn;;;
FCS22286;nn;FCS222 - nn;;;
FCS22287;nn;FCS222 - nn;;;
FCS22288;nn;FCS222 - nn;;;
FCS22289;nn;FCS222 - nn;;;
FCS22290;nn;FCS222 - nn;;;
FCS22291;nn;FCS222 - nn;;;
FCS22292;nn;FCS222 - nn;;;
FCS22293;nn;FCS222 - nn;;;
FCS22294;nn;FCS222 - nn;;;
FCS22295;nn;FCS222 - nn;;;
FCS22296;nn;FCS222 - nn;;;
FCS22297;nn;FCS222 - nn;;;
FCS22298;nn;FCS222 - nn;;;
FCS22299;ECHO;FCS222 - ECHO;;;
FCS22400;nn;FCS224 - nn;;;
FCS22401;nn;FCS224 - nn;;;
FCS22402;nn;FCS224 - nn;;;
FCS22403;nn;FCS224 - nn;;;
FCS22404;nn;FCS224 - nn;;;
FCS22405;nn;FCS224 - nn;;;
FCS22406;nn;FCS224 - nn;;;
FCS22407;nn;FCS224 - nn;;;
FCS22408;nn;FCS224 - nn;;;
FCS22409;nn;FCS224 - nn;;;
FCS22410;nn;FCS224 - nn;;;
FCS22411;nn;FCS224 - nn;;;
FCS22412;nn;FCS224 - nn;;;
FCS22413;nn;FCS224 - nn;;;
FCS22414;2X;FCS224 - 2X;;;
FCS22415;nn;FCS224 - nn;;;
FCS22416;nn;FCS224 - nn;;;
FCS22417;Netherlands;FCS224 - Netherlands;;;
FCS22418;nn;FCS224 - nn;;;
FCS22419;nn;FCS224 - nn;;;
FCS22420;D-A-CH;FCS224 - D-A-CH;;;
FCS22421;nn;FCS224 - nn;;;
FCS22422;Italy;FCS224 - Italy;;;
FCS22423;nn;FCS224 - nn;;;
FCS22424;Spain;FCS224 - Spain;;;
FCS22425;nn;FCS224 - nn;;;
FCS22426;Poland;FCS224 - Poland;;;
FCS22427;nn;FCS224 - nn;;;
FCS22428;Switzerland;FCS224 - Switzerland;;;
FCS22429;nn;FCS224 - nn;;;
FCS22430;nn;FCS224 - nn;;;
FCS22431;nn;FCS224 - nn;;;
FCS22432;Austria;FCS224 - Austria;;;
FCS22433;nn;FCS224 - nn;;;
FCS22434;nn;FCS224 - nn;;;
FCS22435;nn;FCS224 - nn;;;
FCS22436;nn;FCS224 - nn;;;
FCS22437;nn;FCS224 - nn;;;
FCS22438;nn;FCS224 - nn;;;
FCS22439;nn;FCS224 - nn;;;
FCS22440;nn;FCS224 - nn;;;
FCS22441;nn;FCS224 - nn;;;
FCS22442;nn;FCS224 - nn;;;
FCS22443;nn;FCS224 - nn;;;
FCS22444;nn;FCS224 - nn;;;
FCS22445;nn;FCS224 - nn;;;
FCS22446;nn;FCS224 - nn;;;
FCS22447;nn;FCS224 - nn;;;
FCS22448;nn;FCS224 - nn;;;
FCS22449;nn;FCS224 - nn;;;
FCS22450;nn;FCS224 - nn;;;
FCS22451;nn;FCS224 - nn;;;
FCS22452;nn;FCS224 - nn;;;
FCS22453;nn;FCS224 - nn;;;
FCS22454;nn;FCS224 - nn;;;
FCS22455;nn;FCS224 - nn;;;
FCS22456;nn;FCS224 - nn;;;
FCS22457;nn;FCS224 - nn;;;
FCS22458;nn;FCS224 - nn;;;
FCS22459;nn;FCS224 - nn;;;
FCS22460;nn;FCS224 - nn;;;
FCS22461;nn;FCS224 - nn;;;
FCS22462;Germany;FCS224 - Germany;;;
FCS22463;nn;FCS224 - nn;;;
FCS22464;nn;FCS224 - nn;;;
FCS22465;nn;FCS224 - nn;;;
FCS22466;nn;FCS224 - nn;;;
FCS22467;nn;FCS224 - nn;;;
FCS22468;nn;FCS224 - nn;;;
FCS22469;nn;FCS224 - nn;;;
FCS22470;nn;FCS224 - nn;;;
FCS22471;nn;FCS224 - nn;;;
FCS22472;nn;FCS224 - nn;;;
FCS22473;nn;FCS224 - nn;;;
FCS22474;nn;FCS224 - nn;;;
FCS22475;nn;FCS224 - nn;;;
FCS22476;nn;FCS224 - nn;;;
FCS22477;nn;FCS224 - nn;;;
FCS22478;2X;FCS224 - 2X;;;
FCS22479;nn;FCS224 - nn;;;
FCS22480;TST;FCS224 - TST;;;
FCS22481;nn;FCS224 - nn;;;
FCS22482;nn;FCS224 - nn;;;
FCS22483;nn;FCS224 - nn;;;
FCS22484;nn;FCS224 - nn;;;
FCS22485;nn;FCS224 - nn;;;
FCS22486;nn;FCS224 - nn;;;
FCS22487;nn;FCS224 - nn;;;
FCS22488;nn;FCS224 - nn;;;
FCS22489;nn;FCS224 - nn;;;
FCS22490;nn;FCS224 - nn;;;
FCS22491;nn;FCS224 - nn;;;
FCS22492;nn;FCS224 - nn;;;
FCS22493;nn;FCS224 - nn;;;
FCS22494;nn;FCS224 - nn;;;
FCS22495;nn;FCS224 - nn;;;
FCS22496;nn;FCS224 - nn;;;
FCS22497;nn;FCS224 - nn;;;
FCS22498;nn;FCS224 - nn;;;
FCS22499;ECHO;FCS224 - ECHO;;;
FCS23200;nn;FCS232 - nn;;;
FCS23201;2X;FCS232 - 2X;;;
FCS23202;nn;FCS232 - nn;;;
FCS23203;nn;FCS232 - nn;;;
FCS23204;2X;FCS232 - 2X;;;
FCS23205;2X;FCS232 - 2X;;;
FCS23206;2X;FCS232 - 2X;;;
FCS23207;2X;FCS232 - 2X;;;
FCS23208;2X;FCS232 - 2X;;;
FCS23209;nn;FCS232 - nn;;;
FCS23210;2X;FCS232 - 2X;;;
FCS23211;2X;FCS232 - 2X;;;
FCS23212;2X;FCS232 - 2X;;;
FCS23213;2X;FCS232 - 2X;;;
FCS23214;nn;FCS232 - nn;;;
FCS23215;nn;FCS232 - nn;;;
FCS23216;nn;FCS232 - nn;;;
FCS23217;Netherlands;FCS232 - Netherlands;;;
FCS23218;nn;FCS232 - nn;;;
FCS23219;nn;FCS232 - nn;;;
FCS23220;D-A-CH;FCS232 - D-A-CH;;;
FCS23221;nn;FCS232 - nn;;;
FCS23222;Italy;FCS232 - Italy;;;
FCS23223;nn;FCS232 - nn;;;
FCS23224;nn;FCS232 - nn;;;
FCS23225;nn;FCS232 - nn;;;
FCS23226;Poland;FCS232 - Poland;;;
FCS23227;nn;FCS232 - nn;;;
FCS23228;Switzerland;FCS232 - Switzerland;;;
FCS23229;nn;FCS232 - nn;;;
FCS23230;nn;FCS232 - nn;;;
FCS23231;nn;FCS232 - nn;;;
FCS23232;Austria;FCS232 - Austria;;;
FCS23233;nn;FCS232 - nn;;;
FCS23234;nn;FCS232 - nn;;;
FCS23235;nn;FCS232 - nn;;;
FCS23236;nn;FCS232 - nn;;;
FCS23237;nn;FCS232 - nn;;;
FCS23238;nn;FCS232 - nn;;;
FCS23239;nn;FCS232 - nn;;;
FCS23240;nn;FCS232 - nn;;;
FCS23241;nn;FCS232 - nn;;;
FCS23242;nn;FCS232 - nn;;;
FCS23243;nn;FCS232 - nn;;;
FCS23244;nn;FCS232 - nn;;;
FCS23245;nn;FCS232 - nn;;;
FCS23246;nn;FCS232 - nn;;;
FCS23247;nn;FCS232 - nn;;;
FCS23248;nn;FCS232 - nn;;;
FCS23249;nn;FCS232 - nn;;;
FCS23250;nn;FCS232 - nn;;;
FCS23251;nn;FCS232 - nn;;;
FCS23252;nn;FCS232 - nn;;;
FCS23253;nn;FCS232 - nn;;;
FCS23254;nn;FCS232 - nn;;;
FCS23255;nn;FCS232 - nn;;;
FCS23256;nn;FCS232 - nn;;;
FCS23257;nn;FCS232 - nn;;;
FCS23258;nn;FCS232 - nn;;;
FCS23259;nn;FCS232 - nn;;;
FCS23260;nn;FCS232 - nn;;;
FCS23261;nn;FCS232 - nn;;;
FCS23262;Germany;FCS232 - Germany;;;
FCS23263;nn;FCS232 - nn;;;
FCS23264;nn;FCS232 - nn;;;
FCS23265;nn;FCS232 - nn;;;
FCS23266;nn;FCS232 - nn;;;
FCS23267;nn;FCS232 - nn;;;
FCS23268;nn;FCS232 - nn;;;
FCS23269;nn;FCS232 - nn;;;
FCS23270;nn;FCS232 - nn;;;
FCS23271;2X;FCS232 - 2X;;;
FCS23272;nn;FCS232 - nn;;;
FCS23273;2X;FCS232 - 2X;;;
FCS23274;nn;FCS232 - nn;;;
FCS23275;nn;FCS232 - nn;;;
FCS23276;2X;FCS232 - 2X;;;
FCS23277;2X;FCS232 - 2X;;;
FCS23278;nn;FCS232 - nn;;;
FCS23279;nn;FCS232 - nn;;;
FCS23280;TST;FCS232 - TST;;;
FCS23281;OE-TEST;FCS232 - OE-TEST;;;
FCS23282;T2;FCS232 - T2;;;
FCS23283;T3;FCS232 - T3;;;
FCS23284;nn;FCS232 - nn;;;
FCS23285;nn;FCS232 - nn;;;
FCS23286;nn;FCS232 - nn;;;
FCS23287;nn;FCS232 - nn;;;
FCS23288;nn;FCS232 - nn;;;
FCS23289;nn;FCS232 - nn;;;
FCS23290;nn;FCS232 - nn;;;
FCS23291;OE-1;FCS232 - OE-1;;;
FCS23292;nn;FCS232 - nn;;;
FCS23293;OE-3;FCS232 - OE-3;;;
FCS23294;nn;FCS232 - nn;;;
FCS23295;nn;FCS232 - nn;;;
FCS23296;nn;FCS232 - nn;;;
FCS23297;nn;FCS232 - nn;;;
FCS23298;OE-8;FCS232 - OE-8;;;
FCS23299;ECHO;FCS232 - ECHO;;;

@ -0,0 +1,272 @@
/*
* Copyright (C) 2016,2017,2018 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 "GPS.h"
#include "YSFPayload.h"
#include "YSFDefines.h"
#include "Utils.h"
#include "CRC.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <cstring>
const unsigned char SHRT_GPS[] = {0x22U, 0x62U};
const unsigned char LONG_GPS[] = {0x47U, 0x64U};
CGPS::CGPS(CAPRSWriter* writer) :
m_writer(writer),
m_buffer(NULL),
m_sent(false)
{
assert(writer != NULL);
m_buffer = new unsigned char[300U];
}
CGPS::~CGPS()
{
delete[] m_buffer;
}
void CGPS::data(const unsigned char* source, const unsigned char* data, unsigned char fi, unsigned char dt, unsigned char fn, unsigned char ft)
{
if (m_sent)
return;
if (fi != YSF_FI_COMMUNICATIONS)
return;
CYSFPayload payload;
if (dt == YSF_DT_VD_MODE1) {
if (fn == 0U || fn == 1U || fn == 2U)
return;
bool valid = payload.readVDMode1Data(data, m_buffer + (fn - 3U) * 20U);
if (!valid)
return;
if (fn == ft) {
bool valid = false;
// Find the end marker
for (unsigned int i = (fn - 2U) * 20U; i > 0U; i--) {
if (m_buffer[i] == 0x03U) {
unsigned char crc = CCRC::addCRC(m_buffer, i + 1U);
if (crc == m_buffer[i + 1U])
valid = true;
break;
}
}
if (valid) {
if (::memcmp(m_buffer + 1U, SHRT_GPS, 2U) == 0) {
CUtils::dump("Short GPS data received", m_buffer, (fn - 2U) * 20U);
transmitGPS(source);
}
if (::memcmp(m_buffer + 1U, LONG_GPS, 2U) == 0) {
CUtils::dump("Long GPS data received", m_buffer, (fn - 2U) * 20U);
transmitGPS(source);
}
m_sent = true;
}
}
} else if (dt == YSF_DT_VD_MODE2) {
if (fn != 6U && fn != 7U)
return;
bool valid = payload.readVDMode2Data(data, m_buffer + (fn - 6U) * 10U);
if (!valid)
return;
if (fn == ft) {
bool valid = false;
// Find the end marker
for (unsigned int i = (fn - 5U) * 10U; i > 0U; i--) {
if (m_buffer[i] == 0x03U) {
unsigned char crc = CCRC::addCRC(m_buffer, i + 1U);
if (crc == m_buffer[i + 1U])
valid = true;
break;
}
}
if (valid) {
if (::memcmp(m_buffer + 1U, SHRT_GPS, 2U) == 0) {
CUtils::dump("Short GPS data received", m_buffer, (fn - 5U) * 10U);
transmitGPS(source);
}
if (::memcmp(m_buffer + 1U, LONG_GPS, 2U) == 0) {
CUtils::dump("Long GPS data received", m_buffer, (fn - 5U) * 10U);
transmitGPS(source);
}
m_sent = true;
}
}
}
}
void CGPS::reset()
{
m_sent = false;
}
void CGPS::transmitGPS(const unsigned char* source)
{
assert(m_writer != NULL);
// We don't know who its from!
if (::memcmp(source, " ", YSF_CALLSIGN_LENGTH) == 0)
return;
for (unsigned int i = 5U; i < 11U; i++) {
unsigned char b = m_buffer[i] & 0xF0U;
if (b != 0x50U && b != 0x30U)
return; // error/unknown
}
unsigned int tens = m_buffer[5U] & 0x0FU;
unsigned int units = m_buffer[6U] & 0x0FU;
unsigned int lat_deg = (tens * 10U) + units;
if (tens > 9U || units > 9U || lat_deg > 89U)
return; // error/unknown
tens = m_buffer[7U] & 0x0FU;
units = m_buffer[8U] & 0x0FU;
unsigned int lat_min = (tens * 10U) + units;
if (tens > 9U || units > 9U || lat_min > 59U)
return; // error/unknown
tens = m_buffer[9U] & 0x0FU;
units = m_buffer[10U] & 0x0FU;
unsigned int lat_min_frac = (tens * 10U) + units;
if (tens > 9U || units > 10U || lat_min_frac > 99U) // units > 10 ??? .. more buggy Yaesu firmware ?
return; // error/unknown
int lat_dir;
unsigned char b = m_buffer[8U] & 0xF0U; // currently a guess
if (b == 0x50U)
lat_dir = 1; // N
else if (b == 0x30U)
lat_dir = -1; // S
else
return; // error/unknown
unsigned int lon_deg;
b = m_buffer[9U] & 0xF0U;
if (b == 0x50U) {
// lon deg 0 to 9, and 100 to 179
b = m_buffer[11U];
if (b >= 0x76U && b <= 0x7FU)
lon_deg = b - 0x76U; // 0 to 9
else if (b >= 0x6CU && b <= 0x75U)
lon_deg = 100U + (b - 0x6CU); // 100 to 109
else if (b >= 0x26U && b <= 0x6BU)
lon_deg = 110U + (b - 0x26U); // 110 to 179
else
return; // error/unknown
} else if (b == 0x30U) {
// lon deg 10 to 99
b = m_buffer[11U];
if (b >= 0x26U && b <= 0x7FU)
lon_deg = 10U + (b - 0x26U); // 10 to 99
else
return; // error/unknown
} else {
return; // error/unknown
}
unsigned int lon_min;
b = m_buffer[12U];
if (b >= 0x58U && b <= 0x61U)
lon_min = b - 0x58U; // 0 to 9
else if (b >= 0x26U && b <= 0x57U)
lon_min = 10U + (b - 0x26U); // 10 to 59
else
return; // error/unknown
unsigned int lon_min_frac;
b = m_buffer[13U];
if (b >= 0x1CU && b <= 0x7FU)
lon_min_frac = b - 0x1CU;
else
return; // error/unknown
int lon_dir;
b = m_buffer[10U] & 0xF0U;
if (b == 0x30U)
lon_dir = 1; // E
else if (b == 0x50U)
lon_dir = -1; // W
else
return; // error/unknown
unsigned int lat_sec = lat_min_frac * 60U;
lat_sec = (lat_sec + (lat_sec % 100U)) / 100U; // with rounding
unsigned int lon_sec = lon_min_frac * 60U;
lon_sec = (lon_sec + (lon_sec % 100U)) / 100U; // with rounding
// >= 0 is north, < 0 is south
float latitude = lat_deg + ((lat_min + ((float)lat_min_frac * 0.01F)) * (1.0F / 60.0F));
latitude *= lat_dir;
// >= 0 is east, < 0 is west
float longitude = lon_deg + ((lon_min + ((float)lon_min_frac * 0.01F)) * (1.0F / 60.0F));
longitude *= lon_dir;
char radio[10U];
switch (m_buffer[4U]) {
case 0x24U:
::strcpy(radio, "FT-1D");
break;
case 0x25U:
::strcpy(radio, "FTM-400D");
break;
case 0x26U:
::strcpy(radio, "DR-1X");
break;
case 0x28U:
::strcpy(radio, "FT-2D");
break;
case 0x29U:
::strcpy(radio, "FTM-100D");
break;
case 0x30U:
::strcpy(radio, "FT-3D");
break;
default:
::sprintf(radio, "0x%02X", m_buffer[4U]);
break;
}
LogMessage("GPS Position from %10.10s of radio=%s lat=%f long=%f", source, radio, latitude, longitude);
m_writer->write(source, radio, m_buffer[4U], latitude, longitude);
m_sent = true;
}

@ -0,0 +1,43 @@
/*
* Copyright (C) 2016,2017,2018 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.
*/
#if !defined(GPS_H)
#define GPS_H
#include "APRSWriter.h"
#include <string>
class CGPS {
public:
CGPS(CAPRSWriter* writer);
~CGPS();
void data(const unsigned char* source, const unsigned char* data, unsigned char fi, unsigned char dt, unsigned char fn, unsigned char ft);
void reset();
private:
CAPRSWriter* m_writer;
unsigned char* m_buffer;
bool m_sent;
void transmitGPS(const unsigned char* source);
};
#endif

File diff suppressed because it is too large Load Diff

@ -0,0 +1,32 @@
/*
* Copyright (C) 2010,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 Golay24128_H
#define Golay24128_H
class CGolay24128 {
public:
static unsigned int encode23127(unsigned int data);
static unsigned int encode24128(unsigned int data);
static unsigned int decode23127(unsigned int code);
static unsigned int decode24128(unsigned int code);
static unsigned int decode24128(unsigned char* bytes);
};
#endif

@ -0,0 +1,136 @@
/*
* Copyright (C) 2015,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 "Log.h"
#if defined(_WIN32) || defined(_WIN64)
#include <Windows.h>
#else
#include <sys/time.h>
#endif
#include <cstdio>
#include <cstdlib>
#include <cstdarg>
#include <ctime>
#include <cassert>
#include <cstring>
static unsigned int m_fileLevel = 2U;
static std::string m_filePath;
static std::string m_fileRoot;
static FILE* m_fpLog = NULL;
static unsigned int m_displayLevel = 2U;
static struct tm m_tm;
static char LEVELS[] = " DMIWEF";
static bool LogOpen()
{
if (m_fileLevel == 0U)
return true;
time_t now;
::time(&now);
struct tm* tm = ::gmtime(&now);
if (tm->tm_mday == m_tm.tm_mday && tm->tm_mon == m_tm.tm_mon && tm->tm_year == m_tm.tm_year) {
if (m_fpLog != NULL)
return true;
} else {
if (m_fpLog != NULL)
::fclose(m_fpLog);
}
char filename[100U];
#if defined(_WIN32) || defined(_WIN64)
::sprintf(filename, "%s\\%s-%04d-%02d-%02d.log", m_filePath.c_str(), m_fileRoot.c_str(), tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
#else
::sprintf(filename, "%s/%s-%04d-%02d-%02d.log", m_filePath.c_str(), m_fileRoot.c_str(), tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
#endif
m_fpLog = ::fopen(filename, "a+t");
m_tm = *tm;
return m_fpLog != NULL;
}
bool LogInitialise(const std::string& filePath, const std::string& fileRoot, unsigned int fileLevel, unsigned int displayLevel)
{
m_filePath = filePath;
m_fileRoot = fileRoot;
m_fileLevel = fileLevel;
m_displayLevel = displayLevel;
return ::LogOpen();
}
void LogFinalise()
{
if (m_fpLog != NULL)
::fclose(m_fpLog);
}
void Log(unsigned int level, const char* fmt, ...)
{
assert(fmt != NULL);
char buffer[300U];
#if defined(_WIN32) || defined(_WIN64)
SYSTEMTIME st;
::GetSystemTime(&st);
::sprintf(buffer, "%c: %04u-%02u-%02u %02u:%02u:%02u.%03u ", LEVELS[level], st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
#else
struct timeval now;
::gettimeofday(&now, NULL);
struct tm* tm = ::gmtime(&now.tv_sec);
::sprintf(buffer, "%c: %04d-%02d-%02d %02d:%02d:%02d.%03lu ", LEVELS[level], tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, now.tv_usec / 1000U);
#endif
va_list vl;
va_start(vl, fmt);
::vsprintf(buffer + ::strlen(buffer), fmt, vl);
va_end(vl);
if (level >= m_fileLevel && m_fileLevel != 0U) {
bool ret = ::LogOpen();
if (!ret)
return;
::fprintf(m_fpLog, "%s\n", buffer);
::fflush(m_fpLog);
}
if (level >= m_displayLevel && m_displayLevel != 0U) {
::fprintf(stdout, "%s\n", buffer);
::fflush(stdout);
}
if (level == 6U) { // Fatal
::fclose(m_fpLog);
exit(1);
}
}

@ -0,0 +1,36 @@
/*
* Copyright (C) 2015,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.
*/
#if !defined(LOG_H)
#define LOG_H
#include <string>
#define LogDebug(fmt, ...) Log(1U, fmt, ##__VA_ARGS__)
#define LogMessage(fmt, ...) Log(2U, fmt, ##__VA_ARGS__)
#define LogInfo(fmt, ...) Log(3U, fmt, ##__VA_ARGS__)
#define LogWarning(fmt, ...) Log(4U, fmt, ##__VA_ARGS__)
#define LogError(fmt, ...) Log(5U, fmt, ##__VA_ARGS__)
#define LogFatal(fmt, ...) Log(6U, fmt, ##__VA_ARGS__)
extern void Log(unsigned int level, const char* fmt, ...);
extern bool LogInitialise(const std::string& filePath, const std::string& fileRoot, unsigned int fileLevel, unsigned int displayLevel);
extern void LogFinalise();
#endif

@ -0,0 +1,30 @@
CC = gcc
CXX = g++
# Use the following CFLAGS and LIBS if you don't want to use gpsd.
CFLAGS = -g -O3 -Wall -std=c++0x -pthread
LIBS = -lm -lpthread
# Use the following CFLAGS and LIBS if you do want to use gpsd.
#CFLAGS = -g -O3 -Wall -DUSE_GPSD -std=c++0x -pthread
#LIBS = -lm -lpthread -lgps
LDFLAGS = -g
OBJECTS = APRSWriter.o Conf.o CRC.o DGIdGateway.o DGIdNetwork.o FCSNetwork.o Golay24128.o GPS.o Log.o StopWatch.o Sync.o Thread.o Timer.o \
UDPSocket.o Utils.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o YSFReflectors.o
all: DGIdGateway
DGIdGateway: $(OBJECTS)
$(CXX) $(OBJECTS) $(CFLAGS) $(LIBS) -o DGIdGateway
%.o: %.cpp
$(CXX) $(CFLAGS) -c -o $@ $<
install:
install -m 755 DGIdGateway /usr/local/bin/
clean:
$(RM) DGIdGateway *.o *.d *.bak *~

@ -0,0 +1,12 @@
The YSF Gateway interfaces the MMDVM Host to the open source YSF Reflector system using the standard Wires-X commands from the radio. It also gateways position information to aprs.fi if sent.
The file YSFHosts.txt holds information about the reflectors available, and the gateway has the ability to reload this file at intervals to ensure that it is always up to date.
It is expected that a call to retrieve this file is done via some mechanism such as cron on Linux. The URLs to retrieve the latest file are [http://register.ysfreflector.de/export_csv.php](http://register.ysfreflector.de/export_csv.php), or [https://register.ysfreflector.de/export_csv.php](https://register.ysfreflector.de/export_csv.php).
An example would be following line in root's crontab, that fetches the reflector-list each 5 minutes:
> sudo crontab -e
add following line:
> */5 * * * * wget -O /var/YSFGateway/YSFHosts.txt http://register.ysfreflector.de/export_csv.php

@ -0,0 +1,149 @@
/*
* Copyright (C) 2006-2009,2012,2013,2015,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 RingBuffer_H
#define RingBuffer_H
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <cstring>
template<class T> class CRingBuffer {
public:
CRingBuffer(unsigned int length, const char* name) :
m_length(length),
m_name(name),
m_buffer(NULL),
m_iPtr(0U),
m_oPtr(0U)
{
assert(length > 0U);
assert(name != NULL);
m_buffer = new T[length];
::memset(m_buffer, 0x00, m_length * sizeof(T));
}
~CRingBuffer()
{
delete[] m_buffer;
}
bool addData(const T* buffer, unsigned int nSamples)
{
if (nSamples >= freeSpace()) {
LogError("**** Overflow in %s ring buffer, %u >= %u", m_name, nSamples, freeSpace());
return false;
}
for (unsigned int i = 0U; i < nSamples; i++) {
m_buffer[m_iPtr++] = buffer[i];
if (m_iPtr == m_length)
m_iPtr = 0U;
}
return true;
}
bool getData(T* buffer, unsigned int nSamples)
{
if (dataSize() < nSamples) {
LogError("**** Underflow in %s ring buffer, %u < %u", m_name, dataSize(), nSamples);
return false;
}
for (unsigned int i = 0U; i < nSamples; i++) {
buffer[i] = m_buffer[m_oPtr++];
if (m_oPtr == m_length)
m_oPtr = 0U;
}
return true;
}
bool peek(T* buffer, unsigned int nSamples)
{
if (dataSize() < nSamples) {
LogError("**** Underflow peek in %s ring buffer, %u < %u", m_name, dataSize(), nSamples);
return false;
}
unsigned int ptr = m_oPtr;
for (unsigned int i = 0U; i < nSamples; i++) {
buffer[i] = m_buffer[ptr++];
if (ptr == m_length)
ptr = 0U;
}
return true;
}
void clear()
{
m_iPtr = 0U;
m_oPtr = 0U;
::memset(m_buffer, 0x00, m_length * sizeof(T));
}
unsigned int freeSpace() const
{
if (m_oPtr == m_iPtr)
return m_length;
if (m_oPtr > m_iPtr)
return m_oPtr - m_iPtr;
return (m_length + m_oPtr) - m_iPtr;
}
unsigned int dataSize() const
{
return m_length - freeSpace();
}
bool hasSpace(unsigned int length) const
{
return freeSpace() > length;
}
bool hasData() const
{
return m_oPtr != m_iPtr;
}
bool isEmpty() const
{
return m_oPtr == m_iPtr;
}
private:
unsigned int m_length;
const char* m_name;
T* m_buffer;
unsigned int m_iPtr;
unsigned int m_oPtr;
};
#endif

@ -0,0 +1,105 @@
/*
* Copyright (C) 2015,2016,2018 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 "StopWatch.h"
#if defined(_WIN32) || defined(_WIN64)
CStopWatch::CStopWatch() :
m_frequencyS(),
m_frequencyMS(),
m_start()
{
::QueryPerformanceFrequency(&m_frequencyS);
m_frequencyMS.QuadPart = m_frequencyS.QuadPart / 1000ULL;
}
CStopWatch::~CStopWatch()
{
}
unsigned long long CStopWatch::time() const
{
LARGE_INTEGER now;
::QueryPerformanceCounter(&now);
return (unsigned long long)(now.QuadPart / m_frequencyMS.QuadPart);
}
unsigned long long CStopWatch::start()
{
::QueryPerformanceCounter(&m_start);
return (unsigned long long)(m_start.QuadPart / m_frequencyS.QuadPart);
}
unsigned int CStopWatch::elapsed()
{
LARGE_INTEGER now;
::QueryPerformanceCounter(&now);
LARGE_INTEGER temp;
temp.QuadPart = (now.QuadPart - m_start.QuadPart) * 1000;
return (unsigned int)(temp.QuadPart / m_frequencyS.QuadPart);
}
#else
#include <cstdio>
#include <ctime>
CStopWatch::CStopWatch() :
m_startMS(0ULL)
{
}
CStopWatch::~CStopWatch()
{
}
unsigned long long CStopWatch::time() const
{
struct timeval now;
::gettimeofday(&now, NULL);
return now.tv_sec * 1000ULL + now.tv_usec / 1000ULL;
}
unsigned long long CStopWatch::start()
{
struct timespec now;
::clock_gettime(CLOCK_MONOTONIC, &now);
m_startMS = now.tv_sec * 1000ULL + now.tv_nsec / 1000000ULL;
return m_startMS;
}
unsigned int CStopWatch::elapsed()
{
struct timespec now;
::clock_gettime(CLOCK_MONOTONIC, &now);
unsigned long long nowMS = now.tv_sec * 1000ULL + now.tv_nsec / 1000000ULL;
return nowMS - m_startMS;
}
#endif

@ -0,0 +1,49 @@
/*
* Copyright (C) 2015,2016,2018 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.
*/
#if !defined(STOPWATCH_H)
#define STOPWATCH_H
#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#else
#include <sys/time.h>
#endif
class CStopWatch
{
public:
CStopWatch();
~CStopWatch();
unsigned long long time() const;
unsigned long long start();
unsigned int elapsed();
private:
#if defined(_WIN32) || defined(_WIN64)
LARGE_INTEGER m_frequencyS;
LARGE_INTEGER m_frequencyMS;
LARGE_INTEGER m_start;
#else
unsigned long long m_startMS;
#endif
};
#endif

@ -0,0 +1,32 @@
/*
* Copyright (C) 2015,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 "Sync.h"
#include "YSFDefines.h"
#include <cstdio>
#include <cassert>
#include <cstring>
void CSync::add(unsigned char* data)
{
assert(data != NULL);
::memcpy(data, YSF_SYNC_BYTES, YSF_SYNC_LENGTH_BYTES);
}

@ -0,0 +1,30 @@
/*
* Copyright (C) 2015,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.
*/
#if !defined(SYNC_H)
#define SYNC_H
class CSync
{
public:
static void add(unsigned char* data);
private:
};
#endif

@ -0,0 +1,101 @@
/*
* Copyright (C) 2015,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 "Thread.h"
#if defined(_WIN32) || defined(_WIN64)
CThread::CThread() :
m_handle()
{
}
CThread::~CThread()
{
}
bool CThread::run()
{
m_handle = ::CreateThread(NULL, 0, &helper, this, 0, NULL);
return m_handle != NULL;
}
void CThread::wait()
{
::WaitForSingleObject(m_handle, INFINITE);
::CloseHandle(m_handle);
}
DWORD CThread::helper(LPVOID arg)
{
CThread* p = (CThread*)arg;
p->entry();
return 0UL;
}
void CThread::sleep(unsigned int ms)
{
::Sleep(ms);
}
#else
#include <unistd.h>
CThread::CThread() :
m_thread()
{
}
CThread::~CThread()
{
}
bool CThread::run()
{
return ::pthread_create(&m_thread, NULL, helper, this) == 0;
}
void CThread::wait()
{
::pthread_join(m_thread, NULL);
}
void* CThread::helper(void* arg)
{
CThread* p = (CThread*)arg;
p->entry();
return NULL;
}
void CThread::sleep(unsigned int ms)
{
::usleep(ms * 1000);
}
#endif

@ -0,0 +1,56 @@
/*
* Copyright (C) 2015,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.
*/
#if !defined(THREAD_H)
#define THREAD_H
#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#else
#include <pthread.h>
#endif
class CThread
{
public:
CThread();
virtual ~CThread();
virtual bool run();
virtual void entry() = 0;
virtual void wait();
static void sleep(unsigned int ms);
private:
#if defined(_WIN32) || defined(_WIN64)
HANDLE m_handle;
#else
pthread_t m_thread;
#endif
#if defined(_WIN32) || defined(_WIN64)
static DWORD __stdcall helper(LPVOID arg);
#else
static void* helper(void* arg);
#endif
};
#endif

@ -0,0 +1,68 @@
/*
* Copyright (C) 2009,2010,2015 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 "Timer.h"
#include <cstdio>
#include <cassert>
CTimer::CTimer(unsigned int ticksPerSec, unsigned int secs, unsigned int msecs) :
m_ticksPerSec(ticksPerSec),
m_timeout(0U),
m_timer(0U)
{
assert(ticksPerSec > 0U);
if (secs > 0U || msecs > 0U) {
// m_timeout = ((secs * 1000U + msecs) * m_ticksPerSec) / 1000U + 1U;
unsigned long long temp = (secs * 1000ULL + msecs) * m_ticksPerSec;
m_timeout = (unsigned int)(temp / 1000ULL + 1ULL);
}
}
CTimer::~CTimer()
{
}
void CTimer::setTimeout(unsigned int secs, unsigned int msecs)
{
if (secs > 0U || msecs > 0U) {
// m_timeout = ((secs * 1000U + msecs) * m_ticksPerSec) / 1000U + 1U;
unsigned long long temp = (secs * 1000ULL + msecs) * m_ticksPerSec;
m_timeout = (unsigned int)(temp / 1000ULL + 1ULL);
} else {
m_timeout = 0U;
m_timer = 0U;
}
}
unsigned int CTimer::getTimeout() const
{
if (m_timeout == 0U)
return 0U;
return (m_timeout - 1U) / m_ticksPerSec;
}
unsigned int CTimer::getTimer() const
{
if (m_timer == 0U)
return 0U;
return (m_timer - 1U) / m_ticksPerSec;
}

@ -0,0 +1,89 @@
/*
* Copyright (C) 2009,2010,2011,2014 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 Timer_H
#define Timer_H
class CTimer {
public:
CTimer(unsigned int ticksPerSec, unsigned int secs = 0U, unsigned int msecs = 0U);
~CTimer();
void setTimeout(unsigned int secs, unsigned int msecs = 0U);
unsigned int getTimeout() const;
unsigned int getTimer() const;
unsigned int getRemaining()
{
if (m_timeout == 0U || m_timer == 0U)
return 0U;
if (m_timer >= m_timeout)
return 0U;
return (m_timeout - m_timer) / m_ticksPerSec;
}
bool isRunning()
{
return m_timer > 0U;
}
void start(unsigned int secs, unsigned int msecs = 0U)
{
setTimeout(secs, msecs);
start();
}
void start()
{
if (m_timeout > 0U)
m_timer = 1U;
}
void stop()
{
m_timer = 0U;
}
bool hasExpired()
{
if (m_timeout == 0U || m_timer == 0U)
return false;
if (m_timer >= m_timeout)
return true;
return false;
}
void clock(unsigned int ticks = 1U)
{
if (m_timer > 0U && m_timeout > 0U)
m_timer += ticks;
}
private:
unsigned int m_ticksPerSec;
unsigned int m_timeout;
unsigned int m_timer;
};
#endif

@ -0,0 +1,264 @@
/*
* Copyright (C) 2006-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 "UDPSocket.h"
#include "Log.h"
#include <cassert>
#if !defined(_WIN32) && !defined(_WIN64)
#include <cerrno>
#include <cstring>
#endif
CUDPSocket::CUDPSocket(const std::string& address, unsigned int port) :
m_address(address),
m_port(port),
m_fd(-1)
{
assert(!address.empty());
#if defined(_WIN32) || defined(_WIN64)
WSAData data;
int wsaRet = ::WSAStartup(MAKEWORD(2, 2), &data);
if (wsaRet != 0)
LogError("Error from WSAStartup");
#endif
}
CUDPSocket::CUDPSocket(unsigned int port) :
m_address(),
m_port(port),
m_fd(-1)
{
#if defined(_WIN32) || defined(_WIN64)
WSAData data;
int wsaRet = ::WSAStartup(MAKEWORD(2, 2), &data);
if (wsaRet != 0)
LogError("Error from WSAStartup");
#endif
}
CUDPSocket::~CUDPSocket()
{
#if defined(_WIN32) || defined(_WIN64)
::WSACleanup();
#endif
}
in_addr CUDPSocket::lookup(const std::string& hostname)
{
in_addr addr;
#if defined(_WIN32) || defined(_WIN64)
unsigned long address = ::inet_addr(hostname.c_str());
if (address != INADDR_NONE && address != INADDR_ANY) {
addr.s_addr = address;
return addr;
}
struct hostent* hp = ::gethostbyname(hostname.c_str());
if (hp != NULL) {
::memcpy(&addr, hp->h_addr_list[0], sizeof(struct in_addr));
return addr;
}
LogError("Cannot find address for host %s", hostname.c_str());
addr.s_addr = INADDR_NONE;
return addr;
#else
in_addr_t address = ::inet_addr(hostname.c_str());
if (address != in_addr_t(-1)) {
addr.s_addr = address;
return addr;
}
struct hostent* hp = ::gethostbyname(hostname.c_str());
if (hp != NULL) {
::memcpy(&addr, hp->h_addr_list[0], sizeof(struct in_addr));
return addr;
}
LogError("Cannot find address for host %s", hostname.c_str());
addr.s_addr = INADDR_NONE;
return addr;
#endif
}
bool CUDPSocket::open()
{
m_fd = ::socket(PF_INET, SOCK_DGRAM, 0);
if (m_fd < 0) {
#if defined(_WIN32) || defined(_WIN64)
LogError("Cannot create the UDP socket, err: %lu", ::GetLastError());
#else
LogError("Cannot create the UDP socket, err: %d", errno);
#endif
return false;
}
if (m_port > 0U) {
sockaddr_in addr;
::memset(&addr, 0x00, sizeof(sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(m_port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (!m_address.empty()) {
#if defined(_WIN32) || defined(_WIN64)
addr.sin_addr.s_addr = ::inet_addr(m_address.c_str());
#else
addr.sin_addr.s_addr = ::inet_addr(m_address.c_str());
#endif
if (addr.sin_addr.s_addr == INADDR_NONE) {
LogError("The local address is invalid - %s", m_address.c_str());
return false;
}
}
int reuse = 1;
if (::setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) == -1) {
#if defined(_WIN32) || defined(_WIN64)
LogError("Cannot set the UDP socket option, err: %lu", ::GetLastError());
#else
LogError("Cannot set the UDP socket option, err: %d", errno);
#endif
return false;
}
if (::bind(m_fd, (sockaddr*)&addr, sizeof(sockaddr_in)) == -1) {
#if defined(_WIN32) || defined(_WIN64)
LogError("Cannot bind the UDP address, err: %lu", ::GetLastError());
#else
LogError("Cannot bind the UDP address, err: %d", errno);
#endif
return false;
}
LogInfo("Opening UDP port on %u", m_port);
}
return true;
}
int CUDPSocket::read(unsigned char* buffer, unsigned int length, in_addr& address, unsigned int& port)
{
assert(buffer != NULL);
assert(length > 0U);
// Check that the readfrom() won't block
fd_set readFds;
FD_ZERO(&readFds);
#if defined(_WIN32) || defined(_WIN64)
FD_SET((unsigned int)m_fd, &readFds);
#else
FD_SET(m_fd, &readFds);
#endif
// Return immediately
timeval tv;
tv.tv_sec = 0L;
tv.tv_usec = 0L;
int ret = ::select(m_fd + 1, &readFds, NULL, NULL, &tv);
if (ret < 0) {
#if defined(_WIN32) || defined(_WIN64)
LogError("Error returned from UDP select, err: %lu", ::GetLastError());
#else
LogError("Error returned from UDP select, err: %d", errno);
#endif
return -1;
}
if (ret == 0)
return 0;
sockaddr_in addr;
#if defined(_WIN32) || defined(_WIN64)
int size = sizeof(sockaddr_in);
#else
socklen_t size = sizeof(sockaddr_in);
#endif
#if defined(_WIN32) || defined(_WIN64)
int len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&addr, &size);
#else
ssize_t len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&addr, &size);
#endif
if (len <= 0) {
#if defined(_WIN32) || defined(_WIN64)
LogError("Error returned from recvfrom, err: %lu", ::GetLastError());
#else
LogError("Error returned from recvfrom, err: %d", errno);
#endif
return -1;
}
address = addr.sin_addr;
port = ntohs(addr.sin_port);
return len;
}
bool CUDPSocket::write(const unsigned char* buffer, unsigned int length, const in_addr& address, unsigned int port)
{
assert(buffer != NULL);
assert(length > 0U);
sockaddr_in addr;
::memset(&addr, 0x00, sizeof(sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr = address;
addr.sin_port = htons(port);
#if defined(_WIN32) || defined(_WIN64)
int ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&addr, sizeof(sockaddr_in));
#else
ssize_t ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&addr, sizeof(sockaddr_in));
#endif
if (ret < 0) {
#if defined(_WIN32) || defined(_WIN64)
LogError("Error returned from sendto, err: %lu", ::GetLastError());
#else
LogError("Error returned from sendto, err: %d", errno);
#endif
return false;
}
#if defined(_WIN32) || defined(_WIN64)
if (ret != int(length))
return false;
#else
if (ret != ssize_t(length))
return false;
#endif
return true;
}
void CUDPSocket::close()
{
#if defined(_WIN32) || defined(_WIN64)
::closesocket(m_fd);
#else
::close(m_fd);
#endif
}

@ -0,0 +1,58 @@
/*
* Copyright (C) 2009-2011,2013,2015,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 UDPSocket_H
#define UDPSocket_H
#include <string>
#if !defined(_WIN32) && !defined(_WIN64)
#include <netdb.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#else
#include <winsock.h>
#endif
class CUDPSocket {
public:
CUDPSocket(const std::string& address, unsigned int port = 0U);
CUDPSocket(unsigned int port = 0U);
~CUDPSocket();
bool open();
int read(unsigned char* buffer, unsigned int length, in_addr& address, unsigned int& port);
bool write(const unsigned char* buffer, unsigned int length, const in_addr& address, unsigned int port);
void close();
static in_addr lookup(const std::string& hostName);
private:
std::string m_address;
unsigned short m_port;
int m_fd;
};
#endif

@ -0,0 +1,146 @@
/*
* Copyright (C) 2009,2014,2015,2016 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; version 2 of the License.
*
* 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.
*/
#include "Utils.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
void CUtils::dump(const std::string& title, const unsigned char* data, unsigned int length)
{
assert(data != NULL);
dump(2U, title, data, length);
}
void CUtils::dump(int level, const std::string& title, const unsigned char* data, unsigned int length)
{
assert(data != NULL);
::Log(level, "%s", title.c_str());
unsigned int offset = 0U;
while (length > 0U) {
std::string output;
unsigned int bytes = (length > 16U) ? 16U : length;
for (unsigned i = 0U; i < bytes; i++) {
char temp[10U];
::sprintf(temp, "%02X ", data[offset + i]);
output += temp;
}
for (unsigned int i = bytes; i < 16U; i++)
output += " ";
output += " *";
for (unsigned i = 0U; i < bytes; i++) {
unsigned char c = data[offset + i];
if (::isprint(c))
output += c;
else
output += '.';
}
output += '*';
::Log(level, "%04X: %s", offset, output.c_str());
offset += 16U;
if (length >= 16U)
length -= 16U;
else
length = 0U;
}
}
void CUtils::dump(const std::string& title, const bool* bits, unsigned int length)
{
assert(bits != NULL);
dump(2U, title, bits, length);
}
void CUtils::dump(int level, const std::string& title, const bool* bits, unsigned int length)
{
assert(bits != NULL);
unsigned char bytes[100U];
unsigned int nBytes = 0U;
for (unsigned int n = 0U; n < length; n += 8U, nBytes++)
bitsToByteBE(bits + n, bytes[nBytes]);
dump(level, title, bytes, nBytes);
}
void CUtils::byteToBitsBE(unsigned char byte, bool* bits)
{
assert(bits != NULL);
bits[0U] = (byte & 0x80U) == 0x80U;
bits[1U] = (byte & 0x40U) == 0x40U;
bits[2U] = (byte & 0x20U) == 0x20U;
bits[3U] = (byte & 0x10U) == 0x10U;
bits[4U] = (byte & 0x08U) == 0x08U;
bits[5U] = (byte & 0x04U) == 0x04U;
bits[6U] = (byte & 0x02U) == 0x02U;
bits[7U] = (byte & 0x01U) == 0x01U;
}
void CUtils::byteToBitsLE(unsigned char byte, bool* bits)
{
assert(bits != NULL);
bits[0U] = (byte & 0x01U) == 0x01U;
bits[1U] = (byte & 0x02U) == 0x02U;
bits[2U] = (byte & 0x04U) == 0x04U;
bits[3U] = (byte & 0x08U) == 0x08U;
bits[4U] = (byte & 0x10U) == 0x10U;
bits[5U] = (byte & 0x20U) == 0x20U;
bits[6U] = (byte & 0x40U) == 0x40U;
bits[7U] = (byte & 0x80U) == 0x80U;
}
void CUtils::bitsToByteBE(const bool* bits, unsigned char& byte)
{
assert(bits != NULL);
byte = bits[0U] ? 0x80U : 0x00U;
byte |= bits[1U] ? 0x40U : 0x00U;
byte |= bits[2U] ? 0x20U : 0x00U;
byte |= bits[3U] ? 0x10U : 0x00U;
byte |= bits[4U] ? 0x08U : 0x00U;
byte |= bits[5U] ? 0x04U : 0x00U;
byte |= bits[6U] ? 0x02U : 0x00U;
byte |= bits[7U] ? 0x01U : 0x00U;
}
void CUtils::bitsToByteLE(const bool* bits, unsigned char& byte)
{
assert(bits != NULL);
byte = bits[0U] ? 0x01U : 0x00U;
byte |= bits[1U] ? 0x02U : 0x00U;
byte |= bits[2U] ? 0x04U : 0x00U;
byte |= bits[3U] ? 0x08U : 0x00U;
byte |= bits[4U] ? 0x10U : 0x00U;
byte |= bits[5U] ? 0x20U : 0x00U;
byte |= bits[6U] ? 0x40U : 0x00U;
byte |= bits[7U] ? 0x80U : 0x00U;
}

@ -0,0 +1,36 @@
/*
* Copyright (C) 2009,2014,2015 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; version 2 of the License.
*
* 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.
*/
#ifndef Utils_H
#define Utils_H
#include <string>
class CUtils {
public:
static void dump(const std::string& title, const unsigned char* data, unsigned int length);
static void dump(int level, const std::string& title, const unsigned char* data, unsigned int length);
static void dump(const std::string& title, const bool* bits, unsigned int length);
static void dump(int level, const std::string& title, const bool* bits, unsigned int length);
static void byteToBitsBE(unsigned char byte, bool* bits);
static void byteToBitsLE(unsigned char byte, bool* bits);
static void bitsToByteBE(const bool* bits, unsigned char& byte);
static void bitsToByteLE(const bool* bits, unsigned char& byte);
private:
};
#endif

@ -0,0 +1,24 @@
/*
* Copyright (C) 2015-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
* 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.
*/
#if !defined(VERSION_H)
#define VERSION_H
const char* VERSION = "20200803";
#endif

@ -0,0 +1,141 @@
/*
* Copyright (C) 2009-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 "YSFConvolution.h"
#include <cstdio>
#include <cassert>
#include <cstring>
const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U};
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
const uint8_t BRANCH_TABLE1[] = {0U, 0U, 0U, 0U, 1U, 1U, 1U, 1U};
const uint8_t BRANCH_TABLE2[] = {0U, 1U, 1U, 0U, 0U, 1U, 1U, 0U};
const unsigned int NUM_OF_STATES_D2 = 8U;
const unsigned int NUM_OF_STATES = 16U;
const uint32_t M = 2U;
const unsigned int K = 5U;
CYSFConvolution::CYSFConvolution() :
m_metrics1(NULL),
m_metrics2(NULL),
m_oldMetrics(NULL),
m_newMetrics(NULL),
m_decisions(NULL),
m_dp(NULL)
{
m_metrics1 = new uint16_t[16U];
m_metrics2 = new uint16_t[16U];
m_decisions = new uint64_t[180U];
}
CYSFConvolution::~CYSFConvolution()
{
delete[] m_metrics1;
delete[] m_metrics2;
delete[] m_decisions;
}
void CYSFConvolution::start()
{
::memset(m_metrics1, 0x00U, NUM_OF_STATES * sizeof(uint16_t));
::memset(m_metrics2, 0x00U, NUM_OF_STATES * sizeof(uint16_t));
m_oldMetrics = m_metrics1;
m_newMetrics = m_metrics2;
m_dp = m_decisions;
}
void CYSFConvolution::decode(uint8_t s0, uint8_t s1)
{
*m_dp = 0U;
for (uint8_t i = 0U; i < NUM_OF_STATES_D2; i++) {
uint8_t j = i * 2U;
uint16_t metric = (BRANCH_TABLE1[i] ^ s0) + (BRANCH_TABLE2[i] ^ s1);
uint16_t m0 = m_oldMetrics[i] + metric;
uint16_t m1 = m_oldMetrics[i + NUM_OF_STATES_D2] + (M - metric);
uint8_t decision0 = (m0 >= m1) ? 1U : 0U;
m_newMetrics[j + 0U] = decision0 != 0U ? m1 : m0;
m0 = m_oldMetrics[i] + (M - metric);
m1 = m_oldMetrics[i + NUM_OF_STATES_D2] + metric;
uint8_t decision1 = (m0 >= m1) ? 1U : 0U;
m_newMetrics[j + 1U] = decision1 != 0U ? m1 : m0;
*m_dp |= (uint64_t(decision1) << (j + 1U)) | (uint64_t(decision0) << (j + 0U));
}
++m_dp;
assert((m_dp - m_decisions) <= 180);
uint16_t* tmp = m_oldMetrics;
m_oldMetrics = m_newMetrics;
m_newMetrics = tmp;
}
void CYSFConvolution::chainback(unsigned char* out, unsigned int nBits)
{
assert(out != NULL);
uint32_t state = 0U;
while (nBits-- > 0) {
--m_dp;
uint32_t i = state >> (9 - K);
uint8_t bit = uint8_t(*m_dp >> i) & 1;
state = (bit << 7) | (state >> 1);
WRITE_BIT1(out, nBits, bit != 0U);
}
}
void CYSFConvolution::encode(const unsigned char* in, unsigned char* out, unsigned int nBits) const
{
assert(in != NULL);
assert(out != NULL);
assert(nBits > 0U);
uint8_t d1 = 0U, d2 = 0U, d3 = 0U, d4 = 0U;
uint32_t k = 0U;
for (unsigned int i = 0U; i < nBits; i++) {
uint8_t d = READ_BIT1(in, i) ? 1U : 0U;
uint8_t g1 = (d + d3 + d4) & 1;
uint8_t g2 = (d + d1 + d2 + d4) & 1;
d4 = d3;
d3 = d2;
d2 = d1;
d1 = d;
WRITE_BIT1(out, k, g1 != 0U);
k++;
WRITE_BIT1(out, k, g2 != 0U);
k++;
}
}

@ -0,0 +1,47 @@
/*
* Copyright (C) 2015,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.
*/
#if !defined(YSFConvolution_H)
#define YSFConvolution_H
#include "YSFConvolution.h"
#include <cstdint>
class CYSFConvolution {
public:
CYSFConvolution();
~CYSFConvolution();
void start();
void decode(uint8_t s0, uint8_t s1);
void chainback(unsigned char* out, unsigned int nBits);
void encode(const unsigned char* in, unsigned char* out, unsigned int nBits) const;
private:
uint16_t* m_metrics1;
uint16_t* m_metrics2;
uint16_t* m_oldMetrics;
uint16_t* m_newMetrics;
uint64_t* m_decisions;
uint64_t* m_dp;
};
#endif

@ -0,0 +1,52 @@
/*
* Copyright (C) 2015,2016,2017,2018 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.
*/
#if !defined(YSFDefines_H)
#define YSFDefines_H
const unsigned int YSF_FRAME_LENGTH_BYTES = 120U;
const unsigned char YSF_SYNC_BYTES[] = {0xD4U, 0x71U, 0xC9U, 0x63U, 0x4DU};
const unsigned int YSF_SYNC_LENGTH_BYTES = 5U;
const unsigned int YSF_FICH_LENGTH_BYTES = 25U;
const unsigned char YSF_SYNC_OK = 0x01U;
const unsigned int YSF_CALLSIGN_LENGTH = 10U;
const unsigned char YSF_FI_HEADER = 0x00U;
const unsigned char YSF_FI_COMMUNICATIONS = 0x01U;
const unsigned char YSF_FI_TERMINATOR = 0x02U;
const unsigned char YSF_FI_TEST = 0x03U;
const unsigned char YSF_DT_VD_MODE1 = 0x00U;
const unsigned char YSF_DT_DATA_FR_MODE = 0x01U;
const unsigned char YSF_DT_VD_MODE2 = 0x02U;
const unsigned char YSF_DT_VOICE_FR_MODE = 0x03U;
const unsigned char YSF_CM_GROUP1 = 0x00U;
const unsigned char YSF_CM_GROUP2 = 0x01U;
const unsigned char YSF_CM_INDIVIDUAL = 0x03U;
const unsigned char YSF_MR_NOT_BUSY = 0x01U;
const unsigned char YSF_MR_BUSY = 0x02U;
const unsigned int FCS_PORT = 62500U;
#endif

@ -0,0 +1,274 @@
/*
* Copyright (C) 2016,2017,2019 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 "YSFConvolution.h"
#include "YSFDefines.h"
#include "Golay24128.h"
#include "YSFFICH.h"
#include "CRC.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <cstring>
const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U};
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
const unsigned int INTERLEAVE_TABLE[] = {
0U, 40U, 80U, 120U, 160U,
2U, 42U, 82U, 122U, 162U,
4U, 44U, 84U, 124U, 164U,
6U, 46U, 86U, 126U, 166U,
8U, 48U, 88U, 128U, 168U,
10U, 50U, 90U, 130U, 170U,
12U, 52U, 92U, 132U, 172U,
14U, 54U, 94U, 134U, 174U,
16U, 56U, 96U, 136U, 176U,
18U, 58U, 98U, 138U, 178U,
20U, 60U, 100U, 140U, 180U,
22U, 62U, 102U, 142U, 182U,
24U, 64U, 104U, 144U, 184U,
26U, 66U, 106U, 146U, 186U,
28U, 68U, 108U, 148U, 188U,
30U, 70U, 110U, 150U, 190U,
32U, 72U, 112U, 152U, 192U,
34U, 74U, 114U, 154U, 194U,
36U, 76U, 116U, 156U, 196U,
38U, 78U, 118U, 158U, 198U};
CYSFFICH::CYSFFICH(const CYSFFICH& fich) :
m_fich(NULL)
{
m_fich = new unsigned char[6U];
::memcpy(m_fich, fich.m_fich, 6U);
}
CYSFFICH::CYSFFICH() :
m_fich(NULL)
{
m_fich = new unsigned char[6U];
memset(m_fich, 0x00U, 6U);
}
CYSFFICH::~CYSFFICH()
{
delete[] m_fich;
}
bool CYSFFICH::decode(const unsigned char* bytes)
{
assert(bytes != NULL);
// Skip the sync bytes
bytes += YSF_SYNC_LENGTH_BYTES;
CYSFConvolution viterbi;
viterbi.start();
// Deinterleave the FICH and send bits to the Viterbi decoder
for (unsigned int i = 0U; i < 100U; i++) {
unsigned int n = INTERLEAVE_TABLE[i];
uint8_t s0 = READ_BIT1(bytes, n) ? 1U : 0U;
n++;
uint8_t s1 = READ_BIT1(bytes, n) ? 1U : 0U;
viterbi.decode(s0, s1);
}
unsigned char output[13U];
viterbi.chainback(output, 96U);
unsigned int b0 = CGolay24128::decode24128(output + 0U);
unsigned int b1 = CGolay24128::decode24128(output + 3U);
unsigned int b2 = CGolay24128::decode24128(output + 6U);
unsigned int b3 = CGolay24128::decode24128(output + 9U);
m_fich[0U] = (b0 >> 4) & 0xFFU;
m_fich[1U] = ((b0 << 4) & 0xF0U) | ((b1 >> 8) & 0x0FU);
m_fich[2U] = (b1 >> 0) & 0xFFU;
m_fich[3U] = (b2 >> 4) & 0xFFU;
m_fich[4U] = ((b2 << 4) & 0xF0U) | ((b3 >> 8) & 0x0FU);
m_fich[5U] = (b3 >> 0) & 0xFFU;
return CCRC::checkCCITT162(m_fich, 6U);
}
void CYSFFICH::encode(unsigned char* bytes)
{
assert(bytes != NULL);
// Skip the sync bytes
bytes += YSF_SYNC_LENGTH_BYTES;
CCRC::addCCITT162(m_fich, 6U);
unsigned int b0 = ((m_fich[0U] << 4) & 0xFF0U) | ((m_fich[1U] >> 4) & 0x00FU);
unsigned int b1 = ((m_fich[1U] << 8) & 0xF00U) | ((m_fich[2U] >> 0) & 0x0FFU);
unsigned int b2 = ((m_fich[3U] << 4) & 0xFF0U) | ((m_fich[4U] >> 4) & 0x00FU);
unsigned int b3 = ((m_fich[4U] << 8) & 0xF00U) | ((m_fich[5U] >> 0) & 0x0FFU);
unsigned int c0 = CGolay24128::encode24128(b0);
unsigned int c1 = CGolay24128::encode24128(b1);
unsigned int c2 = CGolay24128::encode24128(b2);
unsigned int c3 = CGolay24128::encode24128(b3);
unsigned char conv[13U];
conv[0U] = (c0 >> 16) & 0xFFU;
conv[1U] = (c0 >> 8) & 0xFFU;
conv[2U] = (c0 >> 0) & 0xFFU;
conv[3U] = (c1 >> 16) & 0xFFU;
conv[4U] = (c1 >> 8) & 0xFFU;
conv[5U] = (c1 >> 0) & 0xFFU;
conv[6U] = (c2 >> 16) & 0xFFU;
conv[7U] = (c2 >> 8) & 0xFFU;
conv[8U] = (c2 >> 0) & 0xFFU;
conv[9U] = (c3 >> 16) & 0xFFU;
conv[10U] = (c3 >> 8) & 0xFFU;
conv[11U] = (c3 >> 0) & 0xFFU;
conv[12U] = 0x00U;
CYSFConvolution convolution;
unsigned char convolved[25U];
convolution.encode(conv, convolved, 100U);
unsigned int j = 0U;
for (unsigned int i = 0U; i < 100U; i++) {
unsigned int n = INTERLEAVE_TABLE[i];
bool s0 = READ_BIT1(convolved, j) != 0U;
j++;
bool s1 = READ_BIT1(convolved, j) != 0U;
j++;
WRITE_BIT1(bytes, n, s0);
n++;
WRITE_BIT1(bytes, n, s1);
}
}
unsigned char CYSFFICH::getFI() const
{
return (m_fich[0U] >> 6) & 0x03U;
}
unsigned char CYSFFICH::getCM() const
{
return (m_fich[0U] >> 2) & 0x03U;
}
unsigned char CYSFFICH::getBN() const
{
return m_fich[0U] & 0x03U;
}
unsigned char CYSFFICH::getBT() const
{
return (m_fich[1U] >> 6) & 0x03U;
}
unsigned char CYSFFICH::getFN() const
{
return (m_fich[1U] >> 3) & 0x07U;
}
unsigned char CYSFFICH::getFT() const
{
return m_fich[1U] & 0x07U;
}
unsigned char CYSFFICH::getDT() const
{
return m_fich[2U] & 0x03U;
}
unsigned char CYSFFICH::getMR() const
{
return (m_fich[2U] >> 3) & 0x03U;
}
bool CYSFFICH::getDev() const
{
return (m_fich[2U] & 0x40U) == 0x40U;
}
unsigned char CYSFFICH::getDGId() const
{
return m_fich[3U] & 0x7FU;
}
void CYSFFICH::setFI(unsigned char fi)
{
m_fich[0U] &= 0x3FU;
m_fich[0U] |= (fi << 6) & 0xC0U;
}
void CYSFFICH::setFN(unsigned char fn)
{
m_fich[1U] &= 0xC7U;
m_fich[1U] |= (fn << 3) & 0x38U;
}
void CYSFFICH::setFT(unsigned char ft)
{
m_fich[1U] &= 0xF8U;
m_fich[1U] |= ft & 0x07U;
}
void CYSFFICH::setMR(unsigned char mr)
{
m_fich[2U] &= 0xC7U;
m_fich[2U] |= (mr << 3) & 0x38U;
}
void CYSFFICH::setVoIP(bool on)
{
if (on)
m_fich[2U] |= 0x04U;
else
m_fich[2U] &= 0xFBU;
}
void CYSFFICH::setDev(bool on)
{
if (on)
m_fich[2U] |= 0x40U;
else
m_fich[2U] &= 0xBFU;
}
void CYSFFICH::setDGId(unsigned char id)
{
m_fich[3U] &= 0x80U;
m_fich[3U] |= id & 0x7FU;
}
CYSFFICH& CYSFFICH::operator=(const CYSFFICH& fich)
{
if (&fich != this)
::memcpy(m_fich, fich.m_fich, 6U);
return *this;
}

@ -0,0 +1,57 @@
/*
* Copyright (C) 2016,2017,2019 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.
*/
#if !defined(YSFFICH_H)
#define YSFFICH_H
class CYSFFICH {
public:
CYSFFICH(const CYSFFICH& fich);
CYSFFICH();
~CYSFFICH();
bool decode(const unsigned char* bytes);
void encode(unsigned char* bytes);
unsigned char getFI() const;
unsigned char getCM() const;
unsigned char getBN() const;
unsigned char getBT() const;
unsigned char getFN() const;
unsigned char getFT() const;
unsigned char getDT() const;
unsigned char getMR() const;
bool getDev() const;
unsigned char getDGId() const;
void setFI(unsigned char fi);
void setFN(unsigned char fn);
void setFT(unsigned char ft);
void setMR(unsigned char mr);
void setVoIP(bool set);
void setDev(bool set);
void setDGId(unsigned char id);
CYSFFICH& operator=(const CYSFFICH& fich);
private:
unsigned char* m_fich;
};
#endif

@ -0,0 +1,899 @@
90681;0-0-AMERICA;CQ USA! USA!;130.211.170.41;42001;010;http://
03729;0-0-CHINAVIRUS;COVID CHAT;130.211.170.41;42002;001;http://
27793;0-0-CQ-UK-ROOM;cq-uk.co.uk;81.150.10.62;42200;073;http://www.mb6er.com/ysf/
24160;0-CQ-UK-AUSSIE;Reflector 2;81.150.10.63;42100;009;https://www.cq-uk.co.uk
02203;0-HUBNet;Link to HUBNet;81.105.24.211;42000;005;https://hubnetwork.uk/
84922;0-KP3AV-Systems;Puerto Rico HU;70.45.32.69;41000;004;https://www.kp3av.net/
92150;0-MAGA;MAGA AMERICA;130.211.170.41;42000;001;http://no.not.yet/
65702;0-OE-Austria;Official;94.199.173.123;42200;001;http://oe9xvi.dyndns.org:46193
24117;00-AACQ-VK;VK WiRES-X;110.232.113.108;42002;014;http://110.232.113.108/vw
38900;00-AAYSF001;YSF001;110.232.113.108;42000;005;http://ysf001.duckdns.org
38089;0077;IRLP/ DMR/ D-S;23.94.25.146;42002;006;http://xe1dvi.crabdance.com/html/index.php
32642;021YSF;KR 021YSF;27.100.207.79;42000;006;http://ysf021.dvham.com
33280;0303_YSFColo;0303_YSFColo;3.22.106.87;42000;002;http://
40608;069-Er-Super-Fre;BM-YSF-P25-NXD;13.57.29.35;42000;004;http://
84905;096ysf-Busan-KR;Link TG450391;125.135.231.82;42000;000;http://096ysf.duckdns.org
11506;0970_YSFColo;0970_YSFColo;75.71.97.203;42000;004;http://
11500;0E7XTR;Tirol Oberland;185.199.82.169;42000;002;https://inet01.synology.me:46193
02573;1004DMR;DRM C4FM CROSS;218.144.164.10;42000;004;http://1004dmr.dvham.com/indexysf.php
74652;119-YSF;KR 119YSF;61.42.88.20;42000;030;http://ysf119.dvham.com/index.php
68800;2007-DXGROUP;Web Server;89.46.75.115;42000;005;http://89.46.75.115/index
37865;450IPSC2;C4FM TO DMR;220.71.19.222;42000;005;http://450ipsc2.dvham.com/indexysf.php
21796;4X-Israel;Israel Digital;109.226.48.53;42000;001;http://ysf972.ddns.net
06015;50525;Bridge-NXDN-P2;103.1.187.140;42000;003;http://50525.ysfreflector.net
97629;79435;IT S.M.A.M Pis;185.177.59.32;42000;005;http://185.177.59.32
65947;843IPSC2;IPSC2-DMR(TG84;218.144.164.13;42000;001;http://ipsc2843.dvham.com/indexysf.php
60227;911-Cop-Talk;911 Cop Talk;34.238.149.231;42000;002;http://ysf.k2cop.com
83018;95ANorth;Fernley,NV USA;216.128.134.46;42000;001;http://ysf.k7wby.com
44734;AARC-Fusion;AARC Fusion;64.179.223.222;42000;001;https://ysf.spdns.org
17950;AH-HUH.NET;YSF;52.192.129.174;42000;012;http://ah-huh.net/ysf/
02034;Alabama-Link;Alabama-Link;96.47.95.121;42000;048;http://ysf.alabamalink.info/
64230;America-RC;YSF-TO-WIRES-X;65.101.7.50;42001;015;http://arcysf.duckdns.org
21080;AmericaLink;AmericaLink;209.126.110.236;42000;443;http://hamfm.com/ysf/
30458;AnHui-HeFei01;YSF/BM460601;47.116.60.36;42000;003;http://eei-edu.f3322.net
31897;AR-AR-CIRCULO;ROSARIO;181.165.15.51;42000;007;http://circulorosario.linkpc.net
10111;AR-ARG;*ARG* Argentin;149.28.100.251;42000;001;http://ysfarg.ddns.net
73599;AR-TG722-LINK;YSF to TG722;80.211.1.59;42000;000;http://722ysfargentina.dnsalias.com
60842;ARG-FUSION;C4FM;200.81.152.112;42000;000;http://rotativos.dyndns.org:42002
31302;ARG-ROOM;Argentina-ROOM;190.194.12.53;42000;008;http://xlx.argentina-room.dns-cloud.net
66099;ARGENTINA-LINK;Link to TG7227;80.211.7.43;42000;014;http://7221ysfargentina.dnsalias.com
61159;ArkLaTex;ArkLaTex;104.198.203.19;42000;002;http://104.198.203.19
24490;ASL48270;AllStar;104.143.94.48;42042;001;http://104.143.94.48/YSFReflector/index.php
25223;AT-Austria-OE1;OE1XFV;213.47.71.17;42000;003;http://oe1xfv.ddns.net/YSFReflector-Dashboard/
00396;AT-Austria-OE3;OE3AAS;77.116.18.249;42100;001;http://oe3aas.ddns.net/YSFReflector-Dashboard/
71095;AT-Austria-OE5;OE5XOL;185.16.114.90;42000;001;http://oe5xol.ham-radio-op.net/YSFReflector-Dashboard/
59911;AT-Austria-OE8;OE8VIK;178.199.109.52;42000;000;http://oe8vik.internet-box.ch/YSFReflector-Dashboard
23201;AT-C4FM-Austria;(YCS001);89.185.97.38;42000;073;http://c4fm.oevsv.at/ycs/
73082;AU-Albury-Chat;Albury Chat;52.63.126.187;42000;009;http://52.63.126.187/
43110;AU-NSW;AU NSW;123.243.237.216;42000;000;http://ysfnsw.gustotech.net/
05057;AU_TAS;VK7 Tasmania;45.248.50.37;42001;001;http://vk7hse.duckdns.org/ysf
74037;BARC-ONT-CA;Burlington ARC;69.158.63.158;42000;000;http://barcysfreflector.ddns.net
00043;BAYAREA-YSF;Silicon Valley;45.32.129.65;42000;010;http://ysf.bsdworld.org/ysf/
44992;BE-YSF-Liege;Wires-X<>YSF;51.75.249.214;42002;000;http://51.75.249.214/ysf/
64364;BE-YSF-Vl;C4FMVlaanderen;81.95.126.168;42001;009;http://ysf.on4top.be/ysf/
79520;BE-YSF-Wallonie;C4FM Wallon;51.255.193.63;42000;003;http://www.ysfwallonie.net/
46197;BE-YSFEUREGIO;LNK_BE_EUREGIO;213.49.173.226;43000;003;http://rmx.noip.me:6380
00076;Berks-County;Pennsylvania;24.115.37.118;42020;000;http://
69733;BM2410/XLX010D;SSA Bulletin;95.216.197.75;42001;001;http://ysf2.brandmeister.se
56800;Boar's-Nest;Good Ol' Boys;67.140.163.107;42002;000;http://
90558;BR-PU2LRZ;TG268916 WIRES;186.228.91.9;42000;010;http://ysf-brasil.com.br
08059;Brasil-AMRASE;Brasil-Link;201.62.48.60;42000;003;http://ysf.amrase.org.br/ysf
72526;BRAZIL-724;DV Brazil;191.252.203.6;42000;004;https://ysf.dvbrazil.com.br/
85044;C4FM-SEOUL;TG45050 TO C4F;222.110.59.176;42000;004;http://ysfso.dvham.com/indexysf.php
36037;CA-420-Network;RAGCHEW;142.93.158.165;42000;003;https://ysf.420hamradio.network
77353;CA-Canada;C4FM Ontario;144.217.241.23;42100;007;http://c4fmontario.hopto.org
71083;CA-Canada-FR;Fusion Canada;38.110.97.161;42000;015;http://38.110.97.161
29579;CA-CQ-Canada;DMR TGIF 3022;142.93.158.165;42002;003;https://cqcanada.420hamradio.network/
71305;CA-DMRQ-3022;DMRQ TG3022;38.110.97.161;42554;003;http://dmrq.ca/
53710;CA-Maritimes;Can Maritimes;178.128.231.202;42000;007;http://ysf.nbdmr.net
19952;CA-Nanikana;Nanikana;142.217.113.98;42000;000;http://142.217.113.98
36010;CA-ON-ProCom;ON Prov Comms;70.50.41.195;42000;003;http://freestar.homelinux.net/ysf
23829;CA-Upper-Can;Upper Can QRP;64.118.21.239;42100;005;http://ve3ucc.ddns.net/
13339;CA-WEST-CAN;Western Canada;172.105.26.148;42001;000;http://ysf.ve6meo.ca
13124;CA-YSF-CHARC;SW QUEBEC,CA;207.35.36.179;42000;002;https://207.35.36.179
72576;CA-YSF-TO-WIRESX;REF-BRIDGE-LAB;192.222.226.35;42002;000;http://dashboard.va2ss.com:8080/
48095;CAMCAST;YSF REFLECTOR;80.211.12.209;42000;000;http://80.211.12.209/index.php
01177;CARG;CURACAO YSF;138.219.142.144;42000;001;http://138.219.142.144
79602;Carolina-Link;79602;208.104.55.181;42001;012;http://208.104.55.181/index.php
77785;CDARIN;CDARIN-XLX420;149.28.54.17;42002;000;https://xlx.cdarin.net/ysf
30998;CH-228-Swiss;YCS Group 28 S;195.225.116.245;42000;005;http://ysf.hb-connect.ch/
63347;CH-228-Swiss2;HB-CONNECT;176.10.105.210;42002;000;http://
15280;CH-HB9VD;Radioamateurs;217.182.128.3;42000;002;http://reflector.hb9vd.ch/ysf
37664;CH-IT-SWISS;C4FM OM;94.177.215.206;42000;000;http://94.177.215.206
66049;ChinaLink;China YSF Refl;60.219.211.9;42000;000;http://ysf.tocall.fun:8081
22638;CH_JOTA;Jamboree on th;157.161.57.65;42001;000;http://pi2.woody.ch:8080/YSFReflector-Dashboard/ (ipv6 only)
72350;CL-CHILE;YSF to TG730;186.64.123.59;42000;002;http://sdradio.cl/ysf
34287;CL-CL-CHILE;YSF HOTSPOT'S;186.103.150.254;42000;000;https://www.radioaficion.pro/ysf
19525;CL-EMCOMM;TG 730911;186.64.123.59;42001;000;http://sdradio.cl/ysf2
09627;CL-YSF;CHILE YSF ROOM;186.64.123.59;42002;002;http://sdradio.cl/ysf3
18829;CN-CC#1;TG 460501;47.104.177.248;42000;001;https://mmdvm.cc/ysf/
86319;CN-China-#3;C4FM;123.58.6.137;42000;003;http://123.58.6.137:8088/
46055;CN-China-#4;TG460531;112.229.25.110;42003;000;http://pi.jwebid.com:81
49766;CN-China-#7;YSFn/DMR/P25;47.100.76.205;42002;000;http://
50565;CN-CN-BJS-YSF;CN BJS C4FM;49.233.142.122;42250;002;https://ysf.bh1ofp.com/
08408;CN-CN-China-4;P25;47.105.33.47;42003;002;http://www.bg3hbr.cn/ysfp25/
25574;CN-CN-SH;YSF/TG46068;116.235.186.62;42000;002;http://chinafex.tpddns.cn:82
99996;CN-CN-SH-BR4AC;TG46021;118.89.184.51;42000;001;http://
41095;CN-CN-SH-JIUTING;TG4601319;140.143.12.207;42000;001;http://
99117;CN-LiaoNing;YSF by BH2UOL;47.95.194.251;42000;000;http://47.95.194.251
36400;CN-NMG-1#;C4FM China;39.64.187.131;42000;001;http://jw.jwebid.com:88
01347;CN-Shanghai;YSF by BH4EZG;124.78.51.205;42000;000;http://
45441;CN-Shenyang-2;YSF by BH2UOL;139.226.2.194;42000;000;http://angel66.f3322.net:2122/
87327;CN-SHLK;C4FM;218.79.217.10;42000;002;http://
19610;CN-SXXY-YSF;TG46091;123.139.189.182;42000;001;http://ysf.jzsqx.com:3578/ysf/
10552;CN-SZ-YSF;BM TG46073;14.116.159.221;42000;005;http://
78497;CN-TIANJIN;C4FM/TG460022;47.104.79.192;42000;002;http://
57490;CN-Wuhan;CNWUH YSFRef;118.89.199.238;42000;004;http://
84099;CN-XUZHOU;TG460516;119.45.191.42;42000;003;http://www.bd4two.cn
69058;CNARN;CNARN;45.76.175.5;42000;014;http://cnarn.hopto.org
20059;CN_China_#1;W24166/TG46001;58.250.171.29;42000;056;http://ysf.sz790.com:8081/
72001;CO-HK_NAL_LCRA;BM TG732;186.29.69.76;42000;007;http://ysfnal.lcra.org.co
11115;CQ-MICHIGAN;MICHIGAN USA;107.141.52.226;42002;000;http://
27715;CQ-OHIO;Ohio, USA;24.192.74.248;42002;001;http://
18480;CT-BMCAT;C4FM Catalunya;94.177.237.192;42000;010;http://ysf900.dyndns.org/ysf
04523;CT-CATALANA;C4FM CATALUNYA;213.195.111.148;42000;004;http://catalana.ea3hkb.cat
68592;CT-GARRAF;C4FM CATALUNYA;213.195.111.148;42001;005;http://garraf.ea3hkb.cat
99797;CT-RI-ROOM;C4FM LINKED;45.58.45.126;42000;008;http://
12096;CW-ToyTronNet;Sunny Curacao;186.159.96.100;42001;000;http://ysf.toytron.com
14353;CY-YSF-Cyprus;YSF Cyprus Ref;213.7.197.202;42000;001;http://xlx146.ddns.net:81/ysf/
26541;CZ-Czech;TG2300 DCS19V;80.250.3.114;42000;011;http://80.250.3.114/index.php
26541;CZ-Czech;TG2300 DCS19V;80.250.3.114;42000;011;http://xlx230.ok2it.com
52690;CZ-YSF-Klatovy;CZ;46.23.62.124;42200;000;http://46.23.62.124:42080
77329;CZ-YSF-Praha;CZ YSF Praha;185.32.183.148;42000;004;http://185.32.183.148/ysf/
21972;DE-Berlin;Spandau;81.169.245.52;42000;004;http://www.comvision.de/ysf/
42539;DE-Bremen;Bremen-Nord;82.207.204.207;42002;000;http://do0bre.ddns.net/
14187;DE-DL-DL1BH;Bremerhaven;87.245.30.60;42000;003;http://
90730;DE-DL-Elbe-Weser;DL-Elbe-Weser;91.58.164.76;42000;002;http://dl-elbe-weser.spdns.de
07588;DE-DL-Hamburg;Hamburg City;95.116.202.35;42000;006;http://db0fs-router.hamnet.hamburg:22225/index.php
54919;DE-DL-NORDWEST;DL-Nordwest;93.240.48.68;42000;034;http://dl-nordwest.spdns.de
68399;DE-DL-Oberberg;Bergisches Kr.;82.165.136.160;42000;001;http://ysf.shakerware.de
47791;DE-DL-Saar;Saarland;167.86.110.62;42002;001;https://c4fm.ysfreflector.de/DL-Saar/
07794;DE-DL5OCD;Hildesheim;46.41.2.20;42000;004;http://dl5ocd.selfhost.eu
21584;DE-Fusion-MUC;Fusion-MUC;93.240.113.55;42004;002;http://
62829;DE-Germany;YSF262 BM263;167.86.110.62;42000;010;https://c4fm.ysfreflector.de/Germany
22675;DE-Germany02;MultiNet-Bridg;185.228.139.209;42000;009;http://ysf-germany02.xreflector.net/ysf/
92161;DE-GOETTINGEN;Raum Gö;51.15.40.103;42001;005;http://goettingen-ysf.tk
02883;DE-Hannover-XLnk;Hannover und U;81.14.225.84;42000;002;http://ysf.hannover-x.link
44305;DE-Heidekreis;Niedersachsen;91.64.24.111;41000;002;http://do3bsl.ddns.net
19138;DE-HESSEN-F17;F17 Reflector;80.69.46.184;42000;002;http://
55160;DE-Huelzweiler;DL4WM-Reflecto;213.135.12.4;42000;000;http://
93571;DE-Inselfreunde;BM-TG26444;88.198.94.77;42444;002;http://
68030;DE-Laatzen;Hannover;159.69.64.204;42000;001;https://blackdan.de/ysf
90448;DE-Neumarkt;YSF Neumarkt;213.202.228.66;42000;004;http://213.202.228.66/neumarkt/YSFReflector-Dashboard/index.php
87939;DE-Notfunk;NotfunkGruppe;78.47.182.224;42001;000;https://notfunk.ysf.vfdb.org/
61156;DE-Oberbayern;BM-TG26285;88.198.94.77;42285;003;http://
13100;DE-OBERLAUSITZ;YSF Ostsachsen;85.214.61.75;42000;002;https://ysf02.bzsax.de/ysf-ol/
09319;DE-Oberpfalz;Region Opf.;78.47.182.224;42009;007;https://oberpfalz.vfdb.org/
13111;DE-OBL-RAUM-1;YSF;85.214.61.75;42001;000;http://
64445;DE-OWL;XLX508G OWL;185.188.4.15;42001;006;http://ysf.hb9gfx.ch
74154;DE-PEGASUS;Multi-Bridge;78.46.11.65;42000;077;https://status.projekt-pegasus.net/
20548;DE-PEGASUS2;Test System;78.46.11.65;42001;001;https://status.projekt-pegasus.net/
63421;DE-Ruhrgebiet;Ruhrgebiet;144.76.12.90;42000;006;http://dg3yjb.beba.re/YSFReflector
10977;DE-Sachsen;BM TG2629;109.104.48.10;42001;001;http://
68240;DE-Schwarzwald;#68240 Schwarz;185.75.164.30;42000;008;https://db0vs.de/YSFReflector-Dashboard/index.php
55966;DE-Thueringen;Thüringen Ref;195.145.3.97;42000;005;http://44.225.117.67/YSFReflector-Dashboard/
95352;DE-Twitterrunde;GW BM TG263333;167.86.110.62;42001;001;https://c4fm.ysfreflector.de/Twitterrunde
53414;DE-VFDB;Telekom&Post;78.47.182.224;42000;001;https://vfdb.ysf.vfdb.org/
33465;DE_DL-Baltic;Greifswald;81.169.128.244;42001;003;http://ysf.digitalfunk-nordost.de
46981;DL1SGP-YSF;Testing;51.75.79.91;42000;000;http://
58967;DMRPlus-IT;DMRPlus Italia;185.82.114.247;42000;002;http://ysf.aotnet.it/
01579;DO-DOMREP;YSF DRP;172.105.158.111;42000;001;http://hi8k.xreflector.es/
30406;DO-YSF-Dom.-Rep.;YSF for HI;190.166.132.207;42000;002;http://arcrica.dyndns.org:8088
43499;DPRNS;TH DPRNS;203.150.19.24;42000;005;http://c4fm.dprns.com
38035;DRIVETIME;FW Drivetime;71.81.181.30;42061;001;http://ysf.ki5cey.com:45000/
53636;DV-Caribbean;DV Multimode;190.213.20.171;42100;001;http://dvcar.9y4c.tk:8080
31769;DV-Modems;DV_Modems_YSF_;51.91.78.118;42000;001;http://
78427;DX1ARM;DX1ARM-RPT;104.168.176.33;42000;006;http://
11096;DX1O-Amsat-PH;DX1O Amsat PH;206.189.146.41;42000;001;http://206.189.146.41
06989;DXhunter-SM2;DXhunter SM2;95.217.7.128;42000;001;http://95.217.7.128
18196;EA-ARSA;EA2RKS;104.148.41.57;42003;002;http://arsa.xreflector.es/
22401;EA-C4FM-Spain;(YCS224);212.237.3.141;42000;060;http://ycs.xreflector.es/
73531;EA-CANARIAS;CANARIAS;164.132.96.157;42005;000;http://ysfcanarias.c4fm.es/
94533;EA-Distrito-1;Wires X Spain;80.211.102.100;42000;001;http://80.211.102.100
62980;EA-Distrito-4;REM Spain YSF;212.237.0.67;42000;015;http://ysfdistrito4.xreflector.es/
90182;EA-Distrito-7;RC Veleta;212.237.11.53;42000;001;http://212.237.11.53/html/ysf/
18470;EA-EXTREMADURA;EXTREMADURA;51.75.140.10;42002;002;http://ysfextemadura.c4fm.es/ysf2
42670;EA-HAMNET;C4FM Spain;80.211.105.70;42000;001;http://80.211.105.70/
42670;EA-HAMNET;C4FM Spain;80.211.105.70;42000;001;http://80.211.105.70/
55815;EA-SPAIN-21461;MULTIPROTOCOLO;85.255.8.71;42105;002;http://hblinkspain.duckdns.org/YSFReflector
17535;EA-TG21468;CANARIAS;164.132.96.157;42003;004;http://ysfhispano.c4fm.es/
31977;ECOAMERICA;AB6MM;104.194.206.233;42000;002;http://104.194.206.233/index.php
74161;ES-112;EMERGENCIAS;51.77.213.200;42004;000;http://51.77.213.200/ysf4
32027;ES-ADER;ASSOCIACIO ADE;62.171.178.202;42000;004;http://digitalader.ddns.net/ysf
90884;ES-ADR;Radio Club ADR;51.254.128.134;42003;000;http://51.254.128.134/ysf3
66492;ES-AMIRED;YAESU AMIRED;89.38.150.252;42010;000;http://
64324;ES-BM-Sevilla;BM21441;104.148.41.57;42002;001;http://fnssevilla.c4fm.es/ysf2
96308;ES-CACERES;SEC.LOC.URE CC;51.75.140.10;42000;001;http://ysfcaceres.c4fm.es
09059;ES-CANARIAS;Canarias C4FM;185.166.212.132;42000;000;http://185.166.212.132/ysf/
32474;ES-CQ-DX;CQ WORLD WIDE;51.77.213.200;42003;001;http://51.77.213.200/ysf3
41674;ES-EA-SPAIN;Red WiresX ES;212.237.11.53;42002;001;http://ysfspain.c4fm.es/html/ysf2
34018;ES-EA4GAX-YSF;YSF EA4GAX;51.83.78.210;42002;000;http://51.83.78.210/YSF/
16172;ES-EA7URC-Link;EA7URC Oficial;193.30.100.102;42000;001;http://
99760;ES-EALINK;YSF EALINK;194.182.66.76;42000;000;http://www.fusion.ealink.es/ysf/
11650;ES-EL-EJIDO;EL EJIDO SPAIN;80.88.90.73;42000;000;http://80.88.90.73/
41996;ES-ELITE;C4FM;51.77.213.200;42002;019;http://51.77.213.200/ysf2
96124;ES-ES-ALMERIA;YSF ALMERIA;80.211.1.143;42000;002;http://80.211.1.143/ysf/
60725;ES-GOMERA;R5 GOMERA VHF;185.166.212.132;42003;000;http://185.166.212.132/ysf4
10069;ES-IBERIA;C4FM;51.77.213.200;42001;001;http://51.77.213.200/ysf
14275;ES-MADRID;YSF de Madrid;51.254.128.134;42002;001;http://51.254.128.134/ysf2
65531;ES-MARCA;YSF MARCA;80.211.41.147;42000;001;http://80.211.41.147/ysf/
49810;ES-PEANUT-YSF;YSF PEANUT;164.132.96.157;42000;007;http://ysfpeanut.c4fm.es
15642;ES-REM-SPAIN;YSF Reflector;80.211.163.139;42000;005;http://ysfreflector-rem.spdns.org
18044;ES-TECNICO-Y-MAS;URE CT TENERIF;185.166.212.132;42002;000;http://185.166.212.132/ysf3/
45904;ES-TENERIFE;YSF<>TG21438;185.166.212.132;42001;001;http://185.166.212.132/ysf2/
50246;ES-Zulu-Radio;YSF Zulu Radio;51.254.128.134;42000;003;https://zuluradio.es/ysf/
50135;EST-Ref;YSF reflector;95.216.163.65;42000;001;http://ysf.2ip.ee/dashboard
06975;Europe-YSF;Europe-YSF;93.240.48.68;42100;004;http://Europe-YSF.spdns.org:81
00007;EUROPELINK;Europe link;161.97.73.43;42000;142;http://europelink.pa7lim.nl
13029;FI-MIKKELI;Mikkeli YSF;139.162.159.150;42000;003;http://139.162.159.150/ysf/
96442;Foxhole;RagChew;52.176.105.136;42000;000;http://ysf.kz4fox.com
95198;FR-Centre-France;Centre-France;185.4.78.122;42002;009;http://ysf-centre-france.f1tzo.com:81
00645;FR-FON-Gateway;Salon FON GW;185.4.78.122;42000;001;http://ysf-fon-gateway.f1tzo.com:81
71173;FR-Franche-Comte;Franche-Comte;51.75.252.197;42000;000;http://
30262;FR-International;Salon Interna.;185.4.78.122;42005;002;http://ysf-international-rrf.f1tzo.com:81
72173;FR-RIDF;FR Reseau IDF;185.4.78.122;42001;001;http://
86886;FR-Room-ZIT;Room F1ZIT;151.80.143.185;42002;035;http://151.80.143.185/zit/YSFReflector-Dashboard/
39510;FR-wiresxfrance;Wires-X-France;151.80.143.185;42001;000;http://151.80.143.185/WXF/YSFReflector-Dashboard/index.php
83665;FR-YSF-Alpes;Rhone-Alpes;217.182.66.229;42000;000;http://ysf-alpes.f4gve.net
13844;FR-YSF-Cappelle;YSF Room F1ZKY;2.59.239.114;42000;000;http://ysf.a3rn.org:2626
77805;FR-YSF-Dijon;FR YSF Dijon;185.216.25.140;42000;001;http://
58617;FR-YSF-France;Fusion France;87.98.132.205;42000;037;http://ysf-france.fr/
64879;FR-YSF-FraWide;France-Wide;5.135.190.184;42010;005;http://ns3294400.ovh.net/YSFDashboard/
44708;FR-YSF-HBLink;C4FM HBLink TG;82.64.55.217;42000;000;http://ysf-hblink.dyndns.org:8778/
16762;FR-YSF-HDF;Region Nord;51.15.172.24;42001;000;https://srv.hambox.fr/hdf-dashboard/
91713;FR-YSF-Limouzi;C4FM Limousin;82.64.55.4;42000;002;http://ysf-limousin.dyndns.org:8787
34722;FR-YSF-Linux-fr;Linux French;213.32.19.95;42000;000;http://vps.hambox.fr/ysf-linux-fr/
41576;FR-YSF-Nantes;YSF Room F5ZLK;92.222.75.165;42000;003;http://www.f5ore.dyndns.org
46353;FR-YSF-Nord;Nord;178.32.163.106;42000;002;http://
24703;FR-YSF-NordOuest;XLX933-E;78.206.208.208;42000;001;http://78.206.208.208:8081/YSFReflector-Dashboard/index.php
59495;FR-YSF-St-Amand;St Amand (59);51.15.172.24;42000;000;http://
04170;FR-YSF-TEST;France-Tests;51.75.133.61;42000;000;http://vps731279.ovh.net/
39300;FR-YSF-URGENCE;FR-emcom;78.206.208.208;42021;003;https://fr-emcom.com/
87357;GB-2E0ENN-DIRECT;Direct Server;86.181.36.50;42003;000;http://
46504;GB-400-Club;400 Club;157.245.45.67;42008;001;https://400club.446em.uk
91153;GB-4SQITYSF;4SquareIT YSF;34.89.92.173;42000;000;http://ysf.eilec.com
01918;GB-Allstars;Fusion Allstrs;81.133.73.69;42002;005;http://
88473;GB-BARC-CLUB;Burnham On Sea;88.97.60.42;42002;003;http://88.97.60.42:8080/
42233;GB-BLIND-VETS;Blind Veterans;159.65.16.93;42000;005;http://
70507;GB-CelticCluster;YSF-Reflector;85.159.210.162;42000;000;https://ysfref.celticcluster.org
88972;GB-CovARS;Coventry ARS;18.130.199.150;42001;001;http://ysf2.g1iul.org.uk
23952;GB-CQ-Sussex;All Welcome;84.9.168.216;42002;001;http://
19889;GB-Dartmoor-Room;Dartmoor Area;80.229.144.250;42002;001;http://
64259;GB-Durham;YSFReflector;34.89.108.212;42000;000;http://
91767;GB-Fusion-Kernow;Fusion SW UK;87.117.229.165;43000;001;http://ysf.mb6cc.co.uk
08248;GB-GX4MWS-Club;Macc A.R. Club;188.165.209.35;42000;000;http://
16437;GB-hideout;xlx201;157.245.45.67;42003;001;https://ukhide.446em.uk
57727;GB-HUBNet;Link to HUBNet;5.57.94.92;42000;013;https://hubnetwork.uk/
84338;GB-M0OUK-Link;www.OARC.uk;165.22.121.251;42002;003;http://ysf.oarc.uk/
54916;GB-MB6RI;YSFR mb6ri.co.;86.132.7.82;42200;001;http://wires-xuk.sytes.net/
97576;GB-N.Ireland;YSF N.Ireland;87.117.229.165;42500;002;http://
13344;GB-North-West-UK;NWRG;209.250.255.162;42000;006;http://209.250.255.162/
58362;GB-NorthWestLink;TG23520;217.46.179.246;42004;001;http://
26368;GB-qso365;qso365.co.uk;212.159.79.56;42002;002;http://g6nhu.getmyip.com:8900
41012;GB-Sandbox;Testing;88.97.60.42;42003;000;http://88.97.60.42:8090
23551;GB-SCOT-MULTI;SCOTLAND MULTI;92.3.117.38;42000;001;http://
67256;GB-Smoggie-UK;SMOGGIE LINK;108.61.172.174;42000;004;http://
62400;GB-W.Mids;IO82UI;86.148.110.250;42021;001;http://wfrg.ddns.net/
06284;GB-WARC;Warrington ARC;109.148.101.52;42000;004;http://
93529;GB-WestBerkshire;West Berks UK;62.232.43.186;42000;003;http://m0cuk.uk:8080
13322;GB-xlx201b;MultiMode;157.245.45.67;42001;001;https://xlx201b.446em.uk
41142;GB-XLX969;Relfector for;142.93.46.36;42000;000;http://xlx969.nwfg.online
27617;GB-YORKSHIRE-YSF;YSF Leeds UK;45.58.139.108;42000;001;http://45.58.139.108/
23945;GB3TH;Tamworth UK;5.2.112.26;42000;004;http://5.2.112.26
77817;GB7SJ;Repeater link;217.46.179.246;42000;006;http://
83260;GR-HellasFame;Greek YSF Test;95.179.190.33;42000;002;http://stargate-dmr.net:8080
96370;Gr8ter-Detroit;Great Lakes MI;107.141.52.226;42006;001;http://
89995;Great-Lakes;Great Lakes Ar;107.141.52.226;42003;001;http://
60237;GT-ASL-48455;AllStar Audio;190.148.222.28;42101;001;http://190.148.222.28:8502/index.php
36606;GT-Guatemala;Enlace DMR+;104.143.94.48;42142;003;http://104.143.94.48/YSFReflector/YSFHBLink/index.php
25419;Guatemala;Link Regional;ysf.tg9aor.net;42000;002;http://
47247;HB-C4FM-Basel;Gruppo HB9CSR;212.237.33.114;43000;003;http://212.237.33.114/c4fm/index.php
87252;HBLINK-SPAIN;HBLINK SPAIN;85.255.8.71;42000;002;http://hblinkspain.duckdns.org/YSF
73821;HCRA-YSF;HCRA Refl;168.235.80.185;42001;001;http://ysf.nt1k.com
23667;HELLAS-Zone;YSF Reflector;85.93.91.80;42000;016;http://www.hellaszone.com/index.php/ysf-hellas-zone
36039;HK-HAM;YSF<=>454;119.237.142.173;42002;002;http://ysf.852ham.org/
56322;HN-HONDURAS;YSF Honduras;104.223.170.236;42000;002;http://ysfhonduras.xreflector.es/
01689;HP-PANAMA-HUB;C4FM DMR;179.63.194.94;42000;013;http://hp-panama-hub.c4fmpanama.org/
14248;HR-9A-C4FM;9A C4FM HR;35.175.149.169;42000;004;http://35.175.149.169
18164;HU-Balaton;YSF Siofok;5.189.162.5;42200;002;http://5.189.162.5
49993;HU-HU-TG2162;BM TG2162;185.187.75.192;42300;003;http://brandmeister.hu/ysfref2162/
41120;HU-Hungary;BM TG216;185.187.75.192;42100;003;http://brandmeister.hu/ysfref/
26973;Hudson-City-NJ;YSF Reflector;192.223.27.159;42000;003;http://ysf.dmrnet.net/ysf
52077;IE_YSF_Ireland;Fusion <> DMR;44.155.254.23;42000;004;https://ysf-2724.ei3rcw.ampr.org/index.php
14689;Indiana-Link-So;Bridge:IRLP_00;107.155.116.148;42000;008;http://107.155.116.148/ysf
96014;IRLP_0070;Bridge to 0070;75.127.13.79;42000;003;http://k5nx.com/YSFdashboard
60905;IRLP_0087;Bridge to 0087;192.210.239.5;42000;001;http://k8lrc.crabdance.com/index.php
75373;IT-773Cluster;TG222773 - BM;89.46.75.166;42000;003;http://xlx773.iz0rin.it/ysf/
92157;IT-APRS-PUGLIA;www.aprspuglia;185.216.27.214;42000;000;http://185.216.27.214/
54102;IT-ARI-VINCI;C4FM;80.211.99.134;42000;001;http://80.211.99.134
46773;IT-C4FM-ABRUZZO;IT-DMR 22261;5.88.241.47;42001;003;http://ysf-abruzzo.ariroseto.it/ysf
17120;IT-C4FM-HBLink-D;Zona1 Piemonte;94.177.173.53;42000;001;http://94.177.173.53/ysf/index.php
22201;IT-C4FM-Italy;(YCS222);94.177.187.31;42000;023;http://ycs.grupporadiofirenze.net/ycs/
16547;IT-C4FM-LECCE;YSFReflector;80.211.133.104;42000;004;http://c4fm-lecce.ddns.net/index.php
16547;IT-C4FM-LECCE;YSFReflector;80.211.133.104;42000;004;http://c4fm-lecce.ddns.net/index.php
30483;IT-C4FM-Lodi;Lombardia;94.177.187.40;42000;004;http://ysflodi.iw2gob.it/c4fm/index.php
14115;IT-C4FM-PUGLIA;DMR TG PUGLIA;95.248.215.75;42000;002;http://ysfpuglia.iz7gll.it:8888
26765;IT-C4FM-ROSETO;IT-DMR 222035;109.239.250.3;42000;002;http://ysf-roseto.ariroseto.it/ysf
06901;IT-C4FM-TERAMO;C4FM TERAMO;195.32.87.220;42000;000;http://ysf-teramo.ns0.it/
94514;IT-CALABRIA;MP CALABRIA;185.250.144.228;42000;001;http://185.250.144.228/
27746;IT-CATANIA;TG22491-BM;91.92.136.252;42000;001;http://91.92.136.252/YSFdash
23740;IT-DGT-Zona-0;Rete DGT zona0;185.177.59.221;42000;001;http://185.177.59.221/YSF/
47946;IT-Digiland;Italia;82.223.18.138;42000;002;http://82.223.18.138/ysf/index.php
58288;IT-GDO-FUSION;C4FM OSSOLA;88.149.167.221;42000;000;http://iz1zpj.duckdns.org
76421;IT-GIOIATAURO;#76421;80.211.74.187;42000;005;http://ysf.rcdigital.it
26045;IT-GRF-YSF;TUSCANY MULTIP;31.14.142.119;42005;008;http://ysf.grupporadiofirenze.net/ysf_5
03832;IT-I0-LAZIO;773RadioGroup;93.186.255.126;42000;005;http://ysf.iz0rin.it/ysf
45679;IT-I6-ABRUZZO;IT-I6-ABRUZZO;95.246.180.57;42000;001;http://iz6ouf77.ddns.net/ysf/
64599;IT-IQ3CR;ARI Belluno;95.233.192.20;42000;000;http://iq3cr.ddns.net/index.php
92365;IT-IS0-Sardegna;Multiprotocoll;51.254.206.201;42000;002;https://ysf.is0.org
18255;IT-ITALIA;YSF Italia CIS;185.177.59.166;42000;002;http://
18316;IT-ITALY-I2-MI;ITALY-I2-MI;94.33.52.82;42001;002;http://www.iw2hgl.it
82021;IT-IU3GMR-YSF;IU3GMR ROOM;95.233.192.20;43000;000;http://iu3gmr.ddns.net/index.php
05579;IT-PERAZZA;YSF Reflector;195.128.234.114;42001;000;http://ysf.iz6rnd.it
73436;IT-RedNet;Svxlink-net;80.211.239.167;42010;001;http://rednet.iu0krr.it/YSF_2/
01444;IT-RNG-NET;GRF CLUSTER;164.68.100.69;42444;001;http://XLX038.grupporadiofirenze.net
10885;IT-RNRE-YSF;CROSSLINK;31.14.135.7;42000;001;http://ysf-10885.duckdns.org/ysf/
34697;IT-SICILIA;#34697;80.211.84.249;42001;004;http://ysf.digitalsicilia.it
12385;IT-TERNI;TERNI TG88;80.211.239.167;42020;001;http://itterni.iu0krr.it/YSF_1/
79445;IT-TUSCANY;C4FM-DMR-NXDN;80.211.99.134;42001;001;http://80.211.99.134/YSFTuscany/
71249;IT-UMBRIA;YSF UMBRIA;80.211.239.167;42000;001;http://itumbria.iu0krr.it/YSF_3/
72983;IT-VENETO;VENETO MULTIP;81.174.3.170;42010;000;http://ysfr.dyndns.org
93884;IT-YSF-BRESCIA;CLUSTER BS;212.237.56.10;42000;001;http://ysf.dmrbrescia.it
28345;IT-YSF-CUNEO;C4FM ROOM CUNE;82.56.147.96;42000;000;http://
43102;IT-YSF-HBLINK;TG 22200;80.211.64.211;42005;001;https://ysf.hblink.it
65716;IT-YSF-LUCANIA;YSF LUCANIA;51.255.172.249;42001;000;http://ysf.iz8gur.it/
31585;IT-YSF-NORD;ITALY NORD;212.237.9.215;42000;007;http://ysfitalynord.dyndns.biz/ysf/
82044;IT-YSFROOM-ITALY;WIRES-X ITALY;80.211.96.39;42000;029;http://ysfroomitaly.iw2gob.it/c4fm/index.php
67411;IT-Zona-4;EmiliaRomagna;212.84.32.29;42000;000;http://
11881;IT-Zona-9;Sicilia;80.211.62.178;42001;004;http://80.211.62.178/YSF/index.php
22211;IT_C4FM-LIGURIA;Reg. Liguria;212.237.8.77;42004;001;http://
22236;IT_C4FM-TIGULLIO;Tigullio;188.213.173.69;42000;001;http://c4fm.selfip.com/
00012;JAPANLINK;Japan link;207.244.224.170;42000;053;http://japanlink.xreflector-jp.org
90219;Jason's-Bar;C4FM Saloon;67.205.134.229;42000;001;http://ysf.w4jmf.com
25383;JP-JAPAN;Fusion Japan;122.222.1.50;42000;017;http://c4fm.owari.biz/ysfref/
88748;JP-SAKURA-Net;SNWLab Fusion;153.126.179.214;42000;000;http://ysfref.snwlab.net/
15742;JP-YSF-NAGOYA;YSF;221.170.106.177;42000;013;http://xrf098.mydns.jp:8030
79605;JP-YSF-ONOGORO;YSF;157.65.31.91;42001;000;http://xlx970.onogoro.net/
30051;JP-YSFDMR-Net;YSF;211.131.179.106;42000;003;http://ysfreflector.pgw.jp
80960;JP_XRF499;YSF;203.137.76.22;42000;001;http://xrf499.xreflector-jp.org/ysf/
31983;K8JTK-Hub;DVMIS;149.28.114.219;42001;002;http://YSFReflector31983.K8JTK.org
10482;KAPIHAN;kapihan.net;45.77.186.5;42001;007;http://ysf.kapihan.net
22856;KAPIHAN2;kapihan.net;144.202.99.113;42001;001;http://ysf2.kapihan.net
89902;KB1NE-GROUP;NE Wireless;104.236.92.130;42000;001;http://
36745;KN6CLM;Elevated RF;107.172.156.110;42000;001;http://107.172.156.110/
92708;konabarbarian;SF Bay Area;54.197.204.105;42000;002;http://
48316;KP4GA;Puerto Rico;66.50.96.7;42000;001;http://kp4ga.selfip.com/
44444;KR1P;YSF to AllStar;166.70.154.77;42225;003;http://ysf.kr1p.org
17077;LaGrandeDigital;www.lagrandefl;99.145.170.193;42000;002;http://digital.lagrandefl.com
33461;LATINOS-UNIDO;HISPANIC TG;174.138.36.176;42000;002;http://
59933;LibertyNet;W8RFA Free4all;68.60.143.37;42000;000;http://
15425;LincsLink;14 characters;86.181.36.50;42002;003;http://
07188;LZ0IOS;Repeater Sofia;46.233.56.166;42005;002;http://
24597;M1AXM-CQUK;Devon UK;fusion2.m1axm.co.uk;42001;000;http://fusion.m1axm.co.uk
53278;MALLORCA;ZONA EA;82.223.122.28;42000;001;http://
13827;ME-YSFMontenegro;TG29792;89.188.45.102;43007;004;http://13827ysf.ddns.net
74718;MID-MICHIGAN;GREAT LAKES;107.141.52.226;42005;000;http://
21505;MIL+VET;Mil and Vets;5.81.41.50;42000;001;http://gb7rn.ddns.net/9111
23944;MX-Fusion-Mexico;Fusion Mexico;200.57.9.10;42000;004;http://ysf.ared.org.mx
67915;MX-Normex;YSF;208.82.116.113;42000;000;http://208.82.116.113/index.php
11714;MY-Malaysia-Net;Malaysia Net;150.129.184.54;42000;002;http://ysf.dmrnet.org/ysf/index.php
35767;N1AJW-Test-2;Potpourri;104.153.109.57;42005;003;https:// 104.153.109.57
88843;NA9PL_PAAROS;PAAROS.com;159.203.73.99;42000;004;http://NA9PL.com/YSF/
77518;NEARC;BM TG 31257;172.245.110.121;42000;001;http://ysf.w0jay.com/YSFReflector-Dashboard/index.php
62121;NEMARC-Fusion;NEMARC;3.225.138.100;42003;005;http://k2ej-ysf.ddns.net/
45734;NETSWATbg;YSF SWATbg NET;94.26.58.60;42005;000;https://ysf.swat.bg
32772;NL-C4FM-Dutch;NL C4FM Dutch;81.169.224.52;42000;002;http://nlc4fmdutch.pa7lim.nl
96455;NL-Central;Centraal NL;90.145.156.242;42000;079;http://c4fm.digitalevoice.nl
31911;NL-DARES;EMCOMM NL;80.115.153.238;42000;000;http://dares.ham-radio-op.net:8080
20070;NL-Hobbyscoop;hobbyscoop.nl;44.137.42.25;42000;004;http://fusion.pi9noz.ampr.org
20431;NL-Limburg;Goojundaag LB;37.97.194.88;42002;001;http://limburg.is-very-nice.org
73238;NL-Noord;test reflector;44.137.87.82;42000;002;http://44.137.87.82/index.php
63539;NL-Oost;test reflector;44.137.87.83;42000;002;http://44.137.87.83/index.php
59819;NL-PA0ROB;test nlx204;82.171.119.45;42004;000;http://nlpa0rob.ddns.net/
01966;NL-PD4MM;Marcel QPO;80.115.153.238;42004;001;http://pd4mm.nl
73443;NL-PI1DAF;Multi Repeater;86.80.221.107;42000;002;http:/pd0poh.ddns.net
91665;NL-RNLMC;Marine Corps;95.111.246.149;42001;001;http://Marines.Ham-Radio-OP.net
63234;NL-TechTalk;204_Z - TG2045;82.171.119.45;42002;002;http://nltechtalk.ddns.net
71117;NL-TEST;Dutch test;173.249.54.49;42000;002;http://ysftest.pa7lim.nl
76591;NL-XLX204X;Multi Mode [X];82.171.119.45;42003;002;http://nlxlx204x.ddns.net/
44919;NO-General;Norwegian chat;80.89.46.242;42000;002;http://ysf.hamlabs.no/ysf/index.php
21302;North-Mich;W1WRS repeater;47.224.93.95;42002;002;http://192.168.1.12
67703;Northern-NH-ASL;US NNHASL;72.73.78.92;42000;001;https://nhhub.wordpress.com/
33156;NV-Bridge;Fernley, NV;71.89.225.19;42000;000;http://
51561;NZ-Ashburton;Repeater;114.23.212.119;42000;008;http://zl4rx.co.nz:89
59115;NZ-Canterbury-NZ;Wires-X <<>> B;124.197.62.162;42050;002;http://canterburydigitalreflectors.hopto.org
62078;NZ-Christchurch;South Island -;124.197.62.162;42000;001;http://xlx530.hopto.org/YSF
75161;NZ-ROAR-NZ;Rotarians ARNZ;203.86.194.92;42000;001;http://www.xlx299.nz/ysf/
52755;NZ-Talk;Kiwi Link;123.255.62.27;42000;001;http://nz-talk.ddns.net:89
29073;NZ-Whangarei;ZL1AMK YSF;218.101.105.192;42000;001;http://zl1amk.ddns.net:85
33191;NZ-YSF-Reflector;NZ Reflector;114.23.212.119;43000;001;http://zl4rx.co.nz:88
89797;NZ-YSF-XLX287;ysf.zl2wl.nz;45.32.90.50;42000;001;http://ysf.zl2wl.nz
07338;NZ-YSF-XLX750;http://www.xlx;203.86.206.49;42001;002;http://ysf.xlx750.nz
72753;Oakland;W6OAK;45.77.188.74;42000;001;http://ysf.w6oak.org/
40557;Ohio-Link---LGLG;OHIO-LINK;209.190.4.10;42000;047;http://ysf.glorb.com
72170;openGD77;openGD77;128.199.76.58;42000;001;http://128.199.76.58/
52792;Orobie-Reflector;EchoLink Refle;80.211.131.80;42000;002;http://ysf-dagobah.hblink.it/
15639;Ostsee;Backup DL5CG;91.66.81.13;42001;001;http://dl5cg.ddns.net/ysf
23020;Ottawa-Ont;Canada Link;184.175.49.98;42000;003;http://ysf-ottawa.ddns.net
08344;PA-ysf-hp3icc;Ysf Chiriqui;190.141.113.82;42000;007;http://ysf-hp3icc.ddns.net/
99999;Parrot;Parrot;137.226.79.115;42020;000;http://
79383;PH-BISDAK;Bisayang Dako;45.79.92.86;42002;001;http://xlx.dmrphilippines.network/ysfbisdak
59008;PH-DX1AFP;PHILCCOM;167.99.190.123;42100;002;http://167.99.190.123/dx1afp/index.php
78258;PH-DX1PAR;DX1PAR;178.128.216.38;42100;012;http://
19751;PH-DX1WPI;DX1WPI;167.99.190.123;42000;001;http://167.99.190.123/index.php
18808;PH-DX2ACV;MAHARLIKA;108.61.216.100;42030;005;http://ph-dx2acv.ddns.net
71972;PH-DX7NRD;NORAD7;140.82.14.24;42002;001;http://
10707;PH-DX9RAG-FDCCU;PH Davao-Cotab;149.28.76.10;42000;001;http://dx9rag-n0mis.ddns.net
09543;PH-MAHARLIKA;MAHARLIKA;149.28.94.53;42100;001;http://149.28.94.53/index.php
43437;PH-WMG-ZAM;WMG;67.205.154.243;42000;004;http://
08318;PH-YSF-DX3NE;YSF-DX3NE;8.3.29.153;42000;002;http://dx3ne.ddns.net
35328;PIJALNIA-PIWA;OPIS PIJANY;64.53.214.179;42005;000;http://64.53.214.179
25393;PL-4280;YSF/DMR/DCS132;155.133.14.66;42031;001;https://brandmeister.network/?page=lh&DestinationID=260080
61266;PL-BRIDGE;Poland BRIDGE;91.197.227.13;42026;000;http://ysfbridge.pzk.pl/
68368;PL-HBLink;HBLink Polska;80.211.208.227;42080;001;https://ysf.hblink.pl
22538;PL-Kutno;Kutno;77.55.209.188;42078;001;https://ysf.hblink.kutno.pl/
74359;PL-Local;Local;91.201.88.18;42234;000;http://
29114;PL-POLAND;YSF PL POLAND;80.211.251.171;42025;016;http://
15495;PL-POLSKA;POLSKA WIRESX;155.133.14.66;42026;008;http://
55546;PL-Silesia;Poland Silesia;91.197.227.13;42003;000;http://ysfsilesia.pzk.pl/
82068;PL-SLASK;Regionalna;91.201.88.18;42237;001;http://
53245;PL-SP1;YSF SP1;155.133.14.66;42041;000;http://ysf016.wiresx.pl:8081/sp1/
12508;PL-SP2;YSF SP2;155.133.14.66;42042;000;http://ysf016.wiresx.pl:8081/sp2/
02328;PL-SP3;YSF SP3;155.133.14.66;42043;000;http://ysf016.wiresx.pl:8081/sp3/
48598;PL-SP4;YSF SP4;155.133.14.66;42044;000;http://ysf016.wiresx.pl:8081/sp4/
45300;PL-SP5;YSF SP5;155.133.14.66;42045;000;http://ysf016.wiresx.pl:8081/sp5/
92967;PL-SP6;YSF SP6;155.133.14.66;42046;000;http://ysf016.wiresx.pl:8081/sp6/
92078;PL-SP7;YSF SP7;155.133.14.66;42047;000;http://ysf016.wiresx.pl:8081/sp7/
71372;PL-SP8;YSF SP8;155.133.14.66;42048;000;http://ysf016.wiresx.pl:8081/sp8/
78984;PL-SP9;YSF SP9;155.133.14.66;42049;000;http://ysf016.wiresx.pl:8081/sp9/
38691;PL-SR4H;SR4H-ROOM;91.244.185.128;42000;001;http://
40464;PL-SR7MK;Swiety Krzyz W;155.133.14.66;42024;001;http://ysf016.wiresx.pl:8081/sr7mk/
40594;PL-SR8DEF;Debica;155.133.14.66;42033;001;http://
78099;PL-SR8FWD;Wlodawa WiresX;155.133.14.66;42030;001;http://sr8fwd.wiresx.pl
79009;PL-SR8K;Dubiecko;155.133.14.66;42032;002;http://ysf016.wiresx.pl:8081/sr8k/
91407;PL-SR8LUF;Lublin;155.133.14.66;42028;001;http://ysf016.wiresx.pl:8081/sr8luf/
87318;PL-SR8UVC;Chotylow;155.133.14.66;42034;001;http://
54644;PL-SR8UWD;Wlodawa YSF;155.133.14.66;42027;001;http://sr8uwd.wiresx.pl
64506;PL-SR8WD;Wlodawa;155.133.14.66;42029;001;http://ysf016.wiresx.pl:8081/sr8dmr/
83600;PL-SR9DBN;Myslowice;91.201.88.18;42235;001;http://
39816;PL-SR9DX;Bytom;85.11.120.150;42223;001;http://www.dx.katowice.pl
52742;PL-WARMIA-MAZURY;Elblag;109.241.51.213;42055;003;http://sp2wlf.tplinkdns.com/
09815;PL-XLX132;D-Star Gateway;91.203.55.87;42001;002;http://xlx132.dstar.radom.pl/ysf/
80986;PL-YSF260;BM TG260;155.133.14.66;42035;003;http://ysf016.wiresx.pl:8081/260/
37358;PLUG;The Philly LUG;173.12.0.169;42000;003;http://ham.daotechnologies.com/ysf-dashboard
92044;PR-KP4CA;Boriken DMR Ne;64.154.38.101;42000;003;http://boriken-ysf.ddns.net/
02986;PT-YSF009;C4FM-Portugal;109.71.44.237;42000;002;http://c4fm.from-ct.com/
45742;PT-YSF012;BM2682-Link;194.38.140.204;42100;002;http://ysf012.from-ct.com
52639;PT-YSF268;BM2682-Link;194.38.140.204;42125;001;http://ysf268.from-ct.com
15461;PT-YSF903;BM2682-Link;194.38.140.204;42150;001;http://ysf903.from-ct.com
09658;PT-YSF915;BM2682-Link;164.68.117.231;42000;001;http://ysf915.from-ct.com
30270;PUERTO-RICO;ENLACE BORICUA;162.243.169.90;42000;004;http://kp4msr.praredn.org
45591;QUAHOG-NETWORK;BM-TG-31445;45.77.213.187;42000;002;http://ysf.ridigitallink.net
95623;R.C.-AMIRED---C4;WiresX CATALUN;89.36.215.181;42000;016;http://89.36.215.181
64150;Radio-Oasis;ham radio;50.82.207.97;42000;000;http://50.82.207.97/dashboard
66265;Randin;RCRG (Ki4eki);75.145.198.42;42000;001;http://
23531;RAYNET-UK;RAYNET-UK_YSF_;51.91.78.118;42001;007;http://23531.raynet-uk.net/
31444;RI-DIGITAL-LINK;BM-TG-31444;155.138.201.254;42000;002;http://c4fm.ridigitallink.net/
43537;RO-YO-EmCom;EmCom Romania;89.33.44.100;42112;003;http://yo2loj.ro/emcom
03435;RO-YSF-BM-226;YSF BM TG226;89.33.44.100;42002;003;http://ysf2bm.hamnet.ro
95093;RO-YSF-DMR-YO-W;YSF DMR+ Link;89.33.44.100;42007;005;http://ysf2dmr.hamnet.ro
75904;RRARE-OKTX;Red RiverOK/TX;18.218.160.231;42000;002;http://18.218.160.231/index.php
40387;RU-DMR;TG2503;188.42.30.175;42000;004;https://ysf.dstar.su/dash/
39544;RU-KAVKAZ;North Caucasus;37.18.35.2;42000;003;http://kavkaz.qrz.ru/YSF/
09020;RU-KRSNDR;Krasnodar;176.192.125.46;42002;001;http://c4fm.tk/YSF3/index.php
67143;RU-MAYKOP;Maykop;176.192.125.46;42005;001;http://176.192.125.46/YSF5/
27797;RU-MOSCOW;MOSKWA;128.0.132.69;42000;003;http://128.0.132.69
31022;RU-POCTOB;Rostov-Don;83.69.77.96;42000;001;http://c4fm.xyz/our-c4fm-wires-x-room.php
11193;RU-RADIOCULT;YSF;91.247.248.67;42000;001;http://ysf.radiocult.su:8083
17383;RU-SCANNER;Russia;176.192.125.46;42000;004;http://176.192.125.46/YSF/
58312;RU-SHAKHTY;Shakhty;176.192.125.46;42004;001;http://c4fm.tk/YSF4/
16530;RU-VLGDNK;Volgodonsk;176.192.125.46;42001;002;http://176.192.125.46/YSF2/
25641;RUDIVO;YSF;194.182.85.217;42000;008;http://194.182.85.217/
75294;RV-rpt-group;Rogue Valley;71.94.243.50;42001;001;http://
23611;SAT-TRAC;TG 31683;192.99.245.120;42001;003;http://192.99.245.120
40208;SC-Scotland;Scottish YSF;13.69.14.204;42000;018;http://c4fm.dvscotland.net
02868;SCAN-i-546;SCAN-i 546;149.28.202.133;42001;006;http://scanintl.spdns.org
82040;SD_HUB;DMR-ALLSTAR;155.138.225.161;42000;003;http://ysfreflector.sddstar.com
93753;SE-SE0O_CROSS;YSF>DMR TG2400;31.211.216.13;42000;002;http://
06000;SE-SM4-SE-01302;Fusion to SM4;94.234.176.231;42000;002;http://94.234.176.231:3180
80858;SE-SWEDEN-HUB;Wires-X, DMR;95.216.151.253;42000;007;http://ysf.forthmeijer.com
69673;SE-TG240240-Link;TG240240 Link;95.216.197.75;42000;003;http://ysf.brandmeister.se
65461;SE-Virginia;Tidewater;71.120.150.136;41500;001;http://71.120.150.136
30217;SEOH-YSFLINK;SEOH YSFLINK;44.70.25.177;42002;002;http://k8khw.dyndns-remote.com
43075;SE_SwedenLink_28;SE_SwedenLink_;94.254.105.236;42000;002;http://ysfsl.c4fm.se
16390;SG-YSF-V2;SINGAPORE-YSF;14.102.146.160;42002;001;https://ysf.lucifernet.com/
48857;SI-Slovenia;YSF>DMR TG293;188.230.203.194;42000;004;http://xlx511.ddns.net:46193/index.php
62716;SI-Slovenia2;YSF Slovenia;109.182.208.84;42000;002;http://router.dyn.ts.si:38401/
98269;SK-B.Bystrica;YFS Slovak;178.143.62.29;42000;002;http://ysfreflektor.koren.network:8080
83776;SKYNET-YSF;SKYNET/C4FM;167.172.17.107;42000;001;http://c4fm37040.ddns.net/
28735;SMS1;SMS backup;167.99.135.20;42000;000;http://
29961;SNARS;SNARS TG31328;162.248.93.209;42000;001;http://ysf.snars.net
27688;SO-Oregon-rc;SO RC;71.94.243.50;42000;002;http://blahdiadem.hopto.org
80956;SuperARC;Phoenix, AZ;69.71.61.230;42000;002;http://
77982;SZ790;TG46073;58.250.171.29;50790;001;http://
08580;tgwells-ysf;tgwells-ysf;18.191.186.57;42000;000;http://tgwells.com
40538;The-Missing-Link;Inland Empire;76.174.207.37;42003;001;http://ysfkc6gwf.ddns.net
45800;TheHideoutCrew;Yeet;69.164.222.140;42002;004;http://69.164.222.140/
31110;Tipton-ARS;Tipton Co, TN;207.65.47.88;42000;000;http://
22539;TN-NETDA;TN-NETDA;155.138.237.140;42040;006;http://
44212;TNARES-EAST;TNARES-EAST;155.138.237.140;42110;001;http://
07683;TNARES-MID;TNARES-MID;155.138.237.140;42120;000;http://
76787;TNARES-STWIDE;TNARES-STWIDE;155.138.237.140;42100;004;http://
76805;TNARES-TAC-E;TNARES-TAC-E;155.138.237.140;42140;000;http://
67313;TNARES-TAC-M;TNARES-TAC-M;155.138.237.140;42150;000;http://
47567;TNARES-TAC-W;TNARES-TAC-W;155.138.237.140;42160;000;http://
48064;TNARES-WEST;TNARES-WEST;155.138.237.140;42130;000;http://
43513;TROJMIASTO;Poland Tricity;195.140.190.58;42000;000;http://ysftricity.ham-dmr.pl/
30743;TW-HAMTALK;C4FM @HAMTALK;118.150.164.96;42000;004;http://www.hamtalk.net/ysfr
26112;TW-YSF338;YSF@TYARC;114.32.215.38;42000;002;http://ysftw338.ddns.net
39369;UA-Azimuth;Azimuth-club;193.27.208.38;42000;001;http://193.27.208.38
55467;UA-Dnipro;DMR TG25504;5.255.33.253;42004;001;http://
57835;UA-Emergency;DMR TG2559;5.255.33.253;42003;001;http://
46588;UA-Exolink;DMR/C4FM;5.255.33.253;42000;001;http://
37683;UA-Kyiv-city;DMR TG25501;5.255.33.253;42001;001;http://
82255;UA-LVOV-YSF;DMR TG25514;134.249.141.148;42002;001;http://ysf82255.uw0wu.ml
50847;UA-Mykolayiv;DMR TG25515;5.255.33.253;42005;001;http://
85106;UA-Odesa;DMR TG25516;5.255.33.253;42002;001;http://
88338;UA-UA-Ref;YSF UA reflect;95.216.163.65;42100;001;http://ysf.2ip.ee/dashboard2
66216;UA-Zakarpatia;DMR TG25507;142.91.158.199;42002;001;http://xrf255.reflector.up4dar.de/ysf/index.php
13201;UK-DVMEGA;DVMEGA CHAT;212.237.34.32;42000;002;http://c4fm.dvmega.co.uk
83087;UK_YSF_BM_UK;UK_Ref_DN_ONLY;87.117.229.171;42000;012;http://
20087;UNIVERSAL-TWR;SE MI DIGITAL;107.141.52.226;42001;000;http://
74940;Unix;Unix system ad;185.244.130.88;42002;000;http://ysf.sysprotect.eu
74940;Unix;Unix system ad;185.244.130.88;42002;000;http://ysf.sysprotect.eu
65416;URSALAMANCA;URE SALAMANCA;31.14.139.112;42000;000;http://31.14.139.112
51380;Uruguay-YSF;UY YSF;201.217.131.107;42000;006;http://cx4ae.no-ip.org
29727;Uruguay-YSF-Char;Uruguay C4FM;201.217.131.106;42000;001;http://ysfuruguay.ddns.net
59210;US-1st-Resp;TGIF TG 450;157.245.247.7;42000;003;http://
51123;US-31150;Hawaii;149.28.82.52;42000;005;http://149.28.82.52/YSF
44693;US-42001hamshack;paducah;142.93.53.85;42000;000;http://
09344;US-AC1KV;AC1KV Rptr;140.82.14.24;42000;001;http://
75056;US-AF4Y;AF4Y Refelctor;107.191.51.252;42000;006;http://
61482;US-AfterNetK4DJL;AfterNet K4DJL;96.47.95.121;42003;001;http://afternet.alabamalink.info
21988;US-AggielandLink;Aggieland Link;71.252.210.227;42000;000;https://www.aggielandlink.com/Dashboard
57882;US-AK4LT;The Fire Ants;51.79.69.216;42000;002;http://
75021;US-AMLEG-NCKYP42;KB4KY Repeater;67.215.222.30;42000;000;https://tinyurl.com/y5tlg93t
11689;US-Amsat;Satellite Ops;149.28.241.59;42000;017;http://149.28.241.59
55223;US-AZ-SEOC;Oro Valley ARC;69.244.58.8;42001;001;http://
36252;US-AZ-TUCSON;Oro Valley ARC;69.244.58.8;42000;003;http://
79496;US-Beards-Den;Open Room;68.4.184.234;42200;003;http://k6tvb.isa-geek.com:8888/index.php
00081;US-Berks-County;Pennsylvania;24.152.248.205;42042;000;http://
85490;US-BM-TG-31083;CO Severe WX;54.191.50.212;42050;001;http://54.191.50.212/ysf2
99256;US-BM-TG-31088;Colorado HD;54.191.50.212;42005;005;http://54.191.50.212
97501;US-BRRO;688;54.89.57.238;42000;001;http://xlx688.ab8m.com/
44742;US-CARA;CARA Group;45.79.93.167;43000;003;http://xlx.cara.nu/ysf
25662;US-Carlisle,PA;N3JUO;174.49.161.236;42002;000;http://ysfcvpa.hopto.org
94390;US-Central-AL;WiresX 21713;99.46.36.113;8001;006;http://
49235;US-CKRG;Central Kansas;100.25.76.93;42000;004;http://
44977;US-CNJHAM;Link to XLX020;52.23.107.220;42000;004;http://ysfreflector.kb2ear.net
99032;US-CO-KF0ABA;NOCO Ragchew;73.34.87.216;42000;000;http://ysfnode.jmrust.com/
53927;US-CO-WE0FUN;Fun Machine Co;199.59.31.9;42000;003;http://c4fm.we0fun.com
23160;US-ColoradoMega;CO Transcode;74.91.118.134;42000;011;http://ysf.parkerradio.org/ysf
71941;US-Connecticut;N1AJW-Test;192.223.31.208;42000;000;https://192.223.31.208
62608;US-Connecticut-1;CT Chat;192.223.31.208;42010;001;http://192.223.31.208
91800;US-CQ-California;CAL-YSFtoWires;104.218.36.162;42001;004;http://ysfxlx.dyndns.org
62208;US-CQ-NODAK-A-ZX;CQ NorthDakota;18.217.188.43;42000;006;http://ysf.cqnodak.com
73884;US-craftwerx;team-craftwerx;67.160.251.224;42511;002;http://
46301;US-CW-Ops;CW Academy/CW;107.182.34.107;42002;002;http://cwopsysf.dyndns.org
50279;US-DUDE-Link;DUDE XLX106;69.163.163.88;42000;008;http://xlx106.dudetronics.com
38542;US-DX-HUB;US DX-HUB;45.32.193.214;42000;000;http://45.32.193.214/YSF
40422;US-DX3CA-OMG;OLD MAN GROUP;149.248.6.211;42000;007;http://dx3caomg.tqhhc.com
23957;US-DX3L-YSF;RIZAL-LATITUDE;140.186.202.60;42000;004;http://latitudeysf.ddns.net
11102;US-DXLINKSYSTEM;DX-LINK SYSTEM;155.138.236.26;42000;003;http://xlx749ysf.drgnz.com
43953;US-East-Pipeline;Link;75.68.143.156;42007;009;http://
88084;US-EcosDelCoqui;Conociendo Ami;66.223.212.215;42002;003;http://ecosdelcoqui.kl4ne.net
88023;US-EOH-GWY-HUB;X Hub/Bridge;64.154.38.103;42000;001;http://29999.link/YSF
12567;US-ERDN;ERDN YSF Ref;173.208.200.179;42000;001;https://ysf.kc1awv.net/index.php
12567;US-ERDN;ERDN YSF Ref;173.208.200.179;42000;000;https://xlx337.kc1awv.net
13458;US-FACSchool-ARC;New Iberia, LA;98.191.70.50;42000;002;http://longwire.net:8088
11665;US-Farmers;Farm Talk;67.140.163.107;42010;001;http://
37921;US-FLORIDA;FL REFLECTOR;76.109.114.132;42000;002;http://
04154;US-Georgia;Georgia USA;45.32.223.140;42000;000;http://ysf-ga.ka7utd.com/
99602;US-GulfBeach-FL;Gulfcoastradio;50.116.24.240;42000;006;http://50.116.24.240
36271;US-GulfCoast-FL;Gulfcoastradio;18.205.34.190;42000;000;http://ysf36271.ddns.net
01896;US-HarleyHangout;DMR_AllStar;38.133.241.80;42000;002;http://
93877;US-Houston-Texas;Houston Texas;23.30.91.29;42000;002;http://ysf.cognetic.com
01037;US-HRCC-LINK;HRCC LINK;209.182.218.92;42001;007;http://ysf.hrcc.link
02931;US-Hudson-NY;Upstate NY;24.105.206.243;42002;006;http://keetz.mynetgear.com
04400;US-HXO;HXO 31325;162.248.93.209;42005;001;http://ysf.hxo.radio
83132;US-Illinois-Link;Illinois Link;74.208.235.115;42000;016;http://74.208.235.115/YSFReflector-Dashboard/
02500;US-IL_NGRMARC;NG Radio Club;73.74.148.160;42000;001;http://
80060;US-JAXBCH-Link;JAX BCH Link;66.177.51.38;42000;000;http://
68798;US-JerryNet;YSF Reflector;18.216.66.72;42000;002;https://ysf.ad6dm.net
01295;US-JOTA-1;9071;104.200.25.53;42001;001;http://
27662;US-JOTA-2;9072;104.200.25.53;42002;000;http://
02177;US-K3IHI-RPT;YSF TG;131.106.30.132;42000;003;http://
05944;US-K4LPD-YSF;YSFReflector;134.209.44.53;42000;001;http://k4lpd.luisra369.com
32343;US-K4NWS;ALERT-K4NWS;34.219.110.119;42000;001;http://ysf.alert-alabama.org/YSFReflector-Dashboard/
37581;US-K7SFQ-YSF;K7SFQ YSF Ref;50.39.137.114;42000;000;http://
12345;US-K9EQ-----DYEF;Development;167.99.150.253;42004;000;http://
81734;US-K9POL;US K9POL;104.238.162.162;42000;000;http://
12479;US-Kansas-City;WIRES-X MOKAN;99.169.52.241;42000;006;http://www.salaman.org/ysf
08398;US-Kansas3120;ks-dmr.net;129.130.229.11;42030;004;http://129.130.229.11:15426/3120/
77661;US-KB1NYT-YSF;Swansea, MA;24.218.238.119;42000;002;http://kb1nyt.hopto.org:8091/ysf
57046;US-KB4OVL;Indian Rvr FL;69.137.164.8;42000;001;http://
04438;US-KC2RC;KC2RC W-X room;3.82.236.213;42000;004;http://3.82.236.213/
69140;US-KE4SCS;KE4SCS Rptr;155.138.222.156;42000;000;http://155.138.222.156
92516;US-Kentucky-LARC;Local Rag Chew;161.35.141.182;42000;001;http://
43114;US-KENTUCKY-OWWZ;W4IOD Test Ref;76.244.26.57;42000;002;http://
40806;US-KENTUCKY-WXGC;W4IOD Repeater;167.99.150.253;42002;008;http://mnwis-ysf.ddns.net/W4IOD.php
02824;US-KI5HXE;KI5HXE;157.245.138.123;42000;000;http://
03772;US-KitsapLink;Kitsap Talk;98.125.77.141;42810;000;http://
40438;US-KK4OVW-TN-YTR;White House T;104.56.140.47;42000;001;http://
25956;US-KM4EDS;Blount County;96.47.95.121;42002;003;http://danny.alabamalink.info
93262;US-KO4AXW-7;Richmond, Virg;142.93.202.44;42000;000;http://ko4axw-ysf.ddns.net/index.php
29162;US-Ktown;Los Angeles Kt;104.174.35.78;42002;000;https://192.168.0.40
43310;US-KU0S;Test Bridged Y;76.196.111.153;42000;002;http://ysf.ku0s.com/dashboard/
21511;US-KV4S;KV4S;96.47.95.121;42004;002;http://kv4s.alabamalink.info
44967;US-Ky-Hood-Rats;Hood Rats Club;67.140.163.107;42020;001;http://kyhoodrats.ddns.net
97215;US-LEO-ARC;LEO ARC;74.91.116.36;42000;006;http://74.91.116.36
65982;US-LHSREF;LHS Podcast;67.224.119.40;42000;001;http://reflector.k5tux.us/Dashboard
01240;US-LosAngeles;SocalPinoy;47.180.104.101;42003;002;http://socalpinoy.ddns.net
44428;US-Magnolia-Link;Magnolia Wires;76.107.175.206;42042;001;http://
87168;US-Marana-AZ;Oro Valley ARC;69.244.58.8;42002;001;http://
68928;US-MID-TN-RM;Middle Tenn;104.56.140.47;42001;000;http://
42592;US-MissingLynk;MissingLynk;104.248.12.84;42000;001;http://104.248.12.84
21493;US-MNWIS----RDNT;21493;167.99.150.253;42000;018;http://mnwis-ysf.ddns.net
77445;US-Muletown-TN;Maury County;104.237.132.247;42000;002;http://104.237.132.247
43210;US-MVARC----KBNA;MVARC Idaho;167.99.150.253;42003;004;http://
92059;US-N1TVI;Dew-Cave;159.65.189.183;42001;000;http://n1tvi.net:8081
93958;US-N4KWT-ALPHA;Louisville, KY;23.126.8.172;42002;000;http://23.126.8.172/index.php
08035;US-N4KWT-BRAVO;Louisville, KY;23.126.8.173;42000;000;http://23.126.8.173/index.php
59680;US-N8RQJ-RPT;WiresX 49602;157.245.93.169;42000;001;http://157.245.93.169
90882;US-NACS;C4FM;68.232.234.210;42000;001;http://
54635;US-Nashville-HUB;Nashville-HUB;34.235.143.37;42000;002;http://
06177;US-NC-440-Link;NC 440 Link;172.104.214.72;42000;001;http://ysf.msmts.com
32398;US-NE-Oregon;Oregon Room;73.25.190.37;42000;002;http://
56521;US-Nebraska_Hub;D-Star DMR YSF;71.8.194.163;42000;003;http://ysf.ham-radio-op.net
77204;US-Nevada;Nevada TG3132;162.248.93.209;42001;002;http://ysf.snars.net/nevada
93319;US-NgakNgak;Ngakngakan YSF;45.79.92.86;42000;004;http://xlx.dmrphilippines.network/ysf
58333;US-NOMBRA;nombra.tech;172.90.53.5;42001;000;http://
00561;US-North-America;DVSwitch.org;44.103.34.4;42000;000;http://dvswitch.org/YSF_NA/
27402;US-Northstar;Northstar Link;149.28.113.51;42000;001;http://149.28.113.51
83242;US-NW-Ohio;YSF-NW-Ohio;18.188.19.87;42000;001;http://ec2-18-188-19-87.us-east-2.compute.amazonaws.com/
13070;US-NWMO;NW Missouri;199.188.121.118;42000;001;http://nwmoroom.duckdns.org
53594;US-Ohio;Ohio;192.241.240.7;42000;005;http://ysf.n8qq.com
19053;US-OklahomaLink;RCWA.org;3.208.70.29;42000;013;http://3.208.70.29
72321;US-OMG-LA-LV;OLD MAN GROUP;149.248.21.148;42002;002;http://omglalv.tqhhc.com
14927;US-OMISS---YSF;YSF Multimode;104.49.29.243;42001;002;http://
74158;US-Oro-Valley-AZ;Oro Valley ARC;75.146.134.22;42000;023;http://
59281;US-OVARC-Test;Oro Valley ARC;69.244.58.8;42003;000;http://
06864;US-Penn-Link_1;XLX045A YSF;54.85.206.3;42000;004;http://xlx045.pennlinkgroup.com/ysfA
20223;US-Penn-Link_2;XLX045D YSF;54.85.206.3;42006;000;http://xlx045.Pennlinkgroup.com/ysfD/
69186;US-Penn-Link_3;XLX545B YSF;3.215.215.169;42001;001;http://xlx545.pennlinkgroup.com/ysfA
35119;US-Penn-Link_4;XLX045E YSF;54.85.206.3;42001;002;http://xlx045.pennlinkgroup.com/ysfE
92207;US-Penn-Link_5;XLX545E YSF;3.215.215.169;42000;002;http://xlx545.pennlinkgroup.com/ysfE
17947;US-Penn-Link_7;XLX045C YSF;54.85.206.3;42002;001;http://xlx045.Pennlinkgroup.com/ysfC/
19669;US-Penn-Link_8;XLX545A;3.215.215.169;42002;001;http://xlx545.pennlinkgroup.com/ysfA
69614;US-Phoenix-AZ;Phoenix AZ;68.14.214.57;42500;003;http://68.14.214.57:8080
30887;US-Phoenix-AZ-2;Phoenix AZ 2;72.194.183.82;42501;001;http://72.194.183.82:8081
31672;US-Pi-Star-Multi;Pi-Star Multi;142.44.240.244;42000;002;https://multi-reflector.pistar.uk
03169;US-PINOY-5155;PEANUT-PINOY;107.172.83.104;45000;002;http://ysf-p555.ddns.net
00094;US-Pottstown-Pa;Pennsylvania;69.249.242.117;42000;000;http://
63222;US-QCWA;Chapter 147;94.177.189.17;42000;003;http://94.177.189.17/ysf
63222;US-QCWA;Chapter 147;94.177.189.17;42000;003;http://ysfqcwa.xreflector.es
61324;US-Radio-Kollel;Torah Kollel;54.83.61.74;42000;000;http://
35010;US-Reddit;DMR TG 98003;74.214.25.135;42000;007;http://xlx216.km8v.com/
40874;US-REF020A;REF020A Link;52.23.107.220;42100;002;http://ysf020.kb2ear.net
33703;US-RKT-CTY-HSV;RKT.CTY.HSV.AL;136.53.51.207;42000;000;http://136.53.51.207
84105;US-RMM-YSF;RMM YSF;96.244.208.211;55555;000;http://ysf.robmon.com
92805;US-RocketCity-AL;Huntsville, AL;155.138.207.101;42000;002;http://155.138.207.101
38469;US-RuralMN-707;Rural MN;24.230.163.50;42000;002;https://707ysf.kd0ioe.com
84398;US-SADRC;SanAntonioDRC;173.226.176.18;42000;017;http://
52470;US-SARA-QRX-FCMG;Stillwater MN;69.147.211.168;42000;001;http://
39642;US-Secret-TG;Secret;75.118.136.88;42002;000;http://
92722;US-Skyhub-Link;Denver SkyHub;65.114.195.171;42000;010;http://kg0sky.duckdns.org/YSFReflector-Dashboard
40861;US-SOMN-----FAPG;SO MN;64.254.189.194;42000;003;http://
12461;US-South-MS-Net;South MS Net;50.246.136.107;42000;000;http://50.246.136.107:42001
29364;US-South-Texas;South Texas;76.183.98.122;42011;002;http://ae5jo.bounceme.net
96447;US-SOUTHEASTLINK;Provided by: L;45.32.214.224;42000;009;http://selink.lmarc.net/YSFDash/index.php
73102;US-Southwest-USA;Southwest USA;24.121.90.225;42000;011;http://24.121.90.225:8888/index.php
18503;US-SpaceCityChat;SpaceCityChat;108.209.70.215;42000;001;http://kk4lpo.ddnsgeek.com
95375;US-Steel-City;Pittsburgh, PA;71.60.185.34;42000;000;http://steelcityusa.ddns.net/
53632;US-TGIF;TGIF 31665;74.91.125.81;42000;003;http://tgif.network/ysf
81342;US-THINKNET;TEXAS US;104.239.146.135;42000;001;http://thinknet.mostlychris.com
23964;US-TREKFAN;TrekFan;138.68.11.56;42000;000;http://skylab.trekfan.org
08106;US-Triangle-Net;Triangle Net;74.91.121.182;42000;001;http://
15783;US-Truck-Travel;Truck Travel;74.91.121.182;42002;004;http://travel.atruckerslife.com
00546;US-Tucson-AZ;Oro Valley ARC;69.244.58.8;42004;004;http://
55817;US-Uni-Link;UniversityLink;128.83.129.92;42000;002;http://repeaters.as.utexas.edu/ysf/
55326;US-US-JOTA;DMR 907;104.200.25.53;42000;001;http://
03732;US-US-WNY-XRX;XRX Club;98.3.111.214;42000;001;http://
99539;US-VaDigital;YSF Reflector;3.19.122.217;42000;004;http://ysf.vadigital.network
13120;US-W2MMD-Sknkwks;W2MMD Sknkwks;72.82.133.138;42000;004;http://
39114;US-W6AUSBeeville;YSF Beeville;151.80.166.60;42000;000;http://
02512;US-WA-PNW;PNW Rag chew;144.202.95.90;42000;000;http://ysf.kc9gwk.com
07923;US-WA3PNY-GW;Input 1 to Net;3.215.215.169;42003;006;http://xlx545.pennlinkgroup.com/ysfG
64020;US-WA3PNY-GW2;Input 2 to Net;54.85.206.3;42004;002;http://xlx245.pennlinkgroup.com/ysfG2/
24157;US-Western-NC;WNC and nearby;199.168.200.18;42000;002;http://
37733;US-WestSide;Waukesha, WI;54.70.201.171;42000;010;http://www.reflectorusa.com
97689;US-Wi-Fi-Talk;Wireless Pros;173.162.46.202;42000;001;http://ysf.n4taj.com:8989
40396;US-WKENTUCKYDXEB;K4KMW RF Link;68.57.59.67;42000;001;http://
21335;US-WM-CONNECT;Wires-X 21335;199.85.255.10;42000;009;http://ysfdash.wmtg.me
98899;US-WolfDen;Massachusetts;100.0.63.70;42000;014;http://wolfden.ddnsgeek.com:42080
31357;US-WU3K;US WU3K;96.255.162.150;42000;000;http://
19941;US-WV-LINK;WV DIGI LINK;142.93.246.87;42000;002;http://
73602;US-XLX625;WA8BRO;68.55.76.168;42000;001;http://xlx625.wa8bro.com
55812;US-YSF-FDCCU;US San Diego;104.207.152.88;42000;004;http://ysf-n0mis.ddns.net
98060;US-YSF-Miami;YSF Miami;104.148.41.76;42000;002;http://104.148.41.76
12224;US-YSF-NE;NEW-ENGLAND;18.204.209.243;42000;002;http://
41373;US-YSF295;OMIK RADIO;64.137.187.75;42000;002;http://ysf295.dyndns.org
97912;US_SIN_Southern;Indiana_Link;142.93.181.147;42000;019;http://w9windigital.org/ysf
67356;US_SKYNET;SKYNET;104.130.158.171;42000;003;http://ysfdash.mostlychris.com:9000
82699;VCDRC;VCDRC TG31070;162.248.93.209;42003;001;http://ysf.snars.net/vcdrc/
20818;VE2YXY-TEST;VE2YXY-TEST;138.197.143.53;42000;001;http://
21468;WIRES-X;Room 21468;190.148.222.28;42103;000;http://
38635;Wires-X-YO-W;WiresX Romania;89.33.44.100;42003;001;http://wiresx.hamnet.ro
00008;WORLDLINK;World link;209.126.0.55;42000;017;http://worldlink.pa7lim.nl
27142;W_Tennessee;YSF Reflector;3.15.171.29;42000;001;http://
18145;XLX000;XLX reflector;45.56.118.86;42000;009;http://xlx000.xlxreflector.org
71981;XLX004;XLX reflector;44.103.34.3;42001;011;http://xlx004.kb8zgl.net
65978;XLX010;XLX reflector;85.197.129.86;42000;105;http://xlx.brandmeister.se
66396;XLX020;XLX reflector;66.175.215.217;42000;019;http://xlx020.k2ie.net
53148;XLX022;XLX reflector;83.137.45.98;42000;081;http://xlx022.tms-it.net
41945;XLX023;XLX reflector;77.85.192.94;42000;015;http://xlx023.ddns.net
86381;XLX026;XLX reflector;209.42.149.140;42000;014;http://xlx026.cnharc.org
29295;XLX029;XLX reflector;45.62.239.138;42000;000;http://029.r2i.net
44644;XLX032;XLX reflector;158.64.26.140;42000;015;http://xlx032.epf.lu
67001;XLX033;XLX reflector;46.226.178.81;42000;009;http://xrf033.dyndns.org
13908;XLX037;XLX reflector;198.100.154.155;42000;002;http://xlx037.ddns.net
82176;XLX038;XLX reflector;164.68.100.69;42000;000;http://xlx038.grupporadiofirenze.net/db/dashboard/
72207;XLX040;XLX reflector;109.71.45.29;42000;016;http://xrf040.dyndns.org
15976;XLX043;XLX reflector;206.189.239.225;42000;005;http://xlx043.pauldingares.com
80207;XLX046;XLX reflector;98.128.173.195;42000;000;https://xlx.c4fm.se
16909;XLX048;XLX reflector;45.62.213.248;42000;000;http://xlx048.ds6.com
13440;XLX051;XLX reflector;93.186.254.219;42001;037;http://xlx051-ea5spain.duckdns.org
90443;XLX056;XLX reflector;155.138.237.66;42000;008;http://scmidlands.network
89670;XLX062;XLX reflector;52.139.47.149;42000;001;http://xlx.baddogmedia.ca
64547;XLX069;XLX reflector;51.77.213.200;42000;003;http://51.77.213.200/db
42356;XLX070;COVENTRY ARS;18.130.199.150;42000;001;http://xlx070.g1iul.org.uk
67018;XLX077;XLX reflector;23.94.25.146;42000;005;http://xe1dvi.crabdance.com/db/index.php
75749;XLX094;XLX reflector;96.126.124.4;42000;000;http://xlx.txi35hams.com
59637;XLX098;XLX reflector;221.170.106.177;42001;154;http://xrf098.mydns.jp
74096;XLX100;XLX reflector;45.62.241.133;42000;000;http://xlx100.xlxreflector.org
39444;XLX101;XLX reflector;45.62.245.46;42000;000;http://xlx101.xlxreflector.org
57188;XLX102;XLX reflector;45.79.220.142;42000;027;http://xlx102.xlxreflector.org
37102;XLX104;XLX reflector;50.116.38.232;42000;007;http://xlx104.xlxreflector.org
58717;XLX105;XLX reflector;51.254.99.78;42000;003;http://ysf.xrf105.fr
92626;XLX109;XLX reflector;218.221.179.75;42000;001;http://109.bayfm78.tokyo/
20012;XLX124;XLX reflector;211.14.169.234;42000;140;http://xrf124.xreflector-jp.org
35367;XLX126;XLX reflector;217.173.179.95;42000;002;http://xlx126.noip.pl:8080
39815;XLX129;XLX reflector;220.145.77.199;42000;190;http://guwgw.cir-ins.com/
88621;XLX131;XLX reflector;80.127.118.226;42000;004;https://xlx131.pe1er.nl
77462;XLX132;XLX reflector;91.203.55.87;42000;038;http://xlx132.dstar.radom.pl/index.php?show=repeaters
48375;XLX140;WORLDWIDE;95.211.211.145;42000;000;http://xlx140.nix.pt
93407;XLX143;XLX reflector;161.35.235.224;42100;001;http://
59323;XLX174;XLX reflector;81.169.128.244;42000;007;http://xlx.digitalfunk-nordost.de
07483;XLX175;XLX Reflector;162.248.92.25;38000;000;http://ysf.ke8khn.com
95272;XLX185;XLX reflector;89.215.13.208;42000;011;http://xlx185.lz2kac.org:8680
86930;XLX200;XLX reflector;62.171.191.147;42000;001;http://xlxzone.net/index.php
62200;XLX201;XLX reflector;157.245.45.67;42000;013;https://xlx201.446em.uk
62862;XLX204;room Z Wires-X;82.171.119.45;42001;023;http://xlx204.ddns.net/
70248;XLX207;XLX reflector;150.129.138.49;42000;004;http://xlx.br2sy.net
20236;XLX208;XLX reflector;51.178.80.187;42000;016;https://xlx208.f5kav.fr/index.php
60106;XLX220;XLX reflector;124.41.83.11;42000;176;http://xlx220.sapotech.com
79890;XLX227;XLX reflector;89.33.44.100;42000;026;http://xlx227.hamnet.ro
34300;XLX229;XLX reflector;194.191.4.54;42000;047;http://dstar.hamnet.xyz
03349;XLX232;XLX reflector;89.185.97.35;42000;132;http://dstar.oevsv.at/db/index.php?show=modules
66065;XLX240;ZOMBIE-ALERT;107.141.52.226;42000;037;http://
31725;XLX250;XLX reflector;44.159.15.2;42000;011;https://xlx.ham.in.th
31855;XLX255;UA XLXd255 REF;142.91.158.199;42000;029;http://xrf255.reflector.up4dar.de/db/index.php
10347;XLX256;XLX reflector;162.238.214.18;42000;008;http://162.238.214.18
24862;XLX257;UA XLXd257 REF;134.249.141.148;42000;003;http://xlxd257.uw0wu.ml
14019;XLX260;XLX reflector;80.211.208.227;42000;008;https://xlx260.hblink.pl
83294;XLX267;XLX reflector;185.244.130.88;42000;000;http://ysf.sysprotect.eu
42725;XLX268;XLX reflector;194.38.140.204;42000;058;https://xlx268.from-ct.com
64702;XLX270;XLX reflector;158.64.26.132;42000;046;https://xlx270.epf.lu/
44047;XLX290;XLX reflector;44.182.7.20;42000;005;http://xlx.digitalsicilia.it
81632;XLX295;XLX reflector;64.137.161.161;42000;021;http://xlx295.dyndns.org
95424;XLX298;XLX reflector;219.107.78.72;42001;015;http://xrf298.mydns.jp
23565;XLX301;Canberra Link;124.187.44.129;42000;002;http://xlx301.duckdns.org
67862;XLX302;XLX reflector;144.217.241.23;42000;027;http://xlx302.hopto.org/db/
30362;XLX305;XLX reflector;178.250.54.203;42000;001;http://xlx.m5adi.com/
35947;XLX307;XLX reflector;72.21.76.154;42000;035;https://xlx307.openquad.net
92688;XLX311;XLX reflector;91.204.44.37;42000;000;https://xlx311.db0he.de
08623;XLX312;TriStateDMR;192.241.160.183;42000;008;http://xlx.dmr-marc.net
29178;XLX314;XLX reflector;186.19.139.15;42000;000;http://xlx314.ddns.net
38481;XLX328;XLX reflector;212.237.33.114;42000;022;http://212.237.33.114/index.php
83603;XLX330;"Megalink 330";44.70.49.128;42000;003;http://xlx.megalink.network
66149;XLX334;XLX reflector;96.47.95.121;42001;058;http://xlx.alabamalink.info
26906;XLX339;Hannover-XLink;nc.hannover-x.link;0;005;https://xlx.hannover-x.link
51599;XLX345;XLX reflector;73.253.128.47;42000;003;http://xlx345.dyndns.org:82
96507;XLX358;XLX reflector;93.152.167.4;42000;000;http://xlx358.ddns.net/
22852;XLX359;XLX reflector;94.156.172.213;42000;048;http://xlx359.ddns.net/
04965;XLX362;XLX reflector;198.166.220.68;42000;002;http://xlx362.gcdtech.ca/index.php
74839;XLX369;XLX reflector;72.89.122.8;42000;005;http://xlx369.w4eae.net
40341;XLX375;XLX reflector;12.221.169.50;42000;001;http://
88395;XLX377;XLX reflector;186.159.96.100;42000;003;http://xlx.toytron.com
45641;XLX381;TRIANGLE NC;74.91.114.100;42000;006;http://ysf.trianglenc.net
84823;XLX383;Kingsland GA;74.91.121.41;42000;003;http://74.91.121.41
00389;XLX389;XLX reflector;49.176.201.188;42000;051;http://xlxdmr.duckdns.org/db/
48042;XLX395;XLX reflector;95.255.196.50;42444;011;http://xlx395.grupporadiofirenze.net
66392;XLX398;XLX reflector;139.64.246.155;42000;000;http://xlx398.dyndns.org
64192;XLX410;XLX-REFLECTOR;166.78.145.146;42000;014;https://xlx.n5amd.com
29299;XLX420;XLX reflector;149.28.54.17;42000;000;https://xlx.cdarin.net
58291;XLX421;XLX reflector;118.189.181.236;42000;041;http://9v1lh.spdns.org:8086/
45165;XLX422;XLX reflector;93.240.48.68;42200;003;http://dl-nordwest.spdns.de:82/
26451;XLX425;XLX reflector;77.203.220.188;42000;004;http://srv-xlx.ddns.net
92585;XLX431;XLX reflector;61.195.98.225;42000;240;http://xrf431.xreflector-jp.org/
62243;XLX434;XLX reflector;51.254.128.134;42001;004;http://51.254.128.134/db
66583;XLX444;XLX reflector;46.38.241.228;42000;057;http://ysf444.pa3dfn.nl
68810;XLX449;XLX reflector;75.68.26.134;42000;000;http://hub.ollieted.com/db/
90015;XLX450;XLX reflector;45.62.241.140;42000;001;http://xlx450.xlxreflector.org
71743;XLX451;XLX reflector;45.62.239.185;42000;000;http://451.ds6.com
26845;XLX452;XLX reflector;45.62.210.37;42000;000;http://xlx452.ds6.com
26845;XLX452;XLX reflector;206.208.56.14;42000;000;http://xlx451.xreflector.org
97273;XLX453;HKHAM node -1-;61.239.171.240;42000;032;http://xlx453.hkham.org:8087/db
73993;XLX454;HKHAM node -2-;218.103.102.5;42000;059;http://xlx454.hkham.net/ysf
43173;XLX455;XLX reflector;208.71.169.83;42000;002;http://
93342;XLX456;XLX reflector;54.37.205.183;42000;046;https://xlx456.de
92227;XLX469;XLX reflector;104.207.138.156;42000;001;http://xlx469.kb0isw.com/index.php
98796;XLX479;XLX reflector;198.58.106.10;42000;007;http://zenas.n9ink.net
78936;XLX480;XLX reflector;95.179.145.178;42000;000;http://95.179.145.178
49716;XLX500;XLX reflector;58.96.21.253;42000;006;http://xlx500.org
51594;XLX502;XLX reflector;190.148.222.28;42102;017;http://190.148.222.28:8503/dashboard/index.php
07490;XLX503;XLX reflector;179.51.0.153;42000;008;http://179.51.0.153:8503/dashboard
71247;XLX504;XLX reflector;200.52.151.155;42000;002;http://200.52.151.155:8504/index.php
85857;XLX505;XLX reflector;45.248.50.37;42000;014;http://vk7hse.duckdns.org/xlx
88194;XLX507;XLX reflector;201.224.1.251;42000;005;http://xlx507.c4fmpanama.org/
64446;XLX508;XLX508 OWL;185.188.4.15;42000;052;http://xlx508.hb9gfx.ch
12230;XLX514;XLX reflector;203.137.118.143;42000;234;http://xrf514.xreflector-jp.org/
07475;XLX520;XLX reflector;44.159.15.1;42000;071;http://ysf.dtdxa.com
18807;XLX522;XLX reflector;14.102.146.160;42000;035;https://xlx.lucifernet.com/dashboard/index.php
59245;XLX530;XLX reflector;124.197.62.162;42025;031;http://xlx530.hopto.org
40946;XLX531;XLX reflector;149.28.170.145;42000;035;http://xlx531.drgnz.com
19577;XLX538;XLX reflector;183.76.38.69;42000;139;http://xrf538.mydns.jp
52074;XLX546;XLX reflector;149.28.202.133;42000;001;http://xlxscanintl.spdns.org
52074;XLX546;XLX reflector;149.28.202.133;42000;001;http://scani546.mooo.com
93887;XLX547;XLX reflector;45.77.186.5;42000;005;http://xlx.kapihan.net
83362;XLX548;XLX reflector;144.202.99.113;42000;000;http://xlx2.kapihan.net
28340;XLX560;XLX reflector;150.66.42.72;42000;229;http://xrf560.xreflector-jp.org/
08806;XLX595;XLX reflector;124.26.61.245;42000;014;http://hamradio.dip.jp
00412;XLX600;XLX reflector;13.69.14.204;42001;045;http://xlx600.dvscotland.net
91682;XLX621;HRCCLINK XLX;209.182.218.92;42000;006;http://xlxd.hrcc.link
36240;XLX634;XLX reflector;150.66.9.57;42000;016;http://xrf634.xreflector-jp.org/
13946;XLX651;XLX reflector;104.143.94.48;42200;004;http://104.143.94.48/XLX/dashboard/index.php
52732;XLX654;XLX reflector;94.33.52.82;42002;002;http://www.iw2hgl.it:81
84093;XLX669;XLX reflector;144.202.115.103;42000;003;http://xlx669-maharlika.ddns.net
76138;XLX679;XLX reflector;45.79.180.62;42000;005;http://xlx.borris.me
03560;XLX698;XLX reflector;203.137.123.89;42000;231;http://xrf698.xreflector-jp.org/
86410;XLX710;XLX reflector;209.126.0.55;42001;000;http://xlx710.pa7lim.nl
51642;XLX711;XLX reflector;192.243.108.150;42000;000;http://xlx711-ni.ddns.net
51265;XLX714;XLX reflector;213.195.111.148;44000;012;http://xlx714.ea3hkb.cat
78911;XLX716;XLX reflector;190.232.249.27;42000;005;http://xlx716.ddns.net/
88921;XLX725;XLX reflector;172.245.9.180;42000;000;http://xrf725.nq4t.com
84891;XLX741;XLX reflector;203.137.78.41;42000;220;http://xrf741.xreflector-jp.org
59607;XLX748;XLX reflector;64.137.174.49;42000;000;http://xlx748.dyndns.org
89323;XLX749;XLX reflector;45.76.252.9;42000;004;http://xlx749.drgnz.com/
32748;XLX750;XLX reflector;203.86.206.49;42000;103;http://www.xlx750.nz
41007;XLX751;XLX-REFLECTOR;149.28.71.1;42000;027;https://xlx751.drgnz.com/
62994;XLX758;XLX reflector;93.240.113.55;42000;001;http://
73934;XLX760;XLX reflector;172.245.71.164;42000;002;http://
67173;XLX776;XLX reflector;118.27.26.18;42000;172;http://776.bayfm78.tokyo/
01906;XLX778;XLX reflector;77.237.7.125;42000;018;https://xlx.hblink.kutno.pl/
38363;XLX781;XLX reflector;101.143.242.199;42000;240;http://xrf781.xreflector-jp.org/
45047;XLX799;XLX reflector;37.143.205.157;42000;006;http://xlxsof.ddns.net
53055;XLX800;XLX reflector;87.252.188.119;42000;015;http://xlx800.ddns.net
16226;XLX807;XLX reflector;116.91.197.3;42000;109;http://xrf807.owari.biz
55102;XLX810;XLX reflector;71.41.121.228;42000;003;http://xlx810.xlxreflector.org
48348;XLX812;XLX reflector;203.145.233.141;42000;138;http://xrf812.xreflector-jp.org/
70562;XLX837;XLX reflector;204.16.243.183;42000;000;http://xlx837.ai3i.net
54890;XLX840;XLX reflector;3.22.173.251;42000;001;http://ysf.lyrg.co.uk/
51106;XLX847;XLX reflector;204.16.243.184;42000;000;http://xlx847.ai3i.net
23661;XLX857;XLX reflector;204.16.243.185;42000;003;http://xlx857.ai3i.net
39930;XLX860;Allgaeu;24.134.86.93;42000;002;http://db0ess.de
08422;XLX888;XLX reflector;212.237.11.233;42000;019;http://xlx888.duckdns.org/db/index.php
48010;XLX891;XLX reflector;209.251.60.221;42000;007;http://xlx891.cidcomm.com
44904;XLX899;XLX reflector;45.14.224.180;42000;002;http://xlx899.mywire.org/
71144;XLX905;XLX reflector;94.199.173.123;42000;052;http://xlx905.oe9.at
82567;XLX922;XLX reflector;81.150.10.62;42000;016;https://www.cq-uk.co.uk
52616;XLX934;XLX reflector;79.6.136.177;42000;011;http://xlx934.arifvg.it
70191;XLX945;XLX reflector;213.202.229.40;42000;051;http://dcs945.xreflector.net
94341;XLX950;XLX reflector;158.64.26.134;42000;080;http://xlx950.epf.lu
43446;XLX957;XLX reflector;89.46.67.252;42000;004;http://xlx.dmrbrescia.it/xlxd/
15401;XLX960;XLX reflector;184.23.183.98;42000;006;http://xlxlist.dyndns.org
13897;XLX965;XLX reflector;80.211.190.216;42000;012;http://xlx965.hblink.it
45678;XLX970;XLX reflector;157.65.31.91;42000;204;http://ysf.onogoro.net/
96771;XLX973;XLX reflector;211.14.169.43;42000;015;http://xrf973.xreflector-jp.org/
85560;XLX978;XLX reflector;3.96.147.240;42000;004;http://xlx978.dyndns.org
37815;XLX994;XLX reflector;95.179.231.28;42000;008;https://xlx994.onlineradioclub.org
30906;XLXARG;XLX reflector;45.62.247.43;42000;009;http://xlxarg.no9s.org
91940;XLXCFR;XLX reflector;104.167.102.44;42000;009;http://xlxcfr.no9s.org
50281;XLXGUS;XLX reflector;104.167.112.102;42000;009;http://xlxgus.xlxreflector.org
17004;YO-Wires-X-E;WiresX Romania;85.122.16.152;42000;000;http://85.122.16.152
48709;YSF-24566;IT RADIOSCOUT;217.182.156.147;42000;000;http://ysf.radioscout.it/YSFReflector-Dashboard/
75917;YSF-768;Portugal 768;80.211.15.21;42000;002;http://ysf.voxpopuli.pt
54357;YSF-HBL-GDA;HBLink Polska;77.55.212.58;42000;000;http://77.55.212.58:8888
23053;YSF-IQ2AQ-L;YSF-SVXLINK;80.211.32.170;42000;003;http://80.211.32.170/ysf
06595;YSF-OMEGA;TAMBAYAN C4FM;107.175.49.145;42000;004;http://omegacomm.ddns.net
64915;YSF-PINOY;SPECTRUM;144.202.115.103;42030;006;http://ysf-pinoyspectrum.ddns.net
98022;YSF-PUSA;YSF-PUSA;149.248.7.112;42000;000;http://ab6bp.ddns.net
01183;YSF-TAMBAYAN;TAMBAYAN;47.157.208.97;42050;000;http://ysf-pinoytambayan.ddns.net
26626;YSF-TI;YSF Tango Indi;165.227.115.205;42000;002;http://xrf.ossdr.com/ysf
77299;YSF-TSIONG;Tambayan;107.175.215.106;42050;000;http://tsiong.ddns.net
41577;YSF-YO-W;Fusion Romania;89.33.44.100;42001;004;http://ysf.hamnet.ro
94614;YSF004;US Michigan Ro;44.103.34.3;42000;001;http://ysf004.kb8zgl.net/YSFReflector
43223;YSF2WIRESX;WIRESX 43223;104.143.94.48;42424;004;http://
49868;YSF345;USA CTDGroup;73.253.128.47;42002;001;http://ysf345.dyndns.org:82/YSF/
86137;ysf4aws;ysf4aws;18.210.76.48;42000;000;http://
88240;ZOMBIE-ALERT;WiresX #28298;107.141.52.226;42009;016;http://zombiealert.ddns.net

@ -0,0 +1,91 @@
#! /bin/bash
###############################################################################
#
# YSFHostsupdate.sh
#
# Copyright (C) 2016 by Tony Corbett G0WFV
# Adapted to YSFHosts by Paul Nannery KC2VRJ on 6/28/2016 with all crdeit
# to G0WFV for the orignal script.
#
# 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.
#
###############################################################################
#
# On a Linux based system, such as a Raspberry Pi, this script will perform all
# the steps required to maintain the YSFHosts.txt (or similar) file for you.
#
# It is designed to run from crontab and will download the YSFHosts from the
# master ysfreflector.de database and optionally keep a backup of previously
# created files for you.
#
# It will also prune the number of backup files according to a value specified
# by you in the configuration below.
#
# To install in root's crontab use the command ...
#
# sudo crontab -e
#
# ... and add the following line to the bottom of the file ...
#
# 0 0 * * * /path/to/script/YSFHostsupdate.sh 1>/dev/null 2>&1
#
# ... where /path/to/script/ should be replaced by the path to this script.
#
###############################################################################
#
# CONFIGURATION
#
# Full path to YSFHosts
YSFHOSTS=/path/to/YSFHosts.txt
# How many YSFHosts files do you want backed up (0 = do not keep backups)
YSFHOSTSFILEBACKUP=1
###############################################################################
#
# Do not edit below here
#
###############################################################################
# Check we are root
if [ "$(id -u)" != "0" ]
then
echo "This script must be run as root" 1>&2
exit 1
fi
# Create backup of old file
if [ ${YSFHOSTSFILEBACKUP} -ne 0 ]
then
cp ${YSFHOSTS} ${YSFHOSTS}.$(date +%d%m%y)
fi
# Prune backups
BACKUPCOUNT=$(ls ${YSFHOSTS}.* | wc -l)
BACKUPSTODELETE=$(expr ${BACKUPCOUNT} - ${YSFHOSTSFILEBACKUP})
if [ ${BACKUPCOUNT} -gt ${YSFHOSTSFILEBACKUP} ]
then
for f in $(ls -tr ${YSFHOSTS}.* | head -${BACKUPSTODELETE})
do
rm -f $f
done
fi
# Generate YSFHosts.txt file
curl https://register.ysfreflector.de/export_csv.php > ${YSFHOSTS}
exit 0

@ -0,0 +1,206 @@
/*
* Copyright (C) 2009-2014,2016,2017,2018 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 "YSFDefines.h"
#include "YSFNetwork.h"
#include "Utils.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <cstring>
const unsigned int BUFFER_LENGTH = 200U;
CYSFNetwork::CYSFNetwork(const std::string& address, unsigned int port, const std::string& callsign, bool debug) :
m_socket(address, port),
m_debug(debug),
m_address(),
m_port(0U),
m_poll(NULL),
m_unlink(NULL),
m_buffer(1000U, "YSF Network Buffer"),
m_pollTimer(1000U, 5U),
m_name(),
m_linked(false)
{
m_poll = new unsigned char[14U];
::memcpy(m_poll + 0U, "YSFP", 4U);
m_unlink = new unsigned char[14U];
::memcpy(m_unlink + 0U, "YSFU", 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);
}
}
CYSFNetwork::CYSFNetwork(unsigned int port, const std::string& callsign, bool debug) :
m_socket(port),
m_debug(debug),
m_address(),
m_port(0U),
m_poll(NULL),
m_unlink(NULL),
m_buffer(1000U, "YSF Network Buffer"),
m_pollTimer(1000U, 5U)
{
m_poll = new unsigned char[14U];
::memcpy(m_poll + 0U, "YSFP", 4U);
m_unlink = new unsigned char[14U];
::memcpy(m_unlink + 0U, "YSFU", 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);
}
}
CYSFNetwork::~CYSFNetwork()
{
delete[] m_poll;
}
bool CYSFNetwork::open()
{
LogMessage("Opening YSF network connection");
return m_socket.open();
}
void CYSFNetwork::setDestination(const std::string& name, const in_addr& address, unsigned int port)
{
m_name = name;
m_address = address;
m_port = port;
m_linked = false;
}
void CYSFNetwork::clearDestination()
{
m_address.s_addr = INADDR_NONE;
m_port = 0U;
m_linked = false;
m_pollTimer.stop();
}
void CYSFNetwork::write(const unsigned char* data)
{
assert(data != NULL);
if (m_port == 0U)
return;
if (m_debug)
CUtils::dump(1U, "YSF Network Data Sent", data, 155U);
m_socket.write(data, 155U, m_address, m_port);
}
void CYSFNetwork::writePoll(unsigned int count)
{
if (m_port == 0U)
return;
m_pollTimer.start();
for (unsigned int i = 0U; i < count; i++)
m_socket.write(m_poll, 14U, m_address, m_port);
}
void CYSFNetwork::writeUnlink(unsigned int count)
{
m_pollTimer.stop();
if (m_port == 0U)
return;
for (unsigned int i = 0U; i < count; i++)
m_socket.write(m_unlink, 14U, m_address, m_port);
m_linked = false;
}
void CYSFNetwork::clock(unsigned int ms)
{
unsigned char buffer[BUFFER_LENGTH];
in_addr address;
unsigned int port;
m_pollTimer.clock(ms);
if (m_pollTimer.isRunning() && m_pollTimer.hasExpired())
writePoll();
int length = m_socket.read(buffer, BUFFER_LENGTH, address, port);
if (length <= 0)
return;
if (m_port == 0U)
return;
if (address.s_addr != m_address.s_addr || port != m_port)
return;
if (::memcmp(buffer, "YSFP", 4U) == 0 && !m_linked) {
if (strcmp(m_name.c_str(),"MMDVM")== 0)
LogMessage("Link successful to %s", m_name.c_str());
else
LogMessage("Linked to %s", m_name.c_str());
m_linked = true;
}
if (m_debug)
CUtils::dump(1U, "YSF Network Data Received", buffer, length);
unsigned char len = length;
m_buffer.addData(&len, 1U);
m_buffer.addData(buffer, length);
}
unsigned int CYSFNetwork::read(unsigned char* data)
{
assert(data != NULL);
if (m_buffer.isEmpty())
return 0U;
unsigned char len = 0U;
m_buffer.getData(&len, 1U);
m_buffer.getData(data, len);
return len;
}
void CYSFNetwork::close()
{
m_socket.close();
LogMessage("Closing YSF network connection");
}

@ -0,0 +1,67 @@
/*
* Copyright (C) 2009-2014,2016,2017,2018,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
* 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 YSFNetwork_H
#define YSFNetwork_H
#include "DGIdNetwork.h"
#include "YSFDefines.h"
#include "UDPSocket.h"
#include "RingBuffer.h"
#include "Timer.h"
#include <cstdint>
#include <string>
class CYSFNetwork : public CDGIdNetwork {
public:
CYSFNetwork(const std::string& address, unsigned int port, const std::string& callsign, bool debug);
CYSFNetwork(unsigned int port, const std::string& callsign, bool debug);
virtual ~CYSFNetwork();
virtual bool open();
virtual void link();
void setDestination(const std::string& name, const in_addr& address, unsigned int port);
virtual void write(unsigned int dgId, const unsigned char* data);
void writePoll(unsigned int count = 1U);
virtual void unlink();
virtual unsigned int read(unsigned int dgId, unsigned char* data);
virtual void clock(unsigned int ms);
virtual void close();
private:
CUDPSocket m_socket;
bool m_debug;
in_addr m_address;
unsigned int m_port;
unsigned char* m_poll;
unsigned char* m_unlink;
CRingBuffer<unsigned char> m_buffer;
CTimer m_pollTimer;
std::string m_name;
bool m_linked;
};
#endif

@ -0,0 +1,357 @@
/*
* Copyright (C) 2016 Jonathan Naylor, G4KLX
* Copyright (C) 2016 Mathias Weyland, HB9FRV
*
* 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; version 2 of the License.
*
* 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.
*/
#include "YSFConvolution.h"
#include "YSFPayload.h"
#include "YSFDefines.h"
#include "Utils.h"
#include "CRC.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <cstring>
#include <cstdint>
const unsigned int INTERLEAVE_TABLE_9_20[] = {
0U, 40U, 80U, 120U, 160U, 200U, 240U, 280U, 320U,
2U, 42U, 82U, 122U, 162U, 202U, 242U, 282U, 322U,
4U, 44U, 84U, 124U, 164U, 204U, 244U, 284U, 324U,
6U, 46U, 86U, 126U, 166U, 206U, 246U, 286U, 326U,
8U, 48U, 88U, 128U, 168U, 208U, 248U, 288U, 328U,
10U, 50U, 90U, 130U, 170U, 210U, 250U, 290U, 330U,
12U, 52U, 92U, 132U, 172U, 212U, 252U, 292U, 332U,
14U, 54U, 94U, 134U, 174U, 214U, 254U, 294U, 334U,
16U, 56U, 96U, 136U, 176U, 216U, 256U, 296U, 336U,
18U, 58U, 98U, 138U, 178U, 218U, 258U, 298U, 338U,
20U, 60U, 100U, 140U, 180U, 220U, 260U, 300U, 340U,
22U, 62U, 102U, 142U, 182U, 222U, 262U, 302U, 342U,
24U, 64U, 104U, 144U, 184U, 224U, 264U, 304U, 344U,
26U, 66U, 106U, 146U, 186U, 226U, 266U, 306U, 346U,
28U, 68U, 108U, 148U, 188U, 228U, 268U, 308U, 348U,
30U, 70U, 110U, 150U, 190U, 230U, 270U, 310U, 350U,
32U, 72U, 112U, 152U, 192U, 232U, 272U, 312U, 352U,
34U, 74U, 114U, 154U, 194U, 234U, 274U, 314U, 354U,
36U, 76U, 116U, 156U, 196U, 236U, 276U, 316U, 356U,
38U, 78U, 118U, 158U, 198U, 238U, 278U, 318U, 358U};
const unsigned int INTERLEAVE_TABLE_5_20[] = {
0U, 40U, 80U, 120U, 160U,
2U, 42U, 82U, 122U, 162U,
4U, 44U, 84U, 124U, 164U,
6U, 46U, 86U, 126U, 166U,
8U, 48U, 88U, 128U, 168U,
10U, 50U, 90U, 130U, 170U,
12U, 52U, 92U, 132U, 172U,
14U, 54U, 94U, 134U, 174U,
16U, 56U, 96U, 136U, 176U,
18U, 58U, 98U, 138U, 178U,
20U, 60U, 100U, 140U, 180U,
22U, 62U, 102U, 142U, 182U,
24U, 64U, 104U, 144U, 184U,
26U, 66U, 106U, 146U, 186U,
28U, 68U, 108U, 148U, 188U,
30U, 70U, 110U, 150U, 190U,
32U, 72U, 112U, 152U, 192U,
34U, 74U, 114U, 154U, 194U,
36U, 76U, 116U, 156U, 196U,
38U, 78U, 118U, 158U, 198U};
const unsigned char WHITENING_DATA[] = {0x93U, 0xD7U, 0x51U, 0x21U, 0x9CU, 0x2FU, 0x6CU, 0xD0U, 0xEFU, 0x0FU,
0xF8U, 0x3DU, 0xF1U, 0x73U, 0x20U, 0x94U, 0xEDU, 0x1EU, 0x7CU, 0xD8U};
const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U};
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
CYSFPayload::CYSFPayload()
{
}
CYSFPayload::~CYSFPayload()
{
}
bool CYSFPayload::readVDMode1Data(const unsigned char* data, unsigned char* dt)
{
assert(data != NULL);
assert(dt != NULL);
data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES;
unsigned char dch[45U];
const unsigned char* p1 = data;
unsigned char* p2 = dch;
for (unsigned int i = 0U; i < 5U; i++) {
::memcpy(p2, p1, 9U);
p1 += 18U; p2 += 9U;
}
CYSFConvolution conv;
conv.start();
for (unsigned int i = 0U; i < 180U; i++) {
unsigned int n = INTERLEAVE_TABLE_9_20[i];
uint8_t s0 = READ_BIT1(dch, n) ? 1U : 0U;
n++;
uint8_t s1 = READ_BIT1(dch, n) ? 1U : 0U;
conv.decode(s0, s1);
}
unsigned char output[23U];
conv.chainback(output, 176U);
bool ret = CCRC::checkCCITT16(output, 22U);
if (ret) {
for (unsigned int i = 0U; i < 20U; i++)
output[i] ^= WHITENING_DATA[i];
CUtils::dump(1U, "V/D Mode 1 Data", output, 20U);
::memcpy(dt, output, 20U);
}
return ret;
}
bool CYSFPayload::readVDMode2Data(const unsigned char* data, unsigned char* dt)
{
assert(data != NULL);
assert(dt != NULL);
data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES;
unsigned char dch[25U];
const unsigned char* p1 = data;
unsigned char* p2 = dch;
for (unsigned int i = 0U; i < 5U; i++) {
::memcpy(p2, p1, 5U);
p1 += 18U; p2 += 5U;
}
CYSFConvolution conv;
conv.start();
for (unsigned int i = 0U; i < 100U; i++) {
unsigned int n = INTERLEAVE_TABLE_5_20[i];
uint8_t s0 = READ_BIT1(dch, n) ? 1U : 0U;
n++;
uint8_t s1 = READ_BIT1(dch, n) ? 1U : 0U;
conv.decode(s0, s1);
}
unsigned char output[13U];
conv.chainback(output, 96U);
bool ret = CCRC::checkCCITT16(output, 12U);
if (ret) {
for (unsigned int i = 0U; i < 10U; i++)
output[i] ^= WHITENING_DATA[i];
CUtils::dump(1U, "V/D Mode 2 Data", output, YSF_CALLSIGN_LENGTH);
::memcpy(dt, output, YSF_CALLSIGN_LENGTH);
}
return ret;
}
bool CYSFPayload::readDataFRModeData1(const unsigned char* data, unsigned char* dt)
{
assert(data != NULL);
assert(dt != NULL);
::memset(dt, ' ', 20U);
data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES;
unsigned char dch[45U];
const unsigned char* p1 = data;
unsigned char* p2 = dch;
for (unsigned int i = 0U; i < 5U; i++) {
::memcpy(p2, p1, 9U);
p1 += 18U; p2 += 9U;
}
CYSFConvolution conv;
conv.start();
for (unsigned int i = 0U; i < 180U; i++) {
unsigned int n = INTERLEAVE_TABLE_9_20[i];
uint8_t s0 = READ_BIT1(dch, n) ? 1U : 0U;
n++;
uint8_t s1 = READ_BIT1(dch, n) ? 1U : 0U;
conv.decode(s0, s1);
}
unsigned char output[23U];
conv.chainback(output, 176U);
bool ret = CCRC::checkCCITT16(output, 22U);
if (ret) {
for (unsigned int i = 0U; i < 20U; i++)
output[i] ^= WHITENING_DATA[i];
CUtils::dump(1U, "FR Mode Data 1", output, 20U);
::memcpy(dt, output, 20U);
}
return ret;
}
bool CYSFPayload::readDataFRModeData2(const unsigned char* data, unsigned char* dt)
{
assert(data != NULL);
assert(dt != NULL);
::memset(dt, ' ', 20U);
data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES;
unsigned char dch[45U];
const unsigned char* p1 = data + 9U;
unsigned char* p2 = dch;
for (unsigned int i = 0U; i < 5U; i++) {
::memcpy(p2, p1, 9U);
p1 += 18U; p2 += 9U;
}
CYSFConvolution conv;
conv.start();
for (unsigned int i = 0U; i < 180U; i++) {
unsigned int n = INTERLEAVE_TABLE_9_20[i];
uint8_t s0 = READ_BIT1(dch, n) ? 1U : 0U;
n++;
uint8_t s1 = READ_BIT1(dch, n) ? 1U : 0U;
conv.decode(s0, s1);
}
unsigned char output[23U];
conv.chainback(output, 176U);
bool ret = CCRC::checkCCITT16(output, 22U);
if (ret) {
for (unsigned int i = 0U; i < 20U; i++)
output[i] ^= WHITENING_DATA[i];
CUtils::dump(1U, "FR Mode Data 2", output, 20U);
::memcpy(dt, output, 20U);
}
return ret;
}
void CYSFPayload::writeDataFRModeData1(const unsigned char* dt, unsigned char* data)
{
assert(dt != NULL);
assert(data != NULL);
data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES;
unsigned char output[25U];
for (unsigned int i = 0U; i < 20U; i++)
output[i] = dt[i] ^ WHITENING_DATA[i];
CCRC::addCCITT16(output, 22U);
output[22U] = 0x00U;
unsigned char convolved[45U];
CYSFConvolution conv;
conv.encode(output, convolved, 180U);
unsigned char bytes[45U];
unsigned int j = 0U;
for (unsigned int i = 0U; i < 180U; i++) {
unsigned int n = INTERLEAVE_TABLE_9_20[i];
bool s0 = READ_BIT1(convolved, j) != 0U;
j++;
bool s1 = READ_BIT1(convolved, j) != 0U;
j++;
WRITE_BIT1(bytes, n, s0);
n++;
WRITE_BIT1(bytes, n, s1);
}
unsigned char* p1 = data;
unsigned char* p2 = bytes;
for (unsigned int i = 0U; i < 5U; i++) {
::memcpy(p1, p2, 9U);
p1 += 18U; p2 += 9U;
}
}
void CYSFPayload::writeDataFRModeData2(const unsigned char* dt, unsigned char* data)
{
assert(dt != NULL);
assert(data != NULL);
data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES;
unsigned char output[25U];
for (unsigned int i = 0U; i < 20U; i++)
output[i] = dt[i] ^ WHITENING_DATA[i];
CCRC::addCCITT16(output, 22U);
output[22U] = 0x00U;
unsigned char convolved[45U];
CYSFConvolution conv;
conv.encode(output, convolved, 180U);
unsigned char bytes[45U];
unsigned int j = 0U;
for (unsigned int i = 0U; i < 180U; i++) {
unsigned int n = INTERLEAVE_TABLE_9_20[i];
bool s0 = READ_BIT1(convolved, j) != 0U;
j++;
bool s1 = READ_BIT1(convolved, j) != 0U;
j++;
WRITE_BIT1(bytes, n, s0);
n++;
WRITE_BIT1(bytes, n, s1);
}
unsigned char* p1 = data + 9U;
unsigned char* p2 = bytes;
for (unsigned int i = 0U; i < 5U; i++) {
::memcpy(p1, p2, 9U);
p1 += 18U; p2 += 9U;
}
}

@ -0,0 +1,42 @@
/*
* 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.
*/
#if !defined(YSFPayload_H)
#define YSFPayload_H
#include <string>
class CYSFPayload {
public:
CYSFPayload();
~CYSFPayload();
bool readVDMode1Data(const unsigned char* data, unsigned char* dt);
bool readVDMode2Data(const unsigned char* data, unsigned char* dt);
bool readDataFRModeData1(const unsigned char* data, unsigned char* dt);
bool readDataFRModeData2(const unsigned char* data, unsigned char* dt);
void writeDataFRModeData1(const unsigned char* dt, unsigned char* data);
void writeDataFRModeData2(const unsigned char* dt, unsigned char* data);
private:
};
#endif

@ -0,0 +1,107 @@
/*
* 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
* 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 "YSFReflectors.h"
#include "Log.h"
#include <algorithm>
#include <functional>
#include <cstdio>
#include <cassert>
#include <cstring>
#include <cctype>
CYSFReflectors::CYSFReflectors(const std::string& hostsFile) :
m_hostsFile(hostsFile),
m_reflectors()
{
}
CYSFReflectors::~CYSFReflectors()
{
for (std::vector<CYSFReflector*>::iterator it = m_reflectors.begin(); it != m_reflectors.end(); ++it)
delete *it;
m_reflectors.clear();
}
bool CYSFReflectors::load()
{
FILE* fp = ::fopen(m_hostsFile.c_str(), "rt");
if (fp != NULL) {
char buffer[100U];
while (::fgets(buffer, 100U, fp) != NULL) {
if (buffer[0U] == '#')
continue;
char* p1 = ::strtok(buffer, ";\r\n");
char* p2 = ::strtok(NULL, ";\r\n");
char* p3 = ::strtok(NULL, ";\r\n");
char* p4 = ::strtok(NULL, ";\r\n");
char* p5 = ::strtok(NULL, ";\r\n");
char* p6 = ::strtok(NULL, "\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_address = address;
refl->m_port = (unsigned int)::atoi(p5);
m_reflectors.push_back(refl);
}
}
}
::fclose(fp);
}
size_t size = m_reflectors.size();
LogInfo("Loaded %u YSF reflectors", size);
return true;
}
CYSFReflector* CYSFReflectors::findById(const std::string& id)
{
for (std::vector<CYSFReflector*>::const_iterator it = m_reflectors.cbegin(); it != m_reflectors.cend(); ++it) {
if (id == (*it)->m_id)
return *it;
}
LogMessage("Trying to find non existent YSF reflector with an id of %s", id.c_str());
return NULL;
}
CYSFReflector* CYSFReflectors::findByName(const std::string& name)
{
for (std::vector<CYSFReflector*>::const_iterator it = m_reflectors.cbegin(); it != m_reflectors.cend(); ++it) {
if (name == (*it)->m_name)
return *it;
}
LogMessage("Trying to find non existent YSF reflector with a name of %s", name.c_str());
return NULL;
}

@ -0,0 +1,58 @@
/*
* 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
* 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.
*/
#if !defined(YSFReflectors_H)
#define YSFReflectors_H
#include "UDPSocket.h"
#include <vector>
#include <string>
class CYSFReflector {
public:
CYSFReflector() :
m_id(),
m_name(),
m_address(),
m_port(0U)
{
}
std::string m_id;
std::string m_name;
in_addr m_address;
unsigned int m_port;
};
class CYSFReflectors {
public:
CYSFReflectors(const std::string& hostsFile);
~CYSFReflectors();
bool load();
CYSFReflector* findById(const std::string& id);
CYSFReflector* findByName(const std::string& name);
private:
std::string m_hostsFile;
std::vector<CYSFReflector*> m_reflectors;
};
#endif

@ -1,4 +1,4 @@
SUBDIRS = YSFGateway YSFParrot YSFReflector
SUBDIRS = DGIdGateway YSFGateway YSFParrot YSFReflector
CLEANDIRS = $(SUBDIRS:%=clean-%)
INSTALLDIRS = $(SUBDIRS:%=install-%)

Loading…
Cancel
Save