Completed
Push — master ( 556f43...aecbfe )
by Marcel
01:49
created

src/WebSockets/WebSocketHandler.php (2 issues)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace BeyondCode\LaravelWebSockets\WebSockets;
4
5
use Exception;
6
use Ratchet\ConnectionInterface;
7
use BeyondCode\LaravelWebSockets\Apps\App;
8
use Ratchet\RFC6455\Messaging\MessageInterface;
9
use Ratchet\WebSocket\MessageComponentInterface;
10
use BeyondCode\LaravelWebSockets\QueryParameters;
11
use BeyondCode\LaravelWebSockets\Facades\StatisticsLogger;
12
use BeyondCode\LaravelWebSockets\Dashboard\DashboardLogger;
13
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
14
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\UnknownAppKey;
15
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\WebSocketException;
16
use BeyondCode\LaravelWebSockets\WebSockets\Messages\PusherMessageFactory;
17
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\ConnectionsOverCapacity;
18
19
class WebSocketHandler implements MessageComponentInterface
20
{
21
    /** @var \BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager */
22
    protected $channelManager;
23
24
    public function __construct(ChannelManager $channelManager)
25
    {
26
        $this->channelManager = $channelManager;
27
    }
28
29
    public function onOpen(ConnectionInterface $connection)
30
    {
31
        $this
32
            ->verifyAppKey($connection)
33
            ->limitConcurrentConnections($connection)
34
            ->generateSocketId($connection)
35
            ->establishConnection($connection);
36
    }
37
38
    public function onMessage(ConnectionInterface $connection, MessageInterface $message)
39
    {
40
        $message = PusherMessageFactory::createForMessage($message, $connection, $this->channelManager);
41
42
        $message->respond();
43
44
        StatisticsLogger::webSocketMessage($connection);
45
    }
46
47
    public function onClose(ConnectionInterface $connection)
48
    {
49
        $this->channelManager->removeFromAllChannels($connection);
50
51
        DashboardLogger::disconnection($connection);
52
53
        StatisticsLogger::disconnection($connection);
54
    }
55
56
    public function onError(ConnectionInterface $connection, Exception $exception)
57
    {
58
        if ($exception instanceof WebSocketException) {
59
            $connection->send(json_encode(
60
                $exception->getPayload()
61
            ));
62
        }
63
    }
64
65
    protected function verifyAppKey(ConnectionInterface $connection)
66
    {
67
        $appKey = QueryParameters::create($connection->httpRequest)->get('appKey');
68
69
        if (! $app = App::findByKey($appKey)) {
70
            throw new UnknownAppKey($appKey);
71
        }
72
73
        $connection->app = $app;
74
75
        return $this;
76
    }
77
78
    protected function limitConcurrentConnections(ConnectionInterface $connection)
79
    {
80
        if (! is_null($capacity = $connection->app->capacity)) {
0 ignored issues
show
Accessing app on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
81
            $connectionsCount = $this->channelManager->getConnectionCount($connection->app->id);
0 ignored issues
show
Accessing app on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
82
            if ($connectionsCount >= $capacity) {
83
                throw new ConnectionsOverCapacity();
84
            }
85
        }
86
87
        return $this;
88
    }
89
90
    protected function generateSocketId(ConnectionInterface $connection)
91
    {
92
        $socketId = sprintf('%d.%d', random_int(1, 1000000000), random_int(1, 1000000000));
93
94
        $connection->socketId = $socketId;
95
96
        return $this;
97
    }
98
99
    protected function establishConnection(ConnectionInterface $connection)
100
    {
101
        $connection->send(json_encode([
102
            'event' => 'pusher:connection_established',
103
            'data' => json_encode([
104
                'socket_id' => $connection->socketId,
105
                'activity_timeout' => 30,
106
            ]),
107
        ]));
108
109
        DashboardLogger::connection($connection);
110
111
        StatisticsLogger::connection($connection);
112
113
        return $this;
114
    }
115
}
116