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 Socket.Worker Worker;
45 #if MOONLIGHT || NET_4_0
46 public Exception ConnectByNameError { get; internal set; }
49 public event EventHandler<SocketAsyncEventArgs> Completed;
51 IList <ArraySegment <byte>> _bufferList;
53 public Socket AcceptSocket { get; set; }
54 public byte[] Buffer { get; private set; }
56 public IList<ArraySegment<byte>> BufferList {
57 get { return _bufferList; }
59 if (Buffer != null && value != null)
60 throw new ArgumentException ("Buffer and BufferList properties cannot both be non-null.");
65 public int BytesTransferred { get; internal set; }
66 public int Count { get; internal set; }
67 public bool DisconnectReuseSocket { get; set; }
68 public SocketAsyncOperation LastOperation { get; private set; }
69 public int Offset { get; private set; }
70 public EndPoint RemoteEndPoint {
71 get { return remote_ep; }
72 set { remote_ep = value; }
75 public IPPacketInformation ReceiveMessageFromPacketInfo { get; private set; }
76 public SendPacketsElement[] SendPacketsElements { get; set; }
77 public TransmitFileOptions SendPacketsFlags { get; set; }
79 [MonoTODO ("unused property")]
80 public int SendPacketsSendSize { get; set; }
81 public SocketError SocketError { get; set; }
82 public SocketFlags SocketFlags { get; set; }
83 public object UserToken { get; set; }
85 #if MOONLIGHT && !INSIDE_SYSTEM
86 private SocketClientAccessPolicyProtocol policy_protocol;
88 public SocketClientAccessPolicyProtocol SocketClientAccessPolicyProtocol {
89 get { return policy_protocol; }
91 if ((value != SocketClientAccessPolicyProtocol.Tcp) && (value != SocketClientAccessPolicyProtocol.Http))
92 throw new ArgumentException ("Invalid value");
93 policy_protocol = value;
98 internal Socket curSocket;
100 public Socket ConnectSocket {
102 switch (SocketError) {
103 case SocketError.AccessDenied:
111 internal bool PolicyRestricted { get; private set; }
113 internal SocketAsyncEventArgs (bool policy) :
116 PolicyRestricted = policy;
120 public SocketAsyncEventArgs ()
122 Worker = new Socket.Worker (this);
126 BytesTransferred = 0;
128 DisconnectReuseSocket = false;
129 LastOperation = SocketAsyncOperation.None;
131 RemoteEndPoint = null;
133 SendPacketsElements = null;
134 SendPacketsFlags = TransmitFileOptions.UseDefaultWorkerThread;
136 SendPacketsSendSize = -1;
137 SocketError = SocketError.Success;
138 SocketFlags = SocketFlags.None;
141 #if MOONLIGHT && !INSIDE_SYSTEM
142 policy_protocol = SocketClientAccessPolicyProtocol.Tcp;
146 ~SocketAsyncEventArgs ()
151 void Dispose (bool disposing)
156 if (disposed || Interlocked.CompareExchange (ref in_progress, 0, 0) != 0)
158 if (Worker != null) {
166 RemoteEndPoint = null;
169 SendPacketsElements = null;
173 public void Dispose ()
176 GC.SuppressFinalize (this);
179 internal void SetLastOperation (SocketAsyncOperation op)
182 throw new ObjectDisposedException ("System.Net.Sockets.SocketAsyncEventArgs");
183 if (Interlocked.Exchange (ref in_progress, 1) != 0)
184 throw new InvalidOperationException ("Operation already in progress");
188 protected virtual void OnCompleted (SocketAsyncEventArgs e)
193 EventHandler<SocketAsyncEventArgs> handler = e.Completed;
195 handler (e.curSocket, e);
198 public void SetBuffer (int offset, int count)
200 SetBufferInternal (Buffer, offset, count);
203 public void SetBuffer (byte[] buffer, int offset, int count)
205 SetBufferInternal (buffer, offset, count);
208 void SetBufferInternal (byte[] buffer, int offset, int count)
210 if (buffer != null) {
211 if (BufferList != null)
212 throw new ArgumentException ("Buffer and BufferList properties cannot both be non-null.");
214 int buflen = buffer.Length;
215 if (offset < 0 || (offset != 0 && offset >= buflen))
216 throw new ArgumentOutOfRangeException ("offset");
218 if (count < 0 || count > buflen - offset)
219 throw new ArgumentOutOfRangeException ("count");
228 internal static AsyncCallback Dispatcher = new AsyncCallback (DispatcherCB);
230 static void DispatcherCB (IAsyncResult ares)
232 SocketAsyncEventArgs args = (SocketAsyncEventArgs) ares.AsyncState;
233 if (Interlocked.Exchange (ref args.in_progress, 0) != 1)
234 throw new InvalidOperationException ("No operation in progress");
235 SocketAsyncOperation op = args.LastOperation;
237 // -SocketOperation.AcceptReceive not used in SocketAsyncEventArgs
238 // -SendPackets and ReceiveMessageFrom are not implemented yet
239 if (op == SocketAsyncOperation.Receive)
240 args.ReceiveCallback (ares);
241 else if (op == SocketAsyncOperation.Send)
242 args.SendCallback (ares);
244 else if (op == SocketAsyncOperation.ReceiveFrom)
245 args.ReceiveFromCallback (ares);
246 else if (op == SocketAsyncOperation.SendTo)
247 args.SendToCallback (ares);
248 else if (op == SocketAsyncOperation.Accept)
249 args.AcceptCallback (ares);
250 else if (op == SocketAsyncOperation.Disconnect)
251 args.DisconnectCallback (ares);
253 else if (op == SocketAsyncOperation.Connect)
254 args.ConnectCallback ();
256 else if (op == Socket.SocketOperation.ReceiveMessageFrom)
257 else if (op == Socket.SocketOperation.SendPackets)
260 throw new NotImplementedException (String.Format ("Operation {0} is not implemented", op));
264 internal void ReceiveCallback (IAsyncResult ares)
267 BytesTransferred = curSocket.EndReceive (ares);
268 } catch (SocketException se){
269 SocketError = se.SocketErrorCode;
270 } catch (ObjectDisposedException) {
271 SocketError = SocketError.OperationAborted;
277 void ConnectCallback ()
280 SocketError = (SocketError) Worker.result.error;
286 internal void SendCallback (IAsyncResult ares)
289 BytesTransferred = curSocket.EndSend (ares);
290 } catch (SocketException se){
291 SocketError = se.SocketErrorCode;
292 } catch (ObjectDisposedException) {
293 SocketError = SocketError.OperationAborted;
300 internal void AcceptCallback (IAsyncResult ares)
303 AcceptSocket = curSocket.EndAccept (ares);
304 } catch (SocketException ex) {
305 SocketError = ex.SocketErrorCode;
306 } catch (ObjectDisposedException) {
307 SocketError = SocketError.OperationAborted;
309 if (AcceptSocket == null)
310 AcceptSocket = new Socket (curSocket.AddressFamily, curSocket.SocketType, curSocket.ProtocolType, (IntPtr)(-1));
315 internal void DisconnectCallback (IAsyncResult ares)
318 curSocket.EndDisconnect (ares);
319 } catch (SocketException ex) {
320 SocketError = ex.SocketErrorCode;
321 } catch (ObjectDisposedException) {
322 SocketError = SocketError.OperationAborted;
328 internal void ReceiveFromCallback (IAsyncResult ares)
331 BytesTransferred = curSocket.EndReceiveFrom (ares, ref remote_ep);
332 } catch (SocketException ex) {
333 SocketError = ex.SocketErrorCode;
334 } catch (ObjectDisposedException) {
335 SocketError = SocketError.OperationAborted;
341 internal void SendToCallback (IAsyncResult ares)
344 BytesTransferred = curSocket.EndSendTo (ares);
345 } catch (SocketException ex) {
346 SocketError = ex.SocketErrorCode;
347 } catch (ObjectDisposedException) {
348 SocketError = SocketError.OperationAborted;