public function executeCommand($cmd)
    {
        $this->checkConnected();

        $write = @fwrite($this->socket, "$cmd\r\n");
        if (false === $write) {
            throw new Exception\IOError('Error while writing to the Tor server');
        }

        $data = [];
        while (true) {
            $response = fread($this->socket, 1024);

            $multiline = false;
            $last_code = null;
            $last_separator = null;
            foreach (explode("\r\n", $response) as $line) {
                $code = substr($line, 0, 3);
                $separator = substr($line, 3, 1);
                $message = substr($line, 4);

                if ('+' === $separator) {
                    $multiline = true;
                    $last_code = $code;
                    $last_separator = $separator;
                }

                if ($multiline) {
                    $data[] = [
                        'code' => $last_code,
                        'separator' => $last_separator,
                        'message' => $line,
                    ];
                } else {
                    if (false === $code || false === $separator) {
                        $e = new Exception\ProtocolError('Bad response format');
                        $e->setResponse($response);

                        throw $e;
                    }

                    if (!in_array($separator, [' ', '+', '-'])) {
                        $e = new Exception\ProtocolError('Unknown separator');
                        $e->setResponse($response);

                        throw $e;
                    }

                    if (!in_array(substr($code, 0, 1), ['2', '6'])) {
                        $e = new Exception\TorError($message, $code);
                        $e->setResponse($response);

                        return $e;
                    }

                    $data[] = [
                        'code' => $code,
                        'separator' => $separator,
                        'message' => $message,
                    ];
                }

                if (' ' === $separator) {
                    break 2;
                }
            }
        }

        return $data;
    }