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}"); } }
// 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)}"); }
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); }
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"); } }
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); }
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"); }
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)); }
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); }); }
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")); }
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")); }
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()}"); }
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}"); }
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; } } }
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(); } }
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); }
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(); } }