pull/1/head
Tom Early 6 years ago
parent 30a47e1bd3
commit ef252ec37a

@ -89,31 +89,32 @@ CCodecStream::~CCodecStream()
bool CCodecStream::Init(uint16 uiPort) bool CCodecStream::Init(uint16 uiPort)
{ {
bool ok;
// reset stop flag // reset stop flag
m_bStopThread = false; m_bConnected = m_bStopThread = false;
// create server's IP // create server's IP
m_Ip = g_Reflector.GetTranscoderIp();
m_uiPort = uiPort; m_uiPort = uiPort;
auto s = g_Reflector.GetTranscoderIp();
m_Ip.Initialize(strchr(s, ':') ? AF_INET6 : AF_INET, m_uiPort, s);
// create our socket // create our socket
ok = m_Socket.Open(uiPort); if (m_Ip.IsSet())
if ( ok ) {
{ if (! m_Socket.Open(m_Ip)) {
// start thread; std::cerr << "Error opening socket on port UDP" << uiPort << " on ip " << m_Ip << std::endl;
m_pThread = new std::thread(CCodecStream::Thread, this); return false;
m_bConnected = true; }
} }
else else
{ {
std::cout << "Error opening socket on port UDP" << uiPort << " on ip " << g_Reflector.GetListenIp() << std::endl; std::cerr << "Could not initialize Codec Stream on " << m_Ip << std::endl;
m_bConnected = false; return false;
} }
// done m_pThread = new std::thread(CCodecStream::Thread, this);
return ok; m_bConnected = true;
return true;
} }
void CCodecStream::Close(void) void CCodecStream::Close(void)

@ -35,26 +35,15 @@
bool CDcsProtocol::Init(void) bool CDcsProtocol::Init(void)
{ {
bool ok;
// base class // base class
ok = CProtocol::Init(); if (! Initialize("DCS", DCS_PORT))
return false;
// update the reflector callsign
m_ReflectorCallsign.PatchCallsign(0, (const uint8 *)"DCS", 3);
// create our socket
ok &= m_Socket.Open(DCS_PORT);
if ( !ok )
{
std::cout << "Error opening socket on port UDP" << DCS_PORT << " on ip " << g_Reflector.GetListenIp() << std::endl;
}
// update time // update time
m_LastKeepaliveTime.Now(); m_LastKeepaliveTime.Now();
// done // done
return ok; return true;
} }
@ -72,7 +61,7 @@ void CDcsProtocol::Task(void)
CDvFramePacket *Frame; CDvFramePacket *Frame;
// handle incoming packets // handle incoming packets
if ( m_Socket.Receive(Buffer, Ip, 20) ) if ( m_Socket6.Receive(Buffer, Ip, 10) || m_Socket4.Receive(Buffer, Ip, 10) )
{ {
// crack the packet // crack the packet
if ( IsValidDvPacket(Buffer, &Header, &Frame) ) if ( IsValidDvPacket(Buffer, &Header, &Frame) )
@ -114,7 +103,7 @@ void CDcsProtocol::Task(void)
{ {
// acknowledge the request // acknowledge the request
EncodeConnectAckPacket(Callsign, ToLinkModule, &Buffer); EncodeConnectAckPacket(Callsign, ToLinkModule, &Buffer);
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
// create the client // create the client
CDcsClient *client = new CDcsClient(Callsign, Ip, ToLinkModule); CDcsClient *client = new CDcsClient(Callsign, Ip, ToLinkModule);
@ -129,14 +118,14 @@ void CDcsProtocol::Task(void)
// deny the request // deny the request
EncodeConnectNackPacket(Callsign, ToLinkModule, &Buffer); EncodeConnectNackPacket(Callsign, ToLinkModule, &Buffer);
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
} }
} }
else else
{ {
// deny the request // deny the request
EncodeConnectNackPacket(Callsign, ToLinkModule, &Buffer); EncodeConnectNackPacket(Callsign, ToLinkModule, &Buffer);
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
} }
} }
@ -153,7 +142,7 @@ void CDcsProtocol::Task(void)
clients->RemoveClient(client); clients->RemoveClient(client);
// and acknowledge the disconnect // and acknowledge the disconnect
EncodeConnectNackPacket(Callsign, ' ', &Buffer); EncodeConnectNackPacket(Callsign, ' ', &Buffer);
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
} }
g_Reflector.ReleaseClients(); g_Reflector.ReleaseClients();
} }
@ -310,7 +299,7 @@ void CDcsProtocol::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()); Send(buffer, client->GetIp());
} }
} }
@ -346,8 +335,8 @@ void CDcsProtocol::HandleKeepalives(void)
EncodeKeepAlivePacket(&keepalive2, client); EncodeKeepAlivePacket(&keepalive2, client);
// send keepalive // send keepalive
m_Socket.Send(keepalive1, client->GetIp()); Send(keepalive1, client->GetIp());
m_Socket.Send(keepalive2, client->GetIp()); Send(keepalive2, client->GetIp());
// is this client busy ? // is this client busy ?
if ( client->IsAMaster() ) if ( client->IsAMaster() )
@ -361,7 +350,7 @@ void CDcsProtocol::HandleKeepalives(void)
// no, disconnect // no, disconnect
CBuffer disconnect; CBuffer disconnect;
EncodeDisconnectPacket(&disconnect, client); EncodeDisconnectPacket(&disconnect, client);
m_Socket.Send(disconnect, client->GetIp()); Send(disconnect, client->GetIp());
// remove it // remove it
std::cout << "DCS client " << client->GetCallsign() << " keepalive timeout" << std::endl; std::cout << "DCS client " << client->GetCallsign() << " keepalive timeout" << std::endl;

@ -19,7 +19,7 @@
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>. // along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#ifndef cdcsprotocol_h #ifndef cdcsprotocol_h
@ -42,7 +42,7 @@ class CDcsStreamCacheItem
public: public:
CDcsStreamCacheItem() { m_iSeqCounter = 0; } CDcsStreamCacheItem() { m_iSeqCounter = 0; }
~CDcsStreamCacheItem() {} ~CDcsStreamCacheItem() {}
CDvHeaderPacket m_dvHeader; CDvHeaderPacket m_dvHeader;
uint32 m_iSeqCounter; uint32 m_iSeqCounter;
}; };
@ -50,35 +50,29 @@ public:
class CDcsProtocol : public CProtocol class CDcsProtocol : public CProtocol
{ {
public: public:
// constructor
CDcsProtocol() {};
// destructor
virtual ~CDcsProtocol() {};
// initialization // initialization
bool Init(void); bool Init(void);
// task // task
void Task(void); void Task(void);
protected: protected:
// queue helper // queue helper
void HandleQueue(void); void HandleQueue(void);
// keepalive helpers // keepalive helpers
void HandleKeepalives(void); void HandleKeepalives(void);
// stream helpers // stream helpers
bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &); bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &);
// packet decoding helpers // packet decoding helpers
bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *); bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *);
bool IsValidDisconnectPacket(const CBuffer &, CCallsign *); bool IsValidDisconnectPacket(const CBuffer &, CCallsign *);
bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *); bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *);
bool IsValidDvPacket(const CBuffer &, CDvHeaderPacket **, CDvFramePacket **); bool IsValidDvPacket(const CBuffer &, CDvHeaderPacket **, CDvFramePacket **);
bool IsIgnorePacket(const CBuffer &); bool IsIgnorePacket(const CBuffer &);
// packet encoding helpers // packet encoding helpers
void EncodeKeepAlivePacket(CBuffer *); void EncodeKeepAlivePacket(CBuffer *);
void EncodeKeepAlivePacket(CBuffer *, CClient *); void EncodeKeepAlivePacket(CBuffer *, CClient *);
@ -87,11 +81,11 @@ protected:
void EncodeDisconnectPacket(CBuffer *, CClient *); void EncodeDisconnectPacket(CBuffer *, CClient *);
void EncodeDvPacket(const CDvHeaderPacket &, const CDvFramePacket &, uint32, CBuffer *) const; void EncodeDvPacket(const CDvHeaderPacket &, const CDvFramePacket &, uint32, CBuffer *) const;
void EncodeDvLastPacket(const CDvHeaderPacket &, const CDvFramePacket &, uint32, CBuffer *) const; void EncodeDvLastPacket(const CDvHeaderPacket &, const CDvFramePacket &, uint32, CBuffer *) const;
protected: protected:
// for keep alive // for keep alive
CTimePoint m_LastKeepaliveTime; CTimePoint m_LastKeepaliveTime;
// for queue header caches // for queue header caches
std::array<CDcsStreamCacheItem, NB_OF_MODULES> m_StreamsCache; std::array<CDcsStreamCacheItem, NB_OF_MODULES> m_StreamsCache;
}; };

@ -37,27 +37,16 @@
bool CDextraProtocol::Init(void) bool CDextraProtocol::Init(void)
{ {
bool ok;
// base class // base class
ok = CProtocol::Init(); if (! Initialize("XRF", DEXTRA_PORT))
return false;
// update the reflector callsign
m_ReflectorCallsign.PatchCallsign(0, (const uint8 *)"XRF", 3);
// create our socket
ok &= m_Socket.Open(DEXTRA_PORT);
if ( !ok )
{
std::cout << "Error opening socket on port UDP" << DEXTRA_PORT << " on ip " << g_Reflector.GetListenIp() << std::endl;
}
// update time // update time
m_LastKeepaliveTime.Now(); m_LastKeepaliveTime.Now();
m_LastPeersLinkTime.Now(); m_LastPeersLinkTime.Now();
// done // done
return ok; return true;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -75,7 +64,7 @@ void CDextraProtocol::Task(void)
CDvLastFramePacket *LastFrame; CDvLastFramePacket *LastFrame;
// any incoming packet ? // any incoming packet ?
if ( m_Socket.Receive(Buffer, Ip, 20) ) if ( m_Socket6.Receive(Buffer, Ip, 10) || m_Socket4.Receive(Buffer, Ip, 10) )
{ {
// crack the packet // crack the packet
if ( (Frame = IsValidDvFramePacket(Buffer)) != NULL ) if ( (Frame = IsValidDvFramePacket(Buffer)) != NULL )
@ -143,7 +132,7 @@ void CDextraProtocol::Task(void)
{ {
// acknowledge the request // acknowledge the request
EncodeConnectAckPacket(&Buffer, ProtRev); EncodeConnectAckPacket(&Buffer, ProtRev);
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
// create the client // create the client
CDextraClient *client = new CDextraClient(Callsign, Ip, ToLinkModule, ProtRev); CDextraClient *client = new CDextraClient(Callsign, Ip, ToLinkModule, ProtRev);
@ -160,14 +149,14 @@ void CDextraProtocol::Task(void)
// deny the request // deny the request
EncodeConnectNackPacket(&Buffer); EncodeConnectNackPacket(&Buffer);
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
} }
} }
else else
{ {
// deny the request // deny the request
EncodeConnectNackPacket(&Buffer); EncodeConnectNackPacket(&Buffer);
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
} }
} }
else if ( IsValidDisconnectPacket(Buffer, &Callsign) ) else if ( IsValidDisconnectPacket(Buffer, &Callsign) )
@ -183,11 +172,11 @@ void CDextraProtocol::Task(void)
if ( client->GetProtocolRevision() == 1 ) if ( client->GetProtocolRevision() == 1 )
{ {
EncodeDisconnectedPacket(&Buffer); EncodeDisconnectedPacket(&Buffer);
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
} }
else if ( client->GetProtocolRevision() == 2 ) else if ( client->GetProtocolRevision() == 2 )
{ {
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
} }
// and remove it // and remove it
clients->RemoveClient(client); clients->RemoveClient(client);
@ -271,7 +260,7 @@ void CDextraProtocol::HandleQueue(void)
int n = packet->IsDvHeader() ? 5 : 1; int n = packet->IsDvHeader() ? 5 : 1;
for ( int i = 0; i < n; i++ ) for ( int i = 0; i < n; i++ )
{ {
m_Socket.Send(buffer, client->GetIp()); Send(buffer, client->GetIp());
} }
} }
} }
@ -303,7 +292,7 @@ void CDextraProtocol::HandleKeepalives(void)
while ( (client = clients->FindNextClient(PROTOCOL_DEXTRA, it)) != NULL ) while ( (client = clients->FindNextClient(PROTOCOL_DEXTRA, it)) != NULL )
{ {
// send keepalive // send keepalive
m_Socket.Send(keepalive, client->GetIp()); Send(keepalive, client->GetIp());
// client busy ? // client busy ?
if ( client->IsAMaster() ) if ( client->IsAMaster() )
@ -325,7 +314,7 @@ void CDextraProtocol::HandleKeepalives(void)
// no, disconnect // no, disconnect
CBuffer disconnect; CBuffer disconnect;
EncodeDisconnectPacket(&disconnect, client->GetReflectorModule()); EncodeDisconnectPacket(&disconnect, client->GetReflectorModule());
m_Socket.Send(disconnect, client->GetIp()); Send(disconnect, client->GetIp());
// remove it // remove it
std::cout << "DExtra client " << client->GetCallsign() << " keepalive timeout" << std::endl; std::cout << "DExtra client " << client->GetCallsign() << " keepalive timeout" << std::endl;
@ -354,7 +343,7 @@ void CDextraProtocol::HandleKeepalives(void)
CClients *clients = g_Reflector.GetClients(); CClients *clients = g_Reflector.GetClients();
for ( auto cit=peer->cbegin(); cit!=peer->cend(); cit++ ) for ( auto cit=peer->cbegin(); cit!=peer->cend(); cit++ )
{ {
m_Socket.Send(disconnect, (*cit)->GetIp()); Send(disconnect, (*cit)->GetIp());
} }
g_Reflector.ReleaseClients(); g_Reflector.ReleaseClients();
@ -387,7 +376,7 @@ void CDextraProtocol::HandlePeerLinks(void)
{ {
// send disconnect packet // send disconnect packet
EncodeDisconnectPacket(&buffer, peer->GetReflectorModules()[0]); EncodeDisconnectPacket(&buffer, peer->GetReflectorModules()[0]);
m_Socket.Send(buffer, peer->GetIp()); Send(buffer, peer->GetIp());
std::cout << "Sending disconnect packet to XRF peer " << peer->GetCallsign() << std::endl; std::cout << "Sending disconnect packet to XRF peer " << peer->GetCallsign() << std::endl;
// remove client // remove client
peers->RemovePeer(peer); peers->RemovePeer(peer);
@ -408,7 +397,7 @@ void CDextraProtocol::HandlePeerLinks(void)
(*it).ResolveIp(); (*it).ResolveIp();
// send connect packet to re-initiate peer link // send connect packet to re-initiate peer link
EncodeConnectPacket(&buffer, (*it).GetModules()); EncodeConnectPacket(&buffer, (*it).GetModules());
m_Socket.Send(buffer, (*it).GetIp(), DEXTRA_PORT); Send(buffer, (*it).GetIp(), DEXTRA_PORT);
std::cout << "Sending connect packet to XRF peer " << (*it).GetCallsign() << " @ " << (*it).GetIp() << " for module " << (*it).GetModules()[1] << " (module " << (*it).GetModules()[0] << ")" << std::endl; std::cout << "Sending connect packet to XRF peer " << (*it).GetCallsign() << " @ " << (*it).GetIp() << " for module " << (*it).GetModules()[1] << " (module " << (*it).GetModules()[0] << ")" << std::endl;
} }
} }

