public IAsyncDisposable RegisterForUpdates(string installDirectory, string profileId, IPEndPoint localEndpoint, IPEndPoint steamEndpoint, Action <IAsyncDisposable, ServerStatusUpdate> updateCallback) { var registration = new ServerStatusUpdateRegistration { AsmId = Config.Default.ASMUniqueKey, InstallDirectory = installDirectory, ProfileId = profileId, LocalEndpoint = localEndpoint, SteamEndpoint = steamEndpoint, UpdateCallback = updateCallback, }; registration.UnregisterAction = async() => { var tcs = new TaskCompletionSource <bool>(); _eventQueue.Post(() => { if (_serverRegistrations.Contains(registration)) { Logger.Debug("Removing registration for L:{0} S:{1}", registration.LocalEndpoint, registration.SteamEndpoint); _serverRegistrations.Remove(registration); } tcs.TrySetResult(true); return(Task.FromResult(true)); }); await tcs.Task; }; _eventQueue.Post(() => { if (!_serverRegistrations.Contains(registration)) { Logger.Debug("Adding registration for L:{0} S:{1}", registration.LocalEndpoint, registration.SteamEndpoint); _serverRegistrations.Add(registration); var registrationKey = registration.SteamEndpoint.ToString(); _lastExternalCallQuery[registrationKey] = DateTime.MinValue; _lastExternalStatusQuery[registrationKey] = DateTime.MinValue; } return(Task.FromResult(true)); } ); return(registration); }
private void PostServerStatusUpdate(ServerStatusUpdateRegistration registration, StatusCallback callback, ServerStatusUpdate statusUpdate) { _eventQueue.Post(() => { if (this._serverRegistrations.Contains(registration)) { try { callback(registration, statusUpdate); } catch (Exception ex) { DebugUtils.WriteFormatThreadSafeAsync("Exception during local status update callback: {0}\n{1}", ex.Message, ex.StackTrace).DoNotWait(); } } return(TaskUtils.FinishedTask); }); }
public IAsyncDisposable RegisterForUpdates(string installDirectory, IPEndPoint localEndpoint, IPEndPoint steamEndpoint, Action <IAsyncDisposable, ServerStatusUpdate> updateCallback) { var registration = new ServerStatusUpdateRegistration { InstallDirectory = installDirectory, LocalEndpoint = localEndpoint, SteamEndpoint = steamEndpoint, UpdateCallback = updateCallback }; registration.UnregisterAction = async() => { var tcs = new TaskCompletionSource <bool>(); eventQueue.Post(() => { if (serverRegistrations.Contains(registration)) { logger.Debug("Removing registration for L:{0} S:{1}", registration.LocalEndpoint, registration.SteamEndpoint); serverRegistrations.Remove(registration); } tcs.TrySetResult(true); return(Task.FromResult(true)); }); await tcs.Task; }; eventQueue.Post(() => { if (!serverRegistrations.Contains(registration)) { logger.Debug("Adding registration for L:{0} S:{1}", registration.LocalEndpoint, registration.SteamEndpoint); serverRegistrations.Add(registration); } return(Task.FromResult(true)); } ); return(registration); }
private async Task <ServerStatusUpdate> GenerateServerStatusUpdateAsync(ServerStatusUpdateRegistration registration) { var registrationKey = registration.SteamEndpoint.ToString(); // // First check the process status // Process process; var processStatus = GetServerProcessStatus(registration, out process); switch (processStatus) { case ServerProcessStatus.NotInstalled: return(new ServerStatusUpdate { Status = ServerStatus.NotInstalled }); case ServerProcessStatus.Stopped: return(new ServerStatusUpdate { Status = ServerStatus.Stopped }); case ServerProcessStatus.Unknown: return(new ServerStatusUpdate { Status = ServerStatus.Unknown }); case ServerProcessStatus.Running: break; default: Debugger.Break(); break; } var currentStatus = ServerStatus.Initializing; // // If the process was running do we then perform network checks. // Logger.Debug("Checking server local status at {0}", registration.LocalEndpoint); // get the server information direct from the server using local connection. ReadOnlyCollection <Player> players; var localInfo = GetLocalNetworkStatus(registration.LocalEndpoint, out players); if (localInfo != null) { currentStatus = ServerStatus.RunningLocalCheck; // // Now that it's running, we can check the publication status. // Logger.Debug("Checking server public status at {0}", registration.SteamEndpoint); // get the server information direct from the server using public connection. var serverStatus = NetworkUtils.CheckServerStatusDirect(registration.SteamEndpoint); // check if the server returned the information. if (!serverStatus) { // server did not return any information var lastExternalStatusQuery = _lastExternalStatusQuery.ContainsKey(registrationKey) ? _lastExternalStatusQuery[registrationKey] : DateTime.MinValue; if (DateTime.Now >= lastExternalStatusQuery.AddMilliseconds(REMOTE_STATUS_QUERY_DELAY)) { currentStatus = ServerStatus.RunningExternalCheck; // get the server information direct from the server using external connection. var uri = new Uri(string.Format(Config.Default.ServerStatusUrlFormat, Config.Default.ServerManagerCode, registration.SteamEndpoint.Address, registration.SteamEndpoint.Port)); serverStatus = await NetworkUtils.CheckServerStatusViaAPI(uri, registration.SteamEndpoint); _lastExternalStatusQuery[registrationKey] = DateTime.Now; } } //var lastExternalCallQuery = _lastExternalCallQuery.ContainsKey(registrationKey) ? _lastExternalCallQuery[registrationKey] : DateTime.MinValue; //if (lastExternalCallQuery == DateTime.MinValue) //{ // // perform a server call to the web api. // var uri = new Uri(string.Format(Config.Default.ServerCallUrlFormat, Config.Default.ServerManagerCode, registration.SteamEndpoint.Address, registration.SteamEndpoint.Port, Config.Default.ServerManagerUniqueKey, registration.ProfileId)); // await NetworkUtils.PerformServerCallToAPI(uri, registration.SteamEndpoint); // _lastExternalCallQuery[registrationKey] = DateTime.Now; //} // check if the server returned the information. if (serverStatus) { currentStatus = ServerStatus.Published; } else { Logger.Debug("No public status returned for {0}", registration.SteamEndpoint); } } var statusUpdate = new ServerStatusUpdate { Process = process, Status = currentStatus, ServerInfo = localInfo, Players = players }; return(await Task.FromResult(statusUpdate)); }
private static ServerProcessStatus GetServerProcessStatus(ServerStatusUpdateRegistration updateContext, out Process serverProcess) { serverProcess = null; if (String.IsNullOrWhiteSpace(updateContext.InstallDirectory)) { return(ServerProcessStatus.NotInstalled); } var serverExePath = Path.Combine(updateContext.InstallDirectory, Config.Default.ServerBinaryRelativePath, Config.Default.ServerExe); if (!File.Exists(serverExePath)) { return(ServerProcessStatus.NotInstalled); } // // The server appears to be installed, now determine if it is running or stopped. // try { foreach (var process in Process.GetProcessesByName(Config.Default.ServerProcessName)) { var commandLine = ProcessUtils.GetCommandLineForProcess(process.Id)?.ToLower(); if (commandLine != null && commandLine.Contains(updateContext.InstallDirectory.ToLower()) && commandLine.Contains(Config.Default.ServerExe.ToLower())) { // Does this match our server exe and port? var serverArgMatch = String.Format(Config.Default.ServerCommandLineArgsMatchFormat, updateContext.LocalEndpoint.Port).ToLower(); if (commandLine.Contains(serverArgMatch)) { // Was an IP set on it? var anyIpArgMatch = String.Format(Config.Default.ServerCommandLineArgsIPMatchFormat, String.Empty).ToLower(); if (commandLine.Contains(anyIpArgMatch)) { // If we have a specific IP, check for it. var ipArgMatch = String.Format(Config.Default.ServerCommandLineArgsIPMatchFormat, updateContext.LocalEndpoint.Address.ToString()).ToLower(); if (!commandLine.Contains(ipArgMatch)) { // Specific IP set didn't match continue; } // Specific IP matched } // Either specific IP matched or no specific IP was set and we will claim this is ours. process.EnableRaisingEvents = true; if (process.HasExited) { return(ServerProcessStatus.Stopped); } serverProcess = process; return(ServerProcessStatus.Running); } } } } catch (Exception ex) { Logger.Debug("Exception while checking process status: {0}\n{1}", ex.Message, ex.StackTrace); } return(ServerProcessStatus.Stopped); }
private static async Task <ServerStatusUpdate> GenerateServerStatusUpdateAsync(ServerStatusUpdateRegistration registration) { // // First check the process status // Process process; var processStatus = GetServerProcessStatus(registration, out process); switch (processStatus) { case ServerProcessStatus.NotInstalled: return(new ServerStatusUpdate { Status = ServerStatus.NotInstalled }); case ServerProcessStatus.Stopped: return(new ServerStatusUpdate { Status = ServerStatus.Stopped }); case ServerProcessStatus.Running: break; default: Debugger.Break(); break; } ServerStatus currentStatus = ServerStatus.Initializing; // // If the process was running do we then perform network checks. // ServerInfo localInfo; ReadOnlyCollection <Player> players; localInfo = GetLocalNetworkStatus(registration.LocalEndpoint, out players); if (localInfo != null) { currentStatus = ServerStatus.Running; // // Now that it's running, we can check the publication status. // logger.Debug("Checking server public status at {0}", registration.SteamEndpoint); var serverInfo = await NetworkUtils.GetServerNetworkInfo(registration.SteamEndpoint); if (serverInfo != null) { currentStatus = ServerStatus.Published; } else { logger.Debug("No public status returned for {0}", registration.SteamEndpoint); } } var statusUpdate = new ServerStatusUpdate { Process = process, Status = currentStatus, ServerInfo = localInfo, Players = players }; return(await Task.FromResult(statusUpdate)); }