Skip to content

Commit

Permalink
Merge pull request #5 from matracine/fixread
Browse files Browse the repository at this point in the history
Fix #2: Change read logic
  • Loading branch information
EvilFreelancer authored Mar 11, 2019
2 parents 952e4ef + b00d896 commit 00a84b7
Showing 1 changed file with 24 additions and 12 deletions.
36 changes: 24 additions & 12 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -224,13 +224,21 @@ public function write($query): Client
/**
* Read answer from server after query was executed
*
* A Mikrotik reply is formed of blocks
* Each block starts with a word, one of ('!re', '!trap', '!done', '!fatal')
* Each block end with an zero byte (empty line)
* Reply ends with a complete !done or !fatal block (ended with 'empty line')
* A !fatal block precedes TCP connexion close
*
* @param bool $parse
* @return array
*/
public function read(bool $parse = true): array
{
// By default response is empty
$response = [];
// We have to wait a !done or !fatal
$lastReply = false;

// Read answer from socket in loop
while (true) {
Expand All @@ -239,21 +247,25 @@ public function read(bool $parse = true): array
$byte = fread($this->_socket, 1);
$length = $this->getLength(\ord($byte));

// Save only non empty strings
if ($length > 0) {
// Save output line to response array
$response[] = stream_get_contents($this->_socket, $length);
if ($length == 0) {
if ($lastReply) {
// We received a !done or !fatal message in a precedent loop
// response is complete
break;
}
// We did not receive the !done or !fatal message
// This 0 length message is the end of a reply !re or !trap
// We have to wait the router to send a !done or !fatal reply followed by optionals values and a 0 length message
continue;
}

// If we get a !done line in response, change state of $isDone variable
$isDone = ('!done' === end($response));

// Get status about latest operation
$status = stream_get_meta_data($this->_socket);
// Save output line to response array
$response[] = $line = stream_get_contents($this->_socket, $length);

// If we do not have unread bytes from socket or <-same and if done, then exit from loop
if ((!$status['unread_bytes']) || (!$status['unread_bytes'] && $isDone)) {
break;
// If we get a !done or !fatal line in response, we are now ready to finish the read
// but we need to wait a 0 length message, switch the flag
if ('!done' === $line || '!fatal' === $line) {
$lastReply = true;
}
}

Expand Down

0 comments on commit 00a84b7

Please sign in to comment.