@ -19,7 +19,7 @@
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>. // along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#ifndef cdextraprotocol_h #ifndef cdextraprotocol_h
@ -58,15 +58,9 @@
class CDextraProtocol : public CProtocol class CDextraProtocol : public CProtocol
{ {
public: public:
// constructor
CDextraProtocol() {};
// destructor
virtual ~CDextraProtocol() {};
// initialization // initialization
bool Init(void); bool Init(void);
// task // task
void Task(void); void Task(void);
@ -80,7 +74,7 @@ protected:
// stream helpers // stream helpers
bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &); bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &);
// packet decoding helpers // packet decoding helpers
bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *, int *); bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *, int *);
bool IsValidDisconnectPacket(const CBuffer &, CCallsign *); bool IsValidDisconnectPacket(const CBuffer &, CCallsign *);
@ -88,7 +82,7 @@ protected:
CDvHeaderPacket *IsValidDvHeaderPacket(const CBuffer &); CDvHeaderPacket *IsValidDvHeaderPacket(const CBuffer &);
CDvFramePacket *IsValidDvFramePacket(const CBuffer &); CDvFramePacket *IsValidDvFramePacket(const CBuffer &);
CDvLastFramePacket *IsValidDvLastFramePacket(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 *);
@ -99,7 +93,7 @@ protected:
bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const; bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const;
bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const; bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const;
bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const; bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const;
protected: protected:
// time // time
CTimePoint m_LastKeepaliveTime; CTimePoint m_LastKeepaliveTime;

@ -56,16 +56,9 @@ static uint8 g_DmrSyncMSData[] = { 0x0D,0x5D,0x7F,0x77,0xFD,0x75,0x70 };
bool CDmrmmdvmProtocol::Init(void) bool CDmrmmdvmProtocol::Init(void)
{ {
bool ok;
// base class // base class
ok = CProtocol::Init(); if (! Initialize(NULL, DMRMMDVM_PORT))
return false;
// update the reflector callsign
//m_ReflectorCallsign.PatchCallsign(0, (const uint8 *)"DMR", 3);
// create our socket
ok &= m_Socket.Open(DMRMMDVM_PORT);
// update time // update time
m_LastKeepaliveTime.Now(); m_LastKeepaliveTime.Now();
@ -76,7 +69,7 @@ bool CDmrmmdvmProtocol::Init(void)
m_uiAuthSeed = (uint32)rand(); m_uiAuthSeed = (uint32)rand();
// done // done
return ok; return true;
} }
@ -97,7 +90,7 @@ void CDmrmmdvmProtocol::Task(void)
CDvLastFramePacket *LastFrame; CDvLastFramePacket *LastFrame;
// handle incoming packets // handle incoming packets
if ( m_Socket.Receive(Buffer, Ip, 20) ) if ( m_Socket6.Receive(Buffer, Ip, 10) || m_Socket6.Receive(Buffer, Ip, 10) )
{ {
//Buffer.DebugDump(g_Reflector.m_DebugFile); //Buffer.DebugDump(g_Reflector.m_DebugFile);
// crack the packet // crack the packet
@ -141,13 +134,13 @@ void CDmrmmdvmProtocol::Task(void)
{ {
// acknowledge the request // acknowledge the request
EncodeConnectAckPacket(&Buffer, Callsign, m_uiAuthSeed); EncodeConnectAckPacket(&Buffer, Callsign, m_uiAuthSeed);
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
} }
else else
{ {
// deny the request // deny the request
EncodeNackPacket(&Buffer, Callsign); EncodeNackPacket(&Buffer, Callsign);
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
} }
} }
@ -160,7 +153,7 @@ void CDmrmmdvmProtocol::Task(void)
{ {
// acknowledge the request // acknowledge the request
EncodeAckPacket(&Buffer, Callsign); EncodeAckPacket(&Buffer, Callsign);
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
// add client if needed // add client if needed
CClients *clients = g_Reflector.GetClients(); CClients *clients = g_Reflector.GetClients();
@ -187,7 +180,7 @@ void CDmrmmdvmProtocol::Task(void)
{ {
// deny the request // deny the request
EncodeNackPacket(&Buffer, Callsign); EncodeNackPacket(&Buffer, Callsign);
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
} }
} }
@ -210,7 +203,7 @@ void CDmrmmdvmProtocol::Task(void)
// acknowledge the request // acknowledge the request
EncodeAckPacket(&Buffer, Callsign); EncodeAckPacket(&Buffer, Callsign);
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
} }
else if ( IsValidKeepAlivePacket(Buffer, &Callsign) ) else if ( IsValidKeepAlivePacket(Buffer, &Callsign) )
{ {
@ -224,7 +217,7 @@ void CDmrmmdvmProtocol::Task(void)
{ {
// acknowledge // acknowledge
EncodeKeepAlivePacket(&Buffer, client); EncodeKeepAlivePacket(&Buffer, client);
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
// and mark as alive // and mark as alive
client->Alive(); client->Alive();
@ -243,7 +236,7 @@ void CDmrmmdvmProtocol::Task(void)
// acknowledge the request // acknowledge the request
EncodeAckPacket(&Buffer, Callsign); EncodeAckPacket(&Buffer, Callsign);
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
} }
else if ( Buffer.size() != 55 ) else if ( Buffer.size() != 55 )
{ {
@ -450,7 +443,7 @@ void CDmrmmdvmProtocol::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()); Send(buffer, client->GetIp());
} }
} }
@ -489,7 +482,7 @@ void CDmrmmdvmProtocol::HandleKeepalives(void)
{ {
// no, disconnect // no, disconnect
CBuffer disconnect; CBuffer disconnect;
m_Socket.Send(disconnect, client->GetIp()); Send(disconnect, client->GetIp());
// remove it // remove it
std::cout << "DMRmmdvm client " << client->GetCallsign() << " keepalive timeout" << std::endl; std::cout << "DMRmmdvm client " << client->GetCallsign() << " keepalive timeout" << std::endl;

@ -54,11 +54,11 @@ class CDmrmmdvmStreamCacheItem
public: public:
CDmrmmdvmStreamCacheItem() {} CDmrmmdvmStreamCacheItem() {}
~CDmrmmdvmStreamCacheItem() {} ~CDmrmmdvmStreamCacheItem() {}
CDvHeaderPacket m_dvHeader; CDvHeaderPacket m_dvHeader;
CDvFramePacket m_dvFrame0; CDvFramePacket m_dvFrame0;
CDvFramePacket m_dvFrame1; CDvFramePacket m_dvFrame1;
uint8 m_uiSeqId; uint8 m_uiSeqId;
}; };
@ -66,28 +66,22 @@ public:
class CDmrmmdvmProtocol : public CProtocol class CDmrmmdvmProtocol : public CProtocol
{ {
public: public:
// constructor
CDmrmmdvmProtocol() {};
// destructor
virtual ~CDmrmmdvmProtocol() {};
// initialization // initialization
bool Init(void); bool Init(void);
// task // task
void Task(void); void Task(void);
protected: protected:
// queue helper // queue helper
void HandleQueue(void); void HandleQueue(void);
// keepalive helpers // keepalive helpers
void HandleKeepalives(void); void HandleKeepalives(void);
// stream helpers // stream helpers
bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &, uint8, uint8); bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &, uint8, uint8);
// packet decoding helpers // packet decoding helpers
bool IsValidConnectPacket(const CBuffer &, CCallsign *, const CIp &); bool IsValidConnectPacket(const CBuffer &, CCallsign *, const CIp &);
bool IsValidAuthenticationPacket(const CBuffer &, CCallsign *, const CIp &); bool IsValidAuthenticationPacket(const CBuffer &, CCallsign *, const CIp &);
@ -99,7 +93,7 @@ protected:
bool IsValidDvHeaderPacket(const CBuffer &, CDvHeaderPacket **, uint8 *, uint8 *); bool IsValidDvHeaderPacket(const CBuffer &, CDvHeaderPacket **, uint8 *, uint8 *);
bool IsValidDvFramePacket(const CBuffer &, CDvFramePacket **); bool IsValidDvFramePacket(const CBuffer &, CDvFramePacket **);
bool IsValidDvLastFramePacket(const CBuffer &, CDvLastFramePacket **); bool IsValidDvLastFramePacket(const CBuffer &, CDvLastFramePacket **);
// packet encoding helpers // packet encoding helpers
void EncodeKeepAlivePacket(CBuffer *, CClient *); void EncodeKeepAlivePacket(CBuffer *, CClient *);
void EncodeAckPacket(CBuffer *, const CCallsign &); void EncodeAckPacket(CBuffer *, const CCallsign &);
@ -109,11 +103,11 @@ protected:
bool EncodeDvHeaderPacket(const CDvHeaderPacket &, uint8, CBuffer *) const; bool EncodeDvHeaderPacket(const CDvHeaderPacket &, uint8, CBuffer *) const;
void EncodeDvPacket(const CDvHeaderPacket &, const CDvFramePacket &, const CDvFramePacket &, const CDvFramePacket &, uint8, CBuffer *) const; void EncodeDvPacket(const CDvHeaderPacket &, const CDvFramePacket &, const CDvFramePacket &, const CDvFramePacket &, uint8, CBuffer *) const;
void EncodeDvLastPacket(const CDvHeaderPacket &, uint8, CBuffer *) const; void EncodeDvLastPacket(const CDvHeaderPacket &, uint8, CBuffer *) const;
// dmr DstId to Module helper // dmr DstId to Module helper
char DmrDstIdToModule(uint32) const; char DmrDstIdToModule(uint32) const;
uint32 ModuleToDmrDestId(char) const; uint32 ModuleToDmrDestId(char) const;
// Buffer & LC helpers // Buffer & LC helpers
void AppendVoiceLCToBuffer(CBuffer *, uint32) const; void AppendVoiceLCToBuffer(CBuffer *, uint32) const;
void AppendTerminatorLCToBuffer(CBuffer *, uint32) const; void AppendTerminatorLCToBuffer(CBuffer *, uint32) const;
@ -125,13 +119,13 @@ protected:
protected: protected:
// for keep alive // for keep alive
CTimePoint m_LastKeepaliveTime; CTimePoint m_LastKeepaliveTime;
// for stream id // for stream id
uint16 m_uiStreamId; uint16 m_uiStreamId;
// for queue header caches // for queue header caches
std::array<CDmrmmdvmStreamCacheItem, NB_OF_MODULES> m_StreamsCache; std::array<CDmrmmdvmStreamCacheItem, NB_OF_MODULES> m_StreamsCache;
// for authentication // for authentication
uint32 m_uiAuthSeed; uint32 m_uiAuthSeed;
}; };

