Update of /cvsroot/simspark/simspark/spark/oxygen/simulationserver In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15620/simulationserver Added Files: agentcontrol.cpp agentcontrol.h agentcontrol_c.cpp monitorcontrol.cpp monitorcontrol.h monitorcontrol_c.cpp netbuffer.cpp netbuffer.h netclient.cpp netclient.h netclient_c.cpp netcontrol.cpp netcontrol.h netcontrol_c.cpp netmessage.cpp netmessage.h netmessage_c.cpp simcontrolnode.cpp simcontrolnode.h simcontrolnode_c.cpp simulationserver.cpp simulationserver.h simulationserver_c.cpp Log Message: --- NEW FILE: simcontrolnode.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: simcontrolnode.h,v 1.1 2005/12/05 21:21:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef OXYGEN_SIMCONTROLNODE_H #define OXYGEN_SIMCONTROLNODE_H #include <zeitgeist/node.h> namespace oxygen { class SimulationServer; /** \class SimControlNode defines an interface for classes that are registered to the SimulationServer. The interface defines callbacks for the initial startup of the simulation, it's final shutdown and for different phases of each simulation cycle. SimControlNodes are used extend and customize the simulation runloop and to delegate tasks, like network management, reading of mouse and keyboard input, writing a simulation log, rendering etc. */ class SimControlNode : public zeitgeist::Node { public: SimControlNode(); virtual ~SimControlNode(); /** called once when the simulation is started */ virtual void InitSimulation() {}; /** called once before the simulation is shut down */ virtual void DoneSimulation() {}; /** called when a new simulation cycle starts, before the simulation is stepped */ virtual void StartCycle() {}; /** called each simulation cycle to send agent sensor information */ virtual void SenseAgent() {}; /** called each simulation cycle to carry out agent actions */ virtual void ActAgent() {}; /** called when the current simulation cycle ends */ virtual void EndCycle() {}; protected: /** returns a reference to the SimulationServer */ boost::shared_ptr<SimulationServer> GetSimulationServer(); }; DECLARE_CLASS(SimControlNode); } // namespace oxygen #endif // OXYGEN_SIMCONTROLNODE_H --- NEW FILE: monitorcontrol.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2003 Koblenz University $Id: monitorcontrol.h,v 1.1 2005/12/05 21:21:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef OXYGEN_MONITORCONTROL_H #define OXYGEN_MONITORCONTROL_H #include "netcontrol.h" namespace oxygen { class MonitorServer; /** \class MonitorConrol is a NetControl node that manages the communication with monitors in cooperation with the MonitorServer. */ class MonitorControl : public NetControl { public: MonitorControl(); virtual ~MonitorControl(); /** forwards all pending messages from all connected monitors to the MonitorServer */ virtual void StartCycle(); /** updates all connected monitors at the end of each simulation cycle */ virtual void EndCycle(); /** called when a new client connects */ virtual void ClientConnect(boost::shared_ptr<Client> client); /** returns the monitor update interval in cycles */ int GetMonitorInterval(); /** sets the monitor update interval in cycles */ void SetMonitorInterval(int i); protected: virtual void OnLink(); virtual void OnUnlink(); protected: /** cached reference to the MonitorServer */ boost::shared_ptr<MonitorServer> mMonitorServer; /** the update interval for the connected monitors in cycles */ int mMonitorInterval; }; DECLARE_CLASS(MonitorControl); } // namespace oxygen #endif // OXYGEN_MONITORCONTROL_H --- NEW FILE: agentcontrol.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2003 Koblenz University $Id: agentcontrol.h,v 1.1 2005/12/05 21:21:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef OXYGEN_AGENTCONTROL_H #define OXYGEN_AGENTCONTROL_H #include "netcontrol.h" namespace oxygen { class GameControlServer; /** \class AgentControl is a NetControl node that manages the communication with agents in cooperation with the GameControlServer. */ class AgentControl : public NetControl { public: AgentControl(); virtual ~AgentControl(); /** called when a new client connects */ virtual void ClientConnect(boost::shared_ptr<Client> client); /** called when a client disconnects */ virtual void ClientDisconnect(boost::shared_ptr<Client> client); /** forwards all pending messages from all connected agents to the GameControlServer */ virtual void StartCycle(); /** generates and sends sense updates to all connected agents */ virtual void EndCycle(); protected: virtual void OnLink(); virtual void OnUnlink(); protected: /** cached reference to the GameControlServer */ boost::shared_ptr<GameControlServer> mGameControlServer; }; DECLARE_CLASS(AgentControl); } // namespace oxygen #endif // OXYGEN_AGENTCONTROL_H --- NEW FILE: netmessage_c.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2003 Koblenz University $Id: netmessage_c.cpp,v 1.1 2005/12/05 21:21:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "netmessage.h" using namespace oxygen; using namespace std; void CLASS(NetMessage)::DefineClass() { DEFINE_BASECLASS(zeitgeist/Leaf); } --- NEW FILE: monitorcontrol.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2003 Koblenz University $Id: monitorcontrol.cpp,v 1.1 2005/12/05 21:21:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "monitorcontrol.h" #include "simulationserver.h" #include "netmessage.h" #include <zeitgeist/logserver/logserver.h> #include <oxygen/monitorserver/monitorserver.h> #include <oxygen/sceneserver/sceneserver.h> #include <oxygen/sceneserver/scene.h> using namespace oxygen; using namespace zeitgeist; using namespace boost; using namespace std; MonitorControl::MonitorControl() : NetControl() { mLocalAddr.setPort(3200); mMonitorInterval = 30; } MonitorControl::~MonitorControl() { } void MonitorControl::OnLink() { NetControl::OnLink(); shared_ptr<SimulationServer> sim = GetSimulationServer(); if (sim.get() == 0) { GetLog()->Error() << "(MonitorControl) ERROR: SimulationServer not found\n"; return; } mMonitorServer = sim->GetMonitorServer(); } void MonitorControl::OnUnlink() { NetControl::OnUnlink(); mMonitorServer.reset(); } void MonitorControl::ClientConnect(shared_ptr<Client> client) { if ( (mMonitorServer.get() == 0) || (mNetMessage.get() == 0) ) { return; } string header = mMonitorServer->GetMonitorHeaderInfo(); mNetMessage->PrepareToSend(header); SendMessage(client->addr,header); } void MonitorControl::EndCycle() { NetControl::EndCycle(); const int cycle = GetSimulationServer()->GetCycle(); if (cycle % mMonitorInterval) { return; } if ( (mMonitorServer.get() == 0) || (mNetMessage.get() == 0) || (mClients.size() == 0) ) { return; } // send updates to all connected monitors string info = mMonitorServer->GetMonitorInfo(); mNetMessage->PrepareToSend(info); for ( TAddrMap::iterator iter = mClients.begin(); iter != mClients.end(); ++iter ) { SendMessage((*iter).second,info); } // reset the modified flag for the active scene shared_ptr<SceneServer> sceneServer = GetSimulationServer()->GetSceneServer(); if (sceneServer.get() !=0) { shared_ptr<Scene> scene = sceneServer->GetActiveScene(); if (scene.get() != 0) { scene->SetModified(false); } } } void MonitorControl::StartCycle() { NetControl::StartCycle(); if ( (mMonitorServer.get() == 0) || (mNetMessage.get() == 0) ) { return; } // pass all received messages to the MonitorServer for ( TBufferMap::iterator iter = mBuffers.begin(); iter != mBuffers.end(); ++iter ) { shared_ptr<NetBuffer>& netBuff = (*iter).second; if ( (netBuff.get() == 0) || (netBuff->IsEmpty()) ) { continue; } string message; while (mNetMessage->Extract(netBuff,message)) { mMonitorServer->ParseMonitorMessage(message); } } } int MonitorControl::GetMonitorInterval() { return mMonitorInterval; } void MonitorControl::SetMonitorInterval(int i) { mMonitorInterval = i; } --- NEW FILE: netmessage.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2003 Koblenz University $Id: netmessage.cpp,v 1.1 2005/12/05 21:21:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "netmessage.h" #include "netbuffer.h" #include <netinet/in.h> using namespace oxygen; using namespace zeitgeist; using namespace std; using namespace boost; NetMessage::NetMessage() : Leaf() { } NetMessage::~NetMessage() { } void NetMessage::PrepareToSend(std::string& msg) { // prefix the message with it's payload length unsigned int len = htonl(msg.size()); string prefix((const char*)&len,sizeof(unsigned int)); msg = prefix + msg; } bool NetMessage::Extract(shared_ptr<NetBuffer> buffer, std::string& msg) { // a message is prefixed with it's payload length const unsigned int preSz = sizeof(unsigned int); string& data = buffer->GetData(); if (data.size() < preSz) { return false; } unsigned int msgLen = ntohl((*(unsigned int*)data.data())); if (data.size() < (msgLen + preSz)) { // incomplete message return false; } // copy to msg and cut from buffer msg = string(data.c_str() + preSz, msgLen); data.erase(0, preSz + msgLen); // zero terminate received data msg += '\0'; return true; } --- NEW FILE: simcontrolnode.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: simcontrolnode.cpp,v 1.1 2005/12/05 21:21:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "simcontrolnode.h" #include "simulationserver.h" using namespace oxygen; using namespace zeitgeist; using namespace salt; using namespace std; using namespace boost; SimControlNode::SimControlNode() : Node() { } SimControlNode::~SimControlNode() { } shared_ptr<SimulationServer> SimControlNode::GetSimulationServer() { return shared_static_cast<SimulationServer> (make_shared(GetParent())); } --- NEW FILE: netbuffer.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2003 Koblenz University $Id: netbuffer.cpp,v 1.1 2005/12/05 21:21:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "netbuffer.h" using namespace oxygen; using namespace rcss::net; using namespace std; void NetBuffer::AddFragment(const std::string& d) { mData += d; } const Addr& NetBuffer::GetAddr() const { return mAddr; } string& NetBuffer::GetData() { return mData; } bool NetBuffer::IsEmpty() const { return mData.empty(); } --- NEW FILE: simulationserver_c.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: simulationserver_c.cpp,v 1.1 2005/12/05 21:21:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "simulationserver.h" using namespace oxygen; using namespace std; FUNCTION(SimulationServer,quit) { obj->Quit(); return true; } FUNCTION(SimulationServer,initControlNode) { string inClassName; string inName; if ( (in.GetSize() != 2) || (! in.GetValue(in[0],inClassName)) || (! in.GetValue(in[1],inName)) ) { return false; } return obj->InitControlNode(inClassName,inName); } FUNCTION(SimulationServer, getTime) { return obj->GetTime(); } FUNCTION(SimulationServer, setSimStep) { float inDeltaTime; if ( (in.GetSize() != 1) || (! in.GetValue(in[0], inDeltaTime)) ) { return false; } obj->SetSimStep(inDeltaTime); return true; } FUNCTION(SimulationServer, getSimStep) { return obj->GetSimStep(); } FUNCTION(SimulationServer, setAutoTimeMode) { bool inSet; if ( (in.GetSize() != 1) || (! in.GetValue(in[0], inSet)) ) { return false; } obj->SetAutoTimeMode(inSet); return true; } FUNCTION(SimulationServer, getAutoTimeMode) { return obj->GetAutoTimeMode(); } void CLASS(SimulationServer)::DefineClass() { DEFINE_BASECLASS(zeitgeist/Node); DEFINE_FUNCTION(quit); DEFINE_FUNCTION(initControlNode); DEFINE_FUNCTION(getTime); DEFINE_FUNCTION(setSimStep); DEFINE_FUNCTION(getSimStep); DEFINE_FUNCTION(setAutoTimeMode); DEFINE_FUNCTION(getAutoTimeMode); } --- NEW FILE: agentcontrol_c.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2003 Koblenz University $Id: agentcontrol_c.cpp,v 1.1 2005/12/05 21:21:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "agentcontrol.h" using namespace oxygen; using namespace std; void CLASS(AgentControl)::DefineClass() { DEFINE_BASECLASS(oxygen/NetControl); } --- NEW FILE: netbuffer.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2003 Koblenz University $Id: netbuffer.h,v 1.1 2005/12/05 21:21:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef OXYGEN_NETBUFFER_H #define OXYGEN_NETBUFFER_H #include <rcssnet/addr.hpp> namespace oxygen { /** \class NetBuffer is a buffer that is used to hold the raw network stream of data. The NetMessage class is responsible to extract meaningful messages. */ class NetBuffer { public: NetBuffer() {}; NetBuffer(rcss::net::Addr addr, const std::string& data) : mAddr(addr), mData(data) {} /** appends a fragment to the buffer */ void AddFragment(const std::string& d); /** returns true iff the buffer is empty*/ bool IsEmpty() const; /** returns the network address associated with this buffer */ const rcss::net::Addr& GetAddr() const; /** returns the managed buffer */ std::string& GetData(); protected: /** the associated network address */ rcss::net::Addr mAddr; /** the managed buffer */ std::string mData; }; } // namespace oxygen #endif // OXYGEN_NETBUFFER_H --- NEW FILE: netmessage.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2003 Koblenz University $Id: netmessage.h,v 1.1 2005/12/05 21:21:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef OXYGEN_NETMESSAGE_H #define OXYGEN_NETMESSAGE_H #include <zeitgeist/class.h> #include <zeitgeist/leaf.h> namespace oxygen { class NetBuffer; /** \class NetMessage is responsible for the segmentation of raw received network data into meaningful messages, stripping any meta message information (e.g. msg length prefixes). It further is responsible to prepare a message to be sent over the network, i.e. to add any necessary meta information. The default NetMessage class implements a simple length prefixed protocol, i.e. it adds the payload length to a string sent over the network. */ class NetMessage : public zeitgeist::Leaf { public: NetMessage(); virtual ~NetMessage(); /** prepares a message that is sent to a client, i.e. adds any neccessary meta information. The default implementation prefixes the message with its total length */ virtual void PrepareToSend(std::string& msg); /** extracts a message from a network receive buffer into 'msg', i.e. it removes any meta information and returns the first complete message. The extracted message must be removed from the network buffer. ExtractMessage returns true iff it successfully extracted a message. The default implementation expects length prefixed strings. */ virtual bool Extract(boost::shared_ptr<NetBuffer> buffer, std::string& msg); }; DECLARE_CLASS(NetMessage); } // namespace oxygen #endif // OXYGEN_NETMESSAGE_H --- NEW FILE: simulationserver.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: simulationserver.cpp,v 1.1 2005/12/05 21:21:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "simulationserver.h" #include "simcontrolnode.h" #include <oxygen/monitorserver/monitorserver.h> #include <oxygen/sceneserver/sceneserver.h> #include <oxygen/gamecontrolserver/gamecontrolserver.h> #include <zeitgeist/logserver/logserver.h> #include <signal.h> using namespace oxygen; using namespace zeitgeist; using namespace salt; using namespace std; using namespace boost; bool SimulationServer::mExit = false; void SimulationServer::CatchSignal(int sig_num) { if (sig_num == SIGINT) { signal(SIGINT, CatchSignal); SimulationServer::mExit = true; std::cout << "(SimulationServer) caught SIGINT. exiting.\n"; } } SimulationServer::SimulationServer() : Node() { mSimTime = 0.0f; mSimStep = 0.2f; mAutoTime = true; mCycle = 0; mSumDeltaTime = 0; mArgC = 0; mArgV = 0; signal(SIGINT, CatchSignal); } SimulationServer::~SimulationServer() { } void SimulationServer::OnLink() { mMonitorServer = shared_dynamic_cast<MonitorServer> (GetCore()->Get("/sys/server/monitor")); if (mMonitorServer.get() == 0) { GetLog()->Error() << "(SimulationServer) ERROR: MonitorServer not found.\n"; } mGameControlServer = shared_dynamic_cast<GameControlServer> (GetCore()->Get("/sys/server/gamecontrol")); if (mGameControlServer.get() == 0) { GetLog()->Error() << "(SimulationServer) ERROR: GameControlServer not found.\n"; } mSceneServer = shared_dynamic_cast<SceneServer> (GetCore()->Get("/sys/server/scene")); if (mSceneServer.get() == 0) { GetLog()->Error() << "(SimulationServer) ERROR: SceneServer not found.\n"; } } void SimulationServer::OnUnlink() { mMonitorServer.reset(); mGameControlServer.reset(); mSceneServer.reset(); } void SimulationServer::Quit() { mExit = true; } int SimulationServer::GetArgC() { return mArgC; } char** SimulationServer::GetArgV() { return mArgV; } float SimulationServer::GetTime() { return mSimTime; } float SimulationServer::GetSimStep() { return mSimStep; } void SimulationServer::SetSimStep(float deltaTime) { mSimStep = deltaTime; } float SimulationServer::GetSumDeltaTime() { return mSumDeltaTime; } void SimulationServer::SetAutoTimeMode(bool set) { mAutoTime = set; } bool SimulationServer::GetAutoTimeMode() { return mAutoTime; } int SimulationServer::GetCycle() { return mCycle; } bool SimulationServer::InitControlNode(const std::string& className, const std::string& name) { shared_ptr<SimControlNode> importer = shared_dynamic_cast<SimControlNode>(GetCore()->New(className)); if (importer.get() == 0) { GetLog()->Error() << "(SimulationServer) ERROR: " << "Unable to create '" << className << "'\n"; return false; } importer->SetName(name); AddChildReference(importer); GetLog()->Normal() << "(SimulationServer) SimControlNode '" << name << "' registered\n"; return true; } shared_ptr<SimControlNode> SimulationServer::GetControlNode(const string& controlName) { shared_ptr<SimControlNode> ctrNode = shared_dynamic_cast<SimControlNode>(GetChild(controlName)); if (ctrNode.get() == 0) { GetLog()->Normal() << "(SimulationServer) SimControlNode '" << controlName << "' not found\n"; } return ctrNode; } void SimulationServer::AdvanceTime(float deltaTime) { mSumDeltaTime += deltaTime; } void SimulationServer::Step() { if ( (mSceneServer.get() == 0) || (mGameControlServer.get() == 0) ) { return; } if (mSimStep > 0) { // world is stepped in discrete steps while (mSumDeltaTime >= mSimStep) { mSceneServer->Update(mSimStep); mGameControlServer->Update(mSimStep); mSumDeltaTime -= mSimStep; mSimTime += mSimStep; } } else { // simulate passed time in one single step mSceneServer->Update(mSumDeltaTime); mGameControlServer->Update(mSimStep); mSimTime += mSumDeltaTime; mSumDeltaTime = 0; } } void SimulationServer::ControlEvent(EControlEvent event) { for ( TLeafList::iterator iter=begin(); iter != end(); ++iter ) { shared_ptr<SimControlNode> ctrNode = shared_dynamic_cast<SimControlNode>(*iter); if (ctrNode.get() == 0) { continue; } switch (event) { case CE_Init : ctrNode->InitSimulation(); break; case CE_Done : ctrNode->DoneSimulation(); break; case CE_StartCycle : ctrNode->StartCycle(); break; case CE_SenseAgent : ctrNode->SenseAgent(); break; case CE_ActAgent : ctrNode->ActAgent(); break; case CE_EndCycle : ctrNode->EndCycle(); break; default: GetLog()->Error() << "(SimulationServer) ERROR: unknown control event " << event << "\n"; return; } } } void SimulationServer::Run(int argc, char** argv) { GetLog()->Normal() << "(SimulationServer) entering runloop\n"; // cache argc and argv, to make it accessible for registerd // SimControlNodes mArgC = argc; mArgV = argv; ControlEvent(CE_Init); while (! mExit) { ++mCycle; ControlEvent(CE_StartCycle); ControlEvent(CE_SenseAgent); ControlEvent(CE_ActAgent); if (mAutoTime) { AdvanceTime(mSimStep); } Step(); ControlEvent(CE_EndCycle); } ControlEvent(CE_Done); mArgC = 0; mArgV = 0; GetLog()->Normal() << "(SimulationServer) leaving runloop at t=" << mSimTime << "\n"; } shared_ptr<GameControlServer> SimulationServer::GetGameControlServer() { return mGameControlServer; } shared_ptr<MonitorServer> SimulationServer::GetMonitorServer() { return mMonitorServer; } shared_ptr<SceneServer> SimulationServer::GetSceneServer() { return mSceneServer; } --- NEW FILE: monitorcontrol_c.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2003 Koblenz University $Id: monitorcontrol_c.cpp,v 1.1 2005/12/05 21:21:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "monitorcontrol.h" using namespace oxygen; using namespace std; FUNCTION(MonitorControl, getMonitorInterval) { return obj->GetMonitorInterval(); } FUNCTION(MonitorControl, setMonitorInterval) { int inInterval; if ( (in.GetSize() != 1) || (! in.GetValue(in.begin(), inInterval)) ) { return false; } obj->SetMonitorInterval(inInterval); return true; } void CLASS(MonitorControl)::DefineClass() { DEFINE_BASECLASS(oxygen/NetControl); DEFINE_FUNCTION(getMonitorInterval); DEFINE_FUNCTION(setMonitorInterval); } --- NEW FILE: simcontrolnode_c.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: simcontrolnode_c.cpp,v 1.1 2005/12/05 21:21:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "simcontrolnode.h" using namespace oxygen; using namespace std; void CLASS(SimControlNode)::DefineClass() { DEFINE_BASECLASS(zeitgeist/Node); } --- NEW FILE: netclient_c.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: netclient_c.cpp,v 1.1 2005/12/05 21:21:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "netclient.h" using namespace std; using namespace oxygen; FUNCTION(NetClient, getServer) { return obj->GetServer(); } FUNCTION(NetClient, setServer) { string inServer; if ( (in.GetSize() != 1) || (! in.GetValue(in[0], inServer)) ) { return false; } obj->SetServer(inServer); return true; } FUNCTION(NetClient, setClientTypeTCP) { obj->SetClientType(NetControl::ST_TCP); return true; } FUNCTION(NetClient, setClientTypeUDP) { obj->SetClientType(NetControl::ST_UDP); return true; } FUNCTION(NetClient, getPort) { return obj->GetPort(); } FUNCTION(NetClient, setPort) { int inPort; if ( (in.GetSize() != 1) || (! in.GetValue(in[0], inPort)) ) { return false; } obj->SetPort(inPort); return true; } void CLASS(NetClient)::DefineClass() { DEFINE_BASECLASS(oxygen/SimControlNode); DEFINE_FUNCTION(getServer); DEFINE_FUNCTION(setServer); DEFINE_FUNCTION(getPort); DEFINE_FUNCTION(setPort); DEFINE_FUNCTION(setClientTypeTCP); DEFINE_FUNCTION(setClientTypeUDP); } --- NEW FILE: netclient.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: netclient.cpp,v 1.1 2005/12/05 21:21:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "netclient.h" #include <zeitgeist/logserver/logserver.h> #include <netinet/in.h> #include <rcssnet/exception.hpp> using namespace oxygen; using namespace zeitgeist; using namespace rcss::net; using namespace salt; using namespace boost; using namespace std; NetClient::NetClient() : SimControlNode() { mHost = "127.0.0.1"; mPort = 3200; mBufferSize = 64 * 1024; mBuffer = shared_array<char>(new char[mBufferSize]); mType = NetControl::ST_TCP; mNetBuffer = shared_ptr<NetBuffer>(new NetBuffer()); } NetClient::~NetClient() { } void NetClient::SetServer(const std::string& host) { mHost = host; } const std::string& NetClient::GetServer() const { return mHost; } void NetClient::SetPort(int port) { mPort = port; } int NetClient::GetPort() const { return mPort; } void NetClient::SetClientType(NetControl::ESocketType type) { mType = type; } NetControl::ESocketType NetClient::GetClientType() { return mType; } bool NetClient::Connect() { mSocket = NetControl::CreateSocket(mType); if (mSocket.get() == 0) { return false; } GetLog()->Normal() << "(NetClient) '" << GetName() << "'connecting to " << ((mType == NetControl::ST_UDP) ? "UDP " : "TCP ") << mHost << ":" << mPort << "\n"; try { Addr local(INADDR_ANY,INADDR_ANY); mSocket->bind(local); } catch (BindErr error) { GetLog()->Error() << "(NetClient) '" << GetName() << "' failed to bind socket with '" << error.what() << "'" << endl; mSocket->close(); return false; } try { Addr server(mPort,mHost); mSocket->connect(server); } catch (ConnectErr error) { GetLog()->Error() << "(NetClient) '" << GetName() << "' connection failed with: '" << error.what() << "'" << endl; mSocket->close(); mSocket.reset(); return false; } if (mSocket->isConnected()) { cout << "(NetClient) '" << GetName() << "' connected successfully" << endl; } // assure that a NetMessage object is registered mNetMessage = FindChildSupportingClass<NetMessage>(); if (mNetMessage.get() == 0) { mNetMessage = shared_ptr<NetMessage>(new NetMessage()); } return true; } void NetClient::SendMessage(const string& msg) { if (mNetMessage.get() == 0) { return; } string preparedMsg = msg; mNetMessage->PrepareToSend(preparedMsg);; if (mSocket.get() == 0) { return; } int rval = 0; if (mType == NetControl::ST_UDP) { Addr server(mPort,mHost); rval = mSocket->send(msg.data(), msg.size(), server); } else { rval = mSocket->send(preparedMsg.data(), preparedMsg.size()); } if (rval < 0) { GetLog()->Error() << "(NetClient::SendMessage) ERROR: " << "send returned error '" << strerror(errno) << "' " << endl; } } void NetClient::CloseConnection() { if (mSocket.get() == 0) { return; } mSocket->close(); mSocket.reset(); GetLog()->Normal() << "(NetClient) '" << GetName() << "' closed connection to " << mHost << ":" << mPort << "\n"; mNetMessage.reset(); } void NetClient::ReadFragments() { if (mSocket.get() == 0) { return; } for (;;) { // test for available data int fd = mSocket->getFD(); fd_set readfds; FD_ZERO(&readfds); FD_SET(fd,&readfds); timeval time; time.tv_sec = 0; time.tv_usec = 0; int rval = select(fd+1, &readfds, 0, 0, &time ); if (rval == 0) { break; } if (rval < 0) { GetLog()->Error() << "(NetClient) ERROR select on client " << "socket failed with '" << strerror(errno) << "'" << endl; CloseConnection(); return; } rval = mSocket->recv(mBuffer.get(),mBufferSize); if (rval == 0) { CloseConnection(); return; } if (rval < 0) { GetLog()->Error() << "(NetClient) '" << GetName() << "' ERROR: '" << GetName() << "' recv returned error '" << strerror(errno) << "' " << endl; return; } string fragment(mBuffer.get(),rval); mNetBuffer->AddFragment(string(mBuffer.get(),rval)); } } --- NEW FILE: netcontrol.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2003 Koblenz University $Id: netcontrol.h,v 1.1 2005/12/05 21:21:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef OXYGEN_NETCONTROL_H #define OXYGEN_NETCONTROL_H #include "simcontrolnode.h" #include "netbuffer.h" #include <rcssnet/socket.hpp> #include <boost/shared_array.hpp> namespace oxygen { class GameControlServer; class NetMessage; /** \class NetControl is a SimControlNode that accepts and manages a set of network client connections via UDP or TCP. With each simulation cycle it collects all pending client messages in a set of network buffers, each corresponding to a client. It furthes provides methods to send messages to connected clients. The segmentation of the received data into messages and the composition of messages is delegated to a NetMessage class that is registered to a NetControl node. It is responsible to manage the MetaProtocol, i.e. it adds and removes any additional message framing and type information. */ class NetControl : public SimControlNode { public: enum ESocketType { ST_TCP, ST_UDP }; struct Client { public: int id; rcss::net::Addr addr; boost::shared_ptr<rcss::net::Socket> socket; public: Client() : id(-1) {}; Client(int i, const rcss::net::Addr& a, boost::shared_ptr<rcss::net::Socket> s = boost::shared_ptr<rcss::net::Socket>() ) : id(i), addr(a), socket(s) {}; }; // mapping from a client remote address to Client struct typedef std::map<rcss::net::Addr, boost::shared_ptr<Client> > TAddrMap; // mapping from a client remote address to a corresponding buffer typedef std::map<rcss::net::Addr, boost::shared_ptr<NetBuffer> > TBufferMap; typedef std::list<rcss::net::Addr> TAddrList; public: NetControl(); virtual ~NetControl(); /** creates the managed socket, when the simulation starts */ virtual void InitSimulation(); /** called once before the simulation is shut down */ virtual void DoneSimulation(); /** called when a new simulation cycle starts, before the simulation is stepped */ virtual void StartCycle(); /** called when the current simulation cycle ends */ virtual void EndCycle(); /** called when a new client connects */ virtual void ClientConnect(boost::shared_ptr<Client> client); /** called when a client disconnects */ virtual void ClientDisconnect(boost::shared_ptr<Client> client); /** sets the local port, on which connections are accepted */ void SetServerPort(rcss::net::Addr::PortType port); /** returns the local port, on which connections are accepted */ rcss::net::Addr::PortType GetServerPort(); /** sets the type of the socket on which connections are accepted */ void SetServerType(ESocketType type); /** returns the type of the socket on which connections are accepted */ ESocketType GetServerType(); /** sends a message to the given client */ void SendMessage(boost::shared_ptr<Client> client, const std::string& msg); /** sends a message to the client with the given address */ void SendMessage(const rcss::net::Addr& addr, const std::string& msg); /** create a socket according to the given ESocketType */ static boost::shared_ptr<rcss::net::Socket> NetControl::CreateSocket(ESocketType type); protected: /** returns a human readable description of the socket type and port*/ std::string NetControl::DescribeSocketType(); /** checks for and accepts pending TCP connections */ void AcceptTCPConnections(); /** reads and stores all available messages */ void NetControl::ReadMessages(); /** reads and stores all available TCP messages */ void ReadTCPMessages(); /** reads and stores all available UDP messages. UDP fragments from unknown sources generate new client entries */ void ReadUDPMessages(); /** copies the message fragment with length \param size currently in the receive buffer to the input queue of the client with the remoted address \param addr */ void StoreFragment(const rcss::net::Addr& addr, int size); /** creates a new client entry. \param from is the remote adress of the client. \param socket gives the loacl socket for a TCP connection the for a TCP connection */ void AddClient(const rcss::net::Addr& from, boost::shared_ptr<rcss::net::Socket> socket = boost::shared_ptr<rcss::net::Socket>()); /** removes a client entry and closes the associated socket. \param from is the remote adress of the client. */ void RemoveClient(const rcss::net::Addr& from); /** removes all clients marked in the mCloseClients list */ void CloseDeadConnections(); protected: /** cached reference to the NetMessage child node */ boost::shared_ptr<NetMessage> mNetMessage; /** the local port, on which connections are accepted */ rcss::net::Addr mLocalAddr; /** the type of created socket */ ESocketType mSocketType; /** the socket used to accept connections */ boost::shared_ptr<rcss::net::Socket> mSocket; /** map of known clients, based on remote address */ TAddrMap mClients; /** list of client connections to be closed */ TAddrList mCloseClients; /** list of queued messages */ TBufferMap mBuffers; /** the size of the allocated receive buffer */ int mBufferSize; /** the receive buffer */ boost::shared_array<char> mBuffer; /** the next available unique client id */ int mClientId; }; DECLARE_CLASS(NetControl); } // namespace oxygen #endif // OXYGEN_NETCONTROL_H --- NEW FILE: netcontrol.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2003 Koblenz University $Id: netcontrol.cpp,v 1.1 2005/12/05 21:21:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "netcontrol.h" #include "netmessage.h" #include <zeitgeist/logserver/logserver.h> #include <netinet/in.h> #include <rcssnet/exception.hpp> #include <rcssnet/tcpsocket.hpp> #include <rcssnet/udpsocket.hpp> #include <sstream> #include <cerrno> using namespace rcss::net; using namespace oxygen; using namespace zeitgeist; using namespace boost; using namespace std; NetControl::NetControl() : SimControlNode() { mBufferSize = 64 * 1024; mBuffer = shared_array<char>(new char[mBufferSize]); mSocketType = ST_TCP; mLocalAddr = Addr(INADDR_ANY, INADDR_ANY); mClientId = 1; } NetControl::~NetControl() { } void NetControl::SetServerPort(Addr::PortType port) { mLocalAddr.setPort(port); } rcss::net::Addr::PortType NetControl::GetServerPort() { return mLocalAddr.getPort(); } void NetControl::SetServerType(ESocketType type) { mSocketType = type; } NetControl::ESocketType NetControl::GetServerType() { return mSocketType; } boost::shared_ptr<Socket> NetControl::CreateSocket(ESocketType type) { shared_ptr<Socket> socket; try { switch (type) { case ST_UDP: socket = shared_ptr<Socket>(new UDPSocket()); break; case ST_TCP: socket = shared_ptr<Socket>(new TCPSocket()); break; default: cerr << "(NetControl) ERROR: unknown socket type " << type << "\n"; break; } } catch (OpenErr error) { cerr << "(NetControl) failed to create socket with '" << error.what() << endl; } return socket; } string NetControl::DescribeSocketType() { stringstream ss; switch (mSocketType) { case ST_UDP: ss << "UDP"; break; case ST_TCP: ss << "TCP"; break; default: ss << "(unknown socket type)"; break; } ss << ":" << mLocalAddr.getPort(); return ss.str(); } void NetControl::InitSimulation() { // assert that the local port has been set if (mLocalAddr.getPort() == INADDR_ANY) { GetLog()->Error() << "(NetControl) ERROR: local port has no been set in '" << GetClass()->GetName() << "'\n"; return; } GetLog()->Normal() << "(NetControl) '" << GetName() << "' setting up a server on " << DescribeSocketType() << std::endl; mSocket = CreateSocket(mSocketType); if (mSocket.get() == 0) { return; } int ret = mSocket->setNonBlocking(true); if (ret < 0) { GetLog()->Error() << "(NetControl) failed to set server socket to non " << "blocking mode with '" << strerror(errno) << "'\n"; mSocket->close(); return; } try { mSocket->bind(mLocalAddr); } catch (BindErr error) { GetLog()->Error() << "(NetControl) failed to bind socket with '" << error.what() << "'" << endl; mSocket->close(); return; } try { if (mSocketType == ST_TCP) { #ifdef SOMAXCONN mSocket->listen(SOMAXCONN); #else mSocket->listen(50); #endif } } catch (ListenErr error) { GetLog()->Error() << "(NetControl) failed to listen on socket with '" << error.what() << "'" << endl; mSocket->close(); return; } // assure that a NetMessage object is registered mNetMessage = FindChildSupportingClass<NetMessage>(); if (mNetMessage.get() == 0) { mNetMessage = shared_ptr<NetMessage>(new NetMessage()); } } void NetControl::DoneSimulation() { // reset the cached NetMessage reference mNetMessage.reset(); // close all client connections for ( TAddrMap::iterator iter = mClients.begin(); iter != mClients.end(); ++iter ) { RemoveClient((*iter).second->addr); } // shutdown the server socket mSocket->close(); GetLog()->Normal() << "(NetControl) '" << GetName() << "' closed server socket " << DescribeSocketType() << std::endl; mSocket.reset(); mClients.clear(); } void NetControl::AddClient(const Addr& from, shared_ptr<Socket> socket) { shared_ptr<Client> client(new Client(mClientId,from,socket)); mClients[from] = client; GetLog()->Normal() << "(NetControl) '" << GetName() << "' accepted a " << ((socket.get() != 0) ? "TCP" : "UDP") << " connection from '" << from.getHostStr() << ":" << from.getPort() << "' id " << mClientId << endl; mClientId++; ClientConnect(client); } void NetControl::RemoveClient(const Addr& from) { TAddrMap::iterator mapIter = mClients.find(from); if (mapIter == mClients.end()) { GetLog()->Warning() << "(NetControl) '" << GetName() << "' RemoveClient called with an unknown client address\n"; return; } shared_ptr<Client> client = (*mapIter).second; ClientDisconnect(client); shared_ptr<Socket> socket = client->socket; GetLog()->Normal() << "(NetControl) '" << GetName() << "' closing a " << ((socket.get() != 0) ? "TCP" : "UDP") << " connection from '" << from.getHostStr() << ":" << from.getPort() << "' id " << client->id << endl; if (socket.get() != 0) { socket->close(); } mClients.erase(mapIter); } void NetControl::ClientConnect(shared_ptr<Client> /*client*/) { // empty callback, implemented in derived classes } void NetControl::ClientDisconnect(shared_ptr<Client> /*client*/) { // empty callback, implemented in derived classes } void NetControl::SendMessage(shared_ptr<Client> client, const string& msg) { if (client.get() == 0) { return; } int rval = 0; shared_ptr<Socket> socket = client->socket; if (socket.get() == 0) { // udp client if (mSocket.get() != 0) { rval = mSocket->send(msg.data(), msg.size(), client->addr); } } else { // tcp client rval = socket->send(msg.data(), msg.size()); } if (rval < 0) { GetLog()->Error() << "(NetControl::SendMessage) ERROR: '" << GetName() << "' send returned error '" << strerror(errno) << "' " << endl; } } void NetControl::SendMessage(const Addr& addr, const string& msg) { TAddrMap::iterator iter = mClients.find(addr); if (iter == mClients.end()) { GetLog()->Error() << "(NetControl::SendMessage) ERROR: unknown client address '" << addr.getHostStr() << ":" << addr.getPort() << "'\n"; return; } SendMessage((*iter).second,msg); } void NetControl::AcceptTCPConnections() { if ( (mSocketType != ST_TCP) || (mSocket.get() == 0) ) { return; } int fd = mSocket->getFD(); fd_set readfds; FD_ZERO(&readfds); FD_SET(fd,&readfds); timeval time; time.tv_sec = 0; time.tv_usec = 0; for(;;) { int ret = select(fd+1, &readfds, 0, 0, &time); if (ret == 0) { // no more connections pending break; } if (ret < 0) { GetLog()->Error() << "(NetControl) ERROR: '" << GetName() << "' select returned error on server socket " << DescribeSocketType() << ' ' << strerror(errno) << "\n" << "(NetControl) ERROR: closing server socket" << endl; mSocket->close(); mSocket.reset(); break; } try { Addr addr; shared_ptr<Socket> socket(mSocket->accept(addr)); int ret = socket->setNonBlocking(true); if (ret < 0) { GetLog()->Error() << "(NetControl) failed to set client socket to" << " non blocking mode with '" << strerror(errno) << "'. closing connection\n"; ... [truncated message content] |