Jump to content

Sockets, UDP, Linux....Wth?!


RyanEricW

Recommended Posts

Basically the problem lies within connecting or writing using sockets. Here's the weird thing, this works perfectly on windows based server, but when I use it on a linux server, it's like linux doesn't even want to work with UDP stuff.

I'm very frusted and been pulling hairs out for 5 hours now...

Hopefully someone can help.

 

This connects to a Half-Life 2 server and pulls data like (server name, max players, current players, etc).

 

index.php

<?
require("CServerInfo.php");

$sinfo = array();
$sinfo = $ServerInfo->getInfo("66.55.154.167","27015");

?>

 

CServerInfo.php

<?php
if(!isset($_SESSION)) // We are using AJAX so need a new session, as we bypass some stuff before 
	session_start();

define('INFO_RESPONSE_HL1',0x6D); 
    define('CHALLENGE_RESPONSE',0x41); 
    include 'hexdump.php';
    
class CServerInfo
{
	var $raw;
	function getInfo($address,$port)
	{
		if (isset($_SESSION['getInfo.' . $address . '.' . $port]) && is_array($_SESSION['getInfo.' . $address . '.' . $port])) 
		{
			return $_SESSION['getInfo.' . $address . '.' . $port];
		}

		$ret = array();
		$s = fsockopen("udp://".$address,$port,$errno,$errstring,1);
		if (!$s) echo "$errstring ($errno)<br />\n";
    
		stream_set_timeout($s,1);
		if(!fwrite($s,"\xFF\xFF\xFF\xFF\x54Source Engine Query",39))
		{
			echo "Error Writing Data. $errstring ($errno)";
		}
		$packet = fread($s,1024);
		echo "Packet: $packet";
		if(empty($packet))
		{
			$_SESSION['getInfo.' . $address . '.' . $port] = $this->getInfoProxy($address, $port);
			return $this->getInfoProxy($address, $port);
		}

		$parr = explode("\x00",substr($packet,6));
		if(!isset($packet[4])) {
			$_SESSION['getInfo.' . $address . '.' . $port] = array();
			return $_SESSION['getInfo.' . $address . '.' . $port];
		}
		if (ord($packet[4]) == INFO_RESPONSE_HL1)
		{	//HL1 Response
			$packet = substr($packet,strpos($packet,"\x00")+1);

			$parr = explode("\x00",$packet);
			$ret['hostname'] = $parr[0];
			$ret['map'] = $parr[1];
			$ret['gamename'] = $parr[2];
			$ret['gamedesc'] = $parr[3];
			$packet = substr($packet,strlen($ret['hostname'])+1+strlen($ret['map'])+1+strlen($ret['gamename'])+1+strlen($ret['gamedesc'])+1);
			$ret['numplayers'] = ord($packet[0]);
			$ret['maxplayers'] = ord($packet[1]);
			//$version = ord($packet[2]);
			$ret['dedicated'] = $packet[3];
			$ret['os'] = $packet[4];
			$ret['password'] = ord($packet[5]);

			if (ord($packet[6]))
			{	//Skip mod info
				$packet = substr($packet,strpos($packet,"\x00")+1);
				$packet = substr($packet,strpos($packet,"\x00")+3);
			}
			else
			{
				$packet = substr($packet,6);
			}
			$ret['secure'] = ord($packet[0]);
			$ret['botcount'] = ord($packet[1]);
		}
		else
		{	//HL2 Response
			$ret['hostname'] = $parr[0];	
			$ret['map'] = $parr[1];
			$ret['gamename'] = $parr[2];
			$ret['gamedesc'] = $parr[3];
			$packet = substr($packet,6+strlen($ret['hostname'])+1+strlen($ret['map'])+1+strlen($ret['gamename'])+1+strlen($ret['gamedesc'])+1+2);
			$ret['numplayers'] = ord($packet[0]);
			$ret['maxplayers'] = ord($packet[1]);
			$ret['botcount'] = ord($packet[2]);
			$ret['dedicated'] = ord($packet[3]);
			$ret['os'] = $packet[4];
			$ret['password'] = ord($packet[5]);
			$ret['secure'] = $packet[6];
		}
		$_SESSION['getInfo.' . $address . '.' . $port] = $ret;
		return $ret;				
	}

	function getPlayers($address,$port)
	{
		set_magic_quotes_runtime(0);
		$ret = array();
		$s = fsockopen("udp://".$address,$port,$errno,$errstring,1);

		stream_set_timeout($s,1); // 1 second timeout on read/write operations
		fwrite($s,"\xFF\xFF\xFF\xFF\x57"); //Get challenge #	
		$packet = fread($s,1024);
		$chalId = $this->getChallenge($packet);
		fwrite($s,"\xFF\xFF\xFF\xFF\x55".$chalId);
		$packet = fread($s,2048);	
		if(empty($packet))
		{
			return $this->getPlayersProxy($address, $port);
		}		
		$packet = substr($packet,5);
		$nump = ord($packet[0]);
		$packet = substr($packet,1);
		$this->raw = $packet;		

		for ($i=0;$i<$nump;$i++)
		{
			$temp = array();

			$temp['index']	= 	$this->_getbyte();
			$temp['name']=  $this->_getnullstr();
			$temp['kills']= $this->_getlong();
			$temp['time']=  SecondsToString((int)$this->_getfloat(),true);

			if(!empty($temp['name']))
				array_push($ret,$temp);
		}	

		array_qsort($ret, 'kills', SORT_DESC);
		return $ret;
	}

