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
41 public SocketOperation operation;
43 Exception DelayedException;
45 public EndPoint EndPoint; // Connect,ReceiveFrom,SendTo
46 public byte [] Buffer; // Receive,ReceiveFrom,Send,SendTo
47 public int Offset; // Receive,ReceiveFrom,Send,SendTo
48 public int Size; // Receive,ReceiveFrom,Send,SendTo
49 public SocketFlags SockFlags; // Receive,ReceiveFrom,Send,SendTo
50 public Socket AcceptSocket; // AcceptReceive
51 public IPAddress[] Addresses; // Connect
52 public int Port; // Connect
53 public IList<ArraySegment<byte>> Buffers; // Receive, Send
54 public bool ReuseSocket; // Disconnect
55 public int CurrentAddress; // Connect
57 public Socket AcceptedSocket;
64 public IntPtr Handle {
65 get { return socket != null ? socket.Handle : IntPtr.Zero; }
68 /* Used by SocketAsyncEventArgs */
69 public SocketAsyncResult ()
74 public void Init (Socket socket, AsyncCallback callback, object state, SocketOperation operation)
76 base.Init (callback, state);
79 this.operation = operation;
81 DelayedException = null;
87 SockFlags = SocketFlags.None;
95 AcceptedSocket = null;
103 public SocketAsyncResult (Socket socket, AsyncCallback callback, object state, SocketOperation operation)
104 : base (callback, state)
106 this.socket = socket;
107 this.operation = operation;
110 public SocketError ErrorCode {
112 SocketException ex = DelayedException as SocketException;
114 return ex.SocketErrorCode;
117 return (SocketError) error;
119 return SocketError.Success;
123 public void CheckIfThrowDelayedException ()
125 if (DelayedException != null) {
126 socket.is_connected = false;
127 throw DelayedException;
131 socket.is_connected = false;
132 throw new SocketException (error);
136 internal override void CompleteDisposed ()
141 public void Complete ()
143 if (operation != SocketOperation.Receive && socket.CleanedUp)
144 DelayedException = new ObjectDisposedException (socket.GetType ().ToString ());
148 /* It is possible that this.socket is modified by this.Init which has been called by the callback. This
149 * would lead to inconsistency, as we would for example not release the correct socket.ReadSem or
151 * For example, this can happen with AcceptAsync followed by a ReceiveAsync on the same
152 * SocketAsyncEventArgs */
153 Socket completedSocket = socket;
154 SocketOperation completedOperation = operation;
156 AsyncCallback callback = AsyncCallback;
157 if (callback != null) {
158 ThreadPool.UnsafeQueueUserWorkItem (_ => callback (this), null);
161 /* Warning: any field on the current SocketAsyncResult might have changed, as the callback might have
162 * called this.Init */
164 switch (completedOperation) {
165 case SocketOperation.Receive:
166 case SocketOperation.ReceiveFrom:
167 case SocketOperation.ReceiveGeneric:
168 case SocketOperation.Accept:
169 completedSocket.ReadSem.Release ();
171 case SocketOperation.Send:
172 case SocketOperation.SendTo:
173 case SocketOperation.SendGeneric:
174 completedSocket.WriteSem.Release ();
178 // IMPORTANT: 'callback', if any is scheduled from unmanaged code
181 public void Complete (bool synch)
183 CompletedSynchronously = synch;
187 public void Complete (int total)
193 public void Complete (Exception e, bool synch)
195 DelayedException = e;
196 CompletedSynchronously = synch;
200 public void Complete (Exception e)
202 DelayedException = e;
206 public void Complete (Socket s)
212 public void Complete (Socket s, int total)