/** * Sends the query over a communicator. * * The only difference with the non private equivalent is that this one does * not do locking. * * @param Communicator $com The communicator to send the query over. * * @return int The number of bytes sent. */ private function _send(Communicator $com) { if (!$com->getTransmitter()->isAcceptingData()) { throw new SocketException('Transmitter is invalid. Sending aborted.', SocketException::CODE_UNACCEPTING_QUERY); } $bytes = 0; foreach ($this->words as $queryWord) { list($predicate, $value) = $queryWord; $prefix = '?' . $predicate; if (null === $value) { $bytes += $com->sendWord($prefix); } else { $prefix .= '='; if (is_string($value)) { $bytes += $com->sendWord($prefix . $value); } else { $bytes += $com->sendWordFromStream($prefix, $value); } } } return $bytes; }
/** * Sends a request over a communicator. * * The only difference with the non private equivalent is that this one does * not do locking. * * @param Communicator $com The communicator to send the request over. * * @return int The number of bytes sent. * @see Client::sendSync() * @see Client::sendAsync() */ private function _send(Communicator $com) { if (!$com->getTransmitter()->isAcceptingData()) { throw new SocketException('Transmitter is invalid. Sending aborted.', SocketException::CODE_UNACCEPTING_REQEUST); } $bytes = 0; $bytes += $com->sendWord($this->getCommand()); if (null !== ($tag = $this->getTag())) { $bytes += $com->sendWord('.tag=' . $tag); } foreach ($this->getAllArguments() as $name => $value) { $prefix = '=' . $name . '='; if (is_string($value)) { $bytes += $com->sendWord($prefix . $value); } else { $bytes += $com->sendWordFromStream($prefix, $value); } } $query = $this->getQuery(); if ($query instanceof Query) { $bytes += $query->send($com); } $bytes += $com->sendWord(''); return $bytes; }
/** * Extracts a new response from a communicator. * * This is the function that performs the actual receiving, while the * constructor is also involved in locks and registry sync. * * @param Communicator $com The communicator from which to extract * the new response. * @param bool $asStream Whether to populate the argument values * with streams instead of strings. * @param int $timeout_s If a response is not immediatly * available, wait this many seconds. If NULL, wait indefinetly. * @param int $timeout_us Microseconds to add to the waiting time. * * @return void */ private function _receive(Communicator $com, $asStream = false, $timeout_s = 0, $timeout_us = null) { if (!$com->getTransmitter()->isDataAwaiting($timeout_s, $timeout_us)) { throw new SocketException('No data within the time limit', SocketException::CODE_NO_DATA); } $this->setType($com->getNextWord()); if ($asStream) { for ($word = $com->getNextWordAsStream(), fseek($word, 0, SEEK_END); ftell($word) !== 0; $word = $com->getNextWordAsStream(), fseek($word, 0, SEEK_END)) { rewind($word); $ind = fread($word, 1); if ('=' === $ind || '.' === $ind) { $prefix = stream_get_line($word, null, '='); } if ('=' === $ind) { $value = fopen('php://temp', 'r+b'); $bytesCopied = ftell($word); while (!feof($word)) { $bytesCopied += stream_copy_to_stream($word, $value, 0xfffff, $bytesCopied); } rewind($value); $this->setArgument($prefix, $value); continue; } if ('.' === $ind && 'tag' === $prefix) { $this->setTag(stream_get_contents($word, -1, -1)); continue; } rewind($word); $this->unrecognizedWords[] = $word; } } else { for ($word = $com->getNextWord(); '' !== $word; $word = $com->getNextWord()) { if (preg_match('/^=([^=]+)=(.*)$/sS', $word, $matches)) { $this->setArgument($matches[1], $matches[2]); } elseif (preg_match('/^\\.tag=(.*)$/sS', $word, $matches)) { $this->setTag($matches[1]); } else { $this->unrecognizedWords[] = $word; } } } }
/** * Login to a RouterOS connection. * * @param Communicator $com The communicator to attempt to login to. * @param string $username The RouterOS username. * @param string $password The RouterOS password. * @param int|null $timeout The time to wait for each response. NULL * waits indefinetly. * * @return bool TRUE on success, FALSE on failure. */ public static function login(Communicator $com, $username, $password = '', $timeout = null) { if (null !== ($remoteCharset = $com->getCharset($com::CHARSET_REMOTE)) && null !== ($localCharset = $com->getCharset($com::CHARSET_LOCAL))) { $password = iconv($localCharset, $remoteCharset . '//IGNORE//TRANSLIT', $password); } $old = null; try { if ($com->getTransmitter()->isPersistent()) { $old = $com->getTransmitter()->lock(S::DIRECTION_ALL); $result = self::_login($com, $username, $password, $timeout); $com->getTransmitter()->lock($old, true); return $result; } return self::_login($com, $username, $password, $timeout); } catch (Exception $e) { if ($com->getTransmitter()->isPersistent() && null !== $old) { $com->getTransmitter()->lock($old, true); } throw $e instanceof NotSupportedException || $e instanceof UnexpectedValueException || !$com->getTransmitter()->isDataAwaiting() ? new SocketException('This is not a compatible RouterOS service', SocketException::CODE_SERVICE_INCOMPATIBLE, $e) : $e; } }