protected function getMessage($requestId, $timeout) { $this->setTimeout($timeout); $header = $this->readHeaderFromSocket(); if ($requestId != $header['responseTo']) { throw new \RuntimeException(sprintf('request/cursor mismatch: %d vs %d', $requestId, $header['responseTo'])); } $data = $this->readFromSocket($header['messageLength'] - Protocol::MSG_HEADER_SIZE); $header = substr($data, 0, 20); $vars = unpack('Vflags/V2cursorId/VstartingFrom/VnumberReturned', $header); $documents = bson_decode_multiple(substr($data, 20)); if ($documents) { $this->throwExceptionIfError($documents[0]); } else { $documents = []; } return ['result' => $documents, 'cursorId' => Util::decodeInt64($vars['cursorId1'], $vars['cursorId2']) ?: null, 'start' => $vars['startingFrom'], 'count' => $vars['numberReturned']]; }
public static function decDocument($data, &$offset) { $docLen = Util::unpack('Vlen', $data, $offset, 4)['len'] - 5; // subtract len. and null-terminator $document = []; $parsedLen = 0; while (0 !== ord($data[$offset])) { $elmLen = $offset; $elm = self::decElement($data, $offset); $parsedLen += $offset - $elmLen; $document[$elm[0]] = $elm[1]; } if ($docLen !== $parsedLen) { throw new \RuntimeException(sprintf('Document length doesn\'t match total size of parsed elements (%d:%d)', $docLen, $parsedLen)); } $offset++; // add one byte for document nul-terminator return $document; }