2015-11-30 17:33:16 -08:00
|
|
|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
|
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
|
|
|
|
|
|
using System;
|
|
|
|
using System.Diagnostics;
|
|
|
|
using System.IO;
|
|
|
|
using System.Net;
|
|
|
|
using System.Net.Sockets;
|
|
|
|
using System.Threading;
|
2016-02-24 16:53:16 -08:00
|
|
|
using System.Threading.Tasks;
|
2015-11-30 17:33:16 -08:00
|
|
|
using Microsoft.Extensions.Testing.Abstractions;
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
|
|
|
|
namespace Microsoft.DotNet.Tools.Test
|
|
|
|
{
|
2016-02-12 18:22:35 -08:00
|
|
|
public class ReportingChannel : IReportingChannel
|
2015-11-30 17:33:16 -08:00
|
|
|
{
|
|
|
|
public static ReportingChannel ListenOn(int port)
|
|
|
|
{
|
|
|
|
// This fixes the mono incompatibility but ties it to ipv4 connections
|
2016-02-24 16:53:16 -08:00
|
|
|
var listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
2015-11-30 17:33:16 -08:00
|
|
|
|
2016-02-24 16:53:16 -08:00
|
|
|
listenSocket.Bind(new IPEndPoint(IPAddress.Loopback, port));
|
|
|
|
listenSocket.Listen(10);
|
2015-11-30 17:33:16 -08:00
|
|
|
|
2016-02-24 16:53:16 -08:00
|
|
|
return new ReportingChannel(listenSocket);
|
2015-11-30 17:33:16 -08:00
|
|
|
}
|
|
|
|
|
2016-02-24 16:53:16 -08:00
|
|
|
private BinaryWriter _writer;
|
|
|
|
private BinaryReader _reader;
|
|
|
|
private Socket _listenSocket;
|
2015-11-30 17:33:16 -08:00
|
|
|
|
2016-02-24 16:53:16 -08:00
|
|
|
private ReportingChannel(Socket listenSocket)
|
2015-11-30 17:33:16 -08:00
|
|
|
{
|
2016-02-24 16:53:16 -08:00
|
|
|
_listenSocket = listenSocket;
|
|
|
|
Port = ((IPEndPoint)listenSocket.LocalEndPoint).Port;
|
2015-11-30 17:33:16 -08:00
|
|
|
}
|
|
|
|
|
2016-02-12 18:22:35 -08:00
|
|
|
public event EventHandler<Message> MessageReceived;
|
2015-11-30 17:33:16 -08:00
|
|
|
|
|
|
|
public Socket Socket { get; private set; }
|
|
|
|
|
2016-02-24 16:53:16 -08:00
|
|
|
public int Port { get; }
|
|
|
|
|
|
|
|
public void Accept()
|
|
|
|
{
|
|
|
|
new Thread(() =>
|
|
|
|
{
|
|
|
|
using (_listenSocket)
|
|
|
|
{
|
|
|
|
Socket = _listenSocket.Accept();
|
|
|
|
|
|
|
|
var stream = new NetworkStream(Socket);
|
|
|
|
_writer = new BinaryWriter(stream);
|
|
|
|
_reader = new BinaryReader(stream);
|
|
|
|
|
|
|
|
// Read incoming messages on the background thread
|
|
|
|
new Thread(ReadMessages) { IsBackground = true }.Start();
|
|
|
|
}
|
|
|
|
}) { IsBackground = true }.Start();
|
|
|
|
}
|
2016-02-12 18:22:35 -08:00
|
|
|
|
2015-11-30 17:33:16 -08:00
|
|
|
public void Send(Message message)
|
|
|
|
{
|
|
|
|
lock (_writer)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
TestHostTracing.Source.TraceEvent(
|
|
|
|
TraceEventType.Verbose,
|
|
|
|
0,
|
2016-02-12 18:22:35 -08:00
|
|
|
"[ReportingChannel]: Send({0})",
|
2015-11-30 17:33:16 -08:00
|
|
|
message);
|
|
|
|
|
|
|
|
_writer.Write(JsonConvert.SerializeObject(message));
|
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
{
|
|
|
|
TestHostTracing.Source.TraceEvent(
|
|
|
|
TraceEventType.Error,
|
|
|
|
0,
|
|
|
|
"[ReportingChannel]: Error sending {0}",
|
|
|
|
ex);
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void SendError(string error)
|
|
|
|
{
|
|
|
|
Send(new Message()
|
|
|
|
{
|
|
|
|
MessageType = "Error",
|
|
|
|
Payload = JToken.FromObject(new ErrorMessage()
|
|
|
|
{
|
|
|
|
Message = error,
|
|
|
|
}),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
public void SendError(Exception ex)
|
|
|
|
{
|
|
|
|
SendError(ex.ToString());
|
|
|
|
}
|
|
|
|
|
|
|
|
private void ReadMessages()
|
|
|
|
{
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2016-02-24 16:53:16 -08:00
|
|
|
var rawMessage = _reader.ReadString();
|
|
|
|
var message = JsonConvert.DeserializeObject<Message>(rawMessage);
|
2016-02-12 18:22:35 -08:00
|
|
|
|
|
|
|
MessageReceived?.Invoke(this, message);
|
2015-11-30 17:33:16 -08:00
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
{
|
|
|
|
TestHostTracing.Source.TraceEvent(
|
|
|
|
TraceEventType.Error,
|
|
|
|
0,
|
|
|
|
"[ReportingChannel]: Waiting for message failed {0}",
|
|
|
|
ex);
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
{
|
|
|
|
Socket.Dispose();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|