/// <summary> /// Opens the local server for local coyote test processes to connect to. /// </summary> internal async Task RunServerAsync() { this.WriteLine("Starting telemetry server..."); var resolver = new SmartSocketTypeResolver(typeof(TelemetryEvent), typeof(TelemetryMetric)); var server = SmartSocketServer.StartServer(TelemetryServerEndPoint, resolver, null /* localhost only */, UdpGroupAddress, UdpGroupPort); server.ClientConnected += this.OnClientConnected; server.ClientDisconnected += this.OnClientDisconnected; this.Server = server; // Here we see the reason for this entire class. In order to allow coyote.exe to terminate quickly // and not lose telemetry messages, we have to wait a bit to allow the App Insights cloud messages // to get through, then we can safely terminate this server process. while (this.Telemetry != null && this.LastEvent + this.ServerTerminateDelay > DateTime.Now) { await Task.Delay((int)this.ServerTerminateDelay.TotalMilliseconds); if (this.PendingEvents) { this.WriteLine("Flushing telemetry..."); this.PendingEvents = false; this.Telemetry.Flush(); this.LastEvent = DateTime.Now; // go around again to give flush time to finish. } } this.Telemetry = null; }
/// <summary> /// Opens the local server for TestingProcesses to connect to. /// If we are not running anything out of process then this does nothing. /// </summary> private void StartServer() { if (!this.IsRunOutOfProcess) { return; } var resolver = new SmartSocketTypeResolver(typeof(BugFoundMessage), typeof(TestReportMessage), typeof(TestServerMessage), typeof(TestProgressMessage), typeof(TestTraceMessage), typeof(TestReport), typeof(CoverageInfo), typeof(Configuration)); var server = SmartSocketServer.StartServer(this.Configuration.TestingSchedulerEndPoint, resolver, this.Configuration.TestingSchedulerIpAddress); server.ClientConnected += this.OnClientConnected; server.ClientDisconnected += this.OnClientDisconnected; server.BackChannelOpened += this.OnBackChannelOpened; // pass this along to the TestingProcesses. this.Configuration.TestingSchedulerIpAddress = server.EndPoint.ToString(); IO.Debug.WriteLine($"... Server listening on '{server.EndPoint}'"); this.Server = server; }
/// <summary> /// Opens the remote notification listener. If this is /// not a parallel testing process, then this operation /// does nothing. /// </summary> private async Task ConnectToServer() { string serviceName = this.Configuration.TestingSchedulerEndPoint; var source = new System.Threading.CancellationTokenSource(); var resolver = new SmartSocketTypeResolver(typeof(BugFoundMessage), typeof(TestReportMessage), typeof(TestServerMessage), typeof(TestProgressMessage), typeof(TestTraceMessage), typeof(TestReport), typeof(CoverageInfo), typeof(Configuration)); SmartSocketClient client = null; if (!string.IsNullOrEmpty(this.Configuration.TestingSchedulerIpAddress)) { string[] parts = this.Configuration.TestingSchedulerIpAddress.Split(':'); if (parts.Length == 2) { var endPoint = new IPEndPoint(IPAddress.Parse(parts[0]), int.Parse(parts[1])); while (!source.IsCancellationRequested && client == null) { client = await SmartSocketClient.ConnectAsync(endPoint, this.Name, resolver); } } } else { client = await SmartSocketClient.FindServerAsync(serviceName, this.Name, resolver, source.Token); } if (client == null) { throw new Exception("Failed to connect to server"); } client.Error += this.OnClientError; client.ServerName = serviceName; this.Server = client; // open back channel so server can also send messages to us any time. await client.OpenBackChannel(this.OnBackChannelConnected); }
/// <summary> /// Starts a telemetry server in a separate coyote process. /// </summary> private async Task ConnectToServer(string serverPath) { this.FindServerTokenSource = new CancellationTokenSource(); var token = this.FindServerTokenSource.Token; string serviceName = CoyoteTelemetryServer.TelemetryServerEndPoint; var resolver = new SmartSocketTypeResolver(typeof(TelemetryEvent), typeof(TelemetryMetric)); SmartSocketClient client = null; var findTask = SmartSocketClient.FindServerAsync(serviceName, this.Name, resolver, token, CoyoteTelemetryServer.UdpGroupAddress, CoyoteTelemetryServer.UdpGroupPort); try { if (findTask.Wait(1000, token)) { client = findTask.Result; } } catch { // timeout or cancelled. if (token.IsCancellationRequested) { return; } } if (client is null) { try { StartServer(serverPath); client = await SmartSocketClient.FindServerAsync(serviceName, this.Name, resolver, token, CoyoteTelemetryServer.UdpGroupAddress, CoyoteTelemetryServer.UdpGroupPort); } catch { // failed to connect to new telemetry server this.Enabled = false; return; } } client.Error += this.OnClientError; client.ServerName = serviceName; this.Server = client; // send any pending queue of stuff. List <SocketMessage> pending = null; lock (this.Pending) { pending = this.Pending; this.Pending = null; } foreach (var e in pending) { await this.Server.SendReceiveAsync(e); } this.PendingCleared.Set(); _ = Task.Run(this.SendHeartbeats); }