diff --git a/reflector/BMClient.h b/reflector/BMClient.h index 8455e83..875abbb 100644 --- a/reflector/BMClient.h +++ b/reflector/BMClient.h @@ -19,7 +19,7 @@ #pragma once #include "Client.h" -#include "URFClient.h" +#include "XLXClient.h" class CBmClient : public CClient { @@ -33,11 +33,11 @@ public: virtual ~CBmClient() {}; // identity - EProtocol GetProtocol(void) const { return EProtocol::ulx; } - int GetProtocolRevision(void) const { return XLX_PROTOCOL_REVISION_2; } - const char *GetProtocolName(void) const { return "XLX"; } - ECodecType GetCodec(void) const { return ECodecType::dmr; } - bool IsPeer(void) const { return true; } + EProtocol GetProtocol(void) const { return EProtocol::xlx; } + EProtoRev GetProtocolRevision(void) const { return EProtoRev::m17; } + const char *GetProtocolName(void) const { return "XLX"; } + ECodecType GetCodec(void) const { return ECodecType::dmr; } + bool IsPeer(void) const { return true; } // status bool IsAlive(void) const; diff --git a/reflector/BMPeer.cpp b/reflector/BMPeer.cpp index 846fc64..e688697 100644 --- a/reflector/BMPeer.cpp +++ b/reflector/BMPeer.cpp @@ -56,7 +56,7 @@ bool CBmPeer::IsAlive(void) const //////////////////////////////////////////////////////////////////////////////////////// // revision helper -int CBmPeer::GetProtocolRevision(const CVersion &version) +EProtoRev CBmPeer::GetProtocolRevision(const CVersion &version) { - return XLX_PROTOCOL_REVISION_2; + return EProtoRev::ambe; } diff --git a/reflector/BMPeer.h b/reflector/BMPeer.h index c0c28d2..fff2268 100644 --- a/reflector/BMPeer.h +++ b/reflector/BMPeer.h @@ -40,9 +40,9 @@ public: bool IsAlive(void) const; // identity - EProtocol GetProtocol(void) const { return EProtocol::ulx; } + EProtocol GetProtocol(void) const { return EProtocol::xlx; } const char *GetProtocolName(void) const { return "XLX"; } // revision helper - static int GetProtocolRevision(const CVersion &); + static EProtoRev GetProtocolRevision(const CVersion &); }; diff --git a/reflector/Client.h b/reflector/Client.h index d4e329b..18f354d 100644 --- a/reflector/Client.h +++ b/reflector/Client.h @@ -24,7 +24,7 @@ #include "Buffer.h" #include "Packet.h" -enum class EXLXProtocol { original, revised, ambe, m17 }; +enum class EProtoRev { original, revised, ambe, urf }; class CClient { @@ -54,7 +54,7 @@ public: // identity virtual EProtocol GetProtocol(void) const { return EProtocol::none; } - virtual EXLXProtocol GetProtocolRevision(void) const { return EXLXProtocol::m17; } + virtual EProtoRev GetProtocolRevision(void) const { return EProtoRev::ambe; } virtual ECodecType GetCodec(void) const { return ECodecType::none; } virtual const char *GetProtocolName(void) const { return "none"; } virtual bool IsNode(void) const { return false; } diff --git a/reflector/DCSProtocol.cpp b/reflector/DCSProtocol.cpp index 34b8b2c..a5d68bc 100644 --- a/reflector/DCSProtocol.cpp +++ b/reflector/DCSProtocol.cpp @@ -72,16 +72,7 @@ void CDcsProtocol::Task(void) { OnDvHeaderPacketIn(Header, Ip); - if ( !Frame->IsLastPacket() ) - { - //std::cout << "DCS DV frame" << std::endl; - OnDvFramePacketIn(Frame, &Ip); - } - else - { - //std::cout << "DCS DV last frame" << std::endl; - OnDvLastFramePacketIn((std::unique_ptr &)Frame, &Ip); - } + OnDvFramePacketIn(Frame, &Ip); } } else if ( IsValidConnectPacket(Buffer, &Callsign, &ToLinkModule) ) @@ -393,16 +384,7 @@ bool CDcsProtocol::IsValidDvPacket(const CBuffer &Buffer, std::unique_ptr(new CDvHeaderPacket((struct dstar_header *)&(Buffer.data()[4]), *((uint16_t *)&(Buffer.data()[43])), 0x80)); // get the frame - if ( Buffer.data()[45] & 0x40U ) - { - // it's the last frame - frame = std::unique_ptr(new CDvLastFramePacket((SDstarFrame *)&(Buffer.data()[46]), *((uint16_t *)&(Buffer.data()[43])), Buffer.data()[45])); - } - else - { - // it's a regular DV frame - frame = std::unique_ptr(new CDvFramePacket((SDstarFrame *)&(Buffer.data()[46]), *((uint16_t *)&(Buffer.data()[43])), Buffer.data()[45])); - } + frame = std::unique_ptr(new CDvFramePacket((SDStarFrame *)&(Buffer.data()[46]), *((uint16_t *)&(Buffer.data()[43])), Buffer.data()[45])); // check validity of packets if ( header && header->IsValid() && frame && frame->IsValid() ) diff --git a/reflector/DCSProtocol.h b/reflector/DCSProtocol.h index eb10c80..0ce92fe 100644 --- a/reflector/DCSProtocol.h +++ b/reflector/DCSProtocol.h @@ -22,7 +22,6 @@ #include "Protocol.h" #include "DVHeaderPacket.h" #include "DVFramePacket.h" -#include "DVLastFramePacket.h" //////////////////////////////////////////////////////////////////////////////////////// // define diff --git a/reflector/DExtraProtocol.cpp b/reflector/DExtraProtocol.cpp index ef60895..c7ef032 100644 --- a/reflector/DExtraProtocol.cpp +++ b/reflector/DExtraProtocol.cpp @@ -54,7 +54,6 @@ void CDextraProtocol::Task(void) int ProtRev; std::unique_ptr Header; std::unique_ptr Frame; - std::unique_ptr LastFrame; // any incoming packet ? #if DSTAR_IPV6==true @@ -80,10 +79,6 @@ void CDextraProtocol::Task(void) OnDvHeaderPacketIn(Header, Ip); } } - else if ( IsValidDvLastFramePacket(Buffer, LastFrame) ) - { - OnDvLastFramePacketIn(LastFrame, &Ip); - } else if ( IsValidConnectPacket(Buffer, &Callsign, &ToLinkModule, &ProtRev) ) { std::cout << "DExtra connect packet for module " << ToLinkModule << " from " << Callsign << " at " << Ip << " rev " << ProtRev << std::endl; @@ -151,12 +146,12 @@ void CDextraProtocol::Task(void) if ( client != nullptr ) { // ack disconnect packet - if ( client->GetProtocolRevision() == 1 ) + if ( client->GetProtocolRevision() == EProtoRev::revised ) { EncodeDisconnectedPacket(&Buffer); Send(Buffer, Ip); } - else if ( client->GetProtocolRevision() == 2 ) + else if ( client->GetProtocolRevision() == EProtoRev::ambe ) { Send(Buffer, Ip); } @@ -412,7 +407,7 @@ void CDextraProtocol::OnDvHeaderPacketIn(std::unique_ptr &Heade // get client callsign rpt1 = client->GetCallsign(); // apply protocol revision details - if ( client->GetProtocolRevision() == 2 ) + if ( client->GetProtocolRevision() == EProtoRev::ambe ) { // update Header RPT2 module letter with // the module the client is linked to @@ -507,7 +502,7 @@ bool CDextraProtocol::IsValidDvFramePacket(const CBuffer &Buffer, std::unique_pt if ( 27==Buffer.size() && 0==Buffer.Compare((uint8_t *)"DSVT", 4) && 0x20U==Buffer.data()[4] && 0x20U==Buffer.data()[8] && 0U==(Buffer.data()[14] & 0x40U) ) { // create packet - dvframe = std::unique_ptr(new CDvFramePacket((SDstarFrame *)&(Buffer.data()[15]), *((uint16_t *)&(Buffer.data()[12])), Buffer.data()[14])); + dvframe = std::unique_ptr(new CDvFramePacket((SDStarFrame *)&(Buffer.data()[15]), *((uint16_t *)&(Buffer.data()[12])), Buffer.data()[14])); // check validity of packet if ( dvframe && dvframe->IsValid() ) return true; @@ -515,18 +510,6 @@ bool CDextraProtocol::IsValidDvFramePacket(const CBuffer &Buffer, std::unique_pt return false; } -bool CDextraProtocol::IsValidDvLastFramePacket(const CBuffer &Buffer, std::unique_ptr &dvframe) -{ - if ( 27==Buffer.size() && 0==Buffer.Compare((uint8_t *)"DSVT", 4) && 0x20U==Buffer.data()[4] && 0x20U==Buffer.data()[8] && (Buffer.data()[14] & 0x40) ) - { - // create packet - dvframe = std::unique_ptr(new CDvLastFramePacket((SDstarFrame *)&(Buffer.data()[15]), *((uint16_t *)&(Buffer.data()[12])), Buffer.data()[14])); - // check validity of packet - if ( dvframe && dvframe->IsValid() ) - return true; - } - return false; -} //////////////////////////////////////////////////////////////////////////////////////// // packet encoding helpers @@ -618,16 +601,3 @@ bool CDextraProtocol::EncodeDvFramePacket(const CDvFramePacket &Packet, CBuffer return true; } - -bool CDextraProtocol::EncodeDvLastFramePacket(const CDvLastFramePacket &Packet, CBuffer *Buffer) const -{ - uint8_t tag1[] = { 'D','S','V','T',0x20,0x00,0x00,0x00,0x20,0x00,0x01,0x02 }; - uint8_t tag2[] = { 0x55,0xC8,0x7A,0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x1A,0xC6 }; - - Buffer->Set(tag1, sizeof(tag1)); - Buffer->Append(Packet.GetStreamId()); - Buffer->Append((uint8_t)((Packet.GetPacketId() % 21) | 0x40)); - Buffer->Append(tag2, sizeof(tag2)); - - return true; -} diff --git a/reflector/DExtraProtocol.h b/reflector/DExtraProtocol.h index f870363..88dc746 100644 --- a/reflector/DExtraProtocol.h +++ b/reflector/DExtraProtocol.h @@ -19,10 +19,9 @@ #pragma once #include "Timer.h" -#include "DCSProtocol.h" +#include "Protocol.h" #include "DVHeaderPacket.h" #include "DVFramePacket.h" -#include "DVLastFramePacket.h" //////////////////////////////////////////////////////////////////////////////////////// @@ -74,7 +73,6 @@ protected: bool IsValidKeepAlivePacket( const CBuffer &, CCallsign *); bool IsValidDvHeaderPacket( const CBuffer &, std::unique_ptr &); bool IsValidDvFramePacket( const CBuffer &, std::unique_ptr &); - bool IsValidDvLastFramePacket(const CBuffer &, std::unique_ptr &); // packet encoding helpers void EncodeKeepAlivePacket(CBuffer *); @@ -85,7 +83,6 @@ protected: void EncodeDisconnectedPacket(CBuffer *); bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const; bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const; - bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const; protected: // time diff --git a/reflector/DMRMMDVMProtocol.cpp b/reflector/DMRMMDVMProtocol.cpp index 2ec463d..983acc1 100644 --- a/reflector/DMRMMDVMProtocol.cpp +++ b/reflector/DMRMMDVMProtocol.cpp @@ -78,8 +78,8 @@ void CDmrmmdvmProtocol::Task(void) int iRssi; uint8_t Cmd; uint8_t CallType; - std::unique_ptr Header; - std::unique_ptr LastFrame; + std::unique_ptr Header; + std::unique_ptr LastFrame; std::array, 3> Frames; // handle incoming packets @@ -113,7 +113,7 @@ void CDmrmmdvmProtocol::Task(void) } else if ( IsValidDvLastFramePacket(Buffer, LastFrame) ) { - OnDvLastFramePacketIn(LastFrame, &Ip); + OnDvFramePacketIn(LastFrame, &Ip); } else if ( IsValidConnectPacket(Buffer, &Callsign, Ip) ) { @@ -707,15 +707,15 @@ bool CDmrmmdvmProtocol::IsValidDvFramePacket(const CBuffer &Buffer, std::array(new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 1)); + frames[0] = std::unique_ptr(new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 1, false)); // frame2 memcpy(dmrambe, &dmr3ambe[9], 9); - frames[1] = std::unique_ptr(new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 2)); + frames[1] = std::unique_ptr(new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 2, false)); // frame3 memcpy(dmrambe, &dmr3ambe[18], 9); - frames[2] = std::unique_ptr(new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 3)); + frames[2] = std::unique_ptr(new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 3, false)); // check if (frames[0] && frames[1] && frames[2]) @@ -725,7 +725,7 @@ bool CDmrmmdvmProtocol::IsValidDvFramePacket(const CBuffer &Buffer, std::array &frame) +bool CDmrmmdvmProtocol::IsValidDvLastFramePacket(const CBuffer &Buffer, std::unique_ptr &frame) { uint8_t tag[] = { 'D','M','R','D' }; @@ -769,7 +769,7 @@ bool CDmrmmdvmProtocol::IsValidDvLastFramePacket(const CBuffer &Buffer, std::uni // and packet - frame = std::unique_ptr(new CDvLastFramePacket(ambe, dmrsync, uiStreamId, 0, 0)); + frame = std::unique_ptr(new CDvFramePacket(ambe, dmrsync, uiStreamId, 0, 0, true)); if (frame) return true; } diff --git a/reflector/DMRMMDVMProtocol.h b/reflector/DMRMMDVMProtocol.h index 6adf4d1..71a5559 100644 --- a/reflector/DMRMMDVMProtocol.h +++ b/reflector/DMRMMDVMProtocol.h @@ -19,10 +19,9 @@ #pragma once #include "Timer.h" -#include "DCSProtocol.h" +#include "Protocol.h" #include "DVHeaderPacket.h" #include "DVFramePacket.h" -#include "DVLastFramePacket.h" //////////////////////////////////////////////////////////////////////////////////////// // define @@ -82,7 +81,7 @@ protected: bool IsValidRssiPacket(const CBuffer &, CCallsign *, int *); bool IsValidDvHeaderPacket(const CBuffer &, std::unique_ptr &, uint8_t *, uint8_t *); bool IsValidDvFramePacket(const CBuffer &, std::array, 3> &); - bool IsValidDvLastFramePacket(const CBuffer &, std::unique_ptr &); + bool IsValidDvLastFramePacket(const CBuffer &, std::unique_ptr &); // packet encoding helpers void EncodeKeepAlivePacket(CBuffer *, std::shared_ptr); diff --git a/reflector/DMRPlusProtocol.cpp b/reflector/DMRPlusProtocol.cpp index e108c16..e87df22 100644 --- a/reflector/DMRPlusProtocol.cpp +++ b/reflector/DMRPlusProtocol.cpp @@ -475,21 +475,21 @@ bool CDmrplusProtocol::IsValidDvFramePacket(const CIp &Ip, const CBuffer &Buffer uint32_t uiStreamId = IpToStreamId(Ip); // frame1 memcpy(dmrambe, &dmr3ambe[0], 9); - frames[0] = std::unique_ptr(new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 1)); + frames[0] = std::unique_ptr(new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 1, false)); // frame2 memcpy(dmrambe, &dmr3ambe[9], 9); - frames[1] = std::unique_ptr(new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 2)); + frames[1] = std::unique_ptr(new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 2, false)); // frame3 memcpy(dmrambe, &dmr3ambe[18], 9); if ( uiPacketType == 3 ) { - frames[2] = std::unique_ptr(new CDvLastFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 3)); + frames[2] = std::unique_ptr(new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 3, true)); } else { - frames[2] = std::unique_ptr(new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 3)); + frames[2] = std::unique_ptr(new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 3, false)); } // check diff --git a/reflector/DMRPlusProtocol.h b/reflector/DMRPlusProtocol.h index 250dc5f..2d30d5a 100644 --- a/reflector/DMRPlusProtocol.h +++ b/reflector/DMRPlusProtocol.h @@ -19,10 +19,9 @@ #pragma once #include "Timer.h" -#include "DCSProtocol.h" +#include "Protocol.h" #include "DVHeaderPacket.h" #include "DVFramePacket.h" -#include "DVLastFramePacket.h" //////////////////////////////////////////////////////////////////////////////////////// // define diff --git a/reflector/DPlusProtocol.cpp b/reflector/DPlusProtocol.cpp index 7cf3e02..e217be3 100644 --- a/reflector/DPlusProtocol.cpp +++ b/reflector/DPlusProtocol.cpp @@ -52,7 +52,6 @@ void CDplusProtocol::Task(void) CCallsign Callsign; std::unique_ptr Header; std::unique_ptr Frame; - std::unique_ptr LastFrame; // handle incoming packets #if DSTAR_IPV6==true @@ -79,10 +78,6 @@ void CDplusProtocol::Task(void) OnDvHeaderPacketIn(Header, Ip); } } - else if ( IsValidDvLastFramePacket(Buffer, LastFrame) ) - { - OnDvLastFramePacketIn(LastFrame, &Ip); - } else if ( IsValidConnectPacket(Buffer) ) { std::cout << "DPlus connect request packet from " << Ip << std::endl; @@ -428,23 +423,13 @@ bool CDplusProtocol::IsValidDvHeaderPacket(const CBuffer &Buffer, std::unique_pt bool CDplusProtocol::IsValidDvFramePacket(const CBuffer &Buffer, std::unique_ptr &dvframe) { - if ( 29==Buffer.size() && 0x1DU==Buffer.data()[0] && 0x80U==Buffer.data()[1] && 0==Buffer.Compare((uint8_t *)"DSVT", 2, 4) && 0x20U==Buffer.data()[6] && 0x20U==Buffer.data()[10] ) - { - // create packet - dvframe = std::unique_ptr(new CDvFramePacket((SDstarFrame *)&(Buffer.data()[17]), *((uint16_t *)&(Buffer.data()[14])), Buffer.data()[16])); - // check validity of packet - if ( dvframe && dvframe->IsValid() ) - return true; - } - return false; -} - -bool CDplusProtocol::IsValidDvLastFramePacket(const CBuffer &Buffer, std::unique_ptr &dvframe) -{ - if ( 32==Buffer.size() && 0==Buffer.Compare((uint8_t *)"DSVT", 2, 4) && 0x20U==Buffer.data()[0] && 0x80U==Buffer.data()[1] && 0x20U==Buffer.data()[6] && 0x20U==Buffer.data()[10] ) + auto size = Buffer.size(); + if ( (29==size || 32==size) && 0x1DU==Buffer.data()[0] && 0x80U==Buffer.data()[1] && 0==Buffer.Compare((uint8_t *)"DSVT", 2, 4) && 0x20U==Buffer.data()[6] && 0x20U==Buffer.data()[10] ) { - // create packet - dvframe = std::unique_ptr(new CDvLastFramePacket((SDstarFrame *)&(Buffer.data()[17]), *((uint16_t *)&(Buffer.data()[14])), Buffer.data()[16])); + if (32==size) + dvframe = std::unique_ptr(new CDvFramePacket((SDStarFrame *)&(Buffer.data()[17]), *((uint16_t *)&(Buffer.data()[14])), 0x40U | Buffer.data()[16])); + else + dvframe = std::unique_ptr(new CDvFramePacket((SDStarFrame *)&(Buffer.data()[17]), *((uint16_t *)&(Buffer.data()[14])), Buffer.data()[16])); // check validity of packet if ( dvframe && dvframe->IsValid() ) return true; @@ -510,7 +495,7 @@ bool CDplusProtocol::EncodeDvFramePacket(const CDvFramePacket &Packet, CBuffer * } -bool CDplusProtocol::EncodeDvLastFramePacket(const CDvLastFramePacket &Packet, CBuffer *Buffer) const +bool CDplusProtocol::EncodeDvLastFramePacket(const CDvFramePacket &Packet, CBuffer *Buffer) const { uint8_t tag1[] = { 0x20,0x80,0x44,0x53,0x56,0x54,0x20,0x00,0x81,0x00,0x20,0x00,0x01,0x02 }; uint8_t tag2[] = { 0x55,0xC8,0x7A,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x25,0x1A,0xC6 }; diff --git a/reflector/DPlusProtocol.h b/reflector/DPlusProtocol.h index 954bb6b..a7813e6 100644 --- a/reflector/DPlusProtocol.h +++ b/reflector/DPlusProtocol.h @@ -22,7 +22,6 @@ #include "Protocol.h" #include "DVHeaderPacket.h" #include "DVFramePacket.h" -#include "DVLastFramePacket.h" class CDplusClient; @@ -62,7 +61,6 @@ protected: bool IsValidKeepAlivePacket(const CBuffer &); bool IsValidDvHeaderPacket(const CBuffer &, std::unique_ptr &); bool IsValidDvFramePacket(const CBuffer &, std::unique_ptr &); - bool IsValidDvLastFramePacket(const CBuffer &, std::unique_ptr &); // packet encoding helpers void EncodeKeepAlivePacket(CBuffer *); @@ -71,7 +69,7 @@ protected: void EncodeDisconnectPacket(CBuffer *); bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const; bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const; - bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const; + bool EncodeDvLastFramePacket(const CDvFramePacket &, CBuffer *) const; protected: diff --git a/reflector/DVFramePacket.cpp b/reflector/DVFramePacket.cpp index a1a90d6..c790474 100644 --- a/reflector/DVFramePacket.cpp +++ b/reflector/DVFramePacket.cpp @@ -50,8 +50,8 @@ CDvFramePacket::CDvFramePacket(const SDStarFrame *dvframe, uint16_t sid, uint8_t // dmr constructor -CDvFramePacket::CDvFramePacket(const uint8_t *ambe, const uint8_t *sync, uint16_t sid, uint8_t pid, uint8_t spid) - : CPacket(sid, pid, spid) +CDvFramePacket::CDvFramePacket(const uint8_t *ambe, const uint8_t *sync, uint16_t sid, uint8_t pid, uint8_t spid, bool islast) + : CPacket(sid, pid, spid, islast) { memcpy(m_TCPack.dmr, ambe, 9); memcpy(m_uiDvSync, sync, 7); @@ -64,8 +64,8 @@ CDvFramePacket::CDvFramePacket(const uint8_t *ambe, const uint8_t *sync, uint16_ // ysf constructor -CDvFramePacket::CDvFramePacket(const uint8_t *ambe, uint16_t sid, uint8_t pid, uint8_t spid, uint8_t fid) - : CPacket(sid, pid, spid, fid) +CDvFramePacket::CDvFramePacket(const uint8_t *ambe, uint16_t sid, uint8_t pid, uint8_t spid, uint8_t fid, bool islast) + : CPacket(sid, pid, spid, fid, islast) { memcpy(m_TCPack.dmr, ambe, 9); memset(m_uiDvSync, 0, 7); @@ -81,8 +81,23 @@ CDvFramePacket::CDvFramePacket(const uint8_t *ambe, uint16_t sid, uint8_t pid, u CDvFramePacket::CDvFramePacket (uint16_t sid, uint8_t dstarpid, const uint8_t *dstarambe, const uint8_t *dstardvdata, - uint8_t dmrpid, uint8_t dprspid, const uint8_t *dmrambe, const uint8_t *dmrsync, ECodecType codecInType, const uint8_t *codec2, const uint8_t * nonce) - : CPacket(sid, dstarpid, dmrpid, dprspid, 0xFF, 0xFF, 0xFF, codecInType) + uint8_t dmrpid, uint8_t dprspid, const uint8_t *dmrambe, const uint8_t *dmrsync, ECodecType codecInType, bool islast) + : CPacket(sid, dstarpid, dmrpid, dprspid, 0xFF, 0xFF, 0xFF, codecInType, islast) +{ + ::memcpy(m_TCPack.dstar, dstarambe, 9); + ::memcpy(m_uiDvData, dstardvdata, 3); + ::memcpy(m_TCPack.dmr, dmrambe, 9); + ::memcpy(m_uiDvSync, dmrsync, 7); + m_TCPack.codec_in = codecInType; +} + +// urf constructor + +CDvFramePacket::CDvFramePacket +(uint16_t sid, + uint8_t dstarpid, const uint8_t *dstarambe, const uint8_t *dstardvdata, + uint8_t dmrpid, uint8_t dprspid, const uint8_t *dmrambe, const uint8_t *dmrsync, ECodecType codecInType, const uint8_t *codec2, const uint8_t * nonce, bool islast) + : CPacket(sid, dstarpid, dmrpid, dprspid, 0xFF, 0xFF, 0xFF, codecInType, islast) { memcpy(m_TCPack.dstar, dstarambe, 9); memcpy(m_uiDvData, dstardvdata, 3); diff --git a/reflector/DVFramePacket.h b/reflector/DVFramePacket.h index 2452599..c21fe27 100644 --- a/reflector/DVFramePacket.h +++ b/reflector/DVFramePacket.h @@ -43,11 +43,13 @@ public: // DStar frame CDvFramePacket(const SDStarFrame *dstarframe, uint16_t streamid, uint8_t counter); // DMR Frame - CDvFramePacket(const uint8_t *ambe, const uint8_t *sync, uint16_t streamid, uint8_t counter1, uint8_t counter2); + CDvFramePacket(const uint8_t *ambe, const uint8_t *sync, uint16_t streamid, uint8_t counter1, uint8_t counter2, bool islast); // YSF Frame - CDvFramePacket(const uint8_t *ambe, uint16_t streamid, uint8_t counter1, uint8_t counter2, uint8_t counter3); + CDvFramePacket(const uint8_t *ambe, uint16_t streamid, uint8_t counter1, uint8_t counter2, uint8_t counter3, bool islast); + // XLX Frame + CDvFramePacket(uint16_t streamid, uint8_t counter, const uint8_t *ambe, const uint8_t *dvdata, uint8_t counter1, uint8_t counter2, const uint8_t *ambe2, const uint8_t *dmrsync, ECodecType type, bool islast); // URF Frame - CDvFramePacket(uint16_t streamid, uint8_t dstarcounter, const uint8_t *dstarambe, const uint8_t *dvdata, uint8_t dmrcounter1, uint8_t dmrcounter2, const uint8_t *dmrambe, const uint8_t *dmrsync, ECodecType type, const uint8_t *m17codec, const uint8_t *nonce); + CDvFramePacket(uint16_t streamid, uint8_t dstarcounter, const uint8_t *dstarambe, const uint8_t *dvdata, uint8_t dmrcounter1, uint8_t dmrcounter2, const uint8_t *dmrambe, const uint8_t *dmrsync, ECodecType type, const uint8_t *m17codec, const uint8_t *nonce, bool islast); CDvFramePacket(const CM17Packet &m17); // virtual duplication diff --git a/reflector/DVHeaderPacket.cpp b/reflector/DVHeaderPacket.cpp index 27adbac..83e5c25 100644 --- a/reflector/DVHeaderPacket.cpp +++ b/reflector/DVHeaderPacket.cpp @@ -52,7 +52,7 @@ CDvHeaderPacket::CDvHeaderPacket(const struct dstar_header *buffer, uint16_t sid // dmr constructor CDvHeaderPacket::CDvHeaderPacket(uint32_t my, const CCallsign &ur, const CCallsign &rpt1, const CCallsign &rpt2, uint16_t sid, uint8_t pid, uint8_t spid) - : CPacket(sid, pid, spid) + : CPacket(sid, pid, spid, false) { m_uiFlag1 = 0; m_uiFlag2 = 0; diff --git a/reflector/DVHeaderPacket.h b/reflector/DVHeaderPacket.h index a242fbe..c08921c 100644 --- a/reflector/DVHeaderPacket.h +++ b/reflector/DVHeaderPacket.h @@ -95,14 +95,14 @@ public: protected: // data - uint8_t m_uiFlag1; - uint8_t m_uiFlag2; - uint8_t m_uiFlag3; + uint8_t m_uiFlag1; + uint8_t m_uiFlag2; + uint8_t m_uiFlag3; CCallsign m_csUR; CCallsign m_csRPT1; CCallsign m_csRPT2; CCallsign m_csMY; - uint16_t m_uiCrc; + uint16_t m_uiCrc; #ifdef IMPLEMENT_CDVHEADERPACKET_CONST_CHAR_OPERATOR // buffer char m_sz[256]; diff --git a/reflector/DVLastFramePacket.cpp b/reflector/DVLastFramePacket.cpp deleted file mode 100644 index 31e96ba..0000000 --- a/reflector/DVLastFramePacket.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. -// -// urfd -- The universal reflector -// Copyright © 2021 Thomas A. Early N7TAE -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -#include "Main.h" -#include "DVLastFramePacket.h" - -// constructor -CDvLastFramePacket::CDvLastFramePacket() -{ -} - -// dstar constructor -CDvLastFramePacket::CDvLastFramePacket(const SDStarFrame *DvFrame, uint16_t sid, uint8_t pid) - : CDvFramePacket(DvFrame, sid, pid) -{ -} - -// dmr constructor -CDvLastFramePacket::CDvLastFramePacket(const uint8_t *ambe, const uint8_t *sync, uint16_t sid, uint8_t pid, uint8_t spid) - : CDvFramePacket(ambe, sync, sid, pid, spid) -{ -} - -// ysf constructor -CDvLastFramePacket::CDvLastFramePacket(const uint8_t *ambe, uint16_t sid, uint8_t pid, uint8_t spid, uint8_t fid) - : CDvFramePacket(ambe, sid, pid, spid, fid) -{ -} - -// urf constructor -CDvLastFramePacket::CDvLastFramePacket -(uint16_t sid, uint8_t dstarpid, const uint8_t *dstarambe, const uint8_t *dstardvdata, uint8_t dmrpid, uint8_t dprspid, const uint8_t *dmrambe, const uint8_t *dmrsync, ECodecType type, const uint8_t *codec2, const uint8_t *nonce) - : CDvFramePacket(sid, dstarpid, dstarambe, dstardvdata, dmrpid, dprspid, dmrambe, dmrsync, type, codec2, nonce) -{ -} - -// m17 constructor -CDvLastFramePacket::CDvLastFramePacket(const CM17Packet &m17) : CDvFramePacket(m17) -{ -} - -// copy constructor -CDvLastFramePacket::CDvLastFramePacket(const CDvLastFramePacket &DvFrame) - : CDvFramePacket(DvFrame) -{ -} - -// virtual duplication -std::unique_ptr CDvLastFramePacket::Duplicate(void) const -{ - return std::unique_ptr(new CDvLastFramePacket(*this)); -} diff --git a/reflector/DVLastFramePacket.h b/reflector/DVLastFramePacket.h deleted file mode 100644 index 796606b..0000000 --- a/reflector/DVLastFramePacket.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. -// -// urfd -- The universal reflector -// Copyright © 2021 Thomas A. Early N7TAE -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -#include "DVFramePacket.h" - -//////////////////////////////////////////////////////////////////////////////////////// -// defines - - -//////////////////////////////////////////////////////////////////////////////////////// -// class - -class CDvLastFramePacket : public CDvFramePacket -{ -public: - // empty constructor - CDvLastFramePacket(); - // DStar constructor - CDvLastFramePacket(const SDStarFrame *dvframe, uint16_t streamid, uint8_t counter); - // DRM constructor - CDvLastFramePacket(const uint8_t *ambe, const uint8_t *sync, uint16_t streamid, uint8_t counter1, uint8_t counter2); - // YSF constructor - CDvLastFramePacket(const uint8_t *ambe, uint16_t streamid, uint8_t counter1, uint8_t counter2, uint8_t counter3); - // URF constructor - CDvLastFramePacket(uint16_t streamid, uint8_t dstarcounter, const uint8_t *dstarambe, const uint8_t *dvdata, uint8_t dmrcounter1, uint8_t dmrcounter2, const uint8_t *dmrambe, const uint8_t *dmrsync, ECodecType type, const uint8_t *codec2, const uint8_t *nonce); - // M17 constructor - CDvLastFramePacket(const CM17Packet &); - // copy constructor - CDvLastFramePacket(const CDvLastFramePacket &); - - // virtual duplication - std::unique_ptr Duplicate(void) const; - - // identity - bool IsLastPacket(void) const { return true; } - bool HasTranscodableData(void) const { return false; } -}; diff --git a/reflector/G3Protocol.cpp b/reflector/G3Protocol.cpp index bbbc471..5c947c8 100644 --- a/reflector/G3Protocol.cpp +++ b/reflector/G3Protocol.cpp @@ -372,7 +372,6 @@ void CG3Protocol::Task(void) int ProtRev; std::unique_ptr Header; std::unique_ptr Frame; - std::unique_ptr LastFrame; // any incoming packet ? if ( m_Socket4.Receive(Buffer, Ip, 20) ) @@ -413,10 +412,6 @@ void CG3Protocol::Task(void) OnDvHeaderPacketIn(Header, *BaseIp); } } - else if ( IsValidDvLastFramePacket(Buffer, LastFrame) ) - { - OnDvLastFramePacketIn(LastFrame, BaseIp); - } } } @@ -603,23 +598,10 @@ bool CG3Protocol::IsValidDvHeaderPacket(const CBuffer &Buffer, std::unique_ptr &dvframe) { - if ( 27==Buffer.size() && 0==Buffer.Compare((uint8_t *)"DSVT", 4) && 0x20U==Buffer.data()[4] && 0x20U==Buffer.data()[8] && 0U==(Buffer.data()[14] & 0x40U) ) - { - // create packet - dvframe = std::unique_ptr(new CDvFramePacket((SDstarFrame *)&(Buffer.data()[15]), *((uint16_t *)&(Buffer.data()[12])), Buffer.data()[14])); - // check validity of packet - if ( dvframe && dvframe->IsValid() ) - return true; - } - return false; -} - -bool CG3Protocol::IsValidDvLastFramePacket(const CBuffer &Buffer, std::unique_ptr &dvframe) -{ - if ( 27==Buffer.size() && 0==Buffer.Compare((uint8_t *)"DSVT", 4) && 0x20U==Buffer.data()[4] && 0x20U==Buffer.data()[8] && (Buffer.data()[14] & 0x40U) ) + if ( 27==Buffer.size() && 0==Buffer.Compare((uint8_t *)"DSVT", 4) && 0x20U==Buffer.data()[4] && 0x20U==Buffer.data()[8] ) { // create packet - dvframe = std::unique_ptr(new CDvLastFramePacket((SDstarFrame *)&(Buffer.data()[15]), *((uint16_t *)&(Buffer.data()[12])), Buffer.data()[14])); + dvframe = std::unique_ptr(new CDvFramePacket((SDStarFrame *)&(Buffer.data()[15]), *((uint16_t *)&(Buffer.data()[12])), Buffer.data()[14])); // check validity of packet if ( dvframe && dvframe->IsValid() ) return true; @@ -659,7 +641,7 @@ bool CG3Protocol::EncodeDvFramePacket(const CDvFramePacket &Packet, CBuffer *Buf } -bool CG3Protocol::EncodeDvLastFramePacket(const CDvLastFramePacket &Packet, CBuffer *Buffer) const +bool CG3Protocol::EncodeDvLastFramePacket(const CDvFramePacket &Packet, CBuffer *Buffer) const { uint8_t tag1[] = { 'D','S','V','T',0x20,0x00,0x00,0x00,0x20,0x00,0x01,0x02 }; uint8_t tag2[] = { 0x55,0xC8,0x7A,0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x1A,0xC6 }; diff --git a/reflector/G3Protocol.h b/reflector/G3Protocol.h index e50901f..1af3836 100644 --- a/reflector/G3Protocol.h +++ b/reflector/G3Protocol.h @@ -20,10 +20,9 @@ #include #include "Timer.h" -#include "DCSProtocol.h" +#include "Protocol.h" #include "DVHeaderPacket.h" #include "DVFramePacket.h" -#include "DVLastFramePacket.h" #include "RawSocket.h" #include "UDPMsgSocket.h" @@ -98,12 +97,11 @@ protected: // packet decoding helpers bool IsValidDvHeaderPacket(const CBuffer &, std::unique_ptr &); bool IsValidDvFramePacket(const CBuffer &, std::unique_ptr &); - bool IsValidDvLastFramePacket(const CBuffer &, std::unique_ptr &); // packet encoding helpers bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const; bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const; - bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const; + bool EncodeDvLastFramePacket(const CDvFramePacket &, CBuffer *) const; protected: std::future m_PresenceFuture, m_ConfigFuture, m_IcmpFuture; diff --git a/reflector/M17Protocol.cpp b/reflector/M17Protocol.cpp index 73adf33..a63ce45 100644 --- a/reflector/M17Protocol.cpp +++ b/reflector/M17Protocol.cpp @@ -73,16 +73,7 @@ void CM17Protocol::Task(void) { OnDvHeaderPacketIn(Header, Ip); - if ( !Frame->IsLastPacket() ) - { - //std::cout << "M17 DV frame" << std::endl; - OnDvFramePacketIn(Frame, &Ip); - } - else - { - //std::cout << "M17 DV last frame" << std::endl; - OnDvLastFramePacketIn((std::unique_ptr &)Frame, &Ip); - } + OnDvFramePacketIn((std::unique_ptr &)Frame, &Ip); } } else if ( IsValidConnectPacket(Buffer, Callsign, ToLinkModule) ) @@ -373,16 +364,7 @@ bool CM17Protocol::IsValidDvPacket(const CBuffer &Buffer, std::unique_ptr(new CDvHeaderPacket(m17)); // get the frame - if (m17.IsLastPacket()) - { - // it's the last frame - frame = std::unique_ptr(new CDvLastFramePacket(m17)); - } - else - { - // it's a regular DV frame - frame = std::unique_ptr(new CDvFramePacket(m17)); - } + frame = std::unique_ptr(new CDvFramePacket(m17)); // check validity of packets if ( header && header->IsValid() && frame && frame->IsValid() ) diff --git a/reflector/M17Protocol.h b/reflector/M17Protocol.h index d91830d..6cf39e7 100644 --- a/reflector/M17Protocol.h +++ b/reflector/M17Protocol.h @@ -22,7 +22,6 @@ #include "Protocol.h" #include "DVHeaderPacket.h" #include "DVFramePacket.h" -#include "DVLastFramePacket.h" #include "M17CRC.h" //////////////////////////////////////////////////////////////////////////////////////// diff --git a/reflector/Main.h b/reflector/Main.h index f71fe79..09127ba 100644 --- a/reflector/Main.h +++ b/reflector/Main.h @@ -49,15 +49,19 @@ #define DMR_IPV4 true #define YSF_IPV4 true #define XLX_IPV4 true +#define M17_IPV4 true +#define URF_IPV4 true #define DSTAR_IPV6 true #define DMR_IPV6 false #define YSF_IPV6 false #define XLX_IPV6 false +#define M17_IPV6 true +#define URF_IPV6 true // version ----------------------------------------------------- -#define VERSION_MAJOR 17 +#define VERSION_MAJOR 1 #define VERSION_MINOR 0 #define VERSION_REVISION 0 @@ -73,9 +77,9 @@ // protocols --------------------------------------------------- #ifndef NO_G3 -enum class EProtocol { any, none, dextra, dplus, dcs, ulx, dmrplus, dmrmmdvm, ysf, m17, g3 }; +enum class EProtocol { any, none, dextra, dplus, dcs, xlx, urf, dmrplus, dmrmmdvm, ysf, m17, g3 }; #else -enum class EProtocol { any, none, dextra, dplus, dcs, xlx, dmrplus, dmrmmdvm, ysf, m17 }; +enum class EProtocol { any, none, dextra, dplus, dcs, xlx, urf, dmrplus, dmrmmdvm, ysf, m17 }; #endif // DExtra @@ -100,6 +104,12 @@ enum class EProtocol { any, none, dextra, dplus, dcs, xlx, dmrplus, dmrmmdvm, ys #define XLX_KEEPALIVE_TIMEOUT (XLX_KEEPALIVE_PERIOD*30) // in seconds #define XLX_RECONNECT_PERIOD 5 // in seconds +// URF +#define URF_PORT 10017 // UDP port +#define URF_KEEPALIVE_PERIOD 1 // in seconds +#define URF_KEEPALIVE_TIMEOUT (XLX_KEEPALIVE_PERIOD*30) // in seconds +#define URF_RECONNECT_PERIOD 5 // in seconds + // DMRPlus (dongle) #define DMRPLUS_PORT 8880 // UDP port #define DMRPLUS_KEEPALIVE_PERIOD 1 // in seconds diff --git a/reflector/Packet.cpp b/reflector/Packet.cpp index 1e192ef..b3620bb 100644 --- a/reflector/Packet.cpp +++ b/reflector/Packet.cpp @@ -37,6 +37,7 @@ CPacket::CPacket() m_cModule = ' '; m_uiOriginId = ORIGIN_LOCAL; m_eCodecIn = ECodecType::none; + m_bLastPacket = false; }; // dstar contrsuctor @@ -54,11 +55,12 @@ CPacket::CPacket(uint16_t sid, uint8_t dstarpid) m_cModule = ' '; m_uiOriginId = ORIGIN_LOCAL; m_eCodecIn = ECodecType::dstar; + m_bLastPacket = (0x40U == (dstarpid & 0x40U)); }; // dmr constructor -CPacket::CPacket(uint16_t sid, uint8_t dmrpid, uint8_t dmrspid) +CPacket::CPacket(uint16_t sid, uint8_t dmrpid, uint8_t dmrspid, bool lastpacket) { m_uiStreamId = sid; m_uiDmrPacketId = dmrpid; @@ -71,11 +73,12 @@ CPacket::CPacket(uint16_t sid, uint8_t dmrpid, uint8_t dmrspid) m_cModule = ' '; m_uiOriginId = ORIGIN_LOCAL; m_eCodecIn = ECodecType::dmr; + m_bLastPacket = lastpacket; }; // ysf constructor -CPacket::CPacket(uint16_t sid, uint8_t ysfpid, uint8_t ysfsubpid, uint8_t ysffrid) +CPacket::CPacket(uint16_t sid, uint8_t ysfpid, uint8_t ysfsubpid, uint8_t ysffrid, bool lastpacket) { m_uiStreamId = sid; m_uiYsfPacketId = ysfpid; @@ -88,11 +91,12 @@ CPacket::CPacket(uint16_t sid, uint8_t ysfpid, uint8_t ysfsubpid, uint8_t ysffri m_cModule = ' '; m_uiOriginId = ORIGIN_LOCAL; m_eCodecIn = ECodecType::dmr; + m_bLastPacket = lastpacket; } // xlx constructor -CPacket::CPacket(uint16_t sid, uint8_t dstarpid, uint8_t dmrpid, uint8_t dmrsubpid, uint8_t ysfpid, uint8_t ysfsubpid, uint8_t ysffrid, ECodecType codecIn) +CPacket::CPacket(uint16_t sid, uint8_t dstarpid, uint8_t dmrpid, uint8_t dmrsubpid, uint8_t ysfpid, uint8_t ysfsubpid, uint8_t ysffrid, ECodecType codecIn, bool lastpacket) { m_uiStreamId = sid; m_uiDstarPacketId = dstarpid; @@ -105,6 +109,7 @@ CPacket::CPacket(uint16_t sid, uint8_t dstarpid, uint8_t dmrpid, uint8_t dmrsubp m_cModule = ' '; m_uiOriginId = ORIGIN_LOCAL; m_eCodecIn = codecIn; + m_bLastPacket = lastpacket; } // m17 constructor @@ -120,6 +125,7 @@ CPacket::CPacket(const CM17Packet &m17) : CPacket() m_uiYsfPacketFrameId = 0xFF; m_eCodecIn = (0x6U == (0x6U & m17.GetFrameType())) ? ECodecType::c2_1600 : ECodecType::c2_3200; m_uiM17FrameNumber = 0x7FFFU & m17.GetFrameNumber(); + m_bLastPacket = m17.IsLastPacket(); } //////////////////////////////////////////////////////////////////////////////////////// diff --git a/reflector/Packet.h b/reflector/Packet.h index 6ab5dfa..5c76f11 100644 --- a/reflector/Packet.h +++ b/reflector/Packet.h @@ -32,9 +32,9 @@ public: // constructor CPacket(); CPacket(uint16_t sid, uint8_t dstarpid); - CPacket(uint16_t sid, uint8_t dmrpid, uint8_t dmrsubpid); - CPacket(uint16_t sid, uint8_t ysfpid, uint8_t ysfsubpid, uint8_t ysfsubpidmax); - CPacket(uint16_t sid, uint8_t dstarpid, uint8_t dmrpid, uint8_t dmrsubpid, uint8_t ysfpid, uint8_t ysfsubpid, uint8_t ysfsubpidmax, ECodecType); + CPacket(uint16_t sid, uint8_t dmrpid, uint8_t dmrsubpid, bool lastpacket); + CPacket(uint16_t sid, uint8_t ysfpid, uint8_t ysfsubpid, uint8_t ysfsubpidmax, bool lastpacket); + CPacket(uint16_t sid, uint8_t dstarpid, uint8_t dmrpid, uint8_t dmrsubpid, uint8_t ysfpid, uint8_t ysfsubpid, uint8_t ysfsubpidmax, ECodecType, bool lastpacket); CPacket(const CM17Packet &); // destructor @@ -44,10 +44,10 @@ public: virtual std::unique_ptr Duplicate(void) const = 0; // identity - virtual bool IsDvHeader(void) const { return false; } - virtual bool IsDvFrame(void) const { return false; } - virtual bool IsLastPacket(void) const { return false; } - virtual bool HasTranscodableData(void) const { return false; } + virtual bool IsDvHeader(void) const { return false; } + virtual bool IsDvFrame(void) const { return false; } + virtual bool HasTranscodableData(void) const { return false; } + bool IsLastPacket(void) const { return m_bLastPacket; } // get virtual bool IsValid(void) const { return true; } @@ -72,6 +72,9 @@ public: protected: // data + ECodecType m_eCodecIn; + bool m_bLastPacket; + char m_cModule; uint16_t m_uiStreamId; uint16_t m_uiM17FrameNumber; uint8_t m_uiDstarPacketId; @@ -80,7 +83,5 @@ protected: uint8_t m_uiYsfPacketId; uint8_t m_uiYsfPacketSubId; uint8_t m_uiYsfPacketFrameId; - char m_cModule; uint8_t m_uiOriginId; - ECodecType m_eCodecIn; }; diff --git a/reflector/Protocol.cpp b/reflector/Protocol.cpp index 50527bc..9f66a7f 100644 --- a/reflector/Protocol.cpp +++ b/reflector/Protocol.cpp @@ -17,7 +17,7 @@ // along with this program. If not, see . #include "Main.h" -#include "DCSProtocol.h" +#include "Protocol.h" #include "Clients.h" #include "Reflector.h" @@ -130,12 +130,8 @@ void CProtocol::Close(void) bool CProtocol::EncodeDvPacket(const CPacket &packet, CBuffer *buffer) const { if ( packet.IsDvFrame() ) - { - if ( packet.IsLastPacket() ) - return EncodeDvLastFramePacket((CDvLastFramePacket &)packet, buffer); - else - return EncodeDvFramePacket((CDvFramePacket &)packet, buffer); - } + return EncodeDvFramePacket((CDvFramePacket &)packet, buffer); + if ( packet.IsDvHeader() ) return EncodeDvHeaderPacket((CDvHeaderPacket &)packet, buffer); @@ -158,34 +154,11 @@ void CProtocol::OnDvFramePacketIn(std::unique_ptr &Frame, const stream->Push(std::move(Frame)); stream->Unlock(); } - // else - // { - // std::cout << "Orphaned Frame with ID " << Frame->GetStreamId() << " on " << *Ip << std::endl; - // } -} - -void CProtocol::OnDvLastFramePacketIn(std::unique_ptr &Frame, const CIp *Ip) -{ - // find the stream - auto stream = GetStream(Frame->GetStreamId(), Ip); - if ( stream ) + else { - // push - stream->Lock(); - stream->Push(std::move(Frame)); - stream->Unlock(); - - // Don't close yet, this stops the last packet relfection bug that was fixed in upstream by the same change. - // Don't close the stream yet but rely on CheckStreamsTimeout - // mechanism, so the stream will be closed after the queues have - // been sinked out. This avoid last packets to be send back - // to transmitting client (master) - + std::cout << "Orphaned Frame with ID " << Frame->GetStreamId() << " on " << *Ip << std::endl; + Frame.reset(); } - // else - // { - // std::cout << "Orphaned Last Frame with ID " << Frame->GetStreamId() << " on " << *Ip << std::endl; - // } } //////////////////////////////////////////////////////////////////////////////////////// diff --git a/reflector/Protocol.h b/reflector/Protocol.h index 67c2a2b..5b5da32 100644 --- a/reflector/Protocol.h +++ b/reflector/Protocol.h @@ -22,7 +22,6 @@ #include "PacketStream.h" #include "DVHeaderPacket.h" #include "DVFramePacket.h" -#include "DVLastFramePacket.h" //////////////////////////////////////////////////////////////////////////////////////// @@ -88,12 +87,10 @@ protected: virtual bool EncodeDvPacket(const CPacket &, CBuffer *) const; virtual bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const { return false; } virtual bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const { return false; } - virtual bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const { return false; } // stream helpers virtual void OnDvHeaderPacketIn(std::unique_ptr &, const CIp &) {} virtual void OnDvFramePacketIn(std::unique_ptr &, const CIp * = nullptr); - virtual void OnDvLastFramePacketIn(std::unique_ptr &, const CIp * = nullptr); // stream handle helpers std::shared_ptr GetStream(uint16_t, const CIp * = nullptr); diff --git a/reflector/Protocols.cpp b/reflector/Protocols.cpp index 7dba043..c3f7ac1 100644 --- a/reflector/Protocols.cpp +++ b/reflector/Protocols.cpp @@ -24,6 +24,7 @@ #include "DMRPlusProtocol.h" #include "DMRMMDVMProtocol.h" #include "YSFProtocol.h" +#include "M17Protocol.h" #ifndef NO_G3 #include "G3Protocol.h" #endif @@ -69,7 +70,11 @@ bool CProtocols::Init(void) return false; m_Protocols.emplace_back(std::unique_ptr(new CURFProtocol)); - if (! m_Protocols.back()->Initialize("XLX", EProtocol::ulx, XLX_PORT, DMR_IPV4, DMR_IPV6)) + if (! m_Protocols.back()->Initialize("URF", EProtocol::urf, URF_PORT, URF_IPV4, URF_IPV6)) + return false; + + m_Protocols.emplace_back(std::unique_ptr(new CM17Protocol)); + if (! m_Protocols.back()->Initialize("URF", EProtocol::m17, M17_PORT, M17_IPV4, M17_IPV6)) return false; #ifndef NO_G3 diff --git a/reflector/Protocols.h b/reflector/Protocols.h index 0dc4002..32bbf1e 100644 --- a/reflector/Protocols.h +++ b/reflector/Protocols.h @@ -18,7 +18,7 @@ #pragma once -#include "DCSProtocol.h" +#include "Protocol.h" class CProtocols { diff --git a/reflector/URFClient.cpp b/reflector/URFClient.cpp new file mode 100644 index 0000000..b9605b1 --- /dev/null +++ b/reflector/URFClient.cpp @@ -0,0 +1,50 @@ +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// urfd -- The universal reflector +// Copyright © 2021 Thomas A. Early N7TAE +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include +#include "Main.h" +#include "URFClient.h" + + +//////////////////////////////////////////////////////////////////////////////////////// +// constructors + +CURFClient::CURFClient() +{ + m_ProtRev = EProtoRev::original; +} + +CURFClient::CURFClient(const CCallsign &callsign, const CIp &ip, char reflectorModule, EProtoRev protRev) + : CClient(callsign, ip, reflectorModule) +{ + m_ProtRev = protRev; +} + +CURFClient::CURFClient(const CURFClient &client) + : CClient(client) +{ + m_ProtRev = client.m_ProtRev; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// status + +bool CURFClient::IsAlive(void) const +{ + return (m_LastKeepaliveTime.time() < URF_KEEPALIVE_TIMEOUT); +} diff --git a/reflector/URFClient.h b/reflector/URFClient.h new file mode 100644 index 0000000..89d70ac --- /dev/null +++ b/reflector/URFClient.h @@ -0,0 +1,53 @@ +#pragma once + +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// urfd -- The universal reflector +// Copyright © 2021 Thomas A. Early N7TAE +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + + +#include "Client.h" + +enum class EURFProtocol { original }; + +class CURFClient : public CClient +{ +public: + // constructors + CURFClient(); + CURFClient(const CCallsign &, const CIp &, char = ' ', EProtoRev = EProtoRev::original); + CURFClient(const CURFClient &); + + // destructor + virtual ~CURFClient() {}; + + // identity + EProtocol GetProtocol(void) const { return EProtocol::urf; } + EProtoRev GetProtocolRevision(void) const { return m_ProtRev; } + const char *GetProtocolName(void) const { return "URF"; } + ECodecType GetCodec(void) const { return ECodecType::none; }; + bool IsPeer(void) const { return true; } + + // status + bool IsAlive(void) const; + + // reporting + void WriteXml(std::ofstream &) {} + +protected: + // data + EProtoRev m_ProtRev; +}; diff --git a/reflector/URFPeer.cpp b/reflector/URFPeer.cpp new file mode 100644 index 0000000..970882c --- /dev/null +++ b/reflector/URFPeer.cpp @@ -0,0 +1,63 @@ +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// urfd -- The universal reflector +// Copyright © 2021 Thomas A. Early N7TAE +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "Main.h" +#include +#include "Reflector.h" +#include "URFPeer.h" +#include "URFClient.h" + + +//////////////////////////////////////////////////////////////////////////////////////// +// constructor + + +CURFPeer::CURFPeer() +{ +} + +CURFPeer::CURFPeer(const CCallsign &callsign, const CIp &ip, const char *modules, const CVersion &version) + : CPeer(callsign, ip, modules, version) +{ + // get protocol revision + EProtoRev protrev = GetProtocolRevision(version); + //std::cout << "Adding XLX peer with protocol revision " << protrev << std::endl; + + // and construct all xlx clients + for ( unsigned i = 0; i < ::strlen(modules); i++ ) + { + // create and append to vector + m_Clients.push_back(std::make_shared(callsign, ip, modules[i], protrev)); + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// status + +bool CURFPeer::IsAlive(void) const +{ + return (m_LastKeepaliveTime.time() < URF_KEEPALIVE_TIMEOUT); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// revision helper + +EProtoRev CURFPeer::GetProtocolRevision(const CVersion &/*version*/) +{ + return EProtoRev::urf; +} diff --git a/reflector/URFPeer.h b/reflector/URFPeer.h new file mode 100644 index 0000000..cabe679 --- /dev/null +++ b/reflector/URFPeer.h @@ -0,0 +1,48 @@ +#pragma once + +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// urfd -- The universal reflector +// Copyright © 2021 Thomas A. Early N7TAE +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "Peer.h" +#include "URFClient.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// define + + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CURFPeer : public CPeer +{ +public: + // constructors + CURFPeer(); + CURFPeer(const CCallsign &, const CIp &, const char *, const CVersion &); + CURFPeer(const CURFPeer &) = delete; + + // status + bool IsAlive(void) const; + + // identity + EProtocol GetProtocol(void) const { return EProtocol::urf; } + const char *GetProtocolName(void) const { return "URF"; } + + // revision helper + static EProtoRev GetProtocolRevision(const CVersion &); +}; diff --git a/reflector/URFProtocol.cpp b/reflector/URFProtocol.cpp new file mode 100644 index 0000000..efd8b84 --- /dev/null +++ b/reflector/URFProtocol.cpp @@ -0,0 +1,577 @@ +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// urfd -- The universal reflector +// Copyright © 2021 Thomas A. Early N7TAE +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include +#include "Main.h" +#include "URFPeer.h" +#include "URFProtocol.h" +#include "Reflector.h" +#include "GateKeeper.h" + + +//////////////////////////////////////////////////////////////////////////////////////// +// operation + +bool CURFProtocol::Initialize(const char *type, const EProtocol ptype, const uint16_t port, const bool has_ipv4, const bool has_ipv6) +{ + if (! CProtocol::Initialize(type, ptype, port, has_ipv4, has_ipv6)) + return false; + + // update time + m_LastKeepaliveTime.start(); + m_LastPeersLinkTime.start(); + + // done + return true; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// task + +void CURFProtocol::Task(void) +{ + CBuffer Buffer; + CIp Ip; + CCallsign Callsign; + char Modules[27]; + CVersion Version; + std::unique_ptr Header; + std::unique_ptr Frame; + std::unique_ptr LastFrame; + + // any incoming packet ? +#if XLX_IPV6==true +#if XLX_IPV4==true + if ( ReceiveDS(Buffer, Ip, 20) ) +#else + if ( Receive6(Buffer, Ip, 20) ) +#endif +#else + if ( Receive4(Buffer, Ip, 20) ) +#endif + { + // crack the packet + if ( IsValidDvFramePacket(Buffer, Frame) ) + { + OnDvFramePacketIn(Frame, &Ip); + } + else if ( IsValidDvHeaderPacket(Buffer, Header) ) + { + // callsign allowed? + if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip) ) + { + OnDvHeaderPacketIn(Header, Ip); + } + } + else if ( IsValidConnectPacket(Buffer, &Callsign, Modules, &Version) ) + { + 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, EProtocol::urf, Modules) ) + { + // acknowledge connecting request + // following is version dependent + if (EProtoRev::urf == CURFPeer::GetProtocolRevision(Version)) + { + // already connected ? + CPeers *peers = g_Reflector.GetPeers(); + if ( peers->FindPeer(Callsign, Ip, EProtocol::xlx) == nullptr ) + { + // acknowledge the request + EncodeConnectAckPacket(&Buffer, Modules); + Send(Buffer, Ip); + } + g_Reflector.ReleasePeers(); + + } + else + { + EncodeConnectNackPacket(&Buffer); + Send(Buffer, Ip); + } + } + else + { + // deny the request + EncodeConnectNackPacket(&Buffer); + Send(Buffer, Ip); + } + } + else if ( IsValidAckPacket(Buffer, &Callsign, Modules, &Version) ) + { + std::cout << "XLX ack packet for modules " << Modules << " from " << Callsign << " at " << Ip << std::endl; + + // callsign authorized? + if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::xlx, Modules) ) + { + // already connected ? + CPeers *peers = g_Reflector.GetPeers(); + if ( peers->FindPeer(Callsign, Ip, EProtocol::xlx) == nullptr ) + { + // create the new peer + // this also create one client per module + std::shared_ptrpeer = std::make_shared(Callsign, Ip, Modules, Version); + + // append the peer to reflector peer list + // this also add all new clients to reflector client list + peers->AddPeer(peer); + } + g_Reflector.ReleasePeers(); + } + } + else if ( IsValidDisconnectPacket(Buffer, &Callsign) ) + { + std::cout << "XLX disconnect packet from " << Callsign << " at " << Ip << std::endl; + + // find peer + CPeers *peers = g_Reflector.GetPeers(); + std::shared_ptrpeer = peers->FindPeer(Ip, EProtocol::xlx); + if ( peer != nullptr ) + { + // remove it from reflector peer list + // this also remove all concerned clients from reflector client list + // and delete them + peers->RemovePeer(peer); + } + g_Reflector.ReleasePeers(); + } + else if ( IsValidNackPacket(Buffer, &Callsign) ) + { + std::cout << "XLX nack packet from " << Callsign << " at " << Ip << std::endl; + } + else if ( IsValidKeepAlivePacket(Buffer, &Callsign) ) + { + //std::cout << "XLX keepalive packet from " << Callsign << " at " << Ip << std::endl; + + // find peer + CPeers *peers = g_Reflector.GetPeers(); + std::shared_ptrpeer = peers->FindPeer(Ip, EProtocol::xlx); + if ( peer != nullptr ) + { + // keep it alive + peer->Alive(); + } + g_Reflector.ReleasePeers(); + } + else + { + std::string title("Unknown XLX packet from "); + title += Ip.GetAddress(); + Buffer.Dump(title); + } + } + + // handle end of streaming timeout + CheckStreamsTimeout(); + + // handle queue from reflector + HandleQueue(); + + // keep alive + if ( m_LastKeepaliveTime.time() > URF_KEEPALIVE_PERIOD ) + { + // handle keep alives + HandleKeepalives(); + + // update time + m_LastKeepaliveTime.start(); + } + + // peer connections + if ( m_LastPeersLinkTime.time() > URF_RECONNECT_PERIOD ) + { + // handle remote peers connections + HandlePeerLinks(); + + // update time + m_LastPeersLinkTime.start(); + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// queue helper + +void CURFProtocol::HandleQueue(void) +{ + m_Queue.Lock(); + while ( !m_Queue.empty() ) + { + // get the packet + auto packet = m_Queue.pop(); + + // check if origin of packet is local + // if not, do not stream it out as it will cause + // network loop between linked XLX peers + if ( packet->IsLocalOrigin() ) + { + // encode it + CBuffer buffer; + if ( EncodeDvPacket(*packet, &buffer) ) + { + // and push it to all our clients linked to the module and who are not streaming in + CClients *clients = g_Reflector.GetClients(); + auto it = clients->begin(); + std::shared_ptrclient = nullptr; + while ( (client = clients->FindNextClient(EProtocol::xlx, it)) != nullptr ) + { + // is this client busy ? + if ( !client->IsAMaster() && (client->GetReflectorModule() == packet->GetModule()) ) + { + // no, send the packet + // this is protocol revision dependent + if (EProtoRev::urf == client->GetProtocolRevision()) + { + Send(buffer, client->GetIp()); + } + } + } + g_Reflector.ReleaseClients(); + } + } + } + m_Queue.Unlock(); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// keepalive helpers + +void CURFProtocol::HandleKeepalives(void) +{ + // DExtra protocol sends and monitors keepalives packets + // event if the client is currently streaming + // so, send keepalives to all + CBuffer keepalive; + EncodeKeepAlivePacket(&keepalive); + + // iterate on peers + CPeers *peers = g_Reflector.GetPeers(); + auto pit = peers->begin(); + std::shared_ptrpeer = nullptr; + while ( (peer = peers->FindNextPeer(EProtocol::xlx, pit)) != nullptr ) + { + // send keepalive + Send(keepalive, peer->GetIp()); + + // client busy ? + if ( peer->IsAMaster() ) + { + // yes, just tickle it + peer->Alive(); + } + // otherwise check if still with us + else if ( !peer->IsAlive() ) + { + // no, disconnect + CBuffer disconnect; + EncodeDisconnectPacket(&disconnect); + Send(disconnect, peer->GetIp()); + + // remove it + std::cout << "XLX peer " << peer->GetCallsign() << " keepalive timeout" << std::endl; + peers->RemovePeer(peer); + } + } + g_Reflector.ReleasePeers(); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// Peers helpers + +void CURFProtocol::HandlePeerLinks(void) +{ + CBuffer buffer; + + // get the list of peers + CPeerCallsignList *list = g_GateKeeper.GetPeerList(); + CPeers *peers = g_Reflector.GetPeers(); + + // check if all our connected peers are still listed by gatekeeper + // if not, disconnect + auto pit = peers->begin(); + std::shared_ptrpeer = nullptr; + while ( (peer = peers->FindNextPeer(EProtocol::xlx, pit)) != nullptr ) + { + if ( list->FindListItem(peer->GetCallsign()) == nullptr ) + { + // send disconnect packet + EncodeDisconnectPacket(&buffer); + Send(buffer, peer->GetIp()); + std::cout << "Sending disconnect packet to XLX peer " << peer->GetCallsign() << std::endl; + // remove client + peers->RemovePeer(peer); + } + } + + // check if all ours peers listed by gatekeeper are connected + // if not, connect or reconnect + for ( auto it=list->begin(); it!=list->end(); it++ ) + { + if ( (*it).GetCallsign().HasSameCallsignWithWildcard(CCallsign("XRF*")) ) + continue; + if ( peers->FindPeer((*it).GetCallsign(), EProtocol::xlx) == nullptr ) + { + // resolve again peer's IP in case it's a dynamic IP + (*it).ResolveIp(); + // send connect packet to re-initiate peer link + EncodeConnectPacket(&buffer, (*it).GetModules()); + Send(buffer, (*it).GetIp(), URF_PORT); + std::cout << "Sending connect packet to XLX peer " << (*it).GetCallsign() << " @ " << (*it).GetIp() << " for modules " << (*it).GetModules() << std::endl; + } + } + + // done + g_Reflector.ReleasePeers(); + g_GateKeeper.ReleasePeerList(); +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// streams helpers + +void CURFProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, const CIp &Ip) +{ + CCallsign peer; + + // todo: verify Packet.GetModuleId() is in authorized list of XLX of origin + // todo: do the same for DVFrame and DVLAstFrame packets + + // tag packet as remote peer origin + Header->SetRemotePeerOrigin(); + + // find the stream + auto stream = GetStream(Header->GetStreamId()); + if ( stream ) + { + // stream already open + // skip packet, but tickle the stream + stream->Tickle(); + } + else + { + CCallsign my(Header->GetMyCallsign()); + CCallsign rpt1(Header->GetRpt1Callsign()); + CCallsign rpt2(Header->GetRpt2Callsign()); + // no stream open yet, open a new one + // find this client + std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, EProtocol::xlx, Header->GetRpt2Module()); + if ( client ) + { + // and try to open the stream + if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) + { + // keep the handle + m_Streams.push_back(stream); + } + // get origin + peer = client->GetCallsign(); + } + // release + g_Reflector.ReleaseClients(); + // update last heard + g_Reflector.GetUsers()->Hearing(my, rpt1, rpt2, peer); + g_Reflector.ReleaseUsers(); + } +} + +void CURFProtocol::OnDvFramePacketIn(std::unique_ptr &DvFrame, const CIp *Ip) +{ + // tag packet as remote peer origin + DvFrame->SetRemotePeerOrigin(); + + // and call base class + OnDvFramePacketIn(DvFrame, Ip); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// packet decoding helpers + +bool CURFProtocol::IsValidKeepAlivePacket(const CBuffer &Buffer, CCallsign *callsign) +{ + bool valid = false; + if (Buffer.size() == 9) + { + callsign->SetCallsign(Buffer.data(), 8); + valid = callsign->IsValid(); + } + return valid; +} + + +bool CURFProtocol::IsValidConnectPacket(const CBuffer &Buffer, CCallsign *callsign, char *modules, CVersion *version) +{ + bool valid = false; + uint8_t magic[] = { 'C','O','N','N' }; + if ((Buffer.size() == 40) && (0 == Buffer.Compare(magic, 4)) && (Buffer.data()[36] == 0)) + { + callsign->CodeIn(Buffer.data()+4); + valid = callsign->IsValid(); + *version = CVersion(Buffer.at(37), Buffer.at(38), Buffer.at(39)); + memcpy(modules, Buffer.data()+10, 27); + for ( unsigned i = 0; i < ::strlen(modules), valid; i++ ) + { + valid &= (nullptr != strchr(ACTIVE_MODULES, modules[i])); + } + } + return valid; +} + +bool CURFProtocol::IsValidDisconnectPacket(const CBuffer &Buffer, CCallsign *callsign) +{ + bool valid = false; + uint8_t magic[] = { 'D','I','S','C' }; + if ((Buffer.size() == 10) && (0 == Buffer.Compare(magic, 4))) + { + callsign->CodeIn(Buffer.data()+4); + valid = callsign->IsValid(); + } + return valid; +} + +bool CURFProtocol::IsValidAckPacket(const CBuffer &Buffer, CCallsign *callsign, char *modules, CVersion *version) +{ + bool valid = false; + uint8_t magic[] = { 'A','C','K','N' }; + if ((Buffer.size() == 40) && (0 == Buffer.Compare(magic, 4)) && (Buffer.data()[36] == 0)) + { + callsign->CodeIn(Buffer.data()+4); + valid = callsign->IsValid(); + *version = CVersion(Buffer.at(37), Buffer.at(38), Buffer.at(39)); + memcpy(modules, Buffer.data()+10, 27); + for ( unsigned i = 0; i < ::strlen(modules), valid; i++ ) + { + valid &= (nullptr != strchr(ACTIVE_MODULES, modules[i])); + } + } + return valid; +} + +bool CURFProtocol::IsValidNackPacket(const CBuffer &Buffer, CCallsign *callsign) +{ + bool valid = false; + uint8_t magic[] = { 'N','A','C','K' }; + if ((Buffer.size() == 10) && (0 == Buffer.Compare(magic, 4))) + { + callsign->CodeIn(Buffer.data()+4); + valid = callsign->IsValid(); + } + return valid; +} + +bool CURFProtocol::IsValidDvHeaderPacket(const CBuffer &Buffer, std::unique_ptr &header) +{ + if (sizeof(CDvHeaderPacket) == Buffer.size()) { + header = std::unique_ptr(new CDvHeaderPacket()); + memcpy(header.get(), Buffer.data(), sizeof(CDvHeaderPacket)); + if (header) { + if (header->IsValid()) + return true; + else + header.reset(); + } + } + return false; +} + +bool CURFProtocol::IsValidDvFramePacket(const CBuffer &Buffer, std::unique_ptr &dvframe) +{ + // otherwise try protocol revision 2 + if (sizeof(CDvFramePacket)==Buffer.size()) + { + // create packet + dvframe = std::unique_ptr(new CDvFramePacket()); + memcpy(dvframe.get(), Buffer.data(), sizeof(CDvFramePacket)); + // check validity of packet + if (dvframe) { + if (dvframe->IsValid()) + return true; + else + dvframe.reset(); + } + } + return false; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// packet encoding helpers + +bool CURFProtocol::EncodeDvHeaderPacket(const CDvHeaderPacket &packet, CBuffer *buffer) const +{ + auto len = sizeof(CDvHeaderPacket); + buffer->resize(len); + memcpy(buffer->data(), &packet, len); + return true; +} + +bool CURFProtocol::EncodeDvFramePacket(const CDvFramePacket &packet, CBuffer *buffer) const +{ + auto len = sizeof(CDvFramePacket); + buffer->resize(len); + memcpy(buffer->data(), &packet, len); + return true; +} + +void CURFProtocol::EncodeKeepAlivePacket(CBuffer *Buffer) +{ + Buffer->Set("PING"); + Buffer->resize(10); + g_Reflector.GetCallsign().CodeOut(Buffer->data()+4); +} + +void CURFProtocol::EncodeConnectPacket(CBuffer *Buffer, const char *Modules) +{ + // tag + Buffer->Set("CONN"); + // our callsign + Buffer->resize(37); + g_Reflector.GetCallsign().CodeOut(Buffer->data()+4); + // our version + Buffer->ReplaceAt(10, (uint8_t *)Modules, strlen(Modules)); + Buffer->Append((uint8_t)VERSION_MAJOR); + Buffer->Append((uint8_t)VERSION_MINOR); + Buffer->Append((uint8_t)VERSION_REVISION); +} + +void CURFProtocol::EncodeDisconnectPacket(CBuffer *Buffer) +{ + Buffer->Set("DISC"); + // our callsign + Buffer->resize(10); + g_Reflector.GetCallsign().CodeOut(Buffer->data()+4); +} + +void CURFProtocol::EncodeConnectAckPacket(CBuffer *Buffer, const char *Modules) +{ + Buffer->Set("ACKN"); + // our callsign + Buffer->resize(37); + g_Reflector.GetCallsign().CodeOut(Buffer->data()+4); + // the shared modules + Buffer->ReplaceAt(10, (uint8_t *)Modules, strlen(Modules)); + // our version + Buffer->Append((uint8_t)VERSION_MAJOR); + Buffer->Append((uint8_t)VERSION_MINOR); + Buffer->Append((uint8_t)VERSION_REVISION); +} + +void CURFProtocol::EncodeConnectNackPacket(CBuffer *Buffer) +{ + Buffer->Set("NACK"); + Buffer->resize(10); + g_Reflector.GetCallsign().CodeOut(Buffer->data()+4); +} diff --git a/reflector/URFProtocol.h b/reflector/URFProtocol.h new file mode 100644 index 0000000..1c01c5d --- /dev/null +++ b/reflector/URFProtocol.h @@ -0,0 +1,71 @@ +#pragma once + +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// urfd -- The universal reflector +// Copyright © 2021 Thomas A. Early N7TAE +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "Version.h" +#include "Timer.h" +#include "Protocol.h" +#include "Clients.h" + +class CPeer; + +class CURFProtocol : public CProtocol +{ +public: + // initialization + bool Initialize(const char *type, const EProtocol ptype, const uint16_t port, const bool has_ipv4, const bool has_ipv6); + + // task + void Task(void); + +protected: + // queue helper + void HandleQueue(void); + + // keepalive helpers + void HandlePeerLinks(void); + void HandleKeepalives(void); + + // stream helpers + void OnDvHeaderPacketIn(std::unique_ptr &, const CIp &); + void OnDvFramePacketIn(std::unique_ptr &, const CIp * = nullptr); + + // packet decoding helpers + 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 *); + bool IsValidDvHeaderPacket(const CBuffer &, std::unique_ptr &); + bool IsValidDvFramePacket(const CBuffer &, std::unique_ptr &); + + // packet encoding helpers + void EncodeKeepAlivePacket(CBuffer *); + void EncodeConnectPacket(CBuffer *, const char *); + void EncodeDisconnectPacket(CBuffer *); + void EncodeConnectAckPacket(CBuffer *, const char *); + void EncodeConnectNackPacket(CBuffer *Buffer); + bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const; + bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const; + +protected: + // time + CTimer m_LastKeepaliveTime; + CTimer m_LastPeersLinkTime; +}; diff --git a/reflector/XLXClient.cpp b/reflector/XLXClient.cpp index 8608c2f..fca2166 100644 --- a/reflector/XLXClient.cpp +++ b/reflector/XLXClient.cpp @@ -1,50 +1,77 @@ +// +// cxlxclient.cpp +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 28/01/2016. // Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. - -// urfd -- The universal reflector -// Copyright © 2021 Thomas A. Early N7TAE // -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. +// ---------------------------------------------------------------------------- +// This file is part of xlxd. // -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// 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. // -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// 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 . +// ---------------------------------------------------------------------------- #include #include "Main.h" -#include "URFClient.h" +#include "XLXClient.h" //////////////////////////////////////////////////////////////////////////////////////// // constructors -CURFClient::CURFClient() +CXlxClient::CXlxClient() { - m_ProtRev = EXLXProtocol::m17; + m_ProtRev = EProtoRev::original; } -CURFClient::CURFClient(const CCallsign &callsign, const CIp &ip, char reflectorModule, EXLXProtocol protRev) +CXlxClient::CXlxClient(const CCallsign &callsign, const CIp &ip, char reflectorModule, EProtoRev protRev) : CClient(callsign, ip, reflectorModule) { m_ProtRev = protRev; } -CURFClient::CURFClient(const CURFClient &client) +CXlxClient::CXlxClient(const CXlxClient &client) : CClient(client) { m_ProtRev = client.m_ProtRev; } +//////////////////////////////////////////////////////////////////////////////////////// +// identity + +ECodecType CXlxClient::GetCodec(void) const +{ + ECodecType codec; + + switch ( GetProtocolRevision() ) + { + case EProtoRev::original: + case EProtoRev::revised: + default: + codec = ECodecType::dstar; + break; + case EProtoRev::ambe: + codec = ECodecType::none; + break; + } + return codec; +} + //////////////////////////////////////////////////////////////////////////////////////// // status -bool CURFClient::IsAlive(void) const +bool CXlxClient::IsAlive(void) const { return (m_LastKeepaliveTime.time() < XLX_KEEPALIVE_TIMEOUT); } diff --git a/reflector/XLXClient.h b/reflector/XLXClient.h index 722efb2..7bc96c3 100644 --- a/reflector/XLXClient.h +++ b/reflector/XLXClient.h @@ -1,3 +1,5 @@ +#pragma once + // Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. // urfd -- The universal reflector @@ -16,27 +18,37 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -#pragma once #include "Client.h" -class CURFClient : public CClient +//////////////////////////////////////////////////////////////////////////////////////// +// define + +#define XLX_PROTOCOL_REVISION_0 0 // AMBE only, original connect mechanism +#define XLX_PROTOCOL_REVISION_1 1 // AMBE only, revised connect mechanism +#define XLX_PROTOCOL_REVISION_2 2 // Transcoded AMBE+AMBE2 interlink + + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CXlxClient : public CClient { public: // constructors - CURFClient(); - CURFClient(const CCallsign &, const CIp &, char = ' ', EXLXProtocol = EXLXProtocol::m17); - CURFClient(const CURFClient &); + CXlxClient(); + CXlxClient(const CCallsign &, const CIp &, char = ' ', EProtoRev = EProtoRev::original); + CXlxClient(const CXlxClient &); // destructor - virtual ~CURFClient() {}; + virtual ~CXlxClient() {}; // identity - EProtocol GetProtocol(void) const { return EProtocol::ulx; } - EXLXProtocol GetProtocolRevision(void) const { return m_ProtRev; } - const char *GetProtocolName(void) const { return "XLX"; } - ECodecType GetCodec(void) const { return ECodecType::none; } - bool IsPeer(void) const { return true; } + EProtocol GetProtocol(void) const { return EProtocol::xlx; } + EProtoRev GetProtocolRevision(void) const { return m_ProtRev; } + const char *GetProtocolName(void) const { return "XLX"; } + ECodecType GetCodec(void) const; + bool IsPeer(void) const { return true; } // status bool IsAlive(void) const; @@ -46,5 +58,5 @@ public: protected: // data - EXLXProtocol m_ProtRev; + EProtoRev m_ProtRev; }; diff --git a/reflector/XLXPeer.cpp b/reflector/XLXPeer.cpp index 128924b..d0eeee8 100644 --- a/reflector/XLXPeer.cpp +++ b/reflector/XLXPeer.cpp @@ -1,4 +1,4 @@ -// Copyright © 2016 Jean-Luc Deltombe (LX3JL). All rights reserved. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. // urfd -- The universal reflector // Copyright © 2021 Thomas A. Early N7TAE @@ -16,40 +16,41 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -#include "Main.h" #include + +#include "Main.h" #include "Reflector.h" -#include "URFPeer.h" -#include "URFClient.h" +#include "XLXPeer.h" +#include "XLXClient.h" //////////////////////////////////////////////////////////////////////////////////////// // constructor -CURFPeer::CURFPeer() +CXlxPeer::CXlxPeer() { } -CURFPeer::CURFPeer(const CCallsign &callsign, const CIp &ip, const char *modules, const CVersion &version) +CXlxPeer::CXlxPeer(const CCallsign &callsign, const CIp &ip, const char *modules, const CVersion &version) : CPeer(callsign, ip, modules, version) { // get protocol revision - int protrev = GetProtocolRevision(version); + EProtoRev protrev = GetProtocolRevision(version); //std::cout << "Adding XLX peer with protocol revision " << protrev << std::endl; // and construct all xlx clients for ( unsigned i = 0; i < ::strlen(modules); i++ ) { // create and append to vector - m_Clients.push_back(std::make_shared(callsign, ip, modules[i], protrev)); + m_Clients.push_back(std::make_shared(callsign, ip, modules[i], protrev)); } } //////////////////////////////////////////////////////////////////////////////////////// // status -bool CURFPeer::IsAlive(void) const +bool CXlxPeer::IsAlive(void) const { return (m_LastKeepaliveTime.time() < XLX_KEEPALIVE_TIMEOUT); } @@ -57,17 +58,17 @@ bool CURFPeer::IsAlive(void) const //////////////////////////////////////////////////////////////////////////////////////// // revision helper -int CURFPeer::GetProtocolRevision(const CVersion &version) +EProtoRev CXlxPeer::GetProtocolRevision(const CVersion &version) { - int protrev = XLX_PROTOCOL_REVISION_0; + EProtoRev protrev = EProtoRev::original; if ( version.IsEqualOrHigherTo(CVersion(2,2,0)) ) { - protrev = XLX_PROTOCOL_REVISION_2; + protrev = EProtoRev::ambe; } else if ( version.IsEqualOrHigherTo(CVersion(1,4,0)) ) { - protrev = XLX_PROTOCOL_REVISION_1; + protrev = EProtoRev::revised; } return protrev; } diff --git a/reflector/XLXPeer.h b/reflector/XLXPeer.h index 96b2266..ee7a490 100644 --- a/reflector/XLXPeer.h +++ b/reflector/XLXPeer.h @@ -1,4 +1,6 @@ -/// Copyright © 2016 Jean-Luc Deltombe (LX3JL). All rights reserved. +#pragma once + +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. // urfd -- The universal reflector // Copyright © 2021 Thomas A. Early N7TAE @@ -16,26 +18,24 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -#pragma once - #include "Peer.h" -#include "URFClient.h" +#include "XLXClient.h" -class CURFPeer : public CPeer +class CXlxPeer : public CPeer { public: // constructors - CURFPeer(); - CURFPeer(const CCallsign &, const CIp &, const char *, const CVersion &); - CURFPeer(const CURFPeer &) = delete; + CXlxPeer(); + CXlxPeer(const CCallsign &, const CIp &, const char *, const CVersion &); + CXlxPeer(const CXlxPeer &) = delete; // status bool IsAlive(void) const; // identity - EProtocol GetProtocol(void) const { return EProtocol::ulx; } - const char *GetProtocolName(void) const { return "XLX"; } + EProtocol GetProtocol(void) const { return EProtocol::xlx; } + const char *GetProtocolName(void) const { return "XLX"; } // revision helper - static int GetProtocolRevision(const CVersion &); + static EProtoRev GetProtocolRevision(const CVersion &); }; diff --git a/reflector/XLXProtocol.cpp b/reflector/XLXProtocol.cpp index bc29e67..f02da3b 100644 --- a/reflector/XLXProtocol.cpp +++ b/reflector/XLXProtocol.cpp @@ -16,11 +16,12 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -#include "Main.h" #include -#include "URFPeer.h" + +#include "Main.h" +#include "XLXPeer.h" #include "BMPeer.h" -#include "URFProtocol.h" +#include "XLXProtocol.h" #include "Reflector.h" #include "GateKeeper.h" @@ -28,7 +29,7 @@ //////////////////////////////////////////////////////////////////////////////////////// // operation -bool CURFProtocol::Initialize(const char *type, const EProtocol ptype, const uint16_t port, const bool has_ipv4, const bool has_ipv6) +bool CXlxProtocol::Initialize(const char *type, EProtocol ptype, const uint16_t port, const bool has_ipv4, const bool has_ipv6) { if (! CProtocol::Initialize(type, ptype, port, has_ipv4, has_ipv6)) return false; @@ -44,7 +45,7 @@ bool CURFProtocol::Initialize(const char *type, const EProtocol ptype, const uin //////////////////////////////////////////////////////////////////////////////////////// // task -void CURFProtocol::Task(void) +void CXlxProtocol::Task(void) { CBuffer Buffer; CIp Ip; @@ -53,7 +54,6 @@ void CURFProtocol::Task(void) CVersion Version; std::unique_ptr Header; std::unique_ptr Frame; - std::unique_ptr LastFrame; // any incoming packet ? #if XLX_IPV6==true @@ -79,26 +79,26 @@ void CURFProtocol::Task(void) OnDvHeaderPacketIn(Header, Ip); } } - else if ( IsValidDvLastFramePacket(Buffer, LastFrame) ) + else if ( IsValidDvLastFramePacket(Buffer, Frame) ) { - OnDvLastFramePacketIn(LastFrame, &Ip); + OnDvLastFramePacketIn(Frame, &Ip); } else if ( IsValidConnectPacket(Buffer, &Callsign, Modules, &Version) ) { 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, EProtocol::ulx, Modules) ) + if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::xlx, Modules) ) { // acknowledge connecting request // following is version dependent switch ( GetConnectingPeerProtocolRevision(Callsign, Version) ) { - case XLX_PROTOCOL_REVISION_0: + case EProtoRev::original: { // already connected ? CPeers *peers = g_Reflector.GetPeers(); - if ( peers->FindPeer(Callsign, Ip, EProtocol::ulx) == nullptr ) + if ( peers->FindPeer(Callsign, Ip, EProtocol::xlx) == nullptr ) { // acknowledge the request EncodeConnectAckPacket(&Buffer, Modules); @@ -108,8 +108,8 @@ void CURFProtocol::Task(void) } break; - case XLX_PROTOCOL_REVISION_1: - case XLX_PROTOCOL_REVISION_2: + case EProtoRev::revised: + case EProtoRev::ambe: default: // acknowledge the request EncodeConnectAckPacket(&Buffer, Modules); @@ -129,11 +129,11 @@ void CURFProtocol::Task(void) std::cout << "XLX ack packet for modules " << Modules << " from " << Callsign << " at " << Ip << std::endl; // callsign authorized? - if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::ulx, Modules) ) + if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::xlx, Modules) ) { // already connected ? CPeers *peers = g_Reflector.GetPeers(); - if ( peers->FindPeer(Callsign, Ip, EProtocol::ulx) == nullptr ) + if ( peers->FindPeer(Callsign, Ip, EProtocol::xlx) == nullptr ) { // create the new peer // this also create one client per module @@ -152,7 +152,7 @@ void CURFProtocol::Task(void) // find peer CPeers *peers = g_Reflector.GetPeers(); - std::shared_ptrpeer = peers->FindPeer(Ip, EProtocol::ulx); + std::shared_ptrpeer = peers->FindPeer(Ip, EProtocol::xlx); if ( peer != nullptr ) { // remove it from reflector peer list @@ -172,7 +172,7 @@ void CURFProtocol::Task(void) // find peer CPeers *peers = g_Reflector.GetPeers(); - std::shared_ptrpeer = peers->FindPeer(Ip, EProtocol::ulx); + std::shared_ptrpeer = peers->FindPeer(Ip, EProtocol::xlx); if ( peer != nullptr ) { // keep it alive @@ -218,7 +218,7 @@ void CURFProtocol::Task(void) //////////////////////////////////////////////////////////////////////////////////////// // queue helper -void CURFProtocol::HandleQueue(void) +void CXlxProtocol::HandleQueue(void) { m_Queue.Lock(); while ( !m_Queue.empty() ) @@ -246,7 +246,7 @@ void CURFProtocol::HandleQueue(void) CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; - while ( (client = clients->FindNextClient(EProtocol::ulx, it)) != nullptr ) + while ( (client = clients->FindNextClient(EProtocol::xlx, it)) != nullptr ) { // is this client busy ? if ( !client->IsAMaster() && (client->GetReflectorModule() == packet->GetModule()) ) @@ -255,13 +255,13 @@ void CURFProtocol::HandleQueue(void) // this is protocol revision dependent switch ( client->GetProtocolRevision() ) { - case XLX_PROTOCOL_REVISION_0: - case XLX_PROTOCOL_REVISION_1: + case EProtoRev::original: + case EProtoRev::revised: Send(bufferLegacy, client->GetIp()); break; - case XLX_PROTOCOL_REVISION_2: + case EProtoRev::ambe: default: -#ifdef TRANSCODER_IP +#ifdef TRANSCODED_MODULES if ( g_Transcoder.IsConnected() ) { Send(buffer, client->GetIp()); @@ -285,7 +285,7 @@ void CURFProtocol::HandleQueue(void) //////////////////////////////////////////////////////////////////////////////////////// // keepalive helpers -void CURFProtocol::HandleKeepalives(void) +void CXlxProtocol::HandleKeepalives(void) { // DExtra protocol sends and monitors keepalives packets // event if the client is currently streaming @@ -297,7 +297,7 @@ void CURFProtocol::HandleKeepalives(void) CPeers *peers = g_Reflector.GetPeers(); auto pit = peers->begin(); std::shared_ptrpeer = nullptr; - while ( (peer = peers->FindNextPeer(EProtocol::ulx, pit)) != nullptr ) + while ( (peer = peers->FindNextPeer(EProtocol::xlx, pit)) != nullptr ) { // send keepalive Send(keepalive, peer->GetIp()); @@ -327,7 +327,7 @@ void CURFProtocol::HandleKeepalives(void) //////////////////////////////////////////////////////////////////////////////////////// // Peers helpers -void CURFProtocol::HandlePeerLinks(void) +void CXlxProtocol::HandlePeerLinks(void) { CBuffer buffer; @@ -339,7 +339,7 @@ void CURFProtocol::HandlePeerLinks(void) // if not, disconnect auto pit = peers->begin(); std::shared_ptrpeer = nullptr; - while ( (peer = peers->FindNextPeer(EProtocol::ulx, pit)) != nullptr ) + while ( (peer = peers->FindNextPeer(EProtocol::xlx, pit)) != nullptr ) { if ( list->FindListItem(peer->GetCallsign()) == nullptr ) { @@ -358,7 +358,7 @@ void CURFProtocol::HandlePeerLinks(void) { if ( (*it).GetCallsign().HasSameCallsignWithWildcard(CCallsign("XRF*")) ) continue; - if ( peers->FindPeer((*it).GetCallsign(), EProtocol::ulx) == nullptr ) + if ( peers->FindPeer((*it).GetCallsign(), EProtocol::xlx) == nullptr ) { // resolve again peer's IP in case it's a dynamic IP (*it).ResolveIp(); @@ -378,7 +378,7 @@ void CURFProtocol::HandlePeerLinks(void) //////////////////////////////////////////////////////////////////////////////////////// // streams helpers -void CURFProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, const CIp &Ip) +void CXlxProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, const CIp &Ip) { CCallsign peer; @@ -403,7 +403,7 @@ void CURFProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, CCallsign rpt2(Header->GetRpt2Callsign()); // no stream open yet, open a new one // find this client - std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, EProtocol::ulx, Header->GetRpt2Module()); + std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, EProtocol::xlx, Header->GetRpt2Module()); if ( client ) { // and try to open the stream @@ -423,7 +423,7 @@ void CURFProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, } } -void CURFProtocol::OnDvFramePacketIn(std::unique_ptr &DvFrame, const CIp *Ip) +void CXlxProtocol::OnDvFramePacketIn(std::unique_ptr &DvFrame, const CIp *Ip) { // tag packet as remote peer origin DvFrame->SetRemotePeerOrigin(); @@ -432,20 +432,20 @@ void CURFProtocol::OnDvFramePacketIn(std::unique_ptr &DvFrame, c CDextraProtocol::OnDvFramePacketIn(DvFrame, Ip); } -void CURFProtocol::OnDvLastFramePacketIn(std::unique_ptr &DvFrame, const CIp *Ip) +void CXlxProtocol::OnDvLastFramePacketIn(std::unique_ptr &DvFrame, const CIp *Ip) { // tag packet as remote peer origin DvFrame->SetRemotePeerOrigin(); // anc call base class - CDextraProtocol::OnDvLastFramePacketIn(DvFrame, Ip); + CDextraProtocol::OnDvFramePacketIn(DvFrame, Ip); } //////////////////////////////////////////////////////////////////////////////////////// // packet decoding helpers -bool CURFProtocol::IsValidKeepAlivePacket(const CBuffer &Buffer, CCallsign *callsign) +bool CXlxProtocol::IsValidKeepAlivePacket(const CBuffer &Buffer, CCallsign *callsign) { bool valid = false; if (Buffer.size() == 9) @@ -457,7 +457,7 @@ bool CURFProtocol::IsValidKeepAlivePacket(const CBuffer &Buffer, CCallsign *call } -bool CURFProtocol::IsValidConnectPacket(const CBuffer &Buffer, CCallsign *callsign, char *modules, CVersion *version) +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)) @@ -474,7 +474,7 @@ bool CURFProtocol::IsValidConnectPacket(const CBuffer &Buffer, CCallsign *callsi return valid; } -bool CURFProtocol::IsValidDisconnectPacket(const CBuffer &Buffer, CCallsign *callsign) +bool CXlxProtocol::IsValidDisconnectPacket(const CBuffer &Buffer, CCallsign *callsign) { bool valid = false; if ((Buffer.size() == 10) && (Buffer.data()[0] == 'U') && (Buffer.data()[9] == 0)) @@ -485,7 +485,7 @@ bool CURFProtocol::IsValidDisconnectPacket(const CBuffer &Buffer, CCallsign *cal return valid; } -bool CURFProtocol::IsValidAckPacket(const CBuffer &Buffer, CCallsign *callsign, char *modules, CVersion *version) +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)) @@ -502,7 +502,7 @@ bool CURFProtocol::IsValidAckPacket(const CBuffer &Buffer, CCallsign *callsign, return valid; } -bool CURFProtocol::IsValidNackPacket(const CBuffer &Buffer, CCallsign *callsign) +bool CXlxProtocol::IsValidNackPacket(const CBuffer &Buffer, CCallsign *callsign) { bool valid = false; if ((Buffer.size() == 10) && (Buffer.data()[0] == 'N') && (Buffer.data()[9] == 0)) @@ -513,7 +513,7 @@ bool CURFProtocol::IsValidNackPacket(const CBuffer &Buffer, CCallsign *callsign) return valid; } -bool CURFProtocol::IsValidDvFramePacket(const CBuffer &Buffer, std::unique_ptr &dvframe) +bool CXlxProtocol::IsValidDvFramePacket(const CBuffer &Buffer, std::unique_ptr &dvframe) { // base class first (protocol revision 1 and lower) if (CDextraProtocol::IsValidDvFramePacket(Buffer, dvframe)) @@ -529,7 +529,8 @@ bool CURFProtocol::IsValidDvFramePacket(const CBuffer &Buffer, std::unique_ptrIsValid() ) @@ -538,23 +539,24 @@ bool CURFProtocol::IsValidDvFramePacket(const CBuffer &Buffer, std::unique_ptr &dvframe) +bool CXlxProtocol::IsValidDvLastFramePacket(const CBuffer &Buffer, std::unique_ptr &dvframe) { // base class first (protocol revision 1 and lower) - if (CDextraProtocol::IsValidDvLastFramePacket(Buffer, dvframe)) + if (CDextraProtocol::IsValidDvFramePacket(Buffer, dvframe)) return true; // otherwise try protocol revision 2 if ( 45==Buffer.size() && 0==Buffer.Compare((uint8_t *)"DSVT", 4) && 0x20U==Buffer.data()[4] && 0x20U==Buffer.data()[8] && (Buffer.data()[14] & 0x40U) ) { // create packet - dvframe = std::unique_ptr(new CDvLastFramePacket( + dvframe = std::unique_ptr(new CDvFramePacket( // sid *((uint16_t *)&(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]))); + Buffer.data()[27], Buffer.data()[28], &(Buffer.data()[29]), &(Buffer.data()[38]), + ECodecType::dmr, true)); // check validity of packet if ( dvframe && dvframe->IsValid() ) @@ -566,12 +568,12 @@ bool CURFProtocol::IsValidDvLastFramePacket(const CBuffer &Buffer, std::unique_p //////////////////////////////////////////////////////////////////////////////////////// // packet encoding helpers -void CURFProtocol::EncodeKeepAlivePacket(CBuffer *Buffer) +void CXlxProtocol::EncodeKeepAlivePacket(CBuffer *Buffer) { Buffer->Set(GetReflectorCallsign()); } -void CURFProtocol::EncodeConnectPacket(CBuffer *Buffer, const char *Modules) +void CXlxProtocol::EncodeConnectPacket(CBuffer *Buffer, const char *Modules) { uint8_t tag[] = { 'L' }; @@ -589,7 +591,7 @@ void CURFProtocol::EncodeConnectPacket(CBuffer *Buffer, const char *Modules) Buffer->resize(39); } -void CURFProtocol::EncodeDisconnectPacket(CBuffer *Buffer) +void CXlxProtocol::EncodeDisconnectPacket(CBuffer *Buffer) { uint8_t tag[] = { 'U' }; @@ -601,7 +603,7 @@ void CURFProtocol::EncodeDisconnectPacket(CBuffer *Buffer) Buffer->Append((uint8_t)0); } -void CURFProtocol::EncodeConnectAckPacket(CBuffer *Buffer, const char *Modules) +void CXlxProtocol::EncodeConnectAckPacket(CBuffer *Buffer, const char *Modules) { uint8_t tag[] = { 'A' }; @@ -619,7 +621,7 @@ void CURFProtocol::EncodeConnectAckPacket(CBuffer *Buffer, const char *Modules) Buffer->resize(39); } -void CURFProtocol::EncodeConnectNackPacket(CBuffer *Buffer) +void CXlxProtocol::EncodeConnectNackPacket(CBuffer *Buffer) { uint8_t tag[] = { 'N' }; @@ -631,26 +633,26 @@ void CURFProtocol::EncodeConnectNackPacket(CBuffer *Buffer) Buffer->Append((uint8_t)0); } -bool CURFProtocol::EncodeDvFramePacket(const CDvFramePacket &Packet, CBuffer *Buffer) const +bool CXlxProtocol::EncodeDvFramePacket(const CDvFramePacket &Packet, CBuffer *Buffer) const { uint8_t 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_t)(Packet.GetDstarPacketId() % 21)); - Buffer->Append((uint8_t *)Packet.GetAmbe(), 9); + Buffer->Append((uint8_t *)Packet.GetCodecData(ECodecType::dstar), 9); Buffer->Append((uint8_t *)Packet.GetDvData(), 3); Buffer->Append((uint8_t)Packet.GetDmrPacketId()); Buffer->Append((uint8_t)Packet.GetDmrPacketSubid()); - Buffer->Append((uint8_t *)Packet.GetAmbePlus(), 9); + Buffer->Append((uint8_t *)Packet.GetCodecData(ECodecType::dmr), 9); Buffer->Append((uint8_t *)Packet.GetDvSync(), 7); return true; } -bool CURFProtocol::EncodeDvLastFramePacket(const CDvLastFramePacket &Packet, CBuffer *Buffer) const +bool CXlxProtocol::EncodeDvLastFramePacket(const CDvFramePacket &Packet, CBuffer *Buffer) const { uint8_t tag[] = { 'D','S','V','T',0x20,0x00,0x00,0x00,0x20,0x00,0x01,0x02 }; uint8_t dstarambe[] = { 0x55,0xC8,0x7A,0x00,0x00,0x00,0x00,0x00,0x00 }; @@ -665,7 +667,7 @@ bool CURFProtocol::EncodeDvLastFramePacket(const CDvLastFramePacket &Packet, CBu Buffer->Append((uint8_t)Packet.GetDmrPacketId()); Buffer->Append((uint8_t)Packet.GetDmrPacketSubid()); - Buffer->Append((uint8_t *)Packet.GetAmbePlus(), 9); + Buffer->Append((uint8_t *)Packet.GetCodecData(ECodecType::dmr), 9); Buffer->Append((uint8_t *)Packet.GetDvSync(), 7); return true; @@ -674,9 +676,9 @@ bool CURFProtocol::EncodeDvLastFramePacket(const CDvLastFramePacket &Packet, CBu //////////////////////////////////////////////////////////////////////////////////////// // protocol revision helper -int CURFProtocol::GetConnectingPeerProtocolRevision(const CCallsign &Callsign, const CVersion &Version) +EProtoRev CXlxProtocol::GetConnectingPeerProtocolRevision(const CCallsign &Callsign, const CVersion &Version) { - int protrev; + EProtoRev protrev; // BM ? if ( Callsign.HasSameCallsignWithWildcard(CCallsign("BM*")) ) @@ -686,14 +688,14 @@ int CURFProtocol::GetConnectingPeerProtocolRevision(const CCallsign &Callsign, c // otherwise, assume native xlx else { - protrev = CURFPeer::GetProtocolRevision(Version); + protrev = CXlxPeer::GetProtocolRevision(Version); } // done return protrev; } -std::shared_ptr CURFProtocol::CreateNewPeer(const CCallsign &Callsign, const CIp &Ip, char *Modules, const CVersion &Version) +std::shared_ptr CXlxProtocol::CreateNewPeer(const CCallsign &Callsign, const CIp &Ip, char *Modules, const CVersion &Version) { // BM ? if ( Callsign.HasSameCallsignWithWildcard(CCallsign("BM*")) ) @@ -702,6 +704,6 @@ std::shared_ptr CURFProtocol::CreateNewPeer(const CCallsign &Callsign, co } else { - return std::make_shared(Callsign, Ip, Modules, Version); + return std::make_shared(Callsign, Ip, Modules, Version); } } diff --git a/reflector/XLXProtocol.h b/reflector/XLXProtocol.h index 10544ba..f312f64 100644 --- a/reflector/XLXProtocol.h +++ b/reflector/XLXProtocol.h @@ -1,3 +1,5 @@ +#pragma once + // Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. // urfd -- The universal reflector @@ -16,8 +18,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -#pragma once - #include "Version.h" #include "Timer.h" #include "DExtraProtocol.h" @@ -30,11 +30,11 @@ class CPeer; //////////////////////////////////////////////////////////////////////////////////////// // class -class CURFProtocol : public CDextraProtocol +class CXlxProtocol : public CDextraProtocol { public: // initialization - bool Initialize(const char *type, const EProtocol ptype, const uint16_t port, const bool has_ipv4, const bool has_ipv6); + bool Initialize(const char *type, EProtocol ptype, const uint16_t port, const bool has_ipv4, const bool has_ipv6); // task void Task(void); @@ -50,7 +50,7 @@ protected: // stream helpers void OnDvHeaderPacketIn(std::unique_ptr &, const CIp &); void OnDvFramePacketIn(std::unique_ptr &, const CIp * = nullptr); - void OnDvLastFramePacketIn(std::unique_ptr &, const CIp * = nullptr); + void OnDvLastFramePacketIn(std::unique_ptr &, const CIp * = nullptr); // packet decoding helpers bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *); @@ -59,7 +59,7 @@ protected: bool IsValidAckPacket(const CBuffer &, CCallsign *, char *, CVersion *); bool IsValidNackPacket(const CBuffer &, CCallsign *); bool IsValidDvFramePacket(const CBuffer &, std::unique_ptr &); - bool IsValidDvLastFramePacket(const CBuffer &, std::unique_ptr &); + bool IsValidDvLastFramePacket(const CBuffer &, std::unique_ptr &); // packet encoding helpers void EncodeKeepAlivePacket(CBuffer *); @@ -68,10 +68,10 @@ protected: void EncodeConnectAckPacket(CBuffer *, const char *); void EncodeConnectNackPacket(CBuffer *); bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const; - bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const; + bool EncodeDvLastFramePacket(const CDvFramePacket &, CBuffer *) const; // protocol revision helper - int GetConnectingPeerProtocolRevision(const CCallsign &, const CVersion &); + EProtoRev GetConnectingPeerProtocolRevision(const CCallsign &, const CVersion &); std::shared_ptrCreateNewPeer(const CCallsign &, const CIp &, char *, const CVersion &); protected: diff --git a/reflector/YSFProtocol.cpp b/reflector/YSFProtocol.cpp index a75fbd1..6a6a49a 100644 --- a/reflector/YSFProtocol.cpp +++ b/reflector/YSFProtocol.cpp @@ -79,7 +79,7 @@ void CYsfProtocol::Task(void) std::unique_ptr Header; std::array, 5> Frames; std::unique_ptr OneFrame; - std::unique_ptr LastFrame; + std::unique_ptr LastFrame; // handle outgoing packets { @@ -130,7 +130,7 @@ void CYsfProtocol::Task(void) else if ( IsValidDvLastFramePacket(Ip, Fich, Buffer, OneFrame, LastFrame) ) { OnDvFramePacketIn(OneFrame, &Ip); - OnDvLastFramePacketIn(LastFrame, &Ip); + OnDvFramePacketIn(LastFrame, &Ip); } } else if ( IsValidConnectPacket(Buffer, &Callsign) ) @@ -445,8 +445,8 @@ bool CYsfProtocol::IsValidDvHeaderPacket(const CIp &Ip, const CYSFFICH &Fich, co { uint8_t uiAmbe[9]; memset(uiAmbe, 0x00, sizeof(uiAmbe)); - frames[0] = std::unique_ptr(new CDvFramePacket(uiAmbe, uiStreamId, Fich.getFN(), 0, 0)); - frames[1] = std::unique_ptr(new CDvFramePacket(uiAmbe, uiStreamId, Fich.getFN(), 1, 0)); + frames[0] = std::unique_ptr(new CDvFramePacket(uiAmbe, uiStreamId, Fich.getFN(), 0, 0, false)); + frames[1] = std::unique_ptr(new CDvFramePacket(uiAmbe, uiStreamId, Fich.getFN(), 1, 0, false)); } // check validity of packets @@ -476,11 +476,11 @@ bool CYsfProtocol::IsValidDvFramePacket(const CIp &Ip, const CYSFFICH &Fich, con // get DV frames uint8_t fid = Buffer.data()[34]; - frames[0] = std::unique_ptr(new CDvFramePacket(ambe0, uiStreamId, Fich.getFN(), 0, fid)); - frames[1] = std::unique_ptr(new CDvFramePacket(ambe1, uiStreamId, Fich.getFN(), 1, fid)); - frames[2] = std::unique_ptr(new CDvFramePacket(ambe2, uiStreamId, Fich.getFN(), 2, fid)); - frames[3] = std::unique_ptr(new CDvFramePacket(ambe3, uiStreamId, Fich.getFN(), 3, fid)); - frames[4] = std::unique_ptr(new CDvFramePacket(ambe4, uiStreamId, Fich.getFN(), 4, fid)); + frames[0] = std::unique_ptr(new CDvFramePacket(ambe0, uiStreamId, Fich.getFN(), 0, fid, false)); + frames[1] = std::unique_ptr(new CDvFramePacket(ambe1, uiStreamId, Fich.getFN(), 1, fid, false)); + frames[2] = std::unique_ptr(new CDvFramePacket(ambe2, uiStreamId, Fich.getFN(), 2, fid, false)); + frames[3] = std::unique_ptr(new CDvFramePacket(ambe3, uiStreamId, Fich.getFN(), 3, fid, false)); + frames[4] = std::unique_ptr(new CDvFramePacket(ambe4, uiStreamId, Fich.getFN(), 4, fid, false)); // check validity of packets if ( frames[0] && frames[0]->IsValid() && frames[1] && frames[1]->IsValid() && frames[2] && frames[2]->IsValid() && frames[3] && frames[3]->IsValid() && frames[4] && frames[4]->IsValid() ) @@ -489,7 +489,7 @@ bool CYsfProtocol::IsValidDvFramePacket(const CIp &Ip, const CYSFFICH &Fich, con return false; } -bool CYsfProtocol::IsValidDvLastFramePacket(const CIp &Ip, const CYSFFICH &Fich, const CBuffer &Buffer, std::unique_ptr &oneframe, std::unique_ptr &lastframe) +bool CYsfProtocol::IsValidDvLastFramePacket(const CIp &Ip, const CYSFFICH &Fich, const CBuffer &Buffer, std::unique_ptr &oneframe, std::unique_ptr &lastframe) { // DV header ? if ( Fich.getFI() == YSF_FI_TERMINATOR ) @@ -501,8 +501,8 @@ bool CYsfProtocol::IsValidDvLastFramePacket(const CIp &Ip, const CYSFFICH &Fich, { uint8_t uiAmbe[9]; memset(uiAmbe, 0x00, sizeof(uiAmbe)); - oneframe = std::unique_ptr(new CDvFramePacket(uiAmbe, uiStreamId, Fich.getFN(), 0, 0)); - lastframe = std::unique_ptr(new CDvLastFramePacket(uiAmbe, uiStreamId, Fich.getFN(), 1, 0)); + oneframe = std::unique_ptr(new CDvFramePacket(uiAmbe, uiStreamId, Fich.getFN(), 0, 0, false)); + lastframe = std::unique_ptr(new CDvFramePacket(uiAmbe, uiStreamId, Fich.getFN(), 1, 0, true)); } // check validity of packets diff --git a/reflector/YSFProtocol.h b/reflector/YSFProtocol.h index 0bb1d8f..27e9d3f 100644 --- a/reflector/YSFProtocol.h +++ b/reflector/YSFProtocol.h @@ -19,10 +19,9 @@ #pragma once #include "Timer.h" -#include "DCSProtocol.h" +#include "Protocol.h" #include "DVHeaderPacket.h" #include "DVFramePacket.h" -#include "DVLastFramePacket.h" #include "YSFDefines.h" #include "YSFFich.h" #include "WiresXInfo.h" @@ -87,7 +86,7 @@ protected: bool IsValidDvPacket(const CBuffer &, CYSFFICH *); bool IsValidDvHeaderPacket(const CIp &, const CYSFFICH &, const CBuffer &, std::unique_ptr &, std::array, 5> &); bool IsValidDvFramePacket(const CIp &, const CYSFFICH &, const CBuffer &, std::array, 5> &); - bool IsValidDvLastFramePacket(const CIp &, const CYSFFICH &, const CBuffer &, std::unique_ptr &, std::unique_ptr &); + bool IsValidDvLastFramePacket(const CIp &, const CYSFFICH &, const CBuffer &, std::unique_ptr &, std::unique_ptr &); // DV packet encoding helpers void EncodeConnectAckPacket(CBuffer *) const;