Shadowrun: Awakened 29 September 2011 - Build 871
ZoneServer.cpp
Go to the documentation of this file.
00001 #include "ZoneServer.h"
00002 
00003 namespace SraNetwork {
00004     ZoneServer::ZoneServer(void)
00005     {
00006     }
00007 
00008 
00009     ZoneServer::~ZoneServer(void)
00010     {
00011     }
00012 
00013     void ZoneServer::Run()
00014     {   
00015         //Initalizing stuff:
00016         int lastPortUsed = 6000; //The next unused port, we will start at port 6000. !Attention! do not try to use a port > 9999 or the udk server wont't accept connections...
00017         //we may need a list of used ports later so if we have started a looot of zones we may 
00018         //have a "port-number-overrun" so we can start from the beginning without using an already opened port.
00019         std::map<int, ZoneInfo>::iterator it;
00020 
00021         //Connect to world server
00022         m_rServerInterface = RakPeerInterface::GetInstance();
00023         SocketDescriptor chatSocket(SraNetwork::ZONE_SERVER_PORT, 0);
00024         m_rServerInterface->Startup(1, &chatSocket, 1);
00025         m_rServerInterface->Connect(SraNetwork::WORLD_SERVER_ADDR, SraNetwork::SERVER_ZONE_PORT, 0, 0, 0);
00026 
00027         printf("ZoneServer connecting to World ....");
00028         bool done = false; 
00029         bool result = false; //don't return in loop so we can shut down RakNet before exiting
00030         while (!done) //Block while connecing
00031         {
00032             Packet* m_pPacket = m_rServerInterface->Receive();
00033             if (m_pPacket) 
00034             {
00035                 if (m_pPacket->data[0] == ID_CONNECTION_REQUEST_ACCEPTED) 
00036                 {
00037                     result = true;
00038                 } 
00039                 else if (m_pPacket->data[0] == ID_CONNECTION_ATTEMPT_FAILED)
00040                 {
00041                     printf("Failed: connection attempt failed\n");
00042                 } else 
00043                 {
00044                     printf("Failed: Unknown opcode %d\n", m_pPacket->data[0]);
00045                 }
00046                 m_rServerInterface->DeallocatePacket(m_pPacket);
00047                 m_pPacket = 0;
00048                 done = true;
00049             }
00050             Sleep(10);
00051         }
00052         if (!result)
00053         {
00054             printf("Failed to connect to world, exiting now\n");
00055             m_rServerInterface->Shutdown(0);
00056             return;
00057         }
00058         printf("Connection established, waiting for zone connections\n");
00059 
00060         bool running = true; //maybe we do not need this, but i don't like while(1) :P
00061         while (running)
00062         {
00063             Packet* m_pPacket = m_rServerInterface->Receive();
00064             if (m_pPacket) 
00065             {
00066                 if ( m_pPacket->data[0] == ID_CONNECTION_LOST ) {
00067                     printf("Lost connection to world server ! Shutting down now\n");
00068                     running = false;
00069                 } else {
00070                     SraNetwork::SraZonePacket *pack = (SraZonePacket*)m_pPacket->data;
00071                     printf("Client with id : %d connects to zone %d\n", pack->clientID, pack->toZoneID);
00072                     if ( pack->fromZoneID == -1 || (pack->toZoneID != -1 && pack->fromZoneID != -1) ) 
00073                     {
00074                         it = m_mZones.find(pack->toZoneID);
00075                         int currentPort;
00076                         if ( it == m_mZones.end() ) 
00077                         {
00078                             currentPort  = lastPortUsed++;
00079                             //requested zone is not running, so start it now:
00080                             if (!spawnZone( pack->toZoneID, currentPort) ) 
00081                             {
00082                                 printf("Uh oh, could not spawn zone, this is really bad and we should do something about it\n");
00083                             }
00084                         } else {
00085                             //Zone is running:
00086                             currentPort = it->second.zonePort;
00087                         }
00088                         SraZonePacket answer;
00089                         ZeroMemory(&answer,sizeof(answer));
00090                         answer.clientID = pack->clientID;
00091                         answer.fromZoneID = -1;
00092                         answer.toZoneID = currentPort;
00093                         printf("Zone spawned, sending OK\n");
00094                         if (m_rServerInterface != 0) {
00095                         //Send answer to server
00096                         m_rServerInterface->Send( (char*)&answer, sizeof(answer), HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true);
00097                         } else {
00098                             printf("m_r server interface null!\n");
00099                         }
00100 
00101                     } else if (pack->toZoneID == -1)
00102                     {
00103                         //client is logging off, so we maaaay shut down zoneID
00104                     } else {
00105                         printf("Corrupted package\n");
00106                     }
00107                 }
00108             }
00109             m_rServerInterface->DeallocatePacket(m_pPacket);
00110             Sleep(10);
00111         }
00112         //Shut down zone processes
00113         for (it = m_mZones.begin(); it != m_mZones.end(); ++it)
00114         {
00115             shutdownZone( it->first );
00116         }
00117         m_rServerInterface->Shutdown(0);
00118     }
00119 
00120     bool ZoneServer::spawnZone(int zoneID, int port)
00121     {
00122         STARTUPINFO si;
00123         ZeroMemory(&si, sizeof(si));
00124         PROCESS_INFORMATION pi;
00125         ZeroMemory(&pi, sizeof(pi));
00126         si.cb = sizeof(si);
00127         
00128         std::wostringstream str;
00129         //Assuming that this zone server is executed from udk\binaries\win32\usercode
00130         str << "..\\udk.exe server TestBox?dedicated?listen=true -port=" << port << " -console -log";
00131         TCHAR * command = new TCHAR[wcslen(str.str().c_str())];
00132         
00133         wcscpy(command, str.str().c_str());
00134         printf("Starting zone : %ws with id %d\n", command, zoneID);
00135         // Start the udk process. 
00136         if( !CreateProcess( NULL,  
00137             command,        // udk.exe -PORT=%port% -console -log
00138             NULL,
00139             NULL,
00140             FALSE,
00141             0,    
00142             NULL, 
00143             NULL, 
00144             &si,            // Pointer to STARTUPINFO structure
00145             &pi )           // Pointer to PROCESS_INFORMATION structure
00146             ) 
00147         {
00148             printf( "CreateProcess failed (%d).\n", GetLastError() );
00149             return false;
00150         }
00151 
00152         //Store zone info 
00153         ZoneInfo info;
00154         ZeroMemory(&info, sizeof(info));
00155         memcpy_s( &info.procInfo, sizeof(pi), &pi, sizeof(pi));
00156         info.zonePort = port;
00157         m_mZones.insert( std::pair<int, ZoneInfo>(zoneID, info) );
00158         return true;
00159     }
00160 
00161     void ZoneServer::shutdownZone( int zoneID ) 
00162     {
00163         std::map<int, ZoneInfo>::iterator it;
00164 
00165         it = m_mZones.find( zoneID);
00166         if ( it != m_mZones.end() ) 
00167         {
00168             CloseHandle( it->second.procInfo.hProcess);
00169             CloseHandle( it->second.procInfo.hThread);
00170         }
00171     }
00172 }

Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.

GNU Lesser General Public License 3 Sourceforge.net