Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
Socks5Connection.cs
1using System;
2using System.IO;
3using System.Text;
4using System.Threading.Tasks;
5
7{
11 public class Socks5Connection : IDisposable
12 {
13 private Socks5Server server;
14 private BinaryTcpClient client;
15 private byte[] addr = null;
16 private string streamId = null;
17 private bool disposed = false;
18 private int inputState = 0;
19 private ushort port;
20 private byte nr;
21 private byte command;
22 private byte addrType;
23 private byte[] methods;
24
31 {
32 this.client = Client;
33 this.server = Server;
34
35 this.client.OnDisconnected += this.Client_OnDisconnected;
36 this.client.OnError += this.Client_OnError;
37 this.client.OnReceived += this.Client_OnReceived;
38 }
39
44 {
45 get => this.server;
46 }
47
51 public string RemoteEndPoint => this.client.RemoteEndPoint;
52
56 [Obsolete("Use the DisposeAsync() method.")]
57 public void Dispose()
58 {
59 this.DisposeAsync().Wait();
60 }
61
65 public async Task DisposeAsync()
66 {
67 if (!this.disposed)
68 {
69 this.disposed = true;
70
71 if (!(this.streamId is null))
72 {
73 this.server.UnregisterStream(this.streamId, this);
74 this.streamId = null;
75 }
76
77 this.server = null;
78 this.inputState = -1;
79
80 if (!(this.client is null))
81 {
82 await this.client.DisposeAsync();
83 this.client = null;
84 }
85 }
86 }
87
91 public void CloseWhenDone()
92 {
93 this.client?.DisposeWhenDone();
94 }
95
96 private async Task<bool> Client_OnReceived(object _, bool ConstantBuffer, byte[] Buffer, int Offset, int Count)
97 {
98 try
99 {
100 if (this.server.HasSniffers)
101 this.server.ReceiveBinary(ConstantBuffer, Buffer, Offset, Count);
102
103 return await this.ParseIncoming(ConstantBuffer, Buffer, Offset, Count);
104 }
105 catch (Exception ex)
106 {
107 if (!this.disposed)
108 this.server.Exception(ex);
109
110 return false;
111 }
112 }
113
114 private Task Client_OnError(object Sender, Exception Exception)
115 {
116 return this.DisposeAsync();
117 }
118
119 private Task Client_OnDisconnected(object Sender, EventArgs e)
120 {
121 return this.DisposeAsync();
122 }
123
124 private async Task<bool> ParseIncoming(bool ConstantBuffer, byte[] Buffer, int Offset, int Count)
125 {
126 byte b;
127
128 while (Count-- > 0)
129 {
130 b = Buffer[Offset++];
131
132 switch (this.inputState)
133 {
134 case 0: // Version
135 if (b != 5)
136 {
137 await this.DisposeAsync();
138 return false;
139 }
140 this.inputState++;
141 break;
142
143 case 1: // Nr methods.
144 this.nr = b;
145 this.methods = new byte[b];
146
147 if (this.nr == 0)
148 {
149 this.inputState += 2;
150 if (!await this.SendAuthenticationMethod())
151 return false;
152 }
153 else
154 this.inputState++;
155 break;
156
157 case 2: // Method
158 this.methods[^this.nr] = b;
159 this.nr--;
160 if (this.nr == 0)
161 {
162 this.inputState++;
163 if (!await this.SendAuthenticationMethod())
164 return false;
165 }
166 break;
167
168 case 3: // Version
169 if (b != 5)
170 {
171 await this.DisposeAsync();
172 return false;
173 }
174 this.inputState++;
175 break;
176
177 case 4: // Command
178 this.command = b;
179 this.inputState++;
180 break;
181
182 case 5: // Reserved
183 this.inputState++;
184 break;
185
186 case 6: // Address type
187 switch (this.addrType = b)
188 {
189 case 1:
190 this.nr = 4;
191 this.addr = new byte[4];
192 this.inputState += 2;
193 break;
194
195 case 3:
196 this.inputState++;
197 break;
198
199 case 4:
200 this.nr = 16;
201 this.addr = new byte[16];
202 this.inputState += 2;
203 break;
204
205 default:
206 await this.DisposeAsync();
207 return false;
208 }
209 break;
210
211 case 7: // Address length
212 this.nr = b;
213 this.addr = new byte[b];
214 this.inputState++;
215 break;
216
217 case 8: // Address
218 this.addr[^this.nr] = b;
219 this.nr--;
220 if (this.nr == 0)
221 this.inputState++;
222 break;
223
224 case 9: // Port, MSB
225 this.port = b;
226 this.inputState++;
227 break;
228
229 case 10: // Port, LSB
230 this.port <<= 8;
231 this.port |= b;
232 this.inputState = 3;
233 if (!await this.ExecuteCommand())
234 {
235 await this.DisposeAsync();
236 return false;
237 }
238 break;
239
240 case 11: // Wait for activation
241 break;
242
243 case 12: // Data through active channel.
244 if (this.server.TryGetRemoteEndPoint(this.streamId, this, out Socks5Connection RemoteEndPoint))
245 return await RemoteEndPoint.client.SendAsync(ConstantBuffer, Buffer, Offset - 1, Count + 1, null, null);
246 else
247 {
248 await this.DisposeAsync();
249 return false;
250 }
251 }
252 }
253
254 return true;
255 }
256
257 internal bool WaitingForActivation
258 {
259 get { return this.inputState == 11; }
260 }
261
262 internal void Activate()
263 {
264 this.inputState = 12;
265 }
266
267 private Task<bool> SendAuthenticationMethod()
268 {
269 foreach (byte b in this.methods)
270 {
271 if (b == 0)
272 return this.client.SendAsync(true, new byte[] { 5, 0 }, null, null);
273 }
274
275 return this.client.SendAsync(true, new byte[] { 5, 0xff }, (Sender, e) =>
276 {
277 return this.DisposeAsync();
278 }, null);
279 }
280
281 private async Task<bool> ExecuteCommand()
282 {
283 using MemoryStream Response = new MemoryStream();
284
285 Response.WriteByte(5);
286
287 if (this.addrType != 3)
288 Response.WriteByte(8);
289 else if (this.command != 1)
290 Response.WriteByte(7);
291 else
292 {
293 Response.WriteByte(0);
294
295 this.inputState = 11;
296 this.streamId = Encoding.ASCII.GetString(this.addr);
297
298 if (!this.server.RegisterConnection(this.streamId, this))
299 {
300 this.streamId = null;
301 await this.DisposeAsync();
302 return false;
303 }
304 }
305
306 Response.WriteByte(0);
307 Response.WriteByte(this.addrType);
308
309 if (this.addrType == 3)
310 Response.WriteByte((byte)this.addr.Length);
311
312 Response.Write(this.addr, 0, this.addr.Length);
313 Response.WriteByte((byte)(this.port >> 8));
314 Response.WriteByte((byte)(this.port & 0xff));
315
316 return await this.client.SendAsync(true, Response.ToArray(), null, null);
317 }
318
319 }
320}
Implements a binary TCP Client, by encapsulating a TcpClient. It also makes the use of TcpClient safe...
Task< bool > SendAsync(byte[] Packet)
Sends a binary packet.
string RemoteEndPoint
Remote End-point of connection. This corresponds to the IP Endpoint of the remote party in normal cas...
void DisposeWhenDone()
Disposes the client when done sending all data.
virtual Task DisposeAsync()
Disposes of the object asynchronously. The underlying TcpClient is either disposed directly,...
void Exception(Exception Exception)
Called to inform the viewer of an exception state.
bool HasSniffers
If there are sniffers registered on the object.
void ReceiveBinary(int Count)
Called when binary data has been received.
Socks5Connection(BinaryTcpClient Client, Socks5Server Server)
Class managing a connection.
async Task DisposeAsync()
Closes the connection and disposes of all resources.
void CloseWhenDone()
Closes connection when done.
Socks5Server Server
SOCKS5 Server serving the client.
Definition: ImplTypes.g.cs:58