Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions reflector/Buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ void CBuffer::ReplaceAt(int i, const uint8_t *ptr, int len)
////////////////////////////////////////////////////////////////////////////////////////
// operation

int CBuffer::Compare(uint8_t *buffer, int len) const
int CBuffer::Compare(const uint8_t *buffer, int len) const
{
int result = -1;
if ( m_data.size() >= unsigned(len) )
Expand All @@ -134,7 +134,7 @@ int CBuffer::Compare(uint8_t *buffer, int len) const
return result;
}

int CBuffer::Compare(uint8_t *buffer, int off, int len) const
int CBuffer::Compare(const uint8_t *buffer, int off, int len) const
{
int result = -1;
if ( m_data.size() >= unsigned(off+len) )
Expand Down
4 changes: 2 additions & 2 deletions reflector/Buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ class CBuffer
void ReplaceAt(int, const uint8_t *, int);

// operation
int Compare(uint8_t *, int) const;
int Compare(uint8_t *, int, int) const;
int Compare(const uint8_t *, int) const;
int Compare(const uint8_t *, int, int) const;

// operator
bool operator ==(const CBuffer &) const;
Expand Down
3 changes: 1 addition & 2 deletions reflector/Callsign.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,9 @@ bool CCallsign::IsValid(void) const
}
}
valid = valid && (iNum < 3);
// all remaining char are letter, number or space
for ( ; i < CALLSIGN_LEN; i++)
{
valid = valid && (IsLetter(m_Callsign.c[i]) || IsNumber(m_Callsign.c[i]) || IsSpace(m_Callsign.c[i]));
valid = valid && (IsLetter(m_Callsign.c[i]) || IsNumber(m_Callsign.c[i]) || IsSpace(m_Callsign.c[i]) || m_Callsign.c[i] == '-' || m_Callsign.c[i] == '.' || m_Callsign.c[i] == '/');
}

// prefix
Expand Down
8 changes: 8 additions & 0 deletions reflector/Configure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
#define JIPV6EXTERNAL "IPv6External"
#define JJSONPATH "JsonPath"
#define JM17 "M17"
#define JM17LEGACYCOMPAT "M17LegacyCompat"
#define JMMDVM "MMDVM"
#define JMODE "Mode"
#define JMODULE "Module"
Expand Down Expand Up @@ -368,6 +369,8 @@ bool CConfigure::ReadData(const std::string &path)
case ESection::m17:
if (0 == key.compare(JPORT))
data[g_Keys.m17.port] = getUnsigned(value, "M17 Port", 1024, 65535, 17000);
else if (0 == key.compare(JM17LEGACYCOMPAT))
data[g_Keys.m17.compat] = IS_TRUE(value[0]);
else
badParam(key);
break;
Expand Down Expand Up @@ -684,6 +687,11 @@ bool CConfigure::ReadData(const std::string &path)
isDefined(ErrorLevel::fatal, JDMRPLUS, JPORT, g_Keys.dmrplus.port, rval);
isDefined(ErrorLevel::fatal, JDPLUS, JPORT, g_Keys.dplus.port, rval);
isDefined(ErrorLevel::fatal, JM17, JPORT, g_Keys.m17.port, rval);
if (data.contains(g_Keys.m17.compat))
data[g_Keys.m17.compat] = GetBoolean(g_Keys.m17.compat);
else
data[g_Keys.m17.compat] = true; // Default to Legacy Mode (54 bytes) for compatibility

isDefined(ErrorLevel::fatal, JURF, JPORT, g_Keys.urf.port, rval);

// BM
Expand Down
9 changes: 6 additions & 3 deletions reflector/JsonKeys.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@ struct SJsonKeys {
dcs { "DCSPort" },
dextra { "DExtraPort" },
dmrplus { "DMRPlusPort" },
dplus { "DPlusPort" },
m17 { "M17Port" },
urf { "URFPort" };
dplus { "DPlusPort" };

struct { const std::string port, compat; }
m17 { "M17Port", "M17LegacyCompat" };

PORTONLY urf { "URFPort" };

struct G3 { const std::string enable; }
g3 { "G3Enable" };
Expand Down
7 changes: 4 additions & 3 deletions reflector/M17Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,17 @@
// constructors

CM17Client::CM17Client()
: m_IsListenOnly(false)
{
}

CM17Client::CM17Client(const CCallsign &callsign, const CIp &ip, char reflectorModule)
: CClient(callsign, ip, reflectorModule)
CM17Client::CM17Client(const CCallsign &callsign, const CIp &ip, char reflectorModule, bool isListenOnly)
: CClient(callsign, ip, reflectorModule), m_IsListenOnly(isListenOnly)
{
}

CM17Client::CM17Client(const CM17Client &client)
: CClient(client)
: CClient(client), m_IsListenOnly(client.m_IsListenOnly)
{
}

Expand Down
6 changes: 5 additions & 1 deletion reflector/M17Client.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class CM17Client : public CClient
public:
// constructors
CM17Client();
CM17Client(const CCallsign &, const CIp &, char);
CM17Client(const CCallsign &, const CIp &, char, bool isListenOnly = false);
CM17Client(const CM17Client &);

// destructor
Expand All @@ -37,6 +37,10 @@ class CM17Client : public CClient

// status
bool IsAlive(void) const;
bool IsListenOnly(void) const { return m_IsListenOnly; }

private:
bool m_IsListenOnly;
};

