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 ;
17
+ private $ ipv6 ;
13
18
14
19
/** @test */
15
20
public function connectionToTcpServerShouldSucceedWithLocalhost ()
@@ -29,4 +34,174 @@ public function connectionToTcpServerShouldSucceedWithLocalhost()
29
34
$ connection ->close ();
30
35
$ server ->close ();
31
36
}
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
+ // IPv4 not supported on this system
61
+ $ this ->assertFalse ($ this ->ipv4 ());
62
+ return ;
63
+ }
64
+
65
+ $ loop = Factory::create ();
66
+
67
+ $ connector = new Connector ($ loop , array ('happy_eyeballs ' => true ));
68
+
69
+ $ ip = Block \await ($ this ->request ('ipv4.tlund.se ' , $ connector ), $ loop , self ::TIMEOUT );
70
+
71
+ $ this ->assertSame ($ ip , filter_var ($ ip , FILTER_VALIDATE_IP , FILTER_FLAG_IPV4 ), $ ip );
72
+ $ this ->assertFalse (filter_var ($ ip , FILTER_VALIDATE_IP , FILTER_FLAG_IPV6 ), $ ip );
73
+ }
74
+
75
+ /**
76
+ * @test
77
+ * @group internet
78
+ */
79
+ public function connectionToRemoteTCP6ServerShouldResultInOurIP ()
80
+ {
81
+ if ($ this ->ipv6 () === false ) {
82
+ // IPv6 not supported on this system
83
+ $ this ->assertFalse ($ this ->ipv6 ());
84
+ return ;
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
+ * @group internet
100
+ *
101
+ * @expectedException \RuntimeException
102
+ * @expectedExceptionMessageRegExp /Connection to ipv6.tlund.se:80 failed/
103
+ */
104
+ public function tryingToConnectToAnIPv6OnlyHostWithOutHappyEyeBallsShouldResultInFailure ()
105
+ {
106
+ $ loop = Factory::create ();
107
+
108
+ $ connector = new Connector ($ loop , array ('happy_eyeballs ' => false ));
109
+
110
+ Block \await ($ this ->request ('ipv6.tlund.se ' , $ connector ), $ loop , self ::TIMEOUT );
111
+ }
112
+
113
+ /**
114
+ * @test
115
+ * @group internet
116
+ *
117
+ * @expectedException \RuntimeException
118
+ * @expectedExceptionMessageRegExp /Connection to tcp:\/\/193.15.228.195:80 failed:/
119
+ */
120
+ public function connectingDirectlyToAnIPv4AddressShouldFailWhenIPv4IsntAvailable ()
121
+ {
122
+ if ($ this ->ipv4 () === true ) {
123
+ // IPv4 supported on this system
124
+ throw new \RuntimeException ('Connection to tcp://193.15.228.195:80 failed: ' );
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
+ Block \await ($ this ->request ($ host , $ connector ), $ loop , self ::TIMEOUT );
134
+ }
135
+
136
+ /**
137
+ * @test
138
+ * @group internet
139
+ *
140
+ * @expectedException \RuntimeException
141
+ * @expectedExceptionMessageRegExp /Connection to tcp:\/\/\[2a00:801:f::195\]:80 failed:/
142
+ */
143
+ public function connectingDirectlyToAnIPv6AddressShouldFailWhenIPv6IsntAvailable ()
144
+ {
145
+ if ($ this ->ipv6 () === true ) {
146
+ // IPv6 supported on this system
147
+ throw new \RuntimeException ('Connection to tcp://[2a00:801:f::195]:80 failed: ' );
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
+ }
32
207
}
0 commit comments