add more plumbing to the CFNE for future use;

pull/51/head
Bryan Biedenkapp 2 years ago
parent e7ce1d1f20
commit 4acb60aeff

@ -15,6 +15,7 @@
#include "Defines.h"
#include "nxdn/NXDNDefines.h"
#include "nxdn/NXDNUtils.h"
#include "Utils.h"
using namespace nxdn;
@ -45,3 +46,19 @@ void NXDNUtils::scrambler(uint8_t* data)
for (uint32_t i = 0U; i < NXDN_FRAME_LENGTH_BYTES; i++)
data[i] ^= SCRAMBLER[i];
}
/// <summary>
/// Helper to add the post field bits on NXDN frame data.
/// </summary>
/// <param name="data"></param>
void NXDNUtils::addPostBits(uint8_t* data)
{
assert(data != nullptr);
// post field
for (uint32_t i = 0U; i < NXDN_CAC_E_POST_FIELD_BITS; i++) {
uint32_t n = i + NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_CAC_FEC_LENGTH_BITS + NXDN_CAC_E_POST_FIELD_BITS;
bool b = READ_BIT(NXDN_PREAMBLE, i);
WRITE_BIT(data, n, b);
}
}

@ -28,6 +28,8 @@ namespace nxdn
public:
/// <summary>Helper to scramble the NXDN frame data.</summary>
static void scrambler(uint8_t* data);
/// <summary>Helper to add the post field bits on NXDN frame data.</summary>
static void addPostBits(uint8_t* data);
};
} // namespace nxdn

@ -11,8 +11,11 @@
*
*/
#include "fne/Defines.h"
#include "common/dmr/lc/csbk/CSBKFactory.h"
#include "common/dmr/lc/LC.h"
#include "common/dmr/lc/FullLC.h"
#include "common/dmr/SlotType.h"
#include "common/dmr/Sync.h"
#include "common/Clock.h"
#include "common/Log.h"
#include "common/Utils.h"
@ -542,4 +545,68 @@ bool TagDMRData::validate(uint32_t peerId, data::Data& data, uint32_t streamId)
}
return true;
}
}
/// <summary>
/// Helper to write a NACK RSP packet.
/// </summary>
/// <param name="peerId"></param>
/// <param name="dstId"></param>
/// <param name="reason"></param>
/// <param name="service"></param>
void TagDMRData::write_CSBK_NACK_RSP(uint32_t peerId, uint32_t dstId, uint8_t reason, uint8_t service)
{
std::unique_ptr<lc::csbk::CSBK_NACK_RSP> csbk = std::make_unique<lc::csbk::CSBK_NACK_RSP>();
csbk->setServiceKind(service);
csbk->setReason(reason);
csbk->setSrcId(DMR_WUID_ALL); // hmmm...
csbk->setDstId(dstId);
write_CSBK(peerId, csbk.get());
}
/// <summary>
/// Helper to write a network CSBK.
/// </summary>
/// <param name="peerId"></param>
/// <param name="csbk"></param>
void TagDMRData::write_CSBK(uint32_t peerId, lc::CSBK* csbk)
{
uint8_t data[DMR_FRAME_LENGTH_BYTES + 2U];
::memset(data + 2U, 0x00U, DMR_FRAME_LENGTH_BYTES);
SlotType slotType;
slotType.setColorCode(0U);
slotType.setDataType(DT_CSBK);
// Regenerate the CSBK data
csbk->encode(data + 2U);
// Regenerate the Slot Type
slotType.encode(data + 2U);
// Convert the Data Sync to be from the BS or MS as needed
Sync::addDMRDataSync(data + 2U, true);
data::Data dmrData;
dmrData.setSlotNo(1U);
dmrData.setDataType(DT_CSBK);
dmrData.setSrcId(csbk->getSrcId());
dmrData.setDstId(csbk->getDstId());
dmrData.setFLCO(csbk->getGI() ? FLCO_GROUP : FLCO_PRIVATE);
dmrData.setN(0U);
dmrData.setSeqNo(0U);
dmrData.setBER(0U);
dmrData.setRSSI(0U);
dmrData.setData(data + 2U);
uint32_t streamId = m_network->createStreamId();
uint32_t messageLength = 0U;
UInt8Array message = m_network->createDMR_Message(messageLength, streamId, dmrData);
if (message == nullptr) {
return;
}
m_network->writePeer(peerId, { NET_FUNC_PROTOCOL, NET_PROTOCOL_SUBFUNC_DMR }, message.get(), messageLength, RTP_END_OF_CALL_SEQ, streamId, false, true);
}

