1--TEST-- 2Bug #74159: Writing a large buffer to non-blocking encrypted streams fails 3--EXTENSIONS-- 4openssl 5--SKIPIF-- 6<?php 7if (!function_exists("proc_open")) die("skip no proc_open"); 8?> 9--FILE-- 10<?php 11$certFile = __DIR__ . DIRECTORY_SEPARATOR . 'bug74159.pem.tmp'; 12$cacertFile = __DIR__ . DIRECTORY_SEPARATOR . 'bug74159-ca.pem.tmp'; 13 14// the server code is doing many readings in a short interval which is 15// not really reliable on more powerful machine but cover different 16// scenarios which might be useful. More reliable test is bug72333.phpt 17$serverCode = <<<'CODE' 18 $serverUri = "ssl://127.0.0.1:10012"; 19 $serverFlags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN; 20 $serverCtx = stream_context_create(['ssl' => [ 21 'local_cert' => '%s', 22 'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_2_SERVER, 23 ]]); 24 25 $server = stream_socket_server($serverUri, $errno, $errstr, $serverFlags, $serverCtx); 26 phpt_notify(); 27 28 $client = stream_socket_accept($server, 1); 29 30 if (!$client) { 31 exit(); 32 } 33 34 $data = ''; 35 while (strlen($data) < 0xfffff) { 36 $buffer = fread($client, 8192); 37 if (empty($buffer)) { 38 exit(); 39 } 40 $data .= $buffer; 41 usleep(100); 42 } 43 44 fclose($client); 45CODE; 46$serverCode = sprintf($serverCode, $certFile); 47 48$peerName = 'bug74159'; 49$clientCode = <<<'CODE' 50 function streamRead($stream) : int { 51 return strlen(fread($stream, 8192)); 52 } 53 54 function streamWrite($stream, $data) : int { 55 return fwrite($stream, $data); 56 } 57 58 function waitForWrite(...$streams) : bool { 59 $read = null; 60 $except = null; 61 while($streams && !($n = stream_select($read, $streams, $except, 1))); 62 return $n > 0; 63 } 64 65 function waitForRead(...$streams) : bool { 66 $write = null; 67 $except = null; 68 while ($streams && !($n = stream_select($streams, $write, $except, 1))); 69 return $n > 0; 70 } 71 72 set_error_handler(function ($errno, $errstr) { 73 exit("$errstr\n"); 74 }); 75 76 $serverUri = "tcp://127.0.0.1:10012"; 77 $clientFlags = STREAM_CLIENT_CONNECT; 78 $clientCtx = stream_context_create(['ssl' => [ 79 'verify_peer' => true, 80 'cafile' => '%s', 81 'peer_name' => '%s', 82 ]]); 83 84 phpt_wait(); 85 86 $fp = stream_socket_client($serverUri, $errno, $errstr, 1, $clientFlags, $clientCtx); 87 88 stream_set_blocking($fp, false); 89 while (0 === ($n = stream_socket_enable_crypto($fp, true, STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT))); 90 91 $data = str_repeat("a", 0xfffff); 92 $written = 0; 93 $total = $written; 94 while(!empty($data)) { 95 $written = streamWrite($fp, $data); 96 $total += $written; 97 $data = substr($data, $written); 98 waitForWrite($fp); 99 } 100 printf("Written %%d bytes\n", $total); 101 102 while(waitForRead($fp)) { 103 streamRead($fp); 104 if (feof($fp)) { 105 break; 106 } 107 } 108 109 exit("DONE\n"); 110CODE; 111$clientCode = sprintf($clientCode, $cacertFile, $peerName); 112 113include 'CertificateGenerator.inc'; 114$certificateGenerator = new CertificateGenerator(); 115$certificateGenerator->saveCaCert($cacertFile); 116$certificateGenerator->saveNewCertAsFileWithKey($peerName, $certFile); 117 118include 'ServerClientTestCase.inc'; 119ServerClientTestCase::getInstance()->run($clientCode, $serverCode); 120?> 121--CLEAN-- 122<?php 123@unlink(__DIR__ . DIRECTORY_SEPARATOR . 'bug74159.pem.tmp'); 124@unlink(__DIR__ . DIRECTORY_SEPARATOR . 'bug74159-ca.pem.tmp'); 125?> 126--EXPECT-- 127Written 1048575 bytes 128DONE 129