"system level connect()" is not further documented inside the php documentation so it is hard to find out more about error numbers.
someone suggest a more system-close way to find out more about error numbers here: http://www.askapache.com/php/fsockopen-socket.html (an interesting read about fsockopen anyway).
in my case i could debug to the fact that fsocketopen error number 16 was resulted in the inpossibility to resolve a hostname.
fsockopen
(PHP 4, PHP 5)
fsockopen — 인터넷이나 유닉스 도메인의 소켓 연결을 열어줍니다.
Description
인터넷 (TCP 또는 UDP를 사용하는AF_INET) 또는 유닉스(AF_UNIX)도메인에서 스트림 연결을 시작합니다. 이것은 인터넷 도메인이라는 것 때문에 TCP 소켓을 port 상에서 hostname 에 연결하는 것을 열어줍니다. hostname 은 이와 같은 경우에 완전히 증명이 된 도메인 네임이거나 IP 어드레스일 수 있습니다. UDP 연결에서는 프로토콜을 미리 정의해야 합니다 : udp://hostname . 유닉스 도메인에서는 hostname 이 소켓의 경로로 사용될 수 있는데 이 경우에 port 는 0 으로 설정되어야 합니다. 선택사항인 timeout 은 시스템 호출에 연결되는 것에 대한 시간초과가 몇 초안에 이루어지도록 설정할 수 있습니다.
fsockopen()은 다른 파일관련 함수(다음과 같은 fgets(), fgetss(), fputs(), fclose() 그리고 feof()) 와 사용할 수 있는 파일 포인터를 반환합니다.
호출에 실패하면 FALSE를 반환하고 임의항목인 errno 와 errstr 인수가 있다면 시스템 차원의 connect()호출 에서 발생한 실제의 시스템 차원의 에러를 측정하기 위해 설정될 수 있습니다. 반환되는 errno 가 0 이고 함수가 FALSE를 반환했다면 connect()호출 이전에 에러가 발생했다는 것을 알 수 있습니다. 이것은 소켓을 초기화하면서 발생한 문제일 가능성이 높습니다. 주의할 것은 errno 와 errstr 인수는 레러 passed by reference되어야 합니다.
환경에 따라 유닉스 도메인이나 선택사항인 연결 시간초과는 사용이 지원되지 않을 수도 있습니다.
소켓은 기본적으로 블로킹 모드(blocking mode)로 열려집니다. socket_set_blocking()을 사용해서 블로킹모드 해제상태(non-blocking mode) 로 전환할 수 있습니다..
Example#1 fsockopen() 예문
$fp = fsockopen ("www.php.net", 80, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)<br>\n";
} else {
fputs ($fp, "GET / HTTP/1.0\r\n\r\n");
while (!feof($fp)) {
echo fgets ($fp,128);
}
fclose ($fp);
}
Example#2 UDP 연결을 사용합니다
<?php
$fp = fsockopen("udp://127.0.0.1", 13, $errno, $errstr);
if (!$fp) {
echo "ERROR: $errno - $errstr<br>\n";
} else {
fwrite($fp,"\n");
echo fread($fp, 26);
fclose($fp);
}
?>
참조: pfsockopen(), socket_set_blocking(), socket_set_timeout(), fgets(), fgetss(), fputs(), fclose(), 그리고 feof()).Note: 시간초과 매개변수는 PHP 3.0.9 에 소개가 되었고 UDP 지원은 PHP 4에 추가되었습니다.
fsockopen
12-Oct-2008 05:26
09-Sep-2008 08:28
Notice using "tcp" insted of "http"
<?
fsockopen("tcp://example.net",80 , $errno, $errstr, 30);
?>
06-Sep-2008 09:00
My $0.02 on handling chunked transfer encoded output... Has rudimentary error handling.
<?php
//
// Example usage...
//
$server = '127.0.0.1';
$port = '80';
$uri = '/cgi-bin/random-cgi';
$content = 'Your post content...';
$post_results = httpPost($server,$port,$uri,$content);
if (!is_string($post_results)) {
die('uh oh, something went wrong');
} else {
die('Here are your results: ' . $post_results);
}
//
// Post provided content to an http server and optionally
// convert chunk encoded results. Returns false on errors,
// result of post on success. This example only handles http,
// not https.
//
function httpPost($ip=null,$port=80,$uri=null,$content=null) {
if (empty($ip)) { return false; }
if (!is_numeric($port)) { return false; }
if (empty($uri)) { return false; }
if (empty($content)) { return false; }
// generate headers in array.
$t = array();
$t[] = 'POST ' . $uri . ' HTTP/1.1';
$t[] = 'Content-Type: text/html';
$t[] = 'Host: ' . $ip . ':' . $port;
$t[] = 'Content-Length: ' . strlen($content);
$t[] = 'Connection: close';
$t = implode("\r\n",$t) . "\r\n\r\n" . $content;
//
// Open socket, provide error report vars and timeout of 10
// seconds.
//
$fp = @fsockopen($ip,$port,$errno,$errstr,10);
// If we don't have a stream resource, abort.
if (!(get_resource_type($fp) == 'stream')) { return false; }
//
// Send headers and content.
//
if (!fwrite($fp,$t)) {
fclose($fp);
return false;
}
//
// Read all of response into $rsp and close the socket.
//
$rsp = '';
while(!feof($fp)) { $rsp .= fgets($fp,8192); }
fclose($fp);
//
// Call parseHttpResponse() to return the results.
//
return parseHttpResponse($rsp);
}
//
// Accepts provided http content, checks for a valid http response,
// unchunks if needed, returns http content without headers on
// success, false on any errors.
//
function parseHttpResponse($content=null) {
if (empty($content)) { return false; }
// split into array, headers and content.
$hunks = explode("\r\n\r\n",trim($content));
if (!is_array($hunks) or count($hunks) < 2) {
return false;
}
$header = $hunks[count($hunks) - 2];
$body = $hunks[count($hunks) - 1];
$headers = explode("\n",$header);
unset($hunks);
unset($header);
if (!verifyHttpResponse($headers)) { return false; }
if (in_array('Transfer-Coding: chunked',$headers)) {
return trim(unchunkHttpResponse($body));
} else {
return trim($body);
}
}
//
// Validate http responses by checking header. Expects array of
// headers as argument. Returns boolean.
//
function validateHttpResponse($headers=null) {
if (!is_array($headers) or count($headers) < 1) { return false; }
switch(trim(strtolower($headers[0]))) {
case 'http/1.0 100 ok':
case 'http/1.0 200 ok':
case 'http/1.1 100 ok':
case 'http/1.1 200 ok':
return true;
break;
}
return false;
}
//
// Unchunk http content. Returns unchunked content on success,
// false on any errors... Borrows from code posted above by
// jbr at ya-right dot com.
//
function unchunkHttpResponse($str=null) {
if (!is_string($str) or strlen($str) < 1) { return false; }
$eol = "\r\n";
$add = strlen($eol);
$tmp = $str;
$str = '';
do {
$tmp = ltrim($tmp);
$pos = strpos($tmp, $eol);
if ($pos === false) { return false; }
$len = hexdec(substr($tmp,0,$pos));
if (!is_numeric($len) or $len < 0) { return false; }
$str .= substr($tmp, ($pos + $add), $len);
$tmp = substr($tmp, ($len + $pos + $add));
$check = trim($tmp);
} while(!empty($check));
unset($tmp);
return $str;
}
?>
18-Aug-2008 03:34
Sending multiple files with form(modification of sir_reality2001 at yahoo dot com's and Duukkis's scripts):
<?php
$boundary = "AaB03x";
$boundary2 = "BbC04y";
// Build the header
$header = "POST remoteurl HTTP/1.0\r\n";
$header .= "Host: remotehost\r\n";
$header .= "Content-Type: multipart/form-data; boundary=$boundary\r\n";
// attach post vars
foreach($_POST AS $index => $value){
$data .="--$boundary\r\n";
$data .= "Content-Disposition: form-data; name=\"".$index."\"\r\n";
$data .= "\r\n".$value."\r\n";
$data .="--$boundary\r\n";
}
// and attach the file
for ($i=0; $i<count($_FILES['userfile']['name']);$i++)
{
$data .= "--$boundary\r\n";
if ($_FILES['userfile']['name'][$i] != '')
{
$content_file = join("", file($_FILES['userfile']['tmp_name'][$i]));
$data.="Content-Disposition: file; name=\"userfile[$i]\"; filename=\"".$_FILES['userfile']['name'][$i]."\"\r\n";
$data .= "Content-Type: ".$_FILES['userfile']['type'][$i]."\r\n\r\n";
$data .= "".$content_file."\r\n";
$data .="--$boundary\r\n";
}
}
$data .="--$boundary--\r\n";
$header .= "Content-length: " . strlen($data) . "\r\n\r\n";
$fp = fsockopen($remote_server, 80);
?>
21-Jul-2008 05:32
When you try to POST/GET requests via HTTPS over SSL/TLS you should notice this:
<?php
// preconditions
$port = 80 | 443
$host = "www.example.com";
$method = "POST" | "GET";
$contenttype = "text/html" | "text/plain" | "text/xml" | ...;
$data = "<something>";
// script
if($port == 443)
$sslhost = "ssl://".$host;
else
$sslhost = $host;
$fp = fsockopen($sslhost, $port);
fputs($fp, "$method $path HTTP/1.1\r\n");
fputs($fp, "Host: $host\r\n");
fputs($fp, "Content-type: $contenttype\r\n");
fputs($fp, "Content-length: ".strlen($data)."\r\n");
fputs($fp, "Connection: close\r\n");
fputs($fp, "\r\n");
?>
The server usually does not understand the HTTP-header "Host: XXX" if you provide it with the trailing "ssl://" used by fsockopen(); If you do it anyway you probably get a HTTP 400 back as response. :-)
08-Mar-2008 07:15
An edit to my below function for extra headers support and a bit of debugging
( array("key" => "value") type)
<?php
if(!function_exists("download")){
function download($uri, $port = 80, $extra_headers = NULL){
if(!function_exists("stripos")){
function stripos($str, $needle, $offset=0){
return strpos(strtolower($str),strtolower($needle),$offset);
}/* endfunction stripos */
}/* endfunction exists stripos*/
if(!is_int($port))$port = 80;
if(!is_array($extra_headers))$extra_headers = array();
$uri = strtr( strval($uri), array("http://" => "", "https://" => "ssl://", "ssl://" => "ssl://", "\\" => "/", "//" => "/") );
if( ( $protocol = stripos($uri, "://") ) !== FALSE ){
if( ( $domain_pos = stripos($uri, "/", ($protocol + 3)) ) !== FALSE ){
$domain = substr($uri, 0, $domain_pos);
$file = substr($uri, $domain_pos);
}
else{
$domain = $uri;
$file = "/";
}
}
else{
if( ( $domain_pos = stripos($uri, "/") ) !== FALSE ){
$domain = substr($uri, 0, $domain_pos);
$file = substr($uri, $domain_pos);
}
else{
$domain = $uri;
$file = "/";
}
}
$fp = fsockopen($domain, $port, $errno, $errstr, 30);
if(!$fp){
return FALSE;
}
else{
$out = "GET " . $file . " HTTP/1.1\r\n";
$out .= "Host: " . $domain . "\r\n";
foreach( $extra_headers as $nm => $vl ){
$out .= strtr( strval($nm), array( "\r" => "", "\n" => "", ": " => "", ":" => "") ) . ": " . strtr( strval($vl), array( "\r" => "", "\n" => "", ": " => "", ":" => "") ) . "\r\n";
}
$out .= "Connection: Close\r\n\r\n";
$response = "";
fwrite($fp, $out);
while (!feof($fp)) {
$response .= fgets($fp, 128);
}
fclose($fp);
global $http_response_header;
$http_response_header = array();
if( stripos($response, "\r\n\r\n") !== FALSE ){
$hc = explode("\r\n\r\n", $response);
$headers = explode("\r\n", $hc[0]);
if(!is_array($headers))$headers = array();
foreach($headers as $key => $header){
$a = "";
$b = "";
if( stripos($header, ":") !== FALSE ){
list($a, $b) = explode(":", $header);
$http_response_header[trim($a)] = trim($b);
}
}
return end($hc);
}
else if( stripos($response, "\r\n") !== FALSE ){
$headers = explode("\r\n", $response);
if(!is_array($headers))$headers = array();
foreach($headers as $key => $header){
if( $key < ( count($headers) - 1 ) ){
$a = "";
$b = "";
if( stripos($header, ":") !== FALSE ){
list($a, $b) = explode(":", $header);
$http_response_header[trim($a)] = trim($b);
}
}
}
return end($headers);
}
else{
return $response;
}
}
}/*endfunction download*/
}/*endif no function download*/
?>
27-Dec-2007 09:12
<?php
// Check for new version
$current_version = explode('.', '1.0.00');
$minor_revision = (int) $current_version[2];
$errno = 0;
$errstr = $version_info = '';
if ($fsock = fsockopen("www.exanmple.eu", 80, $errno, $errstr, 30))
{
@fputs($fsock, "GET /ver.txt HTTP/1.1\r\n");
@fputs($fsock, "HOST: www.example.eu\r\n");
@fputs($fsock, "Connection: close\r\n\r\n");
$get_info = false;
while (!@feof($fsock))
{
if ($get_info)
{
$version_info .= @fread($fsock, 1024);
}
else
{
if (@fgets($fsock, 1024) == "\r\n")
{
$get_info = true;
}
}
}
@fclose($fsock);
$version_info = explode("\n", $version_info);
$latest_head_revision = (int) $version_info[0];
$latest_minor_revision = (int) $version_info[2];
$latest_version = (int) $version_info[0] . '.' . (int) $version_info[1] . '.' . (int) $version_info[2];
if ($latest_head_revision == 2 && $minor_revision == $latest_minor_revision)
{
$version_info = '<p style="color:green">OK</p>';
}
else
{
$version_info = '<p style="color:red">neaktualne';
$version_info .= '<br />'Latest_version_info' . $latest_version) . ' ' . sprintf(Current_version_info'. '1.0.00') . '</p>';
}
}
else
{
if ($errstr)
{
$version_info = '<p style="color:red">' . sprintf(Connect_socket_error) . '</p>';
}
else
{
$version_info = '<p>'Socket_functions_disabled'</p>';
}
}
$version_info .= '<p>'Mailing_list_subscribe_reminder'</p>';
echo $version_info;
?>
05-Dec-2007 02:59
Make a ping test with PHP
The problem with fsockopen is you have to known the destination port.
A real ping function could be :
<?php
function php_ping($url) {
$addr=parse_url($url);
$host=$addr['host'];
exec("ping -c 1 -w 1 $host", $list);
if (strpos($list[4],"1 received")>0) {
return true ;
}
return false;
}
?>
But if your router refuse the ping ... the result will be always false > you may test both (fsockopen and ping)
13-Nov-2007 05:13
After several days of trying to get telnet going from php 5.2, i've come up with http://www.dali.net.nz/Telnet.class.php.txt
based on the one found at http://cvs.adfinis.ch/cvs.php/phpStreamcast/telnet.class.php
example usage:
<?php
$telnet = new Telnet('telnethost.example.com');
$telnet->login('username', 'password');
echo $telnet->exec('ifconfig') . "\n";
echo $telnet->exec('ls -lh') . "\n";
$telnet->disconnect();
?>
04-Sep-2007 06:34
I don't know why it's not mentioned here (or am I missing something), but the DEFAULT stream timeout is set according to default_socket_timeout in your php.ini file. Took forever for me to dig that up....
23-Jul-2007 09:32
I was having trouble doing an https in fopen and with fsockopen where the address had ssl://. I was getting error code 114 in the log. After much research i found that there was some ssl conflict trouble with MySQL 5.0.20-5.0.33. It had some functions that were interfering with openssl that showed up in the php install.
http://bugs.mysql.com/bug.php?id=21930
http://bugs.mysql.com/bug.php?id=19289
17-Jul-2007 04:37
I ran into a problem where I needed to make an fsockopen() style connection from one specific ip address on a server with multiple ip aliases. Unfortunately fsockopen() does not allow the specification of a source address making it unsuitable. I could not find any other solutions elsewhere so here is mine for those with php 5.1.0 or greater.
<?php
// connect to the internet using the '192.168.0.100' IP
$opts = array('socket' => array('bindto' => '192.168.0.100:0'));
$context = stream_context_create($opts);
$fp = stream_socket_client("tcp://www.example.com:80", $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $context);
?>
Now $fp can be used like a resource handle returned by a vanilla fsockopen() call!
03-Jul-2007 06:58
easy get UIDL.
A code is better than the feof.
<?php
$fp = fsockopen($host, 110, $errno, $errstr, 5);
if ($fp > 0) {
fread($fp,1024);
fputs($fp, "USER $user\r\n");
fread($fp,1024);
fputs($fp, "PASS $pass\r\n");
fread($fp,1024);
fputs($fp, "UIDL\r\n");
fgets($fp,1024);
do {
$line = rtrim(fgets($fp, 1024));
if ($line == '.') break;
list(, $UIDL) = split(' ', $line, 2);
echo $UIDL;
} while ($line != '.');
fputs($fp, "QUIT\r\n");
}
fclose($fp);
?>
26-May-2007 07:29
To check if a Url is Online (with http and https)
Using @fgets to hide Warning when using SSL
(Bug: "Warning: function.fgets SSL: fatal protocol error", http://bugs.php.net/bug.php?id=23220)
<?php
function isOnline($url) {
if (!$url_info = parse_url($url)) {
return false;
}
switch ($url_info['scheme']) {
case 'https':
$scheme = 'ssl://';
$port = 443;
break;
case 'http':
default:
$scheme = '';
$port = 80;
}
$data = "";
$fid = @fsockopen($scheme . $url_info['host'], $port, $errno, $errstr, 30);
if ($fid) {
fputs($fid, 'HEAD ' . (isset($url_info['path'])? $url_info['path']: '/') . (isset($url_info['query'])? '?' . $url_info['query']: '') . " HTTP/1.0\r\n" .
"Connection: close\r\n" .
'Host: ' . $url_info['host'] . "\r\n\r\n");
while (!feof($fid)) {
$data .= @fgets($fid, 128);
}
fclose($fid);
return !empty($data);
} else {
return false;
}
}
?>
HTTP/1.1 requires that all clients support chunked transfer encoding. If you don't want to implement that and just want something simple, make HTTP/1.0 requests instead:
<?php
...
fputs("GET $path HTTP/1.0\r\n");
fputs("Host: $host\r\n");
...etc..
?>
01-Mar-2007 08:17
[EDIT by danbrown AT php DOT net: This note contains a big-fixed version of the user function decode_body(). Fix by (martjean77 at hot dot sapm dot mail dot com) [sic].]
Handling chunked data needs careful handling, because the data can also be compressed inside the chunked data, and chunked data can have many parts, so you need to watch for that. Here a simple example that uses one function decode_header(); to build the header into a key => value array, so it makes it easy to test for the content and transfer types inside the decode_body(); function!
<?php
function decode_header ( $str )
{
$part = preg_split ( "/\r?\n/", $str, -1, PREG_SPLIT_NO_EMPTY );
$out = array ();
for ( $h = 0; $h < sizeof ( $part ); $h++ )
{
if ( $h != 0 )
{
$pos = strpos ( $part[$h], ':' );
$k = strtolower ( str_replace ( ' ', '', substr ( $part[$h], 0, $pos ) ) );
$v = trim ( substr ( $part[$h], ( $pos + 1 ) ) );
}
else
{
$k = 'status';
$v = explode ( ' ', $part[$h] );
$v = $v[1];
}
if ( $k == 'set-cookie' )
{
$out['cookies'][] = $v;
}
else if ( $k == 'content-type' )
{
if ( ( $cs = strpos ( $v, ';' ) ) !== false )
{
$out[$k] = substr ( $v, 0, $cs );
}
else
{
$out[$k] = $v;
}
}
else
{
$out[$k] = $v;
}
}
return $out;
}
function decode_body ( $info, $str, $eol = "\r\n" )
{
$tmp = $str;
$add = strlen ( $eol );
$str = '';
if ( isset ( $info['transfer-encoding'] ) && $info['transfer-encoding'] == 'chunked' )
{
do
{
$tmp = ltrim ( $tmp );
$pos = strpos ( $tmp, $eol );
$len = hexdec ( substr ( $tmp, 0, $pos ) );
if ( isset ( $info['content-encoding'] ) )
{
$str .= gzinflate ( substr ( $tmp, ( $pos + $add + 10 ), $len ) );
}
else
{
$str .= substr ( $tmp, ( $pos + $add ), $len );
}
$tmp = substr ( $tmp, ( $len + $pos + $add ) );
$check = trim ( $tmp );
}
while ( ! empty ( $check ) );
}
else if ( isset ( $info['content-encoding'] ) )
{
$str = gzinflate ( substr ( $tmp, 10 ) );
}
else {
$str = $tmp;
}
return $str;
}
if ( ( $io = fsockopen( "www.yahoo.com", 80, $errno, $errstr, 5 ) ) !== false )
{
$send = "GET / HTTP/1.1\r\n";
$send .= "Host: www.yahoo.com\r\n";
$send .= "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2.1) Gecko/20021204\r\n";
$send .= "Referer: http://www.yahoo.com/\r\n";
$send .= "Accept: text/xml,application/xml,application/xhtml+xml,";
$send .= "text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,";
$send .= "image/jpeg,image/gif;q=0.2,text/css,*/*;q=0.1\r\n";
$send .= "Accept-Language: en-us, en;q=0.50\r\n";
$send .= "Accept-Encoding: gzip, deflate, compress;q=0.9\r\n";
$send .= "Connection: Close\r\n\r\n";
fputs ( $io, $send );
$send = '';
do
{
$send .= fgets ( $io, 4096 );
} while ( strpos ( $send, "\r\n\r\n" ) === false );
$info = decode_header ( $send );
$send = '';
while ( ! feof ( $io ) )
{
$send .= fread ( $io, 8192 );
}
fclose ( $io );
$send = decode_body ( $info, $send );
echo '<h3>Header Array</h3>';
echo '<pre>';
print_r ( $info );
echo '</pre>';
echo '<h3>Document Body</h3>';
echo $send;
}
?>
29-Jan-2007 07:52
This script checks specific ports so you need to have the correct port open on the server for this to work.
E.g if i have a windows domain controller and it is servering LDAP then the following would be used to check it is online:
<?php
chkServer("MyDC", "389");
?>
for a webserver:
<?php
chkServer("MyWebSvr", "80");
?>
etc etc
--------------------------------------------------------
<?php
// check if a server is up by connecting to a port
function chkServer($host, $port)
{
$hostip = @gethostbyname($host); // resloves IP from Hostname returns hostname on failure
if ($hostip == $host) // if the IP is not resloved
{
echo "Server is down or does not exist";
}
else
{
if (!$x = @fsockopen($hostip, $port, $errno, $errstr, 5)) // attempt to connect
{
echo "Server is down";
}
else
{
echo "Server is up";
if ($x)
{
@fclose($x); //close connection
}
}
}
}
?>
24-Jan-2007 03:01
The following function performs pop3 authentication. Returns NULL on error, or true/false to indicate username/password matching:
$address is the hostname of the server and $ssl is a boolean that indicates whether an SSL connection is requested.
<?php
function pop3authCheck($username, $password, $address, $ssl)
{
if ($ssl)
$uri="ssl://$address:995";
else
$uri="tcp://$address:110";
$fp=fsockopen($uri);
if (!$fp)
return(NULL);
$st=fgets($fp, 512);
if (substr($st, 0, 3)!="+OK")
{
fclose($fp);
return(NULL);
}
$st="USER $username\n";
if (fwrite($fp, $st)!=strlen($st))
{
fclose($fp);
return(NULL);
}
$st=fgets($fp, 512);
if (substr($st, 0, 3)!="+OK")
{
fclose($fp);
return(NULL);
}
$st="PASS $password\n";
if (fwrite($fp, $st)!=strlen($st))
{
fclose($fp);
return(NULL);
}
$st=fgets($fp, 512);
fclose($fp);
if (substr($st, 0, 3)=="+OK")
return(true);
else if (substr($st, 0, 4)=="+ERR")
return(false);
else
return(NULL);
}
?>
19-Dec-2006 07:20
here is my contribution for parsing chunked data.
please note: this function simply handles the RESPONSE, not the HEADERS, it would be your job to check the headers for 'Transfer-Encoding: chunked' field:
<?php
function parseChunked($response) {
$do = true;
$return = "";
$size = NULL;
while($do) {
// suppress warnings w/ @ if offset not in string (past end)
$pos = @strpos($response, "\r\n", 0);
if(!($pos === false) && $size === NULL) {
// we found CRLF, get len from hex
$size = hexdec(substr($response, 0, $pos));
// get the actual chunk-len, reset $response, $size