////////////////////////////////////////////////////////////////////////////////////////
122 changes: 108 additions & 14 deletions reflector/M17Packet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,21 @@

#include "M17Packet.h"

CM17Packet::CM17Packet(const uint8_t *buf)
CM17Packet::CM17Packet(const uint8_t *buf, bool isStandard)
: m_isStandard(isStandard)
{
memcpy(m17.magic, buf, sizeof(SM17Frame));

destination.CodeIn(m17.lich.addr_dst);
source.CodeIn(m17.lich.addr_src);
if (m_isStandard)
{
memcpy(m_frame.buffer, buf, sizeof(SM17FrameStandard));
destination.CodeIn(m_frame.standard.lich.addr_dst);
source.CodeIn(m_frame.standard.lich.addr_src);
}
else
{
memcpy(m_frame.buffer, buf, sizeof(SM17FrameLegacy));
destination.CodeIn(m_frame.legacy.lich.addr_dst);
source.CodeIn(m_frame.legacy.lich.addr_src);
}
}

const CCallsign &CM17Packet::GetDestCallsign() const
Expand All @@ -46,45 +55,130 @@ char CM17Packet::GetDestModule() const

uint16_t CM17Packet::GetFrameNumber() const
{
return ntohs(m17.framenumber);
if (m_isStandard)
return ntohs(m_frame.standard.framenumber);
else
return ntohs(m_frame.legacy.framenumber);
}

uint16_t CM17Packet::GetFrameType() const
{
return ntohs(m17.lich.frametype);
if (m_isStandard)
return ntohs(m_frame.standard.lich.frametype);
else
return ntohs(m_frame.legacy.lich.frametype);
}

const uint8_t *CM17Packet::GetPayload() const
{
return m17.payload;
if (m_isStandard)
return m_frame.standard.payload;
else
return m_frame.legacy.payload;
}

const uint8_t *CM17Packet::GetNonce() const
{
return m17.lich.nonce;
if (m_isStandard)
return m_frame.standard.lich.nonce;
else
return m_frame.legacy.lich.nonce;
}

void CM17Packet::SetPayload(const uint8_t *newpayload)
{
memcpy(m17.payload, newpayload, 16);
if (m_isStandard)
memcpy(m_frame.standard.payload, newpayload, 16);
else
memcpy(m_frame.legacy.payload, newpayload, 16);
}

uint16_t CM17Packet::GetStreamId() const
{
return ntohs(m17.streamid);
if (m_isStandard)
return ntohs(m_frame.standard.streamid);
else
return ntohs(m_frame.legacy.streamid);
}

uint16_t CM17Packet::GetCRC() const
{
return ntohs(m17.crc);
if (m_isStandard)
return ntohs(m_frame.standard.crc);
else
return ntohs(m_frame.legacy.crc);
}

void CM17Packet::SetCRC(uint16_t crc)
{
m17.crc = htons(crc);
if (m_isStandard)
m_frame.standard.crc = htons(crc);
else
m_frame.legacy.crc = htons(crc);
}

void CM17Packet::SetDestCallsign(const CCallsign &cs)
{
destination = cs;
if (m_isStandard)
destination.CodeOut(m_frame.standard.lich.addr_dst);
else
destination.CodeOut(m_frame.legacy.lich.addr_dst);
}

void CM17Packet::SetSourceCallsign(const CCallsign &cs)
{
source = cs;
if (m_isStandard)
source.CodeOut(m_frame.standard.lich.addr_src);
else
source.CodeOut(m_frame.legacy.lich.addr_src);
}

void CM17Packet::SetStreamId(uint16_t id)
{
if (m_isStandard)
m_frame.standard.streamid = htons(id);
else
m_frame.legacy.streamid = htons(id);
}

void CM17Packet::SetFrameNumber(uint16_t fn)
{
if (m_isStandard)
m_frame.standard.framenumber = htons(fn);
else
m_frame.legacy.framenumber = htons(fn);
}

