Merge pull request #2815 from lambdageek/dev/monoerror-mono_compile_method
[mono.git] / mcs / class / System / System.Net.Sockets / Socket.cs
index 0f5ad52bbe5cb5912786e7c9cf86a1d46359f615..d71b3eecabe26a4a8ded29eff3d04f184f62bec3 100644 (file)
@@ -201,11 +201,9 @@ namespace System.Net.Sockets
                        this.address_family = addressFamily;
                        this.socket_type = socketType;
                        this.protocol_type = protocolType;
-                       
-                       int error;
-                       var handle = Socket_internal (addressFamily, socketType, protocolType, out error);
 
-                       this.safe_handle = new SafeSocketHandle (handle, true);
+                       int error;
+                       this.safe_handle = new SafeSocketHandle (Socket_internal (addressFamily, socketType, protocolType, out error), true);
 
                        if (error != 0)
                                throw new SocketException (error);
@@ -953,7 +951,7 @@ namespace System.Net.Sockets
 
                        InitSocketAsyncEventArgs (e, AcceptAsyncCallback, e, SocketOperation.Accept);
 
-                       QueueIOSelectorJob (readQ, e.socket_async_result.handle, new IOSelectorJob (IOOperation.Read, BeginAcceptCallback, e.socket_async_result));
+                       QueueIOSelectorJob (readQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginAcceptCallback, e.socket_async_result));
 
                        return true;
                }
@@ -986,23 +984,27 @@ namespace System.Net.Sockets
 
                        SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.Accept);
 
-                       QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, BeginAcceptCallback, 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;
-
+                       Socket acc_socket = null;
                        try {
-                               socket = sockares.socket.Accept ();
+                               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;
                        }
-
-                       sockares.Complete (socket);
+                       sockares.Complete (acc_socket);
                });
 
                public IAsyncResult BeginAccept (int receiveSize, AsyncCallback callback, object state)
@@ -1019,7 +1021,7 @@ namespace System.Net.Sockets
                                SockFlags = SocketFlags.None,
                        };
 
-                       QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, BeginAcceptReceiveCallback, sockares));
+                       QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginAcceptReceiveCallback, sockares));
 
                        return sockares;
                }
@@ -1054,7 +1056,7 @@ namespace System.Net.Sockets
                                AcceptSocket = acceptSocket,
                        };
 
-                       QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, BeginAcceptReceiveCallback, sockares));
+                       QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginAcceptReceiveCallback, sockares));
 
                        return sockares;
                }
@@ -1149,7 +1151,12 @@ namespace System.Net.Sockets
 
                        if (local_end == null)
                                throw new ArgumentNullException("local_end");
-
+                               
+                       var ipEndPoint = local_end as IPEndPoint;
+                       if (ipEndPoint != null) {
+                               local_end = RemapIPEndPoint (ipEndPoint);       
+                       }
+                       
                        int error;
                        Bind_internal (safe_handle, local_end.Serialize(), out error);
 
@@ -1241,6 +1248,8 @@ namespace System.Net.Sockets
                        int error = 0;
                        foreach (IPAddress address in addresses) {
                                IPEndPoint iep = new IPEndPoint (address, port);
+                               
+                               iep = RemapIPEndPoint (iep);
 
                                Connect_internal (safe_handle, iep.Serialize (), out error);
                                if (error == 0) {
@@ -1285,6 +1294,10 @@ namespace System.Net.Sockets
 
                        if (is_listening)
                                throw new InvalidOperationException ();
+                               
+                       if (ep != null) {
+                               remoteEP = RemapIPEndPoint (ep);
+                       }
 
                        SocketAddress serial = remoteEP.Serialize ();
 
@@ -1410,6 +1423,8 @@ namespace System.Net.Sockets
                                        sockares.Complete (new SocketException ((int) SocketError.AddressNotAvailable), true);
                                        return sockares;
                                }
+                               
+                               end_point = RemapIPEndPoint (ep);
                        }
 
                        int error = 0;
@@ -1420,8 +1435,7 @@ namespace System.Net.Sockets
                                // an error. Better to just close the socket and move on.
                                connect_in_progress = false;
                                safe_handle.Dispose ();
-                               var handle = Socket_internal (address_family, socket_type, protocol_type, out error);
-                               safe_handle = new SafeSocketHandle (handle, true);
+                               safe_handle = new SafeSocketHandle (Socket_internal (address_family, socket_type, protocol_type, out error), true);
                                if (error != 0)
                                        throw new SocketException (error);
                        }
@@ -1454,7 +1468,7 @@ namespace System.Net.Sockets
                        is_bound = false;
                        connect_in_progress = true;
 
