Exemplo n.º 1
0
 /**
  * Process the response
  *
  * @return array
  * @throws \GameQ\Exception\Protocol
  */
 public function processResponse()
 {
     // Will hold the packets after sorting
     $packets = [];
     // We need to pre-sort these for split packets so we can do extra work where needed
     foreach ($this->packets_response as $response) {
         $buffer = new Buffer($response);
         // Pull out the header
         $header = $buffer->read(5);
         // Add the packet to the proper section, we will combine later
         $packets[$header][] = $buffer->getBuffer();
     }
     unset($buffer);
     $results = [];
     // Now let's iterate and process
     foreach ($packets as $header => $packetGroup) {
         // Figure out which packet response this is
         if (!array_key_exists($header, $this->responses)) {
             throw new Exception(__METHOD__ . " response type '{$header}' is not valid");
         }
         // Now we need to call the proper method
         $results = array_merge($results, call_user_func_array([$this, $this->responses[$header]], [new Buffer(implode($packetGroup))]));
     }
     unset($packets);
     return $results;
 }
Exemplo n.º 2
0
 /**
  * Process the response
  *
  * @return array
  * @throws \GameQ\Exception\Protocol
  */
 public function processResponse()
 {
     // Make a new buffer out of all of the packets
     $buffer = new Buffer(implode('', $this->packets_response));
     // Check the header TS3
     if (($header = trim($buffer->readString("\n"))) !== 'TS3') {
         throw new Exception(__METHOD__ . " Expected header '{$header}' does not match expected 'TS3'.");
     }
     // Convert all the escaped characters
     $raw = str_replace(['\\\\', '\\/'], ['\\', '/'], $buffer->getBuffer());
     // Explode the sections and filter to remove empty, junk ones
     $sections = array_filter(explode("\n", $raw), function ($value) {
         $value = trim($value);
         // Not empty string or a message response for "error id=\d"
         return !empty($value) && substr($value, 0, 5) !== 'error';
     });
     // Trim up the values to remove extra whitespace
     $sections = array_map('trim', $sections);
     // Set the result to a new result instance
     $result = new Result();
     // Iterate over the sections and offload the parsing
     foreach ($sections as $section) {
         // Grab a snip of the data so we can figure out what it is
         $check = substr(trim($section), 0, 4);
         // Use the first part of the response to figure out where we need to go
         if ($check == 'virt') {
             // Server info
             $this->processDetails($section, $result);
         } elseif ($check == 'cid=') {
             // Channels
             $this->processChannels($section, $result);
         } elseif ($check == 'clid') {
             // Clients (players)
             $this->processPlayers($section, $result);
         }
     }
     unset($buffer, $sections, $section, $check);
     return $result->fetch();
 }
Exemplo n.º 3
0
 /**
  * Handles processing the player and team data into a usable format
  *
  * @param \GameQ\Buffer $buffer
  * @param \GameQ\Result $result
  */
 protected function processPlayersAndTeams(Buffer &$buffer, Result &$result)
 {
     /*
      * Explode the data into groups. First is player, next is team (item_t)
      * Each group should be as follows:
      *
      * [0] => item_
      * [1] => information for item_
      * ...
      */
     $data = explode("", $buffer->getBuffer());
     // By default item_group is blank, this will be set for each loop thru the data
     $item_group = '';
     // By default the item_type is blank, this will be set on each loop
     $item_type = '';
     // Loop through all of the $data for information and pull it out into the result
     for ($x = 0; $x < count($data) - 1; $x++) {
         // Pull out the item
         $item = $data[$x];
         // If this is an empty item, move on
         if ($item == '' || $item == "") {
             continue;
         }
         /*
          * Left as reference:
          *
          * Each block of player_ and team_t have preceding junk chars
          *
          * player_ is actually \x01player_
          * team_t is actually \x00\x02team_t
          *
          * Probably a by-product of the change to exploding the data from the original.
          *
          * For now we just strip out these characters
          */
         // Check to see if $item has a _ at the end, this is player info
         if (substr($item, -1) == '_') {
             // Set the item group
             $item_group = 'players';
             // Set the item type, rip off any trailing stuff and bad chars
             $item_type = rtrim(str_replace("", '', $item), '_');
         } elseif (substr($item, -2) == '_t') {
             // Check to see if $item has a _t at the end, this is team info
             // Set the item group
             $item_group = 'teams';
             // Set the item type, rip off any trailing stuff and bad chars
             $item_type = rtrim(str_replace(["", ""], '', $item), '_t');
         } else {
             // We can assume it is data belonging to a previously defined item
             // Make a temp buffer so we have easier access to the data
             $buf_temp = new Buffer($item, Buffer::NUMBER_TYPE_BIGENDIAN);
             // Get the values
             while ($buf_temp->getLength()) {
                 // No value so break the loop, end of string
                 if (($val = $buf_temp->readString()) === '') {
                     break;
                 }
                 // Add the value to the proper item in the correct group
                 $result->addSub($item_group, $item_type, utf8_encode(trim($val)));
             }
             // Unset our buffer
             unset($buf_temp);
         }
     }
     // Free up some memory
     unset($data, $item, $item_group, $item_type, $val);
 }