	function getChallenge($packet)
	{
		if(isset($packet[4]) && ord($packet[4]) == CHALLENGE_RESPONSE)
		{
			return substr($packet,5);
		}
		return "\xFF\xFF\xFF\xFF";
	}


	/* 
		Proxy functions are used when there is a problem with blocked ports,
	   	or firewalls like with some webhosts.
	*/
	function getInfoProxy($address,$port)
	{
		if(!(isset($address) && isset($port)))
			return false;

		$ret = array();
		$info = @file_get_contents(SERVER_QUERY . "?ip=" . $address . "&port=" .$port."&type=info");
		if(strstr($info, "Page not found"))
			return false;
		if($info)
		{
			$inf = explode("\t", $info);
			$ret['hostname'] = $inf[0];
			$ret['numplayers'] = $inf[1];
			$ret['maxplayers'] = $inf[2];
			$ret['map'] = $inf[3];
			$_SESSION['getInfo.' . $address . '.' . $port] = $ret;
			return $ret;
		}
		else
			return false;				
	}

	function getPlayersProxy($address,$port)
	{
		if(!(isset($address) && isset($port)))
			return false;
		$ret = array();
		$players = @file_get_contents(SERVER_QUERY . "?ip=" . $address . "&port=" .$port."&type=players");
		if(strstr($players, "Page not found"))
			return false;
		if($players)
		{
			$plr = explode("\n", $players);
			foreach($plr AS $player)
			{
				$items = explode("\t", $player);
				if(!isset($items[1])) {
					continue;
				}
				$row = array();
				$row['index'] = $items[0];
				$row['name'] = $items[1];
				$row['kills'] = $items[2];
				$row['time'] = $items[3];
				array_push($ret, $row);
			}
			return $ret;
		}
		else 
			return false;
	}

function _getnullstr() 
{
	if (empty($this->raw)) 
		return '';
	$end = strpos($this->raw, "\0");
	$str = substr($this->raw, 0, $end);
	$this->raw = substr($this->raw, $end+1);
	return $str;
}

function _getchar() 
{
	return sprintf("%c", $this->_getbyte());
}


function _getbyte() 
{
	$byte = substr($this->raw, 0, 1);
	$this->raw = substr($this->raw, 1);
	return ord($byte);
}

function _getshort() 
{
	$lo = $this->_getbyte();
	$hi = $this->_getbyte();
	$short = ($hi <<  | $lo;
	return $short;
}

function _getlong() 
{
	$lo = $this->_getshort();
	$hi = $this->_getshort();
	$long = ($hi << 16) | $lo;
	return $long;
}

function _getfloat() 
{
	$f = @unpack("f1float", $this->raw);
	$this->raw = substr($this->raw, 4);
	return $f['float'];
}	
}
$ServerInfo = new CServerInfo();		
?>

hexdump.php

<?php
	function hexdump ($data, $htmloutput = true, $uppercase = false, $return = false)
	{
	    // Init
	    $hexi   = '';
	    $ascii  = '';
	    $dump   = ($htmloutput === true) ? '<pre>' : '';
	    $offset = 0;
	    $len    = strlen($data);

	    // Upper or lower case hexidecimal
	    $x = ($uppercase === false) ? 'x' : 'X';

	    // Iterate string
	    for ($i = $j = 0; $i < $len; $i++)
	    {
	        // Convert to hexidecimal
	        $hexi .= sprintf("%02$x ", ord($data[$i]));

	        // Replace non-viewable bytes with '.'
	        if (ord($data[$i]) >= 32) {
	            $ascii .= ($htmloutput === true) ?
	                            htmlentities($data[$i]) :
	                            $data[$i];
	        } else {
	            $ascii .= '.';
	        }

	        // Add extra column spacing
	        if ($j === 7) {
	            $hexi  .= ' ';
	            $ascii .= ' ';
	        }

	        // Add row
	        if (++$j === 16 || $i === $len - 1) {
	            // Join the hexi / ascii output
	            $dump .= sprintf("%04$x  %-49s  %s", $offset, $hexi, $ascii);
	            
	            // Reset vars
	            $hexi   = $ascii = '';
	            $offset += 16;
	            $j      = 0;
	            
	            // Add newline            
	            if ($i !== $len - 1) {
	                $dump .= "\n";
	            }
	        }
	    }

	    // Finish dump
	    $dump .= $htmloutput === true ?
	                '</pre>' :
	                '';
	    $dump .= "\n";

	    // Output method
	    if ($return === false) {
	        echo $dump;
	    } else {
	        return $dump;
	    }
	}
?>

Link to comment
Share on other sites

I installed the script from where I got the includes from and they said:

 

Notice: fwrite() [function.fwrite]: send of 25 bytes failed with errno=1 Operation not permitted in /home/convictg/public_html/phgstats/classes/hl.class.php on line 78

 

Notice: fwrite() [function.fwrite]: send of 5 bytes failed with errno=1 Operation not permitted in /home/convictg/public_html/phgstats/classes/hl.class.php on line 59

 

Notice: fwrite() [function.fwrite]: send of 5 bytes failed with errno=1 Operation not permitted in /home/convictg/public_html/phgstats/classes/hl.class.php on line 100

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.