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