* As such, this value is set on Bind, SentTo, ReceiveFrom,
* Connect, etc.
*/
- private EndPoint seed_endpoint = null;
+ internal EndPoint seed_endpoint = null;
#if NET_2_0
private bool isbound;
get {
return(connected);
}
+
+ internal set { connected = value; }
}
#if NET_2_0
}
}
+#if NET_2_0
+ public bool AcceptAsync (SocketAsyncEventArgs e)
+ {
+ // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
+
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+ if (!IsBound)
+ throw new InvalidOperationException ("You must call the Bind method before performing this operation.");
+ if (!islistening)
+ throw new InvalidOperationException ("You must call the Listen method before performing this operation.");
+ if (e.BufferList != null)
+ throw new ArgumentException ("Multiple buffers cannot be used with this method.");
+ if (e.Count < 0)
+ throw new ArgumentOutOfRangeException ("e.Count");
+
+ Socket acceptSocket = e.AcceptSocket;
+ if (acceptSocket != null) {
+ if (acceptSocket.IsBound || acceptSocket.Connected)
+ throw new InvalidOperationException ("AcceptSocket: The socket must not be bound or connected.");
+ } else
+ e.AcceptSocket = new Socket (AddressFamily, SocketType, ProtocolType);
+
+ try {
+ e.DoOperation (SocketAsyncOperation.Accept, this);
+ } catch {
+ ((IDisposable)e).Dispose ();
+ throw;
+ }
+
+ // We always return true for now
+ return true;
+ }
+#endif
+
// Creates a new system socket, returning the handle
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern static IntPtr Accept_internal(IntPtr sock, out int error);
return(accepted);
}
- private void Accept (Socket acceptSocket)
+ internal void Accept (Socket acceptSocket)
{
if (disposed && closed)
throw new ObjectDisposedException (GetType ().ToString ());
{
this.Close ();
}
-#endif
+ public bool ConnectAsync (SocketAsyncEventArgs e)
+ {
+ // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
+
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+ if (islistening)
+ throw new InvalidOperationException ("You may not perform this operation after calling the Listen method.");
+ if (e.RemoteEndPoint == null)
+ throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
+ if (e.BufferList != null)
+ throw new ArgumentException ("Multiple buffers cannot be used with this method.");
+
+ e.DoOperation (SocketAsyncOperation.Connect, this);
+
+ // We always return true for now
+ return true;
+ }
+#endif
+
// Connects to the remote address
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern static void Connect_internal(IntPtr sock,
Connect (hostent.AddressList, port);
}
+#if NET_2_0
+ public bool DisconnectAsync (SocketAsyncEventArgs e)
+ {
+ // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+
+ e.DoOperation (SocketAsyncOperation.Disconnect, this);
+
+ return true;
+ }
+#endif
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern static void Disconnect_internal(IntPtr sock,
bool reuse,
* also needs to check the socket error status, but
* getsockopt(..., SO_ERROR) clears the error.
*/
- private bool Poll (int time_us, SelectMode mode, out int socket_error)
+ internal bool Poll (int time_us, SelectMode mode, out int socket_error)
{
if (disposed && closed)
throw new ObjectDisposedException (GetType ().ToString ());
return result;
}
+
+#if NET_2_0
+ public bool ReceiveAsync (SocketAsyncEventArgs e)
+ {
+ // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
+ //
+ // LAME SPEC: the ArgumentException is never thrown, instead an NRE is
+ // thrown when e.Buffer and e.BufferList are null (works fine when one is
+ // set to a valid object)
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+
+ // We do not support recv into multiple buffers yet
+ if (e.BufferList != null)
+ throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
+
+ e.DoOperation (SocketAsyncOperation.Receive, this);
+
+ // We always return true for now
+ return true;
+ }
+#endif
public int Receive (byte [] buf)
{
SocketFlags flags,
out int error);
- int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
+ internal int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
{
int nativeError;
int ret = Receive_internal (socket, buf, offset, size, flags, out nativeError);
return ret;
}
+
+#if NET_2_0
+ public bool ReceiveFromAsync (SocketAsyncEventArgs e)
+ {
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+
+ // We do not support recv into multiple buffers yet
+ if (e.BufferList != null)
+ throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
+ if (e.RemoteEndPoint == null)
+ throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
+
+ e.DoOperation (SocketAsyncOperation.ReceiveFrom, this);
+
+ // We always return true for now
+ return true;
+ }
+#endif
public int ReceiveFrom (byte [] buf, ref EndPoint remote_end)
{
return ReceiveFrom_nochecks (buf, offset, size, flags, ref remote_end);
}
- int ReceiveFrom_nochecks (byte [] buf, int offset, int size, SocketFlags flags,
- ref EndPoint remote_end)
+ internal int ReceiveFrom_nochecks (byte [] buf, int offset, int size, SocketFlags flags,
+ ref EndPoint remote_end)
{
SocketAddress sockaddr = remote_end.Serialize();
int cnt, error;
}
#if NET_2_0
+ [MonoTODO ("Not implemented")]
+ public bool ReceiveMessageFromAsync (SocketAsyncEventArgs e)
+ {
+ // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+
+ throw new NotImplementedException ();
+ }
+
[MonoTODO ("Not implemented")]
public int ReceiveMessageFrom (byte[] buffer, int offset,
int size,
*/
throw new NotImplementedException ();
}
+
+ [MonoTODO ("Not implemented")]
+ public bool SendPacketsAsync (SocketAsyncEventArgs e)
+ {
+ // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
+
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+
+ throw new NotImplementedException ();
+ }
+
+ public bool SendAsync (SocketAsyncEventArgs e)
+ {
+ // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
+
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+ if (e.Buffer == null && e.BufferList == null)
+ throw new ArgumentException ("Either e.Buffer or e.BufferList must be valid buffers.");
+
+ e.DoOperation (SocketAsyncOperation.Send, this);
+
+ // We always return true for now
+ return true;
+ }
#endif
public int Send (byte [] buf)
SocketFlags flags,
out int error);
- int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
+ internal int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
{
if (size == 0) {
error = SocketError.Success;
/* FIXME: Implement TransmitFile */
throw new NotImplementedException ();
}
-#endif
+ public bool SendToAsync (SocketAsyncEventArgs e)
+ {
+ // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
+
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+ if (e.RemoteEndPoint == null)
+ throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
+
+ e.DoOperation (SocketAsyncOperation.SendTo, this);
+
+ // We always return true for now
+ return true;
+ }
+#endif
+
public int SendTo (byte [] buffer, EndPoint remote_end)
{
if (disposed && closed)
return SendTo_nochecks (buffer, offset, size, flags, remote_end);
}
- int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags,
- EndPoint remote_end)
+ internal int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags,
+ EndPoint remote_end)
{
SocketAddress sockaddr = remote_end.Serialize ();
#if NET_2_0
using System;
using System.Collections.Generic;
+using System.Threading;
namespace System.Net.Sockets
{
public class SocketAsyncEventArgs : EventArgs, IDisposable
- {
+ {
public event EventHandler<SocketAsyncEventArgs> Completed;
IList <ArraySegment <byte>> _bufferList;
public SocketFlags SocketFlags { get; set; }
public object UserToken { get; set; }
+ Socket curSocket;
+
public SocketAsyncEventArgs ()
{
AcceptSocket = null;
if (disposing)
GC.SuppressFinalize (this);
- }
-
- public void Dispose ()
- {
- Dispose (true);
- }
+ }
void IDisposable.Dispose ()
{
protected virtual void OnCompleted (SocketAsyncEventArgs e)
{
- if (Completed != null)
- Completed (this, e);
+ if (e == null)
+ return;
+
+ if (e.Completed != null)
+ e.Completed (e.curSocket, e);
}
public void SetBuffer (int offset, int count)
if (offset < 0 || offset >= buflen)
throw new ArgumentOutOfRangeException ("offset");
- if (count < 0 || count + offset >= buflen)
+ if (count < 0 || count + offset > buflen)
throw new ArgumentOutOfRangeException ("count");
}
Offset = offset;
Buffer = buffer;
}
+
+#region Internals
+ void AcceptCallback ()
+ {
+ SocketError = SocketError.Success;
+ LastOperation = SocketAsyncOperation.Accept;
+ try {
+ curSocket.Accept (AcceptSocket);
+ } catch (SocketException ex) {
+ SocketError = ex.SocketErrorCode;
+ throw;
+ } finally {
+ OnCompleted (this);
+ }
+ }
+
+ void ReceiveCallback ()
+ {
+ SocketError = SocketError.Success;
+ LastOperation = SocketAsyncOperation.Receive;
+ SocketError error = SocketError.Success;
+
+ try {
+ BytesTransferred = curSocket.Receive_nochecks (Buffer, Offset, Count, SocketFlags, out error);
+ } finally {
+ SocketError = error;
+ OnCompleted (this);
+ }
+ }
+
+ void ConnectCallback ()
+ {
+ SocketError = SocketError.Success;
+ LastOperation = SocketAsyncOperation.Connect;
+ SocketError error = SocketError.Success;
+
+ try {
+ if (!curSocket.Blocking) {
+ int success;
+ curSocket.Poll (-1, SelectMode.SelectWrite, out success);
+ SocketError = (SocketError)success;
+ if (success == 0)
+ curSocket.Connected = true;
+ else
+ return;
+ } else {
+ curSocket.seed_endpoint = RemoteEndPoint;
+ curSocket.Connect (RemoteEndPoint);
+ curSocket.Connected = true;
+ }
+ } finally {
+ SocketError = error;
+ OnCompleted (this);
+ }
+ }
+
+ void SendCallback ()
+ {
+ SocketError = SocketError.Success;
+ LastOperation = SocketAsyncOperation.Send;
+ SocketError error = SocketError.Success;
+
+ try {
+ BytesTransferred = curSocket.Send_nochecks (Buffer, Offset, Count, SocketFlags.None, out error);
+ } finally {
+ SocketError = error;
+ OnCompleted (this);
+ }
+ }
+
+ void DisconnectCallback ()
+ {
+ SocketError = SocketError.Success;
+ LastOperation = SocketAsyncOperation.Disconnect;
+
+ try {
+ curSocket.Disconnect (DisconnectReuseSocket);
+ } catch (SocketException ex) {
+ SocketError = ex.SocketErrorCode;
+ throw;
+ } finally {
+ OnCompleted (this);
+ }
+ }
+
+ void ReceiveFromCallback ()
+ {
+ SocketError = SocketError.Success;
+ LastOperation = SocketAsyncOperation.ReceiveFrom;
+
+ try {
+ EndPoint ep = RemoteEndPoint;
+ BytesTransferred = curSocket.ReceiveFrom_nochecks (Buffer, Offset, Count, SocketFlags, ref ep);
+ } catch (SocketException ex) {
+ SocketError = ex.SocketErrorCode;
+ throw;
+ } finally {
+ OnCompleted (this);
+ }
+ }
+
+ void SendToCallback ()
+ {
+ SocketError = SocketError.Success;
+ LastOperation = SocketAsyncOperation.SendTo;
+ int total = 0;
+
+ try {
+ int count = Count;
+
+ while (total < count)
+ total += curSocket.SendTo_nochecks (Buffer, Offset, count, SocketFlags, RemoteEndPoint);
+ BytesTransferred = total;
+ } catch (SocketException ex) {
+ SocketError = ex.SocketErrorCode;
+ throw;
+ } finally {
+ OnCompleted (this);
+ }
+ }
+
+ internal void DoOperation (SocketAsyncOperation operation, Socket socket)
+ {
+ ThreadStart callback;
+ curSocket = socket;
+
+ switch (operation) {
+ case SocketAsyncOperation.Accept:
+ callback = new ThreadStart (AcceptCallback);
+ break;
+
+ case SocketAsyncOperation.Receive:
+ callback = new ThreadStart (ReceiveCallback);
+ break;
+
+ case SocketAsyncOperation.Connect:
+ callback = new ThreadStart (ConnectCallback);
+ break;
+
+ case SocketAsyncOperation.Disconnect:
+ callback = new ThreadStart (DisconnectCallback);
+ break;
+
+ case SocketAsyncOperation.ReceiveFrom:
+ callback = new ThreadStart (ReceiveFromCallback);
+ break;
+
+ case SocketAsyncOperation.Send:
+ callback = new ThreadStart (SendCallback);
+ break;
+
+ case SocketAsyncOperation.SendTo:
+ callback = new ThreadStart (SendToCallback);
+ break;
+
+ default:
+ throw new NotSupportedException ();
+ break;
+ }
+
+ Thread t = new Thread (callback);
+ t.IsBackground = true;
+ t.Start ();
+ }
+#endregion
}
}
#endif