1 // System.Net.Sockets.SocketAsyncResult.cs
4 // Ludovic Henry <ludovic@xamarin.com>
6 // Copyright (C) 2015 Xamarin, Inc. (https://www.xamarin.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 using System.Collections;
30 using System.Collections.Generic;
31 using System.Runtime.InteropServices;
32 using System.Runtime.Remoting.Messaging;
33 using System.Threading;
35 namespace System.Net.Sockets
37 [StructLayout (LayoutKind.Sequential)]
38 internal sealed class SocketAsyncResult: IOAsyncResult
42 public SocketOperation operation;
44 Exception DelayedException;
46 public EndPoint EndPoint; // Connect,ReceiveFrom,SendTo
47 public byte [] Buffer; // Receive,ReceiveFrom,Send,SendTo
48 public int Offset; // Receive,ReceiveFrom,Send,SendTo
49 public int Size; // Receive,ReceiveFrom,Send,SendTo
50 public SocketFlags SockFlags; // Receive,ReceiveFrom,Send,SendTo
51 public Socket AcceptSocket; // AcceptReceive
52 public IPAddress[] Addresses; // Connect
53 public int Port; // Connect
54 public IList<ArraySegment<byte>> Buffers; // Receive, Send
55 public bool ReuseSocket; // Disconnect
56 public int CurrentAddress; // Connect
58 public Socket AcceptedSocket;
65 /* Used by SocketAsyncEventArgs */
66 public SocketAsyncResult ()
71 public void Init (Socket socket, AsyncCallback callback, object state, SocketOperation operation)
73 base.Init (callback, state);
76 this.handle = socket != null ? socket.Handle : IntPtr.Zero;
77 this.operation = operation;
79 DelayedException = null;
85 SockFlags = SocketFlags.None;
93 AcceptedSocket = null;
101 public SocketAsyncResult (Socket socket, AsyncCallback callback, object state, SocketOperation operation)
102 : base (callback, state)
104 this.socket = socket;
105 this.handle = socket != null ? socket.Handle : IntPtr.Zero;
106 this.operation = operation;
109 public SocketError ErrorCode {
111 SocketException ex = DelayedException as SocketException;
113 return ex.SocketErrorCode;
116 return (SocketError) error;
118 return SocketError.Success;
122 public void CheckIfThrowDelayedException ()
124 if (DelayedException != null) {
125 socket.is_connected = false;
126 throw DelayedException;
130 socket.is_connected = false;
131 throw new SocketException (error);
135 internal override void CompleteDisposed ()
140 public void Complete ()
142 if (operation != SocketOperation.Receive && socket.is_disposed)
143 DelayedException = new ObjectDisposedException (socket.GetType ().ToString ());
147 AsyncCallback callback = AsyncCallback;
148 if (callback != null) {
149 ThreadPool.UnsafeQueueUserWorkItem (_ => callback (this), null);
152 Queue<KeyValuePair<IntPtr, IOSelectorJob>> queue = null;
154 case SocketOperation.Receive:
155 case SocketOperation.ReceiveFrom:
156 case SocketOperation.ReceiveGeneric:
157 case SocketOperation.Accept:
158 queue = socket.readQ;
160 case SocketOperation.Send:
161 case SocketOperation.SendTo:
162 case SocketOperation.SendGeneric:
163 queue = socket.writeQ;
169 /* queue.Count will only be 0 if the socket is closed while receive/send/accept
170 * operation(s) are pending and at least one call to this method is waiting
171 * on the lock while another one calls CompleteAllOnDispose() */
173 queue.Dequeue (); /* remove ourselves */
174 if (queue.Count > 0) {
175 if (!socket.is_disposed) {
176 IOSelector.Add (queue.Peek ().Key, queue.Peek ().Value);
178 /* CompleteAllOnDispose */
179 KeyValuePair<IntPtr, IOSelectorJob> [] jobs = queue.ToArray ();
180 for (int i = 0; i < jobs.Length; i++)
181 ThreadPool.QueueUserWorkItem (j => ((IOSelectorJob) j).MarkDisposed (), jobs [i].Value);
188 // IMPORTANT: 'callback', if any is scheduled from unmanaged code
191 public void Complete (bool synch)
193 CompletedSynchronously = synch;
197 public void Complete (int total)
203 public void Complete (Exception e, bool synch)
205 DelayedException = e;
206 CompletedSynchronously = synch;
210 public void Complete (Exception e)
212 DelayedException = e;
216 public void Complete (Socket s)
222 public void Complete (Socket s, int total)