void CM17Packet::SetFrameType(uint16_t ft)
{
if (m_isStandard)
m_frame.standard.lich.frametype = htons(ft);
else
m_frame.legacy.lich.frametype = htons(ft);
}

void CM17Packet::SetMagic()
{
if (m_isStandard)
memcpy(m_frame.standard.magic, "M17 ", 4);
else
memcpy(m_frame.legacy.magic, "M17 ", 4);
}

void CM17Packet::SetNonce(const uint8_t *nonce)
{
if (m_isStandard)
memcpy(m_frame.standard.lich.nonce, nonce, 14);
else
memcpy(m_frame.legacy.lich.nonce, nonce, 14);
}

bool CM17Packet::IsLastPacket() const
{
return ((0x8000u & ntohs(m17.framenumber)) == 0x8000u);
if (m_isStandard)
return ((0x8000u & ntohs(m_frame.standard.framenumber)) == 0x8000u);
else
return ((0x8000u & ntohs(m_frame.legacy.framenumber)) == 0x8000u);
}
50 changes: 45 additions & 5 deletions reflector/M17Packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,42 @@

// M17 Packets
//all structures must be big endian on the wire, so you'll want htonl (man byteorder 3) and such.
using SM17Lich = struct __attribute__((__packed__)) lich_tag {
using SM17LichLegacy = struct __attribute__((__packed__)) lich_tag {
uint8_t addr_dst[6];
uint8_t addr_src[6];
uint16_t frametype; //frametype flag field per the M17 spec
uint8_t nonce[14]; //bytes for the nonce
}; // 6 + 6 + 2 + 14 = 28 bytes

// Standard LICH includes CRC
using SM17LichStandard = struct __attribute__((__packed__)) lich_std_tag {
uint8_t addr_dst[6];
uint8_t addr_src[6];
uint16_t frametype;
uint8_t nonce[14];
uint16_t crc;
}; // 6 + 6 + 2 + 14 + 2 = 30 bytes

//without SYNC or other parts
using SM17Frame = struct __attribute__((__packed__)) m17_tag {
using SM17FrameLegacy = struct __attribute__((__packed__)) m17_tag {
uint8_t magic[4];
uint16_t streamid;
SM17Lich lich;
SM17LichLegacy lich;
uint16_t framenumber;
uint8_t payload[16];
uint16_t crc; //16 bit CRC
}; // 4 + 2 + 28 + 2 + 16 + 2 = 54 bytes

using SM17FrameStandard = struct __attribute__((__packed__)) m17_std_tag {
uint8_t magic[4];
uint16_t streamid;
SM17LichStandard lich;
uint16_t framenumber;
uint8_t payload[16];
uint16_t crc; //16 bit CRC
}; // 4 + 2 + 30 + 2 + 16 + 2 = 56 bytes


using SLinkPacket = struct __attribute__((__packed__)) link_tag {
uint8_t magic[4];
uint8_t fromcs[6];
Expand All @@ -57,7 +76,7 @@ class CM17Packet
{
public:
CM17Packet() {}
CM17Packet(const uint8_t *buf);
CM17Packet(const uint8_t *buf, bool isStandard = false);
const CCallsign &GetDestCallsign() const;
const CCallsign &GetSourceCallsign() const;
char GetDestModule() const;
Expand All @@ -69,9 +88,30 @@ class CM17Packet
uint16_t GetStreamId() const;
uint16_t GetCRC() const;
void SetCRC(uint16_t crc);
void SetDestCallsign(const CCallsign &cs);
void SetSourceCallsign(const CCallsign &cs);
void SetStreamId(uint16_t id);
void SetFrameNumber(uint16_t fn);
void SetFrameType(uint16_t ft);
void SetNonce(const uint8_t *nonce);

void SetMagic();

uint8_t *GetLICHPointer() { return m_isStandard ? (uint8_t*)&m_frame.standard.lich : (uint8_t*)&m_frame.legacy.lich; }
size_t GetLICHSize() const { return m_isStandard ? sizeof(SM17LichStandard) : sizeof(SM17LichLegacy); }

const uint8_t *GetBuffer() const { return m_frame.buffer; }
size_t GetSize() const { return m_isStandard ? sizeof(SM17FrameStandard) : sizeof(SM17FrameLegacy); }

bool IsLastPacket() const;

private:
CCallsign destination, source;
SM17Frame m17;
// Flexible storage for either Legacy or Standard frame
union {
SM17FrameLegacy legacy;
SM17FrameStandard standard;
uint8_t buffer[60];
} m_frame;
bool m_isStandard;
};
Loading