implement start of support for non-authoritative CC (this is a situation where a FNE STC is configured); implement RCON to return the list of configured voice channels from a CC; continue implementation of permit-tg (still not done);

3.0-rcon_maint
Bryan Biedenkapp 3 years ago
parent 5813bcb915
commit a102956e1d

@ -110,12 +110,15 @@ Control::~Control()
/// Helper to set DMR configuration options.
/// </summary>
/// <param name="conf">Instance of the ConfigINI class.</param>
/// <param name="netId"></param>
/// <param name="siteId"></param>
/// <param name="channelId"></param>
/// <param name="channelNo"></param>
/// <param name="voiceChNo">Voice Channel Number list.</param>
/// <param name="voiceChData">Voice Channel data map.</param>
/// <param name="netId">DMR Network ID.</param>
/// <param name="siteId">DMR Site ID.</param>
/// <param name="channelId">Channel ID.</param>
/// <param name="channelNo">Channel Number.</param>
/// <param name="printOptions"></param>
void Control::setOptions(yaml::Node& conf, uint32_t netId, uint8_t siteId, uint8_t channelId, uint32_t channelNo, bool printOptions)
void Control::setOptions(yaml::Node& conf, const std::vector<uint32_t> voiceChNo, const std::unordered_map<uint32_t, lookups::VoiceChData> voiceChData,
uint32_t netId, uint8_t siteId, uint8_t channelId, uint32_t channelNo, bool printOptions)
{
yaml::Node systemConf = conf["system"];
yaml::Node dmrProtocol = conf["protocols"]["dmr"];
@ -139,7 +142,7 @@ void Control::setOptions(yaml::Node& conf, uint32_t netId, uint8_t siteId, uint8
dedicatedTSCC = false;
}
Slot::setSiteData(netId, siteId, channelId, channelNo, dedicatedTSCC);
Slot::setSiteData(voiceChNo, voiceChData, netId, siteId, channelId, channelNo, dedicatedTSCC);
Slot::setAlohaConfig(nRandWait, backOff);
m_tsccSlotNo = (uint8_t)control["slot"].as<uint32_t>(0U);
@ -328,9 +331,20 @@ void Control::clock()
/// Permits a TGID on a non-authoritative host.
/// </summary>
/// <param name="dstId"></param>
void Control::permittedTG(uint32_t dstId)
/// <paran name="slot"></param>
void Control::permittedTG(uint32_t dstId, uint8_t slot)
{
// TODO TODO
switch (slot) {
case 1U:
m_slot1->permittedTG(dstId);
break;
case 2U:
m_slot2->permittedTG(dstId);
break;
default:
LogError(LOG_NET, "DMR, invalid slot, slotNo = %u", slot);
break;
}
}
/// <summary>

@ -41,6 +41,7 @@
#include "lookups/IdenTableLookup.h"
#include "lookups/RadioIdLookup.h"
#include "lookups/TalkgroupIdLookup.h"
#include "lookups/AffiliationLookup.h"
#include "yaml/Yaml.h"
namespace dmr
@ -68,7 +69,8 @@ namespace dmr
~Control();
/// <summary>Helper to set DMR configuration options.</summary>
void setOptions(yaml::Node& conf, uint32_t netId, uint8_t siteId, uint8_t channelId, uint32_t channelNo, bool printOptions);
void setOptions(yaml::Node& conf, const std::vector<uint32_t> voiceChNo, const std::unordered_map<uint32_t, lookups::VoiceChData> voiceChData,
uint32_t netId, uint8_t siteId, uint8_t channelId, uint32_t channelNo, bool printOptions);
/// <summary>Gets a flag indicating whether the DMR control channel is running.</summary>
bool getCCRunning() { return m_ccRunning; }
@ -91,7 +93,7 @@ namespace dmr
void clock();
/// <summary>Permits a TGID on a non-authoritative host.</summary>
void permittedTG(uint32_t dstId);
void permittedTG(uint32_t dstId, uint8_t slot);
/// <summary>Helper to return the slot carrying the TSCC.</summary>
Slot* getTSCCSlot() const;

@ -125,6 +125,7 @@ Slot::Slot(uint32_t slotNo, uint32_t timeout, uint32_t tgHang, uint32_t queueSiz
m_rfLastDstId(0U),
m_netState(RS_NET_IDLE),
m_netLastDstId(0U),
m_permittedDstId(0U),
m_rfLC(nullptr),
m_rfPrivacyLC(nullptr),
m_rfDataHeader(nullptr),
@ -538,6 +539,19 @@ void Slot::clock()
}
}
/// <summary>
/// Permits a TGID on a non-authoritative host.
/// </summary>
/// <param name="dstId"></param>
void Slot::permittedTG(uint32_t dstId)
{
if (!m_authoritative) {
return;
}
m_permittedDstId = dstId;
}
/// <summary>
/// Helper to change the debug and verbose state.
/// </summary>
@ -645,12 +659,15 @@ void Slot::init(Control* dmr, bool authoritative, uint32_t colorCode, SiteData s
/// <summary>
/// Sets local configured site data.
/// </summary>
/// <param name="voiceChNo">Voice Channel Number list.</param>
/// <param name="voiceChData">Voice Channel data map.</param>
/// <param name="netId">DMR Network ID.</param>
/// <param name="siteId">DMR Site ID.</param>
/// <param name="channelId">Channel ID.</param>
/// <param name="channelNo">Channel Number.</param>
/// <param name="requireReg"></param>
void Slot::setSiteData(uint32_t netId, uint8_t siteId, uint8_t channelId, uint32_t channelNo, bool requireReg)
void Slot::setSiteData(const std::vector<uint32_t> voiceChNo, const std::unordered_map<uint32_t, lookups::VoiceChData> voiceChData,
uint32_t netId, uint8_t siteId, uint8_t channelId, uint32_t channelNo, bool requireReg)
{
m_siteData = SiteData(SITE_MODEL_SMALL, netId, siteId, 3U, requireReg);
m_channelNo = channelNo;
@ -664,6 +681,13 @@ void Slot::setSiteData(uint32_t netId, uint8_t siteId, uint8_t channelId, uint32
}
}
std::vector<uint32_t> availCh = voiceChNo;
for (auto it = availCh.begin(); it != availCh.end(); ++it) {
m_affiliations->addRFCh(*it);
}
m_affiliations->setRFChData(voiceChData);
lc::CSBK::setSiteData(m_siteData);
}

@ -94,6 +94,9 @@ namespace dmr
/// <summary>Updates the slot processor.</summary>
void clock();
/// <summary>Permits a TGID on a non-authoritative host.</summary>
void permittedTG(uint32_t dstId);
/// <summary>Gets instance of the ControlSignaling class.</summary>
packet::ControlSignaling* control() { return m_control; }
@ -110,7 +113,8 @@ namespace dmr
network::BaseNetwork* network, bool duplex, lookups::RadioIdLookup* ridLookup, lookups::TalkgroupIdLookup* tidLookup,
lookups::IdenTableLookup* idenTable, lookups::RSSIInterpolator* rssiMapper, uint32_t jitter, bool verbose);
/// <summary>Sets local configured site data.</summary>
static void setSiteData(uint32_t netId, uint8_t siteId, uint8_t channelId, uint32_t channelNo, bool requireReq);
static void setSiteData(const std::vector<uint32_t> voiceChNo, const std::unordered_map<uint32_t, lookups::VoiceChData> voiceChData,
uint32_t netId, uint8_t siteId, uint8_t channelId, uint32_t channelNo, bool requireReq);
/// <summary>Sets TSCC Aloha configuration.</summary>
static void setAlohaConfig(uint8_t nRandWait, uint8_t backOff);
@ -132,6 +136,8 @@ namespace dmr
RPT_NET_STATE m_netState;
uint32_t m_netLastDstId;
uint32_t m_permittedDstId;
std::unique_ptr<lc::LC> m_rfLC;
std::unique_ptr<lc::PrivacyLC> m_rfPrivacyLC;
std::unique_ptr<data::DataHeader> m_rfDataHeader;

