<?php
##
## [PHP/bandwidth] check network interface bandwidth
##
## [author]
##  - 'Chilbong Kim' san2(at)linuxchannel.net
##
## [changes]
##  - 2006.05.12 (ver 0.3.1p2): bug fixed
##  - 2003.07.11 (ver 0.3.1p1): is_array() checked
##  - 2003.04.23 (ver 0.3.1)  : bug fix(for FreeBSD)
##  - 2002.10.15 (ver 0.3.0)  : php class modified
##  - 2002.09.05 (ver 0.2.0)  : support FreeBSD 
##  - 2002.09.04 (ver 0.1.0)  : support shared memory
##
## [download]
##  - http://ftp.linuxchannel.net/devel/php_bandwidth/
##
## [reference]
##   - http://www.kernel.org/pub/software/web/bwbar/
##
## [example]
##
##  $bw = new bandwidth();
##
##  echo  <<<_EOF_
##  receive  : $bw->R,
##  transmit : $bw->T at intervals of $bw->usec seconds<BR>\n
##  _EOF_;
##

class bandwidth
{
  var 
$R$T$usec;
  var 
$BW = array();

  
## 3 arguments :
  ##    $bps => 0(MBPS,default), 1(MBytes/s) 
  ##    $iface => check interface(default to 'eth0')
  ##    $file => create tmp php file(default to '/tmp/bandwidth.cfg.php')
  ##
  ## return values :
  ##    $this->R : Received bandwidth
  ##    $this->T : Transmited bandwidth
  ##    $this->usec : time(seconds)
  ##    $this->BW = array('R'=>$this->R,'T'=>$this->T,'usec'=>$this->usec);
  ##
  
function bandwidth($bps=0$iface='eth0'$file='/tmp/bandwidth.cfg.php')
  {
    if(!
$os $this->support_os())
    {
        
$this->$this->'not support this os('.PHP_OS.')';
        return 
0;
    }

    
$func 'get_netstat_'.$os;
    if(!
$stat $this->$func($iface))
    {
        
$this->$this->'can\'t open iface('.$iface.')'.
            
' or can\'t running netstat command';
        return 
0;
    }

    if(
function_exists('sem_get') && function_exists('shm_attach'))
    {
        
$_BW $this->get_shm();
        
$use_shm 1;
    }
    else if(
file_exists($file)) @include_once $file;

    
$time explode(' ',microtime());
    
$usec sprintf('%.6f',$time[0] + $time[1]);

    
## change values, and to write
    ##
    
if($use_shm)
        
$this->get_shm(array('usec'=>$usec,'R'=>$stat['R_bytes'],'T'=>$stat['T_bytes']));
    else {
        
$content "<?php\n\$_BW['usec'] = $usec;\n\$_BW['R'] = $stat[R_bytes];\n".
            
"\$_BW['T'] = $stat[T_bytes];\n?>";
        
$this->put_file($file,$content);
    }

    if(
$_BW && is_array($_BW))
    {
        
$usec -= $_BW['usec'] ;
        
$this->usec number_format($usec,2);

        
$stat['R_bytes'] -= $_BW['R'];
        
$stat['T_bytes'] -= $_BW['T'];
        
$this->$this->get_unit($stat['R_bytes']/$usec,$bps);
        
$this->$this->get_unit($stat['T_bytes']/$usec,$bps);

        
$this->BW = array('R'=>$this->R,'T'=>$this->T,'usec'=>$this->usec);
    }
  }

  function 
support_os()
  {
    
$os strtolower(PHP_OS);
    if(
preg_match('/linux|freebsd/i',$os)) return $os;
  }

  function 
get_netstat_linux($iface 'eth0')
  {
    if(!
$netstat = @file('/proc/net/dev')) return 0;

    for(
$i=3$i<count($netstat); $i++) {
        
$tmp explode(':',$netstat[$i]);
        
$stat['iface'] = trim($tmp[0]);

        list(
$stat['R_bytes'],$stat['R_packets'],$stat['R_errs'],$stat['R_drop'],
            
$null,$null,$null,$null,$stat['T_bytes'],$stat['T_packets'],
            
$stat['T_errs'],$stat['T_drop'],$stat['T_colls']
        ) = 
preg_split('/\s+/',trim($tmp[1]));

        if(
$iface == $stat['iface']) break;
    }

    return 
$stat;
  }

  function 
get_netstat_freebsd($iface 'fxp0')
  {
    
$iface str_replace('eth','fxp',$iface); // force to
    
if(!$netstat = @exec("netstat -b -I $iface | grep Link")) return 0;

    list(
$name,$mtu,$link,$hw,$stat['R_packets'],$stat['R_errs'],$stat['R_bytes'],
        
$stat['T_packets'],$stat['T_errs'],$stat['T_bytes'],$stat['T_colls']
    ) = 
preg_split('/\s+/',$netstat);

    return 
$stat;
  }

  
## $size format 'bytes'
  ## $bps(0) => MBPS(MBits/sec)
  ## $bps(1) => MBytes/sec
  ##
  
function get_unit($size$bps=0)
  {
    if(
$bps$unit ' MBytes/s';
    else { 
$size *= 8$unit ' MBPS'; }

    return 
number_format($size/1048576,2).$unit;
  }

  function 
put_diofile($file$content)
  {
    if(
$fp = @dio_open($file,O_WRONLY+O_CREAT,0600)) {
        
$bytes dio_write($fp,$content);
        
dio_close($fp);
    }
    
//return $bytes;
  
}

  function 
put_file($file$content)
  {
    if(
function_exists(dio_open)) return $this->put_diofile($file,$content);

    if(
$fp = @fopen($file,'w')) {
        
fputs($fp$content);
        
fclose($fp);
    }
  }

  
## http://www.php.net/manual/en/ref.sem.php
  ## http://www.php.net/manual/en/function.shm-attach.php
  ##
  
function get_shm($array=0)
  {
    
$_shm['size'] = 512// about 260 ~ bytes
    
$_shm['key'] = 0x7068705f;
    
$_shm['max'] = 10;

    if(!
$id['sem'] = sem_get($_shm['key'],$_shm['max'])) return 0;
    if(!@
sem_acquire($id['sem']))
    { @
sem_remove($id['sem']); return 0; }

    if(!
$id['shm'] = shm_attach($_shm['key'],$_shm['size']))
    { @
sem_remove($id['sem']); return 0; }

    
$return = @shm_get_var($id['shm'],$_shm['key']);
    if(
$array) {
        if(!
shm_put_var($id['shm'],$_shm['key'],$array))
        { @
sem_remove($id['sem']); @shm_remove($id['shm']); return 0; }
    }

    @
shm_detach($id['shm']);
    @
sem_release($id['sem']);

    return 
$return;
  }
// end of this class

/***
## example
##

$bw = new bandwidth();

echo  <<<_EOF_
receive  : $bw->R,
transmit : $bw->T at intervals of last $bw->usec seconds<HR>\n
_EOF_;

var_dump($bw->BW);

***/
?>