I'm trying to send a huge amount of data using SSL/TLS connection in PHP. It works pretty well if the data chunk isn't very big or if I don't use TLS, but what I need (near 2MiB), the fwrite
function shows the warning:
Warning: fwrite(): SSL operation failed with code 1. OpenSSL Error messages: error: 1409F07F: SSL routines: SSL3_WRITE_PENDING: bad write retry
The relevant code I'm using to connect clients:
$cntxt = stream_context_create(array('ssl' => array('local_cert' => 'certificate.pem')));
$server = stream_socket_server('tls://127.0.0.1:8080', $errno, $errstr, STREAM_SERVER_BIND|STREAM_SERVER_LISTEN, $cntxt);
// Wait for client connection //
$client = stream_socket_accept($server);
// Use non-blocking socket to allow answering many clients at a time
stream_set_blocking($client, 0);
$clients[] = $client;
When sending data, it's append to a buffer and, from time to time, this function is called for each client and linked buffer:
function trySend($client, &$buffer) {
if (strlen($buffer)) {
$len = fwrite($client, $buffer);
$buffer = substr($buffer, $len);
}
}
As I said, my code works for small ammount of data or for normal (non-TLS) connections. I've searched for this error and found http://www.openssl.org/docs/ssl/SSL_write.html:
SSL_write() will only return with success, when the complete contents of buf of length num has been written. This default behaviour can be changed with the SSL_MODE_ENABLE_PARTIAL_WRITE option of SSL_CTX_set_mode(3). When this flag is set, SSL_write() will also return with success, when a partial write has been successfully completed. In this case the SSL_write() operation is considered completed. The bytes are sent and a new SSL_write() operation with a new buffer (with the already sent bytes removed) must be started. A partial write is performed with the size of a message block, which is 16kB for SSLv3/TLSv1.
But how can I do this in PHP?
Any help appreciated :)
I have found I can get around this problem by restricting the length of the string passed to fwrite() to 8192, which prevents fwrite() warning.
So for the code in your example I would try changing the substr() call to:
$buffer = substr($buffer, $len, 8192);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With