/**
  * {@inheritdoc}
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     Logger::set(new NullLogger());
     $this->input = $input;
     $this->output = $output;
     $this->config = $this->getContainer()->getParameter('voryx_thruway');
     switch ($input->getArgument('action')) {
         case "start":
             $this->start();
             break;
         case "stop":
             $this->stop();
             break;
         case "restart":
             $this->restart();
             break;
         case "status":
             $this->status();
             break;
         case "add":
             $this->add();
             break;
         default:
             $output->writeln("Expected an action: start, stop, status");
     }
 }
Exemple #2
0
 public function connect(\Closure $callback, array $options = [])
 {
     $options = array_merge(['logging' => $this->logging, 'loggingOutput' => $this->loggingOutput, 'connectionTimeout' => null, 'connectionOptions' => []], $options);
     if (!$options['logging']) {
         Logger::set(new NullLogger());
     }
     if (!$options['loggingOutput']) {
         ob_start();
     }
     $connection = $this->createConnection($options['connectionOptions']);
     $connection->once('open', function (ClientSession $session) use($connection, $callback) {
         call_user_func_array($callback, [$connection, $session]);
     });
     if ($options['connectionTimeout'] !== null) {
         $loop = $connection->getClient()->getLoop();
         $timer = $loop->addTimer($options['connectionTimeout'], function () use($loop) {
             $loop->stop();
         });
         $connection->once('close', function () use($timer) {
             $timer->cancel();
             \Yii::warning('WAMP connection closed by timeout.');
         });
     }
     $connection->open();
     if ($options['logging']) {
         \Yii::info(ob_get_contents());
     }
     if (!$options['loggingOutput']) {
         ob_clean();
     }
 }
Exemple #3
0
 /**
  * Start the transport
  *
  * @param boolean $startLoop
  * @throws \Exception
  */
 public function start($debug = false, $startLoop = true)
 {
     if (!$debug) {
         Logger::set(new NullLogger());
     }
     parent::start($startLoop);
 }
 /**
  * //@todo implement a non-blocking version of this
  *
  * @param $topicName
  * @param $arguments
  * @param array|null $argumentsKw
  * @param null $options
  * @return \React\Promise\Promise
  */
 public function publish($topicName, $arguments, $argumentsKw = [], $options = null)
 {
     //Use the serializer to serialize and than deserialize.  This is a hack because the serializer doesn't support the array format and we need to be able to handle Entities
     $arguments = json_decode($this->serializer->serialize($arguments, "json"));
     $argumentsKw = json_decode($this->serializer->serialize($argumentsKw, "json"));
     //If we already have a client open that we can use, use that
     if ($this->container->initialized('wamp_kernel') && ($client = $this->container->get('wamp_kernel')->getClient())) {
         $session = $this->container->get('wamp_kernel')->getSession();
         return $session->publish($topicName, $arguments, $argumentsKw, $options);
     }
     if (is_array($options)) {
         $options = (object) $options;
     }
     if (!is_object($options)) {
         $options = (object) [];
     }
     Logger::set(new NullLogger());
     //If we don't already have a long running client, get a short lived one.
     $client = $this->getShortClient();
     $options->acknowledge = true;
     $deferrer = new Deferred();
     $client->on("open", function (ClientSession $session, TransportInterface $transport) use($deferrer, $topicName, $arguments, $argumentsKw, $options) {
         $session->publish($topicName, $arguments, $argumentsKw, $options)->then(function () use($deferrer, $transport) {
             $transport->close();
             $deferrer->resolve();
         });
     });
     $client->on("error", function ($error) use($topicName) {
         $this->container->get('logger')->addError("Got the following error when trying to publish to '{$topicName}': {$error}");
     });
     $client->start();
     return $deferrer->promise();
 }
 /**
  * @param SessionEvent $event
  */
 public function onOpen(SessionEvent $event)
 {
     /* @var $mapping \Voryx\ThruwayBundle\Mapping\URIClassMapping */
     foreach ($event->getResourceMappings() as $name => $mapping) {
         $annotation = $mapping->getAnnotation();
         if (!$annotation instanceof Register) {
             continue;
         }
         $topicStateHandler = $annotation->getTopicStateHandlerFor();
         if (!$topicStateHandler) {
             continue;
         }
         $session = $event->getSession();
         $registration = new \stdClass();
         $registration->handler_uri = $annotation->getName();
         $registration->uri = $annotation->getTopicStateHandlerFor();
         $registration->options = $annotation->getTopicStateHandlerOptions();
         //Register Topic Handlers
         $registration->topic = $topicStateHandler;
         $session->call('add_state_handler', [$registration])->then(function ($res) use($annotation) {
             Logger::info($this, "Registered topic handler RPC: '{$annotation->getName()}'' for topic: '{$annotation->getTopicStateHandlerFor()}'");
         }, function (ErrorMessage $error) use($annotation) {
             Logger::error($this, "Unable to register topic handler RPC: '{$annotation->getName()}'' for topic: '{$annotation->getTopicStateHandlerFor()}'' Error: '{$error->getErrorURI()}''");
         });
     }
 }
 /**
  * Start transport provider
  *
  * @param \Thruway\Peer\ClientInterface $client
  * @param \React\EventLoop\LoopInterface $loop
  */
 public function startTransportProvider(ClientInterface $client, LoopInterface $loop)
 {
     Logger::info($this, "Starting Transport");
     $this->client = $client;
     $this->loop = $loop;
     $this->connector = new Factory($this->loop);
     $this->connector->__invoke($this->URL, ['wamp.2.json'])->then(function (WebSocket $conn) {
         Logger::info($this, "Pawl has connected");
         $transport = new PawlTransport($conn, $this->loop);
         $transport->setSerializer(new JsonSerializer());
         $this->client->onOpen($transport);
         $conn->on('message', function ($msg) use($transport) {
             Logger::debug($this, "Received: {$msg}");
             try {
                 $this->client->onMessage($transport, $transport->getSerializer()->deserialize($msg));
             } catch (DeserializationException $e) {
                 Logger::warning($this, "Deserialization exception occurred.");
             } catch (\Exception $e) {
                 Logger::warning($this, "Exception occurred during onMessage: " . $e->getMessage());
             }
         });
         $conn->on('close', function ($conn) {
             Logger::info($this, "Pawl has closed");
             $this->client->onClose('close');
         });
         $conn->on('pong', function ($frame, $ws) use($transport) {
             $transport->onPong($frame, $ws);
         });
     }, function ($e) {
         $this->client->onClose('unreachable');
         Logger::info($this, "Could not connect: {$e->getMessage()}");
         // $this->loop->stop();
     });
 }
