1 | <?php |
||
32 | abstract class AbstractClientManager extends AbstractManager implements |
||
33 | MessageComponentInterface, |
||
34 | EventSubscriberInterface, |
||
35 | HandlerInterface |
||
36 | { |
||
37 | |||
38 | use DelegatesMessagesTrait; |
||
39 | |||
40 | /** |
||
41 | * @var \SplObjectStorage the connected clients |
||
42 | */ |
||
43 | protected $_connectedClients; |
||
44 | |||
45 | /** |
||
46 | * @var \SplObjectStorage the authenticated clients |
||
47 | */ |
||
48 | protected $_authenticatedClients; |
||
49 | |||
50 | |||
51 | /** |
||
52 | * WebSocketManager constructor. |
||
53 | * |
||
54 | * @param Configuration $configuration |
||
55 | * @param LoggerInterface $logger |
||
56 | * @param EventDispatcher $eventDispatcher |
||
57 | */ |
||
58 | 4 | public function __construct( |
|
69 | |||
70 | |||
71 | /** |
||
72 | * @inheritdoc |
||
73 | */ |
||
74 | 4 | public static function getSubscribedEvents() |
|
75 | { |
||
76 | return [ |
||
77 | 4 | Events::INSTANCE_STATUS_UPDATES => 'onInstanceStatusUpdates', |
|
78 | ]; |
||
79 | } |
||
80 | |||
81 | |||
82 | /** |
||
83 | * @param InstanceStatusUpdatesEvent $event |
||
84 | */ |
||
85 | 1 | public function onInstanceStatusUpdates(InstanceStatusUpdatesEvent $event) |
|
86 | { |
||
87 | 1 | $this->logger->debug('Broadcasting statuses to all clients'); |
|
88 | 1 | $message = new StatusUpdatesMessage($event->getInstanceStatusCollection()); |
|
89 | |||
90 | 1 | foreach ($this->_authenticatedClients as $client) |
|
91 | { |
||
92 | /* @var ConnectionInterface $client */ |
||
93 | 1 | $this->sendMessage($message, $client); |
|
94 | } |
||
95 | 1 | } |
|
96 | |||
97 | |||
98 | /** |
||
99 | * @inheritdoc |
||
100 | */ |
||
101 | 4 | public function onOpen(ConnectionInterface $conn) |
|
106 | |||
107 | |||
108 | /** |
||
109 | * @inheritdoc |
||
110 | */ |
||
111 | public function onClose(ConnectionInterface $conn) |
||
118 | |||
119 | |||
120 | /** |
||
121 | * @inheritdoc |
||
122 | */ |
||
123 | public function onError(ConnectionInterface $conn, \Exception $e) |
||
127 | |||
128 | |||
129 | /** |
||
130 | * @inheritdoc |
||
131 | */ |
||
132 | 3 | public function handleMessage(AbstractMessage $message, ConnectionInterface $sender) |
|
133 | { |
||
134 | 3 | if ($message->getType() !== AbstractMessage::TYPE_AUTHENTICATION_REQUEST) |
|
135 | return false; |
||
136 | |||
137 | /* @var AuthenticationRequest $message */ |
||
138 | 3 | $status = AuthenticationResponse::STATUS_FAILURE; |
|
139 | |||
140 | // Add the sender to the list of authenticated clients |
||
141 | 3 | if ($message->getAccessToken() === $this->configuration->getAccessToken()) |
|
142 | { |
||
143 | 3 | $status = AuthenticationResponse::STATUS_SUCCESS; |
|
144 | 3 | $this->_authenticatedClients->attach($sender); |
|
145 | |||
146 | 3 | $this->logger->notice('Client authenticated successfully'); |
|
147 | } |
||
148 | else |
||
149 | 1 | $this->logger->warning('Got invalid authentication request from client'); |
|
150 | |||
151 | 3 | return new AuthenticationResponse($status); |
|
152 | } |
||
153 | |||
154 | |||
155 | /** |
||
156 | * Dispatches incoming client messages to the appropriate handlers |
||
157 | * |
||
158 | * @param ConnectionInterface $from |
||
159 | * @param string $msg |
||
160 | */ |
||
161 | 1 | public function onMessage(ConnectionInterface $from, $msg) |
|
162 | { |
||
163 | try |
||
164 | { |
||
165 | 1 | $message = MessageFactory::factory($msg); |
|
166 | |||
167 | 1 | $this->logger->debug('Got message from client (type: {messageType})', [ |
|
168 | 1 | 'messageType' => $message->getType(), |
|
169 | ]); |
||
170 | |||
171 | // Attempt to delegate the message |
||
172 | try |
||
173 | { |
||
174 | 1 | $response = $this->tryDelegateMessage($message, $from); |
|
175 | 1 | $this->sendMessage($response, $from); |
|
176 | } |
||
177 | catch (RequestFailedException $e) |
||
178 | { |
||
179 | $this->logger->error('The request failed: ' . $e->getMessage()); |
||
180 | } |
||
181 | catch (UnhandledMessageException $e) |
||
182 | { |
||
183 | $this->logger->error('Unhandled message (type: {messageType})', [ |
||
184 | 1 | 'messageType' => $message->getType(), |
|
185 | ]); |
||
186 | } |
||
187 | } |
||
188 | catch (MalformedRequestException $e) |
||
189 | { |
||
190 | $this->logger->error('Got malformed message from client (reason: {reason})', [ |
||
191 | 'reason' => $e->getMessage(), |
||
192 | ]); |
||
193 | } |
||
194 | catch (UnknownRequestException $e) |
||
195 | { |
||
196 | // The server itself sometimes sends out messages that are received here, hence debug |
||
197 | $this->logger->debug('Got unknown message from client (type: {messageType})', [ |
||
198 | 'messageType' => $e->getType(), |
||
199 | ]); |
||
200 | } |
||
201 | 1 | } |
|
202 | |||
203 | |||
204 | /** |
||
205 | * @param AbstractMessage $message |
||
206 | * @param ConnectionInterface $target |
||
207 | */ |
||
208 | 2 | private function sendMessage(AbstractMessage $message, ConnectionInterface $target) |
|
212 | |||
213 | } |
||
214 |