[Yake-svn] SF.net SVN: yake: [1495] trunk/yake
Status: Beta
Brought to you by:
psyclonist
From: <psy...@us...> - 2006-11-18 21:03:58
|
Revision: 1495 http://svn.sourceforge.net/yake/?rev=1495&view=rev Author: psyclonist Date: 2006-11-18 13:03:56 -0800 (Sat, 18 Nov 2006) Log Message: ----------- new demo for demonstrating remoting objects, improved net component (interface, functionality, docs) Modified Paths: -------------- trunk/yake/common/bin/debug/yake.graphics.ogre_resources.cfg trunk/yake/scripts/msvc8/net.vcproj trunk/yake/src/yake/ent/object_mgr.cpp trunk/yake/src/yake/net/detail/netCommon.cpp trunk/yake/src/yake/net/detail/netEnetClientPacketConnection.cpp trunk/yake/src/yake/net/detail/netEnetServerPacketConnection.cpp trunk/yake/src/yake/net/detail/netEventConnection.cpp trunk/yake/src/yake/net/detail/netInternal.cpp trunk/yake/src/yake/net/net.cpp trunk/yake/src/yake/samples/net/packet/demo.cpp trunk/yake/src/yake/samples/net/roclient/ROClient.cpp trunk/yake/src/yake/samples/net/roserver/ROServer.cpp trunk/yake/yake/net/detail/netEnetClientPacketConnection.h trunk/yake/yake/net/detail/netEnetServerPacketConnection.h trunk/yake/yake/net/detail/netEventConnection.h trunk/yake/yake/net/detail/netInternal.h trunk/yake/yake/net/net.h trunk/yake/yake/net/netBitstream.h trunk/yake/yake/net/netBitstream.inl trunk/yake/yake/net/netBitstreamAdapters.h trunk/yake/yake/net/netCommon.h trunk/yake/yake/net/netEvent.h trunk/yake/yake/net/netPacket.h trunk/yake/yake/net/netPrerequisites.h trunk/yake/yake/net/netTypes.h trunk/yake/yake/samples/net/common/commonEvents.h trunk/yake/yake/samples/net/common/config.h trunk/yake/yake/samples/net/roclient/ROClient.h trunk/yake/yake/samples/net/roserver/ROServer.h Added Paths: ----------- trunk/yake/common/bin/debug/rodemo.cfg trunk/yake/common/bin/debug/rodemo_client.cfg trunk/yake/common/bin/debug/rodemo_server.cfg trunk/yake/common/bin/debug/rodemo_serverclient.cfg trunk/yake/common/bin/release/rodemo.cfg trunk/yake/common/bin/release/rodemo_client.cfg trunk/yake/common/bin/release/rodemo_server.cfg trunk/yake/common/bin/release/rodemo_serverclient.cfg trunk/yake/scripts/msvc8/samples/net/sampleRoInprocess.vcproj trunk/yake/src/yake/net/detail/netDataChunk.cpp trunk/yake/src/yake/net/detail/netPacket.cpp trunk/yake/src/yake/samples/net/roinprocess/ trunk/yake/src/yake/samples/net/roinprocess/pch.cpp trunk/yake/yake/samples/net/common/roCommon.h Added: trunk/yake/common/bin/debug/rodemo.cfg =================================================================== --- trunk/yake/common/bin/debug/rodemo.cfg (rev 0) +++ trunk/yake/common/bin/debug/rodemo.cfg 2006-11-18 21:03:56 UTC (rev 1495) @@ -0,0 +1,11 @@ +rodemo +{ + server + { + start 1 + } + client + { + count 0 + } +} Added: trunk/yake/common/bin/debug/rodemo_client.cfg =================================================================== --- trunk/yake/common/bin/debug/rodemo_client.cfg (rev 0) +++ trunk/yake/common/bin/debug/rodemo_client.cfg 2006-11-18 21:03:56 UTC (rev 1495) @@ -0,0 +1,11 @@ +rodemo +{ + server + { + start 0 + } + client + { + count 1 + } +} Added: trunk/yake/common/bin/debug/rodemo_server.cfg =================================================================== --- trunk/yake/common/bin/debug/rodemo_server.cfg (rev 0) +++ trunk/yake/common/bin/debug/rodemo_server.cfg 2006-11-18 21:03:56 UTC (rev 1495) @@ -0,0 +1,11 @@ +rodemo +{ + server + { + start 1 + } + client + { + count 0 + } +} Added: trunk/yake/common/bin/debug/rodemo_serverclient.cfg =================================================================== --- trunk/yake/common/bin/debug/rodemo_serverclient.cfg (rev 0) +++ trunk/yake/common/bin/debug/rodemo_serverclient.cfg 2006-11-18 21:03:56 UTC (rev 1495) @@ -0,0 +1,11 @@ +rodemo +{ + server + { + start 1 + } + client + { + count 1 + } +} Modified: trunk/yake/common/bin/debug/yake.graphics.ogre_resources.cfg =================================================================== --- trunk/yake/common/bin/debug/yake.graphics.ogre_resources.cfg 2006-11-01 15:25:54 UTC (rev 1494) +++ trunk/yake/common/bin/debug/yake.graphics.ogre_resources.cfg 2006-11-18 21:03:56 UTC (rev 1495) @@ -22,3 +22,4 @@ FileSystem=../../media/gui.cegui.fonts/ FileSystem=../../media/gui.cegui.layouts/ Zip=../../media/skybox.zip +FileSystem=C:/Programme/Autodesk/3dsMax8/OSM/ Added: trunk/yake/common/bin/release/rodemo.cfg =================================================================== --- trunk/yake/common/bin/release/rodemo.cfg (rev 0) +++ trunk/yake/common/bin/release/rodemo.cfg 2006-11-18 21:03:56 UTC (rev 1495) @@ -0,0 +1,11 @@ +rodemo +{ + server + { + start 1 + } + client + { + count 0 + } +} Added: trunk/yake/common/bin/release/rodemo_client.cfg =================================================================== --- trunk/yake/common/bin/release/rodemo_client.cfg (rev 0) +++ trunk/yake/common/bin/release/rodemo_client.cfg 2006-11-18 21:03:56 UTC (rev 1495) @@ -0,0 +1,11 @@ +rodemo +{ + server + { + start 0 + } + client + { + count 1 + } +} Added: trunk/yake/common/bin/release/rodemo_server.cfg =================================================================== --- trunk/yake/common/bin/release/rodemo_server.cfg (rev 0) +++ trunk/yake/common/bin/release/rodemo_server.cfg 2006-11-18 21:03:56 UTC (rev 1495) @@ -0,0 +1,11 @@ +rodemo +{ + server + { + start 1 + } + client + { + count 0 + } +} Added: trunk/yake/common/bin/release/rodemo_serverclient.cfg =================================================================== --- trunk/yake/common/bin/release/rodemo_serverclient.cfg (rev 0) +++ trunk/yake/common/bin/release/rodemo_serverclient.cfg 2006-11-18 21:03:56 UTC (rev 1495) @@ -0,0 +1,11 @@ +rodemo +{ + server + { + start 1 + } + client + { + count 1 + } +} Modified: trunk/yake/scripts/msvc8/net.vcproj =================================================================== --- trunk/yake/scripts/msvc8/net.vcproj 2006-11-01 15:25:54 UTC (rev 1494) +++ trunk/yake/scripts/msvc8/net.vcproj 2006-11-18 21:03:56 UTC (rev 1495) @@ -222,6 +222,10 @@ > </File> <File + RelativePath="..\..\src\yake\net\detail\netDataChunk.cpp" + > + </File> + <File RelativePath="..\..\src\yake\net\detail\netEnetClientPacketConnection.cpp" > </File> @@ -237,6 +241,10 @@ RelativePath="..\..\src\yake\net\detail\netInternal.cpp" > </File> + <File + RelativePath="..\..\src\yake\net\detail\netPacket.cpp" + > + </File> </Filter> <Filter Name="enet" Added: trunk/yake/scripts/msvc8/samples/net/sampleRoInprocess.vcproj =================================================================== --- trunk/yake/scripts/msvc8/samples/net/sampleRoInprocess.vcproj (rev 0) +++ trunk/yake/scripts/msvc8/samples/net/sampleRoInprocess.vcproj 2006-11-18 21:03:56 UTC (rev 1495) @@ -0,0 +1,244 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8,00" + Name="sampleRoInprocess" + ProjectGUID="{8CB64BC3-7D11-484F-8D10-17DC105701F6}" + Keyword="Win32Proj" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="../../../../common/bin/debug" + IntermediateDirectory="../../../../common/obj/debug/$(ProjectName)" + ConfigurationType="1" + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + CharacterSet="2" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="../../../../;../../../../dependencies/boost/;../../../../dependencies/ttl/" + PreprocessorDefinitions="_STLP_DEBUG;WIN32;_DEBUG;_CONSOLE" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="3" + RuntimeTypeInfo="true" + UsePrecompiledHeader="2" + PrecompiledHeaderThrough="yake/samples/net/roinprocess/pch.h" + WarningLevel="3" + Detect64BitPortabilityProblems="true" + DebugInformationFormat="4" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="base.lib graphics.lib physics.lib audio.lib data.lib input.lib yapp.lib scripting.lib ent.lib" + OutputFile="$(OutDir)/$(ProjectName).exe" + LinkIncremental="2" + AdditionalLibraryDirectories="../../../../common/lib;../../../../common/lib/debug;../../../../dependencies/lib" + GenerateDebugInformation="true" + ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb" + SubSystem="1" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="../../../../common/bin/release" + IntermediateDirectory="../../../../common/obj/release/$(ProjectName)" + ConfigurationType="1" + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + CharacterSet="2" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories="../../../../;../../../../dependencies/boost/;../../../../dependencies/ttl/" + PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE" + RuntimeLibrary="2" + RuntimeTypeInfo="true" + UsePrecompiledHeader="2" + PrecompiledHeaderThrough="yake/samples/net/roinprocess/pch.h" + WarningLevel="3" + Detect64BitPortabilityProblems="true" + DebugInformationFormat="3" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="base.lib graphics.lib physics.lib audio.lib data.lib input.lib yapp.lib scripting.lib ent.lib" + OutputFile="$(OutDir)/$(ProjectName).exe" + LinkIncremental="1" + AdditionalLibraryDirectories="../../../../common/lib;../../../../common/lib/release;../../../../dependencies/lib" + GenerateDebugInformation="false" + SubSystem="1" + OptimizeReferences="2" + EnableCOMDATFolding="2" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="inc" + > + <File + RelativePath="..\..\..\..\yake\samples\net\roinprocess\pch.h" + > + </File> + <File + RelativePath="..\..\..\..\yake\samples\net\roclient\ROClient.h" + > + </File> + <File + RelativePath="..\..\..\..\yake\samples\net\common\roCommon.h" + > + </File> + <File + RelativePath="..\..\..\..\yake\samples\net\roserver\ROServer.h" + > + </File> + </Filter> + <Filter + Name="src" + > + <File + RelativePath="..\..\..\..\src\yake\samples\net\roinprocess\demo.cpp" + > + </File> + <File + RelativePath="..\..\..\..\src\yake\samples\net\roinprocess\pch.cpp" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="1" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="1" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\..\..\src\yake\samples\net\roclient\ROClient.cpp" + > + </File> + <File + RelativePath="..\..\..\..\src\yake\samples\net\roserver\ROServer.cpp" + > + </File> + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> Modified: trunk/yake/src/yake/ent/object_mgr.cpp =================================================================== --- trunk/yake/src/yake/ent/object_mgr.cpp 2006-11-01 15:25:54 UTC (rev 1494) +++ trunk/yake/src/yake/ent/object_mgr.cpp 2006-11-18 21:03:56 UTC (rev 1495) @@ -37,11 +37,9 @@ YAKE_ASSERT( ret.first == object::RC_OK )(ret.first)(ret.second); return makeObject( ret.second ); } - Object* ObjectManager::makeObject(const ClassId clsId) + void ObjectManager::setupObjectPostCreate(Object* obj) { - Object* obj = objMgr_.createObject(clsId); - YAKE_ASSERT( obj )(clsId); - objs_.push_back( obj ); + YAKE_ASSERT( obj ); obj->registerMessageListeners(msgRouter_); @@ -50,9 +48,27 @@ obj->init(); listeners_onObjectInitialized(obj); + } + Object* ObjectManager::makeObject(const ObjectId objId) + { + Object* obj = objMgr_.createObject(objId.classId(),objId); + YAKE_ASSERT( obj )(objId); + objs_.push_back( obj ); + this->setupObjectPostCreate(obj); + return obj; } + Object* ObjectManager::makeObject(const ClassId clsId) + { + Object* obj = objMgr_.createObject(clsId); + YAKE_ASSERT( obj )(clsId); + objs_.push_back( obj ); + + this->setupObjectPostCreate(obj); + + return obj; + } void ObjectManager::destroyObject(Object* obj) { YAKE_ASSERT( obj ); @@ -114,7 +130,24 @@ msg->setTarget( MessageTraits::kBroadcastTarget ); msgRouter_.post( msg ); } + void ObjectManager::setClassIdGenerationRange(const ClassId min, const ClassId max) + { + objMgr_.setClassIdGenerationRange( min, max ); + } + bool ObjectManager::registerClassAlias(const String& aliasName, const ClassId targetClsId) + { + object::ResultCode ret = objMgr_.registerClassAlias( aliasName, targetClsId ); + return (ret == object::RC_OK); + } + bool ObjectManager::registerClassAlias(const ClassId aliasClsId, const ClassId targetClsId) + { + object::ResultCode ret = objMgr_.registerClassAlias( aliasClsId, targetClsId ); + return (ret == object::RC_OK); + } + Object* ObjectManager::getObject(const ObjectId objId) const + { + return objMgr_.getObject( objId ); + } } } - Modified: trunk/yake/src/yake/net/detail/netCommon.cpp =================================================================== --- trunk/yake/src/yake/net/detail/netCommon.cpp 2006-11-01 15:25:54 UTC (rev 1494) +++ trunk/yake/src/yake/net/detail/netCommon.cpp 2006-11-18 21:03:56 UTC (rev 1495) @@ -25,6 +25,7 @@ // Windows Header Files: #include <windows.h> +namespace yake { namespace net { //------------------------------------------------------------------------- @@ -89,7 +90,7 @@ {} Address::~Address() {} - Address& Address::operator =(const net::Address& rhs) + Address& Address::operator =(const Address& rhs) { if (this == &rhs) return *this; @@ -167,11 +168,31 @@ reliability_ = rel; return *this; } + SendOptions& SendOptions::reliable() + { + reliability_ = R_RELIABLE; + return *this; + } + SendOptions& SendOptions::unreliable() + { + reliability_ = R_UNRELIABLE; + return *this; + } SendOptions& SendOptions::ordering(const Ordering ord) { ordering_ = ord; return *this; } + SendOptions& SendOptions::ordered() + { + ordering_ = O_ORDERED; + return *this; + } + SendOptions& SendOptions::unordered() + { + ordering_ = O_UNORDERED; + return *this; + } SendOptions& SendOptions::channel(const ChannelId id) { channelId_ = id; @@ -237,3 +258,4 @@ } } // namespace net +} // namespace yake Added: trunk/yake/src/yake/net/detail/netDataChunk.cpp =================================================================== --- trunk/yake/src/yake/net/detail/netDataChunk.cpp (rev 0) +++ trunk/yake/src/yake/net/detail/netDataChunk.cpp 2006-11-18 21:03:56 UTC (rev 1495) @@ -0,0 +1,85 @@ +#include <yake/net/pch.h> +#include <yake/net/netCommon.h> + +namespace yake { +namespace net { + + DataChunk::DataChunk(const void* data, const size_t len) : buf_(0), bufSize_(0), dataSize_(0) + { + if (data && len) + this->reset( data, len ); + } + DataChunk::~DataChunk() + { + this->clear(); + } + const void* DataChunk::data() const + { + return buf_; + } + void* DataChunk::data() + { + return buf_; + } + size_t DataChunk::size() const + { + return dataSize_; + } + size_t DataChunk::capacity() const + { + return bufSize_; + } + void DataChunk::reset(const void* dataPtr, const size_t dataSize) + { + this->resize(dataSize,kThrowAwayData); + if (dataSize_) + { + assert( dataSize_ == dataSize ); + assert( bufSize_ >= dataSize ); + memcpy( buf_, dataPtr, dataSize_ ); + } + } + void DataChunk::resize(size_t newDataSize, ResizeMode keepData) + { + if (newDataSize <= bufSize_) + { + dataSize_ = newDataSize; + return; + } + if (keepData == kThrowAwayData || !buf_) + { + if (buf_) + delete [] buf_; + buf_ = new byte[newDataSize]; + bufSize_ = newDataSize; + dataSize_ = newDataSize; + return; + } + else if (keepData == kKeepData) + { + byte_ptr newBuf = new byte[newDataSize]; + assert( buf_ ); + memcpy( newBuf, buf_, std::min(newDataSize,dataSize_) ); + delete [] buf_; + buf_ = newBuf; + bufSize_ = newDataSize; + dataSize_ = newDataSize; + return; + } + else + throw std::runtime_error("DataChunk::resize(): unhandled ResizeMode"); + } + void DataChunk::shrink() + { + if (buf_ && (bufSize_ > dataSize_)) + { + byte_ptr newBuf = new byte[dataSize_]; + memcpy( newBuf, buf_, dataSize_ ); + delete [] buf_; + buf_ = newBuf; + bufSize_ = dataSize_; + } + } + +} // namespace net +} // namespace yake Modified: trunk/yake/src/yake/net/detail/netEnetClientPacketConnection.cpp =================================================================== --- trunk/yake/src/yake/net/detail/netEnetClientPacketConnection.cpp 2006-11-01 15:25:54 UTC (rev 1494) +++ trunk/yake/src/yake/net/detail/netEnetClientPacketConnection.cpp 2006-11-18 21:03:56 UTC (rev 1495) @@ -4,6 +4,7 @@ #include <yake/net/detail/netInternal.h> #include <yake/net/detail/netEnetClientPacketConnection.h> +namespace yake { namespace net { IClientPacketConnection* createClientPacketConnection() { @@ -76,7 +77,7 @@ } m_address.port = addr.port(); - m_peer = enet_host_connect( m_host, &m_address, 2 /*channel count*/ ); + m_peer = enet_host_connect( m_host, &m_address, 4 /*channel count*/ ); if (!m_peer) { NET_ERROR("Could not connect to server!"); @@ -115,16 +116,18 @@ if (m_serverPeer) enet_peer_disconnect( m_serverPeer, 0 /*@todo data*/ ); - /*@todo handle graceful disconnects... + // handle graceful disconnects... Timer timer; timer.start(); - while (timer.getTime() < 1) + // now wait until either disconnected or we time out. + while (m_serverPeer && timer.getTime() < 1) { net::update(); - net::native::sleep(10); + this->update(); + net::native::sleep(0); } - */ + // hard disconnect enet_peer_reset( m_peer ); enet_host_destroy( m_host ); m_host = 0; @@ -170,7 +173,7 @@ m_serverIp = ipToString( host ); const uint8 tmp = 0x7F; - this->send(&tmp,1,SendOptions().reliability(R_RELIABLE)); + this->send(PacketPtr(new Packet(&tmp,1)),SendOptions().reliability(R_RELIABLE)); } break; case ENET_EVENT_TYPE_RECEIVE: @@ -186,7 +189,8 @@ } else if (event.packet) { - this->fireCallback_PacketReceived(0,event.packet->data,event.packet->dataLength,ChannelId(event.channelID)); + this->fireCallback_PacketReceived( + 0,PacketPtr(new Packet(event.packet->data,event.packet->dataLength)),ChannelId(event.channelID)); } { //boost::mutex::scoped_lock enetLock(getEnetMtx()); @@ -203,18 +207,38 @@ break; }; } + // Send queued packets: + this->sendOutgoingPacketQ(); } - void EnetClientPacketConnection::send( const void* dataPtr, const size_t dataSize, const net::SendOptions& opt ) + void EnetClientPacketConnection::sendOutgoingPacketQ() { - this->sendBroadcast( dataPtr, dataSize, opt.getReliability(), opt.getOrdering(), opt.getChannel() ); + for (OutgoingPacketQ::const_iterator it = m_outgoingPacketQ.begin(); it != m_outgoingPacketQ.end(); ++it) + { + const SendOptions& opt = it->opt_; + const PacketPtr& pckt = it->pckt_; + YAKE_ASSERT( pckt.get() ); + this->sendBroadcast( pckt->payload().data(), pckt->payload().size(), + opt.getReliability(), opt.getOrdering(), opt.getChannel() ); + } + m_outgoingPacketQ.clear(); } - void EnetClientPacketConnection::send(const PeerId, const void* dataPtr, const size_t dataSize, const SendOptions& opt ) + void EnetClientPacketConnection::send( const PacketPtr& pckt, const SendOptions& opt ) { - this->sendBroadcast( dataPtr, dataSize, opt.getReliability(), opt.getOrdering(), opt.getChannel() ); + YAKE_ASSERT( pckt ); + if (!pckt) + return; + OutgoingPacket pcktEntry; + pcktEntry.opt_ = opt; + pcktEntry.pckt_ = pckt; + m_outgoingPacketQ.push_back( pcktEntry ); } + void EnetClientPacketConnection::send(const PeerId, const PacketPtr& pckt, const SendOptions& opt ) + { + this->send( pckt, opt ); + } void EnetClientPacketConnection::sendTo(const PeerId clientId, const void* dataPtr, const size_t dataSize, const Reliability rel, const Ordering ord, const ChannelId channel) { - sendBroadcast(dataPtr,dataSize,rel,ord,channel); + this->sendBroadcast(dataPtr,dataSize,rel,ord,channel); } void EnetClientPacketConnection::sendBroadcast(const void* dataPtr, const size_t dataSize, const Reliability rel, const Ordering, const ChannelId channel) { @@ -237,3 +261,4 @@ } // namespace impl } // namespace net +} // namespace yake Modified: trunk/yake/src/yake/net/detail/netEnetServerPacketConnection.cpp =================================================================== --- trunk/yake/src/yake/net/detail/netEnetServerPacketConnection.cpp 2006-11-01 15:25:54 UTC (rev 1494) +++ trunk/yake/src/yake/net/detail/netEnetServerPacketConnection.cpp 2006-11-18 21:03:56 UTC (rev 1495) @@ -4,6 +4,7 @@ #include <yake/net/detail/netInternal.h> #include <yake/net/detail/netEnetServerPacketConnection.h> +namespace yake { namespace net { IServerPacketConnection* createServerPacketConnection() { @@ -122,21 +123,35 @@ NET_ASSERT( m_host ); if (m_host) { - if (m_host->peerCount > 0) + if (!m_clients.empty()) { + for (PeerToClientMap::iterator itClient = m_clients.begin(); + itClient != m_clients.end(); ++itClient) + { + if (itClient->second->state != CS_DEAD && + itClient->second->state != CS_CONNECTED) + { + itClient->second->state = CS_DISCONNECTING; + } + } + // try to gracefully disconnect clients for (size_t i=0; i<m_host->peerCount; ++i) + { enet_peer_disconnect( &m_host->peers[i], 0 /*@todo data*/ ); + } - /** @todo handle graceful disconnects... + // handle graceful disconnects... Timer timer; timer.start(); - while (timer.getTime() < 2) // wait 2 seconds for acknowledgement + // wait max 2 seconds for disconnect acknowledgement from client. + // or stop waiting when client count reaches 0. + while (!m_clients.empty() && timer.getTime() < 2) { net::update(); - net::native::sleep(10); + this->update(); + net::native::sleep(0); } - */ // forcefully disconnect remaining clients if (m_host->peerCount > 0) @@ -173,6 +188,7 @@ return; // set client state itFindClient->second->state = CS_DISCONNECTING; + itFindClient->second->timeLeft_ = 2.; // 2 seconds for graceful disconnect // disconnect enet client { //boost::mutex::scoped_lock enetLock(getEnetMtx()); @@ -300,13 +316,14 @@ } const uint8 tmp = 0x7F; - this->send(peerId,&tmp,1,SendOptions().reliability(R_RELIABLE)); + this->send(peerId,PacketPtr(new Packet(&tmp,1)),SendOptions().reliability(R_RELIABLE)); } break; case ENET_EVENT_TYPE_RECEIVE: NET_ASSERT( event.packet ); NET_ASSERT( event.peer ); - NET_ASSERT( event.peer->data ); + //NET_ASSERT( event.peer->data ); + if (event.peer->data) { const ClientState cs = getClientState( event.peer ); if (cs == CS_CONNECTING) @@ -335,7 +352,9 @@ peerId = (reinterpret_cast<Client*>(event.peer->data))->id; } - fireCallback_PacketReceived(peerId,event.packet->data,event.packet->dataLength,event.channelID); + // This copies the packet data, at the moment. @todo optimize copy away + fireCallback_PacketReceived(peerId, + PacketPtr(new Packet(event.packet->data,event.packet->dataLength)),event.channelID); } { // destroy enet packet @@ -374,21 +393,49 @@ break; }; } + // Send any queued packets. + this->sendOutgoingPacketQ(); } - void EnetServerPacketConnection::send( const void* dataPtr, const size_t dataSize, const net::SendOptions& opt ) + void EnetServerPacketConnection::sendOutgoingPacketQ() { - const PeerId peerId = opt.getPeerId(); - if (peerId != PEERID_BROADCAST) - this->sendTo( peerId, dataPtr, dataSize, opt.getReliability(), opt.getOrdering(), opt.getChannel() ); - else - this->sendBroadcast( dataPtr, dataSize, opt.getReliability(), opt.getOrdering(), opt.getChannel() ); + for (OutgoingPacketQ::const_iterator it = m_outgoingPacketQ.begin(); it != m_outgoingPacketQ.end(); ++it) + //YAKE_FOR_EACH(OutgoingPacketQ::const_iterator,it,m_outgoingPacketQ) + { + const SendOptions& opt = it->opt_; + const PacketPtr& pckt = it->pckt_; + YAKE_ASSERT( pckt.get() ); + if (it->target_ == PEERID_BROADCAST) + this->sendBroadcast( pckt->payload().data(), pckt->payload().size(), + opt.getReliability(), opt.getOrdering(), opt.getChannel() ); + else + this->sendTo( it->target_, pckt->payload().data(), pckt->payload().size(), + opt.getReliability(), opt.getOrdering(), opt.getChannel() ); + } + m_outgoingPacketQ.clear(); } - void EnetServerPacketConnection::send(const PeerId peerId, const void* dataPtr, const size_t dataSize, const SendOptions& opt ) + void EnetServerPacketConnection::send( const PacketPtr& pckt, const SendOptions& opt ) { - SendOptions options = opt; - options.peerId( peerId ); - send( dataPtr, dataSize, options ); + YAKE_ASSERT( pckt ); + if (!pckt) + return; + OutgoingPacket pcktEntry; + pcktEntry.opt_ = opt; + pcktEntry.pckt_ = pckt; + pcktEntry.target_ = opt.getPeerId(); + m_outgoingPacketQ.push_back( pcktEntry ); } + void EnetServerPacketConnection::send(const PeerId peerId, const PacketPtr& pckt, const SendOptions& opt ) + { + YAKE_ASSERT( pckt ); + if (!pckt) + return; + OutgoingPacket pcktEntry; + pcktEntry.opt_ = opt; + pcktEntry.opt_.peerId( peerId ); + pcktEntry.pckt_ = pckt; + pcktEntry.target_ = opt.getPeerId(); + m_outgoingPacketQ.push_back( pcktEntry ); + } void EnetServerPacketConnection::sendTo(const PeerId clientId, const void* dataPtr, const size_t dataSize, const Reliability rel, const Ordering, const ChannelId channel) { NET_ASSERT( dataSize > 0 ); @@ -406,8 +453,9 @@ // send //boost::mutex::scoped_lock clientsLock(m_clientsMtx); IdToClientMap::const_iterator it = m_id2client.find( clientId ); - NET_ASSERT( it != m_id2client.end() ); - enet_peer_send( it->second->peer, channel, packet ); + NET_ASSERT( it != m_id2client.end() )( clientId ).warning("unknown client id"); + if (it != m_id2client.end()) + enet_peer_send( it->second->peer, channel, packet ); } } void EnetServerPacketConnection::sendBroadcast(const void* dataPtr, const size_t dataSize, const Reliability rel, const Ordering, const ChannelId channel) @@ -430,3 +478,4 @@ } // namespace impl } // namespace net +} // namespace yake Modified: trunk/yake/src/yake/net/detail/netEventConnection.cpp =================================================================== --- trunk/yake/src/yake/net/detail/netEventConnection.cpp 2006-11-01 15:25:54 UTC (rev 1494) +++ trunk/yake/src/yake/net/detail/netEventConnection.cpp 2006-11-18 21:03:56 UTC (rev 1495) @@ -5,6 +5,7 @@ #include <yake/net/detail/netInternal.h> #include <yake/net/detail/netEventConnection.h> +namespace yake { namespace net { const NetEvent::id_type NetEvent::EVTID_NONE = 0xff; NetEvent::NetEvent(const id_type id) : id_(id) @@ -97,7 +98,7 @@ } if (conn_) { - conn_->addPacketReceivedCallback( boost::bind(&EventConnection::onReceivePacket,this,_1,_2,_3,_4) ); + conn_->addPacketReceivedCallback( boost::bind(&EventConnection::onReceivePacket,this,_1,_2,_3) ); started_ = true; } return started_; @@ -152,10 +153,18 @@ out.flush(); NET_LOG("EvtConn: sending " << int(data.size()) << " bytes to '" << int(opt.getPeerId()) << "'."); - conn_->send( &data.front(), data.size(), opt ); + conn_->send( PacketPtr(new Packet(&data.front(), data.size() )), opt ); //@todo optimize copy out! } - void EventConnection::onReceivePacket(const PeerId peerId, const void* dataPtr, const size_t dataLen, const ChannelId channel) + void EventConnection::onReceivePacket(const PeerId peerId, const PacketPtr& pckt, const ChannelId channel) { + NET_ASSERT( pckt ); + if (!pckt) + { + NET_LOG("EvtConn: handling invalid packet object from '" << int(peerId) << "'."); + return; + } + const void* dataPtr = pckt->payload().data(); + const size_t dataLen = pckt->payload().size(); NET_LOG("EvtConn: received " << int(dataLen) << " bytes from '" << int(peerId) << "'."); NET_ASSERT( dataPtr && dataLen > 0 ); NET_ASSERT( dataLen >= sizeof(event_id) ); @@ -275,7 +284,9 @@ if (!processEventFn_.empty()) processEventFn_( it->peerId_, *it->evt_, it->channel_ ); it->fnDestroy_( it->evt_ ); + ++stats_.numEventsProcessed; } } } // namespace impl } // namespace net +} // namespace yake Modified: trunk/yake/src/yake/net/detail/netInternal.cpp =================================================================== --- trunk/yake/src/yake/net/detail/netInternal.cpp 2006-11-01 15:25:54 UTC (rev 1494) +++ trunk/yake/src/yake/net/detail/netInternal.cpp 2006-11-18 21:03:56 UTC (rev 1495) @@ -2,9 +2,13 @@ #include <yake/net/net.h> #include <yake/net/detail/netInternal.h> +#include <boost/thread/mutex.hpp> +namespace yake { namespace net { void update() { + static boost::mutex s_mtx; + boost::mutex::scoped_lock lck(s_mtx); impl::UpdateThread::instance().__update__(); } namespace impl { @@ -121,3 +125,4 @@ } // namespace impl } // namespace net +} // namespace yake Added: trunk/yake/src/yake/net/detail/netPacket.cpp =================================================================== --- trunk/yake/src/yake/net/detail/netPacket.cpp (rev 0) +++ trunk/yake/src/yake/net/detail/netPacket.cpp 2006-11-18 21:03:56 UTC (rev 1495) @@ -0,0 +1,16 @@ +#include <yake/net/pch.h> +#include <yake/net/netCommon.h> + +namespace yake { +namespace net { + + Packet::Packet(const void* dataPtr, const size_t dataSize) : payload_(dataPtr,dataSize) + { + } + const DataChunk& Packet::payload() const + { + return payload_; + } + +} // namespace net +} // namespace yake Modified: trunk/yake/src/yake/net/net.cpp =================================================================== --- trunk/yake/src/yake/net/net.cpp 2006-11-01 15:25:54 UTC (rev 1494) +++ trunk/yake/src/yake/net/net.cpp 2006-11-18 21:03:56 UTC (rev 1495) @@ -31,6 +31,7 @@ #endif // PLATFORM_WIN32 +namespace yake { namespace net { bool initialize() @@ -50,4 +51,4 @@ } } // namespace net - +} // namespace yake Modified: trunk/yake/src/yake/samples/net/packet/demo.cpp =================================================================== --- trunk/yake/src/yake/samples/net/packet/demo.cpp 2006-11-01 15:25:54 UTC (rev 1494) +++ trunk/yake/src/yake/samples/net/packet/demo.cpp 2006-11-18 21:03:56 UTC (rev 1495) @@ -92,13 +92,13 @@ YAKE_ASSERT( conn_ ); YAKE_ASSERT( started_ ); std::string hello("hello!"); - conn_->send( hello.c_str(), hello.size(), net::SendOptions().reliability(net::R_RELIABLE) ); + conn_->send( hello.c_str(), hello.size(), net::SendOptions().reliable() ); COUTLN("server:broadcastHello() " << conn_->getNumConnectedClients() << " client(s)"); } void client_onPacketReceived(const net::PeerId peerId, const void* data, const size_t len, const net::ChannelId channel) { - COUTLN(" client " << peerId << " packet(size=" << len << ") on channel " << channel << "\n"); + COUTLN(" client " << peerId << " packet(size=" << len << ") on channel " << int(channel) << "\n"); } int main(int argc, char* argv[]) Modified: trunk/yake/src/yake/samples/net/roclient/ROClient.cpp =================================================================== --- trunk/yake/src/yake/samples/net/roclient/ROClient.cpp 2006-11-01 15:25:54 UTC (rev 1494) +++ trunk/yake/src/yake/samples/net/roclient/ROClient.cpp 2006-11-18 21:03:56 UTC (rev 1495) @@ -1,29 +1,32 @@ -#include <yake/samples/net/roclient/pch.h> +#include <yake/samples/net/roinprocess/pch.h> #include <yake/base/yake.h> +#include <yake/object/yakeObjects.h> +#include <yake/ent/ent.h> #include <yake/net/net.h> #include <yake/samples/net/common/common.h> #include <yake/samples/net/common/commonEvents.h> #include <yake/samples/net/roclient/ROClient.h> +namespace yake { namespace ro { - client::client() : - timedOut_(false), running_(false), stage_(CS_JOINING) + client::client(const net::Address& serverAddr) : + timedOut_(false), stage_(CS_JOINING), objMgr_(0), serverAddr_(serverAddr), packetConnStarted_(false) { } client::~client() { stop(); } - bool client::running() const + void client::setObjectManager(ent::ObjectManager* objMgr) { - boost::mutex::scoped_lock lck(runningMtx_); - return running_; + objMgr_ = objMgr; } - bool client::start(const net::Address& serverAddr) + bool client::onStart() { try { // create connection & register callbacks + packetConnStarted_ = false; conn_.reset( net::createClientPacketConnection() ); assert( conn_ ); @@ -31,8 +34,15 @@ conn_->addStartedCallback( boost::bind(&client::onClientStarted,this) ); // attempt to connect to server - conn_->connect( serverAddr ); + /* + conn_->connect( serverAddr_, true, 2000 ); + */ + conn_->connect( serverAddr_ ); + this->waitForStart(); + if (timedOut_.getCopy()) + return false; + return true; } catch (const net::Exception& e) @@ -44,9 +54,9 @@ } void client::waitForStart() { - while (!timedOut_.getCopy() && !running()) + while (!timedOut_.getCopy() && !packetConnStarted_) { - net::native::sleep(10); + net::native::sleep(0); net::update(); } if (timedOut_.getCopy()) @@ -64,9 +74,11 @@ evtConn_->registerEvent( s2cEvtJoinReqReply::ID, net::NetEvent::DIR_ANY, s2cEvtJoinReqReply::create, s2cEvtJoinReqReply::destroy ); evtConn_->registerEvent( s2cEvtClassTable::ID, net::NetEvent::DIR_ANY, - s2cEvtClassTable::create, s2cEvtClassTable::destroy ); + s2cEvtClassTable::create, s2cEvtClassTable::destroy ); + evtConn_->registerEvent( s2cEvtCreateObject::ID, net::NetEvent::DIR_ANY, + s2cEvtCreateObject::create, s2cEvtCreateObject::destroy ); - evtConn_->setProcessEventCallback( boost::bind(&client::init_onProcessEvent,this,_1,_2,_3) ); + evtConn_->setProcessEventCallback( boost::bind(&client::onProcessEvent,this,_1,_2,_3) ); evtConn_->setPacketConnection( conn_.get(), net::NetEvent::DIR_ANY ); evtConn_->start(); @@ -86,30 +98,32 @@ evt.setId( 23 ); // invalid id! evtConn_->sendEvent( evt, net::SendOptions().channel(CHANNELID_CONTROL) ); + + currEvtProcessFn_ = boost::bind(&client::init_onProcessEvent,this,_1,_2,_3); + /* while (stage_ == CS_JOINING) { evtConn_->poll(); net::update(); net::native::sleep(0); } + */ } void client::step() { if (!running()) return; - evtConn_->poll(); + assert( evtConn_.get() ); + if (evtConn_.get()) + evtConn_->poll(); if (stage_ == CS_RUNNING) { } } - void client::stop() + void client::onStop() { - { - boost::mutex::scoped_lock lck(runningMtx_); - running_ = false; - } // clean up if (evtConn_) { @@ -120,16 +134,13 @@ { conn_->disconnect(); conn_.reset(); + packetConnStarted_ = false; } } void client::onClientStarted() { COUTLN("client started."); - - { - boost::mutex::scoped_lock lck(runningMtx_); - running_ = true; - } + packetConnStarted_ = true; } void client::onTimeOut() { @@ -145,8 +156,68 @@ COUTLN("client (running) received event (" << (int)evt.id() << ")."); if (evt.id() == s2cEvtClassTable::ID) { - COUTLN("starting sim " << evt.id()); + COUTLN("client: starting sim " << int(evt.id())); + const s2cEvtClassTable& reply = static_cast<const s2cEvtClassTable&>( evt ); + COUTLN(" " << int(reply.globalClassIds_.size()) << " class(es)"); + for (std::map<std::string,ent::ClassId>::const_iterator it = reply.globalClassIds_.begin(); + it != reply.globalClassIds_.end(); ++it) + { + const std::string& clsName = it->first; + const ent::ClassId globalClsId = it->second; + COUTLN(" ['" << clsName << "'] = " << int(globalClsId)); + if (!objMgr_) + { + COUTLN(" -> no object manager"); + } + else + { + ent::ObjectManager::ClassIdLookupResult ret = objMgr_->getClassId( clsName ); + if (ret.first) + { + const ent::ClassId localClsId = ret.second; + if (localClsId != it->second) + { + if (objMgr_->registerClassAlias( globalClsId, localClsId )) + { + COUTLN(" -> successfully registered alias"); + } + else + { + COUTLN(" -> failed to register alias"); + } + } + else + { + COUTLN(" -> no need to register an alias (global id = local id; and names match)"); + } + } + else + { + COUTLN(" -> class with this name not registered locally!"); + } + } + } } + else if (evt.id() == s2cEvtCreateObject::ID) + { + COUTLN("client: creating object"); + const s2cEvtCreateObject& reply = static_cast<const s2cEvtCreateObject&>( evt ); + COUTLN(" object class='" << int(reply.objId_.classId()) << "' serNo='" << int(reply.objId_.serialNo()) << "'"); + if (objMgr_) + { + ent::Object* o = objMgr_->makeObject( reply.objId_ ); + if (o) + { + COUTLN(" successfully created! (class='" << o->isA()->name() << "')"); + objMgr_->destroyObject( o ); + } + else + COUTLN(" failed to create!"); + } + } + //else if (evt.id() == s2cUpdateObject::ID) + { + } } void client::init_onProcessEvent(const net::PeerId, const net::NetEvent& evt, const net::ChannelId) { @@ -158,18 +229,26 @@ const s2cEvtJoinReqReply& reply = static_cast<const s2cEvtJoinReqReply&>( evt ); if (reply.accepted) { - COUTLN("CONNECTED TO SERVER."); + COUTLN("client: CONNECTED TO SERVER."); stage_ = CS_RUNNING; + currEvtProcessFn_ = boost::bind(&client::running_onProcessEvent,this,_1,_2,_3); } else { - COUTLN("SERVER DENIED ACCESS!"); + COUTLN("client: SERVER DENIED ACCESS!"); stage_ = CS_DEAD; - evtConn_->setProcessEventCallback( boost::bind(&client::init_onProcessEvent,this,_1,_2,_3) ); + currEvtProcessFn_ = boost::bind(&client::init_onProcessEvent,this,_1,_2,_3); } } } } + void client::onProcessEvent(const net::PeerId pId, const net::NetEvent& evt, const net::ChannelId cId) + { + COUTLN("client (dispatcher) received event (" << (int)evt.id() << ")."); + if (!currEvtProcessFn_.empty()) + currEvtProcessFn_(pId,evt,cId); + this->dispatchNetEvent(pId,evt,cId); + } } // namespace ro - +} // namespace yake Added: trunk/yake/src/yake/samples/net/roinprocess/pch.cpp =================================================================== --- trunk/yake/src/yake/samples/net/roinprocess/pch.cpp (rev 0) +++ trunk/yake/src/yake/samples/net/roinprocess/pch.cpp 2006-11-18 21:03:56 UTC (rev 1495) @@ -0,0 +1 @@ +#include <yake/samples/net/roinprocess/pch.h> Modified: trunk/yake/src/yake/samples/net/roserver/ROServer.cpp =================================================================== --- trunk/yake/src/yake/samples/net/roserver/ROServer.cpp 2006-11-01 15:25:54 UTC (rev 1494) +++ trunk/yake/src/yake/samples/net/roserver/ROServer.cpp 2006-11-18 21:03:56 UTC (rev 1495) @@ -1,15 +1,201 @@ -#include <yake/samples/net/roserver/pch.h> +#include <yake/samples/net/roinprocess/pch.h> +#include <yake/object/yakeObjects.h> +#include <yake/ent/ent.h> #include <yake/net/net.h> #include <yake/samples/net/common/common.h> #include <yake/samples/net/common/commonEvents.h> #include <yake/samples/net/roserver/ROServer.h> +namespace yake { namespace ro { //----------------------------------------------------------------------------- + IServiceHost::IServiceHost() : running_(false) + { + } + bool IServiceHost::running() const + { + boost::mutex::scoped_lock lck(runningMtx_); + return running_; + } + bool IServiceHost::start() + { + bool succ = this->onStart(); + if (!succ) + return false; + + { + boost::mutex::scoped_lock lck(runningMtx_); + running_ = true; + } + + // start services + YAKE_FOR_EACH(detail::ServiceManager::const_service_iterator,it,serviceMgr_) + { + (*it)->onStart(*this); + } + + return true; + } + void IServiceHost::stop() + { + { + boost::mutex::scoped_lock lck(runningMtx_); + running_ = false; + } + + // stop services + YAKE_FOR_EACH(detail::ServiceManager::const_service_iterator,it,serviceMgr_) + { + (*it)->onStop(*this); + } + + // stop the rest + this->onStop(); + } + void IServiceHost::addService(IServicePtr service, const std::string& tag) + { + serviceMgr_.addService( service, tag ); + if (this->running()) + service->onStart(*this); + } + void IServiceHost::removeAllServices() + { + serviceMgr_.removeAllServices(); + } + IServicePtr IServiceHost::removeService(const std::string & tag) + { + IServicePtr service = serviceMgr_.removeService( tag ); + if (service && this->running()) + service->onStop(*this); + return service; + } + IServicePtr IServiceHost::removeService(IServicePtr service) + { + serviceMgr_.removeService( service ); + if (service && this->running()) + service->onStop(*this); + return service; + } + IServicePtr IServiceHost::getService(const std::string& tag) const + { + return serviceMgr_.getService( tag ); + } + void IServiceHost::dispatchNetEvent(const net::PeerId pId, const net::NetEvent& evt, const net::ChannelId cId) + { + // find catch-all for this channel (ignore event id) + { + SigMap::const_iterator it = sigMap_.find( ChannelEventIdPair(cId,net::NetEvent::EVTID_NONE) ); + if (it != sigMap_.end()) + (*it->second)(pId,evt,cId); + } + + // find signal for this channel and event id: + SigMap::const_iterator it = sigMap_.find( ChannelEventIdPair(cId,evt.id()) ); + if (it == sigMap_.end()) + return; + (*it->second)(pId,evt,cId); + } + SignalConnection IServiceHost::subscribeToNetEvent( + const net::NetEvent::id_type eId, const net::ChannelId cId, const EvtProcessEventFn& fn) + { + const ChannelEventIdPair idPair(cId,eId); + + SigMap::iterator it = sigMap_.find( idPair ); + if (it == sigMap_.end()) + { + ProcessEventSigPtr sig( new ProcessEventSig() ); + sigMap_[ idPair ] = sig; + return sig->connect( fn ); + } + return it->second->connect(fn); + } + SignalConnection IServiceHost::subscribeToNetEventChannel( + const net::ChannelId cId, const EvtProcessEventFn& fn) + { + const ChannelEventIdPair idPair(cId,net::NetEvent::EVTID_NONE); + + SigMap::iterator it = sigMap_.find( idPair ); + if (it == sigMap_.end()) + { + ProcessEventSigPtr sig( new ProcessEventSig() ); + sigMap_[ idPair ] = sig; + return sig->connect( fn ); + } + return it->second->connect(fn); + } + + //----------------------------------------------------------------------------- + namespace detail { + + void ServiceManager::addService(IServicePtr service, const std::string& tag) + { + YAKE_ASSERT( service ); + if (!service) + return; + + services_.insert( service ); + if (!tag.empty()) + { + YAKE_ASSERT( tag2service_.find(tag) == tag2service_.end() ).debug("duplicate tag!"); + tag2service_[ tag ] = service; + } + } + IServicePtr ServiceManager::getService(const std::string& tag) const + { + TagMap::const_iterator itFind = tag2service_.find(tag); + return (itFind == tag2service_.end() ? IServicePtr() : itFind->second); + } + IServicePtr ServiceManager::removeService(const std::string& tag) + { + TagMap::iterator itFind = tag2service_.find(tag); + if (itFind == tag2service_.end()) + return IServicePtr(); + IServicePtr service = itFind->second; + tag2service_.erase( itFind ); + services_.erase( service ); + return service; + } + IServicePtr ServiceManager::removeService(const IServicePtr service) + { + YAKE_FOR_EACH(TagMap::iterator,itFind,tag2service_) + { + if (itFind->second == service) + { + tag2service_.erase( itFind ); + break; + } + } + services_.erase( service ); + return service; + } + void ServiceManager::removeAllServices() + { + tag2service_.clear(); + services_.clear(); + } + ServiceManager::const_service_iterator ServiceManager::begin() const + { + return services_.begin(); + } + ServiceManager::const_service_iterator ServiceManager::end() const + { + return services_.end(); + } + + } // namespace detail + //----------------------------------------------------------------------------- namespace server_impl { - class client + class client : public server::iclient { public: + + virtual void sendEvent(const net::NetEvent& evt, + const net::SendOptions& opt = net::SendOptions().channel(CHANNELID_CONTROL)) + { + YAKE_ASSERT( evtConn ); + evtConn->sendEvent( evt, opt ); + } + enum stage_t { CS_WAIT_FOR_REQ = 1, // waiting for "req join" @@ -22,15 +208,24 @@ AM_REGULAR, AM_SPECTATOR }; - net::PeerId id; - stage_t stage; - access_mode_t accessMode; - net::INetEventConnection* evtConn; + net::PeerId id; + stage_t stage; + access_mode_t accessMode; + SharedPtr<net::INetEventConnection> evtConn; + server& svr; - client() : id(net::NetEvent::EVTID_NONE), stage(CS_DEAD), accessMode(AM_REGULAR), evtConn(0) + client(server& svrObj) : + id(net::NetEvent::EVTID_NONE), + stage(CS_DEAD), + accessMode(AM_REGULAR), + svr(svrObj) { processEventFn_ = boost::bind(&client::init_onProcessEvent,this,_1,_2); } + virtual net::PeerId getPeerId() const + { + return this->id; + } void onProcessEvent(const net::NetEvent& evt, const net::ChannelId channel) { YAKE_ASSERT( !processEventFn_.empty() ); @@ -48,58 +243,86 @@ //----------------------------------------------------------------------------- - server::server() : conn_(0), running_(false), evtConn_(0) + server::server() : packetConnStarted_(false) { } server::~server() { stop(); } - bool server::start() + /* + void server::queueEvent(const net::PeerId id, net::NetEvent* evt, const net::ChannelId cId) { + SOF_ASSERT( evt ); + if (!evt) + return; + outEvtQ_.push_back( EventQEntry(id,evt,cId) ); + } + */ + SignalConnection server::subscribeToClientSimulationStarted(const ClientSimulationStartedSignal::slot_type& slot) + { + return sigClientSimulationStarted_.connect(slot); + } + SignalConnection server::subscribeToClientDisconnected(const ClientDisconnectedSignal::slot_type& slot) + { + return sigClientDisconnected_.connect(slot); + } + const s2cEvtClassTable& server::getClassTableMessage() const + { + return evtClassTbl_; + } + void server::onClientSimStarted(iclient&c) + { + sigClientSimulationStarted_(c); + } + void server::setClassTableMessage(const s2cEvtClassTable& msg) + { + msg.copyTo( evtClassTbl_ ); + } + bool server::onStart() + { if (conn_) return true; - const net::uint16 port = 40000; + const uint16 port = 40000; const size_t maxClients = 32; - conn_ = net::createServerPacketConnection(); + conn_.reset( net::createServerPacketConnection() ); YAKE_ASSERT( conn_ ); conn_->addStartedCallback( boost::bind(&server::onServerStarted,this) ); - conn_->addPacketReceivedCallback( boost::bind(&server::onReceivePacket,this,_1,_2,_3,_4) ); + conn_->addPacketReceivedCallback( boost::bind(&server::onReceivePacket,this,_1,_2,_3) ); + conn_->addClientDisconnectedCallback( boost::bind(&server::onClientDisconnected,this,_1) ); COUTLN("starting server at port " << port << " with max. " << maxClients << " clients..."); conn_->start( net::Address(port), maxClients ); - while (!running()) + // wait until net object is up + while (!packetConnStarted_) { //conn_->update(); ->@todo net::update(); - net::native::sleep(10); + net::native::sleep(0); } - return true; } - void server::stop() + void server::onStop() { + // shutdown net resources + if (evtConn_) { - boost::mutex::scoped_lock lck(runningMtx_); - running_ = false; + evtConn_->stop(); + evtConn_.reset(); } - clients_.clear(); if (conn_) { conn_->stop(); - delete conn_; - conn_ = 0; + conn_.reset(); + packetConnStarted_ = false; } - if (evtConn_) - { - evtConn_->stop(); - delete evtConn_; - evtConn_ = 0; - } + + // disconnect/destroy remaining clients + clients_.clear(); } void server::step() { @@ -108,21 +331,12 @@ if (evtConn_) evtConn_->poll(); } - bool server::running() const - { - boost::mutex::scoped_lock lck(runningMtx_); - return running_; - } void server::onServerStarted() { - COUTLN("server started."); - { - boost::mutex::scoped_lock lck(runningMtx_); - running_ = true; - } + COUTLN("server packet connection started."); COUTLN("server: starting event connection..."); YAKE_ASSERT( !evtConn_ ); - evtConn_ = net::createEventConnection(); + evtConn_.reset( net::createEventConnection() ); YAKE_ASSERT( evtConn_ ); evtConn_->setPolling(true); @@ -131,14 +345,17 @@ evtConn_->registerEvent( s2cEvtJoinReqReply::ID, net::NetEvent::DIR_ANY, s2cEvtJoinReqReply::create, s2cEvtJoinReqReply::destroy ); evtConn_->registerEvent( s2cEvtClassTable::ID, net::NetEvent::DIR_ANY, s2cEvtClassTable::create, s2cEvtClassTable::destroy ); evtConn_->registerEvent( c2sEvtSimOk::ID, net::NetEvent::DIR_ANY, c2sEvtSimOk::create, c2sEvtSimOk::destroy ); + evtConn_->registerEvent( s2cEvtCreateObject::ID, net::NetEvent::DIR_ANY, s2cEvtCreateObject::create, s2cEvtCreateObject::destroy ); evtConn_->setProcessEventCallback( boost::bind(&server::onProcessEvent,this,_1,_2,_3) ); - evtConn_->setPacketConnection( conn_, net::NetEvent::DIR_ANY ); + evtConn_->setPacketConnection( conn_.get(), net::NetEvent::DIR_ANY ); evtConn_->start(); COUTLN("server: event connection started."); + + packetConnStarted_ = true; } - void server::onReceivePacket(const net::PeerId peerId, const void* data, const size_t len, const net::ChannelId channel) + void server::onReceivePacket(const net::PeerId peerId, const net::PacketPtr&, const net::ChannelId channel) { COUTLN("server received packet."); //echoing... @@ -149,7 +366,7 @@ try { COUTLN("server received event (" << (int)evt.id() << ")."); - // Let client object handle the event. If no client object exists + // 1. Let client object handle the event. If no client object exists // for this peer, create it. // get client object @@ -157,7 +374,7 @@ ClientPtrMap::iterator it = clients_.find( peerId ); if (it == clients_.end()) { - c.reset( new Client() ); + c.reset( new Client(*this) ); c->id = peerId; c->stage = Client::CS_WAIT_FOR_REQ; c->evtConn = evtConn_; @@ -168,12 +385,25 @@ // handle event c->onProcessEvent( evt, channel ); + + // 2. Let services handle event + this->dispatchNetEvent( peerId, evt, channel ); } catch (...) { COUTLN("server: CAUGHT UNHANDLED EXCEPTION!\n"); } } + void server::onClientDisconnected(const net::PeerId pId) + { + COUTLN("ro::server: client '" << pId << "' disconnected."); + ClientPtrMap::iterator it = this->clients_.find( pId ); + YAKE_ASSERT(it != this->clients_.end())(pId).warning("unknown client disconnected. lookup failed."); + if (it == this->clients_.end()) + return; + this->sigClientDisconnected_( *it->second ); + this->clients_.erase( it ); + } //----------------------------------------------------------------------------- namespace server_impl { @@ -185,28 +415,29 @@ if (evt.id() == c2sEvtJoinReq::ID) { const c2sEvtJoinReq& evtJoinReq = static_cast<const c2sEvtJoinReq&>(evt); - COUTLN(" evt: Join Request"); + COUTLN("server: evt: Join Request"); // send reply: OK - COUTLN(" => accepted"); + COUTLN("server: accepted join request by client"); s2cEvtJoinReqReply joinReply; joinReply.accepted = true; - evtConn->sendEvent( this->id, joinReply, net::SendOptions().channel(CHANNELID_CONTROL) ); + evtConn->sendEvent( this->id, joinReply, net::SendOptions().channel(CHANNELID_CONTROL).ordered().reliable() ); #if NET_STRESS_TEST_LEVEL >= 1 for (size_t i=0; i<3; ++i) evtConn->sendEvent( this->id, joinReply, net::SendOptions().channel(CHANNELID_CONTROL) ); #endif - // - s2cEvtClassTable clsTbl; - clsTbl.globalClassIds_["test"] = 42; - clsTbl.globalClassIds_["player"] = 56; - evtConn->sendEvent( this->id, clsTbl, net::SendOptions().channel(CHANNELID_CONTROL) ); + // replicate class table + evtConn->sendEvent( this->id, this->svr.getClassTableMessage(), + net::SendOptions().channel(CHANNELID_CONTROL).ordered().reliable() ); // use different event callback for the CS_RUNNING stage: - COUTLN(" => RUNNING"); + COUTLN("server: => CLIENT: RUNNING"); processEventFn_ = boost::bind(&client::running_onProcessEvent,this,_1,_2); this->stage = CS_RUNNING; + + // replicate objects + this->svr.onClientSimStarted( *this ); } } void client::running_onProcessEvent(const net::NetEvent& evt, const net::ChannelId channel) @@ -215,9 +446,7 @@ YAKE_ASSERT( stage == CS_RUNNING ); if (stage != CS_RUNNING) return; - //// send class table & start sim - //s2cEvtClassTable evtClassTbl; - //evtConn->sendEvent( this->id, evtClassTbl, net::SendOptions().channel(CHANNELID_SIMCTRL) ); } } // namespace server_impl } // namespace ro +} // namespace yake Modified: trunk/yake/yake/net/detail/netEnetClientPacketConnection.h =================================================================== --- trunk/yake/yake/net/detail/netEnetClientPacketConnection.h 2006-11-01 15:25:54 UTC (rev 1494) +++ trunk/yake/yake/net/detail/netEnetClientPacketConnection.h 2006-11-18 21:03:56 UTC (rev 1495) @@ -1,11 +1,12 @@ -#ifndef NET_ENETCLIENTPACKETCONNECTION_H -#define NET_ENETCLIENTPACKETCONNECTION_H +#ifndef YAKE_NET_ENETCLIENTPACKETCONNECTION_H +#define YAKE_NET_ENETCLIENTPACKETCONNECTION_H +namespace yake { namespace net { namespace impl { //-------------------------------------------------------------------------- - class EnetClientPacketConnection : public ::net::IClientPacketConnection + class EnetClientPacketConnection : public IClientPacketConnection { public: EnetClientPacketConnection(); @@ -14,8 +15,8 @@ virtual void connect( const Address&, const bool doBlock, const uint32 timeOut ); virtual void disconnect(); - virtual void send(const void*, const size_t, const SendOptions& opt = SendOptions()); - virtual void send(const PeerId, const void*, const size_t, const SendOptions& opt = SendOptions()); + virtual void send(const PacketPtr& pckt, const SendOptions& opt = SendOptions()); + virtual void send(const PeerId, const PacketPtr& pckt, const SendOptions& opt = SendOptions()); virtual void addStartedCallback(const OnStartedFn&); virtual CallbackConnection addPacketReceivedCallback( const OnPacketReceivedFn&); @@ -40,17 +41,18 @@ for (OnStartedFnList::const_iterator it = startedFnList_.begin(); it != startedFnList_.end(); ++it) (*it)(); } - void fireCallback_PacketReceived(const PeerId peerId, const void* data, const size_t dataLen, const ChannelId channel) + void fireCallback_PacketReceived(const PeerId peerId, const PacketPtr& pckt, const ChannelId channel) { //boost::mutex::scoped_lock lck(packetReceivedFnListMtx_); for (OnPacketReceivedFnList::const_iterator it = packetReceivedFnList_.begin(); it != packetReceivedFnList_.end(); ++it) - (it->second)(peerId,data,dataLen,channel); + (it->second)(peerId,pckt,channel); } void fireCallback_TimeOut() { for (OnTimeOutFnList::const_iterator it = timeOutFnList_.begin(); it != timeOutFnList_.end(); ++it) (*it)(); } + void sendOutgoingPacketQ(); private: typedef std::deque<OnStartedFn> OnStartedFnList; typedef std::map<CallbackHandle,OnPacketReceivedFn> OnPacketReceivedFnList; @@ -71,9 +73,19 @@ bool m_waitingForConnect; std::string m_serverIp; Timer m_connTimer; + + struct OutgoingPacket + { + //PeerId target_; + PacketPtr pckt_; + SendOptions opt_; + }; + typedef std::deque<OutgoingPacket> OutgoingPacketQ; + OutgoingPacketQ m_outgoingPacketQ; }; } // namespace impl } // namespace net +} // namespace yake #endif Modified: trunk/yake/yake/net/detail/netEnetServerPacketConnection.h =================================================================== --- trunk/yake/yake/net/detail/netEnetServerPacketConnection.h 2006-11-01 15:25:54 UTC (rev 1494) +++ trunk/yake/yake/net/detail/netEnetServerPacketConnection.h 2006-11-18 21:03:56 UTC (rev 1495) @@ -1,11 +1,12 @@ -#ifndef NET_ENETSERVERPACKETCONNECTION_H -#define NET_ENETSERVERPACKETCONNECTION_H +#ifndef YAKE_NET_ENETSERVERPACKETCONNECTION_H +#define YAKE_NET_ENETSERVERPACKETCONNECTION_H +namespace yake { namespace net { namespace impl { //-------------------------------------------------------------------------- - class EnetServerPacketConnection : public ::net::IServerPacketConnection + class EnetServerPacketConnection : public IServerPacketConnection { public: EnetServerPacketConnection(); @@ -30,8 +31,8 @@ virtual void disconnect( const PeerId client ); - virtual void send(const void*, const size_t, const SendOptions& opt = SendOptions()); - virtual void send(const PeerId, const void*, const size_t, const SendOptions& opt = SendOptions()); + virtual void send(const PacketPtr&, const SendOptions& opt = SendOptions()); + virtual void send(const PeerId, const PacketPtr&, const SendOptions& opt = SendOptions()); virtual void addStartedCallback(const OnStartedFn&); virtual void addClientConnectedCallback(const OnClientConnectedFn&); @@ -55,6 +56,7 @@ size_t numMaxLiveClients_; }; private: + // send via enet void sendTo(const PeerId clientId, const void* dataPtr, const size_t dataSize, const Reliability rel, const Ordering, const ChannelId channel); void sendBroadcast(const void* dataPtr, const size_t dataSize, const Reliability rel, const Ordering, const Cha... [truncated message content] |