@ -47,18 +47,11 @@ static uint8 g_DmrSyncMSData[] = { 0x0D,0x5D,0x7F,0x77,0xFD,0x75,0x70 };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// operation // operation
bool CDmrplusProtocol::Init(void) bool CDmrplusProtocol::Init()
{ {
bool ok;
// base class // base class
ok = CProtocol::Init(); if (! Initialize(NULL, DMRPLUS_PORT))
return false;
// update the reflector callsign
//m_ReflectorCallsign.PatchCallsign(0, (const uint8 *)"DMR", 3);
// create our socket
ok &= m_Socket.Open(DMRPLUS_PORT);
// update time // update time
m_LastKeepaliveTime.Now(); m_LastKeepaliveTime.Now();
@ -68,7 +61,7 @@ bool CDmrplusProtocol::Init(void)
::srand((unsigned) time(&t)); ::srand((unsigned) time(&t));
// done // done
return ok; return true;
} }
@ -86,7 +79,7 @@ void CDmrplusProtocol::Task(void)
CDvFramePacket *Frames[3]; CDvFramePacket *Frames[3];
// handle incoming packets // handle incoming packets
if ( m_Socket.Receive(Buffer, Ip, 20) ) if ( m_Socket6.Receive(Buffer, Ip, 10) && m_Socket4.Receive(Buffer, Ip, 10) )
{ {
// crack the packet // crack the packet
if ( IsValidDvFramePacket(Ip, Buffer, Frames) ) if ( IsValidDvFramePacket(Ip, Buffer, Frames) )
@ -135,7 +128,7 @@ void CDmrplusProtocol::Task(void)
{ {
// acknowledge the request // acknowledge the request
EncodeConnectAckPacket(&Buffer); EncodeConnectAckPacket(&Buffer);
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
// add client if needed // add client if needed
CClients *clients = g_Reflector.GetClients(); CClients *clients = g_Reflector.GetClients();
@ -162,7 +155,7 @@ void CDmrplusProtocol::Task(void)
{ {
// deny the request // deny the request
EncodeConnectNackPacket(&Buffer); EncodeConnectNackPacket(&Buffer);
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
} }
} }
@ -324,7 +317,7 @@ void CDmrplusProtocol::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()); Send(buffer, client->GetIp());
} }
} }
g_Reflector.ReleaseClients(); g_Reflector.ReleaseClients();
@ -353,7 +346,7 @@ void CDmrplusProtocol::SendBufferToClients(const CBuffer &buffer, uint8 module)
if ( !client->IsAMaster() && (client->GetReflectorModule() == module) ) if ( !client->IsAMaster() && (client->GetReflectorModule() == module) )
{ {
// no, send the packet // no, send the packet
m_Socket.Send(buffer, client->GetIp()); Send(buffer, client->GetIp());
} }
} }
g_Reflector.ReleaseClients(); g_Reflector.ReleaseClients();
@ -391,7 +384,7 @@ void CDmrplusProtocol::HandleKeepalives(void)
// no, disconnect // no, disconnect
//CBuffer disconnect; //CBuffer disconnect;
//EncodeDisconnectPacket(&disconnect, client); //EncodeDisconnectPacket(&disconnect, client);
//m_Socket.Send(disconnect, client->GetIp()); //Send(disconnect, client->GetIp());
// remove it // remove it
std::cout << "DMRplus client " << client->GetCallsign() << " keepalive timeout" << std::endl; std::cout << "DMRplus client " << client->GetCallsign() << " keepalive timeout" << std::endl;

@ -44,12 +44,11 @@ class CDmrplusStreamCacheItem
{ {
public: public:
CDmrplusStreamCacheItem() { m_uiSeqId = 0x77; } CDmrplusStreamCacheItem() { m_uiSeqId = 0x77; }
~CDmrplusStreamCacheItem() {}
CDvHeaderPacket m_dvHeader; CDvHeaderPacket m_dvHeader;
CDvFramePacket m_dvFrame0; CDvFramePacket m_dvFrame0;
CDvFramePacket m_dvFrame1; CDvFramePacket m_dvFrame1;
uint8 m_uiSeqId; uint8 m_uiSeqId;
}; };
@ -57,35 +56,29 @@ public:
class CDmrplusProtocol : public CProtocol class CDmrplusProtocol : public CProtocol
{ {
public: public:
// constructor
CDmrplusProtocol() {};
// destructor
virtual ~CDmrplusProtocol() {};
// initialization // initialization
bool Init(void); bool Init();
// task // task
void Task(void); void Task(void);
protected: protected:
// queue helper // queue helper
void HandleQueue(void); void HandleQueue(void);
void SendBufferToClients(const CBuffer &, uint8); void SendBufferToClients(const CBuffer &, uint8);
// keepalive helpers // keepalive helpers
void HandleKeepalives(void); void HandleKeepalives(void);
// stream helpers // stream helpers
bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &); bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &);
// packet decoding helpers // packet decoding helpers
bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *, const CIp &); bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *, const CIp &);
bool IsValidDisconnectPacket(const CBuffer &, CCallsign *, char *); bool IsValidDisconnectPacket(const CBuffer &, CCallsign *, char *);
bool IsValidDvHeaderPacket(const CIp &, const CBuffer &, CDvHeaderPacket **); bool IsValidDvHeaderPacket(const CIp &, const CBuffer &, CDvHeaderPacket **);
bool IsValidDvFramePacket(const CIp &, const CBuffer &, CDvFramePacket **); bool IsValidDvFramePacket(const CIp &, const CBuffer &, CDvFramePacket **);
// packet encoding helpers // packet encoding helpers
void EncodeConnectAckPacket(CBuffer *); void EncodeConnectAckPacket(CBuffer *);
void EncodeConnectNackPacket(CBuffer *); void EncodeConnectNackPacket(CBuffer *);
@ -93,27 +86,27 @@ protected:
void EncodeDvPacket(const CDvHeaderPacket &, const CDvFramePacket &, const CDvFramePacket &, const CDvFramePacket &, uint8, CBuffer *) const; void EncodeDvPacket(const CDvHeaderPacket &, const CDvFramePacket &, const CDvFramePacket &, const CDvFramePacket &, uint8, CBuffer *) const;
void EncodeDvLastPacket(const CDvHeaderPacket &, const CDvFramePacket &, const CDvFramePacket &, const CDvFramePacket &, uint8, CBuffer *) const; void EncodeDvLastPacket(const CDvHeaderPacket &, const CDvFramePacket &, const CDvFramePacket &, const CDvFramePacket &, uint8, CBuffer *) const;
void SwapEndianess(uint8 *, int) const; void SwapEndianess(uint8 *, int) const;
// dmr SeqId helper // dmr SeqId helper
uint8 GetNextSeqId(uint8) const; uint8 GetNextSeqId(uint8) const;
// dmr DstId to Module helper // dmr DstId to Module helper
char DmrDstIdToModule(uint32) const; char DmrDstIdToModule(uint32) const;
uint32 ModuleToDmrDestId(char) const; uint32 ModuleToDmrDestId(char) const;
// uiStreamId helpers // uiStreamId helpers
uint32 IpToStreamId(const CIp &) const; uint32 IpToStreamId(const CIp &) const;
// Buffer & LC helpers // Buffer & LC helpers
void AppendVoiceLCToBuffer(CBuffer *, uint32) const; void AppendVoiceLCToBuffer(CBuffer *, uint32) const;
void AppendTerminatorLCToBuffer(CBuffer *, uint32) const; void AppendTerminatorLCToBuffer(CBuffer *, uint32) const;
void ReplaceEMBInBuffer(CBuffer *, uint8) const; void ReplaceEMBInBuffer(CBuffer *, uint8) const;
protected: protected:
// for keep alive // for keep alive
CTimePoint m_LastKeepaliveTime; CTimePoint m_LastKeepaliveTime;
// for queue header caches // for queue header caches
std::array<CDmrplusStreamCacheItem, NB_OF_MODULES> m_StreamsCache; std::array<CDmrplusStreamCacheItem, NB_OF_MODULES> m_StreamsCache;
}; };

