//////////////////////////////////////////////////////////////////////////////////// /// /// \brief Processes message received by the Service. If not supported, then /// message is passed to inheriting services depending on what /// type of control has been established for the component. /// /// This Service supports AccessControl related messages only. /// /// \param[in] message Message data to process. /// //////////////////////////////////////////////////////////////////////////////////// void AccessControl::Receive(const Message* message) { if(AcceptCommandMessage(message) == false) { return; } if(mControllerID == message->GetSourceID()) { mControllerUpdateTime.SetCurrentTime(); } switch(message->GetMessageCode()) { case CONFIRM_CONTROL: { const ConfirmControl* command = dynamic_cast<const ConfirmControl*>(message); if(command == NULL) return; if(command->GetResponseCode() == ConfirmControl::ControlAccepted) { bool firstTime = true; // Lock data. mControlMutex.Lock(); // See if we already had control, and if not, then // we re-acquired control of this component and must // signal via callbacks, etc. of this event. Address::Set::iterator controlledComponent = mControlledComponents.find(message->GetSourceID()); if(controlledComponent != mControlledComponents.end()) { // If we get here, we have been trying to control this // component. Check the control status flag. std::map<Address, bool>::iterator flag = mControlFlags.find(message->GetSourceID()); if(flag->second == true) { // We already had control, nothing new here. // So don't trigger events. firstTime = false; } } mControlledComponents.insert(message->GetSourceID()); mControlConfirmTimes[message->GetSourceID()].SetCurrentTime(); mControlFlags[message->GetSourceID()] = true; // Unlock data. mControlMutex.Unlock(); if(mDebugMessagesFlag) { Mutex::ScopedLock plock(&mDebugMessagesMutex); if(firstTime) { std::cout << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Acquired Control of " << message->GetSourceID().ToString() << " at " << Time::GetUtcTime().ToString() << "\n"; } else { std::cout << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Maintained Control of " << message->GetSourceID().ToString() << " at " << Time::GetUtcTime().ToString() << "\n"; } } // Trigger callbacks if needed. if(firstTime) { Service::Map children = GetChildServices(); Service::Map::iterator child; for(child = children.begin(); child != children.end(); child++) { Child* controlChild = dynamic_cast<Child *>(child->second); if(controlChild) { controlChild->ProcessAcquisitionOfControl(message->GetSourceID()); } } Mutex::ScopedLock cbLock(&mCallbacksMutex); Callback::Set::iterator cb; for(cb = mCallbacks.begin(); cb != mCallbacks.end(); cb++) { (*cb)->ProcessAcquisitionfControl(message->GetSourceID()); } } } else { Address::Set::iterator component; // Lock data. mControlMutex.Lock(); component = mControlledComponents.find(message->GetSourceID()); if(component != mControlledComponents.end()) { std::map<Address, bool>::iterator flag; flag = mMaintainFlags.find(message->GetSourceID()); if(flag != mMaintainFlags.end()) { // If we didn't get control, and we are not // trying to maintain control, remove the component // from our lists. If we don't have high enough authority // then don't bother trying to re-acquire control. if(flag->second == false || command->GetMessageCode() == ConfirmControl::InsufficientAuthority) { EraseComponentControlInfo(message->GetSourceID()); } else // Update control status { mControlFlags[message->GetSourceID()] = false; } } // Delete junk data. else { EraseComponentControlInfo(message->GetSourceID()); } } // Unlock data. mControlMutex.Unlock(); } } break; case QUERY_AUTHORITY: { if(mShutdownServiceFlag) { break; } Mutex::ScopedLock lock(&mControlMutex); ReportAuthority report(message->GetSourceID(), GetComponentID()); report.SetAuthorityCode(mAuthorityCode); Send(&report); } break; case QUERY_CONTROL: { Mutex::ScopedLock lock(&mControlMutex); ReportControl report(message->GetSourceID(), GetComponentID()); report.SetAuthorityCode(mControllerAuthorityCode); report.SetControllingComponent(mControllerID); Send(&report); } break; case QUERY_TIMEOUT: { Mutex::ScopedLock lock(&mControlMutex); ReportTimeout report(message->GetSourceID(), GetComponentID()); report.SetTimeoutSeconds(mTimeoutPeriod); Send(&report); } break; case REJECT_CONTROL: { const RejectControl* command = dynamic_cast<const RejectControl*>(message); if(mShutdownServiceFlag || command == NULL) return; Mutex::ScopedLock lock(&mControlMutex); Address::Set::iterator component; component = mControlledComponents.find(message->GetSourceID()); if(component != mControlledComponents.end()) { std::map<Address, bool>::iterator flag; flag = mMaintainFlags.find(message->GetSourceID()); if(flag != mMaintainFlags.end()) { // If we lost control, and we are not // trying to maintain control, remove the component // from our lists. if(flag->second == false) { mMaintainFlags.erase(flag); mControlFlags.erase(mControlFlags.find(message->GetSourceID())); mControlConfirmTimes.erase(mControlConfirmTimes.find(message->GetSourceID())); mControlledComponents.erase(component); } else // Update control status { mControlFlags[message->GetSourceID()] = false; } // Generate events and callbacks. Mutex::ScopedLock clock(&mCallbacksMutex); Callback::Set::iterator cb; for(cb = mCallbacks.begin(); cb != mCallbacks.end(); cb++) { (*cb)->ProcessLossOfControl(message->GetSourceID()); } } // Delete junk data. else { if(mControlFlags.find(*component) != mControlFlags.end()) { mControlFlags.erase(*component); } mControlledComponents.erase(*component); } } if(mDebugMessagesFlag) { Mutex::ScopedLock plock(&mDebugMessagesMutex); std::cout << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Lost Control of " << message->GetSourceID().ToString() << " at " << Time::GetUtcTime().ToString() << "\n"; } } break; case RELEASE_CONTROL: { const ReleaseControl* command = dynamic_cast<const ReleaseControl*>(message); if(mShutdownServiceFlag || command == NULL) return; Mutex::ScopedLock lock(&mControlMutex); if(command->GetSourceID() == mControllerID) { RejectControl response(mControllerID, GetComponentID()); bool controlReleased = true; Service::Map children = GetChildServices(); Service::Map::iterator child; for(child = children.begin(); child != children.end(); child++) { Child* controlChild = dynamic_cast<Child *>(child->second); if(controlChild) { if(controlChild->ReleaseControl()) { controlReleased; } } } if(controlReleased) { response.SetResponseCode(RejectControl::ControlReleased); Send(&response); mControllerID = Address(); mControllerAuthorityCode = 0; mControllerUpdateTime.Clear(); mControllerCheckTime.Clear(); if(mDebugMessagesFlag) { Mutex::ScopedLock plock(&mDebugMessagesMutex); std::cout << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Control Released from " << message->GetSourceID().ToString() << " at " << Time::GetUtcTime().ToString() << "\n"; } // Generate events and callbacks. Mutex::ScopedLock clock(&mCallbacksMutex); Callback::Set::iterator cb; for(cb = mCallbacks.begin(); cb != mCallbacks.end(); cb++) { (*cb)->ProcessReleaseOfControl(message->GetSourceID()); } SignalEvent(REPORT_CONTROL); } else { response.SetResponseCode(RejectControl::NotAvailable); Send(&response); } } } break; case REPORT_AUTHORITY: { const JAUS::ReportAuthority* report = dynamic_cast<const JAUS::ReportAuthority*>(message); if(report) { // Update Discovery Contents. try { Discovery* discovery = GetComponent()->DiscoveryService(); if(discovery) { discovery->GetSubsystem(report->GetSourceID().mSubsystem)->GetComponent(report->GetSourceID())->mAuthorityLevel = (int)report->GetAuthorityCode(); if( discovery->GetVehicle(report->GetSourceID().mSubsystem).IsValid() && discovery->GetVehicle(report->GetSourceID().mSubsystem)->mAuthority < (int)report->GetAuthorityCode()) { discovery->GetVehicle(report->GetSourceID().mSubsystem)->mAuthority = (int)report->GetAuthorityCode(); } } } catch(Exception& e) { e.Print(); } } } break; case REPORT_CONTROL: // Not used. break; case REPORT_TIMEOUT: { const ReportTimeout* report = dynamic_cast<const ReportTimeout*>(message); if(report == NULL) return; Mutex::ScopedLock lock(&mControlMutex); mTimeoutPeriods[message->GetSourceID()] = report->GetTimeoutSeconds(); if(mTimeoutPeriods[message->GetSourceID()] == 0) { // We always want to check for control. mTimeoutPeriods[message->GetSourceID()] = 2; } } break; case REQUEST_CONTROL: { const RequestControl* command = dynamic_cast<const RequestControl*>(message); if(mShutdownServiceFlag || command == NULL) return; ConfirmControl response(message->GetSourceID(), GetComponentID()); Mutex::ScopedLock lock(&mControlMutex); // If they have minimum authority and we are // not under control or component has greater authority than // the current controller, accept. if(mControllableFlag && command->GetAuthorityCode() >= mAuthorityCode && (mControllerID == command->GetSourceID() || mControllerID.IsValid() == false || command->GetAuthorityCode() > mControllerAuthorityCode)) { bool controlAccepted = true; Service::Map children = GetChildServices(); Service::Map::iterator child; for(child = children.begin(); child != children.end(); child++) { Child* controlChild = dynamic_cast<Child *>(child->second); if(controlChild) { controlAccepted = controlChild->RequestControl(); if(controlAccepted) { break; } } } // This check is needed in case any child // service (Management) is in an Emergency state // and cannot transition. if(controlAccepted == false) { response.SetResponseCode(ConfirmControl::NotAvailable); } else { response.SetResponseCode(ConfirmControl::ControlAccepted); if(mControllerID != command->GetSourceID() && mControllerID.IsValid()) { // Notify controller that they have lost control. RejectControl reject(mControllerID, GetComponentID()); reject.SetResponseCode(RejectControl::ControlReleased); Send(&reject); } mControllerID = message->GetSourceID(); mControllerAuthorityCode = command->GetAuthorityCode(); mControllerCheckTime.SetCurrentTime(); mControllerUpdateTime.SetCurrentTime(); if(mDebugMessagesFlag) { Mutex::ScopedLock plock(&mDebugMessagesMutex); std::cout << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Control Granted to " << message->GetSourceID().ToString() << " at " << Time::GetUtcTime().ToString() << "\n"; } } } else { if(mControllableFlag == false) { response.SetResponseCode(ConfirmControl::NotAvailable); } else { response.SetResponseCode(ConfirmControl::InsufficientAuthority); } if(mDebugMessagesFlag) { Mutex::ScopedLock plock(&mDebugMessagesMutex); std::cout << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Control Rejected from " << message->GetSourceID().ToString() << " at " << Time::GetUtcTime().ToString() << "\n"; } } Send(&response); } break; case SET_AUTHORITY: { const SetAuthority* command = dynamic_cast<const SetAuthority*>(message); if(command == NULL) return; Mutex::ScopedLock lock(&mControlMutex); mAuthorityCode = command->GetAuthorityCode(); SignalEvent(REPORT_AUTHORITY); // Update Discovery Contents. try { Discovery* discovery = GetComponent()->DiscoveryService(); if(discovery) { discovery->GetSubsystem(command->GetDestinationID().mSubsystem)->GetComponent(command->GetDestinationID())->mAuthorityLevel = (int)command->GetAuthorityCode(); if(discovery->GetVehicle(command->GetDestinationID().mSubsystem)->mAuthority < (int)command->GetAuthorityCode()) { discovery->GetVehicle(command->GetDestinationID().mSubsystem)->mAuthority = (int)command->GetAuthorityCode(); } } } catch(Exception& e) { e.Print(); } } break; default: break; }; }
//////////////////////////////////////////////////////////////////////////////////// /// /// \brief Processes message received by the Service. If not supported, then /// message is passed to inheriting services depending on what /// type of control has been established for the component. /// /// This Service supports AccessControl related messages only. /// /// \param[in] message Message data to process. /// //////////////////////////////////////////////////////////////////////////////////// void AccessControl::Receive(const Message* message) { if(AcceptCommandMessage(message) == false) { return; } if(mControllerID == message->GetSourceID()) { mControllerUpdateTime.SetCurrentTime(); } switch(message->GetMessageCode()) { case CONFIRM_CONTROL: { const ConfirmControl* command = static_cast<const ConfirmControl*>(message); if(command == NULL) return; if(command->GetResponseCode() == ConfirmControl::ControlAccepted) { bool firstTime = true; // Lock data. { WriteLock wLock(mControlMutex); // See if we already had control, and if not, then // we re-acquired control of this component and must // signal via callbacks, etc. of this event. Address::Set::iterator controlledComponent = mControlledComponents.find(message->GetSourceID()); if(controlledComponent != mControlledComponents.end()) { // If we get here, we have been trying to control this // component. Check the control status flag. std::map<Address, bool>::iterator flag = mControlFlags.find(message->GetSourceID()); if(flag->second == true) { // We already had control, nothing new here. // So don't trigger events. firstTime = false; } } mControlledComponents.insert(message->GetSourceID()); mControlConfirmTimes[message->GetSourceID()].SetCurrentTime(); mControlFlags[message->GetSourceID()] = true; } if(DebugMessagesEnabled()) { if(firstTime) { std::stringstream dMessage; dMessage << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Acquired Control of " << message->GetSourceID().ToString() << " at " << Time::GetUtcTime().ToString(); PrintDebugMessage(dMessage.str()); } else { std::stringstream dMessage; dMessage << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Maintained Control of " << message->GetSourceID().ToString() << " at " << Time::GetUtcTime().ToString(); PrintDebugMessage(dMessage.str()); } } // Trigger callbacks if needed. if(firstTime) { Service::Map children = GetChildServices(); Service::Map::iterator child; for(child = children.begin(); child != children.end(); child++) { Child* controlChild = dynamic_cast<Child *>(child->second); if(controlChild) { controlChild->ProcessAcquisitionOfControl(message->GetSourceID()); } } { ReadLock cbrLock(mCallbacksMutex); Callback::Set::iterator cb; for(cb = mCallbacks.begin(); cb != mCallbacks.end(); cb++) { (*cb)->ProcessAcquisitionfControl(message->GetSourceID()); } } } } else { Address::Set::iterator component; // Lock data. WriteLock wLock(mControlMutex); component = mControlledComponents.find(message->GetSourceID()); if(component != mControlledComponents.end()) { std::map<Address, bool>::iterator flag; flag = mMaintainFlags.find(message->GetSourceID()); if(flag != mMaintainFlags.end()) { // If we didn't get control, and we are not // trying to maintain control, remove the component // from our lists. If we don't have high enough authority // then don't bother trying to re-acquire control. if(flag->second == false || command->GetMessageCode() == ConfirmControl::InsufficientAuthority) { EraseComponentControlInfo(message->GetSourceID()); } else // Update control status { mControlFlags[message->GetSourceID()] = false; } } // Delete junk data. else { EraseComponentControlInfo(message->GetSourceID()); } } } } break; case QUERY_AUTHORITY: { if(mShutdownServiceFlag) { break; } ReportAuthority report(message->GetSourceID(), GetComponentID()); { ReadLock rLock(mControlMutex); report.SetAuthorityCode(mAuthorityCode); } Send(&report); } break; case QUERY_CONTROL: { ReportControl report(message->GetSourceID(), GetComponentID()); { ReadLock rLock(mControlMutex); report.SetAuthorityCode(mAuthorityCode); report.SetControllingComponent(mControllerID); } Send(&report); } break; case QUERY_TIMEOUT: { ReportTimeout report(message->GetSourceID(), GetComponentID()); { ReadLock rLock(mControlMutex); report.SetTimeoutSeconds(mTimeoutPeriod); } Send(&report); } break; case REJECT_CONTROL: { const RejectControl* command = static_cast<const RejectControl*>(message); if(mShutdownServiceFlag || command == NULL) return; bool signalCallbacks = false; { WriteLock wLock(mControlMutex); // Update state of controlled components. Address::Set::iterator component; component = mControlledComponents.find(message->GetSourceID()); if(component != mControlledComponents.end()) { std::map<Address, bool>::iterator flag; flag = mMaintainFlags.find(message->GetSourceID()); if(flag != mMaintainFlags.end()) { // If we lost control, and we are not // trying to maintain control, remove the component // from our lists. if(flag->second == false) { mMaintainFlags.erase(flag); mControlFlags.erase(mControlFlags.find(message->GetSourceID())); mControlConfirmTimes.erase(mControlConfirmTimes.find(message->GetSourceID())); mControlledComponents.erase(component); } else // Update control status { mControlFlags[message->GetSourceID()] = false; } signalCallbacks = true; } // Delete junk data. else { if(mControlFlags.find(*component) != mControlFlags.end()) { mControlFlags.erase(*component); } mControlledComponents.erase(*component); } } } if(signalCallbacks) { // Generate events and callbacks. ReadLock cbrLock(mCallbacksMutex); Callback::Set::iterator cb; for(cb = mCallbacks.begin(); cb != mCallbacks.end(); cb++) { (*cb)->ProcessLossOfControl(message->GetSourceID()); } } if(DebugMessagesEnabled()) { std::stringstream dMessage; dMessage << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Lost Control of " << message->GetSourceID().ToString() << " at " << Time::GetUtcTime().ToString(); PrintDebugMessage(dMessage.str()); } } break; case RELEASE_CONTROL: { const ReleaseControl* command = static_cast<const ReleaseControl*>(message); if(mShutdownServiceFlag || command == NULL) return; if(command->GetSourceID() == mControllerID) { RejectControl response(mControllerID, GetComponentID()); bool controlReleased = true; Service::Map children = GetChildServices(); Service::Map::iterator child; for(child = children.begin(); child != children.end(); child++) { Child* controlChild = dynamic_cast<Child *>(child->second); if(controlChild) { if(controlChild->ReleaseControl()) { controlReleased; } } } if(controlReleased) { response.SetResponseCode(RejectControl::ControlReleased); Send(&response); // Update data members of who was in control to nobody! { WriteLock wLock(mControlMutex); mControllerID = Address(); mControllerAuthorityCode = 0; mControllerUpdateTime.Clear(); mControllerCheckTime.Clear(); } if(DebugMessagesEnabled()) { std::stringstream dMessage; dMessage << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Control Released from " << message->GetSourceID().ToString() << " at " << Time::GetUtcTime().ToString(); PrintDebugMessage(dMessage.str()); } // Signal a change in control event SignalEvent(REPORT_CONTROL); // Notify children of control release. { // Generate events and callbacks. ReadLock cbrLock(mCallbacksMutex); Callback::Set::iterator cb; for(cb = mCallbacks.begin(); cb != mCallbacks.end(); cb++) { (*cb)->ProcessReleaseOfControl(message->GetSourceID()); } } } else { response.SetResponseCode(RejectControl::NotAvailable); Send(&response); } } } break; case REPORT_AUTHORITY: { const JAUS::ReportAuthority* report = static_cast<const JAUS::ReportAuthority*>(message); if(report) { // Used by Discovery service to keep track of information // about components on the netework } } break; case REPORT_CONTROL: // Not used. break; case REPORT_TIMEOUT: { const ReportTimeout* report = static_cast<const ReportTimeout*>(message); if(report == NULL) return; WriteLock wLock(mControlMutex); mTimeoutPeriods[message->GetSourceID()] = report->GetTimeoutSeconds(); if(mTimeoutPeriods[message->GetSourceID()] == 0) { // We always want to check for control. mTimeoutPeriods[message->GetSourceID()] = 2; } } break; case REQUEST_CONTROL: { const RequestControl* command = static_cast<const RequestControl*>(message); if(mShutdownServiceFlag || command == NULL) return; ConfirmControl response(message->GetSourceID(), GetComponentID()); #ifdef JAUS_USE_UPGRADE_LOCKS UpgradeLock upLock(mControlMutex); #else WriteLock wLock(mControlMutex); #endif // If they have minimum authority and we are // not under control or component has greater authority than // the current controller, accept. if(mControllableFlag && command->GetAuthorityCode() >= mAuthorityCode && (mControllerID == command->GetSourceID() || mControllerID.IsValid() == false || command->GetAuthorityCode() > mControllerAuthorityCode)) { bool controlAccepted = true; Service::Map children = GetChildServices(); Service::Map::iterator child; for(child = children.begin(); child != children.end(); child++) { Child* controlChild = dynamic_cast<Child *>(child->second); if(controlChild) { controlAccepted = controlChild->RequestControl(); if(controlAccepted) { break; } } } // This check is needed in case any child // service (Management) is in an Emergency state // and cannot transition. if(controlAccepted == false) { response.SetResponseCode(ConfirmControl::NotAvailable); } else { response.SetResponseCode(ConfirmControl::ControlAccepted); if(mControllerID != command->GetSourceID() && mControllerID.IsValid()) { // Notify controller that they have lost control. RejectControl reject(mControllerID, GetComponentID()); reject.SetResponseCode(RejectControl::ControlReleased); Send(&reject); } { #ifdef JAUS_USE_UPGRADE_LOCKS UpgradeToUniqueLock uniqueLock(upLock); #endif mControllerID = message->GetSourceID(); mControllerAuthorityCode = command->GetAuthorityCode(); mControllerCheckTime.SetCurrentTime(); mControllerUpdateTime.SetCurrentTime(); } if(DebugMessagesEnabled()) { std::stringstream dMessage; dMessage << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Control Granted to " << message->GetSourceID().ToString() << " at " << Time::GetUtcTime().ToString(); PrintDebugMessage(dMessage.str()); } } } else { if(mControllableFlag == false) { response.SetResponseCode(ConfirmControl::NotAvailable); } else { response.SetResponseCode(ConfirmControl::InsufficientAuthority); } if(DebugMessagesEnabled()) { std::stringstream dMessage; dMessage << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Control Rejected from " << message->GetSourceID().ToString() << " at " << Time::GetUtcTime().ToString(); PrintDebugMessage(dMessage.str()); } } Send(&response); } break; case SET_AUTHORITY: { const SetAuthority* command = static_cast<const SetAuthority*>(message); if(command == NULL) return; SetAuthorityCode(command->GetAuthorityCode()); } break; default: break; }; }