1
0
mirror of https://github.com/ShaYmez/xlxd.git synced 2025-07-29 20:02:24 -04:00

version 1.1.1

corrected file handle resource leak in CCallsignList::GetLastModTime()
This commit is contained in:
LX3JL 2016-01-01 05:21:58 +01:00
parent 22f489e440
commit 6e9b6347c4
4 changed files with 134 additions and 104 deletions

View File

@ -56,30 +56,36 @@ CCallsignList::~CCallsignList()
bool CCallsignList::LoadFromFile(const char *filename) bool CCallsignList::LoadFromFile(const char *filename)
{ {
bool ok = false; bool ok = false;
char sz[CALLSIGN_LEN+1]; char sz[32];
// and load // and load
std::ifstream file (filename); std::ifstream file (filename);
if ( file.is_open() ) if ( file.is_open() )
{ {
Lock(); Lock();
// empty list // empty list
clear(); clear();
// fill with file content // fill with file content
while ( file.getline(sz, sizeof(sz)).good() ) while ( file.getline(sz, sizeof(sz)).good() )
{ {
push_back(CCallsign(sz)); // remove leading & trailing spaces
char *szt = TrimWhiteSpaces(sz);
// and load
if ( ::strlen(szt) > 0 )
{
push_back(CCallsign(szt));
}
} }
// close file // close file
file.close(); file.close();
// keep file path // keep file path
m_Filename = filename; m_Filename = filename;
// update time // update time
GetLastModTime(&m_LastModTime); GetLastModTime(&m_LastModTime);
// and done // and done
Unlock(); Unlock();
ok = true; ok = true;
@ -96,7 +102,7 @@ bool CCallsignList::LoadFromFile(const char *filename)
bool CCallsignList::ReloadFromFile(void) bool CCallsignList::ReloadFromFile(void)
{ {
bool ok = false; bool ok = false;
if ( m_Filename != NULL ) if ( m_Filename != NULL )
{ {
ok = LoadFromFile(m_Filename); ok = LoadFromFile(m_Filename);
@ -107,7 +113,7 @@ bool CCallsignList::ReloadFromFile(void)
bool CCallsignList::NeedReload(void) bool CCallsignList::NeedReload(void)
{ {
bool needReload = false; bool needReload = false;
time_t time; time_t time;
if ( GetLastModTime(&time) ) if ( GetLastModTime(&time) )
{ {
@ -116,38 +122,57 @@ bool CCallsignList::NeedReload(void)
return needReload; return needReload;
} }
bool CCallsignList::GetLastModTime(time_t *time)
{
bool ok = false;
if ( m_Filename != NULL )
{
int file=0;
if( (file = ::open(m_Filename, O_RDONLY)) != -1 )
{
struct stat fileStat;
if( ::fstat(file, &fileStat) != -1 )
{
*time = fileStat.st_mtime;
ok = true;
}
}
}
return ok;
}
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// compare // compare
bool CCallsignList::IsListed(const CCallsign &callsign) const bool CCallsignList::IsListed(const CCallsign &callsign) const
{ {
bool listed = false; bool listed = false;
for ( int i = 0; (i < size()) && !listed; i++ ) for ( int i = 0; (i < size()) && !listed; i++ )
{ {
listed = (data()[i]).HasSameCallsignWithWidlcard(callsign); listed = (data()[i]).HasSameCallsignWithWidlcard(callsign);
} }
return listed; return listed;
} }
////////////////////////////////////////////////////////////////////////////////////////
// helpers
char *CCallsignList::TrimWhiteSpaces(char *str)
{
char *end;
// Trim leading space
while(*str == ' ') str++;
// All spaces?
if(*str == 0)
return str;
// Trim trailing space
end = str + ::strlen(str) - 1;
while((end > str) && (*end == ' ')) end--;
// Write new null terminator
*(end+1) = 0;
return str;
}
bool CCallsignList::GetLastModTime(time_t *time)
{
bool ok = false;
if ( m_Filename != NULL )
{
struct stat fileStat;
if( ::stat(m_Filename, &fileStat) != -1 )
{
*time = fileStat.st_mtime;
ok = true;
}
}
return ok;
}

View File

@ -37,7 +37,7 @@ class CCallsignList : public std::vector<CCallsign>
public: public:
// constructor // constructor
CCallsignList(); CCallsignList();
// destructor // destructor
virtual ~CCallsignList(); virtual ~CCallsignList();
@ -49,14 +49,15 @@ public:
bool LoadFromFile(const char *); bool LoadFromFile(const char *);
bool ReloadFromFile(void); bool ReloadFromFile(void);
bool NeedReload(void); bool NeedReload(void);
// compare // compare
bool IsListed(const CCallsign &) const; bool IsListed(const CCallsign &) const;
protected: protected:
// //
bool GetLastModTime(time_t *); bool GetLastModTime(time_t *);
char *TrimWhiteSpaces(char *);
protected: protected:
// data // data
std::mutex m_Mutex; std::mutex m_Mutex;

View File

@ -19,7 +19,7 @@
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>. // along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#include "main.h" #include "main.h"
@ -87,28 +87,28 @@ CReflector::~CReflector()
bool CReflector::Start(void) bool CReflector::Start(void)
{ {
bool ok = true; bool ok = true;
// reset stop flag // reset stop flag
m_bStopThreads = false; m_bStopThreads = false;
// init gate keeper // init gate keeper
ok &= g_GateKeeper.Init(); ok &= g_GateKeeper.Init();
// create protocols // create protocols
ok &= m_Protocols.Init(); ok &= m_Protocols.Init();
// start one thread per reflector module // start one thread per reflector module
for ( int i = 0; i < NB_OF_MODULES; i++ ) for ( int i = 0; i < NB_OF_MODULES; i++ )
{ {
m_RouterThreads[i] = new std::thread(CReflector::RouterThread, this, &(m_Streams[i])); m_RouterThreads[i] = new std::thread(CReflector::RouterThread, this, &(m_Streams[i]));
} }
// start the reporting threads // start the reporting threads
m_XmlReportThread = new std::thread(CReflector::XmlReportThread, this); m_XmlReportThread = new std::thread(CReflector::XmlReportThread, this);
#ifdef JSON_MONITOR #ifdef JSON_MONITOR
m_JsonReportThread = new std::thread(CReflector::JsonReportThread, this); m_JsonReportThread = new std::thread(CReflector::JsonReportThread, this);
#endif #endif
// done // done
return ok; return ok;
} }
@ -117,7 +117,7 @@ void CReflector::Stop(void)
{ {
// stop & delete all threads // stop & delete all threads
m_bStopThreads = true; m_bStopThreads = true;
// stop & delete report threads // stop & delete report threads
if ( m_XmlReportThread != NULL ) if ( m_XmlReportThread != NULL )
{ {
@ -131,7 +131,7 @@ void CReflector::Stop(void)
delete m_JsonReportThread; delete m_JsonReportThread;
m_JsonReportThread = NULL; m_JsonReportThread = NULL;
} }
// stop & delete all router thread // stop & delete all router thread
for ( int i = 0; i < NB_OF_MODULES; i++ ) for ( int i = 0; i < NB_OF_MODULES; i++ )
{ {
@ -142,10 +142,10 @@ void CReflector::Stop(void)
m_RouterThreads[i] = NULL; m_RouterThreads[i] = NULL;
} }
} }
// close protocols // close protocols
m_Protocols.Close(); m_Protocols.Close();
// close gatekeeper // close gatekeeper
g_GateKeeper.Close(); g_GateKeeper.Close();
} }
@ -161,10 +161,10 @@ bool CReflector::IsStreaming(char module)
CPacketStream *CReflector::OpenStream(CDvHeaderPacket *DvHeader, CClient *client) CPacketStream *CReflector::OpenStream(CDvHeaderPacket *DvHeader, CClient *client)
{ {
CPacketStream *retStream = NULL; CPacketStream *retStream = NULL;
// clients MUST have bee locked by the caller // clients MUST have bee locked by the caller
// so we can freely access it within the fuction // so we can freely access it within the fuction
// check if client is valid candidate // check if client is valid candidate
if ( m_Clients.IsClient(client) && !client->IsAMaster() ) if ( m_Clients.IsClient(client) && !client->IsAMaster() )
{ {
@ -181,14 +181,14 @@ CPacketStream *CReflector::OpenStream(CDvHeaderPacket *DvHeader, CClient *client
// stream open, mark client as master // stream open, mark client as master
// so that it can't be deleted // so that it can't be deleted
client->SetMasterOfModule(module); client->SetMasterOfModule(module);
// update last heard time // update last heard time
client->Heard(); client->Heard();
retStream = stream; retStream = stream;
// and push header packet // and push header packet
stream->Push(DvHeader); stream->Push(DvHeader);
// report // report
std::cout << "Opening stream on module " << module << " for client " << client->GetCallsign() std::cout << "Opening stream on module " << module << " for client " << client->GetCallsign()
<< " with sid " << DvHeader->GetStreamId() << std::endl; << " with sid " << DvHeader->GetStreamId() << std::endl;
@ -225,33 +225,33 @@ void CReflector::CloseStream(CPacketStream *stream)
CTimePoint::TaskSleepFor(10); CTimePoint::TaskSleepFor(10);
} }
} while (!bEmpty); } while (!bEmpty);
// lock it // lock it
stream->Lock(); stream->Lock();
// lock clients // lock clients
GetClients(); GetClients();
// get and check the master // get and check the master
CClient *client = stream->GetOwnerClient(); CClient *client = stream->GetOwnerClient();
if ( client != NULL ) if ( client != NULL )
{ {
// client no longer a master // client no longer a master
client->NotAMaster(); client->NotAMaster();
// notify // notify
g_Reflector.OnStreamClose(stream->GetUserCallsign()); g_Reflector.OnStreamClose(stream->GetUserCallsign());
std::cout << "Closing stream of module " << GetStreamModule(stream) << std::endl; std::cout << "Closing stream of module " << GetStreamModule(stream) << std::endl;
} }
// stop the queue // stop the queue
stream->Close(); stream->Close();
// release clients // release clients
ReleaseClients(); ReleaseClients();
// and unlock // and unlock
stream->Unlock(); stream->Unlock();
} }
@ -264,10 +264,10 @@ void CReflector::RouterThread(CReflector *This, CPacketStream *streamIn)
{ {
// get our module // get our module
uint8 uiModuleId = This->GetStreamModule(streamIn); uint8 uiModuleId = This->GetStreamModule(streamIn);
// get on input queue // get on input queue
CPacket *packet; CPacket *packet;
while ( !This->m_bStopThreads ) while ( !This->m_bStopThreads )
{ {
// any packet in our input queue ? // any packet in our input queue ?
@ -283,31 +283,31 @@ void CReflector::RouterThread(CReflector *This, CPacketStream *streamIn)
packet = NULL; packet = NULL;
} }
streamIn->Unlock(); streamIn->Unlock();
// route it // route it
if ( packet != NULL ) if ( packet != NULL )
{ {
// set origin // set origin
packet->SetModuleId(uiModuleId); packet->SetModuleId(uiModuleId);
// iterate on all protocols // iterate on all protocols
for ( int i = 0; i < This->m_Protocols.Size(); i++ ) for ( int i = 0; i < This->m_Protocols.Size(); i++ )
{ {
// duplicate packet // duplicate packet
CPacket *packetClone = packet->Duplicate(); CPacket *packetClone = packet->Duplicate();
// get protocol // get protocol
CProtocol *protocol = This->m_Protocols.GetProtocol(i); CProtocol *protocol = This->m_Protocols.GetProtocol(i);
// if packet is header, update RPT2 according to protocol // if packet is header, update RPT2 according to protocol
if ( packetClone->IsDvHeader() ) if ( packetClone->IsDvHeader() )
{ {
// get our callsign // get our callsign
CCallsign csRPT = protocol->GetReflectorCallsign(); CCallsign csRPT = protocol->GetReflectorCallsign();
csRPT.SetModule(This->GetStreamModule(streamIn)); csRPT.SetModule(This->GetStreamModule(streamIn));
((CDvHeaderPacket *)packetClone)->SetRpt2Callsign(csRPT); ((CDvHeaderPacket *)packetClone)->SetRpt2Callsign(csRPT);
} }
// and push it // and push it
CPacketQueue *queue = protocol->GetQueue(); CPacketQueue *queue = protocol->GetQueue();
queue->push(packetClone); queue->push(packetClone);
@ -317,7 +317,7 @@ void CReflector::RouterThread(CReflector *This, CPacketStream *streamIn)
delete packet; delete packet;
packet = NULL; packet = NULL;
} }
// wait a bit // wait a bit
CTimePoint::TaskSleepFor(10); CTimePoint::TaskSleepFor(10);
} }
@ -341,7 +341,11 @@ void CReflector::XmlReportThread(CReflector *This)
// and close file // and close file
xmlFile.close(); xmlFile.close();
} }
else
{
std::cout << "Failed to open " << XML_PATH << std::endl;
}
// and wait a bit // and wait a bit
CTimePoint::TaskSleepFor(XML_UPDATE_PERIOD * 1000); CTimePoint::TaskSleepFor(XML_UPDATE_PERIOD * 1000);
} }
@ -353,10 +357,10 @@ void CReflector::JsonReportThread(CReflector *This)
CBuffer Buffer; CBuffer Buffer;
CIp Ip; CIp Ip;
bool bOn; bool bOn;
// init variable // init variable
bOn = false; bOn = false;
// create listening socket // create listening socket
if ( Socket.Open(JSON_PORT) ) if ( Socket.Open(JSON_PORT) )
{ {
@ -370,26 +374,26 @@ void CReflector::JsonReportThread(CReflector *This)
if ( Buffer.Compare((uint8 *)"hello", 5) == 0 ) if ( Buffer.Compare((uint8 *)"hello", 5) == 0 )
{ {
std::cout << "Monitor socket connected with " << Ip << std::endl; std::cout << "Monitor socket connected with " << Ip << std::endl;
// connected // connected
bOn = true; bOn = true;
// announce ourselves // announce ourselves
This->SendJsonReflectorObject(Socket, Ip); This->SendJsonReflectorObject(Socket, Ip);
// dump tables // dump tables
This->SendJsonNodesObject(Socket, Ip); This->SendJsonNodesObject(Socket, Ip);
This->SendJsonStationsObject(Socket, Ip); This->SendJsonStationsObject(Socket, Ip);
} }
else if ( Buffer.Compare((uint8 *)"bye", 3) == 0 ) else if ( Buffer.Compare((uint8 *)"bye", 3) == 0 )
{ {
std::cout << "Monitor socket disconnected" << std::endl; std::cout << "Monitor socket disconnected" << std::endl;
// diconnected // diconnected
bOn = false; bOn = false;
} }
} }
// any notifications ? // any notifications ?
CNotification notification; CNotification notification;
This->m_Notifications.Lock(); This->m_Notifications.Lock();
@ -444,7 +448,7 @@ void CReflector::JsonReportThread(CReflector *This)
void CReflector::OnClientsChanged(void) void CReflector::OnClientsChanged(void)
{ {
CNotification notification(NOTIFICATION_CLIENTS); CNotification notification(NOTIFICATION_CLIENTS);
m_Notifications.Lock(); m_Notifications.Lock();
m_Notifications.push(notification); m_Notifications.push(notification);
m_Notifications.Unlock(); m_Notifications.Unlock();
@ -453,7 +457,7 @@ void CReflector::OnClientsChanged(void)
void CReflector::OnUsersChanged(void) void CReflector::OnUsersChanged(void)
{ {
CNotification notification(NOTIFICATION_USERS); CNotification notification(NOTIFICATION_USERS);
m_Notifications.Lock(); m_Notifications.Lock();
m_Notifications.push(notification); m_Notifications.push(notification);
m_Notifications.Unlock(); m_Notifications.Unlock();
@ -462,7 +466,7 @@ void CReflector::OnUsersChanged(void)
void CReflector::OnStreamOpen(const CCallsign &callsign) void CReflector::OnStreamOpen(const CCallsign &callsign)
{ {
CNotification notification(NOTIFICATION_STREAM_OPEN, callsign); CNotification notification(NOTIFICATION_STREAM_OPEN, callsign);
m_Notifications.Lock(); m_Notifications.Lock();
m_Notifications.push(notification); m_Notifications.push(notification);
m_Notifications.Unlock(); m_Notifications.Unlock();
@ -471,7 +475,7 @@ void CReflector::OnStreamOpen(const CCallsign &callsign)
void CReflector::OnStreamClose(const CCallsign &callsign) void CReflector::OnStreamClose(const CCallsign &callsign)
{ {
CNotification notification(NOTIFICATION_STREAM_CLOSE, callsign); CNotification notification(NOTIFICATION_STREAM_CLOSE, callsign);
m_Notifications.Lock(); m_Notifications.Lock();
m_Notifications.push(notification); m_Notifications.push(notification);
m_Notifications.Unlock(); m_Notifications.Unlock();
@ -521,12 +525,12 @@ void CReflector::WriteXmlFile(std::ofstream &xmlFile)
{ {
// write header // write header
xmlFile << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl; xmlFile << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
// software version // software version
char sz[64]; char sz[64];
::sprintf(sz, "%d.%d.%d", VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION); ::sprintf(sz, "%d.%d.%d", VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION);
xmlFile << "<Version>" << sz << "</Version>" << std::endl; xmlFile << "<Version>" << sz << "</Version>" << std::endl;
// linked nodes // linked nodes
xmlFile << "<" << m_Callsign << "linked nodes>" << std::endl; xmlFile << "<" << m_Callsign << "linked nodes>" << std::endl;
// lock // lock
@ -539,7 +543,7 @@ void CReflector::WriteXmlFile(std::ofstream &xmlFile)
// unlock // unlock
ReleaseClients(); ReleaseClients();
xmlFile << "</" << m_Callsign << "linked nodes>" << std::endl; xmlFile << "</" << m_Callsign << "linked nodes>" << std::endl;
// last heard users // last heard users
xmlFile << "<" << m_Callsign << "heard users>" << std::endl; xmlFile << "<" << m_Callsign << "heard users>" << std::endl;
// lock // lock
@ -562,7 +566,7 @@ void CReflector::SendJsonReflectorObject(CUdpSocket &Socket, CIp &Ip)
char Buffer[1024]; char Buffer[1024];
char cs[CALLSIGN_LEN+1]; char cs[CALLSIGN_LEN+1];
char mod[8] = "\"A\""; char mod[8] = "\"A\"";
// get reflector callsign // get reflector callsign
m_Callsign.GetCallsign((uint8 *)cs); m_Callsign.GetCallsign((uint8 *)cs);
cs[CALLSIGN_LEN] = 0; cs[CALLSIGN_LEN] = 0;
@ -579,7 +583,7 @@ void CReflector::SendJsonReflectorObject(CUdpSocket &Socket, CIp &Ip)
} }
} }
::strcat(Buffer, "]}"); ::strcat(Buffer, "]}");
// and send // and send
Socket.Send(Buffer, Ip); Socket.Send(Buffer, Ip);
} }
@ -591,7 +595,7 @@ void CReflector::SendJsonNodesObject(CUdpSocket &Socket, CIp &Ip)
char Buffer[12+(JSON_NBMAX_NODES*94)]; char Buffer[12+(JSON_NBMAX_NODES*94)];
// nodes object table // nodes object table
::sprintf(Buffer, "{\"nodes\":["); ::sprintf(Buffer, "{\"nodes\":[");
// lock // lock
CClients *clients = GetClients(); CClients *clients = GetClients();
// iterate on clients // iterate on clients
@ -604,21 +608,21 @@ void CReflector::SendJsonNodesObject(CUdpSocket &Socket, CIp &Ip)
} }
} }
// unlock // unlock
ReleaseClients(); ReleaseClients();
::strcat(Buffer, "]}"); ::strcat(Buffer, "]}");
// and send // and send
//std::cout << Buffer << std::endl; //std::cout << Buffer << std::endl;
Socket.Send(Buffer, Ip); Socket.Send(Buffer, Ip);
} }
void CReflector::SendJsonStationsObject(CUdpSocket &Socket, CIp &Ip) void CReflector::SendJsonStationsObject(CUdpSocket &Socket, CIp &Ip)
{ {
char Buffer[15+(LASTHEARD_USERS_MAX_SIZE*94)]; char Buffer[15+(LASTHEARD_USERS_MAX_SIZE*94)];
// stations object table // stations object table
::sprintf(Buffer, "{\"stations\":["); ::sprintf(Buffer, "{\"stations\":[");
// lock // lock
CUsers *users = GetUsers(); CUsers *users = GetUsers();
// iterate on users // iterate on users
@ -629,12 +633,12 @@ void CReflector::SendJsonStationsObject(CUdpSocket &Socket, CIp &Ip)
{ {
::strcat(Buffer, ","); ::strcat(Buffer, ",");
} }
} }
// unlock // unlock
ReleaseUsers(); ReleaseUsers();
::strcat(Buffer, "]}"); ::strcat(Buffer, "]}");
// and send // and send
//std::cout << Buffer << std::endl; //std::cout << Buffer << std::endl;
Socket.Send(Buffer, Ip); Socket.Send(Buffer, Ip);
@ -644,11 +648,11 @@ void CReflector::SendJsonOnairObject(CUdpSocket &Socket, CIp &Ip, const CCallsig
{ {
char Buffer[128]; char Buffer[128];
char sz[CALLSIGN_LEN+1]; char sz[CALLSIGN_LEN+1];
// onair object // onair object
Callsign.GetCallsignString(sz); Callsign.GetCallsignString(sz);
::sprintf(Buffer, "{\"onair\":\"%s\"}", sz); ::sprintf(Buffer, "{\"onair\":\"%s\"}", sz);
// and send // and send
//std::cout << Buffer << std::endl; //std::cout << Buffer << std::endl;
Socket.Send(Buffer, Ip); Socket.Send(Buffer, Ip);
@ -658,11 +662,11 @@ void CReflector::SendJsonOffairObject(CUdpSocket &Socket, CIp &Ip, const CCallsi
{ {
char Buffer[128]; char Buffer[128];
char sz[CALLSIGN_LEN+1]; char sz[CALLSIGN_LEN+1];
// offair object // offair object
Callsign.GetCallsignString(sz); Callsign.GetCallsignString(sz);
::sprintf(Buffer, "{\"offair\":\"%s\"}", sz); ::sprintf(Buffer, "{\"offair\":\"%s\"}", sz);
// and send // and send
//std::cout << Buffer << std::endl; //std::cout << Buffer << std::endl;
Socket.Send(Buffer, Ip); Socket.Send(Buffer, Ip);

View File

@ -19,7 +19,7 @@
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>. // along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#ifndef main_h #ifndef main_h
@ -48,7 +48,7 @@
#define VERSION_MAJOR 1 #define VERSION_MAJOR 1
#define VERSION_MINOR 1 #define VERSION_MINOR 1
#define VERSION_REVISION 0 #define VERSION_REVISION 1
// global ------------------------------------------------------ // global ------------------------------------------------------