@ -16,6 +16,7 @@
#include "fne/Defines.h"
#include "common/dmr/DMRDefines.h"
#include "common/dmr/data/Data.h"
#include "common/dmr/lc/CSBK.h"
#include "common/Clock.h"
#include "network/FNENetwork.h"
@ -75,6 +76,12 @@ namespace network
bool isPeerPermitted(uint32_t peerId, dmr::data::Data& data, uint32_t streamId);
/// <summary>Helper to validate the DMR call stream.</summary>
bool validate(uint32_t peerId, dmr::data::Data& data, uint32_t streamId);
/// <summary>Helper to write a NACK RSP packet.</summary>
void write_CSBK_NACK_RSP(uint32_t peerId, uint32_t dstId, uint8_t reason, uint8_t service);
/// <summary>Helper to write a network CSBK.</summary>
void write_CSBK(uint32_t peerId, dmr::lc::CSBK* csbk);
};
} // namespace fne
} // namespace network

@ -12,6 +12,12 @@
*/
#include "fne/Defines.h"
#include "common/nxdn/NXDNDefines.h"
#include "common/nxdn/channel/LICH.h"
#include "common/nxdn/channel/CAC.h"
#include "common/nxdn/lc/rcch/RCCHFactory.h"
#include "common/nxdn/lc/RTCH.h"
#include "common/nxdn/NXDNUtils.h"
#include "common/nxdn/Sync.h"
#include "common/Clock.h"
#include "common/Log.h"
#include "common/Utils.h"
@ -460,4 +466,86 @@ bool TagNXDNData::validate(uint32_t peerId, lc::RTCH& lc, uint8_t messageType, u
}
return true;
}
}
/// <summary>
/// Helper to write a deny packet.
/// </summary>
/// <param name="peerId"></param>
/// <param name="srcId"></param>
/// <param name="dstId"></param>
/// <param name="reason"></param>
/// <param name="service"></param>
void TagNXDNData::write_Message_Deny(uint32_t peerId, uint32_t srcId, uint32_t dstId, uint8_t reason, uint8_t service)
{
std::unique_ptr<lc::RCCH> rcch = nullptr;
switch (service) {
case RTCH_MESSAGE_TYPE_VCALL:
rcch = std::make_unique<lc::rcch::MESSAGE_TYPE_VCALL_CONN>();
rcch->setMessageType(RTCH_MESSAGE_TYPE_VCALL);
default:
return;
}
rcch->setCauseResponse(reason);
rcch->setSrcId(srcId);
rcch->setDstId(dstId);
if (m_network->m_verbose) {
LogMessage(LOG_RF, "NXDN, MSG_DENIAL (Message Denial), reason = $%02X, service = $%02X, srcId = %u, dstId = %u",
service, srcId, dstId);
}
write_Message(peerId, rcch.get());
}
/// <summary>
/// Helper to write a network RCCH.
/// </summary>
/// <param name="peerId"></param>
/// <param name="rcch"></param>
void TagNXDNData::write_Message(uint32_t peerId, lc::RCCH* rcch)
{
uint8_t data[NXDN_FRAME_LENGTH_BYTES + 2U];
::memset(data + 2U, 0x00U, NXDN_FRAME_LENGTH_BYTES);
Sync::addNXDNSync(data + 2U);
// generate the LICH
channel::LICH lich;
lich.setRFCT(NXDN_LICH_RFCT_RCCH);
lich.setFCT(NXDN_LICH_CAC_OUTBOUND);
lich.setOption(NXDN_LICH_DATA_COMMON);
lich.setOutbound(true);
lich.encode(data + 2U);
uint8_t buffer[NXDN_RCCH_LC_LENGTH_BYTES];
::memset(buffer, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES);
rcch->encode(buffer, NXDN_RCCH_LC_LENGTH_BITS);
// generate the CAC
channel::CAC cac;
cac.setRAN(0U);
cac.setStructure(NXDN_SR_RCCH_SINGLE);
cac.setData(buffer);
cac.encode(data + 2U);
NXDNUtils::scrambler(data + 2U);
NXDNUtils::addPostBits(data + 2U);
lc::RTCH lc = lc::RTCH();
lc.setMessageType(rcch->getMessageType());
lc.setSrcId(rcch->getSrcId());
lc.setDstId(rcch->getDstId());
uint32_t messageLength = 0U;
UInt8Array message = m_network->createNXDN_Message(messageLength, lc, data, NXDN_FRAME_LENGTH_BYTES + 2U);
if (message == nullptr) {
return;
}
uint32_t streamId = m_network->createStreamId();
m_network->writePeer(peerId, { NET_FUNC_PROTOCOL, NET_PROTOCOL_SUBFUNC_NXDN }, message.get(), messageLength, RTP_END_OF_CALL_SEQ, streamId, false, true);
}

