/***************************************************************************** * 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: OjUdpComponentInterface.cpp // // Written By: Danny Kent (jaus AT dannykent DOT com) // // Version: 3.3.0a // // Date: 08/07/08 // // Description: This file provides an interface through which the NM communicates // to components using a non-JAUS compliant synchronous UDP port over // the loopback device. #include "nodeManager/OjUdpComponentInterface.h" #include "nodeManager/events/ErrorEvent.h" OjUdpComponentInterface::OjUdpComponentInterface(FileLoader *configData, EventHandler *handler, JausComponentCommunicationManager *cmptMngr) { this->configData = configData; this->commMngr = cmptMngr; this->eventHandler = handler; this->systemTree = cmptMngr->getSystemTree(); this->nodeManager = cmptMngr->getNodeManagerComponent(); this->type = COMPONENT_INTERFACE; this->name = "OpenJAUS UDP Component to Node Manager Interface"; this->portMap.empty(); // Open our socket if(!this->openSocket()) { throw "OjUdpComponentInterface: Could not open socket\n"; } } OjUdpComponentInterface::~OjUdpComponentInterface(void) { if(running) { this->stopInterface(); } this->closeSocket(); } unsigned int OjUdpComponentInterface::getPort(void) { return this->socket->port; } bool OjUdpComponentInterface::startInterface() { // Setup our thread control flag this->running = true; // Setup our pThread this->startThread(); return true; } bool OjUdpComponentInterface::stopInterface() { // Set our thread control flag to false this->running = false; // Stop our pThread this->stopThread(); return true; } bool OjUdpComponentInterface::processMessage(JausMessage message) { // This interface does not transport jaus messages // This isn't an "error" because the cmptMngr send JausMessages to all known interfaces for broadcasts jausMessageDestroy(message); return false; } bool OjUdpComponentInterface::sendDatagramPacket(DatagramPacket dgPacket) { return true; } bool OjUdpComponentInterface::openSocket(void) { // Read Configuration if(this->configData->GetConfigDataString("Component_Communications", "OpenJAUS_UDP_Port") == "") { this->portNumber = OJ_UDP_DEFAULT_PORT; } else { this->portNumber = this->configData->GetConfigDataInt("Component_Communications", "OpenJAUS_UDP_Port"); } // IP Address if(this->configData->GetConfigDataString("Component_Communications", "OpenJAUS_UDP_IP_Address") == "") { this->ipAddress = inetAddressGetByString((char *)OJ_UDP_DEFAULT_COMPONENT_IP.c_str()); if(this->ipAddress == NULL) { // Cannot open specified IP Address char errorString[128] = {0}; sprintf(errorString, "Could not open default IP Address: %s", OJ_UDP_DEFAULT_COMPONENT_IP.c_str()); ErrorEvent *e = new ErrorEvent(ErrorEvent::Configuration, __FUNCTION__, __LINE__, errorString); this->eventHandler->handleEvent(e); return false; } } else { this->ipAddress = inetAddressGetByString((char *)this->configData->GetConfigDataString("Component_Communications", "OpenJAUS_UDP_IP_Address").c_str()); if(this->ipAddress == NULL) { // Cannot open specified IP Address char errorString[128] = {0}; sprintf(errorString, "Could not open specified IP Address: %s", this->configData->GetConfigDataString("Component_Communications", "OpenJAUS_UDP_IP_Address").c_str()); ErrorEvent *e = new ErrorEvent(ErrorEvent::Configuration, __FUNCTION__, __LINE__, errorString); this->eventHandler->handleEvent(e); return false; } } // Create Component Socket this->socket = datagramSocketCreate(this->portNumber, ipAddress); if(!this->socket) { // Error creating our socket return false; } inetAddressDestroy(this->ipAddress); // Setup Timeout if(this->configData->GetConfigDataString("Component_Communications", "OpenJAUS_UDP_Timeout_Sec") == "") { datagramSocketSetTimeout(this->socket, OJ_UDP_DEFAULT_TIMEOUT); } else { datagramSocketSetTimeout(this->socket, this->configData->GetConfigDataDouble("Component_Communications", "OpenJAUS_UDP_Timeout_Sec")); } return true; } void OjUdpComponentInterface::closeSocket(void) { datagramSocketDestroy(this->socket); } void OjUdpComponentInterface::run() { DatagramPacket packet; JausAddress address, currentAddress; JausAddress lookupAddress; int bytesRecv = 0; char buf[256] = {0}; int componentId = 0; int commandCode = 0; int serviceType = 0; packet = datagramPacketCreate(); packet->bufferSizeBytes = OJ_UDP_INTERFACE_MESSAGE_SIZE_BYTES; packet->buffer = (unsigned char *) calloc(packet->bufferSizeBytes, 1); while(this->running) { bytesRecv = datagramSocketReceive(this->socket, packet); if(bytesRecv == OJ_UDP_INTERFACE_MESSAGE_SIZE_BYTES) { // This is to ensure we are using a valid NM pointer (this occurs this->nodeManager = ((JausComponentCommunicationManager *)this->commMngr)->getNodeManagerComponent(); switch(packet->buffer[0]) { case CHECK_IN: componentId = (packet->buffer[1] & 0xFF); if(componentId < JAUS_MINIMUM_COMPONENT_ID || componentId > JAUS_MAXIMUM_COMPONENT_ID) { sprintf(buf, "Invalid Component Id (%d) trying to check in.", componentId); ErrorEvent *e = new ErrorEvent(ErrorEvent::Configuration, __FUNCTION__, __LINE__, buf); this->eventHandler->handleEvent(e); return; } address = this->nodeManager->checkInLocalComponent(componentId); if(!address || !jausAddressIsValid(address)) { sprintf(buf, "Cannot add local component with Id: %d.", componentId); ErrorEvent *e = new ErrorEvent(ErrorEvent::Warning, __FUNCTION__, __LINE__, buf); this->eventHandler->handleEvent(e); // TODO: Send back checkin error reply (no available instance) break; } memset(packet->buffer, 0, OJ_UDP_INTERFACE_MESSAGE_SIZE_BYTES); packet->buffer[0] = REPORT_ADDRESS; packet->buffer[1] = (unsigned char)(address->instance & 0xFF); packet->buffer[2] = (unsigned char)(address->component & 0xFF); packet->buffer[3] = (unsigned char)(address->node & 0xFF); packet->buffer[4] = (unsigned char)(address->subsystem & 0xFF); datagramSocketSend(this->socket, packet); jausAddressDestroy(address); break; case CHECK_OUT: nodeManager->checkOutLocalComponent(packet->buffer[4], packet->buffer[3], packet->buffer[2], packet->buffer[1]); break; case VERIFY_ADDRESS: lookupAddress = jausAddressCreate(); lookupAddress->instance = (packet->buffer[1] & 0xFF); lookupAddress->component = (packet->buffer[2] & 0xFF); lookupAddress->node = (packet->buffer[3] & 0xFF); lookupAddress->subsystem = (packet->buffer[4] & 0xFF); memset(packet->buffer, 0, OJ_UDP_INTERFACE_MESSAGE_SIZE_BYTES); packet->buffer[0] = ADDRESS_VERIFIED; if(this->systemTree->hasComponent(lookupAddress)) { packet->buffer[1] = JAUS_TRUE; } else { packet->buffer[1] = JAUS_FALSE; } datagramSocketSend(this->socket, packet); jausAddressDestroy(lookupAddress); break; case GET_COMPONENT_ADDRESS_LIST: componentId = packet->buffer[1] & 0xFF; address = systemTree->lookUpAddress(JAUS_ADDRESS_WILDCARD_OCTET, JAUS_ADDRESS_WILDCARD_OCTET, componentId, JAUS_ADDRESS_WILDCARD_OCTET); memset(packet->buffer, 0, OJ_UDP_INTERFACE_MESSAGE_SIZE_BYTES); packet->buffer[0] = COMPONENT_ADDRESS_LIST_RESPONSE; // if(!address || !jausAddressIsValid(address)) { packet->buffer[1] = (unsigned char)(JAUS_INVALID_INSTANCE_ID & 0xFF); packet->buffer[2] = (unsigned char)(JAUS_INVALID_COMPONENT_ID & 0xFF); packet->buffer[3] = (unsigned char)(JAUS_INVALID_NODE_ID & 0xFF); packet->buffer[4] = (unsigned char)(JAUS_INVALID_SUBSYSTEM_ID & 0xFF); } else { packet->buffer[1] = (unsigned char)(address->instance & 0xFF); packet->buffer[2] = (unsigned char)(address->component & 0xFF); packet->buffer[3] = (unsigned char)(address->node & 0xFF); packet->buffer[4] = (unsigned char)(address->subsystem & 0xFF); } datagramSocketSend(this->socket, packet); jausAddressDestroy(address); break; case LOOKUP_ADDRESS: lookupAddress = jausAddressCreate(); lookupAddress->instance = (packet->buffer[1] & 0xFF); lookupAddress->component = (packet->buffer[2] & 0xFF); lookupAddress->node = (packet->buffer[3] & 0xFF); lookupAddress->subsystem = (packet->buffer[4] & 0xFF); memset(packet->buffer, 0, OJ_UDP_INTERFACE_MESSAGE_SIZE_BYTES); packet->buffer[0] = LOOKUP_ADDRESS_RESPONSE; address = systemTree->lookUpAddress(lookupAddress); if(address && jausAddressIsValid(address)) { packet->buffer[5] = (unsigned char) JAUS_TRUE; } else { packet->buffer[5] = (unsigned char) JAUS_FALSE; } packet->buffer[1] = (unsigned char) (address->instance & 0xFF); packet->buffer[2] = (unsigned char) (address->component & 0xFF); packet->buffer[3] = (unsigned char) (address->node & 0xFF); packet->buffer[4] = (unsigned char) (address->subsystem & 0xFF); datagramSocketSend(this->socket, packet); while(address) // NMJ { // NMJ currentAddress = address; // NMJ address = address->next; // NMJ jausAddressDestroy(currentAddress); // NMJ } // NMJ jausAddressDestroy(lookupAddress); break; case LOOKUP_SERVICE_ADDRESS: lookupAddress = jausAddressCreate(); lookupAddress->instance = (packet->buffer[1] & 0xFF); lookupAddress->component = (packet->buffer[2] & 0xFF); lookupAddress->node = (packet->buffer[3] & 0xFF); lookupAddress->subsystem = (packet->buffer[4] & 0xFF); commandCode = (packet->buffer[5] & 0xFF) + ((packet->buffer[6] & 0xFF) << 8); serviceType = (packet->buffer[7] & 0xFF); memset(packet->buffer, 0, OJ_UDP_INTERFACE_MESSAGE_SIZE_BYTES); packet->buffer[0] = LOOKUP_SERVICE_ADDRESS_RESPONSE; address = systemTree->lookUpServiceInSystem(commandCode, serviceType); if(address && jausAddressIsValid(address)) { packet->buffer[5] = (unsigned char) JAUS_TRUE; packet->buffer[1] = (unsigned char) (address->instance & 0xFF); packet->buffer[2] = (unsigned char) (address->component & 0xFF); packet->buffer[3] = (unsigned char) (address->node & 0xFF); packet->buffer[4] = (unsigned char) (address->subsystem & 0xFF); } else { packet->buffer[5] = (unsigned char) JAUS_FALSE; } datagramSocketSend(this->socket, packet); if(address) { jausAddressDestroy(address); jausAddressDestroy(lookupAddress); } break; //case InterfaceMessage.NODE_MANAGER_LOOKUP_SERVICE_ADDRESS_LIST: // lookupAddress = jausAddressCreate(); // lookupAddress->instance(packet->buffer[1] & 0xFF); // lookupAddress->component(packet->buffer[2] & 0xFF); // lookupAddress->node(packet->buffer[3] & 0xFF); // lookupAddress->subsystem(packet->buffer[4] & 0xFF); // // commandCode = (packet->buffer[5] & 0xFF) + ((packet->buffer[6] & 0xFF) << 8); // serviceType = (packet->buffer[7] & 0xFF); // memset(packet->buffer, 0, OJ_UDP_INTERFACE_MESSAGE_SIZE_BYTES); // packet->buffer[0] = LOOKUP_SERVICE_ADDRESS_LIST_RESPONSE; // //System.out.println("CmptInterface: Get address for component ID: " + componentId); // //address = subsystemTable.lookupServiceAddressList(address, commandCode, serviceCommandType); // // if(lookupAddress->subsystem == // if(address == null) // { // replyMessage.getData()[0] = (byte)(0 & 0xff); // replyMessage.getData()[1] = (byte)(0 & 0xff); // replyMessage.getData()[2] = (byte)(0 & 0xff); // replyMessage.getData()[3] = (byte)(0 & 0xff); // replyMessage.getData()[4] = (byte)0; // //System.out.println("CmptInterface: Get address for component ID: " + componentId + " returning: 0.0.0.0"); // } // else // { // replyMessage.getData()[0] = (byte)(address.getInstance() & 0xff); // replyMessage.getData()[1] = (byte)(address.getComponent() & 0xff); // replyMessage.getData()[2] = (byte)(address.getNode() & 0xff); // replyMessage.getData()[3] = (byte)(address.getSubsystem() & 0xff); // replyMessage.getData()[4] = (byte)1; // //System.out.println("CmptInterface: Get address for component ID: " + componentId + " returning: " + address); // } // // replyBuffer = new byte[8]; // replyMessage.pack(replyBuffer); // outPacket = new DatagramPacket(replyBuffer, replyBuffer.length, packet.getAddress(), packet.getPort()); // socket.send(outPacket); // break; default: sprintf(buf, "Unknown Interface Message Received. CC: 0x%02X\n", packet->buffer[0]); ErrorEvent *e = new ErrorEvent(ErrorEvent::Warning, __FUNCTION__, __LINE__, buf); this->eventHandler->handleEvent(e); break; } } } free(packet->buffer); datagramPacketDestroy(packet); } bool OjUdpComponentInterface::processOjNodemanagerInterfaceMessage(char *buffer) { return true; } std::string OjUdpComponentInterface::toString() { return this->name; }