diff --git a/Makefile b/Makefile index 9a24d1a..efdaba6 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ OBJECTS = \ NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o \ NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o \ POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o \ - TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Pi b/Makefile.Pi index fe7da05..640c07f 100644 --- a/Makefile.Pi +++ b/Makefile.Pi @@ -13,7 +13,7 @@ OBJECTS = \ NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o \ NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o \ POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o \ - UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + UDPSocket.o UMP.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Pi.Adafruit b/Makefile.Pi.Adafruit index 1849e68..24c2907 100644 --- a/Makefile.Pi.Adafruit +++ b/Makefile.Pi.Adafruit @@ -14,7 +14,7 @@ OBJECTS = \ NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o \ NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o \ POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o TFTSurenoo.o Thread.o \ - Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + Timer.o UDPSocket.o UMP.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Pi.HD44780 b/Makefile.Pi.HD44780 index f7c0c31..c2faad2 100644 --- a/Makefile.Pi.HD44780 +++ b/Makefile.Pi.HD44780 @@ -13,7 +13,7 @@ OBJECTS = \ NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o \ NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o \ POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o TFTSurenoo.o Thread.o \ - Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + Timer.o UDPSocket.o UMP.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Pi.OLED b/Makefile.Pi.OLED index d6acd67..d2db40c 100644 --- a/Makefile.Pi.OLED +++ b/Makefile.Pi.OLED @@ -13,7 +13,7 @@ OBJECTS = \ NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o \ NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o \ POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o TFTSurenoo.o Thread.o \ - Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + Timer.o UDPSocket.o UMP.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Pi.PCF8574 b/Makefile.Pi.PCF8574 index c3441c6..4c5d3a3 100644 --- a/Makefile.Pi.PCF8574 +++ b/Makefile.Pi.PCF8574 @@ -14,7 +14,7 @@ OBJECTS = \ NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o \ NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o \ POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o TFTSurenoo.o Thread.o \ - Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + Timer.o UDPSocket.o UMP.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Solaris b/Makefile.Solaris index 1d94eef..c50d41e 100644 --- a/Makefile.Solaris +++ b/Makefile.Solaris @@ -13,7 +13,7 @@ OBJECTS = \ NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o \ NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o \ QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o \ - UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + UMP.o UserDB.o UserDBebtry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/UserDB.cpp b/UserDB.cpp new file mode 100644 index 0000000..2e20fb0 --- /dev/null +++ b/UserDB.cpp @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2020 by SASANO Takayoshi JG1UAA + * + * 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 "UserDB.h" +#include "Log.h" + +#include +#include +#include + +CUserDB::CUserDB() : +m_table(), +m_mutex() +{ +} + +CUserDB::~CUserDB() +{ +} + +bool CUserDB::lookup(unsigned int id, class CUserDBentry *entry) +{ + bool rv; + + m_mutex.lock(); + + try { + if (entry != NULL) + *entry = m_table.at(id); + else + m_table.at(id); + + rv = true; + } catch (...) { + rv = false; + } + + m_mutex.unlock(); + + return rv; +} + +bool CUserDB::load(std::string const& filename) +{ + FILE* fp = ::fopen(filename.c_str(), "r"); + if (fp == NULL) { + LogWarning("Cannot open ID lookup table - %s", filename.c_str()); + return false; + } + + m_mutex.lock(); + + // Remove the old entries; + m_table.clear(); + + // set index for entries + char buffer[256U]; + if (::fgets(buffer, sizeof(buffer), fp) == NULL) { + LogWarning("ID lookup file has no entry - %s", filename.c_str()); + m_mutex.unlock(); + ::fclose(fp); + return false; + } + + // no index - set default + std::unordered_map index; + if (!makeindex(buffer, index)) { + ::strncpy(buffer, "RADIO_ID,CALLSIGN,FIRST_NAME", sizeof(buffer)); + makeindex(buffer, index); + ::rewind(fp); + } + + while (::fgets(buffer, sizeof(buffer), fp) != NULL) { + if (buffer[0U] != '#') + parse(buffer, index); + } + + ::fclose(fp); + + size_t size = m_table.size(); + m_mutex.unlock(); + + LogInfo("Loaded %u IDs to lookup table - %s", size, filename.c_str()); + + return (size != 0U); +} + +bool CUserDB::makeindex(char* buf, std::unordered_map& index) +{ + int i; + char *p1, *p2; + + for (i = 0, p1 = tokenize(buf, &p2); p1 != NULL; + i++, p1 = tokenize(p2, &p2)) { + + // create [column keyword] - [column number] table + if (CUserDBentry::isValidKey(p1)) + index[p1] = i; + } + + try { + index.at(keyRADIO_ID); + index.at(keyCALLSIGN); + return true; + } catch (...) { + return false; + } +} + +void CUserDB::parse(char* buf, std::unordered_map& index) +{ + int i; + char *p1, *p2; + std::unordered_map ptr; + unsigned int id; + + for (i = 0, p1 = tokenize(buf, &p2); p1 != NULL; + i++, p1 = tokenize(p2, &p2)) { + + for (auto it = index.begin(); it != index.end(); it++) { + // first: column keyword, second: column number + if (it->second == i) { + ptr[it->first] = p1; + break; + } + } + } + + try { + ptr.at(keyRADIO_ID); + ptr.at(keyCALLSIGN); + } catch (...) { + return; + } + + id = (unsigned int)::atoi(ptr[keyRADIO_ID]); + toupper_string(ptr[keyCALLSIGN]); + + for (auto it = ptr.begin(); it != ptr.end(); it++) { + // no need to regist radio ID + if (it->first == keyRADIO_ID) + continue; + + m_table[id].set(it->first, std::string(it->second)); + } +} + +void CUserDB::toupper_string(char* str) +{ + while (*str != '\0') { + *str = ::toupper(*str); + str++; + } +} + +char* CUserDB::tokenize(char* str, char** next) +{ + if (*str == '\0') + return NULL; + + char* p = ::strpbrk(str, ",\t\r\n"); + if (p == NULL) { + *next = str + ::strlen(str); + } else { + *p = '\0'; + *next = p + 1; + } + + return str; +} diff --git a/UserDB.h b/UserDB.h new file mode 100644 index 0000000..acae103 --- /dev/null +++ b/UserDB.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2020 by SASANO Takayoshi JG1UAA + * + * 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(USERDB_H) +#define USERDB_H + +#include "UserDBentry.h" +#include "Mutex.h" + +class CUserDB { +public: + CUserDB(); + ~CUserDB(); + + bool lookup(unsigned int id, class CUserDBentry *entry); + bool load(std::string const& filename); + +private: + bool makeindex(char* buf, std::unordered_map& index); + void parse(char* buf, std::unordered_map& index); + void toupper_string(char* str); + char* tokenize(char* str, char** next); + + std::unordered_map m_table; + CMutex m_mutex; +}; + +#endif diff --git a/UserDBentry.cpp b/UserDBentry.cpp new file mode 100644 index 0000000..5b66c59 --- /dev/null +++ b/UserDBentry.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2020 by SASANO Takayoshi JG1UAA + * + * 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 "UserDBentry.h" +#include + +CUserDBentry::CUserDBentry() : +m_db() +{ +} + +CUserDBentry::~CUserDBentry() +{ +} + +const std::vector CUserDBentry::keyList { + keyRADIO_ID, keyCALLSIGN, keyFIRST_NAME, keyLAST_NAME, + keyCITY, keySTATE, keyCOUNTRY, +}; + +bool CUserDBentry::isValidKey(const std::string key) +{ + auto it = std::find(keyList.begin(), keyList.end(), key); + return it != keyList.end(); +} + +void CUserDBentry::set(const std::string key, const std::string value) +{ + if (isValidKey(key)) + m_db[key] = value; +} + +std::string CUserDBentry::get(const std::string key) +{ + try { + return m_db.at(key); + } catch (...) { + return ""; + } +} diff --git a/UserDBentry.h b/UserDBentry.h new file mode 100644 index 0000000..d44f451 --- /dev/null +++ b/UserDBentry.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2020 by SASANO Takayoshi JG1UAA + * + * 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(USERDBENTRY_H) +#define USERDBENTRY_H + +#include +#include +#include + +#define keyRADIO_ID "RADIO_ID" +#define keyCALLSIGN "CALLSIGN" +#define keyFIRST_NAME "FIRST_NAME" +#define keyLAST_NAME "LAST_NAME" +#define keyCITY "CITY" +#define keySTATE "STATE" +#define keyCOUNTRY "COUNTRY" + +class CUserDBentry { +public: + CUserDBentry(); + ~CUserDBentry(); + + static const std::vector keyList; + static bool isValidKey(const std::string key); + + void set(const std::string key, const std::string value); + std::string get(const std::string key); + +private: + std::unordered_map m_db; +}; + +#endif