/************************************************************************ SciServer.cpp - Copyright buret Here you can write a license for your code, some comments or any other information you want to have in your generated code. To to this simply configure the "headings" directory in uml to point to a directory where you have your heading files. or you can just replace the contents of this file with your own. If you want to do this, this file is located at /usr/share/apps/umbrello/headings/heading.cpp -->Code Generators searches for heading files based on the file extension i.e. it will look for a file name ending in ".h" to include in C++ header files, and for a file name ending in ".java" to include in all generated java code. If you name the file "heading.", Code Generator will always choose this file even if there are other files with the same extension in the directory. If you name the file something else, it must be the only one with that extension in the directory to guarantee that Code Generator will choose it. you can use variables in your heading files which are replaced at generation time. possible variables are : author, date, time, filename and filepath. just write %variable_name% This file was generated on %date% at %time% The original location of this file is /home/buret/eclipse/maximus/sci/src/SciServer.cpp **************************************************************************/ #include "SciServer.h" #include "Station.h" #include "SciMsg.h" #include "ClockSciMsg.h" #include "Error.h" #include "Logger.h" #include // for 'ofstream' #include #include #include #include #include // for 'ntohl()' and 'ntohs()' #include // for 'cout', 'cerr' and 'clog' using namespace std; // Constructors/Destructors // SciServer::SciServer ( ) : mpSpecializedSciMsgArray(NULL), mArraySize(0), mpListOfStations(NULL), mNetworkClockTick(0) { logFunction(); initAttributes(); } void SciServer::initAttributes ( ) { logFunction(); // Init array // mArraySize = 10; mpSpecializedSciMsgArray = new SciMsg * [mArraySize]; if (NULL != mpSpecializedSciMsgArray) { for (unsigned int i=0; ibegin() ; it != getStationsList()->end(); it++) { station = *it; FD_SET(station->getInputFileDescriptor(), &read_fds); if(station->getInputFileDescriptor() > fd_max) fd_max = station->getInputFileDescriptor(); } result = select(fd_max + 1, &read_fds, NULL, NULL, &timeout); if(result > 0) { // skim through the list... for(fd_index = 0; fd_index <= fd_max; fd_index++) { if(FD_ISSET(fd_index, &read_fds)) { int len, header_len; struct Sci_Msg_Header header; unsigned char *buffer; header_len = sizeof(struct Sci_Msg_Header); if((len = read(fd_index, &header, sizeof(struct Sci_Msg_Header))) < header_len) { clog << logger(LOG_ERROR) << "header read error: len = " << dec << len << ", errno = " << errno << endl; continue; } else { // check for header if(memcmp(&header.magic_id, SCI_MSG_MAGIC, 4)) { clog << logger(LOG_ERROR) << "bad magic id: 0x" << hex << htonl(header.magic_id) << endl; continue; } header.length = ntohs (header.length); if((header.type <= SCI_MSG_TYPE_NONE) || (header.type >= SCI_MSG_TYPE_NB)) { clog << logger(LOG_ERROR) << "bad type: " << dec << header.type << endl; continue; } if(header.version != SCI_MSG_VERSION) { clog << logger(LOG_ERROR) << "bad version: " << dec << header.version << endl; continue; } header.magic_id = ntohl(header.magic_id); header.msg_id = ntohs (header.msg_id); header.station_id = ntohs(header.station_id); header.netclock_high = ntohl(header.netclock_high); header.netclock_low = ntohl(header.netclock_low); header.reserved = ntohs(header.reserved); header.flags = ntohs(header.flags); buffer = (unsigned char *)malloc(header.length); if((len = read(fd_index, buffer, header.length)) != header.length) { clog << logger(LOG_ERROR) << "data read error: len = " << dec << len << ", errno = " << errno << endl; free(buffer); continue; } receiveMsg(&header, header.length, buffer); free(buffer); } } } } station = NULL; // Read log pipes // log(); return bProcess; } bool SciServer::log ( ) const { logFunction(); bool bLog; ofstream stationLogFile; if ( (!getStationLog().empty()) && (getStationLog().compare("-")) ) { stationLogFile.open(getStationLog().c_str(), ios_base::app | ios_base::ate | ios_base::out); } // Skim through stations list // if ( (NULL != mpListOfStations) && (!mpListOfStations->empty()) ) { int length; int maxLength = 1024; char * pBuffer = new char [maxLength]; for (StationsList::const_iterator it = mpListOfStations->begin(); it != mpListOfStations->end(); ++it) { if (NULL != *it) { // Read logs coming from all stations (from log pipes) // length = 0; memset(pBuffer, '\0', maxLength); length = read((*it)->getLogFileDescriptor(), pBuffer, maxLength); if (-1 != length) { if (stationLogFile.is_open()) { stationLogFile.write(pBuffer, length); } else { cout << dec << pBuffer; } bLog = true; } } else { throw Error(__PRETTY_FUNCTION__, "A station pointer is NULL"); } } } stationLogFile.close(); return bLog; } bool SciServer::fillSciMsg ( SciMsg & sci_msg_to_send ) const { logFunction(); bool bFill = false; // Fill SCI msg data length // bFill = sci_msg_to_send.setSciMsgDataLength(sci_msg_to_send.getSpecializedSciMsgHeaderSize() + sci_msg_to_send.getSpecializedSciMsgDataLength()); // Decompose current tick value into two uint32_t values // uint32_t netclockHigh=0, netclockLow=0; netclockLow = (uint32_t)(getNetworkClockTick()); netclockHigh = (uint32_t)(((uint64_t)(getNetworkClockTick()) >> 32)); // Fill SCI msg header // bFill &= sci_msg_to_send.incrementSciMsgId(); // to have an updated msg id struct Sci_Msg_Header sciMsgHeader = { sci_msg_to_send.getDefinedSciMsgMagicId(), sci_msg_to_send.getDefinedSciMsgVersion(), static_cast(sci_msg_to_send.getSciMsgType()), static_cast(sci_msg_to_send.getSciMsgDataLength()), sci_msg_to_send.getSciMsgStationId(), sci_msg_to_send.getSciMsgId(), netclockHigh, netclockLow, 0, // flags 0 }; // reserved bFill &= sci_msg_to_send.setSciMsgHeader(&sciMsgHeader); // As SCI msg header will be sent on an output pipe, 'hton' functions have to be called // sciMsgHeader.magic_id = htonl(sciMsgHeader.magic_id); sciMsgHeader.length = htons(sciMsgHeader.length); sciMsgHeader.station_id = htons(sciMsgHeader.station_id); sciMsgHeader.msg_id = htons(sciMsgHeader.msg_id); sciMsgHeader.netclock_high = htonl(sciMsgHeader.netclock_high); sciMsgHeader.netclock_low = htonl(sciMsgHeader.netclock_low); // Fill SCI msg data length // When sending a SCI msg, SCI msg data contain: // - SCI msg header, // - specialized SCI msg header, // - and specialized SCI msg data // bFill = sci_msg_to_send.setSciMsgDataLength(static_cast(sizeof(struct Sci_Msg_Header)) + sci_msg_to_send.getSpecializedSciMsgHeaderSize() + sci_msg_to_send.getSpecializedSciMsgDataLength()); // Fill SCI msg data // When sending a SCI msg, since only SCI msg data will be sent on an output pipe, // SCI msg header and specialized SCI msg header have to be copied into SCI msg data // Then, specialized SCI msg data have to be copied into SCI msg data // unsigned char * pTempData = new unsigned char [sci_msg_to_send.getSciMsgDataLength()]; if (NULL != pTempData) { memcpy(pTempData, (unsigned char *)&sciMsgHeader, sizeof(struct Sci_Msg_Header)); memcpy(pTempData+sizeof(Sci_Msg_Header), (unsigned char *)sci_msg_to_send.returnSpecializedSciMsgHeader(), sci_msg_to_send.getSpecializedSciMsgHeaderSize()); memcpy(pTempData+sizeof(Sci_Msg_Header)+sci_msg_to_send.getSpecializedSciMsgHeaderSize(), sci_msg_to_send.getSpecializedSciMsgData(), sci_msg_to_send.getSpecializedSciMsgDataLength()); } bFill &= sci_msg_to_send.setSciMsgData(pTempData); // Free temporary allocated memory // if (NULL != pTempData) { delete [] pTempData; pTempData = NULL; } return bFill; } bool SciServer::sendSciMsg ( SciMsg & sci_msg_to_send ) const { logFunction(); bool bSend = false; // Retrieve destination station // Station * destination = NULL; if ( (NULL != mpListOfStations) && (!mpListOfStations->empty()) ) { for (StationsList::const_iterator it = mpListOfStations->begin(); it != mpListOfStations->end(); ++it) { if (NULL != *it) { if ( ((*it)->getStationId()) == sci_msg_to_send.getSciMsgStationId() ) { destination = (*it); // Before sending a SCI msg, check that station status is 'IDLE' // Then, station status is set to 'BUSY' // Station status will stay 'BUSY' until a system 'IDLE' msg will be received // if (MAXIMUS_STATION_STATUS_IDLE != destination->getStationStatus()) { throw Error(__PRETTY_FUNCTION__, "Cannot send msg because station status is not IDLE"); } else { destination->setStationStatus(MAXIMUS_STATION_STATUS_BUSY); } it = mpListOfStations->end(); --it; } } else { throw Error(__PRETTY_FUNCTION__, "Station pointer is NULL"); } } } if (NULL != destination) { // Write data into output pipe // int length=0; int totalLength=0; while(totalLength < (int)sci_msg_to_send.getSciMsgDataLength()) { length = write(destination->getOutputFileDescriptor(), sci_msg_to_send.getSciMsgData() + totalLength, sci_msg_to_send.getSciMsgDataLength()-totalLength); if(length < 0) { throw Error(__PRETTY_FUNCTION__, "Write data failed"); } totalLength += length; } clog << logger(LOG_INFO) << "SCI msg data have been written on pipe" << endl; bSend = true; destination = NULL; } else { throw Error(__PRETTY_FUNCTION__, "Destination station not found"); } return bSend; } bool SciServer::sendSciMsgToAllActiveStations ( SciMsg & sci_msg_to_send ) const { logFunction(); bool bSend = false; // Skim through stations list // if ( (NULL != mpListOfStations) && (!mpListOfStations->empty()) ) { int length; int totalLength; for (StationsList::const_iterator it = mpListOfStations->begin(); it != mpListOfStations->end(); ++it) { if (NULL != *it) { // Send to all stations except the sender // if ( (*it)->getStationId() != sci_msg_to_send.getSciMsgStationId() ) { // Before filling in the message, set station id to the destination station // bSend = sci_msg_to_send.setSciMsgStationId((*it)->getStationId()); bSend &= fillSciMsg(sci_msg_to_send); // Before sending a SCI msg, check that station status is not 'DEACTIVATED' // Then, station status is set to 'BUSY' // Station status will stay 'BUSY' until a system 'IDLE' msg will be received // if (MAXIMUS_STATION_STATUS_DEACTIVATED != (*it)->getStationStatus()) { (*it)->setStationStatus(MAXIMUS_STATION_STATUS_BUSY); // Write data into output pipe // length = 0; totalLength = 0; while(totalLength < (int)sci_msg_to_send.getSciMsgDataLength()) { length = write((*it)->getOutputFileDescriptor(), sci_msg_to_send.getSciMsgData() + totalLength, sci_msg_to_send.getSciMsgDataLength()-totalLength); if(length < 0) { throw Error(__PRETTY_FUNCTION__, "Write data failed"); } totalLength += length; } clog << logger(LOG_INFO) << "SCI msg data have been written on pipe" << endl; bSend = true; } } } else { throw Error(__PRETTY_FUNCTION__, "A station pointer is NULL"); } } } return bSend; } bool SciServer::registerSpecializedSciMsg ( const Sci_Msg_Type sci_msg_type, SciMsg * sci_msg ) { logFunction(); bool bRegister = false; if (NULL != sci_msg) { if (getArraySize() > (unsigned int)sci_msg_type) { if (NULL != getSpecializedSciMsgArray()) { *(mpSpecializedSciMsgArray + (unsigned int)sci_msg_type) = sci_msg; // set mpSpecializedSciMsgArray bRegister = true; } } else { throw Error(__PRETTY_FUNCTION__, "SCI msg type exceeds specialized SCI msg array size"); } } else { throw Error(__PRETTY_FUNCTION__, "SCI msg pointer is NULL"); } return bRegister; } bool SciServer::receiveMsg ( const Sci_Msg_Header * header, const unsigned long data_length, const unsigned char * received_data ) const { logFunction(); bool bReceiveMsg = false; // Log the SCI message header // if (NULL != header) { // Create a specialized SCI message according to the message header type // SciMsg * sciMsg = NULL; Sci_Msg_Type type = static_cast(header->type); bReceiveMsg = createSciMsg (type, &sciMsg); // Process the created specialized SCI message // if ( (NULL != sciMsg) && (0 != bReceiveMsg) ) { if (NULL != received_data) { // Fill SCI msg // bReceiveMsg = fillSciMsg (header, data_length, received_data, &sciMsg); // Check msg compatibility (check msg versions) // Check msg validity // if (0 != bReceiveMsg) { bReceiveMsg = sciMsg->checkCompatibility(); bReceiveMsg &= sciMsg->checkValidity(); } else { throw Error(__PRETTY_FUNCTION__, "SCI msg not correctly filled in"); } // Process SCI msg // if (0 != bReceiveMsg) { bReceiveMsg = processSciMsg (sciMsg); } else { // Display SCI msg header // clog << logger(LOG_ERROR) << "SCI msg header = " << endl; clog << "\tmagic_id = 0x" << setfill('0') << setw(8) << uppercase << hex << sciMsg->getSciMsgHeader()->magic_id << endl; clog << "\tversion = 0x" << setfill('0') << setw(2) << uppercase << hex << static_cast(sciMsg->getSciMsgHeader()->version) << endl; clog << "\ttype = 0x" << setfill('0') << setw(2) << uppercase << hex << static_cast(sciMsg->getSciMsgHeader()->type) << endl; clog << "\tlength = " << dec << sciMsg->getSciMsgHeader()->length << endl; clog << "\tstation_id = 0x" << setfill('0') << setw(4) << uppercase << hex << sciMsg->getSciMsgHeader()->station_id << endl; clog << "\tmsg_id = 0x" << setfill('0') << setw(4) << uppercase << hex << sciMsg->getSciMsgHeader()->msg_id << endl; clog << "\tnetclock = 0x" << setfill('0') << setw(8) << uppercase << hex << sciMsg->getSciMsgHeader()->netclock_high; clog << setfill('0') << setw(8) << uppercase << hex << sciMsg->getSciMsgHeader()->netclock_low << endl; clog << "\tflags = " << dec << sciMsg->getSciMsgHeader()->flags << endl; clog << "\treserved = 0x" << setfill('0') << setw(4) << uppercase << hex << sciMsg->getSciMsgHeader()->reserved << endl; // Display SCI msg data clog << logger(LOG_ERROR) << "SCI msg data = "; for (unsigned int i=0; igetSciMsgType()) ) { delete sciMsg; sciMsg = NULL; } } else { throw Error(__PRETTY_FUNCTION__, "Data pointer is NULL"); } } else { throw Error(__PRETTY_FUNCTION__, "Error when creating SCI msg"); } } else { throw Error(__PRETTY_FUNCTION__, "SCI msg header pointer is NULL"); } return bReceiveMsg; } void SciServer::displaySpecializedSciMsgArray ( ) const { logFunction(); clog << logger(LOG_INFO) << "specialized SCI msg array = " << endl; for (unsigned int i=0; i (unsigned int)type) && (NULL != *(getSpecializedSciMsgArray() + (unsigned int)type)) ) { *received_sci_msg = (*(getSpecializedSciMsgArray() + type))->create(); } else { throw Error(__PRETTY_FUNCTION__, "SCI msg type is invalid: no corresponding SCI msg"); } // Check if the just created SCI msg is valid // if (NULL != *received_sci_msg) { bCreateMsg = true; } else { throw Error(__PRETTY_FUNCTION__, "SCI msg pointer is invalid"); } } else { throw Error(__PRETTY_FUNCTION__, "SCI msg pointer is invalid"); } return bCreateMsg; } bool SciServer::fillSciMsg ( const Sci_Msg_Header * p_msg_header, const unsigned long data_length, const unsigned char * p_received_data, SciMsg ** created_sci_msg ) const { logFunction(); bool bFillMsg = false; // Fill SCI message contents // if (NULL != created_sci_msg) { if (NULL != p_msg_header) { // Set SCI message header // Set SCI message attributes // bFillMsg = (*created_sci_msg)->setSciMsgHeader(p_msg_header); bFillMsg &= (*created_sci_msg)->setSciMsgDataLength(data_length); if (NULL != p_received_data) { bFillMsg &= (*created_sci_msg)->setSciMsgData(p_received_data); // Set specialized SCI message header // Set specialized attributes // bFillMsg &= (*created_sci_msg)->identifySpecializedSciMsgHeader(); // Remove specialized SCI message header from specialized SCI msg data // Then, set specialized SCI message data length, and specialized SCI message data // bFillMsg &= (*created_sci_msg)->identifySpecializedSciMsgData(); } else { throw Error(__PRETTY_FUNCTION__, "Data pointer is NULL"); } } else { throw Error(__PRETTY_FUNCTION__, "SCI msg header pointer is NULL"); } } else { throw Error(__PRETTY_FUNCTION__, "SCI msg pointer is NULL"); } return bFillMsg; } bool SciServer::processSciMsg ( SciMsg * received_sci_msg ) const { logFunction(); bool bProcessMsg = false; if (NULL != received_sci_msg) { bProcessMsg = received_sci_msg->dispatchMsg(); } else { throw Error(__PRETTY_FUNCTION__, "SCI msg pointer is NULL"); } return bProcessMsg; } // protected methods // // Accessor methods // // public attribute accessor methods // // private attribute accessor methods // StationsList * SciServer::getStationsList ( ) const { return mpListOfStations; } bool SciServer::setStationsList ( StationsList * stations_list ) { logFunction(); bool bSetList = false; if (NULL != stations_list) { mpListOfStations = stations_list; bSetList = true; } else { throw Error(__PRETTY_FUNCTION__, "List of stations pointer is NULL"); } return bSetList; } SciMsg ** SciServer::getSpecializedSciMsgArray ( ) const { return mpSpecializedSciMsgArray; } unsigned int SciServer::getArraySize ( ) const { return mArraySize; } Network_Clock_Tick SciServer::getNetworkClockTick ( ) const { return mNetworkClockTick; } bool SciServer::updateTickValue ( const Network_Clock_Tick current_tick_value ) { mNetworkClockTick = current_tick_value; return true; } std::string SciServer::getStationLog ( ) const { return mStationLog; } // protected attribute accessor methods //