Advertisement
vins31

PHP server-list YS protocol library

Dec 26th, 2011
125
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 13.96 KB | None | 0 0
  1. <?php
  2. class YS_protocol
  3. {
  4.     //---------- VAR -------------
  5.     var $buffer      = 0;
  6.     var $prevbuffer  = 0;
  7.     var $debug       = false;
  8.     var $errstr      = "";
  9.     var $fp          = false; //socket
  10.     var $isfsockopen = false;
  11.     var $maxRetry    = 3;
  12.     var $retry       = 0;
  13.     var $maxLook     = 5;
  14.     var $info        = "";//to get the stream time-out info
  15.     var $stop        = false;
  16.     var $version     = 20110207; //YSFS version
  17.     var $ip          = "";
  18.     var $maxpackets  = 31;
  19.    
  20.     var $missile  = 0;
  21.     var $weapon   = 0;
  22.     var $showUser = 0;
  23.     var $radar    = "";
  24.     var $extview  = "";
  25.     var $map      = "";
  26.     var $weather  = "0:0:0:0:0:0:0:0";
  27.     var $userlist = array();
  28.     var $i_users  = 0;
  29.     var $users    = -1; //to don't count phpBot
  30.     var $flying   = 0;
  31.    
  32.    
  33.  
  34.     var $got_map      = false;
  35.     var $got_radar    = false;
  36.     var $got_weather  = false;
  37.     var $got_userlist = false;
  38.    
  39.    
  40.     function YS_protocol($fsockopen=false)
  41.     {
  42.         $this->isfsockopen=$fsockopen;
  43.     }
  44.    
  45.     //---------- SET -------------
  46.    
  47.     function setDebug    ($deb)
  48.     {
  49.         $this->debug    = $deb;
  50.     }
  51.     function setMaxRetry ($nb)
  52.     {
  53.         $this->maxRetry = $nb;
  54.     }
  55.     function setVersion  ($ver)
  56.     {
  57.         $this->version  = $ver;
  58.     }
  59.     function setBuffer   ($buf)
  60.     {
  61.         $this->buffer   = $buf;
  62.     }
  63.    
  64.    
  65.     //---------- GET TYPE -------------
  66.    
  67.     function getIsLaggy()
  68.     {
  69.         return $this->stop;
  70.     }
  71.    
  72.     function getString ($i=0)
  73.     {
  74.         $string = "";
  75.         for ( $k=0 ; $k < strlen($this->buffer) ; $k++ )
  76.         {
  77.             $s = substr($this->buffer,$i+$k,1);
  78.             if (ord($s) == 0)
  79.                 break;
  80.             else
  81.             {
  82.                 $s       = unpack("a", $s);
  83.                 $string .= $s[1];
  84.             }
  85.         }  
  86.         return $string;
  87.     }
  88.  
  89.    
  90.     function getInt ($i=0)
  91.     {
  92.         $s = substr($this->buffer,$i,4);
  93.         if (strlen($s) < 4)
  94.         {
  95.             $this->log3( "<b>Warning:</b> the byte array in getInt is too short");
  96.             $this->stop=true;
  97.             return 0;
  98.         }
  99.         else
  100.         {  
  101.             $i = unpack("I", $s);
  102.             return $i[1];
  103.         }
  104.     }
  105.    
  106.     function getShort ($i=0)
  107.     {
  108.         $s = substr($this->buffer,$i,2);
  109.         if (strlen($s) < 2)
  110.         {
  111.             $this->log3( "<b>Warning:</b> the byte array in getShort is too short");
  112.             $this->stop=true;
  113.             return 0;
  114.         }
  115.         else
  116.         {  
  117.             $i = unpack("S", $s);
  118.             return $i[1];
  119.         }
  120.     }
  121.    
  122.     function getFloat ($i=0)
  123.     {
  124.         $s = substr($this->buffer,$i,4);
  125.         if (strlen($s) < 4)
  126.         {
  127.             $this->log3( "<b>Warning:</b> the byte array in getFloat is too short");
  128.             $this->stop=true;
  129.             return 0;
  130.         }
  131.         else
  132.         {  
  133.             $i = unpack("f", $s);
  134.             return $i[1];
  135.         }
  136.     }
  137.    
  138.     function ushortToBools ($u)
  139.     {
  140.         $bin = sprintf("%b", $u);
  141.         //echo $bin."<br>";
  142.         $a=array(0,0,0,0,0,0,0,0);
  143.         $j=0;
  144.         for($i=strlen($bin)-1; $i>=0;$i--)
  145.         {
  146.             $a[$j]=($bin[$i]==1 ? 1 : 0);
  147.             $j++;
  148.         }
  149.         return $a;
  150.     }
  151.    
  152.     //---------- GET FUNC -------------
  153.    
  154.     function packetDecode()
  155.     {
  156.         $i = 1;
  157.         while (($this->fp)&&($i < $this->maxpackets)&&(!$this->stop))
  158.         {
  159.             if ( ($this->got_map)&&($this->got_weather)&&($this->got_userlist)&&($this->kind()!=37) || (($i>8)&&($this->buffer==$this->prevbuffer)) )
  160.             {// we stop if we finished to read all the userlist or if we received twice the same packet
  161.                 if ($this->debug)
  162.                     echo "<b>STOP</b>";
  163.                 break; // we read everything we needed
  164.             }
  165.             if ($this->debug ==true)
  166.                 echo "<br><b>Looking at</b> ".$this->kind().", packet ".$i.".<br>";
  167.             $this->receive();
  168.             $i++;
  169.             switch ($this->kind())
  170.             {
  171.                 case 4:
  172.                     $this->got_map=true;
  173.                     $this->getMap();
  174.                     break;
  175.                    
  176.                 case 29:
  177.                     $this->getVer();
  178.                     break;
  179.                    
  180.                 case 31:
  181.                     $this->getMissile();
  182.                     break;
  183.                
  184.                 case 33:
  185.                     $this->got_weather = true;
  186.                     $this->getWeather();
  187.                     break;
  188.                    
  189.                 case 37:
  190.                     $this->got_userlist = true;
  191.                     $this->getUserList();
  192.                     break;
  193.                    
  194.                 case 39:
  195.                     $this->getWeapon();
  196.                     $this->YSsend (pack("I",33),4); //so that the server answers the weather packet
  197.                     $this->YSsend (pack("I",37),4);  //so that the server answers the user-list packet
  198.                     break;
  199.                    
  200.                 case 41:
  201.                     $this->getShowUsername();
  202.                     break;
  203.                    
  204.                 case 43:
  205.                     $this->getRadar();
  206.                     $this->got_radar = true;
  207.                     $this->YSsend($this->buffer);
  208.                     break;
  209.                    
  210.                 default:
  211.                     if ($this->debug)
  212.                         print "<br>nothing.<br>";
  213.                     break;
  214.  
  215.             }
  216.            
  217.         }
  218.     }
  219.    
  220.    
  221.     function getShowUsername()
  222.     {
  223.         if (!$this->stop)
  224.         {
  225.             $show = $this->getInt (4);
  226.             if ($this->debug)
  227.                 echo "show ".$show;
  228.             $this->showUser =  $show; //show username within $show, always = 1, never=2
  229.         }
  230.  
  231.     }
  232.  
  233.     function getRadar()
  234.     {
  235.         if (!$this->stop)
  236.         {
  237.             $radar = $this->getString (8);
  238.             if ($this->debug)
  239.                 echo "radar ".$radar;
  240.             if (!$this->got_map)               
  241.                 $this->radar = $radar;
  242.             else
  243.                 $this->extview = $radar;
  244.         }
  245.  
  246.     }
  247.     function getMap ()
  248.     {
  249.         if (!$this->stop)
  250.         {
  251.             $this->map = $this->getString (4);
  252.         }
  253.  
  254.     }
  255.     function getMissile ()
  256.     {
  257.         if (!$this->stop)
  258.         {
  259.             $this->missile =  $this->getInt (4);
  260.         }
  261.     }
  262.     function getWeapon ()
  263.     {
  264.         if (!$this->stop)
  265.         {
  266.             $this->weapon =  $this->getInt (4);
  267.         }
  268.  
  269.     }
  270.     function getWeather ()
  271.     {
  272.         if (!$this->stop)
  273.         {
  274.             //$this->lookfor (33);
  275.             $opt = $this->ushortToBools ($this->getShort(8));
  276.             //print_r ($opt);
  277.             $this->weather =  $this->getInt(4).":".$opt[2].":".$opt[4].":".$opt[6].":".$this->getFloat(12).":".$this->getFloat(20).":".$this->getFloat(16).":".$this->getFloat(24);
  278.         }
  279.  
  280.     }
  281.     function getUserList ()
  282.     {
  283.         if (!$this->stop)
  284.         {
  285.            
  286.             $b[0] = $this->getShort  (4);//2= server //1 flying //not flying //3=server flying
  287.             $b[1] = $this->getShort  (6);// iff
  288.             $b[2] = $this->getInt    (8);// id
  289.             $b[3] = $this->getString (16);// user
  290.             $this->userlist[$this->i_users]= $b;
  291.                    
  292.             if ($b[0] != 2)
  293.             {
  294.                 $this->users  += 1;
  295.                 if ($b[0]==3)
  296.                     $b[0]=1;
  297.                 $this->flying += $b[0];
  298.             }
  299.             $this->i_users +=1;
  300.         }
  301.  
  302.     }
  303.     function getVersion ()
  304.     {
  305.         return $this->getInt(4);
  306.     }
  307.    
  308.     function getVer()
  309.     {
  310.         if (!$this->stop)
  311.         {
  312.             return $this->version;
  313.         }
  314.     }
  315.    
  316.     //---------- Is? -------------
  317.     function kind ()
  318.     {
  319.         if (!$this->stop)
  320.         {
  321.             if ( strlen($this->buffer) >=4 )
  322.             {
  323.                 $k = unpack("I",$this->buffer);
  324.                 return $k[1];
  325.             }
  326.             else
  327.                 return 0;
  328.         }
  329.         else
  330.             return 0;
  331.     }
  332.    
  333.  
  334.     function isVersion    () { return ($this->kind() == 29 ? true : false); }
  335.     function isWeather    () { return ($this->kind() == 33 ? true : false); }  
  336.    
  337.    
  338.     //---------- Debug -------------
  339.     function log3 ($s,$file="errors")
  340.     {
  341.         date_default_timezone_set('UTC');
  342.         $today=date("Y_m_d");
  343.         $file.=$today;
  344.         $f=fopen("log/".$file.".txt","a+");
  345.         fwrite($f,date("r")." ".$this->ip."   ".$s."<br>\r\n");
  346.         fclose($f);
  347.     }
  348.  
  349.     function printBuffer()
  350.     {
  351.         echo time()." ".$this->ip."<br>";
  352.         echo'<br><font face="Courier New, Courier, mono">';
  353.         for ( $k=0 ; $k < strlen($this->buffer) ; $k++)
  354.         {
  355.             printf ("%02X\n", ord(substr($this->buffer,$k,1)));
  356.             echo    " ";
  357.         }
  358.         echo "</font><br>";
  359.     }
  360.    
  361.     function printBuffer2 ($buffer)
  362.     {
  363.         echo time()." ".$this->ip."<br>";
  364.         echo'<br><font face="Courier New, Courier, mono">';
  365.         for ($k=0;$k<strlen($buffer);$k++)
  366.         {
  367.             printf ("%02X\n", ord(substr($buffer,$k,1)));
  368.             echo    " ";
  369.         }
  370.         echo "</font><br>";
  371.     }
  372.    
  373.     function printString()
  374.     {
  375.         echo '<br><font face="Courier New, Courier, mono">';
  376.         for ($k=0;$k<strlen($this->buffer);$k++)
  377.         {
  378.             printf ("%'.2s\n", substr($this->buffer,$k,1));
  379.             echo    " ";
  380.         }
  381.         echo "</font><br>";
  382.     }
  383.    
  384.     function printString2 ($buffer)
  385.     {
  386.         echo '<br><font face="Courier New, Courier, mono">';
  387.         for ($k=0;$k<strlen($buffer);$k++)
  388.         {
  389.             printf ("%'.2s\n", substr($buffer,$k,1));
  390.             echo    " ";
  391.         }
  392.         echo "</font><br>";
  393.     }
  394.    
  395.     //---------- Primary functions -------------
  396.     function YSdisconnect ()
  397.     {
  398.         if ($this->fp)
  399.         {
  400.             if ($this->isfsockopen)
  401.                 fclose($this->fp);
  402.             else
  403.                 socket_close($this->fp);
  404.         }
  405.         if ($this->debug)
  406.             echo "Disconnected<br>";
  407.     }
  408.    
  409.     function YSsend($buffer, $size=0)
  410.     {
  411.         if ($size==0)
  412.             $size=strlen($buffer);
  413.         if ($this->debug ==true)
  414.         {
  415.             echo "<br>Send:<br> (size ".$size."";  
  416.             $this->printBuffer2(pack("I",$size).$buffer);
  417.             $this->printString2(pack("I",$size).$buffer);
  418.         }
  419.         if ($this->isfsockopen)
  420.             fwrite($this->fp, pack("I",$size).$buffer);
  421.         else
  422.             socket_write($this->fp, pack("I",$size).$buffer);
  423.     }
  424.    
  425.     function receive()
  426.     {
  427.         if ( ($this->fp)&&(!$this->stop) )
  428.         {
  429.             if ($this->isfsockopen)
  430.             {
  431.                 $buffer = @fgets($this->fp,5);// +1 -> PHP flaw??
  432.                 $this->info   = stream_get_meta_data($this->fp);
  433.                 if ($this->info['timed_out'])
  434.                 {
  435.                     $this->stop=true;
  436.                     //$this->log3 ("lag");
  437.                     if ($this->debug ==true)
  438.                     {
  439.                         echo "LAGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ".time()."<br>";
  440.                     }
  441.                 }
  442.             }
  443.             else
  444.                 $buffer = @socket_read($this->fp,4);
  445.                
  446.             $size   = @unpack("I",$buffer);
  447.             if ($this->debug ==true)
  448.             {
  449.                 echo "size: ".$size;
  450.             }
  451.             if ($this->isfsockopen)
  452.             {
  453.                 $this->prevbuffer = $this->buffer;
  454.                 $this->buffer = @fgets($this->fp,$size[1]+1);// +1
  455.                 $this->info   = stream_get_meta_data($this->fp);
  456.                 if ($this->info['timed_out'])
  457.                 {
  458.                     $this->stop=true;
  459.                     //$this->log3 ("lag2");
  460.                     if ($this->debug ==true)
  461.                     {
  462.                         echo "LAGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG2 ".time()."<br>";
  463.                     }
  464.                 }
  465.             }
  466.             else
  467.                 $this->buffer = @socket_read($this->fp,$size[1]);
  468.                
  469.             while ( strlen($this->buffer)<$size[1] )
  470.             {
  471.                 if ($this->isfsockopen)
  472.                     $this->buffer .= @fgets($this->fp,$size[1]+1-strlen($this->buffer));
  473.                 else
  474.                     $this->buffer .= @socket_read($this->fp,$size[1]-strlen($this->buffer));
  475.             }
  476.             if ($this->debug)
  477.             {
  478.                 echo "<br>Receive:<br>";
  479.                 $this->printBuffer ();
  480.                 $this->printString ();
  481.             }
  482.         }
  483.         else
  484.         {
  485.             //$this->YSdisconnect ();
  486.             $this->stop=true;
  487.         }
  488.     }
  489.    
  490.    
  491.      function YSconnect($ip="127.0.0.1", $port=7915, $timeout=1)
  492.      {
  493.         $this->ip = $ip;
  494.         $this->log3("connect: ".$ip.":".$port." version: ".$this->version, "pr_");
  495.         if ($this->debug ==true)
  496.             {
  497.                 echo "<br>connect: ".$ip.":".$port." version: ".$this->version."<br>";
  498.             }
  499.         if ($this->debug ==true)
  500.             {
  501.                 echo "Start ".time()."<br>";
  502.             }
  503.         if ($this->retry > $this->maxRetry)
  504.         {
  505.             if ($this->debug ==true)
  506.             {
  507.                 echo "New attempt ".time()."<br>";
  508.             }
  509.             return "Failed";//failed to connected after x attempts
  510.         }
  511.         $version=pack("I",intval($this->version));
  512.         if ($this->isfsockopen)
  513.             $this->fp = @fsockopen($ip, $port, $errno, $errstr, $timeout);
  514.         else
  515.             $this->fp = $this->msConnectSocket($ip, $port, $timeout);
  516.         if ($this->fp==false)
  517.         {
  518.             return "Offline";//offline
  519.         }
  520.         elseif($this->fp)
  521.         {  
  522.             if ($this->debug ==true)
  523.             {
  524.                 echo $ip." login ".time()."<br>";
  525.             }
  526.             if ($this->isfsockopen)
  527.                 stream_set_timeout($this->fp, 2);//Maximum delay accepted
  528.             $this->YSsend("\x01\x00\x00\x00PHP bot\00\00\00\x00\x00\x00\x00\x00\x00".$version,24);
  529.             if ($this->debug ==true)
  530.             {
  531.                 echo "login2 ".time()."<br>";
  532.             }
  533.             $this->receive();
  534.             if ($this->debug ==true)
  535.             {
  536.                 echo "login3 ".time()."<br>";
  537.             }
  538.             if ($this->isVersion ())
  539.             {
  540.                 $oldversion    = $this->version;
  541.                 $this->version = $this->getVersion();
  542.                 if ($this->version!=$oldversion)
  543.                 {
  544.                     if ($this->debug==true)
  545.                         echo "Retry with version ".$this->version."<br>";
  546.                     $this->retry+=1;
  547.                     $this->YSconnect($ip,$port,$timeout);
  548.                 }
  549.             }
  550.             else
  551.             {
  552.                 $this->receive();
  553.                 if ($this->debug ==true)
  554.                 {
  555.                     echo "login3_after_failed_attemp ".time()."<br>";
  556.                 }
  557.                 if ($this->isVersion ())
  558.                 {
  559.                     $oldversion    = $this->version;
  560.                     $this->version = $this->getVersion();
  561.                     if ($this->version!=$oldversion)
  562.                     {
  563.                         if ($this->debug==true)
  564.                             echo "Retry with version ".$this->version."<br>";
  565.                         $this->retry+=1;
  566.                         $this->YSconnect($ip,$port,$timeout);
  567.                     }
  568.                 }
  569.                 else
  570.                 {
  571.                     if ($this->debug ==true)
  572.                     {
  573.                         echo "expected sth else".time()."<br>";
  574.                     }
  575.                     return "Offline";
  576.                 }
  577.  
  578.             }
  579.             if ($this->stop)
  580.                 return "Laggy";
  581.             if ($this->buffer=="")
  582.             {
  583.                 //Server locked
  584.                 $this->YSdisconnect();
  585.                 return "Locked";
  586.             }
  587.             return "Online";
  588.         }
  589.     }
  590.    
  591.     // To replace fsockopen()
  592.     function msConnectSocket($remote, $port, $timeout = 1) {
  593.         # this works whether $remote is a hostname or IP
  594.        $ip = "";
  595.         if( !preg_match('/^\d+\.\d+\.\d+\.\d+$/', $remote) ) {
  596.             $ip =gethostbyname($remote);
  597.             if ($ip == $remote) {
  598.                 $this->errstr = "Error Connecting Socket: Unknown host";
  599. //              echo $errstr;
  600.                 return false;
  601.             }
  602.         } else $ip = $remote;
  603.  
  604.         if (!($_SOCK = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP))) {
  605.             $this->errstr = "Error Creating Socket: ".socket_strerror(socket_last_error());
  606. //          echo $errstr;
  607.             return false;
  608.         }
  609.  
  610.         socket_set_nonblock($_SOCK);//   DEPENDENT ON YOUR CONFIGURATION  UNCOMMENT WITH 000WEBHOST
  611.  
  612.         $error = NULL;
  613.         $attempts = 0;
  614.         $timeout *= 1000;  // adjust because we sleeping in 1 millisecond increments
  615.         $connected= false;
  616.         while (!($connected = @socket_connect($_SOCK, $remote, $port+0)) && $attempts++ < $timeout) {
  617.             $error = socket_last_error();
  618.             if ($error != SOCKET_EINPROGRESS && $error != SOCKET_EALREADY) {
  619.                 $this->errstr = "Error Connecting Socket: ".socket_strerror($error);
  620.                 socket_close($_SOCK);
  621. //              echo $errstr;
  622.                 return false;
  623.             }
  624.             usleep(1000);
  625.         }
  626.  
  627.         if (!$connected) {
  628.             $this->errstr = "Error Connecting Socket: Connect Timed Out After $timeout seconds. ".socket_strerror(socket_last_error());
  629. //          echo $errstr;
  630.             socket_close($_SOCK);
  631.             return false;
  632.         }
  633.        
  634.         socket_set_block($_SOCK);
  635. //      echo "connected";
  636.         return $_SOCK;    
  637.     }
  638. }
  639.  
  640. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement