//
// Authors:
// Marek Habersack (mhabersack@novell.com)
-// Gonzalo Paniagua Javier (gonzalo@novell.com)
+// Gonzalo Paniagua Javier (gonzalo@xamarin.com)
//
// Copyright (c) 2008,2010 Novell, Inc. (http://www.novell.com)
+// Copyright (c) 2011 Xamarin, Inc. (http://xamarin.com)
//
//
using System.Reflection;
using System.Security;
using System.Threading;
-#if MOONLIGHT && !INSIDE_SYSTEM
-using System.Net.Policy;
-#endif
namespace System.Net.Sockets
{
public class SocketAsyncEventArgs : EventArgs, IDisposable
{
+ bool disposed;
+ int in_progress;
internal Socket.Worker Worker;
EndPoint remote_ep;
-#if MOONLIGHT || NET_4_0
+#if NET_4_0
public Exception ConnectByNameError { get; internal set; }
#endif
}
}
- public int BytesTransferred { get; private set; }
- public int Count { get; private set; }
+ public int BytesTransferred { get; internal set; }
+ public int Count { get; internal set; }
public bool DisconnectReuseSocket { get; set; }
public SocketAsyncOperation LastOperation { get; private set; }
public int Offset { get; private set; }
public SocketError SocketError { get; set; }
public SocketFlags SocketFlags { get; set; }
public object UserToken { get; set; }
-
-#if MOONLIGHT && !INSIDE_SYSTEM
- private SocketClientAccessPolicyProtocol policy_protocol;
-
- public SocketClientAccessPolicyProtocol SocketClientAccessPolicyProtocol {
- get { return policy_protocol; }
- set {
- if ((value != SocketClientAccessPolicyProtocol.Tcp) && (value != SocketClientAccessPolicyProtocol.Http))
- throw new ArgumentException ("Invalid value");
- policy_protocol = value;
- }
- }
-#endif
-
internal Socket curSocket;
#if NET_2_1
public Socket ConnectSocket {
SocketError = SocketError.Success;
SocketFlags = SocketFlags.None;
UserToken = null;
-
-#if MOONLIGHT && !INSIDE_SYSTEM
- policy_protocol = SocketClientAccessPolicyProtocol.Tcp;
-#endif
}
~SocketAsyncEventArgs ()
void Dispose (bool disposing)
{
+ disposed = true;
+
if (disposing) {
+ if (disposed || Interlocked.CompareExchange (ref in_progress, 0, 0) != 0)
+ return;
if (Worker != null) {
Worker.Dispose ();
Worker = null;
internal void SetLastOperation (SocketAsyncOperation op)
{
+ if (disposed)
+ throw new ObjectDisposedException ("System.Net.Sockets.SocketAsyncEventArgs");
+ if (Interlocked.Exchange (ref in_progress, 1) != 0)
+ throw new InvalidOperationException ("Operation already in progress");
LastOperation = op;
}
static void DispatcherCB (IAsyncResult ares)
{
SocketAsyncEventArgs args = (SocketAsyncEventArgs) ares.AsyncState;
+ if (Interlocked.Exchange (ref args.in_progress, 0) != 1)
+ throw new InvalidOperationException ("No operation in progress");
SocketAsyncOperation op = args.LastOperation;
// Notes;
// -SocketOperation.AcceptReceive not used in SocketAsyncEventArgs
args.ReceiveCallback (ares);
else if (op == SocketAsyncOperation.Send)
args.SendCallback (ares);
-#if !MOONLIGHT
else if (op == SocketAsyncOperation.ReceiveFrom)
args.ReceiveFromCallback (ares);
else if (op == SocketAsyncOperation.SendTo)
args.AcceptCallback (ares);
else if (op == SocketAsyncOperation.Disconnect)
args.DisconnectCallback (ares);
-#endif
else if (op == SocketAsyncOperation.Connect)
- args.ConnectCallback (); /* This should not be hit yet. See DoOperation() */
+ args.ConnectCallback ();
/*
else if (op == Socket.SocketOperation.ReceiveMessageFrom)
else if (op == Socket.SocketOperation.SendPackets)
void ConnectCallback ()
{
- SocketError error = SocketError.AccessDenied;
try {
-#if MOONLIGHT || NET_4_0
- // Connect to the first address that match the host name, like:
- // http://blogs.msdn.com/ncl/archive/2009/07/20/new-ncl-features-in-net-4-0-beta-2.aspx
- // while skipping entries that do not match the address family
- DnsEndPoint dep = (RemoteEndPoint as DnsEndPoint);
- if (dep != null) {
- IPAddress[] addresses = Dns.GetHostAddresses (dep.Host);
- IPEndPoint endpoint;
-#if MOONLIGHT && !INSIDE_SYSTEM
- if (!PolicyRestricted && !SecurityManager.HasElevatedPermissions) {
- List<IPAddress> valid = new List<IPAddress> ();
- foreach (IPAddress a in addresses) {
- // if we're not downloading a socket policy then check the policy
- // and if we're not running with elevated permissions (SL4 OoB option)
- endpoint = new IPEndPoint (a, dep.Port);
- if (!CrossDomainPolicyManager.CheckEndPoint (endpoint, policy_protocol))
- continue;
- valid.Add (a);
- }
- addresses = valid.ToArray ();
- }
-#endif
- foreach (IPAddress addr in addresses) {
- try {
- if (curSocket.AddressFamily == addr.AddressFamily) {
- endpoint = new IPEndPoint (addr, dep.Port);
- error = TryConnect (endpoint);
- if (error == SocketError.Success) {
- ConnectByNameError = null;
- break;
- }
- }
- } catch (SocketException se) {
- ConnectByNameError = se;
- error = SocketError.AccessDenied;
- }
- }
- } else {
- ConnectByNameError = null;
-#if MOONLIGHT && !INSIDE_SYSTEM
- if (!PolicyRestricted && !SecurityManager.HasElevatedPermissions) {
- if (CrossDomainPolicyManager.CheckEndPoint (RemoteEndPoint, policy_protocol))
- error = TryConnect (RemoteEndPoint);
- } else
-#endif
- error = TryConnect (RemoteEndPoint);
- }
-#else
- error = TryConnect (RemoteEndPoint);
-#endif
+ SocketError = (SocketError) Worker.result.error;
} finally {
- SocketError = error;
OnCompleted (this);
}
}
- SocketError TryConnect (EndPoint endpoint)
- {
- try {
- curSocket.Connect (endpoint);
- return (curSocket.Connected ? 0 : SocketError);
- } catch (SocketException se){
- return se.SocketErrorCode;
- } catch (ObjectDisposedException) {
- return SocketError.OperationAborted;
- }
- }
-
internal void SendCallback (IAsyncResult ares)
{
try {
}
}
-#if !MOONLIGHT
internal void AcceptCallback (IAsyncResult ares)
{
try {
OnCompleted (this);
}
}
-
-#endif
- internal void DoOperation (SocketAsyncOperation operation, Socket socket)
- {
- ThreadStart callback = null;
- curSocket = socket;
-
- switch (operation) {
- case SocketAsyncOperation.Connect:
-#if MOONLIGHT
- socket.seed_endpoint = RemoteEndPoint;
-#endif
- callback = new ThreadStart (ConnectCallback);
- SocketError = SocketError.Success;
- LastOperation = operation;
- break;
-
- default:
- throw new NotSupportedException ();
- }
-
- Thread t = new Thread (callback);
- t.IsBackground = true;
- t.Start ();
- }
#endregion
}
}