DirectTcpProxy.cs 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. using Microsoft;
  2. using Pipelines.Extensions;
  3. using System.IO.Pipelines;
  4. using System.Net;
  5. using System.Net.Sockets;
  6. namespace STUN.Proxy;
  7. public class DirectTcpProxy : ITcpProxy, IDisposableObservable
  8. {
  9. public IPEndPoint? CurrentLocalEndPoint
  10. {
  11. get
  12. {
  13. Verify.NotDisposed(this);
  14. return _tcpClient?.Client.LocalEndPoint as IPEndPoint;
  15. }
  16. }
  17. private TcpClient? _tcpClient;
  18. public async ValueTask<IDuplexPipe> ConnectAsync(IPEndPoint local, IPEndPoint dst, CancellationToken cancellationToken = default)
  19. {
  20. Verify.NotDisposed(this);
  21. Requires.NotNull(local, nameof(local));
  22. Requires.NotNull(dst, nameof(dst));
  23. await CloseAsync(cancellationToken);
  24. _tcpClient = new TcpClient(local) { NoDelay = true };
  25. await _tcpClient.ConnectAsync(dst, cancellationToken);
  26. return _tcpClient.Client.AsDuplexPipe();
  27. }
  28. public ValueTask CloseAsync(CancellationToken cancellationToken = default)
  29. {
  30. Verify.NotDisposed(this);
  31. if (_tcpClient is not null)
  32. {
  33. CloseClient();
  34. _tcpClient = default;
  35. }
  36. return default;
  37. }
  38. private void CloseClient()
  39. {
  40. if (_tcpClient is null)
  41. {
  42. return;
  43. }
  44. _tcpClient.Client.Close(0);
  45. _tcpClient.Dispose();
  46. }
  47. public bool IsDisposed { get; private set; }
  48. public void Dispose()
  49. {
  50. IsDisposed = true;
  51. CloseClient();
  52. GC.SuppressFinalize(this);
  53. }
  54. }