Connection.cs 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.IO;
  4. using System.Net.Sockets;
  5. using System.Threading;
  6. namespace Mirror.SimpleWeb
  7. {
  8. internal sealed class Connection : IDisposable
  9. {
  10. public const int IdNotSet = -1;
  11. readonly object disposedLock = new object();
  12. public TcpClient client;
  13. public int connId = IdNotSet;
  14. public Stream stream;
  15. public Thread receiveThread;
  16. public Thread sendThread;
  17. public ManualResetEventSlim sendPending = new ManualResetEventSlim(false);
  18. public ConcurrentQueue<ArrayBuffer> sendQueue = new ConcurrentQueue<ArrayBuffer>();
  19. public Action<Connection> onDispose;
  20. volatile bool hasDisposed;
  21. public Connection(TcpClient client, Action<Connection> onDispose)
  22. {
  23. this.client = client ?? throw new ArgumentNullException(nameof(client));
  24. this.onDispose = onDispose;
  25. }
  26. /// <summary>
  27. /// disposes client and stops threads
  28. /// </summary>
  29. public void Dispose()
  30. {
  31. Log.Verbose($"Dispose {ToString()}");
  32. // check hasDisposed first to stop ThreadInterruptedException on lock
  33. if (hasDisposed) { return; }
  34. Log.Info($"Connection Close: {ToString()}");
  35. lock (disposedLock)
  36. {
  37. // check hasDisposed again inside lock to make sure no other object has called this
  38. if (hasDisposed) { return; }
  39. hasDisposed = true;
  40. // stop threads first so they don't try to use disposed objects
  41. receiveThread.Interrupt();
  42. sendThread?.Interrupt();
  43. try
  44. {
  45. // stream
  46. stream?.Dispose();
  47. stream = null;
  48. client.Dispose();
  49. client = null;
  50. }
  51. catch (Exception e)
  52. {
  53. Log.Exception(e);
  54. }
  55. sendPending.Dispose();
  56. // release all buffers in send queue
  57. while (sendQueue.TryDequeue(out ArrayBuffer buffer))
  58. {
  59. buffer.Release();
  60. }
  61. onDispose.Invoke(this);
  62. }
  63. }
  64. public override string ToString()
  65. {
  66. System.Net.EndPoint endpoint = client?.Client?.RemoteEndPoint;
  67. return $"[Conn:{connId}, endPoint:{endpoint}]";
  68. }
  69. }
  70. }