Example #1
0
 /**
  * Entry point for all messages received from clients in this proxy 'room'
  *
  * @param WebSocketTransportInterface $user
  * @param WebSocketMessageInterface $msg
  */
 public function onMessage(WebSocketTransportInterface $user, WebSocketMessageInterface $msg)
 {
     try {
         $message = json_decode($msg->getData());
         if ($message->command == 'connect') {
             $this->requestConnect($user, $message);
         } elseif ($message->command == 'write') {
             $this->requestWrite($user, $message);
         } elseif ($message->command == 'close') {
             $this->requestClose($user, $message);
         }
     } catch (Exception $e) {
         $this->logger->err($e->getMessage());
     }
 }
 public function onMessage(WebSocketTransportInterface $user, WebSocketMessageInterface $msg)
 {
     $data = json_decode($msg->getData());
     if ($data == null) {
         $this->say('Unparsable JSON : ' . $msg->getData());
         return false;
     }
     if (!isset($data->type)) {
         $this->say('No type given');
         return false;
     }
     if ($this->debug) {
         $this->say(' <- ' . $data->type);
     }
     switch ($data->type) {
         case 'ping':
             $data->type = 'pong';
             $user->sendString(json_encode($data));
             break;
         case 'pong':
             $user->ping = true;
             break;
         case 'register':
             if (isset($data->player_id) && isset($data->nick)) {
                 $ban = $this->observer->bans->is(null, $data->player_id);
                 if ($ban) {
                     $this->say('Connexion attempt from banned user ' . $data->player_id . ' (' . $ban->reason . ')');
                     $user->sendString('{"type": "ban", "reason": "' . $ban->reason . '"}');
                 } else {
                     $user->player_id = $data->player_id;
                     $user->nick = $data->nick;
                     $this->register_user($user, $data);
                 }
             } else {
                 $this->say('Incomplete registration : ' . $data->player_id . ' / ' . $data->nick);
                 $user->close();
             }
             break;
         default:
             if (isset($user->player_id)) {
                 $this->recieve($user, $data);
             } else {
                 $this->say('Action ' . $data->type . ' from unregistered user');
                 $user->close();
             }
     }
 }
 /**
  * Handles incoming websocket messages, parses them, and emits them as remote events.
  *
  * @param WebSocketMessageInterface $messageRaw A websocket message.
  */
 private function onMessage(WebSocketMessageInterface $message)
 {
     // parse the message and get the event name
     $payload = Payload::fromJson($message->getData());
     if (isset($payload['type'])) {
         switch ($payload['type']) {
             case 'hello':
                 $this->connected = true;
                 break;
             case 'team_rename':
                 $this->team->data['name'] = $payload['name'];
                 break;
             case 'team_domain_change':
                 $this->team->data['domain'] = $payload['domain'];
                 break;
             case 'channel_created':
                 $this->getChannelById($payload['channel']['id'])->then(function (Channel $channel) {
                     $this->channels[$channel->getId()] = $channel;
                 });
                 break;
             case 'channel_deleted':
                 unset($this->channels[$payload['channel']['id']]);
                 break;
             case 'channel_rename':
                 $this->channels[$payload['channel']['id']]->data['name'] = $payload['channel']['name'];
                 break;
             case 'channel_archive':
                 $this->channels[$payload['channel']['id']]->data['is_archived'] = true;
                 break;
             case 'channel_unarchive':
                 $this->channels[$payload['channel']['id']]->data['is_archived'] = false;
                 break;
             case 'group_joined':
                 $group = new Group($this, $payload['channel']);
                 $this->groups[$group->getId()] = $group;
                 break;
             case 'group_rename':
                 $this->groups[$payload['group']['id']]->data['name'] = $payload['channel']['name'];
                 break;
             case 'group_archive':
                 $this->groups[$payload['group']['id']]->data['is_archived'] = true;
                 break;
             case 'group_unarchive':
                 $this->groups[$payload['group']['id']]->data['is_archived'] = false;
                 break;
             case 'im_created':
                 $dm = new DirectMessageChannel($this, $payload['channel']);
                 $this->dms[$dm->getId()] = $dm;
                 break;
         }
         // emit an event with the attached json
         $this->emit($payload['type'], [$payload]);
     } else {
         // If reply_to is set, then it is a server confirmation for a previously
         // sent message
         if (isset($payload['reply_to'])) {
             if (isset($this->pendingMessages[$payload['reply_to']])) {
                 $deferred = $this->pendingMessages[$payload['reply_to']];
                 // Resolve or reject the promise that was waiting for the reply.
                 if (isset($payload['ok']) && $payload['ok'] === true) {
                     $deferred->resolve();
                 } else {
                     $deferred->reject($payload['error']);
                 }
                 unset($this->pendingMessages[$payload['reply_to']]);
             }
         }
     }
 }
