Now before you send me off to Google where I've spent plenty of time on this issue...
Here's the scenario:
Client: SMTP server sending email with 1MB attachment
Middle man: PHP proxy script (https://codereview.stackexchange.com/questions/134880/simple-tcp-proxy)
Destination: PHP script accepting and processing SMTP connection/commands
What happens is, the Client sends SMTP data up until the "DATA" command, which the Destination accepts without any error from the Proxy. During the "DATA" command, when the Client is delivering mail data, this happpens:
PHP Notice: stream_copy_to_stream(): send of 8192 bytes failed with errno=11 Resource temporarily unavailable in /root/proxy.php on line 59
(this occurs on the Proxy script)
line 59 reffered to in the Notice above:
stream_copy_to_stream($client, $dest)
(with $client
referring to Client SMTP server and $dest
referring to Destination PHP script)
I think that this is in regards to the Client attempting to write data to Destination as Destination is busy, but what could it be busy with? Is the Destination still reading data from the stream from Proxy when Client is attempting to write to it? Would that cause this error? What exactly is happening?
If any code is required besides the Proxy code above, please let me know and I'll update this post.
I found a solution myself after rigorous testing. With the way the code was set up, there was only one stream_select()
function blocking and waiting for the $client
stream to have data available for reading. The problem is I didn't include a second stream_select()
to block until the destination stream was writable.
In essence, the following code works 100%:
--- snip ---
stream_select($r_sockets, $w = NULL, $e = NULL, NULL);
stream_select($r = NULL, $w_sockets, $e = NULL, NULL);
in_array($client, $r_sockets) && in_array($dest, $w_sockets) ?
stream_copy_to_stream($client, $dest, 1024):
stream_copy_to_stream($dest, $client, 1024);
The 1024
as the 3rd parameter to stream_copy_to_stream()
is what allowed the data to flow at a stable pace, instead of copying too much data from the $client
to the $dest
and causing the error.