6
6
using System . Threading . Tasks ;
7
7
using System . Runtime . ExceptionServices ;
8
8
using static NetworkTables . Logging . Logger ;
9
+ using Nito . AsyncEx ;
10
+ using System . IO ;
9
11
10
12
namespace NetworkTables . TcpSockets
11
13
{
12
14
internal class TcpConnector
13
15
{
14
- private static bool WaitAndUnwrapException ( Task task , int timeout )
16
+ public class TcpClientNt : IClient
15
17
{
16
- try
18
+ private readonly TcpClient m_client ;
19
+
20
+ internal TcpClientNt ( TcpClient client )
17
21
{
18
- return task . Wait ( timeout ) ;
22
+ m_client = client ;
19
23
}
20
- catch ( AggregateException ex )
24
+
25
+ public Stream GetStream ( )
21
26
{
22
- ExceptionDispatchInfo . Capture ( ex . InnerException ) . Throw ( ) ;
23
- throw ex . InnerException ;
27
+ return m_client . GetStream ( ) ;
28
+ }
29
+ public EndPoint RemoteEndPoint
30
+ {
31
+ get
32
+ {
33
+ return m_client . Client . RemoteEndPoint ;
34
+ }
35
+ }
36
+ public bool NoDelay
37
+ {
38
+ set
39
+ {
40
+ }
41
+ }
42
+
43
+ public void Dispose ( )
44
+ {
45
+ m_client . Dispose ( ) ;
24
46
}
25
47
}
26
48
27
- private static int ResolveHostName ( string hostName , out IPAddress [ ] addr )
49
+ public static IClient Connect ( IList < ( string server , int port ) > servers , Logger logger , TimeSpan timeout )
28
50
{
29
- try
51
+ if ( servers . Count == 0 )
30
52
{
31
- var entries = Dns . GetHostAddressesAsync ( hostName ) ;
32
- var success = WaitAndUnwrapException ( entries , 1000 ) ;
33
- if ( ! success )
53
+ return null ;
54
+ }
55
+
56
+ return new TcpClientNt ( AsyncContext . Run ( async ( ) => {
57
+ TcpClient toReturn = null ;
58
+ var clientTcp = new List < TcpClient > ( ) ;
59
+ var clientTask = new List < Task > ( ) ;
60
+ try
34
61
{
35
- addr = null ;
36
- return 1 ;
62
+ for ( int i = 0 ; i < servers . Count ; i ++ )
63
+ {
64
+ TcpClient client = new TcpClient ( ) ;
65
+ Task connectTask = client . ConnectAsync ( servers [ i ] . server , servers [ i ] . port ) ;
66
+ clientTcp . Add ( client ) ;
67
+ clientTask . Add ( connectTask ) ;
68
+ }
69
+
70
+ // 10 second timeout
71
+ var delayTask = Task . Delay ( timeout ) ;
72
+
73
+ clientTask . Add ( delayTask ) ;
74
+
75
+ while ( clientTcp . Count != 0 )
76
+ {
77
+ var finished = await Task . WhenAny ( clientTask ) ;
78
+
79
+ var index = clientTask . IndexOf ( finished ) ;
80
+ if ( finished == delayTask )
81
+ {
82
+ return null ;
83
+ }
84
+ else if ( finished . IsCompleted && ! finished . IsFaulted && ! finished . IsCanceled )
85
+ {
86
+ toReturn = clientTcp [ index ] ;
87
+ return toReturn ;
88
+ }
89
+ var remove = clientTcp [ index ] ;
90
+ clientTcp . RemoveAt ( index ) ;
91
+ remove . Dispose ( ) ;
92
+ clientTask . RemoveAt ( index ) ;
93
+ }
94
+ return null ;
37
95
}
38
- List < IPAddress > addresses = new List < IPAddress > ( ) ;
39
- foreach ( var ipAddress in entries . Result )
96
+ finally
40
97
{
41
- // Only allow IPV4 addresses for now
42
- // Sockets don't all support IPV6
43
- if ( ipAddress . AddressFamily == AddressFamily . InterNetwork )
98
+ for ( int i = 0 ; i < clientTcp . Count ; i ++ )
44
99
{
45
- if ( ! addresses . Contains ( ipAddress ) )
100
+ if ( clientTcp [ i ] != toReturn )
46
101
{
47
- addresses . Add ( ipAddress ) ;
102
+ try
103
+ {
104
+ clientTcp [ i ] . Dispose ( ) ;
105
+ }
106
+ catch ( Exception e )
107
+ {
108
+ // Ignore exception
109
+ }
48
110
}
49
111
}
50
112
}
51
- addr = addresses . ToArray ( ) ;
52
-
53
- }
54
- catch ( SocketException e )
55
- {
56
- addr = null ;
57
- return ( int ) e . SocketErrorCode ;
58
- }
59
- return 0 ;
113
+ } ) ) ;
60
114
}
61
115
116
+ /*
62
117
public static NtTcpClient Connect(string server, int port, Logger logger, int timeout = 0)
63
118
{
64
119
if (ResolveHostName(server, out IPAddress[] addr) != 0)
@@ -102,5 +157,6 @@ public static NtTcpClient Connect(string server, int port, Logger logger, int ti
102
157
}
103
158
return client;
104
159
}
160
+ */
105
161
}
106
- }
162
+ }
0 commit comments