Skip to content

Commit

Permalink
Introduces TLS support for secure WebSockets (#43)
Browse files Browse the repository at this point in the history
* add tls support

* refactor away from booleans

* docs

* remove auto secure

* wip

* remove method

* update tests

* formatting

* formatting
  • Loading branch information
joedixon authored Feb 16, 2024
1 parent 50eb7a7 commit 7c0f428
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 3 deletions.
3 changes: 3 additions & 0 deletions config/reverb.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
'reverb' => [
'host' => env('REVERB_HOST', '0.0.0.0'),
'port' => env('REVERB_PORT', 8080),
'options' => [
'tls' => [],
],
'scaling' => [
'enabled' => env('REVERB_SCALING_ENABLED', false),
'channel' => env('REVERB_SCALING_CHANNEL', 'reverb'),
Expand Down
1 change: 1 addition & 0 deletions src/Servers/Reverb/Console/Commands/StartServer.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public function handle(): void
$server = ServerFactory::make(
$host = $this->option('host') ?: $config['host'],
$port = $this->option('port') ?: $config['port'],
$config['options'] ?? [],
loop: $loop
);

Expand Down
6 changes: 4 additions & 2 deletions src/Servers/Reverb/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class Factory
/**
* Create a new WebSocket server instance.
*/
public static function make(string $host = '0.0.0.0', string $port = '8080', string $protocol = 'pusher', ?LoopInterface $loop = null): HttpServer
public static function make(string $host = '0.0.0.0', string $port = '8080', array $options = [], string $protocol = 'pusher', ?LoopInterface $loop = null): HttpServer
{
$loop = $loop ?: Loop::get();

Expand All @@ -43,8 +43,10 @@ public static function make(string $host = '0.0.0.0', string $port = '8080', str
default => throw new InvalidArgumentException("Unsupported protocol [{$protocol}]."),
};

$uri = empty($options['tls']) ? "{$host}:{$port}" : "tls://{$host}:{$port}";

return new HttpServer(
new SocketServer("{$host}:{$port}", [], $loop),
new SocketServer($uri, $options, $loop),
$router,
$loop
);
Expand Down
1 change: 0 additions & 1 deletion tests/ReverbTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
use Laravel\Reverb\ServerProviderManager;
use Laravel\Reverb\Servers\Reverb\Contracts\PubSubProvider;
use Laravel\Reverb\Servers\Reverb\Factory;
use Ratchet\Client\WebSocket;
use React\Async\SimpleFiber;
use React\EventLoop\Loop;
use React\Http\Browser;
Expand Down
57 changes: 57 additions & 0 deletions tests/Unit/Servers/Reverb/FactoryTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

use Laravel\Reverb\Servers\Reverb\Factory;
use React\Socket\SecureServer;
use React\Socket\TcpServer;

it('can create a server', function () {
$server = Factory::make();

$socket = (new ReflectionProperty($server, 'socket'))->getValue($server);
$socketServer = (new ReflectionProperty($socket, 'server'))->getValue($socket);

expect($socketServer)->toBeInstanceOf(TcpServer::class);

$server->stop();
});

it('can create a server with the given host and port', function () {
$server = Factory::make('127.0.0.1', '8001');

$socket = (new ReflectionProperty($server, 'socket'))->getValue($server);
$socketServer = (new ReflectionProperty($socket, 'server'))->getValue($socket);

expect($socketServer)->toBeInstanceOf(TcpServer::class);
expect($socketServer->getAddress())->toBe('tcp://127.0.0.1:8001');

$server->stop();
});

it('can create a tls server using a user provided certificate', function () {
$this->app->config->set('reverb.servers.reverb.options.tls.local_cert', '/path/to/cert.pem');
$this->app->config->set('reverb.servers.reverb.options.tls.verify_peer', false);
$server = Factory::make(options: $this->app->config->get('reverb.servers.reverb.options'));

$socket = (new ReflectionProperty($server, 'socket'))->getValue($server);
$socketServer = (new ReflectionProperty($socket, 'server'))->getValue($socket);
$context = (new ReflectionProperty($socketServer, 'context'))->getValue($socketServer);

expect($socketServer)->toBeInstanceOf(SecureServer::class);
expect($context['local_cert'])->toBe('/path/to/cert.pem');
expect($context['verify_peer'])->toBeFalse();

$server->stop();
});

it('can create a server using tls on the given host and port', function () {
$this->app->config->set('reverb.servers.reverb.options.tls.local_cert', '/path/to/cert.pem');
$server = Factory::make('127.0.0.1', '8002', $this->app->config->get('reverb.servers.reverb.options'));

$socket = (new ReflectionProperty($server, 'socket'))->getValue($server);
$socketServer = (new ReflectionProperty($socket, 'server'))->getValue($socket);

expect($socketServer)->toBeInstanceOf(SecureServer::class);
expect($socketServer->getAddress())->toBe('tls://127.0.0.1:8002');

$server->stop();
});

0 comments on commit 7c0f428

Please sign in to comment.