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
52 {
53 get { return this.client.Client.Client.RemoteEndPoint.ToString(); }
54 }
55
59 public void Dispose()
60 {
61 if (!this.disposed)
62 {
63 this.disposed = true;
64
65 if (!(this.streamId is null))
66 {
67 this.server.UnregisterStream(this.streamId, this);
68 this.streamId = null;
69 }
70
71 this.server = null;
72 this.inputState = -1;
73
74 this.client?.Dispose();
75 this.client = null;
76 }
77 }
78
82 public void CloseWhenDone()
83 {
84 this.client?.DisposeWhenDone();
85 }
86
87 private async Task<bool> Client_OnReceived(object Sender, byte[] Buffer, int Offset, int Count)
88 {
89 try
90 {
91 if (this.server.HasSniffers)
92 await this.server.ReceiveBinary(BinaryTcpClient.ToArray(Buffer, Offset, Count));
93
94 return await this.ParseIncoming(Buffer, Offset, Count);
95 }
96 catch (Exception ex)
97 {
98 if (!this.disposed)
99 await this.server.Exception(ex);
100
101 return false;
102 }
103 }
104
105 private Task Client_OnError(object Sender, Exception Exception)
106 {
107 this.Dispose();
108 return Task.CompletedTask;
109 }
110
111 private Task Client_OnDisconnected(object Sender, EventArgs e)
112 {
113 this.Dispose();
114 return Task.CompletedTask;
115 }
116
117 private async Task<bool> ParseIncoming(byte[] Buffer, int Offset, int Count)
118 {
119 byte b;
120
121 while (Count-- > 0)
122 {
123 b = Buffer[Offset++];
124
125 switch (this.inputState)
126 {
127 case 0: // Version
128 if (b != 5)
129 {
130 this.Dispose();
131 return false;
132 }
133 this.inputState++;
134 break;
135
136 case 1: // Nr methods.
137 this.nr = b;
138 this.methods = new byte[b];
139
140 if (this.nr == 0)
141 {
142 this.inputState += 2;
143 if (!await this.SendAuthenticationMethod())
144 return false;
145 }
146 else
147 this.inputState++;
148 break;
149
150 case 2: // Method
151 this.methods[this.methods.Length - this.nr] = b;
152 this.nr--;
153 if (this.nr == 0)
154 {
155 this.inputState++;
156 if (!await this.SendAuthenticationMethod())
157 return false;
158 }
159 break;
160
161 case 3: // Version
162 if (b != 5)
163 {
164 this.Dispose();
165 return false;
166 }
167 this.inputState++;
168 break;
169
170 case 4: // Command
171 this.command = b;
172 this.inputState++;
173 break;
174
175 case 5: // Reserved
176 this.inputState++;
177 break;
178
179 case 6: // Address type
180 switch (this.addrType = b)
181 {
182 case 1:
183 this.nr = 4;
184 this.addr = new byte[4];
185 this.inputState += 2;
186 break;
187
188 case 3:
189 this.inputState++;
190 break;
191
192 case 4:
193 this.nr = 16;
194 this.addr = new byte[16];
195 this.inputState += 2;
196 break;
197
198 default:
199 this.Dispose();
200 return false;
201 }
202 break;
203
204 case 7: // Address length
205 this.nr = b;
206 this.addr = new byte[b];
207 this.inputState++;
208 break;
209
210 case 8: // Address
211 this.addr[this.addr.Length - this.nr] = b;
212 this.nr--;
213 if (this.nr == 0)
214 this.inputState++;
215 break;
216
217 case 9: // Port, MSB
218 this.port = b;
219 this.inputState++;
220 break;
221
222 case 10: // Port, LSB
223 this.port <<= 8;
224 this.port |= b;
225 this.inputState = 3;
226 if (!await this.ExecuteCommand())
227 {
228 this.Dispose();
229 return false;
230 }
231 break;
232
233 case 11: // Wait for activation
234 break;
235
236 case 12: // Data through active channel.
237 if (this.server.TryGetRemoteEndpoint(this.streamId, this, out Socks5Connection RemoteEndpoint))
238 return await RemoteEndpoint.client.SendAsync(Buffer, Offset - 1, Count + 1, null, null);
239 else
240 {
241 this.Dispose();
242 return false;
243 }
244 }
245 }
246
247 return true;
248 }
249
250 internal bool WaitingForActivation
251 {
252 get { return this.inputState == 11; }
253 }
254
255 internal void Activate()
256 {
257 this.inputState = 12;
258 }
259
260 private Task<bool> SendAuthenticationMethod()
261 {
262 foreach (byte b in this.methods)
263 {
264 if (b == 0)
265 return this.client.SendAsync(new byte[] { 5, 0 }, null, null);
266 }
267
268 return this.client.SendAsync(new byte[] { 5, 0xff }, (Sender, e) =>
269 {
270 this.Dispose();
271 return Task.CompletedTask;
272 }, null);
273 }
274
275 private Task<bool> ExecuteCommand()
276 {
277 using (MemoryStream Response = new MemoryStream())
278 {
279 Response.WriteByte(5);
280
281 if (this.addrType != 3)
282 Response.WriteByte(8);
283 else if (this.command != 1)
284 Response.WriteByte(7);
285 else
286 {
287 Response.WriteByte(0);
288
289 this.inputState = 11;
290 this.streamId = Encoding.ASCII.GetString(this.addr);
291
292 if (!this.server.RegisterConnection(this.streamId, this))
293 {
294 this.streamId = null;
295 this.Dispose();
296 return Task.FromResult(false);
297 }
298 }
299
300 Response.WriteByte(0);
301 Response.WriteByte(this.addrType);
302
303 if (this.addrType == 3)
304 Response.WriteByte((byte)this.addr.Length);
305
306 Response.Write(this.addr, 0, this.addr.Length);
307 Response.WriteByte((byte)(this.port >> 8));
308 Response.WriteByte((byte)(this.port & 0xff));
309
310 return this.client.SendAsync(Response.ToArray(), null, null);
311 }
312 }
313
314 }
315}
Implements a binary TCP Client, by encapsulating a TcpClient. It also makes the use of TcpClient safe...
TcpClient Client
Underlying TcpClient object.
Task< bool > SendAsync(byte[] Packet)
Sends a binary packet.
static byte[] ToArray(byte[] Buffer, int Offset, int Count)
Converts a binary subset of a buffer into an array.
void DisposeWhenDone()
Disposes the client when done sending all data.
virtual void Dispose()
Disposes of the object. The underlying TcpClient is either disposed directly, or when asynchronous op...
Task Exception(Exception Exception)
Called to inform the viewer of an exception state.
bool HasSniffers
If there are sniffers registered on the object.
Task ReceiveBinary(byte[] Data)
Called when binary data has been received.
Socks5Connection(BinaryTcpClient Client, Socks5Server Server)
Class managing a connection.
void CloseWhenDone()
Closes connection when done.
Socks5Server Server
SOCKS5 Server serving the client.