@ -17,6 +17,7 @@
#include "common/Clock.h"
#include "common/nxdn/NXDNDefines.h"
#include "common/nxdn/lc/RTCH.h"
#include "common/nxdn/lc/RCCH.h"
#include "network/FNENetwork.h"
#include <deque>
@ -74,6 +75,12 @@ namespace network
bool isPeerPermitted(uint32_t peerId, nxdn::lc::RTCH& lc, uint8_t messageType, uint32_t streamId);
/// <summary>Helper to validate the NXDN call stream.</summary>
bool validate(uint32_t peerId, nxdn::lc::RTCH& control, uint8_t messageType, uint32_t streamId);
/// <summary>Helper to write a deny packet.</summary>
void write_Message_Deny(uint32_t peerId, uint32_t srcId, uint32_t dstId, uint8_t reason, uint8_t service);
/// <summary>Helper to write a network RCCH.</summary>
void write_Message(uint32_t peerId, nxdn::lc::RCCH* rcch);
};
} // namespace fne
} // namespace network

@ -684,4 +684,97 @@ bool TagP25Data::validate(uint32_t peerId, lc::LC& control, uint8_t duid, const
}
return true;
}
}
/// <summary>
/// Helper to write a deny packet.
/// </summary>
/// <param name="peerId"></param>
/// <param name="dstId"></param>
/// <param name="reason"></param>
/// <param name="service"></param>
/// <param name="aiv"></param>
void TagP25Data::write_TSDU_Deny(uint32_t peerId, uint32_t srcId, uint32_t dstId, uint8_t reason, uint8_t service, bool aiv)
{
std::unique_ptr<lc::tsbk::OSP_DENY_RSP> osp = std::make_unique<lc::tsbk::OSP_DENY_RSP>();
osp->setAIV(aiv);
osp->setSrcId(srcId);
osp->setDstId(dstId);
osp->setService(service);
osp->setResponse(reason);
if (m_network->m_verbose) {
LogMessage(LOG_RF, P25_TSDU_STR ", %s, AIV = %u, reason = $%02X, srcId = %u, dstId = %u",
osp->toString().c_str(), osp->getAIV(), reason, osp->getSrcId(), osp->getDstId());
}
write_TSDU(peerId, osp.get());
}
/// <summary>
/// Helper to write a queue packet.
/// </summary>
/// <param name="peerId"></param>
/// <param name="dstId"></param>
/// <param name="reason"></param>
/// <param name="service"></param>
/// <param name="aiv"></param>
/// <param name="grp"></param>
void TagP25Data::write_TSDU_Queue(uint32_t peerId, uint32_t srcId, uint32_t dstId, uint8_t reason, uint8_t service, bool aiv, bool grp)
{
std::unique_ptr<lc::tsbk::OSP_QUE_RSP> osp = std::make_unique<lc::tsbk::OSP_QUE_RSP>();
osp->setAIV(aiv);
osp->setSrcId(srcId);
osp->setDstId(dstId);
osp->setService(service);
osp->setResponse(reason);
osp->setGroup(grp);
if (m_network->m_verbose) {
LogMessage(LOG_RF, P25_TSDU_STR ", %s, AIV = %u, reason = $%02X, srcId = %u, dstId = %u",
osp->toString().c_str(), osp->getAIV(), reason, osp->getSrcId(), osp->getDstId());
}
write_TSDU(peerId, osp.get());
}
/// <summary>
/// Helper to write a network TSDU.
/// </summary>
/// <param name="peerId"></param>
/// <param name="tsbk"></param>
void TagP25Data::write_TSDU(uint32_t peerId, lc::TSBK* tsbk)
{
uint8_t data[P25_TSDU_FRAME_LENGTH_BYTES + 2U];
::memset(data + 2U, 0x00U, P25_TSDU_FRAME_LENGTH_BYTES);
// Generate Sync
Sync::addP25Sync(data + 2U);
// Generate TSBK block
tsbk->setLastBlock(true); // always set last block -- this a Single Block TSDU
tsbk->encode(data + 2U);
if (m_debug) {
LogDebug(LOG_RF, P25_TSDU_STR ", lco = $%02X, mfId = $%02X, lastBlock = %u, AIV = %u, EX = %u, srcId = %u, dstId = %u, sysId = $%03X, netId = $%05X",
tsbk->getLCO(), tsbk->getMFId(), tsbk->getLastBlock(), tsbk->getAIV(), tsbk->getEX(), tsbk->getSrcId(), tsbk->getDstId(),
tsbk->getSysId(), tsbk->getNetId());
Utils::dump(1U, "!!! *TSDU (SBF) TSBK Block Data", data + P25_PREAMBLE_LENGTH_BYTES + 2U, P25_TSBK_FEC_LENGTH_BYTES);
}
lc::LC lc = lc::LC();
lc.setLCO(tsbk->getLCO());
lc.setMFId(tsbk->getMFId());
lc.setSrcId(tsbk->getSrcId());
lc.setDstId(tsbk->getDstId());
uint32_t messageLength = 0U;
UInt8Array message = m_network->createP25_TSDUMessage(messageLength, lc, data);
if (message == nullptr) {
return;
}
uint32_t streamId = m_network->createStreamId();
m_network->writePeer(peerId, { NET_FUNC_PROTOCOL, NET_PROTOCOL_SUBFUNC_P25 }, message.get(), messageLength, RTP_END_OF_CALL_SEQ, streamId, false, true);
}

