Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
Socks5Server.cs
1using System;
3using System.Net;
4using System.Net.NetworkInformation;
6using System.Threading.Tasks;
7using Waher.Events;
11
13{
17 public class Socks5Server : CommunicationLayer, IDisposable
18 {
22 public const int DefaultPort = 1080;
23
27 public const int DefaultConnectionBacklog = 10;
28
29 private LinkedList<TcpListener> listeners = new LinkedList<TcpListener>();
30 private Cache<CaseInsensitiveString, Pair> connections;
31 private bool disposed = false;
32
38 : this(DefaultPort, Sniffers)
39 {
40 }
41
47 public Socks5Server(int Port, params ISniffer[] Sniffers)
48 : this(new int[] { Port }, Sniffers)
49 {
50 }
51
57 public Socks5Server(int[] Ports, params ISniffer[] Sniffers)
58 : base(false, Sniffers)
59 {
60 this.connections = new Cache<CaseInsensitiveString, Pair>(int.MaxValue, TimeSpan.MaxValue, TimeSpan.FromMinutes(1), true);
61 this.connections.Removed += this.ClientConnections_Removed;
62
63 this.Initialize(Ports);
64 }
65
66 private void Initialize(int[] Ports)
67 {
68 try
69 {
70 TcpListener Listener;
71
72 foreach (NetworkInterface Interface in NetworkInterface.GetAllNetworkInterfaces())
73 {
74 if (Interface.OperationalStatus != OperationalStatus.Up)
75 continue;
76
77 IPInterfaceProperties Properties = Interface.GetIPProperties();
78
79 foreach (UnicastIPAddressInformation UnicastAddress in Properties.UnicastAddresses)
80 {
81 if ((UnicastAddress.Address.AddressFamily == AddressFamily.InterNetwork && Socket.OSSupportsIPv4) ||
82 (UnicastAddress.Address.AddressFamily == AddressFamily.InterNetworkV6 && Socket.OSSupportsIPv6))
83 {
84 if (!(Ports is null))
85 {
86 foreach (int C2sPort in Ports)
87 {
88 try
89 {
90 this.Information("Opening port " + C2sPort.ToString() + " on " + UnicastAddress.Address.ToString() + ".");
91
92 Listener = new TcpListener(UnicastAddress.Address, C2sPort);
93 Listener.Start(DefaultConnectionBacklog);
94 Listener.BeginAcceptTcpClient(this.AcceptTcpClientCallback, Listener);
95 this.listeners.AddLast(Listener);
96
97 this.Information("Port " + C2sPort.ToString() + " on " + UnicastAddress.Address.ToString() + " opened.");
98 }
99 catch (Exception ex)
100 {
101 Log.Exception(ex, UnicastAddress.Address.ToString() + ":" + C2sPort);
102 }
103 }
104 }
105 }
106 }
107 }
108 }
109 catch (Exception ex)
110 {
111 Log.Exception(ex);
112 }
113 }
114
115 internal bool RegisterConnection(string StreamId, Socks5Connection Connection)
116 {
117 if (this.connections.TryGetValue(StreamId, out Pair P))
118 {
119 if (P.Connection2 is null)
120 P.Connection2 = Connection;
121 else
122 return false;
123 }
124 else
125 {
126 this.connections[StreamId] = new Pair()
127 {
128 Connection1 = Connection
129 };
130 }
131
132 return true;
133 }
134
135 internal void UnregisterStream(string StreamId, Socks5Connection Connection)
136 {
137 if (this.connections.TryGetValue(StreamId, out Pair P))
138 {
139 if (P.Connection1 == Connection)
140 {
141 P.Closed1 = true;
142 if (P.Closed2)
143 this.connections.Remove(StreamId);
144 else
145 P.Connection2?.CloseWhenDone();
146 }
147 else if (P.Connection2 == Connection)
148 {
149 P.Closed2 = true;
150 if (P.Closed1)
151 this.connections.Remove(StreamId);
152 else
153 P.Connection1?.CloseWhenDone();
154 }
155 }
156 }
157
158 internal bool TryGetRemoteEndPoint(string StreamId, Socks5Connection Sender, out Socks5Connection Receiver)
159 {
160 if (this.connections.TryGetValue(StreamId, out Pair P))
161 {
162 if (P.Connection1 == Sender)
163 Receiver = P.Connection2;
164 else if (P.Connection2 == Sender)
165 Receiver = P.Connection1;
166 else
167 Receiver = null;
168 }
169 else
170 Receiver = null;
171
172 return !(Receiver is null);
173 }
174
175 internal bool Activate(string StreamId)
176 {
177 if (!this.connections.TryGetValue(StreamId, out Pair P))
178 return false;
179
180 if (P.Connection1 is null ||
181 P.Connection2 is null ||
182 !P.Connection1.WaitingForActivation ||
183 !P.Connection2.WaitingForActivation)
184 {
185 return false;
186 }
187
188 P.Connection1.Activate();
189 P.Connection2.Activate();
190
191 return true;
192 }
193
194 private class Pair
195 {
196 public Socks5Connection Connection1 = null;
197 public Socks5Connection Connection2 = null;
198 public bool Closed1 = false;
199 public bool Closed2 = false;
200 }
201
202 private async Task ClientConnections_Removed(object Sender, CacheItemEventArgs<CaseInsensitiveString, Pair> e)
203 {
204 if (!(e.Value.Connection1 is null))
205 await e.Value.Connection1.DisposeAsync();
206
207 if (!(e.Value.Connection2 is null))
208 await e.Value.Connection2.DisposeAsync();
209 }
210
214 public void Dispose()
215 {
216 this.disposed = true;
217
218 this.connections?.Clear();
219 this.connections?.Dispose();
220 this.connections = null;
221
222 if (!(this.listeners is null))
223 {
224 LinkedList<TcpListener> Listeners = this.listeners;
225 this.listeners = null;
226
227 foreach (TcpListener Listener in Listeners)
228 Listener.Stop();
229 }
230 }
231
235 public int[] OpenC2SPorts
236 {
237 get
238 {
239 SortedDictionary<int, bool> Open = new SortedDictionary<int, bool>();
240
241 if (!(this.listeners is null))
242 {
243 IPEndPoint IPEndPoint;
244
245 foreach (TcpListener Listener in this.listeners)
246 {
247 IPEndPoint = Listener.LocalEndpoint as IPEndPoint;
248 if (!(IPEndPoint is null))
249 Open[IPEndPoint.Port] = true;
250 }
251 }
252
253 int[] Result = new int[Open.Count];
254 Open.Keys.CopyTo(Result, 0);
255
256 return Result;
257 }
258 }
259
263 public bool IsOpen
264 {
265 get
266 {
267 return !(this.listeners?.First is null);
268 }
269 }
270
271 private void AcceptTcpClientCallback(IAsyncResult ar)
272 {
273 try
274 {
275 if (this.disposed || NetworkingModule.Stopping)
276 return;
277
278 TcpListener Listener = (TcpListener)ar.AsyncState;
279
280 if (!this.disposed)
281 {
282 try
283 {
284 TcpClient Client = Listener.EndAcceptTcpClient(ar);
286 BinaryTcpClient.Bind(true);
287
288 this.Information("Connection accepted from " + BinaryTcpClient.RemoteEndPoint + ".");
289
291
293 }
294 finally
295 {
296 if (!this.disposed)
297 Listener.BeginAcceptTcpClient(this.AcceptTcpClientCallback, Listener);
298 }
299 }
300 }
301 catch (SocketException)
302 {
303 // Ignore
304 }
305 catch (ObjectDisposedException)
306 {
307 // Ignore
308 }
309 catch (NullReferenceException)
310 {
311 // Ignore
312 }
313 catch (Exception ex)
314 {
315 if (this.listeners is null)
316 return;
317
318 Log.Exception(ex);
319 }
320 }
321
322 }
323}
Static class managing the application event log. Applications and services log events on this static ...
Definition: Log.cs:14
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
Definition: Log.cs:1657
Implements a binary TCP Client, by encapsulating a TcpClient. It also makes the use of TcpClient safe...
void Bind()
Binds to a TcpClient that was already connected when provided to the constructor.
string RemoteEndPoint
Remote End-point of connection. This corresponds to the IP Endpoint of the remote party in normal cas...
void Continue()
Continues reading from the socket, if paused in an event handler.
Simple base class for classes implementing communication protocols.
ISniffer[] Sniffers
Registered sniffers.
void Information(string Comment)
Called to inform the viewer of something.
Module that controls the life cycle of communication.
static bool Stopping
If the system is stopping.
Socks5Server(int[] Ports, params ISniffer[] Sniffers)
SOCKS5 server.
Definition: Socks5Server.cs:57
int[] OpenC2SPorts
C2S Ports successfully opened.
Socks5Server(params ISniffer[] Sniffers)
SOCKS5 server. Default port will be used.
Definition: Socks5Server.cs:37
Socks5Server(int Port, params ISniffer[] Sniffers)
SOCKS5 server.
Definition: Socks5Server.cs:47
const int DefaultPort
Default SOCKS5 Port (1080).
Definition: Socks5Server.cs:22
bool IsOpen
If the server is open and accepts incoming connections.
const int DefaultConnectionBacklog
Default Connection backlog (10).
Definition: Socks5Server.cs:27
Implements an in-memory cache.
Definition: Cache.cs:17
void Dispose()
IDisposable.Dispose
Definition: Cache.cs:99
bool Remove(KeyType Key)
Removes an item from the cache.
Definition: Cache.cs:616
bool TryGetValue(KeyType Key, out ValueType Value)
Tries to get a value from the cache.
Definition: Cache.cs:311
void Clear()
Clears the cache.
Definition: Cache.cs:679
Event arguments for cache item removal events.
ValueType Value
Value of item that was removed.
Interface for sniffers. Sniffers can be added to ICommunicationLayer classes to eavesdrop on communic...
Definition: ISniffer.cs:10