// Ryzom - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // 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 Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #ifndef NL_FE_SEND_SUB_H #define NL_FE_SEND_SUB_H #include "nel/misc/types_nl.h" #include #include "fe_receive_sub.h" class CPrioSub; const uint SYNCSendLatency = 100; // number of ms between sends of SYNC system message const uint PROBESendLatency = 300; // number of ms between sends of PROBE system message /** * Front-end Send Subsystem * \author Olivier Cado * \author Nevrax France * \date 2001 */ class CFeSendSub { public: /* * Buffer and address */ class CSendBuffer { public: typedef bool TSBState; /// Destination address NLNET::CInetAddress DestAddress; /// Used (connected) or not volatile TSBState SBState; /// Output buffer TOutBox OutBox; /// Default constructor CSendBuffer() : SBState(false), OutBox(false, 512) {} // prealloc 512 bytes to avoid bitmemstream reallocation /// Set the new address. state should be SBReady or SBNotReady only. void setAddress( const NLNET::CInetAddress *addr, TSBState state ) { // Copy the address (just a link would not work) DestAddress = *addr; SBState = state; } /// Enable or disable the current address void enableSendBuffer( TSBState state ) { SBState = state; } /// Send the current outbox void sendOutBox( NLNET::CUdpSock *datasock ); }; /// Vector for send buffers indexed by TClientId typedef std::vector TSendBuffers; /// Set of ids of buffers to enable in the flushing buffers before the next swapping typedef std::set TBuffersToEnable; /// Constructor CFeSendSub() : _DataSock( NULL ), _ClientIdCont(), // _UIActions(), _History( NULL ), _PrioSub( NULL ), _TotalBitBandwidth(0xFFFFFFFF), _ClientBitBandwidth(150*8), //_OutputBits(0), _SendCounter(0), _NbActions(0), _NbImpulseActions(0) {} /// Init void init( NLNET::CUdpSock *datasock, THostMap *clientmap, CHistory *history, CPrioSub *priosub ); /// Update void update(); /// Set client bandwidth per cycle in bytes void setClientBandwidth( uint32 bytes ); /// Set total bandwidth per cycle in bytes (limited to 512 MB) (currently not used!) void setTotalBandwidth( uint32 bytes ) { if ( bytes < 536870912 ) // 512 MB _TotalBitBandwidth = bytes*8; else _TotalBitBandwidth = 0xFFFFFFFF; // prevent from overflow } uint32 clientBandwidth() const { return _ClientBitBandwidth; } uint32 totalBandwidth() const { return _TotalBitBandwidth; } TClientIdCont& clientIdCont() { return _ClientIdCont; } volatile uint32 &sendCounter() { return _SendCounter; } /// Set the address for send buffer, to match a connected client void setSendBufferAddress( TClientId id, const NLNET::CInetAddress *addr ) { // We set the address for both, but we can't enable the buffer yet ((*_CurrentFillingBuffers)[id]).setAddress( addr, false /*true*/ ); ((*_CurrentFlushingBuffers)[id]).setAddress( addr, false ); //_BuffersToEnable.insert( id ); // OBSOLETE: now it is enabled/disabled in CFeSendSub::fillPrioritizedActions } /// Unset a send buffer, when a client disconnects void disableSendBuffer( TClientId id ) { // We can disable both, because no problem if the flushing thread sees the state of a buffer change to unused ((*_CurrentFillingBuffers)[id]).enableSendBuffer( false ); ((*_CurrentFlushingBuffers)[id]).enableSendBuffer( false ); // But we must remove the id for _BuffersToEnable in the case when there was // a connection and then a disconnection for the same client in the same cycle // (maybe, not necessary to manage, because unlikely to happen) //_BuffersToEnable.erase( id ); // OBSOLETE } /// Enable a send buffer, the first time when the buffer is ready to be flushed out void enableSendBuffer( TClientId id ) { // In the filling one, we enabled the buffer as soon as the client connected ((*_CurrentFlushingBuffers)[id]).enableSendBuffer( true ); } /// Access the outbox (for filling) TOutBox& outBox( TClientId id ) { return (*_CurrentFillingBuffers)[id].OutBox; } /// Call before a send cycle (even if there is no client) void prepareSendCycle() { _NbActions = 0; _NbImpulseActions = 0; } /// Setup headers for outgoing messages of current cycle (only if there are clients) void prepareHeadersAndFillImpulses(); /// Fill prioritized actions into outgoing messages (only if there are clients) void fillPrioritizedActions(); /// Swap send buffers void swapSendBuffers(); /// Send outgoing messages void flushMessages(); private: /// Socket access NLNET::CUdpSock *_DataSock; /** Client id container (insert()/erase() are done by the receive subsystem who manages the clients). * For a vector, there are as many elements as possibles clients, non-attributed elements are set to NULL. */ TClientIdCont _ClientIdCont; /// Urgent-important actions // CUrgentImportantActions _UIActions; // Client map access THostMap *_ClientMap; /// Packet History access CHistory *_History; // Priority access CPrioSub *_PrioSub; /** Max total bandwidth (bytes per update) * Warning: uint32 for bits => limitation is 512 KB ((2^32-1)/8)) * see setTotalBitBandwidth */ uint32 _TotalBitBandwidth; /// Max bandwidth per client (bytes per update) uint32 _ClientBitBandwidth; /// Number of bits stored for the current cyle //uint32 _OutputBits; /// Number of messages effectively sent (flushed) volatile uint32 _SendCounter; /// Number of actions stored for the current cycle (important + prioritized) uint32 _NbActions; /// Number of important actions stored for the current cycle uint32 _NbImpulseActions; TSendBuffers _SendBuffers1, _SendBuffers2; TSendBuffers *_CurrentFillingBuffers, *_CurrentFlushingBuffers; /// MD5 hash keys of msg.xml and database.xml NLMISC::CHashKeyMD5 _MsgXmlMD5; NLMISC::CHashKeyMD5 _DatabaseXmlMD5; //TBuffersToEnable _BuffersToEnable; // OBSOLETE }; #endif // NL_FE_SEND_SUB_H /* End of fe_send_sub.h */