From 62eac6475615e07418de25b4b3f086d06a673c61 Mon Sep 17 00:00:00 2001 From: Gonzalo Paniagua Javier Date: Thu, 28 Apr 2011 00:01:10 -0400 Subject: [PATCH] [socket] More BeginConnect (IPAddress []) work When trying multiple addresses, the second and sucessive calls to BeginConnect(IPAddress) will cause an error which we would have to ignore and then retry. Since this behavior is not documented, we just close the socket and open a new one for retries is there is already a pending connect attempt. --- .../System/System.Net.Sockets/Socket_2_1.cs | 57 +++++++------------ 1 file changed, 19 insertions(+), 38 deletions(-) diff --git a/mcs/class/System/System.Net.Sockets/Socket_2_1.cs b/mcs/class/System/System.Net.Sockets/Socket_2_1.cs index b97a48976e9..69d4b575353 100644 --- a/mcs/class/System/System.Net.Sockets/Socket_2_1.cs +++ b/mcs/class/System/System.Net.Sockets/Socket_2_1.cs @@ -588,6 +588,8 @@ namespace System.Net.Sockets { result = mconnect; result.Sock.seed_endpoint = ep; result.Sock.connected = true; + result.Sock.isbound = true; + result.Sock.connect_in_progress = false; result.error = 0; result.Complete (); if (is_mconnect) @@ -596,6 +598,7 @@ namespace System.Net.Sockets { } if (!is_mconnect) { + result.Sock.connect_in_progress = false; result.Complete (new SocketException (error_code)); return; } @@ -606,10 +609,9 @@ namespace System.Net.Sockets { mconnect.DoMConnectCallback (); return; } -#if !MOONLIGHT mconnect.Sock.BeginMConnect (mconnect); -#endif } catch (Exception e) { + result.Sock.connect_in_progress = false; if (is_mconnect) result = mconnect; result.Complete (e); @@ -864,6 +866,7 @@ namespace System.Net.Sockets { /* true if we called Close_internal */ private bool closed; internal bool disposed; + bool connect_in_progress; /* * This EndPoint is used when creating new endpoints. Because @@ -1326,42 +1329,6 @@ namespace System.Net.Sockets { [MethodImplAttribute(MethodImplOptions.InternalCall)] extern static bool Poll_internal (IntPtr socket, SelectMode mode, int timeout, out int error); - /* This overload is needed as the async Connect method - * also needs to check the socket error status, but - * getsockopt(..., SO_ERROR) clears the error. - */ - internal bool Poll (int time_us, SelectMode mode, out int socket_error) - { - if (disposed && closed) - throw new ObjectDisposedException (GetType ().ToString ()); - - 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); - - socket_error = (int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error); - - if (mode == SelectMode.SelectWrite && result) { - /* Update the connected state; for - * non-blocking Connect()s this is - * when we can find out that the - * connect succeeded. - */ - if (socket_error == 0) { - connected = true; - isbound = true; - } - } - - return result; - } - [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern static int Receive_internal(IntPtr sock, byte[] buffer, @@ -1515,6 +1482,16 @@ namespace System.Net.Sockets { } int error = 0; + if (connect_in_progress) { + // This could happen when multiple IPs are used + // Calling connect() again will reset the connection attempt and cause + // an error. Better to just close the socket and move on. + connect_in_progress = false; + Close_internal (socket, out error); + socket = Socket_internal (address_family, socket_type, protocol_type, out error); + if (error != 0) + throw new SocketException (error); + } bool blk = blocking; if (blk) Blocking = false; @@ -1525,6 +1502,7 @@ namespace System.Net.Sockets { if (error == 0) { // succeeded synch connected = true; + isbound = true; req.Complete (true); return req; } @@ -1532,12 +1510,15 @@ namespace System.Net.Sockets { if (error != (int) SocketError.InProgress && error != (int) SocketError.WouldBlock) { // error synch connected = false; + isbound = false; req.Complete (new SocketException (error), true); return req; } // continue asynch connected = false; + isbound = false; + connect_in_progress = true; socket_pool_queue (Worker.Dispatcher, req); return req; } -- 2.25.1