-                       IOSelector.Add (sockares.handle, new IOSelectorJob (IOOperation.Write, BeginConnectCallback, sockares));
+                       IOSelector.Add (sockares.Handle, new IOSelectorJob (IOOperation.Write, BeginConnectCallback, sockares));
 
                        return sockares;
                }
@@ -1649,7 +1663,7 @@ namespace System.Net.Sockets
 
                        InitSocketAsyncEventArgs (e, DisconnectAsyncCallback, e, SocketOperation.Disconnect);
 
-                       IOSelector.Add (e.socket_async_result.handle, new IOSelectorJob (IOOperation.Write, BeginDisconnectCallback, e.socket_async_result));
+                       IOSelector.Add (e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Write, BeginDisconnectCallback, e.socket_async_result));
 
                        return true;
                }
@@ -1679,7 +1693,7 @@ namespace System.Net.Sockets
                                ReuseSocket = reuseSocket,
                        };
 
-                       IOSelector.Add (sockares.handle, new IOSelectorJob (IOOperation.Write, BeginDisconnectCallback, sockares));
+                       IOSelector.Add (sockares.Handle, new IOSelectorJob (IOOperation.Write, BeginDisconnectCallback, sockares));
 
                        return sockares;
                }
@@ -1879,7 +1893,7 @@ namespace System.Net.Sockets
 
                                e.socket_async_result.Buffers = e.BufferList;
 
-                               QueueIOSelectorJob (readQ, e.socket_async_result.handle, new IOSelectorJob (IOOperation.Read, BeginReceiveGenericCallback, e.socket_async_result));
+                               QueueIOSelectorJob (readQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveGenericCallback, e.socket_async_result));
                        } else {
                                InitSocketAsyncEventArgs (e, ReceiveAsyncCallback, e, SocketOperation.Receive);
 
@@ -1887,7 +1901,7 @@ namespace System.Net.Sockets
                                e.socket_async_result.Offset = e.Offset;
                                e.socket_async_result.Size = e.Count;
 
-                               QueueIOSelectorJob (readQ, e.socket_async_result.handle, new IOSelectorJob (IOOperation.Read, BeginReceiveCallback, e.socket_async_result));
+                               QueueIOSelectorJob (readQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveCallback, e.socket_async_result));
                        }
 
                        return true;
@@ -1923,7 +1937,7 @@ namespace System.Net.Sockets
                                SockFlags = socket_flags,
                        };
 
-                       QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, BeginReceiveCallback, sockares));
+                       QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveCallback, sockares));
 
                        return sockares;
                }
@@ -1964,7 +1978,7 @@ namespace System.Net.Sockets
                                SockFlags = socketFlags,
                        };
 
-                       QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, BeginReceiveGenericCallback, sockares));
+                       QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveGenericCallback, sockares));
 
                        return sockares;
                }
@@ -2124,7 +2138,7 @@ namespace System.Net.Sockets
                        e.socket_async_result.EndPoint = e.RemoteEndPoint;
                        e.socket_async_result.SockFlags = e.SocketFlags;
 
-                       QueueIOSelectorJob (readQ, e.socket_async_result.handle, new IOSelectorJob (IOOperation.Read, BeginReceiveFromCallback, e.socket_async_result));
+                       QueueIOSelectorJob (readQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveFromCallback, e.socket_async_result));
 
                        return true;
                }
@@ -2163,7 +2177,7 @@ namespace System.Net.Sockets
                                EndPoint = remote_end,
                        };
 
-                       QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, BeginReceiveFromCallback, sockares));
+                       QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveFromCallback, sockares));
 
                        return sockares;
                }
@@ -2483,7 +2497,7 @@ namespace System.Net.Sockets
 
                                e.socket_async_result.Buffers = e.BufferList;
 
-                               QueueIOSelectorJob (writeQ, e.socket_async_result.handle, new IOSelectorJob (IOOperation.Write, BeginSendGenericCallback, e.socket_async_result));
+                               QueueIOSelectorJob (writeQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Write, BeginSendGenericCallback, e.socket_async_result));
                        } else {
                                InitSocketAsyncEventArgs (e, SendAsyncCallback, e, SocketOperation.Send);
 
@@ -2491,7 +2505,7 @@ namespace System.Net.Sockets
                                e.socket_async_result.Offset = e.Offset;
                                e.socket_async_result.Size = e.Count;
 
-                               QueueIOSelectorJob (writeQ, e.socket_async_result.handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, 0), e.socket_async_result));
+                               QueueIOSelectorJob (writeQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, 0), e.socket_async_result));
                        }
 
                        return true;
@@ -2541,7 +2555,7 @@ namespace System.Net.Sockets
                                SockFlags = socket_flags,
                        };
 
-                       QueueIOSelectorJob (writeQ, sockares.handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, 0), sockares));
+                       QueueIOSelectorJob (writeQ, sockares.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, 0), sockares));
 
                        return sockares;
                }
