Channel.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. using System;
  2. using System.Net;
  3. using System.Threading.Tasks;
  4. using Vinno.IUS.Common.IO;
  5. namespace Vinno.IUS.Common.Network.Channels
  6. {
  7. public abstract class Channel: IChannel
  8. {
  9. private static readonly Random Random = new Random();
  10. private const byte MajorVersion = 2;
  11. private const byte MinorVersion = 1;
  12. private bool _closing;
  13. /// <summary>
  14. /// Gets the ChannelId for this Channel;
  15. /// </summary>
  16. public int Id { get; private set; }
  17. /// <summary>
  18. /// Gets if the Channel is Closed.
  19. /// </summary>
  20. public bool IsClosed { get; protected set; }
  21. /// <summary>
  22. /// Raised when channel was closed.
  23. /// </summary>
  24. public event EventHandler Closed;
  25. /// <summary>
  26. /// Gets the Remote host info, for Server, this property means client, for client, this property
  27. /// means server.
  28. /// </summary>
  29. public IPEndPoint Remote { get; set; }
  30. /// <summary>
  31. /// Gets the Local host info, for Server, this property means server, for client, this property
  32. /// means client.
  33. /// </summary>
  34. public IPEndPoint Local { get; set; }
  35. public Channel(int channelId)
  36. {
  37. Id = channelId;
  38. }
  39. /// <summary>
  40. /// Update the channel's Id.
  41. /// </summary>
  42. /// <param name="channelId"></param>
  43. public void UpdateChannelId(int channelId)
  44. {
  45. Id = channelId;
  46. }
  47. protected void ValidateHeader(byte[] headerData)
  48. {
  49. if (headerData.Length != 8)
  50. {
  51. throw new ErrorDataException("Head data length error.");
  52. }
  53. var versionData = new byte[2];
  54. var xyData = new byte[2];
  55. var zData = new short[1];
  56. Buffer.BlockCopy(headerData, 0, versionData, 0, versionData.Length);
  57. if (versionData[0] != MajorVersion)
  58. {
  59. throw new ErrorDataException("Major version not match.");
  60. }
  61. Buffer.BlockCopy(headerData, 4, xyData, 0, xyData.Length);
  62. Buffer.BlockCopy(headerData, 6, zData, 0, zData.Length * sizeof(short));
  63. var x = xyData[0];
  64. var y = xyData[1];
  65. var z = zData[0];
  66. //Calc to see if is valid data.
  67. if (z != x * 2 + y * 2 - (x - y))
  68. {
  69. throw new ErrorDataException("Xyz data error.");
  70. }
  71. }
  72. protected byte[] GetHeaderData()
  73. {
  74. var headerData = new byte[8];
  75. var versionData = new[] { MajorVersion, MinorVersion };
  76. var x = (byte)Random.Next(byte.MaxValue);
  77. var y = (byte)Random.Next(byte.MaxValue);
  78. var z = (short)(x * 2 + y * 2 - (x - y));
  79. var xyData = new[] { x, y };
  80. var zData = new[] { z };
  81. Buffer.BlockCopy(versionData, 0, headerData, 0, versionData.Length);
  82. Buffer.BlockCopy(xyData, 0, headerData, 4, xyData.Length);
  83. Buffer.BlockCopy(zData, 0, headerData, 6, zData.Length * sizeof(short));
  84. return headerData;
  85. }
  86. /// <summary>
  87. /// Read and validate the header from remote.
  88. /// </summary>
  89. /// <param name="timeout">Wait forever if the value is 0</param>
  90. protected abstract void ReadHeader(int timeout = 0);
  91. /// <summary>
  92. /// run task
  93. /// </summary>
  94. /// <returns></returns>
  95. protected virtual async Task ReadHeaderAsync(int timeout = 0)
  96. {
  97. await Task.Run(() => { });
  98. }
  99. /// <summary>
  100. /// Write the header before write buffer.
  101. /// </summary>
  102. /// <param name="timeout">Wait forever if the value is 0</param>
  103. protected abstract void WriteHeader(int timeout = 0);
  104. /// <summary>
  105. /// Write the header before write buffer by async way.
  106. /// </summary>
  107. /// <param name="timeout">Wait forever if the value is 0</param>
  108. protected virtual async Task WriteHeaderAsync(int timeout = 0)
  109. {
  110. await Task.Run(() => { });
  111. }
  112. /// <summary>
  113. /// Close the channel, and raise the event of close.
  114. /// </summary>
  115. public virtual void Close()
  116. {
  117. if (!_closing)
  118. {
  119. _closing = true;
  120. IsClosed = true;
  121. OnClosed();
  122. _closing = false;
  123. }
  124. }
  125. protected virtual void OnClosed()
  126. {
  127. Closed?.Invoke(this, EventArgs.Empty);
  128. }
  129. }
  130. }