@ -84,6 +84,14 @@ namespace network
bool isPeerPermitted(uint32_t peerId, p25::lc::LC& control, uint8_t duid, uint32_t streamId);
/// <summary>Helper to validate the P25 call stream.</summary>
bool validate(uint32_t peerId, p25::lc::LC& control, uint8_t duid, const p25::lc::TSBK* tsbk, uint32_t streamId);
/// <summary>Helper to write a deny packet.</summary>
void write_TSDU_Deny(uint32_t peerId, uint32_t srcId, uint32_t dstId, uint8_t reason, uint8_t service, bool aiv = false);
/// <summary>Helper to write a queue packet.</summary>
void write_TSDU_Queue(uint32_t peerId, uint32_t srcId, uint32_t dstId, uint8_t reason, uint8_t service, bool aiv = false, bool group = true);
/// <summary>Helper to write a network TSDU.</summary>
void write_TSDU(uint32_t peerId, p25::lc::TSBK* tsbk);
};
} // namespace fne
} // namespace network

@ -442,36 +442,28 @@ void ControlSignaling::processNetwork(const data::Data & dmrData)
case SVC_KIND_IND_VOICE_CALL:
writeRF_CSBK_ACK_RSP(srcId, TS_WAIT_RSN, 1U);
if (m_slot->m_authoritative) {
if (!m_slot->m_affiliations->isGranted(dstId)) {
writeRF_CSBK_Grant(srcId, dstId, isp->getServiceOptions(), false, true);
}
if (!m_slot->m_affiliations->isGranted(dstId)) {
writeRF_CSBK_Grant(srcId, dstId, isp->getServiceOptions(), false, true);
}
break;
case SVC_KIND_GRP_VOICE_CALL:
writeRF_CSBK_ACK_RSP(srcId, TS_WAIT_RSN, 1U);
if (m_slot->m_authoritative) {
if (!m_slot->m_affiliations->isGranted(dstId)) {
writeRF_CSBK_Grant(srcId, dstId, isp->getServiceOptions(), true, true);
}
if (!m_slot->m_affiliations->isGranted(dstId)) {
writeRF_CSBK_Grant(srcId, dstId, isp->getServiceOptions(), true, true);
}
break;
case SVC_KIND_IND_DATA_CALL:
case SVC_KIND_IND_UDT_DATA_CALL:
writeRF_CSBK_ACK_RSP(srcId, TS_WAIT_RSN, 0U);
if (!m_slot->m_affiliations->isGranted(dstId)) {
writeRF_CSBK_Data_Grant(srcId, dstId, isp->getServiceOptions(), false, true);
}
writeRF_CSBK_Data_Grant(srcId, dstId, isp->getServiceOptions(), false, true);
break;
case SVC_KIND_GRP_DATA_CALL:
case SVC_KIND_GRP_UDT_DATA_CALL:
writeRF_CSBK_ACK_RSP(srcId, TS_WAIT_RSN, 0U);
if (!m_slot->m_affiliations->isGranted(dstId)) {
writeRF_CSBK_Data_Grant(srcId, dstId, isp->getServiceOptions(), true, true);
}
writeRF_CSBK_Data_Grant(srcId, dstId, isp->getServiceOptions(), true, true);
break;
case SVC_KIND_REG_SVC:
break;
@ -725,7 +717,7 @@ void ControlSignaling::writeRF_CSBK(lc::CSBK* csbk, bool clearBeforeWrite, bool
*/
/// <summary>
/// Helper to write a deny packet.
/// Helper to write a ACK RSP packet.
/// </summary>
/// <param name="dstId"></param>
/// <param name="reason"></param>
@ -742,7 +734,7 @@ void ControlSignaling::writeRF_CSBK_ACK_RSP(uint32_t dstId, uint8_t reason, uint
}
/// <summary>
/// Helper to write a deny packet.
/// Helper to write a NACK RSP packet.
/// </summary>
/// <param name="dstId"></param>
/// <param name="reason"></param>

@ -257,7 +257,7 @@ bool ControlSignaling::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& net
uint16_t srcId = rcch->getSrcId();
uint16_t dstId = rcch->getDstId();
// handle standard P25 reference opcodes
// handle standard NXDN message opcodes
switch (rcch->getMessageType()) {
case RTCH_MESSAGE_TYPE_VCALL:
{
@ -277,6 +277,8 @@ bool ControlSignaling::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& net
}
}
return true; // don't allow this to write to the air
case RCCH_MESSAGE_TYPE_VCALL_CONN:
break; // the FNE may explicitly send these
default:
LogError(LOG_NET, "NXDN, unhandled message type, messageType = $%02X", rcch->getMessageType());
return false;
@ -395,8 +397,7 @@ void ControlSignaling::writeRF_Message(RCCH* rcch, bool noNetwork, bool clearBef
data[1U] = 0x00U;
NXDNUtils::scrambler(data + 2U);
addPostBits(data + 2U);
NXDNUtils::addPostBits(data + 2U);
if (!noNetwork)
writeNetwork(data, NXDN_FRAME_LENGTH_BYTES + 2U);
@ -823,8 +824,7 @@ void ControlSignaling::writeRF_CC_Message_Site_Info()
data[1U] = 0x00U;
NXDNUtils::scrambler(data + 2U);
addPostBits(data + 2U);
NXDNUtils::addPostBits(data + 2U);
if (m_nxdn->m_duplex) {
m_nxdn->addFrame(data, NXDN_FRAME_LENGTH_BYTES + 2U);
@ -868,26 +868,9 @@ void ControlSignaling::writeRF_CC_Message_Service_Info()
data[1U] = 0x00U;
NXDNUtils::scrambler(data + 2U);
addPostBits(data + 2U);
NXDNUtils::addPostBits(data + 2U);
if (m_nxdn->m_duplex) {
m_nxdn->addFrame(data, NXDN_FRAME_LENGTH_BYTES + 2U);
}
}
/// <summary>
/// Helper to add the post field bits on NXDN frame data.
/// </summary>
/// <param name="data"></param>
void ControlSignaling::addPostBits(uint8_t* data)
{
assert(data != nullptr);
// post field
for (uint32_t i = 0U; i < NXDN_CAC_E_POST_FIELD_BITS; i++) {
uint32_t n = i + NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_CAC_FEC_LENGTH_BITS + NXDN_CAC_E_POST_FIELD_BITS;
bool b = READ_BIT(NXDN_PREAMBLE, i);
WRITE_BIT(data, n, b);
}
}

@ -106,9 +106,6 @@ namespace nxdn
void writeRF_CC_Message_Site_Info();
/// <summary>Helper to write a CC SRV_INFO broadcast packet on the RF interface.</summary>
void writeRF_CC_Message_Service_Info();
/// <summary>Helper to add the post field bits on NXDN frame data.</summary>
void addPostBits(uint8_t* data);
};
} // namespace packet
} // namespace nxdn

@ -894,12 +894,9 @@ bool ControlSignaling::processNetwork(uint8_t* data, uint32_t len, lc::LC& contr
break;
case TSBK_ISP_EMERG_ALRM_REQ:
{
ISP_EMERG_ALRM_REQ* isp = static_cast<ISP_EMERG_ALRM_REQ*>(tsbk.get());
// non-emergency mode is a TSBK_OSP_DENY_RSP
if (!isp->getEmergency()) {
// ignore a network deny command
return true; // don't allow this to write to the air
if (!tsbk->getEmergency()) {
break; // the FNE may explicitly send these
} else {
VERBOSE_LOG_TSBK_NET(tsbk->toString(true), srcId, dstId);
return true; // don't allow this to write to the air
@ -915,9 +912,10 @@ bool ControlSignaling::processNetwork(uint8_t* data, uint32_t len, lc::LC& contr
case TSBK_OSP_LOC_REG_RSP:
// ignore a network location registration command
return true; // don't allow this to write to the air
case TSBK_OSP_U_REG_CMD:
break; // the FNE may explicitly send these
case TSBK_OSP_QUE_RSP:
// ignore a network queue command
return true; // don't allow this to write to the air
break; // the FNE may explicitly send these
default:
LogError(LOG_NET, P25_TSDU_STR ", unhandled LCO, mfId = $%02X, lco = $%02X", tsbk->getMFId(), tsbk->getLCO());
return false;

@ -218,7 +218,7 @@ namespace p25
bool writeNet_TSDU_Call_Term(uint32_t srcId, uint32_t dstId);
/// <summary>Helper to write a network TSDU from the RF data queue.</summary>
void writeNet_TSDU_From_RF(lc::TSBK* tsbk, uint8_t * data);
void writeNet_TSDU_From_RF(lc::TSBK* tsbk, uint8_t* data);
/// <summary>Helper to automatically inhibit a source ID on a denial.</summary>
void denialInhibit(uint32_t srcId);

Loading…
Cancel
Save

Powered by TurnKey Linux.