Exemple #7
0
 /**
  * TODO doc block
  */
 public function __construct()
 {
     Logger::set(new NullLogger());
     parent::__construct('realm1');
     $ip = Configure::read('Websockets.ip');
     $port = Configure::read('Websockets.port');
     $this->addTransportProvider(new PawlTransportProvider("ws://" . $ip . ":" . $port . "/"));
 }
 public function handleRouterStart(RouterStartEvent $event)
 {
     $socket = new Server($this->loop);
     $socket->on('connection', [$this, "handleConnection"]);
     Logger::info($this, "Raw socket listening on " . $this->address . ":" . $this->port);
     $socket->listen($this->port, $this->address);
     $this->server = $socket;
 }
 /**
  * Handles session start
  *
  * @param \Thruway\AbstractSession $session
  * @param \Thruway\Transport\TransportProviderInterface $transport
  */
 public function onSessionStart($session, $transport)
 {
     $this->getCallee()->register($session, "thruway.auth.{$this->getMethodName()}.onhello", [$this, 'processHello'], ["replace_orphaned_session" => "yes"])->then(function () use($session) {
         $this->getCallee()->register($session, "thruway.auth.{$this->getMethodName()}.onauthenticate", [$this, 'preProcessAuthenticate'], ["replace_orphaned_session" => "yes"])->then(function () use($session) {
             $this->getCaller()->call($session, 'thruway.auth.registermethod', [$this->getMethodName(), ["onhello" => "thruway.auth.{$this->getMethodName()}.onhello", "onauthenticate" => "thruway.auth.{$this->getMethodName()}.onauthenticate"], $this->getAuthRealms()])->then(function ($args) {
                 Logger::debug($this, "Authentication Method Registration Successful: {$this->getMethodName()}");
             });
         });
     });
 }
 public function handleRouterStart(RouterStartEvent $event)
 {
     $server = new Server($this->bindAddress, $this->port, false, ["wamp.2.json"]);
     Logger::info($this, "Websocket listening on " . $this->bindAddress . ":" . $this->port);
     $this->serverDisposable = $server->subscribe(new CallbackObserver(function (MessageSubject $ms) {
         $this->createNewSessionForMessageSubject($ms);
     }, function (\Exception $err) {
         Logger::error($this, "Received error on server: " . $err->getMessage());
     }, function () {
         Logger::alert($this, "Completed. Not sure if we should ever do that.");
     }));
 }
