This commit is contained in:
Marcel Pociot 2018-11-21 15:42:04 +01:00
parent 8b1e183043
commit 2344c7b704
6 changed files with 78 additions and 4 deletions

View File

@ -23,6 +23,7 @@
],
"require": {
"php": "^7.1",
"ext-json": "*",
"cboden/ratchet": "^0.4.1",
"illuminate/console": "5.6.*|5.7.*",
"illuminate/http": "5.6.*|5.7.*",

View File

@ -2,13 +2,31 @@
namespace BeyondCode\LaravelWebSockets\LaravelEcho\Http\Controllers;
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels\ChannelManager;
use Illuminate\Http\Request;
class EventController extends EchoController
{
/** @var ChannelManager */
private $channelManager;
public function __construct(ChannelManager $channelManager)
{
$this->channelManager = $channelManager;
}
public function __invoke(Request $request)
{
foreach ($request->json()->get('channels', []) as $channelId) {
$channel = $this->channelManager->find($channelId);
$channel->broadcast([
'channel' => $channelId,
'event' => $request->json()->get('name'),
'data' => $request->json()->get('data'),
]);
}
return $request->json()->all();
}
}

View File

@ -2,20 +2,54 @@
namespace BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels;
use Illuminate\Support\Collection;
use Ratchet\ConnectionInterface;
class Channel
{
protected $channelId;
/** @var ConnectionInterface[] */
protected $connections = [];
public function __construct($channelId)
{
$this->channelId = $channelId;
}
/**
* @link https://pusher.com/docs/pusher_protocol#presence-channel-events
*
* @param ConnectionInterface $conn
* @param $payload
*/
public function subscribe(ConnectionInterface $conn, $payload)
{
$this->saveConnection($conn);
// Send the success event
$conn->send(json_encode([
'event' => 'pusher_internal:subscription_succeeded',
'channel' => $this->channelId
]));
}
protected function saveConnection(ConnectionInterface $conn)
{
$this->connections[$conn->socketId] = $conn;
}
public function broadcast($payload)
{
foreach ($this->connections as $connection) {
$connection->send(json_encode($payload));
}
}
public function broadcastToOthers($conn, $payload)
{
Collection::make($this->connections)->reject(function($connection) use ($conn) {
return $connection->socketId === $conn->socketId;
})->each->send(json_encode($payload));
}
}

View File

@ -17,6 +17,11 @@ class ChannelManager
return $this->channels[$channelId];
}
public function find(string $channelId)
{
return $this->channels[$channelId] ?? null;
}
protected function detectChannelClass($channelId) : string
{
if (starts_with($channelId, 'private-')) {

View File

@ -16,6 +16,8 @@ class PresenceChannel extends Channel
*/
public function subscribe(ConnectionInterface $conn, $payload)
{
$this->saveConnection($conn);
$channelData = json_decode($payload->channel_data);
$this->subscriptions[$channelData->user_id] = $channelData;

View File

@ -25,6 +25,10 @@ class EchoServer extends WebSocketController
function onOpen(ConnectionInterface $conn)
{
dump("Client connected");
/**
* There are a couple things we need to do here:
* 1. Authenticate the incoming request by validating the provided APP-ID is known to us (JSON file lookup?)
*/
$socketId = sprintf("%d.%d", getmypid(), random_int(1, 100000000));
@ -43,11 +47,21 @@ class EchoServer extends WebSocketController
dump("Received payload", $payload);
// todo: validate payload
$event = camel_case(str_replace(':', '_', $payload->event));
/**
* Pusher events get a special treatment
*/
if (starts_with($payload->event, 'pusher:')) {
$event = camel_case(str_replace(':', '_', $payload->event));
if (method_exists($this, $event)) {
call_user_func([$this, $event], $conn, $payload->data);
if (method_exists($this, $event)) {
call_user_func([$this, $event], $conn, $payload->data);
}
} else {
// Try to find a channel and broadcast the message to the clients.
$channel = $this->channelManager->find($payload->channel);
if ($channel) {
$channel->broadcast($payload);
}
}
}