/** * @param string $prompt * * @return \Graze\TelnetClient\TelnetResponseInterface * @throws TelnetExceptionInterface */ protected function getResponse($prompt = null) { $isError = false; $buffer = ''; do { // process one character at a time try { $character = $this->socket->read(1); } catch (Exception $e) { throw new TelnetException('failed reading from socket', 0, $e); } if (in_array($character, [$this->NULL, $this->DC1])) { break; } if ($this->interpretAsCommand->interpret($character, $this->socket)) { continue; } $buffer .= $character; // check for prompt if ($this->promptMatcher->isMatch($prompt ?: $this->prompt, $buffer, $this->lineEnding)) { break; } // check for error prompt if ($this->promptMatcher->isMatch($this->promptError, $buffer, $this->lineEnding)) { $isError = true; break; } } while (true); return new TelnetResponse($isError, $this->promptMatcher->getResponseText(), $this->promptMatcher->getMatches()); }
function it_sends_a_packet(Socket $client, Packet $packet) { $rawPacket = pack('VV', 1, Packet::SERVERDATA_EXECCOMMAND) . '/command' . pack('HH', 0x0, 0x0); $packet->convertToRcon()->willReturn($rawPacket); $rawPacket = pack('V', mb_strlen($rawPacket)) . $rawPacket; $client->write($rawPacket)->shouldBeCalled(); $rawPacket = pack('VV', 1, Packet::SERVERDATA_RESPONSE_VALUE) . 'Command result' . pack('HH', 0x0, 0x0); $packetSize = pack('V', mb_strlen($rawPacket)); $client->read(4)->willReturn($packetSize); $client->read(mb_strlen($rawPacket))->willReturn($rawPacket); $response = $this->sendPacket($packet); $response->shouldHaveType('Minecraft\\Rcon\\Packet'); $response->getId()->shouldReturn(1); $response->getType()->shouldReturn(Packet::SERVERDATA_RESPONSE_VALUE); $response->getBody()->shouldReturn('Command result'); }
function it_handles_empty_response_data(\Socket\Raw\Socket $socket, \gries\Rcon\Message $message) { $message->convertToRconData(2)->willReturn('abc1234'); $lengthData = ''; // call to find out the packet length $socket->read(4)->shouldBeCalled()->willReturn($lengthData); $this->sendMessage($message); }
/** * Sends a packet through the connection * * @param Packet $packet * * @return Packet */ public function sendPacket(Packet $packet) { // Create a raw packet $rawPacket = $packet->convertToRcon(); // Attach size $rawPacket = pack('V', mb_strlen($rawPacket)) . $rawPacket; // Write to the socket $this->socket->write($rawPacket); // Read the packet size $packetSize = $this->socket->read(4); $packetSize = unpack('V', $packetSize); $packetSize = reset($packetSize); // TODO: multi-packet responses // Read the packet $rawPacket = $this->socket->read($packetSize); // Parse and return the packet return Packet::createFromRcon($rawPacket); }
/** * @param string $character * @param Socket $socket * * @return bool * @throws TelnetExceptionInterface */ public function interpret($character, Socket $socket) { if ($character != $this->IAC) { return false; } try { $command = $socket->read(1); $option = $socket->read(1); if (in_array($command, [$this->DO, $this->DONT])) { $socket->write($this->IAC . $this->WONT . $option); return true; } if (in_array($command, [$this->WILL, $this->WONT])) { $socket->write($this->IAC . $this->DONT . $option); return true; } } catch (Exception $e) { throw new TelnetException('failed negotiating IAC', 0, $e); } throw new UndefinedCommandException($command); }
public function handleData() { try { $data = $this->socket->read($this->bufferSize); } catch (\Exception $e) { return $this->end(); } if ($data === '') { $this->end(); } else { $this->emit('data', array($data, $this)); } }
/** * This handles a fragmented response. * (https://developer.valvesoftware.com/wiki/Source_RCON_Protocol#Multiple-packet_Responses) * * We basically send a RESPONSE_VALUE Message to the server to force the response of the rest of the package, * until we receive another package or an empty response. * * All the received data is then appended to the current ResponseMessage. * * @param $responseMessage * @throws Exception\InvalidPacketException */ protected function handleFragmentedResponse(Message $responseMessage) { do { usleep(20000); // some servers stop responding if we send to many packages so we wait 20ms $this->client->write(Message::TYPE_RESPONSE_VALUE); $responseData = $this->client->read(4096); if (empty($responseData)) { break; } $fragmentedMessage = new Message(); $fragmentedMessage->initializeFromRconData($responseData, true); $responseMessage->append($fragmentedMessage); if ($fragmentedMessage->getType() !== Message::TYPE_RESPONSE_VALUE) { break; } } while (true); }
/** * A wrapper to cleanly read a response from clamd * * @return string */ private function _receiveResponse() { $result = $this->socket->read(4096); $this->socket->close(); return trim($result); }