Exemplo n.º 4
0
 /**
  * Process the response for the StarMade server
  *
  * @return array
  * @throws \GameQ\Exception\Protocol
  */
 public function processResponse()
 {
     // Holds the results sent back
     $results = [];
     // Holds the processed packets after having been reassembled
     $processed = [];
     // Start up the index for the processed
     $sequence_id_last = 0;
     foreach ($this->packets_response as $packet) {
         // Create a new buffer
         $buffer = new Buffer($packet);
         // Each "good" packet begins with sequence_id (32-bit)
         $sequence_id = $buffer->readInt32();
         // Sequence id is a response
         if (array_key_exists($sequence_id, $this->responses)) {
             $processed[$sequence_id] = $buffer->getBuffer();
             $sequence_id_last = $sequence_id;
         } else {
             // This is a continuation of the previous packet, reset the buffer and append
             $buffer->jumpto(0);
             // Append
             $processed[$sequence_id_last] .= $buffer->getBuffer();
         }
     }
     unset($buffer, $sequence_id_last, $sequence_id);
     // Iterate over the combined packets and do some work
     foreach ($processed as $sequence_id => $data) {
         // Create a new buffer
         $buffer = new Buffer($data);
         // Get the length of the packet
         $packetLength = $buffer->getLength();
         // Check to make sure the expected length matches the real length
         // Subtract 4 for the sequence_id pulled out earlier
         if ($packetLength != $buffer->readInt32() - 4) {
             throw new Exception(__METHOD__ . " packet length does not match expected length!");
         }
         // Now we need to call the proper method
         $results = array_merge($results, call_user_func_array([$this, $this->responses[$sequence_id]], [$buffer]));
     }
     return $results;
 }
Exemplo n.º 5
0
 /**
  * Process the split packets and decompress if necessary
  *
  * @SuppressWarnings(PHPMD.UnusedLocalVariable)
  *
  * @param       $packet_id
  * @param array $packets
  *
  * @return string
  * @throws \GameQ\Exception\Protocol
  */
 protected function processPackets($packet_id, array $packets = [])
 {
     // Init array so we can order
     $packs = [];
     // We have multiple packets so we need to get them and order them
     foreach ($packets as $i => $packet) {
         // Make a buffer so we can read this info
         $buffer = new Buffer($packet);
         // Gold source
         if ($this->source_engine == self::GOLDSOURCE_ENGINE) {
             // Grab the packet number (byte)
             $packet_number = $buffer->readInt8();
             // We need to burn the extra header (\xFF\xFF\xFF\xFF) on first loop
             if ($i == 0) {
                 $buffer->read(4);
             }
             // Now add the rest of the packet to the new array with the packet_number as the id so we can order it
             $packs[$packet_number] = $buffer->getBuffer();
         } else {
             // Number of packets in this set (byte)
             $buffer->readInt8();
             // The current packet number (byte)
             $packet_number = $buffer->readInt8();
             // Check to see if this is compressed
             // @todo: Check to make sure these decompress correctly, new changes may affect this loop.
             if ($packet_id & 2147483648.0) {
                 // Check to see if we have Bzip2 installed
                 if (!function_exists('bzdecompress')) {
                     throw new Exception('Bzip2 is not installed.  See http://www.php.net/manual/en/book.bzip2.php for more info.', 0);
                 }
                 // Get the length of the packet (long)
                 $packet_length = $buffer->readInt32Signed();
                 // Checksum for the decompressed packet (long)
                 $buffer->readInt32Signed();
                 // Try to decompress
                 $result = bzdecompress($buffer->getBuffer());
                 // Now verify the length
                 if (strlen($result) != $packet_length) {
                     throw new Exception("Checksum for compressed packet failed! Length expected: {$packet_length}, length\n                            returned: " . strlen($result));
                 }
             } else {
                 // Get the packet length (short)
                 $buffer->readInt16Signed();
                 // We need to burn the extra header (\xFF\xFF\xFF\xFF) on first loop
                 if ($i == 0) {
                     $buffer->read(4);
                 }
                 // Grab the rest of the buffer as a result
                 $result = $buffer->getBuffer();
             }
             // Add this packet to the list
             $packs[$packet_number] = $result;
         }
         unset($buffer);
     }
     // Free some memory
     unset($packets, $packet);
     // Sort the packets by packet number
     ksort($packs);
     // Now combine the packs into one and return
     return implode("", $packs);
 }