Exemple #11
0
 /**
  * Process error
  *
  * @param \Thruway\AbstractSession $session
  * @param \Thruway\Message\ErrorMessage $msg
  */
 protected function processError(AbstractSession $session, ErrorMessage $msg)
 {
     switch ($msg->getErrorMsgCode()) {
         case Message::MSG_SUBSCRIBE:
             $this->processSubscribeError($session, $msg);
             break;
         case Message::MSG_UNSUBSCRIBE:
             // TODO
             break;
         default:
             Logger::critical($this, "Unhandled error");
     }
 }
 /**
  * Handles session start
  *
  * @param \Thruway\ClientSession $session
  * @param \Thruway\Transport\TransportProviderInterface $transport
  */
 public function onSessionStart($session, $transport)
 {
     $session->register("thruway.auth.{$this->getMethodName()}.onhello", [$this, 'processHello'], ["replace_orphaned_session" => "yes"])->then(function () use($session) {
         $session->register("thruway.auth.{$this->getMethodName()}.onauthenticate", [$this, 'preProcessAuthenticate'], ["replace_orphaned_session" => "yes"])->then(function () use($session) {
             $registrations = new \stdClass();
             $registrations->onhello = "thruway.auth.{$this->getMethodName()}.onhello";
             $registrations->onauthenticate = "thruway.auth.{$this->getMethodName()}.onauthenticate";
             $session->call('thruway.auth.registermethod', [$this->getMethodName(), $registrations, $this->getAuthRealms()])->then(function ($args) {
                 Logger::debug($this, "Authentication Method Registration Successful: {$this->getMethodName()}");
             });
         });
     });
 }
 /**
  * Gets and published the topics state to this subscription
  *
  * @param Subscription $subscription
  * @return mixed
  */
 public function publishState(Subscription $subscription)
 {
     //Pause all non-state building event messages
     $subscription->pauseForState();
     $sessionId = $subscription->getSession()->getSessionId();
     $this->clientSession->call($this->getProcedureName(), [$subscription->getUri(), $sessionId, $subscription->getOptions(), $subscription->getSession()->getAuthenticationDetails()])->then(function ($res) use($subscription) {
         $pubId = null;
         if (isset($res[0])) {
             $pubId = $res[0];
         }
         $subscription->unPauseForState($pubId);
     }, function ($error) use($subscription) {
         Logger::error($this, "Could not call '{$this->getProcedureName()}' when restoring state");
         $subscription->unPauseForState();
     });
 }
 /**
  * Configure optional settings
  *
  * @param $config
  * @param ContainerBuilder $container
  */
 protected function configureOptions(&$config, ContainerBuilder $container)
 {
     if ($config['enable_logging'] !== true) {
         Logger::set(new NullLogger());
     }
     if (isset($config['router']['authentication']) && $config['router']['authentication'] !== false) {
         //Inject the authentication manager into the router
         $container->getDefinition('voryx.thruway.server')->addMethodCall('registerModule', [new Reference('voryx.thruway.authentication.manager')]);
     }
     if ($container->hasDefinition('security.user.provider.concrete.in_memory')) {
         $container->addAliases(['in_memory_user_provider' => 'security.user.provider.concrete.in_memory']);
     }
     //Topic State Handler
     if (isset($config['router']['enable_topic_state']) && $config['router']['enable_topic_state'] === true) {
         $container->getDefinition('voryx.thruway.server')->addMethodCall('registerModule', [new Reference('voryx.thruway.topic.state.handler')]);
     }
 }
