Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

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

…d login).
  • Loading branch information...
commit 77cf445b9f7b020373597dce652e6da426db17fb 1 parent 81e22ca
Vasil Rangelov boenrobot authored
50 src/PEAR2/Net/RouterOS/Client.php
View
@@ -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.
*
65 src/PEAR2/Net/RouterOS/Communicator.php
View
@@ -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;
16 src/PEAR2/Net/RouterOS/Query.php
View
@@ -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
28 src/PEAR2/Net/RouterOS/Request.php
View
@@ -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
2  tests/RequestHandlingTest.php
View
@@ -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.