xlxd 2.2.1

* auto-reload of deride DB
* interlink protocol v2.0
This commit is contained in:
LX3JL 2018-01-12 09:30:59 +01:00
parent ed24a5b8cb
commit 32a437c138
29 changed files with 1072 additions and 298 deletions

View File

@ -25,7 +25,8 @@
#include "main.h"
#include <string.h>
#include <cctype>
#include "cdmriddir.h"
#include "cdmriddirfile.h"
#include "cdmriddirhttp.h"
#include "ccallsign.h"
////////////////////////////////////////////////////////////////////////////////////////
@ -60,16 +61,24 @@ CCallsign::CCallsign(const char *sz, uint32 dmrid)
// dmrid ok ?
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 )
{
const CCallsign *callsign = g_DmridDir.FindCallsign(m_uiDmrid);
if ( callsign != NULL )
{
::memcpy(m_Callsign, callsign->m_Callsign, sizeof(m_Callsign));
}
g_DmridDir.Lock();
{
const CCallsign *callsign = g_DmridDir.FindCallsign(m_uiDmrid);
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
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 )
{
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;
if ( UpdateCallsign )
{
const CCallsign *callsign = g_DmridDir.FindCallsign(dmrid);
if ( callsign != NULL )
{
::memcpy(m_Callsign, callsign->m_Callsign, sizeof(m_Callsign));
}
g_DmridDir.Lock();
{
const CCallsign *callsign = g_DmridDir.FindCallsign(dmrid);
if ( callsign != NULL )
{
::memcpy(m_Callsign, callsign->m_Callsign, sizeof(m_Callsign));
}
}
g_DmridDir.Unlock();
}
}

View File

@ -34,7 +34,7 @@
CCallsignList::CCallsignList()
{
m_Filename = NULL;
::memset(&m_LastModTime, 0, sizeof(CCallsignList));
::memset(&m_LastModTime, 0, sizeof(time_t));
}
////////////////////////////////////////////////////////////////////////////////////////

View File

@ -26,9 +26,95 @@
#include "main.h"
#include "creflector.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
@ -53,218 +139,6 @@ uint32 CDmridDir::FindDmrid(const CCallsign &callsign)
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

View File

@ -32,7 +32,6 @@
#include "cbuffer.h"
#include "ccallsign.h"
// compare function for std::map::find
struct CallsignCompare
@ -48,31 +47,49 @@ class CDmridDir
{
public:
// constructor
CDmridDir() {}
CDmridDir();
// 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
bool RefreshContent(void);
virtual bool LoadContent(CBuffer *) { return false; }
virtual bool RefreshContent(const CBuffer &) { return false; }
// find
const CCallsign *FindCallsign(uint32);
uint32 FindDmrid(const CCallsign &);
protected:
// httpd helpers
bool HttpGet(const char *, const char *, int, CBuffer *);
// syntax helpers
// thread
static void Thread(CDmridDir *);
// reload helpers
bool Reload(void);
virtual bool NeedReload(void) { return false; }
bool IsValidDmrid(const char *);
protected:
// directory
// data
std::map <uint32, CCallsign> m_CallsignMap;
std::map <CCallsign, uint32, CallsignCompare> m_DmridMap;
// Lock()
std::mutex m_Mutex;
// thread
bool m_bStopThread;
std::thread *m_pThread;
};
////////////////////////////////////////////////////////////////////////////////////////
#endif /* cdmriddir_h */

165
src/cdmriddirfile.cpp Normal file
View 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
View 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
View 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
View 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 */

View File

@ -61,6 +61,20 @@ CDvFramePacket::CDvFramePacket(const uint8 *ambe, const uint8 *sync, uint16 sid,
::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
CDvFramePacket::CDvFramePacket(const CDvFramePacket &DvFrame)

View File

@ -55,6 +55,7 @@ public:
CDvFramePacket();
CDvFramePacket(const struct dstar_dvframe *, uint16, 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 &);
// destructor

View File

@ -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
CDvLastFramePacket::CDvLastFramePacket(const CDvLastFramePacket &DvFrame)

View File

@ -42,6 +42,7 @@ public:
CDvLastFramePacket();
CDvLastFramePacket(const struct dstar_dvframe *, uint16, 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 &);
// destructor

View File

@ -59,6 +59,16 @@ CPacket::CPacket(uint16 sid, uint8 dmrpid, uint8 dmrspid)
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

View File

@ -42,6 +42,7 @@ public:
CPacket();
CPacket(uint16 sid, uint8 dstarpid);
CPacket(uint16 sid, uint8 dmrpid, uint8 dmrsubpid);
CPacket(uint16 sid, uint8 dstarpid, uint8 dmrpid, uint8 dmrsubpid);
// destructor
virtual ~CPacket() {};

View File

@ -40,12 +40,13 @@ CPeer::CPeer()
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_Ip = ip;
::memset(m_ReflectorModules, 0, sizeof(m_ReflectorModules));
::strncpy(m_ReflectorModules, modules, sizeof(m_ReflectorModules)-1);
m_Version = version;
m_LastKeepaliveTime.Now();
m_ConnectTime = std::time(NULL);
m_LastHeardTime = std::time(NULL);
@ -56,6 +57,7 @@ CPeer::CPeer(const CPeer &peer)
m_Callsign = peer.m_Callsign;
m_Ip = peer.m_Ip;
::memcpy(m_ReflectorModules, peer.m_ReflectorModules, sizeof(m_ReflectorModules));
m_Version = peer.m_Version;
m_LastKeepaliveTime = peer.m_LastKeepaliveTime;
m_ConnectTime = peer.m_ConnectTime;
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_Ip == m_Ip);
same &= (peer.m_Version == m_Version);
for ( int i = 0; (i < m_Clients.size()) && same ; i++ )
{
same &= (peer.m_Clients[i] == m_Clients[i]);

View File

@ -25,6 +25,7 @@
#ifndef cpeer_h
#define cpeer_h
#include "cversion.h"
#include "ctimepoint.h"
#include "cip.h"
#include "ccallsign.h"
@ -41,7 +42,7 @@ class CPeer
public:
// constructors
CPeer();
CPeer(const CCallsign &, const CIp &, char *);
CPeer(const CCallsign &, const CIp &, char *, const CVersion &);
CPeer(const CPeer &);
// destructor
@ -82,6 +83,7 @@ protected:
CCallsign m_Callsign;
CIp m_Ip;
char m_ReflectorModules[NB_MODULES_MAX+1];
CVersion m_Version;
std::vector<CClient *> m_Clients;
// status

View File

@ -26,7 +26,8 @@
#include <string.h>
#include "creflector.h"
#include "cgatekeeper.h"
#include "cdmriddir.h"
#include "cdmriddirfile.h"
#include "cdmriddirhttp.h"
#include "ctranscoder.h"
////////////////////////////////////////////////////////////////////////////////////////
@ -102,7 +103,7 @@ bool CReflector::Start(void)
ok &= g_GateKeeper.Init();
// init dmrid directory
g_DmridDir.RefreshContent();
g_DmridDir.Init();
// init the transcoder
g_Transcoder.Init();

View File

@ -188,12 +188,6 @@ void CTranscoder::Task(void)
}
// handle end of streaming timeout
//CheckStreamsTimeout();
// handle queue from reflector
//HandleQueue();
// keep client alive
if ( m_LastKeepaliveTime.DurationSinceNow() > TRANSCODER_KEEPALIVE_PERIOD )
{

View File

@ -55,6 +55,9 @@ public:
void Lock(void) { m_Mutex.lock(); }
void Unlock(void) { m_Mutex.unlock(); }
// status
bool IsConnected(void) const { return m_bConnected; }
// manage streams
CCodecStream *GetStream(CPacketStream *, uint8);
void ReleaseStream(CCodecStream *);

87
src/cversion.cpp Normal file
View 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
View 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 */

View File

@ -32,16 +32,40 @@
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)
{
m_ProtRev = protRev;
}
CXlxClient::CXlxClient(const CXlxClient &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;
}
////////////////////////////////////////////////////////////////////////////////////////

View File

@ -31,6 +31,10 @@
////////////////////////////////////////////////////////////////////////////////////////
// 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
@ -40,7 +44,7 @@ class CXlxClient : public CClient
public:
// constructors
CXlxClient();
CXlxClient(const CCallsign &, const CIp &, char = ' ');
CXlxClient(const CCallsign &, const CIp &, char = ' ', int = XLX_PROTOCOL_REVISION_0);
CXlxClient(const CXlxClient &);
// destructor
@ -48,7 +52,9 @@ public:
// identity
int GetProtocol(void) const { return PROTOCOL_XLX; }
int GetProtocolRevision(void) const { return m_ProtRev; }
const char *GetProtocolName(void) const { return "XLX"; }
int GetCodec(void) const;
bool IsPeer(void) const { return true; }
// status
@ -56,6 +62,10 @@ public:
// reporting
void WriteXml(std::ofstream &) {}
protected:
// data
int m_ProtRev;
};
////////////////////////////////////////////////////////////////////////////////////////