Exemple #15
0
 /**
  * This should take a authid string as the argument and return
  * an associative array with authid, key, and salt.
  *
  * If salt is non-null, the key is the salted version of the password.
  *
  * @param $authid
  * @throws \Exception
  * @return array
  */
 public function get($authid)
 {
     try {
         $userProvider = $this->container->getParameter('voryx_thruway')['user_provider'];
         if (null === $userProvider) {
             throw new \Exception('voryx_thruway.user_provider must be set.');
         }
         $user = $this->container->get($userProvider)->loadUserByUsername($authid);
         if (!$user) {
             throw new \Exception("Can't log in, bad credentials");
         }
         return ["user" => $user->getUsername(), "key" => $user->getPassword(), "salt" => $user->getSalt()];
     } catch (\Exception $e) {
         Logger::error($this, $e->getMessage());
         return false;
     }
 }
 /**
  * Get Authenticate message from challenge message
  *
  * @param \Thruway\Message\ChallengeMessage $msg
  * @return \Thruway\Message\AuthenticateMessage|boolean
  */
 public function getAuthenticateFromChallenge(ChallengeMessage $msg)
 {
     Logger::info($this, "Got challenge");
     Logger::debug($this, "Challenge Message: " . json_encode($msg));
     if (!in_array($msg->getAuthMethod(), $this->getAuthMethods())) {
         //throw new \Exception("method isn't in methods");
         return false;
     }
     if (!is_array($msg->getDetails())) {
         Logger::info($this, "No details sent with challenge");
         return false;
     }
     $challenge = '';
     if (isset($msg->getDetails()['challenge'])) {
         $challenge = $msg->getDetails()['challenge'];
     } else {
         Logger::info($this, "No challenge for wampcra?");
         return false;
     }
     $keyToUse = $this->key;
     if (isset($msg->getDetails()['salt'])) {
         // we need a salted key
         $salt = $msg->getDetails()['salt'];
         $keyLen = 32;
         if (isset($msg->getDetails()['keylen'])) {
             if (is_numeric($msg->getDetails()['keylen'])) {
                 $keyLen = $msg->getDetails()['keylen'];
             } else {
                 Logger::error($this, "keylen is not numeric.");
             }
         }
         $iterations = 1000;
         if (isset($msg->getDetails()['iterations'])) {
             if (is_numeric($msg->getDetails()['iterations'])) {
                 $iterations = $msg->getDetails()['iterations'];
             } else {
                 Logger::error($this, "iterations is not numeric.");
             }
         }
         $keyToUse = $this->getDerivedKey($this->key, $salt, $iterations, $keyLen);
     }
     $token = base64_encode(hash_hmac('sha256', $challenge, $keyToUse, true));
     $authMessage = new AuthenticateMessage($token);
     Logger::debug($this, "returning: " . json_encode($authMessage));
     return $authMessage;
 }
 /**
  * Handle process reveived data
  *
  * @param mixed $data
  * @return void
  */
 public function handleData($data)
 {
     //        if ($this->handshakeByte == 0) {
     //            $this->handshakeByte = $data[0];
     //            $data = substr($data, 1);
     //        }
     $this->buffer = $this->buffer . $data;
     $bufferLen = strlen($this->buffer);
     while ($bufferLen > 0 && $bufferLen >= $this->msgLen) {
         if ($this->msgLen == 0) {
             // the next 4 bytes are going to be the msglen
             if ($bufferLen >= 4) {
                 $this->msgLen = array_values(unpack("N", $this->buffer))[0];
                 if ($this->msgLen <= 0) {
                     Logger::error("Invalid message size sent");
                     $this->close();
                 }
                 // shift off the first 4 bytes
                 $bufferLen = $bufferLen - 4;
                 $this->buffer = substr($this->buffer, 4, $bufferLen);
             } else {
                 // we don't have enough to get the message length
                 return;
             }
         }
         if ($bufferLen >= $this->msgLen) {
             $msg = $this->getSerializer()->deserialize(substr($this->buffer, 0, $this->msgLen));
             //$this->peer->onMessage($this, $msg);
             $this->emit("message", [$this, $msg]);
             if ($bufferLen == $this->msgLen) {
                 $this->buffer = "";
                 $this->msgLen = 0;
                 $bufferLen = 0;
             } else {
                 $bufferLen = $bufferLen - $this->msgLen;
                 $this->buffer = substr($this->buffer, $this->msgLen, $bufferLen);
                 $this->msgLen = 0;
             }
         }
     }
 }
 /**
  * Configure optional settings
  *
  * @param $config
  * @param ContainerBuilder $container
  */
 protected function configureOptions(&$config, ContainerBuilder $container)
 {
     //Add optional Manager
     if (isset($config['router']['enable_manager']) && $config['router']['enable_manager'] === true) {
         //Replace the dummy manager with the client manager
         $container->getDefinition('voryx.thruway.manager.client')->setClass('Thruway\\Manager\\ManagerClient');
         //Inject the manager client into the router
         $container->getDefinition('voryx.thruway.server')->addMethodCall('addTransportProvider', [new Reference('voryx.thruway.internal.manager')]);
     }
     if ($config['enable_logging'] !== true) {
         Logger::set(new NullLogger());
     }
     if (isset($config['router']['authentication']) && $config['router']['authentication'] !== false) {
         //Inject the authentication manager into the router
         $container->getDefinition('voryx.thruway.server')->addMethodCall('registerModule', [new Reference('voryx.thruway.authentication.manager')]);
     }
     if ($container->hasDefinition('security.user.provider.concrete.in_memory')) {
         $container->addAliases(['in_memory_user_provider' => 'security.user.provider.concrete.in_memory']);
     }
     //Topic State Handler
     if (isset($config['router']['enable_topic_state']) && $config['router']['enable_topic_state'] === true) {
         $container->getDefinition('voryx.thruway.server')->addMethodCall('registerModule', [new Reference('voryx.thruway.topic.state.handler')]);
     }
 }
