diff --git a/source/gui/MiniMap.cpp b/source/gui/MiniMap.cpp index 7c05024b96..46a502daed 100644 --- a/source/gui/MiniMap.cpp +++ b/source/gui/MiniMap.cpp @@ -195,6 +195,9 @@ void CMiniMap::FireWorldClickEvent(int button, int clicks) Destination.y = CELL_SIZE * m_MapSize * ( (m_CachedActualSize.bottom - MousePos.y) / m_CachedActualSize.GetHeight() ); + UNUSED2(button); + UNUSED2(clicks); +/* g_JSGameEvents.FireWorldClick( button, clicks, @@ -205,6 +208,7 @@ void CMiniMap::FireWorldClickEvent(int button, int clicks) NULL, (int)Destination.x, (int)Destination.y); +*/ } // render view rect : John M. Mena diff --git a/source/main.cpp b/source/main.cpp index 7080d295fe..b20740213b 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -57,7 +57,6 @@ that of Atlas depending on commandline parameters. #include "ps/XML/Xeromyces.h" #include "network/NetClient.h" #include "network/NetServer.h" -//#include "network/SessionManager.h" #include "network/NetSession.h" #include "graphics/Camera.h" #include "graphics/GameView.h" @@ -258,7 +257,6 @@ static void Frame() MICROLOG(L"input"); PumpEvents(); PROFILE_END("input"); - //g_SessionManager.Poll(); PROFILE_START("network poll"); if (g_NetServer) @@ -389,11 +387,6 @@ static void RunGameOrAtlas(int argc, const char* argv[]) // might run Atlas. CXeromyces::Startup(); - // allow switching to old simulation system, before any - // other init code makes use of it - if (args.Has("sim1")) - g_UseSimulation2 = false; - // run Atlas (if requested via args) bool ran_atlas = ATLAS_RunIfOnCmdLine(args); // Atlas handles the whole init/shutdown/etc sequence by itself; diff --git a/source/network/NetClient.cpp b/source/network/NetClient.cpp index a5ea81df21..b1bb6da443 100644 --- a/source/network/NetClient.cpp +++ b/source/network/NetClient.cpp @@ -47,17 +47,6 @@ CNetClient *g_NetClient = NULL; -class CClientTurnManager : public CTurnManager -{ -public: - CClientTurnManager(CNetClient& client) : m_Client(client) { } - virtual void QueueLocalCommand(CNetMessage* pMessage); - virtual void NewTurn(); - virtual bool NewTurnReady() { return m_Client.m_TurnPending; } -private: - CNetClient& m_Client; -}; - //----------------------------------------------------------------------------- // Name: CServerPlayer() // Desc: Constructor @@ -95,19 +84,12 @@ void CServerPlayer::ScriptingInit( void ) CNetClient::CNetClient( CGame* pGame, CGameAttributes* pGameAttribs ) : m_JsPlayers( &m_Players ) { - m_TurnManager = new CClientTurnManager(*this); m_ClientTurnManager = NULL; m_pLocalPlayerSlot = NULL; m_pGame = pGame; m_pGameAttributes = pGameAttribs; - m_TurnPending = false; - //ONCE( ScriptingInit(); ); - - if (!g_UseSimulation2) - m_pGame->GetSimulation()->SetTurnManager(m_TurnManager); - g_ScriptingHost.SetGlobal("g_NetClient", OBJECT_TO_JSVAL(GetScript())); } @@ -147,14 +129,11 @@ void CNetClient::ScriptingInit() AddProperty(L"password", &CNetClient::m_Password); AddProperty(L"playerName", &CNetClient::m_Nickname); - //AddProperty(L"sessionId", &CNetClient::m_SessionID); AddProperty(L"sessions", &CNetClient::m_JsPlayers); CJSMap< PlayerMap >::ScriptingInit("NetClient_SessionMap"); CJSObject::ScriptingInit("NetClient"); - //CGameAttributes::ScriptingInit(); - //CServerPlayer::ScriptingInit(); } //----------------------------------------------------------------------------- @@ -211,18 +190,6 @@ bool CNetClient::SetupSession( CNetSession* pSession ) pSession->AddTransition( NCS_PREGAME, ( uint )NMT_GAME_START, NCS_INGAME, (void*)&OnStartGame_, pContext ); pSession->AddTransition( NCS_INGAME, ( uint )NMT_CHAT, NCS_INGAME, (void*)&OnChat, pContext ); - pSession->AddTransition( NCS_INGAME, ( uint )NMT_GOTO, NCS_INGAME, (void*)&OnInGame, pContext ); - pSession->AddTransition( NCS_INGAME, ( uint )NMT_PATROL, NCS_INGAME, (void*)&OnInGame, pContext ); - pSession->AddTransition( NCS_INGAME, ( uint )NMT_ADD_WAYPOINT, NCS_INGAME, (void*)&OnInGame, pContext ); - pSession->AddTransition( NCS_INGAME, ( uint )NMT_CONTACT_ACTION, NCS_INGAME, (void*)&OnInGame, pContext ); - pSession->AddTransition( NCS_INGAME, ( uint )NMT_PRODUCE, NCS_INGAME, (void*)&OnInGame, pContext ); - pSession->AddTransition( NCS_INGAME, ( uint )NMT_PLACE_OBJECT, NCS_INGAME, (void*)&OnInGame, pContext ); - pSession->AddTransition( NCS_INGAME, ( uint )NMT_RUN, NCS_INGAME, (void*)&OnInGame, pContext ); - pSession->AddTransition( NCS_INGAME, ( uint )NMT_SET_RALLY_POINT, NCS_INGAME, (void*)&OnInGame, pContext ); - pSession->AddTransition( NCS_INGAME, ( uint )NMT_SET_STANCE, NCS_INGAME, (void*)&OnInGame, pContext ); - pSession->AddTransition( NCS_INGAME, ( uint )NMT_NOTIFY_REQUEST, NCS_INGAME, (void*)&OnInGame, pContext ); - pSession->AddTransition( NCS_INGAME, ( uint )NMT_FORMATION_GOTO, NCS_INGAME, (void*)&OnInGame, pContext ); - pSession->AddTransition( NCS_INGAME, ( uint )NMT_FORMATION_CONTACT_ACTION, NCS_INGAME, (void*)&OnInGame, pContext ); pSession->AddTransition( NCS_INGAME, ( uint )NMT_SIMULATION_COMMAND, NCS_INGAME, (void*)&OnInGame, pContext ); pSession->AddTransition( NCS_INGAME, ( uint )NMT_END_COMMAND_BATCH, NCS_INGAME, (void*)&OnInGame, pContext ); @@ -425,15 +392,6 @@ bool CNetClient::OnPreGame( void* pContext, CFsmEvent* pEvent ) switch ( pEvent->GetType() ) { - - //CHAIN(BaseHandler); - //CHAIN(ChatHandler); - -// case NMT_GAME_START: - -// pClient->StartGame(); -// break; - case NMT_PLAYER_LEAVE: { CPlayerLeaveMessage* pMessage = ( CPlayerLeaveMessage* )pEvent->GetParamRef(); @@ -531,38 +489,13 @@ bool CNetClient::OnInGame( void *pContext, CFsmEvent* pEvent ) return true; } - if ( pMessage->GetType() >= NMT_COMMAND_FIRST && pMessage->GetType() < NMT_COMMAND_LAST ) - { - pClient->QueueIncomingMessage( pMessage ); - - return true; - } - if ( pMessage->GetType() == NMT_END_COMMAND_BATCH ) { CEndCommandBatchMessage* pMessage = ( CEndCommandBatchMessage* )pEvent->GetParamRef(); if ( !pMessage ) return false; - if (g_UseSimulation2) - { - CEndCommandBatchMessage* endMessage = static_cast (pMessage); - pClient->m_ClientTurnManager->FinishedAllCommands(endMessage->m_Turn); - } - - pClient->m_TurnManager->SetTurnLength( 1, pMessage->m_TurnLength ); - - pClient->m_TurnPending = true; - - // FIXME When the command batch has ended, we should start accepting - // commands for the next turn. This will be accomplished by calling - // NewTurn. *BUT* we shouldn't prematurely proceed game simulation - // since this will produce jerky playback (everything expects a sim - // turn to have a certain duration). - - // We should make sure that any commands received after this message - // are queued in the next batch (#2 instead of #1). If we're already - // putting everything new in batch 2 - we should fast-forward a bit to - // catch up with the server. + CEndCommandBatchMessage* endMessage = static_cast (pMessage); + pClient->m_ClientTurnManager->FinishedAllCommands(endMessage->m_Turn); } } @@ -622,11 +555,8 @@ bool CNetClient::OnStartGame_( void* pContext, CFsmEvent* pEvent ) CNetClient* pClient = ( CNetClient* )( ( FsmActionCtx* )pContext )->pHost; CNetSession* pSession = ( ( FsmActionCtx* )pContext )->pSession; - if (g_UseSimulation2) - { - pClient->m_ClientTurnManager = new CNetClientTurnManager(*pClient->m_pGame->GetSimulation2(), *pClient, pClient->GetLocalPlayer()->GetPlayerID(), pSession->GetID()); - pClient->m_pGame->SetTurnManager(pClient->m_ClientTurnManager); - } + pClient->m_ClientTurnManager = new CNetClientTurnManager(*pClient->m_pGame->GetSimulation2(), *pClient, pClient->GetLocalPlayer()->GetPlayerID(), pSession->GetID()); + pClient->m_pGame->SetTurnManager(pClient->m_ClientTurnManager); pClient->OnStartGame(); @@ -689,16 +619,6 @@ int CNetClient::StartGame( void ) if ( m_pGame->StartGame( m_pGameAttributes ) != PSRETURN_OK ) return -1; - if (!g_UseSimulation2) - { - // Send an end-of-batch message for turn 0 to signal that we're ready. - CEndCommandBatchMessage endBatch; - endBatch.m_TurnLength = 1000 / g_frequencyFilter->StableFrequency(); - - CNetSession* pSession = GetSession( 0 ); - SendMessage( pSession, &endBatch ); - } - return 0; } @@ -710,47 +630,3 @@ CPlayer* CNetClient::GetLocalPlayer() { return m_pLocalPlayerSlot->GetPlayer(); } - -//----------------------------------------------------------------------------- -// Name: NewTurn() -// Desc: -//----------------------------------------------------------------------------- -void CClientTurnManager::NewTurn() -{ - CScopeLock lock(m_Client.m_Mutex); - - RotateBatches(); - ClearBatch(2); - m_Client.m_TurnPending = false; - - //debug_printf(L"In NewTurn - sending ack\n"); - CEndCommandBatchMessage* pMsg = new CEndCommandBatchMessage; - pMsg->m_TurnLength=1000/g_frequencyFilter->StableFrequency(); // JW: it'd probably be nicer to get the FPS as a parameter - - CNetSession* pSession = m_Client.GetSession( 0 ); - m_Client.SendMessage( pSession, pMsg ); -} - -//----------------------------------------------------------------------------- -// Name: QueueLocalCommand() -// Desc: -//----------------------------------------------------------------------------- -void CClientTurnManager::QueueLocalCommand( CNetMessage* pMessage ) -{ - if ( !pMessage ) return; - - // Don't save these locally, since they'll be bounced by the server anyway - CNetSession* pSession = m_Client.GetSession( 0 ); - m_Client.SendMessage( pSession, pMessage ); -} - -//----------------------------------------------------------------------------- -// Name: QueueIncomingMessage() -// Desc: -//----------------------------------------------------------------------------- -void CNetClient::QueueIncomingMessage( CNetMessage* pMessage ) -{ - CScopeLock lock( m_Mutex ); - - m_TurnManager->QueueMessage( 2, pMessage ); -} diff --git a/source/network/NetClient.h b/source/network/NetClient.h index 224842738a..ce2e194ff4 100644 --- a/source/network/NetClient.h +++ b/source/network/NetClient.h @@ -30,7 +30,6 @@ #include "NetSession.h" #include "NetTurnManager.h" #include "ps/CStr.h" -#include "simulation/TurnManager.h" #include "simulation/ScriptObject.h" #include "scripting/ScriptableObject.h" #include "ps/scripting/JSMap.h" @@ -53,16 +52,12 @@ class CGame; class CGameAttributes; class CServerPlayer; -//typedef std::map< uint, CStr > PlayerMap; typedef std::map< uint, CServerPlayer* > PlayerMap; -/* - CLASS : CServerPlayer - DESCRIPTION : - NOTES : -*/ class CServerPlayer : public CJSObject< CServerPlayer > { + NONCOPYABLE(CServerPlayer); + public: CServerPlayer( uint sessionID, const CStr& nickname ); @@ -71,23 +66,13 @@ public: static void ScriptingInit( void ); uint GetSessionID( void ) const { return m_SessionID; } const CStr GetNickname( void ) const { return m_Nickname; } -protected: private: - CServerPlayer( const CServerPlayer& ); - CServerPlayer& operator=( const CServerPlayer& ); - uint m_SessionID; // Player session ID CStr m_Nickname; // Player nickname }; -/* - CLASS : CNetClient - DESCRIPTION : - NOTES : -*/ - class CNetClient: public CNetHost, public CJSObject { @@ -102,13 +87,6 @@ public: void OnPlayer ( uint ID, const CStr& name ); void OnPlayerLeave ( uint ID ); - /** - * Returns true indicating the host acts as a client - * - * @return Always true - */ - virtual bool IsClient( void ) const { return true; } - // Get a pointer to our player CPlayer* GetLocalPlayer(); @@ -116,20 +94,11 @@ public: CStr m_Nickname; CStr m_Password; - //int m_SessionID; CPlayerSlot *m_pLocalPlayerSlot; CGame *m_pGame; CGameAttributes *m_pGameAttributes; - // Are we currently in a locally-yet-unsimulated turn? - // This is set to true when we receive a command batch and cleared in NewTurn(). - // The server also ensures that it does not send a new turn until we ack one. - bool m_TurnPending; - - // Mutex for accessing batches - CMutex m_Mutex; - // JS event scripts CScriptObject m_OnStartGame; CScriptObject m_OnChat; @@ -141,16 +110,12 @@ public: static void ScriptingInit( void ); int StartGame( void ); - CNetTurnManager* GetTurnManager() { debug_assert(m_ClientTurnManager); return m_ClientTurnManager; } - protected: virtual bool SetupSession ( CNetSession* pSession ); virtual bool HandleConnect ( CNetSession* pSession ); virtual bool HandleDisconnect ( CNetSession *pSession ); - void QueueIncomingMessage ( CNetMessage* pMessage ); - virtual void OnConnectComplete ( void ); virtual void OnStartGame ( void ); @@ -168,10 +133,8 @@ private: bool SetupConnection( JSContext *cx, uintN argc, jsval *argv ); - //CNetSession* m_Session; // Server session PlayerMap m_Players; // List of online players - CTurnManager* m_TurnManager; CNetClientTurnManager* m_ClientTurnManager; }; diff --git a/source/network/NetMessage.cpp b/source/network/NetMessage.cpp index 259961fcc9..80edbcb769 100644 --- a/source/network/NetMessage.cpp +++ b/source/network/NetMessage.cpp @@ -25,8 +25,6 @@ // INCLUDES #include "precompiled.h" -#include "simulation/Entity.h" -#include "ps/Vector2D.h" #include "ps/CLogger.h" #include "Network.h" #include "NetMessage.h" @@ -38,9 +36,6 @@ #define ALLNETMSGS_IMPLEMENT #include "NetMessages.h" -#include -#include - // DEFINES #define LOG_CATEGORY L"net" @@ -113,45 +108,6 @@ const u8* CNetMessage::Deserialize( const u8* pStart, const u8* pEnd ) return pBuffer; } -//----------------------------------------------------------------------------- -// Name: Deserialize() -// Desc: Constructs a CNetMessage object from the specified buffer parameter -// Note: It uses the registered desrializers to create the CNetMessage object -//----------------------------------------------------------------------------- -/*CNetMessage* CNetMessage::Deserialize( - NetMessageType type, - const u8* pBuffer, - uint bufferSize ) -{ - ONCE - ( - SNetMessageDeserializer* pDeserializer = &g_DeserializerRegistrations[ 0 ]; - for ( ; pDeserializer->Deserializer; pDeserializer++ ) - { - g_DeserializerMap.insert( std::make_pair( - pDeserializer->Type, - pDeserializer->Deserializer ) ); - } - ); - - MessageDeserializerMap::const_iterator it = g_DeserializerMap.find( type ); - if ( it == g_DeserializerMap.end() ) - { - LOG(WARNING, LOG_CATEGORY, L"Unknown message received on socket: type 0x%04x, length %u", type, length); - - return NULL; - } - - pfnNetMessageDeserializer pDeserializer = it->second; - if ( pDeserializer ) - { - // Call deserializer - return ( pDeserializer )( pBuffer, bufferSize ); - } - - return NULL; -}*/ - //----------------------------------------------------------------------------- // Name: GetSerializedLength() // Desc: Returns the size of the serialized message @@ -162,42 +118,6 @@ size_t CNetMessage::GetSerializedLength( void ) const return 3; } -//----------------------------------------------------------------------------- -// Name: operator ( ENetPacket* )() -// Desc: Cast to an ENetPacket structure -//----------------------------------------------------------------------------- -/*void CNetMessage::operator ENetPacket*( void ) -{ - // Did we already serialized the message? - if ( m_Packet ) - { - // Dirty message? - if ( m_Dirty ) - { - // Make room for the new message content - enet_packet_resize( m_Packet, GetSerializedLength() ); - - // Serialize into buffer - Serialize( m_Packet->data ); - } - } - else - { - // Serialize message into temporary buffer - u8* pBuffer = new u8[ GetSerializedLength() ]; - if ( !pBuffer ) return NULL; - - Serialize( pBuffer ); - - // Create ENet packet for this message - m_Packet = enet_packet_create( pBuffer, GetSerializedLength(), ENET_PACKET_FLAG_RELIABLE ); - - delete [] pBuffer; - } - - return m_Packet; -}*/ - //----------------------------------------------------------------------------- // Name: ToString() // Desc: Returns a string representation for the message @@ -219,710 +139,6 @@ CStr CNetMessage::ToString( void ) const return ret; } -//----------------------------------------------------------------------------- -// Name: ScriptingInit() -// Desc: -//----------------------------------------------------------------------------- -void CNetMessage::ScriptingInit() -{ - g_ScriptingHost.DefineConstant( "NMT_GOTO", NMT_GOTO ); - g_ScriptingHost.DefineConstant( "NMT_RUN", NMT_RUN ); - g_ScriptingHost.DefineConstant( "NMT_PATROL", NMT_PATROL ); - g_ScriptingHost.DefineConstant( "NMT_ADD_WAYPOINT", NMT_ADD_WAYPOINT ); - g_ScriptingHost.DefineConstant( "NMT_CONTACT_ACTION", NMT_CONTACT_ACTION ); - g_ScriptingHost.DefineConstant( "NMT_PRODUCE", NMT_PRODUCE ); - g_ScriptingHost.DefineConstant( "NMT_PLACE_OBJECT", NMT_PLACE_OBJECT ); - g_ScriptingHost.DefineConstant( "NMT_REMOVE_OBJECT", NMT_REMOVE_OBJECT ); - g_ScriptingHost.DefineConstant( "NMT_SET_RALLY_POINT", NMT_SET_RALLY_POINT ); - g_ScriptingHost.DefineConstant( "NMT_SET_STANCE", NMT_SET_STANCE ); - g_ScriptingHost.DefineConstant( "NMT_NOTIFY_REQUEST", NMT_NOTIFY_REQUEST ); - g_ScriptingHost.DefineConstant( "NMT_FORMATION_GOTO", NMT_FORMATION_GOTO ); - g_ScriptingHost.DefineConstant( "NMT_FORMATION_CONTACT_ACTION", NMT_FORMATION_CONTACT_ACTION ); -} - -//----------------------------------------------------------------------------- -// Name: CommandFromJSArgs() -// Desc: -//----------------------------------------------------------------------------- -CNetMessage* CNetMessage::CommandFromJSArgs( - const CEntityList &entities, - JSContext* pContext, - uintN argc, - jsval* argv, - bool isQueued ) -{ - uint idx = 0; - uint messageType; - - // Validate parameters - if ( argv == 0 ) return NULL; - - try - { - messageType = ToPrimitive< uint >( argv[ idx++ ] ); - } - catch ( PSERROR_Scripting_ConversionFailed ) - { - JS_ReportError( pContext, "Invalid order type" ); - return NULL; - } - - switch ( messageType ) - { - case NMT_GOTO: - { - CGotoMessage* pMessage = new CGotoMessage; - if ( !pMessage ) return NULL; - - pMessage->m_IsQueued = isQueued; - pMessage->m_Entities = entities; - - try - { - if ( idx + 2 > argc ) - { - JS_ReportError( pContext, "Too few parameters!" ); - return NULL; - } - - if ( !JSVAL_IS_INT( argv[ idx ] ) || - !JSVAL_IS_INT( argv[ idx + 1 ] ) ) - { - JS_ReportError( pContext, "Parameter type error!" ); - return NULL; - } - - pMessage->m_TargetX = ToPrimitive< int >( argv[ idx++ ] ); - pMessage->m_TargetY = ToPrimitive< int >( argv[ idx++ ] ); - } - catch ( PSERROR_Scripting_ConversionFailed ) - { - JS_ReportError( pContext, "Invalid location" ); - return NULL; - } - - return pMessage; - } - - case NMT_RUN: - { - CRunMessage* pMessage = new CRunMessage; - if ( !pMessage ) return NULL; - - pMessage->m_IsQueued = isQueued; - pMessage->m_Entities = entities; - - try - { - if ( idx + 2 > argc ) - { - JS_ReportError( pContext, "Too few parameters!" ); - return NULL; - } - - if ( !JSVAL_IS_INT( argv[ idx ] ) || - !JSVAL_IS_INT( argv[ idx + 1 ] ) ) - { - JS_ReportError( pContext, "Parameter type error!" ); - return NULL; - } - - pMessage->m_TargetX = ToPrimitive< int >( argv[ idx++ ] ); - pMessage->m_TargetY = ToPrimitive< int >( argv[ idx++ ] ); - } - catch ( PSERROR_Scripting_ConversionFailed ) - { - JS_ReportError( pContext, "Invalid location" ); - return NULL; - } - - return pMessage; - } - - case NMT_PATROL: - { - CPatrolMessage* pMessage = new CPatrolMessage; - if ( pMessage ) return NULL; - - pMessage->m_IsQueued = isQueued; - pMessage->m_Entities = entities; - - try - { - if ( idx + 2 > argc ) - { - JS_ReportError( pContext, "Too few parameters!" ); - return NULL; - } - - if ( !JSVAL_IS_INT( argv[ idx ] ) || - !JSVAL_IS_INT( argv[ idx + 1 ] ) ) - { - JS_ReportError( pContext, "Parameter type error!" ); - return NULL; - } - - pMessage->m_TargetX = ToPrimitive< int >( argv[ idx++ ] ); - pMessage->m_TargetY = ToPrimitive< int >( argv[ idx++ ] ); - } - catch ( PSERROR_Scripting_ConversionFailed ) - { - JS_ReportError( pContext, "Invalid location" ); - return NULL; - } - - return pMessage; - } - - case NMT_ADD_WAYPOINT: - { - CAddWaypointMessage* pMessage = new CAddWaypointMessage; - if ( !pMessage ) return NULL; - - pMessage->m_IsQueued = isQueued; - pMessage->m_Entities = entities; - - try - { - if ( idx + 2 > argc ) - { - JS_ReportError( pContext, "Too few parameters!" ); - return NULL; - } - - if ( !JSVAL_IS_INT( argv[ idx ] ) || - !JSVAL_IS_INT( argv[ idx + 1 ] ) ) - { - JS_ReportError( pContext, "Parameter type error!" ); - return NULL; - } - - pMessage->m_TargetX = ToPrimitive< int >( argv[ idx++ ] ); - pMessage->m_TargetY = ToPrimitive< int >( argv[ idx++ ] ); - } - catch ( PSERROR_Scripting_ConversionFailed ) - { - JS_ReportError( pContext, "Invalid location" ); - return NULL; - } - - return pMessage; - } - - case NMT_SET_RALLY_POINT: - { - CSetRallyPointMessage* pMessage = new CSetRallyPointMessage; - if ( !pMessage ) return NULL; - - pMessage->m_IsQueued = isQueued; - pMessage->m_Entities = entities; - - try - { - if ( idx + 2 > argc ) - { - JS_ReportError( pContext, "Too few parameters!" ); - return NULL; - } - - if ( !JSVAL_IS_INT( argv[ idx ] ) || - !JSVAL_IS_INT( argv[ idx + 1 ] ) ) - { - JS_ReportError( pContext, "Parameter type error!" ); - return NULL; - } - - pMessage->m_TargetX = ToPrimitive< int >( argv[ idx++ ] ); - pMessage->m_TargetY = ToPrimitive< int >( argv[ idx++ ] ); - } - catch ( PSERROR_Scripting_ConversionFailed ) - { - JS_ReportError( pContext, "Invalid location" ); - return NULL; - } - - return pMessage; - } - - case NMT_SET_STANCE: - { - CSetStanceMessage* pMessage = new CSetStanceMessage; - if ( !pMessage ) return NULL; - - pMessage->m_IsQueued = isQueued; - pMessage->m_Entities = entities; - - try - { - if ( idx + 1 > argc ) - { - JS_ReportError( pContext, "Too few parameters!" ); - return NULL; - } - - if ( !JSVAL_IS_STRING( argv[ idx ] ) ) - { - JS_ReportError( pContext, "Parameter type error!" ); - return NULL; - } - - pMessage->m_Stance = ToPrimitive< CStrW >( argv[ idx++ ] ); - } - catch ( PSERROR_Scripting_ConversionFailed ) - { - JS_ReportError( pContext, "Invalid location" ); - return NULL; - } - - return pMessage; - } - - case NMT_FORMATION_GOTO: - { - CFormationGotoMessage* pMessage = new CFormationGotoMessage; - if ( !pMessage ) return NULL; - - pMessage->m_IsQueued = isQueued; - pMessage->m_Entities = entities; - - try - { - if ( idx + 2 > argc ) - { - JS_ReportError( pContext, "Too few parameters!" ); - return NULL; - } - - if ( !JSVAL_IS_INT( argv[ idx ] ) || - !JSVAL_IS_INT( argv[ idx + 1 ] ) ) - { - JS_ReportError( pContext, "Parameter type error!" ); - return NULL; - } - - pMessage->m_TargetX = ToPrimitive< int >( argv[ idx++ ] ); - pMessage->m_TargetY = ToPrimitive< int >( argv[ idx++ ] ); - } - catch ( PSERROR_Scripting_ConversionFailed ) - { - JS_ReportError( pContext, "Invalid location" ); - return NULL; - } - - return pMessage; - } - - case NMT_CONTACT_ACTION: - { - CContactActionMessage* pMessage = new CContactActionMessage; - if ( !pMessage ) return NULL; - - pMessage->m_IsQueued = isQueued; - pMessage->m_Entities = entities; - - if ( idx + 3 > argc ) - { - JS_ReportError( pContext, "Too few parameters!" ); - return NULL; - } - - if ( !JSVAL_IS_OBJECT( argv[ idx ] ) ) - { - JS_ReportError( pContext, "Parameter type error!" ); - return NULL; - } - - CEntity* pEntity = ToNative< CEntity >( argv[ idx++ ] ); - if ( !pEntity ) - { - JS_ReportError( pContext, "Invalid entity parameter" ); - return NULL; - } - - pMessage->m_Target = pEntity->me; - - if ( !JSVAL_IS_INT( argv[ idx ] ) ) - { - JS_ReportError( pContext, "Parameter type error!" ); - return NULL; - } - - pMessage->m_Action = ToPrimitive< int >( argv[ idx++ ] ); - - if ( !JSVAL_IS_BOOLEAN( argv[ idx ] ) ) - { - JS_ReportError( pContext, "Parameter type error!" ); - return NULL; - } - - pMessage->m_Run = ToPrimitive< bool >( argv[ idx++ ] ); - - return pMessage; - } - - case NMT_NOTIFY_REQUEST: - { - CNotifyRequestMessage* pMessage = new CNotifyRequestMessage; - if ( !pMessage ) return NULL; - - pMessage->m_IsQueued = isQueued; - pMessage->m_Entities = entities; - - if ( idx + 1 > argc ) - { - - JS_ReportError( pContext, "Too few parameters!" ); - return NULL; - } - - if ( !JSVAL_IS_OBJECT( argv[ idx ] ) ) - { - JS_ReportError( pContext, "Parameter type error!" ); - return NULL; - } - - CEntity* pEntity = ToNative< CEntity >( argv[ idx++ ] ); - if ( !pEntity ) - { - JS_ReportError( pContext, "Invalid entity parameter" ); - return NULL; - } - - pMessage->m_Target = pEntity->me; - - return pMessage; - } - - case NMT_FORMATION_CONTACT_ACTION: - { - CFormationContactActionMessage* pMessage = new CFormationContactActionMessage; - if ( !pMessage ) return NULL; - - pMessage->m_IsQueued = isQueued; - pMessage->m_Entities = entities; - - if ( idx + 1 > argc ) - { - JS_ReportError( pContext, "Too few parameters!" );\ - return NULL; - } - - if ( !JSVAL_IS_OBJECT( argv[ idx ] ) ) - { - JS_ReportError( pContext, "Parameter type error!" ); - return NULL; - } - - CEntity* pEntity = ToNative< CEntity >( argv[ idx++ ] ); - if ( !pEntity ) - { - JS_ReportError( pContext, "Invalid entity parameter" ); - return NULL; - } - - pMessage->m_Target = pEntity->me; - - return pMessage; - } - - case NMT_PRODUCE: - { - CProduceMessage* pMessage = new CProduceMessage; - if ( !pMessage ) return NULL; - - pMessage->m_IsQueued = isQueued; - pMessage->m_Entities = entities; - - if ( idx + 1 > argc ) - { - JS_ReportError( pContext, "Too few parameters!" ); - return NULL; - } - - if ( !JSVAL_IS_INT( argv[ idx ] ) ) - { - JS_ReportError( pContext, "Parameter type error!" ); - return NULL; - } - - pMessage->m_Type = ToPrimitive< int >( argv[ idx++ ] ); - - if ( idx + 1 > argc ) - { - JS_ReportError( pContext, "Too few parameters!" ); - return NULL; - } - - if ( !JSVAL_IS_STRING( argv[ idx ] ) ) - { - JS_ReportError( pContext, "Parameter type error!" ); - return NULL; - } - - pMessage->m_Name = ToPrimitive< CStrW >( argv[ idx++ ] ); - - return pMessage; - } - - case NMT_PLACE_OBJECT: - { - CPlaceObjectMessage* pMessage = new CPlaceObjectMessage; - if ( !pMessage ) return NULL; - - pMessage->m_IsQueued = isQueued; - pMessage->m_Entities = entities; - - if ( idx + 1 > argc ) - { - JS_ReportError( pContext, "Too few parameters!" ); - return NULL; - } - - if ( !JSVAL_IS_STRING( argv[ idx ] ) ) - { - JS_ReportError( pContext, "Parameter type error!" ); - return NULL; - } - - pMessage->m_Template = ToPrimitive< CStrW >( argv[ idx++ ] ); - - if ( idx + 1 > argc ) - { - JS_ReportError( pContext, "Too few parameters!" ); - return NULL; - } - - if ( !JSVAL_IS_INT( argv[ idx ] ) ) - { - JS_ReportError( pContext, "Parameter type error!" ); - return NULL; - } - - pMessage->m_X = ToPrimitive< int >( argv[ idx++ ] ); - - if ( idx + 1 > argc ) - { - JS_ReportError( pContext, "Too few parameters!" ); - return NULL; - } - - if ( !JSVAL_IS_INT( argv[ idx ] ) ) - { - JS_ReportError( pContext, "Parameter type error!" ); - return NULL; - } - - pMessage->m_Y = ToPrimitive< int >( argv[ idx++ ] ); - - if ( idx + 1 > argc ) - { - JS_ReportError( pContext, "Too few parameters!" ); - return NULL; - } - if ( !JSVAL_IS_INT( argv[ idx ] ) ) - { - JS_ReportError( pContext, "Parameter type error!" ); - return NULL; - } - - pMessage->m_Z = ToPrimitive< int >( argv[ idx++ ] ); - - if ( idx + 1 > argc ) - { - JS_ReportError( pContext, "Too few parameters!" ); - return NULL; - } - - if ( !JSVAL_IS_INT( argv[ idx ] ) ) - { - JS_ReportError( pContext, "Parameter type error!" ); - return NULL; - } - - pMessage->m_Angle = ToPrimitive< int >( argv[ idx++ ] ); - - return pMessage; - } - - case NMT_REMOVE_OBJECT: - { - CRemoveObjectMessage* pMessage = new CRemoveObjectMessage; - if ( !pMessage ) return NULL; - - pMessage->m_IsQueued = isQueued; - pMessage->m_Entities = entities; - - return pMessage; - } - - default: - - JS_ReportError( pContext, "Invalid order type" ); - break; - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Name: CreatePositionMessage() -// Desc: -//----------------------------------------------------------------------------- -CNetMessage* CNetMessage::CreatePositionMessage( - const CEntityList& entities, - const int type, - CVector2D pos ) -{ - switch ( type ) - { - case NMT_GOTO: - { - CGotoMessage *pMessage = new CGotoMessage; - if ( !pMessage ) return NULL; - - pMessage->m_Entities = entities; - pMessage->m_TargetX = pos.x; - pMessage->m_TargetY = pos.y; - - return pMessage; - } - - case NMT_RUN: - { - CRunMessage *pMessage = new CRunMessage; - if ( !pMessage ) return NULL; - - pMessage->m_Entities = entities; - pMessage->m_TargetX = pos.x; - pMessage->m_TargetY = pos.y; - - return pMessage; - } - - case NMT_PATROL: - { - CPatrolMessage *pMessage = new CPatrolMessage; - if ( !pMessage ) return NULL; - - pMessage->m_Entities = entities; - pMessage->m_TargetX = pos.x; - pMessage->m_TargetY = pos.y; - - return pMessage; - } - - case NMT_ADD_WAYPOINT: - { - CAddWaypointMessage *pMessage = new CAddWaypointMessage; - if ( !pMessage ) return NULL; - - pMessage->m_Entities = entities; - pMessage->m_TargetX = pos.x; - pMessage->m_TargetY = pos.y; - - return pMessage; - } - - case NMT_SET_RALLY_POINT: - { - CSetRallyPointMessage *pMessage = new CSetRallyPointMessage; - if ( !pMessage ) return NULL; - - pMessage->m_Entities = entities; - pMessage->m_TargetX = pos.x; - pMessage->m_TargetY = pos.y; - - return pMessage; - } - - case NMT_FORMATION_GOTO: - { - CFormationGotoMessage *pMessage = new CFormationGotoMessage; - if ( !pMessage ) return NULL; - - pMessage->m_Entities = entities; - pMessage->m_TargetX = pos.x; - pMessage->m_TargetY = pos.y; - - return pMessage; - } - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Name: CreateEntityIntMessage() -// Desc: -//----------------------------------------------------------------------------- -CNetMessage* CNetMessage::CreateEntityIntMessage( - const CEntityList& entities, - const int type, - HEntity& target, - int action ) -{ - switch ( type ) - { - case NMT_CONTACT_ACTION: - { - CContactActionMessage *pMessage = new CContactActionMessage; - if ( !pMessage ) return NULL; - - pMessage->m_Entities = entities; - pMessage->m_Target = target; - pMessage->m_Action = action; - pMessage->m_Run = false; - - return pMessage; - } - - case NMT_NOTIFY_REQUEST: - { - CNotifyRequestMessage *pMessage = new CNotifyRequestMessage; - if ( !pMessage ) return NULL; - - pMessage->m_Entities = entities; - pMessage->m_Target = target; - pMessage->m_Action = action; - - return pMessage; - } - - case NMT_FORMATION_CONTACT_ACTION: - { - CFormationContactActionMessage *pMessage = new CFormationContactActionMessage; - if ( !pMessage ) return NULL; - - pMessage->m_Entities = entities; - pMessage->m_Target = target; - pMessage->m_Action = action; - - return pMessage; - } - } - - return NULL; -} -CNetMessage* CNetMessage::CreateProduceMessage( const CEntityList& entities, const int type, int proType, const CStrW& name ) -{ - switch ( type ) - { - case NMT_PRODUCE: - { - CProduceMessage* pMessage = new CProduceMessage; - if ( !pMessage ) return NULL; - - pMessage->m_Entities = entities; - pMessage->m_Type = proType; - pMessage->m_Name = name; - - return pMessage; - } - } - - return NULL; -} - //----------------------------------------------------------------------------- // Name: CreateMessage() // Desc: Creates the appropriate message based on the given data @@ -939,9 +155,6 @@ CNetMessage* CNetMessageFactory::CreateMessage(const void* pData, // Figure out message type header.Deserialize( ( const u8* )pData, ( const u8* )pData + dataSize ); - // This is what we want - //pNewMessage = m_Pool.GetMessage( header.GetType() ); - switch ( header.GetType() ) { case NMT_GAME_SETUP: @@ -1000,58 +213,6 @@ CNetMessage* CNetMessageFactory::CreateMessage(const void* pData, pNewMessage = new CChatMessage; break; - case NMT_GOTO: - pNewMessage = new CGotoMessage; - break; - - case NMT_PATROL: - pNewMessage = new CPatrolMessage; - break; - - case NMT_ADD_WAYPOINT: - pNewMessage = new CAddWaypointMessage; - break; - - case NMT_CONTACT_ACTION: - pNewMessage = new CContactActionMessage; - break; - - case NMT_PRODUCE: - pNewMessage = new CProduceMessage; - break; - - case NMT_PLACE_OBJECT: - pNewMessage = new CPlaceObjectMessage; - break; - - case NMT_REMOVE_OBJECT: - pNewMessage = new CRemoveObjectMessage; - break; - - case NMT_RUN: - pNewMessage = new CRunMessage; - break; - - case NMT_SET_RALLY_POINT: - pNewMessage = new CSetRallyPointMessage; - break; - - case NMT_SET_STANCE: - pNewMessage = new CSetStanceMessage; - break; - - case NMT_NOTIFY_REQUEST: - pNewMessage = new CNotifyRequestMessage; - break; - - case NMT_FORMATION_GOTO: - pNewMessage = new CFormationGotoMessage; - break; - - case NMT_FORMATION_CONTACT_ACTION: - pNewMessage = new CFormationContactActionMessage; - break; - case NMT_SIMULATION_COMMAND: pNewMessage = new CSimulationMessage(g_Game->GetSimulation2()->GetScriptInterface()); break; diff --git a/source/network/NetMessage.h b/source/network/NetMessage.h index f6f6c5dc51..d7f826e2c5 100644 --- a/source/network/NetMessage.h +++ b/source/network/NetMessage.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2009 Wildfire Games. +/* Copyright (C) 2010 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -138,45 +138,6 @@ public: private: bool m_Dirty; // Message has been modified NetMessageType m_Type; // Message type - -public: - - /** - * Register a selection of message types as JS constants. - * The constant's names will be the same as those of the enums - */ - static void ScriptingInit( void ); - - /*static CCommandMessage* CommandFromJSArgs( - const CEntityList &entities, - JSContext* cx, - uintN argc, - jsval* argv, - bool isQueued );*/ - - static CNetMessage* CommandFromJSArgs( - const CEntityList &entities, - JSContext* cx, - uintN argc, - jsval* argv, - bool isQueued ); - - static CNetMessage* CreatePositionMessage( - const CEntityList& entities, - const int type, - CVector2D pos ); - - static CNetMessage* CreateEntityIntMessage( - const CEntityList& entities, - const int type, - HEntity& target, - int action ); - - static CNetMessage* CreateProduceMessage( - const CEntityList& entities, - const int type, - int proType, - const CStrW& name ); }; /* @@ -197,8 +158,6 @@ public: */ static CNetMessage* CreateMessage( const void* pData, size_t dataSize ); -protected: - private: // Not implemented diff --git a/source/network/NetMessages.h b/source/network/NetMessages.h index 494c38419b..cd78617109 100644 --- a/source/network/NetMessages.h +++ b/source/network/NetMessages.h @@ -66,22 +66,7 @@ enum NetMessageType NMT_FILE_PROGRESS, NMT_GAME_START, NMT_END_COMMAND_BATCH, // In-game stage - NMT_GOTO, - NMT_COMMAND_FIRST = NMT_GOTO, - NMT_PATROL, - NMT_ADD_WAYPOINT, - NMT_CONTACT_ACTION, - NMT_PRODUCE, - NMT_PLACE_OBJECT, - NMT_REMOVE_OBJECT, - NMT_RUN, - NMT_SET_RALLY_POINT, - NMT_SET_STANCE, - NMT_NOTIFY_REQUEST, - NMT_FORMATION_GOTO, - NMT_FORMATION_CONTACT_ACTION, NMT_SIMULATION_COMMAND, - NMT_COMMAND_LAST, NMT_LAST // Last message in the list }; @@ -196,77 +181,6 @@ START_NMT_CLASS_(EndCommandBatch, NMT_END_COMMAND_BATCH) NMT_FIELD_INT(m_TurnLength, u32, 2) END_NMT_CLASS() -START_NMT_CLASS_(Command, NMT_INVALID) - NMT_FIELD(CEntityList, m_Entities) - NMT_FIELD_INT(m_IsQueued, u32, 1) -END_NMT_CLASS() - -DERIVE_NMT_CLASS_(Command, Goto, NMT_GOTO) - NMT_FIELD_INT(m_TargetX, u32, 2) - NMT_FIELD_INT(m_TargetY, u32, 2) -END_NMT_CLASS() - -DERIVE_NMT_CLASS_(Command, Run, NMT_RUN) - NMT_FIELD_INT(m_TargetX, u32, 2) - NMT_FIELD_INT(m_TargetY, u32, 2) -END_NMT_CLASS() - -DERIVE_NMT_CLASS_(Command, Patrol, NMT_PATROL) - NMT_FIELD_INT(m_TargetX, u32, 2) - NMT_FIELD_INT(m_TargetY, u32, 2) -END_NMT_CLASS() - -DERIVE_NMT_CLASS_(Command, AddWaypoint, NMT_ADD_WAYPOINT) - NMT_FIELD_INT(m_TargetX, u32, 2) - NMT_FIELD_INT(m_TargetY, u32, 2) -END_NMT_CLASS() - -DERIVE_NMT_CLASS_(Command, SetRallyPoint, NMT_SET_RALLY_POINT) - NMT_FIELD_INT(m_TargetX, u32, 2) - NMT_FIELD_INT(m_TargetY, u32, 2) -END_NMT_CLASS() - -DERIVE_NMT_CLASS_(Command, SetStance, NMT_SET_STANCE) - NMT_FIELD(CStrW, m_Stance) -END_NMT_CLASS() - -DERIVE_NMT_CLASS_(Command, ContactAction, NMT_CONTACT_ACTION) - NMT_FIELD(HEntity, m_Target) - NMT_FIELD_INT(m_Action, u32, 4) - NMT_FIELD_INT(m_Run, u32, 1) -END_NMT_CLASS() - -DERIVE_NMT_CLASS_(Command, Produce, NMT_PRODUCE) - NMT_FIELD_INT(m_Type, u32, 4) - NMT_FIELD(CStrW, m_Name) -END_NMT_CLASS() - -DERIVE_NMT_CLASS_(Command, PlaceObject, NMT_PLACE_OBJECT) - NMT_FIELD(CStrW, m_Template) - NMT_FIELD_INT(m_X, u32, 4) - NMT_FIELD_INT(m_Y, u32, 4) - NMT_FIELD_INT(m_Z, u32, 4) - NMT_FIELD_INT(m_Angle, u32, 4) // Orientation angle -END_NMT_CLASS() - -DERIVE_NMT_CLASS_(Command, RemoveObject, NMT_REMOVE_OBJECT) -END_NMT_CLASS() - -DERIVE_NMT_CLASS_(Command, NotifyRequest, NMT_NOTIFY_REQUEST) - NMT_FIELD(HEntity, m_Target) - NMT_FIELD_INT(m_Action, u32, 4) -END_NMT_CLASS() - -DERIVE_NMT_CLASS_(Command, FormationGoto, NMT_FORMATION_GOTO) - NMT_FIELD_INT(m_TargetX, u32, 2) - NMT_FIELD_INT(m_TargetY, u32, 2) -END_NMT_CLASS() - -DERIVE_NMT_CLASS_(Command, FormationContactAction, NMT_FORMATION_CONTACT_ACTION) - NMT_FIELD(HEntity, m_Target) - NMT_FIELD_INT(m_Action, u32, 4) -END_NMT_CLASS() - END_NMTS() #else diff --git a/source/network/NetServer.cpp b/source/network/NetServer.cpp index a21f3dc9d7..89f221d9a0 100644 --- a/source/network/NetServer.cpp +++ b/source/network/NetServer.cpp @@ -38,17 +38,6 @@ // DECLARATIONS CNetServer* g_NetServer = NULL; -class CServerTurnManager : public CTurnManager -{ -public: - CServerTurnManager(CNetServer& server) : m_Server(server) { } - virtual void QueueLocalCommand(CNetMessage* pMessage); - virtual void NewTurn(); - virtual bool NewTurnReady(); -private: - CNetServer& m_Server; -}; - //----------------------------------------------------------------------------- // Name: CNetServer() // Desc: Constructor @@ -56,13 +45,11 @@ private: CNetServer::CNetServer( CGame *pGame, CGameAttributes *pGameAttributes ) : m_JsSessions( &m_IDSessions ) { - m_TurnManager = new CServerTurnManager(*this); m_ServerTurnManager = NULL; m_Game = pGame; m_GameAttributes = pGameAttributes; m_MaxObservers = MAX_OBSERVERS; - //m_LastSessionID = 1; m_Port = DEFAULT_HOST_PORT; m_Name = DEFAULT_SERVER_NAME; m_PlayerName = DEFAULT_PLAYER_NAME; @@ -73,16 +60,6 @@ CNetServer::CNetServer( CGame *pGame, CGameAttributes *pGameAttributes ) m_GameAttributes->SetPlayerUpdateCallback( PlayerAttributeUpdate, this ); m_GameAttributes->SetPlayerSlotAssignmentCallback( PlayerSlotAssignment, this ); - if (!g_UseSimulation2) - m_Game->GetSimulation()->SetTurnManager(m_TurnManager); - - // Set an incredibly long turn length for debugging - // (e.g. less command batch spam that way) - for ( uint i = 0; i < 3; i++ ) - { - m_TurnManager->SetTurnLength( i, CTurnManager::DEFAULT_TURN_LENGTH ); - } - g_ScriptingHost.SetGlobal( "g_NetServer", OBJECT_TO_JSVAL( GetScript() ) ); } @@ -117,8 +94,6 @@ void CNetServer::ScriptingInit( void ) AddProperty( L"onClientDisconnect", &CNetServer::m_OnClientDisconnect ); CJSObject< CNetServer >::ScriptingInit( "NetServer" ); - - //CGameAttributes::ScriptingInit(); } //----------------------------------------------------------------------------- @@ -167,18 +142,6 @@ bool CNetServer::SetupSession( CNetSession* pSession ) pSession->AddTransition( NSS_PREGAME, ( uint )NMT_CHAT, NSS_INGAME, (void*)&OnInGame, pContext ); pSession->AddTransition( NSS_INGAME, ( uint )NMT_ERROR, NSS_INGAME, (void*)&OnError, pContext ); pSession->AddTransition( NSS_INGAME, ( uint )NMT_CHAT, NSS_INGAME, (void*)&OnChat, pContext ); - pSession->AddTransition( NSS_INGAME, ( uint )NMT_GOTO, NSS_INGAME, (void*)&OnInGame, pContext ); - pSession->AddTransition( NSS_INGAME, ( uint )NMT_PATROL, NSS_INGAME, (void*)&OnInGame, pContext ); - pSession->AddTransition( NSS_INGAME, ( uint )NMT_ADD_WAYPOINT, NSS_INGAME, (void*)&OnInGame, pContext ); - pSession->AddTransition( NSS_INGAME, ( uint )NMT_CONTACT_ACTION, NSS_INGAME, (void*)&OnInGame, pContext ); - pSession->AddTransition( NSS_INGAME, ( uint )NMT_PRODUCE, NSS_INGAME, (void*)&OnInGame, pContext ); - pSession->AddTransition( NSS_INGAME, ( uint )NMT_PLACE_OBJECT, NSS_INGAME, (void*)&OnInGame, pContext ); - pSession->AddTransition( NSS_INGAME, ( uint )NMT_RUN, NSS_INGAME, (void*)&OnInGame, pContext ); - pSession->AddTransition( NSS_INGAME, ( uint )NMT_SET_RALLY_POINT, NSS_INGAME, (void*)&OnInGame, pContext ); - pSession->AddTransition( NSS_INGAME, ( uint )NMT_SET_STANCE, NSS_INGAME, (void*)&OnInGame, pContext ); - pSession->AddTransition( NSS_INGAME, ( uint )NMT_NOTIFY_REQUEST, NSS_INGAME, (void*)&OnInGame, pContext ); - pSession->AddTransition( NSS_INGAME, ( uint )NMT_FORMATION_GOTO, NSS_INGAME, (void*)&OnInGame, pContext ); - pSession->AddTransition( NSS_INGAME, ( uint )NMT_FORMATION_CONTACT_ACTION, NSS_INGAME, (void*)&OnInGame, pContext ); pSession->AddTransition( NSS_INGAME, ( uint )NMT_SIMULATION_COMMAND, NSS_INGAME, (void*)&OnInGame, pContext ); pSession->AddTransition( NSS_INGAME, ( uint )NMT_END_COMMAND_BATCH, NSS_INGAME, (void*)&OnInGame, pContext ); @@ -345,15 +308,7 @@ void CNetServer::OnPlayerLeave( CNetSession* pSession ) // Validate parameters if ( !pSession ) return; - CPlayer* pPlayer = NULL; - CPlayerSlot* pPlayerSlot = NULL; - CPlayerLeaveMessage playerLeave; - - // Validate parameters - if ( !pSession ) return; - - pPlayer = pSession->GetPlayer(); - pPlayerSlot = pSession->GetPlayerSlot(); + CPlayerSlot* pPlayerSlot = pSession->GetPlayerSlot(); switch ( m_State ) { @@ -371,7 +326,6 @@ void CNetServer::OnPlayerLeave( CNetSession* pSession ) // TODO Set everything up for re-connect and resume if ( pPlayerSlot ) { - m_TurnManager->SetClientPipe( pPlayerSlot->GetSlotID(), NULL ); pPlayerSlot->AssignClosed(); } break; @@ -383,8 +337,8 @@ void CNetServer::OnPlayerLeave( CNetSession* pSession ) } // Inform other clients about client disconnection + CPlayerLeaveMessage playerLeave; playerLeave.m_SessionID = pSession->GetID(); - Broadcast( &playerLeave ); // Script object defined? @@ -416,18 +370,7 @@ bool CNetServer::OnError( void* pContext, CFsmEvent* pEvent ) CErrorMessage* pMessage = ( CErrorMessage* )pEvent->GetParamRef(); if ( pMessage ) { - if ( pMessage->m_State == SS_UNCONNECTED ) - { - //if ( pSession->GetID() != -1) - // pServer->RemoveSession( pSession ); - - //delete pSession; - } - else - { - // Weird stuff... - LOG( CLogger::Warning, LOG_CATEGORY, L"NMT_ERROR: %hs", pMessage->ToString().c_str() ); - } + LOG( CLogger::Warning, LOG_CATEGORY, L"NMT_ERROR: %hs", pMessage->ToString().c_str() ); } return true; @@ -459,8 +402,7 @@ bool CNetServer::OnHandshake( void* pContext, CFsmEvent* pEvent ) CCloseRequestMessage closeRequest; pServer->SendMessage( pSession, &closeRequest ); - CErrorMessage error( PS_OK, SS_UNCONNECTED ); - pSession->Update( ( uint )NMT_ERROR, &error ); + // TODO: probably need to abort and disconnect the session somehow } else { @@ -572,24 +514,10 @@ bool CNetServer::OnInGame( void* pContext, CFsmEvent* pEvent ) return true; } - if ( pMessage->GetType() >= NMT_COMMAND_FIRST && pMessage->GetType() < NMT_COMMAND_LAST ) - { - //pSession->m_pPlayer->ValidateCommand(pMsg); - pServer->QueueIncomingCommand( pMessage ); - - return true; - } - if ( pMessage->GetType() == NMT_END_COMMAND_BATCH ) { - if (g_UseSimulation2) - { - CEndCommandBatchMessage* endMessage = static_cast (pMessage); - pServer->m_ServerTurnManager->NotifyFinishedClientCommands(pSession->GetID(), endMessage->m_Turn); - } - - // TODO Update client timing information and recalculate turn length - pSession->SetReadyForTurn( true ); + CEndCommandBatchMessage* endMessage = static_cast (pMessage); + pServer->m_ServerTurnManager->NotifyFinishedClientCommands(pSession->GetID(), endMessage->m_Turn); } } @@ -642,107 +570,6 @@ CNetSession* CNetServer::GetSessionByID( uint sessionID ) return it->second; } -//----------------------------------------------------------------------------- -// Name: AddSession() -// Desc: Adds a new session to the list of managed sessions -//----------------------------------------------------------------------------- -/*void CNetServer::AddSession( CNetSession* pSession ) -{ - // Validate parameter - if ( !pSession ) return; - - // Setup new session - //SetupNewSession(); - - // Broadcase a new message informing about the newly connected client - CPlayerJoinMessage playerJoin; - playerJoin.m_Clients.resize( 1 ); - playerJoin.m_Clients[ 0 ].m_SessionID = pSession->GetID(); - playerJoin.m_Clients[ 0 ].m_Name = pSession->GetName(); - - Broadcast( playerJoin ); - - // Store new session - m_IDSessions[ pSession->GetID() ] = pSession; -}*/ - -//----------------------------------------------------------------------------- -// Name: RemoveSession() -// Desc: Removes the specified session from the list of sessions -//----------------------------------------------------------------------------- -/*CNetSession* CNetServer::RemoveSession( CNetSession* pSession ) -{ - CPlayer* pPlayer = NULL; - CPlayerSlot* pPlayerSlot = NULL; - CPlayerLeaveMessage playerLeave; - uint sessionID; - - // Validate parameters - if ( !pSession ) return; - - pPlayer = pSession->GetPlayer(); - pPlayerSlot = pSession->GetPlayerSlot(); - sessionID = pSession->GetID(); - - switch ( m_State ) - { - case SERVER_STATE_PREGAME: - - // Delete player's slot and sync client disconnection - if ( pPlayerSlot ) pPlayerSlot->AssignClosed(); - - break; - - case SERVER_STATE_INGAME: - - // Revert player entities to Gaia control and - // wait for client reconnection - // TODO Reassign entities to Gaia control - // TODO Set everything up for re-connect and resume - if ( pPlayerSlot ) - { - SetClientPipe( pPlayerSlot->GetSlotID(), NULL ); - pPlayerSlot->AssignClosed(); - } - - break; - - case SERVER_STATE_POSTGAME: - - // Synchronize disconnection - - break; - } - - // Inform other clients about client disconnection - playerLeave.m_SessionID = sessionID; - - Broadcast( playerLeave ); - - // Free session slot from the list for later reuse - m_IDSessions[ sessionID ] = NULL; - - // TODO Handle observers -}*/ - -//----------------------------------------------------------------------------- -// Name: RemoveAllSessions() -// Desc: Removes all sessions from the list -//----------------------------------------------------------------------------- -/*void CNetServer::RemoveAllSessions( void ) -{ - SessionList::iterator it = m_Sessions.begin(); - for ( ; it != m_Sessions.end(); it++ ) - { - CNetSession* pCurrSession = it->second; - if ( !pCurrSession ) continue; - - RemoveSession( pCurrSession ); - } - - m_Sessions.clear(); -}*/ - //----------------------------------------------------------------------------- // Name: SetPlayerPassword() // Desc: Sets player new password @@ -765,13 +592,8 @@ int CNetServer::StartGame( void ) if ( m_Game->StartGame( m_GameAttributes ) != PSRETURN_OK ) return -1; - if (g_UseSimulation2) - { - m_ServerTurnManager = new CNetServerTurnManager(*m_Game->GetSimulation2(), *this, m_Game->GetLocalPlayer()->GetPlayerID(), SERVER_SESSIONID); - m_Game->SetTurnManager(m_ServerTurnManager); - } - - m_TurnManager->Initialize( m_GameAttributes->GetSlotCount() ); + m_ServerTurnManager = new CNetServerTurnManager(*m_Game->GetSimulation2(), *this, m_Game->GetLocalPlayer()->GetPlayerID(), SERVER_SESSIONID); + m_Game->SetTurnManager(m_ServerTurnManager); for ( i = 0; i < m_GameAttributes->GetSlotCount(); i++ ) { @@ -780,28 +602,15 @@ int CNetServer::StartGame( void ) if ( pCurrSlot->GetAssignment() == SLOT_SESSION ) { - m_TurnManager->SetClientPipe( i, pCurrSlot->GetSession() ); - if (g_UseSimulation2) - m_ServerTurnManager->InitialiseClient(pCurrSlot->GetSessionID()); + m_ServerTurnManager->InitialiseClient(pCurrSlot->GetSessionID()); } } m_State = SERVER_STATE_INGAME; - for ( i = 0; i < GetSessionCount(); i++ ) - { - CNetSession* pCurrSession = GetSession( i ); - if ( !pCurrSession ) continue; - - pCurrSession->StartGame(); - } - CGameStartMessage gameStart; Broadcast( &gameStart ); - // This is the signal for everyone to start their simulations. - //SendBatch( 1 ); - return 0; } @@ -892,23 +701,6 @@ uint CNetServer::GetFreeSessionID( void ) const // No need to be conservative with session IDs; just use a global counter. static uint lastSessionID = CLIENT_MIN_SESSIONID; return lastSessionID++; - - /* - // Loop through the list of sessions and return the first - // ID for which the associated session is NULL. If no such - // free slot is found, return a new session ID which is higher - // than the last session ID from the list. - IDSessionMap::const_iterator it = m_IDSessions.begin(); - for ( ; it != m_IDSessions.end(); it++ ) - { - CNetSession* pCurrSession = it->second; - if ( !pCurrSession ) return it->first; - - sessionID++; - } - - return sessionID; - */ } //----------------------------------------------------------------------------- @@ -996,78 +788,6 @@ bool CNetServer::AllowObserver( CNetSession* UNUSED( pSession ) ) return m_Observers.size() < m_MaxObservers; } -//----------------------------------------------------------------------------- -// Name: NewTurnReady() -// Desc: -//----------------------------------------------------------------------------- -bool CServerTurnManager::NewTurnReady() -{ - // Check whether all sessions are ready for the next turn - for ( uint i = 0; i < m_Server.GetSessionCount(); i++ ) - { - CNetSession* pCurrSession = m_Server.GetSession( i ); - if ( !pCurrSession ) continue; - - if ( !pCurrSession->IsReadyForTurn() ) - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Name: NewTurn() -// Desc: -//----------------------------------------------------------------------------- -void CServerTurnManager::NewTurn() -{ - CScopeLock lock(m_Server.m_Mutex); - - // Reset session ready for next turn flag - for ( uint i = 0; i < m_Server.GetSessionCount(); i++ ) - { - CNetSession* pCurrSession = m_Server.GetSession( i ); - if ( !pCurrSession ) continue; - - pCurrSession->SetReadyForTurn( false ); - } - - RecordBatch( 2 ); - RotateBatches(); - ClearBatch( 2 ); - IterateBatch( 1, CSimulation::GetMessageMask, m_Server.m_Game->GetSimulation() ); - SendBatch( 1 ); - //IterateBatch( 1, SendToObservers, this ); -} - -//----------------------------------------------------------------------------- -// Name: QueueLocalCommand() -// Desc: -//----------------------------------------------------------------------------- -void CServerTurnManager::QueueLocalCommand( CNetMessage *pMessage ) -{ - // Validate parameters - if ( !pMessage ) return; - - //LOG( NORMAL, LOG_CATEGORY, L"CServerTurnManager::QueueLocalCommand(): %hs.", pMessage->ToString().c_str() ); - - QueueMessage( 2, pMessage ); -} - -//----------------------------------------------------------------------------- -// Name: QueueIncomingCommand() -// Desc: -//----------------------------------------------------------------------------- -void CNetServer::QueueIncomingCommand( CNetMessage* pMessage ) -{ - // Validate parameters - if ( !pMessage ) return; - - //LOG( NORMAL, LOG_CATEGORY, L"CNetServer::QueueIncomingCommand(): %hs.", pMessage->ToString().c_str() ); - - m_TurnManager->QueueMessage( 2, pMessage ); -} - //----------------------------------------------------------------------------- // Name: OnChat() // Desc: diff --git a/source/network/NetServer.h b/source/network/NetServer.h index c405f5bbc8..71a1432925 100644 --- a/source/network/NetServer.h +++ b/source/network/NetServer.h @@ -30,7 +30,6 @@ #include "Network.h" #include "NetSession.h" #include "NetTurnManager.h" -#include "simulation/TurnManager.h" #include "scripting/ScriptableObject.h" #include "ps/GameAttributes.h" #include "ps/scripting/JSMap.h" @@ -107,7 +106,6 @@ public: virtual ~CNetServer( void ); bool Start ( JSContext *pContext, uintN argc, jsval *argv ); -// void Shutdown ( void ); /** * Returns true indicating the host acts as a server @@ -132,19 +130,6 @@ public: */ CNetSession* RemoveSession( CNetSession* pSession ); - /** - * Removes all the sessions managed by the network server - * - */ - //void RemoveAllSessions( void ); - - /** - * Returns the number of session the server manages - * - * @return The number of sessions - */ - //uint GetSessionCount( void ) const; - /** * Returns the session object for the specified ID * @@ -154,8 +139,6 @@ public: */ CNetSession* GetSessionByID( uint sessionID ); - CNetTurnManager* GetTurnManager() { debug_assert(m_ServerTurnManager); return m_ServerTurnManager; } - protected: virtual bool SetupSession ( CNetSession* pSession ); @@ -164,26 +147,6 @@ protected: private: - //void ClientConnect ( ENetPeer* pPeer ); - //void ClientDisconnect ( ENetPeer* pPeer ); - //void ClientReceive ( ENetPeer* pPeer, ENetPacket* pPacket ); - - /** - * Returns the session associated with the specified ENet peer - * - * @param pPeer ENet peer - * @return The session object if found or NULL - */ - //CNetSession* GetSessionByPeer( const ENetPeer* pPeer ); - - /** - * Setup client game by sending the apropiate network messages. It also - * inform the client about the other connected clients as well as player - * slot assignment and attributes. - * - */ - //void SetupNewSession( CNetSession* pSession ); - /** * Loads the player properties into the specified message * @@ -232,7 +195,6 @@ private: * @param pProperty Pointer to game property * @param pData Context pointer passed on iteration startup */ - // IterateCB GameSetupMessageCallbak; static void GameSetupMessageCallback( const CStrW& name, ISynchedJSProperty *pProperty, @@ -246,20 +208,9 @@ private: uint GetFreeSessionID( void ) const; IDSessionMap m_IDSessions; // List of connected ID and session pairs - //CScriptObject m_ScriptConnect; // Script client connect dispatch - //CScriptObject m_ScriptDisconnect; // Script client disconnect dispatch - //CScriptObject m_ScriptChat; // Script client chat dispatch - public: - /** - * - * - * @param addr Address where to bind - * @return PS_OK if bind successfully, error code otherwise - */ - //PS_RESULT Bind( const CSocketAddress& addr ); void SetPlayerPassword ( const CStr& password ); CStrW GetPlayerName ( void ) const { return m_PlayerName; } NetServerState GetState ( void ) const { return m_State; } @@ -271,18 +222,6 @@ protected: // Assign a session ID to the session. Do this just before calling AddSession void AssignSessionID( CNetSession* pSession ); - // Add the session. This will be called after the session passes the - // handshake and authentication stages. AssignSessionID should've been called - // on the session prior to calling this method. - //void AddSession( CNetServerSession* pSession ); - - // Remove the session from the server - //void RemoveSession( CNetServerSession* pSession ); - - // Queue a command coming in from the wire. The command has been validated - // by the caller. - void QueueIncomingCommand( CNetMessage* pMessage ); - // Call the JS callback for incoming events void OnPlayerChat ( const CStrW& from, const CStrW& message ); virtual void OnPlayerJoin ( CNetSession* pSession ); @@ -297,12 +236,6 @@ protected: static bool OnInGame ( void* pContext, CFsmEvent* pEvent ); static bool OnChat ( void* pContext, CFsmEvent* pEvent ); - // OVERRIDES FROM CServerSocket - //virtual void OnAccept( const CSocketAddress& address ); - - // Will only be called from the Network Thread, by the OnAccept handler - //virtual CNetServerSession* CreateSession( CSocketInternal* pSocketInternal); - // Ask the server if the session is allowed to start observing. // // Returns: @@ -311,14 +244,11 @@ protected: virtual bool AllowObserver( CNetSession* pSession ); public: - CMutex m_Mutex; // Synchronization object for batches CGame* m_Game; // Pointer to actual game private: CGameAttributes* m_GameAttributes; // Stores game attributes - //int m_LastSessionID; // Stores the last session ID - //SessionMap m_Sessions; // Managed sessions CJSMap< IDSessionMap > m_JsSessions; /* @@ -332,7 +262,6 @@ private: NetServerState m_State; // Holds server state CStrW m_Name; // Server name CStrW m_WelcomeMessage; // Nice welcome message - //CPlayer* m_Player; // Pointer to 'server' player CStrW m_PlayerName; // Player name CStrW m_PlayerPassword; // Player password int m_Port; // The listening port @@ -340,15 +269,10 @@ private: CScriptObject m_OnClientConnect; CScriptObject m_OnClientDisconnect; -// static CGameAttributes::UpdateCallback AttributeUpdate; -// static CPlayer::UpdateCallback PlayerAttributeUpdate; -// static PlayerSlotAssignmentCB PlayerSlotAssignmentCallback; - static void AttributeUpdate ( const CStrW& name, const CStrW& newValue, void* pData); static void PlayerAttributeUpdate ( const CStrW& name, const CStrW& value, CPlayer* pPlayer, void* pData ); static void PlayerSlotAssignment ( void* pData, CPlayerSlot* pPlayerSlot ); - CTurnManager* m_TurnManager; CNetServerTurnManager* m_ServerTurnManager; }; diff --git a/source/network/NetSession.cpp b/source/network/NetSession.cpp index 990dacbb4b..785df03191 100644 --- a/source/network/NetSession.cpp +++ b/source/network/NetSession.cpp @@ -25,9 +25,7 @@ // INCLUDES #include "precompiled.h" -//#include "SessionManager.h" #include "NetSession.h" -//#include "NetServer.h" #include "NetLog.h" // DECLARATIONS @@ -39,11 +37,6 @@ CNetHost::CNetHost( void ) { m_Host = NULL; - m_Buffer = NULL; - m_BufferSize = 0; - -// m_WorkerID = 0; -// m_StopWorker = NULL; } //----------------------------------------------------------------------------- @@ -54,16 +47,8 @@ CNetHost::~CNetHost( void ) { // Release host if ( m_Host ) enet_host_destroy( m_Host ); - if ( m_Buffer ) delete [] m_Buffer; - - // Release running semaphore -// if ( m_StopWorker ) sem_close( m_StopWorker ); m_Host = NULL; - m_Buffer = NULL; - m_BufferSize = 0; -// m_WorkerID = 0; -// m_StopWorker = NULL; } //----------------------------------------------------------------------------- @@ -107,10 +92,6 @@ void CNetHost::Shutdown( void ) // Destroy server if ( m_Host ) enet_host_destroy( m_Host ); - // Stop worker thread -// sem_post( m_StopWorker ); -// if ( m_WorkerID ) pthread_join( m_WorkerID, NULL ); - // Disconnect and release each peer PeerSessionList::iterator it = m_PeerSessions.begin(); for ( ; it != m_PeerSessions.end(); it++ ) @@ -125,7 +106,6 @@ void CNetHost::Shutdown( void ) m_PeerSessions.clear(); m_Host = NULL; -// m_WorkerID = 0; } //----------------------------------------------------------------------------- @@ -227,122 +207,6 @@ bool CNetHost::Disconnect( CNetSession* pSession ) return true; } -//----------------------------------------------------------------------------- -// Name: Run() -// Desc: -//----------------------------------------------------------------------------- -/*bool CNetHost::Run( void ) -{ - debug_assert( m_Host ); - - // Host created? - if ( !m_Host ) return false; - - // Already running? - if ( m_WorkerID != 0 ) return true; - - // Create run semaphore - m_StopWorker = sem_open( "//WFG_HostWorkerRun", O_CREAT | O_EXCL, 0700, 0 ); - if ( !m_StopWorker ) return false; - - // Create worker thread - if ( pthread_create( &m_WorkerID, 0, &WorkerFunc, this ) < 0 ) return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Name: WorkerFunc() -// Desc: Worker thread function -//----------------------------------------------------------------------------- -void* CNetHost::WorkerFunc( void* pData ) -{ - ENetEvent event; - CNetSession* pSession = NULL; - PeerSession item; - PeerSessionList::iterator it; - - // Validate parameters - if ( !pData ) return NULL; - - CNetHost* pHost = ( CNetHost* )pData; - - // Poll host for events - while ( true ) - { - // Decide whether to stop or not - if ( !sem_timedwait( pHost->m_StopWorker, NULL ) ) break; - - int retval = enet_host_service( pHost->m_Host, &event, 100 ); - - // Any event? - if ( !retval ) continue; - - // Any error? - if ( !retval ) break; - - // Handle occured event - switch( event.type ) - { - case ENET_EVENT_TYPE_CONNECT: - - // A new client has connected, handle it - pSession = new CNetSession( pHost, event.peer ); - if ( !pSession ) return NULL; - - // Successfully handled? - if ( !pHost->HandleConnect( pSession ) ) return NULL; - - // Add new item to internal list - item.pPeer = event.peer; - item.pSession = pSession; - pHost->m_PeerSessions.push_back( item ); - - break; - - case ENET_EVENT_TYPE_DISCONNECT: - - // Client has disconnected, handle it - it = pHost->m_PeerSessions.begin();; - for ( ; it != pHost->m_PeerSessions.end(); it++ ) - { - // Is this our session? - if ( it->pPeer == event.peer ) - { - // Successfully handled? - if ( !pHost->HandleDisconnect( it->pSession ) ) return NULL; - - pHost->m_PeerSessions.erase( it ); - } - } - - break; - - case ENET_EVENT_TYPE_RECEIVE: - - // A new data packet was received from client, handle message - it = pHost->m_PeerSessions.begin(); - for ( ; it != pHost->m_PeerSessions.end(); it++ ) - { - // Is this our session? - if ( it->pPeer == event.peer ) - { - // Create message from raw data - CNetMessage* pNewMessage = CNetMessageFactory::CreateMessage( event.packet->data, event.packet->dataLength ); - if ( !pNewMessage ) return NULL; - - // Successfully handled? - if ( !pHost->HandleMessageReceive( pNewMessage, it->pSession ) ) return NULL; - } - } - - break; - } - } - - return NULL; -}*/ - //----------------------------------------------------------------------------- // Name: ProcessEvents() // Desc: Wait for events and shuttles packets between the host and its peers @@ -463,35 +327,6 @@ void CNetHost::Broadcast( const CNetMessage* pMessage ) } } -//----------------------------------------------------------------------------- -// Name: ResizeBuffer() -// Desc: Resizes the internal buffer -//----------------------------------------------------------------------------- -void CNetHost::ResizeBuffer( size_t size ) -{ - // Already enough space? - if ( size <= m_BufferSize ) return; - - // Allocate enough space for the new buffer - u8* pBuffer = new u8[ ALIGN_BLOCK( m_BufferSize + size ) ]; - if ( !pBuffer ) return; - - // Any old data? - if ( m_Buffer ) - { - // Copy old data - memcpy( pBuffer, m_Buffer, m_BufferSize ); - - delete [] m_Buffer; - } - - // Store new buffer - m_Buffer = pBuffer; - - // Store new buffer size - m_BufferSize = ALIGN_BLOCK( m_BufferSize + size ); -} - //----------------------------------------------------------------------------- // Name: SendMessage() // Desc: Sends the specified message to peer @@ -507,15 +342,16 @@ bool CNetHost::SendMessage( debug_assert( m_Host ); size_t size = pMessage->GetSerializedLength(); + debug_assert( size ); // Adjust buffer for message - ResizeBuffer( size ); + m_Buffer.resize( size ); // Save message to internal buffer - pMessage->Serialize( m_Buffer ); + pMessage->Serialize( &m_Buffer[0] ); // Create a reliable packet - ENetPacket* pPacket = enet_packet_create( m_Buffer, size, ENET_PACKET_FLAG_RELIABLE ); + ENetPacket* pPacket = enet_packet_create( &m_Buffer[0], size, ENET_PACKET_FLAG_RELIABLE ); if ( !pPacket ) return false; // Let ENet send the message to peer @@ -529,7 +365,7 @@ bool CNetHost::SendMessage( else { NET_LOG4( "Message %s of size %lu was sent to %p", - pMessage->ToString().c_str(), (unsigned long)pMessage->GetSerializedLength(), pSession->m_Peer->data ); + pMessage->ToString().c_str(), (unsigned long)size, pSession->m_Peer->data ); } enet_host_flush( m_Host ); @@ -625,17 +461,10 @@ CNetSession* CNetHost::GetSession( uint index ) //----------------------------------------------------------------------------- CNetSession::CNetSession( CNetHost* pHost, ENetPeer* pPeer ) { - //ONCE( ScriptingInit(); ); - m_Host = pHost; m_Peer = pPeer; m_ID = INVALID_SESSION; - m_Player = NULL; m_PlayerSlot = NULL; - m_ReadyForTurn = false; - - // Register the network session - //g_SessionManager.Register( this ); } //----------------------------------------------------------------------------- @@ -649,9 +478,6 @@ CNetSession::~CNetSession( void ) //m_Host = NULL; m_Peer = NULL; - - // Unregister the network session - //g_SessionManager.Unregister( this ); } //----------------------------------------------------------------------------- @@ -672,15 +498,6 @@ void CNetSession::SetID( uint ID ) m_ID = ID; } -//----------------------------------------------------------------------------- -// Name: SetPlayer() -// Desc: Set the player for this session -//----------------------------------------------------------------------------- -void CNetSession::SetPlayer( CPlayer* pPlayer ) -{ - m_Player = pPlayer; -} - //----------------------------------------------------------------------------- // Name: SetPlayerSlot() // Desc: Set the player slot for this session @@ -690,39 +507,6 @@ void CNetSession::SetPlayerSlot( CPlayerSlot* pPlayerSlot ) m_PlayerSlot = pPlayerSlot; } -//----------------------------------------------------------------------------- -// Name: StartGame() -// Desc: Called by server after informing all clients about starting the game -//----------------------------------------------------------------------------- -void CNetSession::StartGame( void ) -{ -} - -//----------------------------------------------------------------------------- -// Name: Push() -// Desc: Sends a message through ENet -//----------------------------------------------------------------------------- -void CNetSession::Push( CNetMessage* pMessage ) -{ - // Validate parameters - if ( !pMessage ) return; - - debug_assert( m_Host ); - - m_Host->SendMessage( this, pMessage ); -} - -//----------------------------------------------------------------------------- -// Name: TryPop() -// Desc: Receives a message through ENet -//----------------------------------------------------------------------------- -CNetMessage* CNetSession::TryPop( void ) -{ - debug_assert( m_Host ); - - return m_Host->ReceiveMessage( this ); -} - //----------------------------------------------------------------------------- // Name: ScriptingInit() // Desc: @@ -731,194 +515,6 @@ void CNetSession::ScriptingInit( void ) { AddProperty( L"id", &CNetSession::m_ID ); AddProperty( L"name", &CNetSession::m_Name ); - AddMethod( "close", 0 ); CJSObject::ScriptingInit( "NetSession" ); } - -//----------------------------------------------------------------------------- -// Name: JSI_Close() -// Desc: -//----------------------------------------------------------------------------- -bool CNetSession::JSI_Close( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) ) -{ - return false; -} - -//----------------------------------------------------------------------------- -// Name: HandleMessage() -// Desc: -//----------------------------------------------------------------------------- -//bool CNetSession::HandleMessage( CNetMessage* pMessage ) -//{ -// return true; -//} - -/* -//----------------------------------------------------------------------------- -// Name: CNetServerSession() -// Desc: Constructor -//----------------------------------------------------------------------------- -CNetServerSession::CNetSession( - CNetServer* pServer, - NetMessageHandler* pHandler ) -: CNetSession( pHandler ) -{ - m_Server = pServer; - m_Player = NULL; - m_PlayerSlot = NULL; - m_IsObserver = false; - - //ONCE( ScriptingInit() ); -} - -//----------------------------------------------------------------------------- -// Name: CNetServerSession() -// Desc: Constructor -//----------------------------------------------------------------------------- -CNetServerSession::CNetSession( - CNetServer* pServer, - CSocketInternal* pSocketInternal, - NetMessageHandler* pHandler ) -: CNetSession( pSocketInternal, pHandler ) -{ - m_Server = pServer; - m_Player = NULL; - m_PlayerSlot = NULL; - m_IsObserver = false; - - //ONCE( ScriptingInit() ); -} - -//----------------------------------------------------------------------------- -// Name: ~CNetServerSession() -// Desc: Destructor -//----------------------------------------------------------------------------- -CNetServerSession::~CNetServerSession( void ) -{ -} - -//----------------------------------------------------------------------------- -// Name: StartGame() -// Desc: Called by server after informing all clients about starting the game -//----------------------------------------------------------------------------- -void CNetServerSession::StartGame( void ) -{ -} - -//----------------------------------------------------------------------------- -// Name: SetPlayer() -// Desc: Set the player for this session -//----------------------------------------------------------------------------- -void CNetServerSession::SetPlayer( CPlayer* pPlayer ) -{ - m_Player = pPlayer; -} - -//----------------------------------------------------------------------------- -// Name: SetPlayerSlot() -// Desc: Set the player slot for this session -//----------------------------------------------------------------------------- -void CNetServerSession::SetPlayerSlot( CPlayerSlot* pPlayerSlot ) -{ - m_PlayerSlot = pPlayerSlot; -} - -//----------------------------------------------------------------------------- -// Name: SetID() -// Desc: Set new session ID -//----------------------------------------------------------------------------- -void CNetServerSession::SetID( uint ID ) -{ - m_ID = ID; -} - -//----------------------------------------------------------------------------- -// Name: BaseHandler() -// Desc: -//----------------------------------------------------------------------------- -bool CNetServerSession::BaseHandler( - CNetMessage* pMessage, - CNetSession* pSession ) -{ - debug_assert( pMessage ); - debug_assert( pSession ); - - // Validate parameters - if ( !pMessage || !pSession ) return false; - - CNetServerSession* pSrvSession = dynamic_cast< CNetSession* >( pSession ); - if ( pSrvSession ) return false; - - // Handler NMT_ERROR message only - if ( pMessage->GetType() != NMT_ERROR ) return false; - - CNetErrorMessage* pErrMessage = dynamic_cast< CNetErrorMessage* >( pMessage ); - if ( !pErrMessage ) return false; - - if ( pErrMessage->GetState() == SERVER_STATE_DISCONNECTED ) - { - if ( pSrvSession->m_ID != -1 ) - { - pSrvSession->m_Server->RemoveSession( pSrvSession ); - } - - delete pSrvSession; - } - else - { - // Not disconnected? Weired... - LOG( WARNING, LOG_CATEGORY, L"CNetServerSession::BaseHandler() NMT_ERROR: %hs", pErrMessage->ToString().c_str() ); - } - - delete pMessage; - - return true; -} - -//----------------------------------------------------------------------------- -// Name: HandshakeHandler() -// Desc: -//----------------------------------------------------------------------------- -bool CNetServerSession::HandshakeHandler( - CNetMessage* pMessage, - CNetSession* pSession ) -{ - debug_assert( pMessage ); - debug_assert( pSession ); - debug_assert( m_Server ); - - // Validate parameters - if ( !pMessage || !pSession ) return false; - - CNetServerSession* pSrvSession = dynamic_cast< CNetServerSession* >( pSession ); - if ( !pSrvSession ) return false; - - LOG( NORMAL, LOG_CATEGORY, L"CNetServerSession::HandshakeHandler() %hs", pMessage->ToString().c_str() ); - - // Call base handler if other message thant NMT_ClientHandshake - if ( pMessage->GetType() != NMT_ClientHandshake ) BaseHandler( pMessage, pSession ); - - CClientHandshake* pHandshakeMessage = dynamic_cast< CClientHandshake* >( pMessage ); - if ( !pHandshakeMessage ) return false; - - if ( pHandshakeMessage->m_ProtocolVersion != PS_PROTOCOL_VERSION ) - { - pSrvSession->Push( new CCloseRequestMessage() ); - BaseHandler( new CNetErrorMessage( PS_OK, SERVER_STATE_DISCONNECTED ), pSrvSession ); - } - - //??? (else) - CServerHandshakeResponse* pNewMessage = new CServerHandshakeResponse(); - pNewMessage->m_UseProtocolVersion = PS_PROTOCOL_VERSION; - pNewMessage->m_Flags = 0; - pNewMessage->m_Message = pSrvSession->m_Server->m_WelcomeMessage; - - pSrvSession->Push( pNewMessage ); - - pSrvSession->m_MessageHandler = AuthHandler; - - delete pMessage; - - return true; -}*/ diff --git a/source/network/NetSession.h b/source/network/NetSession.h index 81444766c0..00e6408d4a 100644 --- a/source/network/NetSession.h +++ b/source/network/NetSession.h @@ -29,7 +29,6 @@ // INCLUDES #include "Network.h" #include "ps/GameAttributes.h" -#include "ps/Player.h" #include "fsm.h" #include @@ -66,6 +65,8 @@ typedef std::vector< PeerSession > PeerSessionList; class CNetHost { + NONCOPYABLE(CNetHost); + public: CNetHost( void ); @@ -82,13 +83,6 @@ public: */ virtual bool IsServer( void ) const { return false; } - /** - * Indicates whether the host is currently a client - * - * @return Boolean indicating whether the host is a client - */ - virtual bool IsClient( void ) const { return false; } - /** * Returns the number of sessions for the host * @@ -153,14 +147,6 @@ public: protected: - /** - * Attempts to resize the internal buffer to the size indicated by the - * passed parameter. - * - * @param size The new size for the buffer - */ - void ResizeBuffer( size_t size ); - // Allow application to handle new client connect virtual bool SetupSession ( CNetSession* pSession ); virtual bool HandleConnect ( CNetSession* pSession ); @@ -168,27 +154,11 @@ protected: virtual bool HandleMessageReceive ( CNetMessage* pMessage, CNetSession* pSession ); - - /** - * Worker thread function - * - * @pData Argument specified on thread creation - * @return NULL - */ - //static void* WorkerFunc( void* pData ); - private: - // Not implemented - CNetHost( const CNetHost& ); - CNetHost& operator=( const CNetHost& ); - - u8* m_Buffer; // Serialize out messages buffer - size_t m_BufferSize; // Output buffer size + std::vector m_Buffer; // Serialize out messages buffer ENetHost* m_Host; // Represents this host PeerSessionList m_PeerSessions; // Session list of connected peers - //pthread_t m_WorkerID; // Worker thread - //sem_t* m_StopWorker; // Worker thread stop semaphore }; /* @@ -208,8 +178,7 @@ private: */ class CNetSession : public CFsm, - public CJSObject< CNetSession >, - public IMessagePipeEnd + public CJSObject< CNetSession > { NONCOPYABLE(CNetSession); @@ -247,44 +216,10 @@ public: */ void SetID( uint ID ); - /** - * Allows both client and server to set a callback handler - * - * @param pCallbackHandler Callback handler - */ - //void SetCallbackHandler( ISessionCallback* pCallbackHandler ); - - /** - * Disconnects the client from remote host - * - */ - void Reset( void ); - - void SetPlayer( CPlayer* pPlayer ); - CPlayer* GetPlayer( void ) { return m_Player; } void SetPlayerSlot( CPlayerSlot* pPlayerSlot ); CPlayerSlot* GetPlayerSlot( void ) { return m_PlayerSlot; } - void StartGame( void ); - virtual void Push( CNetMessage* pMessage ); - virtual CNetMessage* TryPop( void ); - bool IsReadyForTurn( void ) const { return m_ReadyForTurn; } - void SetReadyForTurn( bool newValue ) { m_ReadyForTurn = newValue; } - bool JSI_Close( JSContext *cx, uintN argc, jsval *argv ); static void ScriptingInit( void ); - //bool HandleMessage( CNetMessage* pMessage ); - -protected: - - /** - * Process the message passed as parameter - * - * @param message The message to process - * @return true if the message was handler - * successufully, false otherwise - */ - //bool ProcessMessage( const CNetMessage& message ); - private: // Only the hosts can create sessions @@ -294,61 +229,8 @@ private: ENetPeer* m_Peer; // Represents the peer host uint m_ID; // Session ID CStrW m_Name; // Session name - CPlayer* m_Player; CPlayerSlot* m_PlayerSlot; - bool m_ReadyForTurn; // Next turn ready flag }; -/* - CLASS : CNetServerSession - DESCRIPTION : - NOTES : -*/ - -/*class CNetServerSession : public CNetSession, - public CJSObject< CNetServerSession > -{ -public: - - bool IsObserver ( void ) const { return m_IsObserver; } - CPlayer* GetPlayer ( void ) const { return m_Player; } - CPlayerSlot* GetPlayerSlot ( void ) const { return m_PlayerSlot; } - void StartGame ( void ); - void SetPlayer ( CPlayer* pPlayer ); - void SetPlayerSlot ( CPlayerSlot* pPlayerSlot ); - -protected: - - CNetServerSession( - CNetServer* pServer, - NetMessageHandler* pHandler = m_HandshakeHandler ); - CNetServerSession( - CNetServer* pServer, - CSocketInternal* pSocketInternal, - NetMessageHandler* pHandler = m_HandshakeHandler ); - virtual ~CNetServerSession( void ); - -private: - - static void ScriptingInit ( void ); - bool JSI_Close ( - JSContext* pContext, - uintN argc, - jsval* argv ); - - CNetServer* m_Server; - CPlayer* m_Player; - CPlayerSlot* m_PlayerSlot; - bool m_IsObserver; - - static bool HandshakeHandler( CNetMessage* pMessage, CNetSession* pSession ); - static bool ObserverHandler ( CNetMessage* pMessage, CNetSession* pSession ); - static bool BaseHandler ( CNetMessage* pMessage, CNetSession* pSession ); - static bool AuthHandler ( CNetMessage* pMessage, CNetSession* pSession ); - static bool PreGameHandler ( CNetMessage* pMessage, CNetSession* pSession ); - static bool InGameHandler ( CNetMessage* pMessage, CNetSession* pSession ); - static bool ChatHandler ( CNetMessage* pMessage, CNetSession* pSession ); -};*/ - #endif // NETSESSION_H diff --git a/source/network/Network.cpp b/source/network/Network.cpp index 50c0964ec9..a2337d31b8 100644 --- a/source/network/Network.cpp +++ b/source/network/Network.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2009 Wildfire Games. +/* Copyright (C) 2010 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -15,419 +15,20 @@ * along with 0 A.D. If not, see . */ - #include "precompiled.h" #include "Network.h" -#include "Serialization.h" -#include "ps/CLogger.h" -#include "NetLog.h" - -DEFINE_ERROR(CONFLICTING_OP_IN_PROGRESS, "A conflicting operation is already in progress"); - -#define LOG_CATEGORY L"net" - -/** - * The SNetHeader will always be stored in host-order - */ -struct SNetHeader +CStr CErrorMessage::ToString() const { - u8 m_MsgType; - u16 m_MsgLength; - - inline const u8 *Deserialize(const u8 *pos) - { - Deserialize_int_1(pos, m_MsgType); - Deserialize_int_2(pos, m_MsgLength); - return pos; - } - - inline u8 *Serialize(u8 *pos) const - { - Serialize_int_1(pos, m_MsgType); - Serialize_int_2(pos, m_MsgLength); - return pos; - } -}; -#define HEADER_LENGTH 3 - -CMessagePipe::CMessagePipe() -{ - m_Ends[0]=End(this, &m_Queues[0], &m_Queues[1]); - m_Ends[1]=End(this, &m_Queues[1], &m_Queues[0]); -// pthread_cond_init(&m_CondVar, NULL); + return CStr("NetErrorMessage: ") + m_Error; } -void CMessagePipe::End::Push(CNetMessage *msg) -{ - m_pOut->Lock(); - m_pOut->push_back(msg); - m_pOut->Unlock(); - /*pthread_mutex_lock(&m_pPipe->m_CondMutex); - pthread_cond_broadcast(&m_pPipe->m_CondVar); - pthread_mutex_unlock(&m_pPipe->m_CondMutex);*/ -} - -CNetMessage *CMessagePipe::End::TryPop() -{ - CScopeLock lock(m_pIn->m_Mutex); - if (m_pIn->size()) - { - CNetMessage *msg=m_pIn->front(); - m_pIn->pop_front(); - return msg; - } - return NULL; -} - -/*void CMessagePipe::End::WaitPop(CNetMessage *msg) -{ - while (!TryPop(msg)) - { - pthread_mutex_lock(&m_pPipe->m_CondMutex); - pthread_cond_wait(&m_pPipe->m_CondVar, &m_pPipe->m_CondMutex); - pthread_mutex_unlock(&m_pPipe->m_CondMutex); - } -}*/ - -/*CStr CErrorMessage::GetString() const -{ - static const char* const states[]={ - "SS_UNCONNECTED", - "SS_CONNECT_STARTED", - "SS_CONNECTED", - "SS_CLOSED_LOCALLY" - }; - - return CStr("NetErrorMessage: ")+ - m_Error+", Socket State "+states[m_State]; -} - -CStr CConnectCompleteMessage::GetString() const +CStr CConnectCompleteMessage::ToString() const { return CStr("ConnectCompleteMessage"); } -CStr CCloseRequestMessage::GetString() const +CStr CCloseRequestMessage::ToString() const { return CStr("CloseRequestMessage"); -}*/ - -CStr CErrorMessage::ToString( void ) const -{ - static const char* const states[]= - { - "SS_UNCONNECTED", - "SS_CONNECT_STARTED", - "SS_CONNECTED", - "SS_CLOSED_LOCALLY" - }; - - return CStr("NetErrorMessage: ")+ - m_Error+", Socket State "+states[m_State]; } - -CStr CConnectCompleteMessage::ToString( void ) const -{ - return CStr( "ConnectCompleteMessage" ); -} - -CStr CCloseRequestMessage::ToString( void ) const -{ - return CStr( "CloseRequestMessage" ); -} - -void CMessageSocket::Push(CNetMessage *msg) -{ - NET_LOG2( "CMessageSocket::Push(): %s", msg->ToString().c_str() ); - - m_OutQ.Lock(); - m_OutQ.push_back(msg); - m_OutQ.Unlock(); - StartWriteNextMessage(); -} - -CNetMessage *CMessageSocket::TryPop() -{ - CScopeLock lock(m_InQ.m_Mutex); - if (m_InQ.size()) - { - CNetMessage *msg=m_InQ.front(); - m_InQ.pop_front(); - return msg; - } - return NULL; -} - - -void CMessageSocket::StartWriteNextMessage() -{ - m_OutQ.Lock(); - if (!m_IsWriting && m_OutQ.size()) - { - CNetMessage *pMsg=NULL; - while (pMsg == NULL) - { - // This may happen when the last message of the queue is an invalid - // message type (non-network or socket command) - if (m_OutQ.size() == 0) - return; - - // Pop next output message - pMsg=m_OutQ.front(); - m_OutQ.pop_front(); - m_IsWriting=true; - m_OutQ.Unlock(); - - if (pMsg->GetType() == NMT_CLOSE_REQUEST) - { - Close(); - delete pMsg; - pMsg=NULL; - } - else if (pMsg->GetType() < 0) - { - LOG(CLogger::Warning, LOG_CATEGORY, L"CMessageSocket::StartWriteNextMessage(): Non-network message"); - delete pMsg; - pMsg=NULL; - } - } - - // Prepare the header - SNetHeader hdr; - hdr.m_MsgType=pMsg->GetType(); - hdr.m_MsgLength=(u16)pMsg->GetSerializedLength(); - - // Allocate buffer space - if ((size_t)(hdr.m_MsgLength+HEADER_LENGTH) > m_WrBufferSize) - { - //m_WrBufferSize = BUFFER_SIZE(hdr.m_MsgLength+HEADER_LENGTH); - m_WrBufferSize = ALIGN_BLOCK(hdr.m_MsgLength+HEADER_LENGTH); - if (m_pWrBuffer) - m_pWrBuffer=(u8 *)realloc(m_pWrBuffer, m_WrBufferSize); - else - m_pWrBuffer=(u8 *)malloc(m_WrBufferSize); - } - - // Fill in buffer - u8 *pos=m_pWrBuffer; - pos=hdr.Serialize(pos); - pMsg->Serialize(pos); - - // Deallocate message - delete pMsg; - - // Start Write Operation - //printf("CMessageSocket::StartWriteNextMessage(): Writing an MT %d, length %u (%u)\n", hdr.m_MsgType, hdr.m_MsgLength+HEADER_LENGTH, hdr.m_MsgLength); - PS_RESULT res=Write(m_pWrBuffer, hdr.m_MsgLength+HEADER_LENGTH); - if (res != PS_OK) - { - NET_LOG2( "CMessageSocket::StartWriteNextMessage(): %s", res ); - - // Queue Error Message - m_InQ.Lock(); - m_InQ.push_back(new CErrorMessage(res, GetState())); - m_InQ.Unlock(); - } - } - else - { - if (m_IsWriting) - { - NET_LOG( "CMessageSocket::StartWriteNextMessage(): Already writing" ); - } - else - { - NET_LOG("CMessageSocket::StartWriteNextMessage(): Nothing to write"); - } - m_OutQ.Unlock(); - } -} - -void CMessageSocket::WriteComplete(PS_RESULT ec) -{ - NET_LOG2( "CMessageSocket::WriteComplete(): %s", ec ); - - if (ec == PS_OK) - { - if (m_IsWriting) - { - m_OutQ.Lock(); - m_IsWriting=false; - m_OutQ.Unlock(); - StartWriteNextMessage(); - } - else - { - NET_LOG( "CMessageSocket::WriteComplete(): Was not writing" ); - } - } - else - { - // Push an error message - m_InQ.push_back(new CErrorMessage(ec, GetState())); - } -} - -void CMessageSocket::StartReadHeader() -{ - if (m_RdBufferSize < HEADER_LENGTH) - { - //m_RdBufferSize=BUFFER_SIZE(HEADER_LENGTH); - m_RdBufferSize=ALIGN_BLOCK(HEADER_LENGTH); - if (m_pRdBuffer) - m_pRdBuffer=(u8 *)realloc(m_pRdBuffer, m_RdBufferSize); - else - m_pRdBuffer=(u8 *)malloc(m_RdBufferSize); - } - m_ReadingData=false; - printf("CMessageSocket::StartReadHeader(): Trying to read %u\n", HEADER_LENGTH); - PS_RESULT res=Read(m_pRdBuffer, HEADER_LENGTH); - if (res != PS_OK) - { - NET_LOG2( "CMessageSocket::StartReadHeader(): %s", res ); - - // Push an error message - CScopeLock scopeLock(m_InQ.m_Mutex); - m_InQ.push_back(new CErrorMessage(res, GetState())); - } -} - -void CMessageSocket::StartReadMessage() -{ - SNetHeader hdr; - hdr.Deserialize(m_pRdBuffer); - - size_t reqBufSize=HEADER_LENGTH+hdr.m_MsgLength; - if (m_RdBufferSize < reqBufSize) - { - //m_RdBufferSize=BUFFER_SIZE(reqBufSize); - m_RdBufferSize=ALIGN_BLOCK(reqBufSize); - if (m_pRdBuffer) - m_pRdBuffer=(u8 *)realloc(m_pRdBuffer, m_RdBufferSize); - else - m_pRdBuffer=(u8 *)malloc(m_RdBufferSize); - } - m_ReadingData=true; - - if (hdr.m_MsgLength == 0) - { - ReadComplete(PS_OK); - } - else - { - PS_RESULT res=Read(m_pRdBuffer+HEADER_LENGTH, hdr.m_MsgLength); - if (res != PS_OK) - { - NET_LOG2( "CMessageSocket::StartReadMessage(): %s", res ); - - // Queue an error message - CScopeLock scopeLock(m_InQ); - m_InQ.push_back(new CErrorMessage(res, GetState())); - } - } -} - -void CMessageSocket::ReadComplete(PS_RESULT ec) -{ - NET_LOG3( "CMessageSocket::ReadComplete(%ls): %s", m_ReadingData ? L"data":L"header", ec ); - - // Check if we were reading header or message - // If header: - if (!m_ReadingData) - { - StartReadMessage(); - } - // If data: - else - { - SNetHeader hdr; - hdr.Deserialize(m_pRdBuffer); - //CNetMessage *pMsg=CNetMessage::DeserializeMessage((ENetMessageType)hdr.m_MsgType, m_pRdBuffer+HEADER_LENGTH, hdr.m_MsgLength); - CNetMessage *pMsg = CNetMessageFactory::CreateMessage( m_pRdBuffer+HEADER_LENGTH, hdr.m_MsgLength); - if (pMsg) - { - OnMessage(pMsg); - } - else - { - NET_LOG3( "CMessageSocket::ReadComplete(): Deserialization failed! (type %d, length %d)", hdr.m_MsgType, hdr.m_MsgLength ); - NET_LOG( "Data: {" ); - - for (int i=HEADER_LENGTH;iToString().c_str() ); - NET_LOG2( "CMessageSocket::OnMessage(): Queue size now %lu", (unsigned long)m_InQ.size() ); - m_InQ.Unlock(); -} - -void CMessageSocket::ConnectComplete(PS_RESULT ec) -{ - if (ec == PS_OK) - { - StartReadHeader(); - CScopeLock scopeLock(m_InQ); - m_InQ.push_back(new CConnectCompleteMessage()); - } - else - { - CScopeLock scopeLock(m_InQ); - m_InQ.push_back(new CErrorMessage(ec, GetState())); - } -} - -void CMessageSocket::OnClose(PS_RESULT errorCode) -{ - CScopeLock scopeLock(m_InQ.m_Mutex); - m_InQ.push_back(new CErrorMessage(errorCode, GetState())); -} - -CMessageSocket::CMessageSocket(CSocketInternal *pInt): - CStreamSocket(pInt), - m_IsWriting(false), - m_pWrBuffer(NULL), - m_WrBufferSize(0), - m_ReadingData(false), - m_pRdBuffer(NULL), - m_RdBufferSize(0) -{ - StartReadHeader(); -} - -CMessageSocket::CMessageSocket(): - m_IsWriting(false), - m_pWrBuffer(NULL), - m_WrBufferSize(0), - m_ReadingData(false), - m_pRdBuffer(NULL), - m_RdBufferSize(0) -{ -} - -CMessageSocket::~CMessageSocket() -{ - if (m_pRdBuffer) - free(m_pRdBuffer); - if (m_pWrBuffer) - free(m_pWrBuffer); -} - -PS_RESULT CMessageSocket::BeginConnect(const char *address, int port) -{ - StartReadHeader(); - return CStreamSocket::BeginConnect(address, port); -} - -// End of Network.cpp diff --git a/source/network/Network.h b/source/network/Network.h index 992534e230..87da0f4b10 100644 --- a/source/network/Network.h +++ b/source/network/Network.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2009 Wildfire Games. +/* Copyright (C) 2010 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -15,279 +15,48 @@ * along with 0 A.D. If not, see . */ -/* -Network.h - -OVERVIEW - - Contains the public interfaces to the networking code. - - CMessageSocket is a socket that sends and receives messages from the - network. The global interface for sending and receiving messages is - an IMessagePipeEnd. - - CMessagePipe also uses IMessagePipeEnd as its public interface, meaning that - a CMessageSocket can be invisibly replaced with a CMessagePipe. Thus, the - difference between MP and SP games is the source of pipe ends. - - Code that just wants to send messages will most likely only be confronted - with the message pipe end interface. - -EXAMPLES - -To create a queue pair for IPC communication: - - CMessagePipe pipe; - StartThread1(pipe[0]); - StartThread2(pipe[1]); - - The argument type for StartThreadX would be "IMessagePipeEnd &". - -NOTES ON THREAD SAFETY - -All operations on an IMessagePipeEnd are fully thread-secure. Multiple access -to other interfaces of a CMessageSocket is not secure (but the IMessagePipeEnd -interface to a CMessageSocket is still fully thread secure) - -MORE INFO - -*/ - #ifndef INCLUDED_NETWORK_NETWORK #define INCLUDED_NETWORK_NETWORK -//-------------------------------------------------------- -// Includes / Compiler directives -//-------------------------------------------------------- - #include "ps/Pyrogenesis.h" -#include "ps/ThreadUtil.h" - -#include "StreamSocket.h" - #include "NetMessage.h" -#include "lib/bits.h" // round_up -#include -#include - -//------------------------------------------------- -// Typedefs and Macros -//------------------------------------------------- -#define ALIGN_BLOCK( _n ) round_up(size_t(_n), size_t(4096)) - -typedef CLocker > CLockedMessageDeque; - -//------------------------------------------------- -// Error Codes -//------------------------------------------------- - -DECLARE_ERROR( CONFLICTING_OP_IN_PROGRESS ); - -//------------------------------------------------- -// Declarations -//------------------------------------------------- - -class IMessagePipeEnd; -class CMessagePipe; -class CMessageSocket; - -class IMessagePipeEnd -{ -public: - virtual ~IMessagePipeEnd() {} - - /** - * Push a message on the output queue. It will be freed when popped of the - * queue, not by the caller. The pointer must point to memory that can be - * safely freed by delete. - */ - virtual void Push(CNetMessage *msg)=0; - - /** - * Try to pop a message from the input queue - * - * @return A pointer to the popped message, or NULL if the queue was empty - */ - virtual CNetMessage *TryPop()=0; - - /** - * Wait for a message on the input queue - * - * Inputs - * pMsg: A pointer to a message struct to store the popped message - * - * Returns - * Void. The function returns successfully or blocks indefinitely. - */ -// virtual void WaitPop(CNetMessage *)=0; -}; - -/** - * A message pipe with two ends, communication flowing in both directions. - * The two ends are indexed with the [] operator or the GetEnd() method. - * Each end has two associated queues, one input and one output queue. The - * input queue of one End is the output queue of the other End and vice versa. - */ -class CMessagePipe -{ -private: - friend struct End; - - struct End: public IMessagePipeEnd - { - CMessagePipe *m_pPipe; - CLockedMessageDeque *m_pIn; - CLockedMessageDeque *m_pOut; - - inline End() - {} - - inline End(CMessagePipe *pPipe, CLockedMessageDeque *pIn, CLockedMessageDeque *pOut): - m_pPipe(pPipe), m_pIn(pIn), m_pOut(pOut) - {} - - virtual ~End() {} - - virtual void Push(CNetMessage *); - virtual CNetMessage *TryPop(); - //virtual void WaitPop(CNetMessage *); - }; - - CLockedMessageDeque m_Queues[2]; - End m_Ends[2]; -// pthread_cond_t m_CondVar; - pthread_mutex_t m_CondMutex; - -public: - CMessagePipe(); - - /** - * Return one of the two ends of the pipe - */ - inline IMessagePipeEnd &operator [] (int idx) - { - return GetEnd(idx); - } - - /** - * Return one of the two ends of the pipe - */ - inline IMessagePipeEnd &GetEnd(int idx) - { - debug_assert(idx==1 || idx==0); - return m_Ends[idx]; - } -}; - -class CServerSocket: public CSocketBase -{ -protected: - /** - * The default implementation of this method accepts an incoming connection - * and calls OnAccept() with the accepted internal socket instance. - * - * NOTE: Subclasses should never overload this method, overload OnAccept() - * instead. - */ - virtual void OnRead(); - - virtual void OnWrite(); - virtual void OnClose(PS_RESULT errorCode); - -public: - virtual ~CServerSocket(); - - /** - * There is an incoming connection in the queue. Examine the SocketAddress - * and call Accept() or Reject() to accept or reject the incoming - * connection - * - * @see CSocketBase::Accept() - * @see CSocketBase::Reject() - */ - virtual void OnAccept(const CSocketAddress &)=0; -}; - -class CErrorMessage: public CNetMessage +class CErrorMessage : public CNetMessage { public: PS_RESULT m_Error; - ESocketState m_State; - inline CErrorMessage(): + inline CErrorMessage() : CNetMessage(NMT_ERROR) - {} + { + } - inline CErrorMessage(PS_RESULT error, ESocketState state): - CNetMessage(NMT_ERROR), - m_Error(error), - m_State(state) - {} + inline CErrorMessage(PS_RESULT error) : + CNetMessage(NMT_ERROR), m_Error(error) + { + } virtual CStr ToString() const; }; -struct CCloseRequestMessage: public CNetMessage +struct CCloseRequestMessage : public CNetMessage { - inline CCloseRequestMessage(): CNetMessage(NMT_CLOSE_REQUEST) - {} + inline CCloseRequestMessage() : + CNetMessage(NMT_CLOSE_REQUEST) + { + } virtual CStr ToString() const; }; -struct CConnectCompleteMessage: public CNetMessage +struct CConnectCompleteMessage : public CNetMessage { - inline CConnectCompleteMessage(): CNetMessage(NMT_CONNECT_COMPLETE) - {} + inline CConnectCompleteMessage() : + CNetMessage(NMT_CONNECT_COMPLETE) + { + } virtual CStr ToString() const; }; -/** - * Implements a Message Pipe over an Async IO stream socket. - * - * All methods that this class exposes are thread safe and may be called from - * any thread. - */ -class CMessageSocket: protected CStreamSocket, public IMessagePipeEnd -{ - bool m_IsWriting; - u8 *m_pWrBuffer; - size_t m_WrBufferSize; - bool m_ReadingData; - u8 *m_pRdBuffer; - size_t m_RdBufferSize; - - CLockedMessageDeque m_InQ; // Messages read from socket - CLockedMessageDeque m_OutQ;// Messages to write to socket -// pthread_cond_t m_InCond; -// pthread_cond_t m_OutCond; - - void StartWriteNextMessage(); - void StartReadHeader(); - void StartReadMessage(); -protected: - virtual void ReadComplete(PS_RESULT); - virtual void WriteComplete(PS_RESULT); - virtual void OnClose(PS_RESULT); - virtual void ConnectComplete(PS_RESULT); - - virtual void OnMessage(CNetMessage *pMsg); - -public: - CMessageSocket(CSocketInternal *pInt); - CMessageSocket(); - - virtual ~CMessageSocket(); - - virtual void Push(CNetMessage *); - virtual CNetMessage *TryPop(); - - /** - * See CStreamSocket::BeginConnect. - */ - PS_RESULT BeginConnect(const char *address, int port); -}; - #endif diff --git a/source/network/NetworkInternal.h b/source/network/NetworkInternal.h deleted file mode 100644 index 929e1ab6d3..0000000000 --- a/source/network/NetworkInternal.h +++ /dev/null @@ -1,113 +0,0 @@ -/* Copyright (C) 2009 Wildfire Games. - * This file is part of 0 A.D. - * - * 0 A.D. 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, either version 2 of the License, or - * (at your option) any later version. - * - * 0 A.D. 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 0 A.D. If not, see . - */ - -#ifndef INCLUDED_NETWORK_NETWORKINTERNAL -#define INCLUDED_NETWORK_NETWORKINTERNAL - -#include - -#if !OS_WIN - -#define Network_GetErrorString(_error, _buf, _buflen) strerror_r(_error, _buf, _buflen) - -#define Network_LastError errno - -#define closesocket(_fd) close(_fd) - -#else // i.e. #if OS_WIN - -#define Network_GetErrorString(_error, _buf, _buflen) \ - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, _error+WSABASEERR, 0, _buf, _buflen, NULL) -#define Network_LastError (WSAGetLastError() - WSABASEERR) -// These are defined so that WSAGLE - WSABASEERR = E* -// i.e. the same error name can be used in winsock and posix -#define WSABASEERR 10000 - -#define MSG_SOCKET_READY WM_USER - -#endif // #if OS_WIN - -typedef int socket_t; - -class CSocketInternal -{ -public: - socket_t m_fd; - CSocketAddress m_RemoteAddr; - - socket_t m_AcceptFd; - CSocketAddress m_AcceptAddr; - - // Bitwise OR of all operations to listen for. - // See READ and WRITE - int m_Ops; - - char *m_pConnectHost; - int m_ConnectPort; - - u64 m_SentBytes; - u64 m_RecvBytes; - - inline CSocketInternal(): - m_fd(-1), - m_AcceptFd(-1), - m_Ops(0), - m_pConnectHost(NULL), - m_ConnectPort(-1), - m_SentBytes(0), - m_RecvBytes(0) - { - } -}; - -struct CSocketSetInternal -{ - // Any access to the global variables should be protected using m_Mutex - pthread_mutex_t m_Mutex; - pthread_t m_Thread; - - size_t m_NumSockets; - - std::map m_HandleMap; -#if OS_WIN - HWND m_hWnd; -#else - // [0] is for use by RunWaitLoop, [1] for SendWaitLoopAbort and SendWaitLoopUpdate - int m_Pipe[2]; -#endif - - u64 m_GlobalSentBytes; - u64 m_GlobalRecvBytes; - -public: - inline CSocketSetInternal() - { -#if OS_WIN - m_hWnd=NULL; -#else - m_Pipe[0]=-1; - m_Pipe[1]=-1; -#endif - pthread_mutex_init(&m_Mutex, NULL); - m_Thread=0; - m_NumSockets=0; - m_GlobalSentBytes=0; - m_GlobalRecvBytes=0; - } -}; - -#endif diff --git a/source/network/ServerSocket.cpp b/source/network/ServerSocket.cpp deleted file mode 100644 index e78510fda8..0000000000 --- a/source/network/ServerSocket.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright (C) 2009 Wildfire Games. - * This file is part of 0 A.D. - * - * 0 A.D. 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, either version 2 of the License, or - * (at your option) any later version. - * - * 0 A.D. 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 0 A.D. If not, see . - */ - -#include "precompiled.h" - -#include "Network.h" -#include "NetLog.h" - -CServerSocket::~CServerSocket() -{ -} - -void CServerSocket::OnRead() -{ - CSocketAddress remoteAddr; - - PS_RESULT res=PreAccept(remoteAddr); - if (res==PS_OK) - { - OnAccept(remoteAddr); - } - else - { - // All errors are non-critical, so no need to do anything special besides - // not calling OnAccept [ shouldn't be, that is ;-) ] - NET_LOG2( "CServerSocket::OnRead(): PreAccept returned an error: %s", res ); - } -} - -void CServerSocket::OnWrite() -{} - -void CServerSocket::OnClose(PS_RESULT UNUSED(errorCode)) -{} diff --git a/source/network/SocketBase.cpp b/source/network/SocketBase.cpp deleted file mode 100644 index aabe75ee4f..0000000000 --- a/source/network/SocketBase.cpp +++ /dev/null @@ -1,1001 +0,0 @@ -/* Copyright (C) 2009 Wildfire Games. - * This file is part of 0 A.D. - * - * 0 A.D. 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, either version 2 of the License, or - * (at your option) any later version. - * - * 0 A.D. 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 0 A.D. If not, see . - */ - -#include "precompiled.h" - -#if OS_WIN -#include "lib/sysdep/os/win/win.h" -#include "lib/sysdep/os/win/wposix/wsock.h" -#include "lib/sysdep/os/win/wposix/wsock_internal.h" -#endif - -#include "lib/sysdep/cpu.h" - -#include "Network.h" -#include "NetworkInternal.h" - -#include "ps/CStr.h" -// ERROR is defined by some windows header. Undef it -#undef ERROR -#include "ps/CLogger.h" -#include "NetLog.h" - -#if !OS_WIN -# include -# include -# include -#endif - -#define LOG_CATEGORY L"net" - -// Record global transfer statistics (sent/recvd bytes). This will put a lock -// /unlock pair in all read and write operations. -#define RECORD_GLOBAL_STATS 1 - -#define GLOBAL_LOCK() pthread_mutex_lock(&g_SocketSetInternal.m_Mutex) -#define GLOBAL_UNLOCK() pthread_mutex_unlock(&g_SocketSetInternal.m_Mutex) - -CSocketSetInternal g_SocketSetInternal; - -DEFINE_ERROR(NO_SUCH_HOST, "Host not found"); -DEFINE_ERROR(CONNECT_TIMEOUT, "The connection attempt timed out"); -DEFINE_ERROR(CONNECT_REFUSED, "The connection attempt was refused"); -DEFINE_ERROR(NO_ROUTE_TO_HOST, "No route to host"); -DEFINE_ERROR(CONNECTION_BROKEN, "The connection has been closed"); -DEFINE_ERROR(CONNECT_IN_PROGRESS, "The connect attempt has started, but is not yet complete"); -DEFINE_ERROR(PORT_IN_USE, "The port is already in use by another process"); -DEFINE_ERROR(INVALID_PORT, "The port specified is either invalid, or forbidden by system or firewall policy"); -DEFINE_ERROR(INVALID_PROTOCOL, "The socket type or protocol is not supported by the operating system. Make sure that the TCP/IP protocol is installed and activated"); - -// Map an OS error number to a PS_RESULT -PS_RESULT GetPS_RESULT(int error) -{ - switch (error) - { - case EWOULDBLOCK: - case EINPROGRESS: - return PS_OK; - case ENETUNREACH: - case ENETDOWN: - case EADDRNOTAVAIL: - return NO_ROUTE_TO_HOST; - case ETIMEDOUT: - return CONNECT_TIMEOUT; - case ECONNREFUSED: - return CONNECT_REFUSED; - default: - char buf[256]; - Network_GetErrorString(error, buf, sizeof(buf)); - LOG(CLogger::Error, LOG_CATEGORY, L"SocketBase.cpp::GetPS_RESULT(): Unrecognized error %hs[%d]", buf, error); - return PS_FAIL; - } -} - -CSocketAddress::CSocketAddress(int port, ESocketProtocol proto) -{ - memset(&m_Union, 0, sizeof(m_Union)); - switch (proto) - { - case IPv4: - m_Union.m_IPv4.sin_family=PF_INET; - m_Union.m_IPv4.sin_addr.s_addr=htonl(INADDR_ANY); - m_Union.m_IPv4.sin_port=htons(port); - break; - case IPv6: - m_Union.m_IPv6.sin6_family=PF_INET6; - cpu_memcpy(&m_Union.m_IPv6.sin6_addr, &in6addr_any, sizeof(in6addr_any)); - m_Union.m_IPv6.sin6_port=htons(port); - break; - default: - debug_warn(L"CSocketAddress::CSocketAddress: Bad proto"); - } -} - -CSocketAddress CSocketAddress::Loopback(int port, ESocketProtocol proto) -{ - CSocketAddress ret; - switch (proto) - { - case IPv4: - ret.m_Union.m_IPv4.sin_family=PF_INET; - ret.m_Union.m_IPv4.sin_addr.s_addr=htonl(INADDR_LOOPBACK); - ret.m_Union.m_IPv4.sin_port=htons(port); - break; - case IPv6: - ret.m_Union.m_IPv6.sin6_family=PF_INET6; - cpu_memcpy(&ret.m_Union.m_IPv6.sin6_addr, &in6addr_loopback, sizeof(in6addr_loopback)); - ret.m_Union.m_IPv6.sin6_port=htons(port); - break; - default: - debug_warn(L"CSocketAddress::CSocketAddress: Bad proto"); - } - return ret; -} - -PS_RESULT CSocketAddress::Resolve(const char *name, int port, CSocketAddress &addr) -{ - // Use IPV4 by default, ignoring address type. - memset(&addr.m_Union, 0, sizeof(addr.m_Union)); - hostent *he; - addr.m_Union.m_IPv4.sin_family=AF_INET; - addr.m_Union.m_IPv4.sin_port=htons(port); - // Try to parse dot-notation IP - addr.m_Union.m_IPv4.sin_addr.s_addr=inet_addr(name); - if (addr.m_Union.m_IPv4.sin_addr.s_addr==INADDR_NONE) // Not a dotted IP, try name resolution - { - he=gethostbyname(name); - if (!he) - return NO_SUCH_HOST; - addr.m_Union.m_IPv4.sin_addr=*(struct in_addr *)(he->h_addr_list[0]); - } - return PS_OK; -} - -CStr CSocketAddress::GetString() const -{ - char convBuf[NI_MAXHOST]; - int res=getnameinfo((struct sockaddr *)&m_Union, sizeof(struct sockaddr_in), - convBuf, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); - if (res == 0) - return CStr(convBuf); - // getnameinfo won't return a string for the IPv6 unspecified address - else if (m_Union.m_Family == IPv6 && res==EAI_NONAME) - return "::"; - // supported, but failed - else if (errno != ENOSYS) - return ""; - // else: IPv6 not supported, fall back to IPv4 - - if (m_Union.m_Family == IPv4) - { - sprintf_s(convBuf, ARRAY_SIZE(convBuf), "%d.%d.%d.%d", - m_Union.m_IPv4.sin_addr.s_addr&0xff, - (m_Union.m_IPv4.sin_addr.s_addr>>8)&0xff, - (m_Union.m_IPv4.sin_addr.s_addr>>16)&0xff, - (m_Union.m_IPv4.sin_addr.s_addr>>24)&0xff); - return CStr(convBuf); - } - else - return CStr(); -} - -int CSocketAddress::GetPort() const -{ - switch (m_Union.m_Family) - { - case IPv4: - case IPv6: - return ntohs(m_Union.m_IPv4.sin_port); - } - return -1; -} - -CSocketBase::CSocketBase() -{ - m_pInternal=new CSocketInternal; - m_Proto=UNSPEC; - m_NonBlocking=true; - m_State=SS_UNCONNECTED; - m_Error=PS_OK; -} - -CSocketBase::CSocketBase(CSocketInternal *pInt) -{ - m_pInternal=pInt; - m_Proto=pInt->m_RemoteAddr.GetProtocol(); - m_State=SS_CONNECTED; - m_Error=PS_OK; - SetNonBlocking(true); - - NET_LOG2( "CSocketBase::CSocketBase(): Created socket from fd %d", pInt->m_fd ); -} - -CSocketBase::~CSocketBase() -{ - NET_LOG4( "CSocketBase::~CSocketBase(): fd is %d. " - "Received: %lu bytes. Sent: %lu bytes.", - m_pInternal->m_fd, - (unsigned long)m_pInternal->m_RecvBytes, - (unsigned long)m_pInternal->m_SentBytes ); - - Destroy(); - delete m_pInternal; -} - -void CSocketBase::Shutdown() -{ - GLOBAL_LOCK(); - - if (g_SocketSetInternal.m_NumSockets) - { - NET_LOG2( "CSocketBase::Shutdown(): %lu sockets still open! (forcing network shutdown)", (unsigned long)g_SocketSetInternal.m_NumSockets ); - } - -#if RECORD_GLOBAL_STATS - NET_LOG3( "GLOBAL SOCKET STATISTICS: " - "Received: %lu bytes. Sent: %lu bytes.", - (unsigned long)g_SocketSetInternal.m_GlobalRecvBytes, - (unsigned long)g_SocketSetInternal.m_GlobalSentBytes); -#endif - - GLOBAL_UNLOCK(); - if (g_SocketSetInternal.m_Thread) - { - AbortWaitLoop(); - pthread_join(g_SocketSetInternal.m_Thread, NULL); - } -} - -void *WaitLoopThreadMain(void *) -{ - debug_SetThreadName("net_wait"); - - GLOBAL_LOCK(); - CSocketBase::RunWaitLoop(); - - g_SocketSetInternal.m_Thread=0; - - GLOBAL_UNLOCK(); - return NULL; -} - -PS_RESULT CSocketBase::Initialize(ESocketProtocol proto) -{ - // Use IPV4 by default, ignoring address type. - int res=socket(AF_INET, SOCK_STREAM, 0); - - NET_LOG2("CSocketBase::Initialize(): socket() res: %d", res); - - if (res == -1) - { - return INVALID_PROTOCOL; - } - - m_pInternal->m_fd=res; - m_Proto=proto; - - GLOBAL_LOCK(); - if (g_SocketSetInternal.m_NumSockets == 0) - pthread_create(&g_SocketSetInternal.m_Thread, NULL, WaitLoopThreadMain, NULL); - g_SocketSetInternal.m_NumSockets++; - GLOBAL_UNLOCK(); - - SetNonBlocking(m_NonBlocking); - - return PS_OK; -} - -void CSocketBase::Close() -{ - shutdown(m_pInternal->m_fd, SHUT_WR); - m_State=SS_CLOSED_LOCALLY; -} - -void CSocketBase::Destroy() -{ - if (m_pInternal->m_fd == -1) - { - m_State=SS_UNCONNECTED; - return; - } - - // Remove any data associated with the file descriptor - GLOBAL_LOCK(); - debug_assert(g_SocketSetInternal.m_NumSockets > 0); - - g_SocketSetInternal.m_NumSockets--; - g_SocketSetInternal.m_HandleMap.erase(m_pInternal->m_fd); - - if (!g_SocketSetInternal.m_NumSockets) - AbortWaitLoop(); - GLOBAL_UNLOCK(); - - // Disconnect the socket, if it is still connected - if (m_State == SS_CONNECTED || m_State == SS_CLOSED_LOCALLY) - { - // This makes the other end receive a RST, but since - // we've had no chance to close cleanly and the socket must - // be destroyed immediately, we've got no choice - shutdown(m_pInternal->m_fd, SHUT_RDWR); - m_State=SS_UNCONNECTED; - } - // Destroy the socket - closesocket(m_pInternal->m_fd); - m_pInternal->m_fd=-1; -} - -void CSocketBase::SetNonBlocking(bool nonblocking) -{ - m_NonBlocking=nonblocking; -#if OS_WIN - unsigned long nb=nonblocking; - if(!nonblocking) - SendWaitLoopUpdate(); // Need to call WSAAsyncSelect with event=0 before ioctlsocket - int res=ioctlsocket(m_pInternal->m_fd, FIONBIO, &nb); - if (res != 0) - NET_LOG2("SetNonBlocking: res %d", res); -#else - int oldflags=fcntl(m_pInternal->m_fd, F_GETFL, 0); - if (oldflags != -1) - { - if (nonblocking) - oldflags |= O_NONBLOCK; - else - oldflags &= ~O_NONBLOCK; - fcntl(m_pInternal->m_fd, F_SETFL, oldflags); - } -#endif -} - -void CSocketBase::SetTcpNoDelay(bool tcpNoDelay) -{ - // Disable Nagle's Algorithm - int data=tcpNoDelay; - setsockopt(m_pInternal->m_fd, SOL_SOCKET, TCP_NODELAY, (const char *)&data, sizeof(data)); -} - -PS_RESULT CSocketBase::Read(void *buf, size_t len, size_t *bytesRead) -{ - int res; - char errbuf[256]; - - res=recv(m_pInternal->m_fd, (char *)buf, len, 0); - if (res < 0) - { - *bytesRead=0; - int error=Network_LastError; - switch (error) - { - case EWOULDBLOCK: - return PS_OK; - /*case ENETDOWN: - case ENETRESET: - case ENOTCONN: - case ESHUTDOWN: - case ECONNABORTED: - case ECONNRESET: - case ETIMEDOUT:*/ - default: - Network_GetErrorString(error, errbuf, sizeof(errbuf)); - NET_LOG3("Read error %s [%d]", errbuf, error); - m_State=SS_UNCONNECTED; - m_Error=GetPS_RESULT(error); - return m_Error; - } - } - - if (res == 0 && len > 0) // EOF - Cleanly closed socket - { - *bytesRead=0; - m_State=SS_UNCONNECTED; - m_Error=PS_OK; - return CONNECTION_BROKEN; - } - - *bytesRead=res; - - m_pInternal->m_RecvBytes += res; -#if RECORD_GLOBAL_STATS - GLOBAL_LOCK(); - g_SocketSetInternal.m_GlobalRecvBytes += res; - GLOBAL_UNLOCK(); -#endif - - return PS_OK; -} - -PS_RESULT CSocketBase::Write(void *buf, size_t len, size_t *bytesWritten) -{ - int res; - char errbuf[256]; - - res=send(m_pInternal->m_fd, (char *)buf, len, 0); - if (res < 0) - { - *bytesWritten=0; - int err=Network_LastError; - switch (err) - { - case EWOULDBLOCK: - return PS_OK; - /*case ENETDOWN: - case ENETRESET: - case ENOTCONN: - case ESHUTDOWN: - case ECONNABORTED: - case ECONNRESET: - case ETIMEDOUT: - case EHOSTUNREACH:*/ - default: - Network_GetErrorString(err, errbuf, sizeof(errbuf)); - NET_LOG3("Write error %s [%d]", errbuf, err); - m_State=SS_UNCONNECTED; - return CONNECTION_BROKEN; - } - } - - *bytesWritten=res; - - m_pInternal->m_SentBytes += res; -#if RECORD_GLOBAL_STATS - GLOBAL_LOCK(); - g_SocketSetInternal.m_GlobalSentBytes += res; - GLOBAL_UNLOCK(); -#endif - - return PS_OK; -} - -PS_RESULT CSocketBase::Connect(const CSocketAddress &addr) -{ - int res = connect(m_pInternal->m_fd, (struct sockaddr *)(&addr.m_Union), sizeof(struct sockaddr_in)); - NET_LOG3("connect returned %d [%d]", res, m_NonBlocking); - - if (res != 0) - { - int error=Network_LastError; - NET_LOG2("last error was %d", error); - if (m_NonBlocking && error == EWOULDBLOCK) - { - m_State=SS_CONNECT_STARTED; - } - else - { - m_State=SS_UNCONNECTED; - m_Error=GetPS_RESULT(error); - } - } - else - { - m_State=SS_CONNECTED; - m_Error=PS_OK; - } - - return m_Error; -} - -PS_RESULT CSocketBase::Bind(const CSocketAddress &address) -{ - char errBuf[256]; - int res; - - Initialize(address.GetProtocol()); - - SetOpMask(READ); - - res=bind(m_pInternal->m_fd, (const struct sockaddr*)&address, (socklen_t)sizeof(struct sockaddr_in)); - if (res == -1) - { - PS_RESULT ret=PS_FAIL; - int err=Network_LastError; - switch (err) - { - case EADDRINUSE: - ret=PORT_IN_USE; - break; - case EACCES: - case EADDRNOTAVAIL: - ret=INVALID_PORT; - break; - default: - Network_GetErrorString(err, errBuf, sizeof(errBuf)); - LOG(CLogger::Error, LOG_CATEGORY, L"CServerSocket::Bind(): bind: %hs [%d] => PS_FAIL", errBuf, err); - } - m_State=SS_UNCONNECTED; - m_Error=ret; - return ret; - } - - res=listen(m_pInternal->m_fd, 5); - if (res == -1) - { - int err=Network_LastError; - Network_GetErrorString(err, errBuf, sizeof(errBuf)); - LOG(CLogger::Error, LOG_CATEGORY, L"CServerSocket::Bind(): listen: %hs [%d] => PS_FAIL", errBuf, err); - m_State=SS_UNCONNECTED; - return PS_FAIL; - } - - m_State=SS_CONNECTED; - m_Error=PS_OK; - return PS_OK; -} - -PS_RESULT CSocketBase::PreAccept(CSocketAddress &addr) -{ - socklen_t addrLen=sizeof(struct sockaddr_in); - int fd=accept(m_pInternal->m_fd, (struct sockaddr *)&addr.m_Union, &addrLen); - m_pInternal->m_AcceptFd=fd; - m_pInternal->m_AcceptAddr=addr; - if (fd != -1) - return PS_OK; - else - { - PS_RESULT res=GetPS_RESULT(Network_LastError); - // GetPS_RESULT considers some errors non-failures - if (res == PS_OK) - return PS_FAIL; - else - return res; - } -} - -CSocketInternal *CSocketBase::Accept() -{ - if (m_pInternal->m_AcceptFd != -1) - { - CSocketInternal *pInt=new CSocketInternal(); - pInt->m_fd=m_pInternal->m_AcceptFd; - pInt->m_RemoteAddr=m_pInternal->m_AcceptAddr; - - GLOBAL_LOCK(); - g_SocketSetInternal.m_NumSockets++; - GLOBAL_UNLOCK(); - - m_pInternal->m_AcceptFd=-1; - return pInt; - } - else - return NULL; -} - -void CSocketBase::Reject() -{ - shutdown(m_pInternal->m_AcceptFd, SHUT_RDWR); - closesocket(m_pInternal->m_AcceptFd); -} - -// UNIX select loop -#if !OS_WIN -// ConnectError is called on a socket the first time it selects as ready -// after the BeginConnect, to check errors on the socket and update the -// connection status information -// -// Returns: true if error callback should be called, false if it should not -bool CSocketBase::ConnectError(CSocketBase *pSocket) -{ - CSocketInternal *pInt=pSocket->m_pInternal; - size_t buf; - int res; - - if (pSocket->m_State==SS_CONNECT_STARTED) - { - res=read(pInt->m_fd, &buf, 0); - // read of zero bytes should be a successful no-op, unless - // there was an error - if (res == -1) - { - pSocket->m_State=SS_UNCONNECTED; - PS_RESULT connErr=GetPS_RESULT(errno); - NET_LOG4("Connect error: %s [%d:%s]", connErr, errno, strerror(errno)); - pSocket->m_Error=connErr; - return true; - } - else - { - pSocket->m_State=SS_CONNECTED; - pSocket->m_Error=PS_OK; - } - } - - return false; -} - -// SocketWritable is called whenever a socket selects as writable in the unix -// select loop. This will call the callback after checking for a connect error -// if there's a connect in progress, as well as update the socket's state. -// -// Locking: The global mutex must be held when entering this function, and it -// will be held upon return. -void CSocketBase::SocketWritable(CSocketBase *pSock) -{ - //CSocketInternal *pInt=pSock->m_pInternal; - bool isConnectError=false; - - if (pSock->m_State != SS_CONNECTED) - isConnectError=ConnectError(pSock); - - GLOBAL_UNLOCK(); - - if (isConnectError) - pSock->OnClose(pSock->m_Error); - else - pSock->OnWrite(); - - GLOBAL_LOCK(); -} - -// SocketReadable is called whenever a socket selects as writable in the unix -// select loop. This will call the callback after checking for a connect error -// if there's a connect in progress, as well as update the socket's state. -// -// Locking: The global mutex must be held when entering this function, and it -// will be held upon return. -void CSocketBase::SocketReadable(CSocketBase *pSock) -{ - bool isError=false; - - if (pSock->m_State == SS_CONNECT_STARTED) - isError=ConnectError(pSock); - else if (pSock->m_State == SS_UNCONNECTED) - { - // UNCONNECTED sockets don't get callbacks - // Note that server sockets that are bound have state==SS_CONNECTED - return; - } - else if (pSock->m_State != SS_UNCONNECTED) - { - size_t nRead; - errno=0; - int res=ioctl(pSock->m_pInternal->m_fd, FIONREAD, &nRead); - // failure, errno=EINVAL means server socket - // success, nRead != 0 means alive stream socket - if (res == -1 && errno != EINVAL) - { - NET_LOG3("RunWaitLoop:ioctl: Connection broken [%d:%s]", errno, strerror(errno)); - // Don't use API function - we both hold a lock and - // it is unnecessary to SendWaitLoopUpdate at this - // stage - pSock->m_pInternal->m_Ops=0; - pSock->m_State=SS_UNCONNECTED; - if (errno) - pSock->m_Error=GetPS_RESULT(errno); - else - pSock->m_Error=PS_OK; - isError=true; - } - } - - GLOBAL_UNLOCK(); - - if (isError) - pSock->OnClose(pSock->m_Error); - else - pSock->OnRead(); - - GLOBAL_LOCK(); -} - -void CSocketBase::RunWaitLoop() -{ - int res; - - signal(SIGPIPE, SIG_IGN); - - // Create Control Pipe - res=pipe(g_SocketSetInternal.m_Pipe); - if (res != 0) - return; - - // The lock is held upon entry and exit of this loop. There are a few places - // where the lock is released and then re-acquired: when calling callbacks - // and when calling select(). - while (true) - { - std::map::iterator it; - fd_set rfds; - fd_set wfds; - int fd_max=g_SocketSetInternal.m_Pipe[0]; - - // Prepare fd_set: Read - FD_ZERO(&rfds); - FD_SET(g_SocketSetInternal.m_Pipe[0], &rfds); - - // Prepare fd_set: Write - FD_ZERO(&wfds); - - it=g_SocketSetInternal.m_HandleMap.begin(); - while (it != g_SocketSetInternal.m_HandleMap.end()) - { - size_t ops=it->second->m_pInternal->m_Ops; - - if (ops && it->first > fd_max) - fd_max=it->first; - if (ops & READ) - FD_SET(it->first, &rfds); - if (ops & WRITE) - FD_SET(it->first, &wfds); - - ++it; - } - GLOBAL_UNLOCK(); - - // select, timeout infinite - res=select(fd_max+1, &rfds, &wfds, NULL, NULL); - - GLOBAL_LOCK(); - // Check select error - if (res == -1) - { - // It is possible for a socket to be deleted between preparing the - // fd_sets and actually performing the select - in which case it - // will fire a Bad file descriptor error. Simply retry. - if (Network_LastError == EBADF) - continue; - perror("CSocketSet::RunWaitLoop(), select"); - continue; - } - - // Check Control Pipe - if (FD_ISSET(g_SocketSetInternal.m_Pipe[0], &rfds)) - { - char bt; - if (read(g_SocketSetInternal.m_Pipe[0], &bt, 1) == 1) - { - if (bt=='q') - break; - else if (bt=='r') - { - // Reload sockets - just skip to the beginning of the loop - continue; - } - } - - FD_CLR(g_SocketSetInternal.m_Pipe[0], &rfds); - } - - // Go through sockets - int i=-1; - while (++i <= fd_max) - { - if (!FD_ISSET(i, &rfds) && !FD_ISSET(i, &wfds)) - continue; - - it=g_SocketSetInternal.m_HandleMap.find(i); - if (it == g_SocketSetInternal.m_HandleMap.end()) - continue; - - CSocketBase *pSock=it->second; - - if (FD_ISSET(i, &wfds)) - { - SocketWritable(pSock); - } - - // After the callback is called, we must check if the socket - // still exists (sockets may delete themselves in the callback) - it=g_SocketSetInternal.m_HandleMap.find(i); - if (it == g_SocketSetInternal.m_HandleMap.end()) - continue; - - if (FD_ISSET(i, &rfds)) - { - SocketReadable(pSock); - } - } - } - - // Close control pipe - close(g_SocketSetInternal.m_Pipe[0]); - close(g_SocketSetInternal.m_Pipe[1]); - - return; -} - -void CSocketBase::SendWaitLoopAbort() -{ - char msg='q'; - write(g_SocketSetInternal.m_Pipe[1], &msg, 1); -} - -void CSocketBase::SendWaitLoopUpdate() -{ -// NET_LOG("SendWaitLoopUpdate: fd %d, ops %u\n", m_pInternal->m_fd, m_pInternal->m_Ops); - char msg='r'; - write(g_SocketSetInternal.m_Pipe[1], &msg, 1); -} - -// Windows WindowProc for async event notification -#else // i.e. #if OS_WIN - -void WaitLoop_SocketUpdateProc(int fd, int error, int event) -{ - GLOBAL_LOCK(); - CSocketBase *pSock=g_SocketSetInternal.m_HandleMap[fd]; - GLOBAL_UNLOCK(); - - // FIXME What if the fd isn't in the handle map? - - if (error) - { - PS_RESULT res=GetPS_RESULT(error); - pSock->m_Error=res; - pSock->m_State=SS_UNCONNECTED; - if (res == PS_FAIL) - pSock->OnClose(CONNECTION_BROKEN); - return; - } - - if (pSock->m_State==SS_CONNECT_STARTED) - { - pSock->m_Error=PS_OK; - pSock->m_State=SS_CONNECTED; - } - - switch (event) - { - case FD_ACCEPT: - case FD_READ: - pSock->OnRead(); - break; - case FD_CONNECT: - case FD_WRITE: - pSock->OnWrite(); - break; - case FD_CLOSE: - // If FD_CLOSE and error, OnClose has already been called above - // with the appropriate PS_RESULT - pSock->m_State=SS_UNCONNECTED; - pSock->OnClose(PS_OK); - break; - } -} - -LRESULT WINAPI WaitLoop_WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - //printf("WaitLoop_WindowProc(): Windows message: %d:%d:%d\n", msg, wParam, lParam); - switch (msg) - { - case MSG_SOCKET_READY: - { - int event=LOWORD(lParam); - int error=HIWORD(lParam); - - WaitLoop_SocketUpdateProc((int)wParam, error?error-WSABASEERR:0, event); - return FALSE; - } - default: - return DefWindowProc(hWnd, msg, wParam, lParam); - } -} - -// Locked on entry, must be locked on exit -void CSocketBase::RunWaitLoop() -{ - int ret; - char errBuf[256] = {0}; - MSG msg; - - WNDCLASS wc; - ATOM atom; - - memset(&wc, 0, sizeof(WNDCLASS)); - wc.lpszClassName="Network Event WindowClass"; - wc.lpfnWndProc=WaitLoop_WindowProc; - - atom=RegisterClass(&wc); - if (!atom) - { - ret=GetLastError(); - Network_GetErrorString(ret, (LPSTR)&errBuf, 256); - NET_LOG3("RegisterClass: %s [%d]", errBuf, ret); - return; - } - - // Create message window - g_SocketSetInternal.m_hWnd=CreateWindow((LPCTSTR)atom, "Network Event Window", WS_POPUP, 0, 0, 0, 0, NULL, NULL, NULL, NULL); - - if (!g_SocketSetInternal.m_hWnd) - { - ret=GetLastError(); - Network_GetErrorString(ret, errBuf, sizeof(errBuf)); - NET_LOG3("CreateWindowEx: %s [%d]", errBuf, ret); - return; - } - - // If OpMasks where set in another thread before we got this far, - // WSAAsyncSelect will need to be called again - std::map::iterator it; - it=g_SocketSetInternal.m_HandleMap.begin(); - while (it != g_SocketSetInternal.m_HandleMap.end()) - { - it->second->SetOpMask(it->second->GetOpMask()); - ++it; - } - - NET_LOG2("Commencing message loop. hWnd %p", g_SocketSetInternal.m_hWnd); - GLOBAL_UNLOCK(); - - while ((ret=GetMessage(&msg, g_SocketSetInternal.m_hWnd, 0, 0))!=0) - { - //printf("RunWaitLoop(): Windows message: %d:%d:%d\n", msg.message, msg.wParam, msg.lParam); - if (ret == -1) - { - ret=GetLastError(); - Network_GetErrorString(ret, errBuf, sizeof(errBuf)); - NET_LOG3("GetMessage: %s [%d]", errBuf, ret); - } - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - - GLOBAL_LOCK(); - g_SocketSetInternal.m_Thread=0; - // FIXME Leak: Destroy window - g_SocketSetInternal.m_hWnd=0; - - NET_LOG("RunWaitLoop returning"); - return; -} - -void CSocketBase::SendWaitLoopAbort() -{ - if (g_SocketSetInternal.m_hWnd) - { - PostMessage(g_SocketSetInternal.m_hWnd, WM_QUIT, 0, 0); - } - else - NET_LOG("SendWaitLoopUpdate: No WaitLoop Running."); -} - -void CSocketBase::SendWaitLoopUpdate() -{ - GLOBAL_LOCK(); - if (g_SocketSetInternal.m_hWnd) - { - if(m_NonBlocking == false) - { - GLOBAL_UNLOCK(); - WSAAsyncSelect(m_pInternal->m_fd, g_SocketSetInternal.m_hWnd, MSG_SOCKET_READY, 0); - return; - } - - long wsaOps=FD_CLOSE; - if (m_pInternal->m_Ops & READ) - wsaOps |= FD_READ|FD_ACCEPT; - if (m_pInternal->m_Ops & WRITE) - wsaOps |= FD_WRITE|FD_CONNECT; - GLOBAL_UNLOCK(); - //printf("SendWaitLoopUpdate: %d: %u %x -> %p\n", m_pInternal->m_fd, m_pInternal->m_Ops, wsaOps, g_SocketSetInternal.m_hWnd); - WSAAsyncSelect(m_pInternal->m_fd, g_SocketSetInternal.m_hWnd, MSG_SOCKET_READY, wsaOps); - } - else - { - //printf("SendWaitLoopUpdate: No WaitLoop Running.\n"); - GLOBAL_UNLOCK(); - } -} -#endif // #if OS_WIN - -void CSocketBase::AbortWaitLoop() -{ - SendWaitLoopAbort(); -// pthread_join(g_SocketSetInternal.m_Thread); -} - -int CSocketBase::GetOpMask() -{ - return m_pInternal->m_Ops; -} - -void CSocketBase::SetOpMask(int ops) -{ - GLOBAL_LOCK(); - g_SocketSetInternal.m_HandleMap[m_pInternal->m_fd]=this; - m_pInternal->m_Ops=ops; - - /*printf("SetOpMask(fd %d, ops %u) %u\n", - m_pInternal->m_fd, - ops, - g_SocketSetInternal.m_HandleMap[m_pInternal->m_fd]->m_pInternal->m_Ops);*/ - - GLOBAL_UNLOCK(); - - SendWaitLoopUpdate(); -} diff --git a/source/network/SocketBase.h b/source/network/SocketBase.h deleted file mode 100644 index 2fd896946a..0000000000 --- a/source/network/SocketBase.h +++ /dev/null @@ -1,503 +0,0 @@ -/* Copyright (C) 2009 Wildfire Games. - * This file is part of 0 A.D. - * - * 0 A.D. 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, either version 2 of the License, or - * (at your option) any later version. - * - * 0 A.D. 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 0 A.D. If not, see . - */ - -#ifndef INCLUDED_NETWORK_SOCKETBASE -#define INCLUDED_NETWORK_SOCKETBASE - -//-------------------------------------------------------- -// Includes / Compiler directives -//-------------------------------------------------------- - -#include "lib/posix/posix_sock.h" -#include "ps/Pyrogenesis.h" -#include -#include "ps/CStr.h" - -//------------------------------------------------- -// Error Codes -//------------------------------------------------- - -DECLARE_ERROR( CONNECT_TIMEOUT ); -DECLARE_ERROR( CONNECT_REFUSED ); -DECLARE_ERROR( NO_SUCH_HOST ); -DECLARE_ERROR( NO_ROUTE_TO_HOST ); -DECLARE_ERROR( CONNECTION_BROKEN ); -DECLARE_ERROR( WAIT_ABORTED ); -DECLARE_ERROR( PORT_IN_USE ); -DECLARE_ERROR( INVALID_PORT ); -DECLARE_ERROR( WAIT_LOOP_FAIL ); -DECLARE_ERROR( CONNECT_IN_PROGRESS ); -DECLARE_ERROR( INVALID_PROTOCOL ); - -//------------------------------------------------- -// Declarations -//------------------------------------------------- - -class CSocketInternal; - -/** - * An enumeration of all supported protocols, and the special value UNSPEC, - * which represents an invalid address. - */ -// Modifiers Note: Each value in the enum should correspond to a sockaddr_* -// struct and a PF_* value -enum ESocketProtocol -{ - // This should be a value that's invalid for most socket functions, so that - // you don't accidentally use an UNSPEC SocketAddress - // PF_UNSPEC does not work, since it is accepted by many implementations as - // a "default" protocol family - whatever that may be - UNSPEC=((sa_family_t)-1), - IPv4=PF_INET, - IPv6=PF_INET6, - /* More protocols */ -}; - -/** - * A protocol-independent representation of a socket address. All protocols - * in the ESocketProtocol enum should have a corresponding member in this union. - */ -// Modifiers Note: Each member must contain a first field, compatible with the -// sin_family field of sockaddr_in. The field contains the ESocketProtocol value -// for the address, and it is returned by GetProtocol() -struct CSocketAddress -{ - union - { - sa_family_t m_Family; - sockaddr_in m_IPv4; - sockaddr_in6 m_IPv6; - } m_Union; - - inline ESocketProtocol GetProtocol() const - { - return (ESocketProtocol)m_Union.m_Family; - } - - inline CSocketAddress() - { - memset(&m_Union, 0, sizeof(m_Union)); - m_Union.m_Family=UNSPEC; - } - - /** - * Create a wildcard address for the specified protocol with a specified - * port. - * - * @param port The port number, in local byte order - * @param proto The protocol to use; default IPv4 - */ - explicit CSocketAddress(int port, ESocketProtocol proto=IPv4); - - /** - * Create an address from a numerical IPv4 address and port, port in local - * byte order, IPv4 address as a byte array in written order. The Protocol - * of the resulting SocketAddress will be IPv4 - * - * @param address An IPv4 address as a byte array (in written order) - * @param port A port number (0-65535) in local byte order. - */ - CSocketAddress(u8 address[4], int port); - - /** - * Resolve the name using the system name resolution service (i.e. DNS) and - * store the resulting address. When multiple addresses are found, the - * first result is returned. - * - * Note that this call will block until the name resolution attempt is - * either completed successfully or timed out. - * - * @param name The name to resolve - * @param addr A reference to the variable to hold the address - * - * @return The result of the operation - * @retval PS_OK The hostname was successfully retrieved - * @retval NO_SUCH_HOST The hostname was not found - */ - static PS_RESULT Resolve(const char *name, int port, CSocketAddress &addr); - - /** - * Returns the string representation of the address, i.e. the IP (v4 or v6) - * address. Note that the port is not included in the string (mostly due to - * the fact that the port representation differs wildly between address - * families, and that Resolve does not take port as part of the hostname) - */ - CStr GetString() const; - - /** - * Returns the port number part of the address - */ - int GetPort() const; - - /* - Create an address pointing to the loopback, with the specified port and - protocol. Use this with Bind to only listen on the loopback interface. - */ - static CSocketAddress Loopback(int port, ESocketProtocol proto=IPv4); -}; - -/** - * An enumeration of socket states - * - * @see CSocketBase::GetState() - */ -enum ESocketState -{ - /** - * The socket is unconnected. Use GetError() to see if it is due to a - * failure, a clean close, or it was never connected. - * - * @see CSocketBase::GetError() - */ - SS_UNCONNECTED=0, - /** - * A connect attempt has started on a non-blocking socket. The error state - * will be CONNECTION_BROKEN. - * - * @see CSocketBase::OnWrite() - */ - SS_CONNECT_STARTED, - /** - * The socket is connected. The error state will be set to PS_OK. - */ - SS_CONNECTED, - /** - * The connection has been closed on this end, but the other end might have - * sent data that we haven't received yet. The error state will be set to - * PS_OK. - */ - SS_CLOSED_LOCALLY -}; - -/** - * Contains the basic socket I/O abstraction and event callback methods. - * A CSocketBase can only be instantiated as a subclass, none of the functions - * are meant to exist as anything other than helper functions for socket - * classes - * - * Any CSocket subclass that can be Accept:ed by a CServerSocket should - * provide a constructor that takes a CSocketInternal pointer, and hands it to - * the base class constructor. - */ -class CSocketBase -{ -private: - CSocketInternal *m_pInternal; - ESocketState m_State; - PS_RESULT m_Error; - ESocketProtocol m_Proto; - bool m_NonBlocking; - - /** - * Loop forever, waiting for events and calling the callbacks on sockets, - * according to their Op mask. This loop may be aborted by calling - * AbortWaitLoop. - * - * The global lock must be held when calling this function, and will be held - * upon return from it. - */ - static void RunWaitLoop(); - - /** - * The network thread entry point. Simply locks the global lock and calls - * RunWaitLoop. - */ - friend void *WaitLoopThreadMain(void *); - -#if OS_WIN - /** - * Used by the winsock AsyncSelect windowproc - */ - friend void WaitLoop_SocketUpdateProc(int fd, int error, int eventmask); - -#else - // These are utility functions for the unix select loop. Dox can be found in - // the source file. - static bool ConnectError(CSocketBase *); - static void SocketWritable(CSocketBase *); - static void SocketReadable(CSocketBase *); -#endif - - /** - * Abort the call to RunWaitLoop(), if one is currently running. - */ - static void AbortWaitLoop(); - - /** - * Tell the running wait loop to abort. This is the platform-dependent - * implementation of AbortWaitLoop() - */ - static void SendWaitLoopAbort(); - void SendWaitLoopUpdate(); - -protected: - /** - * Initialize a CSocketBase from a CSocketInternal pointer. Use in OnAccept - * callbacks to create an object of your subclass. This constructor should - * be overloaded by any subclass that may be Accept:ed. - */ - CSocketBase(CSocketInternal *pInt); - virtual ~CSocketBase(); - - /** - * Get the op mask for the socket. - */ - int GetOpMask(); - - /** - * Set the op mask for the socket, specifying which callbacks should be - * called by the WaitLoop. The initial op mask is zero, which means that - * this method must be called explicitly for any callbacks to be called. - * Note that before the call to BeginConnect or Bind, any call to this - * method is a no-op. - * - * It is safe to call this function while a RunWaitLoop is running. - * - * The wait loop guarantees that the callbacks specified in ops will be - * called when appropriate, but does not make the opposite guarantee for - * unset bits; i.e. any callback may be called even with a zero op mask. - */ - void SetOpMask(int ops); - -public: - /** - * These values are bitwise or-ed to produce op masks - */ - enum Ops - { - /** - * Call OnRead() on a stream socket when there is data to read from the - * socket, or OnAccept() on a server socket when there are incoming - * connections pending - */ - READ=1, - // Call OnWrite() when there is space available in the socket's output - // buffer. Has no effect on server sockets. - WRITE=2 - }; - - /** - * Constructs a CSocketBase. The OS socket object is not created by the - * constructor, but by the protected Initialize method, which is called by - * Connect and Bind. - * - * @see Connect - * @see Bind - */ - CSocketBase(); - - /** - * Forcibly shuts down the network wait loop. This should happen - * automatically as soon as all sockets are closed. - */ - static void Shutdown(); - - /** - * Returns the protocol set by Initialize. All SocketAddresses used with - * the socket must have the same SocketProtocol - */ - inline ESocketProtocol GetProtocol() const - { return m_Proto; } - - /** - * Destroy the OS socket. If the socket is not cleanly closed before, it - * will be forcefully closed by calling this method. - */ - void Destroy(); - - /** - * Close the socket. No more data can be sent over the socket, but any data - * pending from the remote host will still be received, and the OnRead - * callback called (if the socket's op mask has the READ bit set). Note - * that the socket isn't actually closed until the remote end calls - * Close on the corresponding remote socket, upon which the OnClose - * callback is called with a status code of PS_OK. - */ - void Close(); - - /** - * Create the OS socket for the specified protocol type. - */ - PS_RESULT Initialize(ESocketProtocol proto=IPv4); - - /** - * Connect the socket to the specified address. The socket must be - * initialized for the protocol of the address. - * - * @param addr The address to connect to - * @see SocketAddress::Resolve - */ - PS_RESULT Connect(const CSocketAddress &addr); - - /** @name Functions for Server Sockets */ - //@{ - - /** - * Bind the socket to the specified address and start listening for - * incoming connections. You must initialize the socket for the correct - * SocketProtocol before calling Bind. - * - * @param addr The address to bind to - * @see SocketAddress::SocketAddress(int,SocketProtocol) - */ - PS_RESULT Bind(const CSocketAddress &addr); - - /** - * Store the address of the next incoming connection in the SocketAddress - * pointed to by addr. You must then choose whether to accept or reject the - * connection by calling Accept or Reject - * - * @param addr A pointer to a SocketAddress - * @return PS_OK or an error code - * - * @see Accept(SocketAddress&) - * @see Reject() - */ - PS_RESULT PreAccept(CSocketAddress &addr); - - /** - * Accept the next incoming connection. You must construct a suitable - * CSocketBase subclass using the passed CSocketInternal. - * May only be called after a successful PreAccept call - */ - CSocketInternal *Accept(); - /** - * Reject the next incoming connection. - * - * May only be called after a successful PreAccept call - */ - void Reject(); - - //@} - /** @name Status and Options */ - //@{ - - /** - * Set or reset non-blocking operation. When non-blocking, all socket - * operations will return immediately, having done none or parts of - * the operation. The default state for a socket is non-blocking - * - * @see CSocketBase::Read - * @see CSocketBase::Write - * @see CSocketBase::Connect - */ - void SetNonBlocking(bool nonBlocking=true); - - /** - * Return the current non-blocking state of the socket. - * - * @see SetNonBlocking(bool) - */ - inline bool IsNonBlocking() const - { return m_NonBlocking; } - - /** - * Return the error state of the socket. This will be the same value that - * was returned by the IO function that failed. - * - * @see GetState() - */ - inline PS_RESULT GetErrorState() const - { return m_Error; } - - /** - * Return the connection state of the socket. If the connection status is - * "unconnected", use GetError() to see if it was disconnected due to an - * error, or cleanly closed. - * - * @see SocketState - * @see GetError() - */ - inline ESocketState GetState() const - { return m_State; } - - /** - * Disable Nagle's algorithm (enable no-delay working mode) - */ - void SetTcpNoDelay(bool tcpNoDelay=true); - - /** - * Get the address of the remote end to which the socket is connected. - * - * @return A reference to the socket address - */ - const CSocketAddress &GetRemoteAddress(); - - //@} - /** @name Stream I/O */ - //@{ - - /** - * Attempt to read data from the socket. Any data available without blocking - * will be returned. Note that a successful return does not mean that the - * whole buffer was filled. - * - * @param buf A pointer to the buffer where the data should be written - * @param len The amount of data that should be read. - * @param bytesRead The number of bytes read will be stored in the variable - * pointed to by bytesRead - * - * @retval PS_OK Some or all data was successfully read. - * @retval CONNECTION_BROKEN The socket is not connected or a server socket - */ - PS_RESULT Read(void *buf, size_t len, size_t *bytesRead); - - /** - * Attempt to write data to the socket. All data that can be sent without - * blocking will be buffered. - * - * @param buf A pointer to the data that should be written - * @param len The length of the buffer. - * @param bytesWritten The number of bytes written will be stored in the - * variable pointed to by bytesWritten - * - * @retval PS_OK Some or all data was successfully read. - * @retval CONNECTION_BROKEN The socket is not connected or a server socket - */ - PS_RESULT Write(void *buf, size_t len, size_t *bytesWritten); - - //@} - /** @name Callbacks */ - //@{ - - /** - * Called by the Network Thread when data is available for reading. Use - * SetOpMask with the READ bit set to enable calling of this function. - * - * For server sockets, "data is available for reading" means "incoming - * connections are pending". - */ - virtual void OnRead()=0; - /** - * Called by the Network Thread when data can be written to the socket. - * Will only be called when the WRITE bit is set in the Op Mask of the - * socket. - */ - virtual void OnWrite()=0; - - /** - * The socket has been closed. It is not certain that the error code - * provides meaningful diagnostics. CONNECTION_BROKEN is the generic catch- - * all for erroneous closures, PS_OK for clean closures. - * - * @param errorCode A result code describing the reason why the socket was - * closed - */ - virtual void OnClose(PS_RESULT errorCode)=0; -}; - -#endif diff --git a/source/network/StreamSocket.cpp b/source/network/StreamSocket.cpp deleted file mode 100644 index 5c0e19083d..0000000000 --- a/source/network/StreamSocket.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/* Copyright (C) 2009 Wildfire Games. - * This file is part of 0 A.D. - * - * 0 A.D. 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, either version 2 of the License, or - * (at your option) any later version. - * - * 0 A.D. 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 0 A.D. If not, see . - */ - -#include "precompiled.h" - -#include "Network.h" -#include "StreamSocket.h" - -#include "NetLog.h" - -CStreamSocket::CStreamSocket() -{} - -CStreamSocket::CStreamSocket(CSocketInternal *pInt): - CSocketBase(pInt) -{} - -CStreamSocket::~CStreamSocket() -{ -} - -void *CStreamSocket_ConnectThread(void *data) -{ - debug_SetThreadName("net_connect"); - - CStreamSocket *pSock=(CStreamSocket *)data; - PS_RESULT res=PS_OK; - CSocketAddress addr; - - res=CSocketAddress::Resolve(pSock->m_pConnectHost, pSock->m_ConnectPort, addr); - NET_LOG4("CStreamSocket_ConnectThread: Resolve: %s -> %s [%s]", pSock->m_pConnectHost, addr.GetString().c_str(), res); - if (res == PS_OK) - { - pSock->Initialize(); - // If we don't do this we'll get spurious callbacks called since our - // network thread will notice the socket getting connected (and - // potentially receiving data) while we might not yet have called the - // ConnectComplete callback - pSock->SetOpMask(0); - pSock->SetNonBlocking(false); - res=pSock->Connect(addr); - NET_LOG2("CStreamSocket_ConnectThread: Connect: %s", res); - } - - if (res == PS_OK) - { - pSock->SetNonBlocking(true); - - // This should call the right callbacks, so that you get the expected - // results if you call Read or Write before the connect actually is complete - pSock->SetOpMask((pSock->m_WriteContext.m_Valid?CSocketBase::WRITE:0)|CSocketBase::READ); - } - - pSock->ConnectComplete(res); - - free(pSock->m_pConnectHost); - pSock->m_pConnectHost=NULL; - - return NULL; -} - -PS_RESULT CStreamSocket::BeginConnect(const char *hostname, int port) -{ - m_pConnectHost=strdup(hostname); - m_ConnectPort=port; - - // Start thread - pthread_t thread; - pthread_create(&thread, NULL, &CStreamSocket_ConnectThread, this); - - return PS_OK; -} - -PS_RESULT CStreamSocket::Read(void *buf, size_t len) -{ - // Check socket status - if (GetState() != SS_CONNECTED) - return GetErrorState(); - - // Check for running read operation - if (m_ReadContext.m_Valid) - return CONFLICTING_OP_IN_PROGRESS; - - // Fill in read_cb - m_ReadContext.m_Valid=true; - m_ReadContext.m_pBuffer=buf; - m_ReadContext.m_Length=len; - m_ReadContext.m_Completed=0; - - SetOpMask(GetOpMask()|READ); - - return PS_OK; -} - -PS_RESULT CStreamSocket::Write(void *buf, size_t len) -{ - // Check status - if (GetState() != SS_CONNECTED) - return GetErrorState(); - - // Check running Write operation - if (m_WriteContext.m_Valid) - return CONFLICTING_OP_IN_PROGRESS; - - // Fill in read_cb - m_WriteContext.m_pBuffer=buf; - m_WriteContext.m_Length=len; - m_WriteContext.m_Completed=0; - m_WriteContext.m_Valid=true; - - SetOpMask(GetOpMask()|WRITE); - - return PS_OK; -} - -#define MakeDefaultCallback(_nm) void CStreamSocket::_nm(PS_RESULT error) \ - { NET_LOG2("CStreamSocket::"#_nm"(): %s", error); } - -MakeDefaultCallback(OnClose) -MakeDefaultCallback(ConnectComplete) -MakeDefaultCallback(ReadComplete) -MakeDefaultCallback(WriteComplete) - -void CStreamSocket::OnWrite() -{ - if (!m_WriteContext.m_Valid) - { - SetOpMask(GetOpMask() & (~WRITE)); - return; - } - size_t bytes=0; - PS_RESULT res=CSocketBase::Write( - ((char *)m_WriteContext.m_pBuffer)+m_WriteContext.m_Completed, - m_WriteContext.m_Length-m_WriteContext.m_Completed, - &bytes); - if (res != PS_OK) - { - WriteComplete(res); - return; - } - NET_LOG2("CStreamSocket::OnWrite(): %lu bytes", (unsigned long)bytes); - m_WriteContext.m_Completed+=bytes; - if (m_WriteContext.m_Completed == m_WriteContext.m_Length) - { - m_WriteContext.m_Valid=false; - WriteComplete(PS_OK); - } -} - -void CStreamSocket::OnRead() -{ - if (!m_ReadContext.m_Valid) - { - NET_LOG("CStreamSocket::OnRead(): No Read request in progress"); - return; - } - size_t bytes=0; - PS_RESULT res=CSocketBase::Read( - ((u8 *)m_ReadContext.m_pBuffer)+m_ReadContext.m_Completed, - m_ReadContext.m_Length-m_ReadContext.m_Completed, - &bytes); - NET_LOG4("CStreamSocket::OnRead(): %s, %lu bytes read of %lu", - res, (unsigned long)bytes, - (unsigned long)(m_ReadContext.m_Length-m_ReadContext.m_Completed)); - if (res != PS_OK) - { - ReadComplete(res); - return; - } - m_ReadContext.m_Completed+=bytes; - if (m_ReadContext.m_Completed == m_ReadContext.m_Length) - { - m_ReadContext.m_Valid=false; - ReadComplete(PS_OK); - } -} diff --git a/source/network/StreamSocket.h b/source/network/StreamSocket.h deleted file mode 100644 index b598f4d26d..0000000000 --- a/source/network/StreamSocket.h +++ /dev/null @@ -1,139 +0,0 @@ -/* Copyright (C) 2009 Wildfire Games. - * This file is part of 0 A.D. - * - * 0 A.D. 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, either version 2 of the License, or - * (at your option) any later version. - * - * 0 A.D. 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 0 A.D. If not, see . - */ - -#ifndef INCLUDED_NETWORK_STREAMSOCKET -#define INCLUDED_NETWORK_STREAMSOCKET - -#include "ps/Pyrogenesis.h" -#include "Network.h" -#include "SocketBase.h" - -/** - * A class implementing Async I/O on top of the non-blocking event-driven - * CSocketBase - */ -class CStreamSocket: public CSocketBase -{ - CMutex m_Mutex; - char *m_pConnectHost; - int m_ConnectPort; - - struct SOperationContext - { - bool m_Valid; - void *m_pBuffer; - size_t m_Length; - size_t m_Completed; - - inline SOperationContext(): - m_Valid(false) - {} - }; - SOperationContext m_ReadContext; - SOperationContext m_WriteContext; - -protected: - friend void *CStreamSocket_ConnectThread(void *); - - CStreamSocket(CSocketInternal *pInt); - - /** - * Set the required socket options on the socket. - */ - void SetSocketOptions(); - - /** - * The destructor will disconnect the socket and free any OS resources. - */ - virtual ~CStreamSocket(); - - virtual void OnRead(); - virtual void OnWrite(); - -public: - CStreamSocket(); - - /** - * The Lock function locks a mutex stored in the CStreamSocket object. None - * of the CStreamSocket methods actually use the mutex, it is just there as - * a convenience for the user. - */ - void Lock(); - /** - * The Unlock function unlocks a mutex stored in the CStreamSocket object. - * None of the CSocket methods actually use the mutex, it is just there as a - * convenience for the user. - */ - void Unlock(); - - /** - * Begin a connect operation to the specified host and port. The connect - * operation and name resolution is performed in the background and the - * ConnectComplete callback is called when the connect is complete/failed - * - * Note that a PS_OK return only means that the connect operation has been - * initiated, not that it is successful. - * - * @param hostname A hostname or an IP address of the remote host - * @param port The TCP port number in host byte order - * - * @return PS_OK - The connect has been initiated - */ - PS_RESULT BeginConnect(const char *hostname, int port); - - /** - * Start a read operation. The function call will return immediately and - * complete the I/O in the background. OnRead() will be called when it is - * complete. Until the Read is complete, the buffer should not be touched. - * There can only be one read operation in progress at one time. - * - * Inputs - * buf A pointer to the buffer where the data should be written - * len The length of the buffer. The amount of data the function should - * try to read. - * - * Returns - * PS_OK Some or all data was successfully read. - * CONFLICTING_OP_IN_PROGRESS Another Read operation is alread in progress - * CONNECTION_BROKEN The socket is not connected or a server socket - */ - PS_RESULT Read(void *buf, size_t len); - - /** - * Start a Write operation. The function call will return immediately and - * the I/O complete in the background. OnWrite() will be called when i has - * completed. Until the Write is complete, the buffer shouldn't be touched. - * There can only be one write operation in progress at one time. - * - * @param buf A pointer to the buffer of data to write - * @param len The length of the buffer. - * - * Returns - * PS_OK Some or all data was successfully read. - * CONFLICTING_OP_IN_PROGRESS Another Write operation is in progress - * CONNECTION_BROKEN The socket is not connected or a server socket - */ - PS_RESULT Write(void *buf, size_t len); - - // The default implementation of these methods are no-ops - virtual void ConnectComplete(PS_RESULT errorCode); - virtual void ReadComplete(PS_RESULT errorCode); - virtual void WriteComplete(PS_RESULT errorCode); - virtual void OnClose(PS_RESULT errorCode); -}; - -#endif diff --git a/source/network/StringConverters.h b/source/network/StringConverters.h index 0ab0861942..096eb05e18 100644 --- a/source/network/StringConverters.h +++ b/source/network/StringConverters.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2009 Wildfire Games. +/* Copyright (C) 2010 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -19,7 +19,6 @@ #define INCLUDED_NETWORK_STRINGCONVERTERS #include "ps/CStr.h" -#include "simulation/EntityHandles.h" template CStr NetMessageStringConvert(const _T &arg); @@ -31,10 +30,4 @@ inline CStr NetMessageStringConvert(const _T &arg) return CStr(arg); } -template <> -inline CStr NetMessageStringConvert(const HEntity &arg) -{ - return arg.operator CStr8(); -} - #endif diff --git a/source/ps/GameRecord.cpp b/source/ps/GameRecord.cpp deleted file mode 100644 index 96b5edad67..0000000000 --- a/source/ps/GameRecord.cpp +++ /dev/null @@ -1,24 +0,0 @@ -/* Copyright (C) 2009 Wildfire Games. - * This file is part of 0 A.D. - * - * 0 A.D. 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, either version 2 of the License, or - * (at your option) any later version. - * - * 0 A.D. 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 0 A.D. If not, see . - */ - -#include "precompiled.h" - -#include "GameRecord.h" - -void CGameRecord::WriteMessage(CNetMessage* UNUSED(pMsg)) -{ -} diff --git a/source/ps/GameRecord.h b/source/ps/GameRecord.h deleted file mode 100644 index fa755d37c4..0000000000 --- a/source/ps/GameRecord.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright (C) 2009 Wildfire Games. - * This file is part of 0 A.D. - * - * 0 A.D. 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, either version 2 of the License, or - * (at your option) any later version. - * - * 0 A.D. 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 0 A.D. If not, see . - */ - -#ifndef INCLUDED_GAMERECORD -#define INCLUDED_GAMERECORD - -#include "CStr.h" - -class CNetMessage; -class CTurnManager; - -class CGameRecord -{ - bool m_IsRecording; - CTurnManager *m_pTurnManager; - -public: - void Load(const CStr& filename); - void Record(const CStr& filename); - - bool IsRecording(); - - /* - NOTE: The message will not be deleted by this method. Ownership remains - the caller's. - */ - void WriteMessage(CNetMessage *pMsg); - - CTurnManager *GetPlaybackTurnManager(); -}; - -#endif diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp index 6d9aba884c..a625d72efa 100644 --- a/source/ps/GameSetup/GameSetup.cpp +++ b/source/ps/GameSetup/GameSetup.cpp @@ -452,7 +452,6 @@ static void RegisterJavascriptInterfaces() PlayerCollection::Init( "PlayerCollection" ); // network - CNetMessage::ScriptingInit(); CNetClient::ScriptingInit(); CNetServer::ScriptingInit(); CNetSession::ScriptingInit(); @@ -778,11 +777,6 @@ void Shutdown(int flags) delete &g_ConfigDB; TIMER_END(L"shutdown ConfigDB"); - // Shut down the network loop - TIMER_BEGIN(L"shutdown CSocketBase"); - CSocketBase::Shutdown(); - TIMER_END(L"shutdown CSocketBase"); - TIMER_BEGIN(L"shutdown CNetLogManager"); CNetLogManager::Shutdown(); TIMER_END(L"shutdown CNetLogManager"); diff --git a/source/ps/Interact.cpp b/source/ps/Interact.cpp index 097cd20d28..8aff33496c 100644 --- a/source/ps/Interact.cpp +++ b/source/ps/Interact.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2009 Wildfire Games. +/* Copyright (C) 2010 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -522,138 +522,6 @@ CVector3D CSelectedEntities::GetGroupPosition( i8 groupid ) void CSelectedEntities::Update() { - static std::vector lastSelection; - - // Drop out immediately if we're in some special interaction mode - if (customSelectionMode) - return; - - if( !( m_selected == lastSelection ) ) - { - g_JSGameEvents.FireSelectionChanged( m_selectionChanged ); - lastSelection = m_selected; - } - - if( m_selectionChanged || g_Mouseover.m_targetChanged ) - { - // Can't order anything off the map - if( !g_Game->GetWorld()->GetTerrain()->IsOnMap( g_Mouseover.m_worldposition ) ) - { - m_defaultCommand = -1; - m_secondaryCommand = -1; - return; - } - - // Quick count to see which is the modal default order. - - const int numCommands=NMT_COMMAND_LAST - NMT_COMMAND_FIRST; - int defaultPoll[numCommands]; - std::map defaultCursor[numCommands]; - std::map defaultAction[numCommands]; - - int secondaryPoll[numCommands]; - std::map secondaryCursor[numCommands]; - std::map secondaryAction[numCommands]; - - int t, vote, secvote; - for( t = 0; t < numCommands; t++ ) - { - defaultPoll[t] = 0; - secondaryPoll[t] = 0; - } - - std::vector::iterator it; - for( it = m_selected.begin(); it < m_selected.end(); it++ ) - { - CEventTargetChanged evt( g_Mouseover.m_target ); - (*it)->DispatchEvent( &evt ); - vote = evt.m_defaultOrder - NMT_COMMAND_FIRST; - secvote = evt.m_secondaryOrder - NMT_COMMAND_FIRST; - - if( ( vote >= 0 ) && ( vote < numCommands ) ) - { - defaultPoll[vote]++; - defaultCursor[vote][evt.m_defaultCursor]++; - defaultAction[vote][evt.m_defaultAction]++; - } - if( ( secvote >= 0 ) && ( secvote < numCommands ) ) - { - secondaryPoll[secvote]++; - secondaryCursor[secvote][evt.m_secondaryCursor]++; - secondaryAction[secvote][evt.m_secondaryAction]++; - } - } - - // Don't count GOTO as a majority action unless everything else has 0 votes. - defaultPoll[NMT_GOTO - NMT_COMMAND_FIRST] = 0; - - vote = -1; - secvote = -1; - for( t = 0; t < numCommands; t++ ) - { - if( ( vote == -1 ) || ( defaultPoll[t] > defaultPoll[vote] ) ) - vote = t; - if( ( secvote == -1 ) || ( secondaryPoll[t] > secondaryPoll[secvote] ) ) - secvote = t; - } - - std::map::iterator itv; - std::map::iterator iti; - m_defaultCommand = vote + NMT_COMMAND_FIRST; - m_secondaryCommand = secvote + NMT_COMMAND_FIRST; - - // Now find the most appropriate cursor - t = 0; - for( itv = defaultCursor[vote].begin(); itv != defaultCursor[vote].end(); itv++ ) - { - if( itv->second > t ) - { - t = itv->second; - g_CursorName = itv->first; - } - } - - /* - TODO: provide secondary cursor name? - - t = 0; - for( itv = secondaryCursor[secvote].begin(); itv != secondaryCursor[secvote].end(); itv++ ) - { - if( itv->second > t ) - { - t = itv->second; - g_CursorName = itv->first; - } - }*/ - - // Find the most appropriate action parameter too - t = 0; - for( iti = defaultAction[vote].begin(); iti != defaultAction[vote].end(); iti++ ) - { - if( iti->second > t ) - { - t = iti->second; - m_defaultAction = iti->first; - } - } - - t = 0; - for( iti = secondaryAction[secvote].begin(); iti != secondaryAction[secvote].end(); iti++ ) - { - if( iti->second > t ) - { - t = iti->second; - m_secondaryAction = iti->first; - } - } - - m_selectionChanged = false; - g_Mouseover.m_targetChanged = false; - } - - if( ( m_group_highlight != -1 ) && GetGroupCount( m_group_highlight ) ) - g_Game->GetView()->SetCameraTarget( GetGroupPosition( m_group_highlight ) ); - } void CMouseoverEntities::Update( float timestep ) @@ -1434,6 +1302,7 @@ void CBuildingPlacer::MouseReleased() if( m_valid ) { +/* // issue a place object command across the network CPlaceObjectMessage *msg = new CPlaceObjectMessage(); msg->m_IsQueued = hotkeys[HOTKEY_ORDER_QUEUE]; @@ -1444,6 +1313,7 @@ void CBuildingPlacer::MouseReleased() msg->m_Z = (u32) (clickPos.Z * 1000); msg->m_Angle = (u32) (m_angle * 1000); g_Game->GetSimulation()->QueueLocalCommand(msg); +*/ } if( hotkeys[HOTKEY_ORDER_QUEUE] ) diff --git a/source/scripting/ScriptGlue.cpp b/source/scripting/ScriptGlue.cpp index aa0265d7c3..30cc1230ea 100644 --- a/source/scripting/ScriptGlue.cpp +++ b/source/scripting/ScriptGlue.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2009 Wildfire Games. +/* Copyright (C) 2010 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -204,111 +204,6 @@ JSBool GetPlayerUnitCount( JSContext* cx, JSObject*, uintN argc, jsval* argv, js return JS_TRUE; } - -//Used to create net messages for formations--msgList.front() is the original message. see IssueCommand -void CreateFormationMessage( std::vector& msgList, CNetMessage* msg, CEntityList& formation ) -{ - CNetMessage* retMsg; - const int type = msg->GetType(); - - if ( type == NMT_GOTO ) - { - //formationEnt->GetFormation()->BaseToMovement(); - CGotoMessage* tmp = static_cast(msg); - retMsg = CNetMessage::CreatePositionMessage( formation, NMT_FORMATION_GOTO, - CVector2D(tmp->m_TargetX, tmp->m_TargetY) ); - } - else if( type == NMT_RUN ) - { - CGotoMessage* tmp = static_cast(msg); - retMsg = CNetMessage::CreatePositionMessage( formation, NMT_FORMATION_GOTO, - CVector2D(tmp->m_TargetX, tmp->m_TargetY) ); - } - else if ( type == NMT_CONTACT_ACTION ) - { - CContactActionMessage* tmp = static_cast(msg); - retMsg = CNetMessage::CreateEntityIntMessage(formation, NMT_FORMATION_CONTACT_ACTION, - tmp->m_Target, tmp->m_Action); - } - else - return; - - msgList.push_back(retMsg); -} - -// Issue a command (network message) to an entity or collection. -// params: either an entity- or entity collection object, message ID [int], -// any further params needed by CNetMessage::CommandFromJSArgs -// returns: command in serialized form [string] -JSBool IssueCommand( JSContext* cx, JSObject*, uintN argc, jsval* argv, jsval* rval ) -{ - // at least one for target object, one for isQueued, and then 1 or more for the CommandFromJSArgs - JSU_REQUIRE_MIN_PARAMS(3); - - JSU_ASSERT(JSVAL_IS_OBJECT(argv[0]), "Argument 0 must be an entity collection."); - *rval = JSVAL_NULL; - - CEntityList entities, msgEntities; - - if (JS_InstanceOf(cx, JSVAL_TO_OBJECT(argv[0]), &CEntity::JSI_class, NULL)) - entities.push_back( (ToNative(argv[0])) ->me); - else - entities = *EntityCollection::RetrieveSet(cx, JSVAL_TO_OBJECT(argv[0])); - - typedef std::map EntityStore; - EntityStore entityStore; - - bool isQueued = ToPrimitive(argv[1]); - - //Destroy old notifiers if we're explicitly being reassigned - for ( size_t i=0; i < entities.size(); i++) - { - if ( entities[i]->entf_get(ENTF_DESTROY_NOTIFIERS)) - entities[i]->DestroyAllNotifiers(); - } - - std::vector messages; - - //Generate messages for formations - for (size_t i=0; i < entities.size(); i++ ) - { - if ( entities[i]->m_formation >= 0) - { - CEntityFormation* formation = entities[i]->GetFormation(); - bool duplicate = formation->IsDuplication(); - - if ( formation->IsLocked() && !duplicate) - { - formation->SelectAllUnits(); - entityStore[entities[i]->m_formation] = formation->GetEntityList(); - formation->SetDuplication(true); - } - } - else - msgEntities.push_back( entities[i] ); - } - CNetMessage* msg = CNetMessage::CommandFromJSArgs(msgEntities, cx, argc-2, argv+2, isQueued); - if (!msg) - { - delete msg; - return JS_TRUE; - } - messages.push_back(msg); - - for ( EntityStore::iterator it=entityStore.begin(); it!=entityStore.end(); it++) - CreateFormationMessage(messages, msg, it->second); - - for ( std::vector::iterator it=messages.begin(); it != messages.end(); it++ ) - { - g_Console->InsertMessage(L"IssueCommand: %hs", (*it)->ToString().c_str()); - *rval = g_ScriptingHost.UCStringToValue((*it)->ToString()); - g_Game->GetSimulation()->QueueLocalCommand(*it); - } - - return JS_TRUE; -} - - // Get the state of a given hotkey (from the hotkeys file) JSBool isOrderQueued( JSContext* cx, JSObject* UNUSED(obj), uintN argc, jsval* argv, jsval* rval ) { @@ -1408,7 +1303,6 @@ JSFunctionSpec ScriptFunctionTable[] = JS_FUNC("getEntityByUnitID", GetEntityByUnitID, 1) JS_FUNC("GetPlayerUnitCount", GetPlayerUnitCount, 1) JS_FUNC("getEntityTemplate", GetEntityTemplate, 1) - JS_FUNC("issueCommand", IssueCommand, 2) JS_FUNC("startPlacing", StartPlacing, 1) // Formation diff --git a/source/simulation/EntityFormation.cpp b/source/simulation/EntityFormation.cpp index 64b995f751..96b5634d47 100644 --- a/source/simulation/EntityFormation.cpp +++ b/source/simulation/EntityFormation.cpp @@ -181,8 +181,10 @@ void CEntityFormation::UpdateFormation() } } CEntityList entities = GetEntityList(); +/* CNetMessage* msg = CNetMessage::CreatePositionMessage( entities, NMT_FORMATION_GOTO, m_position ); g_Game->GetSimulation()->QueueLocalCommand(msg); +*/ } diff --git a/source/simulation/EntityScriptInterface.cpp b/source/simulation/EntityScriptInterface.cpp index 508ef7fa2e..34fcc9752c 100644 --- a/source/simulation/EntityScriptInterface.cpp +++ b/source/simulation/EntityScriptInterface.cpp @@ -843,6 +843,7 @@ jsval_t CEntity::GetRallyPoint( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval jsval_t CEntity::SetRallyPointAtCursor( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) ) { // Queue an order over the network to set a rally point +/* CSetRallyPointMessage* msg = new CSetRallyPointMessage; msg->m_Entities = CEntityList(me); msg->m_IsQueued = true; @@ -850,6 +851,7 @@ jsval_t CEntity::SetRallyPointAtCursor( JSContext* UNUSED(cx), uintN UNUSED(argc msg->m_TargetX = (int) point.X; msg->m_TargetY = (int) point.Z; g_Game->GetSimulation()->QueueLocalCommand(msg); +*/ return JS_TRUE; } diff --git a/source/simulation/Simulation.cpp b/source/simulation/Simulation.cpp index a83d884ea1..1b58038b6a 100644 --- a/source/simulation/Simulation.cpp +++ b/source/simulation/Simulation.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2009 Wildfire Games. +/* Copyright (C) 2010 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -42,7 +42,6 @@ #include "simulation/Scheduler.h" #include "simulation/Simulation.h" #include "simulation/TerritoryManager.h" -#include "simulation/TurnManager.h" #include "simulation/TriggerManager.h" #define LOG_CATEGORY L"simulation" @@ -50,7 +49,6 @@ CSimulation::CSimulation(CGame *pGame): m_pGame(pGame), m_pWorld(pGame->GetWorld()), - m_pTurnManager((g_SinglePlayerTurnManager=new CSinglePlayerTurnManager())), m_DeltaTime(0), m_Time(0) { @@ -58,16 +56,12 @@ CSimulation::CSimulation(CGame *pGame): CSimulation::~CSimulation() { -delete g_SinglePlayerTurnManager; - g_SinglePlayerTurnManager=NULL; } int CSimulation::Initialize(CGameAttributes* pAttribs) { m_Random.seed(0); // TODO: Store a random seed in CGameAttributes and synchronize it accross the network - m_pTurnManager->Initialize(m_pGame->GetNumPlayers()); - // Call the game startup script // TODO: Maybe don't do this if we're in Atlas // [2006-06-26 20ms] @@ -93,42 +87,9 @@ void CSimulation::RegisterInit(CGameAttributes *pAttribs) -bool CSimulation::Update(double frameTime) +bool CSimulation::Update(double UNUSED(frameTime)) { bool ok = true; - - m_DeltaTime += frameTime; - - if (m_DeltaTime >= 0.0) - { - // A new simulation frame is required. - if (m_pTurnManager->NewTurnReady()) - { - PROFILE( "simulation turn" ); - Simulate(); - double turnLength = m_pTurnManager->GetTurnLength() / 1000.0; - m_DeltaTime -= turnLength; - if (m_DeltaTime >= 0.0) - { - // The desired sim frame rate can't be achieved - we're being called - // with average(frameTime) > turnLength. - // Let the caller know we can't go fast enough - they should try - // cutting down on Interpolate and rendering, and call us a few times - // with frameTime == 0 to give us a chance to catch up. - ok = false; - debug_printf(L"WARNING: missing a simulation turn due to low FPS\n"); - } - } - else - { - // The network is lagging behind the simulation rate. - // Set delta time back to zero so we don't jump into the middle - // of the next simulation frame when we get the next turn. - // This creates "lag" on the client rather than just jumpiness. - m_DeltaTime = 0; - } - } - return ok; } @@ -138,18 +99,8 @@ void CSimulation::DiscardMissedUpdates() m_DeltaTime = 0.0; } -void CSimulation::Interpolate(double frameTime) +void CSimulation::Interpolate(double UNUSED(frameTime)) { - double turnLength = m_pTurnManager->GetTurnLength()/1000.0; - - // 'offset' should be how far we are between the previous and next - // simulation frames. - // m_DeltaTime/turnLength will usually be between -1 and 0, indicating - // the time until the next frame, so we can use that easily. - // If the simulation is going too slowly and hasn't been giving a chance - // to catch up before Interpolate is called, then m_DeltaTime > 0, so we'll - // just clamp it to offset=1, which is alright. - Interpolate(frameTime, clamp(m_DeltaTime / turnLength + 1.0, 0.0, 1.0)); } void CSimulation::Interpolate(double frameTime, double offset) @@ -166,40 +117,6 @@ void CSimulation::Interpolate(double frameTime, double offset) void CSimulation::Simulate() { - int time = m_pTurnManager->GetTurnLength(); - - m_Time += time / 1000.0f; -#if defined(DEBUG_SYNCHRONIZATION) - debug_printf(L"Simulation turn: %.3lf\n", m_Time); -#endif - - PROFILE_START( "scheduler tick" ); - g_Scheduler.Update(time); - PROFILE_END( "scheduler tick" ); - PROFILE_START( "entity updates" ); - g_EntityManager.UpdateAll(time); - PROFILE_END( "entity updates" ); - - PROFILE_START( "projectile updates" ); - m_pWorld->GetProjectileManager().UpdateAll(time); - PROFILE_END( "projectile updates" ); - - PROFILE_START( "los update" ); - m_pWorld->GetLOSManager()->Update(); - PROFILE_END( "los update" ); - - PROFILE_START("trigger update"); - g_TriggerManager.Update(time); - PROFILE_END("trigger udpate"); - - PROFILE_START( "turn manager update" ); - m_pTurnManager->NewTurn(); - m_pTurnManager->IterateBatch(0, TranslateMessage, this); - PROFILE_END( "turn manager update" ); - -#if defined(DEBUG_SYNCHRONIZATION) - debug_printf(L"End turn\n", m_Time); -#endif } // Location randomizer, for group orders... @@ -299,159 +216,6 @@ void QueueOrder(const CEntityOrder& order, const std::vector &entities, size_t CSimulation::TranslateMessage(CNetMessage* pMsg, size_t clientMask, void* UNUSED(userdata)) { - CEntityOrder order; - bool isQueued = true; - -#define ENTITY_POSITION(_msg, _order) \ - do { \ - _msg *msg=(_msg *)pMsg; \ - isQueued = msg->m_IsQueued != 0; \ - order.m_type=CEntityOrder::_order; \ - order.m_target_location.x=(float)msg->m_TargetX; \ - order.m_target_location.y=(float)msg->m_TargetY; \ - RandomizeLocations(order, msg->m_Entities, isQueued); \ - } while(0) -#define ENTITY_POSITION_FORM(_msg, _order) \ - do { \ - _msg *msg=(_msg *)pMsg; \ - isQueued = msg->m_IsQueued != 0; \ - order.m_type=CEntityOrder::_order; \ - order.m_target_location.x=(float)msg->m_TargetX; \ - order.m_target_location.y=(float)msg->m_TargetY; \ - FormationLocations(order, msg->m_Entities, isQueued); \ - } while(0) -#define ENTITY_ENTITY_INT(_msg, _order) \ - do { \ - _msg *msg=(_msg *)pMsg; \ - isQueued = msg->m_IsQueued != 0; \ - order.m_type=CEntityOrder::_order; \ - order.m_target_entity=msg->m_Target; \ - order.m_action=msg->m_Action; \ - QueueOrder(order, msg->m_Entities, isQueued); \ - } while(0) -#define ENTITY_ENTITY_INT_BOOL(_msg, _order) \ - do { \ - _msg *msg=(_msg *)pMsg; \ - isQueued = msg->m_IsQueued != 0; \ - order.m_type=CEntityOrder::_order; \ - order.m_target_entity=msg->m_Target; \ - order.m_action=msg->m_Action; \ - order.m_run=msg->m_Run != 0; \ - QueueOrder(order, msg->m_Entities, isQueued); \ - } while(0) -#define ENTITY_INT_STRING(_msg, _order) \ - do { \ - _msg *msg=(_msg *)pMsg; \ - isQueued = msg->m_IsQueued != 0; \ - order.m_type=CEntityOrder::_order; \ - order.m_name=msg->m_Name; \ - order.m_produce_type=msg->m_Type; \ - QueueOrder(order, msg->m_Entities, isQueued); \ - } while(0) -#define ENTITY_STRING(_msg, _order) \ - do { \ - _msg *msg=(_msg *)pMsg; \ - isQueued = msg->m_IsQueued != 0; \ - order.m_type=CEntityOrder::_order; \ - order.m_name=msg->m_Stance; \ - QueueOrder(order, msg->m_Entities, isQueued); \ - } while(0) - - switch (pMsg->GetType()) - { - case NMT_ADD_WAYPOINT: - { - CAddWaypointMessage *msg=(CAddWaypointMessage *)pMsg; - isQueued = msg->m_IsQueued != 0; - order.m_type=CEntityOrder::ORDER_LAST; - order.m_target_location.x=(float)msg->m_TargetX; - order.m_target_location.y=(float)msg->m_TargetY; - for(CEntityIt it = msg->m_Entities.begin(); it != msg->m_Entities.end(); ++it) - { - HEntity& hentity = *it; - - const CEntityOrders& order_queue = hentity->m_orderQueue; - for(CEntityOrderCRIt ord_it = order_queue.rbegin(); ord_it != order_queue.rend(); ++ord_it) - { - if (ord_it->m_type == CEntityOrder::ORDER_PATH_END_MARKER) - { - order.m_type = CEntityOrder::ORDER_GOTO; - hentity->PushOrder(order); - break; - } - if (ord_it->m_type == CEntityOrder::ORDER_PATROL) - { - order.m_type = ord_it->m_type; - hentity->PushOrder(order); - break; - } - } - if (order.m_type == CEntityOrder::ORDER_LAST) - { - LOG(CLogger::Error, LOG_CATEGORY, L"Got an AddWaypoint message for an entity that isn't moving."); - } - } - break; - } - case NMT_GOTO: - ENTITY_POSITION(CGotoMessage, ORDER_GOTO); - break; - case NMT_RUN: - ENTITY_POSITION(CRunMessage, ORDER_RUN); - break; - case NMT_PATROL: - ENTITY_POSITION(CPatrolMessage, ORDER_PATROL); - break; - case NMT_SET_RALLY_POINT: - ENTITY_POSITION(CSetRallyPointMessage, ORDER_SET_RALLY_POINT); - break; - case NMT_SET_STANCE: - ENTITY_STRING(CSetStanceMessage, ORDER_SET_STANCE); - break; - case NMT_FORMATION_GOTO: - ENTITY_POSITION_FORM(CFormationGotoMessage, ORDER_GOTO); - break; - //TODO: make formation move to within range of target and then attack normally - case NMT_CONTACT_ACTION: - ENTITY_ENTITY_INT_BOOL(CContactActionMessage, ORDER_CONTACT_ACTION); - break; - case NMT_FORMATION_CONTACT_ACTION: - ENTITY_ENTITY_INT(CFormationContactActionMessage, ORDER_CONTACT_ACTION); - break; - case NMT_NOTIFY_REQUEST: - ENTITY_ENTITY_INT(CNotifyRequestMessage, ORDER_NOTIFY_REQUEST); - break; - case NMT_PRODUCE: - ENTITY_INT_STRING(CProduceMessage, ORDER_PRODUCE); - break; - case NMT_PLACE_OBJECT: - { - CPlaceObjectMessage *msg = (CPlaceObjectMessage *) pMsg; - isQueued = msg->m_IsQueued != 0; - - // Figure out the player - CPlayer* player = 0; - if(msg->m_Entities.size() > 0) - player = msg->m_Entities[0]->GetPlayer(); - else - player = g_Game->GetLocalPlayer(); - - // Create the object - CVector3D pos(msg->m_X/1000.0f, msg->m_Y/1000.0f, msg->m_Z/1000.0f); - HEntity newObj = g_EntityManager.CreateFoundation( msg->m_Template, player, pos, msg->m_Angle/1000.0f ); - newObj->m_actor->SetPlayerID(player->GetPlayerID()); - if( newObj->Initialize() ) - { - // Order all the selected units to work on the new object using the given action - order.m_type = CEntityOrder::ORDER_START_CONSTRUCTION; - order.m_new_obj = newObj; - QueueOrder(order, msg->m_Entities, isQueued); - } - } - break; - - } - return clientMask; } @@ -466,7 +230,6 @@ size_t CSimulation::GetMessageMask(CNetMessage* UNUSED(pMsg), size_t UNUSED(oldM void CSimulation::QueueLocalCommand(CNetMessage *pMsg) { - m_pTurnManager->QueueLocalCommand(pMsg); } diff --git a/source/simulation/Simulation.h b/source/simulation/Simulation.h index bbb6ea24f0..678dd070bb 100644 --- a/source/simulation/Simulation.h +++ b/source/simulation/Simulation.h @@ -23,14 +23,12 @@ class CGame; class CGameAttributes; class CWorld; -class CTurnManager; class CNetMessage; class CSimulation { CGame *m_pGame; CWorld *m_pWorld; - CTurnManager *m_pTurnManager; // Current game time; store as double for precision double m_Time; @@ -51,11 +49,6 @@ public: CSimulation(CGame *pGame); ~CSimulation(); - inline void SetTurnManager(CTurnManager *pTurnManager) - { m_pTurnManager=pTurnManager; } - inline CTurnManager *GetTurnManager() - { return m_pTurnManager; } - void RegisterInit(CGameAttributes *pGameAttributes); int Initialize(CGameAttributes *pGameAttributes); diff --git a/source/simulation/TurnManager.cpp b/source/simulation/TurnManager.cpp deleted file mode 100644 index 426341a05f..0000000000 --- a/source/simulation/TurnManager.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* Copyright (C) 2010 Wildfire Games. - * This file is part of 0 A.D. - * - * 0 A.D. 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, either version 2 of the License, or - * (at your option) any later version. - * - * 0 A.D. 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 0 A.D. If not, see . - */ - -#include "precompiled.h" - -#include "TurnManager.h" -#include "network/NetMessage.h" -#include "network/Network.h" -#include "ps/GameRecord.h" -#include "ps/CLogger.h" - -#include - -CSinglePlayerTurnManager *g_SinglePlayerTurnManager=NULL; - -CTurnManager::CTurnManager() -{ - for (int i=0; i<3; i++) - m_Batches[i].m_TurnLength = DEFAULT_TURN_LENGTH; -} - -void CTurnManager::ClearBatch(uintptr_t batch) -{ - typedef std::vector MsgVector; - MsgVector &messages=m_Batches[batch].m_Messages; - MsgVector::iterator it=messages.begin(); - while (it != messages.end()) - { - delete it->m_pMessage; - ++it; - } - messages.clear(); -} - -void CTurnManager::SBatch::Swap(SBatch &other) -{ - std::swap(m_Messages, other.m_Messages); - std::swap(m_TurnLength, other.m_TurnLength); -} - -void CTurnManager::RotateBatches() -{ - // {a, b, c} => {b, c, a}: - // {a, b, c} - // -- swap (0, 1) - // {b, a, c} - // -- swap (1, 2) - // {b, c, a} - - m_Batches[0].Swap(m_Batches[1]); - m_Batches[1].Swap(m_Batches[2]); -} - -void CTurnManager::IterateBatch(uintptr_t batch, BatchIteratorFunc *fp, void *userdata) -{ - typedef std::vector MsgVector; - MsgVector &messages=m_Batches[batch].m_Messages; - MsgVector::iterator it=messages.begin(); - while (it != messages.end()) - { - it->m_ClientMask=(*fp)(it->m_pMessage, it->m_ClientMask, userdata); - ++it; - } -} - -void CTurnManager::SendBatch(uintptr_t batch) -{ - typedef std::vector MsgVector; - MsgVector &messages=m_Batches[batch].m_Messages; - MsgVector::iterator it=messages.begin(); - while (it != messages.end()) - { - SendMessageMasked(it->m_pMessage, it->m_ClientMask); - ++it; - } - CEndCommandBatchMessage *pMsg=new CEndCommandBatchMessage(); - pMsg->m_TurnLength=m_Batches[batch].m_TurnLength; - SendMessageMasked(pMsg, (size_t)-1); -} - -void CTurnManager::SendMessageMasked(CNetMessage *pMsg, size_t clientMask) -{ - for (size_t i=0;iPush(pMsg); - } - } -} - -void CTurnManager::QueueMessage(uintptr_t batch, CNetMessage *pMsg) -{ - m_Batches[batch].m_Messages.push_back(SMessageSyncEntry(pMsg)); -} - -void CTurnManager::SetClientPipe(size_t client, IMessagePipeEnd *pipe) -{ - m_Clients[client].m_Pipe=pipe; -} - -void CTurnManager::SetTurnLength(uintptr_t batch, int turnLength) -{ - m_Batches[batch].m_TurnLength=turnLength; -} - -int CTurnManager::GetTurnLength() -{ - return m_Batches[0].m_TurnLength; -} - -void CTurnManager::Initialize(size_t numClients) -{ - m_Clients.resize(numClients); -} - - -void CTurnManager::RecordBatch(uintptr_t batch) -{ - IterateBatch(batch, RecordIterator, m_pRecord); - CEndCommandBatchMessage msg; - m_pRecord->WriteMessage(&msg); -} - -size_t CTurnManager::RecordIterator(CNetMessage *pMsg, uintptr_t clientMask, void *userdata) -{ - CGameRecord *pRecord=(CGameRecord *)userdata; - - pRecord->WriteMessage(pMsg); - - return clientMask; -} - -CSinglePlayerTurnManager::CSinglePlayerTurnManager() -{} - -void CSinglePlayerTurnManager::NewTurn() -{ - RecordBatch(2); - - RotateBatches(); - ClearBatch(2); -} - -void CSinglePlayerTurnManager::QueueLocalCommand(CNetMessage *pMsg) -{ - QueueMessage(2, pMsg); -} - -bool CSinglePlayerTurnManager::NewTurnReady() -{ - return true; -} diff --git a/source/simulation/TurnManager.h b/source/simulation/TurnManager.h deleted file mode 100644 index 5c88a9078d..0000000000 --- a/source/simulation/TurnManager.h +++ /dev/null @@ -1,146 +0,0 @@ -/* Copyright (C) 2009 Wildfire Games. - * This file is part of 0 A.D. - * - * 0 A.D. 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, either version 2 of the License, or - * (at your option) any later version. - * - * 0 A.D. 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 0 A.D. If not, see . - */ - -#ifndef INCLUDED_TURNMANAGER -#define INCLUDED_TURNMANAGER - -//#include "Network/NetMessage.h" -//#include "Network/Network.h" -#include - -class CGameRecord; -class CNetMessage; -class IMessagePipeEnd; - -class CTurnManager -{ -public: - // Default turn length - static const int DEFAULT_TURN_LENGTH = 300; - - // Used with IterateBatch() to iterate a command batch and set the sync mask - // for each message. If the iterating function doesn't wish to change the - // mask, it should return oldMask unchanged. - typedef uintptr_t (BatchIteratorFunc)(CNetMessage *pMsg, uintptr_t oldMask, void *userdata); - - // FIXME Should be in CNetServer instead - struct SClientTimingData - { - // The maximum latency observed from this client - int m_MaxLatency; - // Approximate current round-trip time in milliseconds - int m_Latency; - // Frames per Second - won't be used unless 1000/m_FPS > m_Latency (i.e. - // framerate is too slow to handle [m_Latency] as the turn length) - int m_FPS; - }; - -private: - struct SMessageSyncEntry - { - // A bitmask telling which clients to sync this message to - uintptr_t m_ClientMask; - // The message pointer - CNetMessage *m_pMessage; - - inline SMessageSyncEntry(CNetMessage *pMsg): - m_ClientMask(0), - m_pMessage(pMsg) - {} - }; - - struct SBatch - { - std::vector m_Messages; - int m_TurnLength; - - void Swap(SBatch &other); - }; - - struct SClient - { - // FIXME Move to CNetServer - SClientTimingData m_TimingData; - IMessagePipeEnd *m_Pipe; - }; - - std::vector m_Clients; - SBatch m_Batches[3]; - - CGameRecord *m_pRecord; - -public: - // Rotate the three batches: {0, 1, 2} => {1, 2, 0} - void RotateBatches(); - - // Go through each message in the specified batch and send the message to - // each of the clients whose bit in the message's mask is set - void SendBatch(uintptr_t batch); - void ClearBatch(uintptr_t batch); - - void SetClientPipe(size_t client, IMessagePipeEnd *pipe); - // FIXME Should be in CNetServer instead [and implemented] - // void UpdateTimingData(size_t client, int fps, int currentLatency); - void SetTurnLength(uintptr_t batch, int turnLength); - - void SendMessageMasked(CNetMessage *pMsg, uintptr_t clientMask); - - // Add the message to the specified batch. The message is assumed to be - // validated before passed here, and will be blindly trusted. - void QueueMessage(uintptr_t batch, CNetMessage *pMsg); - - // Send the specified batch to CGameRecord for recording - void RecordBatch(uintptr_t batch); - static BatchIteratorFunc RecordIterator; - -public: - CTurnManager(); - virtual ~CTurnManager() { } - - void Initialize(size_t numClients); - - // Return the millisecond delay between the last frame and the next. - // CSimulation will use this to determine when to perform the deterministic - // update and call NewTurn() - int GetTurnLength(); - - // Called by CSimulation when the current turn time has passed. - virtual void NewTurn() = 0; - - // Used by CSimulation to ask whether it can call NewTurn. - virtual bool NewTurnReady() = 0; - - // Apply a function to all messages in a given batch. - void IterateBatch(uintptr_t batch, BatchIteratorFunc *func, void *userdata); - - // Queue a command originating from the local player. - virtual void QueueLocalCommand(CNetMessage *pMsg) = 0; -}; - -class CSinglePlayerTurnManager: public CTurnManager -{ -public: - CSinglePlayerTurnManager(); - - virtual void NewTurn(); - virtual void QueueLocalCommand(CNetMessage *pMsg); - virtual bool NewTurnReady(); -}; - -extern CSinglePlayerTurnManager *g_SinglePlayerTurnManager; - -#endif