Databases have switched to unordered_map, based on a new union in CCallsign

pull/1/head
Tom Early 3 years ago
parent 7664b7305c
commit 991d4899a0

1
.gitignore vendored

@ -12,3 +12,4 @@ reflector.cfg
wiresx/configure.php wiresx/configure.php
urfd* urfd*
inicheck inicheck
dbutil

@ -31,98 +31,113 @@
CCallsign::CCallsign() CCallsign::CCallsign()
{ {
// blank all // blank all
memset(m_Callsign, ' ', CALLSIGN_LEN); memset(m_Callsign.c, ' ', CALLSIGN_LEN);
memset(m_Suffix, ' ', CALLSUFFIX_LEN); memset(m_Suffix.c, ' ', CALLSUFFIX_LEN);
m_Module = ' '; m_Module = ' ';
m_uiDmrid = 0; m_uiDmrid = 0;
m_coded = 0; m_coded = 0;
} }
CCallsign::CCallsign(const char *sz, uint32_t dmrid, uint16_t nxdnid) CCallsign::CCallsign(const CCallsign &cs)
{ {
// blank all m_Callsign.l = cs.m_Callsign.l;
memset(m_Callsign, ' ', CALLSIGN_LEN); m_Suffix.u = cs.m_Suffix.u;
memset(m_Suffix, ' ', CALLSUFFIX_LEN); m_Module = cs.m_Module;
m_Module = ' '; if (m_Callsign.l)
m_uiDmrid = dmrid; CSIn();
m_uiNXDNid = nxdnid; }
CCallsign::CCallsign(const std::string &cs, uint32_t dmrid, uint16_t nxdnid) : CCallsign()
{
// and populate // and populate
auto len = strlen(sz); m_uiDmrid = dmrid;
m_uiNXDNid = nxdnid;
auto len = cs.size();
if ( len > 0 ) if ( len > 0 )
{ {
// callsign valid // callsign valid
memcpy(m_Callsign, sz, MIN(len, CALLSIGN_LEN-1)); memcpy(m_Callsign.c, cs.c_str(), MIN(len, CALLSIGN_LEN-1));
if ( len > CALLSIGN_LEN ) if ( len >= CALLSIGN_LEN )
{ {
m_Module = sz[len-1]; m_Module = cs.back();
} }
// Calculate the M17 coded callsign auto key = GetKey();
CSIn(); if (0 == m_uiDmrid)
// dmrid ok ?
if ( m_uiDmrid == 0 )
{ {
g_LDid.Lock(); g_LDid.Lock();
{ m_uiDmrid = g_LDid.FindDmrid(key);
m_uiDmrid = g_LDid.FindDmrid(*this);
}
g_LDid.Unlock(); g_LDid.Unlock();
} }
if ( m_uiNXDNid == 0 )
if (0 == m_uiNXDNid)
{ {
g_LNid.Lock(); g_LNid.Lock();
{ m_uiNXDNid = g_LNid.FindNXDNid(key);
m_uiNXDNid = g_LNid.FindNXDNid(*this);
}
g_LNid.Unlock(); g_LNid.Unlock();
} }
} }
else if ( m_uiDmrid != 0 ) else if (dmrid)
{ {
g_LDid.Lock(); g_LDid.Lock();
{ auto pItem = g_LDid.FindCallsign(dmrid);
const CCallsign *callsign = g_LDid.FindCallsign(m_uiDmrid); if (pItem)
if ( callsign != nullptr ) m_Callsign = *pItem;
{
memcpy(m_Callsign, callsign->m_Callsign, CALLSIGN_LEN);
}
}
g_LDid.Unlock(); g_LDid.Unlock();
if ( m_uiNXDNid == 0 ) if (m_Callsign.l && 0 == nxdnid)
{ {
g_LNid.Lock(); g_LNid.Lock();
{ m_uiNXDNid = g_LNid.FindNXDNid(GetKey());
m_uiNXDNid = g_LNid.FindNXDNid(*this);
}
g_LNid.Unlock(); g_LNid.Unlock();
} }
CSIn();
} }
else if ( m_uiNXDNid != 0 ) else if (nxdnid)
{ {
g_LNid.Lock(); g_LNid.Lock();
{ auto pItem = g_LNid.FindCallsign(nxdnid);
const CCallsign *callsign = g_LNid.FindCallsign(m_uiNXDNid); if (pItem)
if ( callsign != nullptr ) m_Callsign = *pItem;
{
memcpy(m_Callsign, callsign->m_Callsign, CALLSIGN_LEN);
}
}
g_LNid.Unlock(); g_LNid.Unlock();
if ( m_uiDmrid == 0 ) if (m_Callsign.l && 0 == dmrid)
{ {
g_LDid.Lock(); g_LDid.Lock();
{ m_uiDmrid = g_LDid.FindDmrid(GetKey());
m_uiDmrid = g_LDid.FindDmrid(*this);
}
g_LDid.Unlock(); g_LDid.Unlock();
} }
}
if (m_Callsign.l)
CSIn(); CSIn();
}
CCallsign::CCallsign(const CCallsign &cs)
{
m_Callsign.l = cs.m_Callsign.l;
m_Suffix.u = cs.m_Suffix.u;
m_Module = cs.m_Module;
m_uiDmrid = cs.m_uiDmrid;
m_uiNXDNid = cs.m_uiNXDNid;
m_coded = cs.m_coded;
}
CCallsign::CCallsign(const UCallsign &ucs) : CCallsign()
{
m_Callsign.l = ucs.l;
}
CCallsign &CCallsign::operator = (const CCallsign &cs)
{
if (this != &cs)
{
m_Callsign.l = cs.m_Callsign.l;
m_Suffix.u = cs.m_Suffix.u;
m_Module = cs.m_Module;
m_uiDmrid = cs.m_uiDmrid;
m_uiNXDNid = cs.m_uiNXDNid;
m_coded = cs.m_coded;
} }
return *this;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -138,8 +153,8 @@ bool CCallsign::IsValid(void) const
int iNum = 0; int iNum = 0;
for ( i = 0; i < 3; i++ ) for ( i = 0; i < 3; i++ )
{ {
valid &= IsLetter(m_Callsign[i]) || IsNumber(m_Callsign[i]); valid = valid && (IsLetter(m_Callsign.c[i]) || IsNumber(m_Callsign.c[i]));
if ( IsNumber(m_Callsign[i]) ) if ( IsNumber(m_Callsign.c[i]) )
{ {
iNum++; iNum++;
} }
@ -148,19 +163,19 @@ bool CCallsign::IsValid(void) const
// all remaining char are letter, number or space // all remaining char are letter, number or space
for ( ; i < CALLSIGN_LEN; i++) for ( ; i < CALLSIGN_LEN; i++)
{ {
valid &= IsLetter(m_Callsign[i]) || IsNumber(m_Callsign[i]) || IsSpace(m_Callsign[i]); valid = valid && (IsLetter(m_Callsign.c[i]) || IsNumber(m_Callsign.c[i]) || IsSpace(m_Callsign.c[i]));
} }
// prefix // prefix
// all chars are number, letter, special char, or space // all chars are number, letter, special char, or space
for ( i = 0; i < CALLSUFFIX_LEN; i++ ) for ( i = 0; i < CALLSUFFIX_LEN; i++ )
{ {
valid &= IsLetter(m_Suffix[i]) || IsNumber(m_Suffix[i]) || IsSpace(m_Suffix[i]) || IsLetterLC(m_Suffix[i]) || IsSpecialChar(m_Suffix[i]); valid = valid && (IsLetter(m_Suffix.c[i]) || IsNumber(m_Suffix.c[i]) || IsSpace(m_Suffix.c[i]) || IsLetterLC(m_Suffix.c[i]) || IsSpecialChar(m_Suffix.c[i]));
} }
// module // module
// is an letter or space // is an letter or space
valid &= IsLetter(m_Module) || IsSpace(m_Module); valid = valid && (IsLetter(m_Module) || IsSpace(m_Module));
// dmrid is not tested, as it can be nullptr // dmrid is not tested, as it can be nullptr
// if station does is not dmr registered // if station does is not dmr registered
@ -171,41 +186,37 @@ bool CCallsign::IsValid(void) const
bool CCallsign::HasSuffix(void) const bool CCallsign::HasSuffix(void) const
{ {
bool has = false; return 0 == memcmp(m_Suffix.c, " ", 4);
for ( int i = 0; i < CALLSUFFIX_LEN; i++ )
{
has |= (m_Suffix[i] != ' ');
}
return has;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// set // set
void CCallsign::SetCallsign(const char *sz, bool UpdateDmrid) void CCallsign::SetCallsign(const std::string &s, bool updateids)
{ {
// set callsign // set callsign
memset(m_Callsign, ' ', CALLSIGN_LEN); memset(m_Callsign.c, ' ', CALLSIGN_LEN);
m_Module = ' '; m_Module = ' ';
auto len = strlen(sz); auto len = s.size();
memcpy(m_Callsign, sz, MIN(len, CALLSIGN_LEN-1)); memcpy(m_Callsign.c, s.c_str(), MIN(len, CALLSIGN_LEN-1));
if ( len > CALLSIGN_LEN ) if ( len >= CALLSIGN_LEN )
{ {
m_Module = sz[len-1]; m_Module = s.back();
} }
// update M17 coded callsign // update M17 coded callsign
CSIn(); CSIn();
// and update dmrid // and update dmrid
if ( UpdateDmrid ) if (updateids)
{ {
auto key = GetKey();
g_LDid.Lock(); g_LDid.Lock();
{ {
m_uiDmrid = g_LDid.FindDmrid(*this); m_uiDmrid = g_LDid.FindDmrid(key);
} }
g_LDid.Unlock(); g_LDid.Unlock();
g_LNid.Lock(); g_LNid.Lock();
{ {
m_uiNXDNid = g_LNid.FindNXDNid(*this); m_uiNXDNid = g_LNid.FindNXDNid(key);
} }
g_LNid.Unlock(); g_LNid.Unlock();
} }
@ -214,14 +225,14 @@ void CCallsign::SetCallsign(const char *sz, bool UpdateDmrid)
void CCallsign::SetCallsign(const uint8_t *buffer, int len, bool UpdateDmrid) void CCallsign::SetCallsign(const uint8_t *buffer, int len, bool UpdateDmrid)
{ {
// set callsign // set callsign
memset(m_Callsign, ' ', CALLSIGN_LEN); memset(m_Callsign.c, ' ', CALLSIGN_LEN);
m_Module = ' '; m_Module = ' ';
memcpy(m_Callsign, buffer, MIN(len, (int)CALLSIGN_LEN-1)); memcpy(m_Callsign.c, buffer, MIN(len, (int)CALLSIGN_LEN-1));
for ( unsigned i = 0; i < CALLSIGN_LEN; i++ ) for ( unsigned i = 0; i < CALLSIGN_LEN; i++ )
{ {
if ( m_Callsign[i] == 0 ) if ( m_Callsign.c[i] == 0 )
{ {
m_Callsign[i] = ' '; m_Callsign.c[i] = ' ';
} }
} }
if ( (len >= (int)CALLSIGN_LEN) && ((char)buffer[CALLSIGN_LEN-1] != 0) ) if ( (len >= (int)CALLSIGN_LEN) && ((char)buffer[CALLSIGN_LEN-1] != 0) )
@ -231,14 +242,15 @@ void CCallsign::SetCallsign(const uint8_t *buffer, int len, bool UpdateDmrid)
CSIn(); CSIn();
if ( UpdateDmrid ) if ( UpdateDmrid )
{ {
auto key = GetKey();
g_LDid.Lock(); g_LDid.Lock();
{ {
m_uiDmrid = g_LDid.FindDmrid(*this); m_uiDmrid = g_LDid.FindDmrid(key);
} }
g_LDid.Unlock(); g_LDid.Unlock();
g_LNid.Lock(); g_LNid.Lock();
{ {
m_uiNXDNid = g_LNid.FindNXDNid(*this); m_uiNXDNid = g_LNid.FindNXDNid(key);
} }
g_LNid.Unlock(); g_LNid.Unlock();
} }
@ -251,13 +263,14 @@ void CCallsign::SetDmrid(uint32_t dmrid, bool UpdateCallsign)
{ {
g_LDid.Lock(); g_LDid.Lock();
{ {
const CCallsign *callsign = g_LDid.FindCallsign(dmrid); auto callsign = g_LDid.FindCallsign(dmrid);
if ( callsign != nullptr ) if ( callsign != nullptr )
{ {
memcpy(m_Callsign, callsign->m_Callsign, CALLSIGN_LEN); m_Callsign.l = callsign->l;
} }
} }
g_LDid.Unlock(); g_LDid.Unlock();
CSIn();
} }
} }
@ -276,13 +289,14 @@ void CCallsign::SetNXDNid(uint16_t nxdnid, bool UpdateCallsign)
{ {
g_LNid.Lock(); g_LNid.Lock();
{ {
const CCallsign *callsign = g_LNid.FindCallsign(nxdnid); auto callsign = g_LNid.FindCallsign(nxdnid);
if ( callsign != nullptr ) if ( callsign != nullptr )
{ {
memcpy(m_Callsign, callsign->m_Callsign, CALLSIGN_LEN); m_Callsign.l = callsign->l;
} }
} }
g_LNid.Unlock(); g_LNid.Unlock();
CSIn();
} }
} }
@ -301,17 +315,17 @@ void CCallsign::SetCSModule(char c)
} }
void CCallsign::SetSuffix(const char *sz) void CCallsign::SetSuffix(const std::string &s)
{ {
memset(m_Suffix, ' ', CALLSUFFIX_LEN); memset(m_Suffix.c, ' ', CALLSUFFIX_LEN);
memcpy(m_Suffix, sz, MIN(strlen(sz), CALLSUFFIX_LEN)); memcpy(m_Suffix.c, s.c_str(), MIN(s.size(), CALLSUFFIX_LEN));
} }
void CCallsign::SetSuffix(const uint8_t *buffer, int len) void CCallsign::SetSuffix(const uint8_t *buffer, int len)
{ {
len = MIN(len, (int)CALLSUFFIX_LEN); len = MIN(len, (int)CALLSUFFIX_LEN);
memset(m_Suffix, ' ', CALLSUFFIX_LEN); memset(m_Suffix.c, ' ', CALLSUFFIX_LEN);
memcpy(m_Suffix, buffer, len); memcpy(m_Suffix.c, buffer, len);
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -321,7 +335,7 @@ void CCallsign::PatchCallsign(int off, const char *patch, int len)
{ {
if ( off < CALLSIGN_LEN ) if ( off < CALLSIGN_LEN )
{ {
memcpy(m_Callsign, patch, MIN(len, (int)CALLSIGN_LEN - off)); memcpy(m_Callsign.c, patch, MIN(len, (int)CALLSIGN_LEN - off));
} }
CSIn(); CSIn();
} }
@ -330,9 +344,24 @@ void CCallsign::PatchCallsign(int off, const char *patch, int len)
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// get // get
const UCallsign CCallsign::GetKey() const
{
UCallsign rval;
rval.l = 0;
for (unsigned i=0; i<CALLSIGN_LEN; i++)
{
auto c = m_Callsign.c[i];
if (IsLetter(c) || IsNumber(c))
rval.c[i] = c;
else
break;
}
return rval;
}
void CCallsign::GetCallsign(uint8_t *buffer) const void CCallsign::GetCallsign(uint8_t *buffer) const
{ {
memcpy(buffer, m_Callsign, CALLSIGN_LEN); memcpy(buffer, m_Callsign.c, CALLSIGN_LEN);
if ( HasModule() ) if ( HasModule() )
{ {
buffer[CALLSIGN_LEN-1] = m_Module; buffer[CALLSIGN_LEN-1] = m_Module;
@ -342,51 +371,52 @@ void CCallsign::GetCallsign(uint8_t *buffer) const
void CCallsign::GetCallsignString(char *sz) const void CCallsign::GetCallsignString(char *sz) const
{ {
unsigned i; unsigned i;
for ( i = 0; (i < CALLSIGN_LEN) && (m_Callsign[i] != ' '); i++ ) for ( i = 0; (i < CALLSIGN_LEN) && (m_Callsign.c[i] != ' '); i++ )
{ {
sz[i] = m_Callsign[i]; sz[i] = m_Callsign.c[i];
} }
sz[i] = 0; sz[i] = 0;
} }
const std::string CCallsign::GetCS(unsigned len) const const std::string CCallsign::GetCS() const
{ {
std::string rval(m_Callsign, CALLSIGN_LEN); std::string rval(m_Callsign.c, CALLSIGN_LEN);
rval.append(1, m_Module); if (' ' != m_Module)
rval.append(1, m_Module);
return rval; return rval;
} }
void CCallsign::GetSuffix(uint8_t *buffer) const void CCallsign::GetSuffix(uint8_t *buffer) const
{ {
memcpy(buffer, m_Suffix, CALLSUFFIX_LEN); memcpy(buffer, m_Suffix.c, CALLSUFFIX_LEN);
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// compare // compare
bool CCallsign::HasSameCallsign(const CCallsign &Callsign) const bool CCallsign::HasSameCallsign(const CCallsign &cs) const
{ {
return (memcmp(m_Callsign, Callsign.m_Callsign, CALLSIGN_LEN) == 0); return (memcmp(m_Callsign.c, cs.m_Callsign.c, CALLSIGN_LEN) == 0);
} }
bool CCallsign::HasSameCallsignWithWildcard(const CCallsign &callsign) const bool CCallsign::HasSameCallsignWithWildcard(const CCallsign &cs) const
{ {
bool same = true; bool same = true;
bool done = false; bool done = false;
for ( unsigned i = 0; (i < CALLSIGN_LEN) && same && !done; i++ ) for ( unsigned i = 0; (i < CALLSIGN_LEN) && same && !done; i++ )
{ {
if ( !(done = ((m_Callsign[i] == '*') || (callsign[i] == '*'))) ) if ( !(done = ((m_Callsign.c[i] == '*') || (cs.m_Callsign.c[i] == '*'))) )
{ {
same &= (m_Callsign[i] == callsign[i]); same = same && (m_Callsign.c[i] == cs.m_Callsign.c[i]);
} }
} }
return same; return same;
} }
bool CCallsign::HasLowerCallsign(const CCallsign &Callsign) const bool CCallsign::HasLowerCallsign(const CCallsign &cs) const
{ {
return (memcmp(m_Callsign, Callsign.m_Callsign, CALLSIGN_LEN) < 0); return (memcmp(m_Callsign.c, cs.m_Callsign.c, CALLSIGN_LEN) < 0);
} }
bool CCallsign::HasSameModule(const CCallsign &Callsign) const bool CCallsign::HasSameModule(const CCallsign &Callsign) const
@ -398,36 +428,33 @@ bool CCallsign::HasSameModule(const CCallsign &Callsign) const
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// operators // operators
bool CCallsign::operator ==(const CCallsign &callsign) const bool CCallsign::operator ==(const CCallsign &cs) const
{ {
return ((memcmp(callsign.m_Callsign, m_Callsign, CALLSIGN_LEN) == 0) && (m_Module == callsign.m_Module) return (cs.m_Callsign.l == m_Callsign.l) && (m_Module == cs.m_Module) && (cs.m_Suffix.u == m_Suffix.u) && (m_uiDmrid == cs.m_uiDmrid) && (m_uiNXDNid == cs.m_uiNXDNid);
&& (memcmp(callsign.m_Suffix, m_Suffix, CALLSUFFIX_LEN) == 0)
&& (m_uiDmrid == callsign.m_uiDmrid)
);
} }
CCallsign::operator const char *() const CCallsign::operator const char *() const
{ {
static char m_sz[CALLSIGN_LEN+CALLSUFFIX_LEN+5]; static char sz[CALLSIGN_LEN+CALLSUFFIX_LEN+5];
// empty // empty
memset(m_sz, 0, sizeof(m_sz)); memset(sz, 0, sizeof(sz));
// callsign // callsign
memcpy(m_sz, m_Callsign, CALLSIGN_LEN); memcpy(sz, m_Callsign.c, CALLSIGN_LEN);
// module // module
if ( HasModule() ) if ( HasModule() )
{ {
m_sz[CALLSIGN_LEN] = m_Module; sz[CALLSIGN_LEN] = m_Module;
} }
// suffix // suffix
if ( HasSuffix() ) if ( HasSuffix() )
{ {
::strcat(m_sz, " / "); ::strcat(sz, " / ");
::strncat(m_sz, m_Suffix, CALLSUFFIX_LEN); ::strncat(sz, m_Suffix.c, CALLSUFFIX_LEN);
} }
// done // done
return m_sz; return sz;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -499,7 +526,7 @@ void CCallsign::CSIn()
m_coded = pos; m_coded = pos;
m_coded *= 40; m_coded *= 40;
for( int i=CALLSIGN_LEN-2; i>=0; i-- ) { for( int i=CALLSIGN_LEN-2; i>=0; i-- ) {
pos = m17_alphabet.find(m_Callsign[i]); pos = m17_alphabet.find(m_Callsign.c[i]);
if (pos == std::string::npos) { if (pos == std::string::npos) {
pos = 0; pos = 0;
} }

@ -27,6 +27,18 @@
#define CALLSIGN_LEN 8 #define CALLSIGN_LEN 8
#define CALLSUFFIX_LEN 4 #define CALLSUFFIX_LEN 4
union UCallsign
{
char c[CALLSIGN_LEN];
uint64_t l;
};
union USuffix
{
char c[CALLSUFFIX_LEN];
uint32_t u;
};
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// class // class
@ -36,7 +48,9 @@ class CCallsign
public: public:
// contructors // contructors
CCallsign(); CCallsign();
CCallsign(const char *, uint32_t = 0, uint16_t = 0); CCallsign(const UCallsign &cs); // no id lookup
CCallsign(const CCallsign &cs);
CCallsign(const std::string &cs, uint32_t dmrid = 0, uint16_t nxdnid = 0);
// status // status
bool IsValid(void) const; bool IsValid(void) const;
@ -44,23 +58,24 @@ public:
bool HasModule(void) const { return m_Module != ' '; } bool HasModule(void) const { return m_Module != ' '; }
// set // set
void SetCallsign(const char *, bool = true); void SetCallsign(const std::string &s, bool updateids = true);
void SetCallsign(const uint8_t *, int, bool = true); void SetCallsign(const uint8_t *, int, bool = true);
void SetDmrid(uint32_t, bool = true); void SetDmrid(uint32_t, bool = true);
void SetDmrid(const uint8_t *, bool = true); void SetDmrid(const uint8_t *, bool = true);
void SetNXDNid(uint16_t, bool = true); void SetNXDNid(uint16_t, bool = true);
void SetNXDNid(const uint8_t *, bool = true); void SetNXDNid(const uint8_t *, bool = true);
void SetCSModule(char); void SetCSModule(char);
void SetSuffix(const char *); void SetSuffix(const std::string &s);
void SetSuffix(const uint8_t *, int); void SetSuffix(const uint8_t *, int);
// modify // modify
void PatchCallsign(int, const char *, int); void PatchCallsign(int, const char *, int);
// get // get
const UCallsign GetKey() const;
void GetCallsign(uint8_t *) const; void GetCallsign(uint8_t *) const;
void GetCallsignString(char *) const; void GetCallsignString(char *) const;
const std::string GetCS(unsigned len = 9) const; const std::string GetCS() const;
uint32_t GetDmrid(void) const { return m_uiDmrid; } uint32_t GetDmrid(void) const { return m_uiDmrid; }
uint16_t GetNXDNid(void) const { return m_uiNXDNid; } uint16_t GetNXDNid(void) const { return m_uiNXDNid; }
void GetSuffix(uint8_t *) const; void GetSuffix(uint8_t *) const;
@ -73,6 +88,7 @@ public:
bool HasSameModule(const CCallsign &) const; bool HasSameModule(const CCallsign &) const;
// operators // operators
CCallsign &operator = (const CCallsign &cs);
bool operator ==(const CCallsign &) const; bool operator ==(const CCallsign &) const;
operator const char *() const; operator const char *() const;
@ -92,10 +108,10 @@ protected:
protected: protected:
// data // data
char m_Callsign[CALLSIGN_LEN]; UCallsign m_Callsign;
char m_Suffix[CALLSUFFIX_LEN]; USuffix m_Suffix;
char m_Module; char m_Module;
uint32_t m_uiDmrid; uint32_t m_uiDmrid;
uint16_t m_uiNXDNid; uint16_t m_uiNXDNid;
uint64_t m_coded; // M17 encoded callsign uint64_t m_coded; // M17 encoded callsign
}; };

@ -86,7 +86,7 @@ void CLookup::Thread()
// It would be a lot of work (iterating on an unordered_map) to do otherwise! // It would be a lot of work (iterating on an unordered_map) to do otherwise!
if (http_loaded || ERefreshType::file == m_Type) if (http_loaded || ERefreshType::file == m_Type)
ClearContents(); ClearContents();
UpdateContent(ss); UpdateContent(ss, Eaction::normal);
Unlock(); Unlock();
} }
@ -115,7 +115,7 @@ bool CLookup::LoadContentFile(std::stringstream &ss)
return rval; return rval;
} }
bool CLookup::Dump() bool CLookup::Utility(Eaction action)
{ {
std::stringstream ss; std::stringstream ss;
LoadParameters(); LoadParameters();

@ -24,14 +24,16 @@
#include "Callsign.h" #include "Callsign.h"
#include "Configure.h" #include "Configure.h"
enum class Eaction { normal, parse, error_only };
// compare function for std::map::find // compare function for std::map::find
struct CCallsignHash struct CCallsignHash
{ {
std::size_t operator() (const CCallsign &cs) const std::size_t operator() (const UCallsign &ucs) const
{ {
std::hash<std::string> hash; std::hash<uint64_t> hash;
return hash(cs.GetCS()); return hash(ucs.l);
} }
}; };
@ -50,7 +52,7 @@ public:
// locks // locks
void Lock(void) { m_Mutex.lock(); } void Lock(void) { m_Mutex.lock(); }
void Unlock(void) { m_Mutex.unlock(); } void Unlock(void) { m_Mutex.unlock(); }
bool Dump(void); bool Utility(Eaction action);
protected: protected:
std::time_t GetLastModTime(); std::time_t GetLastModTime();
@ -61,7 +63,7 @@ protected:
// refresh // refresh
bool LoadContentHttp(std::stringstream &ss); bool LoadContentHttp(std::stringstream &ss);
bool LoadContentFile(std::stringstream &ss); bool LoadContentFile(std::stringstream &ss);
virtual void UpdateContent(std::stringstream &ss) = 0; virtual void UpdateContent(std::stringstream &ss, Eaction action) = 0;
std::mutex m_Mutex; std::mutex m_Mutex;
ERefreshType m_Type; ERefreshType m_Type;

@ -37,10 +37,9 @@ void CLookupDmr::LoadParameters()
m_Url.assign(g_Conf.GetString(g_Keys.dmriddb.url)); m_Url.assign(g_Conf.GetString(g_Keys.dmriddb.url));
} }
uint32_t CLookupDmr::FindDmrid(const CCallsign &callsign) const uint32_t CLookupDmr::FindDmrid(const UCallsign &ucs) const
{ {
auto found = m_DmridMap.find(ucs);
auto found = m_DmridMap.find(callsign);
if ( found != m_DmridMap.end() ) if ( found != m_DmridMap.end() )
{ {
return (found->second); return (found->second);
@ -48,7 +47,7 @@ uint32_t CLookupDmr::FindDmrid(const CCallsign &callsign)
return 0; return 0;
} }
const CCallsign *CLookupDmr::FindCallsign(uint32_t dmrid) const UCallsign *CLookupDmr::FindCallsign(const uint32_t dmrid) const
{ {
auto found = m_CallsignMap.find(dmrid); auto found = m_CallsignMap.find(dmrid);
if ( found != m_CallsignMap.end() ) if ( found != m_CallsignMap.end() )
@ -58,27 +57,47 @@ const CCallsign *CLookupDmr::FindCallsign(uint32_t dmrid)
return nullptr; return nullptr;
} }
void CLookupDmr::UpdateContent(std::stringstream &ss) void CLookupDmr::UpdateContent(std::stringstream &ss, Eaction action)
{ {
std::string line; std::string line;
while (std::getline(ss, line)) while (std::getline(ss, line))
{ {
std::string cs_str, id_str; bool failed = true;
std::istringstream iss(line); auto l = atol(line.c_str()); // no throw guarantee
std::getline(iss, id_str, ';'); if (0L < l && l <= 9999999L)
std::getline(iss, cs_str, ';');
auto lid = stol(id_str);
if (lid > 0 && lid < 0x1000000 && cs_str.size() < CALLSIGN_LEN)
{ {
auto id = uint32_t(lid); auto id = uint32_t(l);
CCallsign cs(cs_str.c_str(), id); auto p1 = line.find(';');
m_DmridMap[cs] = id; if (std::string::npos != p1)
m_CallsignMap[id] = cs; {
auto p2 = line.find(';', ++p1);
if (std::string::npos != p2)
{
const auto cs_str(line.substr(p1, p2-p1));
CCallsign cs;
cs.SetCallsign(cs_str, false);
if (cs.IsValid())
{
failed = false;
if (Eaction::normal == action)
{
auto key = cs.GetKey();
m_DmridMap[key] = id;
m_CallsignMap[id] = key;
}
else if (Eaction::parse == action)
{
std::cout << id << ';' << cs_str << ";\n";
}
}
}
}
} }
else if (Eaction::error_only == action && failed)
{ {
std::cout << "DMR Id '" << id_str << ';' << cs_str << ";' is malformed" << std::endl; std::cout << "Bad syntax at line '" << line << "'\n";
} }
} }
std::cout << "DMR Id database size now is " << m_DmridMap.size() << std::endl; if (Eaction::normal == action)
std::cout << "DMR Id database size: " << m_DmridMap.size() << std::endl;
} }

@ -24,15 +24,15 @@ class CLookupDmr : public CLookup
{ {
public: public:
~CLookupDmr() {} ~CLookupDmr() {}
uint32_t FindDmrid(const CCallsign &cs); const uint32_t FindDmrid(const UCallsign &ucs) const;
const CCallsign *FindCallsign(uint32_t dmrid); const UCallsign *FindCallsign(uint32_t dmrid) const;
protected: protected:
void ClearContents(); void ClearContents();
void LoadParameters(); void LoadParameters();
void UpdateContent(std::stringstream &ss); void UpdateContent(std::stringstream &ss, Eaction action);
private: private:
std::unordered_map<uint32_t, CCallsign> m_CallsignMap; std::unordered_map<uint32_t, UCallsign> m_CallsignMap;
std::unordered_map<CCallsign, uint32_t, CCallsignHash> m_DmridMap; std::unordered_map<UCallsign, uint32_t, CCallsignHash> m_DmridMap;
}; };

@ -37,7 +37,7 @@ void CLookupNxdn::LoadParameters()
m_Url.assign(g_Conf.GetString(g_Keys.nxdniddb.url)); m_Url.assign(g_Conf.GetString(g_Keys.nxdniddb.url));
} }
const CCallsign *CLookupNxdn::FindCallsign(uint16_t nxdnid) const UCallsign *CLookupNxdn::FindCallsign(uint16_t nxdnid) const
{ {
auto found = m_CallsignMap.find(nxdnid); auto found = m_CallsignMap.find(nxdnid);
if ( found != m_CallsignMap.end() ) if ( found != m_CallsignMap.end() )
@ -47,37 +47,57 @@ const CCallsign *CLookupNxdn::FindCallsign(uint16_t nxdnid)
return nullptr; return nullptr;
} }
uint16_t CLookupNxdn::FindNXDNid(const CCallsign &callsign) const uint16_t CLookupNxdn::FindNXDNid(const UCallsign &ucs) const
{ {
auto found = m_NxdnidMap.find(callsign); auto found = m_NxdnidMap.find(ucs);
if ( found != m_NxdnidMap.end() ) if ( found != m_NxdnidMap.end() )
{ {
return (found->second); return found->second;
} }
return 0; return 0;
} }
void CLookupNxdn::UpdateContent(std::stringstream &ss) void CLookupNxdn::UpdateContent(std::stringstream &ss, Eaction action)
{ {
std::string line; std::string line;
while (std::getline(ss, line)) while (std::getline(ss, line))
{ {
std::string cs_str, id_str; bool failed = true;
std::istringstream iss(line); auto l = atol(line.c_str()); // no throw guarantee
std::getline(iss, id_str, ','); if (0 < l && l < 0x10000UL)
std::getline(iss, cs_str, ',');
auto lid = stol(id_str);
if (lid > 0 && lid < 0x10000 && cs_str.size() < CALLSIGN_LEN)
{ {
auto id = uint16_t(lid); auto id = uint32_t(l);
CCallsign cs(cs_str.c_str(), 0, id); auto p1 = line.find(',');
m_NxdnidMap[cs] = id; if (std::string::npos != p1)
m_CallsignMap[id] = cs; {
auto p2 = line.find(',', ++p1);
if (std::string::npos != p2)
{
const auto cs_str = line.substr(p1, p2-p1);
CCallsign cs;
cs.SetCallsign(cs_str, false);
if (cs.IsValid())
{
failed = false;
if (Eaction::normal == action)
{
auto key = cs.GetKey();
m_NxdnidMap[key] = id;
m_CallsignMap[id] = key;
}
else if (Eaction::parse == action)
{
std::cout << id << ',' << cs_str << ",\n";
}
}
}
}
} }
else if (Eaction::error_only == action && failed)
{ {
std::cout << "NXDN Id '" << id_str << ',' << cs_str << ",' is malformed" << std::endl; std::cout << "Bad syntax at line '" << line << "'\n";
} }
} }
std::cout << "NXDN Id database size now is " << m_NxdnidMap.size() << std::endl; if (Eaction::normal == action)
std::cout << "NXDN Id database size: " << m_NxdnidMap.size() << std::endl;
} }

@ -23,14 +23,14 @@
class CLookupNxdn : public CLookup class CLookupNxdn : public CLookup
{ {
public: public:
uint16_t FindNXDNid(const CCallsign &callsign); const uint16_t FindNXDNid(const UCallsign &ucs) const;
const CCallsign *FindCallsign(uint16_t id); const UCallsign *FindCallsign(const uint16_t id) const;
protected: protected:
void ClearContents(); void ClearContents();
void LoadParameters(); void LoadParameters();
void UpdateContent(std::stringstream &ss); void UpdateContent(std::stringstream &ss, Eaction action);
private: private:
std::unordered_map <uint32_t, CCallsign> m_CallsignMap; std::unordered_map <uint32_t, UCallsign> m_CallsignMap;
std::unordered_map <CCallsign, uint32_t, CCallsignHash> m_NxdnidMap; std::unordered_map <UCallsign, uint32_t, CCallsignHash> m_NxdnidMap;
}; };

@ -39,34 +39,43 @@ void CLookupYsf::LoadParameters()
m_DefaultRx = g_Conf.GetUnsigned(g_Keys.ysf.defaultrxfreq); m_DefaultRx = g_Conf.GetUnsigned(g_Keys.ysf.defaultrxfreq);
} }
void CLookupYsf::UpdateContent(std::stringstream &ss) void CLookupYsf::UpdateContent(std::stringstream &ss, Eaction action)
{ {
std::string line; std::string line;
while (std::getline(ss, line)) while (std::getline(ss, line))
{ {
CCallsign cs;
std::string cs_str, tx_str, rx_str; std::string cs_str, tx_str, rx_str;
std::istringstream iss(line); std::istringstream iss(line);
std::getline(iss, cs_str, ';'); std::getline(iss, cs_str, ';');
std::getline(iss, tx_str, ';'); std::getline(iss, tx_str, ';');
std::getline(iss, rx_str, ';'); std::getline(iss, rx_str, ';');
auto ltx = stol(tx_str); cs.SetCallsign(cs_str, false);
auto lrx = stol(rx_str); auto ltx = atol(tx_str.c_str());
if (ltx > 40000000 && ltx < 0x100000000 && lrx > 40000000 && lrx < 0x100000000 && CCallsign(cs_str.c_str()).IsValid()) auto lrx = atol(rx_str.c_str());
if (ltx > 40000000 && ltx < 0x100000000 && lrx > 40000000 && lrx < 0x100000000 && cs.IsValid())
{ {
m_map.emplace(CCallsign(cs_str.c_str()), CYsfNode(uint32_t(ltx), uint32_t(lrx))); if (Eaction::parse == action)
{
std::cout << cs_str << ';' << tx_str << ';' << rx_str << ";\n";
}
else if (Eaction::normal == action)
{
m_map[cs.GetKey()] = CYsfNode(ltx, lrx);
}
} }
else else if (Eaction::error_only == action)
{ {
std::cout << "YSF value '" << cs_str << ';' << tx_str << ';' << rx_str << ";' is malformed" << std::endl; std::cout << "YSF value '" << line << ";' is malformed" << std::endl;
} }
} }
std::cout << "DMR Id database size now is " << m_map.size() << std::endl; std::cout << "DMR Id database size now is " << m_map.size() << std::endl;
} }
void CLookupYsf::FindFrequencies(const CCallsign &callsign, uint32_t &txfreq, uint32_t &rxfreq) void CLookupYsf::FindFrequencies(const CCallsign &cs, uint32_t &txfreq, uint32_t &rxfreq)
{ {
auto found = m_map.find(callsign); auto found = m_map.find(cs.GetKey());
if ( found != m_map.end() ) if (found != m_map.end())
{ {
txfreq = found->second.GetTxFrequency(); txfreq = found->second.GetTxFrequency();
rxfreq = found->second.GetRxFrequency(); rxfreq = found->second.GetRxFrequency();

@ -21,7 +21,7 @@
#include "YSFNode.h" #include "YSFNode.h"
#include "Lookup.h" #include "Lookup.h"
using CsNodeMap = std::unordered_map<CCallsign, CYsfNode, CCallsignHash>; using CsNodeMap = std::unordered_map<UCallsign, CYsfNode, CCallsignHash>;
class CLookupYsf : public CLookup class CLookupYsf : public CLookup
{ {
@ -31,7 +31,7 @@ public:
protected: protected:
void ClearContents(); void ClearContents();
void LoadParameters(); void LoadParameters();
void UpdateContent(std::stringstream &ss); void UpdateContent(std::stringstream &ss, Eaction action);
private: private:
CsNodeMap m_map; CsNodeMap m_map;

@ -20,9 +20,11 @@
#include "Global.h" #include "Global.h"
#ifndef UTILITY
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// global objects // global objects
SJsonKeys g_Keys;
CReflector g_Refl; CReflector g_Refl;
CGateKeeper g_Gate; CGateKeeper g_Gate;
CConfigure g_Conf; CConfigure g_Conf;
@ -30,7 +32,6 @@ CVersion g_Vers(3,0,0); // The major byte should only change if the interlink
CLookupDmr g_LDid; CLookupDmr g_LDid;
CLookupNxdn g_LNid; CLookupNxdn g_LNid;
CLookupYsf g_LYtr; CLookupYsf g_LYtr;
SJsonKeys g_Keys;
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -75,3 +76,149 @@ int main(int argc, char *argv[])
// done // done
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
#else // UTILITY is defined
#include <unistd.h>
////////////////////////////////////////////////////////////////////////////////////////
// global objects
SJsonKeys g_Keys;
CConfigure g_Conf;
CLookupDmr g_LDid;
CLookupNxdn g_LNid;
CLookupYsf g_LYtr;
static void usage(std::ostream &os, const char *name)
{
os << "Usage: " << name << " [-d | -n | -y] [-p | -q] inifile\n";
os << "Where:\n"
" -d - read the DMR Id http source (default)\n"
" -n - read the NXDN Id http source\n"
" -y - read the YSF Tx/Tx http source\n"
" -p - parse the input, removing bad lines\n"
" -q - parse the input, but only output problem lines in the http source\n"
" infile - an error-free urfd ini file (check it first with inicheck)\n"
"Without -p or -q, no parsing is done and the raw http source is output\n"
<< std::endl;
}
enum class Edb { none, dmr, nxdn, ysf };
int main(int argc, char *argv[])
{
Edb db = Edb::none;
Eaction action = Eaction::normal;
while (1)
{
auto c = getopt(argc, argv, "dnypq");
if (c < 0)
{
if (1 == argc)
{
usage(std::cout, argv[0]);
return EXIT_SUCCESS;
}
break;
}
else
{
switch (c)
{
// define the input souce
case 'd':
if (Edb::none == db)
db = Edb::dmr;
else
{
std::cerr << "You can only select one database!\n";
usage(std::cerr, argv[0]);
return EXIT_FAILURE;
}
break;
case 'n':
if (Edb::none == db)
db = Edb::nxdn;
else
{
std::cerr << "You can only select one database!\n";
usage(std::cerr, argv[0]);
return EXIT_FAILURE;
}
break;
case 'y':
if (Edb::none == db)
db = Edb::ysf;
else
{
std::cerr << "You can only select one database!\n";
usage(std::cerr, argv[0]);
return EXIT_FAILURE;
}
break;
// define the action
case 'p':
if (Eaction::err_only == action)
{
std::cerr << "You can't specify both -p and -q!\n";
usage(std::cerr, argv[0]);
return EXIT_FAILURE;
}
else
action = Eaction::parse;
break;
case 'q':
if (Eaction::parse == action)
{
std::cerr << "You can't specify both -p and -q!\n";
usage(std::cerr, argv[0]);
return EXIT_FAILURE;
}
else
action = Eaction::err_only;
break;
// finally
default:
usage(std::cerr, argv[0]);
return EXIT_FAILURE;
break;
}
}
}
if (optind + 1 != argc)
{
std::cerr << argv[0] << ": " << ((optind==argc) ? "No ini file specified!" : "Too many arguments!") << std::endl;
usage(std::cerr, argv[0]);
exit(EXIT_FAILURE);
}
if (g_Conf.ReadData(argv[optind]))
return EXIT_FAILURE;
if (Edb::none == db)
db = Edb::dmr;
switch (db)
{
case Edb::dmr:
g_LDid.Utility(action);
break;
case Edb::nxdn:
g_LNid.Utility(action);
break;
case Edb::ysf:
g_LYtr.Utility(action);
break;
}
return EXIT_SUCCESS;
}
#endif

@ -22,6 +22,8 @@ EXE = urfd
INICHECK = inicheck INICHECK = inicheck
DBUTIL = dbutil
include configure.mk include configure.mk
ifeq ($(debug), true) ifeq ($(debug), true)
@ -36,7 +38,7 @@ SRCS = $(wildcard *.cpp)
OBJS = $(SRCS:.cpp=.o) OBJS = $(SRCS:.cpp=.o)
DEPS = $(SRCS:.cpp=.d) DEPS = $(SRCS:.cpp=.d)
all : $(EXE) $(INICHECK) all : $(EXE) $(INICHECK) $(DBUTIL)
$(EXE) : $(OBJS) $(EXE) : $(OBJS)
$(CXX) $^ -o $@ $(LDFLAGS) $(CXX) $^ -o $@ $(LDFLAGS)
@ -44,11 +46,14 @@ $(EXE) : $(OBJS)
$(INICHECK) : Configure.cpp CurlGet.cpp $(INICHECK) : Configure.cpp CurlGet.cpp
$(CXX) -DINICHECK $(CFLAGS) Configure.cpp CurlGet.cpp -o $(INICHECK) -lcurl $(CXX) -DINICHECK $(CFLAGS) Configure.cpp CurlGet.cpp -o $(INICHECK) -lcurl
$(DBUTIL) : Main.cpp Configure.cpp CurlGet.cpp Lookup.cpp LookupDmr.cpp LookupNxdn.cpp LookupYsf.cpp YSFNode.cpp Callsign.cpp
$(CXX) -DUTILITY $(CFLAGS) -o dbutil Main.cpp Configure.cpp CurlGet.cpp Lookup.cpp LookupDmr.cpp LookupNxdn.cpp LookupYsf.cpp YSFNode.cpp Callsign.cpp -lcurl
%.o : %.cpp %.o : %.cpp
$(CXX) $(CFLAGS) -c $< -o $@ $(CXX) $(CFLAGS) -c $< -o $@
clean : clean :
$(RM) *.o *.d $(EXE) $(INICHECK) $(RM) *.o *.d $(EXE) $(INICHECK) $(DBUTIL)
-include $(DEPS) -include $(DEPS)

@ -1,15 +1,16 @@
###### URFD CONFIGURATION Example ###### ###### URFD CONFIGURATION Example ######
# comments begin with '#'
# Do not use quotes, unless in a comment! # Do not use quotes, unless in a comment!
[Names] [Names]
Callsign = URF??? # where ? is A-Z or 0-9 Callsign = URF??? # where ? is A-Z or 0-9
SysopEmail = you@somewhere.com SysopEmail = me@somewhere.com
# 2-letter country codes are listed at https://www.iban.com/country-codes # 2-letter country codes are listed at https://www.iban.com/country-codes
Country = US Country = GB
Sponsor = My Ham Club Sponsor = My Home Club
[IpAddresses] [IpAddresses]
# Binding addresses are usually the 'any' address # Binding addresses are usually the 'any' address
@ -19,16 +20,15 @@ IPv4Binding = 0.0.0.0
# IPv6Binding = :: # IPv6Binding = ::
# define if you want to override what urfd finds using ipv4.icanhazip.com # define if you want to override what urfd finds using ipv4.icanhazip.com
# IPv4External = 1.2.3.4 # IPv4External = 4.3.2.1
# define if you want to override what urfd finds using ipv6.icanhazip.com # define if you want to override what urfd finds using ipv6.icanhazip.com
# IPv6External = a:b:c:e:f:0:1:2 # IPv6External = f:e:d:c:b:a:9:0
Transcoder = local # SORRY, but only local TC's are supported right now! Transcoder = local # SORRY, but only local TC's are supported right now!
[Modules] [Modules]
Modules = ADMSZ
# Modules = ABCDEFGHIJKLMNOPQRSTUVWXYZ # Modules = ABCDEFGHIJKLMNOPQRSTUVWXYZ
Modules = ADMSZ
Transcoded = A # comment out if you don't have transcoding hardware Transcoded = A # comment out if you don't have transcoding hardware
# Create Descriptions as needed... # Create Descriptions as needed...
DescriptionA = Transcoded DescriptionA = Transcoded
@ -58,7 +58,7 @@ Port = 17000
[MMDVM] [MMDVM]
Port = 62030 Port = 62030
DefaultId = 0 # if the DMR id is zero, this will be used (also used for P25) DefaultId = 0
[NXDN] [NXDN]
Port = 41400 Port = 41400
@ -77,7 +77,7 @@ Port = 10017
Port = 34001 Port = 34001
AutoLinkModule = A # comment out if you want to disable AL AutoLinkModule = A # comment out if you want to disable AL
DefaultCallsign = ALLSTAR DefaultCallsign = ALLSTAR
ClientFilePath = /home/user/urfd/USRPClients.txt ClientFilePath = /usr/local/etc/USRPClients.txt
[YSF] [YSF]
Port = 42000 Port = 42000
@ -91,31 +91,30 @@ RegistrationDescription = URF Reflector
######## Database files ######## Database files
[DMR ID DB] [DMR ID DB]
Hostname = xlxapi.rlx.lu Mode = http #### Mode is "http", "file", or "both"
Suffix = api/exportdmr.php #### if "both", the url will be read first
Mode = http FilePath = /usr/local/etc/dmrid.dat # for you to add your own values
RefreshMin = 179 # will be reloaded quickly, about 10s
FilePath = /home/user/urfd/dmrid.dat URL = http://xlxapi.rlx.lu/api/exportdmr.php # if Mode "http" or "both"
RefreshMin = 179 # RefreshMin will only be used if the Mode is "file"
[NXDN ID DB] [NXDN ID DB]
Hostname = www.dudetronics.com
Suffix = ar-dns/NXDN.csv
Mode = http Mode = http
RefreshMin = 181 FilePath = /usr/local/etc/nxdn.dat
FilePath = /home/user/urfd/nxdn.dat URL = https://radioid.net/static/nxdn.csv
RefreshMin = 1440 # radioid.net says this file is updated once/day
[YSF TX/RX DB] [YSF TX/RX DB]
Hostname = xlxapi.rlx.lu
Suffix = api/exportysfrepeaters.php
Mode = http Mode = http
FilePath = /usr/local/etc/ysfnode.dat
URL = http://xlxapi.rlx.lu/api/exportysfrepeaters.php
RefreshMin = 191 RefreshMin = 191
FilePath = /home/user/urfd/ysfnode.dat
######### Other File locations ######### Other File locations
[Files] [Files]
PidPath = /var/run/urfd.pid PidPath = /var/run/urfd.pid
JsonPath = /var/log/urfd.json JsonPath = /var/log/urfd.json
WhitelistPath = /home/user/urfd/urfd.whitelist WhitelistPath = /usr/local/etc/urfd.whitelist
BlacklistPath = /home/user/urfd/urfd.blacklist BlacklistPath = /usr/local/etc/urfd.blacklist
InterlinkPath = /home/user/urfd/urfd.interlink InterlinkPath = /usr/local/etc/urfd.interlink
G3TerminalPath = /home/user/urfd/urfd.terminal G3TerminalPath = /usr/local/etc/urfd.terminal

Loading…
Cancel
Save

Powered by TurnKey Linux.