Exemple #19
0
 /**
  * @param Session $session
  * @param ErrorMessage $msg
  */
 private function processInterruptError(Session $session, ErrorMessage $msg)
 {
     $call = isset($this->callInterruptIndex[$msg->getRequestId()]) ? $this->callInterruptIndex[$msg->getRequestId()] : null;
     if (!$call) {
         Logger::warning($this, "Interrupt error with no corresponding interrupt index");
         return;
     }
     $errorMsgToCaller = ErrorMessage::createErrorMessageFromMessage($call->getCancelMessage());
     $errorMsgToCaller->setErrorURI($msg->getErrorURI());
     $callerSession = $call->getCallerSession();
     $callerSession->sendMessage($errorMsgToCaller);
     $call->getRegistration()->removeCall($call);
     $this->removeCall($call);
 }
 /**
  * Add new realm
  *
  * @param \Thruway\Realm $realm
  * @throws \Thruway\Exception\InvalidRealmNameException
  * @throws \Exception
  */
 public function addRealm(Realm $realm)
 {
     $realmName = $realm->getRealmName();
     if (!static::validRealmName($realm->getRealmName())) {
         throw new InvalidRealmNameException();
     }
     if (array_key_exists($realm->getRealmName(), $this->realms)) {
         throw new \Exception("There is already a realm \"" . $realm->getRealmName() . "\"");
     }
     Logger::debug($this, "Adding realm \"" . $realmName . "\"");
     $this->realms[$realm->getRealmName()] = $realm;
     $this->router->getEventDispatcher()->dispatch('new_realm', new NewRealmEvent($realm));
 }
Exemple #21
0
 /**
  * This creates a specific error message depending on the message we are reporting
  * an error on.
  *
  * @param \Thruway\Message\Message $msg
  * @param string $errorUri
  * @return \Thruway\Message\ErrorMessage
  */
 public static function createErrorMessageFromMessage(Message $msg, $errorUri = null)
 {
     if ($errorUri === null) {
         $errorUri = "wamp.error.unknown";
     }
     if (method_exists($msg, "getRequestId")) {
         return new ErrorMessage($msg->getMsgCode(), $msg->getRequestId(), new \stdClass(), $errorUri);
     }
     Logger::error(null, "Can't send an error message because the message didn't not have a request id ");
 }
Exemple #22
0
 /**
  * Handle close transport
  *
  * @param \Thruway\Transport\TransportInterface $transport
  */
 public function onClose(TransportInterface $transport)
 {
     Logger::debug($this, "onClose from " . json_encode($transport->getTransportDetails()));
     $this->sessions->detach($transport);
 }
Exemple #23
0
 /**
  * Process on session leave
  *
  * @param \Thruway\Session $session
  */
 public function leave(Session $session)
 {
     Logger::debug($this, "Leaving realm {$session->getRealm()->getRealmName()}");
     if ($this->getAuthenticationManager() !== null) {
         $this->getAuthenticationManager()->onSessionClose($session);
     }
     foreach ($this->roles as $role) {
         $role->leave($session);
     }
     $this->sessions->detach($session);
 }
Exemple #24
0
 /**
  * process unregister
  *
  * @param \Thruway\ClientSession $session
  * @param string $Uri
  * @throws \Exception
  * @return \React\Promise\Promise|false
  */
 public function unregister(ClientSession $session, $Uri)
 {
     // TODO: maybe add an option to wait for pending calls to finish
     $registration = null;
     foreach ($this->registrations as $k => $r) {
         if (isset($r['procedure_name'])) {
             if ($r['procedure_name'] == $Uri) {
                 $registration =& $this->registrations[$k];
                 break;
             }
         }
     }
     if ($registration === null) {
         Logger::warning($this, "registration not found: " . $Uri);
         return false;
     }
     // we remove the callback from the client here
     // because we don't want the client to respond to any more calls
     $registration['callback'] = null;
     $futureResult = new Deferred();
     if (!isset($registration["registration_id"])) {
         // this would happen if the registration was never acknowledged by the router
         // we should remove the registration and resolve any pending deferreds
         Logger::error($this, "Registration ID is not set while attempting to unregister " . $Uri);
         // reject the pending registration
         $registration['futureResult']->reject();
         // TODO: need to figure out what to do in this off chance
         // We should still probably return a promise here that just rejects
         // there is an issue with the pending registration too that
         // the router may have a "REGISTERED" in transit and may still think that is
         // good to go - so maybe still send the unregister?
     }
     $requestId = Session::getUniqueId();
     // save the request id so we can find this in the registration
     // list to call the deferred and remove it from the list
     $registration['unregister_request_id'] = $requestId;
     $registration['unregister_deferred'] = $futureResult;
     $unregisterMsg = new UnregisterMessage($requestId, $registration['registration_id']);
     $session->sendMessage($unregisterMsg);
     return $futureResult->promise();
 }
Exemple #25
0
 /**
  * @return int
  */
 public function decPendingCallCount()
 {
     // if we are already at zero - something is wrong
     if ($this->pendingCallCount == 0) {
         Logger::alert($this, 'Session pending call count wants to go negative.');
         return 0;
     }
     return $this->pendingCallCount--;
 }
Exemple #26
0
 public function setup()
 {
     \Thruway\Logging\Logger::set(new \Psr\Log\NullLogger());
     $this->router = new \Thruway\Peer\Router();
 }
Exemple #27
0
 /**
  * Process Welcome message
  *
  * @param \Thruway\ClientSession $session
  * @param \Thruway\Message\WelcomeMessage $msg
  */
 public function processWelcome(ClientSession $session, WelcomeMessage $msg)
 {
     Logger::info($this, "We have been welcomed...");
     //TODO: I'm sure that there are some other things that we need to do here
     $session->setSessionId($msg->getSessionId());
     $this->emit('open', [$session, $this->transport, $msg->getDetails()]);
     $session->setState(Session::STATE_UP);
 }
 /**
  * Set manager
  *
  * @param \Thruway\Manager\ManagerInterface $manager
  */
 public function setManager(ManagerInterface $manager)
 {
     $this->manager = $manager;
     Logger::info($this, "Manager attached to PawlTransportProvider");
 }
 /**
  * @param Subscription $subscription
  * @return StateHandlerRegistration|bool|null
  */
 private function getStateHandlerRegistrationForSubscription(Subscription $subscription)
 {
     $subscriptionGroup = $subscription->getSubscriptionGroup();
     if ($subscriptionGroup instanceof SubscriptionGroup) {
         if (!$this->stateHandlerMap->contains($subscriptionGroup)) {
             $this->setupStateHandlerRegistration($subscriptionGroup);
         }
         return $this->stateHandlerMap[$subscriptionGroup];
     }
     Logger::alert($this, "processSubscriptionAdded called with subscription that does not have subscriptionGroup set.");
     return false;
 }
Exemple #30
0
 /**
  * Process on session leave
  *
  * @param \Thruway\Session $session
  */
 public function leave(Session $session)
 {
     Logger::debug($this, "Leaving realm {$session->getRealm()->getRealmName()}");
     $this->sessions->detach($session);
 }