#include "munga.h" #pragma hdrstop #include "hostmgr.h" #include "interest.h" #include "icom.h" #include "app.h" #include "notation.h" #include "nttmgr.h" #if defined(TRACE_ROUTE_PACKET) static BitTrace Route_Packet("Route Packet"); # define SET_ROUTE_PACKET() Route_Packet.Set() # define CLEAR_ROUTE_PACKET() Route_Packet.Clear() #else # define SET_ROUTE_PACKET() # define CLEAR_ROUTE_PACKET() #endif const NetworkAddress NullNetworkAddress = 0x00000000;// 0.0.0.0 (in TCP land); //############################################################################# // Shared Data Support // NetworkClient::SharedData NetworkClient::DefaultData( NetworkClient::GetClassDerivations(), NetworkClient::GetMessageHandlers() ); // //############################################################################# // Code for the network client class //############################################################################# // Derivation* NetworkClient::GetClassDerivations() { static Derivation classDerivations(Receiver::GetClassDerivations(), "NetworkClient"); return &classDerivations; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Constructor for the NetworkClient // NetworkClient::NetworkClient( ClassID class_ID, SharedData &virtual_data, ClientID client_ID ): Receiver(class_ID, virtual_data) { clientID = client_ID; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Destructor for the NetworkClient // NetworkClient::~NetworkClient() { } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Destructor for the NetworkClient // Logical NetworkClient::TestInstance() const { return IsDerivedFrom(*GetClassDerivations()); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Receive packet for the NetworkClient // void NetworkClient::ReceiveNetworkPacket( NetworkPacket*, Receiver::Message *packet_message ) { Dispatch(packet_message); } // //############################################################################# // Code for the network manager class //############################################################################# const Receiver::HandlerEntry NetworkManager::MessageHandlerEntries[]= { MESSAGE_ENTRY(NetworkManager,ReceiveEggFile) }; Receiver::MessageHandlerSet& NetworkManager::GetMessageHandlers() { static Receiver::MessageHandlerSet messageHandlers(ELEMENTS(NetworkManager::MessageHandlerEntries), NetworkManager::MessageHandlerEntries, NetworkClient::GetMessageHandlers()); return messageHandlers; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Shared Data Support // NetworkManager::SharedData NetworkManager::DefaultData( NetworkManager::GetClassDerivations(), NetworkManager::GetMessageHandlers() ); Derivation* NetworkManager::GetClassDerivations() { static Derivation classDerivations(NetworkClient::GetClassDerivations(), "NetworkManager"); return &classDerivations; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Constructor for the NetworkManager // NetworkManager::NetworkManager(SharedData &shared_data): NetworkClient(NetworkManagerClassID, shared_data, NetworkManagerClientID) { // basic init goes here gameID = 0; addresses = NULL; num_addresses = 0; eggTempBuffer = NULL; networkEggNotationFile = NULL; eggTempNext = 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Creates a host for us. Any derived class must deal with reading the // notation file to get the network nodes to connect to. This start is // designed for STAND-ALONE MODE ONLY and should not be inherited for use by // void NetworkManager::StartConnecting(Mission *) { Check(this); // //--------------------------------------------------------- // Make the local host, and get the application to adopt it //--------------------------------------------------------- // SOCKADDR_IN address; address.sin_family = AF_INET; address.sin_addr.S_un.S_addr = 1; Host *local_host = new Host(1, GameMachineHostType, &address); Register_Object(local_host); Check(application); Check(application->GetHostManager()); application->GetHostManager()->AdoptLocalHost(local_host); // //-------------------------------------------------------------------- // Now, since this host creator is for stand-alone mode, send the load // mission message to the application //-------------------------------------------------------------------- // Check(application); Application::Message load_message( Application::LoadMissionMessageID, sizeof(Application::Message) ); application->Post(DefaultEventPriority, application, &load_message); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // NetworkManager::EndMission This routine is called when a mission ends to // allow the network management system to do stuff (like disconnecting network // connections between pods and so on) // Logical NetworkManager::Shutdown() { // // If there is a notation file floating about, kill it! // if (networkEggNotationFile) { Unregister_Object(networkEggNotationFile); delete networkEggNotationFile; } // // Deregister local host // Host *local_host; local_host = application->GetHostManager()->OrphanLocalHost(); Unregister_Object(local_host); delete local_host; return True; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Destructor for the NetworkManager // NetworkManager::~NetworkManager() { // shutdown net goes here } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // NetworkManager::ReceiveEggFileMessageHandler // void NetworkManager::ReceiveEggFileMessageHandler( ReceiveEggFileMessage* EggMessage ) { // // An egg sequence number of -1 means that the egg is posted locally, and // should just call create mission // if (EggMessage->sequenceNumber == -1) { application->CreateMission(networkEggNotationFile); return; } if (EggMessage->sequenceNumber == 0) { // // Make a buffer // eggTempBuffer = new char[EggMessage->notationFileLength]; Register_Pointer(eggTempBuffer); eggTempNext = 0; } // // Write the egg data into the buffer // memcpy( (eggTempBuffer+eggTempNext), EggMessage->notationData, EggMessage->thisMessageLength ); eggTempNext += EggMessage->thisMessageLength; // // If we don't have all the data, return and wait for more // if(eggTempNext < EggMessage->notationFileLength) { return; } // // We've got all the data, make the notation file // networkEggNotationFile = new NotationFile(); Register_Object(networkEggNotationFile); networkEggNotationFile->ReadText(eggTempBuffer, eggTempNext); networkEggNotationFile->WriteFile("last.egg"); // // Now turn the notation file into a mission // application->CreateMission(networkEggNotationFile); // // Get rid of the ram buffer now that we're done with it // Unregister_Pointer(eggTempBuffer); delete eggTempBuffer; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // NetworkManager::Send Handles sending a message to a specific network address // which can NOT be us. Default behavior is to do nothing, as no network is // hooked up if we get here // void NetworkManager::Send( Message *, ClientID, HostID ) { } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // NetworkManager::Broadcast Handles broadcasting a message to everyone, // including ourselves. !!!! Reliable broadcasting is currently used, // implimented by sending a point-to-point message to every destination. // void NetworkManager::Broadcast( Message *message, ClientID client_id ) { // // Send this message back to ourselves // NetworkClient *client = GetNetworkClientPointer(client_id); Check(client); client->ReceiveNetworkPacket(NULL, message); // // Broadcast the message to everyone else on the network // ExclusiveBroadcast(message,client_id); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // NetworkManager::ExclusiveBroadcast Broadcasts a message to everyone on the // network execpt us. Default behavior sends it to nobody, as there is really // no network // void NetworkManager::ExclusiveBroadcast( Message *, ClientID ) { } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // NetworkManager::GetNetworkClientPointer Determine who the client of a // message is and return a pointer to them. // NetworkClient* NetworkManager::GetNetworkClientPointer(ClientID client_id) { switch (client_id) { case NetworkClient::NetworkManagerClientID: return this; case NetworkClient::EntityManagerClientID: Check(application); return application->GetEntityManager(); case NetworkClient::HostManagerClientID: Check(application); return application->GetHostManager(); case NetworkClient::InterestManagerClientID: Check(application); return application->GetInterestManager(); case NetworkClient::IcomManagerClientID: Check(application); return application->GetIntercomManager(); case NetworkClient::ApplicationClientID: Check(application); return application; default: DEBUG_STREAM << "------UNKNOWN NETWORK CLIENT ID " << client_id << std::endl << std::flush; Fail("Unknown Client ID"); break; } return NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // NetworkManager::RoutePacket // Logical NetworkManager::RoutePacket() { Check(this); Byte message_buffer[NETWORKMANAGER_BUFFER_SIZE]; NetworkPacket *p; // // Return if check buffers doesn't have a packet for us // if (!CheckBuffers((NetworkPacket*)message_buffer)) { return False; } // // Process and route the packet properly // p = (NetworkPacket*)message_buffer; if (p->gameID == gameID) { // cout<<"++++++++client "<clientID<<" gameID "<gameID<<" fromHost "<fromHost<<"\n"; NetworkClient *client = GetNetworkClientPointer(p->clientID); Check(client); SET_ROUTE_PACKET(); client->ReceiveNetworkPacket(p, &p->messageData); CLEAR_ROUTE_PACKET(); } else { DEBUG_STREAM << "+++++++++ client " << p->clientID << " gameID " << p->gameID << " fromHost " << p->fromHost << std::endl << std::flush; Fail("######### NOT A PACKET FOR THIS GAME!"); } RemovePacket(p); return True; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // NetworkManager::ExecuteBackground Allows the network to perform tasks in // the applications background. The method should return True if the manager // is busy, false otherwise. For example, if the input and output buffers of // the network driver are not empty then return True, otherwise return False. // Logical NetworkManager::ExecuteBackground() { return True; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // NetworkManager::CheckBuffers Checks to see if there is a message for us // buffered up in the network interface card and returns a pointer to it. // Logical NetworkManager::CheckBuffers(NetworkPacket*) { Fail("NetworkManager::CheckBuffers - should never reach here!"); return False; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // NetworkManager::RemovePacket If the network implimentation requires us to // free up a packet buffer, this routine would do it. // void NetworkManager::RemovePacket(NetworkPacket*) { Fail("NetworkManager::RemovePacket - should never reach here!"); }