//
// Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
// http://www.myelin.co.nz
-// (c) 2004-2006 Novell, Inc. (http://www.novell.com)
+// (c) 2004-2011 Novell, Inc. (http://www.novell.com)
//
-
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
using System.Net.Configuration;
using System.Text;
using System.Timers;
-#if !MOONLIGHT
using System.Net.NetworkInformation;
-#endif
namespace System.Net.Sockets
{
{
private bool islistening;
private bool useoverlappedIO;
+ private const int SOCKET_CLOSED = 10004;
+
+ private static readonly string timeout_exc_msg = "A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond";
static void AddSockets (List<Socket> sockets, IList list, string name)
{
}
}
-#if !MOONLIGHT
public bool AcceptAsync (SocketAsyncEventArgs e)
{
// NO check is made whether e != null in MS.NET (NRE is thrown in such case)
e.curSocket = this;
Worker w = e.Worker;
- w.Init (this, null, e.AcceptCallback, SocketOperation.Accept);
- socket_pool_queue (w.Accept, w.result);
+ w.Init (this, e, SocketOperation.Accept);
+ int count;
+ lock (readQ) {
+ readQ.Enqueue (e.Worker);
+ count = readQ.Count;
+ }
+ if (count == 1)
+ socket_pool_queue (Worker.Dispatcher, w.result);
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, bool blocking);
int error = 0;
IntPtr sock = (IntPtr) (-1);
- blocking_thread = Thread.CurrentThread;
try {
+ RegisterForBlockingSyscall ();
sock = Accept_internal(socket, out error, blocking);
- } catch (ThreadAbortException) {
- if (disposed) {
- Thread.ResetAbort ();
- error = (int) SocketError.Interrupted;
- }
} finally {
- blocking_thread = null;
+ UnRegisterForBlockingSyscall ();
+ }
+
+ if (error != 0) {
+ if (closed)
+ error = SOCKET_CLOSED;
+ throw new SocketException(error);
}
- if (error != 0)
- throw new SocketException (error);
-
Socket accepted = new Socket(this.AddressFamily, this.SocketType,
this.ProtocolType, sock);
int error = 0;
IntPtr sock = (IntPtr)(-1);
- blocking_thread = Thread.CurrentThread;
try {
+ RegisterForBlockingSyscall ();
sock = Accept_internal (socket, out error, blocking);
- } catch (ThreadAbortException) {
- if (disposed) {
- Thread.ResetAbort ();
- error = (int)SocketError.Interrupted;
- }
} finally {
- blocking_thread = null;
+ UnRegisterForBlockingSyscall ();
}
- if (error != 0)
+ if (error != 0) {
+ if (closed)
+ error = SOCKET_CLOSED;
throw new SocketException (error);
+ }
acceptSocket.address_family = this.AddressFamily;
acceptSocket.socket_type = this.SocketType;
throw new InvalidOperationException ();
SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Accept);
- Worker worker = new Worker (req);
- socket_pool_queue (worker.Accept, req);
+ int count;
+ lock (readQ) {
+ readQ.Enqueue (req.Worker);
+ count = readQ.Count;
+ }
+ if (count == 1)
+ socket_pool_queue (Worker.Dispatcher, req);
return req;
}
throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.AcceptReceive);
- Worker worker = new Worker (req);
req.Buffer = new byte[receiveSize];
req.Offset = 0;
req.Size = receiveSize;
req.SockFlags = SocketFlags.None;
- socket_pool_queue (worker.AcceptReceive, req);
+ int count;
+ lock (readQ) {
+ readQ.Enqueue (req.Worker);
+ count = readQ.Count;
+ }
+ if (count == 1)
+ socket_pool_queue (Worker.Dispatcher, req);
return req;
}
}
SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.AcceptReceive);
- Worker worker = new Worker (req);
req.Buffer = new byte[receiveSize];
req.Offset = 0;
req.Size = receiveSize;
req.SockFlags = SocketFlags.None;
req.AcceptSocket = acceptSocket;
- socket_pool_queue (worker.AcceptReceive, req);
- return(req);
- }
-
- public IAsyncResult BeginConnect(EndPoint end_point,
- AsyncCallback callback,
- object state) {
-
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- if (end_point == null)
- throw new ArgumentNullException ("end_point");
-
- SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Connect);
- req.EndPoint = end_point;
-
- // Bug #75154: Connect() should not succeed for .Any addresses.
- if (end_point is IPEndPoint) {
- IPEndPoint ep = (IPEndPoint) end_point;
- if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)) {
- req.Complete (new SocketException ((int) SocketError.AddressNotAvailable), true);
- return req;
- }
- }
-
- int error = 0;
- if (!blocking) {
- SocketAddress serial = end_point.Serialize ();
- Connect_internal (socket, serial, out error);
- if (error == 0) {
- // succeeded synch
- connected = true;
- req.Complete (true);
- } else if (error != (int) SocketError.InProgress && error != (int) SocketError.WouldBlock) {
- // error synch
- connected = false;
- req.Complete (new SocketException (error), true);
- }
- }
-
- if (blocking || error == (int) SocketError.InProgress || error == (int) SocketError.WouldBlock) {
- // continue asynch
- connected = false;
- Worker worker = new Worker (req);
- socket_pool_queue (worker.Connect, req);
+ int count;
+ lock (readQ) {
+ readQ.Enqueue (req.Worker);
+ count = readQ.Count;
}
-
+ if (count == 1)
+ socket_pool_queue (Worker.Dispatcher, req);
return(req);
}
if (address.ToString ().Length == 0)
throw new ArgumentException ("The length of the IP address is zero");
+ if (port <= 0 || port > 65535)
+ throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
+
if (islistening)
throw new InvalidOperationException ();
return(BeginConnect (iep, callback, state));
}
- public IAsyncResult BeginConnect (IPAddress[] addresses,
- int port,
- AsyncCallback callback,
- object state)
- {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- if (addresses == null)
- throw new ArgumentNullException ("addresses");
-
- if (this.AddressFamily != AddressFamily.InterNetwork &&
- this.AddressFamily != AddressFamily.InterNetworkV6)
- throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
-
- if (islistening)
- throw new InvalidOperationException ();
-
- SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Connect);
- req.Addresses = addresses;
- req.Port = port;
-
- connected = false;
- Worker worker = new Worker (req);
- socket_pool_queue (worker.Connect, req);
-
- return(req);
- }
-
public IAsyncResult BeginConnect (string host, int port,
AsyncCallback callback,
object state)
address_family != AddressFamily.InterNetworkV6)
throw new NotSupportedException ("This method is valid only for sockets in the InterNetwork and InterNetworkV6 families");
+ if (port <= 0 || port > 65535)
+ throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
+
if (islistening)
throw new InvalidOperationException ();
- IPAddress [] addresses = Dns.GetHostAddresses (host);
- return (BeginConnect (addresses, port, callback, state));
+ return BeginConnect (Dns.GetHostAddresses (host), port, callback, state);
}
public IAsyncResult BeginDisconnect (bool reuseSocket,
SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Disconnect);
req.ReuseSocket = reuseSocket;
-
- Worker worker = new Worker (req);
- socket_pool_queue (worker.Disconnect, req);
-
+ socket_pool_queue (Worker.Dispatcher, req);
return(req);
}
+
+ void CheckRange (byte[] buffer, int offset, int size)
+ {
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
+
+ if (offset > buffer.Length)
+ throw new ArgumentOutOfRangeException ("offset", "offset must be <= buffer.Length");
+
+ if (size < 0)
+ throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
+
+ if (size > buffer.Length - offset)
+ throw new ArgumentOutOfRangeException ("size", "size must be <= buffer.Length - offset");
+ }
public IAsyncResult BeginReceive(byte[] buffer, int offset,
int size,
if (buffer == null)
throw new ArgumentNullException ("buffer");
- if (offset < 0 || offset > buffer.Length)
- throw new ArgumentOutOfRangeException ("offset");
-
- if (size < 0 || offset + size > buffer.Length)
- throw new ArgumentOutOfRangeException ("size");
+ CheckRange (buffer, offset, size);
SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Receive);
req.Buffer = buffer;
req.Offset = offset;
req.Size = size;
req.SockFlags = socket_flags;
- Worker worker = new Worker (req);
int count;
lock (readQ) {
- readQ.Enqueue (worker);
+ readQ.Enqueue (req.Worker);
count = readQ.Count;
}
if (count == 1)
- socket_pool_queue (worker.Receive, req);
+ socket_pool_queue (Worker.Dispatcher, req);
return req;
}
SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveGeneric);
req.Buffers = buffers;
req.SockFlags = socketFlags;
- Worker worker = new Worker (req);
int count;
lock(readQ) {
- readQ.Enqueue (worker);
+ readQ.Enqueue (req.Worker);
count = readQ.Count;
}
if (count == 1)
- socket_pool_queue (worker.ReceiveGeneric, req);
+ socket_pool_queue (Worker.Dispatcher, req);
return req;
}
if (remote_end == null)
throw new ArgumentNullException ("remote_end");
- if (offset < 0)
- throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
-
- if (size < 0)
- throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
-
- if (offset + size > buffer.Length)
- throw new ArgumentOutOfRangeException ("offset, size", "offset + size exceeds the buffer length");
+ CheckRange (buffer, offset, size);
SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveFrom);
req.Buffer = buffer;
req.Size = size;
req.SockFlags = socket_flags;
req.EndPoint = remote_end;
- Worker worker = new Worker (req);
int count;
lock (readQ) {
- readQ.Enqueue (worker);
+ readQ.Enqueue (req.Worker);
count = readQ.Count;
}
if (count == 1)
- socket_pool_queue (worker.ReceiveFrom, req);
+ socket_pool_queue (Worker.Dispatcher, req);
return req;
}
if (remoteEP == null)
throw new ArgumentNullException ("remoteEP");
- if (offset < 0 || offset > buffer.Length)
- throw new ArgumentOutOfRangeException ("offset");
-
- if (size < 0 || offset + size > buffer.Length)
- throw new ArgumentOutOfRangeException ("size");
+ CheckRange (buffer, offset, size);
throw new NotImplementedException ();
}
if (buffer == null)
throw new ArgumentNullException ("buffer");
- if (offset < 0)
- throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
-
- if (size < 0)
- throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
-
- if (offset + size > buffer.Length)
- throw new ArgumentOutOfRangeException ("offset, size", "offset + size exceeds the buffer length");
+ CheckRange (buffer, offset, size);
if (!connected)
throw new SocketException ((int)SocketError.NotConnected);
req.Offset = offset;
req.Size = size;
req.SockFlags = socket_flags;
- Worker worker = new Worker (req);
int count;
lock (writeQ) {
- writeQ.Enqueue (worker);
+ writeQ.Enqueue (req.Worker);
count = writeQ.Count;
}
if (count == 1)
- socket_pool_queue (worker.Send, req);
+ socket_pool_queue (Worker.Dispatcher, req);
return req;
}
SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.SendGeneric);
req.Buffers = buffers;
req.SockFlags = socketFlags;
- Worker worker = new Worker (req);
int count;
lock (writeQ) {
- writeQ.Enqueue (worker);
+ writeQ.Enqueue (req.Worker);
count = writeQ.Count;
}
if (count == 1)
- socket_pool_queue (worker.SendGeneric, req);
+ socket_pool_queue (Worker.Dispatcher, req);
return req;
}
throw new FileNotFoundException ();
SendFileHandler d = new SendFileHandler (SendFile);
- return new SendFileAsyncResult (d, d.BeginInvoke (fileName, preBuffer, postBuffer, flags, callback, state));
+ return new SendFileAsyncResult (d, d.BeginInvoke (fileName, preBuffer, postBuffer, flags, ar => {
+ SendFileAsyncResult sfar = new SendFileAsyncResult (d, ar);
+ callback (sfar);
+ }, state));
}
public IAsyncResult BeginSendTo(byte[] buffer, int offset,
if (buffer == null)
throw new ArgumentNullException ("buffer");
- if (offset < 0)
- throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
-
- if (size < 0)
- throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
-
- if (offset + size > buffer.Length)
- throw new ArgumentOutOfRangeException ("offset, size", "offset + size exceeds the buffer length");
+ CheckRange (buffer, offset, size);
SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.SendTo);
req.Buffer = buffer;
req.Size = size;
req.SockFlags = socket_flags;
req.EndPoint = remote_end;
- Worker worker = new Worker (req);
int count;
lock (writeQ) {
- writeQ.Enqueue (worker);
+ writeQ.Enqueue (req.Worker);
count = writeQ.Count;
}
if (count == 1)
- socket_pool_queue (worker.SendTo, req);
+ socket_pool_queue (Worker.Dispatcher, req);
return req;
}
seed_endpoint = local_end;
}
-#if !MOONLIGHT
- 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
-
public void Connect (IPAddress address, int port)
{
Connect (new IPEndPoint (address, port));
Connect (addresses, port);
}
-#if !MOONLIGHT
public bool DisconnectAsync (SocketAsyncEventArgs e)
{
// NO check is made whether e != null in MS.NET (NRE is thrown in such case)
throw new ObjectDisposedException (GetType ().ToString ());
e.curSocket = this;
- e.Worker.Init (this, null, e.DisconnectCallback, SocketOperation.Disconnect);
- socket_pool_queue (e.Worker.Disconnect, e.Worker.result);
+ e.Worker.Init (this, e, SocketOperation.Disconnect);
+ socket_pool_queue (Worker.Dispatcher, e.Worker.result);
return true;
}
-#endif
[MethodImplAttribute(MethodImplOptions.InternalCall)]
extern static void Disconnect_internal(IntPtr sock, bool reuse, out int error);
req.CheckIfThrowDelayedException();
}
-#if !MOONLIGHT
public void EndDisconnect (IAsyncResult asyncResult)
{
if (disposed && closed)
req.CheckIfThrowDelayedException ();
}
-#endif
[MonoTODO]
public int EndReceiveMessageFrom (IAsyncResult asyncResult,
ares.Delegate.EndInvoke (ares.Original);
}
-#if !MOONLIGHT
public int EndSendTo (IAsyncResult result)
{
if (disposed && closed)
req.CheckIfThrowDelayedException();
return req.Total;
}
-#endif
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern static void GetSocketOption_arr_internal(IntPtr socket,
public int Receive (byte [] buffer)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
-
- SocketError error;
-
- int ret = Receive_nochecks (buffer, 0, buffer.Length, SocketFlags.None, out error);
-
- if (error != SocketError.Success)
- throw new SocketException ((int) error);
-
- return ret;
+ return Receive (buffer, SocketFlags.None);
}
public int Receive (byte [] buffer, SocketFlags flags)
if (error != SocketError.Success) {
if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
- throw new SocketException ((int) error, "Operation timed out.");
+ throw new SocketException ((int) error, timeout_exc_msg);
throw new SocketException ((int) error);
}
if (buffer == null)
throw new ArgumentNullException ("buffer");
- if (size < 0 || size > buffer.Length)
- throw new ArgumentOutOfRangeException ("size");
+ CheckRange (buffer, 0, size);
SocketError error;
if (error != SocketError.Success) {
if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
- throw new SocketException ((int) error, "Operation timed out.");
+ throw new SocketException ((int) error, timeout_exc_msg);
throw new SocketException ((int) error);
}
if (buffer == null)
throw new ArgumentNullException ("buffer");
- if (offset < 0 || offset > buffer.Length)
- throw new ArgumentOutOfRangeException ("offset");
-
- if (size < 0 || offset + size > buffer.Length)
- throw new ArgumentOutOfRangeException ("size");
+ CheckRange (buffer, offset, size);
SocketError error;
if (error != SocketError.Success) {
if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
- throw new SocketException ((int) error, "Operation timed out.");
+ throw new SocketException ((int) error, timeout_exc_msg);
throw new SocketException ((int) error);
}
if (buffer == null)
throw new ArgumentNullException ("buffer");
- if (offset < 0 || offset > buffer.Length)
- throw new ArgumentOutOfRangeException ("offset");
-
- if (size < 0 || offset + size > buffer.Length)
- throw new ArgumentOutOfRangeException ("size");
+ CheckRange (buffer, offset, size);
return Receive_nochecks (buffer, offset, size, flags, out error);
}
-#if !MOONLIGHT
public bool ReceiveFromAsync (SocketAsyncEventArgs e)
{
if (disposed && closed)
throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
e.curSocket = this;
- e.Worker.Init (this, null, e.ReceiveFromCallback, SocketOperation.ReceiveFrom);
+ e.Worker.Init (this, e, SocketOperation.ReceiveFrom);
SocketAsyncResult res = e.Worker.result;
res.Buffer = e.Buffer;
res.Offset = e.Offset;
res.Size = e.Count;
res.EndPoint = e.RemoteEndPoint;
res.SockFlags = e.SocketFlags;
- Worker worker = new Worker (e);
int count;
lock (readQ) {
- readQ.Enqueue (worker);
+ readQ.Enqueue (e.Worker);
count = readQ.Count;
}
if (count == 1)
- socket_pool_queue (e.Worker.ReceiveFrom, res);
+ socket_pool_queue (Worker.Dispatcher, res);
return true;
}
-#endif
public int ReceiveFrom (byte [] buffer, ref EndPoint remoteEP)
{
if (remoteEP == null)
throw new ArgumentNullException ("remoteEP");
- if (offset < 0 || offset > buffer.Length)
- throw new ArgumentOutOfRangeException ("offset");
-
- if (size < 0 || offset + size > buffer.Length)
- throw new ArgumentOutOfRangeException ("size");
+ CheckRange (buffer, offset, size);
return ReceiveFrom_nochecks (buffer, offset, size, flags, ref remoteEP);
}
connected = false;
else if (err == SocketError.WouldBlock && blocking) { // This might happen when ReceiveTimeout is set
if (throwOnError)
- throw new SocketException ((int) SocketError.TimedOut, "Operation timed out");
+ throw new SocketException ((int) SocketError.TimedOut, timeout_exc_msg);
error = (int) SocketError.TimedOut;
return 0;
}
if (remoteEP == null)
throw new ArgumentNullException ("remoteEP");
- if (offset < 0 || offset > buffer.Length)
- throw new ArgumentOutOfRangeException ("offset");
-
- if (size < 0 || offset + size > buffer.Length)
- throw new ArgumentOutOfRangeException ("size");
+ CheckRange (buffer, offset, size);
/* FIXME: figure out how we get hold of the
* IPPacketInformation
if (buf == null)
throw new ArgumentNullException ("buf");
- if (size < 0 || size > buf.Length)
- throw new ArgumentOutOfRangeException ("size");
+ CheckRange (buf, 0, size);
SocketError error;
if (buf == null)
throw new ArgumentNullException ("buffer");
- if (offset < 0 || offset > buf.Length)
- throw new ArgumentOutOfRangeException ("offset");
-
- if (size < 0 || offset + size > buf.Length)
- throw new ArgumentOutOfRangeException ("size");
+ CheckRange (buf, offset, size);
SocketError error;
if (buf == null)
throw new ArgumentNullException ("buffer");
- if (offset < 0 || offset > buf.Length)
- throw new ArgumentOutOfRangeException ("offset");
-
- if (size < 0 || offset + size > buf.Length)
- throw new ArgumentOutOfRangeException ("size");
+ CheckRange (buf, offset, size);
return Send_nochecks (buf, offset, size, flags, out error);
}
}
}
-#if !MOONLIGHT
public bool SendToAsync (SocketAsyncEventArgs e)
{
// NO check is made whether e != null in MS.NET (NRE is thrown in such case)
throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
e.curSocket = this;
- e.Worker.Init (this, null, e.SendToCallback, SocketOperation.SendTo);
+ e.Worker.Init (this, e, SocketOperation.SendTo);
SocketAsyncResult res = e.Worker.result;
res.Buffer = e.Buffer;
res.Offset = e.Offset;
res.Size = e.Count;
res.SockFlags = e.SocketFlags;
res.EndPoint = e.RemoteEndPoint;
- Worker worker = new Worker (e);
int count;
lock (writeQ) {
- writeQ.Enqueue (worker);
+ writeQ.Enqueue (e.Worker);
count = writeQ.Count;
}
if (count == 1)
- socket_pool_queue (e.Worker.SendTo, res);
+ socket_pool_queue (Worker.Dispatcher, res);
return true;
}
-#endif
public int SendTo (byte [] buffer, EndPoint remote_end)
{
if (remote_end == null)
throw new ArgumentNullException ("remote_end");
- if (size < 0 || size > buffer.Length)
- throw new ArgumentOutOfRangeException ("size");
+ CheckRange (buffer, 0, size);
return SendTo_nochecks (buffer, 0, size, flags, remote_end);
}
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");
+ CheckRange (buffer, offset, size);
return SendTo_nochecks (buffer, offset, size, flags, remote_end);
}