mirror of
https://github.com/ShaYmez/xlxd.git
synced 2024-09-27 23:36:36 -04:00
xlxd 2.2.1
* auto-reload of deride DB * interlink protocol v2.0
This commit is contained in:
parent
ed24a5b8cb
commit
32a437c138
@ -25,7 +25,8 @@
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include "cdmriddir.h"
|
#include "cdmriddirfile.h"
|
||||||
|
#include "cdmriddirhttp.h"
|
||||||
#include "ccallsign.h"
|
#include "ccallsign.h"
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -60,16 +61,24 @@ CCallsign::CCallsign(const char *sz, uint32 dmrid)
|
|||||||
// dmrid ok ?
|
// dmrid ok ?
|
||||||
if ( m_uiDmrid == 0 )
|
if ( m_uiDmrid == 0 )
|
||||||
{
|
{
|
||||||
m_uiDmrid = g_DmridDir.FindDmrid(*this);
|
g_DmridDir.Lock();
|
||||||
|
{
|
||||||
|
m_uiDmrid = g_DmridDir.FindDmrid(*this);
|
||||||
|
}
|
||||||
|
g_DmridDir.Unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( m_uiDmrid != 0 )
|
else if ( m_uiDmrid != 0 )
|
||||||
{
|
{
|
||||||
const CCallsign *callsign = g_DmridDir.FindCallsign(m_uiDmrid);
|
g_DmridDir.Lock();
|
||||||
if ( callsign != NULL )
|
{
|
||||||
{
|
const CCallsign *callsign = g_DmridDir.FindCallsign(m_uiDmrid);
|
||||||
::memcpy(m_Callsign, callsign->m_Callsign, sizeof(m_Callsign));
|
if ( callsign != NULL )
|
||||||
}
|
{
|
||||||
|
::memcpy(m_Callsign, callsign->m_Callsign, sizeof(m_Callsign));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_DmridDir.Unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +160,11 @@ void CCallsign::SetCallsign(const char *sz, bool UpdateDmrid)
|
|||||||
// and update dmrid
|
// and update dmrid
|
||||||
if ( UpdateDmrid )
|
if ( UpdateDmrid )
|
||||||
{
|
{
|
||||||
m_uiDmrid = g_DmridDir.FindDmrid(*this);
|
g_DmridDir.Lock();
|
||||||
|
{
|
||||||
|
m_uiDmrid = g_DmridDir.FindDmrid(*this);
|
||||||
|
}
|
||||||
|
g_DmridDir.Unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,7 +187,11 @@ void CCallsign::SetCallsign(const uint8 *buffer, int len, bool UpdateDmrid)
|
|||||||
}
|
}
|
||||||
if ( UpdateDmrid )
|
if ( UpdateDmrid )
|
||||||
{
|
{
|
||||||
m_uiDmrid = g_DmridDir.FindDmrid(*this);
|
g_DmridDir.Lock();
|
||||||
|
{
|
||||||
|
m_uiDmrid = g_DmridDir.FindDmrid(*this);
|
||||||
|
}
|
||||||
|
g_DmridDir.Unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,11 +200,15 @@ void CCallsign::SetDmrid(uint32 dmrid, bool UpdateCallsign)
|
|||||||
m_uiDmrid = dmrid;
|
m_uiDmrid = dmrid;
|
||||||
if ( UpdateCallsign )
|
if ( UpdateCallsign )
|
||||||
{
|
{
|
||||||
const CCallsign *callsign = g_DmridDir.FindCallsign(dmrid);
|
g_DmridDir.Lock();
|
||||||
if ( callsign != NULL )
|
{
|
||||||
{
|
const CCallsign *callsign = g_DmridDir.FindCallsign(dmrid);
|
||||||
::memcpy(m_Callsign, callsign->m_Callsign, sizeof(m_Callsign));
|
if ( callsign != NULL )
|
||||||
}
|
{
|
||||||
|
::memcpy(m_Callsign, callsign->m_Callsign, sizeof(m_Callsign));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_DmridDir.Unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
CCallsignList::CCallsignList()
|
CCallsignList::CCallsignList()
|
||||||
{
|
{
|
||||||
m_Filename = NULL;
|
m_Filename = NULL;
|
||||||
::memset(&m_LastModTime, 0, sizeof(CCallsignList));
|
::memset(&m_LastModTime, 0, sizeof(time_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -26,9 +26,95 @@
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "creflector.h"
|
#include "creflector.h"
|
||||||
#include "cdmriddir.h"
|
#include "cdmriddir.h"
|
||||||
|
#include "cdmriddirfile.h"
|
||||||
|
#include "cdmriddirhttp.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor & destructor
|
||||||
|
|
||||||
|
CDmridDir::CDmridDir()
|
||||||
|
{
|
||||||
|
m_bStopThread = false;
|
||||||
|
m_pThread = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
CDmridDir::~CDmridDir()
|
||||||
|
{
|
||||||
|
// kill threads
|
||||||
|
m_bStopThread = true;
|
||||||
|
if ( m_pThread != NULL )
|
||||||
|
{
|
||||||
|
m_pThread->join();
|
||||||
|
delete m_pThread;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CDmridDir g_DmridDir;
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// init & close
|
||||||
|
|
||||||
|
bool CDmridDir::Init(void)
|
||||||
|
{
|
||||||
|
// load content
|
||||||
|
Reload();
|
||||||
|
|
||||||
|
// reset stop flag
|
||||||
|
m_bStopThread = false;
|
||||||
|
|
||||||
|
// start thread;
|
||||||
|
m_pThread = new std::thread(CDmridDir::Thread, this);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDmridDir::Close(void)
|
||||||
|
{
|
||||||
|
m_bStopThread = true;
|
||||||
|
if ( m_pThread != NULL )
|
||||||
|
{
|
||||||
|
m_pThread->join();
|
||||||
|
delete m_pThread;
|
||||||
|
m_pThread = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// thread
|
||||||
|
|
||||||
|
void CDmridDir::Thread(CDmridDir *This)
|
||||||
|
{
|
||||||
|
while ( !This->m_bStopThread )
|
||||||
|
{
|
||||||
|
// Wait 30 seconds
|
||||||
|
CTimePoint::TaskSleepFor(DMRIDDB_REFRESH_RATE * 60000);
|
||||||
|
|
||||||
|
// have lists files changed ?
|
||||||
|
if ( This->NeedReload() )
|
||||||
|
{
|
||||||
|
This->Reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Reload
|
||||||
|
|
||||||
|
bool CDmridDir::Reload(void)
|
||||||
|
{
|
||||||
|
CBuffer buffer;
|
||||||
|
bool ok = false;
|
||||||
|
|
||||||
|
if ( LoadContent(&buffer) )
|
||||||
|
{
|
||||||
|
Lock();
|
||||||
|
{
|
||||||
|
ok = RefreshContent(buffer);
|
||||||
|
}
|
||||||
|
Unlock();
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// find
|
// find
|
||||||
@ -53,218 +139,6 @@ uint32 CDmridDir::FindDmrid(const CCallsign &callsign)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// refresh
|
|
||||||
|
|
||||||
#if (DMRIDDB_USE_RLX_SERVER == 1)
|
|
||||||
bool CDmridDir::RefreshContent(void)
|
|
||||||
{
|
|
||||||
bool ok = true;
|
|
||||||
CBuffer buffer;
|
|
||||||
|
|
||||||
// get file from xlxapi server
|
|
||||||
if ( (ok = HttpGet("xlxapi.rlx.lu", "api/exportdmr.php", 80, &buffer)) )
|
|
||||||
{
|
|
||||||
// clear directory
|
|
||||||
m_CallsignMap.clear();
|
|
||||||
m_DmridMap.clear();
|
|
||||||
|
|
||||||
// scan file
|
|
||||||
if ( buffer.size() > 0 )
|
|
||||||
{
|
|
||||||
char *ptr1 = (char *)buffer.data();
|
|
||||||
char *ptr2;
|
|
||||||
// get next line
|
|
||||||
while ( (ptr2 = ::strchr(ptr1, '\n')) != NULL )
|
|
||||||
{
|
|
||||||
*ptr2 = 0;
|
|
||||||
// get items
|
|
||||||
char *dmrid;
|
|
||||||
char *callsign;
|
|
||||||
if ( ((dmrid = ::strtok(ptr1, ";")) != NULL) && IsValidDmrid(dmrid) )
|
|
||||||
{
|
|
||||||
if ( ((callsign = ::strtok(NULL, ";")) != NULL) )
|
|
||||||
{
|
|
||||||
// new entry
|
|
||||||
uint32 ui = atoi(dmrid);
|
|
||||||
CCallsign cs(callsign, ui);
|
|
||||||
if ( cs.IsValid() )
|
|
||||||
{
|
|
||||||
m_CallsignMap.insert(std::pair<uint32,CCallsign>(ui, cs));
|
|
||||||
m_DmridMap.insert(std::pair<CCallsign,uint32>(cs,ui));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// next line
|
|
||||||
ptr1 = ptr2+1;
|
|
||||||
}
|
|
||||||
// done
|
|
||||||
ok = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// report
|
|
||||||
std::cout << "Read " << m_DmridMap.size() << " DMR id from online database " << std::endl;
|
|
||||||
|
|
||||||
// done
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
bool CDmridDir::RefreshContent(void)
|
|
||||||
{
|
|
||||||
bool ok = true;
|
|
||||||
CBuffer buffer;
|
|
||||||
std::ifstream file;
|
|
||||||
std::streampos size;
|
|
||||||
|
|
||||||
// open file
|
|
||||||
file.open(DMRIDDB_PATH, std::ios::in | std::ios::binary | std::ios::ate);
|
|
||||||
if ( file.is_open() )
|
|
||||||
{
|
|
||||||
// clear directory
|
|
||||||
m_CallsignMap.clear();
|
|
||||||
m_DmridMap.clear();
|
|
||||||
|
|
||||||
// scan file
|
|
||||||
size = file.tellg();
|
|
||||||
if ( size > 0 )
|
|
||||||
{
|
|
||||||
// read file into buffer
|
|
||||||
buffer.resize((int)size+1);
|
|
||||||
file.seekg (0, std::ios::beg);
|
|
||||||
file.read((char *)buffer.data(), (int)size);
|
|
||||||
|
|
||||||
// close file
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
// crack it
|
|
||||||
char *ptr1 = (char *)buffer.data();
|
|
||||||
char *ptr2;
|
|
||||||
// get next line
|
|
||||||
while ( (ptr2 = ::strchr(ptr1, '\n')) != NULL )
|
|
||||||
{
|
|
||||||
*ptr2 = 0;
|
|
||||||
// get items
|
|
||||||
char *dmrid;
|
|
||||||
char *callsign;
|
|
||||||
if ( ((dmrid = ::strtok(ptr1, ";")) != NULL) && IsValidDmrid(dmrid) )
|
|
||||||
{
|
|
||||||
if ( ((callsign = ::strtok(NULL, ";")) != NULL) )
|
|
||||||
{
|
|
||||||
// new entry
|
|
||||||
uint32 ui = atoi(dmrid);
|
|
||||||
CCallsign cs(callsign, ui);
|
|
||||||
if ( cs.IsValid() )
|
|
||||||
{
|
|
||||||
m_CallsignMap.insert(std::pair<uint32,CCallsign>(ui, cs));
|
|
||||||
m_DmridMap.insert(std::pair<CCallsign,uint32>(cs,ui));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// next line
|
|
||||||
ptr1 = ptr2+1;
|
|
||||||
}
|
|
||||||
// done
|
|
||||||
ok = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// report
|
|
||||||
std::cout << "Read " << m_DmridMap.size() << " DMR id from online database " << std::endl;
|
|
||||||
|
|
||||||
// done
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// httpd helpers
|
|
||||||
|
|
||||||
#define DMRID_HTTPGET_SIZEMAX (256)
|
|
||||||
#define DMRID_TEXTFILE_SIZEMAX (10*1024*1024)
|
|
||||||
|
|
||||||
bool CDmridDir::HttpGet(const char *hostname, const char *filename, int port, CBuffer *buffer)
|
|
||||||
{
|
|
||||||
bool ok = false;
|
|
||||||
int sock_id;
|
|
||||||
|
|
||||||
// open socket
|
|
||||||
if ( (sock_id = ::socket(AF_INET, SOCK_STREAM, 0)) >= 0 )
|
|
||||||
{
|
|
||||||
// get hostname address
|
|
||||||
struct sockaddr_in servaddr;
|
|
||||||
struct hostent *hp;
|
|
||||||
::memset(&servaddr,0,sizeof(servaddr));
|
|
||||||
if( (hp = gethostbyname(hostname)) != NULL )
|
|
||||||
{
|
|
||||||
// dns resolved
|
|
||||||
::memcpy((char *)&servaddr.sin_addr.s_addr, (char *)hp->h_addr, hp->h_length);
|
|
||||||
servaddr.sin_port = htons(port);
|
|
||||||
servaddr.sin_family = AF_INET;
|
|
||||||
|
|
||||||
// connect
|
|
||||||
if ( ::connect(sock_id, (struct sockaddr *)&servaddr, sizeof(servaddr)) == 0)
|
|
||||||
{
|
|
||||||
// send the GET request
|
|
||||||
char request[DMRID_HTTPGET_SIZEMAX];
|
|
||||||
::sprintf(request, "GET /%s HTTP/1.0\r\nFrom: %s\r\nUser-Agent: xlxd\r\n\r\n",
|
|
||||||
filename, (const char *)g_Reflector.GetCallsign());
|
|
||||||
::write(sock_id, request, strlen(request));
|
|
||||||
|
|
||||||
// config receive timeouts
|
|
||||||
fd_set read_set;
|
|
||||||
struct timeval timeout;
|
|
||||||
timeout.tv_sec = 5;
|
|
||||||
timeout.tv_usec = 0;
|
|
||||||
FD_ZERO(&read_set);
|
|
||||||
FD_SET(sock_id, &read_set);
|
|
||||||
|
|
||||||
// get the reply back
|
|
||||||
buffer->clear();
|
|
||||||
bool done = false;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
char buf[1440];
|
|
||||||
ssize_t len = 0;
|
|
||||||
select(sock_id+1, &read_set, NULL, NULL, &timeout);
|
|
||||||
//if ( (ret > 0) || ((ret < 0) && (errno == EINPROGRESS)) )
|
|
||||||
//if ( ret >= 0 )
|
|
||||||
//{
|
|
||||||
usleep(5000);
|
|
||||||
len = read(sock_id, buf, 1440);
|
|
||||||
if ( len > 0 )
|
|
||||||
{
|
|
||||||
buffer->Append((uint8 *)buf, (int)len);
|
|
||||||
ok = true;
|
|
||||||
}
|
|
||||||
//}
|
|
||||||
done = (len <= 0);
|
|
||||||
|
|
||||||
} while (!done);
|
|
||||||
buffer->Append((uint8)0);
|
|
||||||
|
|
||||||
// and disconnect
|
|
||||||
close(sock_id);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "Cannot establish connection with host " << hostname << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "Host " << hostname << " not found" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "Failed to open wget socket" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// done
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// syntax helpers
|
// syntax helpers
|
||||||
|
@ -32,7 +32,6 @@
|
|||||||
#include "cbuffer.h"
|
#include "cbuffer.h"
|
||||||
#include "ccallsign.h"
|
#include "ccallsign.h"
|
||||||
|
|
||||||
|
|
||||||
// compare function for std::map::find
|
// compare function for std::map::find
|
||||||
|
|
||||||
struct CallsignCompare
|
struct CallsignCompare
|
||||||
@ -48,31 +47,49 @@ class CDmridDir
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// constructor
|
// constructor
|
||||||
CDmridDir() {}
|
CDmridDir();
|
||||||
|
|
||||||
// destructor
|
// destructor
|
||||||
~CDmridDir() {}
|
~CDmridDir();
|
||||||
|
|
||||||
|
// init & close
|
||||||
|
virtual bool Init(void);
|
||||||
|
virtual void Close(void);
|
||||||
|
|
||||||
|
// locks
|
||||||
|
void Lock(void) { m_Mutex.lock(); }
|
||||||
|
void Unlock(void) { m_Mutex.unlock(); }
|
||||||
|
|
||||||
// refresh
|
// refresh
|
||||||
bool RefreshContent(void);
|
virtual bool LoadContent(CBuffer *) { return false; }
|
||||||
|
virtual bool RefreshContent(const CBuffer &) { return false; }
|
||||||
|
|
||||||
// find
|
// find
|
||||||
const CCallsign *FindCallsign(uint32);
|
const CCallsign *FindCallsign(uint32);
|
||||||
uint32 FindDmrid(const CCallsign &);
|
uint32 FindDmrid(const CCallsign &);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// httpd helpers
|
// thread
|
||||||
bool HttpGet(const char *, const char *, int, CBuffer *);
|
static void Thread(CDmridDir *);
|
||||||
|
|
||||||
// syntax helpers
|
// reload helpers
|
||||||
|
bool Reload(void);
|
||||||
|
virtual bool NeedReload(void) { return false; }
|
||||||
bool IsValidDmrid(const char *);
|
bool IsValidDmrid(const char *);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// directory
|
// data
|
||||||
std::map <uint32, CCallsign> m_CallsignMap;
|
std::map <uint32, CCallsign> m_CallsignMap;
|
||||||
std::map <CCallsign, uint32, CallsignCompare> m_DmridMap;
|
std::map <CCallsign, uint32, CallsignCompare> m_DmridMap;
|
||||||
|
|
||||||
|
// Lock()
|
||||||
|
std::mutex m_Mutex;
|
||||||
|
|
||||||
|
// thread
|
||||||
|
bool m_bStopThread;
|
||||||
|
std::thread *m_pThread;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#endif /* cdmriddir_h */
|
#endif /* cdmriddir_h */
|
||||||
|
165
src/cdmriddirfile.cpp
Normal file
165
src/cdmriddirfile.cpp
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
//
|
||||||
|
// cdmriddirfile.cpp
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 29/12/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd 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 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include "main.h"
|
||||||
|
#include "cdmriddirfile.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if (DMRIDDB_USE_RLX_SERVER == 0)
|
||||||
|
CDmridDirFile g_DmridDir;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor & destructor
|
||||||
|
|
||||||
|
CDmridDirFile::CDmridDirFile()
|
||||||
|
{
|
||||||
|
::memset(&m_LastModTime, 0, sizeof(time_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// init & close
|
||||||
|
|
||||||
|
bool CDmridDirFile::Init(void)
|
||||||
|
{
|
||||||
|
return CDmridDir::Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// refresh
|
||||||
|
|
||||||
|
bool CDmridDirFile::NeedReload(void)
|
||||||
|
{
|
||||||
|
bool needReload = false;
|
||||||
|
|
||||||
|
time_t time;
|
||||||
|
if ( GetLastModTime(&time) )
|
||||||
|
{
|
||||||
|
needReload = time != m_LastModTime;
|
||||||
|
}
|
||||||
|
return needReload;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CDmridDirFile::LoadContent(CBuffer *buffer)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
std::ifstream file;
|
||||||
|
std::streampos size;
|
||||||
|
|
||||||
|
// open file
|
||||||
|
file.open(DMRIDDB_PATH, std::ios::in | std::ios::binary | std::ios::ate);
|
||||||
|
if ( file.is_open() )
|
||||||
|
{
|
||||||
|
// read file
|
||||||
|
size = file.tellg();
|
||||||
|
if ( size > 0 )
|
||||||
|
{
|
||||||
|
// read file into buffer
|
||||||
|
buffer->resize((int)size+1);
|
||||||
|
file.seekg (0, std::ios::beg);
|
||||||
|
file.read((char *)buffer->data(), (int)size);
|
||||||
|
|
||||||
|
// close file
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
// update time
|
||||||
|
GetLastModTime(&m_LastModTime);
|
||||||
|
|
||||||
|
// done
|
||||||
|
ok = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CDmridDirFile::RefreshContent(const CBuffer &buffer)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
|
||||||
|
// clear directory
|
||||||
|
m_CallsignMap.clear();
|
||||||
|
m_DmridMap.clear();
|
||||||
|
|
||||||
|
// scan buffer
|
||||||
|
if ( buffer.size() > 0 )
|
||||||
|
{
|
||||||
|
// crack it
|
||||||
|
char *ptr1 = (char *)buffer.data();
|
||||||
|
char *ptr2;
|
||||||
|
|
||||||
|
// get next line
|
||||||
|
while ( (ptr2 = ::strchr(ptr1, '\n')) != NULL )
|
||||||
|
{
|
||||||
|
*ptr2 = 0;
|
||||||
|
// get items
|
||||||
|
char *dmrid;
|
||||||
|
char *callsign;
|
||||||
|
if ( ((dmrid = ::strtok(ptr1, ";")) != NULL) && IsValidDmrid(dmrid) )
|
||||||
|
{
|
||||||
|
if ( ((callsign = ::strtok(NULL, ";")) != NULL) )
|
||||||
|
{
|
||||||
|
// new entry
|
||||||
|
uint32 ui = atoi(dmrid);
|
||||||
|
CCallsign cs(callsign, ui);
|
||||||
|
if ( cs.IsValid() )
|
||||||
|
{
|
||||||
|
m_CallsignMap.insert(std::pair<uint32,CCallsign>(ui, cs));
|
||||||
|
m_DmridMap.insert(std::pair<CCallsign,uint32>(cs,ui));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// next line
|
||||||
|
ptr1 = ptr2+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
ok = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// report
|
||||||
|
std::cout << "Read " << m_DmridMap.size() << " DMR id from file " << DMRIDDB_PATH << std::endl;
|
||||||
|
|
||||||
|
// done
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CDmridDirFile::GetLastModTime(time_t *time)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
|
||||||
|
struct stat fileStat;
|
||||||
|
if( ::stat(DMRIDDB_PATH, &fileStat) != -1 )
|
||||||
|
{
|
||||||
|
*time = fileStat.st_mtime;
|
||||||
|
ok = true;
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
59
src/cdmriddirfile.h
Normal file
59
src/cdmriddirfile.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
// cdmrididirfile.h
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 29/12/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd 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 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef cdmrididirfile_h
|
||||||
|
#define cdmrididirfile_h
|
||||||
|
|
||||||
|
#include "cdmriddir.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class CDmridDirFile : public CDmridDir
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
CDmridDirFile();
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
~CDmridDirFile() {}
|
||||||
|
|
||||||
|
// init & close
|
||||||
|
bool Init(void);
|
||||||
|
|
||||||
|
// refresh
|
||||||
|
bool LoadContent(CBuffer *);
|
||||||
|
bool RefreshContent(const CBuffer &);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// reload helpers
|
||||||
|
bool NeedReload(void);
|
||||||
|
bool GetLastModTime(time_t *);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// data
|
||||||
|
time_t m_LastModTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* cdmrididirfile_h */
|
182
src/cdmriddirhttp.cpp
Normal file
182
src/cdmriddirhttp.cpp
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
//
|
||||||
|
// cdmriddirhttp.cpp
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 29/12/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd 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 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "main.h"
|
||||||
|
#include "creflector.h"
|
||||||
|
#include "cdmriddirhttp.h"
|
||||||
|
|
||||||
|
#if (DMRIDDB_USE_RLX_SERVER == 1)
|
||||||
|
CDmridDirHttp g_DmridDir;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// refresh
|
||||||
|
|
||||||
|
bool CDmridDirHttp::LoadContent(CBuffer *buffer)
|
||||||
|
{
|
||||||
|
// get file from xlxapi server
|
||||||
|
return HttpGet("xlxapi.rlx.lu", "api/exportdmr.php", 80, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CDmridDirHttp::RefreshContent(const CBuffer &buffer)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
|
||||||
|
// clear directory
|
||||||
|
m_CallsignMap.clear();
|
||||||
|
m_DmridMap.clear();
|
||||||
|
|
||||||
|
// scan file
|
||||||
|
if ( buffer.size() > 0 )
|
||||||
|
{
|
||||||
|
char *ptr1 = (char *)buffer.data();
|
||||||
|
char *ptr2;
|
||||||
|
// get next line
|
||||||
|
while ( (ptr2 = ::strchr(ptr1, '\n')) != NULL )
|
||||||
|
{
|
||||||
|
*ptr2 = 0;
|
||||||
|
// get items
|
||||||
|
char *dmrid;
|
||||||
|
char *callsign;
|
||||||
|
if ( ((dmrid = ::strtok(ptr1, ";")) != NULL) && IsValidDmrid(dmrid) )
|
||||||
|
{
|
||||||
|
if ( ((callsign = ::strtok(NULL, ";")) != NULL) )
|
||||||
|
{
|
||||||
|
// new entry
|
||||||
|
uint32 ui = atoi(dmrid);
|
||||||
|
CCallsign cs(callsign, ui);
|
||||||
|
if ( cs.IsValid() )
|
||||||
|
{
|
||||||
|
m_CallsignMap.insert(std::pair<uint32,CCallsign>(ui, cs));
|
||||||
|
m_DmridMap.insert(std::pair<CCallsign,uint32>(cs,ui));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// next line
|
||||||
|
ptr1 = ptr2+1;
|
||||||
|
}
|
||||||
|
// done
|
||||||
|
ok = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// report
|
||||||
|
std::cout << "Read " << m_DmridMap.size() << " DMR id from xlxapi.rlx.lu database " << std::endl;
|
||||||
|
|
||||||
|
// done
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// httpd helpers
|
||||||
|
|
||||||
|
#define DMRID_HTTPGET_SIZEMAX (256)
|
||||||
|
#define DMRID_TEXTFILE_SIZEMAX (10*1024*1024)
|
||||||
|
|
||||||
|
bool CDmridDirHttp::HttpGet(const char *hostname, const char *filename, int port, CBuffer *buffer)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
int sock_id;
|
||||||
|
|
||||||
|
// open socket
|
||||||
|
if ( (sock_id = ::socket(AF_INET, SOCK_STREAM, 0)) >= 0 )
|
||||||
|
{
|
||||||
|
// get hostname address
|
||||||
|
struct sockaddr_in servaddr;
|
||||||
|
struct hostent *hp;
|
||||||
|
::memset(&servaddr,0,sizeof(servaddr));
|
||||||
|
if( (hp = gethostbyname(hostname)) != NULL )
|
||||||
|
{
|
||||||
|
// dns resolved
|
||||||
|
::memcpy((char *)&servaddr.sin_addr.s_addr, (char *)hp->h_addr, hp->h_length);
|
||||||
|
servaddr.sin_port = htons(port);
|
||||||
|
servaddr.sin_family = AF_INET;
|
||||||
|
|
||||||
|
// connect
|
||||||
|
if ( ::connect(sock_id, (struct sockaddr *)&servaddr, sizeof(servaddr)) == 0)
|
||||||
|
{
|
||||||
|
// send the GET request
|
||||||
|
char request[DMRID_HTTPGET_SIZEMAX];
|
||||||
|
::sprintf(request, "GET /%s HTTP/1.0\r\nFrom: %s\r\nUser-Agent: xlxd\r\n\r\n",
|
||||||
|
filename, (const char *)g_Reflector.GetCallsign());
|
||||||
|
::write(sock_id, request, strlen(request));
|
||||||
|
|
||||||
|
// config receive timeouts
|
||||||
|
fd_set read_set;
|
||||||
|
struct timeval timeout;
|
||||||
|
timeout.tv_sec = 5;
|
||||||
|
timeout.tv_usec = 0;
|
||||||
|
FD_ZERO(&read_set);
|
||||||
|
FD_SET(sock_id, &read_set);
|
||||||
|
|
||||||
|
// get the reply back
|
||||||
|
buffer->clear();
|
||||||
|
bool done = false;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
char buf[1440];
|
||||||
|
ssize_t len = 0;
|
||||||
|
select(sock_id+1, &read_set, NULL, NULL, &timeout);
|
||||||
|
//if ( (ret > 0) || ((ret < 0) && (errno == EINPROGRESS)) )
|
||||||
|
//if ( ret >= 0 )
|
||||||
|
//{
|
||||||
|
usleep(5000);
|
||||||
|
len = read(sock_id, buf, 1440);
|
||||||
|
if ( len > 0 )
|
||||||
|
{
|
||||||
|
buffer->Append((uint8 *)buf, (int)len);
|
||||||
|
ok = true;
|
||||||
|
}
|
||||||
|
//}
|
||||||
|
done = (len <= 0);
|
||||||
|
|
||||||
|
} while (!done);
|
||||||
|
buffer->Append((uint8)0);
|
||||||
|
|
||||||
|
// and disconnect
|
||||||
|
close(sock_id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Cannot establish connection with host " << hostname << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Host " << hostname << " not found" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Failed to open wget socket" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return ok;
|
||||||
|
}
|
52
src/cdmriddirhttp.h
Normal file
52
src/cdmriddirhttp.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
//
|
||||||
|
// cdmriddirhttp.h
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 29/12/2017.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd 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 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef cdmriddirhttp_h
|
||||||
|
#define cdmriddirhttp_h
|
||||||
|
|
||||||
|
#include "cdmriddir.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class CDmridDirHttp : public CDmridDir
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
CDmridDirHttp() {}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
~CDmridDirHttp() {}
|
||||||
|
|
||||||
|
// refresh
|
||||||
|
bool LoadContent(CBuffer *);
|
||||||
|
bool RefreshContent(const CBuffer &);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// reload helpers
|
||||||
|
bool NeedReload(void) { return true; }
|
||||||
|
bool HttpGet(const char *, const char *, int, CBuffer *);
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* cdmriddirhttp_h */
|
@ -61,6 +61,20 @@ CDvFramePacket::CDvFramePacket(const uint8 *ambe, const uint8 *sync, uint16 sid,
|
|||||||
::memset(m_uiDvData, 0, sizeof(m_uiDvData));
|
::memset(m_uiDvData, 0, sizeof(m_uiDvData));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dstar + dmr constructor
|
||||||
|
|
||||||
|
CDvFramePacket::CDvFramePacket
|
||||||
|
(uint16 sid,
|
||||||
|
uint8 dstarpid, const uint8 *dstarambe, const uint8 *dstardvdata,
|
||||||
|
uint8 dmrpid, uint8 dprspid, const uint8 *dmrambe, const uint8 *dmrsync)
|
||||||
|
: CPacket(sid, dstarpid, dmrpid, dprspid)
|
||||||
|
{
|
||||||
|
::memcpy(m_uiAmbe, dstarambe, sizeof(m_uiAmbe));
|
||||||
|
::memcpy(m_uiDvData, dstardvdata, sizeof(m_uiDvData));
|
||||||
|
::memcpy(m_uiAmbePlus, dmrambe, sizeof(m_uiAmbePlus));
|
||||||
|
::memcpy(m_uiDvSync, dmrsync, sizeof(m_uiDvSync));
|
||||||
|
}
|
||||||
|
|
||||||
// copy constructor
|
// copy constructor
|
||||||
|
|
||||||
CDvFramePacket::CDvFramePacket(const CDvFramePacket &DvFrame)
|
CDvFramePacket::CDvFramePacket(const CDvFramePacket &DvFrame)
|
||||||
|
@ -55,6 +55,7 @@ public:
|
|||||||
CDvFramePacket();
|
CDvFramePacket();
|
||||||
CDvFramePacket(const struct dstar_dvframe *, uint16, uint8);
|
CDvFramePacket(const struct dstar_dvframe *, uint16, uint8);
|
||||||
CDvFramePacket(const uint8 *, const uint8 *, uint16, uint8, uint8);
|
CDvFramePacket(const uint8 *, const uint8 *, uint16, uint8, uint8);
|
||||||
|
CDvFramePacket(uint16, uint8, const uint8 *, const uint8 *, uint8, uint8, const uint8 *, const uint8 *);
|
||||||
CDvFramePacket(const CDvFramePacket &);
|
CDvFramePacket(const CDvFramePacket &);
|
||||||
|
|
||||||
// destructor
|
// destructor
|
||||||
|
@ -47,6 +47,16 @@ CDvLastFramePacket::CDvLastFramePacket(const uint8 *ambe, const uint8 *sync, uin
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dstar + dmr constructor
|
||||||
|
|
||||||
|
CDvLastFramePacket::CDvLastFramePacket
|
||||||
|
(uint16 sid,
|
||||||
|
uint8 dstarpid, const uint8 *dstarambe, const uint8 *dstardvdata,
|
||||||
|
uint8 dmrpid, uint8 dprspid, const uint8 *dmrambe, const uint8 *dmrsync)
|
||||||
|
: CDvFramePacket(sid, dstarpid, dstarambe, dstardvdata, dmrpid, dprspid, dmrambe, dmrsync)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// copy constructor
|
// copy constructor
|
||||||
|
|
||||||
CDvLastFramePacket::CDvLastFramePacket(const CDvLastFramePacket &DvFrame)
|
CDvLastFramePacket::CDvLastFramePacket(const CDvLastFramePacket &DvFrame)
|
||||||
|
@ -42,6 +42,7 @@ public:
|
|||||||
CDvLastFramePacket();
|
CDvLastFramePacket();
|
||||||
CDvLastFramePacket(const struct dstar_dvframe *, uint16, uint8);
|
CDvLastFramePacket(const struct dstar_dvframe *, uint16, uint8);
|
||||||
CDvLastFramePacket(const uint8 *, const uint8 *, uint16, uint8, uint8);
|
CDvLastFramePacket(const uint8 *, const uint8 *, uint16, uint8, uint8);
|
||||||
|
CDvLastFramePacket(uint16, uint8, const uint8 *, const uint8 *, uint8, uint8, const uint8 *, const uint8 *);
|
||||||
CDvLastFramePacket(const CDvLastFramePacket &);
|
CDvLastFramePacket(const CDvLastFramePacket &);
|
||||||
|
|
||||||
// destructor
|
// destructor
|
||||||
|
@ -59,6 +59,16 @@ CPacket::CPacket(uint16 sid, uint8 dmrpid, uint8 dmrspid)
|
|||||||
m_uiOriginId = ORIGIN_LOCAL;
|
m_uiOriginId = ORIGIN_LOCAL;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CPacket::CPacket(uint16 sid, uint8 dstarpid, uint8 dmrpid, uint8 dmrsubpid)
|
||||||
|
{
|
||||||
|
m_uiStreamId = sid;
|
||||||
|
m_uiDstarPacketId = dstarpid;
|
||||||
|
m_uiDmrPacketId = dmrpid;
|
||||||
|
m_uiDmrPacketSubid = dmrsubpid;
|
||||||
|
m_uiModuleId = ' ';
|
||||||
|
m_uiOriginId = ORIGIN_LOCAL;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// virtual duplication
|
// virtual duplication
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ public:
|
|||||||
CPacket();
|
CPacket();
|
||||||
CPacket(uint16 sid, uint8 dstarpid);
|
CPacket(uint16 sid, uint8 dstarpid);
|
||||||
CPacket(uint16 sid, uint8 dmrpid, uint8 dmrsubpid);
|
CPacket(uint16 sid, uint8 dmrpid, uint8 dmrsubpid);
|
||||||
|
CPacket(uint16 sid, uint8 dstarpid, uint8 dmrpid, uint8 dmrsubpid);
|
||||||
|
|
||||||
// destructor
|
// destructor
|
||||||
virtual ~CPacket() {};
|
virtual ~CPacket() {};
|
||||||
|
@ -40,12 +40,13 @@ CPeer::CPeer()
|
|||||||
m_LastHeardTime = std::time(NULL);
|
m_LastHeardTime = std::time(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
CPeer::CPeer(const CCallsign &callsign, const CIp &ip, char *modules)
|
CPeer::CPeer(const CCallsign &callsign, const CIp &ip, char *modules, const CVersion &version)
|
||||||
{
|
{
|
||||||
m_Callsign = callsign;
|
m_Callsign = callsign;
|
||||||
m_Ip = ip;
|
m_Ip = ip;
|
||||||
::memset(m_ReflectorModules, 0, sizeof(m_ReflectorModules));
|
::memset(m_ReflectorModules, 0, sizeof(m_ReflectorModules));
|
||||||
::strncpy(m_ReflectorModules, modules, sizeof(m_ReflectorModules)-1);
|
::strncpy(m_ReflectorModules, modules, sizeof(m_ReflectorModules)-1);
|
||||||
|
m_Version = version;
|
||||||
m_LastKeepaliveTime.Now();
|
m_LastKeepaliveTime.Now();
|
||||||
m_ConnectTime = std::time(NULL);
|
m_ConnectTime = std::time(NULL);
|
||||||
m_LastHeardTime = std::time(NULL);
|
m_LastHeardTime = std::time(NULL);
|
||||||
@ -56,6 +57,7 @@ CPeer::CPeer(const CPeer &peer)
|
|||||||
m_Callsign = peer.m_Callsign;
|
m_Callsign = peer.m_Callsign;
|
||||||
m_Ip = peer.m_Ip;
|
m_Ip = peer.m_Ip;
|
||||||
::memcpy(m_ReflectorModules, peer.m_ReflectorModules, sizeof(m_ReflectorModules));
|
::memcpy(m_ReflectorModules, peer.m_ReflectorModules, sizeof(m_ReflectorModules));
|
||||||
|
m_Version = peer.m_Version;
|
||||||
m_LastKeepaliveTime = peer.m_LastKeepaliveTime;
|
m_LastKeepaliveTime = peer.m_LastKeepaliveTime;
|
||||||
m_ConnectTime = peer.m_ConnectTime;
|
m_ConnectTime = peer.m_ConnectTime;
|
||||||
m_LastHeardTime = peer.m_LastHeardTime;
|
m_LastHeardTime = peer.m_LastHeardTime;
|
||||||
@ -82,6 +84,7 @@ bool CPeer::operator ==(const CPeer &peer) const
|
|||||||
|
|
||||||
same &= (peer.m_Callsign == m_Callsign);
|
same &= (peer.m_Callsign == m_Callsign);
|
||||||
same &= (peer.m_Ip == m_Ip);
|
same &= (peer.m_Ip == m_Ip);
|
||||||
|
same &= (peer.m_Version == m_Version);
|
||||||
for ( int i = 0; (i < m_Clients.size()) && same ; i++ )
|
for ( int i = 0; (i < m_Clients.size()) && same ; i++ )
|
||||||
{
|
{
|
||||||
same &= (peer.m_Clients[i] == m_Clients[i]);
|
same &= (peer.m_Clients[i] == m_Clients[i]);
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#ifndef cpeer_h
|
#ifndef cpeer_h
|
||||||
#define cpeer_h
|
#define cpeer_h
|
||||||
|
|
||||||
|
#include "cversion.h"
|
||||||
#include "ctimepoint.h"
|
#include "ctimepoint.h"
|
||||||
#include "cip.h"
|
#include "cip.h"
|
||||||
#include "ccallsign.h"
|
#include "ccallsign.h"
|
||||||
@ -41,7 +42,7 @@ class CPeer
|
|||||||
public:
|
public:
|
||||||
// constructors
|
// constructors
|
||||||
CPeer();
|
CPeer();
|
||||||
CPeer(const CCallsign &, const CIp &, char *);
|
CPeer(const CCallsign &, const CIp &, char *, const CVersion &);
|
||||||
CPeer(const CPeer &);
|
CPeer(const CPeer &);
|
||||||
|
|
||||||
// destructor
|
// destructor
|
||||||
@ -82,6 +83,7 @@ protected:
|
|||||||
CCallsign m_Callsign;
|
CCallsign m_Callsign;
|
||||||
CIp m_Ip;
|
CIp m_Ip;
|
||||||
char m_ReflectorModules[NB_MODULES_MAX+1];
|
char m_ReflectorModules[NB_MODULES_MAX+1];
|
||||||
|
CVersion m_Version;
|
||||||
std::vector<CClient *> m_Clients;
|
std::vector<CClient *> m_Clients;
|
||||||
|
|
||||||
// status
|
// status
|
||||||
|
@ -26,7 +26,8 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "creflector.h"
|
#include "creflector.h"
|
||||||
#include "cgatekeeper.h"
|
#include "cgatekeeper.h"
|
||||||
#include "cdmriddir.h"
|
#include "cdmriddirfile.h"
|
||||||
|
#include "cdmriddirhttp.h"
|
||||||
#include "ctranscoder.h"
|
#include "ctranscoder.h"
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -102,7 +103,7 @@ bool CReflector::Start(void)
|
|||||||
ok &= g_GateKeeper.Init();
|
ok &= g_GateKeeper.Init();
|
||||||
|
|
||||||
// init dmrid directory
|
// init dmrid directory
|
||||||
g_DmridDir.RefreshContent();
|
g_DmridDir.Init();
|
||||||
|
|
||||||
// init the transcoder
|
// init the transcoder
|
||||||
g_Transcoder.Init();
|
g_Transcoder.Init();
|
||||||
|
@ -188,12 +188,6 @@ void CTranscoder::Task(void)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle end of streaming timeout
|
|
||||||
//CheckStreamsTimeout();
|
|
||||||
|
|
||||||
// handle queue from reflector
|
|
||||||
//HandleQueue();
|
|
||||||
|
|
||||||
// keep client alive
|
// keep client alive
|
||||||
if ( m_LastKeepaliveTime.DurationSinceNow() > TRANSCODER_KEEPALIVE_PERIOD )
|
if ( m_LastKeepaliveTime.DurationSinceNow() > TRANSCODER_KEEPALIVE_PERIOD )
|
||||||
{
|
{
|
||||||
|
@ -55,6 +55,9 @@ public:
|
|||||||
void Lock(void) { m_Mutex.lock(); }
|
void Lock(void) { m_Mutex.lock(); }
|
||||||
void Unlock(void) { m_Mutex.unlock(); }
|
void Unlock(void) { m_Mutex.unlock(); }
|
||||||
|
|
||||||
|
// status
|
||||||
|
bool IsConnected(void) const { return m_bConnected; }
|
||||||
|
|
||||||
// manage streams
|
// manage streams
|
||||||
CCodecStream *GetStream(CPacketStream *, uint8);
|
CCodecStream *GetStream(CPacketStream *, uint8);
|
||||||
void ReleaseStream(CCodecStream *);
|
void ReleaseStream(CCodecStream *);
|
||||||
|
87
src/cversion.cpp
Normal file
87
src/cversion.cpp
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
//
|
||||||
|
// cversion.cpp
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 05/01/2018.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd 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 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "cversion.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// constructor
|
||||||
|
|
||||||
|
CVersion::CVersion()
|
||||||
|
{
|
||||||
|
m_iMajor = 0;
|
||||||
|
m_iMinor = 0;
|
||||||
|
m_iRevision = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CVersion::CVersion(int iMajor, int iMinor, int iRevision)
|
||||||
|
{
|
||||||
|
m_iMajor = iMajor;
|
||||||
|
m_iMinor = iMinor;
|
||||||
|
m_iRevision = iRevision;
|
||||||
|
}
|
||||||
|
|
||||||
|
CVersion::CVersion(const CVersion &Version)
|
||||||
|
{
|
||||||
|
m_iMajor = Version.m_iMajor;
|
||||||
|
m_iMinor = Version.m_iMinor;
|
||||||
|
m_iRevision = Version.m_iRevision;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// comparaison
|
||||||
|
|
||||||
|
bool CVersion::IsEqualOrHigherTo(const CVersion &version) const
|
||||||
|
{
|
||||||
|
if ( m_iMajor > version.m_iMajor )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if ( m_iMajor == version.m_iMajor )
|
||||||
|
{
|
||||||
|
if ( m_iMinor > version.m_iMinor )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if ( m_iMinor == version.m_iMinor )
|
||||||
|
{
|
||||||
|
if ( m_iRevision >= version.m_iRevision )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// operator
|
||||||
|
|
||||||
|
bool CVersion::operator ==(const CVersion &Version) const
|
||||||
|
{
|
||||||
|
return ( (Version.m_iMajor == m_iMajor) &&
|
||||||
|
(Version.m_iMinor == m_iMinor) &&
|
||||||
|
(Version.m_iRevision == m_iRevision )) ;
|
||||||
|
}
|
||||||
|
|
64
src/cversion.h
Normal file
64
src/cversion.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
//
|
||||||
|
// cversion.h
|
||||||
|
// xlxd
|
||||||
|
//
|
||||||
|
// Created by Jean-Luc Deltombe (LX3JL) on 05/01/2018.
|
||||||
|
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||||
|
//
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// This file is part of xlxd.
|
||||||
|
//
|
||||||
|
// xlxd 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 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// xlxd 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef cversion_h
|
||||||
|
#define cversion_h
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class
|
||||||
|
|
||||||
|
class CVersion
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
CVersion();
|
||||||
|
CVersion(int, int, int);
|
||||||
|
CVersion(const CVersion &);
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
virtual ~CVersion() {}
|
||||||
|
|
||||||
|
// get
|
||||||
|
int GetMajor(void) const { return m_iMajor; }
|
||||||
|
int GetMinor(void) const { return m_iMinor; }
|
||||||
|
int GetRevision(void) const { return m_iRevision; }
|
||||||
|
|
||||||
|
// comparaison
|
||||||
|
bool IsEqualOrHigherTo(const CVersion &) const;
|
||||||
|
|
||||||
|
// operator
|
||||||
|
bool operator ==(const CVersion &) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// data
|
||||||
|
int m_iMajor;
|
||||||
|
int m_iMinor;
|
||||||
|
int m_iRevision;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif /* cversion_h */
|
@ -32,16 +32,40 @@
|
|||||||
|
|
||||||
CXlxClient::CXlxClient()
|
CXlxClient::CXlxClient()
|
||||||
{
|
{
|
||||||
|
m_ProtRev = XLX_PROTOCOL_REVISION_0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CXlxClient::CXlxClient(const CCallsign &callsign, const CIp &ip, char reflectorModule)
|
CXlxClient::CXlxClient(const CCallsign &callsign, const CIp &ip, char reflectorModule, int protRev)
|
||||||
: CClient(callsign, ip, reflectorModule)
|
: CClient(callsign, ip, reflectorModule)
|
||||||
{
|
{
|
||||||
|
m_ProtRev = protRev;
|
||||||
}
|
}
|
||||||
|
|
||||||
CXlxClient::CXlxClient(const CXlxClient &client)
|
CXlxClient::CXlxClient(const CXlxClient &client)
|
||||||
: CClient(client)
|
: CClient(client)
|
||||||
{
|
{
|
||||||
|
m_ProtRev = client.m_ProtRev;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// identity
|
||||||
|
|
||||||
|
int CXlxClient::GetCodec(void) const
|
||||||
|
{
|
||||||
|
int codec;
|
||||||
|
|
||||||
|
switch ( GetProtocolRevision() )
|
||||||
|
{
|
||||||
|
case XLX_PROTOCOL_REVISION_0:
|
||||||
|
case XLX_PROTOCOL_REVISION_1:
|
||||||
|
default:
|
||||||
|
codec = CODEC_AMBEPLUS;
|
||||||
|
break;
|
||||||
|
case XLX_PROTOCOL_REVISION_2:
|
||||||
|
codec = CODEC_NONE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return codec;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -31,6 +31,10 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// define
|
// define
|
||||||
|
|
||||||
|
#define XLX_PROTOCOL_REVISION_0 0 // AMBE only, original connect mechanism
|
||||||
|
#define XLX_PROTOCOL_REVISION_1 1 // AMBE only, revised connect mechanism
|
||||||
|
#define XLX_PROTOCOL_REVISION_2 2 // Transcoded AMBE+AMBE2 interlink
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// class
|
// class
|
||||||
@ -40,7 +44,7 @@ class CXlxClient : public CClient
|
|||||||
public:
|
public:
|
||||||
// constructors
|
// constructors
|
||||||
CXlxClient();
|
CXlxClient();
|
||||||
CXlxClient(const CCallsign &, const CIp &, char = ' ');
|
CXlxClient(const CCallsign &, const CIp &, char = ' ', int = XLX_PROTOCOL_REVISION_0);
|
||||||
CXlxClient(const CXlxClient &);
|
CXlxClient(const CXlxClient &);
|
||||||
|
|
||||||
// destructor
|
// destructor
|
||||||
@ -48,7 +52,9 @@ public:
|
|||||||
|
|
||||||
// identity
|
// identity
|
||||||
int GetProtocol(void) const { return PROTOCOL_XLX; }
|
int GetProtocol(void) const { return PROTOCOL_XLX; }
|
||||||
|
int GetProtocolRevision(void) const { return m_ProtRev; }
|
||||||
const char *GetProtocolName(void) const { return "XLX"; }
|
const char *GetProtocolName(void) const { return "XLX"; }
|
||||||
|
int GetCodec(void) const;
|
||||||
bool IsPeer(void) const { return true; }
|
bool IsPeer(void) const { return true; }
|
||||||
|
|
||||||
// status
|
// status
|
||||||
@ -56,6 +62,10 @@ public:
|
|||||||
|
|
||||||
// reporting
|
// reporting
|
||||||
void WriteXml(std::ofstream &) {}
|
void WriteXml(std::ofstream &) {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// data
|
||||||
|
int m_ProtRev;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -37,14 +37,18 @@ CXlxPeer::CXlxPeer()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CXlxPeer::CXlxPeer(const CCallsign &callsign, const CIp &ip, char *modules)
|
CXlxPeer::CXlxPeer(const CCallsign &callsign, const CIp &ip, char *modules, const CVersion &version)
|
||||||
: CPeer(callsign, ip, modules)
|
: CPeer(callsign, ip, modules, version)
|
||||||
{
|
{
|
||||||
|
// get protocol revision
|
||||||
|
int protrev = GetProtocolRevision(version);
|
||||||
|
//std::cout << "Adding XLX peer with protocol revision " << protrev << std::endl;
|
||||||
|
|
||||||
// and construct all xlx clients
|
// and construct all xlx clients
|
||||||
for ( int i = 0; i < ::strlen(modules); i++ )
|
for ( int i = 0; i < ::strlen(modules); i++ )
|
||||||
{
|
{
|
||||||
// create
|
// create
|
||||||
CXlxClient *client = new CXlxClient(callsign, ip, modules[i]);
|
CXlxClient *client = new CXlxClient(callsign, ip, modules[i], protrev);
|
||||||
// and append to vector
|
// and append to vector
|
||||||
m_Clients.push_back(client);
|
m_Clients.push_back(client);
|
||||||
}
|
}
|
||||||
@ -82,3 +86,21 @@ bool CXlxPeer::IsAlive(void) const
|
|||||||
return (m_LastKeepaliveTime.DurationSinceNow() < XLX_KEEPALIVE_TIMEOUT);
|
return (m_LastKeepaliveTime.DurationSinceNow() < XLX_KEEPALIVE_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// revision helper
|
||||||
|
|
||||||
|
int CXlxPeer::GetProtocolRevision(const CVersion &version)
|
||||||
|
{
|
||||||
|
int protrev = XLX_PROTOCOL_REVISION_0;
|
||||||
|
|
||||||
|
if ( version.IsEqualOrHigherTo(CVersion(2,2,0)) )
|
||||||
|
{
|
||||||
|
protrev = XLX_PROTOCOL_REVISION_2;
|
||||||
|
}
|
||||||
|
else if ( version.IsEqualOrHigherTo(CVersion(1,4,0)) )
|
||||||
|
{
|
||||||
|
protrev = XLX_PROTOCOL_REVISION_1;
|
||||||
|
}
|
||||||
|
return protrev;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -26,9 +26,11 @@
|
|||||||
#define cxlxpeer_h
|
#define cxlxpeer_h
|
||||||
|
|
||||||
#include "cpeer.h"
|
#include "cpeer.h"
|
||||||
|
#include "cxlxclient.h"
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
// define
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// class
|
// class
|
||||||
@ -38,7 +40,7 @@ class CXlxPeer : public CPeer
|
|||||||
public:
|
public:
|
||||||
// constructors
|
// constructors
|
||||||
CXlxPeer();
|
CXlxPeer();
|
||||||
CXlxPeer(const CCallsign &, const CIp &, char *);
|
CXlxPeer(const CCallsign &, const CIp &, char *, const CVersion &);
|
||||||
CXlxPeer(const CXlxPeer &);
|
CXlxPeer(const CXlxPeer &);
|
||||||
|
|
||||||
// destructor
|
// destructor
|
||||||
@ -46,9 +48,13 @@ public:
|
|||||||
|
|
||||||
// status
|
// status
|
||||||
bool IsAlive(void) const;
|
bool IsAlive(void) const;
|
||||||
|
|
||||||
// identity
|
// identity
|
||||||
int GetProtocol(void) const { return PROTOCOL_XLX; }
|
int GetProtocol(void) const { return PROTOCOL_XLX; }
|
||||||
const char *GetProtocolName(void) const { return "XLX"; }
|
const char *GetProtocolName(void) const { return "XLX"; }
|
||||||
|
|
||||||
|
// revision helper
|
||||||
|
static int GetProtocolRevision(const CVersion &);
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -67,10 +67,10 @@ void CXlxProtocol::Task(void)
|
|||||||
CIp Ip;
|
CIp Ip;
|
||||||
CCallsign Callsign;
|
CCallsign Callsign;
|
||||||
char Modules[NB_MODULES_MAX+1];
|
char Modules[NB_MODULES_MAX+1];
|
||||||
|
CVersion Version;
|
||||||
CDvHeaderPacket *Header;
|
CDvHeaderPacket *Header;
|
||||||
CDvFramePacket *Frame;
|
CDvFramePacket *Frame;
|
||||||
CDvLastFramePacket *LastFrame;
|
CDvLastFramePacket *LastFrame;
|
||||||
uint8 Major, Minor, Revision;
|
|
||||||
|
|
||||||
// any incoming packet ?
|
// any incoming packet ?
|
||||||
if ( m_Socket.Receive(&Buffer, &Ip, 20) != -1 )
|
if ( m_Socket.Receive(&Buffer, &Ip, 20) != -1 )
|
||||||
@ -106,34 +106,41 @@ void CXlxProtocol::Task(void)
|
|||||||
// handle it
|
// handle it
|
||||||
OnDvLastFramePacketIn(LastFrame, &Ip);
|
OnDvLastFramePacketIn(LastFrame, &Ip);
|
||||||
}
|
}
|
||||||
else if ( IsValidConnectPacket(Buffer, &Callsign, Modules, &Major, &Minor, &Revision) )
|
else if ( IsValidConnectPacket(Buffer, &Callsign, Modules, &Version) )
|
||||||
{
|
{
|
||||||
std::cout << "XLX (" << (int)Major << "." << (int)Minor << "." << (int)Revision
|
std::cout << "XLX ("
|
||||||
|
<< Version.GetMajor() << "." << Version.GetMinor() << "." << Version.GetRevision()
|
||||||
<< ") connect packet for modules " << Modules
|
<< ") connect packet for modules " << Modules
|
||||||
<< " from " << Callsign << " at " << Ip << std::endl;
|
<< " from " << Callsign << " at " << Ip << std::endl;
|
||||||
|
|
||||||
// callsign authorized?
|
// callsign authorized?
|
||||||
if ( g_GateKeeper.MayLink(Callsign, Ip, PROTOCOL_XLX, Modules) )
|
if ( g_GateKeeper.MayLink(Callsign, Ip, PROTOCOL_XLX, Modules) )
|
||||||
{
|
{
|
||||||
|
// acknowledge connecting request
|
||||||
// following is version dependent
|
// following is version dependent
|
||||||
// for backward compatibility, only send ACK once
|
switch ( CXlxPeer::GetProtocolRevision(Version) )
|
||||||
if ( (Major == 1) && (Minor < 4) )
|
|
||||||
{
|
{
|
||||||
// already connected ?
|
case XLX_PROTOCOL_REVISION_0:
|
||||||
CPeers *peers = g_Reflector.GetPeers();
|
{
|
||||||
if ( peers->FindPeer(Callsign, Ip, PROTOCOL_XLX) == NULL )
|
// already connected ?
|
||||||
{
|
CPeers *peers = g_Reflector.GetPeers();
|
||||||
|
if ( peers->FindPeer(Callsign, Ip, PROTOCOL_XLX) == NULL )
|
||||||
|
{
|
||||||
|
// acknowledge the request
|
||||||
|
EncodeConnectAckPacket(&Buffer, Modules);
|
||||||
|
m_Socket.Send(Buffer, Ip);
|
||||||
|
}
|
||||||
|
g_Reflector.ReleasePeers();
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case XLX_PROTOCOL_REVISION_1:
|
||||||
|
case XLX_PROTOCOL_REVISION_2:
|
||||||
|
default:
|
||||||
// acknowledge the request
|
// acknowledge the request
|
||||||
EncodeConnectAckPacket(&Buffer, Modules);
|
EncodeConnectAckPacket(&Buffer, Modules);
|
||||||
m_Socket.Send(Buffer, Ip);
|
m_Socket.Send(Buffer, Ip);
|
||||||
}
|
break;
|
||||||
g_Reflector.ReleasePeers();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// acknowledge the request
|
|
||||||
EncodeConnectAckPacket(&Buffer, Modules);
|
|
||||||
m_Socket.Send(Buffer, Ip);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -143,7 +150,7 @@ void CXlxProtocol::Task(void)
|
|||||||
m_Socket.Send(Buffer, Ip);
|
m_Socket.Send(Buffer, Ip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( IsValidAckPacket(Buffer, &Callsign, Modules) )
|
else if ( IsValidAckPacket(Buffer, &Callsign, Modules, &Version) )
|
||||||
{
|
{
|
||||||
std::cout << "XLX ack packet for modules " << Modules << " from " << Callsign << " at " << Ip << std::endl;
|
std::cout << "XLX ack packet for modules " << Modules << " from " << Callsign << " at " << Ip << std::endl;
|
||||||
|
|
||||||
@ -156,8 +163,8 @@ void CXlxProtocol::Task(void)
|
|||||||
{
|
{
|
||||||
// create the new peer
|
// create the new peer
|
||||||
// this also create one client per module
|
// this also create one client per module
|
||||||
CXlxPeer *peer = new CXlxPeer(Callsign, Ip, Modules);
|
CXlxPeer *peer = new CXlxPeer(Callsign, Ip, Modules, Version);
|
||||||
|
|
||||||
// append the peer to reflector peer list
|
// append the peer to reflector peer list
|
||||||
// this also add all new clients to reflector client list
|
// this also add all new clients to reflector client list
|
||||||
peers->AddPeer(peer);
|
peers->AddPeer(peer);
|
||||||
@ -253,6 +260,13 @@ void CXlxProtocol::HandleQueue(void)
|
|||||||
CBuffer buffer;
|
CBuffer buffer;
|
||||||
if ( EncodeDvPacket(*packet, &buffer) )
|
if ( EncodeDvPacket(*packet, &buffer) )
|
||||||
{
|
{
|
||||||
|
// encode revision dependent version
|
||||||
|
CBuffer bufferLegacy = buffer;
|
||||||
|
if ( packet->IsDvFrame() && (bufferLegacy.size() == 45) )
|
||||||
|
{
|
||||||
|
bufferLegacy.resize(27);
|
||||||
|
}
|
||||||
|
|
||||||
// and push it to all our clients linked to the module and who are not streaming in
|
// and push it to all our clients linked to the module and who are not streaming in
|
||||||
CClients *clients = g_Reflector.GetClients();
|
CClients *clients = g_Reflector.GetClients();
|
||||||
int index = -1;
|
int index = -1;
|
||||||
@ -263,7 +277,25 @@ void CXlxProtocol::HandleQueue(void)
|
|||||||
if ( !client->IsAMaster() && (client->GetReflectorModule() == packet->GetModuleId()) )
|
if ( !client->IsAMaster() && (client->GetReflectorModule() == packet->GetModuleId()) )
|
||||||
{
|
{
|
||||||
// no, send the packet
|
// no, send the packet
|
||||||
m_Socket.Send(buffer, client->GetIp());
|
// this is protocol revision dependent
|
||||||
|
switch ( client->GetProtocolRevision() )
|
||||||
|
{
|
||||||
|
case XLX_PROTOCOL_REVISION_0:
|
||||||
|
case XLX_PROTOCOL_REVISION_1:
|
||||||
|
m_Socket.Send(bufferLegacy, client->GetIp());
|
||||||
|
break;
|
||||||
|
case XLX_PROTOCOL_REVISION_2:
|
||||||
|
default:
|
||||||
|
if ( g_Transcoder.IsConnected() )
|
||||||
|
{
|
||||||
|
m_Socket.Send(buffer, client->GetIp());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_Socket.Send(bufferLegacy, client->GetIp());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_Reflector.ReleaseClients();
|
g_Reflector.ReleaseClients();
|
||||||
@ -459,7 +491,7 @@ bool CXlxProtocol::IsValidKeepAlivePacket(const CBuffer &Buffer, CCallsign *call
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CXlxProtocol::IsValidConnectPacket(const CBuffer &Buffer, CCallsign *callsign, char *modules, uint8 *major, uint8 *minor, uint8 *rev)
|
bool CXlxProtocol::IsValidConnectPacket(const CBuffer &Buffer, CCallsign *callsign, char *modules, CVersion *version)
|
||||||
{
|
{
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
if ((Buffer.size() == 39) && (Buffer.data()[0] == 'L') && (Buffer.data()[38] == 0))
|
if ((Buffer.size() == 39) && (Buffer.data()[0] == 'L') && (Buffer.data()[38] == 0))
|
||||||
@ -467,9 +499,7 @@ bool CXlxProtocol::IsValidConnectPacket(const CBuffer &Buffer, CCallsign *callsi
|
|||||||
callsign->SetCallsign((const uint8 *)&(Buffer.data()[1]), 8);
|
callsign->SetCallsign((const uint8 *)&(Buffer.data()[1]), 8);
|
||||||
::strcpy(modules, (const char *)&(Buffer.data()[12]));
|
::strcpy(modules, (const char *)&(Buffer.data()[12]));
|
||||||
valid = callsign->IsValid();
|
valid = callsign->IsValid();
|
||||||
*major = Buffer.data()[9];
|
*version = CVersion(Buffer.data()[9], Buffer.data()[10], Buffer.data()[11]);
|
||||||
*minor = Buffer.data()[10];
|
|
||||||
*rev = Buffer.data()[11];
|
|
||||||
for ( int i = 0; i < ::strlen(modules); i++ )
|
for ( int i = 0; i < ::strlen(modules); i++ )
|
||||||
{
|
{
|
||||||
valid &= IsLetter(modules[i]);
|
valid &= IsLetter(modules[i]);
|
||||||
@ -489,7 +519,7 @@ bool CXlxProtocol::IsValidDisconnectPacket(const CBuffer &Buffer, CCallsign *cal
|
|||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CXlxProtocol::IsValidAckPacket(const CBuffer &Buffer, CCallsign *callsign, char *modules)
|
bool CXlxProtocol::IsValidAckPacket(const CBuffer &Buffer, CCallsign *callsign, char *modules, CVersion *version)
|
||||||
{
|
{
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
if ((Buffer.size() == 39) && (Buffer.data()[0] == 'A') && (Buffer.data()[38] == 0))
|
if ((Buffer.size() == 39) && (Buffer.data()[0] == 'A') && (Buffer.data()[38] == 0))
|
||||||
@ -497,6 +527,7 @@ bool CXlxProtocol::IsValidAckPacket(const CBuffer &Buffer, CCallsign *callsign,
|
|||||||
callsign->SetCallsign((const uint8 *)&(Buffer.data()[1]), 8);
|
callsign->SetCallsign((const uint8 *)&(Buffer.data()[1]), 8);
|
||||||
::strcpy(modules, (const char *)&(Buffer.data()[12]));
|
::strcpy(modules, (const char *)&(Buffer.data()[12]));
|
||||||
valid = callsign->IsValid();
|
valid = callsign->IsValid();
|
||||||
|
*version = CVersion(Buffer.data()[9], Buffer.data()[10], Buffer.data()[11]);
|
||||||
for ( int i = 0; i < ::strlen(modules); i++ )
|
for ( int i = 0; i < ::strlen(modules); i++ )
|
||||||
{
|
{
|
||||||
valid &= IsLetter(modules[i]);
|
valid &= IsLetter(modules[i]);
|
||||||
@ -516,6 +547,74 @@ bool CXlxProtocol::IsValidNackPacket(const CBuffer &Buffer, CCallsign *callsign)
|
|||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CDvFramePacket *CXlxProtocol::IsValidDvFramePacket(const CBuffer &Buffer)
|
||||||
|
{
|
||||||
|
CDvFramePacket *dvframe = NULL;
|
||||||
|
|
||||||
|
// base class first (protocol revision 1 and lower)
|
||||||
|
dvframe = CDextraProtocol::IsValidDvFramePacket(Buffer);
|
||||||
|
|
||||||
|
// otherwise try protocol revision 2
|
||||||
|
if ( (dvframe == NULL) &&
|
||||||
|
(Buffer.size() == 45) && (Buffer.Compare((uint8 *)"DSVT", 4) == 0) &&
|
||||||
|
(Buffer.data()[4] == 0x20) && (Buffer.data()[8] == 0x20) &&
|
||||||
|
((Buffer.data()[14] & 0x40) == 0) )
|
||||||
|
{
|
||||||
|
// create packet
|
||||||
|
dvframe = new CDvFramePacket(
|
||||||
|
// sid
|
||||||
|
*((uint16 *)&(Buffer.data()[12])),
|
||||||
|
// dstar
|
||||||
|
Buffer.data()[14], &(Buffer.data()[15]), &(Buffer.data()[24]),
|
||||||
|
// dmr
|
||||||
|
Buffer.data()[27], Buffer.data()[28], &(Buffer.data()[29]), &(Buffer.data()[38]));
|
||||||
|
|
||||||
|
// check validity of packet
|
||||||
|
if ( !dvframe->IsValid() )
|
||||||
|
{
|
||||||
|
delete dvframe;
|
||||||
|
dvframe = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return dvframe;
|
||||||
|
}
|
||||||
|
|
||||||
|
CDvLastFramePacket *CXlxProtocol::IsValidDvLastFramePacket(const CBuffer &Buffer)
|
||||||
|
{
|
||||||
|
CDvLastFramePacket *dvframe = NULL;
|
||||||
|
|
||||||
|
// base class first (protocol revision 1 and lower)
|
||||||
|
dvframe = CDextraProtocol::IsValidDvLastFramePacket(Buffer);
|
||||||
|
|
||||||
|
// otherwise try protocol revision 2
|
||||||
|
if ( (dvframe == NULL) &&
|
||||||
|
(Buffer.size() == 45) && (Buffer.Compare((uint8 *)"DSVT", 4) == 0) &&
|
||||||
|
(Buffer.data()[4] == 0x20) && (Buffer.data()[8] == 0x20) &&
|
||||||
|
((Buffer.data()[14] & 0x40) != 0) )
|
||||||
|
{
|
||||||
|
// create packet
|
||||||
|
dvframe = new CDvLastFramePacket(
|
||||||
|
// sid
|
||||||
|
*((uint16 *)&(Buffer.data()[12])),
|
||||||
|
// dstar
|
||||||
|
Buffer.data()[14], &(Buffer.data()[15]), &(Buffer.data()[24]),
|
||||||
|
// dmr
|
||||||
|
Buffer.data()[27], Buffer.data()[28], &(Buffer.data()[29]), &(Buffer.data()[38]));
|
||||||
|
|
||||||
|
// check validity of packet
|
||||||
|
if ( !dvframe->IsValid() )
|
||||||
|
{
|
||||||
|
delete dvframe;
|
||||||
|
dvframe = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
return dvframe;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// packet encoding helpers
|
// packet encoding helpers
|
||||||
|
|
||||||
@ -584,3 +683,42 @@ void CXlxProtocol::EncodeConnectNackPacket(CBuffer *Buffer)
|
|||||||
Buffer->Append((uint8)0);
|
Buffer->Append((uint8)0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CXlxProtocol::EncodeDvFramePacket(const CDvFramePacket &Packet, CBuffer *Buffer) const
|
||||||
|
{
|
||||||
|
uint8 tag[] = { 'D','S','V','T',0x20,0x00,0x00,0x00,0x20,0x00,0x01,0x02 };
|
||||||
|
|
||||||
|
Buffer->Set(tag, sizeof(tag));
|
||||||
|
Buffer->Append(Packet.GetStreamId());
|
||||||
|
Buffer->Append((uint8)(Packet.GetDstarPacketId() % 21));
|
||||||
|
Buffer->Append((uint8 *)Packet.GetAmbe(), AMBE_SIZE);
|
||||||
|
Buffer->Append((uint8 *)Packet.GetDvData(), DVDATA_SIZE);
|
||||||
|
|
||||||
|
Buffer->Append((uint8)Packet.GetDmrPacketId());
|
||||||
|
Buffer->Append((uint8)Packet.GetDmrPacketSubid());
|
||||||
|
Buffer->Append((uint8 *)Packet.GetAmbePlus(), AMBEPLUS_SIZE);
|
||||||
|
Buffer->Append((uint8 *)Packet.GetDvSync(), DVSYNC_SIZE);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CXlxProtocol::EncodeDvLastFramePacket(const CDvLastFramePacket &Packet, CBuffer *Buffer) const
|
||||||
|
{
|
||||||
|
uint8 tag[] = { 'D','S','V','T',0x20,0x00,0x00,0x00,0x20,0x00,0x01,0x02 };
|
||||||
|
uint8 dstarambe[] = { 0x55,0xC8,0x7A,0x00,0x00,0x00,0x00,0x00,0x00 };
|
||||||
|
uint8 dstardvdata[] = { 0x25,0x1A,0xC6 };
|
||||||
|
|
||||||
|
Buffer->Set(tag, sizeof(tag));
|
||||||
|
Buffer->Append(Packet.GetStreamId());
|
||||||
|
Buffer->Append((uint8)((Packet.GetPacketId() % 21) | 0x40));
|
||||||
|
Buffer->Append(dstarambe, sizeof(dstarambe));
|
||||||
|
Buffer->Append(dstardvdata, sizeof(dstardvdata));
|
||||||
|
|
||||||
|
|
||||||
|
Buffer->Append((uint8)Packet.GetDmrPacketId());
|
||||||
|
Buffer->Append((uint8)Packet.GetDmrPacketSubid());
|
||||||
|
Buffer->Append((uint8 *)Packet.GetAmbePlus(), AMBEPLUS_SIZE);
|
||||||
|
Buffer->Append((uint8 *)Packet.GetDvSync(), DVSYNC_SIZE);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
#ifndef cxlxprotocol_h
|
#ifndef cxlxprotocol_h
|
||||||
#define cxlxprotocol_h
|
#define cxlxprotocol_h
|
||||||
|
|
||||||
|
#include "cversion.h"
|
||||||
#include "ctimepoint.h"
|
#include "ctimepoint.h"
|
||||||
#include "cdextraprotocol.h"
|
#include "cdextraprotocol.h"
|
||||||
#include "cclients.h"
|
#include "cclients.h"
|
||||||
@ -65,18 +65,22 @@ protected:
|
|||||||
void OnDvLastFramePacketIn(CDvLastFramePacket *, const CIp * = NULL);
|
void OnDvLastFramePacketIn(CDvLastFramePacket *, const CIp * = NULL);
|
||||||
|
|
||||||
// packet decoding helpers
|
// packet decoding helpers
|
||||||
bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *);
|
bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *);
|
||||||
bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *, uint8 *, uint8 *, uint8 *);
|
bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *, CVersion *);
|
||||||
bool IsValidDisconnectPacket(const CBuffer &, CCallsign *);
|
bool IsValidDisconnectPacket(const CBuffer &, CCallsign *);
|
||||||
bool IsValidAckPacket(const CBuffer &, CCallsign *, char *);
|
bool IsValidAckPacket(const CBuffer &, CCallsign *, char *, CVersion *);
|
||||||
bool IsValidNackPacket(const CBuffer &, CCallsign *);
|
bool IsValidNackPacket(const CBuffer &, CCallsign *);
|
||||||
|
CDvFramePacket *IsValidDvFramePacket(const CBuffer &);
|
||||||
|
CDvLastFramePacket *IsValidDvLastFramePacket(const CBuffer &);
|
||||||
|
|
||||||
// packet encoding helpers
|
// packet encoding helpers
|
||||||
void EncodeKeepAlivePacket(CBuffer *);
|
void EncodeKeepAlivePacket(CBuffer *);
|
||||||
void EncodeConnectPacket(CBuffer *, const char *);
|
void EncodeConnectPacket(CBuffer *, const char *);
|
||||||
void EncodeDisconnectPacket(CBuffer *);
|
void EncodeDisconnectPacket(CBuffer *);
|
||||||
void EncodeConnectAckPacket(CBuffer *, const char *);
|
void EncodeConnectAckPacket(CBuffer *, const char *);
|
||||||
void EncodeConnectNackPacket(CBuffer *);
|
void EncodeConnectNackPacket(CBuffer *);
|
||||||
|
bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const;
|
||||||
|
bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// time
|
// time
|
||||||
|
@ -94,6 +94,9 @@ int main(int argc, const char * argv[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// splash
|
||||||
|
std::cout << "Starting xlxd " << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_REVISION << std::endl << std::endl;
|
||||||
|
|
||||||
// initialize reflector
|
// initialize reflector
|
||||||
g_Reflector.SetCallsign(argv[1]);
|
g_Reflector.SetCallsign(argv[1]);
|
||||||
g_Reflector.SetListenIp(CIp(argv[2]));
|
g_Reflector.SetListenIp(CIp(argv[2]));
|
||||||
|
18
src/main.h
18
src/main.h
@ -48,8 +48,8 @@
|
|||||||
// version -----------------------------------------------------
|
// version -----------------------------------------------------
|
||||||
|
|
||||||
#define VERSION_MAJOR 2
|
#define VERSION_MAJOR 2
|
||||||
#define VERSION_MINOR 0
|
#define VERSION_MINOR 2
|
||||||
#define VERSION_REVISION 0
|
#define VERSION_REVISION 1
|
||||||
|
|
||||||
// global ------------------------------------------------------
|
// global ------------------------------------------------------
|
||||||
|
|
||||||
@ -127,8 +127,9 @@
|
|||||||
|
|
||||||
// DMRid database -----------------------------------------------
|
// DMRid database -----------------------------------------------
|
||||||
|
|
||||||
#define DMRIDDB_USE_RLX_SERVER 0
|
#define DMRIDDB_USE_RLX_SERVER 1 // 1 = use http, 0 = use local file
|
||||||
#define DMRIDDB_PATH "/xlxd/dmrid.dat"
|
#define DMRIDDB_PATH "/xlxd/dmrid.dat" // local file path
|
||||||
|
#define DMRIDDB_REFRESH_RATE 180 // in minutes
|
||||||
|
|
||||||
|
|
||||||
// xml & json reporting -----------------------------------------
|
// xml & json reporting -----------------------------------------
|
||||||
@ -180,8 +181,13 @@ extern CReflector g_Reflector;
|
|||||||
class CGateKeeper;
|
class CGateKeeper;
|
||||||
extern CGateKeeper g_GateKeeper;
|
extern CGateKeeper g_GateKeeper;
|
||||||
|
|
||||||
class CDmridDir;
|
#if (DMRIDDB_USE_RLX_SERVER == 1)
|
||||||
extern CDmridDir g_DmridDir;
|
class CDmridDirHttp;
|
||||||
|
extern CDmridDirHttp g_DmridDir;
|
||||||
|
#else
|
||||||
|
class CDmridDirFile;
|
||||||
|
extern CDmridDirFile g_DmridDir;
|
||||||
|
#endif
|
||||||
|
|
||||||
class CTranscoder;
|
class CTranscoder;
|
||||||
extern CTranscoder g_Transcoder;
|
extern CTranscoder g_Transcoder;
|
||||||
|
Loading…
Reference in New Issue
Block a user