| /*--------------------------------------------------------------------------------------------- | 
|  *  Copyright (c) Microsoft Corporation. All rights reserved. | 
|  *  Licensed under the MIT License. See License.txt in the project root for license information. | 
|  *--------------------------------------------------------------------------------------------*/ | 
|  using System; | 
| using System.Net; | 
| using System.Threading; | 
|   | 
| namespace Microsoft.Unity.VisualStudio.Editor.Messaging | 
| { | 
|     internal class TcpListener | 
|     { | 
|         private const int ListenTimeoutMilliseconds = 5000; | 
|   | 
|         private class State | 
|         { | 
|             public System.Net.Sockets.TcpListener TcpListener; | 
|             public byte[] Buffer; | 
|         } | 
|   | 
|         public static int Queue(byte[] buffer) | 
|         { | 
|             var tcpListener = new System.Net.Sockets.TcpListener(IPAddress.Any, 0); | 
|             var state = new State {Buffer = buffer, TcpListener = tcpListener}; | 
|   | 
|             try | 
|             { | 
|                 tcpListener.Start(); | 
|   | 
|                 int port = ((IPEndPoint)tcpListener.LocalEndpoint).Port; | 
|   | 
|                 ThreadPool.QueueUserWorkItem(_ => | 
|                 { | 
|                     bool listening = true; | 
|                      | 
|                     while (listening) | 
|                     { | 
|                         var handle = tcpListener.BeginAcceptTcpClient(OnIncomingConnection, state); | 
|                         listening = handle.AsyncWaitHandle.WaitOne(ListenTimeoutMilliseconds); | 
|                     } | 
|                      | 
|                     Cleanup(state); | 
|                 }); | 
|   | 
|                 return port; | 
|             } | 
|             catch (Exception) | 
|             { | 
|                 Cleanup(state); | 
|                 return -1; | 
|             } | 
|         } | 
|   | 
|         private static void OnIncomingConnection(IAsyncResult result) | 
|         { | 
|             var state = (State)result.AsyncState; | 
|   | 
|             try | 
|             { | 
|                 using (var client = state.TcpListener.EndAcceptTcpClient(result)) | 
|                 { | 
|                     using (var stream = client.GetStream()) | 
|                     { | 
|                         stream.Write(state.Buffer, 0, state.Buffer.Length); | 
|                     } | 
|                 } | 
|             } | 
|             catch (Exception) | 
|             { | 
|                 // Ignore and cleanup | 
|             } | 
|         } | 
|   | 
|         private static void Cleanup(State state) | 
|         { | 
|             state.TcpListener?.Stop(); | 
|   | 
|             state.TcpListener = null; | 
|             state.Buffer = null; | 
|         } | 
|     } | 
| } |