php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #49486 socket_read couldn't detect the end of data
Submitted: 2009-09-06 13:34 UTC Modified: 2009-09-07 14:16 UTC
From: kernins at gmail dot com Assigned:
Status: Not a bug Package: Sockets related
PHP Version: 5.2.9, 5.3.0 OS: Debian 4.0, WinXP SP3
Private report: No CVE-ID: None
 [2009-09-06 13:34 UTC] kernins at gmail dot com
Description:
------------
App description: Script should connect to socks4/5 or CONNECT proxy and establish a tunnel to some host, google.com:80, for example.

Problem: socket_read() couldn't detect the end of data while reading response from socks4/5 server (response to initial hello msg or connect command) or from connect-proxy (response to connect command).

Reproduce code:
---------------
$host=gethostbyname("google.com"); $port=80;
$proxy_ip="212.27.33.4"; $proxy_port=8118;
if(!preg_match('/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/',$host,$ip)) die();
$s5_init="\x05\x01\x00";
$s5_connect="\x05\x01\x00\x01".chr($ip[1]).chr($ip[2]).chr($ip[3]).chr($ip[4]).pack('n',$port);
$s4="\x04\x01".pack('n',$port).chr($ip[1]).chr($ip[2]).chr($ip[3]).chr($ip[4])."\x00";
$connect="CONNECT google.com:80 HTTP/1.1\r\nProxy-Connection: keep-alive\r\n\r\n";

$sock=socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($sock,SOL_SOCKET,SO_SNDTIMEO,array('sec'=>5,'usec'=>0));
socket_set_option($sock,SOL_SOCKET,SO_RCVTIMEO,array('sec'=>15,'usec'=>0));
socket_connect($sock,$proxy_ip,$proxy_port);
echo "written: ".socket_write($sock,$connect).PHP_EOL;
//$data=socket_read($sock,1024,PHP_BINARY_READ);
while($data=socket_read($sock,1024,PHP_BINARY_READ)) var_dump($data);
$err=socket_last_error($sock);
$e=socket_get_option($sock,SOL_SOCKET,SO_ERROR);
var_dump($data,$err,socket_strerror($err),$e,socket_strerror($e));

Expected result:
----------------
In blocking mode:
while($data=socket_read($sock,1024,PHP_BINARY_READ))
will make two or more iterations, at last iteration socket_read will return emty string indicating end of data.

In non-blocking mode:
socket_select will return socket two or more times as ready for reading. Last time socket_read will return emty string indicating end of data.

Actual result:
--------------
In blocking mode:
if I use a single socket_read($sock,1024,PHP_BINARY_READ) call, it returns data without any significant delay or error. In that case there are no problems.

But
while($data=socket_read($sock,1024,PHP_BINARY_READ))
will return all response in first iteration and then blocks until timeout was reached (if I set it via socket_set_option) and return false with EAGAIN error. If timeout is not set it will return epmty string and no errors as expected, but before this block for couple of minutes.

In non-blocking:
Whole response was also successfully recieved after first socket_select return, and then this socket has no more returned by socket_select as ready for reading.

I've tested this on debian PHP 5.2.9-0.dotdeb.1 with Suhosin-Patch 0.9.7 and WinXP php 5.3.0 (binary from php.net) with some public socks and connect proxies and with SHHTunnel 4.3.0.0 for Win which has built in socks 4/5 proxy.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-09-07 14:16 UTC] sjoerd@php.net
Thank you for your report.

Socket_read only returns false when the remote end has closed the connection. It will not return false when the remote side has not closed the connection but does not send data anymore. This is expected behavior. Socket_read can not detect the "end of data", other than the other side closing the connection.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 19 01:01:28 2024 UTC