You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
93 lines
2.4 KiB
93 lines
2.4 KiB
/*--------------------------------------------------------------------------------------------- |
|
* 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.Net.Sockets; |
|
using System.Threading; |
|
|
|
namespace Microsoft.Unity.VisualStudio.Editor.Messaging |
|
{ |
|
internal class TcpClient |
|
{ |
|
private const int ConnectOrReadTimeoutMilliseconds = 5000; |
|
|
|
private class State |
|
{ |
|
public System.Net.Sockets.TcpClient TcpClient; |
|
public NetworkStream NetworkStream; |
|
public byte[] Buffer; |
|
public Action<byte[]> OnBufferAvailable; |
|
} |
|
|
|
public static void Queue(IPAddress address, int port, int bufferSize, Action<byte[]> onBufferAvailable) |
|
{ |
|
var client = new System.Net.Sockets.TcpClient(); |
|
var state = new State {OnBufferAvailable = onBufferAvailable, TcpClient = client, Buffer = new byte[bufferSize]}; |
|
|
|
try |
|
{ |
|
ThreadPool.QueueUserWorkItem(_ => |
|
{ |
|
var handle = client.BeginConnect(address, port, OnClientConnected, state); |
|
if (!handle.AsyncWaitHandle.WaitOne(ConnectOrReadTimeoutMilliseconds)) |
|
Cleanup(state); |
|
}); |
|
} |
|
catch (Exception) |
|
{ |
|
Cleanup(state); |
|
} |
|
} |
|
|
|
private static void OnClientConnected(IAsyncResult result) |
|
{ |
|
var state = (State)result.AsyncState; |
|
|
|
try |
|
{ |
|
state.TcpClient.EndConnect(result); |
|
state.NetworkStream = state.TcpClient.GetStream(); |
|
var handle = state.NetworkStream.BeginRead(state.Buffer, 0, state.Buffer.Length, OnEndRead, state); |
|
if (!handle.AsyncWaitHandle.WaitOne(ConnectOrReadTimeoutMilliseconds)) |
|
Cleanup(state); |
|
} |
|
catch (Exception) |
|
{ |
|
Cleanup(state); |
|
} |
|
} |
|
|
|
private static void OnEndRead(IAsyncResult result) |
|
{ |
|
var state = (State)result.AsyncState; |
|
|
|
try |
|
{ |
|
var count = state.NetworkStream.EndRead(result); |
|
if (count == state.Buffer.Length) |
|
state.OnBufferAvailable?.Invoke(state.Buffer); |
|
} |
|
catch (Exception) |
|
{ |
|
// Ignore and cleanup |
|
} |
|
finally |
|
{ |
|
Cleanup(state); |
|
} |
|
} |
|
|
|
private static void Cleanup(State state) |
|
{ |
|
state.NetworkStream?.Dispose(); |
|
state.TcpClient?.Close(); |
|
|
|
state.NetworkStream = null; |
|
state.TcpClient = null; |
|
state.Buffer = null; |
|
state.OnBufferAvailable = null; |
|
} |
|
} |
|
}
|
|
|