You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

TCPRelay.cs 30 kB

12 years ago
12 years ago
10 years ago
12 years ago
12 years ago
10 years ago
12 years ago
12 years ago
12 years ago
12 years ago
10 years ago
12 years ago
12 years ago
12 years ago
12 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
10 years ago
12 years ago
12 years ago
12 years ago
10 years ago
12 years ago
12 years ago
12 years ago
10 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
10 years ago
12 years ago
12 years ago
12 years ago
12 years ago
10 years ago
12 years ago
12 years ago
12 years ago
12 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net;
  5. using System.Net.Sockets;
  6. using System.Timers;
  7. using Shadowsocks.Controller.Strategy;
  8. using Shadowsocks.Encryption;
  9. using Shadowsocks.ForwardProxy;
  10. using Shadowsocks.Model;
  11. using Shadowsocks.Util.Sockets;
  12. namespace Shadowsocks.Controller
  13. {
  14. class TCPRelay : Listener.Service
  15. {
  16. private ShadowsocksController _controller;
  17. private DateTime _lastSweepTime;
  18. private Configuration _config;
  19. public ISet<TCPHandler> Handlers { get; set; }
  20. public TCPRelay(ShadowsocksController controller, Configuration conf)
  21. {
  22. _controller = controller;
  23. _config = conf;
  24. Handlers = new HashSet<TCPHandler>();
  25. _lastSweepTime = DateTime.Now;
  26. }
  27. public override bool Handle(byte[] firstPacket, int length, Socket socket, object state)
  28. {
  29. if (socket.ProtocolType != ProtocolType.Tcp
  30. || (length < 2 || firstPacket[0] != 5))
  31. return false;
  32. socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
  33. TCPHandler handler = new TCPHandler(_controller, _config, this, socket);
  34. IList<TCPHandler> handlersToClose = new List<TCPHandler>();
  35. lock (Handlers)
  36. {
  37. Handlers.Add(handler);
  38. DateTime now = DateTime.Now;
  39. if (now - _lastSweepTime > TimeSpan.FromSeconds(1))
  40. {
  41. _lastSweepTime = now;
  42. foreach (TCPHandler handler1 in Handlers)
  43. if (now - handler1.lastActivity > TimeSpan.FromSeconds(900))
  44. handlersToClose.Add(handler1);
  45. }
  46. }
  47. foreach (TCPHandler handler1 in handlersToClose)
  48. {
  49. Logging.Debug("Closing timed out TCP connection.");
  50. handler1.Close();
  51. }
  52. /*
  53. * Start after we put it into Handlers set. Otherwise if it failed in handler.Start()
  54. * then it will call handler.Close() before we add it into the set.
  55. * Then the handler will never release until the next Handle call. Sometimes it will
  56. * cause odd problems (especially during memory profiling).
  57. */
  58. handler.Start(firstPacket, length);
  59. return true;
  60. }
  61. public override void Stop()
  62. {
  63. List<TCPHandler> handlersToClose = new List<TCPHandler>();
  64. lock (Handlers)
  65. {
  66. handlersToClose.AddRange(Handlers);
  67. }
  68. handlersToClose.ForEach(h=>h.Close());
  69. }
  70. public void UpdateInboundCounter(Server server, long n)
  71. {
  72. _controller.UpdateInboundCounter(server, n);
  73. }
  74. public void UpdateOutboundCounter(Server server, long n)
  75. {
  76. _controller.UpdateOutboundCounter(server, n);
  77. }
  78. public void UpdateLatency(Server server, TimeSpan latency)
  79. {
  80. _controller.UpdateLatency(server, latency);
  81. }
  82. }
  83. class TCPHandler
  84. {
  85. class AsyncSession
  86. {
  87. public IForwardProxy Remote { get; }
  88. public AsyncSession(IForwardProxy remote)
  89. {
  90. Remote = remote;
  91. }
  92. }
  93. class AsyncSession<T> : AsyncSession
  94. {
  95. public T State { get; set; }
  96. public AsyncSession(IForwardProxy remote, T state) : base(remote)
  97. {
  98. State = state;
  99. }
  100. public AsyncSession(AsyncSession session, T state): base(session.Remote)
  101. {
  102. State = state;
  103. }
  104. }
  105. private readonly int _serverTimeout;
  106. private readonly int _proxyTimeout;
  107. // Size of receive buffer.
  108. public static readonly int RecvSize = 8192;
  109. public static readonly int RecvReserveSize = IVEncryptor.ONETIMEAUTH_BYTES + IVEncryptor.AUTH_BYTES; // reserve for one-time auth
  110. public static readonly int BufferSize = RecvSize + RecvReserveSize + 32;
  111. public DateTime lastActivity;
  112. private ShadowsocksController _controller;
  113. private Configuration _config;
  114. private TCPRelay _tcprelay;
  115. private Socket _connection;
  116. private IEncryptor _encryptor;
  117. private Server _server;
  118. private AsyncSession _currentRemoteSession;
  119. private bool _proxyConnected;
  120. private bool _destConnected;
  121. private byte _command;
  122. private byte[] _firstPacket;
  123. private int _firstPacketLength;
  124. private int _totalRead = 0;
  125. private int _totalWrite = 0;
  126. private byte[] _remoteRecvBuffer = new byte[BufferSize];
  127. private byte[] _remoteSendBuffer = new byte[BufferSize];
  128. private byte[] _connetionRecvBuffer = new byte[BufferSize];
  129. private byte[] _connetionSendBuffer = new byte[BufferSize];
  130. private bool _connectionShutdown = false;
  131. private bool _remoteShutdown = false;
  132. private bool _closed = false;
  133. // instance-based lock without static
  134. private readonly object _encryptionLock = new object();
  135. private readonly object _decryptionLock = new object();
  136. private readonly object _closeConnLock = new object();
  137. private DateTime _startConnectTime;
  138. private DateTime _startReceivingTime;
  139. private DateTime _startSendingTime;
  140. private EndPoint _destEndPoint = null;
  141. public TCPHandler(ShadowsocksController controller, Configuration config, TCPRelay tcprelay, Socket socket)
  142. {
  143. _controller = controller;
  144. _config = config;
  145. _tcprelay = tcprelay;
  146. _connection = socket;
  147. _proxyTimeout = config.proxy.proxyTimeout * 1000;
  148. _serverTimeout = config.GetCurrentServer().timeout * 1000;
  149. lastActivity = DateTime.Now;
  150. }
  151. public void CreateRemote()
  152. {
  153. Server server = _controller.GetAServer(IStrategyCallerType.TCP, (IPEndPoint)_connection.RemoteEndPoint, _destEndPoint);
  154. if (server == null || server.server == "")
  155. throw new ArgumentException("No server configured");
  156. lock (_encryptionLock)
  157. {
  158. lock (_decryptionLock)
  159. {
  160. _encryptor = EncryptorFactory.GetEncryptor(server.method, server.password, server.auth, false);
  161. }
  162. }
  163. this._server = server;
  164. }
  165. public void Start(byte[] firstPacket, int length)
  166. {
  167. _firstPacket = firstPacket;
  168. _firstPacketLength = length;
  169. HandshakeReceive();
  170. }
  171. private void CheckClose()
  172. {
  173. if (_connectionShutdown && _remoteShutdown)
  174. Close();
  175. }
  176. public void Close()
  177. {
  178. lock (_closeConnLock)
  179. {
  180. if (_closed) return;
  181. _closed = true;
  182. }
  183. lock (_tcprelay.Handlers)
  184. {
  185. _tcprelay.Handlers.Remove(this);
  186. }
  187. try
  188. {
  189. _connection.Shutdown(SocketShutdown.Both);
  190. _connection.Close();
  191. }
  192. catch (Exception e)
  193. {
  194. Logging.LogUsefulException(e);
  195. }
  196. if (_currentRemoteSession != null)
  197. {
  198. try
  199. {
  200. var remote = _currentRemoteSession.Remote;
  201. remote.Shutdown(SocketShutdown.Both);
  202. remote.Close();
  203. }
  204. catch (Exception e)
  205. {
  206. Logging.LogUsefulException(e);
  207. }
  208. }
  209. lock (_encryptionLock)
  210. {
  211. lock (_decryptionLock)
  212. {
  213. _encryptor?.Dispose();
  214. }
  215. }
  216. }
  217. private void HandshakeReceive()
  218. {
  219. if (_closed) return;
  220. try
  221. {
  222. int bytesRead = _firstPacketLength;
  223. if (bytesRead > 1)
  224. {
  225. byte[] response = { 5, 0 };
  226. if (_firstPacket[0] != 5)
  227. {
  228. // reject socks 4
  229. response = new byte[] { 0, 91 };
  230. Logging.Error("socks 5 protocol error");
  231. }
  232. _connection.BeginSend(response, 0, response.Length, SocketFlags.None, new AsyncCallback(HandshakeSendCallback), null);
  233. }
  234. else
  235. Close();
  236. }
  237. catch (Exception e)
  238. {
  239. Logging.LogUsefulException(e);
  240. Close();
  241. }
  242. }
  243. private void HandshakeSendCallback(IAsyncResult ar)
  244. {
  245. if (_closed) return;
  246. try
  247. {
  248. _connection.EndSend(ar);
  249. // +-----+-----+-------+------+----------+----------+
  250. // | VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
  251. // +-----+-----+-------+------+----------+----------+
  252. // | 1 | 1 | X'00' | 1 | Variable | 2 |
  253. // +-----+-----+-------+------+----------+----------+
  254. // Skip first 3 bytes, and read 2 more bytes to analysis the address.
  255. // 2 more bytes is designed if address is domain then we don't need to read once more to get the addr length.
  256. // TODO validate
  257. _connection.BeginReceive(_connetionRecvBuffer, 0, 3 + 2, SocketFlags.None,
  258. new AsyncCallback(handshakeReceive2Callback), null);
  259. }
  260. catch (Exception e)
  261. {
  262. Logging.LogUsefulException(e);
  263. Close();
  264. }
  265. }
  266. private void handshakeReceive2Callback(IAsyncResult ar)
  267. {
  268. if (_closed) return;
  269. try
  270. {
  271. int bytesRead = _connection.EndReceive(ar);
  272. if (bytesRead >= 5)
  273. {
  274. _command = _connetionRecvBuffer[1];
  275. if (_command != 1 && _command != 3)
  276. {
  277. Logging.Debug("Unsupported CMD=" + _command);
  278. Close();
  279. }
  280. else
  281. {
  282. int atyp = _connetionRecvBuffer[3];
  283. switch (atyp)
  284. {
  285. case 1: // IPv4 address, 4 bytes
  286. ReadAddress(4 + 2 - 1);
  287. break;
  288. case 3: // domain name, length + str
  289. int len = _connetionRecvBuffer[4];
  290. ReadAddress(len + 2);
  291. break;
  292. case 4: // IPv6 address, 16 bytes
  293. ReadAddress(16 + 2 - 1);
  294. break;
  295. default:
  296. Logging.Debug("Unsupported ATYP=" + atyp);
  297. Close();
  298. break;
  299. }
  300. }
  301. }
  302. else
  303. {
  304. Logging.Debug("failed to recv data in Shadowsocks.Controller.TCPHandler.handshakeReceive2Callback()");
  305. Close();
  306. }
  307. }
  308. catch (Exception e)
  309. {
  310. Logging.LogUsefulException(e);
  311. Close();
  312. }
  313. }
  314. private void ReadAddress(int bytesRemain)
  315. {
  316. Array.Copy(_connetionRecvBuffer, 3, _connetionRecvBuffer, 0, 2);
  317. // Read the remain address bytes
  318. _connection.BeginReceive(_connetionRecvBuffer, 2, RecvSize - 2, SocketFlags.None, OnAddressFullyRead, bytesRemain);
  319. }
  320. private void OnAddressFullyRead(IAsyncResult ar)
  321. {
  322. if (_closed) return;
  323. try
  324. {
  325. int bytesRead = _connection.EndReceive(ar);
  326. int bytesRemain = (int) ar.AsyncState;
  327. if (bytesRead >= bytesRemain)
  328. {
  329. _firstPacketLength = bytesRead + 2;
  330. int atyp = _connetionRecvBuffer[0];
  331. string dst_addr = "Unknown";
  332. int dst_port = -1;
  333. switch (atyp)
  334. {
  335. case 1: // IPv4 address, 4 bytes
  336. dst_addr = new IPAddress(_connetionRecvBuffer.Skip(1).Take(4).ToArray()).ToString();
  337. dst_port = (_connetionRecvBuffer[5] << 8) + _connetionRecvBuffer[6];
  338. break;
  339. case 3: // domain name, length + str
  340. int len = _connetionRecvBuffer[1];
  341. dst_addr = System.Text.Encoding.UTF8.GetString(_connetionRecvBuffer, 2, len);
  342. dst_port = (_connetionRecvBuffer[len + 2] << 8) + _connetionRecvBuffer[len + 3];
  343. break;
  344. case 4: // IPv6 address, 16 bytes
  345. dst_addr = $"[{new IPAddress(_connetionRecvBuffer.Skip(1).Take(16).ToArray())}]";
  346. dst_port = (_connetionRecvBuffer[17] << 8) + _connetionRecvBuffer[18];
  347. break;
  348. }
  349. if (_config.isVerboseLogging)
  350. {
  351. Logging.Info($"connect to {dst_addr}:{dst_port}");
  352. }
  353. _destEndPoint = SocketUtil.GetEndPoint(dst_addr, dst_port);
  354. if (_command == 1)
  355. {
  356. byte[] response = {5, 0, 0, 1, 0, 0, 0, 0, 0, 0};
  357. _connection.BeginSend(response, 0, response.Length, SocketFlags.None,
  358. new AsyncCallback(ResponseCallback), null);
  359. }
  360. else if (_command == 3)
  361. {
  362. HandleUDPAssociate();
  363. }
  364. }
  365. else
  366. {
  367. Logging.Debug("failed to recv data in Shadowsocks.Controller.TCPHandler.OnAddressFullyRead()");
  368. Close();
  369. }
  370. }
  371. catch (Exception e)
  372. {
  373. Logging.LogUsefulException(e);
  374. Close();
  375. }
  376. }
  377. private void HandleUDPAssociate()
  378. {
  379. IPEndPoint endPoint = (IPEndPoint)_connection.LocalEndPoint;
  380. byte[] address = endPoint.Address.GetAddressBytes();
  381. int port = endPoint.Port;
  382. byte[] response = new byte[4 + address.Length + 2];
  383. response[0] = 5;
  384. switch (endPoint.AddressFamily)
  385. {
  386. case AddressFamily.InterNetwork:
  387. response[3] = 1;
  388. break;
  389. case AddressFamily.InterNetworkV6:
  390. response[3] = 4;
  391. break;
  392. }
  393. address.CopyTo(response, 4);
  394. response[response.Length - 1] = (byte)(port & 0xFF);
  395. response[response.Length - 2] = (byte)((port >> 8) & 0xFF);
  396. _connection.BeginSend(response, 0, response.Length, SocketFlags.None, new AsyncCallback(ReadAll), true);
  397. }
  398. private void ReadAll(IAsyncResult ar)
  399. {
  400. if (_closed) return;
  401. try
  402. {
  403. if (ar.AsyncState != null)
  404. {
  405. _connection.EndSend(ar);
  406. _connection.BeginReceive(_connetionRecvBuffer, 0, RecvSize, SocketFlags.None, new AsyncCallback(ReadAll), null);
  407. }
  408. else
  409. {
  410. int bytesRead = _connection.EndReceive(ar);
  411. if (bytesRead > 0)
  412. {
  413. _connection.BeginReceive(_connetionRecvBuffer, 0, RecvSize, SocketFlags.None, new AsyncCallback(ReadAll), null);
  414. }
  415. else
  416. Close();
  417. }
  418. }
  419. catch (Exception e)
  420. {
  421. Logging.LogUsefulException(e);
  422. Close();
  423. }
  424. }
  425. private void ResponseCallback(IAsyncResult ar)
  426. {
  427. try
  428. {
  429. _connection.EndSend(ar);
  430. StartConnect();
  431. }
  432. catch (Exception e)
  433. {
  434. Logging.LogUsefulException(e);
  435. Close();
  436. }
  437. }
  438. // inner class
  439. private class ProxyTimer : Timer
  440. {
  441. public AsyncSession Session;
  442. public EndPoint DestEndPoint;
  443. public Server Server;
  444. public ProxyTimer(int p) : base(p)
  445. {
  446. }
  447. }
  448. private class ServerTimer : Timer
  449. {
  450. public AsyncSession Session;
  451. public Server Server;
  452. public ServerTimer(int p) : base(p) { }
  453. }
  454. private void StartConnect()
  455. {
  456. try
  457. {
  458. CreateRemote();
  459. // Setting up proxy
  460. IForwardProxy remote;
  461. EndPoint proxyEP;
  462. if (_config.proxy.useProxy)
  463. {
  464. switch (_config.proxy.proxyType)
  465. {
  466. case ProxyConfig.PROXY_SOCKS5:
  467. remote = new Socks5Proxy();
  468. break;
  469. case ProxyConfig.PROXY_HTTP:
  470. remote = new HttpProxy();
  471. break;
  472. default:
  473. throw new NotSupportedException("Unknown forward proxy.");
  474. }
  475. proxyEP = SocketUtil.GetEndPoint(_config.proxy.proxyServer, _config.proxy.proxyPort);
  476. }
  477. else
  478. {
  479. remote = new DirectConnect();
  480. proxyEP = null;
  481. }
  482. var session = new AsyncSession(remote);
  483. lock (_closeConnLock)
  484. {
  485. if (Closed)
  486. {
  487. remote.Close();
  488. return;
  489. }
  490. _currentRemoteSession = session;
  491. }
  492. ProxyTimer proxyTimer = new ProxyTimer(_proxyTimeout);
  493. proxyTimer.AutoReset = false;
  494. proxyTimer.Elapsed += proxyConnectTimer_Elapsed;
  495. proxyTimer.Enabled = true;
  496. proxyTimer.Session = session;
  497. proxyTimer.DestEndPoint = SocketUtil.GetEndPoint(_server.server, _server.server_port);
  498. proxyTimer.Server = _server;
  499. _proxyConnected = false;
  500. // Connect to the proxy server.
  501. remote.BeginConnectProxy(proxyEP, new AsyncCallback(ProxyConnectCallback), new AsyncSession<ProxyTimer>(remote, proxyTimer));
  502. }
  503. catch (Exception e)
  504. {
  505. Logging.LogUsefulException(e);
  506. Close();
  507. }
  508. }
  509. private void proxyConnectTimer_Elapsed(object sender, ElapsedEventArgs e)
  510. {
  511. var timer = (ProxyTimer) sender;
  512. timer.Elapsed -= proxyConnectTimer_Elapsed;
  513. timer.Enabled = false;
  514. timer.Dispose();
  515. if (_proxyConnected || _destConnected || _closed)
  516. {
  517. return;
  518. }
  519. var proxy = timer.Session.Remote;
  520. Logging.Info($"Proxy {proxy.ProxyEndPoint} timed out");
  521. proxy.Close();
  522. Close();
  523. }
  524. private void ProxyConnectCallback(IAsyncResult ar)
  525. {
  526. Server server = null;
  527. if (_closed)
  528. {
  529. return;
  530. }
  531. try
  532. {
  533. var session = (AsyncSession<ProxyTimer>) ar.AsyncState;
  534. ProxyTimer timer = session.State;
  535. var destEndPoint = timer.DestEndPoint;
  536. server = timer.Server;
  537. timer.Elapsed -= proxyConnectTimer_Elapsed;
  538. timer.Enabled = false;
  539. timer.Dispose();
  540. var remote = session.Remote;
  541. // Complete the connection.
  542. remote.EndConnectProxy(ar);
  543. _proxyConnected = true;
  544. if (_config.isVerboseLogging)
  545. {
  546. if (!(remote is DirectConnect))
  547. {
  548. Logging.Info($"Socket connected to proxy {remote.ProxyEndPoint}");
  549. }
  550. }
  551. _startConnectTime = DateTime.Now;
  552. ServerTimer connectTimer = new ServerTimer(_serverTimeout);
  553. connectTimer.AutoReset = false;
  554. connectTimer.Elapsed += destConnectTimer_Elapsed;
  555. connectTimer.Enabled = true;
  556. connectTimer.Session = session;
  557. connectTimer.Server = server;
  558. _destConnected = false;
  559. // Connect to the remote endpoint.
  560. remote.BeginConnectDest(destEndPoint, new AsyncCallback(ConnectCallback), new AsyncSession<ServerTimer>(session, connectTimer));
  561. }
  562. catch (ArgumentException)
  563. {
  564. }
  565. catch (Exception e)
  566. {
  567. Logging.LogUsefulException(e);
  568. Close();
  569. }
  570. }
  571. private void destConnectTimer_Elapsed(object sender, ElapsedEventArgs e)
  572. {
  573. var timer = (ServerTimer)sender;
  574. timer.Elapsed -= destConnectTimer_Elapsed;
  575. timer.Enabled = false;
  576. timer.Dispose();
  577. if (_destConnected || _closed)
  578. {
  579. return;
  580. }
  581. var session = timer.Session;
  582. Server server = timer.Server;
  583. IStrategy strategy = _controller.GetCurrentStrategy();
  584. strategy?.SetFailure(server);
  585. Logging.Info($"{server.FriendlyName()} timed out");
  586. session.Remote.Close();
  587. Close();
  588. }
  589. private void ConnectCallback(IAsyncResult ar)
  590. {
  591. if (_closed) return;
  592. try
  593. {
  594. var session = (AsyncSession<ServerTimer>) ar.AsyncState;
  595. ServerTimer timer = session.State;
  596. _server = timer.Server;
  597. timer.Elapsed -= destConnectTimer_Elapsed;
  598. timer.Enabled = false;
  599. timer.Dispose();
  600. var remote = session.Remote;
  601. // Complete the connection.
  602. remote.EndConnectDest(ar);
  603. _destConnected = true;
  604. if (_config.isVerboseLogging)
  605. {
  606. Logging.Info($"Socket connected to ss server: {_server.FriendlyName()}");
  607. }
  608. var latency = DateTime.Now - _startConnectTime;
  609. IStrategy strategy = _controller.GetCurrentStrategy();
  610. strategy?.UpdateLatency(_server, latency);
  611. _tcprelay.UpdateLatency(_server, latency);
  612. StartPipe(session);
  613. }
  614. catch (ArgumentException)
  615. {
  616. }
  617. catch (Exception e)
  618. {
  619. if (_server != null)
  620. {
  621. IStrategy strategy = _controller.GetCurrentStrategy();
  622. strategy?.SetFailure(_server);
  623. }
  624. Logging.LogUsefulException(e);
  625. Close();
  626. }
  627. }
  628. private void StartPipe(AsyncSession session)
  629. {
  630. if (_closed) return;
  631. try
  632. {
  633. _startReceivingTime = DateTime.Now;
  634. session.Remote.BeginReceive(_remoteRecvBuffer, 0, RecvSize, SocketFlags.None, new AsyncCallback(PipeRemoteReceiveCallback), session);
  635. SendToServer(_firstPacketLength, session);
  636. }
  637. catch (Exception e)
  638. {
  639. Logging.LogUsefulException(e);
  640. Close();
  641. }
  642. }
  643. private void PipeRemoteReceiveCallback(IAsyncResult ar)
  644. {
  645. if (_closed) return;
  646. try
  647. {
  648. var session = (AsyncSession) ar.AsyncState;
  649. int bytesRead = session.Remote.EndReceive(ar);
  650. _totalRead += bytesRead;
  651. _tcprelay.UpdateInboundCounter(_server, bytesRead);
  652. if (bytesRead > 0)
  653. {
  654. lastActivity = DateTime.Now;
  655. int bytesToSend;
  656. lock (_decryptionLock)
  657. {
  658. _encryptor.Decrypt(_remoteRecvBuffer, bytesRead, _remoteSendBuffer, out bytesToSend);
  659. }
  660. _connection.BeginSend(_remoteSendBuffer, 0, bytesToSend, SocketFlags.None, new AsyncCallback(PipeConnectionSendCallback), session);
  661. IStrategy strategy = _controller.GetCurrentStrategy();
  662. strategy?.UpdateLastRead(_server);
  663. }
  664. else
  665. {
  666. _connection.Shutdown(SocketShutdown.Send);
  667. _connectionShutdown = true;
  668. CheckClose();
  669. }
  670. }
  671. catch (Exception e)
  672. {
  673. Logging.LogUsefulException(e);
  674. Close();
  675. }
  676. }
  677. private void PipeConnectionReceiveCallback(IAsyncResult ar)
  678. {
  679. if (_closed) return;
  680. try
  681. {
  682. int bytesRead = _connection.EndReceive(ar);
  683. var session = (AsyncSession) ar.AsyncState;
  684. var remote = session.Remote;
  685. if (bytesRead > 0)
  686. {
  687. SendToServer(bytesRead, session);
  688. }
  689. else
  690. {
  691. remote.Shutdown(SocketShutdown.Send);
  692. _remoteShutdown = true;
  693. CheckClose();
  694. }
  695. }
  696. catch (Exception e)
  697. {
  698. Logging.LogUsefulException(e);
  699. Close();
  700. }
  701. }
  702. private void SendToServer(int length, AsyncSession session)
  703. {
  704. _totalWrite += length;
  705. int bytesToSend;
  706. lock (_encryptionLock)
  707. {
  708. _encryptor.Encrypt(_connetionRecvBuffer, length, _connetionSendBuffer, out bytesToSend);
  709. }
  710. _tcprelay.UpdateOutboundCounter(_server, bytesToSend);
  711. _startSendingTime = DateTime.Now;
  712. session.Remote.BeginSend(_connetionSendBuffer, 0, bytesToSend, SocketFlags.None, new AsyncCallback(PipeRemoteSendCallback), session);
  713. IStrategy strategy = _controller.GetCurrentStrategy();
  714. strategy?.UpdateLastWrite(_server);
  715. }
  716. private void PipeRemoteSendCallback(IAsyncResult ar)
  717. {
  718. if (_closed) return;
  719. try
  720. {
  721. var session = (AsyncSession)ar.AsyncState;
  722. session.Remote.EndSend(ar);
  723. _connection.BeginReceive(_connetionRecvBuffer, 0, RecvSize, SocketFlags.None, new AsyncCallback(PipeConnectionReceiveCallback), session);
  724. }
  725. catch (Exception e)
  726. {
  727. Logging.LogUsefulException(e);
  728. Close();
  729. }
  730. }
  731. private void PipeConnectionSendCallback(IAsyncResult ar)
  732. {
  733. try
  734. {
  735. var session = (AsyncSession)ar.AsyncState;
  736. _connection.EndSend(ar);
  737. session.Remote.BeginReceive(_remoteRecvBuffer, 0, RecvSize, SocketFlags.None, new AsyncCallback(PipeRemoteReceiveCallback), session);
  738. }
  739. catch (Exception e)
  740. {
  741. Logging.LogUsefulException(e);
  742. Close();
  743. }
  744. }
  745. }
  746. }