//===========================================================================// // File: Connection.cpp // Project: MUNGA Brick: Replicator // Contents: //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 08/24/97 JMA Infrastructure changes. // 08/25/97 ECH Infrastructure changes. // //---------------------------------------------------------------------------// // Copyright (C) 1994-1997, Virtual World Entertainment, Inc. // // PROPRIETARY AND CONFIDENTIAL // //===========================================================================// #include "AdeptHeaders.hpp" #include "Connection.hpp" #include "Replicator.hpp" //#define HUNT_BUG "your_loginname_here" //############################################################################# //######################### Connection ########################### //############################################################################# Connection* Connection::Local = NULL; Connection* Connection::Server = NULL; Connection* Connection::Hermit = NULL; const Receiver::MessageEntry Connection::MessageEntries[]= { MESSAGE_ENTRY(Connection, Replicate), MESSAGE_ENTRY(Connection, Replicator) }; Connection::ClassData* Connection::DefaultData = NULL; Stuff::SafeChainOf* g_pTempReplicators = NULL; // jcem #ifdef _DEBUG int g_nMechLabs = 0; #endif // _DEBUG // //############################################################################# //############################################################################# // void Connection::InitializeClass() { Verify(!DefaultData); DefaultData = new ClassData( ConnectionClassID, "Adept::Connection", InBox::DefaultData, ELEMENTS(MessageEntries), MessageEntries ); Register_Object(DefaultData); } // //############################################################################# //############################################################################# // void Connection::TerminateClass() { Unregister_Object(DefaultData); delete DefaultData; DefaultData = NULL; } // //############################################################################# //############################################################################# // Connection::Connection( BYTE id, DWORD network_address, const char *name ): InBox(DefaultData, Network::ConnectionBoxID), allReplicators(NULL), nextReplicatorID(id) { Check_Pointer(this); connectionID = id; networkAddress = network_address; connectionName = name; bytesToTransfer = 0; dataBuffer = NULL; // we dont add here due to the fact we don't really know // if this is the local connection or hermit connection at this point... for (int i = 0; i < 8192; ++i) { usedConnections[i] = 0x0; } replicatorCount = 0; } // //############################################################################# //############################################################################# // Connection::~Connection() { if (Network::GetInstance() != NULL) { Network::GetInstance()->RemoveConnectionToStats(connectionID); } SafeChainIteratorOf replicators(&allReplicators); Replicator *replicator; while ((replicator = replicators.GetCurrent()) != NULL) { Check_Object(replicator); Unregister_Object(replicator); delete replicator; replicators.First(); } } // //############################################################################# //############################################################################# // void Connection::DeleteChildren(void) { SafeChainIteratorOf replicators(&allReplicators); Replicator *replicator; while ((replicator = replicators.GetCurrent()) != NULL) { Check_Object(replicator); Unregister_Object(replicator); delete replicator; replicators.First(); } nextReplicatorID = ReplicatorID(connectionID); for (int i = 0; i < 8192; ++i) { usedConnections[i] = 0x0; } replicatorCount = 0; } // //############################################################################# //############################################################################# // void Connection::ReplicateMessageHandler( const Replicator::CreateMessage *message ) { Check_Object(this); Check_Object(message); Verify(message->messageID == ReplicateMessageID); // //----------------------------------------------------------- // Get the class data for the object to be replicated and the // make method //----------------------------------------------------------- // RegisteredClass::ClassData *class_data = RegisteredClass::FindClassData(message->classID); Check_Object(class_data); Verify(class_data->IsDerivedFrom(Replicator::DefaultData)); Replicator::Factory make_method = Cast_Pointer(Replicator::ClassData*, class_data)->replicatorFactory; Check_Pointer(make_method); // //-------------------- // Execute make method //-------------------- // ReplicatorID base_id = message->replicatorID; (*make_method)(message, &base_id); } // //############################################################################# //############################################################################# // void Connection::ReplicatorMessageHandler( const Message *manager_message ) { Check_Object(this); Check_Object(manager_message); Verify(manager_message->messageID == ReplicatorMessageID); // //--------------------------- // Get message for replicator //--------------------------- // const Replicator::Message *replicator_message = reinterpret_cast( reinterpret_cast(manager_message) + sizeof(*manager_message) ); Check_Object(replicator_message); Verify(replicator_message->replicatorID != ReplicatorID::Null); #if defined(HUNT_BUG) SPEW(( HUNT_BUG, "Received message for %d:%d", replicator_message->replicatorID.connectionID, replicator_message->replicatorID.localID )); #endif // //-------------------- // Find the replicator //-------------------- // Replicator *replicator = FindReplicator(replicator_message->replicatorID); // //---------------------------------------------- // If the replicator exists, send it the message //---------------------------------------------- // if (replicator) { Check_Object(replicator); replicator->Receive(replicator_message); } } // //############################################################################# //############################################################################# // const ReplicatorID& Connection::GetNextReplicatorID() { if (!this) { Check_Object(Connection::Hermit); return Connection::Hermit->GetNextReplicatorID(); } Check_Object(this); ++nextReplicatorID.localID; int loop_killer = 0; while (ISConnectionUsed(nextReplicatorID.localID)) { ++nextReplicatorID.localID; if (loop_killer > 65537) STOP(("No connections Left")); loop_killer++; } return nextReplicatorID; } // //############################################################################# //############################################################################# // void Connection::AddReplicator(Replicator *replicator) { Check_Object(this); Check_Object(replicator); // //--------------------------------------------- // Make sure that the replicator is safe to use //--------------------------------------------- // Verify(!FindReplicator(replicator->GetReplicatorID())); allReplicators.Add(replicator); Verify(replicator->GetReplicatorID().connectionID == connectionID); if (replicator->GetReplicatorID().localID > nextReplicatorID.localID) { nextReplicatorID.localID = replicator->GetReplicatorID().localID; } ReplicatorCreated(replicator); if (g_pTempReplicators) { // jcem g_pTempReplicators->Add(replicator); #ifdef _DEBUG gosASSERT(g_nMechLabs == 1); #endif // _DEBUG } else { #ifdef _DEBUG gosASSERT(g_nMechLabs <= 1); #endif // _DEBUG } } // //############################################################################# //############################################################################# // void Connection::RemoveReplicator(Replicator *replicator) { Check_Object(this); Check_Object(replicator); // //--------------------------------------------- // Make sure that the replicator is safe to use //--------------------------------------------- // ReplicatorDestroyed(replicator); Check_Object(FindReplicator(replicator->GetReplicatorID())); allReplicators.RemovePlug(replicator); replicator->owningConnection = NULL; } // //############################################################################# //############################################################################# // void Connection::ReplicatorCreated( Replicator *replicator ) { Check_Object(this); Check_Object(replicator); SetConnectionUsed(replicator->GetReplicatorID().localID); ++replicatorCount; #ifdef _ARMOR if (Stuff::ArmorLevel > 2) { Verify(allReplicators.GetSize() == replicatorCount); } #endif } // //############################################################################# //############################################################################# // void Connection::ReplicatorDestroyed(Replicator *replicator) { Check_Object(this); ClearConnectionUsed(replicator->GetReplicatorID().localID); --replicatorCount; #ifdef _ARMOR if (Stuff::ArmorLevel > 2) { Verify(allReplicators.GetSize()-1 == replicatorCount); } #endif } // //############################################################################# //############################################################################# // void Connection::SetConnectionUsed(int connection) { Verify(!ISConnectionUsed(connection)); Check_Object(this); Verify(connection < 65536); int byte = connection>>3; int bit = connection&0x7; Verify(byte < 8192); usedConnections[byte] |= 0x1<>3; int bit = connection&0x7; Verify(byte < 8192); usedConnections[byte] &= ~(0x1<>3; int bit = connection&0x7; Verify(byte < 8192); Check_Object(this); return (usedConnections[byte]&(0x1<GetReplicatorMode() == Replicator::ReplicantMode); Verify(replicator_message->replicatorID != ReplicatorID::Null); // //------------------------------------------------ // Build a network message in dynamic build buffer //------------------------------------------------ // #if defined(HUNT_BUG) SPEW(( HUNT_BUG, "Sending message to master %d:%d", replicator_message->replicatorID.connectionID, replicator_message->replicatorID.localID )); #endif size_t total_size = sizeof(Message) + replicator_message->messageLength; DynamicMemoryStream build_buffer(total_size); Message *manager_message = new (build_buffer.GetPointer()) Message( ReplicatorMessageID, total_size, 0, replicator_message->messageFlags ); Check_Object(manager_message); build_buffer.AdvancePointer(sizeof(*manager_message)); Mem_Copy( build_buffer.GetPointer(), replicator_message, replicator_message->messageLength, build_buffer.GetBytesRemaining() ); // //------------- // Send message //------------- // Send(manager_message, replicator->owningConnection); } // //############################################################################# //############################################################################# // void Connection::BroadcastToReplicants( Replicator *replicator, const Replicator::Message *replicator_message ) { Check_Object(this); Check_Object(replicator); Check_Object(replicator_message); Verify(replicator->GetReplicatorMode() == Replicator::MasterMode); Verify(replicator_message->replicatorID != ReplicatorID::Null); #if defined(HUNT_BUG) SPEW(( HUNT_BUG, "Sending message to replicants of %d:%d", replicator_message->replicatorID.connectionID, replicator_message->replicatorID.localID )); #endif // //------------------------------------------------ // Build a network message in dynamic build buffer //------------------------------------------------ // size_t total_size = sizeof(Message) + replicator_message->messageLength; DynamicMemoryStream build_buffer(total_size); Message *manager_message = new (build_buffer.GetPointer()) Message( ReplicatorMessageID, total_size, 0, replicator_message->messageFlags ); Check_Object(manager_message); build_buffer.AdvancePointer(sizeof(*manager_message)); Mem_Copy( build_buffer.GetPointer(), replicator_message, replicator_message->messageLength, build_buffer.GetBytesRemaining() ); // //------------- // Send message //------------- // ExclusiveBroadcast(manager_message); } // //############################################################################# //############################################################################# // Replicator* Connection::FindReplicator(const ReplicatorID &id) { Check_Object(this); Check_Object(&id); Connection *connection; connection = this; if(id.connectionID != connectionID) { Check_Object(Network::GetInstance()); connection = Network::GetInstance()->GetConnection(id.connectionID); } // //-------------------------------------------------------------------- // For now, we will spin through the loop. This will not be good soon //-------------------------------------------------------------------- // SafeChainIteratorOf replicators(&connection->allReplicators); Replicator *replicator; while ((replicator = replicators.ReadAndNext()) != NULL) { Check_Object(replicator); if (replicator->GetReplicatorID() == id) return replicator; } return NULL; } void Connection::DeleteReplicator(Replicator* p) { delete p; }