/***************************************************************************** * Copyright (c) 2008, University of Florida * All rights reserved. * * This file is part of OpenJAUS. OpenJAUS is distributed under the BSD * license. See the LICENSE file for details. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the University of Florida nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ****************************************************************************/ // File Name: JausNodeCommunicationManager.cpp // // Written By: Danny Kent (jaus AT dannykent DOT com) // // Version: 3.3.0a // // Date: 08/07/08 // // Description: This file defines a JausNodeCommunicationManager.cpp class. // This is derived from a the JausCommunicationManager class and supports // different node interfaces. #include "nodeManager/JausNodeCommunicationManager.h" #include "nodeManager/JausOpcUdpInterface.h" #include "nodeManager/JudpInterface.h" #include "nodeManager/events/ErrorEvent.h" #include "nodeManager/events/ConfigurationEvent.h" JausNodeCommunicationManager::JausNodeCommunicationManager(FileLoader *configData, MessageRouter *msgRouter, SystemTree *systemTree, EventHandler *handler) { this->eventHandler = handler; this->systemTree = systemTree; this->msgRouter = msgRouter; this->configData = configData; this->subsystemGatewayInterface = NULL; // NOTE: These two values should exist in the properties file and should be checked // in the NodeManager class prior to constructing this object mySubsystemId = configData->GetConfigDataInt("JAUS", "SubsystemId"); if(mySubsystemId < JAUS_MINIMUM_SUBSYSTEM_ID || mySubsystemId > JAUS_MAXIMUM_SUBSYSTEM_ID) { // Invalid ID throw "JausNodeCommunicationManager: Config file [JAUS] SubsystemId is invalid\n"; mySubsystemId = JAUS_INVALID_SUBSYSTEM_ID; return; } myNodeId = configData->GetConfigDataInt("JAUS", "NodeId"); if(myNodeId < JAUS_MINIMUM_NODE_ID || myNodeId > JAUS_MAXIMUM_NODE_ID) { // Invalid ID throw "JausNodeCommunicationManager: Config file [JAUS] NodeId is invalid\n"; myNodeId= JAUS_INVALID_NODE_ID; return; } if( configData->GetConfigDataBool("Node_Communications", "Enabled")) { ConfigurationEvent *e = new ConfigurationEvent(__FUNCTION__, __LINE__, "Starting Node Interfaces"); this->eventHandler->handleEvent(e); // Start subsystem interface(s) if(configData->GetConfigDataBool("Node_Communications", "JAUS_OPC_UDP_Interface")) { JausOpcUdpInterface *etgUdpInterface = new JausOpcUdpInterface(configData, this->eventHandler, this); this->interfaces.push_back(etgUdpInterface); char buf[128] = {0}; sprintf(buf, "Opened Node Interface:\t\t%s", etgUdpInterface->toString().c_str()); ConfigurationEvent *e = new ConfigurationEvent(__FUNCTION__, __LINE__, buf); this->eventHandler->handleEvent(e); } if(configData->GetConfigDataBool("Node_Communications", "JUDP_Interface")) { JudpInterface *judpInterface = new JudpInterface(configData, this->eventHandler, this); this->interfaces.push_back(judpInterface); char buf[128] = {0}; sprintf(buf, "Opened Node Interface:\t\t%s", judpInterface->toString().c_str()); ConfigurationEvent *e = new ConfigurationEvent(__FUNCTION__, __LINE__, buf); this->eventHandler->handleEvent(e); } if( this->interfaces.size() > 0) { this->enabled = true; } else { this->enabled = false; } } else { this->enabled = false; } } JausNodeCommunicationManager::~JausNodeCommunicationManager(void) { std::vector::iterator iterator; for(iterator = interfaces.begin(); iterator != interfaces.end(); iterator++) { delete *iterator; } } bool JausNodeCommunicationManager::startInterfaces(void) { bool retVal = true; std::vector ::iterator iter; for(iter = interfaces.begin(); iter != interfaces.end(); iter++) { retVal = retVal && (*iter)->startInterface(); } return retVal; } bool JausNodeCommunicationManager::stopInterfaces(void) { bool retVal = true; std::vector ::iterator iter; for(iter = interfaces.begin(); iter != interfaces.end(); iter++) { retVal = retVal && (*iter)->stopInterface(); } return retVal; } bool JausNodeCommunicationManager::sendJausMessage(JausMessage message) { if(!this->enabled) { // This Communication Manager is turned off // Destroy this message jausMessageDestroy(message); return false; } // This conforms to the NodeCommMngr Routing Table's MsgRouter Source Table v2.0 if(!message) { // Error: Invalid message ErrorEvent *e = new ErrorEvent(ErrorEvent::NullPointer, __FUNCTION__, __LINE__, "Invalid JausMessage."); this->eventHandler->handleEvent(e); return false; } if(message->source->subsystem != mySubsystemId) { if( message->destination->subsystem == JAUS_BROADCAST_SUBSYSTEM_ID || message->destination->subsystem == mySubsystemId) { if(message->destination->node == JAUS_BROADCAST_NODE_ID) { // Send to all other nodes on this subs return sendToAllInterfaces(message); } else if(message->destination->node != myNodeId) { // Route to Node X return sendToNodeX(message); } else { // ERROR: Message received from MsgRouter that is not from this subs is for this node! ErrorEvent *e = new ErrorEvent(ErrorEvent::Routing, __FUNCTION__, __LINE__, "Message received from MsgRouter that is not from this subs is for this node"); this->eventHandler->handleEvent(e); jausMessageDestroy(message); return false; } } else { // ERROR: Message received from MsgRouter that is not from this subs and not for this subs! ErrorEvent *e = new ErrorEvent(ErrorEvent::Routing, __FUNCTION__, __LINE__, "Message received from MsgRouter that is not from this subs and not for this subs!"); this->eventHandler->handleEvent(e); jausMessageDestroy(message); return false; } } else // message->source->subsystem == mySubsystemId { if(message->source->node != myNodeId) { // ERROR: Message received from MsgRouter that has address of another node on this system ErrorEvent *e = new ErrorEvent(ErrorEvent::Routing, __FUNCTION__, __LINE__, "Message received from MsgRouter that has address of another node on this system"); this->eventHandler->handleEvent(e); jausMessageDestroy(message); return false; } else { // Special behavior in here to handle routing of messages to the communicator / primary nodemngr if( message->destination->subsystem != mySubsystemId && message->destination->subsystem != JAUS_BROADCAST_SUBSYSTEM_ID) { return sendToSubsystemGateway(message); } else if(message->destination->subsystem == JAUS_BROADCAST_SUBSYSTEM_ID) { if(message->destination->node == JAUS_BROADCAST_SUBSYSTEM_ID) { // Send to all other nodes return sendToAllInterfaces(message); } else if(message->destination->node == myNodeId) { return sendToSubsystemGateway(message); } else //message->destination->node == X { // Route to node X sendToNodeX(jausMessageClone(message)); // PREVENT DUPLICATION! // If Node X is not the Communicator Node or the Primary node, sendToSubsystemGateway JausAddress commAddress = systemTree->lookUpAddress(mySubsystemId, JAUS_ADDRESS_WILDCARD_OCTET, JAUS_COMMUNICATOR, JAUS_ADDRESS_WILDCARD_OCTET); if(commAddress && commAddress->node != message->destination->node && message->destination->node != JAUS_PRIMARY_NODE_MANAGER_NODE) { sendToSubsystemGateway(jausMessageClone(message)); } jausMessageDestroy(message); return true; } } else //message->destination->subsystem == mySubsystemId { if(message->destination->node == myNodeId) { // ERROR: Msg recv'd which is for this node! ErrorEvent *e = new ErrorEvent(ErrorEvent::Routing, __FUNCTION__, __LINE__, "Message received from MsgRouter that is for my Node!"); this->eventHandler->handleEvent(e); jausMessageDestroy(message); return false; } else if(message->destination->node == JAUS_BROADCAST_NODE_ID) { // Send to all other nodes return sendToAllInterfaces(message); } else { // Route to Node X return sendToNodeX(message); } } } } } bool JausNodeCommunicationManager::receiveJausMessage(JausMessage message, JausTransportInterface *srcInf) { if(!this->enabled) { // This Communication Manager is turned off // Destroy this message jausMessageDestroy(message); return false; } // This conforms to the NodeCommMngr Routing Table's MsgRouter Source Table v2.0 if(!message) { // Error: Invalid message ErrorEvent *e = new ErrorEvent(ErrorEvent::NullPointer, __FUNCTION__, __LINE__, "Invalid JausMessage."); this->eventHandler->handleEvent(e); return false; } // Check for errors if(message->source->subsystem == mySubsystemId) { if(message->source->node == myNodeId) { // Error: Msg recv'd from this node through NodeInf, invalid! ErrorEvent *e = new ErrorEvent(ErrorEvent::Routing, __FUNCTION__, __LINE__, "Message received from NodeInterface that is from my Node!"); this->eventHandler->handleEvent(e); jausMessageDestroy(message); return false; } else { if(message->source->subsystem == mySubsystemId) { // Put Interface data on the map interfaceMap[message->source->node] = srcInf; } else { // Message is from another subsystem this->subsystemGatewayInterface = srcInf; } if(message->destination->subsystem == mySubsystemId) { if(message->destination->node == myNodeId || message->destination->node == JAUS_BROADCAST_NODE_ID) { msgRouter->routeNodeSourceMessage(message); return true; } else { // ERROR: Message not for this node recv'd from another node ErrorEvent *e = new ErrorEvent(ErrorEvent::Routing, __FUNCTION__, __LINE__, "Message not for this node recv'd from another node"); this->eventHandler->handleEvent(e); jausMessageDestroy(message); return false; } } else { msgRouter->routeNodeSourceMessage(message); return true; } } } else //message->source->subsystem != mySubsystemId { if( message->destination->subsystem == JAUS_BROADCAST_SUBSYSTEM_ID || message->destination->subsystem == mySubsystemId) { if(message->destination->node == myNodeId || message->destination->node == JAUS_BROADCAST_NODE_ID) { msgRouter->routeNodeSourceMessage(message); return true; } else { // ERROR: Message not for this node recv'd from another node ErrorEvent *e = new ErrorEvent(ErrorEvent::Routing, __FUNCTION__, __LINE__, "Message not for this node recv'd from another node"); this->eventHandler->handleEvent(e); jausMessageDestroy(message); return false; } } else // message->destination->subsystem == X { // ERROR: Message not for this subsystem and not from this subsystem recv'd from another node ErrorEvent *e = new ErrorEvent(ErrorEvent::Routing, __FUNCTION__, __LINE__, "Message not for this subsystem and not from this subsystem recv'd from another node"); this->eventHandler->handleEvent(e); jausMessageDestroy(message); return false; } } } bool JausNodeCommunicationManager::sendToSubsystemGateway(JausMessage message) { if(!message) { // Error: Invalid message ErrorEvent *e = new ErrorEvent(ErrorEvent::NullPointer, __FUNCTION__, __LINE__, "Invalid JausMessage."); this->eventHandler->handleEvent(e); return false; } if(msgRouter->subsystemCommunicationEnabled()) { // ERROR: This should have gone out to the SubsCommMngr ErrorEvent *e = new ErrorEvent(ErrorEvent::Routing, __FUNCTION__, __LINE__, "Message received in Node Communication Manager which should have gone out the Subsystem Communication manager."); this->eventHandler->handleEvent(e); jausMessageDestroy(message); return false; } // Send to the subsystemGatewayInterface if(subsystemGatewayInterface) { // Send to the Communicator's Node subsystemGatewayInterface->queueJausMessage(message); return true; } else if(myNodeId != JAUS_PRIMARY_NODE_MANAGER_NODE) { // Send to the Primary Node Manager (note this is mainly for backwards compatibility) JausTransportInterface *jtInf = interfaceMap[JAUS_PRIMARY_NODE_MANAGER_NODE]; if(jtInf) { jtInf->queueJausMessage(message); return true; } else { // I don't know how to send something to that node jausMessageDestroy(message); return false; } } else { // No known subsystem interface // This is the Primary Node // And I don't have an active SubsCommMngr jausMessageDestroy(message); return false; } } bool JausNodeCommunicationManager::sendToNodeX(JausMessage message) { if(!message) { // Error: Invalid message ErrorEvent *e = new ErrorEvent(ErrorEvent::NullPointer, __FUNCTION__, __LINE__, "Invalid JausMessage."); this->eventHandler->handleEvent(e); return false; } JausTransportInterface *jtInf = interfaceMap[message->destination->node]; if(jtInf) { jtInf->queueJausMessage(message); return true; } else { // I don't know how to send something to that node jausMessageDestroy(message); return false; } } bool JausNodeCommunicationManager::sendToAllInterfaces(JausMessage message) { std::vector ::iterator iter; if(!message) { // Error: Invalid message ErrorEvent *e = new ErrorEvent(ErrorEvent::NullPointer, __FUNCTION__, __LINE__, "Invalid JausMessage."); this->eventHandler->handleEvent(e); return false; } for(iter = interfaces.begin(); iter != interfaces.end(); iter++) { (*iter)->queueJausMessage(jausMessageClone(message)); } jausMessageDestroy(message); return true; }