PageRenderTime 41ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/source/library/Interlace/ReactorCore/DatagramSocketConnection.cs

https://bitbucket.org/VahidN/interlace
C# | 228 lines | 159 code | 40 blank | 29 comment | 10 complexity | f43f6f6f9deb8c10a07b48906f5a1240 MD5 | raw file
  1. #region Using Directives and Copyright Notice
  2. // Copyright (c) 2007-2010, Computer Consultancy Pty Ltd
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are met:
  7. // * Redistributions of source code must retain the above copyright
  8. // notice, this list of conditions and the following disclaimer.
  9. // * Redistributions in binary form must reproduce the above copyright
  10. // notice, this list of conditions and the following disclaimer in the
  11. // documentation and/or other materials provided with the distribution.
  12. // * Neither the name of the Computer Consultancy Pty Ltd nor the
  13. // names of its contributors may be used to endorse or promote products
  14. // derived from this software without specific prior written permission.
  15. //
  16. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  17. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. // ARE DISCLAIMED. IN NO EVENT SHALL COMPUTER CONSULTANCY PTY LTD BE LIABLE
  20. // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21. // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  22. // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  23. // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24. // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25. // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  26. // DAMAGE.
  27. using System;
  28. using System.Collections.Generic;
  29. using System.Net;
  30. using System.Net.Sockets;
  31. using System.Text;
  32. #endregion
  33. namespace Interlace.ReactorCore
  34. {
  35. public class DatagramSocketConnection : SocketConnection
  36. {
  37. EndPoint _receiveEndpoint;
  38. bool _truncationOccurred = false;
  39. public DatagramSocketConnection(IReactor reactor, Protocol protocol)
  40. : base(reactor, protocol)
  41. {
  42. }
  43. public bool TruncationOccurred
  44. {
  45. get { return _truncationOccurred; }
  46. }
  47. bool IsTemporaryError(SocketError error)
  48. {
  49. switch (error)
  50. {
  51. case SocketError.ConnectionReset:
  52. case SocketError.ConnectionRefused:
  53. return true;
  54. default:
  55. return false;
  56. }
  57. }
  58. protected override void ContinueReceive()
  59. {
  60. IAsyncResult result;
  61. try
  62. {
  63. _receiveEndpoint = new IPEndPoint(IPAddress.Any, 0);
  64. result = _socket.BeginReceiveFrom(_receiveBuffer, 0,
  65. _receiveBuffer.Length, SocketFlags.None, ref _receiveEndpoint, null, null);
  66. }
  67. catch (SocketException ex)
  68. {
  69. // Some errors (for instance, the error from sending to a closed
  70. // port on localhost) should be ignored:
  71. if (IsTemporaryError(ex.SocketErrorCode))
  72. {
  73. ContinueReceive();
  74. return;
  75. }
  76. HandleSocketException(ex);
  77. return;
  78. }
  79. catch (ObjectDisposedException ex)
  80. {
  81. HandleSocketClosed(ex);
  82. return;
  83. }
  84. _reactor.AddResult(result, ReceiveCompleted);
  85. }
  86. void ReceiveCompleted(IAsyncResult result, object state)
  87. {
  88. int bytesReceived;
  89. try
  90. {
  91. bytesReceived = _socket.EndReceiveFrom(result, ref _receiveEndpoint);
  92. }
  93. catch (SocketException ex)
  94. {
  95. // Some errors (for instance, the error from sending to a closed
  96. // port on localhost) should be ignored:
  97. if (IsTemporaryError(ex.SocketErrorCode))
  98. {
  99. ContinueReceive();
  100. return;
  101. }
  102. HandleSocketException(ex);
  103. return;
  104. }
  105. catch (ObjectDisposedException ex)
  106. {
  107. HandleSocketClosed(ex);
  108. return;
  109. }
  110. try
  111. {
  112. _protocol.DataReceived(_receiveEndpoint as IPEndPoint, _receiveBuffer, 0, bytesReceived);
  113. _receiveEndpoint = null;
  114. }
  115. catch (Exception ex)
  116. {
  117. HandleProtocolException(ex);
  118. }
  119. ContinueReceive();
  120. }
  121. protected override void ContinueSend()
  122. {
  123. IAsyncResult result;
  124. try
  125. {
  126. if (_transmitBuffer.EndPointOrNull == null)
  127. {
  128. result = _socket.BeginSend(_transmitBuffer.Data.Array, _transmitBuffer.Data.Offset,
  129. _transmitBuffer.Data.Count, SocketFlags.None, null, null);
  130. }
  131. else
  132. {
  133. result = _socket.BeginSendTo(_transmitBuffer.Data.Array, _transmitBuffer.Data.Offset,
  134. _transmitBuffer.Data.Count, SocketFlags.None, _transmitBuffer.EndPointOrNull, null, null);
  135. }
  136. }
  137. catch (SocketException ex)
  138. {
  139. HandleSocketException(ex);
  140. return;
  141. }
  142. catch (ObjectDisposedException ex)
  143. {
  144. HandleSocketClosed(ex);
  145. return;
  146. }
  147. _reactor.AddResult(result, SendCompleted);
  148. }
  149. void SendCompleted(IAsyncResult result, object state)
  150. {
  151. int bytesSent;
  152. try
  153. {
  154. if (_transmitBuffer.EndPointOrNull == null)
  155. {
  156. bytesSent = _socket.EndSend(result);
  157. }
  158. else
  159. {
  160. bytesSent = _socket.EndSendTo(result);
  161. }
  162. }
  163. catch (SocketException ex)
  164. {
  165. if (IsTemporaryError(ex.SocketErrorCode))
  166. {
  167. _isTransmitting = false;
  168. KickSendQueue();
  169. return;
  170. }
  171. HandleSocketException(ex);
  172. return;
  173. }
  174. catch (ObjectDisposedException ex)
  175. {
  176. HandleSocketClosed(ex);
  177. return;
  178. }
  179. if (bytesSent != _transmitBuffer.Data.Count)
  180. {
  181. _truncationOccurred = true;
  182. return;
  183. }
  184. _isTransmitting = false;
  185. KickSendQueue();
  186. }
  187. }
  188. }