From e6ba73430b79632f83c7ef636f0e8fca62b4d4f1 Mon Sep 17 00:00:00 2001 From: Anonymous Contributor Date: Sun, 10 Sep 2023 07:41:42 +0200 Subject: [PATCH] Add simple OpenSimulator RestConsole client --- app/opensim/RestConsole.php | 124 ++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 app/opensim/RestConsole.php diff --git a/app/opensim/RestConsole.php b/app/opensim/RestConsole.php new file mode 100644 index 0000000..3c9ec40 --- /dev/null +++ b/app/opensim/RestConsole.php @@ -0,0 +1,124 @@ +baseUrl = "http://".$host.':'.$port; + } + + public function startSession(string $username, string $password): bool + { + $response = $this->sendRequest('/StartSession/', [ + 'USER' => $username, + 'PASS' => $password + ]); + + if ($this->detectError($response, '/StartSession/')) { + return false; + } + + $this->sessionId = $response['SessionID']; + $this->readResponses(); + return true; + } + + public function readResponses(): array + { + if ($this->sessionId == null) { + return array(); + } + + $response = $this->sendRequest('/ReadResponses/'.$this->sessionId); + if ($this->detectError($response, '/ReadResponses/')) { + return array(); + } + + return $response['Line']; + } + + public function sendCommand(string $command): bool + { + $response = $this->sendRequest('/SessionCommand/', [ + 'ID' => $this->sessionId, + 'COMMAND' => $command + ]); + + if ($this->detectError($response, '/SessionCommand/')) { + return false; + } + + return $response['Result'] == 'OK'; + } + + private function detectError(array|int $response, string $request): bool + { + if (gettype($response) == 'integer') { + error_log('OS RestConsole request '.$this->baseUrl.$request.' failed, status: '.$response); + return true; + } + + return false; + } + + private function sendRequest(string $request, array $data = array()): array|int + { + $curl = curl_init($this->baseUrl.$request); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_USERAGENT, 'mcp-restconsole/0.0.1'); + curl_setopt($curl, CURLOPT_HTTPHEADER, [ + 'Accept' => 'text/xml' + ]); + + $postData = ''; + foreach ($data as $key => $val) { + $postData = $postData.(strlen($postData) > 0 ? '&' : '').$key.'='.$val; + } + curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); + + $res = curl_exec($curl); + $status = curl_getinfo($curl, CURLINFO_HTTP_CODE); + if ($status != 200) { + return $status; + } + + + return $this->parseXml($res); + } + + private function parseXml(string $response): array + { + $xmlReader = XMLReader::XML($response, "UTF-8"); + $res = array(); + if ($xmlReader->next()) { + $consoleSession = $xmlReader->expand(); + if ($consoleSession->nodeName == 'ConsoleSession') { + foreach ($consoleSession->childNodes as $childNode) { + $name = $childNode->nodeName; + if (isset($res[$name])) { + if (gettype($res[$name]) == 'string') { + $res[$name] = array($res[$name], $childNode->nodeValue); + } + else { + $res[$name][] = $childNode->nodeValue; + } + } + else { + $res[$name] = $childNode->nodeValue; + } + } + } + } + + return $res; + } +}