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