diff --git a/README.md b/README.md index 17d5354..e672559 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ Add the `own3d-socket` configuration within the `config/services.php` config fil 'own3d-socket' => [ 'username' => env('OWN3D_SOCKET_USERNAME', 'own3d-socket'), 'password' => env('OWN3D_SOCKET_PASSWORD') + 'secret' => env('OWN3D_SOCKET_SECRET'), ], ``` diff --git a/src/Own3d/Socket/SocketClient.php b/src/Own3d/Socket/SocketClient.php index 576e54f..ac45ee1 100644 --- a/src/Own3d/Socket/SocketClient.php +++ b/src/Own3d/Socket/SocketClient.php @@ -4,10 +4,19 @@ use GuzzleHttp\Client; use GuzzleHttp\RequestOptions; +use Own3d\Socket\Support\SocketToken; use Throwable; class SocketClient { + /** + * List of available servers. May not be complete. + */ + public const SERVER_IDS = [ + 'socket-edge-hel1-1', + 'socket-edge-hel1-2', + ]; + public static string $baseUrl = 'https://socket-hel1-1.own3d.dev'; private Client $client; @@ -38,10 +47,10 @@ public static function setBaseUrl(string $baseUrl): void * - data: array * * @param array $parameters - * @param array|null $serverId The server id is the hostname, that should receive the message (optional). + * @param string|null $serverId The server id is the hostname, that should receive the message (optional). * @return bool */ - public function emit(array $parameters, array $serverId = null): bool + public function emit(array $parameters, string $serverId = null): bool { $options = [ RequestOptions::JSON => $parameters, @@ -64,6 +73,34 @@ public function emit(array $parameters, array $serverId = null): bool return in_array($response->getStatusCode(), [200, 204]); } + /** + * Sends a message into the own3d websocket system. + * + * @param string $token Pre-signed token for the socket server to emit a message. + * @param string|null $serverId The server id is the hostname, that should receive the message (optional). + * @return bool + */ + public function jwtEmit(string $token, string $serverId = null): bool + { + $options = [ + RequestOptions::JSON => [ + 'token' => $token, + ], + ]; + + if ($serverId) { + $options[RequestOptions::HEADERS]['cookie'] = sprintf('serverid=%s', $serverId); + } + + try { + $response = $this->getClient()->post('jwt-emit', $options); + } catch (Throwable $exception) { + return false; + } + + return in_array($response->getStatusCode(), [200, 204]); + } + public function getClient(): Client { return $this->client; diff --git a/src/Own3d/Socket/Support/SocketToken.php b/src/Own3d/Socket/Support/SocketToken.php new file mode 100644 index 0000000..4e667b1 --- /dev/null +++ b/src/Own3d/Socket/Support/SocketToken.php @@ -0,0 +1,58 @@ + 'auth', + 'room' => $room, + ], 60 * 15)); + } + + /** + * Generate a pre-signed token for the socket server to emit a message. + */ + public static function emit(string $room, string $event, array $data): string + { + return self::encode(self::payload('emit', [ + 'room' => $room, + 'event' => $event, + 'data' => $data, + ], 60 * 15)); + } + + /** + * Helper to generate a JWT token. + */ + public static function encode(array $payload): string + { + return JWT::encode($payload, config('services.own3d-socket.secret'), self::ALGORITHM); + } + + /** + * Helper to decode a JWT token. + */ + private static function payload(string $type, array $extra, float $ttl): array + { + return array_merge([ + 'type' => $type, + 'iat' => time(), + 'exp' => time() + $ttl, + ], $extra); + } +} \ No newline at end of file