SocketAsyncResult sockares = CreateSocketAsyncResultFromSocketAsyncEventArgs (e, SocketOperation.Accept, e.AcceptCallback);
- QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, s => ((SocketAsyncResult) s).Worker.Accept (), sockares));
+ QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, BeginAcceptCallback, sockares));
return true;
}
SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.Accept);
- QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, s => ((SocketAsyncResult) s).Worker.Accept (), sockares));
+ QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, BeginAcceptCallback, sockares));
return sockares;
}
+ static IOAsyncCallback BeginAcceptCallback = new IOAsyncCallback (ares => {
+ SocketAsyncResult sockares = (SocketAsyncResult) ares;
+ Socket socket = null;
+
+ try {
+ socket = sockares.socket.Accept ();
+ } catch (Exception e) {
+ sockares.Complete (e);
+ return;
+ }
+
+ sockares.Complete (socket);
+ });
+
public IAsyncResult BeginAccept (int receiveSize, AsyncCallback callback, object state)
{
ThrowIfDisposedAndClosed ();
SockFlags = SocketFlags.None,
};
- QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, s => ((SocketAsyncResult) s).Worker.AcceptReceive (), sockares));
+ QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, BeginAcceptReceiveCallback, sockares));
return sockares;
}
if (acceptSocket.ProtocolType != ProtocolType.Tcp)
throw new SocketException ((int)SocketError.InvalidArgument);
}
-
+
SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.AcceptReceive) {
Buffer = new byte [receiveSize],
Offset = 0,
AcceptSocket = acceptSocket,
};
- QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, s => ((SocketAsyncResult) s).Worker.AcceptReceive (), sockares));
+ QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, BeginAcceptReceiveCallback, sockares));
return sockares;
}
+ static IOAsyncCallback BeginAcceptReceiveCallback = new IOAsyncCallback (ares => {
+ SocketAsyncResult sockares = (SocketAsyncResult) ares;
+ Socket acc_socket = null;
+
+ try {
+ if (sockares.AcceptSocket == null) {
+ acc_socket = sockares.socket.Accept ();
+ } else {
+ acc_socket = sockares.AcceptSocket;
+ sockares.socket.Accept (acc_socket);
+ }
+ } catch (Exception e) {
+ sockares.Complete (e);
+ return;
+ }
+
+ /* It seems the MS runtime special-cases 0-length requested receive data. See bug 464201. */
+ int total = 0;
+ if (sockares.Size > 0) {
+ try {
+ SocketError error;
+ total = acc_socket.Receive_nochecks (sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, out error);
+ if (error != 0) {
+ sockares.Complete (new SocketException ((int) error));
+ return;
+ }
+ } catch (Exception e) {
+ sockares.Complete (e);
+ return;
+ }
+ }
+
+ sockares.Complete (acc_socket, total);
+ });
+
public Socket EndAccept (IAsyncResult result)
{
int bytes;
buffer = sockares.Buffer;
bytesTransferred = sockares.Total;
- return sockares.Socket;
+ return sockares.AcceptedSocket;
}
static SafeSocketHandle Accept_internal (SafeSocketHandle safeHandle, out int error, bool blocking)
is_bound = false;
connect_in_progress = true;
- IOSelector.Add (sockares.handle, new IOSelectorJob (IOOperation.Write, s => ((SocketAsyncResult) s).Worker.Connect (), sockares));
+ IOSelector.Add (sockares.handle, new IOSelectorJob (IOOperation.Write, BeginConnectCallback, sockares));
return sockares;
}
return sockares;
}
+ static IOAsyncCallback BeginConnectCallback = new IOAsyncCallback (ares => {
+ SocketAsyncResult sockares = (SocketAsyncResult) ares;
+
+ if (sockares.EndPoint == null) {
+ sockares.Complete (new SocketException ((int)SocketError.AddressNotAvailable));
+ return;
+ }
+
+ SocketAsyncResult mconnect = sockares.AsyncState as SocketAsyncResult;
+ bool is_mconnect = mconnect != null && mconnect.Addresses != null;
+
+ try {
+ EndPoint ep = sockares.EndPoint;
+ int error_code = (int) sockares.socket.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
+
+ if (error_code == 0) {
+ if (is_mconnect)
+ sockares = mconnect;
+
+ sockares.socket.seed_endpoint = ep;
+ sockares.socket.is_connected = true;
+ sockares.socket.is_bound = true;
+ sockares.socket.connect_in_progress = false;
+ sockares.error = 0;
+ sockares.Complete ();
+ return;
+ }
+
+ if (!is_mconnect) {
+ sockares.socket.connect_in_progress = false;
+ sockares.Complete (new SocketException (error_code));
+ return;
+ }
+
+ if (mconnect.CurrentAddress >= mconnect.Addresses.Length) {
+ mconnect.Complete (new SocketException (error_code));
+ return;
+ }
+
+ mconnect.socket.BeginMConnect (mconnect);
+ } catch (Exception e) {
+ sockares.socket.connect_in_progress = false;
+
+ if (is_mconnect)
+ sockares = mconnect;
+
+ sockares.Complete (e);
+ return;
+ }
+ });
+
public void EndConnect (IAsyncResult result)
{
ThrowIfDisposedAndClosed ();
SocketAsyncResult sockares = CreateSocketAsyncResultFromSocketAsyncEventArgs (e, SocketOperation.Disconnect, e.DisconnectCallback);
- IOSelector.Add (sockares.handle, new IOSelectorJob (IOOperation.Write, s => ((SocketAsyncResult) s).Worker.Disconnect (), sockares));
+ IOSelector.Add (sockares.handle, new IOSelectorJob (IOOperation.Write, BeginDisconnectCallback, sockares));
return true;
}
ReuseSocket = reuseSocket,
};
- IOSelector.Add (sockares.handle, new IOSelectorJob (IOOperation.Write, s => ((SocketAsyncResult) s).Worker.Disconnect (), sockares));
+ IOSelector.Add (sockares.handle, new IOSelectorJob (IOOperation.Write, BeginDisconnectCallback, sockares));
return sockares;
}
+ static IOAsyncCallback BeginDisconnectCallback = new IOAsyncCallback (ares => {
+ SocketAsyncResult sockares = (SocketAsyncResult) ares;
+
+ try {
+ sockares.socket.Disconnect (sockares.ReuseSocket);
+ } catch (Exception e) {
+ sockares.Complete (e);
+ return;
+ }
+
+ sockares.Complete ();
+ });
+
public void EndDisconnect (IAsyncResult asyncResult)
{
ThrowIfDisposedAndClosed ();
if (e.Buffer == null) {
sockares = CreateSocketAsyncResultFromSocketAsyncEventArgs (e, SocketOperation.ReceiveGeneric, e.ReceiveCallback);
sockares.Buffers = e.BufferList;
+
+ QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, BeginReceiveGenericCallback, sockares));
} else {
sockares = CreateSocketAsyncResultFromSocketAsyncEventArgs (e, SocketOperation.Receive, e.ReceiveCallback);
sockares.Buffer = e.Buffer;
sockares.Offset = e.Offset;
sockares.Size = e.Count;
- }
- QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, s => ((SocketAsyncResult) s).Worker.Receive (), sockares));
+ QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, BeginReceiveCallback, sockares));
+ }
return true;
}
SockFlags = socket_flags,
};
- QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, s => ((SocketAsyncResult) s).Worker.Receive (), sockares));
+ QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, BeginReceiveCallback, sockares));
return sockares;
}
return BeginReceive (buffer, offset, size, flags, callback, state);
}
+ static IOAsyncCallback BeginReceiveCallback = new IOAsyncCallback (ares => {
+ SocketAsyncResult sockares = (SocketAsyncResult) ares;
+ int total = 0;
+
+ try {
+ total = Receive_internal (sockares.socket.safe_handle, sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, out sockares.error);
+ } catch (Exception e) {
+ sockares.Complete (e);
+ return;
+ }
+
+ sockares.Complete (total);
+ });
+
[CLSCompliant (false)]
public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, AsyncCallback callback, object state)
{
SockFlags = socketFlags,
};
- QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, s => ((SocketAsyncResult) s).Worker.Receive (), sockares));
+ QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, BeginReceiveGenericCallback, sockares));
return sockares;
}
return BeginReceive (buffers, socketFlags, callback, state);
}
+ static IOAsyncCallback BeginReceiveGenericCallback = new IOAsyncCallback (ares => {
+ SocketAsyncResult sockares = (SocketAsyncResult) ares;
+ int total = 0;
+
+ try {
+ total = sockares.socket.Receive (sockares.Buffers, sockares.SockFlags);
+ } catch (Exception e) {
+ sockares.Complete (e);
+ return;
+ }
+
+ sockares.Complete (total);
+ });
+
public int EndReceive (IAsyncResult result)
{
SocketError error;
return sockares.Total;
}
- internal int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
+ int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
{
int nativeError;
int ret = Receive_internal (safe_handle, buf, offset, size, flags, out nativeError);
[MethodImplAttribute (MethodImplOptions.InternalCall)]
extern static int Receive_internal (IntPtr sock, WSABUF[] bufarray, SocketFlags flags, out int error);
- internal static int Receive_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, out int error)
+ static int Receive_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, out int error)
{
try {
safeHandle.RegisterForBlockingSyscall ();
{
ThrowIfDisposedAndClosed ();
ThrowIfBufferNull (buffer);
- ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
-
- if (remoteEP == null)
- throw new ArgumentNullException ("remoteEP");
- return ReceiveFrom_nochecks (buffer, 0, buffer.Length, SocketFlags.None, ref remoteEP);
+ return ReceiveFrom (buffer, 0, buffer.Length, SocketFlags.None, ref remoteEP);
}
public int ReceiveFrom (byte [] buffer, SocketFlags flags, ref EndPoint remoteEP)
{
ThrowIfDisposedAndClosed ();
ThrowIfBufferNull (buffer);
- ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
- if (remoteEP == null)
- throw new ArgumentNullException ("remoteEP");
-
- return ReceiveFrom_nochecks (buffer, 0, buffer.Length, flags, ref remoteEP);
+ return ReceiveFrom (buffer, 0, buffer.Length, flags, ref remoteEP);
}
public int ReceiveFrom (byte [] buffer, int size, SocketFlags flags, ref EndPoint remoteEP)
ThrowIfBufferNull (buffer);
ThrowIfBufferOutOfRange (buffer, 0, size);
- if (remoteEP == null)
- throw new ArgumentNullException ("remoteEP");
-
- return ReceiveFrom_nochecks (buffer, 0, size, flags, ref remoteEP);
+ return ReceiveFrom (buffer, 0, size, flags, ref remoteEP);
}
public int ReceiveFrom (byte [] buffer, int offset, int size, SocketFlags flags, ref EndPoint remoteEP)
if (remoteEP == null)
throw new ArgumentNullException ("remoteEP");
- return ReceiveFrom_nochecks (buffer, offset, size, flags, ref remoteEP);
+ int error;
+ return ReceiveFrom_nochecks_exc (buffer, offset, size, flags, ref remoteEP, true, out error);
}
public bool ReceiveFromAsync (SocketAsyncEventArgs e)
sockares.EndPoint = e.RemoteEndPoint;
sockares.SockFlags = e.SocketFlags;
- QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, s => ((SocketAsyncResult) s).Worker.ReceiveFrom (), sockares));
+ QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, BeginReceiveFromCallback, sockares));
return true;
}
EndPoint = remote_end,
};
- QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, s => ((SocketAsyncResult) s).Worker.ReceiveFrom (), sockares));
+ QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, BeginReceiveFromCallback, sockares));
return sockares;
}
+ static IOAsyncCallback BeginReceiveFromCallback = new IOAsyncCallback (ares => {
+ SocketAsyncResult sockares = (SocketAsyncResult) ares;
+ int total = 0;
+
+ try {
+ int error;
+ total = sockares.socket.ReceiveFrom_nochecks_exc (sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, ref sockares.EndPoint, true, out error);
+ } catch (Exception e) {
+ sockares.Complete (e);
+ return;
+ }
+
+ sockares.Complete (total);
+ });
+
public int EndReceiveFrom(IAsyncResult result, ref EndPoint end_point)
{
ThrowIfDisposedAndClosed ();
return sockares.Total;
}
- internal int ReceiveFrom_nochecks (byte [] buf, int offset, int size, SocketFlags flags, ref EndPoint remote_end)
- {
- int error;
- return ReceiveFrom_nochecks_exc (buf, offset, size, flags, ref remote_end, true, out error);
- }
-
internal int ReceiveFrom_nochecks_exc (byte [] buf, int offset, int size, SocketFlags flags, ref EndPoint remote_end, bool throwOnError, out int error)
{
SocketAddress sockaddr = remote_end.Serialize();
return ret;
}
- internal int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
+ int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
{
if (size == 0) {
error = SocketError.Success;
if (e.Buffer == null) {
sockares = CreateSocketAsyncResultFromSocketAsyncEventArgs (e, SocketOperation.SendGeneric, e.SendCallback);
sockares.Buffers = e.BufferList;
+
+ QueueIOSelectorJob (writeQ, sockares.handle, new IOSelectorJob (IOOperation.Write, BeginSendGenericCallback, sockares));
} else {
sockares = CreateSocketAsyncResultFromSocketAsyncEventArgs (e, SocketOperation.Send, e.SendCallback);
sockares.Buffer = e.Buffer;
sockares.Offset = e.Offset;
sockares.Size = e.Count;
- }
- QueueIOSelectorJob (writeQ, sockares.handle, new IOSelectorJob (IOOperation.Write, s => ((SocketAsyncResult) s).Worker.Send (), sockares));
+ QueueIOSelectorJob (writeQ, sockares.handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, 0), sockares));
+ }
return true;
}
SockFlags = socket_flags,
};
- QueueIOSelectorJob (writeQ, sockares.handle, new IOSelectorJob (IOOperation.Write, s => ((SocketAsyncResult) s).Worker.Send (), sockares));
+ QueueIOSelectorJob (writeQ, sockares.handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, 0), sockares));
return sockares;
}
+ static void BeginSendCallback (SocketAsyncResult sockares, int sent_so_far)
+ {
+ int total = 0;
+
+ try {
+ total = Socket.Send_internal (sockares.socket.safe_handle, sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, out sockares.error);
+ } catch (Exception e) {
+ sockares.Complete (e);
+ return;
+ }
+
+ if (sockares.error == 0) {
+ sent_so_far += total;
+ sockares.Offset += total;
+ sockares.Size -= total;
+
+ if (sockares.socket.is_disposed) {
+ sockares.Complete (total);
+ return;
+ }
+
+ if (sockares.Size > 0) {
+ IOSelector.Add (sockares.handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, sent_so_far), sockares));
+ return; // Have to finish writing everything. See bug #74475.
+ }
+
+ sockares.Total = sent_so_far;
+ }
+
+ sockares.Complete (total);
+ }
+
public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, AsyncCallback callback, object state)
{
ThrowIfDisposedAndClosed ();
SockFlags = socketFlags,
};
- QueueIOSelectorJob (writeQ, sockares.handle, new IOSelectorJob (IOOperation.Write, s => ((SocketAsyncResult) s).Worker.SendGeneric (), sockares));
+ QueueIOSelectorJob (writeQ, sockares.handle, new IOSelectorJob (IOOperation.Write, BeginSendGenericCallback, sockares));
return sockares;
}
return BeginSend (buffers, socketFlags, callback, state);
}
+ static IOAsyncCallback BeginSendGenericCallback = new IOAsyncCallback (ares => {
+ SocketAsyncResult sockares = (SocketAsyncResult) ares;
+ int total = 0;
+
+ try {
+ total = sockares.socket.Send (sockares.Buffers, sockares.SockFlags);
+ } catch (Exception e) {
+ sockares.Complete (e);
+ return;
+ }
+
+ sockares.Complete (total);
+ });
+
public int EndSend (IAsyncResult result)
{
SocketError error;
[MethodImplAttribute (MethodImplOptions.InternalCall)]
extern static int Send_internal (IntPtr sock, WSABUF[] bufarray, SocketFlags flags, out int error);
- internal static int Send_internal (SafeSocketHandle safeHandle, byte[] buf, int offset, int count, SocketFlags flags, out int error)
+ static int Send_internal (SafeSocketHandle safeHandle, byte[] buf, int offset, int count, SocketFlags flags, out int error)
{
try {
safeHandle.RegisterForBlockingSyscall ();
{
ThrowIfDisposedAndClosed ();
ThrowIfBufferNull (buffer);
- ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
- if (remote_end == null)
- throw new ArgumentNullException ("remote_end");
-
- return SendTo_nochecks (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
+ return SendTo (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
}
public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
{
ThrowIfDisposedAndClosed ();
ThrowIfBufferNull (buffer);
- ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
- if (remote_end == null)
- throw new ArgumentNullException ("remote_end");
-
- return SendTo_nochecks (buffer, 0, buffer.Length, flags, remote_end);
+ return SendTo (buffer, 0, buffer.Length, flags, remote_end);
}
public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
{
- ThrowIfDisposedAndClosed ();
- ThrowIfBufferNull (buffer);
- ThrowIfBufferOutOfRange (buffer, 0, size);
-
- if (remote_end == null)
- throw new ArgumentNullException ("remote_end");
-
- return SendTo_nochecks (buffer, 0, size, flags, remote_end);
+ return SendTo (buffer, 0, size, flags, remote_end);
}
public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags, EndPoint remote_end)
return SendTo_nochecks (buffer, offset, size, flags, remote_end);
}
- internal int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags, EndPoint remote_end)
- {
- int error;
- int ret = SendTo_internal (safe_handle, buffer, offset, size, flags, remote_end.Serialize (), out error);
-
- SocketError err = (SocketError) error;
- if (err != 0) {
- if (err != SocketError.WouldBlock && err != SocketError.InProgress)
- is_connected = false;
- throw new SocketException (error);
- }
-
- is_connected = true;
- is_bound = true;
- seed_endpoint = remote_end;
-
- return ret;
- }
-
public bool SendToAsync (SocketAsyncEventArgs e)
{
// NO check is made whether e != null in MS.NET (NRE is thrown in such case)
sockares.SockFlags = e.SocketFlags;
sockares.EndPoint = e.RemoteEndPoint;
- QueueIOSelectorJob (writeQ, sockares.handle, new IOSelectorJob (IOOperation.Write, s => ((SocketAsyncResult) s).Worker.SendTo (), sockares));
+ QueueIOSelectorJob (writeQ, sockares.handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, 0), sockares));
return true;
}
EndPoint = remote_end,
};
- QueueIOSelectorJob (writeQ, sockares.handle, new IOSelectorJob (IOOperation.Write, s => ((SocketAsyncResult) s).Worker.SendTo (), sockares));
+ QueueIOSelectorJob (writeQ, sockares.handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, 0), sockares));
return sockares;
}
+ static void BeginSendToCallback (SocketAsyncResult sockares, int sent_so_far)
+ {
+ int total = 0;
+ try {
+ total = sockares.socket.SendTo_nochecks (sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, sockares.EndPoint);
+
+ if (sockares.error == 0) {
+ sent_so_far += total;
+ sockares.Offset += total;
+ sockares.Size -= total;
+ }
+
+ if (sockares.Size > 0) {
+ IOSelector.Add (sockares.handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, sent_so_far), sockares));
+ return; // Have to finish writing everything. See bug #74475.
+ }
+
+ sockares.Total = sent_so_far;
+ } catch (Exception e) {
+ sockares.Complete (e);
+ return;
+ }
+
+ sockares.Complete ();
+ }
+
public int EndSendTo (IAsyncResult result)
{
ThrowIfDisposedAndClosed ();
return sockares.Total;
}
+ int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags, EndPoint remote_end)
+ {
+ int error;
+ int ret = SendTo_internal (safe_handle, buffer, offset, size, flags, remote_end.Serialize (), out error);
+
+ SocketError err = (SocketError) error;
+ if (err != 0) {
+ if (err != SocketError.WouldBlock && err != SocketError.InProgress)
+ is_connected = false;
+ throw new SocketException (error);
+ }
+
+ is_connected = true;
+ is_bound = true;
+ seed_endpoint = remote_end;
+
+ return ret;
+ }
+
static int SendTo_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, SocketAddress sa, out int error)
{
try {
SocketAsyncResult CreateSocketAsyncResultFromSocketAsyncEventArgs (SocketAsyncEventArgs e, SocketOperation op, AsyncCallback callback)
{
- SocketAsyncResult sockares = new SocketAsyncResult (this, s => SocketAsyncEventArgsCallback (callback, s), e, op, null);
- SocketAsyncWorker worker = new SocketAsyncWorker (sockares);
-
- sockares.Worker = worker;
+ SocketAsyncResult sockares = new SocketAsyncResult (this, s => SocketAsyncEventArgsCallback (callback, s), e, op);
- e.Worker = sockares.Worker;
e.curSocket = this;
e.SetLastOperation (SocketOperationToSocketAsyncOperation (op));
e.SocketError = SocketError.Success;
+++ /dev/null
-// System.Net.Sockets.SocketAsyncWorker.cs
-//
-// Authors:
-// Ludovic Henry <ludovic@xamarin.com>
-//
-// Copyright (C) 2015 Xamarin, Inc. (https://www.xamarin.com)
-//
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System.Threading;
-
-namespace System.Net.Sockets
-{
- internal sealed class SocketAsyncWorker
- {
- public SocketAsyncResult result;
- SocketAsyncEventArgs args;
-
- public SocketAsyncWorker (SocketAsyncEventArgs args)
- {
- this.args = args;
- result = new SocketAsyncResult ();
- result.Worker = this;
- }
-
- public SocketAsyncWorker (SocketAsyncResult ares)
- {
- this.result = ares;
- }
-
- public void Dispose ()
- {
- if (result != null) {
- result.Dispose ();
- result = null;
- args = null;
- }
- }
-
- public void Accept ()
- {
- Socket acc_socket = null;
- try {
- if (args != null && args.AcceptSocket != null) {
- result.socket.Accept (args.AcceptSocket);
- acc_socket = args.AcceptSocket;
- } else {
- acc_socket = result.socket.Accept ();
- if (args != null)
- args.AcceptSocket = acc_socket;
- }
- } catch (Exception e) {
- result.Complete (e);
- return;
- }
-
- result.Complete (acc_socket);
- }
-
- /* only used in 2.0 profile and newer, but
- * leave in older profiles to keep interface
- * to runtime consistent
- */
- public void AcceptReceive ()
- {
- Socket acc_socket = null;
- try {
- if (result.AcceptSocket == null) {
- acc_socket = result.socket.Accept ();
- } else {
- acc_socket = result.AcceptSocket;
- result.socket.Accept (acc_socket);
- }
- } catch (Exception e) {
- result.Complete (e);
- return;
- }
-
- /* It seems the MS runtime
- * special-cases 0-length requested
- * receive data. See bug 464201.
- */
- int total = 0;
- if (result.Size > 0) {
- try {
- SocketError error;
- total = acc_socket.Receive_nochecks (result.Buffer, result.Offset, result.Size, result.SockFlags, out error);
- if (error != 0) {
- result.Complete (new SocketException ((int) error));
- return;
- }
- } catch (Exception e) {
- result.Complete (e);
- return;
- }
- }
-
- result.Complete (acc_socket, total);
- }
-
- public void Connect ()
- {
- if (result.EndPoint == null) {
- result.Complete (new SocketException ((int)SocketError.AddressNotAvailable));
- return;
- }
-
- SocketAsyncResult mconnect = result.AsyncState as SocketAsyncResult;
- bool is_mconnect = (mconnect != null && mconnect.Addresses != null);
- try {
- int error_code;
- EndPoint ep = result.EndPoint;
- error_code = (int) result.socket.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
- if (error_code == 0) {
- if (is_mconnect)
- result = mconnect;
- result.socket.seed_endpoint = ep;
- result.socket.is_connected = true;
- result.socket.is_bound = true;
- result.socket.connect_in_progress = false;
- result.error = 0;
- result.Complete ();
- return;
- }
-
- if (!is_mconnect) {
- result.socket.connect_in_progress = false;
- result.Complete (new SocketException (error_code));
- return;
- }
-
- if (mconnect.CurrentAddress >= mconnect.Addresses.Length) {
- mconnect.Complete (new SocketException (error_code));
- return;
- }
- mconnect.socket.BeginMConnect (mconnect);
- } catch (Exception e) {
- result.socket.connect_in_progress = false;
- if (is_mconnect)
- result = mconnect;
- result.Complete (e);
- return;
- }
- }
-
- /* Also only used in 2.0 profile and newer */
- public void Disconnect ()
- {
- try {
- if (args != null)
- result.ReuseSocket = args.DisconnectReuseSocket;
- result.socket.Disconnect (result.ReuseSocket);
- } catch (Exception e) {
- result.Complete (e);
- return;
- }
- result.Complete ();
- }
-
- public void Receive ()
- {
- if (result.operation == SocketOperation.ReceiveGeneric) {
- ReceiveGeneric ();
- return;
- }
-
- int total = 0;
- try {
- total = Socket.Receive_internal (result.socket.safe_handle, result.Buffer, result.Offset, result.Size, result.SockFlags, out result.error);
- } catch (Exception e) {
- result.Complete (e);
- return;
- }
-
- result.Complete (total);
- }
-
- public void ReceiveFrom ()
- {
- int total = 0;
- try {
- total = result.socket.ReceiveFrom_nochecks (result.Buffer, result.Offset, result.Size, result.SockFlags, ref result.EndPoint);
- } catch (Exception e) {
- result.Complete (e);
- return;
- }
-
- result.Complete (total);
- }
-
- public void ReceiveGeneric ()
- {
- int total = 0;
- try {
- total = result.socket.Receive (result.Buffers, result.SockFlags);
- } catch (Exception e) {
- result.Complete (e);
- return;
- }
- result.Complete (total);
- }
-
- int send_so_far;
-
- void UpdateSendValues (int last_sent)
- {
- if (result.error == 0) {
- send_so_far += last_sent;
- result.Offset += last_sent;
- result.Size -= last_sent;
- }
- }
-
- public void Send ()
- {
- if (result.operation == SocketOperation.SendGeneric) {
- SendGeneric ();
- return;
- }
-
- int total = 0;
- try {
- total = Socket.Send_internal (result.socket.safe_handle, result.Buffer, result.Offset, result.Size, result.SockFlags, out result.error);
- } catch (Exception e) {
- result.Complete (e);
- return;
- }
-
- if (result.error == 0) {
- UpdateSendValues (total);
- if (result.socket.is_disposed) {
- result.Complete (total);
- return;
- }
-
- if (result.Size > 0) {
- IOSelector.Add (result.handle, new IOSelectorJob (IOOperation.Write, s => ((SocketAsyncResult) s).Worker.Send (), result));
- return; // Have to finish writing everything. See bug #74475.
- }
- result.Total = send_so_far;
- send_so_far = 0;
- }
- result.Complete (total);
- }
-
- public void SendTo ()
- {
- int total = 0;
- try {
- total = result.socket.SendTo_nochecks (result.Buffer, result.Offset, result.Size, result.SockFlags, result.EndPoint);
-
- UpdateSendValues (total);
- if (result.Size > 0) {
- IOSelector.Add (result.handle, new IOSelectorJob (IOOperation.Write, s => ((SocketAsyncResult) s).Worker.SendTo (), result));
- return; // Have to finish writing everything. See bug #74475.
- }
- result.Total = send_so_far;
- send_so_far = 0;
- } catch (Exception e) {
- send_so_far = 0;
- result.Complete (e);
- return;
- }
-
- result.Complete ();
- }
-
- public void SendGeneric ()
- {
- int total = 0;
- try {
- total = result.socket.Send (result.Buffers, result.SockFlags);
- } catch (Exception e) {
- result.Complete (e);
- return;
- }
- result.Complete (total);
- }
- }
-}