Example #4
0
 public function sendMessage(WebSocketMessageInterface $msg)
 {
     foreach ($msg->getFrames() as $frame) {
         if ($this->sendFrame($frame) === false) {
             return false;
         }
     }
     return true;
 }
 public function onMessage(WebSocketTransportInterface $user, WebSocketMessageInterface $msg)
 {
     //do nothing
     $this->logger->notice("Client is talking to the wind. ({$msg->getData()}, {$user->getId()})");
 }
Example #6
0
 public function onMessage(WebSocketTransportInterface $user, WebSocketMessageInterface $msg)
 {
     //do nothing
     $this->logger->notice("User {$user->getId()} is not in a room but tried to say: {$msg->getData()}");
 }
 /**
  * Handle a message from a client.
  *
  * @param WebSocketTransportInterface $user
  * @param WebSocketMessageInterface $msg
  */
 public function onMessage(WebSocketTransportInterface $user, WebSocketMessageInterface $msg)
 {
     $data = json_decode($msg->getData(), true);
     if (!$data['action'] || !in_array($data['action'], ['subscribe', 'unsubscribe', 'publish'])) {
         return;
     }
     switch ($data['action']) {
         case 'subscribe':
         case 'unsubscribe':
             if (isset($data['query'])) {
                 $args = json_decode($data['query'], true);
                 $count = count($args);
                 if ($count > 1) {
                     for ($i = 1; $i < $count; $i++) {
                         $newArg = \Nymph\REST::translateSelector($args[$i]);
                         if ($newArg === false) {
                             return;
                         }
                         $args[$i] = $newArg;
                     }
                 }
                 if (count($args) > 1) {
                     $options = $args[0];
                     unset($args[0]);
                     \Nymph\Nymph::formatSelectors($args);
                     $args = array_merge([$options], $args);
                 }
                 $args[0]['skip_ac'] = true;
                 $serialArgs = serialize($args);
                 if ($data['action'] === 'subscribe') {
                     if (!key_exists($serialArgs, $this->subscriptions['queries'])) {
                         $guidArgs = $args;
                         $guidArgs[0]['return'] = 'guid';
                         $this->subscriptions['queries'][$serialArgs] = ['current' => call_user_func_array("\\Nymph\\Nymph::getEntities", $guidArgs)];
                     }
                     $this->subscriptions['queries'][$serialArgs][] = ['client' => $user, 'query' => $data['query'], 'count' => !!$data['count']];
                     $this->logger->notice("Client subscribed to a query! ({$serialArgs}, {$user->getId()})");
                     if (RequirePHP::_('NymphPubSubConfig')['broadcast_counts']) {
                         // Notify clients of the subscription count.
                         $count = count($this->subscriptions['queries'][$serialArgs]) - 1;
                         foreach ($this->subscriptions['queries'][$serialArgs] as $key => $curClient) {
                             if ($key === 'current') {
                                 continue;
                             }
                             if ($curClient['count']) {
                                 $curClient['client']->sendString(json_encode(['query' => $curClient['query'], 'count' => $count]));
                             }
                         }
                     }
                 } elseif ($data['action'] === 'unsubscribe') {
                     if (!key_exists($serialArgs, $this->subscriptions['queries'])) {
                         return;
                     }
                     foreach ($this->subscriptions['queries'][$serialArgs] as $key => $value) {
                         if ($key === 'current') {
                             continue;
                         }
                         if ($user->getId() === $value['client']->getId() && $data['query'] === $value['query']) {
                             unset($this->subscriptions['queries'][$serialArgs][$key]);
                             $this->logger->notice("Client unsubscribed from a query! ({$serialArgs}, {$user->getId()})");
                             if (RequirePHP::_('NymphPubSubConfig')['broadcast_counts']) {
                                 // Notify clients of the subscription count.
                                 $count = count($this->subscriptions['queries'][$serialArgs]) - 1;
                                 foreach ($this->subscriptions['queries'][$serialArgs] as $key => $curClient) {
                                     if ($key === 'current') {
                                         continue;
                                     }
                                     if ($curClient['count']) {
                                         $curClient['client']->sendString(json_encode(['query' => $curClient['query'], 'count' => $count]));
                                     }
                                 }
                             }
                             if (count($this->subscriptions['queries'][$serialArgs]) === 1) {
                                 unset($this->subscriptions['queries'][$serialArgs]);
                             }
                         }
                     }
                 }
             } elseif (isset($data['uid']) && is_string($data['uid'])) {
                 if ($data['action'] === 'subscribe') {
                     if (!key_exists($data['uid'], $this->subscriptions['uids'])) {
                         $this->subscriptions['uids'][$data['uid']] = [];
                     }
                     $this->subscriptions['uids'][$data['uid']][] = ['client' => $user, 'count' => !!$data['count']];
                     $this->logger->notice("Client subscribed to a UID! ({$data['uid']}, {$user->getId()})");
                     if (RequirePHP::_('NymphPubSubConfig')['broadcast_counts']) {
                         // Notify clients of the subscription count.
                         $count = count($this->subscriptions['uids'][$data['uid']]);
                         foreach ($this->subscriptions['uids'][$data['uid']] as $curClient) {
                             if ($curClient['count']) {
                                 $curClient['client']->sendString(json_encode(['uid' => $data['uid'], 'count' => $count]));
                             }
                         }
                     }
                 } elseif ($data['action'] === 'unsubscribe') {
                     if (!key_exists($data['uid'], $this->subscriptions['uids'])) {
                         return;
                     }
                     foreach ($this->subscriptions['uids'][$data['uid']] as $key => $value) {
                         if ($user->getId() === $value['client']->getId()) {
                             unset($this->subscriptions['uids'][$data['uid']][$key]);
                             $this->logger->notice("Client unsubscribed from a UID! ({$data['uid']}, {$user->getId()})");
                             if (RequirePHP::_('NymphPubSubConfig')['broadcast_counts']) {
                                 // Notify clients of the subscription count.
                                 $count = count($this->subscriptions['uids'][$data['uid']]);
                                 foreach ($this->subscriptions['uids'][$data['uid']] as $curClient) {
                                     if ($curClient['count']) {
                                         $curClient['client']->sendString(json_encode(['uid' => $data['uid'], 'count' => $count]));
                                     }
                                 }
                             }
                             break;
                         }
                     }
                     if (count($this->subscriptions['uids'][$data['uid']]) === 0) {
                         unset($this->subscriptions['uids'][$data['uid']]);
                     }
                 }
             }
             break;
         case 'publish':
             if (isset($data['guid']) && ($data['event'] === 'delete' || isset($data['entity']) && ($data['event'] === 'create' || $data['event'] === 'update'))) {
                 $this->logger->notice("Received an entity publish! ({$data['guid']}, {$data['event']}, {$user->getId()})");
                 // Relay the publish to other servers.
                 $this->relay($msg->getData());
                 foreach ($this->subscriptions['queries'] as $curQuery => &$curClients) {
                     if ($data['event'] === 'delete' || $data['event'] === 'update') {
                         // Check if it is in any queries' currents.
                         if (in_array($data['guid'], $curClients['current'])) {
                             // Update currents list.
                             $guidArgs = unserialize($curQuery);
                             $guidArgs[0]['return'] = 'guid';
                             $curClients['current'] = call_user_func_array("\\Nymph\\Nymph::getEntities", $guidArgs);
                             // Notify subscribers.
                             foreach ($curClients as $key => $curClient) {
                                 if ($key === 'current') {
                                     continue;
                                 }
                                 $this->logger->notice("Notifying client of modification! ({$curClient['client']->getId()})");
                                 $curClient['client']->sendString(json_encode(['query' => $curClient['query']]));
                             }
                             continue;
                         }
                     }
                     // It isn't in the current matching entities.
                     if ($data['event'] === 'create' || $data['event'] === 'update') {
                         // Check if it matches any queries.
                         $selectors = unserialize($curQuery);
                         $options = $selectors[0];
                         unset($selectors[0]);
                         $entityData = $data['entity']['data'];
                         $entityData['cdate'] = $data['entity']['cdate'];
                         $entityData['mdate'] = $data['entity']['mdate'];
                         $entitySData = [];
                         if ($options['class'] === $data['entity']['class'] && \Nymph\Nymph::checkData($entityData, $entitySData, $selectors, $data['guid'], $data['entity']['tags'])) {
                             // Update currents list.
                             $guidArgs = unserialize($curQuery);
                             $guidArgs[0]['return'] = 'guid';
                             $curClients['current'] = call_user_func_array("\\Nymph\\Nymph::getEntities", $guidArgs);
                             // If we're here, it means the query didn't
                             // match the entity before, and now it does. We
                             // could check currents to see if it's been
                             // removed by limits, but that may give us bad
                             // data, since the client queries are filtered
                             // by Tilmeld.
                             // Notify subscribers.
                             foreach ($curClients as $key => $curClient) {
                                 if ($key === 'current') {
                                     continue;
                                 }
                                 $this->logger->notice("Notifying client of new match! ({$curClient['client']->getId()})");
                                 $curClient['client']->sendString(json_encode(['query' => $curClient['query']]));
                             }
                         }
                     }
                 }
                 unset($curClients);
             } elseif ((isset($data['name']) || isset($data['oldName']) && isset($data['newName'])) && in_array($data['event'], ['newUID', 'setUID', 'renameUID', 'deleteUID'])) {
                 $this->logger->notice("Received a UID publish! (" . (isset($data['name']) ? $data['name'] : "{$data['oldName']} => {$data['newName']}") . ", {$data['event']}, {$user->getId()})");
                 // Relay the publish to other servers.
                 $this->relay($msg->getData());
                 foreach ($data as $key => $name) {
                     if (!in_array($key, ['name', 'newName', 'oldName']) || !key_exists($name, $this->subscriptions['uids'])) {
                         continue;
                     }
                     foreach ($this->subscriptions['uids'][$name] as $curClient) {
                         $this->logger->notice("Notifying client of {$data['event']}! ({$name}, {$curClient['client']->getId()})");
                         $curClient['client']->sendString(json_encode(['uid' => $name]));
                     }
                 }
             }
             break;
     }
 }