28
28
*/
29
29
class HeartBeat
30
30
{
31
+ private const DEFAULT_TIMEOUT = 10 ;
32
+
31
33
/**
32
34
* @var string The host you want to verify
33
35
*/
@@ -57,7 +59,7 @@ class HeartBeat
57
59
* @param int $port
58
60
* @param int $timeout
59
61
*/
60
- public function __construct (?string $ host = null , int $ port = 80 , int $ timeout = 10 )
62
+ public function __construct (?string $ host = null , int $ port = Vies:: VIES_PORT , int $ timeout = self :: DEFAULT_TIMEOUT )
61
63
{
62
64
if (null !== $ host ) {
63
65
$ this ->setHost ($ host );
@@ -150,23 +152,35 @@ public function isAlive(): bool
150
152
*/
151
153
private function reachOut (): bool
152
154
{
153
- $ errno = 0 ;
154
- $ error = '' ;
155
- $ hostname = $ this ->getHost ();
156
- $ portNumber = $ this ->getPort ();
157
- $ timeToLive = $ this ->getTimeout ();
158
155
try {
159
- if (false === ($ handle = \fsockopen ('tcp:// ' . $ hostname , $ portNumber , $ errno , $ error , $ timeToLive ))) {
160
- return false ;
161
- }
162
- } catch (\Exception $ exception ) {
156
+ $ data = $ this ->getSecuredResponse ();
157
+ } catch (\RuntimeException $ runtimeException ) {
163
158
return false ;
164
159
}
160
+ return (
161
+ (0 === strcmp ('HTTP/1.1 200 OK ' , $ data [0 ])) ||
162
+ (0 === strcmp ('HTTP/1.1 307 Temporary Redirect ' , $ data [0 ]))
163
+ );
164
+ }
165
+
166
+ /**
167
+ * This method will make a simple request inside a stream
168
+ * resource to retrieve its contents. Useful inside secured
169
+ * streams.
170
+ *
171
+ * @param resource $handle
172
+ * @return array
173
+ */
174
+ private function readContents ($ handle ): array
175
+ {
176
+ if (! is_resource ($ handle )) {
177
+ throw new \InvalidArgumentException ('Expecting a resource to be provided ' );
178
+ }
165
179
$ response = '' ;
166
- $ uri = sprintf ('%s://%s/ ' , Vies::VIES_PROTO , Vies:: VIES_DOMAIN );
180
+ $ uri = sprintf ('%s://%s/ ' , Vies::VIES_PROTO , $ this -> host );
167
181
$ stream = [
168
182
'GET ' . $ uri . ' HTTP/1.0 ' ,
169
- 'Host: ' . Vies:: VIES_DOMAIN ,
183
+ 'Host: ' . $ this -> host ,
170
184
'Connection: close ' ,
171
185
];
172
186
fwrite ($ handle , implode ("\r\n" , $ stream ) . "\r\n\r\n" );
@@ -176,9 +190,48 @@ private function reachOut(): bool
176
190
fclose ($ handle );
177
191
$ response = str_replace ("\r\n" , PHP_EOL , $ response );
178
192
$ data = explode (PHP_EOL , $ response );
179
- return (
180
- (0 === strcmp ('HTTP/1.1 200 OK ' , $ data [0 ])) ||
181
- (0 === strcmp ('HTTP/1.1 307 Temporary Redirect ' , $ data [0 ]))
193
+ return $ data ;
194
+ }
195
+
196
+ /**
197
+ * Will make a secured request over SSL/TLS where this
198
+ * method will first create a secured stream before
199
+ * making the request.
200
+ *
201
+ * @return array
202
+ * @throws \RuntimeException
203
+ * @see https://bytephunk.wordpress.com/2017/11/27/ssl-tls-stream-sockets-in-php-7/
204
+ */
205
+ private function getSecuredResponse (): array
206
+ {
207
+ $ streamOptions = [
208
+ 'ssl ' => [
209
+ 'verify_peer ' => true ,
210
+ 'verify_peer_name ' => true ,
211
+ 'allow_self_signed ' => false ,
212
+ ],
213
+ ];
214
+ $ streamContext = stream_context_create ($ streamOptions );
215
+ $ socketAddress = sprintf (
216
+ 'tls://%s:%d ' ,
217
+ $ this ->host ,
218
+ $ this ->port
219
+ );
220
+ $ error = null ;
221
+ $ errno = null ;
222
+ $ stream = stream_socket_client (
223
+ $ socketAddress ,
224
+ $ errno ,
225
+ $ error ,
226
+ self ::DEFAULT_TIMEOUT ,
227
+ STREAM_CLIENT_CONNECT ,
228
+ $ streamContext
182
229
);
230
+
231
+ if (! $ stream ) {
232
+ throw new \RuntimeException ('Can not create socket stream: ' . $ error );
233
+ }
234
+
235
+ return $ this ->readContents ($ stream );
183
236
}
184
237
}
0 commit comments