@@ -74,74 +74,77 @@ private void ConfigureConnectedSocket(Socket socket)
7474
7575 private void Connect ( Socket socket , EndPoint endPoint , CancellationToken cancellationToken )
7676 {
77- IAsyncResult asyncResult ;
78- var dnsEndPoint = endPoint as DnsEndPoint ;
79- if ( dnsEndPoint != null )
80- {
81- // mono doesn't support DnsEndPoint in its BeginConnect method.
82- asyncResult = socket . BeginConnect ( dnsEndPoint . Host , dnsEndPoint . Port , null , null ) ;
83- }
84- else
85- {
86- asyncResult = socket . BeginConnect ( endPoint , null , null ) ;
87- }
77+ var cancelled = false ;
78+ var timedOut = false ;
8879
89- asyncResult . AsyncWaitHandle . WaitOne ( _settings . ConnectTimeout ) ;
90- if ( ! asyncResult . IsCompleted )
80+ using ( var registration = cancellationToken . Register ( ( ) => { cancelled = true ; try { socket . Close ( ) ; } catch { } } ) )
81+ using ( var timer = new Timer ( _ => { timedOut = true ; try { socket . Close ( ) ; } catch { } } , null , _settings . ConnectTimeout , Timeout . InfiniteTimeSpan ) )
9182 {
9283 try
9384 {
94- socket . Dispose ( ) ;
85+ var dnsEndPoint = endPoint as DnsEndPoint ;
86+ if ( dnsEndPoint != null )
87+ {
88+ // mono doesn't support DnsEndPoint in its BeginConnect method.
89+ socket . Connect ( dnsEndPoint . Host , dnsEndPoint . Port ) ;
90+ }
91+ else
92+ {
93+ socket . Connect ( endPoint ) ;
94+ }
9595 }
9696 catch
9797 {
98- // ignore exceptions
98+ if ( ! cancelled && ! timedOut )
99+ {
100+ throw ;
101+ }
99102 }
103+ }
100104
105+ cancellationToken . ThrowIfCancellationRequested ( ) ;
106+ if ( timedOut )
107+ {
101108 var message = string . Format ( "Timed out connecting to {0}. Timeout was {1}." , endPoint , _settings . ConnectTimeout ) ;
102109 throw new TimeoutException ( message ) ;
103110 }
104-
105- socket . EndConnect ( asyncResult ) ;
106111 }
107112
108113 private async Task ConnectAsync ( Socket socket , EndPoint endPoint , CancellationToken cancellationToken )
109114 {
110- Task connectTask ;
111- var dnsEndPoint = endPoint as DnsEndPoint ;
112- if ( dnsEndPoint != null )
113- {
114- // mono doesn't support DnsEndPoint in its BeginConnect method.
115- connectTask = Task . Factory . FromAsync ( socket . BeginConnect ( dnsEndPoint . Host , dnsEndPoint . Port , null , null ) , socket . EndConnect ) ;
116- }
117- else
118- {
119- connectTask = Task . Factory . FromAsync ( socket . BeginConnect ( endPoint , null , null ) , socket . EndConnect ) ;
120- }
115+ var cancelled = false ;
116+ var timedOut = false ;
121117
122- if ( _settings . ConnectTimeout == Timeout . InfiniteTimeSpan )
118+ using ( var registration = cancellationToken . Register ( ( ) => { cancelled = true ; try { socket . Close ( ) ; } catch { } } ) )
119+ using ( var timer = new Timer ( _ => { timedOut = true ; try { socket . Close ( ) ; } catch { } } , null , _settings . ConnectTimeout , Timeout . InfiniteTimeSpan ) )
123120 {
124- await connectTask . ConfigureAwait ( false ) ;
125- return ;
126- }
127-
128- using ( var delayCancellationTokenSource = new CancellationTokenSource ( ) )
129- {
130- var delayTask = Task . Delay ( _settings . ConnectTimeout , delayCancellationTokenSource . Token ) ;
131-
132- var completedTask = await Task . WhenAny ( connectTask , delayTask ) . ConfigureAwait ( false ) ;
133-
134- // kill the delay timer as soon as possible
135- delayCancellationTokenSource . Cancel ( ) ;
136-
137- if ( completedTask == delayTask && ! socket . Connected )
121+ try
122+ {
123+ var dnsEndPoint = endPoint as DnsEndPoint ;
124+ if ( dnsEndPoint != null )
125+ {
126+ // mono doesn't support DnsEndPoint in its BeginConnect method.
127+ await Task . Factory . FromAsync ( socket . BeginConnect ( dnsEndPoint . Host , dnsEndPoint . Port , null , null ) , socket . EndConnect ) . ConfigureAwait ( false ) ;
128+ }
129+ else
130+ {
131+ await Task . Factory . FromAsync ( socket . BeginConnect ( endPoint , null , null ) , socket . EndConnect ) . ConfigureAwait ( false ) ;
132+ }
133+ }
134+ catch
138135 {
139- socket . Dispose ( ) ;
140- var message = string . Format ( "Timed out connecting to {0}. Timeout was {1}." , endPoint , _settings . ConnectTimeout ) ;
141- throw new TimeoutException ( message ) ;
136+ if ( ! cancelled && ! timedOut )
137+ {
138+ throw ;
139+ }
142140 }
141+ }
143142
144- await connectTask . ConfigureAwait ( false ) ;
143+ cancellationToken . ThrowIfCancellationRequested ( ) ;
144+ if ( timedOut )
145+ {
146+ var message = string . Format ( "Timed out connecting to {0}. Timeout was {1}." , endPoint , _settings . ConnectTimeout ) ;
147+ throw new TimeoutException ( message ) ;
145148 }
146149 }
147150
0 commit comments