mirror of
https://github.com/snltty/linker.git
synced 2025-10-30 04:02:13 +08:00
桌面共享使用打洞或者服务器中继进行代理
This commit is contained in:
@@ -1,10 +1,11 @@
|
|||||||
using common.libs.extends;
|
using common.libs.extends;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace cmonitor.client.tunnel
|
namespace cmonitor.client.tunnel
|
||||||
{
|
{
|
||||||
public delegate Task TunnelReceivceCallback(Memory<byte> data, object state);
|
public delegate Task TunnelReceivceCallback(ITunnelConnection connection,Memory<byte> data, object state);
|
||||||
public delegate Task TunnelCloseCallback(object state);
|
public delegate Task TunnelCloseCallback(ITunnelConnection connection,object state);
|
||||||
|
|
||||||
public enum TunnelProtocolType : byte
|
public enum TunnelProtocolType : byte
|
||||||
{
|
{
|
||||||
@@ -57,6 +58,7 @@ namespace cmonitor.client.tunnel
|
|||||||
|
|
||||||
public bool Connected => Socket != null && Socket.Connected;
|
public bool Connected => Socket != null && Socket.Connected;
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
public Socket Socket { get; init; }
|
public Socket Socket { get; init; }
|
||||||
|
|
||||||
|
|
||||||
@@ -101,7 +103,7 @@ namespace cmonitor.client.tunnel
|
|||||||
int offset = e.Offset;
|
int offset = e.Offset;
|
||||||
int length = e.BytesTransferred;
|
int length = e.BytesTransferred;
|
||||||
|
|
||||||
await receiveCallback(e.Buffer.AsMemory(offset, length), e.UserToken).ConfigureAwait(false);
|
await receiveCallback(this,e.Buffer.AsMemory(offset, length), e.UserToken).ConfigureAwait(false);
|
||||||
|
|
||||||
if (Socket.Available > 0)
|
if (Socket.Available > 0)
|
||||||
{
|
{
|
||||||
@@ -110,7 +112,7 @@ namespace cmonitor.client.tunnel
|
|||||||
length = Socket.Receive(e.Buffer);
|
length = Socket.Receive(e.Buffer);
|
||||||
if (length > 0)
|
if (length > 0)
|
||||||
{
|
{
|
||||||
await receiveCallback(e.Buffer.AsMemory(offset, length), e.UserToken).ConfigureAwait(false);
|
await receiveCallback(this,e.Buffer.AsMemory(offset, length), e.UserToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -143,7 +145,7 @@ namespace cmonitor.client.tunnel
|
|||||||
}
|
}
|
||||||
private void CloseClientSocket(SocketAsyncEventArgs e)
|
private void CloseClientSocket(SocketAsyncEventArgs e)
|
||||||
{
|
{
|
||||||
closeCallback(e.UserToken);
|
closeCallback(this,e.UserToken);
|
||||||
e.Dispose();
|
e.Dispose();
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
using cmonitor.client.api;
|
using cmonitor.client.api;
|
||||||
|
using cmonitor.client.tunnel;
|
||||||
using cmonitor.config;
|
using cmonitor.config;
|
||||||
using cmonitor.plugins.relay.transport;
|
|
||||||
using common.libs;
|
using common.libs;
|
||||||
using common.libs.api;
|
using common.libs.api;
|
||||||
using common.libs.extends;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace cmonitor.plugins.relay
|
namespace cmonitor.plugins.relay
|
||||||
@@ -27,17 +26,16 @@ namespace cmonitor.plugins.relay
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
RelayTransportState state = await relayTransfer.ConnectAsync(param.Content, "test", config.Data.Client.Relay.SecretKey);
|
ITunnelConnection connection = await relayTransfer.ConnectAsync(param.Content, "test", config.Data.Client.Relay.SecretKey);
|
||||||
if (state != null)
|
if (connection != null)
|
||||||
{
|
{
|
||||||
var socket = state.Socket;
|
|
||||||
for (int i = 0; i < 10; i++)
|
for (int i = 0; i < 10; i++)
|
||||||
{
|
{
|
||||||
Logger.Instance.Debug($"relay [test] send {i}");
|
Logger.Instance.Debug($"relay [test] send {i}");
|
||||||
socket.Send(Encoding.UTF8.GetBytes($"snltty.relay.{i}"));
|
await connection.SendAsync(Encoding.UTF8.GetBytes($"snltty.relay.{i}"));
|
||||||
await Task.Delay(10);
|
await Task.Delay(10);
|
||||||
}
|
}
|
||||||
socket.SafeClose();
|
connection.Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -48,23 +46,21 @@ namespace cmonitor.plugins.relay
|
|||||||
}
|
}
|
||||||
private void RelayTest()
|
private void RelayTest()
|
||||||
{
|
{
|
||||||
relayTransfer.OnConnected += (RelayTransportState state) =>
|
relayTransfer.SetConnectCallback("test", (ITunnelConnection connection) =>
|
||||||
{
|
|
||||||
if (state.Info.TransactionId == "test")
|
|
||||||
{
|
{
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
byte[] bytes = new byte[1024];
|
connection.BeginReceive(async (ITunnelConnection connection, Memory<byte> data, object state) =>
|
||||||
while (true)
|
|
||||||
{
|
{
|
||||||
int length = state.Socket.Receive(bytes);
|
Logger.Instance.Debug($"relay [{connection.TransactionId}] receive {Encoding.UTF8.GetString(data.Span)}");
|
||||||
if (length == 0) break;
|
await Task.CompletedTask;
|
||||||
|
},
|
||||||
Logger.Instance.Debug($"relay [{state.Info.TransactionId}] receive {Encoding.UTF8.GetString(bytes.AsSpan(0,length))}");
|
async (ITunnelConnection connection, object state) =>
|
||||||
}
|
{
|
||||||
|
await Task.CompletedTask;
|
||||||
|
}, null);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
using cmonitor.client;
|
using cmonitor.client.tunnel;
|
||||||
using cmonitor.config;
|
using cmonitor.config;
|
||||||
using cmonitor.plugins.relay.transport;
|
using cmonitor.plugins.relay.transport;
|
||||||
using cmonitor.server;
|
|
||||||
using common.libs;
|
using common.libs;
|
||||||
using common.libs.extends;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace cmonitor.plugins.relay
|
namespace cmonitor.plugins.relay
|
||||||
@@ -18,7 +15,7 @@ namespace cmonitor.plugins.relay
|
|||||||
private readonly Config config;
|
private readonly Config config;
|
||||||
private readonly ServiceProvider serviceProvider;
|
private readonly ServiceProvider serviceProvider;
|
||||||
|
|
||||||
public Action<RelayTransportState> OnConnected { get; set; } = (state) => { };
|
private Dictionary<string, Action<ITunnelConnection>> OnConnected { get; } = new Dictionary<string, Action<ITunnelConnection>>();
|
||||||
|
|
||||||
public RelayTransfer(Config config, ServiceProvider serviceProvider)
|
public RelayTransfer(Config config, ServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
@@ -35,7 +32,19 @@ namespace cmonitor.plugins.relay
|
|||||||
Logger.Instance.Warning($"load relay transport:{string.Join(",", transports.Select(c => c.Name))}");
|
Logger.Instance.Warning($"load relay transport:{string.Join(",", transports.Select(c => c.Name))}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<RelayTransportState> ConnectAsync(string remoteMachineName, string transactionId, string secretKey)
|
public void SetConnectCallback(string transactionId, Action<ITunnelConnection> callback)
|
||||||
|
{
|
||||||
|
if (OnConnected.TryGetValue(transactionId, out Action<ITunnelConnection> _callback) == false)
|
||||||
|
{
|
||||||
|
OnConnected[transactionId] = callback;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OnConnected[transactionId] += callback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ITunnelConnection> ConnectAsync(string remoteMachineName, string transactionId, string secretKey)
|
||||||
{
|
{
|
||||||
IEnumerable<ITransport> _transports = transports.OrderBy(c => c.Name);
|
IEnumerable<ITransport> _transports = transports.OrderBy(c => c.Name);
|
||||||
foreach (RelayCompactInfo item in config.Data.Client.Relay.Servers.Where(c => c.Disabled == false))
|
foreach (RelayCompactInfo item in config.Data.Client.Relay.Servers.Where(c => c.Disabled == false))
|
||||||
@@ -58,10 +67,10 @@ namespace cmonitor.plugins.relay
|
|||||||
TransactionId = transactionId,
|
TransactionId = transactionId,
|
||||||
TransportName = transport.Name
|
TransportName = transport.Name
|
||||||
};
|
};
|
||||||
Socket socket = await transport.RelayAsync(relayInfo);
|
ITunnelConnection connection = await transport.RelayAsync(relayInfo);
|
||||||
if (socket != null)
|
if (connection != null)
|
||||||
{
|
{
|
||||||
return new RelayTransportState { Info = relayInfo, Socket = socket, Direction = RelayTransportDirection.Forward };
|
return connection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -76,10 +85,13 @@ namespace cmonitor.plugins.relay
|
|||||||
ITransport _transports = transports.FirstOrDefault(c => c.Name == relayInfo.TransportName);
|
ITransport _transports = transports.FirstOrDefault(c => c.Name == relayInfo.TransportName);
|
||||||
if (_transports != null)
|
if (_transports != null)
|
||||||
{
|
{
|
||||||
Socket socket = await _transports.OnBeginAsync(relayInfo);
|
ITunnelConnection connection = await _transports.OnBeginAsync(relayInfo);
|
||||||
if (socket != null)
|
if (connection != null)
|
||||||
{
|
{
|
||||||
OnConnected(new RelayTransportState { Info = relayInfo, Socket = socket, Direction = RelayTransportDirection.Reverse });
|
if (OnConnected.TryGetValue(connection.TransactionId, out Action<ITunnelConnection> callback))
|
||||||
|
{
|
||||||
|
callback(connection);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
using MemoryPack;
|
using cmonitor.client.tunnel;
|
||||||
|
using MemoryPack;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
|
||||||
|
|
||||||
namespace cmonitor.plugins.relay.transport
|
namespace cmonitor.plugins.relay.transport
|
||||||
{
|
{
|
||||||
public interface ITransport
|
public interface ITransport
|
||||||
{
|
{
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
public Task<Socket> RelayAsync(RelayInfo relayInfo);
|
public TunnelProtocolType ProtocolType { get; }
|
||||||
public Task<Socket> OnBeginAsync(RelayInfo relayInfo);
|
|
||||||
|
public Task<ITunnelConnection> RelayAsync(RelayInfo relayInfo);
|
||||||
|
public Task<ITunnelConnection> OnBeginAsync(RelayInfo relayInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MemoryPackable]
|
[MemoryPackable]
|
||||||
@@ -26,19 +28,4 @@ namespace cmonitor.plugins.relay.transport
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum RelayTransportDirection : byte
|
|
||||||
{
|
|
||||||
Forward = 0,
|
|
||||||
Reverse = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class RelayTransportState
|
|
||||||
{
|
|
||||||
public RelayInfo Info { get; set; }
|
|
||||||
|
|
||||||
public RelayTransportDirection Direction { get; set; } = RelayTransportDirection.Reverse;
|
|
||||||
|
|
||||||
public Socket Socket { get; set; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using cmonitor.plugins.relay.messenger;
|
using cmonitor.client.tunnel;
|
||||||
|
using cmonitor.plugins.relay.messenger;
|
||||||
using cmonitor.server;
|
using cmonitor.server;
|
||||||
using common.libs;
|
using common.libs;
|
||||||
using common.libs.extends;
|
using common.libs.extends;
|
||||||
@@ -11,6 +12,7 @@ namespace cmonitor.plugins.relay.transport
|
|||||||
public sealed class TransportSelfHost : ITransport
|
public sealed class TransportSelfHost : ITransport
|
||||||
{
|
{
|
||||||
public string Name => "self";
|
public string Name => "self";
|
||||||
|
public TunnelProtocolType ProtocolType => TunnelProtocolType.Tcp;
|
||||||
|
|
||||||
private readonly TcpServer tcpServer;
|
private readonly TcpServer tcpServer;
|
||||||
private readonly MessengerSender messengerSender;
|
private readonly MessengerSender messengerSender;
|
||||||
@@ -22,9 +24,9 @@ namespace cmonitor.plugins.relay.transport
|
|||||||
this.messengerSender = messengerSender;
|
this.messengerSender = messengerSender;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Socket> RelayAsync(RelayInfo relayInfo)
|
public async Task<ITunnelConnection> RelayAsync(RelayInfo relayInfo)
|
||||||
{
|
{
|
||||||
Socket socket = new Socket(relayInfo.Server.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
Socket socket = new Socket(relayInfo.Server.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
|
||||||
socket.Reuse(true);
|
socket.Reuse(true);
|
||||||
socket.IPv6Only(relayInfo.Server.AddressFamily, false);
|
socket.IPv6Only(relayInfo.Server.AddressFamily, false);
|
||||||
await socket.ConnectAsync(relayInfo.Server).WaitAsync(TimeSpan.FromSeconds(5));
|
await socket.ConnectAsync(relayInfo.Server).WaitAsync(TimeSpan.FromSeconds(5));
|
||||||
@@ -43,12 +45,21 @@ namespace cmonitor.plugins.relay.transport
|
|||||||
}
|
}
|
||||||
await socket.SendAsync(relayFlagData);
|
await socket.SendAsync(relayFlagData);
|
||||||
await Task.Delay(10);
|
await Task.Delay(10);
|
||||||
return socket;
|
return new TunnelConnectionTcp
|
||||||
|
{
|
||||||
|
Direction = TunnelDirection.Forward,
|
||||||
|
ProtocolType = TunnelProtocolType.Tcp,
|
||||||
|
RemoteMachineName = relayInfo.RemoteMachineName,
|
||||||
|
Socket = socket,
|
||||||
|
TransactionId = relayInfo.TransactionId,
|
||||||
|
TransportName = Name,
|
||||||
|
Type = TunnelType.Relay
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Socket> OnBeginAsync(RelayInfo relayInfo)
|
public async Task<ITunnelConnection> OnBeginAsync(RelayInfo relayInfo)
|
||||||
{
|
{
|
||||||
Socket socket = new Socket(relayInfo.Server.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
Socket socket = new Socket(relayInfo.Server.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
|
||||||
socket.Reuse(true);
|
socket.Reuse(true);
|
||||||
socket.IPv6Only(relayInfo.Server.AddressFamily, false);
|
socket.IPv6Only(relayInfo.Server.AddressFamily, false);
|
||||||
await socket.ConnectAsync(relayInfo.Server).WaitAsync(TimeSpan.FromSeconds(5));
|
await socket.ConnectAsync(relayInfo.Server).WaitAsync(TimeSpan.FromSeconds(5));
|
||||||
@@ -67,7 +78,16 @@ namespace cmonitor.plugins.relay.transport
|
|||||||
}
|
}
|
||||||
await socket.SendAsync(relayFlagData);
|
await socket.SendAsync(relayFlagData);
|
||||||
await Task.Delay(10);
|
await Task.Delay(10);
|
||||||
return socket;
|
return new TunnelConnectionTcp
|
||||||
|
{
|
||||||
|
Direction = TunnelDirection.Reverse,
|
||||||
|
ProtocolType = TunnelProtocolType.Tcp,
|
||||||
|
RemoteMachineName = relayInfo.RemoteMachineName,
|
||||||
|
Socket = socket,
|
||||||
|
TransactionId = relayInfo.TransactionId,
|
||||||
|
TransportName = Name,
|
||||||
|
Type = TunnelType.Relay
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using cmonitor.client;
|
using cmonitor.client;
|
||||||
using cmonitor.client.api;
|
using cmonitor.client.api;
|
||||||
|
using cmonitor.client.tunnel;
|
||||||
using cmonitor.config;
|
using cmonitor.config;
|
||||||
using cmonitor.plugins.signin.messenger;
|
using cmonitor.plugins.signin.messenger;
|
||||||
using cmonitor.plugins.tunnel.server;
|
using cmonitor.plugins.tunnel.server;
|
||||||
@@ -38,17 +39,16 @@ namespace cmonitor.plugins.tunnel
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
TunnelTransportState state = await tunnelTransfer.ConnectAsync(param.Content, "test");
|
ITunnelConnection connection = await tunnelTransfer.ConnectAsync(param.Content, "test");
|
||||||
if (state != null)
|
if (connection != null)
|
||||||
{
|
{
|
||||||
var socket = state.ConnectedObject as Socket;
|
|
||||||
for (int i = 0; i < 10; i++)
|
for (int i = 0; i < 10; i++)
|
||||||
{
|
{
|
||||||
Logger.Instance.Debug($"tunnel [test] send {i}");
|
Logger.Instance.Debug($"tunnel [test] send {i}");
|
||||||
socket.Send(BitConverter.GetBytes(i));
|
await connection.SendAsync(BitConverter.GetBytes(i));
|
||||||
await Task.Delay(10);
|
await Task.Delay(10);
|
||||||
}
|
}
|
||||||
socket.SafeClose();
|
connection.Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -59,17 +59,18 @@ namespace cmonitor.plugins.tunnel
|
|||||||
}
|
}
|
||||||
private void TunnelTest()
|
private void TunnelTest()
|
||||||
{
|
{
|
||||||
tunnelTransfer.OnConnected += (TunnelTransportState state) =>
|
tunnelTransfer.SetConnectCallback("test", (ITunnelConnection connection) =>
|
||||||
{
|
{
|
||||||
if (state.TransactionId == "test" && state.TransportType == ProtocolType.Tcp)
|
connection.BeginReceive(async (ITunnelConnection connection, Memory<byte> data, object state) => {
|
||||||
{
|
|
||||||
tunnelBindServer.BindReceive(state.ConnectedObject as Socket, null, async (token, data) =>
|
Logger.Instance.Debug($"tunnel [{connection.TransactionId}] receive {BitConverter.ToInt32(data.Span)}");
|
||||||
{
|
await Task.CompletedTask;
|
||||||
Logger.Instance.Debug($"tunnel [{state.TransactionId}] receive {BitConverter.ToInt32(data.Span)}");
|
|
||||||
|
}, async (ITunnelConnection connection, object state) => {
|
||||||
|
await Task.CompletedTask;
|
||||||
|
}, null);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using cmonitor.client;
|
using cmonitor.client;
|
||||||
|
using cmonitor.client.tunnel;
|
||||||
using cmonitor.config;
|
using cmonitor.config;
|
||||||
using cmonitor.plugins.tunnel.compact;
|
using cmonitor.plugins.tunnel.compact;
|
||||||
using cmonitor.plugins.tunnel.messenger;
|
using cmonitor.plugins.tunnel.messenger;
|
||||||
@@ -8,8 +9,8 @@ using common.libs;
|
|||||||
using common.libs.extends;
|
using common.libs.extends;
|
||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Transactions;
|
||||||
|
|
||||||
namespace cmonitor.plugins.tunnel
|
namespace cmonitor.plugins.tunnel
|
||||||
{
|
{
|
||||||
@@ -23,7 +24,7 @@ namespace cmonitor.plugins.tunnel
|
|||||||
private readonly MessengerSender messengerSender;
|
private readonly MessengerSender messengerSender;
|
||||||
private readonly CompactTransfer compactTransfer;
|
private readonly CompactTransfer compactTransfer;
|
||||||
|
|
||||||
public Action<TunnelTransportState> OnConnected { get; set; } = (state) => { };
|
private Dictionary<string, Action<ITunnelConnection>> OnConnected { get; } = new Dictionary<string, Action<ITunnelConnection>>();
|
||||||
|
|
||||||
public TunnelTransfer(Config config, ServiceProvider serviceProvider, ClientSignInState clientSignInState, MessengerSender messengerSender, CompactTransfer compactTransfer)
|
public TunnelTransfer(Config config, ServiceProvider serviceProvider, ClientSignInState clientSignInState, MessengerSender messengerSender, CompactTransfer compactTransfer)
|
||||||
{
|
{
|
||||||
@@ -53,45 +54,44 @@ namespace cmonitor.plugins.tunnel
|
|||||||
Logger.Instance.Warning($"load tunnel transport:{string.Join(",", transports.Select(c => c.Name))}");
|
Logger.Instance.Warning($"load tunnel transport:{string.Join(",", transports.Select(c => c.Name))}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<TunnelTransportState> ConnectAsync(string remoteMachineName, string transactionId)
|
public async Task<ITunnelConnection> ConnectAsync(string remoteMachineName, string transactionId)
|
||||||
{
|
{
|
||||||
IEnumerable<ITransport> _transports = transports.OrderBy(c => c.Type);
|
IEnumerable<ITransport> _transports = transports.OrderBy(c => c.ProtocolType);
|
||||||
foreach (ITransport transport in _transports)
|
foreach (ITransport transport in _transports)
|
||||||
{
|
{
|
||||||
//获取自己的外网ip
|
//获取自己的外网ip
|
||||||
TunnelTransportExternalIPInfo localInfo = await GetLocalInfo(transport.Type);
|
TunnelTransportExternalIPInfo localInfo = await GetLocalInfo(transport.ProtocolType);
|
||||||
if (localInfo == null)
|
if (localInfo == null)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//获取对方的外网ip
|
//获取对方的外网ip
|
||||||
TunnelTransportExternalIPInfo remoteInfo = await GetRemoteInfo(remoteMachineName, transport.Type);
|
TunnelTransportExternalIPInfo remoteInfo = await GetRemoteInfo(remoteMachineName, transport.ProtocolType);
|
||||||
if (remoteInfo == null)
|
if (remoteInfo == null)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
TunnelTransportInfo tunnelTransportInfo = new TunnelTransportInfo
|
TunnelTransportInfo tunnelTransportInfo = new TunnelTransportInfo
|
||||||
{
|
{
|
||||||
Direction = TunnelTransportDirection.Forward,
|
Direction = TunnelDirection.Forward,
|
||||||
TransactionId = transactionId,
|
TransactionId = transactionId,
|
||||||
TransportName = transport.Name,
|
TransportName = transport.Name,
|
||||||
TransportType = transport.Type,
|
TransportType = transport.ProtocolType,
|
||||||
Local = localInfo,
|
Local = localInfo,
|
||||||
Remote = remoteInfo,
|
Remote = remoteInfo,
|
||||||
};
|
};
|
||||||
TunnelTransportState state = await transport.ConnectAsync(tunnelTransportInfo);
|
ITunnelConnection connection = await transport.ConnectAsync(tunnelTransportInfo);
|
||||||
if (state != null)
|
if (connection != null)
|
||||||
{
|
{
|
||||||
state.Direction = TunnelTransportDirection.Forward;
|
_OnConnected(connection);
|
||||||
_OnConnected(state);
|
return connection;
|
||||||
return state;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public void OnBegin(TunnelTransportInfo tunnelTransportInfo)
|
public void OnBegin(TunnelTransportInfo tunnelTransportInfo)
|
||||||
{
|
{
|
||||||
ITransport _transports = transports.FirstOrDefault(c => c.Name == tunnelTransportInfo.TransportName && c.Type == tunnelTransportInfo.TransportType);
|
ITransport _transports = transports.FirstOrDefault(c => c.Name == tunnelTransportInfo.TransportName && c.ProtocolType == tunnelTransportInfo.TransportType);
|
||||||
if (_transports != null)
|
if (_transports != null)
|
||||||
{
|
{
|
||||||
_transports.OnBegin(tunnelTransportInfo);
|
_transports.OnBegin(tunnelTransportInfo);
|
||||||
@@ -99,7 +99,7 @@ namespace cmonitor.plugins.tunnel
|
|||||||
}
|
}
|
||||||
public void OnFail(TunnelTransportInfo tunnelTransportInfo)
|
public void OnFail(TunnelTransportInfo tunnelTransportInfo)
|
||||||
{
|
{
|
||||||
ITransport _transports = transports.FirstOrDefault(c => c.Name == tunnelTransportInfo.TransportName && c.Type == tunnelTransportInfo.TransportType);
|
ITransport _transports = transports.FirstOrDefault(c => c.Name == tunnelTransportInfo.TransportName && c.ProtocolType == tunnelTransportInfo.TransportType);
|
||||||
if (_transports != null)
|
if (_transports != null)
|
||||||
{
|
{
|
||||||
_transports.OnFail(tunnelTransportInfo);
|
_transports.OnFail(tunnelTransportInfo);
|
||||||
@@ -111,7 +111,7 @@ namespace cmonitor.plugins.tunnel
|
|||||||
return await GetLocalInfo(request.TransportType);
|
return await GetLocalInfo(request.TransportType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<TunnelTransportExternalIPInfo> GetLocalInfo(ProtocolType transportType)
|
private async Task<TunnelTransportExternalIPInfo> GetLocalInfo(TunnelProtocolType transportType)
|
||||||
{
|
{
|
||||||
TunnelCompactIPEndPoint[] ips = await compactTransfer.GetExternalIPAsync(transportType);
|
TunnelCompactIPEndPoint[] ips = await compactTransfer.GetExternalIPAsync(transportType);
|
||||||
if (ips != null && ips.Length > 0)
|
if (ips != null && ips.Length > 0)
|
||||||
@@ -126,7 +126,7 @@ namespace cmonitor.plugins.tunnel
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
private async Task<TunnelTransportExternalIPInfo> GetRemoteInfo(string remoteMachineName, ProtocolType transportType)
|
private async Task<TunnelTransportExternalIPInfo> GetRemoteInfo(string remoteMachineName, TunnelProtocolType transportType)
|
||||||
{
|
{
|
||||||
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
|
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||||
{
|
{
|
||||||
@@ -168,6 +168,19 @@ namespace cmonitor.plugins.tunnel
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void SetConnectCallback(string transactionId, Action<ITunnelConnection> callback)
|
||||||
|
{
|
||||||
|
if (OnConnected.TryGetValue(transactionId, out Action<ITunnelConnection> _callback) == false)
|
||||||
|
{
|
||||||
|
OnConnected[transactionId] = callback;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OnConnected[transactionId] += callback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public Dictionary<string, TunnelConnectInfo> Connections { get; } = new Dictionary<string, TunnelConnectInfo>();
|
public Dictionary<string, TunnelConnectInfo> Connections { get; } = new Dictionary<string, TunnelConnectInfo>();
|
||||||
private int connectionsChangeFlag = 1;
|
private int connectionsChangeFlag = 1;
|
||||||
public bool ConnectionChanged => Interlocked.CompareExchange(ref connectionsChangeFlag, 0, 1) == 1;
|
public bool ConnectionChanged => Interlocked.CompareExchange(ref connectionsChangeFlag, 0, 1) == 1;
|
||||||
@@ -191,23 +204,27 @@ namespace cmonitor.plugins.tunnel
|
|||||||
info.Status = TunnelConnectStatus.Connecting;
|
info.Status = TunnelConnectStatus.Connecting;
|
||||||
Interlocked.Exchange(ref connectionsChangeFlag, 1);
|
Interlocked.Exchange(ref connectionsChangeFlag, 1);
|
||||||
}
|
}
|
||||||
private void _OnConnected(TunnelTransportState state)
|
private void _OnConnected(ITunnelConnection connection)
|
||||||
{
|
{
|
||||||
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||||
{
|
{
|
||||||
Logger.Instance.Debug($"tunnel connect [{state.TransactionId}]->{state.RemoteMachineName} success");
|
Logger.Instance.Debug($"tunnel connect [{connection.TransactionId}]->{connection.RemoteMachineName} success");
|
||||||
}
|
}
|
||||||
CheckDic(state.RemoteMachineName, out TunnelConnectInfo info);
|
CheckDic(connection.RemoteMachineName, out TunnelConnectInfo info);
|
||||||
info.Status = TunnelConnectStatus.Connected;
|
info.Status = TunnelConnectStatus.Connected;
|
||||||
info.State = state;
|
info.Connection = connection;
|
||||||
Interlocked.Exchange(ref connectionsChangeFlag, 1);
|
Interlocked.Exchange(ref connectionsChangeFlag, 1);
|
||||||
OnConnected(state);
|
|
||||||
}
|
if (OnConnected.TryGetValue(connection.TransactionId, out Action<ITunnelConnection> _callback) == false)
|
||||||
private void OnDisConnected(TunnelTransportState state)
|
|
||||||
{
|
{
|
||||||
CheckDic(state.RemoteMachineName, out TunnelConnectInfo info);
|
_callback(connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void OnDisConnected(ITunnelConnection connection)
|
||||||
|
{
|
||||||
|
CheckDic(connection.RemoteMachineName, out TunnelConnectInfo info);
|
||||||
info.Status = TunnelConnectStatus.None;
|
info.Status = TunnelConnectStatus.None;
|
||||||
info.State = null;
|
info.Connection = null;
|
||||||
Interlocked.Exchange(ref connectionsChangeFlag, 1);
|
Interlocked.Exchange(ref connectionsChangeFlag, 1);
|
||||||
}
|
}
|
||||||
private void OnConnectFail(string machineName)
|
private void OnConnectFail(string machineName)
|
||||||
@@ -218,7 +235,7 @@ namespace cmonitor.plugins.tunnel
|
|||||||
}
|
}
|
||||||
CheckDic(machineName, out TunnelConnectInfo info);
|
CheckDic(machineName, out TunnelConnectInfo info);
|
||||||
info.Status = TunnelConnectStatus.None;
|
info.Status = TunnelConnectStatus.None;
|
||||||
info.State = null;
|
info.Connection = null;
|
||||||
Interlocked.Exchange(ref connectionsChangeFlag, 1);
|
Interlocked.Exchange(ref connectionsChangeFlag, 1);
|
||||||
}
|
}
|
||||||
private void CheckDic(string name, out TunnelConnectInfo info)
|
private void CheckDic(string name, out TunnelConnectInfo info)
|
||||||
@@ -233,7 +250,7 @@ namespace cmonitor.plugins.tunnel
|
|||||||
public sealed class TunnelConnectInfo
|
public sealed class TunnelConnectInfo
|
||||||
{
|
{
|
||||||
public TunnelConnectStatus Status { get; set; }
|
public TunnelConnectStatus Status { get; set; }
|
||||||
public TunnelTransportState State { get; set; }
|
public ITunnelConnection Connection { get; set; }
|
||||||
}
|
}
|
||||||
public enum TunnelConnectStatus
|
public enum TunnelConnectStatus
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using cmonitor.config;
|
using cmonitor.client.tunnel;
|
||||||
|
using cmonitor.config;
|
||||||
using common.libs;
|
using common.libs;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
@@ -28,7 +29,7 @@ namespace cmonitor.plugins.tunnel.compact
|
|||||||
Logger.Instance.Warning($"load tunnel compacts:{string.Join(",", compacts.Select(c => c.Name))}");
|
Logger.Instance.Warning($"load tunnel compacts:{string.Join(",", compacts.Select(c => c.Name))}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<TunnelCompactIPEndPoint[]> GetExternalIPAsync(ProtocolType protocolType)
|
public async Task<TunnelCompactIPEndPoint[]> GetExternalIPAsync(TunnelProtocolType protocolType)
|
||||||
{
|
{
|
||||||
TunnelCompactIPEndPoint[] endpoints = new TunnelCompactIPEndPoint[config.Data.Client.Tunnel.Servers.Length];
|
TunnelCompactIPEndPoint[] endpoints = new TunnelCompactIPEndPoint[config.Data.Client.Tunnel.Servers.Length];
|
||||||
|
|
||||||
@@ -42,12 +43,12 @@ namespace cmonitor.plugins.tunnel.compact
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
IPEndPoint server = NetworkHelper.GetEndPoint(item.Host, 3478);
|
IPEndPoint server = NetworkHelper.GetEndPoint(item.Host, 3478);
|
||||||
if (protocolType == ProtocolType.Tcp)
|
if (protocolType == TunnelProtocolType.Tcp)
|
||||||
{
|
{
|
||||||
TunnelCompactIPEndPoint externalIP = await compact.GetTcpExternalIPAsync(server);
|
TunnelCompactIPEndPoint externalIP = await compact.GetTcpExternalIPAsync(server);
|
||||||
endpoints[i] = externalIP;
|
endpoints[i] = externalIP;
|
||||||
}
|
}
|
||||||
else if (protocolType == ProtocolType.Udp)
|
else if (protocolType == TunnelProtocolType.Udp)
|
||||||
{
|
{
|
||||||
TunnelCompactIPEndPoint externalIP = await compact.GetUdpExternalIPAsync(server);
|
TunnelCompactIPEndPoint externalIP = await compact.GetUdpExternalIPAsync(server);
|
||||||
endpoints[i] = externalIP;
|
endpoints[i] = externalIP;
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ namespace cmonitor.plugins.tunnel.server
|
|||||||
|
|
||||||
public Action<object, Socket> OnTcpConnected { get; set; } = (state, socket) => { };
|
public Action<object, Socket> OnTcpConnected { get; set; } = (state, socket) => { };
|
||||||
public Action<object, UdpClient> OnUdpConnected { get; set; } = (state, udpClient) => { };
|
public Action<object, UdpClient> OnUdpConnected { get; set; } = (state, udpClient) => { };
|
||||||
public Action<object> OnDisConnected { get; set; } = (state) => { };
|
|
||||||
|
|
||||||
private ConcurrentDictionary<int, SocketAsyncEventArgs> acceptBinds = new ConcurrentDictionary<int, SocketAsyncEventArgs>();
|
private ConcurrentDictionary<int, SocketAsyncEventArgs> acceptBinds = new ConcurrentDictionary<int, SocketAsyncEventArgs>();
|
||||||
|
|
||||||
@@ -85,9 +84,6 @@ namespace cmonitor.plugins.tunnel.server
|
|||||||
case SocketAsyncOperation.Accept:
|
case SocketAsyncOperation.Accept:
|
||||||
ProcessAccept(e);
|
ProcessAccept(e);
|
||||||
break;
|
break;
|
||||||
case SocketAsyncOperation.Receive:
|
|
||||||
ProcessReceive(e);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -119,87 +115,6 @@ namespace cmonitor.plugins.tunnel.server
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BindReceive(Socket socket, object state, OnTunnelData dataCallback)
|
|
||||||
{
|
|
||||||
if (socket == null || socket.RemoteEndPoint == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
socket.KeepAlive();
|
|
||||||
AsyncUserToken userToken = new AsyncUserToken
|
|
||||||
{
|
|
||||||
SourceSocket = socket,
|
|
||||||
State = state,
|
|
||||||
OnData = dataCallback,
|
|
||||||
LocalPort = (socket.LocalEndPoint as IPEndPoint).Port,
|
|
||||||
};
|
|
||||||
|
|
||||||
SocketAsyncEventArgs readEventArgs = new SocketAsyncEventArgs
|
|
||||||
{
|
|
||||||
UserToken = userToken,
|
|
||||||
SocketFlags = SocketFlags.None,
|
|
||||||
};
|
|
||||||
readEventArgs.SetBuffer(new byte[8 * 1024], 0, 8 * 1024);
|
|
||||||
readEventArgs.Completed += IO_Completed;
|
|
||||||
if (socket.ReceiveAsync(readEventArgs) == false)
|
|
||||||
{
|
|
||||||
ProcessReceive(readEventArgs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private async void ProcessReceive(SocketAsyncEventArgs e)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
AsyncUserToken token = (AsyncUserToken)e.UserToken;
|
|
||||||
|
|
||||||
if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
|
|
||||||
{
|
|
||||||
int offset = e.Offset;
|
|
||||||
int length = e.BytesTransferred;
|
|
||||||
|
|
||||||
await token.OnData(token, e.Buffer.AsMemory(0, length));
|
|
||||||
if (token.SourceSocket.Available > 0)
|
|
||||||
{
|
|
||||||
while (token.SourceSocket.Available > 0)
|
|
||||||
{
|
|
||||||
length = token.SourceSocket.Receive(e.Buffer);
|
|
||||||
if (length > 0)
|
|
||||||
{
|
|
||||||
await token.OnData(token, e.Buffer.AsMemory(0, length));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CloseClientSocket(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (token.SourceSocket.Connected == false)
|
|
||||||
{
|
|
||||||
CloseClientSocket(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (token.SourceSocket.ReceiveAsync(e) == false)
|
|
||||||
{
|
|
||||||
ProcessReceive(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CloseClientSocket(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
|
||||||
Logger.Instance.Error(ex);
|
|
||||||
|
|
||||||
CloseClientSocket(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void CloseClientSocket(SocketAsyncEventArgs e)
|
private void CloseClientSocket(SocketAsyncEventArgs e)
|
||||||
{
|
{
|
||||||
if (e == null || e.UserToken == null) return;
|
if (e == null || e.UserToken == null) return;
|
||||||
@@ -214,7 +129,6 @@ namespace cmonitor.plugins.tunnel.server
|
|||||||
{
|
{
|
||||||
CloseClientSocket(saea1);
|
CloseClientSocket(saea1);
|
||||||
}
|
}
|
||||||
OnDisConnected(token.State);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,9 +140,6 @@ namespace cmonitor.plugins.tunnel.server
|
|||||||
public Socket SourceSocket { get; set; }
|
public Socket SourceSocket { get; set; }
|
||||||
public SocketAsyncEventArgs Saea { get; set; }
|
public SocketAsyncEventArgs Saea { get; set; }
|
||||||
public object State { get; set; }
|
public object State { get; set; }
|
||||||
|
|
||||||
public OnTunnelData OnData { get; set; }
|
|
||||||
|
|
||||||
public int LocalPort { get; set; }
|
public int LocalPort { get; set; }
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
using MemoryPack;
|
using cmonitor.client.tunnel;
|
||||||
|
using MemoryPack;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace cmonitor.plugins.tunnel.transport
|
namespace cmonitor.plugins.tunnel.transport
|
||||||
{
|
{
|
||||||
public interface ITransport
|
public interface ITransport
|
||||||
{
|
{
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
public ProtocolType Type { get; }
|
public TunnelProtocolType ProtocolType { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 发送连接信息
|
/// 发送连接信息
|
||||||
@@ -26,11 +25,11 @@ namespace cmonitor.plugins.tunnel.transport
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 收到连接
|
/// 收到连接
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Action<TunnelTransportState> OnConnected { get; set; }
|
public Action<ITunnelConnection> OnConnected { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 断开连接
|
/// 断开连接
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Action<TunnelTransportState> OnDisConnected { get; set; }
|
public Action<ITunnelConnection> OnDisConnected { get; set; }
|
||||||
|
|
||||||
public Action<string> OnConnectFail { get; set; }
|
public Action<string> OnConnectFail { get; set; }
|
||||||
|
|
||||||
@@ -39,7 +38,7 @@ namespace cmonitor.plugins.tunnel.transport
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tunnelTransportInfo">你的名字</param>
|
/// <param name="tunnelTransportInfo">你的名字</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Task<TunnelTransportState> ConnectAsync(TunnelTransportInfo tunnelTransportInfo);
|
public Task<ITunnelConnection> ConnectAsync(TunnelTransportInfo tunnelTransportInfo);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 收到开始连接
|
/// 收到开始连接
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -57,7 +56,7 @@ namespace cmonitor.plugins.tunnel.transport
|
|||||||
public sealed partial class TunnelTransportExternalIPRequestInfo
|
public sealed partial class TunnelTransportExternalIPRequestInfo
|
||||||
{
|
{
|
||||||
public string RemoteMachineName { get; set; }
|
public string RemoteMachineName { get; set; }
|
||||||
public ProtocolType TransportType { get; set; }
|
public TunnelProtocolType TransportType { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[MemoryPackable]
|
[MemoryPackable]
|
||||||
@@ -83,43 +82,11 @@ namespace cmonitor.plugins.tunnel.transport
|
|||||||
|
|
||||||
public string TransactionId { get; set; }
|
public string TransactionId { get; set; }
|
||||||
|
|
||||||
public ProtocolType TransportType { get; set; }
|
public TunnelProtocolType TransportType { get; set; }
|
||||||
public string TransportName { get; set; }
|
public string TransportName { get; set; }
|
||||||
|
|
||||||
public TunnelTransportDirection Direction { get; set; }
|
public TunnelDirection Direction { get; set; }
|
||||||
}
|
|
||||||
|
|
||||||
public enum TunnelTransportDirection : byte
|
|
||||||
{
|
|
||||||
Forward = 0,
|
|
||||||
Reverse = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum TunnelTransportType
|
|
||||||
{
|
|
||||||
Tcp = ProtocolType.Tcp,
|
|
||||||
Udp = ProtocolType.Udp,
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class TunnelTransportState
|
|
||||||
{
|
|
||||||
public string RemoteMachineName { get; set; }
|
|
||||||
public string TransactionId { get; set; }
|
|
||||||
public string TransportName { get; set; }
|
|
||||||
public ProtocolType TransportType { get; set; }
|
|
||||||
|
|
||||||
public TunnelTransportDirection Direction { get; set; } = TunnelTransportDirection.Reverse;
|
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
public object ConnectedObject { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public interface ITunnelConnection
|
|
||||||
{
|
|
||||||
public TunnelTransportType TransportType { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using cmonitor.plugins.tunnel.server;
|
using cmonitor.client.tunnel;
|
||||||
|
using cmonitor.plugins.tunnel.server;
|
||||||
using common.libs;
|
using common.libs;
|
||||||
using common.libs.extends;
|
using common.libs.extends;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
@@ -10,14 +11,14 @@ namespace cmonitor.plugins.tunnel.transport
|
|||||||
public sealed class TransportTcpNutssb : ITransport
|
public sealed class TransportTcpNutssb : ITransport
|
||||||
{
|
{
|
||||||
public string Name => "TcpNutssb";
|
public string Name => "TcpNutssb";
|
||||||
public ProtocolType Type => ProtocolType.Tcp;
|
public TunnelProtocolType ProtocolType => TunnelProtocolType.Tcp;
|
||||||
|
|
||||||
public Func<TunnelTransportInfo, Task<bool>> OnSendConnectBegin { get; set; } = async (info) => { return await Task.FromResult<bool>(false); };
|
public Func<TunnelTransportInfo, Task<bool>> OnSendConnectBegin { get; set; } = async (info) => { return await Task.FromResult<bool>(false); };
|
||||||
public Func<TunnelTransportInfo, Task> OnSendConnectFail { get; set; } = async (info) => { await Task.CompletedTask; };
|
public Func<TunnelTransportInfo, Task> OnSendConnectFail { get; set; } = async (info) => { await Task.CompletedTask; };
|
||||||
public Action<TunnelTransportInfo> OnConnectBegin { get; set; } = (info) => { };
|
public Action<TunnelTransportInfo> OnConnectBegin { get; set; } = (info) => { };
|
||||||
public Action<TunnelTransportInfo> OnConnecting { get; set; }
|
public Action<TunnelTransportInfo> OnConnecting { get; set; }
|
||||||
public Action<TunnelTransportState> OnConnected { get; set; } = (state) => { };
|
public Action<ITunnelConnection> OnConnected { get; set; } = (state) => { };
|
||||||
public Action<TunnelTransportState> OnDisConnected { get; set; } = (state) => { };
|
public Action<ITunnelConnection> OnDisConnected { get; set; } = (state) => { };
|
||||||
public Action<string> OnConnectFail { get; set; } = (machineName) => { };
|
public Action<string> OnConnectFail { get; set; } = (machineName) => { };
|
||||||
|
|
||||||
|
|
||||||
@@ -26,26 +27,25 @@ namespace cmonitor.plugins.tunnel.transport
|
|||||||
{
|
{
|
||||||
this.tunnelBindServer = tunnelBindServer;
|
this.tunnelBindServer = tunnelBindServer;
|
||||||
tunnelBindServer.OnTcpConnected += OnTcpConnected;
|
tunnelBindServer.OnTcpConnected += OnTcpConnected;
|
||||||
tunnelBindServer.OnDisConnected += OnTcpDisConnected;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<TunnelTransportState> ConnectAsync(TunnelTransportInfo tunnelTransportInfo)
|
public async Task<ITunnelConnection> ConnectAsync(TunnelTransportInfo tunnelTransportInfo)
|
||||||
{
|
{
|
||||||
OnConnecting(tunnelTransportInfo);
|
OnConnecting(tunnelTransportInfo);
|
||||||
|
|
||||||
//正向连接
|
//正向连接
|
||||||
tunnelTransportInfo.Direction = TunnelTransportDirection.Forward;
|
tunnelTransportInfo.Direction = TunnelDirection.Forward;
|
||||||
if (await OnSendConnectBegin(tunnelTransportInfo) == false)
|
if (await OnSendConnectBegin(tunnelTransportInfo) == false)
|
||||||
{
|
{
|
||||||
OnConnectFail(tunnelTransportInfo.Remote.MachineName);
|
OnConnectFail(tunnelTransportInfo.Remote.MachineName);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
TunnelTransportState state = await ConnectForward(tunnelTransportInfo);
|
ITunnelConnection connection = await ConnectForward(tunnelTransportInfo);
|
||||||
if (state != null) return state;
|
if (connection != null) return connection;
|
||||||
|
|
||||||
//反向连接
|
//反向连接
|
||||||
TunnelTransportInfo tunnelTransportInfo1 = tunnelTransportInfo.ToJsonFormat().DeJson<TunnelTransportInfo>();
|
TunnelTransportInfo tunnelTransportInfo1 = tunnelTransportInfo.ToJsonFormat().DeJson<TunnelTransportInfo>();
|
||||||
tunnelTransportInfo1.Direction = TunnelTransportDirection.Reverse;
|
tunnelTransportInfo1.Direction = TunnelDirection.Reverse;
|
||||||
tunnelBindServer.Bind(tunnelTransportInfo1.Local.Local, tunnelTransportInfo1);
|
tunnelBindServer.Bind(tunnelTransportInfo1.Local.Local, tunnelTransportInfo1);
|
||||||
BindAndTTL(tunnelTransportInfo1);
|
BindAndTTL(tunnelTransportInfo1);
|
||||||
if (await OnSendConnectBegin(tunnelTransportInfo1) == false)
|
if (await OnSendConnectBegin(tunnelTransportInfo1) == false)
|
||||||
@@ -53,8 +53,8 @@ namespace cmonitor.plugins.tunnel.transport
|
|||||||
OnConnectFail(tunnelTransportInfo.Remote.MachineName);
|
OnConnectFail(tunnelTransportInfo.Remote.MachineName);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
state = await WaitReverse(tunnelTransportInfo1);
|
connection = await WaitReverse(tunnelTransportInfo1);
|
||||||
if (state != null) return state;
|
if (connection != null) return connection;
|
||||||
|
|
||||||
//正向反向都失败
|
//正向反向都失败
|
||||||
await OnSendConnectFail(tunnelTransportInfo);
|
await OnSendConnectFail(tunnelTransportInfo);
|
||||||
@@ -65,22 +65,22 @@ namespace cmonitor.plugins.tunnel.transport
|
|||||||
public void OnBegin(TunnelTransportInfo tunnelTransportInfo)
|
public void OnBegin(TunnelTransportInfo tunnelTransportInfo)
|
||||||
{
|
{
|
||||||
OnConnectBegin(tunnelTransportInfo);
|
OnConnectBegin(tunnelTransportInfo);
|
||||||
if (tunnelTransportInfo.Direction == TunnelTransportDirection.Forward)
|
if (tunnelTransportInfo.Direction == TunnelDirection.Forward)
|
||||||
{
|
{
|
||||||
tunnelBindServer.Bind(tunnelTransportInfo.Local.Local, tunnelTransportInfo);
|
tunnelBindServer.Bind(tunnelTransportInfo.Local.Local, tunnelTransportInfo);
|
||||||
}
|
}
|
||||||
Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
if (tunnelTransportInfo.Direction == TunnelTransportDirection.Forward)
|
if (tunnelTransportInfo.Direction == TunnelDirection.Forward)
|
||||||
{
|
{
|
||||||
BindAndTTL(tunnelTransportInfo);
|
BindAndTTL(tunnelTransportInfo);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TunnelTransportState state = await ConnectForward(tunnelTransportInfo);
|
ITunnelConnection connection = await ConnectForward(tunnelTransportInfo);
|
||||||
if (state != null)
|
if (connection != null)
|
||||||
{
|
{
|
||||||
OnConnected(state);
|
OnConnected(connection);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -96,7 +96,7 @@ namespace cmonitor.plugins.tunnel.transport
|
|||||||
tunnelBindServer.RemoveBind(tunnelTransportInfo.Local.Local.Port);
|
tunnelBindServer.RemoveBind(tunnelTransportInfo.Local.Local.Port);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<TunnelTransportState> ConnectForward(TunnelTransportInfo tunnelTransportInfo)
|
private async Task<ITunnelConnection> ConnectForward(TunnelTransportInfo tunnelTransportInfo)
|
||||||
{
|
{
|
||||||
await Task.Delay(20);
|
await Task.Delay(20);
|
||||||
//要连接哪些IP
|
//要连接哪些IP
|
||||||
@@ -109,7 +109,7 @@ namespace cmonitor.plugins.tunnel.transport
|
|||||||
};
|
};
|
||||||
foreach (IPEndPoint ep in eps)
|
foreach (IPEndPoint ep in eps)
|
||||||
{
|
{
|
||||||
Socket targetSocket = new(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
Socket targetSocket = new(ep.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
|
||||||
targetSocket.IPv6Only(ep.Address.AddressFamily, false);
|
targetSocket.IPv6Only(ep.Address.AddressFamily, false);
|
||||||
targetSocket.ReuseBind(new IPEndPoint(ep.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, tunnelTransportInfo.Local.Local.Port));
|
targetSocket.ReuseBind(new IPEndPoint(ep.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, tunnelTransportInfo.Local.Local.Port));
|
||||||
IAsyncResult result = targetSocket.BeginConnect(ep, null, null);
|
IAsyncResult result = targetSocket.BeginConnect(ep, null, null);
|
||||||
@@ -133,13 +133,16 @@ namespace cmonitor.plugins.tunnel.transport
|
|||||||
}
|
}
|
||||||
|
|
||||||
targetSocket.EndConnect(result);
|
targetSocket.EndConnect(result);
|
||||||
return new TunnelTransportState
|
return new TunnelConnectionTcp
|
||||||
{
|
{
|
||||||
ConnectedObject = targetSocket,
|
Socket = targetSocket,
|
||||||
TransactionId = tunnelTransportInfo.TransactionId,
|
TransactionId = tunnelTransportInfo.TransactionId,
|
||||||
RemoteMachineName = tunnelTransportInfo.Remote.MachineName,
|
RemoteMachineName = tunnelTransportInfo.Remote.MachineName,
|
||||||
TransportName = Name,
|
TransportName = Name,
|
||||||
TransportType = Type
|
Direction = tunnelTransportInfo.Direction,
|
||||||
|
ProtocolType = ProtocolType,
|
||||||
|
Type = TunnelType.P2P,
|
||||||
|
Label = string.Empty
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -167,7 +170,7 @@ namespace cmonitor.plugins.tunnel.transport
|
|||||||
//过滤掉不支持IPV6的情况
|
//过滤掉不支持IPV6的情况
|
||||||
IEnumerable<Socket> sockets = eps.Where(c => NotIPv6Support(c.Address) == false).Select(ip =>
|
IEnumerable<Socket> sockets = eps.Where(c => NotIPv6Support(c.Address) == false).Select(ip =>
|
||||||
{
|
{
|
||||||
Socket targetSocket = new(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
Socket targetSocket = new(ip.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
targetSocket.IPv6Only(ip.Address.AddressFamily, false);
|
targetSocket.IPv6Only(ip.Address.AddressFamily, false);
|
||||||
@@ -188,16 +191,16 @@ namespace cmonitor.plugins.tunnel.transport
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private ConcurrentDictionary<string, TaskCompletionSource<TunnelTransportState>> reverseDic = new ConcurrentDictionary<string, TaskCompletionSource<TunnelTransportState>>();
|
private ConcurrentDictionary<string, TaskCompletionSource<ITunnelConnection>> reverseDic = new ConcurrentDictionary<string, TaskCompletionSource<ITunnelConnection>>();
|
||||||
private async Task<TunnelTransportState> WaitReverse(TunnelTransportInfo tunnelTransportInfo)
|
private async Task<ITunnelConnection> WaitReverse(TunnelTransportInfo tunnelTransportInfo)
|
||||||
{
|
{
|
||||||
TaskCompletionSource<TunnelTransportState> tcs = new TaskCompletionSource<TunnelTransportState>();
|
TaskCompletionSource<ITunnelConnection> tcs = new TaskCompletionSource<ITunnelConnection>();
|
||||||
reverseDic.TryAdd(tunnelTransportInfo.Remote.MachineName, tcs);
|
reverseDic.TryAdd(tunnelTransportInfo.Remote.MachineName, tcs);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
TunnelTransportState state = await tcs.Task.WaitAsync(TimeSpan.FromMilliseconds(3000));
|
ITunnelConnection connection = await tcs.Task.WaitAsync(TimeSpan.FromMilliseconds(3000));
|
||||||
return state;
|
return connection;
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
@@ -214,15 +217,18 @@ namespace cmonitor.plugins.tunnel.transport
|
|||||||
{
|
{
|
||||||
if (state is TunnelTransportInfo _state && _state.TransportName == Name)
|
if (state is TunnelTransportInfo _state && _state.TransportName == Name)
|
||||||
{
|
{
|
||||||
TunnelTransportState result = new TunnelTransportState
|
TunnelConnectionTcp result = new TunnelConnectionTcp
|
||||||
{
|
{
|
||||||
RemoteMachineName = _state.Remote.MachineName,
|
RemoteMachineName = _state.Remote.MachineName,
|
||||||
TransportType = ProtocolType.Tcp,
|
Direction = _state.Direction,
|
||||||
ConnectedObject = socket,
|
ProtocolType = TunnelProtocolType.Tcp,
|
||||||
|
Socket = socket,
|
||||||
|
Type = TunnelType.P2P,
|
||||||
TransactionId = _state.TransactionId,
|
TransactionId = _state.TransactionId,
|
||||||
TransportName = _state.TransportName,
|
TransportName = _state.TransportName,
|
||||||
|
Label = string.Empty,
|
||||||
};
|
};
|
||||||
if (reverseDic.TryRemove(_state.Remote.MachineName, out TaskCompletionSource<TunnelTransportState> tcs))
|
if (reverseDic.TryRemove(_state.Remote.MachineName, out TaskCompletionSource<ITunnelConnection> tcs))
|
||||||
{
|
{
|
||||||
tcs.SetResult(result);
|
tcs.SetResult(result);
|
||||||
return;
|
return;
|
||||||
@@ -231,20 +237,6 @@ namespace cmonitor.plugins.tunnel.transport
|
|||||||
OnConnected(result);
|
OnConnected(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void OnTcpDisConnected(object state)
|
|
||||||
{
|
|
||||||
if (state is TunnelTransportInfo _state && _state.TransportName == Name)
|
|
||||||
{
|
|
||||||
TunnelTransportState result = new TunnelTransportState
|
|
||||||
{
|
|
||||||
RemoteMachineName = _state.Remote.MachineName,
|
|
||||||
TransportType = ProtocolType.Tcp,
|
|
||||||
TransactionId = _state.TransactionId,
|
|
||||||
TransportName = _state.TransportName,
|
|
||||||
};
|
|
||||||
OnDisConnected(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool NotIPv6Support(IPAddress ip)
|
private bool NotIPv6Support(IPAddress ip)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using common.libs;
|
using cmonitor.client.tunnel;
|
||||||
|
using common.libs;
|
||||||
using common.libs.extends;
|
using common.libs.extends;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
@@ -9,10 +10,11 @@ namespace cmonitor.plugins.viewer.proxy
|
|||||||
{
|
{
|
||||||
public class ViewerProxy
|
public class ViewerProxy
|
||||||
{
|
{
|
||||||
private SocketAsyncEventArgs acceptEventArg;
|
private AsyncUserToken userToken;
|
||||||
private Socket socket;
|
private Socket socket;
|
||||||
private UdpClient udpClient;
|
private UdpClient udpClient;
|
||||||
private NumberSpace ns = new NumberSpace();
|
private readonly NumberSpace ns = new NumberSpace();
|
||||||
|
private readonly ConcurrentDictionary<ConnectId, Socket> dic = new ConcurrentDictionary<ConnectId, Socket>();
|
||||||
|
|
||||||
public IPEndPoint LocalEndpoint => socket?.LocalEndPoint as IPEndPoint ?? new IPEndPoint(IPAddress.Any, 0);
|
public IPEndPoint LocalEndpoint => socket?.LocalEndPoint as IPEndPoint ?? new IPEndPoint(IPAddress.Any, 0);
|
||||||
|
|
||||||
@@ -32,14 +34,16 @@ namespace cmonitor.plugins.viewer.proxy
|
|||||||
socket.ReuseBind(localEndPoint);
|
socket.ReuseBind(localEndPoint);
|
||||||
socket.Listen(int.MaxValue);
|
socket.Listen(int.MaxValue);
|
||||||
|
|
||||||
acceptEventArg = new SocketAsyncEventArgs
|
userToken = new AsyncUserToken
|
||||||
{
|
{
|
||||||
UserToken = new AsyncUserToken
|
Socket = socket
|
||||||
|
};
|
||||||
|
SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs
|
||||||
{
|
{
|
||||||
SourceSocket = socket
|
UserToken = userToken,
|
||||||
},
|
|
||||||
SocketFlags = SocketFlags.None,
|
SocketFlags = SocketFlags.None,
|
||||||
};
|
};
|
||||||
|
userToken.Saea = acceptEventArg;
|
||||||
|
|
||||||
acceptEventArg.Completed += IO_Completed;
|
acceptEventArg.Completed += IO_Completed;
|
||||||
StartAccept(acceptEventArg);
|
StartAccept(acceptEventArg);
|
||||||
@@ -56,11 +60,11 @@ namespace cmonitor.plugins.viewer.proxy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private readonly AsyncUserUdpToken asyncUserUdpToken = new AsyncUserUdpToken
|
private readonly AsyncUserUdpToken asyncUserUdpToken = new AsyncUserUdpToken
|
||||||
{
|
{
|
||||||
Proxy = new ProxyInfo { Step = ProxyStep.Forward, Direction = ProxyDirection.UnPack, ConnectId = 0 }
|
Proxy = new ProxyInfo { Step = ProxyStep.Forward, ConnectId = 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
private async void ReceiveCallbackUdp(IAsyncResult result)
|
private async void ReceiveCallbackUdp(IAsyncResult result)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -83,15 +87,13 @@ namespace cmonitor.plugins.viewer.proxy
|
|||||||
await Task.CompletedTask;
|
await Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void StartAccept(SocketAsyncEventArgs acceptEventArg)
|
private void StartAccept(SocketAsyncEventArgs acceptEventArg)
|
||||||
{
|
{
|
||||||
acceptEventArg.AcceptSocket = null;
|
acceptEventArg.AcceptSocket = null;
|
||||||
AsyncUserToken token = (AsyncUserToken)acceptEventArg.UserToken;
|
AsyncUserToken token = (AsyncUserToken)acceptEventArg.UserToken;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (token.SourceSocket.AcceptAsync(acceptEventArg) == false)
|
if (token.Socket.AcceptAsync(acceptEventArg) == false)
|
||||||
{
|
{
|
||||||
ProcessAccept(acceptEventArg);
|
ProcessAccept(acceptEventArg);
|
||||||
}
|
}
|
||||||
@@ -138,7 +140,7 @@ namespace cmonitor.plugins.viewer.proxy
|
|||||||
socket.KeepAlive();
|
socket.KeepAlive();
|
||||||
AsyncUserToken userToken = new AsyncUserToken
|
AsyncUserToken userToken = new AsyncUserToken
|
||||||
{
|
{
|
||||||
SourceSocket = socket,
|
Socket = socket,
|
||||||
Proxy = new ProxyInfo { Data = Helper.EmptyArray, Step = ProxyStep.Request, ConnectId = ns.Increment() }
|
Proxy = new ProxyInfo { Data = Helper.EmptyArray, Step = ProxyStep.Request, ConnectId = ns.Increment() }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -147,6 +149,8 @@ namespace cmonitor.plugins.viewer.proxy
|
|||||||
UserToken = userToken,
|
UserToken = userToken,
|
||||||
SocketFlags = SocketFlags.None,
|
SocketFlags = SocketFlags.None,
|
||||||
};
|
};
|
||||||
|
userToken.Saea = readEventArgs;
|
||||||
|
|
||||||
readEventArgs.SetBuffer(new byte[8 * 1024], 0, 8 * 1024);
|
readEventArgs.SetBuffer(new byte[8 * 1024], 0, 8 * 1024);
|
||||||
readEventArgs.Completed += IO_Completed;
|
readEventArgs.Completed += IO_Completed;
|
||||||
if (socket.ReceiveAsync(readEventArgs) == false)
|
if (socket.ReceiveAsync(readEventArgs) == false)
|
||||||
@@ -162,46 +166,45 @@ namespace cmonitor.plugins.viewer.proxy
|
|||||||
}
|
}
|
||||||
private async void ProcessReceive(SocketAsyncEventArgs e)
|
private async void ProcessReceive(SocketAsyncEventArgs e)
|
||||||
{
|
{
|
||||||
|
AsyncUserToken token = (AsyncUserToken)e.UserToken;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
AsyncUserToken token = (AsyncUserToken)e.UserToken;
|
|
||||||
|
|
||||||
if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
|
if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
|
||||||
{
|
{
|
||||||
int offset = e.Offset;
|
int offset = e.Offset;
|
||||||
int length = e.BytesTransferred;
|
int length = e.BytesTransferred;
|
||||||
await ReadPacket(e, token, e.Buffer.AsMemory(offset, length));
|
await ReadPacket(token, e.Buffer.AsMemory(offset, length));
|
||||||
if (token.SourceSocket.Available > 0)
|
if (token.Socket.Available > 0)
|
||||||
{
|
{
|
||||||
while (token.SourceSocket.Available > 0)
|
while (token.Socket.Available > 0)
|
||||||
{
|
{
|
||||||
length = token.SourceSocket.Receive(e.Buffer);
|
length = token.Socket.Receive(e.Buffer);
|
||||||
if (length > 0)
|
if (length > 0)
|
||||||
{
|
{
|
||||||
await ReadPacket(e, token, e.Buffer.AsMemory(0, length));
|
await ReadPacket(token, e.Buffer.AsMemory(0, length));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CloseClientSocket(e);
|
CloseClientSocket(token);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token.SourceSocket.Connected == false)
|
if (token.Socket.Connected == false)
|
||||||
{
|
{
|
||||||
CloseClientSocket(e);
|
CloseClientSocket(token);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token.SourceSocket.ReceiveAsync(e) == false)
|
if (token.Socket.ReceiveAsync(e) == false)
|
||||||
{
|
{
|
||||||
ProcessReceive(e);
|
ProcessReceive(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CloseClientSocket(e);
|
CloseClientSocket(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -209,55 +212,38 @@ namespace cmonitor.plugins.viewer.proxy
|
|||||||
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||||
Logger.Instance.Error(ex);
|
Logger.Instance.Error(ex);
|
||||||
|
|
||||||
CloseClientSocket(e);
|
CloseClientSocket(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private async Task ReadPacket(AsyncUserToken token, Memory<byte> data)
|
||||||
private async Task ReadPacket(SocketAsyncEventArgs e, AsyncUserToken token, Memory<byte> data)
|
|
||||||
{
|
{
|
||||||
if (token.Proxy.Step == ProxyStep.Request)
|
if (token.Proxy.Step == ProxyStep.Request)
|
||||||
{
|
{
|
||||||
await Connect(token);
|
await Connect(token);
|
||||||
if (token.TargetSocket != null)
|
if (token.Connection != null)
|
||||||
{
|
{
|
||||||
//发送连接请求包
|
//发送连接请求包
|
||||||
await SendToTarget(e, token).ConfigureAwait(false);
|
await SendToConnection(token).ConfigureAwait(false);
|
||||||
|
|
||||||
token.Proxy.Step = ProxyStep.Forward;
|
token.Proxy.Step = ProxyStep.Forward;
|
||||||
token.Proxy.TargetEP = null;
|
token.Proxy.TargetEP = null;
|
||||||
|
|
||||||
//发送后续数据包
|
//发送后续数据包
|
||||||
token.Proxy.Data = data;
|
token.Proxy.Data = data;
|
||||||
await SendToTarget(e, token).ConfigureAwait(false);
|
await SendToConnection(token).ConfigureAwait(false);
|
||||||
|
|
||||||
//绑定
|
//绑定
|
||||||
dic.TryAdd(new ConnectId(token.Proxy.ConnectId, token.TargetSocket.GetHashCode()), token.SourceSocket);
|
dic.TryAdd(new ConnectId(token.Proxy.ConnectId, token.Connection.GetHashCode()), token.Socket);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CloseClientSocket(e);
|
CloseClientSocket(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
token.Proxy.Data = data;
|
token.Proxy.Data = data;
|
||||||
await SendToTarget(e, token).ConfigureAwait(false);
|
await SendToConnection(token).ConfigureAwait(false);
|
||||||
}
|
|
||||||
}
|
|
||||||
private async Task SendToTarget(SocketAsyncEventArgs e, AsyncUserToken token)
|
|
||||||
{
|
|
||||||
byte[] connectData = token.Proxy.ToBytes(out int length);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await token.TargetSocket.SendAsync(connectData.AsMemory(0, length), SocketFlags.None);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
CloseClientSocket(e);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
token.Proxy.Return(connectData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,26 +252,115 @@ namespace cmonitor.plugins.viewer.proxy
|
|||||||
await Task.CompletedTask;
|
await Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected bool BindReceiveTarget(Socket targetSocket, Socket sourceSocket)
|
private async Task SendToConnection(AsyncUserToken token)
|
||||||
|
{
|
||||||
|
byte[] connectData = token.Proxy.ToBytes(out int length);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await token.Connection.SendAsync(connectData.AsMemory(0, length)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
CloseClientSocket(token);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
token.Proxy.Return(connectData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void BindConnectionReceive(ITunnelConnection connection)
|
||||||
|
{
|
||||||
|
connection.BeginReceive(InputConnectionData, CloseConnection, new AsyncUserToken
|
||||||
|
{
|
||||||
|
Connection = connection,
|
||||||
|
Buffer = new ReceiveDataBuffer(),
|
||||||
|
Proxy = new ProxyInfo { }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
protected async Task InputConnectionData(ITunnelConnection connection, Memory<byte> memory, object userToken)
|
||||||
|
{
|
||||||
|
AsyncUserToken token = userToken as AsyncUserToken;
|
||||||
|
//是一个完整的包
|
||||||
|
if (token.Buffer.Size == 0 && memory.Length > 4)
|
||||||
|
{
|
||||||
|
int packageLen = memory.ToInt32();
|
||||||
|
if (packageLen == memory.Length - 4)
|
||||||
|
{
|
||||||
|
token.Proxy.DeBytes(memory.Slice(0, packageLen + 4));
|
||||||
|
await ReadConnectionPack(token).ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//不是完整包
|
||||||
|
token.Buffer.AddRange(memory);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int packageLen = token.Buffer.Data.ToInt32();
|
||||||
|
if (packageLen > token.Buffer.Size - 4)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
token.Proxy.DeBytes(token.Buffer.Data.Slice(0, packageLen + 4));
|
||||||
|
await ReadConnectionPack(token).ConfigureAwait(false);
|
||||||
|
|
||||||
|
token.Buffer.RemoveRange(0, packageLen + 4);
|
||||||
|
} while (token.Buffer.Size > 4);
|
||||||
|
}
|
||||||
|
protected async Task CloseConnection(ITunnelConnection connection, object userToken)
|
||||||
|
{
|
||||||
|
CloseClientSocket(userToken as AsyncUserToken);
|
||||||
|
await Task.CompletedTask;
|
||||||
|
}
|
||||||
|
private async Task ReadConnectionPack(AsyncUserToken token)
|
||||||
|
{
|
||||||
|
if (token.Proxy.Step == ProxyStep.Request)
|
||||||
|
{
|
||||||
|
await ConnectBind(token).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await SendToSocket(token).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private async Task ConnectBind(AsyncUserToken token)
|
||||||
|
{
|
||||||
|
Socket socket = new Socket(token.Proxy.TargetEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||||
|
socket.KeepAlive();
|
||||||
|
await socket.ConnectAsync(token.Proxy.TargetEP);
|
||||||
|
|
||||||
|
dic.TryAdd(new ConnectId(token.Proxy.ConnectId, token.Connection.GetHashCode()), socket);
|
||||||
|
|
||||||
|
BindReceiveTarget(new AsyncUserToken
|
||||||
|
{
|
||||||
|
Connection = token.Connection,
|
||||||
|
Socket = socket,
|
||||||
|
Proxy = new ProxyInfo
|
||||||
|
{
|
||||||
|
ConnectId = token.Proxy.ConnectId,
|
||||||
|
Step = ProxyStep.Forward
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
private async Task SendToSocket(AsyncUserToken token)
|
||||||
|
{
|
||||||
|
ConnectId connectId = new ConnectId(token.Proxy.ConnectId, token.Connection.GetHashCode());
|
||||||
|
if (dic.TryGetValue(connectId, out Socket source))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
BindReceiveTarget(new AsyncUserToken
|
await source.SendAsync(token.Proxy.Data);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
{
|
{
|
||||||
TargetSocket = targetSocket,
|
CloseClientSocket(token);
|
||||||
SourceSocket = sourceSocket,
|
|
||||||
Buffer = new ReceiveDataBuffer(),
|
|
||||||
Proxy = new ProxyInfo { Direction = ProxyDirection.UnPack }
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.Instance.Error(ex);
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void IO_CompletedTarget(object sender, SocketAsyncEventArgs e)
|
private void IO_CompletedTarget(object sender, SocketAsyncEventArgs e)
|
||||||
{
|
{
|
||||||
switch (e.LastOperation)
|
switch (e.LastOperation)
|
||||||
@@ -308,7 +383,7 @@ namespace cmonitor.plugins.viewer.proxy
|
|||||||
};
|
};
|
||||||
readEventArgs.SetBuffer(new byte[8 * 1024], 0, 8 * 1024);
|
readEventArgs.SetBuffer(new byte[8 * 1024], 0, 8 * 1024);
|
||||||
readEventArgs.Completed += IO_CompletedTarget;
|
readEventArgs.Completed += IO_CompletedTarget;
|
||||||
if (userToken.TargetSocket.ReceiveAsync(readEventArgs) == false)
|
if (userToken.Socket.ReceiveAsync(readEventArgs) == false)
|
||||||
{
|
{
|
||||||
ProcessReceiveTarget(readEventArgs);
|
ProcessReceiveTarget(readEventArgs);
|
||||||
}
|
}
|
||||||
@@ -321,48 +396,49 @@ namespace cmonitor.plugins.viewer.proxy
|
|||||||
}
|
}
|
||||||
private async void ProcessReceiveTarget(SocketAsyncEventArgs e)
|
private async void ProcessReceiveTarget(SocketAsyncEventArgs e)
|
||||||
{
|
{
|
||||||
|
AsyncUserToken token = (AsyncUserToken)e.UserToken;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
AsyncUserToken token = (AsyncUserToken)e.UserToken;
|
|
||||||
|
|
||||||
if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
|
if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
|
||||||
{
|
{
|
||||||
int offset = e.Offset;
|
int offset = e.Offset;
|
||||||
int length = e.BytesTransferred;
|
int length = e.BytesTransferred;
|
||||||
|
|
||||||
await ReadPacketTarget(e, token, e.Buffer.AsMemory(offset, length)).ConfigureAwait(false);
|
token.Proxy.Data = e.Buffer.AsMemory(offset, length);
|
||||||
|
await SendToConnection(token).ConfigureAwait(false);
|
||||||
|
|
||||||
if (token.TargetSocket.Available > 0)
|
if (token.Socket.Available > 0)
|
||||||
{
|
{
|
||||||
while (token.TargetSocket.Available > 0)
|
while (token.Socket.Available > 0)
|
||||||
{
|
{
|
||||||
length = token.TargetSocket.Receive(e.Buffer);
|
length = token.Socket.Receive(e.Buffer);
|
||||||
if (length > 0)
|
if (length > 0)
|
||||||
{
|
{
|
||||||
await ReadPacketTarget(e, token, e.Buffer.AsMemory(0, length)).ConfigureAwait(false);
|
token.Proxy.Data = e.Buffer.AsMemory(0, length);
|
||||||
|
await SendToConnection(token).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CloseClientSocket(e);
|
CloseClientSocket(token);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token.TargetSocket.Connected == false)
|
if (token.Connection.Connected == false)
|
||||||
{
|
{
|
||||||
CloseClientSocket(e);
|
CloseClientSocket(token);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token.TargetSocket.ReceiveAsync(e) == false)
|
if (token.Socket.ReceiveAsync(e) == false)
|
||||||
{
|
{
|
||||||
ProcessReceiveTarget(e);
|
ProcessReceiveTarget(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CloseClientSocket(e);
|
CloseClientSocket(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -370,126 +446,19 @@ namespace cmonitor.plugins.viewer.proxy
|
|||||||
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||||
Logger.Instance.Error(ex);
|
Logger.Instance.Error(ex);
|
||||||
|
|
||||||
CloseClientSocket(e);
|
CloseClientSocket(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<ConnectId, Socket> dic = new ConcurrentDictionary<ConnectId, Socket>();
|
|
||||||
private async Task ReadPacketTarget(SocketAsyncEventArgs e, AsyncUserToken token, Memory<byte> data)
|
|
||||||
{
|
|
||||||
//A 到 B
|
|
||||||
if (token.Proxy.Direction == ProxyDirection.UnPack)
|
|
||||||
{
|
|
||||||
//是一个完整的包
|
|
||||||
if (token.Buffer.Size == 0 && data.Length > 4)
|
|
||||||
{
|
|
||||||
int packageLen = data.ToInt32();
|
|
||||||
if (packageLen == data.Length - 4)
|
|
||||||
{
|
|
||||||
token.Proxy.DeBytes(data.Slice(0, packageLen + 4));
|
|
||||||
await ReadPacketTarget(e, token).ConfigureAwait(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//不是完整包
|
private void CloseClientSocket(AsyncUserToken token)
|
||||||
token.Buffer.AddRange(data);
|
|
||||||
do
|
|
||||||
{
|
{
|
||||||
int packageLen = token.Buffer.Data.ToInt32();
|
if (token.Connection != null)
|
||||||
if (packageLen > token.Buffer.Size - 4)
|
|
||||||
{
|
{
|
||||||
break;
|
int code = token.Connection.GetHashCode();
|
||||||
}
|
if (token.Connection.Connected == false)
|
||||||
token.Proxy.DeBytes(token.Buffer.Data.Slice(0, packageLen + 4));
|
|
||||||
await ReadPacketTarget(e, token).ConfigureAwait(false);
|
|
||||||
|
|
||||||
token.Buffer.RemoveRange(0, packageLen + 4);
|
|
||||||
} while (token.Buffer.Size > 4);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
token.Proxy.Data = data;
|
foreach (ConnectId item in dic.Keys.Where(c => c.hashCode == code).ToList())
|
||||||
await SendToSource(e, token).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private async Task ReadPacketTarget(SocketAsyncEventArgs e, AsyncUserToken token)
|
|
||||||
{
|
|
||||||
if (token.Proxy.Step == ProxyStep.Request)
|
|
||||||
{
|
|
||||||
await ConnectBind(e, token).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await SendToSource(e, token).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private async Task ConnectBind(SocketAsyncEventArgs e, AsyncUserToken token)
|
|
||||||
{
|
|
||||||
Socket socket = new Socket(token.Proxy.TargetEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
|
||||||
socket.KeepAlive();
|
|
||||||
await socket.ConnectAsync(token.Proxy.TargetEP);
|
|
||||||
|
|
||||||
dic.TryAdd(new ConnectId(token.Proxy.ConnectId, token.TargetSocket.GetHashCode()), socket);
|
|
||||||
|
|
||||||
BindReceiveTarget(new AsyncUserToken
|
|
||||||
{
|
|
||||||
TargetSocket = socket,
|
|
||||||
SourceSocket = token.TargetSocket,
|
|
||||||
Proxy = new ProxyInfo
|
|
||||||
{
|
|
||||||
Direction = ProxyDirection.Pack,
|
|
||||||
ConnectId = token.Proxy.ConnectId,
|
|
||||||
Step = ProxyStep.Forward
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
private async Task SendToSource(SocketAsyncEventArgs e, AsyncUserToken token)
|
|
||||||
{
|
|
||||||
if (token.Proxy.Direction == ProxyDirection.UnPack)
|
|
||||||
{
|
|
||||||
ConnectId connectId = new ConnectId(token.Proxy.ConnectId, token.TargetSocket.GetHashCode());
|
|
||||||
if (dic.TryGetValue(connectId, out Socket source))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await source.SendAsync(token.Proxy.Data);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
CloseClientSocket(e);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
byte[] connectData = token.Proxy.ToBytes(out int length);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await token.SourceSocket.SendAsync(connectData.AsMemory(0, length), SocketFlags.None);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
CloseClientSocket(e);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
token.Proxy.Return(connectData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CloseClientSocket(SocketAsyncEventArgs e)
|
|
||||||
{
|
|
||||||
if (e == null) return;
|
|
||||||
AsyncUserToken token = e.UserToken as AsyncUserToken;
|
|
||||||
if (token.TargetSocket != null)
|
|
||||||
{
|
|
||||||
int code = token.TargetSocket.GetHashCode();
|
|
||||||
if (token.TargetSocket.Connected == false)
|
|
||||||
{
|
|
||||||
foreach (ConnectId item in dic.Keys.Where(c => c.socket == code).ToList())
|
|
||||||
{
|
{
|
||||||
dic.TryRemove(item, out _);
|
dic.TryRemove(item, out _);
|
||||||
}
|
}
|
||||||
@@ -499,28 +468,36 @@ namespace cmonitor.plugins.viewer.proxy
|
|||||||
dic.TryRemove(new ConnectId(token.Proxy.ConnectId, code), out _);
|
dic.TryRemove(new ConnectId(token.Proxy.ConnectId, code), out _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (token.SourceSocket != null)
|
|
||||||
{
|
|
||||||
token.Clear();
|
token.Clear();
|
||||||
e.Dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
public void Stop()
|
public void Stop()
|
||||||
{
|
{
|
||||||
CloseClientSocket(acceptEventArg);
|
CloseClientSocket(userToken);
|
||||||
udpClient?.Close();
|
udpClient?.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum ProxyStep : byte
|
||||||
|
{
|
||||||
|
Request = 1,
|
||||||
|
Forward = 2
|
||||||
|
}
|
||||||
|
public record struct ConnectId
|
||||||
|
{
|
||||||
|
public ulong connectId;
|
||||||
|
public int hashCode;
|
||||||
|
|
||||||
|
public ConnectId(ulong connectId, int hashCode)
|
||||||
|
{
|
||||||
|
this.connectId = connectId;
|
||||||
|
this.hashCode = hashCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
public sealed class ProxyInfo
|
public sealed class ProxyInfo
|
||||||
{
|
{
|
||||||
public ulong ConnectId { get; set; }
|
public ulong ConnectId { get; set; }
|
||||||
|
|
||||||
public ProxyStep Step { get; set; } = ProxyStep.Request;
|
public ProxyStep Step { get; set; } = ProxyStep.Request;
|
||||||
|
|
||||||
public ProxyDirection Direction { get; set; } = ProxyDirection.Pack;
|
|
||||||
|
|
||||||
public IPEndPoint TargetEP { get; set; }
|
public IPEndPoint TargetEP { get; set; }
|
||||||
|
|
||||||
public Memory<byte> Data { get; set; }
|
public Memory<byte> Data { get; set; }
|
||||||
@@ -595,7 +572,6 @@ namespace cmonitor.plugins.viewer.proxy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public sealed class AsyncUserUdpToken
|
public sealed class AsyncUserUdpToken
|
||||||
{
|
{
|
||||||
public UdpClient SourceSocket { get; set; }
|
public UdpClient SourceSocket { get; set; }
|
||||||
@@ -606,53 +582,31 @@ namespace cmonitor.plugins.viewer.proxy
|
|||||||
{
|
{
|
||||||
SourceSocket?.Close();
|
SourceSocket?.Close();
|
||||||
SourceSocket = null;
|
SourceSocket = null;
|
||||||
|
|
||||||
GC.Collect();
|
GC.Collect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public sealed class AsyncUserToken
|
public sealed class AsyncUserToken
|
||||||
{
|
{
|
||||||
public Socket SourceSocket { get; set; }
|
public Socket Socket { get; set; }
|
||||||
public Socket TargetSocket { get; set; }
|
public ITunnelConnection Connection { get; set; }
|
||||||
|
|
||||||
public ProxyInfo Proxy { get; set; }
|
public ProxyInfo Proxy { get; set; }
|
||||||
|
|
||||||
public ReceiveDataBuffer Buffer { get; set; }
|
public ReceiveDataBuffer Buffer { get; set; }
|
||||||
|
|
||||||
|
public SocketAsyncEventArgs Saea { get; set; }
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
SourceSocket?.SafeClose();
|
Socket?.SafeClose();
|
||||||
SourceSocket = null;
|
Socket = null;
|
||||||
|
|
||||||
Buffer?.Clear();
|
Buffer?.Clear();
|
||||||
|
|
||||||
|
Saea?.Dispose();
|
||||||
|
|
||||||
GC.Collect();
|
GC.Collect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ProxyStep : byte
|
|
||||||
{
|
|
||||||
Request = 1,
|
|
||||||
Forward = 2
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum ProxyDirection
|
|
||||||
{
|
|
||||||
Pack = 0,
|
|
||||||
UnPack = 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
public record struct ConnectId
|
|
||||||
{
|
|
||||||
public ulong connectId;
|
|
||||||
public int socket;
|
|
||||||
|
|
||||||
public ConnectId(ulong connectId, int socket)
|
|
||||||
{
|
|
||||||
this.connectId = connectId;
|
|
||||||
this.socket = socket;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
using cmonitor.client.running;
|
using cmonitor.client.running;
|
||||||
|
using cmonitor.client.tunnel;
|
||||||
using cmonitor.config;
|
using cmonitor.config;
|
||||||
using cmonitor.plugins.relay;
|
using cmonitor.plugins.relay;
|
||||||
using cmonitor.plugins.relay.transport;
|
|
||||||
using cmonitor.plugins.tunnel;
|
using cmonitor.plugins.tunnel;
|
||||||
using cmonitor.plugins.tunnel.transport;
|
|
||||||
using common.libs;
|
using common.libs;
|
||||||
using System.Net.Sockets;
|
|
||||||
|
|
||||||
namespace cmonitor.plugins.viewer.proxy
|
namespace cmonitor.plugins.viewer.proxy
|
||||||
{
|
{
|
||||||
@@ -16,7 +14,7 @@ namespace cmonitor.plugins.viewer.proxy
|
|||||||
private readonly RelayTransfer relayTransfer;
|
private readonly RelayTransfer relayTransfer;
|
||||||
private readonly Config config;
|
private readonly Config config;
|
||||||
|
|
||||||
private Socket tunnelSocket;
|
private ITunnelConnection connection;
|
||||||
|
|
||||||
public ViewerProxyClient(RunningConfig runningConfig, TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, Config config)
|
public ViewerProxyClient(RunningConfig runningConfig, TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, Config config)
|
||||||
{
|
{
|
||||||
@@ -28,55 +26,27 @@ namespace cmonitor.plugins.viewer.proxy
|
|||||||
Start(0);
|
Start(0);
|
||||||
Logger.Instance.Info($"start viewer proxy, port : {LocalEndpoint.Port}");
|
Logger.Instance.Info($"start viewer proxy, port : {LocalEndpoint.Port}");
|
||||||
|
|
||||||
Tunnel();
|
tunnelTransfer.SetConnectCallback("viewer", BindConnectionReceive);
|
||||||
|
relayTransfer.SetConnectCallback("viewer", BindConnectionReceive);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task Connect(AsyncUserToken token)
|
protected override async Task Connect(AsyncUserToken token)
|
||||||
{
|
{
|
||||||
token.Proxy.TargetEP = runningConfig.Data.Viewer.ConnectEP;
|
token.Proxy.TargetEP = runningConfig.Data.Viewer.ConnectEP;
|
||||||
if (tunnelSocket == null || tunnelSocket.Connected == false)
|
token.Connection = connection;
|
||||||
|
if (connection == null || connection.Connected == false)
|
||||||
{
|
{
|
||||||
TunnelTransportState state = await tunnelTransfer.ConnectAsync(runningConfig.Data.Viewer.ServerMachine, "viewer");
|
connection = await tunnelTransfer.ConnectAsync(runningConfig.Data.Viewer.ServerMachine, "viewer");
|
||||||
if (state != null)
|
if (connection == null)
|
||||||
{
|
{
|
||||||
if (state.TransportType == ProtocolType.Tcp)
|
connection = await relayTransfer.ConnectAsync(runningConfig.Data.Viewer.ServerMachine, "viewer", config.Data.Client.Relay.SecretKey);
|
||||||
|
}
|
||||||
|
if (connection != null)
|
||||||
{
|
{
|
||||||
tunnelSocket = state.ConnectedObject as Socket;
|
BindConnectionReceive(connection);
|
||||||
token.TargetSocket = tunnelSocket;
|
token.Connection = connection;
|
||||||
BindReceiveTarget(tunnelSocket, token.SourceSocket);
|
}
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RelayTransportState relayState = await relayTransfer.ConnectAsync(runningConfig.Data.Viewer.ServerMachine, "viewer", config.Data.Client.Relay.SecretKey);
|
|
||||||
if (relayState != null)
|
|
||||||
{
|
|
||||||
tunnelSocket = relayState.Socket;
|
|
||||||
token.TargetSocket = tunnelSocket;
|
|
||||||
BindReceiveTarget(tunnelSocket, token.SourceSocket);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
tunnelSocket = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Tunnel()
|
|
||||||
{
|
|
||||||
tunnelTransfer.OnConnected += (TunnelTransportState state) =>
|
|
||||||
{
|
|
||||||
if (state != null && state.TransportType == ProtocolType.Tcp && state.TransactionId == "viewer" && state.Direction == TunnelTransportDirection.Reverse)
|
|
||||||
{
|
|
||||||
BindReceiveTarget(state.ConnectedObject as Socket, null);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
relayTransfer.OnConnected += (RelayTransportState state) =>
|
|
||||||
{
|
|
||||||
if (state != null && state.Info.TransactionId == "viewer" && state.Direction == RelayTransportDirection.Reverse)
|
|
||||||
{
|
|
||||||
BindReceiveTarget(state.Socket, null);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user