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

WebSocketHandler::limitConcurrentConnections()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.9
c 0
b 0
f 0
cc 3
nc 3
nop 1
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');
0 ignored issues
show
Bug introduced by freek
Accessing httpRequest 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...
68
69
        if (! $app = App::findByKey($appKey)) {
70
            throw new UnknownAppKey($appKey);
71
        }
72
73
        $connection->app = $app;
0 ignored issues
show
Bug introduced by freek
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...
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
Bug introduced by Ahmed Al-Shahawi
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
Bug introduced by Ahmed Al-Shahawi
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;
0 ignored issues
show
Bug introduced by freek
Accessing socketId 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...
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,
0 ignored issues
show
Bug introduced by Marcel Pociot
Accessing socketId 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...
105
                'activity_timeout' => 30,
106
            ]),
107
        ]));
108
109
        DashboardLogger::connection($connection);
110
111
        StatisticsLogger::connection($connection);
112
113
        return $this;
114
    }
115
}
116