// System.Net.Sockets.Socket.cs
//
// Authors:
-// Phillip Pearson (pp@myelin.co.nz)
-// Dick Porter <dick@ximian.com>
+// Phillip Pearson (pp@myelin.co.nz)
+// Dick Porter <dick@ximian.com>
+// Gonzalo Paniagua Javier (gonzalo@ximian.com)
//
// Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
// http://www.myelin.co.nz
+// (c) 2004 Novell, Inc. (http://www.novell.com)
//
using System;
using System.Net;
using System.Collections;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
using System.Threading;
using System.Reflection;
using System.IO;
{
public class Socket : IDisposable
{
+ [StructLayout (LayoutKind.Sequential)]
private sealed class SocketAsyncResult: IAsyncResult
{
- private object state;
- private WaitHandle waithandle;
- private bool completed_sync, completed;
- private Worker worker;
- private Exception delayedException = null;
+ /* Same structure in the runtime */
+ public Socket Sock;
+ IntPtr handle;
+ object state;
+ AsyncCallback callback;
+ WaitHandle waithandle;
- public SocketAsyncResult(object state) {
- this.state=state;
- completed_sync=completed=false;
+ Exception delayedException;
+
+ public EndPoint EndPoint; // Connect,ReceiveFrom,SendTo
+ public byte [] Buffer; // Receive,ReceiveFrom,Send,SendTo
+ public int Offset; // Receive,ReceiveFrom,Send,SendTo
+ public int Size; // Receive,ReceiveFrom,Send,SendTo
+ public SocketFlags SockFlags; // Receive,ReceiveFrom,Send,SendTo
+
+ // Return values
+ Socket acc_socket;
+ int total;
+
+ bool completed_sync;
+ bool completed;
+ AsyncCallback real_callback;
+ int error;
+
+ public SocketAsyncResult (Socket sock, object state, AsyncCallback callback)
+ {
+ this.Sock = sock;
+ this.handle = sock.socket;
+ this.state = state;
+ this.real_callback = callback;
+ SockFlags = SocketFlags.None;
}
- public void SetDelayedException (Exception e) {
- delayedException = e;
+ public void CreateAsyncDelegate ()
+ {
+ if (real_callback != null)
+ this.callback = new AsyncCallback (FakeCB);
}
- public void CheckIfThrowDelayedException () {
+ static void FakeCB (IAsyncResult result)
+ {
+ SocketAsyncResult ares = (SocketAsyncResult) result;
+ ares.real_callback.BeginInvoke (ares, null, null);
+ }
+
+ public void CheckIfThrowDelayedException ()
+ {
if (delayedException != null)
throw delayedException;
+
+ if (error != 0)
+ throw new SocketException (error);
+ }
+
+ public void Complete ()
+ {
+ IsCompleted = true;
+ if (real_callback != null)
+ real_callback (this);
+ }
+
+ public void Complete (int total)
+ {
+ this.total = total;
+ Complete ();
+ }
+
+ public void Complete (Exception e)
+ {
+ delayedException = e;
+ Complete ();
+ }
+
+ public void Complete (Socket s)
+ {
+ acc_socket = s;
+ Complete ();
}
public object AsyncState {
get {
- return(state);
+ return state;
}
}
}
}
- public Worker Worker {
+ public Socket Socket {
get {
- return(worker);
+ return acc_socket;
}
- set {
- worker=value;
+ }
+
+ public int Total {
+ get {
+ return total;
}
}
}
private sealed class Worker
{
- private AsyncCallback callback;
- private SocketAsyncResult result;
- private Socket socket;
-
- // Parameters
- private EndPoint endpoint; // Connect,ReceiveFrom,SendTo
- private byte[] buffer; // Receive,ReceiveFrom,Send,SendTo
- private int offset; // Receive,ReceiveFrom,Send,SendTo
- private int size; // Receive,ReceiveFrom,Send,SendTo
- private SocketFlags sockflags; // Receive,ReceiveFrom,Send,SendTo
-
- // Return values
- private Socket acc_socket;
- private int total;
-
+ SocketAsyncResult result;
- // For Accept
- public Worker(Socket req_sock,
- AsyncCallback req_callback,
- SocketAsyncResult req_result)
- : this(req_sock, null, 0, 0, SocketFlags.None,
- null, req_callback, req_result) {}
-
- // For Connect
- public Worker(Socket req_sock, EndPoint req_endpoint,
- AsyncCallback req_callback,
- SocketAsyncResult req_result)
- : this(req_sock, null, 0, 0, SocketFlags.None,
- req_endpoint, req_callback,
- req_result) {}
-
- // For Receive and Send
- public Worker(Socket req_sock, byte[] req_buffer,
- int req_offset, int req_size,
- SocketFlags req_sockflags,
- AsyncCallback req_callback,
- SocketAsyncResult req_result)
- : this(req_sock, req_buffer, req_offset,
- req_size, req_sockflags, null,
- req_callback, req_result) {}
-
- // For ReceiveFrom and SendTo
- public Worker(Socket req_sock, byte[] req_buffer,
- int req_offset, int req_size,
- SocketFlags req_sockflags,
- EndPoint req_endpoint,
- AsyncCallback req_callback,
- SocketAsyncResult req_result) {
- socket=req_sock;
- buffer=req_buffer;
- offset=req_offset;
- size=req_size;
- sockflags=req_sockflags;
- endpoint=req_endpoint;
- callback=req_callback;
- result=req_result;
- }
-
- private void End() {
- result.IsCompleted=true;
- if (callback != null)
- callback(result);
+ public Worker (SocketAsyncResult ares)
+ {
+ this.result = ares;
}
-
- public void Accept() {
- lock(result) {
+
+ public void Accept ()
+ {
+ lock (result) {
+ Socket acc_socket = null;
try {
- acc_socket=socket.Accept();
+ acc_socket = result.Sock.Accept ();
} catch (Exception e) {
- result.SetDelayedException(e);
+ result.Complete (e);
+ return;
}
- End();
+
+ result.Complete (acc_socket);
}
}
- public void Connect() {
- lock(result) {
- if (socket.Blocking) {
- try {
- socket.Connect(endpoint);
- } catch (Exception e) {
- result.SetDelayedException(e);
- }
- End ();
- return;
- }
-
- Exception rethrow = null;
+ public void Connect ()
+ {
+ lock (result) {
try {
- socket.Connect (endpoint);
- } catch (SocketException e) {
- //WSAEINPROGRESS
- if (e.NativeErrorCode != 10036) {
- result.SetDelayedException(e);
- End ();
+ result.Sock.Connect (result.EndPoint);
+ } catch (SocketException se) {
+ if (result.Sock.blocking || se.ErrorCode != 10036) {
+ result.Complete (se);
return;
}
-
- socket.Poll (-1, SelectMode.SelectWrite);
+
try {
- socket.Connect (endpoint);
- } catch (SocketException e2) {
- rethrow = e2;
+ result.Sock.Poll (-1, SelectMode.SelectWrite);
+ result.Sock.Connect (result.EndPoint);
+ } catch (Exception k) {
+ result.Complete (k);
+ return;
}
- } catch (Exception e3) {
- rethrow = e3;
+ } catch (Exception e) {
+ result.Complete (e);
+ return;
}
-
- if (rethrow != null)
- result.SetDelayedException(rethrow);
- End ();
+
+ result.Complete ();
}
}
- public void Receive() {
- lock(result) {
- if (socket.Blocking) {
- try {
- total=socket.Receive(buffer, offset,
- size, sockflags);
- } catch (Exception e) {
- result.SetDelayedException(e);
- }
- End();
- return;
- }
-
- Exception rethrow = null;
+ public void Receive ()
+ {
+ lock (result) {
+ int total = 0;
try {
- total = socket.Receive (buffer, offset, size, sockflags);
- } catch (SocketException e) {
- //WSAEWOULDBLOCK
- if (e.NativeErrorCode != 10035) {
- result.SetDelayedException(e);
- End ();
- return;
- }
+ if (!result.Sock.blocking)
+ result.Sock.Poll (-1, SelectMode.SelectRead);
- socket.Poll (-1, SelectMode.SelectRead);
- try {
- total = socket.Receive (buffer, offset, size, sockflags);
- } catch (SocketException e2) {
- rethrow = e2;
- }
- } catch (Exception e3) {
- rethrow = e3;
+ total = result.Sock.Receive_nochecks (result.Buffer,
+ result.Offset,
+ result.Size,
+ result.SockFlags);
+ } catch (Exception e) {
+ result.Complete (e);
+ return;
}
- if (rethrow != null)
- result.SetDelayedException(rethrow);
- End ();
+ result.Complete (total);
}
}
- public void ReceiveFrom() {
- lock(result) {
- if (socket.Blocking) {
- try {
- total=socket.ReceiveFrom(buffer,
- offset, size,
- sockflags,
- ref endpoint);
- } catch (Exception e) {
- result.SetDelayedException(e);
- }
- End();
- return;
- }
-
- Exception rethrow = null;
+ public void ReceiveFrom ()
+ {
+ lock (result) {
+ int total = 0;
try {
- total = socket.ReceiveFrom (buffer, offset, size,
- sockflags, ref endpoint);
- } catch (SocketException e) {
- //WSAEWOULDBLOCK
- if (e.NativeErrorCode != 10035) {
- result.SetDelayedException(e);
- End ();
- return;
- }
-
- socket.Poll (-1, SelectMode.SelectRead);
- try {
- total = socket.ReceiveFrom (buffer, offset, size,
- sockflags, ref endpoint);
- } catch (SocketException e2) {
- rethrow = e2;
- }
- } catch (Exception e3) {
- rethrow = e3;
+ if (!result.Sock.blocking)
+ result.Sock.Poll (-1, SelectMode.SelectRead);
+
+ total = result.Sock.ReceiveFrom_nochecks (result.Buffer,
+ result.Offset,
+ result.Size,
+ result.SockFlags,
+ ref result.EndPoint);
+ } catch (Exception e) {
+ result.Complete (e);
+ return;
}
- if (rethrow != null)
- result.SetDelayedException(rethrow);
- End ();
+ result.Complete (total);
}
}
- public void Send() {
- lock(result) {
- if (socket.Blocking) {
- try {
- total=socket.Send(buffer, offset, size,
- sockflags);
- } catch (Exception e) {
- result.SetDelayedException(e);
- }
- End();
- return;
- }
-
- Exception rethrow = null;
+ public void Send ()
+ {
+ lock (result) {
+ int total = 0;
try {
- total = socket.Send (buffer, offset, size, sockflags);
- } catch (SocketException e) {
- //WSAEWOULDBLOCK
- if (e.NativeErrorCode != 10035) {
- result.SetDelayedException(e);
- End ();
- return;
- }
+ if (!result.Sock.blocking)
+ result.Sock.Poll (-1, SelectMode.SelectWrite);
- socket.Poll (-1, SelectMode.SelectWrite);
- try {
- total = socket.Send (buffer, offset, size, sockflags);
- } catch (SocketException e2) {
- rethrow = e2;
- }
- } catch (Exception e3) {
- rethrow = e3;
+ total = result.Sock.Send_nochecks (result.Buffer,
+ result.Offset,
+ result.Size,
+ result.SockFlags);
+ } catch (Exception e) {
+ result.Complete (e);
+ return;
}
- if (rethrow != null)
- result.SetDelayedException(rethrow);
- End ();
+ result.Complete (total);
}
}
public void SendTo() {
- lock(result) {
- if (socket.Blocking) {
- try {
- total=socket.SendTo(buffer, offset,
- size, sockflags,
- endpoint);
- } catch (Exception e) {
- result.SetDelayedException(e);
- }
- End();
- return;
- }
-
- Exception rethrow = null;
+ lock (result) {
+ int total = 0;
try {
- total = socket.SendTo (buffer, offset, size,
- sockflags, endpoint);
- } catch (SocketException e) {
- //WSAEWOULDBLOCK
- if (e.NativeErrorCode != 10035) {
- result.SetDelayedException(e);
- End ();
- return;
- }
-
- socket.Poll (-1, SelectMode.SelectWrite);
- try {
- total = socket.SendTo (buffer, offset, size,
- sockflags, endpoint);
- } catch (SocketException e2) {
- rethrow = e2;
- }
- } catch (Exception e3) {
- rethrow = e3;
+ if (!result.Sock.blocking)
+ result.Sock.Poll (-1, SelectMode.SelectWrite);
+
+ total = result.Sock.SendTo_nochecks (result.Buffer,
+ result.Offset,
+ result.Size,
+ result.SockFlags,
+ result.EndPoint);
+ } catch (Exception e) {
+ result.Complete (e);
+ return;
}
- if (rethrow != null)
- result.SetDelayedException(rethrow);
- End ();
- }
- }
-
- public EndPoint EndPoint {
- get {
- return(endpoint);
- }
- }
-
- public Socket Socket {
- get {
- return(acc_socket);
- }
- }
-
- public int Total {
- get {
- return(total);
+ result.Complete (total);
}
}
}
private AddressFamily address_family;
private SocketType socket_type;
private ProtocolType protocol_type;
- private bool blocking=true;
+ internal bool blocking=true;
private int pendingEnds;
private int closeDelayed;
+ static readonly bool supportsAsync = FakeGetSupportsAsync ();
delegate void SocketAsyncCall ();
- /*\r
- * These two fields are looked up by name by the runtime, don't change\r
- * their name without also updating the runtime code.\r
+ /*
+ * These two fields are looked up by name by the runtime, don't change
+ * their name without also updating the runtime code.
*/
private static int ipv4Supported = -1, ipv6Supported = -1;
Assembly ass;
try {
- ass=Assembly.Load("Mono.Posix");
+ ass = Assembly.Load (Consts.AssemblyMono_Posix);
} catch (FileNotFoundException) {
return;
}
}
#if NET_1_1
- public static bool SupportsIPv4 {\r
- get {\r
- CheckProtocolSupport();\r
- return ipv4Supported == 1;\r
- }\r
+ public static bool SupportsIPv4 {
+ get {
+ CheckProtocolSupport();
+ return ipv4Supported == 1;
+ }
}
- public static bool SupportsIPv6 {\r
- get {\r
- CheckProtocolSupport();\r
- return ipv6Supported == 1;\r
- }\r
+ public static bool SupportsIPv6 {
+ get {
+ CheckProtocolSupport();
+ return ipv6Supported == 1;
+ }
}
#else
- internal static bool SupportsIPv4 \r
- {\r
- get \r
- {\r
- return true;\r
- }\r
- }
-
- internal static bool SupportsIPv6 \r
- {\r
- get \r
- {\r
- return false;\r
- }\r
- }\r
+ internal static bool SupportsIPv4
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ internal static bool SupportsIPv6
+ {
+ get
+ {
+ return false;
+ }
+ }
#endif
internal static void CheckProtocolSupport()
- {\r
- if(ipv4Supported == -1) {\r
- try {\r
- Socket tmp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);\r
- tmp.Close();\r
-\r
- ipv4Supported = 1;\r
- }\r
- catch {\r
- ipv4Supported = 0;\r
- }\r
- }\r
-\r
- if(ipv6Supported == -1) {\r
- NetConfig config = (NetConfig)System.Configuration.ConfigurationSettings.GetConfig("system.net/settings");\r
-\r
- if(config != null)\r
- ipv6Supported = config.ipv6Enabled?-1:0;\r
-\r
- if(ipv6Supported != 0) {\r
- try {\r
- Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);\r
- tmp.Close();\r
-\r
- ipv6Supported = 1;\r
- }\r
- catch { }\r
- }\r
- }\r
+ {
+ if(ipv4Supported == -1) {
+ try {
+ Socket tmp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+ tmp.Close();
+
+ ipv4Supported = 1;
+ }
+ catch {
+ ipv4Supported = 0;
+ }
+ }
+
+ if(ipv6Supported == -1) {
+ NetConfig config = (NetConfig)System.Configuration.ConfigurationSettings.GetConfig("system.net/settings");
+
+ if(config != null)
+ ipv6Supported = config.ipv6Enabled?-1:0;
+
+ if(ipv6Supported != 0) {
+ try {
+ Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
+ tmp.Close();
+
+ ipv6Supported = 1;
+ }
+ catch { }
+ }
+ }
}
// Creates a new system socket, returning the handle
throw new ObjectDisposedException (GetType ().ToString ());
Interlocked.Increment (ref pendingEnds);
- SocketAsyncResult req=new SocketAsyncResult(state);
- Worker worker=new Worker(this, callback, req);
- req.Worker=worker;
+ SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
+ Worker worker = new Worker (req);
SocketAsyncCall sac = new SocketAsyncCall (worker.Accept);
sac.BeginInvoke (null, null);
return(req);
throw new ArgumentNullException ("end_point");
Interlocked.Increment (ref pendingEnds);
- SocketAsyncResult req=new SocketAsyncResult(state);
- Worker worker=new Worker(this, end_point, callback,
- req);
- req.Worker=worker;
+ SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
+ req.EndPoint = end_point;
+ Worker worker = new Worker (req);
SocketAsyncCall sac = new SocketAsyncCall (worker.Connect);
sac.BeginInvoke (null, null);
return(req);
if (buffer == null)
throw new ArgumentNullException ("buffer");
- if (offset < 0)
- throw new ArgumentOutOfRangeException ("offset must be >= 0");
-
- if (size < 0)
- throw new ArgumentOutOfRangeException ("size must be >= 0");
+ if (offset < 0 || offset > buffer.Length)
+ throw new ArgumentOutOfRangeException ("offset");
- if (offset + size > buffer.Length)
- throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
+ if (size < 0 || offset + size > buffer.Length)
+ throw new ArgumentOutOfRangeException ("size");
Interlocked.Increment (ref pendingEnds);
- SocketAsyncResult req=new SocketAsyncResult(state);
- Worker worker=new Worker(this, buffer, offset, size,
- socket_flags, callback, req);
- req.Worker=worker;
- SocketAsyncCall sac = new SocketAsyncCall (worker.Receive);
- sac.BeginInvoke (null, null);
- return(req);
+ SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
+ req.Buffer = buffer;
+ req.Offset = offset;
+ req.Size = size;
+ req.SockFlags = socket_flags;
+ if (supportsAsync && socket_type == SocketType.Stream) {
+ int error;
+ req.CreateAsyncDelegate ();
+ KeepReference (req);
+ AsyncReceiveInternal (req, out error);
+ if (error != 10036) // WSAEINPROGRESS
+ throw new SocketException (error);
+ } else {
+ Worker worker = new Worker (req);
+ SocketAsyncCall sac = new SocketAsyncCall (worker.Receive);
+ sac.BeginInvoke (null, null);
+ }
+
+ return req;
}
public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset,
throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
Interlocked.Increment (ref pendingEnds);
- SocketAsyncResult req=new SocketAsyncResult(state);
- Worker worker=new Worker(this, buffer, offset, size,
- socket_flags, remote_end,
- callback, req);
- req.Worker=worker;
+ SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
+ req.Buffer = buffer;
+ req.Offset = offset;
+ req.Size = size;
+ req.SockFlags = socket_flags;
+ req.EndPoint = remote_end;
+ Worker worker = new Worker (req);
SocketAsyncCall sac = new SocketAsyncCall (worker.ReceiveFrom);
sac.BeginInvoke (null, null);
- return(req);
+ return req;
}
- public IAsyncResult BeginSend(byte[] buffer, int offset,
- int size,
- SocketFlags socket_flags,
- AsyncCallback callback,
- object state) {
+ public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socket_flags,
+ AsyncCallback callback, object state)
+ {
if (disposed && closed)
throw new ObjectDisposedException (GetType ().ToString ());
throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
Interlocked.Increment (ref pendingEnds);
- SocketAsyncResult req=new SocketAsyncResult(state);
- Worker worker=new Worker(this, buffer, offset, size,
- socket_flags, callback, req);
- req.Worker=worker;
- SocketAsyncCall sac = new SocketAsyncCall (worker.Send);
- sac.BeginInvoke (null, null);
- return(req);
+ SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
+ req.Buffer = buffer;
+ req.Offset = offset;
+ req.Size = size;
+ req.SockFlags = socket_flags;
+ if (supportsAsync && socket_type == SocketType.Stream) {
+ int error;
+ req.CreateAsyncDelegate ();
+ KeepReference (req);
+ AsyncSendInternal (req, out error);
+ if (error != 10036) // WSAEINPROGRESS
+ throw new SocketException (error);
+ } else {
+ Worker worker = new Worker (req);
+ SocketAsyncCall sac = new SocketAsyncCall (worker.Send);
+ sac.BeginInvoke (null, null);
+ }
+ return req;
}
public IAsyncResult BeginSendTo(byte[] buffer, int offset,
throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
Interlocked.Increment (ref pendingEnds);
- SocketAsyncResult req=new SocketAsyncResult(state);
- Worker worker=new Worker(this, buffer, offset, size,
- socket_flags, remote_end,
- callback, req);
- req.Worker=worker;
+ SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
+ req.Buffer = buffer;
+ req.Offset = offset;
+ req.Size = size;
+ req.SockFlags = socket_flags;
+ req.EndPoint = remote_end;
+ Worker worker = new Worker(req);
SocketAsyncCall sac = new SocketAsyncCall (worker.SendTo);
sac.BeginInvoke (null, null);
- return(req);
+ return req;
}
// Creates a new system socket, returning the handle
int error;
- Connect_internal(socket, remote_end.Serialize(),
- out error);
+ SocketAddress serial = remote_end.Serialize ();
+ Connect_internal(socket, serial, out error);
+ if (!blocking && error == 10036) {
+ Poll (-1, SelectMode.SelectWrite);
+ Connect_internal (socket, serial, out error);
+ }
- if (error != 0) {
+ if (error != 0)
throw new SocketException (error);
- }
connected=true;
}
SocketAsyncResult req = result as SocketAsyncResult;
if (req == null)
- throw new ArgumentException ("Invalid IAsyncResult");
+ throw new ArgumentException ("Invalid IAsyncResult", "result");
if (!result.IsCompleted)
result.AsyncWaitHandle.WaitOne();
Interlocked.Decrement (ref pendingEnds);
CheckIfClose ();
req.CheckIfThrowDelayedException();
- return(req.Worker.Socket);
+ return req.Socket;
}
public void EndConnect(IAsyncResult result) {
SocketAsyncResult req = result as SocketAsyncResult;
if (req == null)
- throw new ArgumentException ("Invalid IAsyncResult");
+ throw new ArgumentException ("Invalid IAsyncResult", "result");
if (!result.IsCompleted)
result.AsyncWaitHandle.WaitOne();
SocketAsyncResult req = result as SocketAsyncResult;
if (req == null)
- throw new ArgumentException ("Invalid IAsyncResult");
+ throw new ArgumentException ("Invalid IAsyncResult", "result");
+ RemoveReference (req);
if (!result.IsCompleted)
result.AsyncWaitHandle.WaitOne();
Interlocked.Decrement (ref pendingEnds);
CheckIfClose ();
req.CheckIfThrowDelayedException();
- return(req.Worker.Total);
+ return req.Total;
}
public int EndReceiveFrom(IAsyncResult result,
SocketAsyncResult req = result as SocketAsyncResult;
if (req == null)
- throw new ArgumentException ("Invalid IAsyncResult");
+ throw new ArgumentException ("Invalid IAsyncResult", "result");
if (!result.IsCompleted)
result.AsyncWaitHandle.WaitOne();
Interlocked.Decrement (ref pendingEnds);
CheckIfClose ();
req.CheckIfThrowDelayedException();
- end_point=req.Worker.EndPoint;
- return(req.Worker.Total);
+ end_point = req.EndPoint;
+ return req.Total;
}
public int EndSend(IAsyncResult result) {
SocketAsyncResult req = result as SocketAsyncResult;
if (req == null)
- throw new ArgumentException ("Invalid IAsyncResult");
+ throw new ArgumentException ("Invalid IAsyncResult", "result");
+ RemoveReference (req);
if (!result.IsCompleted)
result.AsyncWaitHandle.WaitOne();
Interlocked.Decrement (ref pendingEnds);
CheckIfClose ();
req.CheckIfThrowDelayedException();
- return(req.Worker.Total);
+ return req.Total;
}
public int EndSendTo(IAsyncResult result) {
SocketAsyncResult req = result as SocketAsyncResult;
if (req == null)
- throw new ArgumentException ("Invalid IAsyncResult");
+ throw new ArgumentException ("Invalid IAsyncResult", "result");
if (!result.IsCompleted)
result.AsyncWaitHandle.WaitOne();
Interlocked.Decrement (ref pendingEnds);
CheckIfClose ();
req.CheckIfThrowDelayedException();
- return(req.Worker.Total);
+ return req.Total;
}
void CheckIfClose ()
byte [] input, byte [] output,
out int error);
- public int IOControl (int ioctl_code, byte [] in_value,
- byte [] out_value)
+ public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value)
{
if (disposed)
throw new ObjectDisposedException (GetType ().ToString ());
}
}
- /* The docs for Poll() are a bit lightweight too, but
- * it seems to be just a simple wrapper around Select.
- */
- public bool Poll(int time_us, SelectMode mode) {
- Socket [] socketlist = new Socket []{this};
- Socket [] n = null;
- int error;
-
- switch(mode) {
- case SelectMode.SelectError:
- Select_internal (ref n, ref n, ref socketlist,
- time_us, out error);
- break;
- case SelectMode.SelectRead:
- Select_internal (ref socketlist, ref n, ref n,
- time_us, out error);
- break;
- case SelectMode.SelectWrite:
- Select_internal (ref n, ref socketlist, ref n,
- time_us, out error);
- break;
- default:
- throw new NotSupportedException();
- }
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern static bool Poll_internal (IntPtr socket, SelectMode mode, int timeout, out int error);
- if (error != 0) {
+ public bool Poll (int time_us, SelectMode mode)
+ {
+ if (mode != SelectMode.SelectRead &&
+ mode != SelectMode.SelectWrite &&
+ mode != SelectMode.SelectError)
+ throw new NotSupportedException ("'mode' parameter is not valid.");
+
+ int error;
+ bool result = Poll_internal (socket, mode, time_us, out error);
+ if (error != 0)
throw new SocketException (error);
- }
- return (socketlist.Length == 1);
+ return result;
}
- public int Receive(byte[] buf) {
- return(Receive(buf, 0, buf.Length, SocketFlags.None));
+ public int Receive (byte [] buf)
+ {
+ if (buf == null)
+ throw new ArgumentNullException ("buf");
+
+ return Receive_nochecks (buf, 0, buf.Length, SocketFlags.None);
}
- public int Receive(byte[] buf, SocketFlags flags) {
- return(Receive(buf, 0, buf.Length, flags));
+ public int Receive (byte [] buf, SocketFlags flags)
+ {
+ if (buf == null)
+ throw new ArgumentNullException ("buf");
+
+ return Receive_nochecks (buf, 0, buf.Length, flags);
}
- public int Receive(byte[] buf, int size, SocketFlags flags) {
- return(Receive(buf, 0, size, flags));
+ public int Receive (byte [] buf, int size, SocketFlags flags)
+ {
+ if (buf == null)
+ throw new ArgumentNullException ("buf");
+
+ if (size < 0 || size > buf.Length)
+ throw new ArgumentOutOfRangeException ("size");
+
+ return Receive_nochecks (buf, 0, size, flags);
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
SocketFlags flags,
out int error);
- public int Receive(byte[] buf, int offset, int size,
- SocketFlags flags) {
- if(buf==null) {
- throw new ArgumentNullException("buffer is null");
- }
- if(offset<0 || offset > buf.Length) {
- throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
- }
- if(size<0 || offset+size > buf.Length) {
- throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
- }
+ public int Receive (byte [] buf, int offset, int size, SocketFlags flags)
+ {
+ if (buf == null)
+ throw new ArgumentNullException ("buf");
+
+ if (offset < 0 || offset > buf.Length)
+ throw new ArgumentOutOfRangeException ("offset");
+
+ if (size < 0 || offset + size > buf.Length)
+ throw new ArgumentOutOfRangeException ("size");
+ return Receive_nochecks (buf, offset, size, flags);
+ }
+
+ int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags)
+ {
int ret, error;
- ret=Receive_internal(socket, buf, offset, size, flags,
- out error);
+ ret = Receive_internal (socket, buf, offset, size, flags, out error);
- if(error != 0) {
- connected=false;
+ if (error != 0) {
+ connected = false;
throw new SocketException (error);
}
- connected=true;
+ connected = true;
- return(ret);
+ return ret;
}
- public int ReceiveFrom(byte[] buf, ref EndPoint remote_end) {
- return(ReceiveFrom(buf, 0, buf.Length,
- SocketFlags.None, ref remote_end));
+ public int ReceiveFrom (byte [] buf, ref EndPoint remote_end)
+ {
+ if (buf == null)
+ throw new ArgumentNullException ("buf");
+
+ if (remote_end == null)
+ throw new ArgumentNullException ("remote_end");
+
+ return ReceiveFrom_nochecks (buf, 0, buf.Length, SocketFlags.None, ref remote_end);
}
- public int ReceiveFrom(byte[] buf, SocketFlags flags,
- ref EndPoint remote_end) {
- return(ReceiveFrom(buf, 0, buf.Length, flags,
- ref remote_end));
+ public int ReceiveFrom (byte [] buf, SocketFlags flags, ref EndPoint remote_end)
+ {
+ if (buf == null)
+ throw new ArgumentNullException ("buf");
+
+ if (remote_end == null)
+ throw new ArgumentNullException ("remote_end");
+
+
+ return ReceiveFrom_nochecks (buf, 0, buf.Length, flags, ref remote_end);
}
- public int ReceiveFrom(byte[] buf, int size, SocketFlags flags,
- ref EndPoint remote_end) {
- return(ReceiveFrom(buf, 0, size, flags,
- ref remote_end));
+ public int ReceiveFrom (byte [] buf, int size, SocketFlags flags,
+ ref EndPoint remote_end)
+ {
+ if (buf == null)
+ throw new ArgumentNullException ("buf");
+
+ if (remote_end == null)
+ throw new ArgumentNullException ("remote_end");
+
+ if (size < 0 || size > buf.Length)
+ throw new ArgumentOutOfRangeException ("size");
+
+ return ReceiveFrom_nochecks (buf, 0, size, flags, ref remote_end);
}
ref SocketAddress sockaddr,
out int error);
- public int ReceiveFrom(byte[] buf, int offset, int size,
- SocketFlags flags,
- ref EndPoint remote_end) {
- if(buf==null) {
- throw new ArgumentNullException("buffer is null");
- }
- if(remote_end==null) {
- throw new ArgumentNullException("remote endpoint is null");
- }
- if(offset<0 || offset>buf.Length) {
- throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
- }
- if(size<0 || offset+size>buf.Length) {
- throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
- }
+ public int ReceiveFrom (byte [] buf, int offset, int size, SocketFlags flags,
+ ref EndPoint remote_end)
+ {
+ if (buf == null)
+ throw new ArgumentNullException ("buf");
+
+ if (remote_end == null)
+ throw new ArgumentNullException ("remote_end");
+
+ if (offset < 0 || offset > buf.Length)
+ throw new ArgumentOutOfRangeException ("offset");
- SocketAddress sockaddr=remote_end.Serialize();
- int count, error;
+ if (size < 0 || offset + size > buf.Length)
+ throw new ArgumentOutOfRangeException ("size");
- count=RecvFrom_internal(socket, buf, offset, size,
- flags, ref sockaddr,
- out error);
+ 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)
+ {
+ SocketAddress sockaddr = remote_end.Serialize();
+ int cnt, error;
+
+ cnt = RecvFrom_internal (socket, buf, offset, size, flags, ref sockaddr, out error);
if (error != 0) {
- connected=false;
+ connected = false;
throw new SocketException (error);
}
- connected=true;
+
+ connected = true;
// Stupidly, EndPoint.Create() is an
// instance method
- remote_end=remote_end.Create(sockaddr);
+ remote_end = remote_end.Create (sockaddr);
- return(count);
+ return cnt;
}
- public int Send(byte[] buf) {
- return(Send(buf, 0, buf.Length, SocketFlags.None));
+ public int Send (byte [] buf)
+ {
+ if (buf == null)
+ throw new ArgumentNullException ("buf");
+
+ return Send_nochecks (buf, 0, buf.Length, SocketFlags.None);
}
- public int Send(byte[] buf, SocketFlags flags) {
- return(Send(buf, 0, buf.Length, flags));
+ public int Send (byte [] buf, SocketFlags flags)
+ {
+ if (buf == null)
+ throw new ArgumentNullException ("buf");
+
+ return Send_nochecks (buf, 0, buf.Length, flags);
}
- public int Send(byte[] buf, int size, SocketFlags flags) {
- return(Send(buf, 0, size, flags));
+ public int Send (byte [] buf, int size, SocketFlags flags)
+ {
+ if (buf == null)
+ throw new ArgumentNullException ("buf");
+
+ if (size < 0 || size > buf.Length)
+ throw new ArgumentOutOfRangeException ("size");
+
+ return Send_nochecks (buf, 0, size, flags);
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
SocketFlags flags,
out int error);
- public int Send (byte[] buf, int offset, int size, SocketFlags flags)
+ public int Send (byte [] buf, int offset, int size, SocketFlags flags)
{
if (buf == null)
throw new ArgumentNullException ("buffer");
if (size < 0 || offset + size > buf.Length)
throw new ArgumentOutOfRangeException ("size");
+ return Send_nochecks (buf, offset, size, flags);
+ }
+
+ int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags)
+ {
if (size == 0)
return 0;
int ret, error;
- ret = Send_internal (socket, buf, offset, size, flags,
- out error);
+ ret = Send_internal (socket, buf, offset, size, flags, out error);
if (error != 0) {
connected = false;
throw new SocketException (error);
}
+
connected = true;
return ret;
}
- public int SendTo(byte[] buffer, EndPoint remote_end) {
- return(SendTo(buffer, 0, buffer.Length,
- SocketFlags.None, remote_end));
+ public int SendTo (byte [] buffer, EndPoint remote_end)
+ {
+ if (buffer == null)
+ throw new ArgumentNullException ("buffer");
+
+ if (remote_end == null)
+ throw new ArgumentNullException ("remote_end");
+
+ return SendTo_nochecks (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
}
- public int SendTo(byte[] buffer, SocketFlags flags,
- EndPoint remote_end) {
- return(SendTo(buffer, 0, buffer.Length, flags,
- remote_end));
+ public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
+ {
+ if (buffer == null)
+ throw new ArgumentNullException ("buffer");
+
+ if (remote_end == null)
+ throw new ArgumentNullException ("remote_end");
+
+ return SendTo_nochecks (buffer, 0, buffer.Length, flags, remote_end);
}
- public int SendTo(byte[] buffer, int size, SocketFlags flags,
- EndPoint remote_end) {
- return(SendTo(buffer, 0, size, flags, remote_end));
+ public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
+ {
+ if (buffer == null)
+ throw new ArgumentNullException ("buffer");
+
+ if (remote_end == null)
+ throw new ArgumentNullException ("remote_end");
+
+ if (size < 0 || size > buffer.Length)
+ throw new ArgumentOutOfRangeException ("size");
+
+ return SendTo_nochecks (buffer, 0, size, flags, remote_end);
}
SocketAddress sa,
out int error);
- public int SendTo(byte[] buffer, int offset, int size,
- SocketFlags flags, EndPoint remote_end) {
- if(buffer==null) {
- throw new ArgumentNullException("buffer is null");
- }
- if(remote_end==null) {
- throw new ArgumentNullException("remote endpoint is null");
- }
- if(offset<0 || offset>buffer.Length) {
- throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
- }
- if(size<0 || offset+size>buffer.Length) {
- throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
- }
+ public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags,
+ EndPoint remote_end)
+ {
+ if (buffer == null)
+ throw new ArgumentNullException ("buffer");
- SocketAddress sockaddr=remote_end.Serialize();
+ if (remote_end == null)
+ throw new ArgumentNullException("remote_end");
+
+ if (offset < 0 || offset > buffer.Length)
+ throw new ArgumentOutOfRangeException ("offset");
+
+ if (size < 0 || offset + size > buffer.Length)
+ throw new ArgumentOutOfRangeException ("size");
+
+ return SendTo_nochecks (buffer, offset, size, flags, remote_end);
+ }
+
+ int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags,
+ EndPoint remote_end)
+ {
+ SocketAddress sockaddr = remote_end.Serialize ();
int ret, error;
- ret=SendTo_internal(socket, buffer, offset, size,
- flags, sockaddr, out error);
+ ret = SendTo_internal (socket, buffer, offset, size, flags, sockaddr, out error);
if (error != 0) {
- connected=false;
+ connected = false;
throw new SocketException (error);
}
- connected=true;
- return(ret);
+ connected = true;
+
+ return ret;
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern static void SetSocketOption_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, object obj_val, byte[] byte_val, int int_val, out int error);
+ private extern static void SetSocketOption_internal (IntPtr socket, SocketOptionLevel level,
+ SocketOptionName name, object obj_val,
+ byte [] byte_val, int int_val,
+ out int error);
public void SetSocketOption(SocketOptionLevel level,
SocketOptionName name,
* used when in fact we want to pass the value
* to the runtime as an int.
*/
- if(opt_value is System.Boolean) {
- bool bool_val=(bool)opt_value;
+ if (opt_value is System.Boolean) {
+ bool bool_val = (bool) opt_value;
+ int int_val = (bool_val) ? 1 : 0;
- /* Stupid casting rules :-( */
- if(bool_val==true) {
- SetSocketOption_internal(socket, level,
- name, null,
- null, 1,
- out error);
- } else {
- SetSocketOption_internal(socket, level,
- name, null,
- null, 0,
- out error);
- }
+ SetSocketOption_internal (socket, level, name, null, null, int_val, out error);
} else {
- SetSocketOption_internal(socket, level, name,
- opt_value, null, 0,
- out error);
+ SetSocketOption_internal (socket, level, name, opt_value, null, 0, out error);
}
if (error != 0) {
~Socket () {
Dispose(false);
}
+
+ static Hashtable asyncObjects;
+
+ static void KeepReference (object o)
+ {
+ lock (typeof (Socket)) {
+ if (asyncObjects == null)
+ asyncObjects = new Hashtable ();
+
+ asyncObjects [o] = o;
+ }
+ }
+
+ static void RemoveReference (object o)
+ {
+ lock (typeof (Socket)) {
+ if (asyncObjects == null)
+ return;
+
+ asyncObjects.Remove (o);
+ }
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern static bool GetSupportsAsync ();
+
+ static bool FakeGetSupportsAsync ()
+ {
+ if (Environment.GetEnvironmentVariable ("MONO_ENABLE_SOCKET_AIO") != null)
+ return GetSupportsAsync ();
+
+ return false;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern static void AsyncReceiveInternal (SocketAsyncResult ares, out int error);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern static void AsyncSendInternal (SocketAsyncResult ares, out int error);
}
}
+