CServerS* CMasterGameServer::GetLeastUsedServer(EGBGameRegion region)
{
	CServerS* selected = NULL;
	int       minGames = 999;

	// search for server with maximum available users
	for(TSupersList::iterator it = supers_.begin(); it != supers_.end(); ++it) 
	{
		CServerS* super = it->second;

		// filter our supervisors if region is specified
		if(region != GBNET_REGION_Unknown && super->region_ != region)
			continue;

		if(super->GetExpectedGames() >= super->maxGames_)
			continue;

		if(super->GetExpectedGames() < minGames) {
			selected = super;
			minGames = super->GetExpectedGames();
		}


	}

	return selected;
}
void CMasterGameServer::OnNetPeerDisconnected(DWORD peerId)
{
	peer_s& peer = peers_[peerId];
	switch(peer.status)
	{
	case PEER_Free:
		break;
	case PEER_Connected:
		break;
	case PEER_Validated:
		break;

	case PEER_GameServer:
		{
			TGamesList::iterator it = games_.find(peerId);
			// see if game was already closed successfully
			if(it == games_.end())
				break;

			CServerG* game = it->second;

			r3dOutToLog("game %s closed unexpectedly\n", game->GetName());
			DeleteGame(game);

			games_.erase(it);
			break;
		}

	case PEER_SuperServer:
		{
			TSupersList::iterator it = supers_.find(peerId);
			if(it == supers_.end()) {
				break;
			}

			CServerS* super = it->second;

			r3dOutToLog("master: super disconnected '%s'[%d] \n", super->GetName(), super->id_);
			//TODO? disconnect all games from there.
			delete super;

			supers_.erase(it);

			// supervisor is disconnected, this might be network problem and other supervisors will be disconnecting as well
			// so we initiate cooldown time to wait for disconnected games, etc, etc
			if(r3dGetTime() > supersCooldown_) {
				r3dOutToLog("starting cooldown timer\n");
				supersCooldown_ = r3dGetTime() + 60.0f;
			}

			break;
		}
	}

	peer.status = PEER_Free;
	return;
}
void CMasterGameServer::DeleteGame(CServerG* game)
{
	CServerS* super = GetServerByGameId(game->id_);

	if(super) {
		super->DeregisterGame(game);
	} else {
		r3dOutToLog("master: game %s from UNKNOWN[%d] supervisor disconnected\n", game->GetName(), game->id_ >> 16);
	}

	delete game;
}
Exemple #4
0
void CMasterGameServer::OnNetPeerDisconnected(DWORD peerId)
{
  peer_s& peer = peers_[peerId];
  switch(peer.status)
  {
    case PEER_Free:
      break;
    case PEER_Connected:
      break;
    case PEER_Validated:
      break;
    
    case PEER_GameServer:
    {
      TGamesList::iterator it = games_.find(peerId);
      // see if game was already closed successfully
      if(it == games_.end())
        break;

      CServerG* game = it->second;

      r3dOutToLog("game %s closed unexpectedly\n", game->GetName());
      DeleteGame(game);

      games_.erase(it);
      break;
    }
      
    case PEER_SuperServer:
    {
      TSupersList::iterator it = supers_.find(peerId);
      if(it == supers_.end()) {
        break;
      }
      
      CServerS* super = it->second;

      r3dOutToLog("master: super '%s' disconnected\n", super->GetName());
      //TODO? disconnect all games from there.
      delete super;
    
      supers_.erase(it);
      break;
    }
  }
  
  peer.status = PEER_Free;
  return;
}
Exemple #5
0
void CMasterGameServer::Start(int port, int in_serverId)
{
  SetConsoleTitle("WO::Master");
  
  masterServerId_ = in_serverId;
  r3d_assert(masterServerId_ > 0 && masterServerId_ < 255);

#if 1  // PAX_BUILD
  DoFirstItemsDbUpdate();
#endif
  DoFirstUpdateCGK();
  
  serverNet.Initialize(this, "serverNet");
  if(!serverNet.CreateHost(port, MAX_PEERS_COUNT)) {
    r3dError("CreateHost failed\n");
  }

  r3dOutToLog("MasterGameServer started at port %d\n", port);
  nextLogTime_ = r3dGetTime();
  
  #if 0
  // register local temp supervisor
  {
    r3dOutToLog("@@@ registering local temp supervisor\n");
    SBPKT_S2M_RegisterMachine_s n;
    n.maxGames = 32;
    n.maxPlayers = n.maxGames * 32;
    n.serverGroup = 0;
    r3dscpy(n.serverName, "arktos01");
    n.portStart = SBNET_GAME_PORT;

    DWORD id = curSuperId_++;
    CServerS* super = new CServerS(id, 0x1, 0);
    super->Init(n);
    supers_.insert(TSupersList::value_type(0x12345, super));
  }
  #endif

  //@ShellExecute(NULL, "open", "SupervisorServer.exe", "", "", SW_SHOW);
  
  return;
}
Exemple #6
0
CServerS* CMasterGameServer::GetLeastUsedServer(EGBGameRegion region)
{
  CServerS* selected = NULL;
  int       maxDiff = -1;
  
  // search for server with maximum available users
  for(TSupersList::iterator it = supers_.begin(); it != supers_.end(); ++it) 
  {
    CServerS* super = it->second;
    
    // filter our supervisors if region is specified
    if(region != GBNET_REGION_Unknown && super->region_ != region)
      continue;
    
    int diff = super->maxPlayers_ - super->GetExpectedPlayers();
    // diff can be negative here, because of unexpected joiners
    if(diff > 0 && diff > maxDiff) {
      maxDiff  = diff;
      selected = super;
    }
  }
  
  return selected;
}
void CMasterGameServer::OnNetData(DWORD peerId, const r3dNetPacketHeader* PacketData, int PacketSize)
{
	if(PacketSize < sizeof(r3dNetPacketHeader)) {
		DisconnectCheatPeer(peerId, "too small packet");
		return;
	}

	// wait for validating packet
	if(!DoValidatePeer(peerId, PacketData, PacketSize))
		return;

	peer_s& peer = peers_[peerId];
	r3d_assert(peer.status >= PEER_Validated);

	switch(PacketData->EventID) 
	{
	default:
		r3dOutToLog("CMasterGameServer: invalid packetId %d", PacketData->EventID);
		DisconnectCheatPeer(peerId, "wrong packet id");
		return;

	case SBPKT_S2M_RegisterMachine:
		{
			const SBPKT_S2M_RegisterMachine_s& n = *(SBPKT_S2M_RegisterMachine_s*)PacketData;
			r3d_assert(sizeof(n) == PacketSize);

			r3d_assert(supers_.find(peerId) == supers_.end());

			DWORD ip = net_->GetPeerIp(peerId);
			DWORD id = curSuperId_++;

			// check if that super is already connected or wasn't disconnected yet
			for(TSupersList::iterator it = supers_.begin(); it != supers_.end(); ++it) 
			{
				CServerS* super = it->second;
				if((super->ip_ == ip || super->ip_ == n.externalIpAddr) && strcmp(super->GetName(), n.serverName) == 0)
				{
					r3dOutToLog("master: DUPLICATE super registered '%s' ip:%s\n", n.serverName, inet_ntoa(*(in_addr*)&ip));
					net_->DisconnectPeer(peerId);
					return;
				}
			}

			CServerS* super = new CServerS(id, ip, peerId);
			super->Init(n);
			supers_.insert(TSupersList::value_type(peerId, super));

			r3d_assert(peer.status == PEER_Validated);
			peer.status = PEER_SuperServer;

			// send registration answer
			{
				SBPKT_M2S_RegisterAns_s n;
				n.id = id;
				net_->SendToPeer(&n, sizeof(n), peerId);
			}
			/*if (n.region == GBNET_REGION_US_West)
			{
			r3dOutToLog("super private zone registered Create RentServer now...\n");
			//gServerConfig->LoadRentConfig();
			}*/
			break;
		}
	case SBPKT_M2G_SendPlayerListEnd:
		{
			const SBPKT_M2G_SendPlayerListEnd_s& n = *(SBPKT_M2G_SendPlayerListEnd_s*)PacketData;
			r3d_assert(sizeof(n) == PacketSize);
			//r3dOutToLog("SBPKT_M2G_SendPlayerListEnd\n");
			gMasterUserServer.SendPlayerListEnd(n.ClientPeerId);
			break;
		}
	case SBPKT_M2G_SendPlayerList:
		{
			const SBPKT_M2G_SendPlayerList_s& n = *(SBPKT_M2G_SendPlayerList_s*)PacketData;
			//r3dOutToLog("SBPKT_M2G_SendPlayerList\n");
			//r3d_assert(sizeof(n) == PacketSize);
			gMasterUserServer.SendPlayerList(n.ClientPeerId,n.alive,n.gamertag,n.rep,n.xp);
			break;
		}
	case SBPKT_G2M_SendScreenShot:
		{
			break;
		}
	case SBPKT_G2M_ScreenShotData:
		{
			const SBPKT_G2M_ScreenShotData_s& n = *(SBPKT_G2M_ScreenShotData_s*)PacketData;
			//r3dOutToLog("Received SS %s\n",n.fname);
			extern bool isEnabledSS;
			if (!isEnabledSS) break;

			_mkdir("SSAH");
			FILE* f = fopen(n.fname, "wb");
			if(f == NULL) {
				r3dOutToLog( "SaveScreenshot unable to save fname:%s", n.fname);
				return;
			}
			fwrite((char*)PacketData + sizeof(n), 1, n.size, f);
			fclose(f);
			break;
		}
	case SBPKT_G2M_SendNoticeMsg:
		{
			const SBPKT_G2M_SendNoticeMsg_s& n = *(SBPKT_G2M_SendNoticeMsg_s*)PacketData;
			r3dOutToLog("Received notice message from peer%d '%s'\n",peerId,n.msg);
			//r3dOutToLog("Brostcast to all servers.\n");
			// scans servers.
			int numgames = 0;
			for(CMasterGameServer::TSupersList::const_iterator it = gMasterGameServer.supers_.begin();
				it != gMasterGameServer.supers_.end();
				++it)
			{
				const CServerS* super = it->second;
				numgames += super->GetExpectedGames();
				for(int i=0; i<super->maxGames_; i++) 
				{
					const CServerG* game = super->games_[i].game;
					if(!game) 
						continue;
					// resend this packet to all servers.
					net_->SendToPeer(&n, sizeof(n), game->peer_, true);
				}
			}
			r3dOutToLog("Send notice packet to %d servers\n",numgames);
			break;
		}
	case SBPKT_G2M_RegisterGame:
		{
			const SBPKT_G2M_RegisterGame_s& n = *(SBPKT_G2M_RegisterGame_s*)PacketData;
			r3d_assert(sizeof(n) == PacketSize);
			r3d_assert(peer.status == PEER_Validated);

			r3dOutToLog("game 0x%x connected\n", n.gameId);

			// register this game in supervisor
			CServerS* super = GetServerByGameId(n.gameId);
			if(super == NULL) {
				// this might happen when supervisor crashed between game start & registration
				r3dOutToLog("game 0x%x without supervisor\n", n.gameId);

				SBPKT_M2G_KillGame_s n1;
				net_->SendToPeer(&n1, sizeof(n1), peerId);
				net_->DisconnectPeer(peerId);
				break;
			}

			CServerG* game = super->CreateGame(n.gameId, peerId);
			r3d_assert(game);

			games_.insert(TGamesList::value_type(peerId, game));

			r3d_assert(peer.status == PEER_Validated);
			peer.status = PEER_GameServer;

#if ENABLED_SERVER_WEAPONARMORY
			SendArmoryInfoToGame(game);
#endif
			break;
		}

	case SBPKT_G2M_AddPlayer:
		{
			const SBPKT_G2M_AddPlayer_s& n = *(SBPKT_G2M_AddPlayer_s*)PacketData;
			r3d_assert(sizeof(n) == PacketSize);

			TGamesList::iterator it = games_.find(peerId);
			r3d_assert(it != games_.end());
			CServerG* game = it->second;
			game->AddPlayer(n.CustomerID);
			break;
		}

	case SBPKT_G2M_RemovePlayer:
		{
			const SBPKT_G2M_RemovePlayer_s& n = *(SBPKT_G2M_RemovePlayer_s*)PacketData;
			r3d_assert(sizeof(n) == PacketSize);

			TGamesList::iterator it = games_.find(peerId);
			r3d_assert(it != games_.end());
			CServerG* game = it->second;
			game->RemovePlayer(n.CustomerID);
			break;
		}

	case SBPKT_G2M_FinishGame:
		{
			const SBPKT_G2M_FinishGame_s& n = *(SBPKT_G2M_FinishGame_s*)PacketData;
			r3d_assert(sizeof(n) == PacketSize);

			TGamesList::iterator it = games_.find(peerId);
			r3d_assert(it != games_.end());
			CServerG* game = it->second;

			r3dOutToLog("game %s finished\n", game->GetName());
			game->finished_ = true;

			break;
		}

	case SBPKT_G2M_CloseGame:
		{
			const SBPKT_G2M_CloseGame_s& n = *(SBPKT_G2M_CloseGame_s*)PacketData;
			r3d_assert(sizeof(n) == PacketSize);

			TGamesList::iterator it = games_.find(peerId);
			r3d_assert(it != games_.end());
			CServerG* game = it->second;

			r3dOutToLog("game %s closed\n", game->GetName());
			DeleteGame(game);

			games_.erase(it);

			break;
		}

	case SBPKT_G2M_DataUpdateReq:
		{
			const SBPKT_G2M_DataUpdateReq_s& n = *(SBPKT_G2M_DataUpdateReq_s*)PacketData;
			r3d_assert(sizeof(n) == PacketSize);

			r3dOutToLog("got SBPKT_G2M_DataUpdateReq\n");
#if ENABLED_SERVER_WEAPONARMORY
			StartItemsDbUpdate(true);
#endif
			break;
		}

	}

	return;
}
Exemple #8
0
void CMasterGameServer::OnNetData(DWORD peerId, const r3dNetPacketHeader* PacketData, int PacketSize)
{
  if(PacketSize < sizeof(r3dNetPacketHeader)) {
    DisconnectCheatPeer(peerId, "too small packet");
    return;
  }

  // wait for validating packet
  if(!DoValidatePeer(peerId, PacketData, PacketSize))
    return;

  peer_s& peer = peers_[peerId];
  r3d_assert(peer.status >= PEER_Validated);
  
  switch(PacketData->EventID) 
  {
    default:
      r3dOutToLog("CMasterGameServer: invalid packetId %d", PacketData->EventID);
      DisconnectCheatPeer(peerId, "wrong packet id");
      return;
      
    case SBPKT_S2M_RegisterMachine:
    {
      const SBPKT_S2M_RegisterMachine_s& n = *(SBPKT_S2M_RegisterMachine_s*)PacketData;
      r3d_assert(sizeof(n) == PacketSize);

      r3d_assert(supers_.find(peerId) == supers_.end());

      DWORD ip = net_->GetPeerIp(peerId);
      DWORD id = curSuperId_++;

      CServerS* super = new CServerS(id, ip, peerId);
      super->Init(n);
      supers_.insert(TSupersList::value_type(peerId, super));
      
      r3d_assert(peer.status == PEER_Validated);
      peer.status = PEER_SuperServer;
      
      // send registration answer
      {
        SBPKT_M2S_RegisterAns_s n;
        n.id = id;
        net_->SendToPeer(&n, sizeof(n), peerId);
      }
      
      break;
    }
    
    case SBPKT_G2M_RegisterGame:
    {
      const SBPKT_G2M_RegisterGame_s& n = *(SBPKT_G2M_RegisterGame_s*)PacketData;
      r3d_assert(sizeof(n) == PacketSize);
      r3d_assert(peer.status == PEER_Validated);

      r3dOutToLog("game 0x%x connected\n", n.gameId);

      // register this game in supervisor
      CServerS* super = GetServerByGameId(n.gameId);
      if(super == NULL) {
        // this might happen when supervisor crashed between game start & registration
        r3dOutToLog("game 0x%x without supervisor\n", n.gameId);
        
        SBPKT_M2G_KillGame_s n1;
        net_->SendToPeer(&n1, sizeof(n1), peerId);
        net_->DisconnectPeer(peerId);
        break;
      }
      
      CServerG* game = super->CreateGame(n.gameId, peerId);
      r3d_assert(game);

      games_.insert(TGamesList::value_type(peerId, game));
      
      r3d_assert(peer.status == PEER_Validated);
      peer.status = PEER_GameServer;
      
#if 1  // PAX_BUILD
      SendArmoryInfoToGame(game);
#endif
      break;
    }

    case SBPKT_G2M_UpdateGame:
    {
      const SBPKT_G2M_UpdateGame_s& n = *(SBPKT_G2M_UpdateGame_s*)PacketData;
      r3d_assert(sizeof(n) == PacketSize);

      TGamesList::iterator it = games_.find(peerId);
      r3d_assert(it != games_.end());
      CServerG* game = it->second;
      game->SetCurrentData(n.timeLeft, n.curPlayers, n.uinfo);
      break;
    }

    case SBPKT_G2M_FinishGame:
    {
      const SBPKT_G2M_FinishGame_s& n = *(SBPKT_G2M_FinishGame_s*)PacketData;
      r3d_assert(sizeof(n) == PacketSize);

      TGamesList::iterator it = games_.find(peerId);
      r3d_assert(it != games_.end());
      CServerG* game = it->second;

      r3dOutToLog("game %s finished\n", game->GetName());
      game->finished_ = true;

      break;
    }

    case SBPKT_G2M_CloseGame:
    {
      const SBPKT_G2M_CloseGame_s& n = *(SBPKT_G2M_CloseGame_s*)PacketData;
      r3d_assert(sizeof(n) == PacketSize);

      TGamesList::iterator it = games_.find(peerId);
      r3d_assert(it != games_.end());
      CServerG* game = it->second;

      r3dOutToLog("game %s closed\n", game->GetName());
      DeleteGame(game);

      games_.erase(it);

      break;
    }
    
    case SBPKT_G2M_DataUpdateReq:
    {
      const SBPKT_G2M_DataUpdateReq_s& n = *(SBPKT_G2M_DataUpdateReq_s*)PacketData;
      r3d_assert(sizeof(n) == PacketSize);

      r3dOutToLog("got SBPKT_G2M_DataUpdateReq\n");
      StartItemsDbUpdate(true);
      break;
    }

  }

  return;
}