📄 socketserver.cc~
字号:
// -*- mode:C++ ; tab-width:4 ; c-basic-offset:4 ; indent-tabs-mode:nil -*-// ----------------------------------------------------------------------------// CERTI - HLA RunTime Infrastructure// Copyright (C) 2002, 2003 ONERA//// This file is part of CERTI-libCERTI//// CERTI-libCERTI is free software ; you can redistribute it and/or// modify it under the terms of the GNU Lesser General Public License// as published by the Free Software Foundation ; either version 2 of// the License, or (at your option) any later version.//// CERTI-libCERTI is distributed in the hope that it will be useful, but// WITHOUT ANY WARRANTY ; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU// Lesser General Public License for more details.//// You should have received a copy of the GNU Lesser General Public// License along with this program ; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307// USA//// $Id: SocketServer.cc,v 3.5 2003/02/19 18:07:30 breholee Exp $// ----------------------------------------------------------------------------#include <config.h>#include "SocketServer.hh"namespace certi {static pdCDebug D("RTIG", "(Socket Server)- ");// ----------------------------------------------------------------------------/*! This method is called when the RTIG wants to initialize its FD_SET before doing a select. It will add all open socket to the set.*/voidSocketServer::addToFDSet(fd_set *select_fdset){ list<SocketTuple *>::iterator i ; for (i = begin(); i != end(); i++) { if ((*i)->ReliableLink != NULL) FD_SET((*i)->ReliableLink->returnSocket(), select_fdset); }}// ----------------------------------------------------------------------------/*! Check if 'message' coming from socket link 'Socket' has a valid Federate field, that is, the Federate number linked to the socket is the same as the Federate Number specified in the message. If not, throw SecurityError.*/voidSocketServer::checkMessage(long socket_number, NetworkMessage *message) const throw (SecurityError){D.Out(pdTrace,"CheckMessage : %ld", socket_number); if ((message->federation == 0) && (message->federate == 0)) return ; Socket *socket ; try { socket = getSocketLink(message->federation, message->federate); } catch (Exception &e) { // BUG: Should put a line in the Audit. D.Out(pdTrace,"C'est bien ici."); throw SecurityError("Message has a unknown origin."); } if (socket->returnSocket() != socket_number) { // BUG: Should put a line in the Audit. throw SecurityError("Message has a forged origin."); }}// ----------------------------------------------------------------------------/*! Close and delete the Socket object whose socket is "Socket", and return the former references associated with this socket in the last two parameters. Those returned references can be used for example to force the Federate out of the Federation. Further call to GetSocket with those references will return a NULL Socket object. Throw RTIinternalError if the socket is not found.*/voidSocketServer::close(long socket, FederationHandle &federation_referenced, FederateHandle &federate_referenced) throw (RTIinternalError){ federation_referenced = 0 ; federate_referenced = 0 ; // It may throw RTIinternalError. SocketTuple *tuple = getWithSocket(socket); federation_referenced = tuple->Federation ; federate_referenced = tuple->Federate ; // If the Tuple had no references, remove it, else just delete the socket. if (tuple->Federation == 0) { list<SocketTuple *>::iterator i ; list<SocketTuple *>::iterator tmp ; for (i = begin(); i != end(); i++) { if (((*i)->ReliableLink != NULL) && ((*i)->ReliableLink->returnSocket() == socket)) { delete (*i); tmp = erase(i); // i is dereferenced. i = tmp-- ; // loop will increment i ; } } } else { tuple->ReliableLink->close(); tuple->BestEffortLink->close(); //A FAIRE : Problablement necessaire de fermer d'abord l'autre cote delete tuple->ReliableLink ; delete tuple->BestEffortLink ; delete tuple->QuickLink; tuple->ReliableLink = NULL ; tuple->BestEffortLink = NULL ; tuple->QuickLink = NULL; }}// ----------------------------------------------------------------------------//! socketServer.SocketServer::SocketServer(SocketTCP *tcp_socket, SocketUDP *udp_socket, int the_port) : list<SocketTuple *>(){ if (tcp_socket == NULL) throw RTIinternalError(); ServerSocketTCP = tcp_socket ; ServerSocketUDP = udp_socket ;}// ----------------------------------------------------------------------------//! Destructor (frees tuple list).SocketServer::~SocketServer(void){ // Deleting remaining tuples. while (!list<SocketTuple *>::empty()) { delete front(); pop_front(); }}// ----------------------------------------------------------------------------//! SocketTuple constructor.SocketTuple::SocketTuple(Socket *tcp_link) : Federation(0), Federate(0){ if (tcp_link != NULL) ReliableLink = (SocketTCP *)tcp_link ; else throw RTIinternalError("Null socket"); BestEffortLink = new SocketUDP(); QuickLink = new SocketSHM();}// ----------------------------------------------------------------------------//! SocketTuple destructor.SocketTuple::~SocketTuple(void){ if (QuickLink != NULL) { //QuickLink->close(); delete QuickLink ; QuickLink = NULL ; } if (BestEffortLink != NULL) { BestEffortLink->close(); delete BestEffortLink ; BestEffortLink = NULL ; } if (BestEffortLink != NULL) { BestEffortLink->close(); delete BestEffortLink ; BestEffortLink = NULL ; } }// ----------------------------------------------------------------------------/*! This method return the first socket object who has been declared active in the fd_set. It can be called several times to get all active sockets.*/Socket *SocketServer::getActiveSocket(fd_set *select_fdset) const{ list<SocketTuple *>::const_iterator i ; for (i = begin(); i != end(); i++) { if (((*i)->ReliableLink != NULL) && (FD_ISSET((*i)->ReliableLink->returnSocket(), select_fdset))) return (*i)->ReliableLink ; /*if (((*i)->QuickLink != NULL) && ((*i)->QuickLink->isDataReady() == RTI_TRUE)) return (*i)->QuickLink;*/ } return NULL ;}// ----------------------------------------------------------------------------/*! Return the Socket object associated with(theFederation, theFederate). If the couple(Federation, Federate) is not found, a FederateNotExecutionMember exception is thrown. If the Federate has crashed, it should return a NULL socket object, but this should not happen. In fact, when a Client(Federate) crashes, the RTIG is supposed be remove all references to this federate. That's the reason why a RTIinternalError is thrown in that case.*/Socket*SocketServer::getSocketLink(FederationHandle the_federation, FederateHandle the_federate, TransportType the_type) const throw (FederateNotExecutionMember, RTIinternalError){ SocketTuple *tuple; D.Out(pdTrace,"getSocketLink .. : % d, %d", the_federation,the_federate); // It may throw FederateNotExecutionMember try { tuple = getWithReferences(the_federation, the_federate); } catch (FederateNotExecutionMember &e) { D.Out(pdExcept, "Error while getSocketLink."); throw FederateNotExecutionMember("Reference to a killed Federate."); } return tuple->QuickLink; if (the_type == RELIABLE) { if (tuple->ReliableLink == 0) throw RTIinternalError("Reference to a killed Federate."); D.Out(pdTrace,"getWithReference"); return tuple->ReliableLink ; } else { if (tuple->BestEffortLink == 0) throw RTIinternalError("Reference to a killed Federate."); D.Out(pdTrace,"getWithReference"); return tuple->BestEffortLink ; }}// ----------------------------------------------------------------------------//! getWithReferences.SocketTuple *SocketServer::getWithReferences(FederationHandle the_federation, FederateHandle the_federate) const throw (FederateNotExecutionMember){ list<SocketTuple *>::const_iterator i ; for (i = begin(); i != end(); i++) { if (((*i)->Federation == the_federation) && ((*i)->Federate == the_federate)) return (*i); } D.Out(pdTrace,"getWithReferences : % d, %d", the_federation,the_federate); throw FederateNotExecutionMember();}// ----------------------------------------------------------------------------//! getWithSocket (private).SocketTuple *SocketServer::getWithSocket(long socket_descriptor) const throw (RTIinternalError){ list<SocketTuple *>::const_iterator i ; for (i = begin(); i != end(); i++) { if (((*i)->ReliableLink != NULL) && ((*i)->ReliableLink->returnSocket() == socket_descriptor)) return (*i); if (((*i)->BestEffortLink != NULL) && ((*i)->BestEffortLink->returnSocket() == socket_descriptor)) return (*i); if (((*i)->QuickLink != NULL) && ((*i)->QuickLink->returnSocket() == socket_descriptor)) return (*i); } D.Out(pdTrace,"getWithSocket : % ld", socket_descriptor); throw RTIinternalError("Socket not found.");}// ----------------------------------------------------------------------------/*! Allocate a new SocketTuple by Accepting on the ServerSocket. The SocketTuple references are empty. Throw RTIinternalError in case of a memory allocation problem.*/voidSocketServer::open(void) throw (RTIinternalError){ SecureTCPSocket *newLink = new SecureTCPSocket(); if (newLink == NULL) throw RTIinternalError("Could not allocate new socket."); //newLink->accept(ServerSocketTCP); SocketTuple *newTuple = new SocketTuple(newLink); newTuple->QuickLink->accept(ServerSocketTCP); if (newTuple == NULL) throw RTIinternalError("Could not allocate new tuple."); push_front(newTuple);}SocketTuple*SocketServer::select(fd_set * fd, bool *terminate){ SocketTuple* tuple; Socket * link;// Initialize fd_set structure with all opened sockets. D.Out(pdTrace,"initialisation de fd_set avec le socket de communication"); FD_ZERO(fd); FD_SET(ServerSocketTCP->returnSocket(), fd); D.Out(pdTrace,"initialisation de fd_set avec les sockets ouverts"); struct timeval delai; delai.tv_sec = 0; delai.tv_usec = 0; // Wait for an incoming message. int result = 0 ; D.Out(pdTrace,"debut de la scrutation"); while(result==0){ FD_ZERO(fd); FD_SET(ServerSocketTCP->returnSocket(), fd); result = ::select(ulimit(4, 0), fd, NULL, NULL,&delai); D.Out(pdTrace,"result = %d",result); list<SocketTuple *>::const_iterator i ; for (i = begin(); i != end(); i++) { if ((*i)->QuickLink == NULL) continue ; if ((*i)->QuickLink->isDataReady() == RTI_TRUE){ D.Out(pdTrace,"requete entrante sur le socket SHM %d",(*i)->QuickLink->returnSocket()); return (*i); } } if (*terminate) return NULL; } D.Out(pdTrace,"requete entrante sur socket TCP"); return NULL;}// ----------------------------------------------------------------------------/*! Change the FederationHandle and the FederateHandle associated with "socket". Once the references have been set for a Socket, they can't be changed. References can be zeros(but should not). Throw RTIinternalError if the References have already been set, or if the Socket is not found.*/voidSocketServer::setReferences(long socket, FederationHandle federation_reference, FederateHandle federate_reference, unsigned long address, unsigned int port) throw (RTIinternalError){ // It may throw RTIinternalError if not found. SocketTuple *tuple = getWithSocket(socket); if ((tuple->Federation != 0) || (tuple->Federate != 0)) // References have already been set once. throw RTIinternalError("Socket References have already been set."); tuple->Federation = federation_reference ; tuple->Federate = federate_reference ; tuple->BestEffortLink->attach(ServerSocketUDP->returnSocket(), address, port);}}// $Id: SocketServer.cc,v 3.5 2003/02/19 18:07:30 breholee Exp $
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -