Skip to content
This repository
Browse code

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

…d login).
  • Loading branch information...
commit 77cf445b9f7b020373597dce652e6da426db17fb 1 parent 81e22ca
Vasil Rangelov authored March 04, 2012
50  src/PEAR2/Net/RouterOS/Client.php
@@ -21,6 +21,11 @@
21 21
 namespace PEAR2\Net\RouterOS;
22 22
 
23 23
 /**
  24
+ * Refers to transmitter direction constants.
  25
+ */
  26
+use PEAR2\Net\Transmitter as T;
  27
+
  28
+/**
24 29
  * A RouterOS client.
25 30
  * 
26 31
  * Provides functionality for easily communicating with a RouterOS host.
@@ -160,23 +165,19 @@ public static function login(Communicator $com, $username, $password = '')
160 165
                 $password
161 166
             );
162 167
         }
163  
-        
  168
+        $old = null;
164 169
         try {
165  
-            $request = new Request('/login');
166  
-            $request->send($com);
167  
-            $response = new Response($com);
168  
-            $request->setArgument('name', $username);
169  
-            $request->setArgument(
170  
-                'response', '00' . md5(
171  
-                    chr(0) . $password
172  
-                    . pack('H*', $response->getArgument('ret'))
173  
-                )
174  
-            );
175  
-            $request->send($com);
176  
-            $response = new Response($com);
177  
-            return $response->getType() === Response::TYPE_FINAL
178  
-                && null === $response->getArgument('ret');
  170
+            if ($com->getTransmitter()->isPersistent()) {
  171
+                $old = $com->getTransmitter()->lock(T\Stream::DIRECTION_ALL);
  172
+                $result = self::_performLogin($com, $username, $password);
  173
+                $com->getTransmitter()->lock($old, true);
  174
+                return $result;
  175
+            }
  176
+            return self::_performLogin($com, $username, $password);
179 177
         } catch (\Exception $e) {
  178
+            if ($com->getTransmitter()->isPersistent() && null !== $old) {
  179
+                $com->getTransmitter()->lock($old, true);
  180
+            }
180 181
             throw ($e instanceof NotSupportedException
181 182
             || $e instanceof UnexpectedValueException
182 183
             || !$com->getTransmitter()->isDataAwaiting()) ? new SocketException(
@@ -185,6 +186,25 @@ public static function login(Communicator $com, $username, $password = '')
185 186
         }
186 187
     }
187 188
     
  189
+    private static function _performLogin(
  190
+        Communicator $com, $username, $password
  191
+    ) {
  192
+        $request = new Request('/login');
  193
+        $request->send($com);
  194
+        $response = new Response($com);
  195
+        $request->setArgument('name', $username);
  196
+        $request->setArgument(
  197
+            'response', '00' . md5(
  198
+                chr(0) . $password
  199
+                . pack('H*', $response->getArgument('ret'))
  200
+            )
  201
+        );
  202
+        $request->send($com);
  203
+        $response = new Response($com);
  204
+        return $response->getType() === Response::TYPE_FINAL
  205
+            && null === $response->getArgument('ret');
  206
+    }
  207
+    
188 208
     /**
189 209
      * Sets the charset(s) for this connection.
190 210
      * 
65  src/PEAR2/Net/RouterOS/Communicator.php
@@ -82,7 +82,7 @@ class Communicator
82 82
     protected $charsets = array();
83 83
 
84 84
     /**
85  
-     * @var TcpClient The transmitter for the connection.
  85
+     * @var T\TcpClient The transmitter for the connection.
86 86
      */
87 87
     protected $trans;
88 88
 
@@ -317,6 +317,12 @@ public function sendWord($word)
317 317
         }
318 318
         $length = strlen($word);
319 319
         static::verifyLengthSupport($length);
  320