View File

@ -37,14 +37,18 @@ CXlxPeer::CXlxPeer()
{
}
CXlxPeer::CXlxPeer(const CCallsign &callsign, const CIp &ip, char *modules)
: CPeer(callsign, ip, modules)
CXlxPeer::CXlxPeer(const CCallsign &callsign, const CIp &ip, char *modules, const CVersion &version)
: 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
for ( int i = 0; i < ::strlen(modules); i++ )
{
// create
CXlxClient *client = new CXlxClient(callsign, ip, modules[i]);
CXlxClient *client = new CXlxClient(callsign, ip, modules[i], protrev);
// and append to vector
m_Clients.push_back(client);
}
@ -82,3 +86,21 @@ bool CXlxPeer::IsAlive(void) const
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;
}

View File

@ -26,9 +26,11 @@
#define cxlxpeer_h
#include "cpeer.h"
#include "cxlxclient.h"
////////////////////////////////////////////////////////////////////////////////////////
//
// define
////////////////////////////////////////////////////////////////////////////////////////
// class
@ -38,7 +40,7 @@ class CXlxPeer : public CPeer
public:
// constructors
CXlxPeer();
CXlxPeer(const CCallsign &, const CIp &, char *);
CXlxPeer(const CCallsign &, const CIp &, char *, const CVersion &);
CXlxPeer(const CXlxPeer &);
// destructor
@ -46,9 +48,13 @@ public:
// status
bool IsAlive(void) const;
// identity
int GetProtocol(void) const { return PROTOCOL_XLX; }
const char *GetProtocolName(void) const { return "XLX"; }
// revision helper
static int GetProtocolRevision(const CVersion &);
};
////////////////////////////////////////////////////////////////////////////////////////

