function it_sends_messages_to_the_server(\Socket\Raw\Socket $socket, \gries\Rcon\Message $message) { $rconData = 'abc1234'; $message->convertToRconData(2)->willReturn($rconData); $socket->write($rconData)->shouldBeCalled(); $this->sendMessage($message); }
/** * @param string $command * * @return void * @throws TelnetExceptionInterface */ protected function write($command) { try { $this->socket->write($command . $this->lineEnding); } catch (Exception $e) { throw new TelnetException(sprintf('failed writing to socket [%s]', $command), 0, $e); } }
/** * 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); }
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'); }
/** * 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); }
/** * @param string $buffer * @return int * @throws Exception */ public function write($buffer) { $totalSent = 0; $length = strlen($buffer); while (true) { $sent = parent::write($buffer); $totalSent += $sent; // Check if the entire message has been sent if ($sent >= $length) { break; } // If not sent the entire message. // Get the part of the message that has not yet been sent as message $buffer = substr($buffer, $sent); // Get the length of the not sent part $length -= $sent; } return $totalSent; }