Compare commits
82 commits
ycs232-kbc
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
aecc34ee64 | ||
|
dfe50c4245 | ||
|
f7f94b3ca1 | ||
|
bf6577e2ca | ||
|
7cbac3bdab | ||
|
95d83fd9ce | ||
|
2530199d54 | ||
|
351e6c2d59 | ||
|
2e303e55e6 | ||
|
daef16c145 | ||
|
3409e45d83 | ||
|
f637ff564f | ||
|
c027bed0aa | ||
|
fd84400bfc | ||
|
9eb6d3967f | ||
|
3731800162 | ||
|
098c4fc6b4 | ||
|
9efe097f0b | ||
|
20096333dd | ||
|
2d92907b96 | ||
|
b743f1a6e8 | ||
|
b0f3f70f77 | ||
|
e3dd9f5321 | ||
|
471d031a08 | ||
|
22a0b9ae28 | ||
|
df5b0346f2 | ||
|
1fab3dbd61 | ||
|
d58edef727 | ||
|
ec16283b5c | ||
|
9bccf4c2b6 | ||
|
cdfc8c9fad | ||
|
1015f3d55f | ||
|
1344f545e9 | ||
|
227b3a9b2f | ||
|
267b8e0809 | ||
|
3af8708977 | ||
|
15247d0c47 | ||
|
e792cab308 | ||
|
c05a7f0205 | ||
|
d3ee33ab0f | ||
|
0e48d79162 | ||
|
7c517f8476 | ||
|
c5d76be1cc | ||
|
9634817ddf | ||
|
6cea7a63bc | ||
|
90233f50e2 | ||
|
1147745c48 | ||
|
301e030b4d | ||
|
54ae27d63b | ||
|
1456810fa9 | ||
|
f0868dd4ba | ||
|
d152dd1074 | ||
|
e68f88e8dc | ||
|
08bb6c2734 | ||
|
20488044b1 | ||
|
3b7ac383db | ||
|
c848b32cce | ||
|
04d4c91f7c | ||
|
dee62db7cd | ||
|
3a99410248 | ||
|
8167158f87 | ||
|
94fbd66cc3 | ||
|
264129e57a | ||
|
480601b954 | ||
|
2d4ffac048 | ||
|
fc76b0f4ab | ||
|
014cddadd5 | ||
|
d6ac3b2be5 | ||
|
c9660478c5 | ||
|
b582905728 | ||
|
ca1e857aa6 | ||
|
10dcdbf56f | ||
|
0c02bec9d2 | ||
|
6c3af73383 | ||
|
d0602d9aa6 | ||
|
51fc88f6e4 | ||
|
05c627c7d5 | ||
|
39f2dc9a0d | ||
|
1a81c4a003 | ||
|
c159461f30 | ||
|
1d428e921d | ||
|
44cf900ec2 |
91 changed files with 4292 additions and 6140 deletions
.gitignoreMakefileREADME.mdYSFClients.sln
DGIdGateway
.vscode
APRSWriter.cppAPRSWriter.hConf.cppConf.hDGIdGateway.cppDGIdGateway.iniDGIdGateway.vcxprojFCSNetwork.cppFCSNetwork.hFCSRooms.txtGPS.cppLog.cppMakefileUDPSocket.cppUDPSocket.hVersion.hYSFDefines.hYSFHosts.txtYSFNetwork.cppYSFNetwork.hYSFReflectors.cppprebuild.cmdYSFGateway
APRSWriter.cppAPRSWriter.hConf.cppConf.hFCSNetwork.cppFCSNetwork.hFCSRooms.txtGPS.cppLog.cppMakefileUDPSocket.cppUDPSocket.hVersion.hWiresX.cppWiresX.hYSFDefines.hYSFGateway.cppYSFGateway.hYSFGateway.iniYSFGateway.vcxprojYSFHosts.txtYSFNetwork.cppYSFNetwork.hYSFReflectors.cppYSFReflectors.hprebuild.cmd
YSFParrot
MakefileNetwork.cppNetwork.hUDPSocket.cppUDPSocket.hVersion.hYSFParrot.cppYSFParrot.hYSFParrot.vcxprojprebuild.cmd
YSFReflector
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -17,3 +17,5 @@ DGIdGateway/DGIdGateway
|
|||
YSFGateway/YSFGateway
|
||||
YSFParrot/YSFParrot
|
||||
YSFReflector/YSFReflector
|
||||
GitVersion.h
|
||||
.vscode
|
||||
|
|
3
DGIdGateway/.vscode/settings.json
vendored
Normal file
3
DGIdGateway/.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"makefile.extensionOutputFolder": "./.vscode"
|
||||
}
|
|
@ -25,7 +25,7 @@
|
|||
#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) :
|
||||
CAPRSWriter::CAPRSWriter(const std::string& callsign, const std::string& rptSuffix, const std::string& address, unsigned short port, const std::string& suffix, bool debug) :
|
||||
m_idTimer(1000U),
|
||||
m_callsign(callsign),
|
||||
m_debug(debug),
|
||||
|
@ -35,6 +35,7 @@ m_latitude(0.0F),
|
|||
m_longitude(0.0F),
|
||||
m_height(0),
|
||||
m_desc(),
|
||||
m_symbol(),
|
||||
m_suffix(suffix),
|
||||
m_aprsAddr(),
|
||||
m_aprsAddrLen(0U),
|
||||
|
@ -63,11 +64,12 @@ CAPRSWriter::~CAPRSWriter()
|
|||
{
|
||||
}
|
||||
|
||||
void CAPRSWriter::setInfo(unsigned int txFrequency, unsigned int rxFrequency, const std::string& desc)
|
||||
void CAPRSWriter::setInfo(unsigned int txFrequency, unsigned int rxFrequency, const std::string& desc, const std::string& symbol)
|
||||
{
|
||||
m_txFrequency = txFrequency;
|
||||
m_rxFrequency = rxFrequency;
|
||||
m_desc = desc;
|
||||
m_symbol = symbol;
|
||||
}
|
||||
|
||||
void CAPRSWriter::setStaticLocation(float latitude, float longitude, int height)
|
||||
|
@ -158,12 +160,15 @@ void CAPRSWriter::write(const unsigned char* source, const char* type, unsigned
|
|||
case 0x24U:
|
||||
case 0x28U:
|
||||
case 0x30U:
|
||||
case 0x33U:
|
||||
symbol = '[';
|
||||
break;
|
||||
case 0x25U:
|
||||
case 0x29U:
|
||||
case 0x31U:
|
||||
symbol = '>';
|
||||
break;
|
||||
case 0x20U:
|
||||
case 0x26U:
|
||||
symbol = 'r';
|
||||
break;
|
||||
|
@ -229,19 +234,19 @@ void CAPRSWriter::sendIdFrameFixed()
|
|||
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",
|
||||
::sprintf(desc, "MMDVM Voice (C4FM) %.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());
|
||||
::sprintf(desc, "MMDVM Voice (C4FM)%s%s", m_desc.empty() ? "" : ", ", m_desc.c_str());
|
||||
}
|
||||
|
||||
const char* band = "4m";
|
||||
if (m_txFrequency >= 1200000000U)
|
||||
band = "1.2";
|
||||
band = "23cm/1.2GHz";
|
||||
else if (m_txFrequency >= 420000000U)
|
||||
band = "440";
|
||||
band = "70cm`";
|
||||
else if (m_txFrequency >= 144000000U)
|
||||
band = "2m";
|
||||
else if (m_txFrequency >= 50000000U)
|
||||
|
@ -265,17 +270,21 @@ void CAPRSWriter::sendIdFrameFixed()
|
|||
::sprintf(lon, "%08.2lf", longitude);
|
||||
|
||||
std::string server = m_callsign;
|
||||
std::string symbol = m_symbol;
|
||||
size_t pos = server.find_first_of('-');
|
||||
if (pos == std::string::npos)
|
||||
server.append("-S");
|
||||
else
|
||||
server.append("S");
|
||||
|
||||
if (symbol.empty())
|
||||
symbol.append("D&");
|
||||
|
||||
char output[500U];
|
||||
::sprintf(output, "%s>APDG03,TCPIP*,qAC,%s:!%s%cD%s%c&/A=%06.0f%s %s\r\n",
|
||||
::sprintf(output, "%s>APDG03,TCPIP*,qAC,%s:!%s%c%c%s%c%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',
|
||||
lat, (m_latitude < 0.0F) ? 'S' : 'N', symbol[0],
|
||||
lon, (m_longitude < 0.0F) ? 'W' : 'E', symbol[1],
|
||||
float(m_height) * 3.28F, band, desc);
|
||||
|
||||
if (m_debug)
|
||||
|
@ -299,7 +308,11 @@ void CAPRSWriter::sendIdFrameMobile()
|
|||
#endif
|
||||
|
||||
|
||||
#if GPSD_API_MAJOR_VERSION >= 10
|
||||
if (m_gpsdData.fix.status != STATUS_FIX)
|
||||
#else
|
||||
if (m_gpsdData.status != STATUS_FIX)
|
||||
#endif
|
||||
return;
|
||||
|
||||
bool latlonSet = (m_gpsdData.set & LATLON_SET) == LATLON_SET;
|
||||
|
@ -323,19 +336,19 @@ void CAPRSWriter::sendIdFrameMobile()
|
|||
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",
|
||||
::sprintf(desc, "MMDVM Voice (C4FM) %.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());
|
||||
::sprintf(desc, "MMDVM Voice (C4FM)%s%s", m_desc.empty() ? "" : ", ", m_desc.c_str());
|
||||
}
|
||||
|
||||
const char* band = "4m";
|
||||
if (m_txFrequency >= 1200000000U)
|
||||
band = "1.2";
|
||||
band = "23cm/1.2GHz";
|
||||
else if (m_txFrequency >= 420000000U)
|
||||
band = "440";
|
||||
band = "70cm";
|
||||
else if (m_txFrequency >= 144000000U)
|
||||
band = "2m";
|
||||
else if (m_txFrequency >= 50000000U)
|
||||
|
@ -359,17 +372,21 @@ void CAPRSWriter::sendIdFrameMobile()
|
|||
::sprintf(lon, "%08.2lf", longitude);
|
||||
|
||||
std::string server = m_callsign;
|
||||
std::string symbol = m_symbol;
|
||||
size_t pos = server.find_first_of('-');
|
||||
if (pos == std::string::npos)
|
||||
server.append("-S");
|
||||
else
|
||||
server.append("S");
|
||||
|
||||
if (symbol.empty())
|
||||
symbol.append("D&");
|
||||
|
||||
char output[500U];
|
||||
::sprintf(output, "%s>APDG03,TCPIP*,qAC,%s:!%s%cD%s%c&",
|
||||
::sprintf(output, "%s>APDG03,TCPIP*,qAC,%s:!%s%c%c%s%c%c",
|
||||
m_callsign.c_str(), server.c_str(),
|
||||
lat, (rawLatitude < 0.0F) ? 'S' : 'N',
|
||||
lon, (rawLongitude < 0.0F) ? 'W' : 'E');
|
||||
lat, (rawLatitude < 0.0F) ? 'S' : 'N', symbol[0],
|
||||
lon, (rawLongitude < 0.0F) ? 'W' : 'E', symbol[1]);
|
||||
|
||||
if (bearingSet && velocitySet)
|
||||
::sprintf(output + ::strlen(output), "%03.0f/%03.0f", rawBearing, rawVelocity * 0.539957F);
|
||||
|
|
|
@ -42,12 +42,12 @@
|
|||
|
||||
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(const std::string& callsign, const std::string& rptSuffix, const std::string& address, unsigned short port, const std::string& suffix, bool debug);
|
||||
~CAPRSWriter();
|
||||
|
||||
bool open();
|
||||
|
||||
void setInfo(unsigned int txFrequency, unsigned int rxFrequency, const std::string& desc);
|
||||
void setInfo(unsigned int txFrequency, unsigned int rxFrequency, const std::string& desc, const std::string& symbol);
|
||||
|
||||
void setStaticLocation(float latitude, float longitude, int height);
|
||||
|
||||
|
@ -69,6 +69,7 @@ private:
|
|||
float m_longitude;
|
||||
int m_height;
|
||||
std::string m_desc;
|
||||
std::string m_symbol;
|
||||
std::string m_suffix;
|
||||
sockaddr_storage m_aprsAddr;
|
||||
unsigned int m_aprsAddrLen;
|
||||
|
|
|
@ -71,6 +71,7 @@ m_aprsAddress(),
|
|||
m_aprsPort(0U),
|
||||
m_aprsSuffix(),
|
||||
m_aprsDescription(),
|
||||
m_aprsSymbol("/r"),
|
||||
m_ysfNetHosts(),
|
||||
m_ysfRFHangTime(60U),
|
||||
m_ysfNetHangTime(60U),
|
||||
|
@ -178,11 +179,11 @@ bool CConf::read()
|
|||
else if (::strcmp(key, "RptAddress") == 0)
|
||||
m_rptAddress = value;
|
||||
else if (::strcmp(key, "RptPort") == 0)
|
||||
m_rptPort = (unsigned int)::atoi(value);
|
||||
m_rptPort = (unsigned short)::atoi(value);
|
||||
else if (::strcmp(key, "LocalAddress") == 0)
|
||||
m_myAddress = value;
|
||||
else if (::strcmp(key, "LocalPort") == 0)
|
||||
m_myPort = (unsigned int)::atoi(value);
|
||||
m_myPort = (unsigned short)::atoi(value);
|
||||
else if (::strcmp(key, "RFHangTime") == 0)
|
||||
m_ysfRFHangTime = m_fcsRFHangTime = m_rfHangTime = (unsigned int)::atoi(value);
|
||||
else if (::strcmp(key, "NetHangTime") == 0)
|
||||
|
@ -225,11 +226,13 @@ bool CConf::read()
|
|||
else if (::strcmp(key, "Address") == 0)
|
||||
m_aprsAddress = value;
|
||||
else if (::strcmp(key, "Port") == 0)
|
||||
m_aprsPort = (unsigned int)::atoi(value);
|
||||
m_aprsPort = (unsigned short)::atoi(value);
|
||||
else if (::strcmp(key, "Suffix") == 0)
|
||||
m_aprsSuffix = value;
|
||||
else if (::strcmp(key, "Description") == 0)
|
||||
m_aprsDescription = value;
|
||||
else if (::strcmp(key, "Symbol") == 0)
|
||||
m_aprsSymbol = value;
|
||||
} else if (section == SECTION_YSF_NETWORK) {
|
||||
if (::strcmp(key, "Hosts") == 0)
|
||||
m_ysfNetHosts = value;
|
||||
|
@ -286,7 +289,7 @@ bool CConf::read()
|
|||
else if (::strcmp(key, "Name") == 0)
|
||||
dgIdData->m_name = value;
|
||||
else if (::strcmp(key, "Port") == 0)
|
||||
dgIdData->m_port = (unsigned int)::atoi(value);
|
||||
dgIdData->m_port = (unsigned short)::atoi(value);
|
||||
else if (::strcmp(key, "Local") == 0)
|
||||
dgIdData->m_local = (unsigned int)::atoi(value);
|
||||
else if (::strcmp(key, "DGId") == 0)
|
||||
|
@ -335,7 +338,7 @@ std::string CConf::getRptAddress() const
|
|||
return m_rptAddress;
|
||||
}
|
||||
|
||||
unsigned int CConf::getRptPort() const
|
||||
unsigned short CConf::getRptPort() const
|
||||
{
|
||||
return m_rptPort;
|
||||
}
|
||||
|
@ -345,7 +348,7 @@ std::string CConf::getMyAddress() const
|
|||
return m_myAddress;
|
||||
}
|
||||
|
||||
unsigned int CConf::getMyPort() const
|
||||
unsigned short CConf::getMyPort() const
|
||||
{
|
||||
return m_myPort;
|
||||
}
|
||||
|
@ -435,7 +438,7 @@ std::string CConf::getAPRSAddress() const
|
|||
return m_aprsAddress;
|
||||
}
|
||||
|
||||
unsigned int CConf::getAPRSPort() const
|
||||
unsigned short CConf::getAPRSPort() const
|
||||
{
|
||||
return m_aprsPort;
|
||||
}
|
||||
|
@ -450,6 +453,11 @@ std::string CConf::getAPRSDescription() const
|
|||
return m_aprsDescription;
|
||||
}
|
||||
|
||||
std::string CConf::getAPRSSymbol() const
|
||||
{
|
||||
return m_aprsSymbol;
|
||||
}
|
||||
|
||||
std::string CConf::getYSFNetHosts() const
|
||||
{
|
||||
return m_ysfNetHosts;
|
||||
|
|
|
@ -33,8 +33,8 @@ struct DGIdData {
|
|||
bool m_static;
|
||||
std::string m_name;
|
||||
std::string m_address;
|
||||
unsigned int m_port;
|
||||
unsigned int m_local;
|
||||
unsigned short m_port;
|
||||
unsigned short m_local;
|
||||
unsigned int m_netDGId;
|
||||
std::vector<IMRSDestination*> m_destinations;
|
||||
unsigned int m_rfHangTime;
|
||||
|
@ -55,9 +55,9 @@ public:
|
|||
std::string getSuffix() const;
|
||||
unsigned int getId() const;
|
||||
std::string getRptAddress() const;
|
||||
unsigned int getRptPort() const;
|
||||
unsigned short getRptPort() const;
|
||||
std::string getMyAddress() const;
|
||||
unsigned int getMyPort() const;
|
||||
unsigned short getMyPort() const;
|
||||
bool getBleep() const;
|
||||
bool getDebug() const;
|
||||
bool getDaemon() const;
|
||||
|
@ -81,9 +81,10 @@ public:
|
|||
// The APRS section
|
||||
bool getAPRSEnabled() const;
|
||||
std::string getAPRSAddress() const;
|
||||
unsigned int getAPRSPort() const;
|
||||
unsigned short getAPRSPort() const;
|
||||
std::string getAPRSSuffix() const;
|
||||
std::string getAPRSDescription() const;
|
||||
std::string getAPRSSymbol() const;
|
||||
|
||||
// The YSF Network section
|
||||
std::string getYSFNetHosts() const;
|
||||
|
@ -102,9 +103,9 @@ private:
|
|||
std::string m_suffix;
|
||||
unsigned int m_id;
|
||||
std::string m_rptAddress;
|
||||
unsigned int m_rptPort;
|
||||
unsigned short m_rptPort;
|
||||
std::string m_myAddress;
|
||||
unsigned int m_myPort;
|
||||
unsigned short m_myPort;
|
||||
unsigned int m_rfHangTime;
|
||||
unsigned int m_netHangTime;
|
||||
bool m_bleep;
|
||||
|
@ -127,9 +128,10 @@ private:
|
|||
|
||||
bool m_aprsEnabled;
|
||||
std::string m_aprsAddress;
|
||||
unsigned int m_aprsPort;
|
||||
unsigned short m_aprsPort;
|
||||
std::string m_aprsSuffix;
|
||||
std::string m_aprsDescription;
|
||||
std::string m_aprsSymbol;
|
||||
|
||||
std::string m_ysfNetHosts;
|
||||
unsigned int m_ysfRFHangTime;
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "Timer.h"
|
||||
#include "Utils.h"
|
||||
#include "Log.h"
|
||||
#include "GitVersion.h"
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <Windows.h>
|
||||
|
@ -69,7 +70,7 @@ int main(int argc, char** argv)
|
|||
for (int currentArg = 1; currentArg < argc; ++currentArg) {
|
||||
std::string arg = argv[currentArg];
|
||||
if ((arg == "-v") || (arg == "--version")) {
|
||||
::fprintf(stdout, "DGIdGateway version %s\n", VERSION);
|
||||
::fprintf(stdout, "DGIdGateway version %s git #%.7s\n", VERSION, gitversion);
|
||||
return 0;
|
||||
} else if (arg.substr(0, 1) == "-") {
|
||||
::fprintf(stderr, "Usage: DGIdGateway [-v|--version] [filename]\n");
|
||||
|
@ -199,7 +200,7 @@ int CDGIdGateway::run()
|
|||
|
||||
bool debug = m_conf.getDebug();
|
||||
std::string myAddress = m_conf.getMyAddress();
|
||||
unsigned int myPort = m_conf.getMyPort();
|
||||
unsigned short myPort = m_conf.getMyPort();
|
||||
|
||||
CYSFNetwork rptNetwork(myAddress, myPort, "MMDVM", rptAddr, rptAddrLen, m_callsign, debug);
|
||||
ret = rptNetwork.open();
|
||||
|
@ -243,7 +244,7 @@ int CDGIdGateway::run()
|
|||
|
||||
if (type == "FCS") {
|
||||
std::string name = (*it)->m_name;
|
||||
unsigned int local = (*it)->m_local;
|
||||
unsigned short local = (*it)->m_local;
|
||||
unsigned int txFrequency = m_conf.getTxFrequency();
|
||||
unsigned int rxFrequency = m_conf.getRxFrequency();
|
||||
std::string locator = calculateLocator();
|
||||
|
@ -303,7 +304,7 @@ int CDGIdGateway::run()
|
|||
LogMessage("Added IMRS:%s to DG-ID %u%s", name.c_str(), dgid, statc ? " (Static)" : "");
|
||||
}
|
||||
} else if (type == "Gateway") {
|
||||
unsigned int local = (*it)->m_local;
|
||||
unsigned short local = (*it)->m_local;
|
||||
|
||||
sockaddr_storage addr;
|
||||
unsigned int addrLen;
|
||||
|
@ -319,7 +320,7 @@ int CDGIdGateway::run()
|
|||
LogWarning("Unable to resolve the address for the YSF Gateway");
|
||||
}
|
||||
} else if (type == "Parrot") {
|
||||
unsigned int local = (*it)->m_local;
|
||||
unsigned short local = (*it)->m_local;
|
||||
|
||||
sockaddr_storage addr;
|
||||
unsigned int addrLen;
|
||||
|
@ -335,7 +336,7 @@ int CDGIdGateway::run()
|
|||
LogWarning("Unable to resolve the address for the YSF Parrot");
|
||||
}
|
||||
} else if (type == "YSF2DMR") {
|
||||
unsigned int local = (*it)->m_local;
|
||||
unsigned short local = (*it)->m_local;
|
||||
|
||||
sockaddr_storage addr;
|
||||
unsigned int addrLen;
|
||||
|
@ -351,7 +352,7 @@ int CDGIdGateway::run()
|
|||
LogWarning("Unable to resolve the address for YSF2DMR");
|
||||
}
|
||||
} else if (type == "YSF2NXDN") {
|
||||
unsigned int local = (*it)->m_local;
|
||||
unsigned short local = (*it)->m_local;
|
||||
|
||||
sockaddr_storage addr;
|
||||
unsigned int addrLen;
|
||||
|
@ -367,7 +368,7 @@ int CDGIdGateway::run()
|
|||
LogWarning("Unable to resolve the address for YSF2NXDN");
|
||||
}
|
||||
} else if (type == "YSF2P25") {
|
||||
unsigned int local = (*it)->m_local;
|
||||
unsigned short local = (*it)->m_local;
|
||||
|
||||
sockaddr_storage addr;
|
||||
unsigned int addrLen;
|
||||
|
@ -407,7 +408,8 @@ int CDGIdGateway::run()
|
|||
CStopWatch stopWatch;
|
||||
stopWatch.start();
|
||||
|
||||
LogMessage("Starting DGIdGateway-%s", VERSION);
|
||||
LogMessage("DGIdGateway-%s is starting", VERSION);
|
||||
LogMessage("Built %s %s (GitID #%.7s)", __TIME__, __DATE__, gitversion);
|
||||
|
||||
DGID_STATUS state = DS_NOTLINKED;
|
||||
unsigned int nPips = 0U;
|
||||
|
@ -425,13 +427,7 @@ int CDGIdGateway::run()
|
|||
if (dgId == WIRESX_DGID)
|
||||
dgId = 0U;
|
||||
|
||||
if (dgId != currentDGId) {
|
||||
if (currentDGId != UNSET_DGID && dgIdNetwork[currentDGId] != NULL && !dgIdNetwork[currentDGId]->m_static) {
|
||||
dgIdNetwork[currentDGId]->unlink();
|
||||
dgIdNetwork[currentDGId]->unlink();
|
||||
dgIdNetwork[currentDGId]->unlink();
|
||||
}
|
||||
|
||||
if (currentDGId == UNSET_DGID) {
|
||||
if (dgIdNetwork[dgId] != NULL && !dgIdNetwork[dgId]->m_static) {
|
||||
dgIdNetwork[dgId]->link();
|
||||
dgIdNetwork[dgId]->link();
|
||||
|
@ -441,13 +437,13 @@ int CDGIdGateway::run()
|
|||
if (dgIdNetwork[dgId] != NULL) {
|
||||
std::string desc = dgIdNetwork[dgId]->getDesc(dgId);
|
||||
LogMessage("DG-ID set to %u (%s) via RF", dgId, desc.c_str());
|
||||
currentDGId = dgId;
|
||||
state = DS_NOTLINKED;
|
||||
} else {
|
||||
LogMessage("DG-ID set to %u (None) via RF", dgId);
|
||||
state = DS_NOTOPEN;
|
||||
}
|
||||
|
||||
currentDGId = dgId;
|
||||
fromRF = true;
|
||||
}
|
||||
|
||||
|
@ -609,7 +605,7 @@ void CDGIdGateway::createGPS()
|
|||
return;
|
||||
|
||||
std::string address = m_conf.getAPRSAddress();
|
||||
unsigned int port = m_conf.getAPRSPort();
|
||||
unsigned short port = m_conf.getAPRSPort();
|
||||
std::string suffix = m_conf.getAPRSSuffix();
|
||||
bool debug = m_conf.getDebug();
|
||||
|
||||
|
@ -618,8 +614,9 @@ void CDGIdGateway::createGPS()
|
|||
unsigned int txFrequency = m_conf.getTxFrequency();
|
||||
unsigned int rxFrequency = m_conf.getRxFrequency();
|
||||
std::string desc = m_conf.getAPRSDescription();
|
||||
std::string symbol = m_conf.getAPRSSymbol();
|
||||
|
||||
m_writer->setInfo(txFrequency, rxFrequency, desc);
|
||||
m_writer->setInfo(txFrequency, rxFrequency, desc, symbol);
|
||||
|
||||
bool enabled = m_conf.getGPSDEnabled();
|
||||
if (enabled) {
|
||||
|
|
|
@ -36,6 +36,7 @@ Address=127.0.0.1
|
|||
Port=8673
|
||||
Description=APRS Description
|
||||
Suffix=Y
|
||||
# Symbol="/r"
|
||||
|
||||
[YSF Network]
|
||||
Hosts=./YSFHosts.txt
|
||||
|
|
|
@ -94,6 +94,9 @@
|
|||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>prebuild.cmd</Command>
|
||||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
|
@ -111,6 +114,9 @@
|
|||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>prebuild.cmd</Command>
|
||||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
|
@ -124,6 +130,9 @@
|
|||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>prebuild.cmd</Command>
|
||||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
|
@ -141,6 +150,9 @@
|
|||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>prebuild.cmd</Command>
|
||||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="APRSWriter.cpp" />
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2014,2016,2017,2018,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2014,2016,2017,2018,2020,2021 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
|
||||
|
@ -29,7 +29,7 @@ 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 statc, bool debug) :
|
||||
CFCSNetwork::CFCSNetwork(const std::string& reflector, unsigned short port, const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, const std::string& locator, unsigned int id, bool statc, bool debug) :
|
||||
m_socket(port),
|
||||
m_debug(debug),
|
||||
m_addr(),
|
||||
|
@ -60,7 +60,7 @@ m_state(DS_NOTOPEN)
|
|||
m_print = reflector.substr(0U, 6U) + "-" + reflector.substr(6U);
|
||||
|
||||
char url[50U];
|
||||
::sprintf(url, "%s.xreflector.net", reflector.c_str());
|
||||
::sprintf(url, "%.6s.xreflector.net", reflector.c_str());
|
||||
if (CUDPSocket::lookup(std::string(url), FCS_PORT, m_addr, m_addrLen) != 0)
|
||||
m_addrLen = 0U;
|
||||
}
|
||||
|
@ -191,7 +191,8 @@ void CFCSNetwork::clock(unsigned int ms)
|
|||
if (length <= 0)
|
||||
return;
|
||||
|
||||
CUtils::dump(1U, "FCS Network Data Received", buffer, length);
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "FCS Network Data Received", buffer, length);
|
||||
|
||||
if (m_state == DS_NOTLINKED)
|
||||
return;
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
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 statc, bool debug);
|
||||
CFCSNetwork(const std::string& reflector, unsigned short port, const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, const std::string& locator, unsigned int id, bool statc, bool debug);
|
||||
virtual ~CFCSNetwork();
|
||||
|
||||
virtual std::string getDesc(unsigned int dgId);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# xreflector.net - FCS_Hosts.txt
|
||||
# Last Update: 10.12.2020 06:50 UTC
|
||||
# Last Update: 13.03.2021 15:50 UTC
|
||||
#
|
||||
FCS00100;Repeater;FCS001 - Repeater;;;
|
||||
FCS00101;Deutschland;FCS001 - Deutschland;;;
|
||||
|
@ -457,7 +457,7 @@ FCS00552;nn;FCS005 - nn;;;
|
|||
FCS00553;nn;FCS005 - nn;;;
|
||||
FCS00554;nn;FCS005 - nn;;;
|
||||
FCS00555;nn;FCS005 - nn;;;
|
||||
FCS00556;nn;FCS005 - nn;;;
|
||||
FCS00556;ARFCOM;FCS005 - ARFCOM;;;
|
||||
FCS00557;nn;FCS005 - nn;;;
|
||||
FCS00558;nn;FCS005 - nn;;;
|
||||
FCS00559;nn;FCS005 - nn;;;
|
||||
|
@ -604,38 +604,38 @@ FCS20699;Test-9;FCS206 - Test-9;;;
|
|||
FCS20700;nn;FCS207 - nn;;;
|
||||
FCS20701;DR-2X;FCS207 - DR-2X;;;
|
||||
FCS20702;Europe;FCS207 - Europe;;;
|
||||
FCS20703;North-America;FCS207 - North-America;;;
|
||||
FCS20704;Asia;FCS207 - Asia;;;
|
||||
FCS20705;Oceania;FCS207 - Oceania;;;
|
||||
FCS20706;Africa;FCS207 - Africa;;;
|
||||
FCS20707;South-America;FCS207 - South-America;;;
|
||||
FCS20703;nn;FCS207 - nn;;;
|
||||
FCS20704;nn;FCS207 - nn;;;
|
||||
FCS20705;nn;FCS207 - nn;;;
|
||||
FCS20706;nn;FCS207 - nn;;;
|
||||
FCS20707;nn;FCS207 - nn;;;
|
||||
FCS20708;nn;FCS207 - nn;;;
|
||||
FCS20709;nn;FCS207 - nn;;;
|
||||
FCS20710;WW-german;FCS207 - WW-german;;;
|
||||
FCS20711;WW-french;FCS207 - WW-french;;;
|
||||
FCS20710;nn;FCS207 - nn;;;
|
||||
FCS20711;nn;FCS207 - nn;;;
|
||||
FCS20712;WW-dutch/flemish;FCS207 - WW-dutch/flemish;;;
|
||||
FCS20713;WW-english;FCS207 - WW-english;;;
|
||||
FCS20714;WW-spanish;FCS207 - WW-spanish;;;
|
||||
FCS20715;WW-portuguese;FCS207 - WW-portuguese;;;
|
||||
FCS20716;WW-italian;FCS207 - WW-italian;;;
|
||||
FCS20713;nn;FCS207 - nn;;;
|
||||
FCS20714;nn;FCS207 - nn;;;
|
||||
FCS20715;nn;FCS207 - nn;;;
|
||||
FCS20716;nn;FCS207 - nn;;;
|
||||
FCS20717;Netherlands;FCS207 - Netherlands;;;
|
||||
FCS20718;Belgium;FCS207 - Belgium;;;
|
||||
FCS20718;nn;FCS207 - nn;;;
|
||||
FCS20719;nn;FCS207 - nn;;;
|
||||
FCS20720;DACH;FCS207 - DACH;;;
|
||||
FCS20721;World-Wide;FCS207 - World-Wide;;;
|
||||
FCS20722;Italy;FCS207 - Italy;;;
|
||||
FCS20723;France;FCS207 - France;;;
|
||||
FCS20724;Spain;FCS207 - Spain;;;
|
||||
FCS20720;nn;FCS207 - nn;;;
|
||||
FCS20721;nn;FCS207 - nn;;;
|
||||
FCS20722;nn;FCS207 - nn;;;
|
||||
FCS20723;nn;FCS207 - nn;;;
|
||||
FCS20724;nn;FCS207 - nn;;;
|
||||
FCS20725;UK-2;FCS207 - UK-2;;;
|
||||
FCS20726;Romania;FCS207 - Romania;;;
|
||||
FCS20727;Portugal;FCS207 - Portugal;;;
|
||||
FCS20728;Switzerland;FCS207 - Switzerland;;;
|
||||
FCS20726;nn;FCS207 - nn;;;
|
||||
FCS20727;nn;FCS207 - nn;;;
|
||||
FCS20728;nn;FCS207 - nn;;;
|
||||
FCS20729;nn;FCS207 - nn;;;
|
||||
FCS20730;nn;FCS207 - nn;;;
|
||||
FCS20731;North-America;FCS207 - North-America;;;
|
||||
FCS20732;Austria;FCS207 - Austria;;;
|
||||
FCS20731;nn;FCS207 - nn;;;
|
||||
FCS20732;nn;FCS207 - nn;;;
|
||||
FCS20733;nn;FCS207 - nn;;;
|
||||
FCS20734;Mexico;FCS207 - Mexico;;;
|
||||
FCS20734;nn;FCS207 - nn;;;
|
||||
FCS20735;United Kingdom;FCS207 - United Kingdom;;;
|
||||
FCS20736;nn;FCS207 - nn;;;
|
||||
FCS20737;nn;FCS207 - nn;;;
|
||||
|
@ -660,10 +660,10 @@ FCS20755;nn;FCS207 - nn;;;
|
|||
FCS20756;nn;FCS207 - nn;;;
|
||||
FCS20757;nn;FCS207 - nn;;;
|
||||
FCS20758;nn;FCS207 - nn;;;
|
||||
FCS20759;Moldova;FCS207 - Moldova;;;
|
||||
FCS20760;Poland;FCS207 - Poland;;;
|
||||
FCS20759;nn;FCS207 - nn;;;
|
||||
FCS20760;nn;FCS207 - nn;;;
|
||||
FCS20761;nn;FCS207 - nn;;;
|
||||
FCS20762;Germany;FCS207 - Germany;;;
|
||||
FCS20762;nn;FCS207 - nn;;;
|
||||
FCS20763;nn;FCS207 - nn;;;
|
||||
FCS20764;nn;FCS207 - nn;;;
|
||||
FCS20765;nn;FCS207 - nn;;;
|
||||
|
@ -671,9 +671,9 @@ FCS20766;nn;FCS207 - nn;;;
|
|||
FCS20767;nn;FCS207 - nn;;;
|
||||
FCS20768;nn;FCS207 - nn;;;
|
||||
FCS20769;nn;FCS207 - nn;;;
|
||||
FCS20770;nn;FCS207 - nn;;;
|
||||
FCS20771;nn;FCS207 - nn;;;
|
||||
FCS20772;Brazil;FCS207 - Brazil;;;
|
||||
FCS20770;Theekransje;FCS207 - Theekransje;;;
|
||||
FCS20771;Rookkamer;FCS207 - Rookkamer;;;
|
||||
FCS20772;Techniek;FCS207 - Techniek;;;
|
||||
FCS20773;nn;FCS207 - nn;;;
|
||||
FCS20774;nn;FCS207 - nn;;;
|
||||
FCS20775;nn;FCS207 - nn;;;
|
||||
|
@ -681,26 +681,26 @@ FCS20776;nn;FCS207 - nn;;;
|
|||
FCS20777;nn;FCS207 - nn;;;
|
||||
FCS20778;nn;FCS207 - nn;;;
|
||||
FCS20779;nn;FCS207 - nn;;;
|
||||
FCS20780;REG0;FCS207 - REG0;;;
|
||||
FCS20781;REG1;FCS207 - REG1;;;
|
||||
FCS20782;REG2;FCS207 - REG2;;;
|
||||
FCS20783;REG3;FCS207 - REG3;;;
|
||||
FCS20784;REG4;FCS207 - REG4;;;
|
||||
FCS20785;REG5;FCS207 - REG5;;;
|
||||
FCS20786;REG6;FCS207 - REG6;;;
|
||||
FCS20787;REG7;FCS207 - REG7;;;
|
||||
FCS20788;REG8;FCS207 - REG8;;;
|
||||
FCS20789;REG9;FCS207 - REG9;;;
|
||||
FCS20780;Groepsgesprekken;FCS207 - Groepsgesprekken;;;
|
||||
FCS20781;nn;FCS207 - nn;;;
|
||||
FCS20782;Groepsgesprekken;FCS207 - Groepsgesprekken;;;
|
||||
FCS20783;nn;FCS207 - nn;;;
|
||||
FCS20784;nn;FCS207 - nn;;;
|
||||
FCS20785;nn;FCS207 - nn;;;
|
||||
FCS20786;nn;FCS207 - nn;;;
|
||||
FCS20787;nn;FCS207 - nn;;;
|
||||
FCS20788;nn;FCS207 - nn;;;
|
||||
FCS20789;nn;FCS207 - nn;;;
|
||||
FCS20790;CLEAR DG-ID;FCS207 - CLEAR DG-ID;;;
|
||||
FCS20791;Test-1;FCS207 - Test-1;;;
|
||||
FCS20792;Test-2;FCS207 - Test-2;;;
|
||||
FCS20793;Test-3;FCS207 - Test-3;;;
|
||||
FCS20794;Test-4;FCS207 - Test-4;;;
|
||||
FCS20795;Test-5;FCS207 - Test-5;;;
|
||||
FCS20796;Test-6;FCS207 - Test-6;;;
|
||||
FCS20797;Test-7;FCS207 - Test-7;;;
|
||||
FCS20798;Test-8;FCS207 - Test-8;;;
|
||||
FCS20799;Test-9;FCS207 - Test-9;;;
|
||||
FCS20791;nn;FCS207 - nn;;;
|
||||
FCS20792;nn;FCS207 - nn;;;
|
||||
FCS20793;nn;FCS207 - nn;;;
|
||||
FCS20794;nn;FCS207 - nn;;;
|
||||
FCS20795;nn;FCS207 - nn;;;
|
||||
FCS20796;nn;FCS207 - nn;;;
|
||||
FCS20797;nn;FCS207 - nn;;;
|
||||
FCS20798;nn;FCS207 - nn;;;
|
||||
FCS20799;Testomgeving;FCS207 - Testomgeving;;;
|
||||
FCS20800;nn;FCS208 - nn;;;
|
||||
FCS20801;DR-2X;FCS208 - DR-2X;;;
|
||||
FCS20802;Europe;FCS208 - Europe;;;
|
||||
|
@ -728,7 +728,7 @@ FCS20823;France;FCS208 - France;;;
|
|||
FCS20824;Spain;FCS208 - Spain;;;
|
||||
FCS20825;nn;FCS208 - nn;;;
|
||||
FCS20826;Romania;FCS208 - Romania;;;
|
||||
FCS20827;Portugal;FCS208 - Portugal;;;
|
||||
FCS20827;nn;FCS208 - nn;;;
|
||||
FCS20828;Switzerland;FCS208 - Switzerland;;;
|
||||
FCS20829;nn;FCS208 - nn;;;
|
||||
FCS20830;nn;FCS208 - nn;;;
|
||||
|
@ -760,8 +760,8 @@ FCS20855;nn;FCS208 - nn;;;
|
|||
FCS20856;nn;FCS208 - nn;;;
|
||||
FCS20857;nn;FCS208 - nn;;;
|
||||
FCS20858;nn;FCS208 - nn;;;
|
||||
FCS20859;Moldova;FCS208 - Moldova;;;
|
||||
FCS20860;Poland;FCS208 - Poland;;;
|
||||
FCS20859;nn;FCS208 - nn;;;
|
||||
FCS20860;nn;FCS208 - nn;;;
|
||||
FCS20861;nn;FCS208 - nn;;;
|
||||
FCS20862;Germany;FCS208 - Germany;;;
|
||||
FCS20863;nn;FCS208 - nn;;;
|
||||
|
@ -795,12 +795,12 @@ FCS20890;CLEAR DG-ID;FCS208 - CLEAR DG-ID;;;
|
|||
FCS20891;Alsace;FCS208 - Alsace;;;
|
||||
FCS20892;Bourgogne-Franche-Comte;FCS208 - Bourgogne-Franche-Comte;;;
|
||||
FCS20893;Loire-Atlantique;FCS208 - Loire-Atlantique;;;
|
||||
FCS20894;Test-4;FCS208 - Test-4;;;
|
||||
FCS20895;Test-5;FCS208 - Test-5;;;
|
||||
FCS20896;Test-6;FCS208 - Test-6;;;
|
||||
FCS20897;Test-7;FCS208 - Test-7;;;
|
||||
FCS20898;Test-8;FCS208 - Test-8;;;
|
||||
FCS20899;Test-9;FCS208 - Test-9;;;
|
||||
FCS20894;YSF-France;FCS208 - YSF-France;;;
|
||||
FCS20895;Urgence France;FCS208 - Urgence France;;;
|
||||
FCS20896;Mayenne-France;FCS208 - Mayenne-France;;;
|
||||
FCS20897;nn;FCS208 - nn;;;
|
||||
FCS20898;Belgique Francophone;FCS208 - Belgique Francophone;;;
|
||||
FCS20899;nn;FCS208 - nn;;;
|
||||
FCS22200;nn;FCS222 - nn;;;
|
||||
FCS22201;nn;FCS222 - nn;;;
|
||||
FCS22202;nn;FCS222 - nn;;;
|
||||
|
@ -817,32 +817,32 @@ FCS22212;nn;FCS222 - nn;;;
|
|||
FCS22213;nn;FCS222 - nn;;;
|
||||
FCS22214;nn;FCS222 - nn;;;
|
||||
FCS22215;nn;FCS222 - nn;;;
|
||||
FCS22216;nn;FCS222 - nn;;;
|
||||
FCS22216;IT-WW;FCS222 - IT-WW;;;
|
||||
FCS22217;Netherlands;FCS222 - Netherlands;;;
|
||||
FCS22218;Belgium;FCS222 - Belgium;;;
|
||||
FCS22218;nn;FCS222 - nn;;;
|
||||
FCS22219;nn;FCS222 - nn;;;
|
||||
FCS22220;D-A-CH;FCS222 - D-A-CH;;;
|
||||
FCS22221;World-Wide;FCS222 - World-Wide;;;
|
||||
FCS22222;Italy-MultiIP;FCS222 - Italy-MultiIP;;;
|
||||
FCS22223;France;FCS222 - France;;;
|
||||
FCS22223;nn;FCS222 - nn;;;
|
||||
FCS22224;Spain;FCS222 - Spain;;;
|
||||
FCS22225;nn;FCS222 - nn;;;
|
||||
FCS22226;Romania;FCS222 - Romania;;;
|
||||
FCS22227;Portugal;FCS222 - Portugal;;;
|
||||
FCS22227;nn;FCS222 - nn;;;
|
||||
FCS22228;Switzerland;FCS222 - Switzerland;;;
|
||||
FCS22229;nn;FCS222 - nn;;;
|
||||
FCS22230;LAZIO;FCS222 - LAZIO;;;
|
||||
FCS22231;nn;FCS222 - nn;;;
|
||||
FCS22230;MP-LAZIO;FCS222 - MP-LAZIO;;;
|
||||
FCS22231;MP-Sardegna;FCS222 - MP-Sardegna;;;
|
||||
FCS22232;Austria;FCS222 - Austria;;;
|
||||
FCS22233;nn;FCS222 - nn;;;
|
||||
FCS22234;Mexico;FCS222 - Mexico;;;
|
||||
FCS22235;United Kingdom;FCS222 - United Kingdom;;;
|
||||
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;MULTIP-TOS;FCS222 - MULTIP-TOS;;;
|
||||
FCS22240;MP-Romagna;FCS222 - MP-Romagna;;;
|
||||
FCS22241;MP-Toscana;FCS222 - MP-Toscana;;;
|
||||
FCS22242;nn;FCS222 - nn;;;
|
||||
FCS22243;nn;FCS222 - nn;;;
|
||||
FCS22244;nn;FCS222 - nn;;;
|
||||
|
@ -889,7 +889,7 @@ FCS22284;Test-4;FCS222 - Test-4;;;
|
|||
FCS22285;Test-5;FCS222 - Test-5;;;
|
||||
FCS22286;Test-6;FCS222 - Test-6;;;
|
||||
FCS22287;Test-7;FCS222 - Test-7;;;
|
||||
FCS22288;Cluster-GRF;FCS222 - Cluster-GRF;;;
|
||||
FCS22288;Test-8;FCS222 - Test-8;;;
|
||||
FCS22289;Test-9;FCS222 - Test-9;;;
|
||||
FCS22290;CLEAR DG-ID;FCS222 - CLEAR DG-ID;;;
|
||||
FCS22291;nn;FCS222 - nn;;;
|
||||
|
@ -910,7 +910,7 @@ FCS22405;Oceania;FCS224 - Oceania;;;
|
|||
FCS22406;Africa;FCS224 - Africa;;;
|
||||
FCS22407;South-America;FCS224 - South-America;;;
|
||||
FCS22408;nn;FCS224 - nn;;;
|
||||
FCS22409;nn;FCS224 - nn;;;
|
||||
FCS22409;C4FM-Link;FCS224 - C4FM-Link;;;
|
||||
FCS22410;WW-german;FCS224 - WW-german;;;
|
||||
FCS22411;WW-french;FCS224 - WW-french;;;
|
||||
FCS22412;WW-dutch/flemish;FCS224 - WW-dutch/flemish;;;
|
||||
|
@ -918,7 +918,7 @@ FCS22413;WW-english;FCS224 - WW-english;;;
|
|||
FCS22414;WW-spanish;FCS224 - WW-spanish;;;
|
||||
FCS22415;WW-portuguese;FCS224 - WW-portuguese;;;
|
||||
FCS22416;WW-italian;FCS224 - WW-italian;;;
|
||||
FCS22417;Netherlands;FCS224 - Netherlands;;;
|
||||
FCS22417;nn;FCS224 - nn;;;
|
||||
FCS22418;RC-VELETA;FCS224 - RC-VELETA;;;
|
||||
FCS22419;nn;FCS224 - nn;;;
|
||||
FCS22420;D-A-CH;FCS224 - D-A-CH;;;
|
||||
|
@ -928,7 +928,7 @@ FCS22423;France;FCS224 - France;;;
|
|||
FCS22424;C4FM-Link;FCS224 - C4FM-Link;;;
|
||||
FCS22425;CQ-UK-2;FCS224 - CQ-UK-2;;;
|
||||
FCS22426;Romania;FCS224 - Romania;;;
|
||||
FCS22427;Portugal;FCS224 - Portugal;;;
|
||||
FCS22427;nn;FCS224 - nn;;;
|
||||
FCS22428;Switzerland;FCS224 - Switzerland;;;
|
||||
FCS22429;nn;FCS224 - nn;;;
|
||||
FCS22430;SKYNET;FCS224 - SKYNET;;;
|
||||
|
@ -951,7 +951,7 @@ FCS22446;nn;FCS224 - nn;;;
|
|||
FCS22447;nn;FCS224 - nn;;;
|
||||
FCS22448;URG-LINK;FCS224 - URG-LINK;;;
|
||||
FCS22449;nn;FCS224 - nn;;;
|
||||
FCS22450;nn;FCS224 - nn;;;
|
||||
FCS22450;Andalucia;FCS224 - Andalucia;;;
|
||||
FCS22451;nn;FCS224 - nn;;;
|
||||
FCS22452;Miami;FCS224 - Miami;;;
|
||||
FCS22453;nn;FCS224 - nn;;;
|
||||
|
@ -973,7 +973,7 @@ FCS22468;CANARIAS;FCS224 - CANARIAS;;;
|
|||
FCS22469;nn;FCS224 - nn;;;
|
||||
FCS22470;DR2X-DMR;FCS224 - DR2X-DMR;;;
|
||||
FCS22471;EA-Distrito-1;FCS224 - EA-Distrito-1;;;
|
||||
FCS22472;EA-Distrito-2;FCS224 - EA-Distrito-2;;;
|
||||
FCS22472;Brazil;FCS224 - Brazil;;;
|
||||
FCS22473;EA-Distrito-3;FCS224 - EA-Distrito-3;;;
|
||||
FCS22474;EA-Distrito-4;FCS224 - EA-Distrito-4;;;
|
||||
FCS22475;EA-Distrito-5;FCS224 - EA-Distrito-5;;;
|
||||
|
@ -995,7 +995,7 @@ FCS22490;Clear-DG-ID;FCS224 - Clear-DG-ID;;;
|
|||
FCS22491;nn;FCS224 - nn;;;
|
||||
FCS22492;nn;FCS224 - nn;;;
|
||||
FCS22493;nn;FCS224 - nn;;;
|
||||
FCS22494;nn;FCS224 - nn;;;
|
||||
FCS22494;RC-Zaria;FCS224 - RC-Zaria;;;
|
||||
FCS22495;LATINOS;FCS224 - LATINOS;;;
|
||||
FCS22496;EA7URF;FCS224 - EA7URF;;;
|
||||
FCS22497;Emergencias;FCS224 - Emergencias;;;
|
||||
|
@ -1019,16 +1019,16 @@ FCS22614;WW-spanish;FCS226 - WW-spanish;;;
|
|||
FCS22615;WW-portuguese;FCS226 - WW-portuguese;;;
|
||||
FCS22616;WW-italian;FCS226 - WW-italian;;;
|
||||
FCS22617;Netherlands;FCS226 - Netherlands;;;
|
||||
FCS22618;Belgium;FCS226 - Belgium;;;
|
||||
FCS22618;nn;FCS226 - nn;;;
|
||||
FCS22619;nn;FCS226 - nn;;;
|
||||
FCS22620;DACH;FCS226 - DACH;;;
|
||||
FCS22621;World-Wide;FCS226 - World-Wide;;;
|
||||
FCS22622;Italy;FCS226 - Italy;;;
|
||||
FCS22623;France;FCS226 - France;;;
|
||||
FCS22623;nn;FCS226 - nn;;;
|
||||
FCS22624;Spain;FCS226 - Spain;;;
|
||||
FCS22625;nn;FCS226 - nn;;;
|
||||
FCS22626;Romania;FCS226 - Romania;;;
|
||||
FCS22627;Portugal;FCS226 - Portugal;;;
|
||||
FCS22627;nn;FCS226 - nn;;;
|
||||
FCS22628;Switzerland;FCS226 - Switzerland;;;
|
||||
FCS22629;nn;FCS226 - nn;;;
|
||||
FCS22630;nn;FCS226 - nn;;;
|
||||
|
@ -1036,7 +1036,7 @@ FCS22631;North-America;FCS226 - North-America;;;
|
|||
FCS22632;Austria;FCS226 - Austria;;;
|
||||
FCS22633;nn;FCS226 - nn;;;
|
||||
FCS22634;Mexico;FCS226 - Mexico;;;
|
||||
FCS22635;United Kingdom;FCS226 - United Kingdom;;;
|
||||
FCS22635;nn;FCS226 - nn;;;
|
||||
FCS22636;nn;FCS226 - nn;;;
|
||||
FCS22637;nn;FCS226 - nn;;;
|
||||
FCS22638;nn;FCS226 - nn;;;
|
||||
|
@ -1071,26 +1071,26 @@ FCS22666;nn;FCS226 - nn;;;
|
|||
FCS22667;nn;FCS226 - nn;;;
|
||||
FCS22668;nn;FCS226 - nn;;;
|
||||
FCS22669;nn;FCS226 - nn;;;
|
||||
FCS22670;Romania;FCS226 - Romania;;;
|
||||
FCS22671;Romania;FCS226 - Romania;;;
|
||||
FCS22672;Romania;FCS226 - Romania;;;
|
||||
FCS22673;Romania;FCS226 - Romania;;;
|
||||
FCS22674;Romania;FCS226 - Romania;;;
|
||||
FCS22675;Romania;FCS226 - Romania;;;
|
||||
FCS22676;Romania;FCS226 - Romania;;;
|
||||
FCS22677;Romania;FCS226 - Romania;;;
|
||||
FCS22678;Romania;FCS226 - Romania;;;
|
||||
FCS22679;Romania;FCS226 - Romania;;;
|
||||
FCS22680;Romania;FCS226 - Romania;;;
|
||||
FCS22681;Romania;FCS226 - Romania;;;
|
||||
FCS22682;Romania;FCS226 - Romania;;;
|
||||
FCS22683;Romania;FCS226 - Romania;;;
|
||||
FCS22684;Romania;FCS226 - Romania;;;
|
||||
FCS22685;Romania;FCS226 - Romania;;;
|
||||
FCS22686;Romania;FCS226 - Romania;;;
|
||||
FCS22687;Romania;FCS226 - Romania;;;
|
||||
FCS22688;Romania;FCS226 - Romania;;;
|
||||
FCS22689;Romania;FCS226 - Romania;;;
|
||||
FCS22670;all-local;FCS226 - all-local;;;
|
||||
FCS22671;RVSU;FCS226 - RVSU;;;
|
||||
FCS22672;Banat;FCS226 - Banat;;;
|
||||
FCS22673;Bucovina;FCS226 - Bucovina;;;
|
||||
FCS22674;Crisana;FCS226 - Crisana;;;
|
||||
FCS22675;Dobrogea;FCS226 - Dobrogea;;;
|
||||
FCS22676;Maramures;FCS226 - Maramures;;;
|
||||
FCS22677;Moldova;FCS226 - Moldova;;;
|
||||
FCS22678;Muntenia;FCS226 - Muntenia;;;
|
||||
FCS22679;Transilvania;FCS226 - Transilvania;;;
|
||||
FCS22680;nn;FCS226 - nn;;;
|
||||
FCS22681;Test;FCS226 - Test;;;
|
||||
FCS22682;YO2;FCS226 - YO2;;;
|
||||
FCS22683;YO3;FCS226 - YO3;;;
|
||||
FCS22684;YO4;FCS226 - YO4;;;
|
||||
FCS22685;YO5;FCS226 - YO5;;;
|
||||
FCS22686;YO6;FCS226 - YO6;;;
|
||||
FCS22687;YO7;FCS226 - YO7;;;
|
||||
FCS22688;YO8;FCS226 - YO8;;;
|
||||
FCS22689;Test;FCS226 - Test;;;
|
||||
FCS22690;CLEAR-DG-ID;FCS226 - CLEAR-DG-ID;;;
|
||||
FCS22691;Test-1;FCS226 - Test-1;;;
|
||||
FCS22692;Test-2;FCS226 - Test-2;;;
|
||||
|
@ -1319,16 +1319,16 @@ FCS25914;WW-spanish;FCS259 - WW-spanish;;;
|
|||
FCS25915;WW-portuguese;FCS259 - WW-portuguese;;;
|
||||
FCS25916;WW-italian;FCS259 - WW-italian;;;
|
||||
FCS25917;Netherlands;FCS259 - Netherlands;;;
|
||||
FCS25918;Belgium;FCS259 - Belgium;;;
|
||||
FCS25918;nn;FCS259 - nn;;;
|
||||
FCS25919;nn;FCS259 - nn;;;
|
||||
FCS25920;DACH;FCS259 - DACH;;;
|
||||
FCS25921;World-Wide;FCS259 - World-Wide;;;
|
||||
FCS25922;Italy;FCS259 - Italy;;;
|
||||
FCS25923;France;FCS259 - France;;;
|
||||
FCS25923;nn;FCS259 - nn;;;
|
||||
FCS25924;Spain;FCS259 - Spain;;;
|
||||
FCS25925;nn;FCS259 - nn;;;
|
||||
FCS25926;Romania;FCS259 - Romania;;;
|
||||
FCS25927;Portugal;FCS259 - Portugal;;;
|
||||
FCS25927;nn;FCS259 - nn;;;
|
||||
FCS25928;Switzerland;FCS259 - Switzerland;;;
|
||||
FCS25929;nn;FCS259 - nn;;;
|
||||
FCS25930;nn;FCS259 - nn;;;
|
||||
|
@ -1336,7 +1336,7 @@ FCS25931;North-America;FCS259 - North-America;;;
|
|||
FCS25932;Austria;FCS259 - Austria;;;
|
||||
FCS25933;nn;FCS259 - nn;;;
|
||||
FCS25934;Mexico;FCS259 - Mexico;;;
|
||||
FCS25935;United Kingdom;FCS259 - United Kingdom;;;
|
||||
FCS25935;nn;FCS259 - nn;;;
|
||||
FCS25936;nn;FCS259 - nn;;;
|
||||
FCS25937;nn;FCS259 - nn;;;
|
||||
FCS25938;nn;FCS259 - nn;;;
|
||||
|
@ -1381,16 +1381,16 @@ FCS25976;nn;FCS259 - nn;;;
|
|||
FCS25977;nn;FCS259 - nn;;;
|
||||
FCS25978;nn;FCS259 - nn;;;
|
||||
FCS25979;nn;FCS259 - nn;;;
|
||||
FCS25980;REG0;FCS259 - REG0;;;
|
||||
FCS25981;REG1;FCS259 - REG1;;;
|
||||
FCS25982;REG2;FCS259 - REG2;;;
|
||||
FCS25983;REG3;FCS259 - REG3;;;
|
||||
FCS25984;REG4;FCS259 - REG4;;;
|
||||
FCS25985;REG5;FCS259 - REG5;;;
|
||||
FCS25986;REG6;FCS259 - REG6;;;
|
||||
FCS25987;REG7;FCS259 - REG7;;;
|
||||
FCS25988;REG8;FCS259 - REG8;;;
|
||||
FCS25989;REG9;FCS259 - REG9;;;
|
||||
FCS25980;nn;FCS259 - nn;;;
|
||||
FCS25981;ER1;FCS259 - ER1;;;
|
||||
FCS25982;ER2;FCS259 - ER2;;;
|
||||
FCS25983;ER3;FCS259 - ER3;;;
|
||||
FCS25984;ER4;FCS259 - ER4;;;
|
||||
FCS25985;ER5;FCS259 - ER5;;;
|
||||
FCS25986;nn;FCS259 - nn;;;
|
||||
FCS25987;nn;FCS259 - nn;;;
|
||||
FCS25988;nn;FCS259 - nn;;;
|
||||
FCS25989;nn;FCS259 - nn;;;
|
||||
FCS25990;CLEAR DG-ID;FCS259 - CLEAR DG-ID;;;
|
||||
FCS25991;Test-1;FCS259 - Test-1;;;
|
||||
FCS25992;Test-2;FCS259 - Test-2;;;
|
||||
|
@ -1401,7 +1401,7 @@ FCS25996;Test-6;FCS259 - Test-6;;;
|
|||
FCS25997;Test-7;FCS259 - Test-7;;;
|
||||
FCS25998;Test-8;FCS259 - Test-8;;;
|
||||
FCS25999;Test-9;FCS259 - Test-9;;;
|
||||
FCS26000;Polska;FCS260 - Polska;;;
|
||||
FCS26000;nn;FCS260 - nn;;;
|
||||
FCS26001;DR-2X;FCS260 - DR-2X;;;
|
||||
FCS26002;Europe;FCS260 - Europe;;;
|
||||
FCS26003;North-America;FCS260 - North-America;;;
|
||||
|
@ -1411,14 +1411,14 @@ FCS26006;Africa;FCS260 - Africa;;;
|
|||
FCS26007;South-America;FCS260 - South-America;;;
|
||||
FCS26008;nn;FCS260 - nn;;;
|
||||
FCS26009;nn;FCS260 - nn;;;
|
||||
FCS26010;WW-german;FCS260 - WW-german;;;
|
||||
FCS26011;WW-french;FCS260 - WW-french;;;
|
||||
FCS26012;WW-dutch/flemish;FCS260 - WW-dutch/flemish;;;
|
||||
FCS26013;WW-english;FCS260 - WW-english;;;
|
||||
FCS26014;WW-spanish;FCS260 - WW-spanish;;;
|
||||
FCS26015;WW-portuguese;FCS260 - WW-portuguese;;;
|
||||
FCS26016;WW-italian;FCS260 - WW-italian;;;
|
||||
FCS26017;Netherlands;FCS260 - Netherlands;;;
|
||||
FCS26010;nn;FCS260 - nn;;;
|
||||
FCS26011;nn;FCS260 - nn;;;
|
||||
FCS26012;nn;FCS260 - nn;;;
|
||||
FCS26013;nn;FCS260 - nn;;;
|
||||
FCS26014;nn;FCS260 - nn;;;
|
||||
FCS26015;nn;FCS260 - nn;;;
|
||||
FCS26016;nn;FCS260 - nn;;;
|
||||
FCS26017;nn;FCS260 - nn;;;
|
||||
FCS26018;Belgium;FCS260 - Belgium;;;
|
||||
FCS26019;nn;FCS260 - nn;;;
|
||||
FCS26020;DACH;FCS260 - DACH;;;
|
||||
|
@ -1428,14 +1428,14 @@ FCS26023;France;FCS260 - France;;;
|
|||
FCS26024;Spain;FCS260 - Spain;;;
|
||||
FCS26025;UK-2;FCS260 - UK-2;;;
|
||||
FCS26026;Romania;FCS260 - Romania;;;
|
||||
FCS26027;Portugal;FCS260 - Portugal;;;
|
||||
FCS26027;nn;FCS260 - nn;;;
|
||||
FCS26028;Switzerland;FCS260 - Switzerland;;;
|
||||
FCS26029;nn;FCS260 - nn;;;
|
||||
FCS26030;nn;FCS260 - nn;;;
|
||||
FCS26031;North-America;FCS260 - North-America;;;
|
||||
FCS26032;Austria;FCS260 - Austria;;;
|
||||
FCS26033;nn;FCS260 - nn;;;
|
||||
FCS26034;Mexico;FCS260 - Mexico;;;
|
||||
FCS26034;nn;FCS260 - nn;;;
|
||||
FCS26035;UK-1;FCS260 - UK-1;;;
|
||||
FCS26036;nn;FCS260 - nn;;;
|
||||
FCS26037;nn;FCS260 - nn;;;
|
||||
|
@ -1460,7 +1460,7 @@ FCS26055;nn;FCS260 - nn;;;
|
|||
FCS26056;nn;FCS260 - nn;;;
|
||||
FCS26057;nn;FCS260 - nn;;;
|
||||
FCS26058;nn;FCS260 - nn;;;
|
||||
FCS26059;Moldova;FCS260 - Moldova;;;
|
||||
FCS26059;nn;FCS260 - nn;;;
|
||||
FCS26060;Poland;FCS260 - Poland;;;
|
||||
FCS26061;nn;FCS260 - nn;;;
|
||||
FCS26062;Germany;FCS260 - Germany;;;
|
||||
|
@ -1481,7 +1481,7 @@ FCS26076;nn;FCS260 - nn;;;
|
|||
FCS26077;nn;FCS260 - nn;;;
|
||||
FCS26078;nn;FCS260 - nn;;;
|
||||
FCS26079;nn;FCS260 - nn;;;
|
||||
FCS26080;nn;FCS260 - nn;;;
|
||||
FCS26080;DMR+ Poland;FCS260 - DMR+ Poland;;;
|
||||
FCS26081;SP1;FCS260 - SP1;;;
|
||||
FCS26082;SP2;FCS260 - SP2;;;
|
||||
FCS26083;SP3;FCS260 - SP3;;;
|
||||
|
@ -1546,7 +1546,7 @@ FCS26241;nn;FCS262 - nn;;;
|
|||
FCS26242;nn;FCS262 - nn;;;
|
||||
FCS26243;nn;FCS262 - nn;;;
|
||||
FCS26244;nn;FCS262 - nn;;;
|
||||
FCS26245;nn;FCS262 - nn;;;
|
||||
FCS26245;Korea;FCS262 - Korea;;;
|
||||
FCS26246;nn;FCS262 - nn;;;
|
||||
FCS26247;nn;FCS262 - nn;;;
|
||||
FCS26248;nn;FCS262 - nn;;;
|
||||
|
@ -1611,29 +1611,29 @@ FCS26806;Africa;FCS268 - Africa;;;
|
|||
FCS26807;South-America;FCS268 - South-America;;;
|
||||
FCS26808;nn;FCS268 - nn;;;
|
||||
FCS26809;nn;FCS268 - nn;;;
|
||||
FCS26810;WW-german;FCS268 - WW-german;;;
|
||||
FCS26810;nn;FCS268 - nn;;;
|
||||
FCS26811;WW-french;FCS268 - WW-french;;;
|
||||
FCS26812;WW-dutch/flemish;FCS268 - WW-dutch/flemish;;;
|
||||
FCS26813;WW-english;FCS268 - WW-english;;;
|
||||
FCS26814;WW-spanish;FCS268 - WW-spanish;;;
|
||||
FCS26815;WW-portuguese;FCS268 - WW-portuguese;;;
|
||||
FCS26816;WW-italian;FCS268 - WW-italian;;;
|
||||
FCS26817;Netherlands;FCS268 - Netherlands;;;
|
||||
FCS26818;Belgium;FCS268 - Belgium;;;
|
||||
FCS26816;nn;FCS268 - nn;;;
|
||||
FCS26817;nn;FCS268 - nn;;;
|
||||
FCS26818;nn;FCS268 - nn;;;
|
||||
FCS26819;nn;FCS268 - nn;;;
|
||||
FCS26820;DACH;FCS268 - DACH;;;
|
||||
FCS26820;nn;FCS268 - nn;;;
|
||||
FCS26821;World-Wide;FCS268 - World-Wide;;;
|
||||
FCS26822;Italy;FCS268 - Italy;;;
|
||||
FCS26823;France;FCS268 - France;;;
|
||||
FCS26824;Spain;FCS268 - Spain;;;
|
||||
FCS26825;nn;FCS268 - nn;;;
|
||||
FCS26826;Romania;FCS268 - Romania;;;
|
||||
FCS26826;nn;FCS268 - nn;;;
|
||||
FCS26827;Portugal;FCS268 - Portugal;;;
|
||||
FCS26828;Switzerland;FCS268 - Switzerland;;;
|
||||
FCS26828;nn;FCS268 - nn;;;
|
||||
FCS26829;nn;FCS268 - nn;;;
|
||||
FCS26830;nn;FCS268 - nn;;;
|
||||
FCS26830;Skynet;FCS268 - Skynet;;;
|
||||
FCS26831;North-America;FCS268 - North-America;;;
|
||||
FCS26832;Austria;FCS268 - Austria;;;
|
||||
FCS26832;nn;FCS268 - nn;;;
|
||||
FCS26833;nn;FCS268 - nn;;;
|
||||
FCS26834;Mexico;FCS268 - Mexico;;;
|
||||
FCS26835;United Kingdom;FCS268 - United Kingdom;;;
|
||||
|
@ -1660,10 +1660,10 @@ FCS26855;nn;FCS268 - nn;;;
|
|||
FCS26856;nn;FCS268 - nn;;;
|
||||
FCS26857;nn;FCS268 - nn;;;
|
||||
FCS26858;nn;FCS268 - nn;;;
|
||||
FCS26859;Moldova;FCS268 - Moldova;;;
|
||||
FCS26860;Poland;FCS268 - Poland;;;
|
||||
FCS26859;nn;FCS268 - nn;;;
|
||||
FCS26860;nn;FCS268 - nn;;;
|
||||
FCS26861;nn;FCS268 - nn;;;
|
||||
FCS26862;Germany;FCS268 - Germany;;;
|
||||
FCS26862;nn;FCS268 - nn;;;
|
||||
FCS26863;nn;FCS268 - nn;;;
|
||||
FCS26864;nn;FCS268 - nn;;;
|
||||
FCS26865;nn;FCS268 - nn;;;
|
||||
|
@ -1692,14 +1692,14 @@ FCS26887;REG7;FCS268 - REG7;;;
|
|||
FCS26888;REG8;FCS268 - REG8;;;
|
||||
FCS26889;REG9;FCS268 - REG9;;;
|
||||
FCS26890;CLEAR DG-ID;FCS268 - CLEAR DG-ID;;;
|
||||
FCS26891;Test-1;FCS268 - Test-1;;;
|
||||
FCS26892;Test-2;FCS268 - Test-2;;;
|
||||
FCS26893;Test-3;FCS268 - Test-3;;;
|
||||
FCS26894;Test-4;FCS268 - Test-4;;;
|
||||
FCS26895;Test-5;FCS268 - Test-5;;;
|
||||
FCS26896;Test-6;FCS268 - Test-6;;;
|
||||
FCS26897;Test-7;FCS268 - Test-7;;;
|
||||
FCS26898;Test-8;FCS268 - Test-8;;;
|
||||
FCS26891;YSF903;FCS268 - YSF903;;;
|
||||
FCS26892;YSF012;FCS268 - YSF012;;;
|
||||
FCS26893;YSF009;FCS268 - YSF009;;;
|
||||
FCS26894;YSF915;FCS268 - YSF915;;;
|
||||
FCS26895;YSF268;FCS268 - YSF268;;;
|
||||
FCS26896;nn;FCS268 - nn;;;
|
||||
FCS26897;nn;FCS268 - nn;;;
|
||||
FCS26898;Brasil-AMRASE;FCS268 - Brasil-AMRASE;;;
|
||||
FCS26899;Test-9;FCS268 - Test-9;;;
|
||||
FCS31000;nn;FCS310 - nn;;;
|
||||
FCS31001;DR-2X;FCS310 - DR-2X;;;
|
||||
|
@ -1737,11 +1737,11 @@ FCS31032;nn;FCS310 - nn;;;
|
|||
FCS31033;East-Hub USA;FCS310 - East-Hub USA;;;
|
||||
FCS31034;West-Hub USA;FCS310 - West-Hub USA;;;
|
||||
FCS31035;WM-Connect;FCS310 - WM-Connect;;;
|
||||
FCS31036;nn;FCS310 - nn;;;
|
||||
FCS31037;nn;FCS310 - nn;;;
|
||||
FCS31038;nn;FCS310 - nn;;;
|
||||
FCS31039;nn;FCS310 - nn;;;
|
||||
FCS31040;nn;FCS310 - nn;;;
|
||||
FCS31036;SE-Link;FCS310 - SE-Link;;;
|
||||
FCS31037;America-Link-USA;FCS310 - America-Link-USA;;;
|
||||
FCS31038;RocketCity-AL;FCS310 - RocketCity-AL;;;
|
||||
FCS31039;Alabama-Link;FCS310 - Alabama-Link;;;
|
||||
FCS31040;FusionNet369;FCS310 - FusionNet369;;;
|
||||
FCS31041;nn;FCS310 - nn;;;
|
||||
FCS31042;nn;FCS310 - nn;;;
|
||||
FCS31043;nn;FCS310 - nn;;;
|
||||
|
@ -1801,6 +1801,106 @@ FCS31096;nn;FCS310 - nn;;;
|
|||
FCS31097;nn;FCS310 - nn;;;
|
||||
FCS31098;nn;FCS310 - nn;;;
|
||||
FCS31099;ECHO;FCS310 - ECHO;;;
|
||||
FCS31100;nn;FCS311 - nn;;;
|
||||
FCS31101;DR-2X;FCS311 - DR-2X;;;
|
||||
FCS31102;Europe;FCS311 - Europe;;;
|
||||
FCS31103;North-America;FCS311 - North-America;;;
|
||||
FCS31104;Asia;FCS311 - Asia;;;
|
||||
FCS31105;Oceania;FCS311 - Oceania;;;
|
||||
FCS31106;Africa;FCS311 - Africa;;;
|
||||
FCS31107;South-America;FCS311 - South-America;;;
|
||||
FCS31108;nn;FCS311 - nn;;;
|
||||
FCS31109;nn;FCS311 - nn;;;
|
||||
FCS31110;nn;FCS311 - nn;;;
|
||||
FCS31111;nn;FCS311 - nn;;;
|
||||
FCS31112;nn;FCS311 - nn;;;
|
||||
FCS31113;WW-english;FCS311 - WW-english;;;
|
||||
FCS31114;nn;FCS311 - nn;;;
|
||||
FCS31115;nn;FCS311 - nn;;;
|
||||
FCS31116;nn;FCS311 - nn;;;
|
||||
FCS31117;nn;FCS311 - nn;;;
|
||||
FCS31118;nn;FCS311 - nn;;;
|
||||
FCS31119;nn;FCS311 - nn;;;
|
||||
FCS31120;nn;FCS311 - nn;;;
|
||||
FCS31121;nn;FCS311 - nn;;;
|
||||
FCS31122;nn;FCS311 - nn;;;
|
||||
FCS31123;nn;FCS311 - nn;;;
|
||||
FCS31124;nn;FCS311 - nn;;;
|
||||
FCS31125;UK-2;FCS311 - UK-2;;;
|
||||
FCS31126;nn;FCS311 - nn;;;
|
||||
FCS31127;nn;FCS311 - nn;;;
|
||||
FCS31128;nn;FCS311 - nn;;;
|
||||
FCS31129;nn;FCS311 - nn;;;
|
||||
FCS31130;nn;FCS311 - nn;;;
|
||||
FCS31131;North-America;FCS311 - North-America;;;
|
||||
FCS31132;nn;FCS311 - nn;;;
|
||||
FCS31133;nn;FCS311 - nn;;;
|
||||
FCS31134;nn;FCS311 - nn;;;
|
||||
FCS31135;WM-Connect;FCS311 - WM-Connect;;;
|
||||
FCS31136;nn;FCS311 - nn;;;
|
||||
FCS31137;America-Link-USA;FCS311 - America-Link-USA;;;
|
||||
FCS31138;RocketCity-Link;FCS311 - RocketCity-Link;;;
|
||||
FCS31139;Alabama-Link;FCS311 - Alabama-Link;;;
|
||||
FCS31140;nn;FCS311 - nn;;;
|
||||
FCS31141;nn;FCS311 - nn;;;
|
||||
FCS31142;US-Georgia;FCS311 - US-Georgia;;;
|
||||
FCS31143;nn;FCS311 - nn;;;
|
||||
FCS31144;nn;FCS311 - nn;;;
|
||||
FCS31145;nn;FCS311 - nn;;;
|
||||
FCS31146;nn;FCS311 - nn;;;
|
||||
FCS31147;nn;FCS311 - nn;;;
|
||||
FCS31148;nn;FCS311 - nn;;;
|
||||
FCS31149;nn;FCS311 - nn;;;
|
||||
FCS31150;nn;FCS311 - nn;;;
|
||||
FCS31151;nn;FCS311 - nn;;;
|
||||
FCS31152;nn;FCS311 - nn;;;
|
||||
FCS31153;nn;FCS311 - nn;;;
|
||||
FCS31154;nn;FCS311 - nn;;;
|
||||
FCS31155;nn;FCS311 - nn;;;
|
||||
FCS31156;nn;FCS311 - nn;;;
|
||||
FCS31157;nn;FCS311 - nn;;;
|
||||
FCS31158;nn;FCS311 - nn;;;
|
||||
FCS31159;nn;FCS311 - nn;;;
|
||||
FCS31160;nn;FCS311 - nn;;;
|
||||
FCS31161;nn;FCS311 - nn;;;
|
||||
FCS31162;nn;FCS311 - nn;;;
|
||||
FCS31163;nn;FCS311 - nn;;;
|
||||
FCS31164;nn;FCS311 - nn;;;
|
||||
FCS31165;nn;FCS311 - nn;;;
|
||||
FCS31166;nn;FCS311 - nn;;;
|
||||
FCS31167;nn;FCS311 - nn;;;
|
||||
FCS31168;nn;FCS311 - nn;;;
|
||||
FCS31169;nn;FCS311 - nn;;;
|
||||
FCS31170;MNTRBO-TEST;FCS311 - MNTRBO-TEST;;;
|
||||
FCS31171;America-RagChew;FCS311 - America-RagChew;;;
|
||||
FCS31172;Amsat;FCS311 - Amsat;;;
|
||||
FCS31173;HUBNET;FCS311 - HUBNET;;;
|
||||
FCS31174;nn;FCS311 - nn;;;
|
||||
FCS31175;USA;FCS311 - USA;;;
|
||||
FCS31176;nn;FCS311 - nn;;;
|
||||
FCS31177;nn;FCS311 - nn;;;
|
||||
FCS31178;nn;FCS311 - nn;;;
|
||||
FCS31179;nn;FCS311 - nn;;;
|
||||
FCS31180;Rural-Minnesota;FCS311 - Rural-Minnesota;;;
|
||||
FCS31181;SARA-QRX-FCMG;FCS311 - SARA-QRX-FCMG;;;
|
||||
FCS31182;nn;FCS311 - nn;;;
|
||||
FCS31183;nn;FCS311 - nn;;;
|
||||
FCS31184;nn;FCS311 - nn;;;
|
||||
FCS31185;nn;FCS311 - nn;;;
|
||||
FCS31186;nn;FCS311 - nn;;;
|
||||
FCS31187;nn;FCS311 - nn;;;
|
||||
FCS31188;nn;FCS311 - nn;;;
|
||||
FCS31189;nn;FCS311 - nn;;;
|
||||
FCS31190;CLEAR DG-ID;FCS311 - CLEAR DG-ID;;;
|
||||
FCS31191;Test-1;FCS311 - Test-1;;;
|
||||
FCS31192;Test-2;FCS311 - Test-2;;;
|
||||
FCS31193;Test-3;FCS311 - Test-3;;;
|
||||
FCS31194;Test-4;FCS311 - Test-4;;;
|
||||
FCS31195;Test-5;FCS311 - Test-5;;;
|
||||
FCS31196;Test-6;FCS311 - Test-6;;;
|
||||
FCS31197;Test-7;FCS311 - Test-7;;;
|
||||
FCS31198;Test-8;FCS311 - Test-8;;;
|
||||
FCS31199;Test-9;FCS311 - Test-9;;;
|
||||
FCS33400;nn;FCS334 - nn;;;
|
||||
FCS33401;DR-2X;FCS334 - DR-2X;;;
|
||||
FCS33402;Europe;FCS334 - Europe;;;
|
||||
|
@ -1819,24 +1919,24 @@ FCS33414;WW-spanish;FCS334 - WW-spanish;;;
|
|||
FCS33415;WW-portuguese;FCS334 - WW-portuguese;;;
|
||||
FCS33416;WW-italian;FCS334 - WW-italian;;;
|
||||
FCS33417;Netherlands;FCS334 - Netherlands;;;
|
||||
FCS33418;Belgium;FCS334 - Belgium;;;
|
||||
FCS33418;nn;FCS334 - nn;;;
|
||||
FCS33419;nn;FCS334 - nn;;;
|
||||
FCS33420;DACH;FCS334 - DACH;;;
|
||||
FCS33421;World-Wide;FCS334 - World-Wide;;;
|
||||
FCS33422;Italy;FCS334 - Italy;;;
|
||||
FCS33423;France;FCS334 - France;;;
|
||||
FCS33423;nn;FCS334 - nn;;;
|
||||
FCS33424;Spain;FCS334 - Spain;;;
|
||||
FCS33425;nn;FCS334 - nn;;;
|
||||
FCS33426;Romania;FCS334 - Romania;;;
|
||||
FCS33427;Portugal;FCS334 - Portugal;;;
|
||||
FCS33427;nn;FCS334 - nn;;;
|
||||
FCS33428;Switzerland;FCS334 - Switzerland;;;
|
||||
FCS33429;nn;FCS334 - nn;;;
|
||||
FCS33430;nn;FCS334 - nn;;;
|
||||
FCS33430;Skynet;FCS334 - Skynet;;;
|
||||
FCS33431;North-America;FCS334 - North-America;;;
|
||||
FCS33432;Austria;FCS334 - Austria;;;
|
||||
FCS33433;nn;FCS334 - nn;;;
|
||||
FCS33434;Mexico;FCS334 - Mexico;;;
|
||||
FCS33435;United Kingdom;FCS334 - United Kingdom;;;
|
||||
FCS33435;CQ-UK;FCS334 - CQ-UK;;;
|
||||
FCS33436;nn;FCS334 - nn;;;
|
||||
FCS33437;nn;FCS334 - nn;;;
|
||||
FCS33438;nn;FCS334 - nn;;;
|
||||
|
@ -1860,8 +1960,8 @@ FCS33455;nn;FCS334 - nn;;;
|
|||
FCS33456;nn;FCS334 - nn;;;
|
||||
FCS33457;nn;FCS334 - nn;;;
|
||||
FCS33458;nn;FCS334 - nn;;;
|
||||
FCS33459;Moldova;FCS334 - Moldova;;;
|
||||
FCS33460;Poland;FCS334 - Poland;;;
|
||||
FCS33459;nn;FCS334 - nn;;;
|
||||
FCS33460;nn;FCS334 - nn;;;
|
||||
FCS33461;nn;FCS334 - nn;;;
|
||||
FCS33462;Germany;FCS334 - Germany;;;
|
||||
FCS33463;nn;FCS334 - nn;;;
|
||||
|
@ -1871,8 +1971,8 @@ FCS33466;nn;FCS334 - nn;;;
|
|||
FCS33467;nn;FCS334 - nn;;;
|
||||
FCS33468;nn;FCS334 - nn;;;
|
||||
FCS33469;nn;FCS334 - nn;;;
|
||||
FCS33470;nn;FCS334 - nn;;;
|
||||
FCS33471;nn;FCS334 - nn;;;
|
||||
FCS33470;Chih-Mexico;FCS334 - Chih-Mexico;;;
|
||||
FCS33471;Mexico;FCS334 - Mexico;;;
|
||||
FCS33472;nn;FCS334 - nn;;;
|
||||
FCS33473;nn;FCS334 - nn;;;
|
||||
FCS33474;nn;FCS334 - nn;;;
|
||||
|
@ -1901,6 +2001,106 @@ FCS33496;Test-6;FCS334 - Test-6;;;
|
|||
FCS33497;Test-7;FCS334 - Test-7;;;
|
||||
FCS33498;Test-8;FCS334 - Test-8;;;
|
||||
FCS33499;Test-9;FCS334 - Test-9;;;
|
||||
FCS45000;nn;FCS450 - nn;;;
|
||||
FCS45001;DR-2X;FCS450 - DR-2X;;;
|
||||
FCS45002;Europe;FCS450 - Europe;;;
|
||||
FCS45003;North-America;FCS450 - North-America;;;
|
||||
FCS45004;Asia;FCS450 - Asia;;;
|
||||
FCS45005;Oceania;FCS450 - Oceania;;;
|
||||
FCS45006;Africa;FCS450 - Africa;;;
|
||||
FCS45007;South-America;FCS450 - South-America;;;
|
||||
FCS45008;nn;FCS450 - nn;;;
|
||||
FCS45009;nn;FCS450 - nn;;;
|
||||
FCS45010;WW-german;FCS450 - WW-german;;;
|
||||
FCS45011;WW-french;FCS450 - WW-french;;;
|
||||
FCS45012;WW-dutch/flemish;FCS450 - WW-dutch/flemish;;;
|
||||
FCS45013;WW-english;FCS450 - WW-english;;;
|
||||
FCS45014;WW-spanish;FCS450 - WW-spanish;;;
|
||||
FCS45015;WW-portuguese;FCS450 - WW-portuguese;;;
|
||||
FCS45016;WW-italian;FCS450 - WW-italian;;;
|
||||
FCS45017;Netherlands;FCS450 - Netherlands;;;
|
||||
FCS45018;Belgium;FCS450 - Belgium;;;
|
||||
FCS45019;nn;FCS450 - nn;;;
|
||||
FCS45020;DACH;FCS450 - DACH;;;
|
||||
FCS45021;World-Wide;FCS450 - World-Wide;;;
|
||||
FCS45022;Italy;FCS450 - Italy;;;
|
||||
FCS45023;nn;FCS450 - nn;;;
|
||||
FCS45024;Spain;FCS450 - Spain;;;
|
||||
FCS45025;nn;FCS450 - nn;;;
|
||||
FCS45026;nn;FCS450 - nn;;;
|
||||
FCS45027;nn;FCS450 - nn;;;
|
||||
FCS45028;Switzerland;FCS450 - Switzerland;;;
|
||||
FCS45029;nn;FCS450 - nn;;;
|
||||
FCS45030;nn;FCS450 - nn;;;
|
||||
FCS45031;North-America;FCS450 - North-America;;;
|
||||
FCS45032;Austria;FCS450 - Austria;;;
|
||||
FCS45033;nn;FCS450 - nn;;;
|
||||
FCS45034;Mexico;FCS450 - Mexico;;;
|
||||
FCS45035;United Kingdom;FCS450 - United Kingdom;;;
|
||||
FCS45036;nn;FCS450 - nn;;;
|
||||
FCS45037;America-Link-USA;FCS450 - America-Link-USA;;;
|
||||
FCS45038;nn;FCS450 - nn;;;
|
||||
FCS45039;nn;FCS450 - nn;;;
|
||||
FCS45040;nn;FCS450 - nn;;;
|
||||
FCS45041;nn;FCS450 - nn;;;
|
||||
FCS45042;nn;FCS450 - nn;;;
|
||||
FCS45043;nn;FCS450 - nn;;;
|
||||
FCS45044;nn;FCS450 - nn;;;
|
||||
FCS45045;Korea;FCS450 - Korea;;;
|
||||
FCS45046;nn;FCS450 - nn;;;
|
||||
FCS45047;nn;FCS450 - nn;;;
|
||||
FCS45048;nn;FCS450 - nn;;;
|
||||
FCS45049;nn;FCS450 - nn;;;
|
||||
FCS45050;nn;FCS450 - nn;;;
|
||||
FCS45051;nn;FCS450 - nn;;;
|
||||
FCS45052;nn;FCS450 - nn;;;
|
||||
FCS45053;nn;FCS450 - nn;;;
|
||||
FCS45054;nn;FCS450 - nn;;;
|
||||
FCS45055;nn;FCS450 - nn;;;
|
||||
FCS45056;nn;FCS450 - nn;;;
|
||||
FCS45057;nn;FCS450 - nn;;;
|
||||
FCS45058;nn;FCS450 - nn;;;
|
||||
FCS45059;nn;FCS450 - nn;;;
|
||||
FCS45060;nn;FCS450 - nn;;;
|
||||
FCS45061;nn;FCS450 - nn;;;
|
||||
FCS45062;Germany;FCS450 - Germany;;;
|
||||
FCS45063;nn;FCS450 - nn;;;
|
||||
FCS45064;nn;FCS450 - nn;;;
|
||||
FCS45065;nn;FCS450 - nn;;;
|
||||
FCS45066;nn;FCS450 - nn;;;
|
||||
FCS45067;nn;FCS450 - nn;;;
|
||||
FCS45068;nn;FCS450 - nn;;;
|
||||
FCS45069;nn;FCS450 - nn;;;
|
||||
FCS45070;nn;FCS450 - nn;;;
|
||||
FCS45071;nn;FCS450 - nn;;;
|
||||
FCS45072;nn;FCS450 - nn;;;
|
||||
FCS45073;nn;FCS450 - nn;;;
|
||||
FCS45074;nn;FCS450 - nn;;;
|
||||
FCS45075;nn;FCS450 - nn;;;
|
||||
FCS45076;nn;FCS450 - nn;;;
|
||||
FCS45077;nn;FCS450 - nn;;;
|
||||
FCS45078;Alabama-Link;FCS450 - Alabama-Link;;;
|
||||
FCS45079;nn;FCS450 - nn;;;
|
||||
FCS45080;REG0;FCS450 - REG0;;;
|
||||
FCS45081;REG1;FCS450 - REG1;;;
|
||||
FCS45082;REG2;FCS450 - REG2;;;
|
||||
FCS45083;REG3;FCS450 - REG3;;;
|
||||
FCS45084;REG4;FCS450 - REG4;;;
|
||||
FCS45085;REG5;FCS450 - REG5;;;
|
||||
FCS45086;REG6;FCS450 - REG6;;;
|
||||
FCS45087;REG7;FCS450 - REG7;;;
|
||||
FCS45088;REG8;FCS450 - REG8;;;
|
||||
FCS45089;REG9;FCS450 - REG9;;;
|
||||
FCS45090;CLEAR DG-ID;FCS450 - CLEAR DG-ID;;;
|
||||
FCS45091;Test-1;FCS450 - Test-1;;;
|
||||
FCS45092;Test-2;FCS450 - Test-2;;;
|
||||
FCS45093;Test-3;FCS450 - Test-3;;;
|
||||
FCS45094;Test-4;FCS450 - Test-4;;;
|
||||
FCS45095;Test-5;FCS450 - Test-5;;;
|
||||
FCS45096;Test-6;FCS450 - Test-6;;;
|
||||
FCS45097;Test-7;FCS450 - Test-7;;;
|
||||
FCS45098;Test-8;FCS450 - Test-8;;;
|
||||
FCS45099;Test-9;FCS450 - Test-9;;;
|
||||
FCS53000;nn;FCS530 - nn;;;
|
||||
FCS53001;DR-2X;FCS530 - DR-2X;;;
|
||||
FCS53002;Europe;FCS530 - Europe;;;
|
||||
|
@ -1919,16 +2119,16 @@ FCS53014;WW-spanish;FCS530 - WW-spanish;;;
|
|||
FCS53015;WW-portuguese;FCS530 - WW-portuguese;;;
|
||||
FCS53016;WW-italian;FCS530 - WW-italian;;;
|
||||
FCS53017;Netherlands;FCS530 - Netherlands;;;
|
||||
FCS53018;Belgium;FCS530 - Belgium;;;
|
||||
FCS53018;nn;FCS530 - nn;;;
|
||||
FCS53019;nn;FCS530 - nn;;;
|
||||
FCS53020;DACH;FCS530 - DACH;;;
|
||||
FCS53021;World-Wide;FCS530 - World-Wide;;;
|
||||
FCS53022;Italy;FCS530 - Italy;;;
|
||||
FCS53023;France;FCS530 - France;;;
|
||||
FCS53023;nn;FCS530 - nn;;;
|
||||
FCS53024;Spain;FCS530 - Spain;;;
|
||||
FCS53025;UK-2;FCS530 - UK-2;;;
|
||||
FCS53026;Romania;FCS530 - Romania;;;
|
||||
FCS53027;Portugal;FCS530 - Portugal;;;
|
||||
FCS53027;nn;FCS530 - nn;;;
|
||||
FCS53028;Switzerland;FCS530 - Switzerland;;;
|
||||
FCS53029;nn;FCS530 - nn;;;
|
||||
FCS53030;nn;FCS530 - nn;;;
|
||||
|
@ -1936,9 +2136,9 @@ FCS53031;North-America;FCS530 - North-America;;;
|
|||
FCS53032;Austria;FCS530 - Austria;;;
|
||||
FCS53033;nn;FCS530 - nn;;;
|
||||
FCS53034;Mexico;FCS530 - Mexico;;;
|
||||
FCS53035;United Kingdom;FCS530 - United Kingdom;;;
|
||||
FCS53035;United-Kingdom-1;FCS530 - United-Kingdom-1;;;
|
||||
FCS53036;nn;FCS530 - nn;;;
|
||||
FCS53037;nn;FCS530 - nn;;;
|
||||
FCS53037;US-America-Link;FCS530 - US-America-Link;;;
|
||||
FCS53038;nn;FCS530 - nn;;;
|
||||
FCS53039;nn;FCS530 - nn;;;
|
||||
FCS53040;nn;FCS530 - nn;;;
|
||||
|
@ -1960,8 +2160,8 @@ FCS53055;nn;FCS530 - nn;;;
|
|||
FCS53056;nn;FCS530 - nn;;;
|
||||
FCS53057;nn;FCS530 - nn;;;
|
||||
FCS53058;nn;FCS530 - nn;;;
|
||||
FCS53059;Moldova;FCS530 - Moldova;;;
|
||||
FCS53060;Poland;FCS530 - Poland;;;
|
||||
FCS53059;nn;FCS530 - nn;;;
|
||||
FCS53060;nn;FCS530 - nn;;;
|
||||
FCS53061;nn;FCS530 - nn;;;
|
||||
FCS53062;Germany;FCS530 - Germany;;;
|
||||
FCS53063;nn;FCS530 - nn;;;
|
||||
|
@ -1973,24 +2173,24 @@ FCS53068;nn;FCS530 - nn;;;
|
|||
FCS53069;nn;FCS530 - nn;;;
|
||||
FCS53070;nn;FCS530 - nn;;;
|
||||
FCS53071;nn;FCS530 - nn;;;
|
||||
FCS53072;Brazil;FCS530 - Brazil;;;
|
||||
FCS53072;nn;FCS530 - nn;;;
|
||||
FCS53073;nn;FCS530 - nn;;;
|
||||
FCS53074;nn;FCS530 - nn;;;
|
||||
FCS53075;nn;FCS530 - nn;;;
|
||||
FCS53076;nn;FCS530 - nn;;;
|
||||
FCS53075;Bridge-UK-TG235;FCS530 - Bridge-UK-TG235;;;
|
||||
FCS53076;America-RC;FCS530 - America-RC;;;
|
||||
FCS53077;nn;FCS530 - nn;;;
|
||||
FCS53078;nn;FCS530 - nn;;;
|
||||
FCS53079;nn;FCS530 - nn;;;
|
||||
FCS53080;REG0;FCS530 - REG0;;;
|
||||
FCS53081;REG1;FCS530 - REG1;;;
|
||||
FCS53082;REG2;FCS530 - REG2;;;
|
||||
FCS53083;REG3;FCS530 - REG3;;;
|
||||
FCS53084;REG4;FCS530 - REG4;;;
|
||||
FCS53085;REG5;FCS530 - REG5;;;
|
||||
FCS53086;REG6;FCS530 - REG6;;;
|
||||
FCS53087;REG7;FCS530 - REG7;;;
|
||||
FCS53088;REG8;FCS530 - REG8;;;
|
||||
FCS53089;REG9;FCS530 - REG9;;;
|
||||
FCS53078;Alabama-Link;FCS530 - Alabama-Link;;;
|
||||
FCS53079;QuadNet-Array;FCS530 - QuadNet-Array;;;
|
||||
FCS53080;NZ-Canterbury-NZ;FCS530 - NZ-Canterbury-NZ;;;
|
||||
FCS53081;ZL-1;FCS530 - ZL-1;;;
|
||||
FCS53082;ZL-2;FCS530 - ZL-2;;;
|
||||
FCS53083;ZL-3;FCS530 - ZL-3;;;
|
||||
FCS53084;ZL-4;FCS530 - ZL-4;;;
|
||||
FCS53085;nn;FCS530 - nn;;;
|
||||
FCS53086;nn;FCS530 - nn;;;
|
||||
FCS53087;nn;FCS530 - nn;;;
|
||||
FCS53088;nn;FCS530 - nn;;;
|
||||
FCS53089;IPSC2 ZL;FCS530 - IPSC2 ZL;;;
|
||||
FCS53090;CLEAR DG-ID;FCS530 - CLEAR DG-ID;;;
|
||||
FCS53091;Test-1;FCS530 - Test-1;;;
|
||||
FCS53092;Test-2;FCS530 - Test-2;;;
|
||||
|
@ -2097,7 +2297,7 @@ FCS72492;Test-2;FCS724 - Test-2;;;
|
|||
FCS72493;Test-3;FCS724 - Test-3;;;
|
||||
FCS72494;Test-4;FCS724 - Test-4;;;
|
||||
FCS72495;Test-5;FCS724 - Test-5;;;
|
||||
FCS72496;Test-6;FCS724 - Test-6;;;
|
||||
FCS72496;Brazil;FCS724 - Brazil;;;
|
||||
FCS72497;Test-7;FCS724 - Test-7;;;
|
||||
FCS72498;Test-8;FCS724 - Test-8;;;
|
||||
FCS72499;Test-9;FCS724 - Test-9;;;
|
||||
|
|
|
@ -270,6 +270,9 @@ void CGPS::transmitGPS(const unsigned char* source)
|
|||
case 0x30U:
|
||||
::strcpy(radio, "FT-3D");
|
||||
break;
|
||||
case 0x33U:
|
||||
::strcpy(radio, "FT-5D");
|
||||
break;
|
||||
default:
|
||||
::sprintf(radio, "0x%02X", m_buffer[4U]);
|
||||
break;
|
||||
|
|
|
@ -161,7 +161,7 @@ void Log(unsigned int level, const char* fmt, ...)
|
|||
|
||||
struct tm* tm = ::gmtime(&now.tv_sec);
|
||||
|
||||
::sprintf(buffer, "%c: %04d-%02d-%02d %02d:%02d:%02d.%03ld ", 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 / 1000L);
|
||||
::sprintf(buffer, "%c: %04d-%02d-%02d %02d:%02d:%02d.%03lld ", 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 / 1000LL);
|
||||
#endif
|
||||
|
||||
va_list vl;
|
||||
|
|
|
@ -23,9 +23,22 @@ DGIdGateway: $(OBJECTS)
|
|||
%.o: %.cpp
|
||||
$(CXX) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
DGIdGateway.o: GitVersion.h FORCE
|
||||
|
||||
.PHONY: GitVersion.h
|
||||
|
||||
FORCE:
|
||||
|
||||
install:
|
||||
install -m 755 DGIdGateway /usr/local/bin/
|
||||
|
||||
clean:
|
||||
$(RM) DGIdGateway *.o *.d *.bak *~
|
||||
|
||||
$(RM) DGIdGateway *.o *.d *.bak *~ GitVersion.h
|
||||
|
||||
GitVersion.h:
|
||||
ifneq ("$(wildcard ../.git/index)","")
|
||||
echo "const char *gitversion = \"$(shell git rev-parse HEAD)\";" > $@
|
||||
else
|
||||
echo "const char *gitversion = \"0000000000000000000000000000000000000000\";" > $@
|
||||
endif
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2006-2016,2020,2024 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
|
||||
|
@ -28,34 +28,25 @@
|
|||
#if defined(HAVE_LOG_H)
|
||||
#include "Log.h"
|
||||
#else
|
||||
#define LogMessage(fmt, ...) ::fprintf(stderr, fmt "\n", ## __VA_ARGS__)
|
||||
#define LogError(fmt, ...) ::fprintf(stderr, fmt "\n", ## __VA_ARGS__)
|
||||
#define LogInfo(fmt, ...) ::fprintf(stderr, fmt "\n", ## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
CUDPSocket::CUDPSocket(const std::string& address, unsigned int port) :
|
||||
m_address_save(address),
|
||||
m_port_save(port),
|
||||
m_counter(0U)
|
||||
CUDPSocket::CUDPSocket(const std::string& address, unsigned short port) :
|
||||
m_localAddress(address),
|
||||
m_localPort(port),
|
||||
m_fd(-1),
|
||||
m_af(AF_UNSPEC)
|
||||
{
|
||||
for (int i = 0; i < UDP_SOCKET_MAX; i++) {
|
||||
m_address[i] = "";
|
||||
m_port[i] = 0U;
|
||||
m_af[i] = 0U;
|
||||
m_fd[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
CUDPSocket::CUDPSocket(unsigned int port) :
|
||||
m_address_save(),
|
||||
m_port_save(port),
|
||||
m_counter(0U)
|
||||
CUDPSocket::CUDPSocket(unsigned short port) :
|
||||
m_localAddress(),
|
||||
m_localPort(port),
|
||||
m_fd(-1),
|
||||
m_af(AF_UNSPEC)
|
||||
{
|
||||
for (int i = 0; i < UDP_SOCKET_MAX; i++) {
|
||||
m_address[i] = "";
|
||||
m_port[i] = 0U;
|
||||
m_af[i] = 0U;
|
||||
m_fd[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
CUDPSocket::~CUDPSocket()
|
||||
|
@ -79,7 +70,7 @@ void CUDPSocket::shutdown()
|
|||
#endif
|
||||
}
|
||||
|
||||
int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_storage& addr, unsigned int& address_length)
|
||||
int CUDPSocket::lookup(const std::string& hostname, unsigned short port, sockaddr_storage& addr, unsigned int& address_length)
|
||||
{
|
||||
struct addrinfo hints;
|
||||
::memset(&hints, 0, sizeof(hints));
|
||||
|
@ -87,15 +78,15 @@ int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_
|
|||
return lookup(hostname, port, addr, address_length, hints);
|
||||
}
|
||||
|
||||
int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_storage& addr, unsigned int& address_length, struct addrinfo& hints)
|
||||
int CUDPSocket::lookup(const std::string& hostname, unsigned short port, sockaddr_storage& addr, unsigned int& address_length, struct addrinfo& hints)
|
||||
{
|
||||
std::string portstr = std::to_string(port);
|
||||
struct addrinfo *res;
|
||||
|
||||
/* port is always digits, no needs to lookup service */
|
||||
/* Port is always digits, no needs to lookup service */
|
||||
hints.ai_flags |= AI_NUMERICSERV;
|
||||
|
||||
int err = getaddrinfo(hostname.empty() ? NULL : hostname.c_str(), portstr.c_str(), &hints, &res);
|
||||
int err = ::getaddrinfo(hostname.empty() ? NULL : hostname.c_str(), portstr.c_str(), &hints, &res);
|
||||
if (err != 0) {
|
||||
sockaddr_in* paddr = (sockaddr_in*)&addr;
|
||||
::memset(paddr, 0x00U, address_length = sizeof(sockaddr_in));
|
||||
|
@ -108,7 +99,7 @@ int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_
|
|||
|
||||
::memcpy(&addr, res->ai_addr, address_length = res->ai_addrlen);
|
||||
|
||||
freeaddrinfo(res);
|
||||
::freeaddrinfo(res);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -120,33 +111,33 @@ bool CUDPSocket::match(const sockaddr_storage& addr1, const sockaddr_storage& ad
|
|||
|
||||
if (type == IMT_ADDRESS_AND_PORT) {
|
||||
switch (addr1.ss_family) {
|
||||
case AF_INET:
|
||||
struct sockaddr_in *in_1, *in_2;
|
||||
in_1 = (struct sockaddr_in*)&addr1;
|
||||
in_2 = (struct sockaddr_in*)&addr2;
|
||||
return (in_1->sin_addr.s_addr == in_2->sin_addr.s_addr) && (in_1->sin_port == in_2->sin_port);
|
||||
case AF_INET6:
|
||||
struct sockaddr_in6 *in6_1, *in6_2;
|
||||
in6_1 = (struct sockaddr_in6*)&addr1;
|
||||
in6_2 = (struct sockaddr_in6*)&addr2;
|
||||
return IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr) && (in6_1->sin6_port == in6_2->sin6_port);
|
||||
default:
|
||||
return false;
|
||||
case AF_INET:
|
||||
struct sockaddr_in *in_1, *in_2;
|
||||
in_1 = (struct sockaddr_in*)&addr1;
|
||||
in_2 = (struct sockaddr_in*)&addr2;
|
||||
return (in_1->sin_addr.s_addr == in_2->sin_addr.s_addr) && (in_1->sin_port == in_2->sin_port);
|
||||
case AF_INET6:
|
||||
struct sockaddr_in6 *in6_1, *in6_2;
|
||||
in6_1 = (struct sockaddr_in6*)&addr1;
|
||||
in6_2 = (struct sockaddr_in6*)&addr2;
|
||||
return IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr) && (in6_1->sin6_port == in6_2->sin6_port);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else if (type == IMT_ADDRESS_ONLY) {
|
||||
switch (addr1.ss_family) {
|
||||
case AF_INET:
|
||||
struct sockaddr_in *in_1, *in_2;
|
||||
in_1 = (struct sockaddr_in*)&addr1;
|
||||
in_2 = (struct sockaddr_in*)&addr2;
|
||||
return in_1->sin_addr.s_addr == in_2->sin_addr.s_addr;
|
||||
case AF_INET6:
|
||||
struct sockaddr_in6 *in6_1, *in6_2;
|
||||
in6_1 = (struct sockaddr_in6*)&addr1;
|
||||
in6_2 = (struct sockaddr_in6*)&addr2;
|
||||
return IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr);
|
||||
default:
|
||||
return false;
|
||||
case AF_INET:
|
||||
struct sockaddr_in *in_1, *in_2;
|
||||
in_1 = (struct sockaddr_in*)&addr1;
|
||||
in_2 = (struct sockaddr_in*)&addr2;
|
||||
return in_1->sin_addr.s_addr == in_2->sin_addr.s_addr;
|
||||
case AF_INET6:
|
||||
struct sockaddr_in6 *in6_1, *in6_2;
|
||||
in6_1 = (struct sockaddr_in6*)&addr1;
|
||||
in6_2 = (struct sockaddr_in6*)&addr2;
|
||||
return IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
|
@ -162,33 +153,34 @@ bool CUDPSocket::isNone(const sockaddr_storage& addr)
|
|||
|
||||
bool CUDPSocket::open(const sockaddr_storage& address)
|
||||
{
|
||||
return open(address.ss_family);
|
||||
m_af = address.ss_family;
|
||||
|
||||
return open();
|
||||
}
|
||||
|
||||
bool CUDPSocket::open(unsigned int af)
|
||||
bool CUDPSocket::open()
|
||||
{
|
||||
return open(0, af, m_address_save, m_port_save);
|
||||
}
|
||||
assert(m_fd == -1);
|
||||
|
||||
bool CUDPSocket::open(const unsigned int index, const unsigned int af, const std::string& address, const unsigned int port)
|
||||
{
|
||||
sockaddr_storage addr;
|
||||
unsigned int addrlen;
|
||||
struct addrinfo hints;
|
||||
|
||||
::memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
hints.ai_family = af;
|
||||
hints.ai_family = m_af;
|
||||
|
||||
/* to determine protocol family, call lookup() first. */
|
||||
int err = lookup(address, port, addr, addrlen, hints);
|
||||
// To determine protocol family, call lookup() on the local address first.
|
||||
int err = lookup(m_localAddress, m_localPort, addr, addrlen, hints);
|
||||
if (err != 0) {
|
||||
LogError("The local address is invalid - %s", address.c_str());
|
||||
LogError("The local address is invalid - %s", m_localAddress.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
int fd = ::socket(addr.ss_family, SOCK_DGRAM, 0);
|
||||
if (fd < 0) {
|
||||
m_af = addr.ss_family;
|
||||
|
||||
m_fd = ::socket(m_af, SOCK_DGRAM, 0);
|
||||
if (m_fd < 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LogError("Cannot create the UDP socket, err: %lu", ::GetLastError());
|
||||
#else
|
||||
|
@ -197,62 +189,51 @@ bool CUDPSocket::open(const unsigned int index, const unsigned int af, const std
|
|||
return false;
|
||||
}
|
||||
|
||||
m_address[index] = address;
|
||||
m_port[index] = port;
|
||||
m_af[index] = addr.ss_family;
|
||||
m_fd[index] = fd;
|
||||
|
||||
if (port > 0U) {
|
||||
if (m_localPort > 0U) {
|
||||
int reuse = 1;
|
||||
if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(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
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (::bind(fd, (sockaddr*)&addr, addrlen) == -1) {
|
||||
if (::bind(m_fd, (sockaddr*)&addr, addrlen) == -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
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
LogInfo("Opening UDP port on %u", port);
|
||||
LogInfo("Opening UDP port on %hu", m_localPort);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storage& address, unsigned int &address_length)
|
||||
int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storage& address, unsigned int &addressLength)
|
||||
{
|
||||
assert(buffer != NULL);
|
||||
assert(length > 0U);
|
||||
assert(m_fd >= 0);
|
||||
|
||||
// Check that the readfrom() won't block
|
||||
int i, n;
|
||||
struct pollfd pfd[UDP_SOCKET_MAX];
|
||||
for (i = n = 0; i < UDP_SOCKET_MAX; i++) {
|
||||
if (m_fd[i] >= 0) {
|
||||
pfd[n].fd = m_fd[i];
|
||||
pfd[n].events = POLLIN;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
// no socket descriptor to receive
|
||||
if (n == 0)
|
||||
return 0;
|
||||
struct pollfd pfd;
|
||||
pfd.fd = m_fd;
|
||||
pfd.events = POLLIN;
|
||||
pfd.revents = 0;
|
||||
|
||||
// Return immediately
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
int ret = WSAPoll(pfd, n, 0);
|
||||
int ret = WSAPoll(&pfd, 1, 0);
|
||||
#else
|
||||
int ret = ::poll(pfd, n, 0);
|
||||
int ret = ::poll(&pfd, 1, 0);
|
||||
#endif
|
||||
if (ret < 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
@ -263,14 +244,7 @@ int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storag
|
|||
return -1;
|
||||
}
|
||||
|
||||
int index;
|
||||
for (i = 0; i < n; i++) {
|
||||
// round robin
|
||||
index = (i + m_counter) % n;
|
||||
if (pfd[index].revents & POLLIN)
|
||||
break;
|
||||
}
|
||||
if (i == n)
|
||||
if ((pfd.revents & POLLIN) == 0)
|
||||
return 0;
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
@ -280,9 +254,9 @@ int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storag
|
|||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
int len = ::recvfrom(pfd[index].fd, (char*)buffer, length, 0, (sockaddr *)&address, &size);
|
||||
int len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&address, &size);
|
||||
#else
|
||||
ssize_t len = ::recvfrom(pfd[index].fd, (char*)buffer, length, 0, (sockaddr *)&address, &size);
|
||||
ssize_t len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&address, &size);
|
||||
#endif
|
||||
if (len <= 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
@ -291,7 +265,7 @@ int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storag
|
|||
LogError("Error returned from recvfrom, err: %d", errno);
|
||||
|
||||
if (len == -1 && errno == ENOTSOCK) {
|
||||
LogMessage("Re-opening UDP port on %u", m_port);
|
||||
LogMessage("Re-opening UDP port on %hu", m_localPort);
|
||||
close();
|
||||
open();
|
||||
}
|
||||
|
@ -299,43 +273,39 @@ int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storag
|
|||
return -1;
|
||||
}
|
||||
|
||||
m_counter++;
|
||||
address_length = size;
|
||||
addressLength = size;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
bool CUDPSocket::write(const unsigned char* buffer, unsigned int length, const sockaddr_storage& address, unsigned int address_length)
|
||||
bool CUDPSocket::write(const unsigned char* buffer, unsigned int length, const sockaddr_storage& address, unsigned int addressLength)
|
||||
{
|
||||
assert(buffer != NULL);
|
||||
assert(length > 0U);
|
||||
assert(m_fd >= 0);
|
||||
|
||||
bool result = false;
|
||||
|
||||
for (int i = 0; i < UDP_SOCKET_MAX; i++) {
|
||||
if (m_fd[i] < 0 || m_af[i] != address.ss_family)
|
||||
continue;
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
int ret = ::sendto(m_fd[i], (char *)buffer, length, 0, (sockaddr *)&address, address_length);
|
||||
int ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&address, addressLength);
|
||||
#else
|
||||
ssize_t ret = ::sendto(m_fd[i], (char *)buffer, length, 0, (sockaddr *)&address, address_length);
|
||||
ssize_t ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&address, addressLength);
|
||||
#endif
|
||||
|
||||
if (ret < 0) {
|
||||
if (ret < 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LogError("Error returned from sendto, err: %lu", ::GetLastError());
|
||||
LogError("Error returned from sendto, err: %lu", ::GetLastError());
|
||||
#else
|
||||
LogError("Error returned from sendto, err: %d", errno);
|
||||
LogError("Error returned from sendto, err: %d", errno);
|
||||
#endif
|
||||
} else {
|
||||
} else {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
if (ret == int(length))
|
||||
result = true;
|
||||
if (ret == int(length))
|
||||
result = true;
|
||||
#else
|
||||
if (ret == ssize_t(length))
|
||||
result = true;
|
||||
if (ret == ssize_t(length))
|
||||
result = true;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -343,18 +313,13 @@ bool CUDPSocket::write(const unsigned char* buffer, unsigned int length, const s
|
|||
|
||||
void CUDPSocket::close()
|
||||
{
|
||||
for (int i = 0; i < UDP_SOCKET_MAX; i++)
|
||||
close(m_fd[i]);
|
||||
}
|
||||
|
||||
void CUDPSocket::close(const unsigned int index)
|
||||
{
|
||||
if (m_fd[index] >= 0) {
|
||||
if (m_fd >= 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
::closesocket(m_fd[index]);
|
||||
::closesocket(m_fd);
|
||||
#else
|
||||
::close(m_fd[index]);
|
||||
::close(m_fd);
|
||||
#endif
|
||||
m_fd[index] = -1;
|
||||
m_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2011,2013,2015,2016,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2011,2013,2015,2016,2020,2024 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
|
||||
|
@ -35,10 +35,6 @@
|
|||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
#if !defined(UDP_SOCKET_MAX)
|
||||
#define UDP_SOCKET_MAX 1
|
||||
#endif
|
||||
|
||||
enum IPMATCHTYPE {
|
||||
IMT_ADDRESS_AND_PORT,
|
||||
IMT_ADDRESS_ONLY
|
||||
|
@ -46,38 +42,38 @@ enum IPMATCHTYPE {
|
|||
|
||||
class CUDPSocket {
|
||||
public:
|
||||
CUDPSocket(const std::string& address, unsigned int port = 0U);
|
||||
CUDPSocket(unsigned int port = 0U);
|
||||
CUDPSocket(const std::string& address, unsigned short port = 0U);
|
||||
CUDPSocket(unsigned short port = 0U);
|
||||
~CUDPSocket();
|
||||
|
||||
bool open(unsigned int af = AF_UNSPEC);
|
||||
bool open();
|
||||
bool open(const sockaddr_storage& address);
|
||||
bool open(const unsigned int index, const unsigned int af, const std::string& address, const unsigned int port);
|
||||
|
||||
int read(unsigned char* buffer, unsigned int length, sockaddr_storage& address, unsigned int &address_length);
|
||||
bool write(const unsigned char* buffer, unsigned int length, const sockaddr_storage& address, unsigned int address_length);
|
||||
int read(unsigned char* buffer, unsigned int length, sockaddr_storage& address, unsigned int &addressLength);
|
||||
bool write(const unsigned char* buffer, unsigned int length, const sockaddr_storage& address, unsigned int addressLength);
|
||||
|
||||
void close();
|
||||
void close(const unsigned int index);
|
||||
|
||||
static void startup();
|
||||
static void shutdown();
|
||||
|
||||
static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage& address, unsigned int& address_length);
|
||||
static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage& address, unsigned int& address_length, struct addrinfo& hints);
|
||||
static int lookup(const std::string& hostName, unsigned short port, sockaddr_storage& address, unsigned int& addressLength);
|
||||
static int lookup(const std::string& hostName, unsigned short port, sockaddr_storage& address, unsigned int& addressLength, struct addrinfo& hints);
|
||||
|
||||
static bool match(const sockaddr_storage& addr1, const sockaddr_storage& addr2, IPMATCHTYPE type = IMT_ADDRESS_AND_PORT);
|
||||
|
||||
static bool isNone(const sockaddr_storage& addr);
|
||||
|
||||
private:
|
||||
std::string m_address_save;
|
||||
unsigned short m_port_save;
|
||||
std::string m_address[UDP_SOCKET_MAX];
|
||||
unsigned short m_port[UDP_SOCKET_MAX];
|
||||
unsigned int m_af[UDP_SOCKET_MAX];
|
||||
int m_fd[UDP_SOCKET_MAX];
|
||||
unsigned int m_counter;
|
||||
std::string m_localAddress;
|
||||
unsigned short m_localPort;
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
SOCKET m_fd;
|
||||
int m_af;
|
||||
#else
|
||||
int m_fd;
|
||||
sa_family_t m_af;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015-2021,2023,2024 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
|
||||
|
@ -19,6 +19,6 @@
|
|||
#if !defined(VERSION_H)
|
||||
#define VERSION_H
|
||||
|
||||
const char* VERSION = "20201108";
|
||||
const char* VERSION = "20240129";
|
||||
|
||||
#endif
|
||||
|
|
|
@ -47,8 +47,8 @@ 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;
|
||||
const unsigned short FCS_PORT = 62500U;
|
||||
|
||||
const unsigned int IMRS_PORT = 21110U;
|
||||
const unsigned short IMRS_PORT = 21110U;
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -27,7 +27,7 @@
|
|||
|
||||
const unsigned int BUFFER_LENGTH = 200U;
|
||||
|
||||
CYSFNetwork::CYSFNetwork(const std::string& localAddress, unsigned int localPort, const std::string& name, const sockaddr_storage& addr, unsigned int addrLen, const std::string& callsign, bool debug) :
|
||||
CYSFNetwork::CYSFNetwork(const std::string& localAddress, unsigned short localPort, const std::string& name, const sockaddr_storage& addr, unsigned int addrLen, const std::string& callsign, bool debug) :
|
||||
m_socket(localAddress, localPort),
|
||||
m_debug(debug),
|
||||
m_addr(addr),
|
||||
|
@ -56,7 +56,7 @@ m_state(DS_NOTOPEN)
|
|||
}
|
||||
}
|
||||
|
||||
CYSFNetwork::CYSFNetwork(unsigned int localPort, const std::string& name, const sockaddr_storage& addr, unsigned int addrLen, const std::string& callsign, bool statc, bool debug) :
|
||||
CYSFNetwork::CYSFNetwork(unsigned short localPort, const std::string& name, const sockaddr_storage& addr, unsigned int addrLen, const std::string& callsign, bool statc, bool debug) :
|
||||
m_socket(localPort),
|
||||
m_debug(debug),
|
||||
m_addr(addr),
|
||||
|
|
|
@ -30,8 +30,8 @@
|
|||
|
||||
class CYSFNetwork : public CDGIdNetwork {
|
||||
public:
|
||||
CYSFNetwork(const std::string& localAddress, unsigned int localPort, const std::string& name, const sockaddr_storage& addr, unsigned int addrLen, const std::string& callsign, bool debug);
|
||||
CYSFNetwork(unsigned int localPort, const std::string& name, const sockaddr_storage& addr, unsigned int addrLen, const std::string& callsign, bool statc, bool debug);
|
||||
CYSFNetwork(const std::string& localAddress, unsigned short localPort, const std::string& name, const sockaddr_storage& addr, unsigned int addrLen, const std::string& callsign, bool debug);
|
||||
CYSFNetwork(unsigned short localPort, const std::string& name, const sockaddr_storage& addr, unsigned int addrLen, const std::string& callsign, bool statc, bool debug);
|
||||
virtual ~CYSFNetwork();
|
||||
|
||||
virtual std::string getDesc(unsigned int dgId);
|
||||
|
|
|
@ -58,7 +58,7 @@ bool CYSFReflectors::load()
|
|||
|
||||
if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL && p6 != NULL) {
|
||||
std::string host = std::string(p4);
|
||||
unsigned int port = (unsigned int)::atoi(p5);
|
||||
unsigned short port = (unsigned short)::atoi(p5);
|
||||
|
||||
if (::strstr(p1, "YCS") == NULL && ::strstr(p2, "YCS") == NULL) {
|
||||
sockaddr_storage addr;
|
||||
|
|
38
DGIdGateway/prebuild.cmd
Normal file
38
DGIdGateway/prebuild.cmd
Normal file
|
@ -0,0 +1,38 @@
|
|||
@echo off
|
||||
REM This pre-build file is for MSVS VC++. It parses the git master hash and
|
||||
REM converts it into GitVersion.h for compiling into builds. [George M1GEO]
|
||||
|
||||
cd %1
|
||||
setlocal enabledelayedexpansion
|
||||
set HEADFILE=..\.git\HEAD
|
||||
set HASHFILE=0
|
||||
if exist %HEADFILE% (
|
||||
for /F "tokens=4 delims=/:" %%a in ('type %HEADFILE%') do set HEADBRANCH=%%a
|
||||
set HASHFILE=.git\refs\heads\!HEADBRANCH!
|
||||
echo Found Git HEAD file: %HEADFILE%
|
||||
echo Git HEAD branch: !HEADBRANCH!
|
||||
echo Git HASH file: !HASHFILE!
|
||||
call :USEHASH
|
||||
) else (
|
||||
echo No head file :(
|
||||
call :USENULL
|
||||
)
|
||||
|
||||
goto :EOF
|
||||
|
||||
:USENULL
|
||||
set GITHASH=0000000000000000000000000000000000000000
|
||||
goto :WRITEGITVERSIONHEADER
|
||||
|
||||
:USEHASH
|
||||
for /f %%i in ('type !HASHFILE!') do set GITHASH=%%i
|
||||
goto :WRITEGITVERSIONHEADER
|
||||
|
||||
:WRITEGITVERSIONHEADER
|
||||
echo // File contains Git commit ID SHA1 present at buildtime (prebuild.cmd) > GitVersion.h
|
||||
echo const char *gitversion = "%GITHASH%"; >> GitVersion.h
|
||||
echo Current Git HASH: %GITHASH%
|
||||
goto :FINISHED
|
||||
|
||||
:FINISHED
|
||||
echo GitVersion.h written...
|
2
Makefile
2
Makefile
|
@ -1,4 +1,4 @@
|
|||
SUBDIRS = DGIdGateway YSFGateway YSFParrot YSFReflector
|
||||
SUBDIRS = DGIdGateway YSFGateway YSFParrot
|
||||
CLEANDIRS = $(SUBDIRS:%=clean-%)
|
||||
INSTALLDIRS = $(SUBDIRS:%=install-%)
|
||||
|
||||
|
|
|
@ -6,12 +6,10 @@ The YSF Gateway allows for use of Yaesu Wires-X commands from the radio to contr
|
|||
|
||||
The DG-ID Gateway allows the use of the DG-ID setting on the radio to control access to the different System Fusion network systems. It optionally sends System Fusion GPS information to aprs.fi.
|
||||
|
||||
The Reflector retransmits any received System Fusion data to other MMDVM Hosts or Gateways logged into the reflector at the time. It also provides status information to potential clients.
|
||||
|
||||
The Gateways and the Reflector have ini files that contain the parameters for running the software. The filename of the ini file is passed as a parameter on the command line. The Parrot takes the UDP port number to listen on as an argument.
|
||||
The Gateways have ini files that contain the parameters for running the software. The filename of the ini file is passed as a parameter on the command line. The Parrot takes the UDP port number to listen on as an argument.
|
||||
|
||||
The MMDVM .ini file should have the IP address and port number of the client in the [System Fusion Network] settings.
|
||||
|
||||
They build on 32-bit and 64-bit Linux as well as on Windows using Visual Studio 2019 on x86 and x64.
|
||||
|
||||
This software is licenced under the GPL v2 and is intended for amateur and educational use only. Use of this software for commercial purposes is strictly forbidden.
|
||||
This software is licenced under the GPL v2 and is primarily intended for amateur and educational use.
|
||||
|
|
|
@ -5,8 +5,6 @@ VisualStudioVersion = 16.0.30406.217
|
|||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "YSFParrot", "YSFParrot\YSFParrot.vcxproj", "{D3BBE5EC-91F7-457B-B782-B616B918708F}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "YSFReflector", "YSFReflector\YSFReflector.vcxproj", "{317D87F1-3485-4739-9F94-A07738B8E19D}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "YSFGateway", "YSFGateway\YSFGateway.vcxproj", "{4F82857B-D2CC-48DC-91A8-6275BDD3081B}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DGIdGateway", "DGIdGateway\DGIdGateway.vcxproj", "{1A4724B0-257E-45E9-943D-EABC56A1027E}"
|
||||
|
@ -27,14 +25,6 @@ Global
|
|||
{D3BBE5EC-91F7-457B-B782-B616B918708F}.Release|x64.Build.0 = Release|x64
|
||||
{D3BBE5EC-91F7-457B-B782-B616B918708F}.Release|x86.ActiveCfg = Release|Win32
|
||||
{D3BBE5EC-91F7-457B-B782-B616B918708F}.Release|x86.Build.0 = Release|Win32
|
||||
{317D87F1-3485-4739-9F94-A07738B8E19D}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{317D87F1-3485-4739-9F94-A07738B8E19D}.Debug|x64.Build.0 = Debug|x64
|
||||
{317D87F1-3485-4739-9F94-A07738B8E19D}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{317D87F1-3485-4739-9F94-A07738B8E19D}.Debug|x86.Build.0 = Debug|Win32
|
||||
{317D87F1-3485-4739-9F94-A07738B8E19D}.Release|x64.ActiveCfg = Release|x64
|
||||
{317D87F1-3485-4739-9F94-A07738B8E19D}.Release|x64.Build.0 = Release|x64
|
||||
{317D87F1-3485-4739-9F94-A07738B8E19D}.Release|x86.ActiveCfg = Release|Win32
|
||||
{317D87F1-3485-4739-9F94-A07738B8E19D}.Release|x86.Build.0 = Release|Win32
|
||||
{4F82857B-D2CC-48DC-91A8-6275BDD3081B}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{4F82857B-D2CC-48DC-91A8-6275BDD3081B}.Debug|x64.Build.0 = Debug|x64
|
||||
{4F82857B-D2CC-48DC-91A8-6275BDD3081B}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#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) :
|
||||
CAPRSWriter::CAPRSWriter(const std::string& callsign, const std::string& rptSuffix, const std::string& address, unsigned short port, const std::string& suffix, bool debug) :
|
||||
m_idTimer(1000U),
|
||||
m_callsign(callsign),
|
||||
m_debug(debug),
|
||||
|
@ -35,6 +35,7 @@ m_latitude(0.0F),
|
|||
m_longitude(0.0F),
|
||||
m_height(0),
|
||||
m_desc(),
|
||||
m_symbol(),
|
||||
m_suffix(suffix),
|
||||
m_aprsAddr(),
|
||||
m_aprsAddrLen(0U),
|
||||
|
@ -63,11 +64,12 @@ CAPRSWriter::~CAPRSWriter()
|
|||
{
|
||||
}
|
||||
|
||||
void CAPRSWriter::setInfo(unsigned int txFrequency, unsigned int rxFrequency, const std::string& desc)
|
||||
void CAPRSWriter::setInfo(unsigned int txFrequency, unsigned int rxFrequency, const std::string& desc, const std::string& symbol)
|
||||
{
|
||||
m_txFrequency = txFrequency;
|
||||
m_rxFrequency = rxFrequency;
|
||||
m_desc = desc;
|
||||
m_symbol = symbol;
|
||||
}
|
||||
|
||||
void CAPRSWriter::setStaticLocation(float latitude, float longitude, int height)
|
||||
|
@ -158,12 +160,15 @@ void CAPRSWriter::write(const unsigned char* source, const char* type, unsigned
|
|||
case 0x24U:
|
||||
case 0x28U:
|
||||
case 0x30U:
|
||||
case 0x33U:
|
||||
symbol = '[';
|
||||
break;
|
||||
case 0x25U:
|
||||
case 0x29U:
|
||||
case 0x31U:
|
||||
symbol = '>';
|
||||
break;
|
||||
case 0x20U:
|
||||
case 0x26U:
|
||||
symbol = 'r';
|
||||
break;
|
||||
|
@ -229,19 +234,19 @@ void CAPRSWriter::sendIdFrameFixed()
|
|||
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",
|
||||
::sprintf(desc, "MMDVM Voice (C4FM) %.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());
|
||||
::sprintf(desc, "MMDVM Voice (C4FM)%s%s", m_desc.empty() ? "" : ", ", m_desc.c_str());
|
||||
}
|
||||
|
||||
const char* band = "4m";
|
||||
if (m_txFrequency >= 1200000000U)
|
||||
band = "1.2";
|
||||
band = "23cm/1.2GHz";
|
||||
else if (m_txFrequency >= 420000000U)
|
||||
band = "440";
|
||||
band = "70cm";
|
||||
else if (m_txFrequency >= 144000000U)
|
||||
band = "2m";
|
||||
else if (m_txFrequency >= 50000000U)
|
||||
|
@ -265,17 +270,21 @@ void CAPRSWriter::sendIdFrameFixed()
|
|||
::sprintf(lon, "%08.2lf", longitude);
|
||||
|
||||
std::string server = m_callsign;
|
||||
std::string symbol = m_symbol;
|
||||
size_t pos = server.find_first_of('-');
|
||||
if (pos == std::string::npos)
|
||||
server.append("-S");
|
||||
else
|
||||
server.append("S");
|
||||
|
||||
if (symbol.empty())
|
||||
symbol.append("D&");
|
||||
|
||||
char output[500U];
|
||||
::sprintf(output, "%s>APDG03,TCPIP*,qAC,%s:!%s%cD%s%c&/A=%06.0f%s %s\r\n",
|
||||
::sprintf(output, "%s>APDG03,TCPIP*,qAC,%s:!%s%c%c%s%c%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',
|
||||
lat, (m_latitude < 0.0F) ? 'S' : 'N', symbol[0],
|
||||
lon, (m_longitude < 0.0F) ? 'W' : 'E', symbol[1],
|
||||
float(m_height) * 3.28F, band, desc);
|
||||
|
||||
if (m_debug)
|
||||
|
@ -298,8 +307,11 @@ void CAPRSWriter::sendIdFrameMobile()
|
|||
return;
|
||||
#endif
|
||||
|
||||
|
||||
#if GPSD_API_MAJOR_VERSION >= 10
|
||||
if (m_gpsdData.fix.status != STATUS_FIX)
|
||||
#else
|
||||
if (m_gpsdData.status != STATUS_FIX)
|
||||
#endif
|
||||
return;
|
||||
|
||||
bool latlonSet = (m_gpsdData.set & LATLON_SET) == LATLON_SET;
|
||||
|
@ -323,19 +335,19 @@ void CAPRSWriter::sendIdFrameMobile()
|
|||
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",
|
||||
::sprintf(desc, "MMDVM Voice (C4FM) %.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());
|
||||
::sprintf(desc, "MMDVM Voice (C4FM)%s%s", m_desc.empty() ? "" : ", ", m_desc.c_str());
|
||||
}
|
||||
|
||||
const char* band = "4m";
|
||||
if (m_txFrequency >= 1200000000U)
|
||||
band = "1.2";
|
||||
band = "23cm/1.2GHz";
|
||||
else if (m_txFrequency >= 420000000U)
|
||||
band = "440";
|
||||
band = "70cm";
|
||||
else if (m_txFrequency >= 144000000U)
|
||||
band = "2m";
|
||||
else if (m_txFrequency >= 50000000U)
|
||||
|
@ -359,17 +371,21 @@ void CAPRSWriter::sendIdFrameMobile()
|
|||
::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");
|
||||
std::string symbol = m_symbol;
|
||||
size_t pos = server.find_first_of('-');
|
||||
if (pos == std::string::npos)
|
||||
server.append("-S");
|
||||
else
|
||||
server.append("S");
|
||||
|
||||
if (symbol.empty())
|
||||
symbol.append("D&");
|
||||
|
||||
char output[500U];
|
||||
::sprintf(output, "%s>APDG03,TCPIP*,qAC,%s:!%s%cD%s%c&",
|
||||
::sprintf(output, "%s>APDG03,TCPIP*,qAC,%s:!%s%c%c%s%c%c",
|
||||
m_callsign.c_str(), server.c_str(),
|
||||
lat, (rawLatitude < 0.0F) ? 'S' : 'N',
|
||||
lon, (rawLongitude < 0.0F) ? 'W' : 'E');
|
||||
lat, (rawLatitude < 0.0F) ? 'S' : 'N', symbol[0],
|
||||
lon, (rawLongitude < 0.0F) ? 'W' : 'E', symbol[1]);
|
||||
|
||||
if (bearingSet && velocitySet)
|
||||
::sprintf(output + ::strlen(output), "%03.0f/%03.0f", rawBearing, rawVelocity * 0.539957F);
|
||||
|
|
|
@ -42,12 +42,12 @@
|
|||
|
||||
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(const std::string& callsign, const std::string& rptSuffix, const std::string& address, unsigned short port, const std::string& suffix, bool debug);
|
||||
~CAPRSWriter();
|
||||
|
||||
bool open();
|
||||
|
||||
void setInfo(unsigned int txFrequency, unsigned int rxFrequency, const std::string& desc);
|
||||
void setInfo(unsigned int txFrequency, unsigned int rxFrequency, const std::string& desc, const std::string& symbol);
|
||||
|
||||
void setStaticLocation(float latitude, float longitude, int height);
|
||||
|
||||
|
@ -69,6 +69,7 @@ private:
|
|||
float m_longitude;
|
||||
int m_height;
|
||||
std::string m_desc;
|
||||
std::string m_symbol;
|
||||
std::string m_suffix;
|
||||
sockaddr_storage m_aprsAddr;
|
||||
unsigned int m_aprsAddrLen;
|
||||
|
|
|
@ -70,6 +70,7 @@ m_aprsAddress(),
|
|||
m_aprsPort(0U),
|
||||
m_aprsSuffix(),
|
||||
m_aprsDescription(),
|
||||
m_aprsSymbol("/r"),
|
||||
m_networkStartup(),
|
||||
m_networkOptions(),
|
||||
m_networkInactivityTimeout(0U),
|
||||
|
@ -183,11 +184,11 @@ bool CConf::read()
|
|||
else if (::strcmp(key, "RptAddress") == 0)
|
||||
m_rptAddress = value;
|
||||
else if (::strcmp(key, "RptPort") == 0)
|
||||
m_rptPort = (unsigned int)::atoi(value);
|
||||
m_rptPort = (unsigned short)::atoi(value);
|
||||
else if (::strcmp(key, "LocalAddress") == 0)
|
||||
m_myAddress = value;
|
||||
else if (::strcmp(key, "LocalPort") == 0)
|
||||
m_myPort = (unsigned int)::atoi(value);
|
||||
m_myPort = (unsigned short)::atoi(value);
|
||||
else if (::strcmp(key, "WiresXMakeUpper") == 0)
|
||||
m_wiresXMakeUpper = ::atoi(value) == 1;
|
||||
else if (::strcmp(key, "WiresXCommandPassthrough") == 0)
|
||||
|
@ -230,11 +231,13 @@ bool CConf::read()
|
|||
else if (::strcmp(key, "Address") == 0)
|
||||
m_aprsAddress = value;
|
||||
else if (::strcmp(key, "Port") == 0)
|
||||
m_aprsPort = (unsigned int)::atoi(value);
|
||||
m_aprsPort = (unsigned short)::atoi(value);
|
||||
else if (::strcmp(key, "Suffix") == 0)
|
||||
m_aprsSuffix = value;
|
||||
else if (::strcmp(key, "Description") == 0)
|
||||
m_aprsDescription = value;
|
||||
else if (::strcmp(key, "Symbol") == 0)
|
||||
m_aprsSymbol = value;
|
||||
} else if (section == SECTION_NETWORK) {
|
||||
if (::strcmp(key, "Startup") == 0)
|
||||
m_networkStartup = value;
|
||||
|
@ -250,7 +253,7 @@ bool CConf::read()
|
|||
if (::strcmp(key, "Enable") == 0)
|
||||
m_ysfNetworkEnabled = ::atoi(value) == 1;
|
||||
else if (::strcmp(key, "Port") == 0)
|
||||
m_ysfNetworkPort = (unsigned int)::atoi(value);
|
||||
m_ysfNetworkPort = (unsigned short)::atoi(value);
|
||||
else if (::strcmp(key, "Hosts") == 0)
|
||||
m_ysfNetworkHosts = value;
|
||||
else if (::strcmp(key, "ReloadTime") == 0)
|
||||
|
@ -258,26 +261,26 @@ bool CConf::read()
|
|||
else if (::strcmp(key, "ParrotAddress") == 0)
|
||||
m_ysfNetworkParrotAddress = value;
|
||||
else if (::strcmp(key, "ParrotPort") == 0)
|
||||
m_ysfNetworkParrotPort = (unsigned int)::atoi(value);
|
||||
m_ysfNetworkParrotPort = (unsigned short)::atoi(value);
|
||||
else if (::strcmp(key, "YSF2DMRAddress") == 0)
|
||||
m_ysfNetworkYSF2DMRAddress = value;
|
||||
else if (::strcmp(key, "YSF2DMRPort") == 0)
|
||||
m_ysfNetworkYSF2DMRPort = (unsigned int)::atoi(value);
|
||||
m_ysfNetworkYSF2DMRPort = (unsigned short)::atoi(value);
|
||||
else if (::strcmp(key, "YSF2NXDNAddress") == 0)
|
||||
m_ysfNetworkYSF2NXDNAddress = value;
|
||||
else if (::strcmp(key, "YSF2NXDNPort") == 0)
|
||||
m_ysfNetworkYSF2NXDNPort = (unsigned int)::atoi(value);
|
||||
m_ysfNetworkYSF2NXDNPort = (unsigned short)::atoi(value);
|
||||
else if (::strcmp(key, "YSF2P25Address") == 0)
|
||||
m_ysfNetworkYSF2P25Address = value;
|
||||
else if (::strcmp(key, "YSF2P25Port") == 0)
|
||||
m_ysfNetworkYSF2P25Port = (unsigned int)::atoi(value);
|
||||
m_ysfNetworkYSF2P25Port = (unsigned short)::atoi(value);
|
||||
} else if (section == SECTION_FCS_NETWORK) {
|
||||
if (::strcmp(key, "Enable") == 0)
|
||||
m_fcsNetworkEnabled = ::atoi(value) == 1;
|
||||
else if (::strcmp(key, "Rooms") == 0)
|
||||
m_fcsNetworkFile = value;
|
||||
else if (::strcmp(key, "Port") == 0)
|
||||
m_fcsNetworkPort = (unsigned int)::atoi(value);
|
||||
m_fcsNetworkPort = (unsigned short)::atoi(value);
|
||||
} else if (section == SECTION_GPSD) {
|
||||
if (::strcmp(key, "Enable") == 0)
|
||||
m_gpsdEnabled = ::atoi(value) == 1;
|
||||
|
@ -289,7 +292,7 @@ bool CConf::read()
|
|||
if (::strcmp(key, "Enable") == 0)
|
||||
m_remoteCommandsEnabled = ::atoi(value) == 1;
|
||||
else if (::strcmp(key, "Port") == 0)
|
||||
m_remoteCommandsPort = (unsigned int)::atoi(value);
|
||||
m_remoteCommandsPort = (unsigned short)::atoi(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -318,7 +321,7 @@ std::string CConf::getRptAddress() const
|
|||
return m_rptAddress;
|
||||
}
|
||||
|
||||
unsigned int CConf::getRptPort() const
|
||||
unsigned short CConf::getRptPort() const
|
||||
{
|
||||
return m_rptPort;
|
||||
}
|
||||
|
@ -328,7 +331,7 @@ std::string CConf::getMyAddress() const
|
|||
return m_myAddress;
|
||||
}
|
||||
|
||||
unsigned int CConf::getMyPort() const
|
||||
unsigned short CConf::getMyPort() const
|
||||
{
|
||||
return m_myPort;
|
||||
}
|
||||
|
@ -428,7 +431,7 @@ std::string CConf::getAPRSAddress() const
|
|||
return m_aprsAddress;
|
||||
}
|
||||
|
||||
unsigned int CConf::getAPRSPort() const
|
||||
unsigned short CConf::getAPRSPort() const
|
||||
{
|
||||
return m_aprsPort;
|
||||
}
|
||||
|
@ -443,6 +446,11 @@ std::string CConf::getAPRSDescription() const
|
|||
return m_aprsDescription;
|
||||
}
|
||||
|
||||
std::string CConf::getAPRSSymbol() const
|
||||
{
|
||||
return m_aprsSymbol;
|
||||
}
|
||||
|
||||
std::string CConf::getNetworkStartup() const
|
||||
{
|
||||
return m_networkStartup;
|
||||
|
@ -473,7 +481,7 @@ bool CConf::getYSFNetworkEnabled() const
|
|||
return m_ysfNetworkEnabled;
|
||||
}
|
||||
|
||||
unsigned int CConf::getYSFNetworkPort() const
|
||||
unsigned short CConf::getYSFNetworkPort() const
|
||||
{
|
||||
return m_ysfNetworkPort;
|
||||
}
|
||||
|
@ -493,7 +501,7 @@ std::string CConf::getYSFNetworkParrotAddress() const
|
|||
return m_ysfNetworkParrotAddress;
|
||||
}
|
||||
|
||||
unsigned int CConf::getYSFNetworkParrotPort() const
|
||||
unsigned short CConf::getYSFNetworkParrotPort() const
|
||||
{
|
||||
return m_ysfNetworkParrotPort;
|
||||
}
|
||||
|
@ -503,7 +511,7 @@ std::string CConf::getYSFNetworkYSF2DMRAddress() const
|
|||
return m_ysfNetworkYSF2DMRAddress;
|
||||
}
|
||||
|
||||
unsigned int CConf::getYSFNetworkYSF2DMRPort() const
|
||||
unsigned short CConf::getYSFNetworkYSF2DMRPort() const
|
||||
{
|
||||
return m_ysfNetworkYSF2DMRPort;
|
||||
}
|
||||
|
@ -513,7 +521,7 @@ std::string CConf::getYSFNetworkYSF2NXDNAddress() const
|
|||
return m_ysfNetworkYSF2NXDNAddress;
|
||||
}
|
||||
|
||||
unsigned int CConf::getYSFNetworkYSF2NXDNPort() const
|
||||
unsigned short CConf::getYSFNetworkYSF2NXDNPort() const
|
||||
{
|
||||
return m_ysfNetworkYSF2NXDNPort;
|
||||
}
|
||||
|
@ -523,7 +531,7 @@ std::string CConf::getYSFNetworkYSF2P25Address() const
|
|||
return m_ysfNetworkYSF2P25Address;
|
||||
}
|
||||
|
||||
unsigned int CConf::getYSFNetworkYSF2P25Port() const
|
||||
unsigned short CConf::getYSFNetworkYSF2P25Port() const
|
||||
{
|
||||
return m_ysfNetworkYSF2P25Port;
|
||||
}
|
||||
|
@ -539,7 +547,7 @@ std::string CConf::getFCSNetworkFile() const
|
|||
return m_fcsNetworkFile;
|
||||
}
|
||||
|
||||
unsigned int CConf::getFCSNetworkPort() const
|
||||
unsigned short CConf::getFCSNetworkPort() const
|
||||
{
|
||||
return m_fcsNetworkPort;
|
||||
}
|
||||
|
@ -564,7 +572,7 @@ bool CConf::getRemoteCommandsEnabled() const
|
|||
return m_remoteCommandsEnabled;
|
||||
}
|
||||
|
||||
unsigned int CConf::getRemoteCommandsPort() const
|
||||
unsigned short CConf::getRemoteCommandsPort() const
|
||||
{
|
||||
return m_remoteCommandsPort;
|
||||
}
|
||||
|
|
|
@ -34,9 +34,9 @@ public:
|
|||
std::string getSuffix() const;
|
||||
unsigned int getId() const;
|
||||
std::string getRptAddress() const;
|
||||
unsigned int getRptPort() const;
|
||||
unsigned short getRptPort() const;
|
||||
std::string getMyAddress() const;
|
||||
unsigned int getMyPort() const;
|
||||
unsigned short getMyPort() const;
|
||||
bool getWiresXMakeUpper() const;
|
||||
bool getWiresXCommandPassthrough() const;
|
||||
bool getDebug() const;
|
||||
|
@ -62,9 +62,10 @@ public:
|
|||
// The APRS section
|
||||
bool getAPRSEnabled() const;
|
||||
std::string getAPRSAddress() const;
|
||||
unsigned int getAPRSPort() const;
|
||||
unsigned short getAPRSPort() const;
|
||||
std::string getAPRSSuffix() const;
|
||||
std::string getAPRSDescription() const;
|
||||
std::string getAPRSSymbol() const;
|
||||
|
||||
// The Network section
|
||||
std::string getNetworkStartup() const;
|
||||
|
@ -75,22 +76,22 @@ public:
|
|||
|
||||
// The YSF Network section
|
||||
bool getYSFNetworkEnabled() const;
|
||||
unsigned int getYSFNetworkPort() const;
|
||||
unsigned short getYSFNetworkPort() const;
|
||||
std::string getYSFNetworkHosts() const;
|
||||
unsigned int getYSFNetworkReloadTime() const;
|
||||
std::string getYSFNetworkParrotAddress() const;
|
||||
unsigned int getYSFNetworkParrotPort() const;
|
||||
unsigned short getYSFNetworkParrotPort() const;
|
||||
std::string getYSFNetworkYSF2DMRAddress() const;
|
||||
unsigned int getYSFNetworkYSF2DMRPort() const;
|
||||
unsigned short getYSFNetworkYSF2DMRPort() const;
|
||||
std::string getYSFNetworkYSF2NXDNAddress() const;
|
||||
unsigned int getYSFNetworkYSF2NXDNPort() const;
|
||||
unsigned short getYSFNetworkYSF2NXDNPort() const;
|
||||
std::string getYSFNetworkYSF2P25Address() const;
|
||||
unsigned int getYSFNetworkYSF2P25Port() const;
|
||||
unsigned short getYSFNetworkYSF2P25Port() const;
|
||||
|
||||
// The FCS Network section
|
||||
bool getFCSNetworkEnabled() const;
|
||||
std::string getFCSNetworkFile() const;
|
||||
unsigned int getFCSNetworkPort() const;
|
||||
unsigned short getFCSNetworkPort() const;
|
||||
|
||||
// The GPSD section
|
||||
bool getGPSDEnabled() const;
|
||||
|
@ -99,7 +100,7 @@ public:
|
|||
|
||||
// The Remote Commands section
|
||||
bool getRemoteCommandsEnabled() const;
|
||||
unsigned int getRemoteCommandsPort() const;
|
||||
unsigned short getRemoteCommandsPort() const;
|
||||
|
||||
private:
|
||||
std::string m_file;
|
||||
|
@ -107,9 +108,9 @@ private:
|
|||
std::string m_suffix;
|
||||
unsigned int m_id;
|
||||
std::string m_rptAddress;
|
||||
unsigned int m_rptPort;
|
||||
unsigned short m_rptPort;
|
||||
std::string m_myAddress;
|
||||
unsigned int m_myPort;
|
||||
unsigned short m_myPort;
|
||||
bool m_wiresXMakeUpper;
|
||||
bool m_wiresXCommandPassthrough;
|
||||
bool m_debug;
|
||||
|
@ -132,9 +133,10 @@ private:
|
|||
|
||||
bool m_aprsEnabled;
|
||||
std::string m_aprsAddress;
|
||||
unsigned int m_aprsPort;
|
||||
unsigned short m_aprsPort;
|
||||
std::string m_aprsSuffix;
|
||||
std::string m_aprsDescription;
|
||||
std::string m_aprsSymbol;
|
||||
|
||||
std::string m_networkStartup;
|
||||
std::string m_networkOptions;
|
||||
|
@ -143,28 +145,28 @@ private:
|
|||
bool m_networkDebug;
|
||||
|
||||
bool m_ysfNetworkEnabled;
|
||||
unsigned int m_ysfNetworkPort;
|
||||
unsigned short m_ysfNetworkPort;
|
||||
std::string m_ysfNetworkHosts;
|
||||
unsigned int m_ysfNetworkReloadTime;
|
||||
std::string m_ysfNetworkParrotAddress;
|
||||
unsigned int m_ysfNetworkParrotPort;
|
||||
unsigned short m_ysfNetworkParrotPort;
|
||||
std::string m_ysfNetworkYSF2DMRAddress;
|
||||
unsigned int m_ysfNetworkYSF2DMRPort;
|
||||
unsigned short m_ysfNetworkYSF2DMRPort;
|
||||
std::string m_ysfNetworkYSF2NXDNAddress;
|
||||
unsigned int m_ysfNetworkYSF2NXDNPort;
|
||||
unsigned short m_ysfNetworkYSF2NXDNPort;
|
||||
std::string m_ysfNetworkYSF2P25Address;
|
||||
unsigned int m_ysfNetworkYSF2P25Port;
|
||||
unsigned short m_ysfNetworkYSF2P25Port;
|
||||
|
||||
bool m_fcsNetworkEnabled;
|
||||
std::string m_fcsNetworkFile;
|
||||
unsigned int m_fcsNetworkPort;
|
||||
unsigned short m_fcsNetworkPort;
|
||||
|
||||
bool m_gpsdEnabled;
|
||||
std::string m_gpsdAddress;
|
||||
std::string m_gpsdPort;
|
||||
|
||||
bool m_remoteCommandsEnabled;
|
||||
unsigned int m_remoteCommandsPort;
|
||||
unsigned short m_remoteCommandsPort;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -29,7 +29,7 @@ const char* FCS_VERSION = "MMDVM";
|
|||
|
||||
const unsigned int BUFFER_LENGTH = 200U;
|
||||
|
||||
CFCSNetwork::CFCSNetwork(unsigned int port, const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, const std::string& locator, unsigned int id, bool debug) :
|
||||
CFCSNetwork::CFCSNetwork(unsigned short 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_addr(),
|
||||
|
|
|
@ -36,7 +36,7 @@ enum FCS_STATE {
|
|||
|
||||
class CFCSNetwork {
|
||||
public:
|
||||
CFCSNetwork(unsigned int port, const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, const std::string& locator, unsigned int id, bool debug);
|
||||
CFCSNetwork(unsigned short port, const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, const std::string& locator, unsigned int id, bool debug);
|
||||
~CFCSNetwork();
|
||||
|
||||
bool open();
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -270,6 +270,9 @@ void CGPS::transmitGPS(const unsigned char* source)
|
|||
case 0x30U:
|
||||
::strcpy(radio, "FT-3D");
|
||||
break;
|
||||
case 0x33U:
|
||||
::strcpy(radio, "FT-5D");
|
||||
break;
|
||||
default:
|
||||
::sprintf(radio, "0x%02X", m_buffer[4U]);
|
||||
break;
|
||||
|
|
|
@ -161,7 +161,7 @@ void Log(unsigned int level, const char* fmt, ...)
|
|||
|
||||
struct tm* tm = ::gmtime(&now.tv_sec);
|
||||
|
||||
::sprintf(buffer, "%c: %04d-%02d-%02d %02d:%02d:%02d.%03ld ", 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 / 1000L);
|
||||
::sprintf(buffer, "%c: %04d-%02d-%02d %02d:%02d:%02d.%03lld ", 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 / 1000LL);
|
||||
#endif
|
||||
|
||||
va_list vl;
|
||||
|
|
|
@ -22,9 +22,22 @@ YSFGateway: $(OBJECTS)
|
|||
%.o: %.cpp
|
||||
$(CXX) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
YSFGateway.o: GitVersion.h FORCE
|
||||
|
||||
.PHONY: GitVersion.h
|
||||
|
||||
FORCE:
|
||||
|
||||
install:
|
||||
install -m 755 YSFGateway /usr/local/bin/
|
||||
|
||||
clean:
|
||||
$(RM) YSFGateway *.o *.d *.bak *~
|
||||
$(RM) YSFGateway *.o *.d *.bak *~ GitVersion.h
|
||||
|
||||
# Export the current git version if the index file exists, else 000...
|
||||
GitVersion.h:
|
||||
ifneq ("$(wildcard ../.git/index)","")
|
||||
echo "const char *gitversion = \"$(shell git rev-parse HEAD)\";" > $@
|
||||
else
|
||||
echo "const char *gitversion = \"0000000000000000000000000000000000000000\";" > $@
|
||||
endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2006-2016,2020,2024 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
|
||||
|
@ -28,34 +28,25 @@
|
|||
#if defined(HAVE_LOG_H)
|
||||
#include "Log.h"
|
||||
#else
|
||||
#define LogMessage(fmt, ...) ::fprintf(stderr, fmt "\n", ## __VA_ARGS__)
|
||||
#define LogError(fmt, ...) ::fprintf(stderr, fmt "\n", ## __VA_ARGS__)
|
||||
#define LogInfo(fmt, ...) ::fprintf(stderr, fmt "\n", ## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
CUDPSocket::CUDPSocket(const std::string& address, unsigned int port) :
|
||||
m_address_save(address),
|
||||
m_port_save(port),
|
||||
m_counter(0U)
|
||||
CUDPSocket::CUDPSocket(const std::string& address, unsigned short port) :
|
||||
m_localAddress(address),
|
||||
m_localPort(port),
|
||||
m_fd(-1),
|
||||
m_af(AF_UNSPEC)
|
||||
{
|
||||
for (int i = 0; i < UDP_SOCKET_MAX; i++) {
|
||||
m_address[i] = "";
|
||||
m_port[i] = 0U;
|
||||
m_af[i] = 0U;
|
||||
m_fd[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
CUDPSocket::CUDPSocket(unsigned int port) :
|
||||
m_address_save(),
|
||||
m_port_save(port),
|
||||
m_counter(0U)
|
||||
CUDPSocket::CUDPSocket(unsigned short port) :
|
||||
m_localAddress(),
|
||||
m_localPort(port),
|
||||
m_fd(-1),
|
||||
m_af(AF_UNSPEC)
|
||||
{
|
||||
for (int i = 0; i < UDP_SOCKET_MAX; i++) {
|
||||
m_address[i] = "";
|
||||
m_port[i] = 0U;
|
||||
m_af[i] = 0U;
|
||||
m_fd[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
CUDPSocket::~CUDPSocket()
|
||||
|
@ -79,7 +70,7 @@ void CUDPSocket::shutdown()
|
|||
#endif
|
||||
}
|
||||
|
||||
int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_storage& addr, unsigned int& address_length)
|
||||
int CUDPSocket::lookup(const std::string& hostname, unsigned short port, sockaddr_storage& addr, unsigned int& address_length)
|
||||
{
|
||||
struct addrinfo hints;
|
||||
::memset(&hints, 0, sizeof(hints));
|
||||
|
@ -87,15 +78,15 @@ int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_
|
|||
return lookup(hostname, port, addr, address_length, hints);
|
||||
}
|
||||
|
||||
int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_storage& addr, unsigned int& address_length, struct addrinfo& hints)
|
||||
int CUDPSocket::lookup(const std::string& hostname, unsigned short port, sockaddr_storage& addr, unsigned int& address_length, struct addrinfo& hints)
|
||||
{
|
||||
std::string portstr = std::to_string(port);
|
||||
struct addrinfo *res;
|
||||
|
||||
/* port is always digits, no needs to lookup service */
|
||||
/* Port is always digits, no needs to lookup service */
|
||||
hints.ai_flags |= AI_NUMERICSERV;
|
||||
|
||||
int err = getaddrinfo(hostname.empty() ? NULL : hostname.c_str(), portstr.c_str(), &hints, &res);
|
||||
int err = ::getaddrinfo(hostname.empty() ? NULL : hostname.c_str(), portstr.c_str(), &hints, &res);
|
||||
if (err != 0) {
|
||||
sockaddr_in* paddr = (sockaddr_in*)&addr;
|
||||
::memset(paddr, 0x00U, address_length = sizeof(sockaddr_in));
|
||||
|
@ -108,7 +99,7 @@ int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_
|
|||
|
||||
::memcpy(&addr, res->ai_addr, address_length = res->ai_addrlen);
|
||||
|
||||
freeaddrinfo(res);
|
||||
::freeaddrinfo(res);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -120,33 +111,33 @@ bool CUDPSocket::match(const sockaddr_storage& addr1, const sockaddr_storage& ad
|
|||
|
||||
if (type == IMT_ADDRESS_AND_PORT) {
|
||||
switch (addr1.ss_family) {
|
||||
case AF_INET:
|
||||
struct sockaddr_in *in_1, *in_2;
|
||||
in_1 = (struct sockaddr_in*)&addr1;
|
||||
in_2 = (struct sockaddr_in*)&addr2;
|
||||
return (in_1->sin_addr.s_addr == in_2->sin_addr.s_addr) && (in_1->sin_port == in_2->sin_port);
|
||||
case AF_INET6:
|
||||
struct sockaddr_in6 *in6_1, *in6_2;
|
||||
in6_1 = (struct sockaddr_in6*)&addr1;
|
||||
in6_2 = (struct sockaddr_in6*)&addr2;
|
||||
return IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr) && (in6_1->sin6_port == in6_2->sin6_port);
|
||||
default:
|
||||
return false;
|
||||
case AF_INET:
|
||||
struct sockaddr_in *in_1, *in_2;
|
||||
in_1 = (struct sockaddr_in*)&addr1;
|
||||
in_2 = (struct sockaddr_in*)&addr2;
|
||||
return (in_1->sin_addr.s_addr == in_2->sin_addr.s_addr) && (in_1->sin_port == in_2->sin_port);
|
||||
case AF_INET6:
|
||||
struct sockaddr_in6 *in6_1, *in6_2;
|
||||
in6_1 = (struct sockaddr_in6*)&addr1;
|
||||
in6_2 = (struct sockaddr_in6*)&addr2;
|
||||
return IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr) && (in6_1->sin6_port == in6_2->sin6_port);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else if (type == IMT_ADDRESS_ONLY) {
|
||||
switch (addr1.ss_family) {
|
||||
case AF_INET:
|
||||
struct sockaddr_in *in_1, *in_2;
|
||||
in_1 = (struct sockaddr_in*)&addr1;
|
||||
in_2 = (struct sockaddr_in*)&addr2;
|
||||
return in_1->sin_addr.s_addr == in_2->sin_addr.s_addr;
|
||||
case AF_INET6:
|
||||
struct sockaddr_in6 *in6_1, *in6_2;
|
||||
in6_1 = (struct sockaddr_in6*)&addr1;
|
||||
in6_2 = (struct sockaddr_in6*)&addr2;
|
||||
return IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr);
|
||||
default:
|
||||
return false;
|
||||
case AF_INET:
|
||||
struct sockaddr_in *in_1, *in_2;
|
||||
in_1 = (struct sockaddr_in*)&addr1;
|
||||
in_2 = (struct sockaddr_in*)&addr2;
|
||||
return in_1->sin_addr.s_addr == in_2->sin_addr.s_addr;
|
||||
case AF_INET6:
|
||||
struct sockaddr_in6 *in6_1, *in6_2;
|
||||
in6_1 = (struct sockaddr_in6*)&addr1;
|
||||
in6_2 = (struct sockaddr_in6*)&addr2;
|
||||
return IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
|
@ -162,33 +153,34 @@ bool CUDPSocket::isNone(const sockaddr_storage& addr)
|
|||
|
||||
bool CUDPSocket::open(const sockaddr_storage& address)
|
||||
{
|
||||
return open(address.ss_family);
|
||||
m_af = address.ss_family;
|
||||
|
||||
return open();
|
||||
}
|
||||
|
||||
bool CUDPSocket::open(unsigned int af)
|
||||
bool CUDPSocket::open()
|
||||
{
|
||||
return open(0, af, m_address_save, m_port_save);
|
||||
}
|
||||
assert(m_fd == -1);
|
||||
|
||||
bool CUDPSocket::open(const unsigned int index, const unsigned int af, const std::string& address, const unsigned int port)
|
||||
{
|
||||
sockaddr_storage addr;
|
||||
unsigned int addrlen;
|
||||
struct addrinfo hints;
|
||||
|
||||
::memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
hints.ai_family = af;
|
||||
hints.ai_family = m_af;
|
||||
|
||||
/* to determine protocol family, call lookup() first. */
|
||||
int err = lookup(address, port, addr, addrlen, hints);
|
||||
// To determine protocol family, call lookup() on the local address first.
|
||||
int err = lookup(m_localAddress, m_localPort, addr, addrlen, hints);
|
||||
if (err != 0) {
|
||||
LogError("The local address is invalid - %s", address.c_str());
|
||||
LogError("The local address is invalid - %s", m_localAddress.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
int fd = ::socket(addr.ss_family, SOCK_DGRAM, 0);
|
||||
if (fd < 0) {
|
||||
m_af = addr.ss_family;
|
||||
|
||||
m_fd = ::socket(m_af, SOCK_DGRAM, 0);
|
||||
if (m_fd < 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LogError("Cannot create the UDP socket, err: %lu", ::GetLastError());
|
||||
#else
|
||||
|
@ -197,62 +189,51 @@ bool CUDPSocket::open(const unsigned int index, const unsigned int af, const std
|
|||
return false;
|
||||
}
|
||||
|
||||
m_address[index] = address;
|
||||
m_port[index] = port;
|
||||
m_af[index] = addr.ss_family;
|
||||
m_fd[index] = fd;
|
||||
|
||||
if (port > 0U) {
|
||||
if (m_localPort > 0U) {
|
||||
int reuse = 1;
|
||||
if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(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
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (::bind(fd, (sockaddr*)&addr, addrlen) == -1) {
|
||||
if (::bind(m_fd, (sockaddr*)&addr, addrlen) == -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
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
LogInfo("Opening UDP port on %u", port);
|
||||
LogInfo("Opening UDP port on %hu", m_localPort);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storage& address, unsigned int &address_length)
|
||||
int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storage& address, unsigned int &addressLength)
|
||||
{
|
||||
assert(buffer != NULL);
|
||||
assert(length > 0U);
|
||||
assert(m_fd >= 0);
|
||||
|
||||
// Check that the readfrom() won't block
|
||||
int i, n;
|
||||
struct pollfd pfd[UDP_SOCKET_MAX];
|
||||
for (i = n = 0; i < UDP_SOCKET_MAX; i++) {
|
||||
if (m_fd[i] >= 0) {
|
||||
pfd[n].fd = m_fd[i];
|
||||
pfd[n].events = POLLIN;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
// no socket descriptor to receive
|
||||
if (n == 0)
|
||||
return 0;
|
||||
struct pollfd pfd;
|
||||
pfd.fd = m_fd;
|
||||
pfd.events = POLLIN;
|
||||
pfd.revents = 0;
|
||||
|
||||
// Return immediately
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
int ret = WSAPoll(pfd, n, 0);
|
||||
int ret = WSAPoll(&pfd, 1, 0);
|
||||
#else
|
||||
int ret = ::poll(pfd, n, 0);
|
||||
int ret = ::poll(&pfd, 1, 0);
|
||||
#endif
|
||||
if (ret < 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
@ -263,14 +244,7 @@ int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storag
|
|||
return -1;
|
||||
}
|
||||
|
||||
int index;
|
||||
for (i = 0; i < n; i++) {
|
||||
// round robin
|
||||
index = (i + m_counter) % n;
|
||||
if (pfd[index].revents & POLLIN)
|
||||
break;
|
||||
}
|
||||
if (i == n)
|
||||
if ((pfd.revents & POLLIN) == 0)
|
||||
return 0;
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
@ -280,9 +254,9 @@ int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storag
|
|||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
int len = ::recvfrom(pfd[index].fd, (char*)buffer, length, 0, (sockaddr *)&address, &size);
|
||||
int len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&address, &size);
|
||||
#else
|
||||
ssize_t len = ::recvfrom(pfd[index].fd, (char*)buffer, length, 0, (sockaddr *)&address, &size);
|
||||
ssize_t len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&address, &size);
|
||||
#endif
|
||||
if (len <= 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
@ -291,7 +265,7 @@ int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storag
|
|||
LogError("Error returned from recvfrom, err: %d", errno);
|
||||
|
||||
if (len == -1 && errno == ENOTSOCK) {
|
||||
LogMessage("Re-opening UDP port on %u", m_port);
|
||||
LogMessage("Re-opening UDP port on %hu", m_localPort);
|
||||
close();
|
||||
open();
|
||||
}
|
||||
|
@ -299,43 +273,39 @@ int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storag
|
|||
return -1;
|
||||
}
|
||||
|
||||
m_counter++;
|
||||
address_length = size;
|
||||
addressLength = size;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
bool CUDPSocket::write(const unsigned char* buffer, unsigned int length, const sockaddr_storage& address, unsigned int address_length)
|
||||
bool CUDPSocket::write(const unsigned char* buffer, unsigned int length, const sockaddr_storage& address, unsigned int addressLength)
|
||||
{
|
||||
assert(buffer != NULL);
|
||||
assert(length > 0U);
|
||||
assert(m_fd >= 0);
|
||||
|
||||
bool result = false;
|
||||
|
||||
for (int i = 0; i < UDP_SOCKET_MAX; i++) {
|
||||
if (m_fd[i] < 0 || m_af[i] != address.ss_family)
|
||||
continue;
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
int ret = ::sendto(m_fd[i], (char *)buffer, length, 0, (sockaddr *)&address, address_length);
|
||||
int ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&address, addressLength);
|
||||
#else
|
||||
ssize_t ret = ::sendto(m_fd[i], (char *)buffer, length, 0, (sockaddr *)&address, address_length);
|
||||
ssize_t ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&address, addressLength);
|
||||
#endif
|
||||
|
||||
if (ret < 0) {
|
||||
if (ret < 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LogError("Error returned from sendto, err: %lu", ::GetLastError());
|
||||
LogError("Error returned from sendto, err: %lu", ::GetLastError());
|
||||
#else
|
||||
LogError("Error returned from sendto, err: %d", errno);
|
||||
LogError("Error returned from sendto, err: %d", errno);
|
||||
#endif
|
||||
} else {
|
||||
} else {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
if (ret == int(length))
|
||||
result = true;
|
||||
if (ret == int(length))
|
||||
result = true;
|
||||
#else
|
||||
if (ret == ssize_t(length))
|
||||
result = true;
|
||||
if (ret == ssize_t(length))
|
||||
result = true;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -343,18 +313,13 @@ bool CUDPSocket::write(const unsigned char* buffer, unsigned int length, const s
|
|||
|
||||
void CUDPSocket::close()
|
||||
{
|
||||
for (int i = 0; i < UDP_SOCKET_MAX; i++)
|
||||
close(m_fd[i]);
|
||||
}
|
||||
|
||||
void CUDPSocket::close(const unsigned int index)
|
||||
{
|
||||
if (m_fd[index] >= 0) {
|
||||
if (m_fd >= 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
::closesocket(m_fd[index]);
|
||||
::closesocket(m_fd);
|
||||
#else
|
||||
::close(m_fd[index]);
|
||||
::close(m_fd);
|
||||
#endif
|
||||
m_fd[index] = -1;
|
||||
m_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2011,2013,2015,2016,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2011,2013,2015,2016,2020,2024 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
|
||||
|
@ -35,10 +35,6 @@
|
|||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
#if !defined(UDP_SOCKET_MAX)
|
||||
#define UDP_SOCKET_MAX 1
|
||||
#endif
|
||||
|
||||
enum IPMATCHTYPE {
|
||||
IMT_ADDRESS_AND_PORT,
|
||||
IMT_ADDRESS_ONLY
|
||||
|
@ -46,38 +42,38 @@ enum IPMATCHTYPE {
|
|||
|
||||
class CUDPSocket {
|
||||
public:
|
||||
CUDPSocket(const std::string& address, unsigned int port = 0U);
|
||||
CUDPSocket(unsigned int port = 0U);
|
||||
CUDPSocket(const std::string& address, unsigned short port = 0U);
|
||||
CUDPSocket(unsigned short port = 0U);
|
||||
~CUDPSocket();
|
||||
|
||||
bool open(unsigned int af = AF_UNSPEC);
|
||||
bool open();
|
||||
bool open(const sockaddr_storage& address);
|
||||
bool open(const unsigned int index, const unsigned int af, const std::string& address, const unsigned int port);
|
||||
|
||||
int read(unsigned char* buffer, unsigned int length, sockaddr_storage& address, unsigned int &address_length);
|
||||
bool write(const unsigned char* buffer, unsigned int length, const sockaddr_storage& address, unsigned int address_length);
|
||||
int read(unsigned char* buffer, unsigned int length, sockaddr_storage& address, unsigned int &addressLength);
|
||||
bool write(const unsigned char* buffer, unsigned int length, const sockaddr_storage& address, unsigned int addressLength);
|
||||
|
||||
void close();
|
||||
void close(const unsigned int index);
|
||||
|
||||
static void startup();
|
||||
static void shutdown();
|
||||
|
||||
static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage& address, unsigned int& address_length);
|
||||
static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage& address, unsigned int& address_length, struct addrinfo& hints);
|
||||
static int lookup(const std::string& hostName, unsigned short port, sockaddr_storage& address, unsigned int& addressLength);
|
||||
static int lookup(const std::string& hostName, unsigned short port, sockaddr_storage& address, unsigned int& addressLength, struct addrinfo& hints);
|
||||
|
||||
static bool match(const sockaddr_storage& addr1, const sockaddr_storage& addr2, IPMATCHTYPE type = IMT_ADDRESS_AND_PORT);
|
||||
|
||||
static bool isNone(const sockaddr_storage& addr);
|
||||
|
||||
private:
|
||||
std::string m_address_save;
|
||||
unsigned short m_port_save;
|
||||
std::string m_address[UDP_SOCKET_MAX];
|
||||
unsigned short m_port[UDP_SOCKET_MAX];
|
||||
unsigned int m_af[UDP_SOCKET_MAX];
|
||||
int m_fd[UDP_SOCKET_MAX];
|
||||
unsigned int m_counter;
|
||||
std::string m_localAddress;
|
||||
unsigned short m_localPort;
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
SOCKET m_fd;
|
||||
int m_af;
|
||||
#else
|
||||
int m_fd;
|
||||
sa_family_t m_af;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015-2021,2023,2024 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
|
||||
|
@ -19,6 +19,6 @@
|
|||
#if !defined(VERSION_H)
|
||||
#define VERSION_H
|
||||
|
||||
const char* VERSION = "20201108";
|
||||
const char* VERSION = "20240129";
|
||||
|
||||
#endif
|
||||
|
|
|
@ -153,22 +153,22 @@ void CWiresX::setInfo(const std::string& name, unsigned int txFrequency, unsigne
|
|||
m_header[i + 14U] = m_node.at(i);
|
||||
}
|
||||
|
||||
void CWiresX::setParrot(const std::string& address, unsigned int port)
|
||||
void CWiresX::setParrot(const std::string& address, unsigned short port)
|
||||
{
|
||||
m_reflectors.setParrot(address, port);
|
||||
}
|
||||
|
||||
void CWiresX::setYSF2DMR(const std::string& address, unsigned int port)
|
||||
void CWiresX::setYSF2DMR(const std::string& address, unsigned short port)
|
||||
{
|
||||
m_reflectors.setYSF2DMR(address, port);
|
||||
}
|
||||
|
||||
void CWiresX::setYSF2NXDN(const std::string& address, unsigned int port)
|
||||
void CWiresX::setYSF2NXDN(const std::string& address, unsigned short port)
|
||||
{
|
||||
m_reflectors.setYSF2NXDN(address, port);
|
||||
}
|
||||
|
||||
void CWiresX::setYSF2P25(const std::string& address, unsigned int port)
|
||||
void CWiresX::setYSF2P25(const std::string& address, unsigned short port)
|
||||
{
|
||||
m_reflectors.setYSF2P25(address, port);
|
||||
}
|
||||
|
|
|
@ -51,10 +51,10 @@ public:
|
|||
~CWiresX();
|
||||
|
||||
void setInfo(const std::string& name, unsigned int txFrequency, unsigned int rxFrequency);
|
||||
void setParrot(const std::string& address, unsigned int port);
|
||||
void setYSF2DMR(const std::string& address, unsigned int port);
|
||||
void setYSF2NXDN(const std::string& address, unsigned int port);
|
||||
void setYSF2P25(const std::string& address, unsigned int port);
|
||||
void setParrot(const std::string& address, unsigned short port);
|
||||
void setYSF2DMR(const std::string& address, unsigned short port);
|
||||
void setYSF2NXDN(const std::string& address, unsigned short port);
|
||||
void setYSF2P25(const std::string& address, unsigned short port);
|
||||
void addFCSRoom(const std::string& id, const std::string& name);
|
||||
|
||||
bool start();
|
||||
|
|
|
@ -47,6 +47,6 @@ 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;
|
||||
const unsigned short FCS_PORT = 62500U;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "Timer.h"
|
||||
#include "Utils.h"
|
||||
#include "Log.h"
|
||||
#include "GitVersion.h"
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <Windows.h>
|
||||
|
@ -47,6 +48,7 @@ const char* DEFAULT_INI_FILE = "/etc/YSFGateway.ini";
|
|||
#include <cstring>
|
||||
#include <clocale>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
|
@ -55,7 +57,7 @@ int main(int argc, char** argv)
|
|||
for (int currentArg = 1; currentArg < argc; ++currentArg) {
|
||||
std::string arg = argv[currentArg];
|
||||
if ((arg == "-v") || (arg == "--version")) {
|
||||
::fprintf(stdout, "YSFGateway version %s\n", VERSION);
|
||||
::fprintf(stdout, "YSFGateway version %s git #%.7s\n", VERSION, gitversion);
|
||||
return 0;
|
||||
} else if (arg.substr(0, 1) == "-") {
|
||||
::fprintf(stderr, "Usage: YSFGateway [-v|--version] [filename]\n");
|
||||
|
@ -199,7 +201,7 @@ int CYSFGateway::run()
|
|||
}
|
||||
|
||||
std::string myAddress = m_conf.getMyAddress();
|
||||
unsigned int myPort = m_conf.getMyPort();
|
||||
unsigned short myPort = m_conf.getMyPort();
|
||||
CYSFNetwork rptNetwork(myAddress, myPort, m_callsign, debug);
|
||||
|
||||
ret = rptNetwork.setDestination("MMDVM", rptAddr, rptAddrLen);
|
||||
|
@ -211,7 +213,7 @@ int CYSFGateway::run()
|
|||
|
||||
bool ysfNetworkEnabled = m_conf.getYSFNetworkEnabled();
|
||||
if (ysfNetworkEnabled) {
|
||||
unsigned int ysfPort = m_conf.getYSFNetworkPort();
|
||||
unsigned short ysfPort = m_conf.getYSFNetworkPort();
|
||||
m_ysfNetwork = new CYSFNetwork(ysfPort, m_callsign, debug);
|
||||
}
|
||||
|
||||
|
@ -222,7 +224,7 @@ int CYSFGateway::run()
|
|||
std::string locator = calculateLocator();
|
||||
unsigned int id = m_conf.getId();
|
||||
|
||||
unsigned int fcsPort = m_conf.getFCSNetworkPort();
|
||||
unsigned short fcsPort = m_conf.getFCSNetworkPort();
|
||||
|
||||
m_fcsNetwork = new CFCSNetwork(fcsPort, m_callsign, rxFrequency, txFrequency, locator, id, debug);
|
||||
ret = m_fcsNetwork->open();
|
||||
|
@ -265,7 +267,8 @@ int CYSFGateway::run()
|
|||
CStopWatch stopWatch;
|
||||
stopWatch.start();
|
||||
|
||||
LogMessage("Starting YSFGateway-%s", VERSION);
|
||||
LogMessage("YSFGateway-%s is starting", VERSION);
|
||||
LogMessage("Built %s %s (GitID #%.7s)", __TIME__, __DATE__, gitversion);
|
||||
|
||||
for (;;) {
|
||||
unsigned char buffer[200U];
|
||||
|
@ -281,10 +284,13 @@ int CYSFGateway::run()
|
|||
CYSFReflector* reflector = m_wiresX->getReflector();
|
||||
if (m_ysfNetwork != NULL && m_linkType == LINK_YSF && wiresXCommandPassthrough && reflector->m_wiresX) {
|
||||
processDTMF(buffer, dt);
|
||||
m_exclude = processWiresX(buffer, fich, true, wiresXCommandPassthrough);
|
||||
processWiresX(buffer, fich, true, wiresXCommandPassthrough);
|
||||
} else {
|
||||
processDTMF(buffer, dt);
|
||||
m_exclude = processWiresX(buffer, fich, false, wiresXCommandPassthrough);
|
||||
processWiresX(buffer, fich, false, wiresXCommandPassthrough);
|
||||
reflector = m_wiresX->getReflector(); //reflector may have changed
|
||||
if (m_ysfNetwork != NULL && m_linkType == LINK_YSF && reflector->m_wiresX)
|
||||
m_exclude = (dt == YSF_DT_DATA_FR_MODE);
|
||||
}
|
||||
|
||||
if (m_gps != NULL)
|
||||
|
@ -454,7 +460,7 @@ void CYSFGateway::createGPS()
|
|||
return;
|
||||
|
||||
std::string address = m_conf.getAPRSAddress();
|
||||
unsigned int port = m_conf.getAPRSPort();
|
||||
unsigned short port = m_conf.getAPRSPort();
|
||||
std::string suffix = m_conf.getAPRSSuffix();
|
||||
bool debug = m_conf.getDebug();
|
||||
|
||||
|
@ -463,8 +469,10 @@ void CYSFGateway::createGPS()
|
|||
unsigned int txFrequency = m_conf.getTxFrequency();
|
||||
unsigned int rxFrequency = m_conf.getRxFrequency();
|
||||
std::string desc = m_conf.getAPRSDescription();
|
||||
std::string symbol = m_conf.getAPRSSymbol();
|
||||
|
||||
m_writer->setInfo(txFrequency, rxFrequency, desc, symbol);
|
||||
|
||||
m_writer->setInfo(txFrequency, rxFrequency, desc);
|
||||
|
||||
bool enabled = m_conf.getGPSDEnabled();
|
||||
if (enabled) {
|
||||
|
@ -503,7 +511,7 @@ void CYSFGateway::createWiresX(CYSFNetwork* rptNetwork)
|
|||
m_wiresX->setInfo(name, txFrequency, rxFrequency);
|
||||
|
||||
std::string address = m_conf.getYSFNetworkParrotAddress();
|
||||
unsigned int port = m_conf.getYSFNetworkParrotPort();
|
||||
unsigned short port = m_conf.getYSFNetworkParrotPort();
|
||||
if (port > 0U)
|
||||
m_wiresX->setParrot(address, port);
|
||||
|
||||
|
@ -530,10 +538,8 @@ void CYSFGateway::createWiresX(CYSFNetwork* rptNetwork)
|
|||
m_wiresX->start();
|
||||
}
|
||||
|
||||
bool CYSFGateway::processWiresX(const unsigned char* buffer, const CYSFFICH& fich, bool dontProcessWiresXLocal, bool wiresXCommandPassthrough)
|
||||
void CYSFGateway::processWiresX(const unsigned char* buffer, const CYSFFICH& fich, bool dontProcessWiresXLocal, bool wiresXCommandPassthrough)
|
||||
{
|
||||
bool ret=true;
|
||||
|
||||
assert(buffer != NULL);
|
||||
|
||||
WX_STATUS status = m_wiresX->process(buffer + 35U, buffer + 14U, fich, dontProcessWiresXLocal);
|
||||
|
@ -624,10 +630,8 @@ bool CYSFGateway::processWiresX(const unsigned char* buffer, const CYSFFICH& fic
|
|||
}
|
||||
break;
|
||||
default:
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CYSFGateway::processDTMF(unsigned char* buffer, unsigned char dt)
|
||||
|
@ -879,8 +883,10 @@ void CYSFGateway::processRemoteCommands()
|
|||
int res = m_remoteSocket->read(buffer, 200U, addr, addrLen);
|
||||
if (res > 0) {
|
||||
buffer[res] = '\0';
|
||||
if (::memcmp(buffer + 0U, "LinkYSF", 7U) == 0) {
|
||||
std::string id = std::string((char*)(buffer + 7U));
|
||||
if ((::memcmp(buffer + 0U, "LinkYSF", 7U) == 0) && (strlen((char*)buffer + 0U) > 8)) {
|
||||
std::string id = std::string((char*)(buffer + 8U));
|
||||
// Left trim
|
||||
id.erase(id.begin(), std::find_if(id.begin(), id.end(), [](unsigned char ch) { return !std::isspace(ch); }));
|
||||
CYSFReflector* reflector = m_reflectors->findById(id);
|
||||
if (reflector == NULL)
|
||||
reflector = m_reflectors->findByName(id);
|
||||
|
@ -908,8 +914,10 @@ void CYSFGateway::processRemoteCommands()
|
|||
LogWarning("Invalid YSF reflector id/name - \"%s\"", id.c_str());
|
||||
return;
|
||||
}
|
||||
} else if (::memcmp(buffer + 0U, "LinkFCS", 7U) == 0) {
|
||||
std::string raw = std::string((char*)(buffer + 7U));
|
||||
} else if ((::memcmp(buffer + 0U, "LinkFCS", 7U) == 0) && (strlen((char*)buffer + 0U) > 8)) {
|
||||
std::string raw = std::string((char*)(buffer + 8U));
|
||||
// Left trim
|
||||
raw.erase(raw.begin(), std::find_if(raw.begin(), raw.end(), [](unsigned char ch) { return !std::isspace(ch); }));
|
||||
std::string id = "FCS00";
|
||||
std::string idShort = "FCS";
|
||||
if (raw.length() == 3U) {
|
||||
|
@ -971,6 +979,13 @@ void CYSFGateway::processRemoteCommands()
|
|||
m_lostTimer.stop();
|
||||
m_linkType = LINK_NONE;
|
||||
}
|
||||
} else if (::memcmp(buffer + 0U, "status", 6U) == 0) {
|
||||
std::string state = std::string("ysf:") + (((m_ysfNetwork == NULL) && (m_fcsNetwork == NULL)) ? "n/a" : ((m_linkType != LINK_NONE) ? "conn" : "disc"));
|
||||
m_remoteSocket->write((unsigned char*)state.c_str(), (unsigned int)state.length(), addr, addrLen);
|
||||
} else if (::memcmp(buffer + 0U, "host", 4U) == 0) {
|
||||
std::string ref = ((((m_ysfNetwork == NULL) && (m_fcsNetwork == NULL)) || (m_linkType == LINK_NONE)) ? "NONE" : m_current);
|
||||
std::string host = std::string("ysf:\"") + ref + "\"";
|
||||
m_remoteSocket->write((unsigned char*)host.c_str(), (unsigned int)host.length(), addr, addrLen);
|
||||
} else {
|
||||
CUtils::dump("Invalid remote command received", buffer, res);
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ private:
|
|||
|
||||
void startupLinking();
|
||||
std::string calculateLocator();
|
||||
bool processWiresX(const unsigned char* buffer, const CYSFFICH& fich, bool dontProcessWiresXLocal, bool wiresXCommandPassthrough);
|
||||
void processWiresX(const unsigned char* buffer, const CYSFFICH& fich, bool dontProcessWiresXLocal, bool wiresXCommandPassthrough);
|
||||
void processDTMF(unsigned char* buffer, unsigned char dt);
|
||||
void createWiresX(CYSFNetwork* rptNetwork);
|
||||
void createGPS();
|
||||
|
|
|
@ -36,6 +36,7 @@ Address=127.0.0.1
|
|||
Port=8673
|
||||
Description=APRS Description
|
||||
Suffix=Y
|
||||
# Symbol="/r"
|
||||
|
||||
[Network]
|
||||
# Startup=FCS00120
|
||||
|
|
|
@ -94,6 +94,9 @@
|
|||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>prebuild.cmd</Command>
|
||||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
|
@ -108,6 +111,9 @@
|
|||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>prebuild.cmd</Command>
|
||||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
|
@ -126,6 +132,9 @@
|
|||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>prebuild.cmd</Command>
|
||||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
|
@ -144,6 +153,9 @@
|
|||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>prebuild.cmd</Command>
|
||||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="APRSWriter.h" />
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -27,7 +27,7 @@
|
|||
|
||||
const unsigned int BUFFER_LENGTH = 200U;
|
||||
|
||||
CYSFNetwork::CYSFNetwork(const std::string& address, unsigned int port, const std::string& callsign, bool debug) :
|
||||
CYSFNetwork::CYSFNetwork(const std::string& address, unsigned short port, const std::string& callsign, bool debug) :
|
||||
m_socket(address, port),
|
||||
m_debug(debug),
|
||||
m_addr(),
|
||||
|
@ -60,7 +60,7 @@ m_linked(false)
|
|||
}
|
||||
}
|
||||
|
||||
CYSFNetwork::CYSFNetwork(unsigned int port, const std::string& callsign, bool debug) :
|
||||
CYSFNetwork::CYSFNetwork(unsigned short port, const std::string& callsign, bool debug) :
|
||||
m_socket(port),
|
||||
m_debug(debug),
|
||||
m_addr(),
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
|
||||
class CYSFNetwork {
|
||||
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);
|
||||
CYSFNetwork(const std::string& address, unsigned short port, const std::string& callsign, bool debug);
|
||||
CYSFNetwork(unsigned short port, const std::string& callsign, bool debug);
|
||||
~CYSFNetwork();
|
||||
|
||||
bool setDestination(const std::string& name, const sockaddr_storage& addr, unsigned int addrLen);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2016-2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016-2021 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
|
||||
|
@ -76,25 +76,25 @@ static bool refComparison(const CYSFReflector* r1, const CYSFReflector* r2)
|
|||
return false;
|
||||
}
|
||||
|
||||
void CYSFReflectors::setParrot(const std::string& address, unsigned int port)
|
||||
void CYSFReflectors::setParrot(const std::string& address, unsigned short port)
|
||||
{
|
||||
m_parrotAddress = address;
|
||||
m_parrotPort = port;
|
||||
}
|
||||
|
||||
void CYSFReflectors::setYSF2DMR(const std::string& address, unsigned int port)
|
||||
void CYSFReflectors::setYSF2DMR(const std::string& address, unsigned short port)
|
||||
{
|
||||
m_YSF2DMRAddress = address;
|
||||
m_YSF2DMRPort = port;
|
||||
}
|
||||
|
||||
void CYSFReflectors::setYSF2NXDN(const std::string& address, unsigned int port)
|
||||
void CYSFReflectors::setYSF2NXDN(const std::string& address, unsigned short port)
|
||||
{
|
||||
m_YSF2NXDNAddress = address;
|
||||
m_YSF2NXDNPort = port;
|
||||
}
|
||||
|
||||
void CYSFReflectors::setYSF2P25(const std::string& address, unsigned int port)
|
||||
void CYSFReflectors::setYSF2P25(const std::string& address, unsigned short port)
|
||||
{
|
||||
m_YSF2P25Address = address;
|
||||
m_YSF2P25Port = port;
|
||||
|
@ -128,7 +128,7 @@ bool CYSFReflectors::load()
|
|||
|
||||
if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL && p6 != NULL) {
|
||||
std::string host = std::string(p4);
|
||||
unsigned int port = (unsigned int)::atoi(p5);
|
||||
unsigned short port = (unsigned short)::atoi(p5);
|
||||
|
||||
sockaddr_storage addr;
|
||||
unsigned int addrLen;
|
||||
|
@ -252,13 +252,19 @@ bool CYSFReflectors::load()
|
|||
}
|
||||
}
|
||||
|
||||
unsigned int id = 10U;
|
||||
for (std::vector<std::pair<std::string, std::string>>::const_iterator it = m_fcsRooms.cbegin(); it != m_fcsRooms.cend(); ++it, id++) {
|
||||
unsigned int id = 9U;
|
||||
for (std::vector<std::pair<std::string, std::string>>::const_iterator it1 = m_fcsRooms.cbegin(); it1 != m_fcsRooms.cend(); ++it1) {
|
||||
bool used;
|
||||
do {
|
||||
id++;
|
||||
used = findById(id);
|
||||
} while (used);
|
||||
|
||||
char text[10U];
|
||||
::sprintf(text, "%05u", id);
|
||||
|
||||
std::string name = it->first;
|
||||
std::string desc = it->second;
|
||||
std::string name = it1->first;
|
||||
std::string desc = it1->second;
|
||||
|
||||
CYSFReflector* refl = new CYSFReflector;
|
||||
refl->m_id = text;
|
||||
|
@ -303,6 +309,19 @@ CYSFReflector* CYSFReflectors::findById(const std::string& id)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool CYSFReflectors::findById(unsigned int id) const
|
||||
{
|
||||
char text[10U];
|
||||
::sprintf(text, "%05u", id);
|
||||
|
||||
for (std::vector<CYSFReflector*>::const_iterator it = m_newReflectors.cbegin(); it != m_newReflectors.cend(); ++it) {
|
||||
if (text == (*it)->m_id)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
CYSFReflector* CYSFReflectors::findByName(const std::string& name)
|
||||
{
|
||||
std::string fullName = name;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2016-2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016-2021 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
|
||||
|
@ -59,10 +59,10 @@ public:
|
|||
CYSFReflectors(const std::string& hostsFile, unsigned int reloadTime, bool makeUpper);
|
||||
~CYSFReflectors();
|
||||
|
||||
void setParrot(const std::string& address, unsigned int port);
|
||||
void setYSF2DMR(const std::string& address, unsigned int port);
|
||||
void setYSF2NXDN(const std::string& address, unsigned int port);
|
||||
void setYSF2P25(const std::string& address, unsigned int port);
|
||||
void setParrot(const std::string& address, unsigned short port);
|
||||
void setYSF2DMR(const std::string& address, unsigned short port);
|
||||
void setYSF2NXDN(const std::string& address, unsigned short port);
|
||||
void setYSF2P25(const std::string& address, unsigned short port);
|
||||
void addFCSRoom(const std::string& id, const std::string& name);
|
||||
|
||||
bool load();
|
||||
|
@ -81,19 +81,21 @@ public:
|
|||
private:
|
||||
std::string m_hostsFile;
|
||||
std::string m_parrotAddress;
|
||||
unsigned int m_parrotPort;
|
||||
unsigned short m_parrotPort;
|
||||
std::string m_YSF2DMRAddress;
|
||||
unsigned int m_YSF2DMRPort;
|
||||
unsigned short m_YSF2DMRPort;
|
||||
std::string m_YSF2NXDNAddress;
|
||||
unsigned int m_YSF2NXDNPort;
|
||||
unsigned short m_YSF2NXDNPort;
|
||||
std::string m_YSF2P25Address;
|
||||
unsigned int m_YSF2P25Port;
|
||||
unsigned short m_YSF2P25Port;
|
||||
std::vector<std::pair<std::string, std::string>> m_fcsRooms;
|
||||
std::vector<CYSFReflector*> m_newReflectors;
|
||||
std::vector<CYSFReflector*> m_currReflectors;
|
||||
std::vector<CYSFReflector*> m_search;
|
||||
bool m_makeUpper;
|
||||
CTimer m_timer;
|
||||
|
||||
bool findById(unsigned int id) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
38
YSFGateway/prebuild.cmd
Normal file
38
YSFGateway/prebuild.cmd
Normal file
|
@ -0,0 +1,38 @@
|
|||
@echo off
|
||||
REM This pre-build file is for MSVS VC++. It parses the git master hash and
|
||||
REM converts it into GitVersion.h for compiling into builds. [George M1GEO]
|
||||
|
||||
cd %1
|
||||
setlocal enabledelayedexpansion
|
||||
set HEADFILE=..\.git\HEAD
|
||||
set HASHFILE=0
|
||||
if exist %HEADFILE% (
|
||||
for /F "tokens=4 delims=/:" %%a in ('type %HEADFILE%') do set HEADBRANCH=%%a
|
||||
set HASHFILE=.git\refs\heads\!HEADBRANCH!
|
||||
echo Found Git HEAD file: %HEADFILE%
|
||||
echo Git HEAD branch: !HEADBRANCH!
|
||||
echo Git HASH file: !HASHFILE!
|
||||
call :USEHASH
|
||||
) else (
|
||||
echo No head file :(
|
||||
call :USENULL
|
||||
)
|
||||
|
||||
goto :EOF
|
||||
|
||||
:USENULL
|
||||
set GITHASH=0000000000000000000000000000000000000000
|
||||
goto :WRITEGITVERSIONHEADER
|
||||
|
||||
:USEHASH
|
||||
for /f %%i in ('type !HASHFILE!') do set GITHASH=%%i
|
||||
goto :WRITEGITVERSIONHEADER
|
||||
|
||||
:WRITEGITVERSIONHEADER
|
||||
echo // File contains Git commit ID SHA1 present at buildtime (prebuild.cmd) > GitVersion.h
|
||||
echo const char *gitversion = "%GITHASH%"; >> GitVersion.h
|
||||
echo Current Git HASH: %GITHASH%
|
||||
goto :FINISHED
|
||||
|
||||
:FINISHED
|
||||
echo GitVersion.h written...
|
|
@ -14,9 +14,21 @@ YSFParrot: $(OBJECTS)
|
|||
%.o: %.cpp
|
||||
$(CXX) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
YSFParrot.o: GitVersion.h FORCE
|
||||
|
||||
.PHONY: GitVersion.h
|
||||
|
||||
FORCE:
|
||||
|
||||
install:
|
||||
install -m 755 YSFParrot /usr/local/bin/
|
||||
|
||||
clean:
|
||||
$(RM) YSFParrot *.o *.d *.bak *~
|
||||
$(RM) YSFParrot *.o *.d *.bak *~ GitVersion.h
|
||||
|
||||
GitVersion.h:
|
||||
ifneq ("$(wildcard ../.git/index)","")
|
||||
echo "const char *gitversion = \"$(shell git rev-parse HEAD)\";" > $@
|
||||
else
|
||||
echo "const char *gitversion = \"0000000000000000000000000000000000000000\";" > $@
|
||||
endif
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
const unsigned int BUFFER_LENGTH = 200U;
|
||||
|
||||
CNetwork::CNetwork(unsigned int port) :
|
||||
CNetwork::CNetwork(unsigned short port) :
|
||||
m_socket(port),
|
||||
m_addr(),
|
||||
m_addrLen(0U)
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
class CNetwork {
|
||||
public:
|
||||
CNetwork(unsigned int port);
|
||||
CNetwork(unsigned short port);
|
||||
~CNetwork();
|
||||
|
||||
bool open();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2016,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2006-2016,2020,2024 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
|
||||
|
@ -33,30 +33,20 @@
|
|||
#define LogInfo(fmt, ...) ::fprintf(stderr, fmt "\n", ## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
CUDPSocket::CUDPSocket(const std::string& address, unsigned int port) :
|
||||
m_address_save(address),
|
||||
m_port_save(port),
|
||||
m_counter(0U)
|
||||
CUDPSocket::CUDPSocket(const std::string& address, unsigned short port) :
|
||||
m_localAddress(address),
|
||||
m_localPort(port),
|
||||
m_fd(-1),
|
||||
m_af(AF_UNSPEC)
|
||||
{
|
||||
for (int i = 0; i < UDP_SOCKET_MAX; i++) {
|
||||
m_address[i] = "";
|
||||
m_port[i] = 0U;
|
||||
m_af[i] = 0U;
|
||||
m_fd[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
CUDPSocket::CUDPSocket(unsigned int port) :
|
||||
m_address_save(),
|
||||
m_port_save(port),
|
||||
m_counter(0U)
|
||||
CUDPSocket::CUDPSocket(unsigned short port) :
|
||||
m_localAddress(),
|
||||
m_localPort(port),
|
||||
m_fd(-1),
|
||||
m_af(AF_UNSPEC)
|
||||
{
|
||||
for (int i = 0; i < UDP_SOCKET_MAX; i++) {
|
||||
m_address[i] = "";
|
||||
m_port[i] = 0U;
|
||||
m_af[i] = 0U;
|
||||
m_fd[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
CUDPSocket::~CUDPSocket()
|
||||
|
@ -80,7 +70,7 @@ void CUDPSocket::shutdown()
|
|||
#endif
|
||||
}
|
||||
|
||||
int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_storage& addr, unsigned int& address_length)
|
||||
int CUDPSocket::lookup(const std::string& hostname, unsigned short port, sockaddr_storage& addr, unsigned int& address_length)
|
||||
{
|
||||
struct addrinfo hints;
|
||||
::memset(&hints, 0, sizeof(hints));
|
||||
|
@ -88,15 +78,15 @@ int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_
|
|||
return lookup(hostname, port, addr, address_length, hints);
|
||||
}
|
||||
|
||||
int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_storage& addr, unsigned int& address_length, struct addrinfo& hints)
|
||||
int CUDPSocket::lookup(const std::string& hostname, unsigned short port, sockaddr_storage& addr, unsigned int& address_length, struct addrinfo& hints)
|
||||
{
|
||||
std::string portstr = std::to_string(port);
|
||||
struct addrinfo *res;
|
||||
|
||||
/* port is always digits, no needs to lookup service */
|
||||
/* Port is always digits, no needs to lookup service */
|
||||
hints.ai_flags |= AI_NUMERICSERV;
|
||||
|
||||
int err = getaddrinfo(hostname.empty() ? NULL : hostname.c_str(), portstr.c_str(), &hints, &res);
|
||||
int err = ::getaddrinfo(hostname.empty() ? NULL : hostname.c_str(), portstr.c_str(), &hints, &res);
|
||||
if (err != 0) {
|
||||
sockaddr_in* paddr = (sockaddr_in*)&addr;
|
||||
::memset(paddr, 0x00U, address_length = sizeof(sockaddr_in));
|
||||
|
@ -109,7 +99,7 @@ int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_
|
|||
|
||||
::memcpy(&addr, res->ai_addr, address_length = res->ai_addrlen);
|
||||
|
||||
freeaddrinfo(res);
|
||||
::freeaddrinfo(res);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -121,33 +111,33 @@ bool CUDPSocket::match(const sockaddr_storage& addr1, const sockaddr_storage& ad
|
|||
|
||||
if (type == IMT_ADDRESS_AND_PORT) {
|
||||
switch (addr1.ss_family) {
|
||||
case AF_INET:
|
||||
struct sockaddr_in *in_1, *in_2;
|
||||
in_1 = (struct sockaddr_in*)&addr1;
|
||||
in_2 = (struct sockaddr_in*)&addr2;
|
||||
return (in_1->sin_addr.s_addr == in_2->sin_addr.s_addr) && (in_1->sin_port == in_2->sin_port);
|
||||
case AF_INET6:
|
||||
struct sockaddr_in6 *in6_1, *in6_2;
|
||||
in6_1 = (struct sockaddr_in6*)&addr1;
|
||||
in6_2 = (struct sockaddr_in6*)&addr2;
|
||||
return IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr) && (in6_1->sin6_port == in6_2->sin6_port);
|
||||
default:
|
||||
return false;
|
||||
case AF_INET:
|
||||
struct sockaddr_in *in_1, *in_2;
|
||||
in_1 = (struct sockaddr_in*)&addr1;
|
||||
in_2 = (struct sockaddr_in*)&addr2;
|
||||
return (in_1->sin_addr.s_addr == in_2->sin_addr.s_addr) && (in_1->sin_port == in_2->sin_port);
|
||||
case AF_INET6:
|
||||
struct sockaddr_in6 *in6_1, *in6_2;
|
||||
in6_1 = (struct sockaddr_in6*)&addr1;
|
||||
in6_2 = (struct sockaddr_in6*)&addr2;
|
||||
return IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr) && (in6_1->sin6_port == in6_2->sin6_port);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else if (type == IMT_ADDRESS_ONLY) {
|
||||
switch (addr1.ss_family) {
|
||||
case AF_INET:
|
||||
struct sockaddr_in *in_1, *in_2;
|
||||
in_1 = (struct sockaddr_in*)&addr1;
|
||||
in_2 = (struct sockaddr_in*)&addr2;
|
||||
return in_1->sin_addr.s_addr == in_2->sin_addr.s_addr;
|
||||
case AF_INET6:
|
||||
struct sockaddr_in6 *in6_1, *in6_2;
|
||||
in6_1 = (struct sockaddr_in6*)&addr1;
|
||||
in6_2 = (struct sockaddr_in6*)&addr2;
|
||||
return IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr);
|
||||
default:
|
||||
return false;
|
||||
case AF_INET:
|
||||
struct sockaddr_in *in_1, *in_2;
|
||||
in_1 = (struct sockaddr_in*)&addr1;
|
||||
in_2 = (struct sockaddr_in*)&addr2;
|
||||
return in_1->sin_addr.s_addr == in_2->sin_addr.s_addr;
|
||||
case AF_INET6:
|
||||
struct sockaddr_in6 *in6_1, *in6_2;
|
||||
in6_1 = (struct sockaddr_in6*)&addr1;
|
||||
in6_2 = (struct sockaddr_in6*)&addr2;
|
||||
return IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
|
@ -163,33 +153,34 @@ bool CUDPSocket::isNone(const sockaddr_storage& addr)
|
|||
|
||||
bool CUDPSocket::open(const sockaddr_storage& address)
|
||||
{
|
||||
return open(address.ss_family);
|
||||
m_af = address.ss_family;
|
||||
|
||||
return open();
|
||||
}
|
||||
|
||||
bool CUDPSocket::open(unsigned int af)
|
||||
bool CUDPSocket::open()
|
||||
{
|
||||
return open(0, af, m_address_save, m_port_save);
|
||||
}
|
||||
assert(m_fd == -1);
|
||||
|
||||
bool CUDPSocket::open(const unsigned int index, const unsigned int af, const std::string& address, const unsigned int port)
|
||||
{
|
||||
sockaddr_storage addr;
|
||||
unsigned int addrlen;
|
||||
struct addrinfo hints;
|
||||
|
||||
::memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
hints.ai_family = af;
|
||||
hints.ai_family = m_af;
|
||||
|
||||
/* to determine protocol family, call lookup() first. */
|
||||
int err = lookup(address, port, addr, addrlen, hints);
|
||||
// To determine protocol family, call lookup() on the local address first.
|
||||
int err = lookup(m_localAddress, m_localPort, addr, addrlen, hints);
|
||||
if (err != 0) {
|
||||
LogError("The local address is invalid - %s", address.c_str());
|
||||
LogError("The local address is invalid - %s", m_localAddress.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
int fd = ::socket(addr.ss_family, SOCK_DGRAM, 0);
|
||||
if (fd < 0) {
|
||||
m_af = addr.ss_family;
|
||||
|
||||
m_fd = ::socket(m_af, SOCK_DGRAM, 0);
|
||||
if (m_fd < 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LogError("Cannot create the UDP socket, err: %lu", ::GetLastError());
|
||||
#else
|
||||
|
@ -198,62 +189,51 @@ bool CUDPSocket::open(const unsigned int index, const unsigned int af, const std
|
|||
return false;
|
||||
}
|
||||
|
||||
m_address[index] = address;
|
||||
m_port[index] = port;
|
||||
m_af[index] = addr.ss_family;
|
||||
m_fd[index] = fd;
|
||||
|
||||
if (port > 0U) {
|
||||
if (m_localPort > 0U) {
|
||||
int reuse = 1;
|
||||
if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(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
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (::bind(fd, (sockaddr*)&addr, addrlen) == -1) {
|
||||
if (::bind(m_fd, (sockaddr*)&addr, addrlen) == -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
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
LogInfo("Opening UDP port on %u", port);
|
||||
LogInfo("Opening UDP port on %hu", m_localPort);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storage& address, unsigned int &address_length)
|
||||
int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storage& address, unsigned int &addressLength)
|
||||
{
|
||||
assert(buffer != NULL);
|
||||
assert(length > 0U);
|
||||
assert(m_fd >= 0);
|
||||
|
||||
// Check that the readfrom() won't block
|
||||
int i, n;
|
||||
struct pollfd pfd[UDP_SOCKET_MAX];
|
||||
for (i = n = 0; i < UDP_SOCKET_MAX; i++) {
|
||||
if (m_fd[i] >= 0) {
|
||||
pfd[n].fd = m_fd[i];
|
||||
pfd[n].events = POLLIN;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
// no socket descriptor to receive
|
||||
if (n == 0)
|
||||
return 0;
|
||||
struct pollfd pfd;
|
||||
pfd.fd = m_fd;
|
||||
pfd.events = POLLIN;
|
||||
pfd.revents = 0;
|
||||
|
||||
// Return immediately
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
int ret = WSAPoll(pfd, n, 0);
|
||||
int ret = WSAPoll(&pfd, 1, 0);
|
||||
#else
|
||||
int ret = ::poll(pfd, n, 0);
|
||||
int ret = ::poll(&pfd, 1, 0);
|
||||
#endif
|
||||
if (ret < 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
@ -264,14 +244,7 @@ int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storag
|
|||
return -1;
|
||||
}
|
||||
|
||||
int index;
|
||||
for (i = 0; i < n; i++) {
|
||||
// round robin
|
||||
index = (i + m_counter) % n;
|
||||
if (pfd[index].revents & POLLIN)
|
||||
break;
|
||||
}
|
||||
if (i == n)
|
||||
if ((pfd.revents & POLLIN) == 0)
|
||||
return 0;
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
@ -281,9 +254,9 @@ int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storag
|
|||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
int len = ::recvfrom(pfd[index].fd, (char*)buffer, length, 0, (sockaddr *)&address, &size);
|
||||
int len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&address, &size);
|
||||
#else
|
||||
ssize_t len = ::recvfrom(pfd[index].fd, (char*)buffer, length, 0, (sockaddr *)&address, &size);
|
||||
ssize_t len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&address, &size);
|
||||
#endif
|
||||
if (len <= 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
@ -292,7 +265,7 @@ int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storag
|
|||
LogError("Error returned from recvfrom, err: %d", errno);
|
||||
|
||||
if (len == -1 && errno == ENOTSOCK) {
|
||||
LogMessage("Re-opening UDP port on %u", m_port);
|
||||
LogMessage("Re-opening UDP port on %hu", m_localPort);
|
||||
close();
|
||||
open();
|
||||
}
|
||||
|
@ -300,43 +273,39 @@ int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storag
|
|||
return -1;
|
||||
}
|
||||
|
||||
m_counter++;
|
||||
address_length = size;
|
||||
addressLength = size;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
bool CUDPSocket::write(const unsigned char* buffer, unsigned int length, const sockaddr_storage& address, unsigned int address_length)
|
||||
bool CUDPSocket::write(const unsigned char* buffer, unsigned int length, const sockaddr_storage& address, unsigned int addressLength)
|
||||
{
|
||||
assert(buffer != NULL);
|
||||
assert(length > 0U);
|
||||
assert(m_fd >= 0);
|
||||
|
||||
bool result = false;
|
||||
|
||||
for (int i = 0; i < UDP_SOCKET_MAX; i++) {
|
||||
if (m_fd[i] < 0 || m_af[i] != address.ss_family)
|
||||
continue;
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
int ret = ::sendto(m_fd[i], (char *)buffer, length, 0, (sockaddr *)&address, address_length);
|
||||
int ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&address, addressLength);
|
||||
#else
|
||||
ssize_t ret = ::sendto(m_fd[i], (char *)buffer, length, 0, (sockaddr *)&address, address_length);
|
||||
ssize_t ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&address, addressLength);
|
||||
#endif
|
||||
|
||||
if (ret < 0) {
|
||||
if (ret < 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LogError("Error returned from sendto, err: %lu", ::GetLastError());
|
||||
LogError("Error returned from sendto, err: %lu", ::GetLastError());
|
||||
#else
|
||||
LogError("Error returned from sendto, err: %d", errno);
|
||||
LogError("Error returned from sendto, err: %d", errno);
|
||||
#endif
|
||||
} else {
|
||||
} else {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
if (ret == int(length))
|
||||
result = true;
|
||||
if (ret == int(length))
|
||||
result = true;
|
||||
#else
|
||||
if (ret == ssize_t(length))
|
||||
result = true;
|
||||
if (ret == ssize_t(length))
|
||||
result = true;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -344,18 +313,13 @@ bool CUDPSocket::write(const unsigned char* buffer, unsigned int length, const s
|
|||
|
||||
void CUDPSocket::close()
|
||||
{
|
||||
for (int i = 0; i < UDP_SOCKET_MAX; i++)
|
||||
close(m_fd[i]);
|
||||
}
|
||||
|
||||
void CUDPSocket::close(const unsigned int index)
|
||||
{
|
||||
if (m_fd[index] >= 0) {
|
||||
if (m_fd >= 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
::closesocket(m_fd[index]);
|
||||
::closesocket(m_fd);
|
||||
#else
|
||||
::close(m_fd[index]);
|
||||
::close(m_fd);
|
||||
#endif
|
||||
m_fd[index] = -1;
|
||||
m_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2011,2013,2015,2016,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2011,2013,2015,2016,2020,2024 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
|
||||
|
@ -35,10 +35,6 @@
|
|||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
#if !defined(UDP_SOCKET_MAX)
|
||||
#define UDP_SOCKET_MAX 1
|
||||
#endif
|
||||
|
||||
enum IPMATCHTYPE {
|
||||
IMT_ADDRESS_AND_PORT,
|
||||
IMT_ADDRESS_ONLY
|
||||
|
@ -46,38 +42,38 @@ enum IPMATCHTYPE {
|
|||
|
||||
class CUDPSocket {
|
||||
public:
|
||||
CUDPSocket(const std::string& address, unsigned int port = 0U);
|
||||
CUDPSocket(unsigned int port = 0U);
|
||||
CUDPSocket(const std::string& address, unsigned short port = 0U);
|
||||
CUDPSocket(unsigned short port = 0U);
|
||||
~CUDPSocket();
|
||||
|
||||
bool open(unsigned int af = AF_UNSPEC);
|
||||
bool open();
|
||||
bool open(const sockaddr_storage& address);
|
||||
bool open(const unsigned int index, const unsigned int af, const std::string& address, const unsigned int port);
|
||||
|
||||
int read(unsigned char* buffer, unsigned int length, sockaddr_storage& address, unsigned int &address_length);
|
||||
bool write(const unsigned char* buffer, unsigned int length, const sockaddr_storage& address, unsigned int address_length);
|
||||
int read(unsigned char* buffer, unsigned int length, sockaddr_storage& address, unsigned int &addressLength);
|
||||
bool write(const unsigned char* buffer, unsigned int length, const sockaddr_storage& address, unsigned int addressLength);
|
||||
|
||||
void close();
|
||||
void close(const unsigned int index);
|
||||
|
||||
static void startup();
|
||||
static void shutdown();
|
||||
|
||||
static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage& address, unsigned int& address_length);
|
||||
static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage& address, unsigned int& address_length, struct addrinfo& hints);
|
||||
static int lookup(const std::string& hostName, unsigned short port, sockaddr_storage& address, unsigned int& addressLength);
|
||||
static int lookup(const std::string& hostName, unsigned short port, sockaddr_storage& address, unsigned int& addressLength, struct addrinfo& hints);
|
||||
|
||||
static bool match(const sockaddr_storage& addr1, const sockaddr_storage& addr2, IPMATCHTYPE type = IMT_ADDRESS_AND_PORT);
|
||||
|
||||
static bool isNone(const sockaddr_storage& addr);
|
||||
|
||||
private:
|
||||
std::string m_address_save;
|
||||
unsigned short m_port_save;
|
||||
std::string m_address[UDP_SOCKET_MAX];
|
||||
unsigned short m_port[UDP_SOCKET_MAX];
|
||||
unsigned int m_af[UDP_SOCKET_MAX];
|
||||
int m_fd[UDP_SOCKET_MAX];
|
||||
unsigned int m_counter;
|
||||
std::string m_localAddress;
|
||||
unsigned short m_localPort;
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
SOCKET m_fd;
|
||||
int m_af;
|
||||
#else
|
||||
int m_fd;
|
||||
sa_family_t m_af;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2020,2024 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
|
||||
|
@ -19,6 +19,6 @@
|
|||
#if !defined(VERSION_H)
|
||||
#define VERSION_H
|
||||
|
||||
const char* VERSION = "20201101";
|
||||
const char* VERSION = "20240129";
|
||||
|
||||
#endif
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "Version.h"
|
||||
#include "Thread.h"
|
||||
#include "Timer.h"
|
||||
#include "GitVersion.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
@ -30,24 +31,32 @@
|
|||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc == 1) {
|
||||
::fprintf(stderr, "Usage: YSFParrot [-d|--debug] <port>\n");
|
||||
return 1;
|
||||
if (argc > 1) {
|
||||
for (int currentArg = 1; currentArg < argc; ++currentArg) {
|
||||
std::string arg = argv[currentArg];
|
||||
if ((arg == "-v") || (arg == "--version")) {
|
||||
::fprintf(stdout, "YSFParrot version %s git #%.7s\n", VERSION, gitversion);
|
||||
return 0;
|
||||
} else if (arg.substr(0, 1) == "-") {
|
||||
::fprintf(stderr, "Usage: YSFParrot [-v|--version] [-d|--debug] <port>\n");
|
||||
return 1;
|
||||
} else {
|
||||
unsigned short port = (unsigned short)::atoi(argv[1U]);
|
||||
if (port == 0U) {
|
||||
::fprintf(stderr, "YSFParrot: invalid port number - %s\n", argv[1U]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
CYSFParrot parrot(port);
|
||||
parrot.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int port = ::atoi(argv[1U]);
|
||||
if (port == 0U) {
|
||||
::fprintf(stderr, "YSFParrot: invalid port number - %s\n", argv[1U]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
CYSFParrot parrot(port);
|
||||
parrot.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CYSFParrot::CYSFParrot(unsigned int port) :
|
||||
CYSFParrot::CYSFParrot(unsigned short port) :
|
||||
m_port(port)
|
||||
{
|
||||
CUDPSocket::startup();
|
||||
|
@ -77,7 +86,8 @@ void CYSFParrot::run()
|
|||
unsigned int count = 0U;
|
||||
bool playing = false;
|
||||
|
||||
::fprintf(stdout, "Starting YSFParrot-%s\n", VERSION);
|
||||
::fprintf(stdout, "YSFParrot-%s is starting", VERSION);
|
||||
::fprintf(stdout, "Built %s %s (GitID #%.7s)", __TIME__, __DATE__, gitversion);
|
||||
|
||||
for (;;) {
|
||||
unsigned char buffer[200U];
|
||||
|
|
|
@ -22,13 +22,13 @@
|
|||
class CYSFParrot
|
||||
{
|
||||
public:
|
||||
CYSFParrot(unsigned int port);
|
||||
CYSFParrot(unsigned short port);
|
||||
~CYSFParrot();
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
unsigned int m_port;
|
||||
unsigned short m_port;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -94,6 +94,9 @@
|
|||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>prebuild.cmd</Command>
|
||||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
|
@ -108,6 +111,9 @@
|
|||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>prebuild.cmd</Command>
|
||||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
|
@ -126,6 +132,9 @@
|
|||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>prebuild.cmd</Command>
|
||||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
|
@ -144,6 +153,9 @@
|
|||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>prebuild.cmd</Command>
|
||||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="StopWatch.h" />
|
||||
|
|
38
YSFParrot/prebuild.cmd
Normal file
38
YSFParrot/prebuild.cmd
Normal file
|
@ -0,0 +1,38 @@
|
|||
@echo off
|
||||
REM This pre-build file is for MSVS VC++. It parses the git master hash and
|
||||
REM converts it into GitVersion.h for compiling into builds. [George M1GEO]
|
||||
|
||||
cd %1
|
||||
setlocal enabledelayedexpansion
|
||||
set HEADFILE=..\.git\HEAD
|
||||
set HASHFILE=0
|
||||
if exist %HEADFILE% (
|
||||
for /F "tokens=4 delims=/:" %%a in ('type %HEADFILE%') do set HEADBRANCH=%%a
|
||||
set HASHFILE=.git\refs\heads\!HEADBRANCH!
|
||||
echo Found Git HEAD file: %HEADFILE%
|
||||
echo Git HEAD branch: !HEADBRANCH!
|
||||
echo Git HASH file: !HASHFILE!
|
||||
call :USEHASH
|
||||
) else (
|
||||
echo No head file :(
|
||||
call :USENULL
|
||||
)
|
||||
|
||||
goto :EOF
|
||||
|
||||
:USENULL
|
||||
set GITHASH=0000000000000000000000000000000000000000
|
||||
goto :WRITEGITVERSIONHEADER
|
||||
|
||||
:USEHASH
|
||||
for /f %%i in ('type !HASHFILE!') do set GITHASH=%%i
|
||||
goto :WRITEGITVERSIONHEADER
|
||||
|
||||
:WRITEGITVERSIONHEADER
|
||||
echo // File contains Git commit ID SHA1 present at buildtime (prebuild.cmd) > GitVersion.h
|
||||
echo const char *gitversion = "%GITHASH%"; >> GitVersion.h
|
||||
echo Current Git HASH: %GITHASH%
|
||||
goto :FINISHED
|
||||
|
||||
:FINISHED
|
||||
echo GitVersion.h written...
|
|
@ -1,200 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015,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 "Conf.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
|
||||
const int BUFFER_SIZE = 500;
|
||||
|
||||
enum SECTION {
|
||||
SECTION_NONE,
|
||||
SECTION_GENERAL,
|
||||
SECTION_INFO,
|
||||
SECTION_LOG,
|
||||
SECTION_NETWORK
|
||||
};
|
||||
|
||||
CConf::CConf(const std::string& file) :
|
||||
m_file(file),
|
||||
m_daemon(false),
|
||||
m_id(0U),
|
||||
m_name(),
|
||||
m_description(),
|
||||
m_logDisplayLevel(0U),
|
||||
m_logFileLevel(0U),
|
||||
m_logFilePath(),
|
||||
m_logFileRoot(),
|
||||
m_logFileRotate(true),
|
||||
m_networkPort(0U),
|
||||
m_networkDebug(false)
|
||||
{
|
||||
}
|
||||
|
||||
CConf::~CConf()
|
||||
{
|
||||
}
|
||||
|
||||
bool CConf::read()
|
||||
{
|
||||
FILE* fp = ::fopen(m_file.c_str(), "rt");
|
||||
if (fp == NULL) {
|
||||
::fprintf(stderr, "Couldn't open the .ini file - %s\n", m_file.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
SECTION section = SECTION_NONE;
|
||||
|
||||
char buffer[BUFFER_SIZE];
|
||||
while (::fgets(buffer, BUFFER_SIZE, fp) != NULL) {
|
||||
if (buffer[0U] == '#')
|
||||
continue;
|
||||
|
||||
if (buffer[0U] == '[') {
|
||||
if (::strncmp(buffer, "[General]", 9U) == 0)
|
||||
section = SECTION_GENERAL;
|
||||
else if (::strncmp(buffer, "[Info]", 6U) == 0)
|
||||
section = SECTION_INFO;
|
||||
else if (::strncmp(buffer, "[Log]", 5U) == 0)
|
||||
section = SECTION_LOG;
|
||||
else if (::strncmp(buffer, "[Network]", 9U) == 0)
|
||||
section = SECTION_NETWORK;
|
||||
else
|
||||
section = SECTION_NONE;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
char* key = ::strtok(buffer, " \t=\r\n");
|
||||
if (key == NULL)
|
||||
continue;
|
||||
|
||||
char* value = ::strtok(NULL, "\r\n");
|
||||
if (value == NULL)
|
||||
continue;
|
||||
|
||||
// Remove quotes from the value
|
||||
size_t len = ::strlen(value);
|
||||
if (len > 1U && *value == '"' && value[len - 1U] == '"') {
|
||||
value[len - 1U] = '\0';
|
||||
value++;
|
||||
} else {
|
||||
char *p;
|
||||
|
||||
// if value is not quoted, remove after # (to make comment)
|
||||
if ((p = strchr(value, '#')) != NULL)
|
||||
*p = '\0';
|
||||
|
||||
// remove trailing tab/space
|
||||
for (p = value + strlen(value) - 1U; p >= value && (*p == '\t' || *p == ' '); p--)
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
if (section == SECTION_GENERAL) {
|
||||
if (::strcmp(key, "Daemon") == 0)
|
||||
m_daemon = ::atoi(value) == 1;
|
||||
} else if (section == SECTION_INFO) {
|
||||
if (::strcmp(key, "Id") == 0)
|
||||
m_id = (unsigned int)::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 (::strcmp(key, "FileRotate") == 0)
|
||||
m_logFileRotate = ::atoi(value) == 1;
|
||||
} else if (section == SECTION_NETWORK) {
|
||||
if (::strcmp(key, "Port") == 0)
|
||||
m_networkPort = (unsigned int)::atoi(value);
|
||||
else if (::strcmp(key, "Debug") == 0)
|
||||
m_networkDebug = ::atoi(value) == 1;
|
||||
}
|
||||
}
|
||||
|
||||
::fclose(fp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CConf::getDaemon() const
|
||||
{
|
||||
return m_daemon;
|
||||
}
|
||||
|
||||
unsigned int CConf::getId() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
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::getLogFileRotate() const
|
||||
{
|
||||
return m_logFileRotate;
|
||||
}
|
||||
|
||||
unsigned int CConf::getNetworkPort() const
|
||||
{
|
||||
return m_networkPort;
|
||||
}
|
||||
|
||||
bool CConf::getNetworkDebug() const
|
||||
{
|
||||
return m_networkDebug;
|
||||
}
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015,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(CONF_H)
|
||||
#define CONF_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class CConf
|
||||
{
|
||||
public:
|
||||
CConf(const std::string& file);
|
||||
~CConf();
|
||||
|
||||
bool read();
|
||||
|
||||
// The General section
|
||||
bool getDaemon() const;
|
||||
|
||||
// The Info section
|
||||
unsigned int getId() 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;
|
||||
bool getLogFileRotate() const;
|
||||
|
||||
// The Network section
|
||||
unsigned int getNetworkPort() const;
|
||||
bool getNetworkDebug() const;
|
||||
|
||||
private:
|
||||
std::string m_file;
|
||||
bool m_daemon;
|
||||
|
||||
unsigned int m_id;
|
||||
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_logFileRotate;
|
||||
|
||||
unsigned int m_networkPort;
|
||||
bool m_networkDebug;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,192 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015,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 "Log.h"
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#include <unistd.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 bool m_fileRotate = true;
|
||||
|
||||
static FILE* m_fpLog = NULL;
|
||||
static bool m_daemon = false;
|
||||
|
||||
static unsigned int m_displayLevel = 2U;
|
||||
|
||||
static struct tm m_tm;
|
||||
|
||||
static char LEVELS[] = " DMIWEF";
|
||||
|
||||
static bool logOpenRotate()
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
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[200U];
|
||||
#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
|
||||
|
||||
if ((m_fpLog = ::fopen(filename, "a+t")) != NULL) {
|
||||
status = true;
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
if (m_daemon)
|
||||
dup2(fileno(m_fpLog), fileno(stderr));
|
||||
#endif
|
||||
}
|
||||
|
||||
m_tm = *tm;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static bool logOpenNoRotate()
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
if (m_fileLevel == 0U)
|
||||
return true;
|
||||
|
||||
if (m_fpLog != NULL)
|
||||
return true;
|
||||
|
||||
char filename[200U];
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
::sprintf(filename, "%s\\%s.log", m_filePath.c_str(), m_fileRoot.c_str());
|
||||
#else
|
||||
::sprintf(filename, "%s/%s.log", m_filePath.c_str(), m_fileRoot.c_str());
|
||||
#endif
|
||||
|
||||
if ((m_fpLog = ::fopen(filename, "a+t")) != NULL) {
|
||||
status = true;
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
if (m_daemon)
|
||||
dup2(fileno(m_fpLog), fileno(stderr));
|
||||
#endif
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool LogOpen()
|
||||
{
|
||||
if (m_fileRotate)
|
||||
return logOpenRotate();
|
||||
else
|
||||
return logOpenNoRotate();
|
||||
}
|
||||
|
||||
bool LogInitialise(bool daemon, const std::string& filePath, const std::string& fileRoot, unsigned int fileLevel, unsigned int displayLevel, bool rotate)
|
||||
{
|
||||
m_filePath = filePath;
|
||||
m_fileRoot = fileRoot;
|
||||
m_fileLevel = fileLevel;
|
||||
m_displayLevel = displayLevel;
|
||||
m_daemon = daemon;
|
||||
m_fileRotate = rotate;
|
||||
|
||||
if (m_daemon)
|
||||
m_displayLevel = 0U;
|
||||
|
||||
return ::LogOpen();
|
||||
}
|
||||
|
||||
void LogFinalise()
|
||||
{
|
||||
if (m_fpLog != NULL)
|
||||
::fclose(m_fpLog);
|
||||
}
|
||||
|
||||
void Log(unsigned int level, const char* fmt, ...)
|
||||
{
|
||||
assert(fmt != NULL);
|
||||
|
||||
char buffer[501U];
|
||||
#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.%03ld ", 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 / 1000L);
|
||||
#endif
|
||||
|
||||
va_list vl;
|
||||
va_start(vl, fmt);
|
||||
|
||||
::vsnprintf(buffer + ::strlen(buffer), 500, 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);
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015,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(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(bool daemon, const std::string& filePath, const std::string& fileRoot, unsigned int fileLevel, unsigned int displayLevel, bool rotate);
|
||||
extern void LogFinalise();
|
||||
|
||||
#endif
|
|
@ -1,22 +0,0 @@
|
|||
CC = cc
|
||||
CXX = c++
|
||||
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -DUDP_SOCKET_MAX=2
|
||||
LIBS = -lpthread
|
||||
LDFLAGS = -g
|
||||
|
||||
OBJECTS = Conf.o Log.o Network.o StopWatch.o Thread.o Timer.o UDPSocket.o Utils.o YSFReflector.o
|
||||
|
||||
all: YSFReflector
|
||||
|
||||
YSFReflector: $(OBJECTS)
|
||||
$(CXX) $(OBJECTS) $(CFLAGS) $(LIBS) -o YSFReflector
|
||||
|
||||
%.o: %.cpp
|
||||
$(CXX) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
install:
|
||||
install -m 755 YSFReflector /usr/local/bin/
|
||||
|
||||
clean:
|
||||
$(RM) YSFReflector *.o *.d *.bak *~
|
||||
|
|
@ -1,155 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2014,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 "YSFDefines.h"
|
||||
#include "Network.h"
|
||||
#include "Utils.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
CNetwork::CNetwork(unsigned int port, unsigned int id, const std::string& name, const std::string& description, bool debug) :
|
||||
m_socket(),
|
||||
m_port(port),
|
||||
m_id(id),
|
||||
m_name(name),
|
||||
m_description(description),
|
||||
m_callsign(),
|
||||
m_debug(debug),
|
||||
m_status(NULL)
|
||||
{
|
||||
m_name.resize(16U, ' ');
|
||||
m_description.resize(14U, ' ');
|
||||
|
||||
m_status = new unsigned char[50U];
|
||||
}
|
||||
|
||||
CNetwork::~CNetwork()
|
||||
{
|
||||
delete[] m_status;
|
||||
}
|
||||
|
||||
bool CNetwork::open()
|
||||
{
|
||||
LogInfo("Opening YSF network connection");
|
||||
|
||||
bool status = false;
|
||||
unsigned int af[] = {AF_INET, AF_INET6};
|
||||
|
||||
for (unsigned int i = 0U; i < UDP_SOCKET_MAX && i < (sizeof(af) / sizeof(unsigned int)); i++)
|
||||
status |= m_socket.open(i, af[i], "", m_port);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool CNetwork::writeData(const unsigned char* data, const sockaddr_storage& addr, unsigned int addrLen)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "YSF Network Data Sent", data, 155U);
|
||||
|
||||
return m_socket.write(data, 155U, addr, addrLen);
|
||||
}
|
||||
|
||||
bool CNetwork::writePoll(const sockaddr_storage& addr, unsigned int addrLen)
|
||||
{
|
||||
unsigned char buffer[20U];
|
||||
|
||||
buffer[0] = 'Y';
|
||||
buffer[1] = 'S';
|
||||
buffer[2] = 'F';
|
||||
buffer[3] = 'P';
|
||||
|
||||
buffer[4U] = 'R';
|
||||
buffer[5U] = 'E';
|
||||
buffer[6U] = 'F';
|
||||
buffer[7U] = 'L';
|
||||
buffer[8U] = 'E';
|
||||
buffer[9U] = 'C';
|
||||
buffer[10U] = 'T';
|
||||
buffer[11U] = 'O';
|
||||
buffer[12U] = 'R';
|
||||
buffer[13U] = ' ';
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "YSF Network Poll Sent", buffer, 14U);
|
||||
|
||||
return m_socket.write(buffer, 14U, addr, addrLen);
|
||||
}
|
||||
|
||||
unsigned int CNetwork::readData(unsigned char* data, unsigned int length, sockaddr_storage& addr, unsigned int& addrLen)
|
||||
{
|
||||
assert(data != NULL);
|
||||
assert(length > 0U);
|
||||
|
||||
int len = m_socket.read(data, length, addr, addrLen);
|
||||
if (len <= 0)
|
||||
return 0U;
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "YSF Network Data Received", data, len);
|
||||
|
||||
// Throw away any options messages
|
||||
if (::memcmp(data, "YSFO", 4U) == 0)
|
||||
return 0U;
|
||||
|
||||
// Throw away any info messages
|
||||
if (::memcmp(data, "YSFI", 4U) == 0)
|
||||
return 0U;
|
||||
|
||||
// Handle incoming status requests
|
||||
if (::memcmp(data, "YSFS", 4U) == 0) {
|
||||
m_socket.write(m_status, 42U, addr, addrLen);
|
||||
return 0U;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void CNetwork::setCount(unsigned int count)
|
||||
{
|
||||
if (count > 999U)
|
||||
count = 999U;
|
||||
|
||||
unsigned int hash = m_id;
|
||||
|
||||
if (hash == 0U) {
|
||||
for (unsigned int i = 0U; i < m_name.size(); i++) {
|
||||
hash += m_name.at(i);
|
||||
hash += (hash << 10);
|
||||
hash ^= (hash >> 6);
|
||||
}
|
||||
|
||||
// Final avalanche
|
||||
hash += (hash << 3);
|
||||
hash ^= (hash >> 11);
|
||||
hash += (hash << 15);
|
||||
}
|
||||
|
||||
::sprintf((char*)m_status, "YSFS%05u%16.16s%14.14s%03u", hash % 100000U, m_name.c_str(), m_description.c_str(), count);
|
||||
}
|
||||
|
||||
void CNetwork::close()
|
||||
{
|
||||
m_socket.close();
|
||||
|
||||
LogInfo("Closing YSF network connection");
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2014,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.
|
||||
*/
|
||||
|
||||
#ifndef Network_H
|
||||
#define Network_H
|
||||
|
||||
#include "YSFDefines.h"
|
||||
#include "UDPSocket.h"
|
||||
#include "Timer.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
class CNetwork {
|
||||
public:
|
||||
CNetwork(unsigned int port, unsigned int id, const std::string& name, const std::string& description, bool debug);
|
||||
~CNetwork();
|
||||
|
||||
bool open();
|
||||
|
||||
bool writeData(const unsigned char* data, const sockaddr_storage& addr, unsigned int addrLen);
|
||||
bool writePoll(const sockaddr_storage& addr, unsigned int addrLen);
|
||||
|
||||
unsigned int readData(unsigned char* data, unsigned int length, sockaddr_storage& addr, unsigned int& addrLen);
|
||||
|
||||
void close();
|
||||
|
||||
void setCount(unsigned int count);
|
||||
|
||||
private:
|
||||
CUDPSocket m_socket;
|
||||
unsigned short m_port;
|
||||
unsigned int m_id;
|
||||
std::string m_name;
|
||||
std::string m_description;
|
||||
std::string m_callsign;
|
||||
bool m_debug;
|
||||
unsigned char* m_status;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,105 +0,0 @@
|
|||
/*
|
||||
* 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
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* 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 <WS2tcpip.h>
|
||||
#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
|
|
@ -1,107 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015,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 "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)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
ts.tv_sec = ms / 1000U;
|
||||
ts.tv_nsec = (ms % 1000U) * 1000000U;
|
||||
|
||||
::nanosleep(&ts, NULL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* 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
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
/*
|
||||
* 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
|
|
@ -1,388 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2006-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 "UDPSocket.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_LOG_H)
|
||||
#include "Log.h"
|
||||
#else
|
||||
#define LogError(fmt, ...) ::fprintf(stderr, fmt "\n", ## __VA_ARGS__)
|
||||
#define LogInfo(fmt, ...) ::fprintf(stderr, fmt "\n", ## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
CUDPSocket::CUDPSocket(const std::string& address, unsigned int port) :
|
||||
m_address_save(address),
|
||||
m_port_save(port),
|
||||
m_counter(0U)
|
||||
{
|
||||
for (int i = 0; i < UDP_SOCKET_MAX; i++) {
|
||||
m_address[i] = "";
|
||||
m_port[i] = 0U;
|
||||
m_af[i] = 0U;
|
||||
m_fd[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
CUDPSocket::CUDPSocket(unsigned int port) :
|
||||
m_address_save(),
|
||||
m_port_save(port),
|
||||
m_counter(0U)
|
||||
{
|
||||
for (int i = 0; i < UDP_SOCKET_MAX; i++) {
|
||||
m_address[i] = "";
|
||||
m_port[i] = 0U;
|
||||
m_af[i] = 0U;
|
||||
m_fd[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
CUDPSocket::~CUDPSocket()
|
||||
{
|
||||
}
|
||||
|
||||
void CUDPSocket::startup()
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
WSAData data;
|
||||
int wsaRet = ::WSAStartup(MAKEWORD(2, 2), &data);
|
||||
if (wsaRet != 0)
|
||||
LogError("Error from WSAStartup");
|
||||
#endif
|
||||
}
|
||||
|
||||
void CUDPSocket::shutdown()
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
::WSACleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_storage& addr, unsigned int& address_length)
|
||||
{
|
||||
struct addrinfo hints;
|
||||
::memset(&hints, 0, sizeof(hints));
|
||||
|
||||
return lookup(hostname, port, addr, address_length, hints);
|
||||
}
|
||||
|
||||
int CUDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_storage& addr, unsigned int& address_length, struct addrinfo& hints)
|
||||
{
|
||||
std::string portstr = std::to_string(port);
|
||||
struct addrinfo *res;
|
||||
|
||||
/* port is always digits, no needs to lookup service */
|
||||
hints.ai_flags |= AI_NUMERICSERV;
|
||||
|
||||
int err = getaddrinfo(hostname.empty() ? NULL : hostname.c_str(), portstr.c_str(), &hints, &res);
|
||||
if (err != 0) {
|
||||
sockaddr_in* paddr = (sockaddr_in*)&addr;
|
||||
::memset(paddr, 0x00U, address_length = sizeof(sockaddr_in));
|
||||
paddr->sin_family = AF_INET;
|
||||
paddr->sin_port = htons(port);
|
||||
paddr->sin_addr.s_addr = htonl(INADDR_NONE);
|
||||
LogError("Cannot find address for host %s", hostname.c_str());
|
||||
return err;
|
||||
}
|
||||
|
||||
::memcpy(&addr, res->ai_addr, address_length = res->ai_addrlen);
|
||||
|
||||
freeaddrinfo(res);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CUDPSocket::match(const sockaddr_storage& addr1, const sockaddr_storage& addr2, IPMATCHTYPE type)
|
||||
{
|
||||
if (addr1.ss_family != addr2.ss_family)
|
||||
return false;
|
||||
|
||||
if (type == IMT_ADDRESS_AND_PORT) {
|
||||
switch (addr1.ss_family) {
|
||||
case AF_INET:
|
||||
struct sockaddr_in *in_1, *in_2;
|
||||
in_1 = (struct sockaddr_in*)&addr1;
|
||||
in_2 = (struct sockaddr_in*)&addr2;
|
||||
return (in_1->sin_addr.s_addr == in_2->sin_addr.s_addr) && (in_1->sin_port == in_2->sin_port);
|
||||
case AF_INET6:
|
||||
struct sockaddr_in6 *in6_1, *in6_2;
|
||||
in6_1 = (struct sockaddr_in6*)&addr1;
|
||||
in6_2 = (struct sockaddr_in6*)&addr2;
|
||||
return IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr) && (in6_1->sin6_port == in6_2->sin6_port);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else if (type == IMT_ADDRESS_ONLY) {
|
||||
switch (addr1.ss_family) {
|
||||
case AF_INET:
|
||||
struct sockaddr_in *in_1, *in_2;
|
||||
in_1 = (struct sockaddr_in*)&addr1;
|
||||
in_2 = (struct sockaddr_in*)&addr2;
|
||||
return in_1->sin_addr.s_addr == in_2->sin_addr.s_addr;
|
||||
case AF_INET6:
|
||||
struct sockaddr_in6 *in6_1, *in6_2;
|
||||
in6_1 = (struct sockaddr_in6*)&addr1;
|
||||
in6_2 = (struct sockaddr_in6*)&addr2;
|
||||
return IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CUDPSocket::isNone(const sockaddr_storage& addr)
|
||||
{
|
||||
struct sockaddr_in *in = (struct sockaddr_in *)&addr;
|
||||
|
||||
return ((addr.ss_family == AF_INET) && (in->sin_addr.s_addr == htonl(INADDR_NONE)));
|
||||
}
|
||||
|
||||
char* CUDPSocket::display(const sockaddr_storage& addr, char* buffer, unsigned int length)
|
||||
{
|
||||
assert(buffer != NULL);
|
||||
assert(length > INET6_ADDRSTRLEN);
|
||||
|
||||
switch (addr.ss_family) {
|
||||
case AF_INET: {
|
||||
struct sockaddr_in* in4 = (struct sockaddr_in*)&addr;
|
||||
::inet_ntop(AF_INET, &in4, buffer, length);
|
||||
::sprintf(buffer + ::strlen(buffer), ":%u", in4->sin_port);
|
||||
}
|
||||
break;
|
||||
|
||||
case AF_INET6: {
|
||||
struct sockaddr_in6* in6 = (struct sockaddr_in6*)&addr;
|
||||
::inet_ntop(AF_INET6, &in6, buffer, length);
|
||||
::sprintf(buffer + ::strlen(buffer), ":%u", in6->sin6_port);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
::strcpy(buffer, "Unknown");
|
||||
break;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
bool CUDPSocket::open(const sockaddr_storage& address)
|
||||
{
|
||||
return open(address.ss_family);
|
||||
}
|
||||
|
||||
bool CUDPSocket::open(unsigned int af)
|
||||
{
|
||||
return open(0, af, m_address_save, m_port_save);
|
||||
}
|
||||
|
||||
bool CUDPSocket::open(const unsigned int index, const unsigned int af, const std::string& address, const unsigned int port)
|
||||
{
|
||||
sockaddr_storage addr;
|
||||
unsigned int addrlen;
|
||||
struct addrinfo hints;
|
||||
|
||||
::memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
hints.ai_family = af;
|
||||
|
||||
/* to determine protocol family, call lookup() first. */
|
||||
int err = lookup(address, port, addr, addrlen, hints);
|
||||
if (err != 0) {
|
||||
LogError("The local address is invalid - %s", address.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
int fd = ::socket(addr.ss_family, SOCK_DGRAM, 0);
|
||||
if (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;
|
||||
}
|
||||
|
||||
m_address[index] = address;
|
||||
m_port[index] = port;
|
||||
m_af[index] = addr.ss_family;
|
||||
m_fd[index] = fd;
|
||||
|
||||
if (port > 0U) {
|
||||
int reuse = 1;
|
||||
if (::setsockopt(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(fd, (sockaddr*)&addr, addrlen) == -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", port);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int CUDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storage& address, unsigned int &address_length)
|
||||
{
|
||||
assert(buffer != NULL);
|
||||
assert(length > 0U);
|
||||
|
||||
// Check that the readfrom() won't block
|
||||
int i, n;
|
||||
struct pollfd pfd[UDP_SOCKET_MAX];
|
||||
for (i = n = 0; i < UDP_SOCKET_MAX; i++) {
|
||||
if (m_fd[i] >= 0) {
|
||||
pfd[n].fd = m_fd[i];
|
||||
pfd[n].events = POLLIN;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
// no socket descriptor to receive
|
||||
if (n == 0)
|
||||
return 0;
|
||||
|
||||
// Return immediately
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
int ret = WSAPoll(pfd, n, 0);
|
||||
#else
|
||||
int ret = ::poll(pfd, n, 0);
|
||||
#endif
|
||||
if (ret < 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LogError("Error returned from UDP poll, err: %lu", ::GetLastError());
|
||||
#else
|
||||
LogError("Error returned from UDP poll, err: %d", errno);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
int index;
|
||||
for (i = 0; i < n; i++) {
|
||||
// round robin
|
||||
index = (i + m_counter) % n;
|
||||
if (pfd[index].revents & POLLIN)
|
||||
break;
|
||||
}
|
||||
if (i == n)
|
||||
return 0;
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
int size = sizeof(sockaddr_storage);
|
||||
#else
|
||||
socklen_t size = sizeof(sockaddr_storage);
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
int len = ::recvfrom(pfd[index].fd, (char*)buffer, length, 0, (sockaddr *)&address, &size);
|
||||
#else
|
||||
ssize_t len = ::recvfrom(pfd[index].fd, (char*)buffer, length, 0, (sockaddr *)&address, &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);
|
||||
|
||||
if (len == -1 && errno == ENOTSOCK) {
|
||||
LogMessage("Re-opening UDP port on %u", m_port);
|
||||
close();
|
||||
open();
|
||||
}
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
m_counter++;
|
||||
address_length = size;
|
||||
return len;
|
||||
}
|
||||
|
||||
bool CUDPSocket::write(const unsigned char* buffer, unsigned int length, const sockaddr_storage& address, unsigned int address_length)
|
||||
{
|
||||
assert(buffer != NULL);
|
||||
assert(length > 0U);
|
||||
|
||||
bool result = false;
|
||||
|
||||
for (int i = 0; i < UDP_SOCKET_MAX; i++) {
|
||||
if (m_fd[i] < 0 || m_af[i] != address.ss_family)
|
||||
continue;
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
int ret = ::sendto(m_fd[i], (char *)buffer, length, 0, (sockaddr *)&address, address_length);
|
||||
#else
|
||||
ssize_t ret = ::sendto(m_fd[i], (char *)buffer, length, 0, (sockaddr *)&address, address_length);
|
||||
#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
|
||||
} else {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
if (ret == int(length))
|
||||
result = true;
|
||||
#else
|
||||
if (ret == ssize_t(length))
|
||||
result = true;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void CUDPSocket::close()
|
||||
{
|
||||
for (int i = 0; i < UDP_SOCKET_MAX; i++)
|
||||
close(m_fd[i]);
|
||||
}
|
||||
|
||||
void CUDPSocket::close(const unsigned int index)
|
||||
{
|
||||
if (m_fd[index] >= 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
::closesocket(m_fd[index]);
|
||||
#else
|
||||
::close(m_fd[index]);
|
||||
#endif
|
||||
m_fd[index] = -1;
|
||||
}
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2011,2013,2015,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.
|
||||
*/
|
||||
|
||||
#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 <poll.h>
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#else
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
#if !defined(UDP_SOCKET_MAX)
|
||||
#define UDP_SOCKET_MAX 1
|
||||
#endif
|
||||
|
||||
enum IPMATCHTYPE {
|
||||
IMT_ADDRESS_AND_PORT,
|
||||
IMT_ADDRESS_ONLY
|
||||
};
|
||||
|
||||
class CUDPSocket {
|
||||
public:
|
||||
CUDPSocket(const std::string& address, unsigned int port = 0U);
|
||||
CUDPSocket(unsigned int port = 0U);
|
||||
~CUDPSocket();
|
||||
|
||||
bool open(unsigned int af = AF_UNSPEC);
|
||||
bool open(const sockaddr_storage& address);
|
||||
bool open(const unsigned int index, const unsigned int af, const std::string& address, const unsigned int port);
|
||||
|
||||
int read(unsigned char* buffer, unsigned int length, sockaddr_storage& address, unsigned int &address_length);
|
||||
bool write(const unsigned char* buffer, unsigned int length, const sockaddr_storage& address, unsigned int address_length);
|
||||
|
||||
void close();
|
||||
void close(const unsigned int index);
|
||||
|
||||
static void startup();
|
||||
static void shutdown();
|
||||
|
||||
static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage& address, unsigned int& address_length);
|
||||
static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage& address, unsigned int& address_length, struct addrinfo& hints);
|
||||
|
||||
static bool match(const sockaddr_storage& addr1, const sockaddr_storage& addr2, IPMATCHTYPE type = IMT_ADDRESS_AND_PORT);
|
||||
|
||||
static bool isNone(const sockaddr_storage& addr);
|
||||
|
||||
static char* display(const sockaddr_storage& address, char* buffer, unsigned int length);
|
||||
|
||||
private:
|
||||
std::string m_address_save;
|
||||
unsigned short m_port_save;
|
||||
std::string m_address[UDP_SOCKET_MAX];
|
||||
unsigned short m_port[UDP_SOCKET_MAX];
|
||||
unsigned int m_af[UDP_SOCKET_MAX];
|
||||
int m_fd[UDP_SOCKET_MAX];
|
||||
unsigned int m_counter;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,146 +0,0 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* 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
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015,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(VERSION_H)
|
||||
#define VERSION_H
|
||||
|
||||
const char* VERSION = "20201124";
|
||||
|
||||
#endif
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* 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(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_GROUP = 0x00U;
|
||||
const unsigned char YSF_CM_INDIVIDUAL = 0x03U;
|
||||
|
||||
const unsigned char YSF_MR_NOT_BUSY = 0x01U;
|
||||
const unsigned char YSF_MR_BUSY = 0x02U;
|
||||
|
||||
#endif
|
|
@ -1,357 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2016,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 "YSFReflector.h"
|
||||
#include "StopWatch.h"
|
||||
#include "Network.h"
|
||||
#include "Version.h"
|
||||
#include "Thread.h"
|
||||
#include "Log.h"
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
const char* DEFAULT_INI_FILE = "YSFReflector.ini";
|
||||
#else
|
||||
const char* DEFAULT_INI_FILE = "/etc/YSFReflector.ini";
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstdarg>
|
||||
#include <ctime>
|
||||
#include <cstring>
|
||||
|
||||
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, "YSFReflector version %s\n", VERSION);
|
||||
return 0;
|
||||
} else if (arg.substr(0, 1) == "-") {
|
||||
::fprintf(stderr, "Usage: YSFReflector [-v|--version] [filename]\n");
|
||||
return 1;
|
||||
} else {
|
||||
iniFile = argv[currentArg];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CYSFReflector* reflector = new CYSFReflector(std::string(iniFile));
|
||||
reflector->run();
|
||||
delete reflector;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CYSFReflector::CYSFReflector(const std::string& file) :
|
||||
m_conf(file),
|
||||
m_repeaters()
|
||||
{
|
||||
CUDPSocket::startup();
|
||||
}
|
||||
|
||||
CYSFReflector::~CYSFReflector()
|
||||
{
|
||||
CUDPSocket::shutdown();
|
||||
}
|
||||
|
||||
void CYSFReflector::run()
|
||||
{
|
||||
bool ret = m_conf.read();
|
||||
if (!ret) {
|
||||
::fprintf(stderr, "YSFReflector: cannot read the .ini file\n");
|
||||
return;
|
||||
}
|
||||
|
||||
#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;
|
||||
} else if (pid != 0) {
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
// Create new session and process group
|
||||
if (::setsid() == -1) {
|
||||
::fprintf(stderr, "Couldn't setsid(), exiting\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the working directory to the root directory
|
||||
if (::chdir("/") == -1) {
|
||||
::fprintf(stderr, "Couldn't cd /, exiting\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (setuid(mmdvm_uid) != 0) {
|
||||
::fprintf(stderr, "Could not set mmdvm UID, exiting\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Double check it worked (AKA Paranoia)
|
||||
if (setuid(0) != -1) {
|
||||
::fprintf(stderr, "It's possible to regain root - something is wrong!, exiting\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
ret = ::LogInitialise(m_daemon, m_conf.getLogFilePath(), m_conf.getLogFileRoot(), m_conf.getLogFileLevel(), m_conf.getLogDisplayLevel(), m_conf.getLogFileRotate());
|
||||
#else
|
||||
ret = ::LogInitialise(false, m_conf.getLogFilePath(), m_conf.getLogFileRoot(), m_conf.getLogFileLevel(), m_conf.getLogDisplayLevel(), m_conf.getLogFileRotate());
|
||||
#endif
|
||||
if (!ret) {
|
||||
::fprintf(stderr, "YSFReflector: unable to open the log file\n");
|
||||
return;
|
||||
}
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
if (m_daemon) {
|
||||
::close(STDIN_FILENO);
|
||||
::close(STDOUT_FILENO);
|
||||
::close(STDERR_FILENO);
|
||||
}
|
||||
#endif
|
||||
|
||||
CNetwork network(m_conf.getNetworkPort(), m_conf.getId(), m_conf.getName(), m_conf.getDescription(), m_conf.getNetworkDebug());
|
||||
|
||||
ret = network.open();
|
||||
if (!ret) {
|
||||
::LogFinalise();
|
||||
return;
|
||||
}
|
||||
|
||||
network.setCount(0);
|
||||
|
||||
CStopWatch stopWatch;
|
||||
stopWatch.start();
|
||||
|
||||
CTimer dumpTimer(1000U, 120U);
|
||||
dumpTimer.start();
|
||||
|
||||
CTimer pollTimer(1000U, 5U);
|
||||
pollTimer.start();
|
||||
|
||||
LogMessage("Starting YSFReflector-%s", VERSION);
|
||||
|
||||
CTimer watchdogTimer(1000U, 0U, 1500U);
|
||||
|
||||
unsigned char tag[YSF_CALLSIGN_LENGTH];
|
||||
unsigned char src[YSF_CALLSIGN_LENGTH];
|
||||
unsigned char dst[YSF_CALLSIGN_LENGTH];
|
||||
|
||||
for (;;) {
|
||||
unsigned char buffer[200U];
|
||||
sockaddr_storage addr;
|
||||
unsigned int addrLen;
|
||||
|
||||
unsigned int len = network.readData(buffer, 200U, addr, addrLen);
|
||||
if (len > 0U) {
|
||||
CYSFRepeater* rpt = findRepeater(addr);
|
||||
if (::memcmp(buffer, "YSFP", 4U) == 0) {
|
||||
if (rpt == NULL) {
|
||||
rpt = new CYSFRepeater;
|
||||
rpt->m_callsign = std::string((char*)(buffer + 4U), 10U);
|
||||
rpt->m_addr = addr;
|
||||
rpt->m_addrLen = addrLen;
|
||||
m_repeaters.push_back(rpt);
|
||||
network.setCount(m_repeaters.size());
|
||||
|
||||
char buff[80U];
|
||||
LogMessage("Adding %s (%s)", rpt->m_callsign.c_str(), CUDPSocket::display(addr, buff, 80U));
|
||||
}
|
||||
rpt->m_timer.start();
|
||||
network.writePoll(addr, addrLen);
|
||||
} else if (::memcmp(buffer + 0U, "YSFU", 4U) == 0 && rpt != NULL) {
|
||||
char buff[80U];
|
||||
LogMessage("Removing %s (%s) unlinked", rpt->m_callsign.c_str(), CUDPSocket::display(addr, buff, 80U));
|
||||
|
||||
for (std::vector<CYSFRepeater*>::iterator it = m_repeaters.begin(); it != m_repeaters.end(); ++it) {
|
||||
CYSFRepeater* itRpt = *it;
|
||||
if (CUDPSocket::match(itRpt->m_addr, rpt->m_addr)) {
|
||||
m_repeaters.erase(it);
|
||||
delete itRpt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
network.setCount(m_repeaters.size());
|
||||
} else if (::memcmp(buffer + 0U, "YSFD", 4U) == 0 && rpt != NULL) {
|
||||
if (!watchdogTimer.isRunning()) {
|
||||
::memcpy(tag, buffer + 4U, YSF_CALLSIGN_LENGTH);
|
||||
|
||||
if (::memcmp(buffer + 14U, " ", YSF_CALLSIGN_LENGTH) != 0)
|
||||
::memcpy(src, buffer + 14U, YSF_CALLSIGN_LENGTH);
|
||||
else
|
||||
::memcpy(src, "??????????", YSF_CALLSIGN_LENGTH);
|
||||
|
||||
if (::memcmp(buffer + 24U, " ", YSF_CALLSIGN_LENGTH) != 0)
|
||||
::memcpy(dst, buffer + 24U, YSF_CALLSIGN_LENGTH);
|
||||
else
|
||||
::memcpy(dst, "??????????", YSF_CALLSIGN_LENGTH);
|
||||
|
||||
LogMessage("Received data from %10.10s to %10.10s at %10.10s", src, dst, buffer + 4U);
|
||||
} else {
|
||||
if (::memcmp(tag, buffer + 4U, YSF_CALLSIGN_LENGTH) == 0) {
|
||||
bool changed = false;
|
||||
|
||||
if (::memcmp(buffer + 14U, " ", YSF_CALLSIGN_LENGTH) != 0 && ::memcmp(src, "??????????", YSF_CALLSIGN_LENGTH) == 0) {
|
||||
::memcpy(src, buffer + 14U, YSF_CALLSIGN_LENGTH);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (::memcmp(buffer + 24U, " ", YSF_CALLSIGN_LENGTH) != 0 && ::memcmp(dst, "??????????", YSF_CALLSIGN_LENGTH) == 0) {
|
||||
::memcpy(dst, buffer + 24U, YSF_CALLSIGN_LENGTH);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
LogMessage("Received data from %10.10s to %10.10s at %10.10s", src, dst, buffer + 4U);
|
||||
}
|
||||
}
|
||||
|
||||
watchdogTimer.start();
|
||||
|
||||
for (std::vector<CYSFRepeater*>::const_iterator it = m_repeaters.begin(); it != m_repeaters.end(); ++it) {
|
||||
if (!CUDPSocket::match((*it)->m_addr, addr))
|
||||
network.writeData(buffer, (*it)->m_addr, (*it)->m_addrLen);
|
||||
}
|
||||
|
||||
if ((buffer[34U] & 0x01U) == 0x01U) {
|
||||
LogMessage("Received end of transmission");
|
||||
watchdogTimer.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int ms = stopWatch.elapsed();
|
||||
stopWatch.start();
|
||||
|
||||
pollTimer.clock(ms);
|
||||
if (pollTimer.hasExpired()) {
|
||||
for (std::vector<CYSFRepeater*>::const_iterator it = m_repeaters.begin(); it != m_repeaters.end(); ++it)
|
||||
network.writePoll((*it)->m_addr, (*it)->m_addrLen);
|
||||
pollTimer.start();
|
||||
}
|
||||
|
||||
// Remove any repeaters that haven't reported for a while
|
||||
for (std::vector<CYSFRepeater*>::iterator it = m_repeaters.begin(); it != m_repeaters.end(); ++it)
|
||||
(*it)->m_timer.clock(ms);
|
||||
|
||||
for (std::vector<CYSFRepeater*>::iterator it = m_repeaters.begin(); it != m_repeaters.end(); ++it) {
|
||||
CYSFRepeater* itRpt = *it;
|
||||
if (itRpt->m_timer.hasExpired()) {
|
||||
char buff[80U];
|
||||
LogMessage("Removing %s (%s) disappeared", itRpt->m_callsign.c_str(), CUDPSocket::display(itRpt->m_addr, buff, 80U));
|
||||
|
||||
m_repeaters.erase(it);
|
||||
delete itRpt;
|
||||
network.setCount(m_repeaters.size());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
watchdogTimer.clock(ms);
|
||||
if (watchdogTimer.isRunning() && watchdogTimer.hasExpired()) {
|
||||
LogMessage("Network watchdog has expired");
|
||||
watchdogTimer.stop();
|
||||
}
|
||||
|
||||
dumpTimer.clock(ms);
|
||||
if (dumpTimer.hasExpired()) {
|
||||
dumpRepeaters();
|
||||
dumpTimer.start();
|
||||
}
|
||||
|
||||
if (ms < 5U)
|
||||
CThread::sleep(5U);
|
||||
}
|
||||
|
||||
network.close();
|
||||
|
||||
::LogFinalise();
|
||||
}
|
||||
|
||||
CYSFRepeater* CYSFReflector::findRepeater(const sockaddr_storage& addr) const
|
||||
{
|
||||
for (std::vector<CYSFRepeater*>::const_iterator it = m_repeaters.begin(); it != m_repeaters.end(); ++it) {
|
||||
if (CUDPSocket::match(addr, (*it)->m_addr))
|
||||
return *it;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CYSFReflector::dumpRepeaters() const
|
||||
{
|
||||
if (m_repeaters.size() == 0U) {
|
||||
LogMessage("No repeaters/gateways linked");
|
||||
return;
|
||||
}
|
||||
|
||||
LogMessage("Currently linked repeaters/gateways:");
|
||||
|
||||
for (std::vector<CYSFRepeater*>::const_iterator it = m_repeaters.begin(); it != m_repeaters.end(); ++it) {
|
||||
std::string callsign = (*it)->m_callsign;
|
||||
sockaddr_storage addr = (*it)->m_addr;
|
||||
unsigned int timer = (*it)->m_timer.getTimer();
|
||||
unsigned int timeout = (*it)->m_timer.getTimeout();
|
||||
|
||||
char buffer[80U];
|
||||
LogMessage(" %s: %s %u/%u", callsign.c_str(), CUDPSocket::display(addr, buffer, 80U), timer, timeout);
|
||||
}
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
* 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(YSFReflector_H)
|
||||
#define YSFReflector_H
|
||||
|
||||
#include "Timer.h"
|
||||
#include "Conf.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#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>
|
||||
#else
|
||||
#include <WS2tcpip.h>
|
||||
#endif
|
||||
|
||||
class CYSFRepeater {
|
||||
public:
|
||||
CYSFRepeater() :
|
||||
m_callsign(),
|
||||
m_addr(),
|
||||
m_addrLen(0U),
|
||||
m_timer(1000U, 60U)
|
||||
{
|
||||
}
|
||||
|
||||
std::string m_callsign;
|
||||
sockaddr_storage m_addr;
|
||||
unsigned int m_addrLen;
|
||||
CTimer m_timer;
|
||||
};
|
||||
|
||||
class CYSFReflector
|
||||
{
|
||||
public:
|
||||
CYSFReflector(const std::string& file);
|
||||
~CYSFReflector();
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
CConf m_conf;
|
||||
std::vector<CYSFRepeater*> m_repeaters;
|
||||
|
||||
CYSFRepeater* findRepeater(const sockaddr_storage& addr) const;
|
||||
void dumpRepeaters() const;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,22 +0,0 @@
|
|||
[General]
|
||||
Daemon=1
|
||||
|
||||
[Info]
|
||||
# Remember to register your YSFReflector at:
|
||||
# https://register.ysfreflector.de
|
||||
# Id=5 digits only
|
||||
Name=16 characters max
|
||||
Description=14 characters max
|
||||
|
||||
[Log]
|
||||
# Logging levels, 0=No logging
|
||||
DisplayLevel=1
|
||||
FileLevel=1
|
||||
FilePath=.
|
||||
FileRoot=YSFReflector
|
||||
FileRotate=1
|
||||
|
||||
[Network]
|
||||
Port=42000
|
||||
Debug=0
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
#!/bin/bash
|
||||
### BEGIN INIT INFO
|
||||
#
|
||||
# Provides: YSFReflector
|
||||
# Required-Start: $all
|
||||
# Required-Stop:
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Example startscript YSFReflector
|
||||
|
||||
#
|
||||
### END INIT INFO
|
||||
## Fill in name of program here.
|
||||
PROG="YSFReflector"
|
||||
PROG_PATH="/usr/local/bin/"
|
||||
PROG_ARGS="/etc/YSFReflector.ini"
|
||||
PIDFILE="/var/run/YSFReflector.pid"
|
||||
USER="root"
|
||||
|
||||
start() {
|
||||
if [ -e $PIDFILE ]; then
|
||||
## Program is running, exit with error.
|
||||
echo "Error! $PROG is currently running!" 1>&2
|
||||
exit 1
|
||||
else
|
||||
cd $PROG_PATH
|
||||
./$PROG $PROG_ARGS
|
||||
echo "$PROG started"
|
||||
touch $PIDFILE
|
||||
fi
|
||||
}
|
||||
|
||||
stop() {
|
||||
if [ -e $PIDFILE ]; then
|
||||
## Program is running, so stop it
|
||||
echo "$PROG is running"
|
||||
rm -f $PIDFILE
|
||||
killall $PROG
|
||||
echo "$PROG stopped"
|
||||
else
|
||||
## Program is not running, exit with error.
|
||||
echo "Error! $PROG not started!" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
## Check to see if we are running as root first.
|
||||
## Found at
|
||||
## http://www.cyberciti.biz/tips/shell-root-user-check-script.html
|
||||
if [ "$(id -u)" != "0" ]; then
|
||||
echo "This script must be run as root" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
exit 0
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
exit 0
|
||||
;;
|
||||
reload|restart|force-reload)
|
||||
stop
|
||||
sleep 5
|
||||
start
|
||||
exit 0
|
||||
;;
|
||||
**)
|
||||
echo "Usage: $0 {start|stop|reload}" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
exit 0
|
||||
### END
|
|
@ -1,175 +0,0 @@
|
|||
<?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>{317D87F1-3485-4739-9F94-A07738B8E19D}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>YSFReflector</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;HAVE_LOG_H;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;HAVE_LOG_H;_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;HAVE_LOG_H;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;HAVE_LOG_H;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="Conf.h" />
|
||||
<ClInclude Include="Log.h" />
|
||||
<ClInclude Include="Network.h" />
|
||||
<ClInclude Include="StopWatch.h" />
|
||||
<ClInclude Include="Thread.h" />
|
||||
<ClInclude Include="Timer.h" />
|
||||
<ClInclude Include="UDPSocket.h" />
|
||||
<ClInclude Include="Utils.h" />
|
||||
<ClInclude Include="Version.h" />
|
||||
<ClInclude Include="YSFDefines.h" />
|
||||
<ClInclude Include="YSFReflector.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Conf.cpp" />
|
||||
<ClCompile Include="Log.cpp" />
|
||||
<ClCompile Include="Network.cpp" />
|
||||
<ClCompile Include="StopWatch.cpp" />
|
||||
<ClCompile Include="Thread.cpp" />
|
||||
<ClCompile Include="Timer.cpp" />
|
||||
<ClCompile Include="UDPSocket.cpp" />
|
||||
<ClCompile Include="Utils.cpp" />
|
||||
<ClCompile Include="YSFReflector.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
|
@ -1,77 +0,0 @@
|
|||
<?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="Network.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="Utils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="YSFDefines.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="YSFReflector.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="StopWatch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Version.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Log.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Conf.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Thread.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Network.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="Utils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="YSFReflector.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="StopWatch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Log.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Conf.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Thread.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -1,29 +0,0 @@
|
|||
FROM debian:buster-slim AS builder
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y build-essential git
|
||||
|
||||
RUN mkdir /code && \
|
||||
git clone https://github.com/g4klx/YSFClients.git /code && \
|
||||
cd /code/YSFReflector/ && \
|
||||
make clean all
|
||||
|
||||
FROM debian:buster-slim
|
||||
|
||||
ENV REFLECTOR_NAME set_me
|
||||
ENV REFLECTOR_DESCRIPTION set_me
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y procps && \
|
||||
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \
|
||||
mkdir /app
|
||||
|
||||
COPY --from=builder /code/YSFReflector/YSFReflector.ini /app/YSFReflector.ini
|
||||
COPY --from=builder /code/YSFReflector/YSFReflector /app/YSFReflector
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
|
||||
EXPOSE 42000/udp
|
||||
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
CMD ["/app/YSFReflector", "/app/YSFReflector.ini"]
|
||||
HEALTHCHECK CMD ps aux | grep [Y]SFReflector || exit 1
|
|
@ -1,25 +0,0 @@
|
|||
# YSFReflector Docker Image
|
||||
|
||||
The `Dockerfile` here is intended to produce an image which will be stored on [Docker Hub](https://hub.docker.com/).
|
||||
|
||||
# Requirements
|
||||
|
||||
* [Docker](https://docs.docker.com/install/)
|
||||
* Firewall setup to accept 42000 (UDP)
|
||||
|
||||
# Usage
|
||||
|
||||
`docker run -e REFLECTOR_NAME=YOUR_NAME_HERE -eREFLECTOR_DESCRIPTION=YOUR_DESCRIPTION_HERE -p 42000:42000/udp neilbartley/ysfreflector:latest`
|
||||
|
||||
# How to build
|
||||
|
||||
Building isn't required unless you need a newer image or have made changes.
|
||||
|
||||
```
|
||||
cd YSFReflector/docker
|
||||
YSF_TAG=$(date +'%Y%m%d')-$(git rev-parse --short HEAD)
|
||||
docker build --rm -t neilbartley/ysfreflector:$YSF_TAG .
|
||||
docker tag neilbartley/ysfreflector:$YSF_TAG neilbartley/ysfreflector:latest
|
||||
docker push neilbartley/ysfreflector:$YSF_TAG
|
||||
docker push neilbartley/ysfreflector:latest
|
||||
```
|
|
@ -1,18 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Disable daemon mode
|
||||
sed -i -e "s/Daemon=1/Daemon=0/g" /app/YSFReflector.ini
|
||||
|
||||
# Reflector name and description validation
|
||||
if [ "${REFLECTOR_NAME}" == "set_me" ] ; then echo "Please set REFLECTOR_NAME environment variable with -e (max 16 characters)"; exit 1 ; fi
|
||||
if [ ${#REFLECTOR_NAME} -gt 16 ] ; then echo "REFLECTOR_NAME environment variable can be at most 16 characters"; exit 1 ; fi
|
||||
if [ "${REFLECTOR_DESCRIPTION}" == "set_me" ] ; then echo "Please set REFLECTOR_DESCRIPTION environment variable with -e (min 14 characters)"; exit 1 ; fi
|
||||
if [ ${#REFLECTOR_DESCRIPTION} -gt 14 ] ; then echo "REFLECTOR_DESCRIPTION environment variable can be at most 14 characters"; exit 1 ; fi
|
||||
|
||||
# Reflector name and description replacement in config file
|
||||
sed -i -e "s/Name=.*/Name=${REFLECTOR_NAME}/g" /app/YSFReflector.ini
|
||||
sed -i -e "s/Description=.*/Description=${REFLECTOR_DESCRIPTION}/g" /app/YSFReflector.ini
|
||||
|
||||
echo "Remember to register your YSFReflector at: https://register.ysfreflector.de"
|
||||
|
||||
exec "$@"
|
Loading…
Add table
Reference in a new issue