source code organization and cleanup;

pull/121/merge
Bryan Biedenkapp 2 weeks ago
parent 2d5e307fd8
commit 689243e099

@ -651,6 +651,13 @@ void RESTAPI::initializeEndpoints()
m_dispatcher.match(FNE_PUT_PEER_RESET).put(REST_API_BIND(RESTAPI::restAPI_PutPeerReset, this));
m_dispatcher.match(FNE_PUT_PEER_RESET_CONN).put(REST_API_BIND(RESTAPI::restAPI_PutPeerResetConn, this));
m_dispatcher.match(FNE_GET_PEER_LIST).get(REST_API_BIND(RESTAPI::restAPI_GetPeerList, this));
m_dispatcher.match(FNE_PUT_PEER_ADD).put(REST_API_BIND(RESTAPI::restAPI_PutPeerAdd, this));
m_dispatcher.match(FNE_PUT_PEER_DELETE).put(REST_API_BIND(RESTAPI::restAPI_PutPeerDelete, this));
m_dispatcher.match(FNE_GET_PEER_COMMIT).get(REST_API_BIND(RESTAPI::restAPI_GetPeerCommit, this));
m_dispatcher.match(FNE_PUT_PEER_NAK_PEERID).put(REST_API_BIND(RESTAPI::restAPI_PutPeerNAKByPeerId, this));
m_dispatcher.match(FNE_PUT_PEER_NAK_ADDRESS).put(REST_API_BIND(RESTAPI::restAPI_PutPeerNAKByAddress, this));
m_dispatcher.match(FNE_GET_RID_QUERY).get(REST_API_BIND(RESTAPI::restAPI_GetRIDQuery, this));
m_dispatcher.match(FNE_PUT_RID_ADD).put(REST_API_BIND(RESTAPI::restAPI_PutRIDAdd, this));
m_dispatcher.match(FNE_PUT_RID_DELETE).put(REST_API_BIND(RESTAPI::restAPI_PutRIDDelete, this));
@ -661,13 +668,6 @@ void RESTAPI::initializeEndpoints()
m_dispatcher.match(FNE_PUT_TGID_DELETE).put(REST_API_BIND(RESTAPI::restAPI_PutTGDelete, this));
m_dispatcher.match(FNE_GET_TGID_COMMIT).get(REST_API_BIND(RESTAPI::restAPI_GetTGCommit, this));
m_dispatcher.match(FNE_GET_PEER_LIST).get(REST_API_BIND(RESTAPI::restAPI_GetPeerList, this));
m_dispatcher.match(FNE_PUT_PEER_ADD).put(REST_API_BIND(RESTAPI::restAPI_PutPeerAdd, this));
m_dispatcher.match(FNE_PUT_PEER_DELETE).put(REST_API_BIND(RESTAPI::restAPI_PutPeerDelete, this));
m_dispatcher.match(FNE_GET_PEER_COMMIT).get(REST_API_BIND(RESTAPI::restAPI_GetPeerCommit, this));
m_dispatcher.match(FNE_PUT_PEER_NAK_PEERID).put(REST_API_BIND(RESTAPI::restAPI_PutPeerNAKByPeerId, this));
m_dispatcher.match(FNE_PUT_PEER_NAK_ADDRESS).put(REST_API_BIND(RESTAPI::restAPI_PutPeerNAKByAddress, this));
m_dispatcher.match(FNE_GET_ADJ_MAP_LIST).get(REST_API_BIND(RESTAPI::restAPI_GetAdjMapList, this));
m_dispatcher.match(FNE_PUT_ADJ_MAP_ADD).put(REST_API_BIND(RESTAPI::restAPI_PutAdjMapAdd, this));
m_dispatcher.match(FNE_PUT_ADJ_MAP_DELETE).put(REST_API_BIND(RESTAPI::restAPI_PutAdjMapDelete, this));
@ -870,6 +870,10 @@ void RESTAPI::restAPI_GetStatus(const HTTPPayload& request, HTTPPayload& reply,
reply.payload(response);
}
/*
** Peer Operations
*/
/* REST API endpoint; implements get peer query request. */
void RESTAPI::restAPI_GetPeerQuery(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
@ -1012,9 +1016,9 @@ void RESTAPI::restAPI_PutPeerResetConn(const HTTPPayload& request, HTTPPayload&
}
}
/* REST API endpoint; implements get radio ID query request. */
/* REST API endpoint; implements get peer list query request. */
void RESTAPI::restAPI_GetRIDQuery(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
void RESTAPI::restAPI_GetPeerList(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
{
if (!validateAuth(request, reply)) {
return;
@ -1023,41 +1027,38 @@ void RESTAPI::restAPI_GetRIDQuery(const HTTPPayload& request, HTTPPayload& reply
json::object response = json::object();
setResponseDefaultStatus(response);
json::array rids = json::array();
if (m_ridLookup != nullptr) {
if (m_ridLookup->table().size() > 0) {
for (auto entry : m_ridLookup->table()) {
json::object ridObj = json::object();
json::array peers = json::array();
if (m_peerListLookup != nullptr) {
if (m_peerListLookup->table().size() > 0) {
for (auto entry : m_peerListLookup->table()) {
json::object peerObj = json::object();
uint32_t rid = entry.first;
ridObj["id"].set<uint32_t>(rid);
bool enabled = entry.second.radioEnabled();
ridObj["enabled"].set<bool>(enabled);
std::string alias = entry.second.radioAlias();
ridObj["alias"].set<std::string>(alias);
uint32_t peerId = entry.first;
std::string peerAlias = entry.second.peerAlias();
bool peerPassword = !entry.second.peerPassword().empty(); // True if password is not empty, otherwise false
bool peerReplica = entry.second.peerReplica();
bool canRequestKeys = entry.second.canRequestKeys();
ridObj["canRequestKeys"].set<bool>(canRequestKeys);
bool canRekey = entry.second.canRekey();
ridObj["canRekey"].set<bool>(canRekey);
json::array allowedKIds = json::array();
std::vector<uint16_t> kIds = entry.second.allowedKIds();
for (uint16_t kId : kIds) {
allowedKIds.push_back(json::value((double)kId));
}
ridObj["allowedKIds"].set<json::array>(allowedKIds);
rids.push_back(json::value(ridObj));
bool canIssueInhibit = entry.second.canIssueInhibit();
bool hasCallPriority = entry.second.hasCallPriority();
peerObj["peerId"].set<uint32_t>(peerId);
peerObj["peerAlias"].set<std::string>(peerAlias);
peerObj["peerPassword"].set<bool>(peerPassword);
peerObj["peerReplica"].set<bool>(peerReplica);
peerObj["canRequestKeys"].set<bool>(canRequestKeys);
peerObj["canIssueInhibit"].set<bool>(canIssueInhibit);
peerObj["hasCallPriority"].set<bool>(hasCallPriority);
peers.push_back(json::value(peerObj));
}
}
}
response["rids"].set<json::array>(rids);
response["peers"].set<json::array>(peers);
reply.payload(response);
}
/* REST API endpoint; implements put radio ID add request. */
/* REST API endpoint; implements put peer add request. */
void RESTAPI::restAPI_PutRIDAdd(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
void RESTAPI::restAPI_PutPeerAdd(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
{
if (!validateAuth(request, reply)) {
return;
@ -1070,84 +1071,102 @@ void RESTAPI::restAPI_PutRIDAdd(const HTTPPayload& request, HTTPPayload& reply,
errorPayload(reply, "OK", HTTPPayload::OK);
if (!req["rid"].is<uint32_t>()) {
errorPayload(reply, "rid was not a valid integer");
// Validate peer ID (required)
if (!req["peerId"].is<uint32_t>()) {
errorPayload(reply, "peerId was not a valid integer");
return;
}
// Get
uint32_t peerId = req["peerId"].get<uint32_t>();
uint32_t rid = req["rid"].get<uint32_t>();
if (!req["enabled"].is<bool>()) {
errorPayload(reply, "enabled was not a valid boolean");
return;
// Get peer alias (optional)
std::string peerAlias = "";
if (req.find("peerAlias") != req.end()) {
// Validate
if (!req["peerAlias"].is<std::string>()) {
errorPayload(reply, "peerAlias was not a valid string");
return;
}
// Get
peerAlias = req["peerAlias"].get<std::string>();
}
bool enabled = req["enabled"].get<bool>();
// Get peer password (optional)
std::string peerPassword = "";
if (req.find("peerPassword") != req.end()) {
// Validate
if (!req["peerPassword"].is<std::string>()) {
errorPayload(reply, "peerPassword was not a valid string");
return;
}
// Get
peerPassword = req["peerPassword"].get<std::string>();
}
std::string alias = "";
// Check if we were provided an alias in the request
if (req.find("alias") != req.end()) {
alias = req["alias"].get<std::string>();
// Get peer link setting (optional)
bool peerReplica = false;
if (req.find("peerReplica") != req.end()) {
// Validate
if (!req["peerReplica"].is<bool>()) {
errorPayload(reply, "peerReplica was not a valid boolean");
return;
}
// Get
peerReplica = req["peerReplica"].get<bool>();
}
// Get canRequestKeys
bool canRequestKeys = false;
if (req.find("canRequestKeys") != req.end()) {
// Validate
if (!req["canRequestKeys"].is<bool>()) {
errorPayload(reply, "canRequestKeys was not a valid boolean");
return;
}
// Get
canRequestKeys = req["canRequestKeys"].get<bool>();
}
bool canRekey = false;
if (req.find("canRekey") != req.end()) {
if (!req["canRekey"].is<bool>()) {
errorPayload(reply, "canRekey was not a valid boolean");
// Get canIssueInhibit
bool canIssueInhibit = false;
if (req.find("canIssueInhibit") != req.end()) {
// Validate
if (!req["canIssueInhibit"].is<bool>()) {
errorPayload(reply, "canIssueInhibit was not a valid boolean");
return;
}
canRekey = req["canRekey"].get<bool>();
// Get
canIssueInhibit = req["canIssueInhibit"].get<bool>();
}
std::vector<uint16_t> allowedKIds;
if (req.find("allowedKIds") != req.end()) {
if (!req["allowedKIds"].is<json::array>()) {
errorPayload(reply, "allowedKIds was not a valid JSON array");
// Get hasCallPriority
bool hasCallPriority = false;
if (req.find("hasCallPriority") != req.end()) {
// Validate
if (!req["hasCallPriority"].is<bool>()) {
errorPayload(reply, "hasCallPriority was not a valid boolean");
return;
}
// Get
hasCallPriority = req["hasCallPriority"].get<bool>();
}
json::array kIdArray = req["allowedKIds"].get<json::array>();
for (auto entry : kIdArray) {
if (!entry.is<uint32_t>()) {
errorPayload(reply, "allowedKIds entry was not a valid number");
return;
}
uint32_t value = entry.get<uint32_t>();
if (value > 0xFFFFU) {
errorPayload(reply, "allowedKIds entry exceeded 16-bit key id range");
return;
}
PeerId entry = PeerId(peerId, peerAlias, peerPassword, false);
allowedKIds.push_back((uint16_t)value);
}
}
// Set additional values
entry.peerReplica(peerReplica);
entry.canRequestKeys(canRequestKeys);
entry.canIssueInhibit(canIssueInhibit);
entry.hasCallPriority(hasCallPriority);
LogInfoEx(LOG_REST, "request to add RID ACL, rid = %u", rid);
LogInfoEx(LOG_REST, "request to add peer ACL, peerId = %u", peerId);
// The addEntry function will automatically update an existing entry, so no need to check for an exisitng one here
m_ridLookup->addEntry(rid, enabled, alias, "", canRequestKeys, canRekey, allowedKIds);
/*
if (m_network != nullptr) {
m_network->m_forceListUpdate = true;
}
*/
m_peerListLookup->addEntry(peerId, entry);
}
/* REST API endpoint; implements put radio ID delete request. */
/* REST API endpoint; implements put peer delete request. */
void RESTAPI::restAPI_PutRIDDelete(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
void RESTAPI::restAPI_PutPeerDelete(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
{
if (!validateAuth(request, reply)) {
return;
@ -1160,32 +1179,21 @@ void RESTAPI::restAPI_PutRIDDelete(const HTTPPayload& request, HTTPPayload& repl
errorPayload(reply, "OK", HTTPPayload::OK);
if (!req["rid"].is<uint32_t>()) {
errorPayload(reply, "rid was not a valid integer");
if (!req["peerId"].is<uint32_t>()) {
errorPayload(reply, "peerId was not a valid integer");
return;
}
uint32_t rid = req["rid"].get<uint32_t>();
RadioId radioId = m_ridLookup->find(rid);
if (radioId.radioDefault()) {
errorPayload(reply, "failed to find specified RID to delete");
return;
}
uint32_t peerId = req["peerId"].get<uint32_t>();
LogInfoEx(LOG_REST, "request to delete RID ACL, rid = %u", rid);
LogInfoEx(LOG_REST, "request to delete peer ACL, peerId = %u", peerId);
m_ridLookup->eraseEntry(rid);
/*
if (m_network != nullptr) {
m_network->m_forceListUpdate = true;
}
*/
m_peerListLookup->eraseEntry(peerId);
}
/* REST API endpoint; implements put radio ID commit request. */
/* REST API endpoint; implements put peer list commit request. */
void RESTAPI::restAPI_GetRIDCommit(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
void RESTAPI::restAPI_GetPeerCommit(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
{
if (!validateAuth(request, reply)) {
return;
@ -1194,87 +1202,55 @@ void RESTAPI::restAPI_GetRIDCommit(const HTTPPayload& request, HTTPPayload& repl
json::object response = json::object();
setResponseDefaultStatus(response);
LogInfoEx(LOG_REST, "request to commit and save RID ACLs");
m_ridLookup->commit();
LogInfoEx(LOG_REST, "request to commit and save peer ACLs");
m_peerListLookup->commit();
reply.payload(response);
}
/* REST API endpoint; implements get talkgroup ID query request. */
/* REST API endpoint; implements put peer NAK request. */
void RESTAPI::restAPI_GetTGQuery(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
void RESTAPI::restAPI_PutPeerNAKByPeerId(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
{
if (!validateAuth(request, reply)) {
return;
}
json::object response = json::object();
setResponseDefaultStatus(response);
json::array tgs = json::array();
if (m_tidLookup != nullptr) {
if (m_tidLookup->groupVoice().size() > 0) {
for (auto entry : m_tidLookup->groupVoice()) {
json::object tg = tgToJson(entry);
tgs.push_back(json::value(tg));
}
}
json::object req = json::object();
if (!parseRequestBody(request, reply, req)) {
return;
}
response["tgs"].set<json::array>(tgs);
reply.payload(response);
}
/* REST API endpoint; implements put talkgroup ID add request. */
errorPayload(reply, "OK", HTTPPayload::OK);
void RESTAPI::restAPI_PutTGAdd(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
{
if (!validateAuth(request, reply)) {
if (!req["peerId"].is<uint32_t>()) {
errorPayload(reply, "peerId was not a valid integer");
return;
}
json::object req = json::object();
if (!parseRequestBody(request, reply, req)) {
uint32_t peerId = req["peerId"].get<uint32_t>();
if (!req["tag"].is<std::string>()) {
errorPayload(reply, "tag was not a valid string");
return;
}
errorPayload(reply, "OK", HTTPPayload::OK);
std::string tag = req["tag"].get<std::string>();
TalkgroupRuleGroupVoice groupVoice = jsonToTG(req, reply);
if (groupVoice.isInvalid()) {
::LogError(LOG_REST, "Unable to parse TG JSON from REST TgAdd");
if (!req["reason"].is<uint32_t>()) {
errorPayload(reply, "reason was not a valid integer");
return;
}
std::string groupName = groupVoice.name();
uint32_t tgId = groupVoice.source().tgId();
uint8_t tgSlot = groupVoice.source().tgSlot();
bool active = groupVoice.config().active();
bool parrot = groupVoice.config().parrot();
uint32_t incCount = groupVoice.config().inclusion().size();
uint32_t excCount = groupVoice.config().exclusion().size();
uint32_t rewrCount = groupVoice.config().rewrite().size();
uint32_t prefCount = groupVoice.config().preferred().size();
if (incCount > 0 && excCount > 0) {
::LogWarning(LOG_REST, "Talkgroup (%s) defines both inclusions and exclusions! Inclusions take precedence and exclusions will be ignored.", groupName.c_str());
}
::LogInfoEx(LOG_REST, "request to add TGID ACL");
::LogInfoEx(LOG_REST, "Talkgroup NAME: %s SRC_TGID: %u SRC_TS: %u ACTIVE: %u PARROT: %u INCLUSIONS: %u EXCLUSIONS: %u REWRITES: %u PREFERRED: %u", groupName.c_str(), tgId, tgSlot, active, parrot, incCount, excCount, rewrCount, prefCount);
uint32_t reasonCode = req["reason"].get<uint32_t>();
m_tidLookup->addEntry(groupVoice);
/*
if (m_network != nullptr) {
m_network->m_forceListUpdate = true;
}
*/
LogInfoEx(LOG_REST, "sending NAK to %u, peerId = %u, tag = %s, reason = %u", peerId, peerId, tag.c_str(), reasonCode);
m_network->writePeerNAK(peerId, m_network->createStreamId(), tag.c_str(), (NET_CONN_NAK_REASON)reasonCode);
}
/* REST API endpoint; implements put talkgroup ID delete request. */
/* REST API endpoint; implements put peer NAK request. */
void RESTAPI::restAPI_PutTGDelete(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
void RESTAPI::restAPI_PutPeerNAKByAddress(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
{
if (!validateAuth(request, reply)) {
return;
@ -1287,58 +1263,57 @@ void RESTAPI::restAPI_PutTGDelete(const HTTPPayload& request, HTTPPayload& reply
errorPayload(reply, "OK", HTTPPayload::OK);
// validate state is a string within the JSON blob
if (!req["tgid"].is<uint32_t>()) {
errorPayload(reply, "tgid was not a valid integer");
if (!req["address"].is<std::string>()) {
errorPayload(reply, "address was not a valid string");
return;
}
// Validate slot
if (!req["slot"].is<uint8_t>()) {
errorPayload(reply, "slot was not a valid char");
}
uint32_t tgid = req["tgid"].get<uint32_t>();
uint8_t slot = req["slot"].get<uint8_t>();
std::string address = req["address"].get<std::string>();
TalkgroupRuleGroupVoice groupVoice = m_tidLookup->find(tgid, slot);
if (groupVoice.isInvalid()) {
errorPayload(reply, "failed to find specified TGID to delete");
if (!req["port"].is<uint16_t>()) {
errorPayload(reply, "port was not a valid integer");
return;
}
::LogInfoEx(LOG_REST, "request to delete TGID ACL, tgid = %u, slot = %u", tgid, slot);
m_tidLookup->eraseEntry(groupVoice.source().tgId(), groupVoice.source().tgSlot());
/*
if (m_network != nullptr) {
m_network->m_forceListUpdate = true;
uint16_t port = req["port"].get<uint16_t>();
if (!req["peerId"].is<uint32_t>()) {
errorPayload(reply, "peerId was not a valid integer");
return;
}
*/
}
/* REST API endpoint; implements put talkgroup ID commit request. */
uint32_t peerId = req["peerId"].get<uint32_t>();
void RESTAPI::restAPI_GetTGCommit(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
{
if (!validateAuth(request, reply)) {
if (!req["tag"].is<std::string>()) {
errorPayload(reply, "tag was not a valid string");
return;
}
json::object response = json::object();
setResponseDefaultStatus(response);
std::string tag = req["tag"].get<std::string>();
LogInfoEx(LOG_REST, "request to commit and save TGID ACLs");
if(!m_tidLookup->commit()) {
errorPayload(reply, "failed to write new TGID file");
if (!req["reason"].is<uint32_t>()) {
errorPayload(reply, "reason was not a valid integer");
return;
}
reply.payload(response);
uint32_t reasonCode = req["reason"].get<uint32_t>();
sockaddr_storage addr;
uint32_t addrLen;
udp::Socket::lookup(address, port, addr, addrLen);
LogInfoEx(LOG_REST, "sending NAK to %s:%u, peerId = %u, tag = %s, reason = %u", address.c_str(), port, peerId, tag.c_str(), reasonCode);
m_network->writePeerNAK(peerId, tag.c_str(), (NET_CONN_NAK_REASON)reasonCode, addr, addrLen);
}
/* REST API endpoint; implements get peer list query request. */
/*
** Radio ID Operations
*/
void RESTAPI::restAPI_GetPeerList(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
/* REST API endpoint; implements get radio ID query request. */
void RESTAPI::restAPI_GetRIDQuery(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
{
if (!validateAuth(request, reply)) {
return;
@ -1347,38 +1322,41 @@ void RESTAPI::restAPI_GetPeerList(const HTTPPayload& request, HTTPPayload& reply
json::object response = json::object();
setResponseDefaultStatus(response);
json::array peers = json::array();
if (m_peerListLookup != nullptr) {
if (m_peerListLookup->table().size() > 0) {
for (auto entry : m_peerListLookup->table()) {
json::object peerObj = json::object();
json::array rids = json::array();
if (m_ridLookup != nullptr) {
if (m_ridLookup->table().size() > 0) {
for (auto entry : m_ridLookup->table()) {
json::object ridObj = json::object();
uint32_t peerId = entry.first;
std::string peerAlias = entry.second.peerAlias();
bool peerPassword = !entry.second.peerPassword().empty(); // True if password is not empty, otherwise false
bool peerReplica = entry.second.peerReplica();
uint32_t rid = entry.first;
ridObj["id"].set<uint32_t>(rid);
bool enabled = entry.second.radioEnabled();
ridObj["enabled"].set<bool>(enabled);
std::string alias = entry.second.radioAlias();
ridObj["alias"].set<std::string>(alias);
bool canRequestKeys = entry.second.canRequestKeys();
bool canIssueInhibit = entry.second.canIssueInhibit();
bool hasCallPriority = entry.second.hasCallPriority();
peerObj["peerId"].set<uint32_t>(peerId);
peerObj["peerAlias"].set<std::string>(peerAlias);
peerObj["peerPassword"].set<bool>(peerPassword);
peerObj["peerReplica"].set<bool>(peerReplica);
peerObj["canRequestKeys"].set<bool>(canRequestKeys);
peerObj["canIssueInhibit"].set<bool>(canIssueInhibit);
peerObj["hasCallPriority"].set<bool>(hasCallPriority);
peers.push_back(json::value(peerObj));
ridObj["canRequestKeys"].set<bool>(canRequestKeys);
bool canRekey = entry.second.canRekey();
ridObj["canRekey"].set<bool>(canRekey);
json::array allowedKIds = json::array();
std::vector<uint16_t> kIds = entry.second.allowedKIds();
for (uint16_t kId : kIds) {
allowedKIds.push_back(json::value((double)kId));
}
ridObj["allowedKIds"].set<json::array>(allowedKIds);
rids.push_back(json::value(ridObj));
}
}
}
response["peers"].set<json::array>(peers);
response["rids"].set<json::array>(rids);
reply.payload(response);
}
/* REST API endpoint; implements put peer add request. */
/* REST API endpoint; implements put radio ID add request. */
void RESTAPI::restAPI_PutPeerAdd(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
void RESTAPI::restAPI_PutRIDAdd(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
{
if (!validateAuth(request, reply)) {
return;
@ -1391,102 +1369,84 @@ void RESTAPI::restAPI_PutPeerAdd(const HTTPPayload& request, HTTPPayload& reply,
errorPayload(reply, "OK", HTTPPayload::OK);
// Validate peer ID (required)
if (!req["peerId"].is<uint32_t>()) {
errorPayload(reply, "peerId was not a valid integer");
if (!req["rid"].is<uint32_t>()) {
errorPayload(reply, "rid was not a valid integer");
return;
}
// Get
uint32_t peerId = req["peerId"].get<uint32_t>();
// Get peer alias (optional)
std::string peerAlias = "";
if (req.find("peerAlias") != req.end()) {
// Validate
if (!req["peerAlias"].is<std::string>()) {
errorPayload(reply, "peerAlias was not a valid string");
return;
}
// Get
peerAlias = req["peerAlias"].get<std::string>();
}
uint32_t rid = req["rid"].get<uint32_t>();
// Get peer password (optional)
std::string peerPassword = "";
if (req.find("peerPassword") != req.end()) {
// Validate
if (!req["peerPassword"].is<std::string>()) {
errorPayload(reply, "peerPassword was not a valid string");
return;
}
// Get
peerPassword = req["peerPassword"].get<std::string>();
if (!req["enabled"].is<bool>()) {
errorPayload(reply, "enabled was not a valid boolean");
return;
}
// Get peer link setting (optional)
bool peerReplica = false;
if (req.find("peerReplica") != req.end()) {
// Validate
if (!req["peerReplica"].is<bool>()) {
errorPayload(reply, "peerReplica was not a valid boolean");
return;
}
// Get
peerReplica = req["peerReplica"].get<bool>();
bool enabled = req["enabled"].get<bool>();
std::string alias = "";
// Check if we were provided an alias in the request
if (req.find("alias") != req.end()) {
alias = req["alias"].get<std::string>();
}
// Get canRequestKeys
bool canRequestKeys = false;
if (req.find("canRequestKeys") != req.end()) {
// Validate
if (!req["canRequestKeys"].is<bool>()) {
errorPayload(reply, "canRequestKeys was not a valid boolean");
return;
}
// Get
canRequestKeys = req["canRequestKeys"].get<bool>();
}
// Get canIssueInhibit
bool canIssueInhibit = false;
if (req.find("canIssueInhibit") != req.end()) {
// Validate
if (!req["canIssueInhibit"].is<bool>()) {
errorPayload(reply, "canIssueInhibit was not a valid boolean");
bool canRekey = false;
if (req.find("canRekey") != req.end()) {
if (!req["canRekey"].is<bool>()) {
errorPayload(reply, "canRekey was not a valid boolean");
return;
}
// Get
canIssueInhibit = req["canIssueInhibit"].get<bool>();
canRekey = req["canRekey"].get<bool>();
}
// Get hasCallPriority
bool hasCallPriority = false;
if (req.find("hasCallPriority") != req.end()) {
// Validate
if (!req["hasCallPriority"].is<bool>()) {
errorPayload(reply, "hasCallPriority was not a valid boolean");
std::vector<uint16_t> allowedKIds;
if (req.find("allowedKIds") != req.end()) {
if (!req["allowedKIds"].is<json::array>()) {
errorPayload(reply, "allowedKIds was not a valid JSON array");
return;
}
// Get
hasCallPriority = req["hasCallPriority"].get<bool>();
}
PeerId entry = PeerId(peerId, peerAlias, peerPassword, false);
json::array kIdArray = req["allowedKIds"].get<json::array>();
for (auto entry : kIdArray) {
if (!entry.is<uint32_t>()) {
errorPayload(reply, "allowedKIds entry was not a valid number");
return;
}
// Set additional values
entry.peerReplica(peerReplica);
entry.canRequestKeys(canRequestKeys);
entry.canIssueInhibit(canIssueInhibit);
entry.hasCallPriority(hasCallPriority);
uint32_t value = entry.get<uint32_t>();
if (value > 0xFFFFU) {
errorPayload(reply, "allowedKIds entry exceeded 16-bit key id range");
return;
}
LogInfoEx(LOG_REST, "request to add peer ACL, peerId = %u", peerId);
allowedKIds.push_back((uint16_t)value);
}
}
m_peerListLookup->addEntry(peerId, entry);
LogInfoEx(LOG_REST, "request to add RID ACL, rid = %u", rid);
// The addEntry function will automatically update an existing entry, so no need to check for an exisitng one here
m_ridLookup->addEntry(rid, enabled, alias, "", canRequestKeys, canRekey, allowedKIds);
/*
if (m_network != nullptr) {
m_network->m_forceListUpdate = true;
}
*/
}
/* REST API endpoint; implements put peer delete request. */
/* REST API endpoint; implements put radio ID delete request. */
void RESTAPI::restAPI_PutPeerDelete(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
void RESTAPI::restAPI_PutRIDDelete(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
{
if (!validateAuth(request, reply)) {
return;
@ -1499,21 +1459,32 @@ void RESTAPI::restAPI_PutPeerDelete(const HTTPPayload& request, HTTPPayload& rep
errorPayload(reply, "OK", HTTPPayload::OK);
if (!req["peerId"].is<uint32_t>()) {
errorPayload(reply, "peerId was not a valid integer");
if (!req["rid"].is<uint32_t>()) {
errorPayload(reply, "rid was not a valid integer");
return;
}
uint32_t peerId = req["peerId"].get<uint32_t>();
uint32_t rid = req["rid"].get<uint32_t>();
LogInfoEx(LOG_REST, "request to delete peer ACL, peerId = %u", peerId);
RadioId radioId = m_ridLookup->find(rid);
if (radioId.radioDefault()) {
errorPayload(reply, "failed to find specified RID to delete");
return;
}
m_peerListLookup->eraseEntry(peerId);
LogInfoEx(LOG_REST, "request to delete RID ACL, rid = %u", rid);
m_ridLookup->eraseEntry(rid);
/*
if (m_network != nullptr) {
m_network->m_forceListUpdate = true;
}
*/
}
/* REST API endpoint; implements put peer list commit request. */
/* REST API endpoint; implements put radio ID commit request. */
void RESTAPI::restAPI_GetPeerCommit(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
void RESTAPI::restAPI_GetRIDCommit(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
{
if (!validateAuth(request, reply)) {
return;
@ -1522,15 +1493,44 @@ void RESTAPI::restAPI_GetPeerCommit(const HTTPPayload& request, HTTPPayload& rep
json::object response = json::object();
setResponseDefaultStatus(response);
LogInfoEx(LOG_REST, "request to commit and save peer ACLs");
m_peerListLookup->commit();
LogInfoEx(LOG_REST, "request to commit and save RID ACLs");
m_ridLookup->commit();
reply.payload(response);
}
/* REST API endpoint; implements put peer NAK request. */
/*
** Talkgroup Operations
*/
void RESTAPI::restAPI_PutPeerNAKByPeerId(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
/* REST API endpoint; implements get talkgroup ID query request. */
void RESTAPI::restAPI_GetTGQuery(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
{
if (!validateAuth(request, reply)) {
return;
}
json::object response = json::object();
setResponseDefaultStatus(response);
json::array tgs = json::array();
if (m_tidLookup != nullptr) {
if (m_tidLookup->groupVoice().size() > 0) {
for (auto entry : m_tidLookup->groupVoice()) {
json::object tg = tgToJson(entry);
tgs.push_back(json::value(tg));
}
}
}
response["tgs"].set<json::array>(tgs);
reply.payload(response);
}
/* REST API endpoint; implements put talkgroup ID add request. */
void RESTAPI::restAPI_PutTGAdd(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
{
if (!validateAuth(request, reply)) {
return;
@ -1543,34 +1543,41 @@ void RESTAPI::restAPI_PutPeerNAKByPeerId(const HTTPPayload& request, HTTPPayload
errorPayload(reply, "OK", HTTPPayload::OK);
if (!req["peerId"].is<uint32_t>()) {
errorPayload(reply, "peerId was not a valid integer");
TalkgroupRuleGroupVoice groupVoice = jsonToTG(req, reply);
if (groupVoice.isInvalid()) {
::LogError(LOG_REST, "Unable to parse TG JSON from REST TgAdd");
return;
}
uint32_t peerId = req["peerId"].get<uint32_t>();
if (!req["tag"].is<std::string>()) {
errorPayload(reply, "tag was not a valid string");
return;
}
std::string groupName = groupVoice.name();
uint32_t tgId = groupVoice.source().tgId();
uint8_t tgSlot = groupVoice.source().tgSlot();
bool active = groupVoice.config().active();
bool parrot = groupVoice.config().parrot();
std::string tag = req["tag"].get<std::string>();
uint32_t incCount = groupVoice.config().inclusion().size();
uint32_t excCount = groupVoice.config().exclusion().size();
uint32_t rewrCount = groupVoice.config().rewrite().size();
uint32_t prefCount = groupVoice.config().preferred().size();
if (!req["reason"].is<uint32_t>()) {
errorPayload(reply, "reason was not a valid integer");
return;
if (incCount > 0 && excCount > 0) {
::LogWarning(LOG_REST, "Talkgroup (%s) defines both inclusions and exclusions! Inclusions take precedence and exclusions will be ignored.", groupName.c_str());
}
uint32_t reasonCode = req["reason"].get<uint32_t>();
::LogInfoEx(LOG_REST, "request to add TGID ACL");
::LogInfoEx(LOG_REST, "Talkgroup NAME: %s SRC_TGID: %u SRC_TS: %u ACTIVE: %u PARROT: %u INCLUSIONS: %u EXCLUSIONS: %u REWRITES: %u PREFERRED: %u", groupName.c_str(), tgId, tgSlot, active, parrot, incCount, excCount, rewrCount, prefCount);
LogInfoEx(LOG_REST, "sending NAK to %u, peerId = %u, tag = %s, reason = %u", peerId, peerId, tag.c_str(), reasonCode);
m_network->writePeerNAK(peerId, m_network->createStreamId(), tag.c_str(), (NET_CONN_NAK_REASON)reasonCode);
m_tidLookup->addEntry(groupVoice);
/*
if (m_network != nullptr) {
m_network->m_forceListUpdate = true;
}
*/
}
/* REST API endpoint; implements put peer NAK request. */
/* REST API endpoint; implements put talkgroup ID delete request. */
void RESTAPI::restAPI_PutPeerNAKByAddress(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
void RESTAPI::restAPI_PutTGDelete(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
{
if (!validateAuth(request, reply)) {
return;
@ -1583,50 +1590,59 @@ void RESTAPI::restAPI_PutPeerNAKByAddress(const HTTPPayload& request, HTTPPayloa
errorPayload(reply, "OK", HTTPPayload::OK);
if (!req["address"].is<std::string>()) {
errorPayload(reply, "address was not a valid string");
// validate state is a string within the JSON blob
if (!req["tgid"].is<uint32_t>()) {
errorPayload(reply, "tgid was not a valid integer");
return;
}
std::string address = req["address"].get<std::string>();
if (!req["port"].is<uint16_t>()) {
errorPayload(reply, "port was not a valid integer");
return;
// Validate slot
if (!req["slot"].is<uint8_t>()) {
errorPayload(reply, "slot was not a valid char");
}
uint16_t port = req["port"].get<uint16_t>();
uint32_t tgid = req["tgid"].get<uint32_t>();
uint8_t slot = req["slot"].get<uint8_t>();
if (!req["peerId"].is<uint32_t>()) {
errorPayload(reply, "peerId was not a valid integer");
TalkgroupRuleGroupVoice groupVoice = m_tidLookup->find(tgid, slot);
if (groupVoice.isInvalid()) {
errorPayload(reply, "failed to find specified TGID to delete");
return;
}
uint32_t peerId = req["peerId"].get<uint32_t>();
if (!req["tag"].is<std::string>()) {
errorPayload(reply, "tag was not a valid string");
return;
::LogInfoEx(LOG_REST, "request to delete TGID ACL, tgid = %u, slot = %u", tgid, slot);
m_tidLookup->eraseEntry(groupVoice.source().tgId(), groupVoice.source().tgSlot());
/*
if (m_network != nullptr) {
m_network->m_forceListUpdate = true;
}
*/
}
std::string tag = req["tag"].get<std::string>();
/* REST API endpoint; implements put talkgroup ID commit request. */
if (!req["reason"].is<uint32_t>()) {
errorPayload(reply, "reason was not a valid integer");
void RESTAPI::restAPI_GetTGCommit(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
{
if (!validateAuth(request, reply)) {
return;
}
uint32_t reasonCode = req["reason"].get<uint32_t>();
sockaddr_storage addr;
uint32_t addrLen;
json::object response = json::object();
setResponseDefaultStatus(response);
udp::Socket::lookup(address, port, addr, addrLen);
LogInfoEx(LOG_REST, "request to commit and save TGID ACLs");
if(!m_tidLookup->commit()) {
errorPayload(reply, "failed to write new TGID file");
return;
}
LogInfoEx(LOG_REST, "sending NAK to %s:%u, peerId = %u, tag = %s, reason = %u", address.c_str(), port, peerId, tag.c_str(), reasonCode);
m_network->writePeerNAK(peerId, tag.c_str(), (NET_CONN_NAK_REASON)reasonCode, addr, addrLen);
reply.payload(response);
}
/*
** Adjacent Site Map Operations
*/
/* REST API endpoint; implements get adjacent site map query request. */
void RESTAPI::restAPI_GetAdjMapList(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
@ -1759,6 +1775,10 @@ void RESTAPI::restAPI_GetAdjMapCommit(const HTTPPayload& request, HTTPPayload& r
reply.payload(response);
}
/*
** Refresh and Statistics/Metadata Operations
*/
/* */
void RESTAPI::restAPI_GetForceUpdate(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)

@ -170,6 +170,10 @@ private:
*/
void restAPI_GetStatus(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
/*
** Peer Operations
*/
/**
* @brief REST API endpoint; implements get peer query request.
* @param request HTTP request.
@ -200,105 +204,117 @@ private:
void restAPI_PutPeerResetConn(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
/**
* @brief REST API endpoint; implements get radio ID query request.
* @brief REST API endpoint; implements get peer list query request.
* @param request HTTP request.
* @param reply HTTP reply.
* @param match HTTP request matcher.
*/
void restAPI_GetRIDQuery(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
void restAPI_GetPeerList(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
/**
* @brief REST API endpoint; implements put radio ID add request.
* @brief REST API endpoint; implements put peer add request.
* @param request HTTP request.
* @param reply HTTP reply.
* @param match HTTP request matcher.
*/
void restAPI_PutRIDAdd(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
void restAPI_PutPeerAdd(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
/**
* @brief REST API endpoint; implements put radio ID delete request.
* @brief REST API endpoint; implements put peer delete request.
* @param request HTTP request.
* @param reply HTTP reply.
* @param match HTTP request matcher.
*/
void restAPI_PutRIDDelete(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
void restAPI_PutPeerDelete(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
/**
* @brief REST API endpoint; implements put radio ID commit request.
* @brief REST API endpoint; implements put peer list commit request.
* @param request HTTP request.
* @param reply HTTP reply.
* @param match HTTP request matcher.
*/
void restAPI_GetRIDCommit(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
void restAPI_GetPeerCommit(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
/**
* @brief REST API endpoint; implements get talkgroup ID query request.
* @brief REST API endpoint; implements put peer NAK request.
* @param request HTTP request.
* @param reply HTTP reply.
* @param match HTTP request matcher.
*/
void restAPI_GetTGQuery(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
void restAPI_PutPeerNAKByPeerId(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
/**
* @brief REST API endpoint; implements put talkgroup ID add request.
* @brief REST API endpoint; implements put peer NAK request.
* @param request HTTP request.
* @param reply HTTP reply.
* @param match HTTP request matcher.
*/
void restAPI_PutTGAdd(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
void restAPI_PutPeerNAKByAddress(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
/*
** Radio ID Operations
*/
/**
* @brief REST API endpoint; implements put talkgroup ID delete request.
* @brief REST API endpoint; implements get radio ID query request.
* @param request HTTP request.
* @param reply HTTP reply.
* @param match HTTP request matcher.
*/
void restAPI_PutTGDelete(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
void restAPI_GetRIDQuery(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
/**
* @brief REST API endpoint; implements put talkgroup ID commit request.
* @brief REST API endpoint; implements put radio ID add request.
* @param request HTTP request.
* @param reply HTTP reply.
* @param match HTTP request matcher.
*/
void restAPI_GetTGCommit(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
void restAPI_PutRIDAdd(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
/**
* @brief REST API endpoint; implements get peer list query request.
* @brief REST API endpoint; implements put radio ID delete request.
* @param request HTTP request.
* @param reply HTTP reply.
* @param match HTTP request matcher.
*/
void restAPI_GetPeerList(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
void restAPI_PutRIDDelete(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
/**
* @brief REST API endpoint; implements put peer add request.
* @brief REST API endpoint; implements put radio ID commit request.
* @param request HTTP request.
* @param reply HTTP reply.
* @param match HTTP request matcher.
*/
void restAPI_PutPeerAdd(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
void restAPI_GetRIDCommit(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
/*
** Talkgroup ID Operations
*/
/**
* @brief REST API endpoint; implements put peer delete request.
* @brief REST API endpoint; implements get talkgroup ID query request.
* @param request HTTP request.
* @param reply HTTP reply.
* @param match HTTP request matcher.
*/
void restAPI_PutPeerDelete(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
void restAPI_GetTGQuery(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
/**
* @brief REST API endpoint; implements put peer list commit request.
* @brief REST API endpoint; implements put talkgroup ID add request.
* @param request HTTP request.
* @param reply HTTP reply.
* @param match HTTP request matcher.
*/
void restAPI_GetPeerCommit(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
void restAPI_PutTGAdd(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
/**
* @brief REST API endpoint; implements put peer NAK request.
* @brief REST API endpoint; implements put talkgroup ID delete request.
* @param request HTTP request.
* @param reply HTTP reply.
* @param match HTTP request matcher.
*/
void restAPI_PutPeerNAKByPeerId(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
void restAPI_PutTGDelete(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
/**
* @brief REST API endpoint; implements put peer NAK request.
* @brief REST API endpoint; implements put talkgroup ID commit request.
* @param request HTTP request.
* @param reply HTTP reply.
* @param match HTTP request matcher.
*/
void restAPI_PutPeerNAKByAddress(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
void restAPI_GetTGCommit(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
/*
** Adjacent Site Map Operations
*/
/**
* @brief REST API endpoint; implements get adjacent site map list query request.
@ -329,6 +345,10 @@ private:
*/
void restAPI_GetAdjMapCommit(const HTTPPayload& request, HTTPPayload& reply, const restapi::RequestMatch& match);
/*
** Refresh and Statistics/Metadata Operations
*/
/**
* @brief
* @param request HTTP request.

Loading…
Cancel
Save

Powered by TurnKey Linux.