View File

@ -67,10 +67,10 @@ void CXlxProtocol::Task(void)
CIp Ip;
CCallsign Callsign;
char Modules[NB_MODULES_MAX+1];
CVersion Version;
CDvHeaderPacket *Header;
CDvFramePacket *Frame;
CDvLastFramePacket *LastFrame;
uint8 Major, Minor, Revision;
// any incoming packet ?
if ( m_Socket.Receive(&Buffer, &Ip, 20) != -1 )
@ -106,34 +106,41 @@ void CXlxProtocol::Task(void)
// handle it
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
<< " from " << Callsign << " at " << Ip << std::endl;
// callsign authorized?
if ( g_GateKeeper.MayLink(Callsign, Ip, PROTOCOL_XLX, Modules) )
{
// acknowledge connecting request
// following is version dependent
// for backward compatibility, only send ACK once
if ( (Major == 1) && (Minor < 4) )
switch ( CXlxPeer::GetProtocolRevision(Version) )
{
// already connected ?
CPeers *peers = g_Reflector.GetPeers();
if ( peers->FindPeer(Callsign, Ip, PROTOCOL_XLX) == NULL )
{
case XLX_PROTOCOL_REVISION_0:
{
// 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
EncodeConnectAckPacket(&Buffer, Modules);
m_Socket.Send(Buffer, Ip);
}
g_Reflector.ReleasePeers();
}
else
{
// acknowledge the request
EncodeConnectAckPacket(&Buffer, Modules);
m_Socket.Send(Buffer, Ip);
break;
}
}
else
@ -143,7 +150,7 @@ void CXlxProtocol::Task(void)
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;
@ -156,8 +163,8 @@ void CXlxProtocol::Task(void)
{
// create the new peer
// 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
// this also add all new clients to reflector client list
peers->AddPeer(peer);
@ -253,6 +260,13 @@ void CXlxProtocol::HandleQueue(void)
CBuffer 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
CClients *clients = g_Reflector.GetClients();
int index = -1;
@ -263,7 +277,25 @@ void CXlxProtocol::HandleQueue(void)
if ( !client->IsAMaster() && (client->GetReflectorModule() == packet->GetModuleId()) )
{
// 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();
@ -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;
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);
::strcpy(modules, (const char *)&(Buffer.data()[12]));
valid = callsign->IsValid();
*major = Buffer.data()[9];
*minor = Buffer.data()[10];
*rev = Buffer.data()[11];
*version = CVersion(Buffer.data()[9], Buffer.data()[10], Buffer.data()[11]);
for ( int i = 0; i < ::strlen(modules); i++ )
{
valid &= IsLetter(modules[i]);
@ -489,7 +519,7 @@ bool CXlxProtocol::IsValidDisconnectPacket(const CBuffer &Buffer, CCallsign *cal
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;
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);
::strcpy(modules, (const char *)&(Buffer.data()[12]));
valid = callsign->IsValid();
*version = CVersion(Buffer.data()[9], Buffer.data()[10], Buffer.data()[11]);
for ( int i = 0; i < ::strlen(modules); i++ )
{
valid &= IsLetter(modules[i]);
@ -516,6 +547,74 @@ bool CXlxProtocol::IsValidNackPacket(const CBuffer &Buffer, CCallsign *callsign)
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
@ -584,3 +683,42 @@ void CXlxProtocol::EncodeConnectNackPacket(CBuffer *Buffer)
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;
}

View File

@ -25,7 +25,7 @@
#ifndef cxlxprotocol_h
#define cxlxprotocol_h
#include "cversion.h"
#include "ctimepoint.h"
#include "cdextraprotocol.h"
#include "cclients.h"
@ -65,18 +65,22 @@ protected:
void OnDvLastFramePacketIn(CDvLastFramePacket *, const CIp * = NULL);
// packet decoding helpers
bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *);
bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *, uint8 *, uint8 *, uint8 *);
bool IsValidDisconnectPacket(const CBuffer &, CCallsign *);
bool IsValidAckPacket(const CBuffer &, CCallsign *, char *);
bool IsValidNackPacket(const CBuffer &, CCallsign *);
bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *);
bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *, CVersion *);
bool IsValidDisconnectPacket(const CBuffer &, CCallsign *);
bool IsValidAckPacket(const CBuffer &, CCallsign *, char *, CVersion *);
bool IsValidNackPacket(const CBuffer &, CCallsign *);
CDvFramePacket *IsValidDvFramePacket(const CBuffer &);
CDvLastFramePacket *IsValidDvLastFramePacket(const CBuffer &);
// packet encoding helpers
void EncodeKeepAlivePacket(CBuffer *);
void EncodeConnectPacket(CBuffer *, const char *);
void EncodeDisconnectPacket(CBuffer *);
void EncodeConnectAckPacket(CBuffer *, const char *);
void EncodeConnectNackPacket(CBuffer *);
void EncodeKeepAlivePacket(CBuffer *);
void EncodeConnectPacket(CBuffer *, const char *);
void EncodeDisconnectPacket(CBuffer *);
void EncodeConnectAckPacket(CBuffer *, const char *);
void EncodeConnectNackPacket(CBuffer *);
bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const;
bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const;
protected:
// time