@ -215,7 +215,11 @@ bool ControlSignaling::process(uint8_t* data, uint32_t len)
// verify the source RID is registered
VERIFY_SRCID_REG("DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_IND_VOICE_CALL (Individual Voice Call)", SVC_KIND_IND_VOICE_CALL, srcId);
writeRF_CSBK_Grant(srcId, dstId, isp->getServiceOptions(), false);
if (m_slot->m_authoritative) {
writeRF_CSBK_Grant(srcId, dstId, isp->getServiceOptions(), false);
} else {
m_slot->m_network->writeGrantReq(modem::DVM_STATE::STATE_DMR, srcId, dstId, m_slot->m_slotNo, true);
}
break;
case SVC_KIND_GRP_VOICE_CALL:
// make sure control data is supported
@ -227,7 +231,11 @@ bool ControlSignaling::process(uint8_t* data, uint32_t len)
// validate the talkgroup ID
VALID_TGID("DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_GRP_VOICE_CALL (Group Voice Call)", SVC_KIND_GRP_VOICE_CALL, srcId, dstId);
writeRF_CSBK_Grant(srcId, dstId, isp->getServiceOptions(), true);
if (m_slot->m_authoritative) {
writeRF_CSBK_Grant(srcId, dstId, isp->getServiceOptions(), true);
} else {
m_slot->m_network->writeGrantReq(modem::DVM_STATE::STATE_DMR, srcId, dstId, m_slot->m_slotNo, false);
}
break;
case SVC_KIND_IND_DATA_CALL:
case SVC_KIND_IND_UDT_DATA_CALL:

@ -113,6 +113,8 @@ Host::Host(const std::string& confFile) :
m_txFrequency(0U),
m_channelId(0U),
m_channelNo(0U),
m_voiceChNo(),
m_voiceChData(),
m_idenTable(nullptr),
m_ridLookup(nullptr),
m_tidLookup(nullptr),
@ -431,7 +433,7 @@ int Host::run()
dmr = std::unique_ptr<dmr::Control>(new dmr::Control(m_authoritative, m_dmrColorCode, callHang, m_dmrQueueSizeBytes, embeddedLCOnly, dumpTAData, m_timeout, m_rfTalkgroupHang,
m_modem, m_network, m_duplex, m_ridLookup, m_tidLookup, m_idenTable, rssi, jitter, dmrDumpDataPacket, dmrRepeatDataPacket,
dmrDumpCsbkData, dmrDebug, dmrVerbose));
dmr->setOptions(m_conf, m_dmrNetId, m_siteId, m_channelId, m_channelNo, true);
dmr->setOptions(m_conf, m_voiceChNo, m_voiceChData, m_dmrNetId, m_siteId, m_channelId, m_channelNo, true);
if (dmrCtrlChannel) {
dmr->setCCRunning(true);
@ -504,7 +506,7 @@ int Host::run()
p25 = std::unique_ptr<p25::Control>(new p25::Control(m_authoritative, m_p25NAC, callHang, m_p25QueueSizeBytes, m_modem, m_network, m_timeout, m_rfTalkgroupHang,
m_duplex, m_ridLookup, m_tidLookup, m_idenTable, rssi, p25DumpDataPacket, p25RepeatDataPacket,
p25DumpTsbkData, p25Debug, p25Verbose));
p25->setOptions(m_conf, m_cwCallsign, m_voiceChNo, m_p25PatchSuperGroup, m_p25NetId, m_p25SysId, m_p25RfssId,
p25->setOptions(m_conf, m_cwCallsign, m_voiceChNo, m_voiceChData, m_p25PatchSuperGroup, m_p25NetId, m_p25SysId, m_p25RfssId,
m_siteId, m_channelId, m_channelNo, true);
if (p25CtrlChannel) {
@ -1847,8 +1849,8 @@ bool Host::readParams()
::LogInfoEx(LOG_HOST, "Voice Channel Id %u Channel No $%04X RCON Adddress %s:%u", m_channelId, chNo, rconAddress.c_str(), rconPort);
// TODO handle storing RCON data for voice channels
VoiceChData data = VoiceChData(chNo, rconAddress, rconPort, rconPassword);
m_voiceChData[chNo] = data;
m_voiceChNo.push_back(chNo);
}
@ -1921,6 +1923,10 @@ bool Host::readParams()
LogInfo(" P25 Network Id: $%05X", m_p25NetId);
LogInfo(" P25 System Id: $%03X", m_p25SysId);
LogInfo(" P25 RFSS Id: $%02X", m_p25RfssId);
if (!m_authoritative) {
LogWarning(LOG_HOST, "Host is non-authoritative, this requires RCON to \"permit-tg\" for VCs and \"grant-tg\" for CCs!");
}
}
else {
LogInfo(" Modem Remote Control: yes");

@ -36,12 +36,14 @@
#include "network/RemoteControl.h"
#include "modem/Modem.h"
#include "Timer.h"
#include "lookups/AffiliationLookup.h"
#include "lookups/IdenTableLookup.h"
#include "lookups/RadioIdLookup.h"
#include "lookups/TalkgroupIdLookup.h"
#include "yaml/Yaml.h"
#include <string>
#include <unordered_map>
// ---------------------------------------------------------------------------
// Class Prototypes
@ -64,6 +66,11 @@ public:
/// <summary>Executes the main modem host processing loop.</summary>
int run();
/// <summary>Gets the voice channel number list.</summary>
std::vector<uint32_t> getVoiceChNo() const { return m_voiceChNo; }
/// <summary>Gets the voice channel data.</summary>
std::unordered_map<uint32_t, lookups::VoiceChData> getVoiceChData() const { return m_voiceChData; }
private:
const std::string& m_confFile;
yaml::Node m_conf;
@ -107,7 +114,9 @@ private:
uint32_t m_txFrequency;
uint8_t m_channelId;
uint32_t m_channelNo;
std::vector<uint32_t> m_voiceChNo;
std::unordered_map<uint32_t, lookups::VoiceChData> m_voiceChData;
lookups::IdenTableLookup* m_idenTable;
lookups::RadioIdLookup* m_ridLookup;

@ -44,6 +44,7 @@ using namespace lookups;
/// <param name="verbose">Flag indicating whether verbose logging is enabled.</param>
AffiliationLookup::AffiliationLookup(const char* name, bool verbose) :
m_rfChTable(),
m_rfChDataTable(),
m_rfGrantChCnt(0U),
m_unitRegTable(),
m_grpAffTable(),
@ -401,6 +402,27 @@ uint32_t AffiliationLookup::getGrantedCh(uint32_t dstId)
return 0U;
}
/// <summary>
/// Helper to get RF channel data.
/// </summary>
/// <param name="chNo"></param>
/// <returns></returns>
VoiceChData AffiliationLookup::getRFChData(uint32_t chNo) const
{
if (chNo == 0U) {
return VoiceChData();
}
VoiceChData data;
try {
data = m_rfChDataTable.at(chNo);
} catch (...) {
data = VoiceChData();
}
return VoiceChData();
}
/// <summary>
/// Updates the processor by the passed number of milliseconds.
/// </summary>

@ -36,6 +36,65 @@
namespace lookups
{
// ---------------------------------------------------------------------------
// Class Declaration
// Represents voice channel data.
// ---------------------------------------------------------------------------
class HOST_SW_API VoiceChData {
public:
/// <summary>Initializes a new instance of the VoiceChData class.</summary>
VoiceChData() :
m_chNo(0U),
m_address(),
m_port(),
m_password()
{
/* stub */
}
/// <summary>Initializes a new instance of the VoiceChData class.</summary>
/// <param name="chNo">Voice Channel Number.</param>
/// <param name="address">RCON Address.</param>
/// <param name="port">RCON Port.</param>
/// <param name="password">RCON Password.</param>
VoiceChData(uint32_t chNo, std::string address, uint16_t port, std::string password) :
m_chNo(chNo),
m_address(address),
m_port(port),
m_password(password)
{
/* stub */
}
/// <summary>Equals operator.</summary>
/// <param name="data"></param>
/// <returns></returns>
VoiceChData & operator=(const VoiceChData & data)
{
if (this != &data) {
m_chNo = data.m_chNo;
m_address = data.m_address;
m_port = data.m_port;
m_password = data.m_password;
}
return *this;
}
/// <summary>Helper to determine if the channel is valid.</summary>
bool isValidCh() { return m_chNo != 0U; }
public:
/// <summary>Voice Channel Number.</summary>
__READONLY_PROPERTY_PLAIN(uint32_t, chNo, chNo);
/// <summary>RCON Address.</summary>
__READONLY_PROPERTY_PLAIN(std::string, address, address);
/// <summary>RCON Port.</summary>
__READONLY_PROPERTY_PLAIN(uint16_t, port, port);
/// <summary>RCON Password.</summary>
__READONLY_PROPERTY_PLAIN(std::string, password, password);
};
// ---------------------------------------------------------------------------
// Class Declaration
// Implements a lookup table class that contains subscriber registration
@ -90,6 +149,11 @@ namespace lookups
/// <summary>Helper to get the channel granted for the given destination ID.</summary>
virtual uint32_t getGrantedCh(uint32_t dstId);
/// <summary>Helper to set RF channel data.</summary>
void setRFChData(const std::unordered_map<uint32_t, VoiceChData> chData) { m_rfChDataTable = chData; }
/// <summary>Helper to get RF channel data.</summary>
VoiceChData getRFChData(uint32_t chNo) const;
/// <summary>Helper to add a RF channel.</summary>
void addRFCh(uint32_t chNo) { m_rfChTable.push_back(chNo); }
/// <summary>Helper to remove a RF channel.</summary>
@ -106,6 +170,7 @@ namespace lookups
protected:
std::vector<uint32_t> m_rfChTable;
std::unordered_map<uint32_t, VoiceChData> m_rfChDataTable;
uint8_t m_rfGrantChCnt;
std::vector<uint32_t> m_unitRegTable;

@ -466,6 +466,38 @@ bool BaseNetwork::writeNXDN(const nxdn::lc::RTCH& lc, const uint8_t* data, const
return writeNXDN(m_id, m_nxdnStreamId, lc, data, len);
}
/// <summary>
/// Writes grant request to the network.
/// </summary>
/// <param name="mode"></param>
/// <param name="srcId"></param>
/// <param name="dstId"></param>
/// <param name="slot"></param>
/// <param name="unitToUnit"></param>
/// <returns></returns>
bool BaseNetwork::writeGrantReq(const uint8_t mode, const uint32_t srcId, const uint32_t dstId, const uint8_t slot, const bool unitToUnit)
{
if (m_status != NET_STAT_RUNNING && m_status != NET_STAT_MST_RUNNING)
return false;
uint8_t buffer[DATA_PACKET_LENGTH];
::memset(buffer, 0x00U, DATA_PACKET_LENGTH);
::memcpy(buffer + 0U, TAG_REPEATER_GRANT, 7U);
__SET_UINT32(m_id, buffer, 7U);
__SET_UINT32(srcId, buffer, 11U); // Source Address
__SET_UINT32(dstId, buffer, 15U); // Destination Address
buffer[19U] = slot; // Slot Number
if (unitToUnit)
buffer[19U] |= 0x80U;
buffer[20U] = mode; // DVM Mode State
return write((uint8_t*)buffer, 21U);
}
/// <summary>
/// Writes the local activity log to the network.
/// </summary>

@ -73,8 +73,6 @@
#define TAG_MASTER_CLOSING "MSTCL"
#define TAG_MASTER_PONG "MSTPONG"
#define TAG_MASTER_GRANT "MSTGRNT"
#define TAG_REPEATER_LOGIN "RPTL"
#define TAG_REPEATER_AUTH "RPTK"
#define TAG_REPEATER_CONFIG "RPTC"
@ -83,6 +81,8 @@
#define TAG_REPEATER_CLOSING "RPTCL"
#define TAG_REPEATER_PING "RPTPING"
#define TAG_REPEATER_GRANT "RPTGRNT"
#define TAG_TRANSFER_ACT_LOG "TRNSLOG"
#define TAG_TRANSFER_DIAG_LOG "TRNSDIAG"
@ -156,6 +156,9 @@ namespace network
/// <summary>Writes NXDN frame data to the network.</summary>
virtual bool writeNXDN(const nxdn::lc::RTCH& lc, const uint8_t* data, const uint32_t len);
/// <summary>Writes a grant request to the network.</summary>
virtual bool writeGrantReq(const uint8_t mode, const uint32_t srcId, const uint32_t dstId, const uint8_t slot, const bool unitToUnit);
/// <summary>Writes the local activity log to the network.</summary>
virtual bool writeActLog(const char* message);

@ -56,14 +56,18 @@ using namespace modem;
// Constants
// ---------------------------------------------------------------------------
#define BAD_CMD_STR "Bad or invalid remote command."
#define INVALID_AUTH_STR "Invalid authentication"
#define INVALID_OPT_STR "Invalid command arguments: "
#define CMD_FAILED_STR "Remote command failed: "
#define RCON_CMD_OK "ACK"
#define RCON_CMD_NACK "NACK: "
#define BAD_CMD_STR "NACK: Bad or invalid remote command"
#define NO_DATA_CMD_STR "NACK: No data"
#define INVALID_AUTH_STR "NACK: Invalid authentication"
#define INVALID_OPT_STR "NACK: Invalid command arguments, "
#define RCD_GET_VERSION "version"
#define RCD_GET_HELP "help"
#define RCD_GET_STATUS "status"
#define RCD_GET_VOICE_CH "voice-ch"
#define RCD_MODE "mdm-mode"
#define RCD_MODE_OPT_IDLE "idle"
@ -76,6 +80,7 @@ using namespace modem;
#define RCD_FORCE_KILL "mdm-force-kill"
#define RCD_PERMIT_TG "permit-tg"
#define RCD_GRANT_TG "grant-tg"
#define RCD_RID_WLIST "rid-whitelist"
#define RCD_RID_BLIST "rid-blacklist"
@ -211,7 +216,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
args.clear();
uint8_t buffer[RC_BUFFER_LENGTH];
std::string reply = "OK";
std::string reply = RCON_CMD_OK;
sockaddr_storage address;
uint32_t addrLen;
@ -245,7 +250,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
uint8_t hash[32U];
::memset(hash, 0x00U, 32U);
if (::memcmp(m_passwordHash, buffer + 2U, 32U) != 0) {
LogError(LOG_RCON, CMD_FAILED_STR INVALID_AUTH_STR " from %s", UDPSocket::address(address).c_str());
LogError(LOG_RCON, INVALID_AUTH_STR " from %s", UDPSocket::address(address).c_str());
reply = INVALID_AUTH_STR;
writeResponse(reply, address, addrLen);
return;
@ -294,6 +299,9 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
else if (rcom == RCD_GET_STATUS) {
reply = rcdGetStatus(host, dmr, p25, nxdn);
}
else if (rcom == RCD_GET_VOICE_CH) {
reply = rcdGetVoiceCh(host, dmr, p25, nxdn);
}
else if (rcom == RCD_MODE && argCnt >= 1U) {
reply = rcdMode(args, host, dmr, p25, nxdn);
}
@ -307,6 +315,9 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
else if (rcom == RCD_PERMIT_TG && argCnt >= 1U) {
reply = rcdPermitTG(args, host, dmr, p25, nxdn);
}
else if (rcom == RCD_GRANT_TG && argCnt >= 1U) {
reply = rcdPermitTG(args, host, dmr, p25, nxdn);
}
else if (rcom == RCD_RID_WLIST && argCnt >= 1U) {
uint32_t srcId = getArgUInt32(args, 0U);
if (srcId != 0U) {
@ -334,12 +345,12 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
g_fireDMRBeacon = true;
}
else {
reply = CMD_FAILED_STR "DMR beacons is not enabled!";
reply = RCON_CMD_NACK "DMR beacons is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
else {
reply = CMD_FAILED_STR "DMR mode is not enabled!";
reply = RCON_CMD_NACK "DMR mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -351,12 +362,12 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
g_fireP25Control = true;
}
else {
reply = CMD_FAILED_STR "P25 control data is not enabled!";
reply = RCON_CMD_NACK "P25 control data is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
else {
reply = CMD_FAILED_STR "P25 mode is not enabled!";
reply = RCON_CMD_NACK "P25 mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -367,12 +378,12 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
p25->trunk()->setConvFallback((fallback == 1U) ? true : false);
}
else {
reply = CMD_FAILED_STR "P25 control data is not enabled!";
reply = RCON_CMD_NACK "P25 control data is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
else {
reply = CMD_FAILED_STR "P25 mode is not enabled!";
reply = RCON_CMD_NACK "P25 mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -397,7 +408,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
}
}
else {
reply = CMD_FAILED_STR "DMR mode is not enabled!";
reply = RCON_CMD_NACK "DMR mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -420,7 +431,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
}
}
else {
reply = CMD_FAILED_STR "DMR mode is not enabled!";
reply = RCON_CMD_NACK "DMR mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -443,7 +454,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
}
}
else {
reply = CMD_FAILED_STR "DMR mode is not enabled!";
reply = RCON_CMD_NACK "DMR mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -466,7 +477,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
}
}
else {
reply = CMD_FAILED_STR "DMR mode is not enabled!";
reply = RCON_CMD_NACK "DMR mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -487,7 +498,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
p25->trunk()->setLastMFId(m_p25MFId);
}
else {
reply = CMD_FAILED_STR "P25 mode is not enabled!";
reply = RCON_CMD_NACK "P25 mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -505,7 +516,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
}
}
else {
reply = CMD_FAILED_STR "P25 mode is not enabled!";
reply = RCON_CMD_NACK "P25 mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -523,7 +534,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
}
}
else {
reply = CMD_FAILED_STR "P25 mode is not enabled!";
reply = RCON_CMD_NACK "P25 mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -541,7 +552,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
}
}
else {
reply = CMD_FAILED_STR "P25 mode is not enabled!";
reply = RCON_CMD_NACK "P25 mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -559,7 +570,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
}
}
else {
reply = CMD_FAILED_STR "P25 mode is not enabled!";
reply = RCON_CMD_NACK "P25 mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -577,7 +588,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
}
}
else {
reply = CMD_FAILED_STR "P25 mode is not enabled!";
reply = RCON_CMD_NACK "P25 mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -595,7 +606,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
}
}
else {
reply = CMD_FAILED_STR "P25 mode is not enabled!";
reply = RCON_CMD_NACK "P25 mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -604,7 +615,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
p25->affiliations().releaseGrant(0, true);
}
else {
reply = CMD_FAILED_STR "P25 mode is not enabled!";
reply = RCON_CMD_NACK "P25 mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -620,7 +631,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
}
}
else {
reply = CMD_FAILED_STR "P25 mode is not enabled!";
reply = RCON_CMD_NACK "P25 mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -630,7 +641,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
if (dmr != nullptr) {
if (host->m_dmrTSCCData) {
if (p25 != nullptr) {
reply = CMD_FAILED_STR "Can't enable DMR control channel while P25 is enabled!";
reply = RCON_CMD_NACK "Can't enable DMR control channel while P25 is enabled!";
LogError(LOG_RCON, reply.c_str());
}
else {
@ -640,12 +651,12 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
}
}
else {
reply = CMD_FAILED_STR "DMR control data is not enabled!";
reply = RCON_CMD_NACK "DMR control data is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
else {
reply = CMD_FAILED_STR "DMR mode is not enabled!";
reply = RCON_CMD_NACK "DMR mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -656,7 +667,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
LogInfoEx(LOG_RCON, reply.c_str());
}
else {
reply = CMD_FAILED_STR "DMR mode is not enabled!";
reply = RCON_CMD_NACK "DMR mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -666,7 +677,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
if (p25 != nullptr) {
if (host->m_p25CCData) {
if (dmr != nullptr) {
reply = CMD_FAILED_STR "Can't enable P25 control channel while DMR is enabled!";
reply = RCON_CMD_NACK "Can't enable P25 control channel while DMR is enabled!";
LogError(LOG_RCON, reply.c_str());
}
else {
@ -680,12 +691,12 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
}
}
else {
reply = CMD_FAILED_STR "P25 control data is not enabled!";
reply = RCON_CMD_NACK "P25 control data is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
else {
reply = CMD_FAILED_STR "P25 mode is not enabled!";
reply = RCON_CMD_NACK "P25 mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -707,12 +718,12 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
LogInfoEx(LOG_RCON, reply.c_str());
}
else {
reply = CMD_FAILED_STR "P25 control data is not enabled!";
reply = RCON_CMD_NACK "P25 control data is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
else {
reply = CMD_FAILED_STR "P25 mode is not enabled!";
reply = RCON_CMD_NACK "P25 mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -726,7 +737,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
reply = string_format("dmr->debug = %u, dmr->verbose = %u", debug, verbose);
}
else {
reply = CMD_FAILED_STR "DMR mode is not enabled!";
reply = RCON_CMD_NACK "DMR mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -737,7 +748,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
dmr->setDebugVerbose((debug == 1U) ? true : false, (verbose == 1U) ? true : false);
}
else {
reply = CMD_FAILED_STR "DMR mode is not enabled!";
reply = RCON_CMD_NACK "DMR mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -749,7 +760,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
reply = string_format("dmr->dumpCsbkData = %u", csbkDump);
}
else {
reply = CMD_FAILED_STR "DMR mode is not enabled!";
reply = RCON_CMD_NACK "DMR mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -759,7 +770,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
dmr->setCSBKVerbose((verbose == 1U) ? true : false);
}
else {
reply = CMD_FAILED_STR "DMR mode is not enabled!";
reply = RCON_CMD_NACK "DMR mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -774,7 +785,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
reply = string_format("p25->debug = %u, p25->verbose = %u", debug, verbose);
}
else {
reply = CMD_FAILED_STR "P25 mode is not enabled!";
reply = RCON_CMD_NACK "P25 mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -785,7 +796,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
p25->setDebugVerbose((debug == 1U) ? true : false, (verbose == 1U) ? true : false);
}
else {
reply = CMD_FAILED_STR "P25 mode is not enabled!";
reply = RCON_CMD_NACK "P25 mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -797,7 +808,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
reply = string_format("p25->dumpTsbkData = %u", tsbkDump);
}
else {
reply = CMD_FAILED_STR "P25 mode is not enabled!";
reply = RCON_CMD_NACK "P25 mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -807,7 +818,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
p25->trunk()->setTSBKVerbose((verbose == 1U) ? true : false);
}
else {
reply = CMD_FAILED_STR "P25 mode is not enabled!";
reply = RCON_CMD_NACK "P25 mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -822,7 +833,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
reply = string_format("nxdn->debug = %u, nxdn->verbose = %u", debug, verbose);
}
else {
reply = CMD_FAILED_STR "NXDN mode is not enabled!";
reply = RCON_CMD_NACK "NXDN mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -833,7 +844,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
nxdn->setDebugVerbose((debug == 1U) ? true : false, (verbose == 1U) ? true : false);
}
else {
reply = CMD_FAILED_STR "NXDN mode is not enabled!";
reply = RCON_CMD_NACK "NXDN mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -845,7 +856,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
reply = string_format("nxdn->dumpRcchData = %u", rcchDump);
}
else {
reply = CMD_FAILED_STR "NXDN mode is not enabled!";
reply = RCON_CMD_NACK "NXDN mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -855,7 +866,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
nxdn->setRCCHVerbose((verbose == 1U) ? true : false);
}
else {
reply = CMD_FAILED_STR "NXDN mode is not enabled!";
reply = RCON_CMD_NACK "NXDN mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -997,12 +1008,14 @@ std::string RemoteControl::displayHelp()
reply += " version Display current version of host\r\n";
reply += " help Displays RCON help\r\n";
reply += " status Display current settings and operation mode\r\n";
reply += " voice-ch Retrieves the list of configured voice channels\r\n";
reply += "\r\n";
reply += " mdm-mode <mode> Set current mode of host (idle, lockout, dmr, p25, nxdn)\r\n";
reply += " mdm-kill Causes the host to quit\r\n";
reply += " mdm-force-kill Causes the host to quit immediately\r\n";
reply += "\r\n";
reply += " permit-tg <state> <dstid> Causes the host to permit the specified destination ID if non-authoritative\r\n";
reply += " grant-tg <state> <dstid> <uu> Causes the host to grant the specified destination ID if non-authoritative\r\n";
reply += "\r\n";
reply += " rid-whitelist <rid> Whitelists the specified RID in the host ACL tables\r\n";
reply += " rid-blacklist <rid> Blacklists the specified RID in the host ACL tables\r\n";
@ -1078,6 +1091,7 @@ std::string RemoteControl::rcdGetStatus(Host* host, dmr::Control* dmr, p25::Cont
reply += string_format("Host State: %u, DMR: %u, P25: %u, NXDN: %u, Port Type: %s, Modem Port: %s, Port Speed: %u, Proto Ver: %u", host->m_state,
dmr != nullptr, p25 != nullptr, nxdn != nullptr, type.c_str(), modemPort.c_str(), portSpeed, host->m_modem->getVersion());
reply += string_format("\r\nDMR CC: %u, P25 CC: %u, NXDN CC: %u", host->m_dmrCtrlChannel, host->m_p25CtrlChannel, host->m_nxdnCtrlChannel);
}
{
@ -1135,6 +1149,33 @@ std::string RemoteControl::rcdGetStatus(Host* host, dmr::Control* dmr, p25::Cont
return reply;
}
/// <summary>
///
/// </summary>
/// <param name="host">Instance of the Host class.</param>
/// <param name="dmr">Instance of the DMR Control class.</param>
/// <param name="p25">Instance of the P25 Control class.</param>
/// <param name="nxdn">Instance of the NXDN Control class.</param>
/// <returns></returns>
std::string RemoteControl::rcdGetVoiceCh(Host* host, dmr::Control* dmr, p25::Control* p25, nxdn::Control* nxdn)
{
std::string reply = "";
if (host->m_voiceChData.size() > 0) {
for (auto it = host->m_voiceChData.begin(); it != host->m_voiceChData.end(); ++it) {
uint32_t chNo = it->first;
lookups::VoiceChData data = it->second;
reply += string_format("\r\n%u, %s:%u", chNo, data.address().c_str(), data.port());
}
}
else {
reply = NO_DATA_CMD_STR;
}
return reply;
}
/// <summary>
///
/// </summary>
@ -1170,7 +1211,7 @@ std::string RemoteControl::rcdMode(std::vector<std::string> args, Host* host, dm
LogInfoEx(LOG_RCON, reply.c_str());
}
else {
reply = CMD_FAILED_STR "DMR mode is not enabled!";
reply = RCON_CMD_NACK "DMR mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -1184,7 +1225,7 @@ std::string RemoteControl::rcdMode(std::vector<std::string> args, Host* host, dm
LogInfoEx(LOG_RCON, reply.c_str());
}
else {
reply = CMD_FAILED_STR "P25 mode is not enabled!";
reply = RCON_CMD_NACK "P25 mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -1198,7 +1239,7 @@ std::string RemoteControl::rcdMode(std::vector<std::string> args, Host* host, dm
LogInfoEx(LOG_RCON, reply.c_str());
}
else {
reply = CMD_FAILED_STR "NXDN mode is not enabled!";
reply = RCON_CMD_NACK "NXDN mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
@ -1224,78 +1265,192 @@ std::string RemoteControl::rcdPermitTG(std::vector<std::string> args, Host* host
{
std::string reply = "";
if (!host->m_authoritative) {
DVM_STATE state = (DVM_STATE)getArgInt32(args, 0U);
uint32_t dstId = getArgInt32(args, 1U);
if (dstId == 0U) {
reply = string_format(INVALID_OPT_STR "illegal TGID permitted (%u)", dstId);
reply = RCON_CMD_NACK "Host is authoritative, cannot permit TG!";
LogError(LOG_RCON, reply.c_str());
return reply;
}
DVM_STATE state = (DVM_STATE)getArgInt32(args, 0U);
uint32_t dstId = getArgInt32(args, 1U);
if (dstId == 0U) {
reply = string_format(INVALID_OPT_STR "illegal TGID permitted (%u)", dstId);
LogError(LOG_RCON, reply.c_str());
return reply;
}
switch (state) {
case STATE_DMR:
#if defined(ENABLE_DMR)
{
uint8_t slot = getArgInt8(args, 2U);
if (slot == 0U) {
reply = INVALID_OPT_STR "illegal slot";
LogError(LOG_RCON, reply.c_str());
return reply;
}
if (dmr != nullptr) {
dmr->permittedTG(dstId, slot);
}
else {
switch (state) {
case STATE_DMR:
#if defined(ENABLE_DMR)
{
if (dmr != nullptr) {
dmr->permittedTG(dstId);
}
else {
reply = CMD_FAILED_STR "DMR mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
reply = RCON_CMD_NACK "DMR mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
#else
{
reply = INVALID_OPT_STR "invalid mode!";
LogError(LOG_RCON, reply.c_str());
}
{
reply = INVALID_OPT_STR "invalid mode!";
LogError(LOG_RCON, reply.c_str());
}
#endif // defined(ENABLE_DMR)
break;
case STATE_P25:
break;
case STATE_P25:
#if defined(ENABLE_P25)
{
if (p25 != nullptr) {
p25->permittedTG(dstId);
}
else {
reply = CMD_FAILED_STR "P25 mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
{
if (p25 != nullptr) {
p25->permittedTG(dstId);
}
else {
reply = RCON_CMD_NACK "P25 mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
#else
{
reply = INVALID_OPT_STR "invalid mode!";
LogError(LOG_RCON, reply.c_str());
}
{
reply = INVALID_OPT_STR "invalid mode!";
LogError(LOG_RCON, reply.c_str());
}
#endif // defined(ENABLE_P25)
break;
case STATE_NXDN:
break;
case STATE_NXDN:
#if defined(ENABLE_NXDN)
{
if (nxdn != nullptr) {
nxdn->permittedTG(dstId);
}
else {
reply = CMD_FAILED_STR "NXDN mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
{
if (nxdn != nullptr) {
nxdn->permittedTG(dstId);
}
else {
reply = RCON_CMD_NACK "NXDN mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
#else
{
reply = INVALID_OPT_STR "invalid mode!";
LogError(LOG_RCON, reply.c_str());
}
{
reply = INVALID_OPT_STR "invalid mode!";
LogError(LOG_RCON, reply.c_str());
}
#endif // defined(ENABLE_NXDN)
break;
default:
reply = INVALID_OPT_STR "invalid mode!";
LogError(LOG_RCON, reply.c_str());
break;
}
break;
default:
reply = INVALID_OPT_STR "invalid mode!";
LogError(LOG_RCON, reply.c_str());
break;
}
return reply;
}
/// <summary>
///
/// </summary>
/// <param name="args"></param>
/// <param name="host">Instance of the Host class.</param>
/// <param name="dmr">Instance of the DMR Control class.</param>
/// <param name="p25">Instance of the P25 Control class.</param>
/// <param name="nxdn">Instance of the NXDN Control class.</param>
/// <returns></returns>
std::string RemoteControl::rcdGrantTG(std::vector<std::string> args, Host* host, dmr::Control* dmr, p25::Control* p25, nxdn::Control* nxdn)
{
std::string reply = "";
if (!host->m_authoritative && (host->m_dmrCtrlChannel || host->m_p25CtrlChannel || host->m_nxdnCtrlChannel)) {
reply = RCON_CMD_NACK "Host is authoritative, cannot grant TG!";
LogError(LOG_RCON, reply.c_str());
return reply;
}
DVM_STATE state = (DVM_STATE)getArgInt32(args, 0U);
uint32_t dstId = getArgInt32(args, 1U);
uint8_t unitToUnit = getArgInt32(args, 2U);
if (unitToUnit > 1U) {
reply = string_format(INVALID_OPT_STR "illegal TGID granted (%u)", dstId);
LogError(LOG_RCON, reply.c_str());
return reply;
}
if (dstId == 0U) {
reply = string_format(INVALID_OPT_STR "illegal TGID granted (%u)", dstId);
LogError(LOG_RCON, reply.c_str());
return reply;
}
switch (state) {
case STATE_DMR:
#if defined(ENABLE_DMR)
{
uint8_t slot = getArgInt8(args, 2U);
if (slot == 0U) {
reply = INVALID_OPT_STR "illegal slot";
LogError(LOG_RCON, reply.c_str());
return reply;
}
if (dmr != nullptr) {
// TODO TODO
//dmr->grantTG(dstId, slot, unitToUnit == 1U);
}
else {
reply = RCON_CMD_NACK "DMR mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
else {
reply = CMD_FAILED_STR "Host is authoritative, cannot permit TG!";
#else
{
reply = INVALID_OPT_STR "invalid mode!";
LogError(LOG_RCON, reply.c_str());
}
#endif // defined(ENABLE_DMR)
break;
case STATE_P25:
#if defined(ENABLE_P25)
{
if (p25 != nullptr) {
// TODO TODO
//p25->grantTG(dstId, unitToUnit == 1U);
}
else {
reply = RCON_CMD_NACK "P25 mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
#else
{
reply = INVALID_OPT_STR "invalid mode!";
LogError(LOG_RCON, reply.c_str());
}
#endif // defined(ENABLE_P25)
break;
case STATE_NXDN:
#if defined(ENABLE_NXDN)
{
if (nxdn != nullptr) {
// TODO TODO
//nxdn->grantTG(dstId, unitToUnit == 1U);
}
else {
reply = RCON_CMD_NACK "NXDN mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
}
#else
{
reply = INVALID_OPT_STR "invalid mode!";
LogError(LOG_RCON, reply.c_str());
}
#endif // defined(ENABLE_NXDN)
break;
default:
reply = INVALID_OPT_STR "invalid mode!";
LogError(LOG_RCON, reply.c_str());
break;
}
return reply;
@ -1355,17 +1510,17 @@ std::string RemoteControl::rcdDMRModemInj(std::vector<std::string> args, Host* h
host->m_modem->injectDMRData2(buffer, fileSize);
}
else {
reply = CMD_FAILED_STR "invalid DMR slot!";
reply = RCON_CMD_NACK "invalid DMR slot!";
LogError(LOG_RCON, reply.c_str());
}
}
else {
reply = CMD_FAILED_STR "DMR data has too many errors!";
reply = RCON_CMD_NACK "DMR data has too many errors!";
LogError(LOG_RCON, reply.c_str());
}
}
else {
reply = CMD_FAILED_STR "DMR failed to open DMR data!";
reply = RCON_CMD_NACK "DMR failed to open DMR data!";
LogError(LOG_RCON, reply.c_str());
}
@ -1377,7 +1532,7 @@ std::string RemoteControl::rcdDMRModemInj(std::vector<std::string> args, Host* h
}
}
else {
reply = CMD_FAILED_STR "DMR mode is not enabled!";
reply = RCON_CMD_NACK "DMR mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
@ -1427,17 +1582,17 @@ std::string RemoteControl::rcdP25ModemInj(std::vector<std::string> args, Host* h
host->m_modem->injectP25Data(buffer, fileSize);
}
else {
reply = CMD_FAILED_STR "P25 data did not contain a valid NID!";
reply = RCON_CMD_NACK "P25 data did not contain a valid NID!";
LogError(LOG_RCON, reply.c_str());
}
}
else {
reply = CMD_FAILED_STR "P25 data has too many errors!";
reply = RCON_CMD_NACK "P25 data has too many errors!";
LogError(LOG_RCON, reply.c_str());
}
}
else {
reply = CMD_FAILED_STR "P25 failed to open P25 data!";
reply = RCON_CMD_NACK "P25 failed to open P25 data!";
LogError(LOG_RCON, reply.c_str());
}
@ -1449,7 +1604,7 @@ std::string RemoteControl::rcdP25ModemInj(std::vector<std::string> args, Host* h
}
}
else {
reply = CMD_FAILED_STR "P25 mode is not enabled!";
reply = RCON_CMD_NACK "P25 mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}
@ -1497,12 +1652,12 @@ std::string RemoteControl::rcdNXDNModemInj(std::vector<std::string> args, Host*
host->m_modem->injectNXDNData(buffer, fileSize);
}
else {
reply = CMD_FAILED_STR "NXDN data has too many errors!";
reply = RCON_CMD_NACK "NXDN data has too many errors!";
LogError(LOG_RCON, reply.c_str());
}
}
else {
reply = CMD_FAILED_STR "NXDN failed to open NXDN data!";
reply = RCON_CMD_NACK "NXDN failed to open NXDN data!";
LogError(LOG_RCON, reply.c_str());
}
@ -1514,7 +1669,7 @@ std::string RemoteControl::rcdNXDNModemInj(std::vector<std::string> args, Host*
}
}
else {
reply = CMD_FAILED_STR "NXDN mode is not enabled!";
reply = RCON_CMD_NACK "NXDN mode is not enabled!";
LogError(LOG_RCON, reply.c_str());
}

@ -92,9 +92,14 @@ private:
/// <summary></summary>
std::string rcdGetStatus(Host* host, dmr::Control* dmr, p25::Control* p25, nxdn::Control* nxdn);
/// <summary></summary>
std::string rcdGetVoiceCh(Host* host, dmr::Control* dmr, p25::Control* p25, nxdn::Control* nxdn);
/// <summary></summary>
std::string rcdMode(std::vector<std::string> args, Host* host, dmr::Control* dmr, p25::Control* p25, nxdn::Control* nxdn);
/// <summary></summary>
std::string rcdPermitTG(std::vector<std::string> args, Host* host, dmr::Control* dmr, p25::Control* p25, nxdn::Control* nxdn);
/// <summary></summary>
std::string rcdGrantTG(std::vector<std::string> args, Host* host, dmr::Control* dmr, p25::Control* p25, nxdn::Control* nxdn);
/// <summary></summary>
std::string rcdDMRModemInj(std::vector<std::string> args, Host* host, dmr::Control* dmr);

@ -105,6 +105,7 @@ Control::Control(bool authoritative, uint32_t ran, uint32_t callHang, uint32_t q
m_rfLastLICH(),
m_rfLC(),
m_netLC(),
m_permittedDstId(0U),
m_rfMask(0U),
m_netMask(0U),
m_idenTable(idenTable),
@ -203,13 +204,15 @@ void Control::reset()
/// </summary>
/// <param name="conf">Instance of the yaml::Node class.</param>
/// <param name="cwCallsign"></param>
/// <param name="voiceChNo"></param>
/// <param name="locId"></param>
/// <param name="channelId"></param>
/// <param name="channelNo"></param>
/// <param name="voiceChNo">Voice Channel Number list.</param>
/// <param name="voiceChData">Voice Channel data map.</param>
/// <param name="locId">NXDN Location ID.</param>
/// <param name="channelId">Channel ID.</param>
/// <param name="channelNo">Channel Number.</param>
/// <param name="printOptions"></param>
void Control::setOptions(yaml::Node& conf, const std::string cwCallsign, const std::vector<uint32_t> voiceChNo,
uint16_t locId, uint8_t channelId, uint32_t channelNo, bool printOptions)
const std::unordered_map<uint32_t, lookups::VoiceChData> voiceChData, uint16_t locId,
uint8_t channelId, uint32_t channelNo, bool printOptions)
{
yaml::Node systemConf = conf["system"];
yaml::Node nxdnProtocol = conf["protocols"]["nxdn"];
@ -249,6 +252,13 @@ void Control::setOptions(yaml::Node& conf, const std::string cwCallsign, const s
m_siteData = SiteData(locId, channelId, channelNo, serviceClass, false);
m_siteData.setCallsign(cwCallsign);
std::vector<uint32_t> availCh = voiceChNo;
for (auto it = availCh.begin(); it != availCh.end(); ++it) {
m_affiliations.addRFCh(*it);
}
m_affiliations.setRFChData(voiceChData);
lc::RCCH::setSiteData(m_siteData);
lc::RCCH::setCallsign(cwCallsign);
@ -261,11 +271,6 @@ void Control::setOptions(yaml::Node& conf, const std::string cwCallsign, const s
}
}
std::vector<uint32_t> availCh = voiceChNo;
for (auto it = availCh.begin(); it != availCh.end(); ++it) {
m_affiliations.addRFCh(*it);
}
if (printOptions) {
LogInfo(" Silence Threshold: %u (%.1f%%)", m_voice->m_silenceThreshold, float(m_voice->m_silenceThreshold) / 12.33F);
@ -591,7 +596,11 @@ void Control::clock(uint32_t ms)
/// <param name="dstId"></param>
void Control::permittedTG(uint32_t dstId)
{
// TODO TODO
if (!m_authoritative) {
return;
}
m_permittedDstId = dstId;
}
/// <summary>

@ -84,7 +84,8 @@ namespace nxdn
/// <summary>Helper to set NXDN configuration options.</summary>
void setOptions(yaml::Node& conf, const std::string cwCallsign, const std::vector<uint32_t> voiceChNo,
uint16_t locId, uint8_t channelId, uint32_t channelNo, bool printOptions);
const std::unordered_map<uint32_t, lookups::VoiceChData> voiceChData, uint16_t locId,
uint8_t channelId, uint32_t channelNo, bool printOptions);
/// <summary>Gets a flag indicating whether the NXDN control channel is running.</summary>
bool getCCRunning() { return m_ccRunning; }
@ -145,6 +146,8 @@ namespace nxdn
lc::RTCH m_rfLC;
lc::RTCH m_netLC;
uint32_t m_permittedDstId;
uint8_t m_rfMask;
uint8_t m_netMask;

@ -181,7 +181,11 @@ bool Trunk::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len)
(rcch->getEncrypted() ? 0x40U : 0x00U) + // Encrypted Flag
(rcch->getPriority() & 0x07U); // Priority
writeRF_Message_Grant(srcId, dstId, serviceOptions, true);
if (m_nxdn->m_authoritative) {
writeRF_Message_Grant(srcId, dstId, serviceOptions, true);
} else {
m_network->writeGrantReq(modem::DVM_STATE::STATE_NXDN, srcId, dstId, 0U, false);
}
}
break;
case RCCH_MESSAGE_TYPE_REG:

@ -115,6 +115,7 @@ Control::Control(bool authoritative, uint32_t nac, uint32_t callHang, uint32_t q
m_rfLastDstId(0U),
m_netState(RS_NET_IDLE),
m_netLastDstId(0U),
m_permittedDstId(0U),
m_tailOnIdle(false),
m_ccRunning(false),
m_ccPrevRunning(false),
@ -208,18 +209,19 @@ void Control::reset()
/// </summary>
/// <param name="conf">Instance of the yaml::Node class.</param>
/// <param name="cwCallsign"></param>
/// <param name="voiceChNo"></param>
/// <param name="voiceChNo">Voice Channel Number list.</param>
/// <param name="voiceChData">Voice Channel data map.</param>
/// <param name="pSuperGroup"></param>
/// <param name="netId"></param>
/// <param name="sysId"></param>
/// <param name="rfssId"></param>
/// <param name="siteId"></param>
/// <param name="channelId"></param>
/// <param name="channelNo"></param>
/// <param name="netId">P25 Network ID.</param>
/// <param name="sysId">P25 System ID.</param>
/// <param name="rfssId">P25 RFSS ID.</param>
/// <param name="siteId">P25 Site ID.</param>
/// <param name="channelId">Channel ID.</param>
/// <param name="channelNo">Channel Number.</param>
/// <param name="printOptions"></param>
void Control::setOptions(yaml::Node& conf, const std::string cwCallsign, const std::vector<uint32_t> voiceChNo,
uint32_t pSuperGroup, uint32_t netId, uint32_t sysId, uint8_t rfssId, uint8_t siteId, uint8_t channelId,
uint32_t channelNo, bool printOptions)
const std::unordered_map<uint32_t, ::lookups::VoiceChData> voiceChData, uint32_t pSuperGroup, uint32_t netId,
uint32_t sysId, uint8_t rfssId, uint8_t siteId, uint8_t channelId, uint32_t channelNo, bool printOptions)
{
yaml::Node systemConf = conf["system"];
yaml::Node p25Protocol = conf["protocols"]["p25"];
@ -309,6 +311,8 @@ void Control::setOptions(yaml::Node& conf, const std::string cwCallsign, const s
m_affiliations.addRFCh(*it);
}
m_affiliations.setRFChData(voiceChData);
uint32_t ccBcstInterval = p25Protocol["control"]["interval"].as<uint32_t>(300U);
m_trunk->m_adjSiteUpdateInterval += ccBcstInterval;
@ -760,7 +764,11 @@ void Control::clock(uint32_t ms)
/// <param name="dstId"></param>
void Control::permittedTG(uint32_t dstId)
{
// TODO TODO
if (!m_authoritative) {
return;
}
m_permittedDstId = dstId;
}
/// <summary>

@ -50,6 +50,8 @@
#include "yaml/Yaml.h"
#include <cstdio>
#include <vector>
#include <unordered_map>
namespace p25
{
@ -84,8 +86,8 @@ namespace p25
/// <summary>Helper to set P25 configuration options.</summary>
void setOptions(yaml::Node& conf, const std::string cwCallsign, const std::vector<uint32_t> voiceChNo,
uint32_t pSuperGroup, uint32_t netId, uint32_t sysId, uint8_t rfssId, uint8_t siteId,
uint8_t channelId, uint32_t channelNo, bool printOptions);
const std::unordered_map<uint32_t, ::lookups::VoiceChData> voiceChData, uint32_t pSuperGroup, uint32_t netId,
uint32_t sysId, uint8_t rfssId, uint8_t siteId, uint8_t channelId, uint32_t channelNo, bool printOptions);
/// <summary>Gets a flag indicating whether the P25 control channel is running.</summary>
bool getCCRunning() { return m_ccRunning; }
@ -178,6 +180,8 @@ namespace p25
RPT_NET_STATE m_netState;
uint32_t m_netLastDstId;
uint32_t m_permittedDstId;
bool m_tailOnIdle;
bool m_ccRunning;
bool m_ccPrevRunning;

@ -219,11 +219,15 @@ bool Trunk::process(uint8_t* data, uint32_t len, lc::TSBK* preDecodedTSBK)
LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_GRP_VCH (Group Voice Channel Request), srcId = %u, dstId = %u", srcId, dstId);
}
uint8_t serviceOptions = (tsbk->getEmergency() ? 0x80U : 0x00U) + // Emergency Flag
(tsbk->getEncrypted() ? 0x40U : 0x00U) + // Encrypted Flag
(tsbk->getPriority() & 0x07U); // Priority
if (m_p25->m_authoritative) {
uint8_t serviceOptions = (tsbk->getEmergency() ? 0x80U : 0x00U) + // Emergency Flag
(tsbk->getEncrypted() ? 0x40U : 0x00U) + // Encrypted Flag
(tsbk->getPriority() & 0x07U); // Priority
writeRF_TSDU_Grant(srcId, dstId, serviceOptions, true);
writeRF_TSDU_Grant(srcId, dstId, serviceOptions, true);
} else {
m_network->writeGrantReq(modem::DVM_STATE::STATE_P25, srcId, dstId, 0U, false);
}
}
break;
case TSBK_IOSP_UU_VCH:
@ -248,11 +252,15 @@ bool Trunk::process(uint8_t* data, uint32_t len, lc::TSBK* preDecodedTSBK)
writeRF_TSDU_UU_Ans_Req(srcId, dstId);
}
else {
uint8_t serviceOptions = (tsbk->getEmergency() ? 0x80U : 0x00U) + // Emergency Flag
(tsbk->getEncrypted() ? 0x40U : 0x00U) + // Encrypted Flag
(tsbk->getPriority() & 0x07U); // Priority
if (m_p25->m_authoritative) {
uint8_t serviceOptions = (tsbk->getEmergency() ? 0x80U : 0x00U) + // Emergency Flag
(tsbk->getEncrypted() ? 0x40U : 0x00U) + // Encrypted Flag
(tsbk->getPriority() & 0x07U); // Priority
writeRF_TSDU_Grant(srcId, dstId, serviceOptions, false);
writeRF_TSDU_Grant(srcId, dstId, serviceOptions, false);
} else {
m_network->writeGrantReq(modem::DVM_STATE::STATE_P25, srcId, dstId, 0U, true);
}
}
}
break;
@ -278,11 +286,15 @@ bool Trunk::process(uint8_t* data, uint32_t len, lc::TSBK* preDecodedTSBK)
writeRF_TSDU_ACK_FNE(dstId, TSBK_IOSP_UU_ANS, false, true);
}
uint8_t serviceOptions = (tsbk->getEmergency() ? 0x80U : 0x00U) + // Emergency Flag
(tsbk->getEncrypted() ? 0x40U : 0x00U) + // Encrypted Flag
(tsbk->getPriority() & 0x07U); // Priority
if (m_p25->m_authoritative) {
uint8_t serviceOptions = (tsbk->getEmergency() ? 0x80U : 0x00U) + // Emergency Flag
(tsbk->getEncrypted() ? 0x40U : 0x00U) + // Encrypted Flag
(tsbk->getPriority() & 0x07U); // Priority
writeRF_TSDU_Grant(srcId, dstId, serviceOptions, false);
writeRF_TSDU_Grant(srcId, dstId, serviceOptions, false);
} else {
m_network->writeGrantReq(modem::DVM_STATE::STATE_P25, srcId, dstId, 0U, true);
}
}
else if (iosp->getResponse() == P25_ANS_RSP_DENY) {
writeRF_TSDU_Deny(P25_WUID_FNE, srcId, P25_DENY_RSN_TGT_UNIT_REFUSED, TSBK_IOSP_UU_ANS);

Loading…
Cancel
Save

Powered by TurnKey Linux.