22
33namespace React \Tests \Socket ;
44
5+ use Clue \React \Block ;
6+ use Evenement \EventEmitterInterface ;
57use React \EventLoop \Factory ;
6- use React \Socket \ SecureServer ;
8+ use React \Promise \ Promise ;
79use React \Socket \ConnectionInterface ;
10+ use React \Socket \SecureConnector ;
11+ use React \Socket \SecureServer ;
812use React \Socket \TcpServer ;
913use React \Socket \TcpConnector ;
10- use React \Socket \SecureConnector ;
11- use Clue \React \Block ;
14+ use React \Socket \ServerInterface ;
1215
1316class FunctionalSecureServerTest extends TestCase
1417{
@@ -86,7 +89,7 @@ public function testWritesDataInMultipleChunksToConnection()
8689 $ promise = $ connector ->connect ($ server ->getAddress ());
8790
8891 $ local = Block \await ($ promise , $ loop , self ::TIMEOUT );
89- /* @var $local React\Stream\Stream */
92+ /* @var $local ConnectionInterface */
9093
9194 $ received = 0 ;
9295 $ local ->on ('data ' , function ($ chunk ) use (&$ received ) {
@@ -118,7 +121,7 @@ public function testWritesMoreDataInMultipleChunksToConnection()
118121 $ promise = $ connector ->connect ($ server ->getAddress ());
119122
120123 $ local = Block \await ($ promise , $ loop , self ::TIMEOUT );
121- /* @var $local React\Stream\Stream */
124+ /* @var $local ConnectionInterface */
122125
123126 $ received = 0 ;
124127 $ local ->on ('data ' , function ($ chunk ) use (&$ received ) {
@@ -151,7 +154,7 @@ public function testEmitsDataFromConnection()
151154 $ promise = $ connector ->connect ($ server ->getAddress ());
152155
153156 $ local = Block \await ($ promise , $ loop , self ::TIMEOUT );
154- /* @var $local React\Stream\Stream */
157+ /* @var $local ConnectionInterface */
155158
156159 $ local ->write ("foo " );
157160
@@ -181,7 +184,7 @@ public function testEmitsDataInMultipleChunksFromConnection()
181184 $ promise = $ connector ->connect ($ server ->getAddress ());
182185
183186 $ local = Block \await ($ promise , $ loop , self ::TIMEOUT );
184- /* @var $local React\Stream\Stream */
187+ /* @var $local ConnectionInterface */
185188
186189 $ local ->write (str_repeat ('* ' , 400000 ));
187190
@@ -210,7 +213,7 @@ public function testPipesDataBackInMultipleChunksFromConnection()
210213 $ promise = $ connector ->connect ($ server ->getAddress ());
211214
212215 $ local = Block \await ($ promise , $ loop , self ::TIMEOUT );
213- /* @var $local React\Stream\Stream */
216+ /* @var $local ConnectionInterface */
214217
215218 $ received = 0 ;
216219 $ local ->on ('data ' , function ($ chunk ) use (&$ received ) {
@@ -361,15 +364,15 @@ public function testEmitsErrorForConnectionWithPeerVerification()
361364 'local_cert ' => __DIR__ . '/../examples/localhost.pem '
362365 ));
363366 $ server ->on ('connection ' , $ this ->expectCallableNever ());
364- $ server -> on ( ' error ' , $ this ->expectCallableOnce () );
367+ $ errorEvent = $ this ->createPromiseForServerError ( $ server );
365368
366369 $ connector = new SecureConnector (new TcpConnector ($ loop ), $ loop , array (
367370 'verify_peer ' => true
368371 ));
369372 $ promise = $ connector ->connect ($ server ->getAddress ());
370-
371373 $ promise ->then (null , $ this ->expectCallableOnce ());
372- Block \sleep (self ::TIMEOUT , $ loop );
374+
375+ Block \await ($ errorEvent , $ loop , self ::TIMEOUT );
373376 }
374377
375378 public function testEmitsErrorIfConnectionIsCancelled ()
@@ -385,16 +388,66 @@ public function testEmitsErrorIfConnectionIsCancelled()
385388 'local_cert ' => __DIR__ . '/../examples/localhost.pem '
386389 ));
387390 $ server ->on ('connection ' , $ this ->expectCallableNever ());
388- $ server -> on ( ' error ' , $ this ->expectCallableOnce () );
391+ $ errorEvent = $ this ->createPromiseForServerError ( $ server );
389392
390393 $ connector = new SecureConnector (new TcpConnector ($ loop ), $ loop , array (
391394 'verify_peer ' => false
392395 ));
393396 $ promise = $ connector ->connect ($ server ->getAddress ());
394397 $ promise ->cancel ();
395-
396398 $ promise ->then (null , $ this ->expectCallableOnce ());
397- Block \sleep (self ::TIMEOUT , $ loop );
399+
400+ Block \await ($ errorEvent , $ loop , self ::TIMEOUT );
401+ }
402+
403+ public function testEmitsErrorIfConnectionIsClosedBeforeHandshake ()
404+ {
405+ $ loop = Factory::create ();
406+
407+ $ server = new TcpServer (0 , $ loop );
408+ $ server = new SecureServer ($ server , $ loop , array (
409+ 'local_cert ' => __DIR__ . '/../examples/localhost.pem '
410+ ));
411+ $ server ->on ('connection ' , $ this ->expectCallableNever ());
412+ $ errorEvent = $ this ->createPromiseForServerError ($ server );
413+
414+ $ connector = new TcpConnector ($ loop );
415+ $ promise = $ connector ->connect (str_replace ('tls:// ' , '' , $ server ->getAddress ()));
416+
417+ $ promise ->then (function (ConnectionInterface $ stream ) {
418+ $ stream ->close ();
419+ });
420+
421+ $ error = Block \await ($ errorEvent , $ loop , self ::TIMEOUT );
422+
423+ $ this ->assertTrue ($ error instanceof \RuntimeException);
424+ $ this ->assertEquals ('Connection lost during TLS handshake ' , $ error ->getMessage ());
425+ $ this ->assertEquals (defined ('SOCKET_ECONNRESET ' ) ? SOCKET_ECONNRESET : 0 , $ error ->getCode ());
426+ }
427+
428+ public function testEmitsErrorIfConnectionIsClosedWithIncompleteHandshake ()
429+ {
430+ $ loop = Factory::create ();
431+
432+ $ server = new TcpServer (0 , $ loop );
433+ $ server = new SecureServer ($ server , $ loop , array (
434+ 'local_cert ' => __DIR__ . '/../examples/localhost.pem '
435+ ));
436+ $ server ->on ('connection ' , $ this ->expectCallableNever ());
437+ $ errorEvent = $ this ->createPromiseForServerError ($ server );
438+
439+ $ connector = new TcpConnector ($ loop );
440+ $ promise = $ connector ->connect (str_replace ('tls:// ' , '' , $ server ->getAddress ()));
441+
442+ $ promise ->then (function (ConnectionInterface $ stream ) {
443+ $ stream ->end ("\x1e" );
444+ });
445+
446+ $ error = Block \await ($ errorEvent , $ loop , self ::TIMEOUT );
447+
448+ $ this ->assertTrue ($ error instanceof \RuntimeException);
449+ $ this ->assertEquals ('Connection lost during TLS handshake ' , $ error ->getMessage ());
450+ $ this ->assertEquals (defined ('SOCKET_ECONNRESET ' ) ? SOCKET_ECONNRESET : 0 , $ error ->getCode ());
398451 }
399452
400453 public function testEmitsNothingIfConnectionIsIdle ()
@@ -415,7 +468,7 @@ public function testEmitsNothingIfConnectionIsIdle()
415468 Block \sleep (self ::TIMEOUT , $ loop );
416469 }
417470
418- public function testEmitsErrorIfConnectionIsNotSecureHandshake ()
471+ public function testEmitsErrorIfConnectionIsHttpInsteadOfSecureHandshake ()
419472 {
420473 $ loop = Factory::create ();
421474
@@ -424,7 +477,7 @@ public function testEmitsErrorIfConnectionIsNotSecureHandshake()
424477 'local_cert ' => __DIR__ . '/../examples/localhost.pem '
425478 ));
426479 $ server ->on ('connection ' , $ this ->expectCallableNever ());
427- $ server -> on ( ' error ' , $ this ->expectCallableOnce () );
480+ $ errorEvent = $ this ->createPromiseForServerError ( $ server );
428481
429482 $ connector = new TcpConnector ($ loop );
430483 $ promise = $ connector ->connect (str_replace ('tls:// ' , '' , $ server ->getAddress ()));
@@ -433,6 +486,59 @@ public function testEmitsErrorIfConnectionIsNotSecureHandshake()
433486 $ stream ->write ("GET / HTTP/1.0 \r\n\r\n" );
434487 });
435488
436- Block \sleep (self ::TIMEOUT , $ loop );
489+ $ error = Block \await ($ errorEvent , $ loop , self ::TIMEOUT );
490+
491+ $ this ->assertTrue ($ error instanceof \RuntimeException);
492+
493+ // OpenSSL error messages are version/platform specific
494+ // Unable to complete TLS handshake: SSL operation failed with code 1. OpenSSL Error messages: error:1408F10B:SSL routines:SSL3_GET_RECORD:http request
495+ // Unable to complete TLS handshake: SSL operation failed with code 1. OpenSSL Error messages: error:1408F10B:SSL routines:ssl3_get_record:wrong version number
496+ // Unable to complete TLS handshake: SSL operation failed with code 1. OpenSSL Error messages: error:1408F10B:SSL routines:func(143):reason(267)
497+ // Unable to complete TLS handshake: Failed setting RSA key
498+ }
499+
500+ public function testEmitsErrorIfConnectionIsUnknownProtocolInsteadOfSecureHandshake ()
501+ {
502+ $ loop = Factory::create ();
503+
504+ $ server = new TcpServer (0 , $ loop );
505+ $ server = new SecureServer ($ server , $ loop , array (
506+ 'local_cert ' => __DIR__ . '/../examples/localhost.pem '
507+ ));
508+ $ server ->on ('connection ' , $ this ->expectCallableNever ());
509+ $ errorEvent = $ this ->createPromiseForServerError ($ server );
510+
511+ $ connector = new TcpConnector ($ loop );
512+ $ promise = $ connector ->connect (str_replace ('tls:// ' , '' , $ server ->getAddress ()));
513+
514+ $ promise ->then (function (ConnectionInterface $ stream ) {
515+ $ stream ->write ("Hello world! \n" );
516+ });
517+
518+ $ error = Block \await ($ errorEvent , $ loop , self ::TIMEOUT );
519+
520+ $ this ->assertTrue ($ error instanceof \RuntimeException);
521+
522+ // OpenSSL error messages are version/platform specific
523+ // Unable to complete TLS handshake: SSL operation failed with code 1. OpenSSL Error messages: error:1408F10B:SSL routines:SSL3_GET_RECORD:unknown protocol
524+ // Unable to complete TLS handshake: SSL operation failed with code 1. OpenSSL Error messages: error:1408F10B:SSL routines:ssl3_get_record:wrong version number
525+ // Unable to complete TLS handshake: SSL operation failed with code 1. OpenSSL Error messages: error:1408F10B:SSL routines:func(143):reason(267)
526+ // Unable to complete TLS handshake: Failed setting RSA key
527+ }
528+
529+ private function createPromiseForServerError (ServerInterface $ server )
530+ {
531+ return $ this ->createPromiseForEvent ($ server , 'error ' , function ($ error ) {
532+ return $ error ;
533+ });
534+ }
535+
536+ private function createPromiseForEvent (EventEmitterInterface $ emitter , $ event , $ fn )
537+ {
538+ return new Promise (function ($ resolve ) use ($ emitter , $ event , $ fn ) {
539+ $ emitter ->on ($ event , function () use ($ resolve , $ fn ) {
540+ $ resolve (call_user_func_array ($ fn , func_get_args ()));
541+ });
542+ });
437543 }
438544}
0 commit comments