View File

@ -94,6 +94,9 @@ int main(int argc, const char * argv[])
return 1;
}
// splash
std::cout << "Starting xlxd " << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_REVISION << std::endl << std::endl;
// initialize reflector
g_Reflector.SetCallsign(argv[1]);
g_Reflector.SetListenIp(CIp(argv[2]));

View File

@ -48,8 +48,8 @@
// version -----------------------------------------------------
#define VERSION_MAJOR 2
#define VERSION_MINOR 0
#define VERSION_REVISION 0
#define VERSION_MINOR 2
#define VERSION_REVISION 1
// global ------------------------------------------------------
@ -127,8 +127,9 @@
// DMRid database -----------------------------------------------
#define DMRIDDB_USE_RLX_SERVER 0
#define DMRIDDB_PATH "/xlxd/dmrid.dat"
#define DMRIDDB_USE_RLX_SERVER 1 // 1 = use http, 0 = use local file
#define DMRIDDB_PATH "/xlxd/dmrid.dat" // local file path
#define DMRIDDB_REFRESH_RATE 180 // in minutes
// xml & json reporting -----------------------------------------
@ -180,8 +181,13 @@ extern CReflector g_Reflector;
class CGateKeeper;
extern CGateKeeper g_GateKeeper;
class CDmridDir;
extern CDmridDir g_DmridDir;
#if (DMRIDDB_USE_RLX_SERVER == 1)
class CDmridDirHttp;
extern CDmridDirHttp g_DmridDir;
#else
class CDmridDirFile;
extern CDmridDirFile g_DmridDir;
#endif
class CTranscoder;
extern CTranscoder g_Transcoder;