+        if ($this->trans->isPersistent()) {
  321
+            $old = $this->trans->lock(T\Stream::DIRECTION_SEND);
  322
+            $bytes = $this->trans->send(self::encodeLength($length) . $word);
  323
+            $this->trans->lock($old, true);
  324
+            return $bytes;
  325
+        }
320 326
         return $this->trans->send(self::encodeLength($length) . $word);
321 327
     }
322 328
 
@@ -440,7 +446,18 @@ public static function encodeLength($length)
440 446
      */
441 447
     public function getNextWord()
442 448
     {
443  
-        $word = $this->trans->receive(self::decodeLength($this->trans), 'word');
  449
+        if ($this->trans->isPersistent()) {
  450
+            $old = $this->trans->lock(T\Stream::DIRECTION_RECEIVE);
  451
+            $word = $this->trans->receive(
  452
+                self::decodeLength($this->trans), 'word'
  453
+            );
  454
+            $this->trans->lock($old, true);
  455
+        } else {
  456
+            $word = $this->trans->receive(
  457
+                self::decodeLength($this->trans), 'word'
  458
+            );
  459
+        }
  460
+        
444 461
         if (null !== ($remoteCharset = $this->getCharset(self::CHARSET_REMOTE))
445 462
             && null !== ($localCharset = $this->getCharset(self::CHARSET_LOCAL))
446 463
         ) {
@@ -450,6 +467,7 @@ public function getNextWord()
450 467
                 $word
451 468
             );
452 469
         }
  470
+        
453 471
         return $word;
454 472
     }
455 473
 
@@ -473,9 +491,19 @@ public function getNextWordAsStream()
473 491
                 $remoteCharset . '.' . $localCharset . '//IGNORE//TRANSLIT'
474 492
             );
475 493
         }
476  
-        $stream = $this->trans->receiveStream(
477  
-            self::decodeLength($this->trans), $filters, 'stream word'
478  
-        );
  494
+        
  495
+        if ($this->trans->isPersistent()) {
  496
+            $old = $this->trans->lock(T\Stream::DIRECTION_RECEIVE);
  497
+            $stream = $this->trans->receiveStream(
  498
+                self::decodeLength($this->trans), $filters, 'stream word'
  499
+            );
  500
+            $this->trans->lock($old, true);
  501
+        } else {
  502
+            $stream = $this->trans->receiveStream(
  503
+                self::decodeLength($this->trans), $filters, 'stream word'
  504
+            );
  505
+        }
  506
+        
479 507
         return $stream;
480 508
     }
481 509
 
@@ -492,6 +520,31 @@ public function getNextWordAsStream()
492 520
      */
493 521
     public static function decodeLength(T\Stream $trans)
494 522
     {
  523
+        if ($trans->isPersistent()) {
  524
+            $old = $trans->lock($trans::DIRECTION_RECEIVE);
  525
+            $length = self::_decodeLength($trans);
  526
+            $trans->lock($old, true);
  527
+            return $length;
  528
+        }
  529
+        return self::_decodeLength($trans);
  530
+    }
  531
+
  532
+    /**
  533
+     * Decodes the lenght of the incoming message.
  534
+     * 
  535
+     * Decodes the lenght of the incoming message, as specified by the RouterOS
  536
+     * API.
  537
+     * 
  538
+     * Difference with the non private function is that this one doesn't perform
  539
+     * locking if the connection is a persistent one.
  540
+     * 
  541
+     * @param T\Stream $trans The transmitter from which to decode the length of
  542
+     * the incoming message.
  543
+     * 
  544
+     * @return int The decoded length
  545
+     */
  546
+    private static function _decodeLength(T\Stream $trans)
  547
