This commit is contained in:
snltty
2024-06-30 15:39:02 +08:00
parent a80ce92f75
commit e2b7cd31cb
48 changed files with 487 additions and 167 deletions

View File

@@ -98,6 +98,12 @@ namespace linker.tunnel.connection
/// 是否SSL
/// </summary>
public bool SSL { get; }
/// <summary>
/// 缓冲区大小
/// </summary>
public byte BufferSize { get; }
/// <summary>
/// 已连接
/// </summary>

View File

@@ -30,6 +30,8 @@ namespace linker.tunnel.connection
public IPEndPoint IPEndPoint { get; init; }
public bool SSL => true;
public byte BufferSize { get; init; } = 3;
public bool Connected => Stream != null && Stream.CanWrite;
public int Delay { get; private set; }
public long SendBytes { get; private set; }
@@ -81,7 +83,7 @@ namespace linker.tunnel.connection
}
private async Task ProcessWrite()
{
byte[] buffer = ArrayPool<byte>.Shared.Rent(16 * 1024);
byte[] buffer = ArrayPool<byte>.Shared.Rent((1 << BufferSize) * 1024);
try
{
while (cancellationTokenSource.IsCancellationRequested == false)

View File

@@ -26,7 +26,7 @@ namespace linker.tunnel.connection
public TunnelDirection Direction { get; init; }
public IPEndPoint IPEndPoint { get; init; }
public bool SSL { get; init; }
public byte BufferSize { get; init; } = 3;
public bool Connected => Socket != null && Environment.TickCount64 - ticks < 15000;
public int Delay { get; private set; }
public long SendBytes { get; private set; }
@@ -73,7 +73,7 @@ namespace linker.tunnel.connection
private async Task ProcessWrite()
{
byte[] buffer = ArrayPool<byte>.Shared.Rent(16 * 1024);
byte[] buffer = ArrayPool<byte>.Shared.Rent((1<<BufferSize) * 1024);
try
{
int length = 0;

View File

@@ -25,6 +25,7 @@ namespace linker.tunnel.connection
public TunnelDirection Direction { get; init; }
public IPEndPoint IPEndPoint { get; init; }
public bool SSL => false;
public byte BufferSize { get; init; } = 3;
public bool Connected => UdpClient != null && Environment.TickCount64 - ticks < 15000;
public int Delay { get; private set; }
@@ -66,7 +67,7 @@ namespace linker.tunnel.connection
}
private async Task ProcessWrite()
{
byte[] buffer = ArrayPool<byte>.Shared.Rent(8 * 1024);
byte[] buffer = ArrayPool<byte>.Shared.Rent((1 << BufferSize) * 1024);
try
{
while (cancellationTokenSource.IsCancellationRequested == false)

View File

@@ -13,17 +13,17 @@ namespace linker.tunnel.proxy
private SemaphoreSlim semaphoreSlimForward = new SemaphoreSlim(10);
private SemaphoreSlim semaphoreSlimReverse = new SemaphoreSlim(10);
public virtual IPAddress UdpBindAdress { get; set;}
public virtual IPAddress UdpBindAdress { get; set; }
public TunnelProxy()
{
TaskUdp();
}
public void Start(IPEndPoint ep)
public void Start(IPEndPoint ep, byte bufferSize)
{
StartTcp(ep);
StartUdp(new IPEndPoint(ep.Address, LocalEndpoint.Port));
StartTcp(ep, bufferSize);
StartUdp(new IPEndPoint(ep.Address, LocalEndpoint.Port), bufferSize);
}
/// <summary>
@@ -97,11 +97,11 @@ namespace linker.tunnel.proxy
break;
}
}
/// <summary>
/// 发送数据到目标服务
/// </summary>
/// <param name="tunnelToken"></param>
/// <returns></returns>
/// <summary>
/// 发送数据到目标服务
/// </summary>
/// <param name="tunnelToken"></param>
/// <returns></returns>
private async Task SendToSocket(AsyncUserTunnelToken tunnelToken)
{
if (tunnelToken.Proxy.Protocol == ProxyProtocol.Tcp)
@@ -132,9 +132,9 @@ namespace linker.tunnel.proxy
{
Request = 1,
Forward = 2,
Receive = 4,
Pause = 8,
Close = 16,
Receive = 3,
Pause = 4,
Close = 5,
}
public enum ProxyProtocol : byte
{
@@ -153,6 +153,7 @@ namespace linker.tunnel.proxy
public ProxyStep Step { get; set; } = ProxyStep.Request;
public ProxyProtocol Protocol { get; set; } = ProxyProtocol.Tcp;
public ProxyDirection Direction { get; set; } = ProxyDirection.Forward;
public byte BufferSize { get; set; } = 3;
public ushort Port { get; set; }
public IPEndPoint SourceEP { get; set; }
@@ -160,6 +161,7 @@ namespace linker.tunnel.proxy
public byte Rsv { get; set; }
public ReadOnlyMemory<byte> Data { get; set; }
public byte[] ToBytes(out int length)
@@ -167,7 +169,7 @@ namespace linker.tunnel.proxy
int sourceLength = SourceEP == null ? 0 : (SourceEP.AddressFamily == AddressFamily.InterNetwork ? 4 : 16) + 2;
int targetLength = TargetEP == null ? 0 : (TargetEP.AddressFamily == AddressFamily.InterNetwork ? 4 : 16) + 2;
length = 4 + 8 + 1 + 1 + 1
length = 4 + 8 + 1 + 1
+ 2
+ 1 + sourceLength
+ 1 + targetLength
@@ -185,13 +187,10 @@ namespace linker.tunnel.proxy
ConnectId.ToBytes(memory.Slice(index));
index += 8;
bytes[index] = (byte)Step;
bytes[index] = (byte)((byte)Step << 4 | (byte)Protocol << 2 | (byte)Direction);
index += 1;
bytes[index] = (byte)Protocol;
index += 1;
bytes[index] = (byte)Direction;
bytes[index] = BufferSize;
index += 1;
Port.ToBytes(memory.Slice(index));
@@ -241,14 +240,12 @@ namespace linker.tunnel.proxy
ConnectId = memory.Slice(index).ToUInt64();
index += 8;
Step = (ProxyStep)span[index];
index += 1;
Step = (ProxyStep)(span[index] >> 4);
Protocol = (ProxyProtocol)(span[index] & 0b1100);
Direction = (ProxyDirection)(span[index] & 0b0011);
index++;
Protocol = (ProxyProtocol)span[index];
index += 1;
Direction = (ProxyDirection)span[index];
index += 1;
BufferSize = span[index];
Port = memory.Slice(index).ToUInt16();
index += 2;

View File

@@ -19,7 +19,7 @@ namespace linker.tunnel.proxy
/// 监听一个端口
/// </summary>
/// <param name="port"></param>
private void StartTcp(IPEndPoint ep)
private void StartTcp(IPEndPoint ep, byte bufferSize)
{
IPEndPoint _localEndPoint = ep;
socket = new Socket(_localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
@@ -33,7 +33,8 @@ namespace linker.tunnel.proxy
AsyncUserToken userToken = new AsyncUserToken
{
ListenPort = LocalEndpoint.Port,
Socket = socket
Socket = socket,
BufferSize = bufferSize
};
_ = StartAccept(userToken);
tcpListens.AddOrUpdate(LocalEndpoint.Port, userToken, (a, b) => userToken);
@@ -75,7 +76,8 @@ namespace linker.tunnel.proxy
{
Socket = socket,
ListenPort = acceptToken.ListenPort,
Buffer = new byte[8 * 1024],
BufferSize = acceptToken.BufferSize,
Buffer = new byte[(1 << acceptToken.BufferSize) * 1024],
Proxy = new ProxyInfo { Data = Helper.EmptyArray, Step = ProxyStep.Request, Port = (ushort)acceptToken.ListenPort, ConnectId = ns.Increment() }
};
_ = BeginReceive(userToken);
@@ -238,7 +240,7 @@ namespace linker.tunnel.proxy
Socket socket = new Socket(token.Proxy.TargetEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.KeepAlive();
ConnectState state = new ConnectState { Connection = token.Connection, ConnectId = token.Proxy.ConnectId, Socket = socket, IPEndPoint = token.Proxy.TargetEP };
ConnectState state = new ConnectState { BufferSize = token.Proxy.BufferSize, Connection = token.Connection, ConnectId = token.Proxy.ConnectId, Socket = socket, IPEndPoint = token.Proxy.TargetEP };
state.CopyData(token.Proxy.Data);
socket.BeginConnect(token.Proxy.TargetEP, ConnectCallback, state);
@@ -250,7 +252,7 @@ namespace linker.tunnel.proxy
{
Connection = state.Connection,
Socket = state.Socket,
Buffer = new byte[8 * 1024],
Buffer = new byte[(1 << state.BufferSize) * 1024],
Proxy = new ProxyInfo
{
ConnectId = state.ConnectId,
@@ -455,6 +457,8 @@ namespace linker.tunnel.proxy
public byte[] Buffer { get; set; }
public byte BufferSize { get; set; } = 3;
public void Clear()
{
Socket?.SafeClose();
@@ -474,6 +478,8 @@ namespace linker.tunnel.proxy
public byte[] Data { get; set; } = Helper.EmptyArray;
public int Length { get; set; }
public byte BufferSize { get; set; } = 3;
public void CopyData(ReadOnlyMemory<byte> data)
{
if (data.Length > 0)

View File

@@ -16,7 +16,7 @@ namespace linker.tunnel.proxy
/// 监听一个端口
/// </summary>
/// <param name="port"></param>
private void StartUdp(IPEndPoint ep)
private void StartUdp(IPEndPoint ep, byte buffersize)
{
try
{
@@ -32,7 +32,7 @@ namespace linker.tunnel.proxy
};
udpListens.AddOrUpdate(ep.Port, asyncUserUdpToken, (a, b) => asyncUserUdpToken);
_ = ReceiveUdp(asyncUserUdpToken);
_ = ReceiveUdp(asyncUserUdpToken, buffersize);
}
catch (Exception ex)
@@ -40,9 +40,9 @@ namespace linker.tunnel.proxy
LoggerHelper.Instance.Error(ex);
}
}
private async Task ReceiveUdp(AsyncUserUdpToken token)
private async Task ReceiveUdp(AsyncUserUdpToken token, byte buffersize)
{
byte[] bytes = new byte[8 * 1024];
byte[] bytes = new byte[(1 << buffersize) * 1024];
IPEndPoint TempRemoteEP = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
while (true)
{
@@ -219,11 +219,12 @@ namespace linker.tunnel.proxy
TargetEP = tunnelToken.Proxy.TargetEP,
Step = tunnelToken.Proxy.Step,
Port = tunnelToken.Proxy.Port,
BufferSize = tunnelToken.Proxy.BufferSize,
},
TargetSocket = socket,
ConnectId = connectId,
Connection = tunnelToken.Connection,
Buffer = new byte[8 * 1027]
Buffer = new byte[(1 << tunnelToken.Proxy.BufferSize) * 1024]
};
udpToken.Proxy.Direction = ProxyDirection.Reverse;
udpConnections.AddOrUpdate(connectId, udpToken, (a, b) => udpToken);

View File

@@ -92,6 +92,8 @@ namespace linker.tunnel.transport
public bool Disabled { get; set; } = false;
public bool Reverse { get; set; } = true;
public bool SSL { get; set; } = true;
public byte BufferSize { get; set; } = 3;
}
public sealed class TunnelTransportItemInfoEqualityComparer : IEqualityComparer<TunnelTransportItemInfo>
{
@@ -138,6 +140,8 @@ namespace linker.tunnel.transport
/// </summary>
public bool SSL { get; set; }
public byte BufferSize { get; set; } = 3;
public List<IPEndPoint> RemoteEndPoints { get; set; }
}

View File

@@ -97,7 +97,7 @@ namespace linker.tunnel.transport
{
//反向连接
TunnelTransportInfo tunnelTransportInfo1 = tunnelTransportInfo.ToJsonFormat().DeJson<TunnelTransportInfo>();
_ = ListenRemoteConnect(tunnelTransportInfo1.Local.Local, quicListenEP, tunnelTransportInfo1);
_ = ListenRemoteConnect(tunnelTransportInfo.BufferSize, tunnelTransportInfo1.Local.Local, quicListenEP, tunnelTransportInfo1);
await Task.Delay(50);
BindAndTTL(tunnelTransportInfo1);
if (await OnSendConnectBegin(tunnelTransportInfo1) == false)
@@ -139,7 +139,7 @@ namespace linker.tunnel.transport
}
if (tunnelTransportInfo.Direction == TunnelDirection.Forward)
{
_ = ListenRemoteConnect(tunnelTransportInfo.Local.Local, quicListenEP, tunnelTransportInfo);
_ = ListenRemoteConnect(tunnelTransportInfo.BufferSize, tunnelTransportInfo.Local.Local, quicListenEP, tunnelTransportInfo);
await Task.Delay(50);
BindAndTTL(tunnelTransportInfo);
}
@@ -173,7 +173,7 @@ namespace linker.tunnel.transport
IPEndPoint local = new IPEndPoint(tunnelTransportInfo.Local.Local.Address, tunnelTransportInfo.Local.Local.Port);
TaskCompletionSource<IPEndPoint> taskCompletionSource = new TaskCompletionSource<IPEndPoint>();
//接收远端数据,收到了就是成功了
Socket remoteUdp = ListenRemoteCallback(local, taskCompletionSource);
Socket remoteUdp = ListenRemoteCallback(tunnelTransportInfo.BufferSize, local, taskCompletionSource);
//给远端发送一些消息
foreach (IPEndPoint ep in tunnelTransportInfo.RemoteEndPoints)
@@ -203,7 +203,7 @@ namespace linker.tunnel.transport
{
IPEndPoint remoteEP = await taskCompletionSource.Task.WaitAsync(TimeSpan.FromMilliseconds(500));
//绑定一个udp用来给QUIC链接
Socket quicUdp = ListenQuicConnect(remoteUdp, remoteEP);
Socket quicUdp = ListenQuicConnect(tunnelTransportInfo.BufferSize, remoteUdp, remoteEP);
QuicConnection connection = connection = await QuicConnection.ConnectAsync(new QuicClientConnectionOptions
{
RemoteEndPoint = new IPEndPoint(IPAddress.Loopback, (quicUdp.LocalEndPoint as IPEndPoint).Port),
@@ -238,6 +238,7 @@ namespace linker.tunnel.transport
Type = TunnelType.P2P,
Mode = TunnelMode.Client,
Label = string.Empty,
BufferSize = tunnelTransportInfo.BufferSize
};
}
catch (Exception ex)
@@ -338,7 +339,7 @@ namespace linker.tunnel.transport
/// <param name="local">绑定的地址</param>
/// <param name="tcs">等待对象,等待得到对方的地址</param>
/// <returns></returns>
private Socket ListenRemoteCallback(IPEndPoint local, TaskCompletionSource<IPEndPoint> tcs)
private Socket ListenRemoteCallback(byte bufferSize, IPEndPoint local, TaskCompletionSource<IPEndPoint> tcs)
{
Socket socketUdp = new Socket(local.AddressFamily, SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp);
socketUdp.ReuseBind(local);
@@ -346,13 +347,13 @@ namespace linker.tunnel.transport
Task.Run(async () =>
{
byte[] buffer = ArrayPool<byte>.Shared.Rent(16 * 1024);
byte[] buffer = ArrayPool<byte>.Shared.Rent((1 << bufferSize) * 1024);
try
{
IPEndPoint tempEp = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
//收到远端的消息,表明对方已收到,再给它发个结束消息,表示可以正常通信了
SocketReceiveFromResult result = await socketUdp.ReceiveFromAsync(buffer, tempEp);
SocketReceiveFromResult result = await socketUdp.ReceiveFromAsync(buffer.AsMemory(), tempEp);
IPEndPoint ep = result.RemoteEndPoint as IPEndPoint;
await socketUdp.SendToAsync(endBytes, ep);
@@ -380,13 +381,13 @@ namespace linker.tunnel.transport
/// <param name="remoteUdp">监听收到消息消息后通过这个udp发送给远端</param>
/// <param name="remoteEP">远端地址</param>
/// <returns></returns>
private Socket ListenQuicConnect(Socket remoteUdp, IPEndPoint remoteEP)
private Socket ListenQuicConnect(byte bufferSize, Socket remoteUdp, IPEndPoint remoteEP)
{
Socket localUdp = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp);
localUdp.Bind(new IPEndPoint(IPAddress.Any, 0));
localUdp.WindowsUdpBug();
_ = WaitQuicConnect(remoteUdp, remoteEP, localUdp);
_ = WaitQuicConnect(bufferSize, remoteUdp, remoteEP, localUdp);
return localUdp;
}
@@ -395,9 +396,9 @@ namespace linker.tunnel.transport
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
private async Task WaitQuicConnect(Socket remoteUdp, IPEndPoint remoteEP, Socket localUdp)
private async Task WaitQuicConnect(byte bufferSize, Socket remoteUdp, IPEndPoint remoteEP, Socket localUdp)
{
byte[] buffer = ArrayPool<byte>.Shared.Rent(16 * 1024);
byte[] buffer = ArrayPool<byte>.Shared.Rent((1 << bufferSize) * 1024);
IPEndPoint tempEp = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
try
{
@@ -407,7 +408,7 @@ namespace linker.tunnel.transport
//发送给远端
await remoteUdp.SendToAsync(buffer.AsMemory(0, result.ReceivedBytes), remoteEP).ConfigureAwait(false);
await Task.WhenAll(CopyToAsync(localUdp, remoteUdp, remoteEP), CopyToAsync(remoteUdp, localUdp, quicEp)).ConfigureAwait(false);
await Task.WhenAll(CopyToAsync(bufferSize, localUdp, remoteUdp, remoteEP), CopyToAsync(bufferSize, remoteUdp, localUdp, quicEp)).ConfigureAwait(false);
}
catch (Exception ex)
{
@@ -431,7 +432,7 @@ namespace linker.tunnel.transport
/// <param name="quicEP">QUIC监听地址</param>
/// <param name="state">收到连接后,调用连接成功回调,带上这个信息</param>
/// <returns></returns>
private async Task ListenRemoteConnect(IPEndPoint local, IPEndPoint quicEP, TunnelTransportInfo state)
private async Task ListenRemoteConnect(byte bufferSize, IPEndPoint local, IPEndPoint quicEP, TunnelTransportInfo state)
{
Socket udpClient = new Socket(local.AddressFamily, SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp);
ListenAsyncToken token = new ListenAsyncToken
@@ -446,7 +447,7 @@ namespace linker.tunnel.transport
udpClient.ReuseBind(local);
udpClient.WindowsUdpBug();
_ = WaitAuth(token, tcs);
_ = WaitAuth(bufferSize, token, tcs);
AddressFamily af = await tcs.Task.WaitAsync(TimeSpan.FromMilliseconds(30000));
}
@@ -464,9 +465,9 @@ namespace linker.tunnel.transport
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
private async Task WaitAuth(ListenAsyncToken token, TaskCompletionSource<AddressFamily> tcs)
private async Task WaitAuth(byte bufferSize, ListenAsyncToken token, TaskCompletionSource<AddressFamily> tcs)
{
byte[] buffer = ArrayPool<byte>.Shared.Rent(16 * 1024);
byte[] buffer = ArrayPool<byte>.Shared.Rent((1 << bufferSize) * 1024);
IPEndPoint tempEp = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
try
{
@@ -482,7 +483,7 @@ namespace linker.tunnel.transport
{
token.RemoteEP = result.RemoteEndPoint as IPEndPoint;
tcs.SetResult(result.RemoteEndPoint.AddressFamily);
_ = Connect2Quic(token);
_ = Connect2Quic(bufferSize, token);
break;
}
else
@@ -510,9 +511,9 @@ namespace linker.tunnel.transport
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
private async Task Connect2Quic(ListenAsyncToken token)
private async Task Connect2Quic(byte bufferSize, ListenAsyncToken token)
{
byte[] buffer = ArrayPool<byte>.Shared.Rent(16 * 1024);
byte[] buffer = ArrayPool<byte>.Shared.Rent((1 << bufferSize) * 1024);
IPEndPoint tempEp = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
try
{
@@ -526,7 +527,7 @@ namespace linker.tunnel.transport
stateDic.AddOrUpdate((token.QuicUdp.LocalEndPoint as IPEndPoint).Port, token, (a, b) => token);
//然后就可以交换数据了
await Task.WhenAll(CopyToAsync(token.RemoteUdp, token.QuicUdp, token.QuicEP), CopyToAsync(token.QuicUdp, token.RemoteUdp, token.RemoteEP)).ConfigureAwait(false);
await Task.WhenAll(CopyToAsync(bufferSize, token.RemoteUdp, token.QuicUdp, token.QuicEP), CopyToAsync(bufferSize, token.QuicUdp, token.RemoteUdp, token.RemoteEP)).ConfigureAwait(false);
}
catch (Exception ex)
{
@@ -549,9 +550,9 @@ namespace linker.tunnel.transport
/// <param name="remote"></param>
/// <param name="remoteEp"></param>
/// <returns></returns>
private async Task CopyToAsync(Socket local, Socket remote, IPEndPoint remoteEp)
private async Task CopyToAsync(byte bufferSize, Socket local, Socket remote, IPEndPoint remoteEp)
{
byte[] buffer = ArrayPool<byte>.Shared.Rent(16 * 1024);
byte[] buffer = ArrayPool<byte>.Shared.Rent((1 << bufferSize) * 1024);
IPEndPoint tempEp = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
try
{
@@ -623,6 +624,7 @@ namespace linker.tunnel.transport
TransportName = state.TransportName,
IPEndPoint = remoteEP,
Label = string.Empty,
BufferSize = state.BufferSize,
};
if (reverseDic.TryRemove(state.Remote.MachineId, out TaskCompletionSource<ITunnelConnection> tcs))
{

View File

@@ -183,7 +183,8 @@ namespace linker.tunnel.transport
Type = TunnelType.P2P,
Mode = TunnelMode.Client,
Label = string.Empty,
SSL = tunnelTransportInfo.SSL
SSL = tunnelTransportInfo.SSL,
BufferSize = tunnelTransportInfo.BufferSize,
};
}
catch (Exception)
@@ -278,7 +279,8 @@ namespace linker.tunnel.transport
TransportName = _state.TransportName,
IPEndPoint = socket.RemoteEndPoint as IPEndPoint,
Label = string.Empty,
SSL = _state.SSL
SSL = _state.SSL,
BufferSize = _state.BufferSize,
};
if (reverseDic.TryRemove(_state.Remote.MachineId, out TaskCompletionSource<ITunnelConnection> tcs))
{

View File

@@ -24,3 +24,10 @@ export const getTunnelTransports = () => {
export const setTunnelTransports = (data) => {
return sendWebsocketMsg('tunnel/SetTransports', data);
}
export const getTunnelExcludeIPs = () => {
return sendWebsocketMsg('tunnel/GetExcludeIPs');
}
export const setTunnelExcludeIPs = (data) => {
return sendWebsocketMsg('tunnel/SetExcludeIPs', data);
}

View File

@@ -12,7 +12,8 @@ export const provideGlobalData = () => {
config: { Common: {}, Client: {}, Running: {} },
configed: false,
signin: { Connected: false, Connecting: false, Version: 'v1.0.0.0' },
groupid: ''
groupid: '',
bufferSize: ['1KB', '2KB', '4KB', '8KB', '16KB', '32KB', '64KB', '128KB', '256KB', '512KB', '1024KB']
});
subWebsocketState((state) => {
globalData.value.connected = state;

View File

@@ -4,9 +4,9 @@
<el-table :data="state.data" size="small" border height="500">
<el-table-column property="RemoteMachineId" label="目标">
<template #default="scope">
<div>
<p>{{scope.row.RemoteMachineName}}</p>
<div :class="{green:scope.row.Connected}">
<p>{{scope.row.IPEndPoint}}</p>
<p>ssl : {{scope.row.SSL}}</p>
</div>
</template>
</el-table-column>
@@ -19,7 +19,7 @@
<template #default="scope">
<div>
<p>{{scope.row.TransportName}}({{ state.protocolTypes[scope.row.ProtocolType] }})</p>
<p>{{ state.types[scope.row.Type] }}</p>
<p>{{ state.types[scope.row.Type] }} - {{1<<scope.row.BufferSize}}KB</p>
</div>
</template>
</el-table-column>
@@ -31,16 +31,11 @@
<el-table-column property="Bytes" label="通信">
<template #default="scope">
<div>
<p>sent : {{scope.row.SendBytesText}}</p>
<p>receive : {{scope.row.ReceiveBytesText}}</p>
<p>up : {{scope.row.SendBytesText}}</p>
<p>down : {{scope.row.ReceiveBytesText}}</p>
</div>
</template>
</el-table-column>
<el-table-column property="Connected" label="连接中" width="60">
<template #default="scope">
<el-switch disabled v-model="scope.row.Connected" inline-prompt active-text="是" inactive-text="否" />
</template>
</el-table-column>
<el-table-column label="操作" width="54">
<template #default="scope">
<el-popconfirm confirm-button-text="确认" cancel-button-text="取消" title="确定关闭此连接?"
@@ -101,4 +96,5 @@ export default {
<style lang="stylus" scoped>
.head{padding-bottom:1rem}
.green{color:green}
</style>

View File

@@ -15,6 +15,7 @@
<span :class="{error:!!item.TargetMsg}">{{ item.TargetEP }}</span>
</span>
</a>
<span> ({{ 1<<item.BufferSize }}KB)</span>
</li>
</template>
</template>
@@ -37,6 +38,7 @@
<span :class="{error:!!item.LocalMsg}">{{ item.LocalEP }}</span>
</span>
</a>
<span> ({{ 1<<item.BufferSize }}KB)</span>
</li>
</template>
</template>

View File

@@ -1,5 +1,5 @@
<template>
<el-dialog v-model="state.show" @open="handleOnShowList" append-to=".app-wrap" :title="`端口转发到【${state.machineName}】`" top="1vh" width="600">
<el-dialog v-model="state.show" @open="handleOnShowList" append-to=".app-wrap" :title="`端口转发到【${state.machineName}】`" top="1vh" width="700">
<div>
<div class="t-c head">
<el-button type="success" size="small" @click="handleAdd">添加</el-button>
@@ -17,6 +17,13 @@
</template>
</template>
</el-table-column>
<el-table-column prop="BufferSize" label="缓冲区" width="100">
<template #default="scope">
<el-select v-model="scope.row.BufferSize" placeholder="Select" size="small" @change="handleEditBlur(scope.row, 'BufferSize')">
<el-option v-for="(item,index) in state.bufferSize" :key="index" :label="item" :value="index"/>
</el-select>
</template>
</el-table-column>
<el-table-column property="BindIPAddress" label="监听IP" width="140">
<template #default="scope">
<el-select v-model="scope.row.BindIPAddress" size="small">
@@ -93,12 +100,14 @@ import { inject, onMounted, onUnmounted, reactive, watch } from 'vue';
import { getForwardInfo, removeForwardInfo, addForwardInfo ,getForwardIpv4,testTargetForwardInfo,testListenForwardInfo } from '@/apis/forward'
import { ElMessage } from 'element-plus';
import {WarnTriangleFilled} from '@element-plus/icons-vue'
import { injectGlobalData } from '@/provide';
export default {
props: ['data','modelValue'],
emits: ['update:modelValue'],
components:{WarnTriangleFilled},
setup(props, { emit }) {
const globalData = injectGlobalData();
const forward = inject('forward');
const state = reactive({
show: true,
@@ -107,7 +116,8 @@ export default {
data: [],
ips:[],
timerTestTarget:0,
timerTestListen:0
timerTestListen:0,
bufferSize:globalData.value.bufferSize,
});
watch(() => state.show, (val) => {
if (!val) {

View File

@@ -17,6 +17,11 @@
</template>
</template>
</el-table-column>
<el-table-column prop="BufferSize" label="缓冲区" width="100">
<template #default="scope">
<span>{{ 1<<scope.row.BufferSize }}KB</span>
</template>
</el-table-column>
<el-table-column property="Temp" label="远程端口/域名" width="160">
<template #default="scope">
<template v-if="scope.row.TempEditing">
@@ -84,14 +89,17 @@ import { inject, onMounted, onUnmounted, reactive, watch } from 'vue';
import { getSForwardInfo, removeSForwardInfo, addSForwardInfo,testLocalSForwardInfo } from '@/apis/sforward'
import { ElMessage } from 'element-plus';
import {WarnTriangleFilled} from '@element-plus/icons-vue'
import { injectGlobalData } from '@/provide';
export default {
props: ['data','modelValue'],
emits: ['update:modelValue'],
components:{WarnTriangleFilled},
setup(props, { emit }) {
const globalData = injectGlobalData();
const sforward = inject('sforward');
const state = reactive({
bufferSize:globalData.value.bufferSize,
show: true,
data: [],
timerTestLocal:0

View File

@@ -32,6 +32,7 @@
</el-switch>
</div>
<div>{{ tuntap.list[scope.row.MachineId].LanIPs.join('、') }}</div>
<div>{{ 1<<tuntap.list[scope.row.MachineId].BufferSize}}KB</div>
</div>
</template>
</el-table-column>

View File

@@ -1,15 +1,20 @@
<template>
<el-dialog v-model="state.show" :close-on-click-modal="false" append-to=".app-wrap" title="设置虚拟网卡IP" width="400">
<el-dialog v-model="state.show" :close-on-click-modal="false" append-to=".app-wrap" title="设置虚拟网卡IP" width="380">
<div>
<el-form ref="ruleFormRef" :model="state.ruleForm" :rules="state.rules" label-width="80">
<el-form-item label="缓冲区" prop="BufferSize">
<el-select v-model="state.ruleForm.BufferSize" placeholder="Select" style="width:12rem">
<el-option v-for="(item,index) in state.bufferSize" :key="index" :label="item" :value="index"/>
</el-select>
</el-form-item>
<el-form-item label="网卡IP" prop="IP">
<el-input v-model="state.ruleForm.IP" />
<el-input v-model="state.ruleForm.IP" style="width:12rem" /> / 24
</el-form-item>
<el-form-item label="局域网IP" prop="LanIP">
<template v-for="(item, index) in state.ruleForm.LanIPs" :key="index">
<div class="flex" style="margin-bottom:.6rem">
<div class="flex-1">
<el-input v-model="state.ruleForm.LanIPs[index]" />
<el-input v-model="state.ruleForm.LanIPs[index]" style="width:12rem" /> / 24
</div>
<div class="pdl-10">
<el-button type="danger" @click="handleDel(index)"><el-icon><Delete /></el-icon></el-button>
@@ -18,9 +23,6 @@
</div>
</template>
</el-form-item>
<el-form-item label="" prop="alert">
<div>网卡IP和局域网IP都是 /24 掩码</div>
</el-form-item>
<el-form-item label="" prop="Btns">
<div>
<el-button @click="state.show = false">取消</el-button>
@@ -33,6 +35,7 @@
</template>
<script>
import {updateTuntap } from '@/apis/tuntap';
import { injectGlobalData } from '@/provide';
import { ElMessage } from 'element-plus';
import { inject, reactive, ref, watch } from 'vue';
@@ -40,13 +43,18 @@ export default {
props: ['modelValue'],
emits: ['change','update:modelValue'],
setup(props, { emit }) {
const globalData = injectGlobalData();
const tuntap = inject('tuntap');
const ruleFormRef = ref(null);
const state = reactive({
show: true,
bufferSize:globalData.value.bufferSize,
ruleForm: {
IP: tuntap.value.current.IP,
LanIPs: tuntap.value.current.LanIPs.slice(0)
LanIPs: tuntap.value.current.LanIPs.slice(0),
BufferSize: tuntap.value.current.BufferSize
},
rules: {}
});
@@ -72,6 +80,7 @@ export default {
const json = JSON.parse(JSON.stringify(tuntap.value.current));
json.IP = state.ruleForm.IP || '0.0.0.0';
json.LanIPs = state.ruleForm.LanIPs.filter(c => c);
json.BufferSize = state.ruleForm.BufferSize;
updateTuntap(json).then(() => {
state.show = false;
ElMessage.success('已操作!');

View File

@@ -0,0 +1,113 @@
<template>
<div class="flex">
<div class="pdr-10 pdb-6 flex-1">
<el-checkbox v-model="state.sync" label="将更改同步到所有客户端" />
</div>
<div>打洞时排除这些IP(比如VPN虚拟网卡IP)</div>
</div>
<el-table :data="state.list" border size="small" width="100%" :height="`${state.height}px`" @cell-dblclick="handleCellClick">
<el-table-column prop="IPAddress" label="IP">
<template #default="scope">
<template v-if="scope.row.IPAddressEditing">
<el-input autofocus size="small" v-model="scope.row.IPAddress" @blur="handleEditBlur(scope.row, 'IPAddress')"></el-input>
</template>
<template v-else>
{{ scope.row.IPAddress }}
</template>
</template>
</el-table-column>
<el-table-column prop="Mask" label="掩码">
<template #default="scope">
<template v-if="scope.row.MaskEditing">
<el-input autofocus size="small" v-model="scope.row.Mask" @blur="handleEditBlur(scope.row, 'Mask')"></el-input>
</template>
<template v-else>
{{ scope.row.Mask }}
</template>
</template>
</el-table-column>
<el-table-column prop="Oper" label="操作" width="104" fixed="right">
<template #default="scope">
<div>
<el-popconfirm title="删除不可逆,是否确认?" @confirm="handleDel(scope.$index)">
<template #reference>
<el-button type="danger" size="small">
<el-icon><Delete /></el-icon>
</el-button>
</template>
</el-popconfirm>
<el-button type="primary" size="small" @click="handleAdd(scope.$index)">
<el-icon><Plus /></el-icon>
</el-button>
</div>
</template>
</el-table-column>
</el-table>
</template>
<script>
import { setTunnelExcludeIPs } from '@/apis/tunnel';
import { injectGlobalData } from '@/provide';
import { ElMessage } from 'element-plus';
import { computed, onMounted, reactive } from 'vue'
export default {
setup(props) {
const globalData = injectGlobalData();
const state = reactive({
list:((globalData.value.config.Running.Tunnel || {ExcludeIPs:[]}).ExcludeIPs || [{IPAddress:'0.0.0.0',Mask:32}]),
types:[],
height: computed(()=>globalData.value.height-130),
sync:true
});
const handleCellClick = (row, column) => {
handleEdit(row, column.property);
}
const handleEdit = (row, p) => {
state.list.forEach(c => {
c[`IPAddressEditing`] = false;
c[`MaskEditing`] = false;
})
row[`${p}Editing`] = true;
}
const handleEditBlur = (row, p) => {
row[`${p}Editing`] = false;
handleSave();
}
const handleDel = (index)=>{
state.list.splice(index,1);
handleSave();
}
const handleAdd = (index)=>{
state.list.splice(index+1,0,{IPAddress:'0.0.0.0',Mask:32});
handleSave();
}
const handleSave = ()=>{
state.list.forEach(c=>{
c.Mask = parseInt(c.Mask);
})
setTunnelExcludeIPs({
sync:state.sync,
list:state.list
}).then(()=>{
ElMessage.success('已操作');
}).catch(()=>{
ElMessage.success('操作失败');
});;
}
onMounted(() => {
if(state.list.length == 0){
state.list = [{IPAddress:'0.0.0.0',Mask:32}];
}
});
return {state,handleCellClick,handleEditBlur,handleDel,handleAdd}
}
}
</script>
<style lang="stylus" scoped>
</style>

View File

@@ -10,6 +10,9 @@
<el-tab-pane label="打洞协议" name="hole">
<Transports v-if="state.connected"></Transports>
</el-tab-pane>
<el-tab-pane label="打洞排除IP" name="ips">
<ExcludeIP v-if="state.connected"></ExcludeIP>
</el-tab-pane>
<el-tab-pane label="中继服务器" name="relay">
<RelayServers v-if="state.connected"></RelayServers>
</el-tab-pane>
@@ -25,10 +28,11 @@ import SignInServers from './SignInServers.vue'
import RelayServers from './RelayServers.vue'
import TunnelServers from './TunnelServers.vue'
import Transports from './Transports.vue'
import ExcludeIP from './ExcludeIP.vue'
import SForward from './SForward.vue'
import { injectGlobalData } from '@/provide';
export default {
components:{SignInServers,RelayServers,TunnelServers,Transports,SForward},
components:{SignInServers,RelayServers,TunnelServers,Transports,ExcludeIP,SForward},
setup(props) {
const globalData = injectGlobalData();

View File

@@ -85,6 +85,7 @@
<script>
import { setRelayServers,getRelayTypes } from '@/apis/relay';
import { injectGlobalData } from '@/provide';
import { ElMessage } from 'element-plus';
import { computed, onMounted, reactive } from 'vue'
export default {
setup(props) {
@@ -147,7 +148,11 @@ export default {
setRelayServers({
sync:state.sync,
list:state.list
});
}).then(()=>{
ElMessage.success('已操作');
}).catch(()=>{
ElMessage.success('操作失败');
});;
}
onMounted(()=>{

View File

@@ -103,7 +103,11 @@ export default {
setSignInServers({
sync:state.sync,
list:state.list
});
}).then(()=>{
ElMessage.success('已操作');
}).catch(()=>{
ElMessage.success('操作失败');
});;
}
return {state,handleCellClick,handleEditBlur,handleDel,handleAdd,handleUse}

View File

@@ -9,6 +9,13 @@
<el-table-column prop="Name" label="名称" width="120"></el-table-column>
<el-table-column prop="Label" label="说明"></el-table-column>
<el-table-column prop="ProtocolType" label="协议" width="60"></el-table-column>
<el-table-column prop="BufferSize" label="缓冲区" width="100">
<template #default="scope">
<el-select v-model="scope.row.BufferSize" placeholder="Select" size="small" @change="handleSave">
<el-option v-for="(item,index) in state.bufferSize" :key="index" :label="item" :value="index"/>
</el-select>
</template>
</el-table-column>
<el-table-column property="Reverse" label="反向" width="60">
<template #default="scope">
<el-switch v-model="scope.row.Reverse" @change="handleSave" inline-prompt active-text="是" inactive-text="否" />
@@ -41,6 +48,7 @@
<script>
import { getTunnelTransports,setTunnelTransports } from '@/apis/tunnel';
import { injectGlobalData } from '@/provide';
import { ElMessage } from 'element-plus';
import { computed, onMounted, reactive } from 'vue'
export default {
setup(props) {
@@ -48,7 +56,8 @@ export default {
const state = reactive({
list:[],
height: computed(()=>globalData.value.height-130),
sync:true
bufferSize:globalData.value.bufferSize,
sync:true,
});
const _getTunnelTransports = ()=>{
@@ -56,7 +65,6 @@ export default {
state.list = res;
});
}
const handleSort = (index,oper)=>{
const current = state.list[index];
const outher = state.list[index+oper];
@@ -67,15 +75,19 @@ export default {
}
handleSave(state.list);
}
const handleSave = ()=>{
state.list = state.list.slice().sort((a,b)=>a.Disabled - b.Disabled);
setTunnelTransports({
sync:state.sync,
List:state.list
}).then(()=>{
ElMessage.success('已操作');
}).catch(()=>{
ElMessage.success('操作失败');
});
}
onMounted(()=>{
_getTunnelTransports();
});

View File

@@ -72,6 +72,7 @@
<script>
import { setTunnelServers,getTunnelTypes } from '@/apis/tunnel';
import { injectGlobalData } from '@/provide';
import { ElMessage } from 'element-plus';
import { computed, onMounted, reactive } from 'vue'
export default {
setup(props) {
@@ -85,7 +86,6 @@ export default {
const _getTunnelTypes = ()=>{
getTunnelTypes().then((res)=>{
console.log(res);
state.types = res;
});
}
@@ -134,7 +134,11 @@ export default {
setTunnelServers({
sync:state.sync,
list:state.list
});
}).then(()=>{
ElMessage.success('已操作');
}).catch(()=>{
ElMessage.success('操作失败');
});;
}
onMounted(()=>{

View File

@@ -64,7 +64,7 @@ namespace linker.plugins.forward
{
try
{
forwardProxy.Start(new System.Net.IPEndPoint(forwardInfo.BindIPAddress, forwardInfo.Port), forwardInfo.TargetEP, forwardInfo.MachineId);
forwardProxy.Start(new System.Net.IPEndPoint(forwardInfo.BindIPAddress, forwardInfo.Port), forwardInfo.TargetEP, forwardInfo.MachineId, forwardInfo.BufferSize);
forwardInfo.Port = forwardProxy.LocalEndpoint.Port;
if (forwardInfo.Port > 0)
@@ -211,7 +211,7 @@ namespace linker.plugins.forward
try
{
forwardProxy.Stop(item.Port);
forwardProxy.Start(new IPEndPoint(item.BindIPAddress, item.Port), item.TargetEP, item.MachineId);
forwardProxy.Start(new IPEndPoint(item.BindIPAddress, item.Port), item.TargetEP, item.MachineId, item.BufferSize);
}
catch (Exception ex)
{
@@ -268,6 +268,7 @@ namespace linker.plugins.forward
old.TargetEP = forwardInfo.TargetEP;
old.MachineId = forwardInfo.MachineId;
old.Started = forwardInfo.Started;
old.BufferSize = forwardInfo.BufferSize;
}
else
{

View File

@@ -21,6 +21,8 @@ namespace linker.client.config
public IPEndPoint TargetEP { get; set; }
public bool Started { get; set; }
public byte BufferSize { get; set; } = 3;
public string Msg { get; set; }
public string TargetMsg { get; set; }

View File

@@ -138,10 +138,10 @@ namespace linker.plugins.forward.proxy
}
public void Start(IPEndPoint ep, IPEndPoint targetEP, string machineId)
public void Start(IPEndPoint ep, IPEndPoint targetEP, string machineId,byte bufferSize)
{
Stop(ep.Port);
base.Start(ep);
base.Start(ep, bufferSize);
caches.TryAdd(LocalEndpoint.Port, new ForwardProxyCacheInfo { Port = LocalEndpoint.Port, TargetEP = targetEP, MachineId = machineId });
}
public override void Stop(int port)

View File

@@ -29,7 +29,7 @@ namespace linker.config
public sealed class RelayConfigServerInfo
{
public string SecretKey { get; set; } = Guid.NewGuid().ToString().ToUpper();
public byte BufferSize { get; set; } = 3;
}
[MemoryPackable]

View File

@@ -172,27 +172,22 @@ namespace linker.plugins.relay.messenger
private async Task Relay(IConnection source, IConnection target, string secretKey)
{
await Task.Delay(100);
int limit = 0;
source.TargetStream = target.SourceStream;
source.TargetSocket = target.SourceSocket;
source.TargetNetworkStream = target.SourceNetworkStream;
source.RelayLimit = (uint)limit;
source.RelayLimit = 0;
target.TargetStream = source.SourceStream;
target.TargetSocket = source.SourceSocket;
target.TargetNetworkStream = source.SourceNetworkStream;
target.RelayLimit = (uint)limit;
target.RelayLimit = 0;
source.Cancel();
target.Cancel();
await Task.Delay(200);
await Task.WhenAll(source.RelayAsync(), target.RelayAsync());
await Task.WhenAll(source.RelayAsync(config.Data.Server.Relay.BufferSize), target.RelayAsync(config.Data.Server.Relay.BufferSize));
}
public sealed class TcsWrap

View File

@@ -87,7 +87,8 @@ namespace linker.plugins.relay.transport
TransactionId = relayInfo.TransactionId,
TransportName = Name,
Type = TunnelType.Relay,
SSL = relayInfo.SSL
SSL = relayInfo.SSL,
BufferSize = 3
};
}
catch (Exception ex)
@@ -148,7 +149,8 @@ namespace linker.plugins.relay.transport
TransactionId = relayInfo.TransactionId,
TransportName = Name,
Type = TunnelType.Relay,
SSL = relayInfo.SSL
SSL = relayInfo.SSL,
BufferSize = 3,
};
}
catch (Exception ex)

View File

@@ -59,7 +59,7 @@ namespace linker.plugins.sforward
SForwardProxy sForwardProxy = serviceProvider.GetService<SForwardProxy>();
if (config.Data.Server.SForward.WebPort > 0)
{
sForwardProxy.Start(config.Data.Server.SForward.WebPort, true);
sForwardProxy.Start(config.Data.Server.SForward.WebPort, true, config.Data.Server.SForward.BufferSize);
LoggerHelper.Instance.Info($"listen server forward web in {config.Data.Server.SForward.WebPort}");
}
LoggerHelper.Instance.Info($"listen server forward tunnel in {string.Join("-", config.Data.Server.SForward.TunnelPortRange)}");

View File

@@ -64,6 +64,7 @@ namespace linker.plugins.sforward
if (result.Result.Code == MessageResponeCodes.OK)
{
SForwardAddResultInfo sForwardAddResultInfo = MemoryPackSerializer.Deserialize<SForwardAddResultInfo>(result.Result.Data.Span);
forwardInfo.BufferSize = sForwardAddResultInfo.BufferSize;
if (sForwardAddResultInfo.Success)
{
forwardInfo.Proxy = true;

View File

@@ -20,6 +20,8 @@ namespace linker.client.config
public string Domain { get; set; }
public int RemotePort { get; set; }
public byte BufferSize { get; set; } = 3;
public IPEndPoint LocalEP { get; set; }
public bool Started { get; set; }
@@ -42,7 +44,7 @@ namespace linker.config
public sealed class SForwardConfigServerInfo
{
public string SecretKey { get; set; } = Guid.NewGuid().ToString().ToUpper();
public byte BufferSize { get; set; } = 3;
public int WebPort { get; set; }
public int[] TunnelPortRange { get; set; } = new int[] { 10000, 60000 };
@@ -65,6 +67,8 @@ namespace linker.plugins.sforward.config
{
public bool Success { get; set; }
public string Message { get; set; }
public byte BufferSize { get; set; }
}
@@ -74,5 +78,7 @@ namespace linker.plugins.sforward.config
public ulong Id { get; set; }
public string Domain { get; set; }
public int RemotePort { get; set; }
public byte BufferSize { get; set; } = 3;
}
}

View File

@@ -5,6 +5,7 @@ using linker.plugins.signin.messenger;
using linker.server;
using MemoryPack;
using linker.plugins.sforward.proxy;
using linker.config;
namespace linker.plugins.sforward.messenger
{
@@ -15,10 +16,10 @@ namespace linker.plugins.sforward.messenger
private readonly ISForwardServerCahing sForwardServerCahing;
private readonly MessengerSender sender;
private readonly SignCaching signCaching;
private readonly ConfigWrap configWrap;
private readonly IValidator validator;
public SForwardServerMessenger(SForwardProxy proxy, ISForwardServerCahing sForwardServerCahing, MessengerSender sender, SignCaching signCaching, IValidator validator)
public SForwardServerMessenger(SForwardProxy proxy, ISForwardServerCahing sForwardServerCahing, MessengerSender sender, SignCaching signCaching, ConfigWrap configWrap, IValidator validator)
{
this.proxy = proxy;
proxy.WebConnect = WebConnect;
@@ -27,6 +28,7 @@ namespace linker.plugins.sforward.messenger
this.sForwardServerCahing = sForwardServerCahing;
this.sender = sender;
this.signCaching = signCaching;
this.configWrap = configWrap;
this.validator = validator;
}
@@ -34,7 +36,7 @@ namespace linker.plugins.sforward.messenger
public void Add(IConnection connection)
{
SForwardAddInfo sForwardAddInfo = MemoryPackSerializer.Deserialize<SForwardAddInfo>(connection.ReceiveRequestWrap.Payload.Span);
SForwardAddResultInfo result = new SForwardAddResultInfo { Success = true };
SForwardAddResultInfo result = new SForwardAddResultInfo { Success = true, BufferSize = configWrap.Data.Server.SForward.BufferSize };
try
{
if (validator.Valid(connection, sForwardAddInfo, out string error) == false)
@@ -67,7 +69,7 @@ namespace linker.plugins.sforward.messenger
}
else
{
string msg = proxy.Start(sForwardAddInfo.RemotePort, false);
string msg = proxy.Start(sForwardAddInfo.RemotePort, false, configWrap.Data.Server.SForward.BufferSize);
if (string.IsNullOrWhiteSpace(msg) == false)
{
result.Success = false;
@@ -177,7 +179,7 @@ namespace linker.plugins.sforward.messenger
{
Connection = sign.Connection,
MessengerId = (ushort)SForwardMessengerIds.Proxy,
Payload = MemoryPackSerializer.Serialize(new SForwardProxyInfo { Domain = host, RemotePort = port, Id = id })
Payload = MemoryPackSerializer.Serialize(new SForwardProxyInfo { Domain = host, RemotePort = port, Id = id, BufferSize= configWrap.Data.Server.SForward.BufferSize })
});
}
return false;
@@ -190,7 +192,7 @@ namespace linker.plugins.sforward.messenger
{
Connection = sign.Connection,
MessengerId = (ushort)SForwardMessengerIds.Proxy,
Payload = MemoryPackSerializer.Serialize(new SForwardProxyInfo { RemotePort = port, Id = id })
Payload = MemoryPackSerializer.Serialize(new SForwardProxyInfo { RemotePort = port, Id = id, BufferSize = configWrap.Data.Server.SForward.BufferSize })
});
}
return false;
@@ -203,7 +205,7 @@ namespace linker.plugins.sforward.messenger
{
Connection = sign.Connection,
MessengerId = (ushort)SForwardMessengerIds.ProxyUdp,
Payload = MemoryPackSerializer.Serialize(new SForwardProxyInfo { RemotePort = port, Id = id })
Payload = MemoryPackSerializer.Serialize(new SForwardProxyInfo { RemotePort = port, Id = id, BufferSize = configWrap.Data.Server.SForward.BufferSize })
});
}
return false;
@@ -231,7 +233,7 @@ namespace linker.plugins.sforward.messenger
SForwardInfo sForwardInfo = runningConfig.Data.SForwards.FirstOrDefault(c => c.Domain == sForwardProxyInfo.Domain);
if (sForwardInfo != null)
{
_ = proxy.OnConnectTcp(sForwardProxyInfo.Id, new System.Net.IPEndPoint(connection.Address.Address, sForwardProxyInfo.RemotePort), sForwardInfo.LocalEP);
_ = proxy.OnConnectTcp(sForwardProxyInfo.BufferSize,sForwardProxyInfo.Id, new System.Net.IPEndPoint(connection.Address.Address, sForwardProxyInfo.RemotePort), sForwardInfo.LocalEP);
}
}
else if (sForwardProxyInfo.RemotePort > 0)
@@ -239,7 +241,7 @@ namespace linker.plugins.sforward.messenger
SForwardInfo sForwardInfo = runningConfig.Data.SForwards.FirstOrDefault(c => c.RemotePort == sForwardProxyInfo.RemotePort);
if (sForwardInfo != null)
{
_ = proxy.OnConnectTcp(sForwardProxyInfo.Id, new System.Net.IPEndPoint(connection.Address.Address, sForwardProxyInfo.RemotePort), sForwardInfo.LocalEP);
_ = proxy.OnConnectTcp(sForwardProxyInfo.BufferSize, sForwardProxyInfo.Id, new System.Net.IPEndPoint(connection.Address.Address, sForwardProxyInfo.RemotePort), sForwardInfo.LocalEP);
}
}
}
@@ -252,7 +254,7 @@ namespace linker.plugins.sforward.messenger
SForwardInfo sForwardInfo = runningConfig.Data.SForwards.FirstOrDefault(c => c.RemotePort == sForwardProxyInfo.RemotePort);
if (sForwardInfo != null)
{
_ = proxy.OnConnectUdp(sForwardProxyInfo.Id, new System.Net.IPEndPoint(connection.Address.Address, sForwardProxyInfo.RemotePort), sForwardInfo.LocalEP);
_ = proxy.OnConnectUdp(sForwardProxyInfo.BufferSize, sForwardProxyInfo.Id, new System.Net.IPEndPoint(connection.Address.Address, sForwardProxyInfo.RemotePort), sForwardInfo.LocalEP);
}
}
}

View File

@@ -13,12 +13,12 @@ namespace linker.plugins.sforward.proxy
UdpTask();
}
public string Start(int port, bool isweb)
public string Start(int port, bool isweb,byte bufferSize)
{
try
{
StartTcp(port, isweb);
StartUdp(port);
StartTcp(port, isweb, bufferSize);
StartUdp(port, bufferSize);
return string.Empty;
}
catch (Exception ex)

View File

@@ -15,10 +15,10 @@ namespace linker.plugins.sforward.proxy
public Func<int, ulong, Task<bool>> TunnelConnect { get; set; } = async (port, id) => { return await Task.FromResult(false); };
public Func<string,int, ulong, Task<bool>> WebConnect { get; set; } = async (host,port, id) => { return await Task.FromResult(false); };
public Func<string, int, ulong, Task<bool>> WebConnect { get; set; } = async (host, port, id) => { return await Task.FromResult(false); };
private void StartTcp(int port, bool isweb)
private void StartTcp(int port, bool isweb, byte bufferSize)
{
IPEndPoint localEndPoint = new IPEndPoint(NetworkHelper.IPv6Support ? IPAddress.IPv6Any : IPAddress.Any, port);
Socket socket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
@@ -30,6 +30,7 @@ namespace linker.plugins.sforward.proxy
ListenPort = port,
SourceSocket = socket,
IsWeb = isweb,
BufferSize = bufferSize,
};
SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs
{
@@ -86,6 +87,7 @@ namespace linker.plugins.sforward.proxy
SourceSocket = socket,
ListenPort = acceptToken.ListenPort,
IsWeb = acceptToken.IsWeb,
BufferSize = acceptToken.BufferSize,
};
_ = BindReceive(userToken);
}
@@ -100,8 +102,8 @@ namespace linker.plugins.sforward.proxy
private async Task BindReceive(AsyncUserToken token)
{
ulong id = ns.Increment();
byte[] buffer1 = ArrayPool<byte>.Shared.Rent(8 * 1024);
byte[] buffer2 = ArrayPool<byte>.Shared.Rent(8 * 1024);
byte[] buffer1 = ArrayPool<byte>.Shared.Rent((1 << token.BufferSize) * 1024);
byte[] buffer2 = ArrayPool<byte>.Shared.Rent((1 << token.BufferSize) * 1024);
try
{
int length = await token.SourceSocket.ReceiveAsync(buffer1.AsMemory(), SocketFlags.None);
@@ -132,7 +134,7 @@ namespace linker.plugins.sforward.proxy
}
else
{
if(await TunnelConnect(token.ListenPort, id) == false)
if (await TunnelConnect(token.ListenPort, id) == false)
{
CloseClientSocket(token);
return;
@@ -144,7 +146,7 @@ namespace linker.plugins.sforward.proxy
token.TargetSocket = await tcs.Task.WaitAsync(TimeSpan.FromMilliseconds(2000)).ConfigureAwait(false);
await token.TargetSocket.SendAsync(buffer1.AsMemory(0, length));
await Task.WhenAll(SwarpData(token, buffer1, token.SourceSocket, token.TargetSocket), SwarpData(token,buffer2, token.TargetSocket, token.SourceSocket));
await Task.WhenAll(CopyToAsync(buffer1, token.SourceSocket, token.TargetSocket), CopyToAsync(buffer2, token.TargetSocket, token.SourceSocket));
CloseClientSocket(token);
}
@@ -157,14 +159,15 @@ namespace linker.plugins.sforward.proxy
tcpConnections.TryRemove(id, out _);
ArrayPool<byte>.Shared.Return(buffer1);
ArrayPool<byte>.Shared.Return(buffer2);
}
}
public async Task OnConnectTcp(ulong id, IPEndPoint server, IPEndPoint service)
public async Task OnConnectTcp(byte bufferSize, ulong id, IPEndPoint server, IPEndPoint service)
{
Socket sourceSocket = null;
Socket targetSocket = null;
byte[] buffer1 = ArrayPool<byte>.Shared.Rent(8 * 1024);
byte[] buffer2 = ArrayPool<byte>.Shared.Rent(8 * 1024);
byte[] buffer1 = ArrayPool<byte>.Shared.Rent((1 << bufferSize) * 1024);
byte[] buffer2 = ArrayPool<byte>.Shared.Rent((1 << bufferSize) * 1024);
try
{
sourceSocket = new Socket(server.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
@@ -179,7 +182,7 @@ namespace linker.plugins.sforward.proxy
id.ToBytes(buffer1.AsMemory(flagBytes.Length));
await sourceSocket.SendAsync(buffer1.AsMemory(0, flagBytes.Length + 8));
await Task.WhenAll(SwarpData(null,buffer1, sourceSocket, targetSocket), SwarpData(null,buffer2, targetSocket, sourceSocket));
await Task.WhenAll(CopyToAsync(buffer1, sourceSocket, targetSocket), CopyToAsync(buffer2, targetSocket, sourceSocket));
}
catch (Exception)
@@ -194,6 +197,7 @@ namespace linker.plugins.sforward.proxy
}
}
private byte[] hostBytes = Encoding.UTF8.GetBytes("Host: ");
private byte[] wrapBytes = Encoding.UTF8.GetBytes("\r\n");
private byte[] colonBytes = Encoding.UTF8.GetBytes(":");
@@ -210,14 +214,15 @@ namespace linker.plugins.sforward.proxy
return Encoding.UTF8.GetString(buffer.Slice(start, length).Span);
}
private async Task SwarpData(AsyncUserToken token,Memory<byte> buffer, Socket source, Socket target)
private async Task CopyToAsync(Memory<byte> buffer, Socket source, Socket target)
{
try
{
int bytesRead;
while ((bytesRead = await source.ReceiveAsync(buffer).ConfigureAwait(false)) != 0)
while ((bytesRead = await source.ReceiveAsync(buffer, SocketFlags.None).ConfigureAwait(false)) != 0)
{
await target.SendAsync(buffer.Slice(0, bytesRead)).ConfigureAwait(false);
await target.SendAsync(buffer.Slice(0, bytesRead), SocketFlags.None).ConfigureAwait(false);
}
}
catch (Exception ex)
@@ -227,6 +232,11 @@ namespace linker.plugins.sforward.proxy
LoggerHelper.Instance.Error(ex);
}
}
finally
{
source.SafeClose();
target.SafeClose();
}
}
private void CloseClientSocket(AsyncUserToken token)
@@ -260,6 +270,8 @@ namespace linker.plugins.sforward.proxy
public Socket SourceSocket { get; set; }
public Socket TargetSocket { get; set; }
public byte BufferSize { get; set; }
public void Clear()
{
SourceSocket?.SafeClose();

View File

@@ -16,7 +16,7 @@ namespace linker.plugins.sforward.proxy
public Func<int, ulong, Task<bool>> UdpConnect { get; set; } = async (port, id) => { return await Task.FromResult(false); };
private void StartUdp(int port)
private void StartUdp(int port, byte bufferSize)
{
Socket socketUdp = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socketUdp.Bind(new IPEndPoint(IPAddress.Any, port));
@@ -28,16 +28,16 @@ namespace linker.plugins.sforward.proxy
socketUdp.EnableBroadcast = true;
socketUdp.WindowsUdpBug();
_ = BindReceive(asyncUserUdpToken);
_ = BindReceive(asyncUserUdpToken, bufferSize);
udpListens.AddOrUpdate(port, asyncUserUdpToken, (a, b) => asyncUserUdpToken);
}
private async Task BindReceive(AsyncUserUdpToken token)
private async Task BindReceive(AsyncUserUdpToken token, byte bufferSize)
{
try
{
byte[] buffer = new byte[8 * 1024];
byte[] buffer = new byte[(1 << bufferSize) * 1024];
IPEndPoint tempRemoteEP = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
while (true)
{
@@ -125,7 +125,7 @@ namespace linker.plugins.sforward.proxy
}
}
}
public async Task OnConnectUdp(ulong id, IPEndPoint server, IPEndPoint service)
public async Task OnConnectUdp(byte bufferSize, ulong id, IPEndPoint server, IPEndPoint service)
{
Socket socketUdp = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socketUdp.WindowsUdpBug();
@@ -137,7 +137,7 @@ namespace linker.plugins.sforward.proxy
await socketUdp.SendToAsync(buffer, server);
Socket serviceUdp = null;
buffer = new byte[8 * 1024];
buffer = new byte[(1 << bufferSize) * 1024];
IPEndPoint tempEp = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
while (true)
{
@@ -160,7 +160,7 @@ namespace linker.plugins.sforward.proxy
_ = Task.Run(async () =>
{
buffer = new byte[8 * 1024];
buffer = new byte[(1 << bufferSize) * 1024];
IPEndPoint tempEp = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
while (true)
{

View File

@@ -10,6 +10,9 @@ using MemoryPack;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using linker.tunnel.wanport;
using System.Linq;
using linker.libs.extends;
using System.Buffers.Binary;
namespace linker.plugins.tunnel
{
@@ -63,7 +66,26 @@ namespace linker.plugins.tunnel
{
return new NetworkInfo
{
LocalIps = config.Data.Client.Tunnel.LocalIPs.Where(c => c.Equals(running.Data.Tuntap.IP) == false).ToArray(),
LocalIps = config.Data.Client.Tunnel.LocalIPs
.Where(c => c.Equals(running.Data.Tuntap.IP) == false)
.Where(c=>
{
if(c.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
uint ip = BinaryPrimitives.ReadUInt32BigEndian(c.GetAddressBytes());
foreach (var item in running.Data.Tunnel.ExcludeIPs)
{
uint maskValue = NetworkHelper.MaskValue(item.Mask);
uint ip1 = BinaryPrimitives.ReadUInt32BigEndian(item.IPAddress.GetAddressBytes());
if((ip & maskValue) == (ip1 & maskValue))
{
return false;
}
}
}
return true;
})
.ToArray(),
RouteLevel = config.Data.Client.Tunnel.RouteLevel + running.Data.Tunnel.RouteLevelPlus,
MachineId = config.Data.Client.Id
};

View File

@@ -10,6 +10,7 @@ using linker.libs.extends;
using MemoryPack;
using System.Collections.Concurrent;
using linker.tunnel.wanport;
using linker.client.config;
namespace linker.plugins.tunnel
{
@@ -149,6 +150,25 @@ namespace linker.plugins.tunnel
}
}
public ExcludeIPItem[] GetExcludeIPs(ApiControllerParamsInfo param)
{
return tunnelConfigTransfer.GetExcludeIPs();
}
public async Task SetExcludeIPs(ApiControllerParamsInfo param)
{
SetExcludeIPsParamInfo info = param.Content.DeJson<SetExcludeIPsParamInfo>();
tunnelConfigTransfer.SettExcludeIPs(info.List);
if (info.Sync)
{
await messengerSender.SendOnly(new MessageRequestWrap
{
Connection = clientSignInState.Connection,
MessengerId = (ushort)TunnelMessengerIds.ExcludeIPsForward,
Payload = MemoryPackSerializer.Serialize(info.List)
});
}
}
public sealed class TunnelListInfo
{
@@ -167,6 +187,11 @@ namespace linker.plugins.tunnel
public bool Sync { get; set; }
public List<TunnelTransportItemInfo> List { get; set; } = new List<TunnelTransportItemInfo>();
}
public sealed class SetExcludeIPsParamInfo
{
public bool Sync { get; set; }
public ExcludeIPItem[] List { get; set; } = Array.Empty<ExcludeIPItem>();
}
}
}

View File

@@ -99,7 +99,6 @@ namespace linker.plugins.tunnel
}
});
}
private TunnelTransportRouteLevelInfo GetLocalRouteLevel()
{
return new TunnelTransportRouteLevelInfo
@@ -110,5 +109,15 @@ namespace linker.plugins.tunnel
};
}
public ExcludeIPItem[] GetExcludeIPs()
{
return running.Data.Tunnel.ExcludeIPs;
}
public void SettExcludeIPs(ExcludeIPItem[] ips)
{
running.Data.Tunnel.ExcludeIPs = ips;
}
}
}

View File

@@ -20,8 +20,18 @@ namespace linker.client.config
public TunnelWanPortInfo[] Servers { get; set; } = Array.Empty<TunnelWanPortInfo>();
public int RouteLevelPlus { get; set; } = 0;
public ExcludeIPItem[] ExcludeIPs { get; set; } = Array.Empty<ExcludeIPItem>();
public List<TunnelTransportItemInfo> Transports { get; set; } = new List<TunnelTransportItemInfo>();
}
[MemoryPackable]
public sealed partial class ExcludeIPItem
{
[MemoryPackAllowSerialize]
public IPAddress IPAddress { get; set;}
public byte Mask { get; set; } = 32;
}
}
namespace linker.config
@@ -133,9 +143,9 @@ namespace linker.config
string MachineName => tunnelTransportWanPortInfo.MachineName;
[MemoryPackConstructor]
SerializableTunnelTransportWanPortInfo(IPEndPoint local, IPEndPoint remote, IPAddress[] localIps, int routeLevel, string machineId,string machineName)
SerializableTunnelTransportWanPortInfo(IPEndPoint local, IPEndPoint remote, IPAddress[] localIps, int routeLevel, string machineId, string machineName)
{
var tunnelTransportWanPortInfo = new TunnelTransportWanPortInfo { Local = local, Remote = remote, LocalIps = localIps, RouteLevel = routeLevel, MachineId = machineId, MachineName= machineName };
var tunnelTransportWanPortInfo = new TunnelTransportWanPortInfo { Local = local, Remote = remote, LocalIps = localIps, RouteLevel = routeLevel, MachineId = machineId, MachineName = machineName };
this.tunnelTransportWanPortInfo = tunnelTransportWanPortInfo;
}
@@ -195,11 +205,14 @@ namespace linker.config
[MemoryPackInclude]
bool Reverse => tunnelTransportItemInfo.Reverse;
[MemoryPackInclude]
byte BufferSize => tunnelTransportItemInfo.BufferSize;
[MemoryPackConstructor]
SerializableTunnelTransportItemInfo(string name, string label, string protocolType, bool disabled, bool reverse)
SerializableTunnelTransportItemInfo(string name, string label, string protocolType, bool disabled, bool reverse, byte buffersize)
{
var tunnelTransportItemInfo = new TunnelTransportItemInfo { Name = name, Label = label, ProtocolType = protocolType, Disabled = disabled, Reverse = reverse };
var tunnelTransportItemInfo = new TunnelTransportItemInfo { Name = name, Label = label, ProtocolType = protocolType, Disabled = disabled, Reverse = reverse, BufferSize = buffersize };
this.tunnelTransportItemInfo = tunnelTransportItemInfo;
}
@@ -264,9 +277,12 @@ namespace linker.config
[MemoryPackInclude]
bool SSL => tunnelTransportInfo.SSL;
[MemoryPackInclude]
byte BufferSize => tunnelTransportInfo.BufferSize;
[MemoryPackConstructor]
SerializableTunnelTransportInfo(TunnelTransportWanPortInfo local, TunnelTransportWanPortInfo remote, string transactionId, TunnelProtocolType transportType, string transportName, TunnelDirection direction, bool ssl)
SerializableTunnelTransportInfo(TunnelTransportWanPortInfo local, TunnelTransportWanPortInfo remote, string transactionId, TunnelProtocolType transportType, string transportName, TunnelDirection direction, bool ssl, byte bufferSize)
{
var tunnelTransportInfo = new TunnelTransportInfo
{
@@ -276,7 +292,8 @@ namespace linker.config
TransportName = transportName,
TransportType = transportType,
Direction = direction,
SSL = ssl
SSL = ssl,
BufferSize = bufferSize,
};
this.tunnelTransportInfo = tunnelTransportInfo;
}

View File

@@ -7,6 +7,7 @@ using linker.tunnel.transport;
using linker.libs;
using MemoryPack;
using linker.tunnel.wanport;
using linker.client.config;
namespace linker.plugins.tunnel.messenger
{
@@ -96,6 +97,13 @@ namespace linker.plugins.tunnel.messenger
TunnelWanPortInfo[] servers = MemoryPackSerializer.Deserialize<TunnelWanPortInfo[]>(connection.ReceiveRequestWrap.Payload.Span);
tunnelMessengerAdapter.SetTunnelWanPortCompacts(servers.ToList());
}
[MessengerId((ushort)TunnelMessengerIds.ExcludeIPs)]
public void ExcludeIPs(IConnection connection)
{
ExcludeIPItem[] ips = MemoryPackSerializer.Deserialize<ExcludeIPItem[]>(connection.ReceiveRequestWrap.Payload.Span);
tunnelConfigTransfer.SettExcludeIPs(ips);
}
}
public sealed class TunnelServerMessenger : IMessenger
@@ -274,6 +282,25 @@ namespace linker.plugins.tunnel.messenger
}
}
}
[MessengerId((ushort)TunnelMessengerIds.ExcludeIPsForward)]
public async Task ExcludeIPsForward(IConnection connection)
{
if (signCaching.TryGet(connection.Id, out SignCacheInfo cache))
{
List<SignCacheInfo> caches = signCaching.Get(cache.GroupId);
foreach (SignCacheInfo item in caches.Where(c => c.MachineId != connection.Id && c.Connected))
{
await messengerSender.SendOnly(new MessageRequestWrap
{
Connection = item.Connection,
MessengerId = (ushort)TunnelMessengerIds.ExcludeIPs,
Payload = connection.ReceiveRequestWrap.Payload
});
}
}
}
}

View File

@@ -28,6 +28,9 @@
Servers = 2015,
ServersForward = 2016,
ExcludeIPs = 2017,
ExcludeIPsForward = 2018,
None = 2099
}
}

View File

@@ -90,6 +90,7 @@ namespace linker.plugins.tuntap
return;
}
tuntapProxy.Start();
while (tuntapProxy.LocalEndpoint == null)
{
await Task.Delay(1000);
@@ -125,6 +126,7 @@ namespace linker.plugins.tuntap
}
try
{
tuntapProxy.Stop();
OnChange();
tuntapVea.Kill();
runningConfig.Data.Tuntap.Running = Status == TuntapStatus.Running;
@@ -162,6 +164,7 @@ namespace linker.plugins.tuntap
{
runningConfig.Data.Tuntap.IP = info.IP;
runningConfig.Data.Tuntap.LanIPs = info.LanIPs;
runningConfig.Data.Tuntap.BufferSize = info.BufferSize;
runningConfig.Data.Update();
if (Status == TuntapStatus.Running)
{
@@ -227,7 +230,8 @@ namespace linker.plugins.tuntap
LanIPs = runningConfig.Data.Tuntap.LanIPs,
MachineId = config.Data.Client.Id,
Status = Status,
Error = tuntapVea.Error
Error = tuntapVea.Error,
BufferSize = runningConfig.Data.Tuntap.BufferSize
};
}
/// <summary>
@@ -377,12 +381,8 @@ namespace linker.plugins.tuntap
await socket.ConnectAsync(new IPEndPoint(IPAddress.Loopback, tuntapProxy.LocalEndpoint.Port)).WaitAsync(TimeSpan.FromMilliseconds(100));
socket.SafeClose();
}
catch (Exception ex)
catch (Exception)
{
LoggerHelper.Instance.Error($"tuntap proxy {new IPEndPoint(IPAddress.Loopback, tuntapProxy.LocalEndpoint.Port)} {ex}");
tuntapProxy.Start();
LoggerHelper.Instance.Debug($"tuntap proxy restart in {new IPEndPoint(IPAddress.Loopback, tuntapProxy.LocalEndpoint.Port)}");
Stop();
await Task.Delay(5000);
Run();

View File

@@ -20,6 +20,7 @@ namespace linker.plugins.tuntap.config
}
public uint IpInt { get; private set; }
public byte BufferSize { get; set; } = 3;
/// <summary>
/// 局域网IP列表

View File

@@ -37,9 +37,6 @@ namespace linker.plugins.tuntap.proxy
this.runningConfig = runningConfig;
this.config = config;
Start();
LoggerHelper.Instance.Info($"start tuntap proxy, listen port : {LocalEndpoint}");
//监听打洞连接成功
tunnelTransfer.SetConnectedCallback("tuntap", OnConnected);
//监听中继连接成功
@@ -51,7 +48,7 @@ namespace linker.plugins.tuntap.proxy
{
Stop(proxyEP.Port);
}
Start(new IPEndPoint(IPAddress.Any, 0));
Start(new IPEndPoint(IPAddress.Any, 0), runningConfig.Data.Tuntap.BufferSize);
proxyEP = new IPEndPoint(IPAddress.Any, LocalEndpoint.Port);
}

View File

@@ -65,6 +65,7 @@ namespace linker.plugins.tuntap.vea
public string Error { get; set; }
public byte BufferSize { get; set; } = 3;
}
[MemoryPackable]

View File

@@ -108,7 +108,7 @@ namespace linker.server
/// 开始中继不再处理包在此之前应该先调用Cancel取消处理包在等待一段时间后再开始中继
/// </summary>
/// <returns></returns>
public Task RelayAsync();
public Task RelayAsync(byte bufferSize);
/// <summary>
/// 取消处理包
@@ -234,7 +234,7 @@ namespace linker.server
public abstract Task<bool> SendAsync(ReadOnlyMemory<byte> data);
public abstract Task<bool> SendAsync(byte[] data, int length);
public abstract Task RelayAsync();
public abstract Task RelayAsync(byte bufferSize);
public virtual void Cancel()
@@ -508,16 +508,16 @@ namespace linker.server
return await SendAsync(data.AsMemory(0, length));
}
public override async Task RelayAsync()
public override async Task RelayAsync(byte bufferSize)
{
if (TargetNetworkStream != null)
{
await CopyToAsync(SourceNetworkStream, TargetNetworkStream);
await CopyToAsync(bufferSize,SourceNetworkStream, TargetNetworkStream);
}
}
private async Task CopyToAsync(NetworkStream source, NetworkStream destination)
private async Task CopyToAsync(byte bufferSize,NetworkStream source, NetworkStream destination)
{
byte[] buffer = ArrayPool<byte>.Shared.Rent(8 * 1024);
byte[] buffer = ArrayPool<byte>.Shared.Rent((1<< bufferSize) * 1024);
try
{
int bytesRead;