@ -36,26 +36,15 @@
bool CDplusProtocol::Init(void) bool CDplusProtocol::Init(void)
{ {
bool ok;
// base class // base class
ok = CProtocol::Init(); if (Initialize("REF", DPLUS_PORT))
return false;
// update the reflector callsign
m_ReflectorCallsign.PatchCallsign(0, (const uint8 *)"REF", 3);
// create our socket
ok &= m_Socket.Open(DPLUS_PORT);
if ( !ok )
{
std::cout << "Error opening socket on port UDP" << DPLUS_PORT << " on ip " << g_Reflector.GetListenIp() << std::endl;
}
// update time // update time
m_LastKeepaliveTime.Now(); m_LastKeepaliveTime.Now();
// done // done
return ok; return true;
} }
@ -73,7 +62,7 @@ void CDplusProtocol::Task(void)
CDvLastFramePacket *LastFrame; CDvLastFramePacket *LastFrame;
// handle incoming packets // handle incoming packets
if ( m_Socket.Receive(Buffer, Ip, 20) ) if ( m_Socket6.Receive(Buffer, Ip, 10) && m_Socket4.Receive(Buffer, Ip, 10) )
{ {
// crack the packet // crack the packet
if ( (Frame = IsValidDvFramePacket(Buffer)) != NULL ) if ( (Frame = IsValidDvFramePacket(Buffer)) != NULL )
@ -110,7 +99,7 @@ void CDplusProtocol::Task(void)
std::cout << "DPlus connect request packet from " << Ip << std::endl; std::cout << "DPlus connect request packet from " << Ip << std::endl;
// acknowledge the request // acknowledge the request
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
} }
else if ( IsValidLoginPacket(Buffer, &Callsign) ) else if ( IsValidLoginPacket(Buffer, &Callsign) )
{ {
@ -121,7 +110,7 @@ void CDplusProtocol::Task(void)
{ {
// acknowledge the request // acknowledge the request
EncodeLoginAckPacket(&Buffer); EncodeLoginAckPacket(&Buffer);
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
// create the client // create the client
CDplusClient *client = new CDplusClient(Callsign, Ip); CDplusClient *client = new CDplusClient(Callsign, Ip);
@ -134,7 +123,7 @@ void CDplusProtocol::Task(void)
{ {
// deny the request // deny the request
EncodeLoginNackPacket(&Buffer); EncodeLoginNackPacket(&Buffer);
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
} }
} }
@ -151,7 +140,7 @@ void CDplusProtocol::Task(void)
clients->RemoveClient(client); clients->RemoveClient(client);
// and acknowledge the disconnect // and acknowledge the disconnect
EncodeDisconnectPacket(&Buffer); EncodeDisconnectPacket(&Buffer);
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
} }
g_Reflector.ReleaseClients(); g_Reflector.ReleaseClients();
} }
@ -313,7 +302,7 @@ void CDplusProtocol::HandleQueue(void)
else if ( packet->IsDvFrame() ) else if ( packet->IsDvFrame() )
{ {
// and send the DV frame // and send the DV frame
m_Socket.Send(buffer, client->GetIp()); Send(buffer, client->GetIp());
// is it time to insert a DVheader copy ? // is it time to insert a DVheader copy ?
if ( (m_StreamsCache[iModId].m_iSeqCounter++ % 21) == 20 ) if ( (m_StreamsCache[iModId].m_iSeqCounter++ % 21) == 20 )
@ -327,7 +316,7 @@ void CDplusProtocol::HandleQueue(void)
else else
{ {
// otherwise, send the original packet // otherwise, send the original packet
m_Socket.Send(buffer, client->GetIp()); Send(buffer, client->GetIp());
} }
} }
} }
@ -360,20 +349,20 @@ void CDplusProtocol::SendDvHeader(CDvHeaderPacket *packet, CDplusClient *client)
if ( EncodeDvPacket(packet2, &buffer2) ) if ( EncodeDvPacket(packet2, &buffer2) )
{ {
// and send it // and send it
m_Socket.Send(buffer2, client->GetIp()); Send(buffer2, client->GetIp());
} }
// client type known ? // client type known ?
if ( !client->HasModule() ) if ( !client->HasModule() )
{ {
// no, send also the genuine packet // no, send also the genuine packet
m_Socket.Send(buffer, client->GetIp()); Send(buffer, client->GetIp());
} }
} }
else else
{ {
// otherwise, send the original packet // otherwise, send the original packet
m_Socket.Send(buffer, client->GetIp()); Send(buffer, client->GetIp());
} }
} }
} }
@ -395,7 +384,7 @@ void CDplusProtocol::HandleKeepalives(void)
{ {
// send keepalive // send keepalive
//std::cout << "Sending DPlus packet @ " << client->GetIp() << std::endl; //std::cout << "Sending DPlus packet @ " << client->GetIp() << std::endl;
m_Socket.Send(keepalive, client->GetIp()); Send(keepalive, client->GetIp());
// is this client busy ? // is this client busy ?
if ( client->IsAMaster() ) if ( client->IsAMaster() )
@ -409,7 +398,7 @@ void CDplusProtocol::HandleKeepalives(void)
// no, disconnect // no, disconnect
CBuffer disconnect; CBuffer disconnect;
EncodeDisconnectPacket(&disconnect); EncodeDisconnectPacket(&disconnect);
m_Socket.Send(disconnect, client->GetIp()); Send(disconnect, client->GetIp());
// and remove it // and remove it
std::cout << "DPlus client " << client->GetCallsign() << " keepalive timeout" << std::endl; std::cout << "DPlus client " << client->GetCallsign() << " keepalive timeout" << std::endl;

@ -19,7 +19,7 @@
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>. // along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#ifndef cdplusprotocol_h #ifndef cdplusprotocol_h
@ -43,8 +43,7 @@ class CDPlusStreamCacheItem
{ {
public: public:
CDPlusStreamCacheItem() { m_iSeqCounter = 0; } CDPlusStreamCacheItem() { m_iSeqCounter = 0; }
~CDPlusStreamCacheItem() {}
CDvHeaderPacket m_dvHeader; CDvHeaderPacket m_dvHeader;
uint8 m_iSeqCounter; uint8 m_iSeqCounter;
}; };
@ -52,12 +51,6 @@ public:
class CDplusProtocol : public CProtocol class CDplusProtocol : public CProtocol
{ {
public: public:
// constructor
CDplusProtocol() {};
// destructor
virtual ~CDplusProtocol() {};
// initialization // initialization
bool Init(void); bool Init(void);
@ -68,13 +61,13 @@ protected:
// queue helper // queue helper
void HandleQueue(void); void HandleQueue(void);
void SendDvHeader(CDvHeaderPacket *, CDplusClient *); void SendDvHeader(CDvHeaderPacket *, CDplusClient *);
// keepalive helpers // keepalive helpers
void HandleKeepalives(void); void HandleKeepalives(void);
// stream helpers // stream helpers
bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &); bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &);
// packet decoding helpers // packet decoding helpers
bool IsValidConnectPacket(const CBuffer &); bool IsValidConnectPacket(const CBuffer &);
bool IsValidLoginPacket(const CBuffer &, CCallsign *); bool IsValidLoginPacket(const CBuffer &, CCallsign *);
@ -83,7 +76,7 @@ protected:
CDvHeaderPacket *IsValidDvHeaderPacket(const CBuffer &); CDvHeaderPacket *IsValidDvHeaderPacket(const CBuffer &);
CDvFramePacket *IsValidDvFramePacket(const CBuffer &); CDvFramePacket *IsValidDvFramePacket(const CBuffer &);
CDvLastFramePacket *IsValidDvLastFramePacket(const CBuffer &); CDvLastFramePacket *IsValidDvLastFramePacket(const CBuffer &);
// packet encoding helpers // packet encoding helpers
void EncodeKeepAlivePacket(CBuffer *); void EncodeKeepAlivePacket(CBuffer *);
void EncodeLoginAckPacket(CBuffer *); void EncodeLoginAckPacket(CBuffer *);
@ -93,11 +86,11 @@ protected:
bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const; bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const;
bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const; bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const;
protected: protected:
// for keep alive // for keep alive
CTimePoint m_LastKeepaliveTime; CTimePoint m_LastKeepaliveTime;
// for queue header caches // for queue header caches
std::array<CDPlusStreamCacheItem, NB_OF_MODULES> m_StreamsCache; std::array<CDPlusStreamCacheItem, NB_OF_MODULES> m_StreamsCache;
}; };

@ -40,55 +40,58 @@
bool CG3Protocol::Init(void) bool CG3Protocol::Init(void)
{ {
bool ok;
ReadOptions(); ReadOptions();
// base class // init reflector apparent callsign
ok = CProtocol::Init(); m_ReflectorCallsign = g_Reflector.GetCallsign();
// update reflector callsign // reset stop flag
m_ReflectorCallsign.PatchCallsign(0, (const uint8 *)"XLX", 3); m_bStopThread = false;
// create our DV socket // update the reflector callsign
ok &= m_Socket.Open(G3_DV_PORT); m_ReflectorCallsign.PatchCallsign(0, (const uint8 *)"XLX", 3);
if ( !ok )
{ // create our sockets
std::cout << "Error opening socket on port UDP" << G3_DV_PORT << " on ip " << g_Reflector.GetListenIp() << std::endl; CIp ip(AF_INET, G3_DV_PORT, g_Reflector.GetListenIPv4());
} if ( ip.IsSet() )
{
//create helper sockets if (! m_Socket4.Open(ip))
ok &= m_PresenceSocket.Open(G3_PRESENCE_PORT); return false;
if ( !ok ) }
{ else
std::cout << "Error opening socket on port UDP" << G3_PRESENCE_PORT << " on ip " << g_Reflector.GetListenIp() << std::endl; return false;
//create helper socket
ip.SetPort(G3_PRESENCE_PORT);
if (! m_PresenceSocket.Open(ip)) {
std::cout << "Error opening socket on port UDP" << G3_PRESENCE_PORT << " on ip " << ip << std::endl;
return false;
} }
ok &= m_ConfigSocket.Open(G3_CONFIG_PORT); ip.SetPort(G3_CONFIG_PORT);
if ( !ok ) if (! m_ConfigSocket.Open(ip))
{ {
std::cout << "Error opening socket on port UDP" << G3_CONFIG_PORT << " on ip " << g_Reflector.GetListenIp() << std::endl; std::cout << "Error opening G3 config socket on port UDP" << G3_CONFIG_PORT << " on ip " << ip << std::endl;
} return false;
}
ok &= m_IcmpRawSocket.Open(IPPROTO_ICMP); if (! m_IcmpRawSocket.Open(IPPROTO_ICMP))
if ( !ok )
{ {
std::cout << "Error opening raw socket for ICMP" << std::endl; std::cout << "Error opening raw socket for ICMP" << std::endl;
return false;
} }
if (ok) // start helper threads
{ m_pThread = new std::thread(CProtocol::Thread, this);
// start helper threads m_pPresenceThread = new std::thread(PresenceThread, this);
m_pPresenceThread = new std::thread(PresenceThread, this); m_pPresenceThread = new std::thread(ConfigThread, this);
m_pPresenceThread = new std::thread(ConfigThread, this); m_pPresenceThread = new std::thread(IcmpThread, this);
m_pPresenceThread = new std::thread(IcmpThread, this);
}
// update time // update time
m_LastKeepaliveTime.Now(); m_LastKeepaliveTime.Now();
// done // done
return ok; return true;
} }
void CG3Protocol::Close(void) void CG3Protocol::Close(void)
@ -390,7 +393,7 @@ void CG3Protocol::Task(void)
CDvLastFramePacket *LastFrame; CDvLastFramePacket *LastFrame;
// any incoming packet ? // any incoming packet ?
if ( m_Socket.Receive(Buffer, Ip, 20) != -1 ) if ( m_Socket4.Receive(Buffer, Ip, 20) )
{ {
CIp ClIp; CIp ClIp;
CIp *BaseIp = NULL; CIp *BaseIp = NULL;
@ -508,7 +511,7 @@ void CG3Protocol::HandleQueue(void)
int n = packet->IsDvHeader() ? 5 : 1; int n = packet->IsDvHeader() ? 5 : 1;
for ( int i = 0; i < n; i++ ) for ( int i = 0; i < n; i++ )
{ {
m_Socket.Send(buffer, client->GetIp()); Send(buffer, client->GetIp());
} }
} }
} }
@ -544,7 +547,7 @@ void CG3Protocol::HandleKeepalives(void)
else else
{ {
// send keepalive packet // send keepalive packet
m_Socket.Send(keepalive, client->GetIp()); Send(keepalive, client->GetIp());
} }
} }
g_Reflector.ReleaseClients(); g_Reflector.ReleaseClients();

