@ -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_Get RIDQuery ( const HTTPPayload & request , HTTPPayload & reply , const RequestMatch & match )
void RESTAPI : : restAPI_Get PeerList ( 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 rid s = json : : array ( ) ;
if ( m_ rid Lookup ! = nullptr ) {
if ( m_ rid Lookup- > table ( ) . size ( ) > 0 ) {
for ( auto entry : m_ rid Lookup- > table ( ) ) {
json : : object rid Obj = json : : object ( ) ;
json : : array pee rs = json : : array ( ) ;
if ( m_ peerList Lookup ! = nullptr ) {
if ( m_ peerList Lookup- > table ( ) . size ( ) > 0 ) {
for ( auto entry : m_ peerList Lookup- > table ( ) ) {
json : : object pee rObj = 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 [ " rid s" ] . set < json : : array > ( rid s) ;
response [ " pee rs" ] . set < json : : array > ( pee rs) ;
reply . payload ( response ) ;
}
/* REST API endpoint; implements put radio ID add request. */
/* REST API endpoint; implements put pee r add request. */
void RESTAPI : : restAPI_Put RID Add( const HTTPPayload & request , HTTPPayload & reply , const RequestMatch & match )
void RESTAPI : : restAPI_Put Peer Add( 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 ;
}
can Rekey = req [ " canRekey " ] . get < bool > ( ) ;
// Get
can IssueInhibit = 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_Put RID Delete( 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 [ " ri d" ] . is < uint32_t > ( ) ) {
errorPayload ( reply , " ri d was not a valid integer" ) ;
if ( ! req [ " peerI d" ] . is < uint32_t > ( ) ) {
errorPayload ( reply , " peerI d 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" , ri d) ;
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_Get RID Commit( 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_ rid Lookup- > commit ( ) ;
LogInfoEx ( LOG_REST , " request to commit and save peer ACLs" ) ;
m_ peerList Lookup- > 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 talkgrou p ID d elet e request. */
/* REST API endpoint; implements put peer NAK request. */
void RESTAPI : : restAPI_Put TGDelete ( 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 pee rs = json : : array ( ) ;
if ( m_ peerList Lookup ! = nullptr ) {
if ( m_ peerList Lookup- > table ( ) . size ( ) > 0 ) {
for ( auto entry : m_ peerList Lookup- > table ( ) ) {
json : : object pee rObj = json : : object ( ) ;
json : : array rid s = json : : array ( ) ;
if ( m_ rid Lookup ! = nullptr ) {
if ( m_ rid Lookup- > table ( ) . size ( ) > 0 ) {
for ( auto entry : m_ rid Lookup- > table ( ) ) {
json : : object rid Obj = 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 [ " pee rs" ] . set < json : : array > ( pee rs) ;
response [ " rid s" ] . set < json : : array > ( rid s) ;
reply . payload ( response ) ;
}
/* REST API endpoint; implements put pee r add request. */
/* REST API endpoint; implements put radio ID add request. */
void RESTAPI : : restAPI_Put Peer Add( const HTTPPayload & request , HTTPPayload & reply , const RequestMatch & match )
void RESTAPI : : restAPI_Put RID Add( 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
can IssueInhibit = req [ " canIssueInhibit " ] . get < bool > ( ) ;
can Rekey = 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_Put RID Delete( 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 [ " peerI d" ] . is < uint32_t > ( ) ) {
errorPayload ( reply , " peerI d was not a valid integer" ) ;
if ( ! req [ " ri d" ] . is < uint32_t > ( ) ) {
errorPayload ( reply , " ri d was not a valid integer" ) ;
return ;
}
uint32_t peerId = req [ " peerI d" ] . get < uint32_t > ( ) ;
uint32_t rid = req [ " ri d" ] . 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_Get RID Commit( 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_ peerList Lookup- > commit ( ) ;
LogInfoEx ( LOG_REST , " request to commit and save RID ACLs" ) ;
m_ rid Lookup- > 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_Put PeerNAKByAddress ( const HTTPPayload & request , HTTPPayload & reply , const RequestMatch & match )
void RESTAPI : : restAPI_Put TGDelete ( 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 )