示例#1
0
        public async Task UpdateRoomState(Guid roomId, int roomPlayersCount, RoomState roomState, string matchMakerUrl, int maxMatchMakingWeight)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(matchMakerUrl))
                {
                    _logger.Error($"SendRoomStateUpdate error: matchmaker URL is empty in properties container");
                    return;
                }

                await _requestSender.SendRequest <UpdateRoomStateResponse>(matchMakerUrl,
                                                                           new UpdateRoomStateRequest(roomId, roomPlayersCount, roomState, maxMatchMakingWeight), (r) =>
                {
                    if (!r.Success)
                    {
                        _logger.Error($"Room update error: {r.Message}");
                    }
                    else
                    {
                        _logger.Debug($"Room update to {matchMakerUrl} with players count {roomPlayersCount}, state {roomState} successful");
                    }
                });
            }
            catch (Exception e)
            {
                _logger.Error($"Update room state error: {e}");
            }
        }
示例#2
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, IShamanLogger logger, IRouterServerInfoProvider serverInfoProvider)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();
            app.UseCookiePolicy();
            if (IsMetricsEnabled())
            {
                app.UseMiddleware <RequestMetricsMiddleWare>();
            }
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });

            serverInfoProvider.Start();

            logger.Error($"Initial server list: {JsonConvert.SerializeObject(serverInfoProvider.GetAllServers(), Formatting.Indented)}");
            logger.Error($"Initial bundles list: {JsonConvert.SerializeObject(serverInfoProvider.GetAllBundles(), Formatting.Indented)}");
        }
示例#3
0
        public int CleanUp()
        {
            int removedPlayers = 0;

            try
            {
                foreach (var player in _roomPlayers.ToArray())
                {
                    if (_roomPlayers.TryRemove(player.Key, out _))
                    {
                        player.Value.Peer.Disconnect(ServerDisconnectReason.RoomCleanup);
                        ++removedPlayers;
                    }
                }

                _packetSender.Stop();
                _roomController.Dispose();
                _taskScheduler.RemoveAll();
                _roomPlayers.Clear();
                //close room on matchmaker
                Close();
            }
            catch (Exception e)
            {
                _logger?.Error($"Error disposing room: {e}");
            }
            finally
            {
                _logger?.Error($"RoomStats: {_roomStats}");
            }

            return(removedPlayers);
        }
示例#4
0
 public bool AddPeerToRoom(IPeer peer, Dictionary <byte, object> peerProperties)
 {
     if (!_roomPlayers.TryAdd(peer.GetSessionId(), new RoomPlayer(peer, peerProperties)))
     {
         _logger.Error($"Error adding player to peer collection");
         return(false);
     }
     return(true);
 }
        public void ProcessConfirmChangeIdEvent(int playerIndex, ConfirmChangeIdEventBase eve)
        {
            var type = eve.GetType();

            if (!_typeToSyncers.TryGetValue(type, out var syncer))
            {
                _logger.Error($"ProcessConfirmChangeIdEvent error: Can not get syncer for type {type}");
                return;
            }
            syncer.ConfirmChangeId(playerIndex, eve.ChangeId);
        }
 private void TrackMmTime(MatchMakingPlayer oldestPlayer)
 {
     if (oldestPlayer != null && oldestPlayer.AddedToMmGroupOn.HasValue)
     {
         _mmMetrics.TrackMmCompleted((long)(DateTime.UtcNow - oldestPlayer.AddedToMmGroupOn.Value).TotalMilliseconds);
     }
     else
     {
         _logger.Error($"Oldest player not found when tracking MM time");
     }
 }
