4
4
5
5
use Clue \React \Block ;
6
6
use React \EventLoop \Factory ;
7
+ use React \Socket \ConnectionInterface ;
7
8
use React \Socket \Connector ;
9
+ use React \Socket \ConnectorInterface ;
8
10
use React \Socket \TcpServer ;
9
11
10
12
class FunctionalConnectorTest extends TestCase
11
13
{
12
- const TIMEOUT = 1.0 ;
14
+ const TIMEOUT = 30.0 ;
15
+
16
+ private $ ipv4 = false ;
17
+ private $ ipv6 = false ;
18
+
19
+ public function __construct ()
20
+ {
21
+ parent ::__construct ();
22
+ $ this ->ipv4 = !!@file_get_contents ('http://ipv4.tlund.se/ ' );
23
+ $ this ->ipv6 = !!@file_get_contents ('http://ipv6.tlund.se/ ' );
24
+ }
13
25
14
26
/** @test */
15
27
public function connectionToTcpServerShouldSucceedWithLocalhost ()
@@ -29,4 +41,146 @@ public function connectionToTcpServerShouldSucceedWithLocalhost()
29
41
$ connection ->close ();
30
42
$ server ->close ();
31
43
}
44
+
45
+ /**
46
+ * @test
47
+ */
48
+ public function connectionToRemoteTCP4n6ServerShouldResultInOurIP ()
49
+ {
50
+ $ loop = Factory::create ();
51
+
52
+ $ connector = new Connector ($ loop , array ('happy_eyeballs ' => true ));
53
+
54
+ $ ip = Block \await ($ this ->request ('dual.tlund.se ' , $ connector ), $ loop , self ::TIMEOUT );
55
+
56
+ $ this ->assertSame ($ ip , filter_var ($ ip , FILTER_VALIDATE_IP , FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 ), $ ip );
57
+ }
58
+
59
+ /**
60
+ * @test
61
+ */
62
+ public function connectionToRemoteTCP4ServerShouldResultInOurIP ()
63
+ {
64
+ if ($ this ->ipv4 === false ) {
65
+ $ this ->markTestSkipped ('IPv4 not supported on this system ' );
66
+ }
67
+
68
+ $ loop = Factory::create ();
69
+
70
+ $ connector = new Connector ($ loop , array ('happy_eyeballs ' => true ));
71
+
72
+ $ ip = Block \await ($ this ->request ('ipv4.tlund.se ' , $ connector ), $ loop , self ::TIMEOUT );
73
+
74
+ $ this ->assertSame ($ ip , filter_var ($ ip , FILTER_VALIDATE_IP , FILTER_FLAG_IPV4 ), $ ip );
75
+ $ this ->assertFalse (filter_var ($ ip , FILTER_VALIDATE_IP , FILTER_FLAG_IPV6 ), $ ip );
76
+ }
77
+
78
+ /**
79
+ * @test
80
+ */
81
+ public function connectionToRemoteTCP6ServerShouldResultInOurIP ()
82
+ {
83
+ if ($ this ->ipv6 === false ) {
84
+ $ this ->markTestSkipped ('IPv6 not supported on this system ' );
85
+ }
86
+
87
+ $ loop = Factory::create ();
88
+
89
+ $ connector = new Connector ($ loop , array ('happy_eyeballs ' => true ));
90
+
91
+ $ ip = Block \await ($ this ->request ('ipv6.tlund.se ' , $ connector ), $ loop , self ::TIMEOUT );
92
+
93
+ $ this ->assertFalse (filter_var ($ ip , FILTER_VALIDATE_IP , FILTER_FLAG_IPV4 ), $ ip );
94
+ $ this ->assertSame ($ ip , filter_var ($ ip , FILTER_VALIDATE_IP , FILTER_FLAG_IPV6 ), $ ip );
95
+ }
96
+
97
+ /**
98
+ * @test
99
+ *
100
+ * @expectedException \RuntimeException
101
+ * @expectedExceptionMessageRegExp /Connection to ipv6.tlund.se:80 failed/
102
+ */
103
+ public function tryingToConnectToAnIPv6OnlyHostWithOutHappyEyeBallsShouldResultInFailure ()
104
+ {
105
+ $ loop = Factory::create ();
106
+
107
+ $ connector = new Connector ($ loop );
108
+
109
+ $ ip = Block \await ($ this ->request ('ipv6.tlund.se ' , $ connector ), $ loop , self ::TIMEOUT );
110
+
111
+ $ this ->assertFalse (filter_var ($ ip , FILTER_VALIDATE_IP , FILTER_FLAG_IPV4 ), $ ip );
112
+ $ this ->assertSame ($ ip , filter_var ($ ip , FILTER_VALIDATE_IP , FILTER_FLAG_IPV6 ), $ ip );
113
+ }
114
+
115
+ /**
116
+ * @test
117
+ *
118
+ * @expectedException \RuntimeException
119
+ * @expectedExceptionMessageRegExp /Connection to tcp:\/\/193.15.228.195:80 failed:/
120
+ */
121
+ public function connectingDirectlyToAnIPv4AddressShouldFailWhenIPv4IsntAvailable ()
122
+ {
123
+ if ($ this ->ipv4 === true ) {
124
+ $ this ->markTestSkipped ('IPv4 supported on this system ' );
125
+ }
126
+
127
+ $ loop = Factory::create ();
128
+
129
+ $ connector = new Connector ($ loop );
130
+
131
+ $ host = current (dns_get_record ('ipv4.tlund.se ' , DNS_A ));
132
+ $ host = $ host ['ip ' ];
133
+ $ ip = Block \await ($ this ->request ($ host , $ connector ), $ loop , self ::TIMEOUT );
134
+
135
+ $ this ->assertSame ($ ip , filter_var ($ ip , FILTER_VALIDATE_IP , FILTER_FLAG_IPV4 ), $ ip );
136
+ $ this ->assertFalse (filter_var ($ ip , FILTER_VALIDATE_IP , FILTER_FLAG_IPV6 ), $ ip );
137
+ }
138
+
139
+ /**
140
+ * @test
141
+ *
142
+ * @expectedException \RuntimeException
143
+ * @expectedExceptionMessageRegExp /Connection to tcp:\/\/\[2a00:801:f::195\]:80 failed:/
144
+ */
145
+ public function connectingDirectlyToAnIPv6AddressShouldFailWhenIPv6IsntAvailable ()
146
+ {
147
+ if ($ this ->ipv6 === true ) {
148
+ $ this ->markTestSkipped ('IPv6 supported on this system ' );
149
+ }
150
+
151
+ $ loop = Factory::create ();
152
+
153
+ $ connector = new Connector ($ loop );
154
+
155
+ $ host = current (dns_get_record ('ipv6.tlund.se ' , DNS_AAAA ));
156
+ $ host = $ host ['ipv6 ' ];
157
+ $ host = '[ ' . $ host . '] ' ;
158
+ $ ip = Block \await ($ this ->request ($ host , $ connector ), $ loop , self ::TIMEOUT );
159
+
160
+ $ this ->assertFalse (filter_var ($ ip , FILTER_VALIDATE_IP , FILTER_FLAG_IPV4 ), $ ip );
161
+ $ this ->assertSame ($ ip , filter_var ($ ip , FILTER_VALIDATE_IP , FILTER_FLAG_IPV6 ), $ ip );
162
+ }
163
+
164
+ /**
165
+ * @internal
166
+ */
167
+ public function parseIpFromPage ($ body )
168
+ {
169
+ $ ex = explode ('title="Look up on bgp.he.net"> ' , $ body );
170
+ $ ex = explode ('< ' , $ ex [1 ]);
171
+
172
+ return $ ex [0 ];
173
+ }
174
+
175
+ private function request ($ host , ConnectorInterface $ connector )
176
+ {
177
+ $ that = $ this ;
178
+ return $ connector ->connect ($ host . ':80 ' )->then (function (ConnectionInterface $ connection ) use ($ host ) {
179
+ $ connection ->write ("GET / HTTP/1.1 \r\nHost: " . $ host . "\r\n\r\n" );
180
+
181
+ return \React \Promise \Stream \buffer ($ connection );
182
+ })->then (function ($ response ) use ($ that ) {
183
+ return $ that ->parseIpFromPage ($ response );
184
+ });
185
+ }
32
186
}
0 commit comments