1- using System . Net ;
1+ using System . Collections . Concurrent ;
2+ using System . Net ;
23using System . Net . Sockets ;
34using ConnectX . Client . Messages . Proxy ;
5+ using ConnectX . Client . Models ;
46using ConnectX . Client . Proxy ;
7+ using ConnectX . Client . Route ;
8+ using ConnectX . Client . Transmission ;
59using ConnectX . Shared . Helpers ;
610using ConnectX . Shared . Interfaces ;
711using Hive . Both . General . Dispatchers ;
@@ -14,15 +18,17 @@ namespace ConnectX.Client.Managers;
1418public abstract class GenericProxyManager : BackgroundService
1519{
1620 //使用一个二元组确定一个连接
17- private readonly Dictionary < TunnelIdentifier , GenericProxyPair > _proxies = [ ] ;
18- private readonly Dictionary < TunnelIdentifier , Socket > _acceptedSockets = [ ] ;
19- private readonly Dictionary < ValueTuple < Guid , ushort > , GenericProxyAcceptor > _acceptors = [ ] ;
21+ private readonly ConcurrentDictionary < TunnelIdentifier , GenericProxyPair > _proxies = [ ] ;
22+ private readonly ConcurrentDictionary < TunnelIdentifier , Socket > _acceptedSockets = [ ] ;
23+ private readonly ConcurrentDictionary < ValueTuple < Guid , ushort > , GenericProxyAcceptor > _acceptors = [ ] ;
2024
2125 private readonly IHostApplicationLifetime _lifetime ;
2226 private readonly IServiceProvider _serviceProvider ;
2327 protected readonly ILogger Logger ;
2428
2529 protected GenericProxyManager (
30+ RouterPacketDispatcher packetDispatcher ,
31+ RelayPacketDispatcher relayPacketDispatcher ,
2632 IHostApplicationLifetime lifetime ,
2733 IServiceProvider serviceProvider ,
2834 ILogger logger )
@@ -31,6 +37,9 @@ protected GenericProxyManager(
3137 _serviceProvider = serviceProvider ;
3238
3339 Logger = logger ;
40+
41+ packetDispatcher . OnReceive < ProxyDisconnectReq > ( RecycleClientProxy ) ;
42+ relayPacketDispatcher . OnReceive < ProxyDisconnectReq > ( RecycleClientProxy ) ;
3443 }
3544
3645 public override void Dispose ( )
@@ -45,6 +54,20 @@ public override void Dispose()
4554 GC . SuppressFinalize ( this ) ;
4655 }
4756
57+ private void RecycleClientProxy ( ProxyDisconnectReq req , PacketContext ctx )
58+ {
59+ var key = new TunnelIdentifier ( req . ClientId , req . ServerRealPort , req . ClientRealPort ) ;
60+
61+ if ( _proxies . TryRemove ( key , out var pair ) )
62+ {
63+ Logger . LogClientProxyDisconnectedBecauseRequested ( key ) ;
64+ pair . Dispose ( ) ;
65+ return ;
66+ }
67+
68+ Logger . LogFailedToShutdownClientProxyBecauseNotFound ( key ) ;
69+ }
70+
4871 public void ReceivedProxyConnectReq (
4972 MessageContext < ProxyConnectReq > ctx ,
5073 ISender sender )
@@ -133,7 +156,11 @@ public virtual GenericProxyPair CreateClientProxy(
133156 dispatcher ,
134157 sender ) ;
135158
136- _proxies . Add ( key , pair ) ;
159+ _proxies . AddOrUpdate ( key , _ => pair , ( _ , old ) =>
160+ {
161+ old . Dispose ( ) ;
162+ return pair ;
163+ } ) ;
137164
138165 Logger . LogCreateProxy ( key ) ;
139166
@@ -164,7 +191,9 @@ public virtual GenericProxyPair CreateClientProxy(
164191 socket ,
165192 key ,
166193 _lifetime . ApplicationStopping ) ;
194+
167195 proxy . OnRealServerDisconnected += OnProxyDisconnected ;
196+ proxy . OnRealServerDisconnected += NotifyServerProxyDisconnect ;
168197
169198 var pair = new GenericProxyPair (
170199 partnerId ,
@@ -174,10 +203,29 @@ public virtual GenericProxyPair CreateClientProxy(
174203 dispatcher ,
175204 sender ) ;
176205
177- _proxies . Add ( key , pair ) ;
206+ _proxies . AddOrUpdate ( key , _ => pair , ( _ , old ) =>
207+ {
208+ old . Dispose ( ) ;
209+ return pair ;
210+ } ) ;
178211 proxy . Start ( ) ;
179212
180213 return proxy ;
214+
215+ void NotifyServerProxyDisconnect ( TunnelIdentifier id , GenericProxyBase proxy )
216+ {
217+ proxy . OnRealServerDisconnected -= NotifyServerProxyDisconnect ;
218+
219+ // 真客户端离开了房间或掉线,通知房主回收对应的 proxy
220+ sender . SendData ( new ProxyDisconnectReq
221+ {
222+ ClientId = id . PartnerId ,
223+ ClientRealPort = id . LocalRealPort ,
224+ ServerRealPort = id . RemoteRealPort
225+ } ) ;
226+
227+ Logger . LogNotifyServerProxyNeedToDisconnect ( id ) ;
228+ }
181229 }
182230
183231 private void OnProxyDisconnected ( TunnelIdentifier id , GenericProxyBase proxy )
@@ -206,11 +254,11 @@ public virtual GenericProxyAcceptor CreateAcceptor(
206254
207255 var key = ( partnerId , remoteRealServerPort ) ;
208256
209- if ( _acceptors . Remove ( key , out var oldAcceptor ) )
257+ if ( _acceptors . TryRemove ( key , out var oldAcceptor ) )
210258 {
211259 if ( oldAcceptor . IsRunning )
212260 {
213- _acceptors . Add ( key , oldAcceptor ) ;
261+ _acceptors . AddOrUpdate ( ( partnerId , remoteRealServerPort ) , _ => oldAcceptor , ( _ , _ ) => oldAcceptor ) ;
214262 throw new InvalidOperationException ( $ "There has been a acceptor with same key: { partnerId } -{ remoteRealServerPort } ") ;
215263 }
216264
@@ -224,7 +272,7 @@ public virtual GenericProxyAcceptor CreateAcceptor(
224272 localMapPort ,
225273 _lifetime . ApplicationStopping ) ;
226274
227- _acceptors . Add ( ( partnerId , remoteRealServerPort ) , acceptor ) ;
275+ _acceptors . AddOrUpdate ( ( partnerId , remoteRealServerPort ) , _ => acceptor , ( _ , _ ) => acceptor ) ;
228276
229277 // 当有真客户端连接的时候,发送一个McConnectReq,当收到回复后启动Proxy(启动的逻辑在OnReceive里)
230278 acceptor . OnRealClientConnected += ( _ , socket ) =>
@@ -240,7 +288,7 @@ public virtual GenericProxyAcceptor CreateAcceptor(
240288 ( ushort ) remoteEndPoint . Port ,
241289 remoteRealServerPort ) ;
242290
243- _acceptedSockets . Add ( id , socket ) ;
291+ _acceptedSockets . AddOrUpdate ( id , _ => socket , ( _ , _ ) => socket ) ;
244292
245293 sender . SendData ( new ProxyConnectReq
246294 {
@@ -351,4 +399,13 @@ public static partial void LogErrorProxyPairWithSameKey(this ILogger logger, Gui
351399
352400 [ LoggerMessage ( LogLevel . Information , "[GEN_PROXY_MANAGER] Create acceptor {Key}" ) ]
353401 public static partial void LogCreateAcceptor ( this ILogger logger , ( Guid , ushort ) key ) ;
402+
403+ [ LoggerMessage ( LogLevel . Information , "[GEN_PROXY_MANAGER] Notify server proxy need to disconnect {Id}" ) ]
404+ public static partial void LogNotifyServerProxyNeedToDisconnect ( this ILogger logger , TunnelIdentifier id ) ;
405+
406+ [ LoggerMessage ( LogLevel . Error , "[GEN_PROXY_MANAGER] Failed to shutdown client proxy because not found {key}" ) ]
407+ public static partial void LogFailedToShutdownClientProxyBecauseNotFound ( this ILogger logger , TunnelIdentifier key ) ;
408+
409+ [ LoggerMessage ( LogLevel . Information , "[GEN_PROXY_MANAGER] Client proxy disconnected because requested {key}" ) ]
410+ public static partial void LogClientProxyDisconnectedBecauseRequested ( this ILogger logger , TunnelIdentifier key ) ;
354411}
0 commit comments