@@ -2568,7 +2582,7 @@ namespace System.Net.Sockets
                                }
 
                                if (sockares.Size > 0) {
-                                       IOSelector.Add (sockares.handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, sent_so_far), sockares));
+                                       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.
                                }
 
@@ -2592,7 +2606,7 @@ namespace System.Net.Sockets
                                SockFlags = socketFlags,
                        };
 
-                       QueueIOSelectorJob (writeQ, sockares.handle, new IOSelectorJob (IOOperation.Write, BeginSendGenericCallback, sockares));
+                       QueueIOSelectorJob (writeQ, sockares.Handle, new IOSelectorJob (IOOperation.Write, BeginSendGenericCallback, sockares));
 
                        return sockares;
                }
@@ -2738,7 +2752,7 @@ namespace System.Net.Sockets
                        e.socket_async_result.SockFlags = e.SocketFlags;
                        e.socket_async_result.EndPoint = e.RemoteEndPoint;
 
-                       QueueIOSelectorJob (writeQ, e.socket_async_result.handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, 0), e.socket_async_result));
+                       QueueIOSelectorJob (writeQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, 0), e.socket_async_result));
 
                        return true;
                }
@@ -2774,7 +2788,7 @@ namespace System.Net.Sockets
                                EndPoint = remote_end,
                        };
 
-                       QueueIOSelectorJob (writeQ, sockares.handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, 0), sockares));
+                       QueueIOSelectorJob (writeQ, sockares.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, 0), sockares));
 
                        return sockares;
                }
@@ -2792,7 +2806,7 @@ namespace System.Net.Sockets
                                }
 
                                if (sockares.Size > 0) {
-                                       IOSelector.Add (sockares.handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, sent_so_far), sockares));
+                                       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.
                                }
 
@@ -3153,27 +3167,24 @@ namespace System.Net.Sockets
 
                public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, bool optionValue)
                {
-                       ThrowIfDisposedAndClosed ();
-
-                       int error;
                        int int_val = optionValue ? 1 : 0;
-                       SetSocketOption_internal (safe_handle, optionLevel, optionName, null, null, int_val, out error);
 
-                       if (error != 0) {
-                               if (error == (int) SocketError.InvalidArgument)
-                                       throw new ArgumentException ();
-                               throw new SocketException (error);
-                       }
+                       SetSocketOption (optionLevel, optionName, int_val);
                }
 
                public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int optionValue)
                {
                        ThrowIfDisposedAndClosed ();
 
+                       if (optionName == SocketOptionName.ReuseAddress && optionValue != 0 && !SupportsPortReuse ())
+                               throw new SocketException ((int) SocketError.OperationNotSupported, "Operating system sockets do not support ReuseAddress.\nIf your socket is not intended to bind to the same address and port multiple times remove this option, otherwise you should ignore this exception inside a try catch and check that ReuseAddress is true before binding to the same address and port multiple times.");
+
                        int error;
                        SetSocketOption_internal (safe_handle, optionLevel, optionName, null, null, optionValue, out error);
 
                        if (error != 0) {
+                               if (error == (int) SocketError.InvalidArgument)
+                                       throw new ArgumentException ();
                                throw new SocketException (error);
                        }
                }
@@ -3286,7 +3297,7 @@ namespace System.Net.Sockets
                }
 
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               extern static void Shutdown_internal (IntPtr socket, SocketShutdown how, out int error);
+               internal extern static void Shutdown_internal (IntPtr socket, SocketShutdown how, out int error);
 
 #endregion
 
@@ -3417,7 +3428,9 @@ namespace System.Net.Sockets
                void InitSocketAsyncEventArgs (SocketAsyncEventArgs e, AsyncCallback callback, object state, SocketOperation operation)
                {
                        e.socket_async_result.Init (this, callback, state, operation);
-
+                       if (e.AcceptSocket != null) {
+                               e.socket_async_result.AcceptSocket = e.AcceptSocket;
+                       }
                        e.current_socket = this;
                        e.SetLastOperation (SocketOperationToSocketAsyncOperation (operation));
                        e.SocketError = SocketError.Success;
@@ -3447,7 +3460,15 @@ namespace System.Net.Sockets
                                throw new NotImplementedException (String.Format ("Operation {0} is not implemented", op));
                        }
                }
-
+               
+               IPEndPoint RemapIPEndPoint (IPEndPoint input) {
+                       // If socket is DualMode ensure we automatically handle mapping IPv4 addresses to IPv6.
+                       if (IsDualMode && input.AddressFamily == AddressFamily.InterNetwork)
+                               return new IPEndPoint (input.Address.MapToIPv6 (), input.Port);
+                       
+                       return input;
+               }
+               
                [StructLayout (LayoutKind.Sequential)]
                struct WSABUF {
                        public int len;