DtlsTransport.cs 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.IO;
  5. using System.Net.Sockets;
  6. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Tls
  7. {
  8. public class DtlsTransport
  9. : DatagramTransport
  10. {
  11. private readonly DtlsRecordLayer m_recordLayer;
  12. private readonly bool m_ignoreCorruptRecords;
  13. internal DtlsTransport(DtlsRecordLayer recordLayer, bool ignoreCorruptRecords)
  14. {
  15. m_recordLayer = recordLayer;
  16. m_ignoreCorruptRecords = ignoreCorruptRecords;
  17. }
  18. /// <exception cref="IOException"/>
  19. public virtual int GetReceiveLimit()
  20. {
  21. return m_recordLayer.GetReceiveLimit();
  22. }
  23. /// <exception cref="IOException"/>
  24. public virtual int GetSendLimit()
  25. {
  26. return m_recordLayer.GetSendLimit();
  27. }
  28. /// <exception cref="IOException"/>
  29. public virtual int Receive(byte[] buf, int off, int len, int waitMillis)
  30. {
  31. if (null == buf)
  32. throw new ArgumentNullException("buf");
  33. if (off < 0 || off >= buf.Length)
  34. throw new ArgumentException("invalid offset: " + off, "off");
  35. if (len < 0 || len > buf.Length - off)
  36. throw new ArgumentException("invalid length: " + len, "len");
  37. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  38. return Receive(buf.AsSpan(off, len), waitMillis);
  39. #else
  40. if (waitMillis < 0)
  41. throw new ArgumentException("cannot be negative", "waitMillis");
  42. try
  43. {
  44. return m_recordLayer.Receive(buf, off, len, waitMillis);
  45. }
  46. catch (TlsFatalAlert fatalAlert)
  47. {
  48. if (m_ignoreCorruptRecords && AlertDescription.bad_record_mac == fatalAlert.AlertDescription)
  49. return -1;
  50. m_recordLayer.Fail(fatalAlert.AlertDescription);
  51. throw fatalAlert;
  52. }
  53. catch (TlsTimeoutException e)
  54. {
  55. throw e;
  56. }
  57. catch (SocketException e)
  58. {
  59. if (TlsUtilities.IsTimeout(e))
  60. throw e;
  61. m_recordLayer.Fail(AlertDescription.internal_error);
  62. throw new TlsFatalAlert(AlertDescription.internal_error, e);
  63. }
  64. // TODO[tls-port] Can we support interrupted IO on .NET?
  65. //catch (InterruptedIOException e)
  66. //{
  67. // throw e;
  68. //}
  69. catch (IOException e)
  70. {
  71. m_recordLayer.Fail(AlertDescription.internal_error);
  72. throw e;
  73. }
  74. catch (Exception e)
  75. {
  76. m_recordLayer.Fail(AlertDescription.internal_error);
  77. throw new TlsFatalAlert(AlertDescription.internal_error, e);
  78. }
  79. #endif
  80. }
  81. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  82. /// <exception cref="IOException"/>
  83. public virtual int Receive(Span<byte> buffer, int waitMillis)
  84. {
  85. if (waitMillis < 0)
  86. throw new ArgumentException("cannot be negative", nameof(waitMillis));
  87. try
  88. {
  89. return m_recordLayer.Receive(buffer, waitMillis);
  90. }
  91. catch (TlsFatalAlert fatalAlert)
  92. {
  93. if (m_ignoreCorruptRecords && AlertDescription.bad_record_mac == fatalAlert.AlertDescription)
  94. return -1;
  95. m_recordLayer.Fail(fatalAlert.AlertDescription);
  96. throw fatalAlert;
  97. }
  98. catch (TlsTimeoutException e)
  99. {
  100. throw e;
  101. }
  102. catch (SocketException e)
  103. {
  104. if (TlsUtilities.IsTimeout(e))
  105. throw e;
  106. m_recordLayer.Fail(AlertDescription.internal_error);
  107. throw new TlsFatalAlert(AlertDescription.internal_error, e);
  108. }
  109. // TODO[tls-port] Can we support interrupted IO on .NET?
  110. //catch (InterruptedIOException e)
  111. //{
  112. // throw e;
  113. //}
  114. catch (IOException e)
  115. {
  116. m_recordLayer.Fail(AlertDescription.internal_error);
  117. throw e;
  118. }
  119. catch (Exception e)
  120. {
  121. m_recordLayer.Fail(AlertDescription.internal_error);
  122. throw new TlsFatalAlert(AlertDescription.internal_error, e);
  123. }
  124. }
  125. #endif
  126. /// <exception cref="IOException"/>
  127. public virtual void Send(byte[] buf, int off, int len)
  128. {
  129. if (null == buf)
  130. throw new ArgumentNullException("buf");
  131. if (off < 0 || off >= buf.Length)
  132. throw new ArgumentException("invalid offset: " + off, "off");
  133. if (len < 0 || len > buf.Length - off)
  134. throw new ArgumentException("invalid length: " + len, "len");
  135. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  136. Send(buf.AsSpan(off, len));
  137. #else
  138. try
  139. {
  140. m_recordLayer.Send(buf, off, len);
  141. }
  142. catch (TlsFatalAlert fatalAlert)
  143. {
  144. m_recordLayer.Fail(fatalAlert.AlertDescription);
  145. throw fatalAlert;
  146. }
  147. catch (TlsTimeoutException e)
  148. {
  149. throw e;
  150. }
  151. catch (SocketException e)
  152. {
  153. if (TlsUtilities.IsTimeout(e))
  154. throw e;
  155. m_recordLayer.Fail(AlertDescription.internal_error);
  156. throw new TlsFatalAlert(AlertDescription.internal_error, e);
  157. }
  158. // TODO[tls-port] Can we support interrupted IO on .NET?
  159. //catch (InterruptedIOException e)
  160. //{
  161. // throw e;
  162. //}
  163. catch (IOException e)
  164. {
  165. m_recordLayer.Fail(AlertDescription.internal_error);
  166. throw e;
  167. }
  168. catch (Exception e)
  169. {
  170. m_recordLayer.Fail(AlertDescription.internal_error);
  171. throw new TlsFatalAlert(AlertDescription.internal_error, e);
  172. }
  173. #endif
  174. }
  175. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  176. public virtual void Send(ReadOnlySpan<byte> buffer)
  177. {
  178. try
  179. {
  180. m_recordLayer.Send(buffer);
  181. }
  182. catch (TlsFatalAlert fatalAlert)
  183. {
  184. m_recordLayer.Fail(fatalAlert.AlertDescription);
  185. throw fatalAlert;
  186. }
  187. catch (TlsTimeoutException e)
  188. {
  189. throw e;
  190. }
  191. catch (SocketException e)
  192. {
  193. if (TlsUtilities.IsTimeout(e))
  194. throw e;
  195. m_recordLayer.Fail(AlertDescription.internal_error);
  196. throw new TlsFatalAlert(AlertDescription.internal_error, e);
  197. }
  198. // TODO[tls-port] Can we support interrupted IO on .NET?
  199. //catch (InterruptedIOException e)
  200. //{
  201. // throw e;
  202. //}
  203. catch (IOException e)
  204. {
  205. m_recordLayer.Fail(AlertDescription.internal_error);
  206. throw e;
  207. }
  208. catch (Exception e)
  209. {
  210. m_recordLayer.Fail(AlertDescription.internal_error);
  211. throw new TlsFatalAlert(AlertDescription.internal_error, e);
  212. }
  213. }
  214. #endif
  215. /// <exception cref="IOException"/>
  216. public virtual void Close()
  217. {
  218. m_recordLayer.Close();
  219. }
  220. }
  221. }
  222. #pragma warning restore
  223. #endif