1 // System.Net.Sockets.SocketAsyncEventArgs.cs
4 // Marek Habersack (mhabersack@novell.com)
5 // Gonzalo Paniagua Javier (gonzalo@xamarin.com)
7 // Copyright (c) 2008,2010 Novell, Inc. (http://www.novell.com)
8 // Copyright (c) 2011 Xamarin, Inc. (http://xamarin.com)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.Collections.Generic;
33 using System.Reflection;
34 using System.Security;
35 using System.Threading;
37 namespace System.Net.Sockets
39 public class SocketAsyncEventArgs : EventArgs, IDisposable
43 internal SocketAsyncWorker Worker;
45 public Exception ConnectByNameError { get; internal set; }
47 public event EventHandler<SocketAsyncEventArgs> Completed;
49 IList <ArraySegment <byte>> _bufferList;
51 public Socket AcceptSocket { get; set; }
52 public byte[] Buffer { get; private set; }
54 public IList<ArraySegment<byte>> BufferList {
55 get { return _bufferList; }
57 if (Buffer != null && value != null)
58 throw new ArgumentException ("Buffer and BufferList properties cannot both be non-null.");
63 public int BytesTransferred { get; internal set; }
64 public int Count { get; internal set; }
65 public bool DisconnectReuseSocket { get; set; }
66 public SocketAsyncOperation LastOperation { get; private set; }
67 public int Offset { get; private set; }
68 public EndPoint RemoteEndPoint {
69 get { return remote_ep; }
70 set { remote_ep = value; }
73 public IPPacketInformation ReceiveMessageFromPacketInfo { get; private set; }
74 public SendPacketsElement[] SendPacketsElements { get; set; }
75 public TransmitFileOptions SendPacketsFlags { get; set; }
77 [MonoTODO ("unused property")]
78 public int SendPacketsSendSize { get; set; }
79 public SocketError SocketError { get; set; }
80 public SocketFlags SocketFlags { get; set; }
81 public object UserToken { get; set; }
82 internal Socket curSocket;
83 public Socket ConnectSocket {
85 switch (SocketError) {
86 case SocketError.AccessDenied:
94 internal bool PolicyRestricted { get; private set; }
96 internal SocketAsyncEventArgs (bool policy) :
99 PolicyRestricted = policy;
102 public SocketAsyncEventArgs ()
104 Worker = new SocketAsyncWorker (this);
108 BytesTransferred = 0;
110 DisconnectReuseSocket = false;
111 LastOperation = SocketAsyncOperation.None;
113 RemoteEndPoint = null;
115 SendPacketsElements = null;
116 SendPacketsFlags = TransmitFileOptions.UseDefaultWorkerThread;
118 SendPacketsSendSize = -1;
119 SocketError = SocketError.Success;
120 SocketFlags = SocketFlags.None;
124 ~SocketAsyncEventArgs ()
129 void Dispose (bool disposing)
134 if (disposed || Interlocked.CompareExchange (ref in_progress, 0, 0) != 0)
136 if (Worker != null) {
144 RemoteEndPoint = null;
147 SendPacketsElements = null;
151 public void Dispose ()
154 GC.SuppressFinalize (this);
157 internal void SetLastOperation (SocketAsyncOperation op)
160 throw new ObjectDisposedException ("System.Net.Sockets.SocketAsyncEventArgs");
161 if (Interlocked.Exchange (ref in_progress, 1) != 0)
162 throw new InvalidOperationException ("Operation already in progress");
166 protected virtual void OnCompleted (SocketAsyncEventArgs e)
171 EventHandler<SocketAsyncEventArgs> handler = e.Completed;
173 handler (e.curSocket, e);
176 public void SetBuffer (int offset, int count)
178 SetBufferInternal (Buffer, offset, count);
181 public void SetBuffer (byte[] buffer, int offset, int count)
183 SetBufferInternal (buffer, offset, count);
186 void SetBufferInternal (byte[] buffer, int offset, int count)
188 if (buffer != null) {
189 if (BufferList != null)
190 throw new ArgumentException ("Buffer and BufferList properties cannot both be non-null.");
192 int buflen = buffer.Length;
193 if (offset < 0 || (offset != 0 && offset >= buflen))
194 throw new ArgumentOutOfRangeException ("offset");
196 if (count < 0 || count > buflen - offset)
197 throw new ArgumentOutOfRangeException ("count");
206 internal static AsyncCallback Dispatcher = new AsyncCallback (DispatcherCB);
208 static void DispatcherCB (IAsyncResult ares)
210 SocketAsyncEventArgs args = (SocketAsyncEventArgs) ares.AsyncState;
212 if (Interlocked.Exchange (ref args.in_progress, 0) != 1)
213 throw new InvalidOperationException ("No operation in progress");
216 * -SocketOperation.AcceptReceive not used in SocketAsyncEventArgs
217 * -SendPackets and ReceiveMessageFrom are not implemented yet */
218 switch (args.LastOperation) {
219 case SocketAsyncOperation.Receive:
220 args.ReceiveCallback (ares);
222 case SocketAsyncOperation.Send:
223 args.SendCallback (ares);
225 case SocketAsyncOperation.ReceiveFrom:
226 args.ReceiveFromCallback (ares);
228 case SocketAsyncOperation.SendTo:
229 args.SendToCallback (ares);
231 case SocketAsyncOperation.Accept:
232 args.AcceptCallback (ares);
234 case SocketAsyncOperation.Disconnect:
235 args.DisconnectCallback (ares);
237 case SocketAsyncOperation.Connect:
238 args.ConnectCallback (ares);
241 case SocketOperation.ReceiveMessageFrom:
242 case SocketOperation.SendPackets:
245 throw new NotImplementedException (String.Format ("Operation {0} is not implemented", args.LastOperation));
249 internal void ReceiveCallback (IAsyncResult ares)
252 BytesTransferred = curSocket.EndReceive (ares);
253 } catch (SocketException se){
254 SocketError = se.SocketErrorCode;
255 } catch (ObjectDisposedException) {
256 SocketError = SocketError.OperationAborted;
262 void ConnectCallback (IAsyncResult ares)
265 curSocket.EndConnect (ares);
266 } catch (SocketException se) {
267 SocketError = se.SocketErrorCode;
268 } catch (ObjectDisposedException) {
269 SocketError = SocketError.OperationAborted;
275 internal void SendCallback (IAsyncResult ares)
278 BytesTransferred = curSocket.EndSend (ares);
279 } catch (SocketException se){
280 SocketError = se.SocketErrorCode;
281 } catch (ObjectDisposedException) {
282 SocketError = SocketError.OperationAborted;
288 internal void AcceptCallback (IAsyncResult ares)
291 AcceptSocket = curSocket.EndAccept (ares);
292 } catch (SocketException ex) {
293 SocketError = ex.SocketErrorCode;
294 } catch (ObjectDisposedException) {
295 SocketError = SocketError.OperationAborted;
297 if (AcceptSocket == null)
298 AcceptSocket = new Socket (curSocket.AddressFamily, curSocket.SocketType, curSocket.ProtocolType, null);
303 internal void DisconnectCallback (IAsyncResult ares)
306 curSocket.EndDisconnect (ares);
307 } catch (SocketException ex) {
308 SocketError = ex.SocketErrorCode;
309 } catch (ObjectDisposedException) {
310 SocketError = SocketError.OperationAborted;
316 internal void ReceiveFromCallback (IAsyncResult ares)
319 BytesTransferred = curSocket.EndReceiveFrom (ares, ref remote_ep);
320 } catch (SocketException ex) {
321 SocketError = ex.SocketErrorCode;
322 } catch (ObjectDisposedException) {
323 SocketError = SocketError.OperationAborted;
329 internal void SendToCallback (IAsyncResult ares)
332 BytesTransferred = curSocket.EndSendTo (ares);
333 } catch (SocketException ex) {
334 SocketError = ex.SocketErrorCode;
335 } catch (ObjectDisposedException) {
336 SocketError = SocketError.OperationAborted;