diff --git a/.gitignore b/.gitignore index b1e9ca5..1babcf3 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,6 @@ qndv qndvrptr qnlink qngateway -qnigateway qnremote qnvoice qnrelay diff --git a/DPlusAuthenticator.cpp b/DPlusAuthenticator.cpp index 00ccf47..9ea9393 100644 --- a/DPlusAuthenticator.cpp +++ b/DPlusAuthenticator.cpp @@ -57,7 +57,7 @@ int CDPlusAuthenticator::Process(CQnetDB &db, const bool reflectors, const bool int CDPlusAuthenticator::authenticate(CQnetDB &db, const bool reflectors, const bool repeaters) { - unsigned char* buffer = new unsigned char[4096U]; + unsigned char buffer[4096U]; ::memset(buffer, ' ', 56U); buffer[0U] = 0x38U; @@ -73,12 +73,12 @@ int CDPlusAuthenticator::authenticate(CQnetDB &db, const bool reflectors, const if (client.Write(buffer, 56U)) { fprintf(stderr, "ERROR: could not write opening phrase\n"); client.Close(); - delete[] buffer; return 0; } int ret = client.ReadExact(buffer, 2U); unsigned int rval = 0; + CHostQueue hqueue; while (ret == 2) { unsigned int len = (buffer[1U] & 0x0FU) * 256U + buffer[0U]; @@ -107,13 +107,17 @@ int CDPlusAuthenticator::authenticate(CQnetDB &db, const bool reflectors, const // An empty name or IP address or an inactive gateway/reflector is not added if (address.size()>0U && name.size()>0U && active) { - rval++; - if (reflectors && 0==name.compare(0, 3, "REF")) - db.UpdateGW(name.c_str(), address.c_str(), 20001); - else if (repeaters && name.compare(0, 3, "REF")) - db.UpdateGW(name.c_str(), address.c_str(), 20001); + if (reflectors && 0==name.compare(0, 3, "REF")) { + rval++; + hqueue.Push(CHost(name.c_str(), address.c_str(), 20001)); + } else if (repeaters && name.compare(0, 3, "REF")) { + rval++; + hqueue.Push(CHost(name.c_str(), address.c_str(), 20001)); + } } } + if (! hqueue.Empty()) + db.UpdateGW(hqueue); ret = client.ReadExact(buffer, 2U); } @@ -121,7 +125,5 @@ int CDPlusAuthenticator::authenticate(CQnetDB &db, const bool reflectors, const printf("Probably authorized DPlus on %s using callsign %s\n", m_address.c_str(), m_loginCallsign.c_str()); client.Close(); - delete[] buffer; - return rval; } diff --git a/HostQueue.h b/HostQueue.h new file mode 100644 index 0000000..ef6e75b --- /dev/null +++ b/HostQueue.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2019 by Thomas A. Early N7TAE + * + * 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. + */ + +#pragma once + +#include +#include + +class CHost { +public: + CHost() {} + + ~CHost() {} + + CHost(const CHost &from) + { + name.assign(from.name); + addr.assign(from.addr); + port = from.port; + } + + CHost(const std::string n, const std::string a, unsigned short p) + { + name.assign(n); + addr.assign(a); + port = p; + } + + CHost &operator=(const CHost &from) + { + name.assign(from.name); + addr.assign(from.addr); + port = from.port; + return *this; + } + + std::string name, addr; + unsigned short port; +}; + +template class CTQueue +{ +public: + CTQueue() {} + + ~CTQueue() + { + Clear(); + } + + void Push(T item) + { + queue.push(item); + } + + T Pop() + { + T item = queue.front(); + queue.pop(); + return item; + } + + bool Empty() + { + return queue.empty(); + } + + void Clear() + { + while (queue.size()) + queue.pop(); + } + +private: + std::queue queue; +}; + +using CHostQueue = CTQueue; diff --git a/QnetDB.cpp b/QnetDB.cpp index 8cb49cd..d099c93 100644 --- a/QnetDB.cpp +++ b/QnetDB.cpp @@ -17,6 +17,7 @@ */ #include + #include "QnetDB.h" bool CQnetDB::Open(const char *name) @@ -102,7 +103,7 @@ bool CQnetDB::UpdateLH(const char *callsign, const char *sfx, const char module, { if (NULL == db) return false; - std::string sql("REPLACE INTO LHEARD (callsign,sfx,module,reflector,lasttime) VALUES ('"); + std::string sql("INSERT OR REPLACE INTO LHEARD (callsign,sfx,module,reflector,lasttime) VALUES ('"); sql.append(callsign); sql.append("','"); sql.append(sfx); @@ -127,7 +128,7 @@ bool CQnetDB::UpdateLS(const char *address, const char from_mod, const char *to_ { if (NULL == db) return false; - std::string sql = "REPLACE INTO LINKSTATUS (ip_address,from_mod,to_callsign,to_mod,linked_time) VALUES ('"; + std::string sql = "INSERT OR REPLACE INTO LINKSTATUS (ip_address,from_mod,to_callsign,to_mod,linked_time) VALUES ('"; sql.append(address); sql.append("','"); sql.append(1, from_mod); @@ -152,10 +153,10 @@ bool CQnetDB::UpdateLS(const char *address, const char from_mod, const char *to_ bool CQnetDB::UpdateGW(const char *name, const char *address, unsigned short port) { if (NULL == db) - return false; + return true; std::string n(name); n.resize(6, ' '); - std::string sql = "REPLACE INTO GATEWAYS (name,address,port) VALUES ('"; + std::string sql = "INSERT OR REPLACE INTO GATEWAYS (name,address,port) VALUES ('"; sql.append(n); sql.append("','"); sql.append(address); @@ -173,6 +174,31 @@ bool CQnetDB::UpdateGW(const char *name, const char *address, unsigned short por return false; } +bool CQnetDB::UpdateGW(CHostQueue &hqueue) +{ + if (NULL == db) + return true; + + char *eMsg; + if (SQLITE_OK != sqlite3_exec(db, "BEGIN TRANSACTION;", NULL, 0, &eMsg)) { + fprintf(stderr, "CQnetDB::UpdateGW BEGIN TRANSATION error: %s\n", eMsg); + sqlite3_free(eMsg); + return true; + } + + while (! hqueue.Empty()) { + auto h = hqueue.Pop(); + UpdateGW(h.name.c_str(), h.addr.c_str(), h.port); + } + + if (SQLITE_OK != sqlite3_exec(db, "COMMIT TRANSACTION;", NULL, 0, &eMsg)) { + fprintf(stderr, "CQnetDB::UpdateGW END TRANSACTION error: %s\n", eMsg); + sqlite3_free(eMsg); + return true; + } + return false; +} + bool CQnetDB::DeleteLS(const char *address) { if (NULL == db) diff --git a/QnetDB.h b/QnetDB.h index a5c8418..db85f6f 100644 --- a/QnetDB.h +++ b/QnetDB.h @@ -22,6 +22,8 @@ #include #include +#include "HostQueue.h" + class CLink { public: CLink(const std::string &call, const unsigned char *addr, time_t ltime) : callsign(call) , address((const char *)addr) , linked_time(ltime) {} @@ -56,6 +58,7 @@ public: bool UpdateLH(const char *callsign, const char *sfx, const char module, const char *reflector); bool UpdateLS(const char *address, const char from_mod, const char *to_callsign, const char to_mod, time_t connect_time); bool UpdateGW(const char *name, const char *address, unsigned short port); + bool UpdateGW(CHostQueue &); bool DeleteLS(const char *address); bool FindLS(const char mod, std::list &linklist); bool FindGW(const char *name, std::string &address, unsigned short &port); diff --git a/QnetLink.cpp b/QnetLink.cpp index 78fb0a0..0a77b62 100644 --- a/QnetLink.cpp +++ b/QnetLink.cpp @@ -307,6 +307,7 @@ void CQnetLink::LoadGateways(const std::string &filename) int count = 0; std::ifstream hostfile(filename); if (hostfile.is_open()) { + CHostQueue hqueue; std::string line; while (std::getline(hostfile, line)) { trim(line); @@ -315,11 +316,13 @@ void CQnetLink::LoadGateways(const std::string &filename) std::string host, address; unsigned short port; iss >> host >> address >> port; - qnDB.UpdateGW(host.c_str(), address.c_str(), port); + hqueue.Push(CHost(host, address, port)); count++; } } hostfile.close(); + if (! hqueue.Empty()) + qnDB.UpdateGW(hqueue); } if (dplus_authorize) {