PageRenderTime 56ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 0ms

/1.3/Source/Rxx-Silverlight 4/System/Net/Sockets/SocketExtensions.cs

#
C# | 417 lines | 320 code | 92 blank | 5 comment | 54 complexity | dbf5a224c5912d61b9511c5c9cbbd555 MD5 | raw file
  1. using System.Collections.Generic;
  2. using System.Diagnostics.CodeAnalysis;
  3. using System.Diagnostics.Contracts;
  4. using Rxx;
  5. namespace System.Net.Sockets
  6. {
  7. public static partial class SocketExtensions
  8. {
  9. [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope",
  10. Justification = "The args object is disposed in the EndInvoke method.")]
  11. internal static IAsyncResult BeginConnect(this Socket socket, EndPoint remoteEP, AsyncCallback callback, object state)
  12. {
  13. Contract.Requires(socket != null);
  14. Contract.Ensures(Contract.Result<IAsyncResult>() != null);
  15. var args = new SocketAsyncEventArgs()
  16. {
  17. RemoteEndPoint = remoteEP
  18. };
  19. return BeginInvoke(callback, state, args, socket.ConnectAsync);
  20. }
  21. [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope",
  22. Justification = "The args object is disposed in the EndInvoke method.")]
  23. internal static IAsyncResult BeginConnect(this Socket socket, IPAddress address, int port, AsyncCallback requestCallback, object state)
  24. {
  25. Contract.Requires(socket != null);
  26. Contract.Ensures(Contract.Result<IAsyncResult>() != null);
  27. var args = new SocketAsyncEventArgs()
  28. {
  29. RemoteEndPoint = new IPEndPoint(address, port)
  30. };
  31. return BeginInvoke(requestCallback, state, args, socket.ConnectAsync);
  32. }
  33. [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope",
  34. Justification = "The args object is disposed in the EndInvoke method.")]
  35. internal static IAsyncResult BeginConnect(this Socket socket, string host, int port, AsyncCallback requestCallback, object state)
  36. {
  37. Contract.Requires(socket != null);
  38. Contract.Ensures(Contract.Result<IAsyncResult>() != null);
  39. var args = new SocketAsyncEventArgs()
  40. {
  41. RemoteEndPoint = new DnsEndPoint(host, port)
  42. };
  43. return BeginInvoke(requestCallback, state, args, socket.ConnectAsync);
  44. }
  45. internal static void EndConnect(this Socket socket, IAsyncResult asyncResult)
  46. {
  47. Contract.Requires(asyncResult != null);
  48. using (var args = EndInvoke(asyncResult))
  49. {
  50. // do nothing
  51. }
  52. }
  53. [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope",
  54. Justification = "The args object is disposed in the EndInvoke method.")]
  55. internal static IAsyncResult BeginReceive(this Socket socket, IList<ArraySegment<byte>> buffers, AsyncCallback callback, object state)
  56. {
  57. Contract.Requires(socket != null);
  58. Contract.Ensures(Contract.Result<IAsyncResult>() != null);
  59. var args = new SocketAsyncEventArgs()
  60. {
  61. BufferList = buffers
  62. };
  63. return BeginInvoke(callback, state, args, socket.ReceiveAsync);
  64. }
  65. [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope",
  66. Justification = "The args object is disposed in the EndInvoke method.")]
  67. internal static IAsyncResult BeginReceive(this Socket socket, IList<ArraySegment<byte>> buffers, out SocketError errorCode, AsyncCallback callback, object state)
  68. {
  69. Contract.Requires(socket != null);
  70. Contract.Ensures(Contract.Result<IAsyncResult>() != null);
  71. var args = new SocketAsyncEventArgs()
  72. {
  73. BufferList = buffers
  74. };
  75. var result = BeginInvoke(callback, state, args, socket.ReceiveAsync);
  76. if (result.CompletedSynchronously)
  77. {
  78. errorCode = args.SocketError;
  79. // Prevent the error from being thrown in EndInvoke
  80. result.OutOfBandData = new object();
  81. }
  82. else
  83. {
  84. errorCode = default(SocketError);
  85. }
  86. return result;
  87. }
  88. [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope",
  89. Justification = "The args object is disposed in the EndInvoke method.")]
  90. internal static IAsyncResult BeginReceive(this Socket socket, byte[] buffer, int offset, int size, AsyncCallback callback, object state)
  91. {
  92. Contract.Requires(socket != null);
  93. Contract.Ensures(Contract.Result<IAsyncResult>() != null);
  94. var args = new SocketAsyncEventArgs();
  95. args.SetBuffer(buffer, offset, size);
  96. return BeginInvoke(callback, state, args, socket.ReceiveAsync);
  97. }
  98. [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope",
  99. Justification = "The args object is disposed in the EndInvoke method.")]
  100. internal static IAsyncResult BeginReceive(this Socket socket, byte[] buffer, int offset, int size, out SocketError errorCode, AsyncCallback callback, object state)
  101. {
  102. Contract.Requires(socket != null);
  103. Contract.Ensures(Contract.Result<IAsyncResult>() != null);
  104. var args = new SocketAsyncEventArgs();
  105. args.SetBuffer(buffer, offset, size);
  106. var result = BeginInvoke(callback, state, args, socket.ReceiveAsync);
  107. if (result.CompletedSynchronously)
  108. {
  109. errorCode = args.SocketError;
  110. // Prevent the error from being thrown in EndInvoke
  111. result.OutOfBandData = new object();
  112. }
  113. else
  114. {
  115. errorCode = default(SocketError);
  116. }
  117. return result;
  118. }
  119. [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope",
  120. Justification = "The args object is disposed in the EndInvoke method.")]
  121. internal static IAsyncResult BeginReceiveFrom(this Socket socket, byte[] buffer, int offset, int size, ref EndPoint remoteEP, AsyncCallback callback, object state)
  122. {
  123. Contract.Requires(socket != null);
  124. Contract.Ensures(Contract.Result<IAsyncResult>() != null);
  125. var args = new SocketAsyncEventArgs()
  126. {
  127. RemoteEndPoint = remoteEP
  128. };
  129. args.SetBuffer(buffer, offset, size);
  130. var result = BeginInvoke(callback, state, args, socket.ReceiveAsync);
  131. if (result.CompletedSynchronously)
  132. {
  133. remoteEP = args.RemoteEndPoint;
  134. }
  135. return result;
  136. }
  137. internal static int EndReceive(this Socket socket, IAsyncResult asyncResult)
  138. {
  139. Contract.Requires(asyncResult != null);
  140. using (var args = EndInvoke(asyncResult))
  141. {
  142. return args.BytesTransferred;
  143. }
  144. }
  145. [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "socket",
  146. Justification = "Needed for parity with .NET 4.0 Framework.")]
  147. internal static int EndReceive(this Socket socket, IAsyncResult asyncResult, out SocketError errorCode)
  148. {
  149. Contract.Requires(asyncResult != null);
  150. using (var args = EndInvoke(asyncResult))
  151. {
  152. errorCode = args.SocketError;
  153. return args.BytesTransferred;
  154. }
  155. }
  156. [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "socket",
  157. Justification = "Needed for parity with .NET 4.0 Framework.")]
  158. internal static int EndReceiveFrom(this Socket socket, IAsyncResult asyncResult, ref EndPoint endPoint)
  159. {
  160. Contract.Requires(asyncResult != null);
  161. using (var args = EndInvoke(asyncResult))
  162. {
  163. endPoint = args.RemoteEndPoint;
  164. return args.BytesTransferred;
  165. }
  166. }
  167. [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope",
  168. Justification = "The args object is disposed in the EndInvoke method.")]
  169. internal static IAsyncResult BeginSend(this Socket socket, IList<ArraySegment<byte>> buffers, AsyncCallback callback, object state)
  170. {
  171. Contract.Requires(socket != null);
  172. Contract.Ensures(Contract.Result<IAsyncResult>() != null);
  173. var args = new SocketAsyncEventArgs()
  174. {
  175. BufferList = buffers
  176. };
  177. return BeginInvoke(callback, state, args, socket.SendAsync);
  178. }
  179. [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope",
  180. Justification = "The args object is disposed in the EndInvoke method.")]
  181. internal static IAsyncResult BeginSend(this Socket socket, IList<ArraySegment<byte>> buffers, out SocketError errorCode, AsyncCallback callback, object state)
  182. {
  183. Contract.Requires(socket != null);
  184. Contract.Ensures(Contract.Result<IAsyncResult>() != null);
  185. var args = new SocketAsyncEventArgs()
  186. {
  187. BufferList = buffers
  188. };
  189. var result = BeginInvoke(callback, state, args, socket.ReceiveAsync);
  190. if (result.CompletedSynchronously)
  191. {
  192. errorCode = args.SocketError;
  193. // Prevent the error from being thrown in EndInvoke
  194. result.OutOfBandData = new object();
  195. }
  196. else
  197. {
  198. errorCode = default(SocketError);
  199. }
  200. return result;
  201. }
  202. [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope",
  203. Justification = "The args object is disposed in the EndInvoke method.")]
  204. internal static IAsyncResult BeginSend(this Socket socket, byte[] buffer, int offset, int size, AsyncCallback callback, object state)
  205. {
  206. Contract.Requires(socket != null);
  207. Contract.Ensures(Contract.Result<IAsyncResult>() != null);
  208. var args = new SocketAsyncEventArgs();
  209. args.SetBuffer(buffer, offset, size);
  210. return BeginInvoke(callback, state, args, socket.SendAsync);
  211. }
  212. [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope",
  213. Justification = "The args object is disposed in the EndInvoke method.")]
  214. internal static IAsyncResult BeginSend(this Socket socket, byte[] buffer, int offset, int size, out SocketError errorCode, AsyncCallback callback, object state)
  215. {
  216. Contract.Requires(socket != null);
  217. Contract.Ensures(Contract.Result<IAsyncResult>() != null);
  218. var args = new SocketAsyncEventArgs();
  219. args.SetBuffer(buffer, offset, size);
  220. var result = BeginInvoke(callback, state, args, socket.ReceiveAsync);
  221. if (result.CompletedSynchronously)
  222. {
  223. errorCode = args.SocketError;
  224. // Prevent the error from being thrown in EndInvoke
  225. result.OutOfBandData = new object();
  226. }
  227. else
  228. {
  229. errorCode = default(SocketError);
  230. }
  231. return result;
  232. }
  233. [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope",
  234. Justification = "The args object is disposed in the EndInvoke method.")]
  235. internal static IAsyncResult BeginSendTo(this Socket socket, byte[] buffer, int offset, int size, EndPoint remoteEP, AsyncCallback callback, object state)
  236. {
  237. Contract.Requires(socket != null);
  238. Contract.Ensures(Contract.Result<IAsyncResult>() != null);
  239. var args = new SocketAsyncEventArgs()
  240. {
  241. RemoteEndPoint = remoteEP
  242. };
  243. args.SetBuffer(buffer, offset, size);
  244. return BeginInvoke(callback, state, args, socket.SendAsync);
  245. }
  246. internal static int EndSend(this Socket socket, IAsyncResult asyncResult)
  247. {
  248. Contract.Requires(asyncResult != null);
  249. using (var args = EndInvoke(asyncResult))
  250. {
  251. return args.BytesTransferred;
  252. }
  253. }
  254. [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "socket",
  255. Justification = "Needed for parity with .NET 4.0 Framework.")]
  256. internal static int EndSend(this Socket socket, IAsyncResult asyncResult, out SocketError errorCode)
  257. {
  258. Contract.Requires(asyncResult != null);
  259. using (var args = EndInvoke(asyncResult))
  260. {
  261. errorCode = args.SocketError;
  262. return args.BytesTransferred;
  263. }
  264. }
  265. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "socket",
  266. Justification = "Must have the same signature as in .NET 4.0.")]
  267. internal static int EndSendTo(this Socket socket, IAsyncResult asyncResult)
  268. {
  269. Contract.Requires(asyncResult != null);
  270. using (var args = EndInvoke(asyncResult))
  271. {
  272. return args.BytesTransferred;
  273. }
  274. }
  275. private static AsyncResult<SocketAsyncEventArgs> BeginInvoke(AsyncCallback callback, object state, SocketAsyncEventArgs args, Func<SocketAsyncEventArgs, bool> target)
  276. {
  277. Contract.Requires(args != null);
  278. Contract.Requires(target != null);
  279. Contract.Ensures(Contract.Result<IAsyncResult>() != null);
  280. var result = new AsyncResult<SocketAsyncEventArgs>(state);
  281. EventHandler<SocketAsyncEventArgs> completed = (sender, e) =>
  282. {
  283. if (!result.IsCompleted)
  284. {
  285. result.Complete(args, synchronous: false);
  286. }
  287. if (callback != null)
  288. {
  289. callback(result);
  290. }
  291. };
  292. args.Completed += completed;
  293. if (!target(args))
  294. {
  295. result.Complete(args, synchronous: true);
  296. completed(null, null);
  297. }
  298. return result;
  299. }
  300. private static SocketAsyncEventArgs EndInvoke(IAsyncResult asyncResult)
  301. {
  302. Contract.Requires(asyncResult != null);
  303. Contract.Ensures(Contract.Result<SocketAsyncEventArgs>() != null);
  304. var result = (AsyncResult<SocketAsyncEventArgs>) asyncResult;
  305. using (result)
  306. {
  307. result.Wait();
  308. var args = result.Data;
  309. Contract.Assume(args != null);
  310. if (result.OutOfBandData == null)
  311. {
  312. if (args.ConnectByNameError != null)
  313. {
  314. throw args.ConnectByNameError;
  315. }
  316. if (args.SocketError != SocketError.Success)
  317. {
  318. throw new SocketException((int) args.SocketError);
  319. }
  320. }
  321. return args;
  322. }
  323. }
  324. }
  325. }