From c9d239213c3537d25aea4b4186995f3d348fdd89 Mon Sep 17 00:00:00 2001 From: Simon Hamp Date: Thu, 9 Nov 2017 18:05:03 +0000 Subject: [PATCH 01/12] Update dependencies --- composer.json | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index 1256f97..2e4990d 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "pelim/laravel-zmq", - "description": "zmq support for Laravel5", + "description": "zmq support for Laravel 5", "license": "MIT", "authors": [ { @@ -8,17 +8,16 @@ "email": "peter.limbach@gmail.com" } ], - "require": { "ext-zmq": "*", - "illuminate/broadcasting": "5.2.*", - "illuminate/contracts": "5.2.*" + "illuminate/broadcasting": "5.5.*", + "illuminate/contracts": "5.5.*" }, "autoload": { "psr-4": { "Pelim\\LaravelZmq\\": "src/" } }, - "minimum-stability": "dev", - "prefer-stable": false + "minimum-stability": "dev", + "prefer-stable": false } \ No newline at end of file From 3608c08d0f81e8bdb9e12d71931977a9a5b32cb2 Mon Sep 17 00:00:00 2001 From: Simon Hamp Date: Thu, 9 Nov 2017 18:09:22 +0000 Subject: [PATCH 02/12] Add Laravel autoloading --- composer.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/composer.json b/composer.json index 2e4990d..302f077 100644 --- a/composer.json +++ b/composer.json @@ -18,6 +18,13 @@ "Pelim\\LaravelZmq\\": "src/" } }, + "extra": { + "laravel": { + "providers": [ + "Pelim\\LaravelZmq\\ZmqServiceProvider" + ] + } + }, "minimum-stability": "dev", "prefer-stable": false } \ No newline at end of file From 3de455e3042de9e6c8c88231bb345384609b63b1 Mon Sep 17 00:00:00 2001 From: Simon Hamp Date: Thu, 9 Nov 2017 18:14:25 +0000 Subject: [PATCH 03/12] Fix config ref error --- src/Zmq.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Zmq.php b/src/Zmq.php index cb30787..8f1099c 100644 --- a/src/Zmq.php +++ b/src/Zmq.php @@ -35,9 +35,9 @@ public function connection($connection = null) { if(!$connection) { - $connection = \Config::get('zmg.default'); + $connection = \Config::get('zmq.default'); } - + return \App::make(sprintf('zmq.connection.%s', $connection))->connect(); } From 73050ae95d61ce0de15536087616ba235ad812a2 Mon Sep 17 00:00:00 2001 From: Simon Hamp Date: Fri, 10 Nov 2017 15:45:25 +0000 Subject: [PATCH 04/12] Fix broadcasting for Laravel 5.5 --- .../Broadcaster/ZmqBroadcaster.php | 49 ++++++++++++++++--- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/src/Broadcasting/Broadcaster/ZmqBroadcaster.php b/src/Broadcasting/Broadcaster/ZmqBroadcaster.php index 59d4156..cb71a57 100644 --- a/src/Broadcasting/Broadcaster/ZmqBroadcaster.php +++ b/src/Broadcasting/Broadcaster/ZmqBroadcaster.php @@ -2,22 +2,24 @@ namespace Pelim\LaravelZmq\Broadcasting\Broadcaster; -use Illuminate\Contracts\Broadcasting\Broadcaster; -use Pelim\LaravelZmq\Connector\ZmqConnector; use Pelim\LaravelZmq\Zmq; +use \Illuminate\Http\Request; +use Pelim\LaravelZmq\Connector\ZmqConnector; +use Illuminate\Broadcasting\Broadcasters\Broadcaster; +use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; /** * Class ZmqBroadcaster * @package Pelim\LaravelZmq\Broadcasting\Broadcaster */ -class ZmqBroadcaster implements Broadcaster +class ZmqBroadcaster extends Broadcaster { /** * @var Zmq */ protected $zmq; - + /** * ZmqBroadcaster constructor. @@ -27,7 +29,7 @@ public function __construct(Zmq $zmq) { $this->zmq = $zmq; } - + /** * {@inheritdoc} */ @@ -35,4 +37,39 @@ public function broadcast(array $channels, $event, array $payload = []) { $this->zmq->publish($channels, $event, $payload, 'publish'); } -} \ No newline at end of file + + public function auth($request) + { + if (Str::startsWith($request->channel_name, ['private-', 'presence-']) && + ! $request->user()) { + throw new AccessDeniedHttpException; + } + + $channelName = Str::startsWith($request->channel_name, 'private-') + ? Str::replaceFirst('private-', '', $request->channel_name) + : Str::replaceFirst('presence-', '', $request->channel_name); + + return parent::verifyUserCanAccessChannel( + $request, + $channelName + ); + } + + public function validAuthenticationResponse($request, $result) + { + if (Str::startsWith($request->channel_name, 'private')) { + return $this->decodePusherResponse( + $this->pusher->socket_auth($request->channel_name, $request->socket_id) + ); + } + + return $this->decodePusherResponse( + $this->pusher->presence_auth( + $request->channel_name, + $request->socket_id, + $request->user()->getAuthIdentifier(), + $result + ) + ); + } +} From e1c2de839efc05e8b72d9d15123ff7c08b0cebda Mon Sep 17 00:00:00 2001 From: Simon Hamp Date: Sat, 11 Nov 2017 12:23:15 +0000 Subject: [PATCH 05/12] Make socket methods dynamic based on config --- src/Connector/ZmqPublish.php | 12 ++++++------ src/Connector/ZmqSubscribe.php | 15 ++++++++++----- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/Connector/ZmqPublish.php b/src/Connector/ZmqPublish.php index 5facb73..4674344 100644 --- a/src/Connector/ZmqPublish.php +++ b/src/Connector/ZmqPublish.php @@ -6,8 +6,8 @@ * Class ZmqConnector * @package Pelim\LaravelZmq\Connector */ -class ZmqPublish extends ZmqConnector { - +class ZmqPublish extends ZmqConnector +{ /** * ZmqPublish constructor. * @param string $connection @@ -18,17 +18,17 @@ public function __construct($connection = 'publish') } /** + * Connect to the socket for publishing. * @return \ZMQSocket */ - public function connect() + public function connect() { $context = new \ZMQContext(); - $socket = new \ZMQSocket($context, \ZMQ::SOCKET_PUB); + $socket = $context->getSocket(config("zmq.{$this->connection}.method", \ZMQ::SOCKET_PUB)); $socket->connect($this->dsn()); - // @need some sleep at :-( usleep(500); return $socket; } -} \ No newline at end of file +} diff --git a/src/Connector/ZmqSubscribe.php b/src/Connector/ZmqSubscribe.php index 53c6e30..f04886c 100644 --- a/src/Connector/ZmqSubscribe.php +++ b/src/Connector/ZmqSubscribe.php @@ -6,8 +6,8 @@ * Class ZmqConnector * @package Pelim\LaravelZmq\Connector */ -class ZmqSubscribe extends ZmqConnector { - +class ZmqSubscribe extends ZmqConnector +{ /** * ZmqPublish constructor. * @param string $connection @@ -17,12 +17,17 @@ public function __construct($connection = 'subscribe') parent::__construct($connection); } + /** + * Connect to the socket for subscribing. + * + * @return \ZMQSocket + */ public function connect() { $context = new \ZMQContext(); - $socket = new \ZMQSocket($context, \ZMQ::SOCKET_SUB); + $socket = $context->getSocket(config("zmq.{$this->connection}.method", \ZMQ::SOCKET_SUB)); $socket->bind($this->dsn()); - + return $socket; } -} \ No newline at end of file +} From 990b34481a72d35c75a9f91d4749cbdd41f1bcc7 Mon Sep 17 00:00:00 2001 From: Simon Hamp Date: Sat, 11 Nov 2017 12:23:58 +0000 Subject: [PATCH 06/12] Set default socket methods in config --- config/zmq.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config/zmq.php b/config/zmq.php index b942b46..12894db 100644 --- a/config/zmq.php +++ b/config/zmq.php @@ -1,19 +1,19 @@ 'publish', - + 'connections' => [ 'publish' => [ 'dsn' => 'tcp://127.0.0.1:5555', + 'method' => \ZMQ::SOCET_PUB, ], 'subscribe' => [ 'dsn' => 'tcp://0.0.0.0:5555', + 'method' => \ZMQ::SOCET_SUB, ], ] -]; \ No newline at end of file +]; From 9ddbad4030c8198233c4a0744ce6fc624c1c427c Mon Sep 17 00:00:00 2001 From: Simon Hamp Date: Sat, 11 Nov 2017 12:24:13 +0000 Subject: [PATCH 07/12] Code cleanup --- src/Connector/ZmqConnector.php | 6 +++--- src/Zmq.php | 15 ++++----------- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/Connector/ZmqConnector.php b/src/Connector/ZmqConnector.php index 99f5bff..06c2b31 100644 --- a/src/Connector/ZmqConnector.php +++ b/src/Connector/ZmqConnector.php @@ -6,8 +6,8 @@ * Class ZmqConnector * @package Pelim\LaravelZmq\Connector */ -abstract class ZmqConnector { - +abstract class ZmqConnector +{ protected $connection; public function __construct($connection) @@ -24,4 +24,4 @@ protected function dsn() { return \Config::get(sprintf('zmq.connections.%s.dsn', $this->connection), 'tcp://127.0.0.1:5555'); } -} \ No newline at end of file +} diff --git a/src/Zmq.php b/src/Zmq.php index 8f1099c..427f444 100644 --- a/src/Zmq.php +++ b/src/Zmq.php @@ -34,7 +34,7 @@ public function __construct(array $connections = []) public function connection($connection = null) { - if(!$connection) { + if (! $connection) { $connection = \Config::get('zmq.default'); } @@ -48,7 +48,6 @@ public function connection($connection = null) */ public function subscribe(array $channels, \Closure $callback, $connection = 'subscribe') { - $connection = $this->connection($connection); foreach ($channels as $channel) { @@ -60,7 +59,6 @@ public function subscribe(array $channels, \Closure $callback, $connection = 'su } while (true) { - $channel = $connection->recv(); $payload = $connection->recv(); @@ -70,11 +68,9 @@ public function subscribe(array $channels, \Closure $callback, $connection = 'su $payload = [$payload]; } - call_user_func($callback, $payload, $channel); usleep(10); - } } @@ -88,15 +84,13 @@ public function publish(array $channels, $event, $payload = [], $connection = 'p { $connection = $this->connection($connection); - if($payload) { + if ($payload) { $payload = json_encode(['event' => $event, 'payload' => $payload]); } else { $payload = $event; } - - foreach($channels as $channel) { - + foreach ($channels as $channel) { \Log::debug('zmq.publish', [ 'channel' => $channel, 'payload' => $payload @@ -105,5 +99,4 @@ public function publish(array $channels, $event, $payload = [], $connection = 'p $connection->send($channel, \ZMQ::MODE_SNDMORE)->send($payload); } } - -} \ No newline at end of file +} From a7fd8905a9acd7510ba08da1171d4cb70973a187 Mon Sep 17 00:00:00 2001 From: Simon Hamp Date: Sat, 11 Nov 2017 12:27:03 +0000 Subject: [PATCH 08/12] Fix typo in default config --- config/zmq.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/zmq.php b/config/zmq.php index 12894db..d75d891 100644 --- a/config/zmq.php +++ b/config/zmq.php @@ -7,12 +7,12 @@ 'publish' => [ 'dsn' => 'tcp://127.0.0.1:5555', - 'method' => \ZMQ::SOCET_PUB, + 'method' => \ZMQ::SOCKET_PUB, ], 'subscribe' => [ 'dsn' => 'tcp://0.0.0.0:5555', - 'method' => \ZMQ::SOCET_SUB, + 'method' => \ZMQ::SOCKET_SUB, ], ] From cdb6cb7e5ab4ff7e41f6677b84712de96e173e4b Mon Sep 17 00:00:00 2001 From: Simon Hamp Date: Mon, 13 Nov 2017 10:18:23 +0000 Subject: [PATCH 09/12] Fix and normalise config variable fetch --- src/Connector/ZmqPublish.php | 3 ++- src/Connector/ZmqSubscribe.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Connector/ZmqPublish.php b/src/Connector/ZmqPublish.php index 4674344..8005690 100644 --- a/src/Connector/ZmqPublish.php +++ b/src/Connector/ZmqPublish.php @@ -24,7 +24,8 @@ public function __construct($connection = 'publish') public function connect() { $context = new \ZMQContext(); - $socket = $context->getSocket(config("zmq.{$this->connection}.method", \ZMQ::SOCKET_PUB)); + $socket_method = \Config::get(sprintf('zmq.connections.%s.method', $this->connection), \ZMQ::SOCKET_PUB); + $socket = $context->getSocket($socket_method); $socket->connect($this->dsn()); usleep(500); diff --git a/src/Connector/ZmqSubscribe.php b/src/Connector/ZmqSubscribe.php index f04886c..f7fd109 100644 --- a/src/Connector/ZmqSubscribe.php +++ b/src/Connector/ZmqSubscribe.php @@ -25,7 +25,8 @@ public function __construct($connection = 'subscribe') public function connect() { $context = new \ZMQContext(); - $socket = $context->getSocket(config("zmq.{$this->connection}.method", \ZMQ::SOCKET_SUB)); + $socket_method = \Config::get(sprintf('zmq.connections.%s.method', $this->connection), \ZMQ::SOCKET_SUB); + $socket = $context->getSocket($socket_method); $socket->bind($this->dsn()); return $socket; From 9e2401464ba1d14ea20dffabc73aa221dd18ff7c Mon Sep 17 00:00:00 2001 From: Simon Hamp Date: Mon, 13 Nov 2017 10:18:48 +0000 Subject: [PATCH 10/12] Log just channel name Keeps logs a bit leaner --- src/Zmq.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Zmq.php b/src/Zmq.php index 427f444..3503dd0 100644 --- a/src/Zmq.php +++ b/src/Zmq.php @@ -92,7 +92,7 @@ public function publish(array $channels, $event, $payload = [], $connection = 'p foreach ($channels as $channel) { \Log::debug('zmq.publish', [ - 'channel' => $channel, + 'channel' => $channel->name, 'payload' => $payload ]); From 39e79358c69e589851c4b5cc0fb37056a14d8c1b Mon Sep 17 00:00:00 2001 From: Simon Hamp Date: Tue, 14 Nov 2017 11:05:33 +0000 Subject: [PATCH 11/12] Improve docs --- README.md | 30 ++++++++++++++++++++++++------ composer.json | 2 +- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index c62a72b..9721a72 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,36 @@ -# laravel-zmq +# Laravel ZeroMQ -subscribe laravel worker to zmq notifications i.e to verify btcoind tx +A Laravel wrapper for `ext-zmq` that exposes a `zmq` broadcast driver to publish your Laravel events via ZeroMQ. ## Requirements -* zmq php ext -* laravel 5.2 +- PHP 7.1 +- Laravel 5.5 +- ZeroMQ +- ext-zmq for PHP ## Installation -include the service provider into your laravel app +```bash +$ composer require pelim/laravel-zmq +``` -`php artisan vendor:publish` +The service provider is loaded automatically in Laravel 5.5 using Package Autodiscovery. +Publish vendor files to create your `config/zmq.php` file +```bash +$ php artisan vendor:publish --provider="Pelim\ZmqServiceProvider" +``` +Update your `config/zmq.php` with the appropriate socket details. +Set `BROADCASTING_DRIVER=zmq` in your `.env` and add the following ZeroMQ connection settings to your `config/broadcasting.php`: + +```php +'connections' => [ + 'zmq' => [ + 'driver' => 'zmq', + ], +] +``` diff --git a/composer.json b/composer.json index 302f077..66ffb83 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "pelim/laravel-zmq", - "description": "zmq support for Laravel 5", + "description": "A ZeroMQ broadcast driver for Laravel 5", "license": "MIT", "authors": [ { From d79f089853492e8b05388d5df31b2100ad19bda4 Mon Sep 17 00:00:00 2001 From: Simon Hamp Date: Tue, 14 Nov 2017 11:39:24 +0000 Subject: [PATCH 12/12] A bunch of fixes Improve requires, fix some actual bugs and improve code style --- composer.json | 3 +- .../Broadcaster/ZmqBroadcaster.php | 36 ++++++---- src/ZmqServiceProvider.php | 71 ++++++++++--------- 3 files changed, 59 insertions(+), 51 deletions(-) diff --git a/composer.json b/composer.json index 66ffb83..69397c9 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,8 @@ "require": { "ext-zmq": "*", "illuminate/broadcasting": "5.5.*", - "illuminate/contracts": "5.5.*" + "illuminate/contracts": "5.5.*", + "illuminate/http": "5.5.*" }, "autoload": { "psr-4": { diff --git a/src/Broadcasting/Broadcaster/ZmqBroadcaster.php b/src/Broadcasting/Broadcaster/ZmqBroadcaster.php index cb71a57..153709f 100644 --- a/src/Broadcasting/Broadcaster/ZmqBroadcaster.php +++ b/src/Broadcasting/Broadcaster/ZmqBroadcaster.php @@ -3,7 +3,7 @@ namespace Pelim\LaravelZmq\Broadcasting\Broadcaster; use Pelim\LaravelZmq\Zmq; -use \Illuminate\Http\Request; +use Illuminate\Http\Request; use Pelim\LaravelZmq\Connector\ZmqConnector; use Illuminate\Broadcasting\Broadcasters\Broadcaster; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; @@ -14,13 +14,11 @@ */ class ZmqBroadcaster extends Broadcaster { - /** * @var Zmq */ protected $zmq; - /** * ZmqBroadcaster constructor. * @param Zmq $zmq @@ -38,6 +36,13 @@ public function broadcast(array $channels, $event, array $payload = []) $this->zmq->publish($channels, $event, $payload, 'publish'); } + /** + * Authenticate the incoming request for a given channel. + * + * @param \Illuminate\Http\Request $request + * @return mixed + * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException + */ public function auth($request) { if (Str::startsWith($request->channel_name, ['private-', 'presence-']) && @@ -55,21 +60,22 @@ public function auth($request) ); } + /** + * Return the valid authentication response. + * + * @param \Illuminate\Http\Request $request + * @param mixed $result + * @return mixed + */ public function validAuthenticationResponse($request, $result) { - if (Str::startsWith($request->channel_name, 'private')) { - return $this->decodePusherResponse( - $this->pusher->socket_auth($request->channel_name, $request->socket_id) - ); + if (is_bool($result)) { + return json_encode($result); } - return $this->decodePusherResponse( - $this->pusher->presence_auth( - $request->channel_name, - $request->socket_id, - $request->user()->getAuthIdentifier(), - $result - ) - ); + return json_encode(['channel_data' => [ + 'user_id' => $request->user()->getAuthIdentifier(), + 'user_info' => $result, + ]]); } } diff --git a/src/ZmqServiceProvider.php b/src/ZmqServiceProvider.php index 5362d0e..2f42ffd 100644 --- a/src/ZmqServiceProvider.php +++ b/src/ZmqServiceProvider.php @@ -3,45 +3,46 @@ namespace Pelim\LaravelZmq; use Illuminate\Support\ServiceProvider; -use Pelim\LaravelZmq\Broadcasting\Broadcaster\ZmqBroadcaster; use Pelim\LaravelZmq\Connector\ZmqPublish; use Pelim\LaravelZmq\Connector\ZmqSubscribe; +use Pelim\LaravelZmq\Broadcasting\Broadcaster\ZmqBroadcaster; /** * Class ZmqServiceProvider * @package Pelim\LaravelZmq */ - -class ZmqServiceProvider extends ServiceProvider { - - public function boot() { - - $this->publishes([__DIR__ .'/../config/zmq.php' => config_path('zmq.php')]); - - $this->app->make('Illuminate\Contracts\Broadcasting\Factory')->extend('zmq', function ($app) { - return new ZmqBroadcaster($this->app['zmq']); - }); - } - - public function register() { - - $this->app->singleton('zmq', function ($app) { - return new Zmq(); - }); - - $this->app->singleton('zmq.connection.publish', function ($app) { - return new ZmqPublish(); - }); - - $this->app->singleton('zmq.connection.subscribe', function ($app) { - return new ZmqSubscribe(); - }); - } - - /** - * @return array - */ - public function provides() { - return ['zmq', 'zmq.connection.subscribe', 'zqm.connection.publish']; - } -} \ No newline at end of file +class ZmqServiceProvider extends ServiceProvider +{ + public function boot() + { + $this->publishes([__DIR__ .'/../config/zmq.php' => config_path('zmq.php')]); + + $this->app->make('Illuminate\Contracts\Broadcasting\Factory') + ->extend('zmq', function ($app) { + return new ZmqBroadcaster($this->app['zmq']); + }); + } + + public function register() + { + $this->app->singleton('zmq', function ($app) { + return new Zmq(); + }); + + $this->app->singleton('zmq.connection.publish', function ($app) { + return new ZmqPublish(); + }); + + $this->app->singleton('zmq.connection.subscribe', function ($app) { + return new ZmqSubscribe(); + }); + } + + /** + * @return array + */ + public function provides() + { + return ['zmq', 'zmq.connection.subscribe', 'zqm.connection.publish']; + } +}