reactphp / socket

Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP.
https://reactphp.org/socket/
MIT License
1.21k stars 157 forks source link

Write never send data #273

Closed mastir closed 2 years ago

mastir commented 3 years ago

When i test my server, i see new connection, but no data sent.

$minimal = hex2bin('78780d0103587350716231840064b1450d0a').hex2bin('78780a1305060400020067e3370d0a').hex2bin('78781f12120612102129c60533baf803bf642414544b00ff0675330005e9001941d00d0a');

$loop = React\EventLoop\Factory::create();
$connector = new React\Socket\Connector($loop);
$port = $argv[1] ?? 33664;
$connector->connect('127.0.0.1:'.$port)->then(function ($conn) use ($loop) {
    $conn->on('data', function($chunk){
        echo '.';
    });
    $conn->on('error', function(){
        echo 'error';
    });
    $conn->on('close', function(){
        echo 'close';
    });
    echo 'Send'.PHP_EOL;
    $conn->send($minimal);
    $conn->end();

});

$loop->run();
echo 'done?'.PHP_EOL;

iptables -L

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination 

I started nc -l 0.0.0.0 33664 and nothing. I see "Send" message, but nothing ever happens. Only if i stop nc i see "close" message. But when i send a big amount of data it works. Tried piping 2mb file with test data and it worked so I tried to save into file this data and pipe it - nothig comes.

mastir commented 3 years ago

Tried without react and everything works

$port = $argv[1] ?? 33664;
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$result = socket_connect($socket, '127.0.0.1', $port);
echo 'Connect: '.($result ? 'OK' : 'FAIL');
if (!$result)exit;

$minimal = hex2bin('78780d0103587350716231840064b1450d0a').hex2bin('78780a1305060400020067e3370d0a').hex2bin('78781f12120612102129c60533baf803bf642414544b00ff0675330005e9001941d00d0a');

echo 'Got:';
socket_write($socket, $minimal, strlen($minimal));
while ($data = socket_read($socket, 2048)) {
    echo chunk_split(bin2hex($data),2,' ');
}
echo "close..\n\n";
socket_close($socket);

Connect: OKGot:78 78 05 01 00 64 ed 77 0d 0a 78 78 05 13 00 67 ef c1 0d 0a

clue commented 2 years ago

@mastir Thanks for reporting, this is a nasty one!

It looks like there's s small oversight and all you're missing is a use ($minimal) in your code. Because this is missing, you're essentially passing an undefined variable to $conn->send() which PHP will report (as a warning in PHP 8+ and as a notice in earlier versions) and continue with a null value, effectively sending nothing.

Your IDE of choice or static analysis tools such as phpstan should be able to point you to this variable. On top of this, you can configure PHP to show this warning/notice to you during runtime.

If you're using an error handler that turns this warning/notice into an Exception or Throwable, the code will currently cause the promise to be rejected on this line. We're working on https://github.com/reactphp/promise/issues/87 to improve default error reporting in this case.

I believe this has been answered, so I'm closing this for now. Please come back with more details if this problem persists and we can always reopen this :+1: