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 26 kB

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