@ -19,7 +19,7 @@
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>. // along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#ifndef cg3protocol_h #ifndef cg3protocol_h
@ -64,17 +64,14 @@ class CG3Protocol : public CProtocol
{ {
public: public:
// constructor // constructor
CG3Protocol() : m_GwAddress(0u), m_Modules("*"), m_LastModTime(0) {}; CG3Protocol() : m_GwAddress(0u), m_Modules("*"), m_LastModTime(0) {}
// destructor
virtual ~CG3Protocol() {};
// initialization // initialization
bool Init(void); bool Init(void);
// close // close
void Close(void); void Close(void);
// task // task
void Task(void); void Task(void);

@ -22,14 +22,19 @@
#include <netdb.h> #include <netdb.h>
#include "cip.h" #include "cip.h"
CIp::CIp() CIp::CIp() : is_set(false)
{ {
Clear(); Clear();
} }
CIp::CIp(const char *address, int family, int type, uint16_t port) CIp::CIp(const char *address, int family, int type, uint16_t port) : is_set(true)
{ {
Clear(); Clear();
if (0 == strncasecmp(address, "none", 4))
{
is_set = false;
return;
}
struct addrinfo hints, *result; struct addrinfo hints, *result;
bzero(&hints, sizeof(struct addrinfo)); bzero(&hints, sizeof(struct addrinfo));
hints.ai_family = family; hints.ai_family = family;
@ -41,7 +46,7 @@ CIp::CIp(const char *address, int family, int type, uint16_t port)
} }
SetPort(port); SetPort(port);
} }
CIp::CIp(const int family, const uint16_t port, const char *address) CIp::CIp(const int family, const uint16_t port, const char *address) : is_set(true)
{ {
Initialize(family, port, address); Initialize(family, port, address);
} }
@ -49,50 +54,68 @@ CIp::CIp(const int family, const uint16_t port, const char *address)
void CIp::Initialize(const int family, const uint16_t port, const char *address) void CIp::Initialize(const int family, const uint16_t port, const char *address)
{ {
Clear(); Clear();
if (0 == strncasecmp(address, "none", 4))
{
is_set = false;
return;
}
is_set = true;
addr.ss_family = family; addr.ss_family = family;
if (AF_INET == family) { if (AF_INET == family)
{
auto addr4 = (struct sockaddr_in *)&addr; auto addr4 = (struct sockaddr_in *)&addr;
addr4->sin_port = htons(port); addr4->sin_port = htons(port);
if (address) { if (address)
{
if (0 == strncasecmp(address, "loc", 3)) if (0 == strncasecmp(address, "loc", 3))
inet_pton(AF_INET, "127.0.0.1", &(addr4->sin_addr)); inet_pton(AF_INET, "127.0.0.1", &(addr4->sin_addr));
else if (0 == strncasecmp(address, "any", 3)) else if (0 == strncasecmp(address, "any", 3))
inet_pton(AF_INET, "0.0.0.0", &(addr4->sin_addr)); inet_pton(AF_INET, "0.0.0.0", &(addr4->sin_addr));
else if (0 == strncasecmp(address, "none", 4)) else
addr.ss_family = AF_UNSPEC; {
else {
if (1 > inet_pton(AF_INET, address, &(addr4->sin_addr))) if (1 > inet_pton(AF_INET, address, &(addr4->sin_addr)))
std::cerr << "Address Initialization Error: '" << address << "' is not a valdid IPV4 address!" << std::endl; std::cerr << "Address Initialization Error: '" << address << "' is not a valdid IPV4 address!" << std::endl;
is_set = false;
} }
} }
} else if (AF_INET6 == family) { }
else if (AF_INET6 == family)
{
auto addr6 = (struct sockaddr_in6 *)&addr; auto addr6 = (struct sockaddr_in6 *)&addr;
addr6->sin6_port = htons(port); addr6->sin6_port = htons(port);
if (address) { if (address)
{
if (0 == strncasecmp(address, "loc", 3)) if (0 == strncasecmp(address, "loc", 3))
inet_pton(AF_INET6, "::1", &(addr6->sin6_addr)); inet_pton(AF_INET6, "::1", &(addr6->sin6_addr));
else if (0 == strncasecmp(address, "any", 3)) else if (0 == strncasecmp(address, "any", 3))
inet_pton(AF_INET6, "::", &(addr6->sin6_addr)); inet_pton(AF_INET6, "::", &(addr6->sin6_addr));
else if (0 == strncasecmp(address, "none", 4)) else
addr.ss_family = AF_UNSPEC; {
else {
if (1 > inet_pton(AF_INET6, address, &(addr6->sin6_addr))) if (1 > inet_pton(AF_INET6, address, &(addr6->sin6_addr)))
std::cerr << "Address Initialization Error: '" << address << "' is not a valid IPV6 address!" << std::endl; std::cerr << "Address Initialization Error: '" << address << "' is not a valid IPV6 address!" << std::endl;
is_set = false;
} }
} }
} else }
else
{
std::cerr << "Error: Wrong address family type:" << family << " for [" << (address ? address : "NULL") << "]:" << port << std::endl; std::cerr << "Error: Wrong address family type:" << family << " for [" << (address ? address : "NULL") << "]:" << port << std::endl;
is_set = false;
}
} }
bool CIp::operator==(const CIp &rhs) const // doesn't compare ports, only addresses and families bool CIp::operator==(const CIp &rhs) const // doesn't compare ports, only addresses and families
{ {
if (addr.ss_family != rhs.addr.ss_family) if (addr.ss_family != rhs.addr.ss_family)
return false; return false;
if (AF_INET == addr.ss_family) { if (AF_INET == addr.ss_family)
{
auto l = (struct sockaddr_in *)&addr; auto l = (struct sockaddr_in *)&addr;
auto r = (struct sockaddr_in *)&rhs.addr; auto r = (struct sockaddr_in *)&rhs.addr;
return (l->sin_addr.s_addr == r->sin_addr.s_addr); return (l->sin_addr.s_addr == r->sin_addr.s_addr);
} else if (AF_INET6 == addr.ss_family) { }
else if (AF_INET6 == addr.ss_family)
{
auto l = (struct sockaddr_in6 *)&addr; auto l = (struct sockaddr_in6 *)&addr;
auto r = (struct sockaddr_in6 *)&rhs.addr; auto r = (struct sockaddr_in6 *)&rhs.addr;
return (0 == memcmp(&(l->sin6_addr), &(r->sin6_addr), sizeof(struct in6_addr))); return (0 == memcmp(&(l->sin6_addr), &(r->sin6_addr), sizeof(struct in6_addr)));
@ -104,11 +127,14 @@ bool CIp::operator!=(const CIp &rhs) const // doesn't compare ports, only addres
{ {
if (addr.ss_family != rhs.addr.ss_family) if (addr.ss_family != rhs.addr.ss_family)
return true; return true;
if (AF_INET == addr.ss_family) { if (AF_INET == addr.ss_family)
{
auto l = (struct sockaddr_in *)&addr; auto l = (struct sockaddr_in *)&addr;
auto r = (struct sockaddr_in *)&rhs.addr; auto r = (struct sockaddr_in *)&rhs.addr;
return (l->sin_addr.s_addr != r->sin_addr.s_addr); return (l->sin_addr.s_addr != r->sin_addr.s_addr);
} else if (AF_INET6 == addr.ss_family) { }
else if (AF_INET6 == addr.ss_family)
{
auto l = (struct sockaddr_in6 *)&addr; auto l = (struct sockaddr_in6 *)&addr;
auto r = (struct sockaddr_in6 *)&rhs.addr; auto r = (struct sockaddr_in6 *)&rhs.addr;
return (0 != memcmp(&(l->sin6_addr), &(r->sin6_addr), sizeof(struct in6_addr))); return (0 != memcmp(&(l->sin6_addr), &(r->sin6_addr), sizeof(struct in6_addr)));
@ -118,12 +144,16 @@ bool CIp::operator!=(const CIp &rhs) const // doesn't compare ports, only addres
bool CIp::AddressIsZero() const bool CIp::AddressIsZero() const
{ {
if (AF_INET == addr.ss_family) { if (AF_INET == addr.ss_family)
auto addr4 = (struct sockaddr_in *)&addr; {
auto addr4 = (struct sockaddr_in *)&addr;
return (addr4->sin_addr.s_addr == 0U); return (addr4->sin_addr.s_addr == 0U);
} else { }
else
{
auto addr6 = (struct sockaddr_in6 *)&addr; auto addr6 = (struct sockaddr_in6 *)&addr;
for (unsigned int i=0; i<16; i++) { for (unsigned int i=0; i<16; i++)
{
if (addr6->sin6_addr.s6_addr[i]) if (addr6->sin6_addr.s6_addr[i])
return false; return false;
} }
@ -133,11 +163,14 @@ bool CIp::AddressIsZero() const
void CIp::ClearAddress() void CIp::ClearAddress()
{ {
if (AF_INET == addr.ss_family) { if (AF_INET == addr.ss_family)
{
auto addr4 = (struct sockaddr_in *)&addr; auto addr4 = (struct sockaddr_in *)&addr;
addr4->sin_addr.s_addr = 0U; addr4->sin_addr.s_addr = 0U;
strcpy(straddr, "0.0.0.0"); strcpy(straddr, "0.0.0.0");
} else { }
else
{
auto addr6 = (struct sockaddr_in6 *)&addr; auto addr6 = (struct sockaddr_in6 *)&addr;
memset(&(addr6->sin6_addr.s6_addr), 0, 16); memset(&(addr6->sin6_addr.s6_addr), 0, 16);
strcpy(straddr, "::"); strcpy(straddr, "::");
@ -149,13 +182,18 @@ const char *CIp::GetAddress() const
if (straddr[0]) if (straddr[0])
return straddr; return straddr;
if (AF_INET == addr.ss_family) { if (AF_INET == addr.ss_family)
{
auto addr4 = (struct sockaddr_in *)&addr; auto addr4 = (struct sockaddr_in *)&addr;
inet_ntop(AF_INET, &(addr4->sin_addr), straddr, INET6_ADDRSTRLEN); inet_ntop(AF_INET, &(addr4->sin_addr), straddr, INET6_ADDRSTRLEN);
} else if (AF_INET6 == addr.ss_family) { }
else if (AF_INET6 == addr.ss_family)
{
auto addr6 = (struct sockaddr_in6 *)&addr; auto addr6 = (struct sockaddr_in6 *)&addr;
inet_ntop(AF_INET6, &(addr6->sin6_addr), straddr, INET6_ADDRSTRLEN); inet_ntop(AF_INET6, &(addr6->sin6_addr), straddr, INET6_ADDRSTRLEN);
} else { }
else
{
std::cerr << "CIp::GetAddress: unknown socket family=" << addr.ss_family << std::endl; std::cerr << "CIp::GetAddress: unknown socket family=" << addr.ss_family << std::endl;
} }
return straddr; return straddr;
@ -176,12 +214,15 @@ std::ostream &operator<<(std::ostream &stream, const CIp &Ip)
uint32_t CIp::GetAddr() const uint32_t CIp::GetAddr() const
{ {
if (AF_INET6 == addr.ss_family) { if (AF_INET6 == addr.ss_family)
{
auto addr6 = (struct sockaddr_in6 *)&addr; auto addr6 = (struct sockaddr_in6 *)&addr;
// hash the results // hash the results
auto *a = (const uint32_t *)&(addr6->sin6_addr.s6_addr); auto *a = (const uint32_t *)&(addr6->sin6_addr.s6_addr);
return a[0] ^ a[1] ^ a[2] ^ a[3]; return a[0] ^ a[1] ^ a[2] ^ a[3];
} else { }
else
{
auto addr4 = (struct sockaddr_in *)&addr; auto addr4 = (struct sockaddr_in *)&addr;
return addr4->sin_addr.s_addr; return addr4->sin_addr.s_addr;
} }
@ -194,10 +235,13 @@ int CIp::GetFamily() const
uint16_t CIp::GetPort() const uint16_t CIp::GetPort() const
{ {
if (AF_INET == addr.ss_family) { if (AF_INET == addr.ss_family)
{
auto addr4 = (struct sockaddr_in *)&addr; auto addr4 = (struct sockaddr_in *)&addr;
return ntohs(addr4->sin_port); return ntohs(addr4->sin_port);
} else if (AF_INET6 == addr.ss_family) { }
else if (AF_INET6 == addr.ss_family)
{
auto addr6 = (struct sockaddr_in6 *)&addr; auto addr6 = (struct sockaddr_in6 *)&addr;
return ntohs(addr6->sin6_port); return ntohs(addr6->sin6_port);
} else } else
@ -206,10 +250,13 @@ uint16_t CIp::GetPort() const
void CIp::SetPort(const uint16_t newport) void CIp::SetPort(const uint16_t newport)
{ {
if (AF_INET == addr.ss_family) { if (AF_INET == addr.ss_family)
{
auto addr4 = (struct sockaddr_in *)&addr; auto addr4 = (struct sockaddr_in *)&addr;
addr4->sin_port = htons(newport); addr4->sin_port = htons(newport);
} else if (AF_INET6 == addr.ss_family) { }
else if (AF_INET6 == addr.ss_family)
{
auto addr6 = (struct sockaddr_in6 *)&addr; auto addr6 = (struct sockaddr_in6 *)&addr;
addr6->sin6_port = htons(newport); addr6->sin6_port = htons(newport);
} }
@ -238,4 +285,5 @@ void CIp::Clear()
{ {
memset(&addr, 0, sizeof(struct sockaddr_storage)); memset(&addr, 0, sizeof(struct sockaddr_storage));
memset(straddr, 0, INET6_ADDRSTRLEN); memset(straddr, 0, INET6_ADDRSTRLEN);
is_set = false;
} }

@ -46,6 +46,7 @@ public:
bool operator!=(const CIp &rhs) const; bool operator!=(const CIp &rhs) const;
// state methods // state methods
bool IsSet() const { return is_set; }
bool AddressIsZero() const; bool AddressIsZero() const;
void ClearAddress(); void ClearAddress();
const char *GetAddress() const; const char *GetAddress() const;
@ -68,6 +69,7 @@ public:
private: private:
struct sockaddr_storage addr; struct sockaddr_storage addr;
mutable char straddr[INET6_ADDRSTRLEN]; mutable char straddr[INET6_ADDRSTRLEN];
bool is_set;
}; };
std::ostream &operator<<(std::ostream &stream, const CIp &Ip); std::ostream &operator<<(std::ostream &stream, const CIp &Ip);

@ -33,11 +33,7 @@
// constructor // constructor
CProtocol::CProtocol() CProtocol::CProtocol() : m_bStopThread(false), m_pThread(NULL) {}
{
m_bStopThread = false;
m_pThread = NULL;
}
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -53,6 +49,10 @@ CProtocol::~CProtocol()
delete m_pThread; delete m_pThread;
} }
// Close sockets
m_Socket6.Close();
m_Socket4.Close();
// empty queue // empty queue
m_Queue.Lock(); m_Queue.Lock();
while ( !m_Queue.empty() ) while ( !m_Queue.empty() )
@ -65,7 +65,7 @@ CProtocol::~CProtocol()
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// initialization // initialization
bool CProtocol::Init(void) bool CProtocol::Initialize(const char *type, uint16 port)
{ {
// init reflector apparent callsign // init reflector apparent callsign
m_ReflectorCallsign = g_Reflector.GetCallsign(); m_ReflectorCallsign = g_Reflector.GetCallsign();
@ -73,13 +73,49 @@ bool CProtocol::Init(void)
// reset stop flag // reset stop flag
m_bStopThread = false; m_bStopThread = false;
// update the reflector callsign
if (type)
m_ReflectorCallsign.PatchCallsign(0, (const uint8 *)type, 3);
// create our sockets
CIp ip4(AF_INET, port, g_Reflector.GetListenIPv4());
if ( ip4.IsSet() )
{
if (! m_Socket4.Open(ip4))
return false;
}
CIp ip6(AF_INET6, port, g_Reflector.GetListenIPv6());
if ( ip6.IsSet() )
{
if (! m_Socket6.Open(ip6))
{
m_Socket4.Close();
return false;
}
}
// start thread; // start thread;
m_pThread = new std::thread(CProtocol::Thread, this); m_pThread = new std::thread(CProtocol::Thread, this);
if (m_pThread == NULL)
{
std::cerr << "Could not start DCS thread!" << std::endl;
m_Socket4.Close();
m_Socket6.Close();
return false;
}
// done // done
return true; return true;
} }
void CProtocol::Thread(CProtocol *This)
{
while (! This->m_bStopThread)
{
This->Task();
}
}
void CProtocol::Close(void) void CProtocol::Close(void)
{ {
m_bStopThread = true; m_bStopThread = true;
@ -89,18 +125,8 @@ void CProtocol::Close(void)
delete m_pThread; delete m_pThread;
m_pThread = NULL; m_pThread = NULL;
} }
} m_Socket4.Close();
m_Socket6.Close();
////////////////////////////////////////////////////////////////////////////////////////
// thread
void CProtocol::Thread(CProtocol *This)
{
while ( !This->m_bStopThread )
{
This->Task();
}
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -263,3 +289,66 @@ uint32 CProtocol::ModuleToDmrDestId(char m) const
{ {
return (uint32)(m - 'A')+1; return (uint32)(m - 'A')+1;
} }
////////////////////////////////////////////////////////////////////////////////////////
// dual stack senders
void CProtocol::Send(const CBuffer &buf, const CIp &Ip) const
{
switch (Ip.GetFamily()) {
case AF_INET:
m_Socket4.Send(buf, Ip);
break;
case AF_INET6:
m_Socket6.Send(buf, Ip);
break;
default:
std::cerr << "Wrong family: " << Ip.GetFamily() << std::endl;
break;
}
}
void CProtocol::Send(const char *buf, const CIp &Ip) const
{
switch (Ip.GetFamily()) {
case AF_INET:
m_Socket4.Send(buf, Ip);
break;
case AF_INET6:
m_Socket6.Send(buf, Ip);
break;
default:
std::cerr << "ERROR: wrong family: " << Ip.GetFamily() << std::endl;
break;
}
}
void CProtocol::Send(const CBuffer &buf, const CIp &Ip, uint16_t port) const
{
switch (Ip.GetFamily()) {
case AF_INET:
m_Socket4.Send(buf, Ip, port);
break;
case AF_INET6:
m_Socket6.Send(buf, Ip, port);
break;
default:
std::cerr << "Wrong family: " << Ip.GetFamily() << " on port " << port << std::endl;
break;
}
}
void CProtocol::Send(const char *buf, const CIp &Ip, uint16_t port) const
{
switch (Ip.GetFamily()) {
case AF_INET:
m_Socket4.Send(buf, Ip, port);
break;
case AF_INET6:
m_Socket6.Send(buf, Ip, port);
break;
default:
std::cerr << "Wrong family: " << Ip.GetFamily() << " on port " << port << std::endl;
break;
}
}

@ -77,7 +77,7 @@ public:
virtual ~CProtocol(); virtual ~CProtocol();
// initialization // initialization
virtual bool Init(void); bool Initialize(const char *, uint16);
virtual void Close(void); virtual void Close(void);
// queue // queue
@ -89,7 +89,7 @@ public:
// task // task
static void Thread(CProtocol *); static void Thread(CProtocol *);
virtual void Task(void) {} virtual void Task(void) = 0;
protected: protected:
// packet encoding helpers // packet encoding helpers
@ -122,9 +122,13 @@ protected:
virtual char DmrDstIdToModule(uint32) const; virtual char DmrDstIdToModule(uint32) const;
virtual uint32 ModuleToDmrDestId(char) const; virtual uint32 ModuleToDmrDestId(char) const;
protected: void Send(const CBuffer &buf, const CIp &Ip) const;
void Send(const char *buf, const CIp &Ip) const;
void Send(const CBuffer &buf, const CIp &Ip, uint16 port) const;
void Send(const char *buf, const CIp &Ip, uint16 port) const;
// socket // socket
CUdpSocket m_Socket; CUdpSocket m_Socket4, m_Socket6;
// streams // streams
std::list<CPacketStream *> m_Streams; std::list<CPacketStream *> m_Streams;

@ -19,7 +19,7 @@
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>. // along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#include "main.h" #include "main.h"
@ -33,18 +33,6 @@
#include "cg3protocol.h" #include "cg3protocol.h"
#include "cprotocols.h" #include "cprotocols.h"
////////////////////////////////////////////////////////////////////////////////////////
// constructor
CProtocols::CProtocols()
{
for ( int i = 0; i < m_Protocols.size(); i++ )
{
m_Protocols[i] = NULL;
}
}
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// destructor // destructor
@ -52,10 +40,12 @@ CProtocols::~CProtocols()
{ {
m_Mutex.lock(); m_Mutex.lock();
{ {
for ( int i = 0; i < m_Protocols.size(); i++ ) for ( auto it=m_Protocols.begin(); it!=m_Protocols.end(); it++)
{ {
delete m_Protocols[i]; (*it)->Close();
} delete *it;
}
m_Protocols.clear();
} }
m_Mutex.unlock(); m_Mutex.unlock();
} }
@ -65,65 +55,105 @@ CProtocols::~CProtocols()
bool CProtocols::Init(void) bool CProtocols::Init(void)
{ {
bool ok = true;
m_Mutex.lock(); m_Mutex.lock();
{ {
// create and initialize DEXTRA auto dextra = new CDextraProtocol;
delete m_Protocols[0]; if (dextra->Init())
m_Protocols[0] = new CDextraProtocol; m_Protocols.push_back(dextra);
ok &= m_Protocols[0]->Init(); else
{
delete dextra;
return false;
}
// create and initialize DPLUS // create and initialize DPLUS
delete m_Protocols[1]; auto dplus = new CDplusProtocol;
m_Protocols[1] = new CDplusProtocol; if (dplus->Init())
ok &= m_Protocols[1]->Init(); m_Protocols.push_back(dplus);
else
{
delete dplus;
return false;
}
// create and initialize DCS // create and initialize DCS
delete m_Protocols[2]; auto dcs = new CDcsProtocol;
m_Protocols[2] = new CDcsProtocol; if (dcs->Init())
ok &= m_Protocols[2]->Init(); m_Protocols.push_back(dcs);
else
{
delete dcs;
return false;
}
// create and initialize XLX - interlink // create and initialize XLX - interlink
delete m_Protocols[3]; auto xlx = new CXlxProtocol;
m_Protocols[3] = new CXlxProtocol; if (xlx->Init())
ok &= m_Protocols[3]->Init(); m_Protocols.push_back(xlx);
else
{
delete xlx;
return false;
}
// create and initialize DMRPLUS // create and initialize DMRPLUS
delete m_Protocols[4]; auto dmrplus = new CDmrplusProtocol;
m_Protocols[4] = new CDmrplusProtocol; if (dmrplus->Init())
ok &= m_Protocols[4]->Init(); m_Protocols.push_back(dmrplus);
else
{
delete dmrplus;
return false;
}
// create and initialize DMRMMDVM // create and initialize DMRMMDVM
delete m_Protocols[5]; auto dmrmmdvm = new CDmrmmdvmProtocol;
m_Protocols[5] = new CDmrmmdvmProtocol; if (dmrmmdvm->Init())
ok &= m_Protocols[5]->Init(); m_Protocols.push_back(dmrmmdvm);
else
{
delete dmrmmdvm;
return false;
}
// create and initialize YSF // create and initialize YSF
delete m_Protocols[6]; auto ysf = new CYsfProtocol;
m_Protocols[6] = new CYsfProtocol; if (ysf->Init())
ok &= m_Protocols[6]->Init(); m_Protocols.push_back(ysf);
else
{
delete ysf;
return false;
}
// create and initialize G3 // create and initialize G3
delete m_Protocols[7]; auto g3 = new CG3Protocol;
m_Protocols[7] = new CG3Protocol; if (g3->Init())
ok &= m_Protocols[7]->Init(); m_Protocols.push_back(g3);
else
{
delete g3;
return true;
}
} }
m_Mutex.unlock(); m_Mutex.unlock();
// done // done
return ok; return true;
} }
void CProtocols::Close(void) void CProtocols::Close(void)
{ {
m_Mutex.lock(); m_Mutex.lock();
{ {
for ( int i = 0; i < m_Protocols.size(); i++ ) for ( auto it=m_Protocols.begin(); it!=m_Protocols.end(); it++)
{ {
m_Protocols[i]->Close(); (*it)->Close();
} delete *it;
}
m_Protocols.clear();
} }
m_Mutex.unlock(); m_Mutex.unlock();
} }

@ -19,7 +19,7 @@
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>. // along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#ifndef cprotocols_h #ifndef cprotocols_h
@ -38,24 +38,21 @@
class CProtocols class CProtocols
{ {
public: public:
// constructors
CProtocols();
// destructors // destructors
virtual ~CProtocols(); ~CProtocols();
// initialization // initialization
bool Init(void); bool Init(void);
void Close(void); void Close(void);
// get // pass-thru
int Size(void) const { return (int)m_Protocols.size(); } std::list<CProtocol *>::iterator begin() { return m_Protocols.begin(); }
CProtocol *GetProtocol(int i) { return m_Protocols[i]; } std::list<CProtocol *>::iterator end() { return m_Protocols.end(); }
protected: protected:
// data // data
std::mutex m_Mutex; std::mutex m_Mutex;
std::array<CProtocol *, NB_OF_PROTOCOLS> m_Protocols; std::list<CProtocol *> m_Protocols;
}; };

@ -348,27 +348,24 @@ void CReflector::RouterThread(CReflector *This, CPacketStream *streamIn)
packet->SetModuleId(uiModuleId); packet->SetModuleId(uiModuleId);
// iterate on all protocols // iterate on all protocols
for ( int i = 0; i < This->m_Protocols.Size(); i++ ) for ( auto it=This->m_Protocols.begin(); it!=This->m_Protocols.end(); it++ )
{ {
// duplicate packet // duplicate packet
CPacket *packetClone = packet->Duplicate(); CPacket *packetClone = packet->Duplicate();
// get protocol
CProtocol *protocol = This->m_Protocols.GetProtocol(i);
// if packet is header, update RPT2 according to protocol // if packet is header, update RPT2 according to protocol
if ( packetClone->IsDvHeader() ) if ( packetClone->IsDvHeader() )
{ {
// get our callsign // get our callsign
CCallsign csRPT = protocol->GetReflectorCallsign(); CCallsign csRPT = (*it)->GetReflectorCallsign();
csRPT.SetModule(This->GetStreamModule(streamIn)); csRPT.SetModule(This->GetStreamModule(streamIn));
((CDvHeaderPacket *)packetClone)->SetRpt2Callsign(csRPT); ((CDvHeaderPacket *)packetClone)->SetRpt2Callsign(csRPT);
} }
// and push it // and push it
CPacketQueue *queue = protocol->GetQueue(); CPacketQueue *queue = (*it)->GetQueue();
queue->push(packetClone); queue->push(packetClone);
protocol->ReleaseQueue(); (*it)->ReleaseQueue();
} }
// done // done
delete packet; delete packet;

@ -4,6 +4,7 @@
// //
// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015. // Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. // Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
// Copyright © 2020 Thomas A. Early, N7TAE
// //
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// This file is part of xlxd. // This file is part of xlxd.
@ -19,7 +20,7 @@
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>. // along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#ifndef creflector_h #ifndef creflector_h
@ -50,96 +51,99 @@ public:
// constructor // constructor
CReflector(); CReflector();
CReflector(const CCallsign &); CReflector(const CCallsign &);
// destructor // destructor
virtual ~CReflector(); virtual ~CReflector();
// settings // settings
void SetCallsign(const CCallsign &callsign) { m_Callsign = callsign; } void SetCallsign(const CCallsign &callsign) { m_Callsign = callsign; }
const CCallsign &GetCallsign(void) const { return m_Callsign; } const CCallsign &GetCallsign(void) const { return m_Callsign; }
void SetListenIp(const CIp &ip) { m_Ip = ip; } void SetListenIPv4(const char *a, const int n) { memset(m_IPv4, 0, n); strncpy(m_IPv4, a, n-1); }
void SetTranscoderIp(const CIp &ip) { m_AmbedIp = ip; } void SetListenIPv6(const char *a, const int n) { memset(m_IPv6, 0, n); strncpy(m_IPv6, a, n-1); }
const CIp &GetListenIp(void) const { return m_Ip; } void SetTranscoderIp(const char *a, const int n) { memset(m_AmbedIp, 0, n); strncpy(m_AmbedIp, a, n-1); }
const CIp &GetTranscoderIp(void) const { return m_AmbedIp; } const char *GetListenIPv4(void) const { return m_IPv4; }
const char *GetListenIPv6(void) const { return m_IPv6; }
const char *GetTranscoderIp(void) const { return m_AmbedIp; }
// operation // operation
bool Start(void); bool Start(void);
void Stop(void); void Stop(void);
// clients // clients
CClients *GetClients(void) { m_Clients.Lock(); return &m_Clients; } CClients *GetClients(void) { m_Clients.Lock(); return &m_Clients; }
void ReleaseClients(void) { m_Clients.Unlock(); } void ReleaseClients(void) { m_Clients.Unlock(); }
// peers // peers
CPeers *GetPeers(void) { m_Peers.Lock(); return &m_Peers; } CPeers *GetPeers(void) { m_Peers.Lock(); return &m_Peers; }
void ReleasePeers(void) { m_Peers.Unlock(); } void ReleasePeers(void) { m_Peers.Unlock(); }
// stream opening & closing // stream opening & closing
CPacketStream *OpenStream(CDvHeaderPacket *, CClient *); CPacketStream *OpenStream(CDvHeaderPacket *, CClient *);
bool IsStreaming(char); bool IsStreaming(char);
void CloseStream(CPacketStream *); void CloseStream(CPacketStream *);
// users // users
CUsers *GetUsers(void) { m_Users.Lock(); return &m_Users; } CUsers *GetUsers(void) { m_Users.Lock(); return &m_Users; }
void ReleaseUsers(void) { m_Users.Unlock(); } void ReleaseUsers(void) { m_Users.Unlock(); }
// get // get
bool IsValidModule(char c) const { return (GetModuleIndex(c) >= 0); } bool IsValidModule(char c) const { return (GetModuleIndex(c) >= 0); }
int GetModuleIndex(char) const; int GetModuleIndex(char) const;
char GetModuleLetter(int i) const { return 'A' + (char)i; } char GetModuleLetter(int i) const { return 'A' + (char)i; }
// notifications // notifications
void OnPeersChanged(void); void OnPeersChanged(void);
void OnClientsChanged(void); void OnClientsChanged(void);
void OnUsersChanged(void); void OnUsersChanged(void);
void OnStreamOpen(const CCallsign &); void OnStreamOpen(const CCallsign &);
void OnStreamClose(const CCallsign &); void OnStreamClose(const CCallsign &);
protected: protected:
// threads // threads
static void RouterThread(CReflector *, CPacketStream *); static void RouterThread(CReflector *, CPacketStream *);
static void XmlReportThread(CReflector *); static void XmlReportThread(CReflector *);
static void JsonReportThread(CReflector *); static void JsonReportThread(CReflector *);
// streams // streams
CPacketStream *GetStream(char); CPacketStream *GetStream(char);
bool IsStreamOpen(const CDvHeaderPacket *); bool IsStreamOpen(const CDvHeaderPacket *);
char GetStreamModule(CPacketStream *); char GetStreamModule(CPacketStream *);
// xml helpers // xml helpers
void WriteXmlFile(std::ofstream &); void WriteXmlFile(std::ofstream &);
// json helpers // json helpers
void SendJsonReflectorObject(CUdpSocket &, CIp &); void SendJsonReflectorObject(CUdpSocket &, CIp &);
void SendJsonNodesObject(CUdpSocket &, CIp &); void SendJsonNodesObject(CUdpSocket &, CIp &);
void SendJsonStationsObject(CUdpSocket &, CIp &); void SendJsonStationsObject(CUdpSocket &, CIp &);
void SendJsonOnairObject(CUdpSocket &, CIp &, const CCallsign &); void SendJsonOnairObject(CUdpSocket &, CIp &, const CCallsign &);
void SendJsonOffairObject(CUdpSocket &, CIp &, const CCallsign &); void SendJsonOffairObject(CUdpSocket &, CIp &, const CCallsign &);
protected: protected:
// identity // identity
CCallsign m_Callsign; CCallsign m_Callsign;
CIp m_Ip; char m_IPv4[INET_ADDRSTRLEN];
CIp m_AmbedIp; char m_IPv6[INET6_ADDRSTRLEN];
char m_AmbedIp[INET6_ADDRSTRLEN];
// objects // objects
CUsers m_Users; // sorted list of lastheard stations CUsers m_Users; // sorted list of lastheard stations
CClients m_Clients; // list of linked repeaters/nodes/peers's modules CClients m_Clients; // list of linked repeaters/nodes/peers's modules
CPeers m_Peers; // list of linked peers CPeers m_Peers; // list of linked peers
CProtocols m_Protocols; // list of supported protocol handlers CProtocols m_Protocols; // list of supported protocol handlers
// queues // queues
std::array<CPacketStream, NB_OF_MODULES> m_Streams; std::array<CPacketStream, NB_OF_MODULES> m_Streams;
// threads // threads
bool m_bStopThreads; bool m_bStopThreads;
std::array<std::thread *, NB_OF_MODULES> m_RouterThreads; std::array<std::thread *, NB_OF_MODULES> m_RouterThreads;
std::thread *m_XmlReportThread; std::thread *m_XmlReportThread;
std::thread *m_JsonReportThread; std::thread *m_JsonReportThread;
// notifications // notifications
CNotificationQueue m_Notifications; CNotificationQueue m_Notifications;
public: public:
#ifdef DEBUG_DUMPFILE #ifdef DEBUG_DUMPFILE
std::ofstream m_DebugFile; std::ofstream m_DebugFile;

@ -75,22 +75,27 @@ bool CTranscoder::Init(void)
m_bStopThread = false; m_bStopThread = false;
// create server's IP // create server's IP
m_Ip = g_Reflector.GetTranscoderIp(); auto s = g_Reflector.GetTranscoderIp();
m_Ip.Initialize(strchr(s, ':') ? AF_INET6 : AF_INET, TRANSCODER_PORT, s);
// create our socket // create our socket
ok = m_Socket.Open(TRANSCODER_PORT); if (m_Ip.IsSet())
if ( ok ) {
{ if (! m_Socket.Open(TRANSCODER_PORT)) {
// start thread; std::cerr << "Error opening socket on port UDP" << TRANSCODER_PORT << " on ip " << m_Ip << std::endl;
m_pThread = new std::thread(CTranscoder::Thread, this); return false;
} }
else }
{ else
std::cout << "Error opening socket on port UDP" << TRANSCODER_PORT << " on ip " << g_Reflector.GetListenIp() << std::endl; {
} std::cerr << "Could not initialize transcoder socket on " << m_Ip << std::endl;
return false;
// done }
return ok;
// start thread;
m_pThread = new std::thread(CTranscoder::Thread, this);
return true;
} }
void CTranscoder::Close(void) void CTranscoder::Close(void)

@ -28,12 +28,12 @@
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// open // open
bool CUdpMsgSocket::Open(uint16 uiPort) bool CUdpMsgSocket::Open(const CIp &ip)
{ {
bool ret; bool ret;
int on = 1; int on = 1;
ret = CUdpSocket::Open(uiPort); ret = CUdpSocket::Open(ip);
setsockopt(m_fd, IPPROTO_IP, IP_PKTINFO, (char *)&on, sizeof(on)); setsockopt(m_fd, IPPROTO_IP, IP_PKTINFO, (char *)&on, sizeof(on));
return ret; return ret;

@ -19,7 +19,7 @@
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>. // along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Description: // Description:
@ -40,7 +40,7 @@ class CUdpMsgSocket : public CUdpSocket
{ {
public: public:
// open // open
bool Open(uint16); bool Open(const CIp &ip);
// read // read
int Receive(CBuffer *, CIp *, int); int Receive(CBuffer *, CIp *, int);

@ -37,27 +37,15 @@
bool CXlxProtocol::Init(void) bool CXlxProtocol::Init(void)
{ {
bool ok; if (! Initialize("XLX", XLX_PORT))
return false;
// base class
ok = CProtocol::Init();
// update the reflector callsign
m_ReflectorCallsign.PatchCallsign(0, (const uint8 *)"XLX", 3);
// create our socket
ok &= m_Socket.Open(XLX_PORT);
if ( !ok )
{
std::cout << "Error opening socket on port UDP" << XLX_PORT << " on ip " << g_Reflector.GetListenIp() << std::endl;
}
// update time // update time
m_LastKeepaliveTime.Now(); m_LastKeepaliveTime.Now();
m_LastPeersLinkTime.Now(); m_LastPeersLinkTime.Now();
// done // done
return ok; return true;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -75,7 +63,7 @@ void CXlxProtocol::Task(void)
CDvLastFramePacket *LastFrame; CDvLastFramePacket *LastFrame;
// any incoming packet ? // any incoming packet ?
if ( m_Socket.Receive(Buffer, Ip, 20) ) if ( m_Socket4.Receive(Buffer, Ip, 10) || m_Socket6.Receive(Buffer, Ip, 10) )
{ {
// crack the packet // crack the packet
if ( (Frame = IsValidDvFramePacket(Buffer)) != NULL ) if ( (Frame = IsValidDvFramePacket(Buffer)) != NULL )
@ -130,7 +118,7 @@ void CXlxProtocol::Task(void)
{ {
// acknowledge the request // acknowledge the request
EncodeConnectAckPacket(&Buffer, Modules); EncodeConnectAckPacket(&Buffer, Modules);
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
} }
g_Reflector.ReleasePeers(); g_Reflector.ReleasePeers();
@ -141,7 +129,7 @@ void CXlxProtocol::Task(void)
default: default:
// acknowledge the request // acknowledge the request
EncodeConnectAckPacket(&Buffer, Modules); EncodeConnectAckPacket(&Buffer, Modules);
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
break; break;
} }
} }
@ -149,7 +137,7 @@ void CXlxProtocol::Task(void)
{ {
// deny the request // deny the request
EncodeConnectNackPacket(&Buffer); EncodeConnectNackPacket(&Buffer);
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
} }
} }
else if ( IsValidAckPacket(Buffer, &Callsign, Modules, &Version) ) else if ( IsValidAckPacket(Buffer, &Callsign, Modules, &Version) )
@ -284,17 +272,17 @@ void CXlxProtocol::HandleQueue(void)
{ {
case XLX_PROTOCOL_REVISION_0: case XLX_PROTOCOL_REVISION_0:
case XLX_PROTOCOL_REVISION_1: case XLX_PROTOCOL_REVISION_1:
m_Socket.Send(bufferLegacy, client->GetIp()); Send(bufferLegacy, client->GetIp());
break; break;
case XLX_PROTOCOL_REVISION_2: case XLX_PROTOCOL_REVISION_2:
default: default:
if ( g_Transcoder.IsConnected() ) if ( g_Transcoder.IsConnected() )
{ {
m_Socket.Send(buffer, client->GetIp()); Send(buffer, client->GetIp());
} }
else else
{ {
m_Socket.Send(bufferLegacy, client->GetIp()); Send(bufferLegacy, client->GetIp());
} }
break; break;
} }
@ -328,7 +316,7 @@ void CXlxProtocol::HandleKeepalives(void)
while ( (peer = peers->FindNextPeer(PROTOCOL_XLX, pit)) != NULL ) while ( (peer = peers->FindNextPeer(PROTOCOL_XLX, pit)) != NULL )
{ {
// send keepalive // send keepalive
m_Socket.Send(keepalive, peer->GetIp()); Send(keepalive, peer->GetIp());
// client busy ? // client busy ?
if ( peer->IsAMaster() ) if ( peer->IsAMaster() )
@ -342,7 +330,7 @@ void CXlxProtocol::HandleKeepalives(void)
// no, disconnect // no, disconnect
CBuffer disconnect; CBuffer disconnect;
EncodeDisconnectPacket(&disconnect); EncodeDisconnectPacket(&disconnect);
m_Socket.Send(disconnect, peer->GetIp()); Send(disconnect, peer->GetIp());
// remove it // remove it
std::cout << "XLX peer " << peer->GetCallsign() << " keepalive timeout" << std::endl; std::cout << "XLX peer " << peer->GetCallsign() << " keepalive timeout" << std::endl;
@ -373,7 +361,7 @@ void CXlxProtocol::HandlePeerLinks(void)
{ {
// send disconnect packet // send disconnect packet
EncodeDisconnectPacket(&buffer); EncodeDisconnectPacket(&buffer);
m_Socket.Send(buffer, peer->GetIp()); Send(buffer, peer->GetIp());
std::cout << "Sending disconnect packet to XLX peer " << peer->GetCallsign() << std::endl; std::cout << "Sending disconnect packet to XLX peer " << peer->GetCallsign() << std::endl;
// remove client // remove client
peers->RemovePeer(peer); peers->RemovePeer(peer);
@ -392,7 +380,7 @@ void CXlxProtocol::HandlePeerLinks(void)
(*it).ResolveIp(); (*it).ResolveIp();
// send connect packet to re-initiate peer link // send connect packet to re-initiate peer link
EncodeConnectPacket(&buffer, (*it).GetModules()); EncodeConnectPacket(&buffer, (*it).GetModules());
m_Socket.Send(buffer, (*it).GetIp(), XLX_PORT); Send(buffer, (*it).GetIp(), XLX_PORT);
std::cout << "Sending connect packet to XLX peer " << (*it).GetCallsign() << " @ " << (*it).GetIp() << " for modules " << (*it).GetModules() << std::endl; std::cout << "Sending connect packet to XLX peer " << (*it).GetCallsign() << " @ " << (*it).GetIp() << " for modules " << (*it).GetModules() << std::endl;
} }
} }

@ -40,31 +40,25 @@ class CPeer;
class CXlxProtocol : public CDextraProtocol class CXlxProtocol : public CDextraProtocol
{ {
public: public:
// constructor
CXlxProtocol() {};
// destructor
virtual ~CXlxProtocol() {};
// initialization // initialization
bool Init(void); bool Init(void);
// task // task
void Task(void); void Task(void);
protected: protected:
// queue helper // queue helper
void HandleQueue(void); void HandleQueue(void);
// keepalive helpers // keepalive helpers
void HandlePeerLinks(void); void HandlePeerLinks(void);
void HandleKeepalives(void); void HandleKeepalives(void);
// stream helpers // stream helpers
bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &); bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &);
void OnDvFramePacketIn(CDvFramePacket *, const CIp * = NULL); void OnDvFramePacketIn(CDvFramePacket *, const CIp * = NULL);
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 *, CVersion *); bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *, CVersion *);
@ -73,7 +67,7 @@ protected:
bool IsValidNackPacket(const CBuffer &, CCallsign *); bool IsValidNackPacket(const CBuffer &, CCallsign *);
CDvFramePacket *IsValidDvFramePacket(const CBuffer &); CDvFramePacket *IsValidDvFramePacket(const CBuffer &);
CDvLastFramePacket *IsValidDvLastFramePacket(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 *);
@ -82,11 +76,11 @@ protected:
void EncodeConnectNackPacket(CBuffer *); void EncodeConnectNackPacket(CBuffer *);
bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const; bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const;
bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const; bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const;
// protocol revision helper // protocol revision helper
int GetConnectingPeerProtocolRevision(const CCallsign &, const CVersion &); int GetConnectingPeerProtocolRevision(const CCallsign &, const CVersion &);
CPeer *CreateNewPeer(const CCallsign &, const CIp &, char *, const CVersion &); CPeer *CreateNewPeer(const CCallsign &, const CIp &, char *, const CVersion &);
protected: protected:
// time // time
CTimePoint m_LastKeepaliveTime; CTimePoint m_LastKeepaliveTime;

@ -47,29 +47,19 @@ CYsfProtocol::CYsfProtocol()
bool CYsfProtocol::Init(void) bool CYsfProtocol::Init(void)
{ {
bool ok;
// base class // base class
ok = CProtocol::Init(); if (! Initialize("YSF", YSF_PORT))
return false;
// update the reflector callsign
m_ReflectorCallsign.PatchCallsign(0, (const uint8 *)"YSF", 3);
// create our socket
ok &= m_Socket.Open(YSF_PORT);
if ( !ok )
{
std::cout << "Error opening socket on port UDP" << YSF_PORT << " on ip " << g_Reflector.GetListenIp() << std::endl;
}
// init the wiresx cmd handler // init the wiresx cmd handler
ok &= m_WiresxCmdHandler.Init(); if (! m_WiresxCmdHandler.Init())
return false;
// update time // update time
m_LastKeepaliveTime.Now(); m_LastKeepaliveTime.Now();
// done // done
return ok; return true;
} }
void CYsfProtocol::Close(void) void CYsfProtocol::Close(void)
@ -105,13 +95,13 @@ void CYsfProtocol::Task(void)
{ {
CWiresxPacket packet = queue->front(); CWiresxPacket packet = queue->front();
queue->pop(); queue->pop();
m_Socket.Send(packet.GetBuffer(), packet.GetIp()); Send(packet.GetBuffer(), packet.GetIp());
} }
m_WiresxCmdHandler.ReleasePacketQueue(); m_WiresxCmdHandler.ReleasePacketQueue();
} }
// handle incoming packets // handle incoming packets
if ( m_Socket.Receive(Buffer, Ip, 20) ) if ( m_Socket6.Receive(Buffer, Ip, 10) || m_Socket4.Receive(Buffer, Ip, 10) )
{ {
// crack the packet // crack the packet
if ( IsValidDvPacket(Buffer, &Fich) ) if ( IsValidDvPacket(Buffer, &Fich) )
@ -164,7 +154,7 @@ void CYsfProtocol::Task(void)
{ {
// acknowledge the request // acknowledge the request
EncodeConnectAckPacket(&Buffer); EncodeConnectAckPacket(&Buffer);
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
// add client if needed // add client if needed
CClients *clients = g_Reflector.GetClients(); CClients *clients = g_Reflector.GetClients();
@ -207,7 +197,7 @@ void CYsfProtocol::Task(void)
std::cout << "YSF server status enquiry from " << Ip << std::endl; std::cout << "YSF server status enquiry from " << Ip << std::endl;
// reply // reply
EncodeServerStatusPacket(&Buffer); EncodeServerStatusPacket(&Buffer);
m_Socket.Send(Buffer, Ip); Send(Buffer, Ip);
} }
else else
{ {
@ -359,7 +349,7 @@ void CYsfProtocol::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()); Send(buffer, client->GetIp());
} }
} }

@ -19,13 +19,12 @@
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>. // along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#include "main.h" #include "main.h"
#include "creflector.h" #include "creflector.h"
#include "syslog.h"
#include <sys/stat.h> #include <sys/stat.h>
@ -41,99 +40,58 @@ CReflector g_Reflector;
int main(int argc, const char * argv[]) int main(int argc, const char * argv[])
{ {
#ifdef RUN_AS_DAEMON
// redirect cout, cerr and clog to syslog
syslog::redirect cout_redir(std::cout);
syslog::redirect cerr_redir(std::cerr);
syslog::redirect clog_redir(std::clog);
//Fork the Parent Process
pid_t pid, sid;
pid = ::fork();
if ( pid < 0 )
{
exit(EXIT_FAILURE);
}
// We got a good pid, Close the Parent Process
if (pid > 0)
{
exit(EXIT_SUCCESS);
}
// Change File Mask
::umask(0);
//Create a new Signature Id for our child
sid = ::setsid();
if (sid < 0)
{
exit(EXIT_FAILURE);
}
// Change Directory
// If we cant find the directory we exit with failure.
if ( (::chdir("/")) < 0)
{
exit(EXIT_FAILURE);
}
// Close Standard File Descriptors
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
#endif
// check arguments // check arguments
if ( argc != 4 ) if ( argc != 5 )
{ {
std::cout << "Usage: xlxd callsign xlxdip ambedip" << std::endl; std::cout << "Usage: " << argv[0] << " callsign ipv4 ipv6 ambedip" << std::endl;
std::cout << "example: xlxd XLX999 192.168.178.212 127.0.0.1" << std::endl; std::cout << "example: " << argv[0] << " XLX999 192.168.178.212 2001:400:534::675b 127.0.0.1" << std::endl;
return 1; return EXIT_FAILURE;
} }
bool is4none = 0 == strncasecmp(argv[2], "none", 4);
bool is6none = 0 == strncasecmp(argv[3], "none", 4);
if (is4none && is6none) {
std::cerr << "Both IPv4 and 6 address can't both be 'none'" << std::endl;
return EXIT_FAILURE;
}
// splash // splash
std::cout << "Starting xlxd " << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_REVISION << std::endl << std::endl; std::cout << "Starting " << argv[0] << " " << 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.SetListenIPv4(argv[2], INET_ADDRSTRLEN);
g_Reflector.SetTranscoderIp(CIp(CIp(argv[3]))); g_Reflector.SetListenIPv6(argv[3], INET6_ADDRSTRLEN);
g_Reflector.SetTranscoderIp(argv[4], INET6_ADDRSTRLEN);
// and let it run // and let it run
if ( !g_Reflector.Start() ) if ( !g_Reflector.Start() )
{ {
std::cout << "Error starting reflector" << std::endl; std::cout << "Error starting reflector" << std::endl;
exit(EXIT_FAILURE); return EXIT_FAILURE;
}
std::cout << "Reflector " << g_Reflector.GetCallsign()
<< "started and listening on " << g_Reflector.GetListenIp() << std::endl;
#ifdef RUN_AS_DAEMON
// run forever
while ( true )
{
// sleep 60 seconds
CTimePoint::TaskSleepFor(60000);
}
#else
// wait any key
for (;;)
{
// sleep 60 seconds
CTimePoint::TaskSleepFor(60000);
#ifdef DEBUG_DUMPFILE
g_Reflector.m_DebugFile.close();
#endif
} }
#endif
std::cout << "Reflector " << g_Reflector.GetCallsign() << "started and listening on ";
// and wait for end if (! is4none)
{
std::cout << g_Reflector.GetListenIPv4();
if (! is6none)
{
std::cout << " and " << g_Reflector.GetListenIPv4() << std::endl;
}
}
else
{
std::cout << g_Reflector.GetListenIPv6() << std::endl;
}
pause(); // wait for any signal
g_Reflector.Stop(); g_Reflector.Stop();
std::cout << "Reflector stopped" << std::endl; std::cout << "Reflector stopped" << std::endl;
// done // done
exit(EXIT_SUCCESS); return EXIT_SUCCESS;
} }

Loading…
Cancel
Save

Powered by TurnKey Linux.