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