+    {
495 548
         $byte = ord($trans->receive(1, 'initial length byte'));
496 549
         if ($byte & 0x80) {
497 550
             if (($byte & 0xC0) === 0x80) {
@@ -508,7 +561,7 @@ public static function decodeLength(T\Stream $trans)
508 561
                     + (double) sprintf('%u', $rem['~']);
509 562
             }
510 563
             throw new NotSupportedException(
511  
-                'Unknown control byte encountered.', 1600, null, $byte
  564
+                'Unknown control byte encountered.', 1601, null, $byte
512 565
             );
513 566
         } else {
514 567
             return $byte;
16  src/PEAR2/Net/RouterOS/Query.php
@@ -21,6 +21,11 @@
21 21
 namespace PEAR2\Net\RouterOS;
22 22
 
23 23
 /**
  24
+ * Refers to transmitter direction constants.
  25
+ */
  26
+use PEAR2\Net\Transmitter as T;
  27
+
  28
+/**
24 29
  * Represents a query for RouterOS requests.
25 30
  * 
26 31
  * @category Net
@@ -169,6 +174,17 @@ public function andWhere($name, $value = null, $action = self::ACTION_EXIST)
169 174
      */
170 175
     public function send(Communicator $com)
171 176
     {
  177
+        if ($com->getTransmitter()->isPersistent()) {
  178
+            $old = $com->getTransmitter()->lock(T\Stream::DIRECTION_SEND);
  179
+            $bytes = $this->_send($com);
  180
+            $com->getTransmitter()->lock($old, true);
  181
+            return $bytes;
  182
+        }
  183
+        return $this->_send($com);
  184
+    }
  185
+    
  186
+    private function _send(Communicator $com)
  187
+    {
172 188
         if (!$com->getTransmitter()->isAcceptingData()) {
173 189
             throw new SocketException(
174 190
                 'Transmitter is invalid. Sending aborted.', 30600
28  src/PEAR2/Net/RouterOS/Request.php
@@ -21,6 +21,11 @@
21 21
 namespace PEAR2\Net\RouterOS;
22 22
 
23 23
 /**
  24
+ * Refers to transmitter direction constants.
  25
+ */
  26
+use PEAR2\Net\Transmitter as T;
  27
+
  28
+/**
24 29
  * Represents a RouterOS request.
25 30
  * 
26 31
  * @category Net
@@ -239,6 +244,29 @@ public function removeAllArguments()
239 244
      */
240 245
     public function send(Communicator $com)
241 246
     {
  247
+        if ($com->getTransmitter()->isPersistent()) {
  248
+            $old = $com->getTransmitter()->lock(T\Stream::DIRECTION_SEND);
  249
+            $bytes = $this->_send($com);
  250
+            $com->getTransmitter()->lock($old, true);
  251
+            return $bytes;
  252
+        }
  253
+        return $this->_send($com);
  254
+    }
  255
+
  256
+    /**
  257
+     * Sends a request over a communicator.
  258
+     * 
  259
+     * The only difference with the non private equivalent is that this one does
  260
+     * not do locking.
  261
+     * 
  262
+     * @param Communicator $com The communicator to send the request over.
  263
+     * 
  264
+     * @return int The number of bytes sent.
  265
+     * @see Client::sendSync()
  266
+     * @see Client::sendAsync()
  267
+     */
  268
+    private function _send(Communicator $com)
  269
+    {
242 270
         if (!$com->getTransmitter()->isAcceptingData()) {
243 271
             throw new SocketException(
244 272
                 'Transmitter is invalid. Sending aborted.', 40900
2  tests/RequestHandlingTest.php
@@ -592,7 +592,7 @@ public function testControlByteException()
592 592
                 Communicator::decodeLength($trans);
593 593
             } catch (NotSupportedException $e) {
594 594
                 $this->assertEquals(
595  
-                    1600, $e->getCode(), 'Improper exception code.'
  595
+                    1601, $e->getCode(), 'Improper exception code.'
596 596
                 );
597 597
                 $this->assertEquals(
598 598
                     $controlByte, $e->getValue(), 'Improper exception value.'

0 notes on commit 77cf445

Please sign in to comment.
Something went wrong with that request. Please try again.