Exemplo n.º 6
0
 /**
  * Process the response
  *
  * @return array
  * @throws \GameQ\Exception\Protocol
  */
 public function processResponse()
 {
     // Make a new buffer out of all of the packets
     $buffer = new Buffer(implode('', $this->packets_response));
     // Check the header [TS]
     if (($header = trim($buffer->readString("\n"))) !== '[TS]') {
         throw new Exception(__METHOD__ . " Expected header '{$header}' does not match expected '[TS]'.");
     }
     // Split this buffer as the data blocks are bound by "OK" and drop any empty values
     $sections = array_filter(explode("OK", $buffer->getBuffer()), function ($value) {
         $value = trim($value);
         return !empty($value);
     });
     // Trim up the values to remove extra whitespace
     $sections = array_map('trim', $sections);
     // Set the result to a new result instance
     $result = new Result();
     // Now we need to iterate over the sections and off load the processing
     foreach ($sections as $section) {
         // Grab a snip of the data so we can figure out what it is
         $check = substr($section, 0, 7);
         // Offload to the proper method
         if ($check == 'server_') {
             // Server settings and info
             $this->processDetails($section, $result);
         } elseif ($check == "id\tcode") {
             // Channel info
             $this->processChannels($section, $result);
         } elseif ($check == "p_id\tc_") {
             // Player info
             $this->processPlayers($section, $result);
         }
     }
     unset($buffer, $sections, $section, $check);
     return $result->fetch();
 }
Exemplo n.º 7
0
 /**
  * Handle processing the status buffer
  *
  * @param Buffer $buffer
  *
  * @return array
  */
 protected function processStatus(Buffer $buffer)
 {
     // Set the result to a new result instance
     $result = new Result();
     // By default dedicted
     $result->add('dedicated', 1);
     // Lets peek and see if the data starts with a \
     if ($buffer->lookAhead(1) == '\\') {
         // Burn the first one
         $buffer->skip(1);
     }
     // Explode the data
     $data = explode('\\', $buffer->getBuffer());
     // No longer needed
     unset($buffer);
     // Init some vars
     $numPlayers = 0;
     $numTeams = 0;
     $itemCount = count($data);
     // Now lets loop the array
     for ($x = 0; $x < $itemCount; $x += 2) {
         // Set some local vars
         $key = $data[$x];
         $val = $data[$x + 1];
         // Check for <variable>_<count> variable (i.e players)
         if (($suffix = strrpos($key, '_')) !== false && is_numeric(substr($key, $suffix + 1))) {
             // See if this is a team designation
             if (substr($key, 0, $suffix) == 'teamname') {
                 $result->addTeam('teamname', $val);
                 $numTeams++;
             } else {
                 // Its a player
                 if (substr($key, 0, $suffix) == 'playername') {
                     $numPlayers++;
                 }
                 $result->addPlayer(substr($key, 0, $suffix), utf8_encode($val));
             }
         } else {
             // Regular variable so just add the value.
             $result->add($key, $val);
         }
     }
     // Add the player and team count
     $result->add('num_players', $numPlayers);
     $result->add('num_teams', $numTeams);
     // Unset some stuff to free up memory
     unset($data, $key, $val, $suffix, $x, $itemCount);
     // Return the result
     return $result->fetch();
 }