Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial locking support (on Communicator, Request, Response, Query an…

…d login).
  • Loading branch information...
commit 77cf445b9f7b020373597dce652e6da426db17fb 1 parent 81e22ca
@boenrobot boenrobot authored
View
50 src/PEAR2/Net/RouterOS/Client.php
@@ -21,6 +21,11 @@
namespace PEAR2\Net\RouterOS;
/**
+ * Refers to transmitter direction constants.
+ */
+use PEAR2\Net\Transmitter as T;
+
+/**
* A RouterOS client.
*
* Provides functionality for easily communicating with a RouterOS host.
@@ -160,23 +165,19 @@ public static function login(Communicator $com, $username, $password = '')
$password
);
}
-
+ $old = null;
try {
- $request = new Request('/login');
- $request->send($com);
- $response = new Response($com);
- $request->setArgument('name', $username);
- $request->setArgument(
- 'response', '00' . md5(
- chr(0) . $password
- . pack('H*', $response->getArgument('ret'))
- )
- );
- $request->send($com);
- $response = new Response($com);
- return $response->getType() === Response::TYPE_FINAL
- && null === $response->getArgument('ret');
+ if ($com->getTransmitter()->isPersistent()) {
+ $old = $com->getTransmitter()->lock(T\Stream::DIRECTION_ALL);
+ $result = self::_performLogin($com, $username, $password);
+ $com->getTransmitter()->lock($old, true);
+ return $result;
+ }
+ return self::_performLogin($com, $username, $password);
} 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(
@@ -185,6 +186,25 @@ public static function login(Communicator $com, $username, $password = '')
}
}
+ private static function _performLogin(
+ Communicator $com, $username, $password
+ ) {
+ $request = new Request('/login');
+ $request->send($com);
+ $response = new Response($com);
+ $request->setArgument('name', $username);
+ $request->setArgument(
+ 'response', '00' . md5(
+ chr(0) . $password
+ . pack('H*', $response->getArgument('ret'))
+ )
+ );
+ $request->send($com);
+ $response = new Response($com);
+ return $response->getType() === Response::TYPE_FINAL
+ && null === $response->getArgument('ret');
+ }
+
/**
* Sets the charset(s) for this connection.
*
View
65 src/PEAR2/Net/RouterOS/Communicator.php
@@ -82,7 +82,7 @@ class Communicator
protected $charsets = array();
/**
- * @var TcpClient The transmitter for the connection.
+ * @var T\TcpClient The transmitter for the connection.
*/
protected $trans;
@@ -317,6 +317,12 @@ public function sendWord($word)
}
$length = strlen($word);
static::verifyLengthSupport($length);
+ if ($this->trans->isPersistent()) {
+ $old = $this->trans->lock(T\Stream::DIRECTION_SEND);
+ $bytes = $this->trans->send(self::encodeLength($length) . $word);
+ $this->trans->lock($old, true);
+ return $bytes;
+ }
return $this->trans->send(self::encodeLength($length) . $word);
}
@@ -440,7 +446,18 @@ public static function encodeLength($length)
*/
public function getNextWord()
{
- $word = $this->trans->receive(self::decodeLength($this->trans), 'word');
+ if ($this->trans->isPersistent()) {
+ $old = $this->trans->lock(T\Stream::DIRECTION_RECEIVE);
+ $word = $this->trans->receive(
+ self::decodeLength($this->trans), 'word'
+ );
+ $this->trans->lock($old, true);
+ } else {
+ $word = $this->trans->receive(
+ self::decodeLength($this->trans), 'word'
+ );
+ }
+
if (null !== ($remoteCharset = $this->getCharset(self::CHARSET_REMOTE))
&& null !== ($localCharset = $this->getCharset(self::CHARSET_LOCAL))
) {
@@ -450,6 +467,7 @@ public function getNextWord()
$word
);
}
+
return $word;
}
@@ -473,9 +491,19 @@ public function getNextWordAsStream()
$remoteCharset . '.' . $localCharset . '//IGNORE//TRANSLIT'
);
}
- $stream = $this->trans->receiveStream(
- self::decodeLength($this->trans), $filters, 'stream word'
- );
+
+ if ($this->trans->isPersistent()) {
+ $old = $this->trans->lock(T\Stream::DIRECTION_RECEIVE);
+ $stream = $this->trans->receiveStream(
+ self::decodeLength($this->trans), $filters, 'stream word'
+ );
+ $this->trans->lock($old, true);
+ } else {
+ $stream = $this->trans->receiveStream(
+ self::decodeLength($this->trans), $filters, 'stream word'
+ );
+ }
+
return $stream;
}
@@ -492,6 +520,31 @@ public function getNextWordAsStream()
*/
public static function decodeLength(T\Stream $trans)
{
+ if ($trans->isPersistent()) {
+ $old = $trans->lock($trans::DIRECTION_RECEIVE);
+ $length = self::_decodeLength($trans);
+ $trans->lock($old, true);
+ return $length;
+ }
+ return self::_decodeLength($trans);
+ }
+
+ /**
+ * Decodes the lenght of the incoming message.
+ *
+ * Decodes the lenght of the incoming message, as specified by the RouterOS
+ * API.
+ *
+ * Difference with the non private function is that this one doesn't perform
+ * locking if the connection is a persistent one.
+ *
+ * @param T\Stream $trans The transmitter from which to decode the length of
+ * the incoming message.
+ *
+ * @return int The decoded length
+ */
+ private static function _decodeLength(T\Stream $trans)
+ {
$byte = ord($trans->receive(1, 'initial length byte'));
if ($byte & 0x80) {
if (($byte & 0xC0) === 0x80) {
@@ -508,7 +561,7 @@ public static function decodeLength(T\Stream $trans)
+ (double) sprintf('%u', $rem['~']);
}
throw new NotSupportedException(
- 'Unknown control byte encountered.', 1600, null, $byte
+ 'Unknown control byte encountered.', 1601, null, $byte
);
} else {
return $byte;
View
16 src/PEAR2/Net/RouterOS/Query.php
@@ -21,6 +21,11 @@
namespace PEAR2\Net\RouterOS;
/**
+ * Refers to transmitter direction constants.
+ */
+use PEAR2\Net\Transmitter as T;
+
+/**
* Represents a query for RouterOS requests.
*
* @category Net
@@ -169,6 +174,17 @@ public function andWhere($name, $value = null, $action = self::ACTION_EXIST)
*/
public function send(Communicator $com)
{
+ if ($com->getTransmitter()->isPersistent()) {
+ $old = $com->getTransmitter()->lock(T\Stream::DIRECTION_SEND);
+ $bytes = $this->_send($com);
+ $com->getTransmitter()->lock($old, true);
+ return $bytes;
+ }
+ return $this->_send($com);
+ }
+
+ private function _send(Communicator $com)
+ {
if (!$com->getTransmitter()->isAcceptingData()) {
throw new SocketException(
'Transmitter is invalid. Sending aborted.', 30600
View
28 src/PEAR2/Net/RouterOS/Request.php
@@ -21,6 +21,11 @@
namespace PEAR2\Net\RouterOS;
/**
+ * Refers to transmitter direction constants.
+ */
+use PEAR2\Net\Transmitter as T;
+
+/**
* Represents a RouterOS request.
*
* @category Net
@@ -239,6 +244,29 @@ public function removeAllArguments()
*/
public function send(Communicator $com)
{
+ if ($com->getTransmitter()->isPersistent()) {
+ $old = $com->getTransmitter()->lock(T\Stream::DIRECTION_SEND);
+ $bytes = $this->_send($com);
+ $com->getTransmitter()->lock($old, true);
+ return $bytes;
+ }
+ return $this->_send($com);
+ }
+
+ /**
+ * 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.', 40900
View
2  tests/RequestHandlingTest.php
@@ -592,7 +592,7 @@ public function testControlByteException()
Communicator::decodeLength($trans);
} catch (NotSupportedException $e) {
$this->assertEquals(
- 1600, $e->getCode(), 'Improper exception code.'
+ 1601, $e->getCode(), 'Improper exception code.'
);
$this->assertEquals(
$controlByte, $e->getValue(), 'Improper exception value.'
Please sign in to comment.
Something went wrong with that request. Please try again.