示例#7
0
        public async Task <T> SendRequest <T>(string serviceUrl, HttpRequestBase request)
            where T : HttpResponseBase, new()
        {
            var responseObject = new T();
            var stopwatch      = Stopwatch.StartNew();
            var requestUri     = $"{serviceUrl}/{request.EndPoint}";

            try
            {
                if (string.IsNullOrWhiteSpace(serviceUrl))
                {
                    throw new Exception($"Base Url address is empty for {request.GetType()}");
                }

                if (string.IsNullOrWhiteSpace(request.EndPoint))
                {
                    throw new Exception($"Request endpoint Url address is empty for {request.GetType()}");
                }

                using (var client = HttpClientFactory.Create())
                {
                    client.Timeout = new TimeSpan(0, 0, 15);

                    var byteContent = new ByteArrayContent(_serializer.Serialize(request));

                    using (var message = await client.PostAsync(requestUri, byteContent))
                    {
                        if (!message.IsSuccessStatusCode)
                        {
                            _logger.Error($"SendRequest {request.GetType()} to {requestUri} error ({stopwatch.ElapsedMilliseconds}ms): {message.StatusCode}");

                            responseObject.ResultCode = ResultCode.SendRequestError;
                        }
                        else
                        {
                            var contentStream = await message.Content.ReadAsStreamAsync();

                            responseObject = _serializer.DeserializeAs <T>(contentStream);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                _logger.Error($"SendRequest {request.GetType()}  to {requestUri} error ({stopwatch.ElapsedMilliseconds}ms): {e}");
                responseObject.ResultCode = ResultCode.SendRequestError;
            }

            return(responseObject);
        }
示例#8
0
        public void Add(MatchMakingPlayer player, List <Guid> groups)
        {
            lock (_syncCollection)
            {
                if (_players.ContainsKey(player.Id))
                {
                    _players.Remove(player.Id);
                    _logger.Error($"Player {player.Id} already added. Deleting previous");
                }

                _players.Add(player.Id, player);
                _mmMetrics.TrackPlayerAdded();

                foreach (var group in groups)
                {
                    if (!_mmGroupToPlayer.ContainsKey(group))
                    {
                        _mmGroupToPlayer.Add(group, new List <MatchMakingPlayer>());
                    }

                    _mmGroupToPlayer[group].Add(player);

                    if (!_playerToMmGroup.ContainsKey(player.Id))
                    {
                        _playerToMmGroup.Add(player.Id, new List <Guid>());
                    }

                    _playerToMmGroup[player.Id].Add(group);
                }
            }
        }
        // private string GetUrl(int gameServerId)
        // {
        //     var server = _gameServerList[gameServerId];
        //     if (server == null)
        //         throw new Exception($"GetUrl error: there is no game server with id = {gameServerId}");
        //
        //     return UrlHelper.GetUrl(server.HttpPort, server.HttpsPort, server.Address);
        // }

        public async Task <Guid> CreateRoom(string gameServerUrl, Guid roomId, Dictionary <byte, object> properties, Dictionary <Guid, Dictionary <byte, object> > players)
        {
            var response = await _requestSender.SendRequest <CreateRoomResponse>(gameServerUrl, new CreateRoomRequest(properties, players)
            {
                RoomId = roomId
            });

            if (!response.Success)
            {
                var msg = $"CreateRoom error: {response.Message}";
                _logger.Error(msg);
                throw new Exception(msg);
            }

            return(response.RoomId);
        }
        public void Connect(string address, int port)
        {
            //switch Sockets implementation.BEGIN
            //_socket = new HazelSock(_logger);
            _socket = new LiteNetSock(_logger);
            //switch sockets implementation.END

            _socket.OnPacketReceived += (endPoint, dataPacket, release) =>
            {
                _onPackageReceived(dataPacket, release);
                //todo if using hazel then this part should be considered in releaseAction param
//                _socket.ReturnBufferToPool(dataPacket.Buffer);
            };
            _socket.OnDisconnected += OnDisconnected;

            _socket.OnConnected += ep => { OnConnectedToServer?.Invoke(); };

            _ep = GetIPEndPointFromHostName(address, port, false); // new IPEndPoint(IPAddress.Parse(address), port);
            _socket.Connect(_ep);

            _connected = true;
            _isTicking = false;
            //Send(new ConnectedEvent());
            _socketTickTask = _taskScheduler.ScheduleOnInterval(() =>
            {
                lock (_stateSync)
                {
                    if (!_connected)
                    {
                        return;
                    }

                    lock (_isTickingMutex)
                    {
                        if (_isTicking)
                        {
                            return;
                        }
                        _isTicking = true;
                    }

                    try
                    {
                        _socket.Tick();
                    }
                    catch (Exception ex)
                    {
                        _logger.Error($"Socket tick error: {ex}");
                    }
                    finally
                    {
                        lock (_isTickingMutex)
                            _isTicking = false;
                    }
                }
            }, 0, 10);
            _logger?.Debug($"Receive loop started");
        }
示例#11
0
        private async Task Load()
        {
            var requestNumber = _getBackendsListRequestCount++;

            //request backends list
            var serverInfos = await _routerClient.GetServerInfoList(false);

            if (!serverInfos.Any())
            {
                return;
            }

            var meList =
                serverInfos.Where(s => s.Identity.Equals(_serverIdentity)).ToArray();

            if (!meList.Any())
            {
                _logger.Error($"BackendProvider.Load error: can not find me({_serverIdentity}) in serve list");
                return;
            }

            if (meList.Length > 1)
            {
                _logger.Error($"BackendProvider.Load attention: more than 1 servers matched me - (record ids: {string.Join<int>(",",meList.Select(m=>m.Id))}) in serve list");
            }

            _me = meList.First();

            var backends = serverInfos.Where(s =>
                                             s.ServerRole == ServerRole.BackEnd && s.Region == _me.Region &&
                                             s.IsApproved && s.AreVersionsIntersect(_me)).ToList();

            if (!backends.Any())
            {
                _logger.Error($"Received 0 backends from Router!");
            }
            else
            {
                if (requestNumber == 1)
                {
                    _logger.Info($"Received {backends.Count} backends from Router");
                }
                _backends = backends;
            }
        }
 public BundleSettingsMetaProvider(IBundleConfig bundleConfig, IShamanLogger logger)
 {
     _logger  = logger;
     _metaUrl = bundleConfig.GetValueOrNull("MetaUrl");
     if (string.IsNullOrWhiteSpace(_metaUrl))
     {
         _logger.Error($"Meta server url was not set in bundle settings file");
     }
 }
        public void Send(byte[] buffer, int offset, int length, bool reliable, bool orderControl, bool returnAfterSend = true)
        {
            if (_serverPeer == null)
            {
                _logger.Error($"Server peer is null");
            }

            _serverPeer?.Send(buffer, offset, length, GetDeliveryMode(reliable, orderControl));
        }
示例#14
0
        private void GetRooms()
        {
            SendShamanRequest <GetRoomListResponse>(new GetRoomListRequest(_matchMakingProperties), response =>
            {
                if (!response.Success)
                {
                    var error = $"GetRooms: Error response {response.Message}";
                    _logger.Error(error);
                    _getRoomsCallback(new List <RoomInfo>());
                    return;
                }

                _getRoomsCallback(response.Rooms);
            });
        }
示例#15
0
        public async Task Actualize(int peersCount)
        {
            var response = await _requestSender.SendRequest <ActualizeServerOnRouterResponse>(_routingConfig.RouterUrl,
                                                                                              new ActualizeServerOnRouterRequest(_routingConfig.Identity, _routingConfig.ServerName, _routingConfig.Region, peersCount, _routingConfig.HttpPort, _routingConfig.HttpsPort));

            if (!response.Success)
            {
                _logger.Error($"MatchMakerServerInfoProvider.ActualizeMe error: {response.Message}");
            }
        }
        public async Task <ActionResult> CreateRoom()
        {
            //Request.Body.Position = 0;
            var input = await Request.GetRawBodyBytesAsync();

            var request = _serializer.DeserializeAs <CreateRoomRequest>(input);
            CreateRoomResponse response = new CreateRoomResponse();

            try
            {
                response.RoomId = _gameServerApi.CreateRoom(request.Properties, request.Players, request.RoomId);
            }
            catch (Exception ex)
            {
                _logger.Error($"Create room error: {ex}");
                response.ResultCode = ResultCode.RequestProcessingError;
            }

            return(new FileContentResult(_serializer.Serialize(response), "text/html"));
        }
示例#17
0
        public async Task <ActionResult> UpdateRoomState()
        {
            //Request.Body.Position = 0;
            var input = await Request.GetRawBodyBytesAsync();

            var request  = _serializer.DeserializeAs <UpdateRoomStateRequest>(input);
            var response = new UpdateRoomStateResponse();

            try
            {
                _roomManager.UpdateRoomState(request.RoomId, request.CurrentPlayerCount, request.State, request.MaxMatchMakingWeight);
            }
            catch (Exception ex)
            {
                _logger.Error($"Update room state error: {ex}");
                response.ResultCode = ResultCode.RequestProcessingError;
            }

            return(new FileContentResult(_serializer.Serialize(response), "text/html"));
        }
示例#18
0
        public async Task Actualize(int peersCount)
        {
            var request = new ActualizeServerOnMatchMakerRequest(_config.GetIdentity(), _config.ServerName,
                                                                 _config.Region, _statsProvider.GetPeerCount(), _config.BindToPortHttp, 0);
            var response =
                await _requestSender.SendRequest <ActualizeServerOnMatchMakerResponse>(_matchMakerInfoProvider.MatchMakerUrl, request);

            if (!response.Success)
            {
                _logger.Error($"GameToMmServerActualizer error: {response.Message}");
            }
        }
        private void CheckRoomsState()
        {
            foreach (var room in _rooms)
            {
                var roomValue = room.Value;
                if (roomValue.IsGameFinished() || IsTimeToForceRoomDestroy(roomValue))
                {
                    _logger.Error($"Room destroy with peers count {roomValue.GetPeerCount()}");
                    DeleteRoom(roomValue.GetRoomId());
                }
            }

            _logger.Info($"Rooms state: Room count {GetRoomsCount()}, peers count {GetPlayersCount()}");
        }
示例#20
0
        private async Task LoadConfig()
        {
            var startNew = Stopwatch.StartNew();

            _serverList = await _configRepo.GetAllServerInfo();

            _bundlesList = await _configRepo.GetBundlesInfo();

            var updateElapsed = startNew.ElapsedMilliseconds;

            if (updateElapsed > 5000)
            {
                _logger.Error($"Long data update: {updateElapsed}ms");
            }

            var staleList = _serverList.Where(l => l.IsApproved && l.ServerRole != ServerRole.BackEnd && !l.IsActual(30000)).ToArray();

            if (staleList.Any())
            {
                _logger.Error($"Staled data ({string.Join(',',staleList.Select(s=>(DateTime.UtcNow - s.ActualizedOn.Value).TotalMilliseconds.ToString()))}) : {JsonConvert.SerializeObject(staleList, Formatting.Indented)}");
            }
        }
        public async Task <string> GetBundleUri()
        {
            var messageSent = false;

            while (true)
            {
                try
                {
                    return(await GetBundleUriImpl());
                }
                catch (BundleNotFoundException e)
                {
                    if (!messageSent)
                    {
                        _logger.Error($"Retry bundle in 3 sec: {e.Message}");
                        messageSent = true;
                    }

                    Thread.Sleep(BundleRetryMsec);
                }
            }
        }
        public IPendingTask ScheduleOnInterval(Func <Task> action, long firstInMs, long regularInMs, bool shortLiving = false)
        {
            var pending = new PendingTask(async() =>
            {
                try
                {
                    await action();
                }
                catch (Exception e)
                {
                    _logger?.Error($"ScheduleOnIntervalAsync task error: {e}");
                }
            }, firstInMs, regularInMs, _logger, shortLiving);

            pending.Schedule();
            lock (_listLock)
            {
                _tasks.Add(pending);
            }

            return(pending);
        }
        public Dictionary <int, float> GetPlayersMissRates(Guid repoId)
        {
            var result             = new Dictionary <int, float>();
            var indexes            = _playerRepo.GetHumanPlayerIndexes().ToList();
            var confirmationMisses = new Dictionary <int, int>();

            if (!_confirmationRepoToChangeId.ContainsKey(repoId))
            {
                throw new Exception($"GetPlayersMissRates error: no repo {repoId}");
            }

            lock (_queueSync)
            {
                var totalChanges = _confirmationRepoToChangeId[repoId].Count;
                foreach (var index in indexes)
                {
                    confirmationMisses.Add(index, 0);
                    result.Add(index, 0);
                }

                foreach (var item in _confirmationRepoToChangeId[repoId])
                {
                    if ((DateTime.UtcNow - _confirmationHistoryTime[item]).TotalMilliseconds < _trackIntervalMs)
                    {
                        continue;
                    }

                    foreach (var index in indexes)
                    {
                        var value = _confirmationHistory[item];
                        if (!IsConfirmedBy(value, index))
                        {
                            confirmationMisses[index]++;
                        }
                    }
                }


                foreach (var index in indexes)
                {
                    result[index] = 100 * (float)confirmationMisses[index] / totalChanges;
                    if (result[index] == 100)
                    {
                        _logger.Error($"");
                    }
                }

                return(result);
            }
        }
        public void UpdateRoomState(Guid roomId, int currentPlayers, RoomState roomState, int currentMaxWeight)
        {
            var room = GetRoom(roomId);

            if (room == null)
            {
                _logger.Error($"UpdateRoomState error: no room with id {roomId}");
                return;
            }

            room.MaxWeightToJoin = currentMaxWeight;
            room.CurrentWeight   = currentPlayers;
            room.UpdateState(roomState);
            _logger.Debug($"Update received: {roomId} State {roomState}");
        }
示例#25
0
        public async Task <EntityDictionary <ServerInfo> > GetServerInfoList(bool actualOnly)
        {
            var response = await _requestSender.SendRequest <GetServerInfoListResponse>(_routingConfig.RouterUrl,
                                                                                        new GetServerInfoListRequest(actualOnly));

            if (response.ResultCode != ResultCode.OK)
            {
                _logger.Error(
                    $"BackendProvider error: error getting backends {response.ResultCode}|{response.Message}");
                _emptyList = new EntityDictionary <ServerInfo>();
                return(_emptyList);
            }

            return(response.ServerInfoList);
        }
 public void UpdateRoom(Guid roomId, Dictionary <Guid, Dictionary <byte, object> > players)
 {
     lock (_syncPeersList)
     {
         var room = GetRoomById(roomId);
         if (room != null)
         {
             room.UpdateRoom(players);
         }
         else
         {
             _logger?.Error($"UpdateRoom error: can not find room {roomId} to add new players");
             return;
         }
     }
 }
示例#27
0
        private void CheckConfirmations()
        {
            var missRates = _confirmationManager.GetPlayersMissRates(_id);

            foreach (var item in missRates)
            {
                if (item.Value >= _forceSyncThreshold)
                {
                    if (_playerRepo.IsPlayerExist(item.Key))
                    {
                        var sessionId = _playerRepo.GetPlayerSessionId(item.Key);
                        _logger.Error($"Forcing player {item.Key} to refresh repo with {typeof(TEvent)} (miss rate {item.Value})");
                        SendForceSync(sessionId);
                        _confirmationManager.ConfirmAllChanges(_id, item.Key);
                    }
                }
            }
        }
 private void Tick()
 {
     lock (_mutex)
     {
         foreach (var item in _connectsFromIp)
         {
             if (item.Value >= _config.MaxConnectsFromSingleIp)
             {
                 _logger.Error($"Ddos probably: ip {item.Key}");
                 if (!_bannedTill.ContainsKey(item.Key))
                 {
                     _bannedTill.Add(item.Key, DateTime.UtcNow.AddMilliseconds(_config.BanDurationMs));
                 }
             }
         }
         _connectsFromIp.Clear();
     }
 }
示例#29
0
        public bool IsBanned(IPEndPoint endPoint)
        {
            try
            {
                if (_config.IsConnectionDdosProtectionOn)
                {
                    return(_ddosProtection.IsBanned(endPoint));
                }
            }
            catch (Exception e)
            {
                //if something go wrong - we return false
                _logger.Error($"IsBanned error: {e}");
                return(false);
            }

            return(false);
        }
示例#30
0
 private void ClientOnPackageReceived(IPacketInfo packet)
 {
     lock (_syncCollection)
     {
         var offsets = PacketInfo.GetOffsetInfo(packet.Buffer, packet.Offset);
         foreach (var item in offsets)
         {
             try
             {
                 ProcessMessage(packet.Buffer, item.Offset, item.Length);
             }
             catch (Exception ex)
             {
                 _logger.Error($"Error processing message: {ex}");
             }
         }
         packet.Dispose();
     }
 }