Merge pull request #4434 from BrzVlad/fix-unload-hang
[mono.git] / mcs / class / System / System.Net.Sockets / SocketTaskExtensions.cs
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 using System.Collections.Generic;
6 using System.Threading.Tasks;
7
8 namespace System.Net.Sockets
9 {
10     public static class SocketTaskExtensions
11     {
12         public static Task<Socket> AcceptAsync(this Socket socket)
13         {
14             return Task<Socket>.Factory.FromAsync(
15                 (callback, state) => ((Socket)state).BeginAccept(callback, state),
16                 asyncResult => ((Socket)asyncResult.AsyncState).EndAccept(asyncResult),
17                 state: socket);
18         }
19
20         public static Task<Socket> AcceptAsync(this Socket socket, Socket acceptSocket)
21         {
22             const int ReceiveSize = 0;
23             return Task<Socket>.Factory.FromAsync(
24                 (socketForAccept, receiveSize, callback, state) => ((Socket)state).BeginAccept(socketForAccept, receiveSize, callback, state),
25                 asyncResult => ((Socket)asyncResult.AsyncState).EndAccept(asyncResult),
26                 acceptSocket,
27                 ReceiveSize,
28                 state: socket);
29         }
30
31         public static Task ConnectAsync(this Socket socket, EndPoint remoteEP)
32         {
33             return Task.Factory.FromAsync(
34                 (targetEndPoint, callback, state) => ((Socket)state).BeginConnect(targetEndPoint, callback, state),
35                 asyncResult => ((Socket)asyncResult.AsyncState).EndConnect(asyncResult),
36                 remoteEP,
37                 state: socket);
38         }
39
40         public static Task ConnectAsync(this Socket socket, IPAddress address, int port)
41         {
42             return Task.Factory.FromAsync(
43                 (targetAddress, targetPort, callback, state) => ((Socket)state).BeginConnect(targetAddress, targetPort, callback, state),
44                 asyncResult => ((Socket)asyncResult.AsyncState).EndConnect(asyncResult),
45                 address,
46                 port,
47                 state: socket);
48         }
49
50         public static Task ConnectAsync(this Socket socket, IPAddress[] addresses, int port)
51         {
52             return Task.Factory.FromAsync(
53                 (targetAddresses, targetPort, callback, state) => ((Socket)state).BeginConnect(targetAddresses, targetPort, callback, state),
54                 asyncResult => ((Socket)asyncResult.AsyncState).EndConnect(asyncResult),
55                 addresses,
56                 port,
57                 state: socket);
58         }
59
60         public static Task ConnectAsync(this Socket socket, string host, int port)
61         {
62             return Task.Factory.FromAsync(
63                 (targetHost, targetPort, callback, state) => ((Socket)state).BeginConnect(targetHost, targetPort, callback, state),
64                 asyncResult => ((Socket)asyncResult.AsyncState).EndConnect(asyncResult),
65                 host,
66                 port,
67                 state: socket);
68         }
69
70         public static Task<int> ReceiveAsync(this Socket socket, ArraySegment<byte> buffer, SocketFlags socketFlags)
71         {
72             return Task<int>.Factory.FromAsync(
73                 (targetBuffer, flags, callback, state) => ((Socket)state).BeginReceive(
74                                                               targetBuffer.Array,
75                                                               targetBuffer.Offset,
76                                                               targetBuffer.Count,
77                                                               flags,
78                                                               callback,
79                                                               state),
80                 asyncResult => ((Socket)asyncResult.AsyncState).EndReceive(asyncResult),
81                 buffer,
82                 socketFlags,
83                 state: socket);
84         }
85
86         public static Task<int> ReceiveAsync(
87             this Socket socket,
88             IList<ArraySegment<byte>> buffers,
89             SocketFlags socketFlags)
90         {
91             return Task<int>.Factory.FromAsync(
92                 (targetBuffers, flags, callback, state) => ((Socket)state).BeginReceive(targetBuffers, flags, callback, state),
93                 asyncResult => ((Socket)asyncResult.AsyncState).EndReceive(asyncResult),
94                 buffers,
95                 socketFlags,
96                 state: socket);
97         }
98
99         public static Task<SocketReceiveFromResult> ReceiveFromAsync(
100             this Socket socket,
101             ArraySegment<byte> buffer,
102             SocketFlags socketFlags,
103             EndPoint remoteEndPoint)
104         {
105             object[] packedArguments = new object[] { socket, remoteEndPoint };
106
107             return Task<SocketReceiveFromResult>.Factory.FromAsync(
108                 (targetBuffer, flags, callback, state) =>
109                 {
110                     var arguments = (object[])state;
111                     var s = (Socket)arguments[0];
112                     var e = (EndPoint)arguments[1];
113
114                     IAsyncResult result = s.BeginReceiveFrom(
115                         targetBuffer.Array,
116                         targetBuffer.Offset,
117                         targetBuffer.Count,
118                         flags,
119                         ref e,
120                         callback,
121                         state);
122
123                     arguments[1] = e;
124                     return result;
125                 },
126                 asyncResult =>
127                 {
128                     var arguments = (object[])asyncResult.AsyncState;
129                     var s = (Socket)arguments[0];
130                     var e = (EndPoint)arguments[1];
131
132                     int bytesReceived = s.EndReceiveFrom(asyncResult, ref e);
133
134                     return new SocketReceiveFromResult()
135                     {
136                         ReceivedBytes = bytesReceived,
137                         RemoteEndPoint = e
138                     };
139                 },
140                 buffer,
141                 socketFlags,
142                 state: packedArguments);
143         }
144
145         public static Task<SocketReceiveMessageFromResult> ReceiveMessageFromAsync(
146             this Socket socket,
147             ArraySegment<byte> buffer,
148             SocketFlags socketFlags,
149             EndPoint remoteEndPoint)
150         {
151             object[] packedArguments = new object[] { socket, socketFlags, remoteEndPoint };
152
153             return Task<SocketReceiveMessageFromResult>.Factory.FromAsync(
154                 (targetBuffer, callback, state) =>
155                 {
156                     var arguments = (object[])state;
157                     var s = (Socket)arguments[0];
158                     var f = (SocketFlags)arguments[1];
159                     var e = (EndPoint)arguments[2];
160
161                     IAsyncResult result = s.BeginReceiveMessageFrom(
162                         targetBuffer.Array,
163                         targetBuffer.Offset,
164                         targetBuffer.Count,
165                         f,
166                         ref e,
167                         callback,
168                         state);
169
170                     arguments[2] = e;
171                     return result;
172                 },
173                 asyncResult =>
174                 {
175                     var arguments = (object[])asyncResult.AsyncState;
176                     var s = (Socket)arguments[0];
177                     var f = (SocketFlags)arguments[1];
178                     var e = (EndPoint)arguments[2];
179                     IPPacketInformation ipPacket;
180
181                     int bytesReceived = s.EndReceiveMessageFrom(
182                         asyncResult,
183                         ref f,
184                         ref e,
185                         out ipPacket);
186
187                     return new SocketReceiveMessageFromResult()
188                     {
189                         PacketInformation = ipPacket,
190                         ReceivedBytes = bytesReceived,
191                         RemoteEndPoint = e,
192                         SocketFlags = f
193                     };
194                 },
195                 buffer,
196                 state: packedArguments);
197         }
198
199         public static Task<int> SendAsync(this Socket socket, ArraySegment<byte> buffer, SocketFlags socketFlags)
200         {
201             return Task<int>.Factory.FromAsync(
202                 (targetBuffer, flags, callback, state) => ((Socket)state).BeginSend(
203                                                               targetBuffer.Array,
204                                                               targetBuffer.Offset,
205                                                               targetBuffer.Count,
206                                                               flags,
207                                                               callback,
208                                                               state),
209                 asyncResult => ((Socket)asyncResult.AsyncState).EndSend(asyncResult),
210                 buffer,
211                 socketFlags,
212                 state: socket);
213         }
214
215         public static Task<int> SendAsync(
216             this Socket socket,
217             IList<ArraySegment<byte>> buffers,
218             SocketFlags socketFlags)
219         {
220             return Task<int>.Factory.FromAsync(
221                 (targetBuffers, flags, callback, state) => ((Socket)state).BeginSend(targetBuffers, flags, callback, state),
222                 asyncResult => ((Socket)asyncResult.AsyncState).EndSend(asyncResult),
223                 buffers,
224                 socketFlags,
225                 state: socket);
226         }
227
228         public static Task<int> SendToAsync(
229             this Socket socket,
230             ArraySegment<byte> buffer,
231             SocketFlags socketFlags,
232             EndPoint remoteEP)
233         {
234             return Task<int>.Factory.FromAsync(
235                 (targetBuffer, flags, endPoint, callback, state) => ((Socket)state).BeginSendTo(
236                                                                         targetBuffer.Array,
237                                                                         targetBuffer.Offset,
238                                                                         targetBuffer.Count,
239                                                                         flags,
240                                                                         endPoint,
241                                                                         callback,
242                                                                         state),
243                 asyncResult => ((Socket)asyncResult.AsyncState).EndSendTo(asyncResult),
244                 buffer,
245                 socketFlags,
246                 remoteEP,
247                 state: socket);
248         }
249     }
250 }