/** * Constructor * * @param \Thruway\Session $callerSession * @param \Thruway\Message\CallMessage $callMessage * @param Registration $registration */ public function __construct(Session $callerSession, CallMessage $callMessage, Procedure $procedure) { $this->callMessage = $callMessage; $this->callerSession = $callerSession; $this->procedure = $procedure; $this->callStart = microtime(true); $this->invocationRequestId = Utils::getUniqueId(); }
/** * Add new user * * @param string $userName * @param string $password * @param string $salt */ function add($userName, $password, $salt = null) { if ($salt !== null) { $key = \Thruway\Common\Utils::getDerivedKey($password, $salt); } else { $key = $password; } $this->users[$userName] = ["authid" => $userName, "key" => $key, "salt" => $salt]; }
/** * Constructor * * @param string $uri * @param \Thruway\Session $session * @param mixed $options */ public function __construct($uri, Session $session, $options = null) { $this->uri = $uri; $this->session = $session; $this->id = Utils::getUniqueId(); $this->disclosePublisher = false; $this->pausedForState = false; $this->pauseQueue = new \SplQueue(); $this->setOptions($options); }
/** * Constructor * * @param \React\EventLoop\LoopInterface $loop */ public function __construct(LoopInterface $loop = null) { Utils::checkPrecision(); $this->loop = $loop ?: Factory::create(); $this->realmManager = new RealmManager(); $this->eventDispatcher = new EventDispatcher(); $this->eventDispatcher->addSubscriber($this); $this->registerModule($this->realmManager); Logger::debug($this, "New router created"); }
public function testMakingCallIncrementsCallCount() { $mockSession = new \Thruway\Session(new \Thruway\Transport\DummyTransport()); $this->assertEquals(0, $this->_registration->getCurrentCallCount()); $callMsg = new \Thruway\Message\CallMessage(\Thruway\Common\Utils::getUniqueId(), new \stdClass(), 'test_procedure'); $procedure = $this->getMockBuilder('\\Thruway\\Procedure')->disableOriginalConstructor()->getMock(); $call = new \Thruway\Call($mockSession, $callMsg, $procedure); $this->_registration->processCall($call); $this->assertEquals(1, $this->_registration->getCurrentCallCount()); }
/** * Constructor * * @param \Thruway\Transport\TransportInterface $transport */ public function __construct(TransportInterface $transport) { $this->transport = $transport; $this->state = static::STATE_PRE_HELLO; $this->sessionId = Utils::getUniqueId(); $this->realm = null; $this->sessionStart = new \DateTime(); $this->authenticationDetails = null; $this->dispatcher = new EventDispatcher(); $this->dispatcher->addRealmSubscriber($this); }
/** * @param $uri * @param $options * @return bool */ public function uriIsValid($uri, $options) { $uri = $this->fixupUri($uri); // if the uri is empty - then match everything if ($uri == "") { return true; } // if there is a trailing . then remove it and run it through the // regular validator $uri = substr($uri, strlen($uri) - 1) == "." ? substr($uri, 0, strlen($uri) - 1) : $uri; // allow matches to a normal URI or one with a trailing dot return Utils::uriIsValid($uri) || Utils::uriIsValid($uri . "."); }
/** * Constructor * * @param \Thruway\Transport\TransportInterface $transport * @param \Thruway\Manager\ManagerInterface $manager */ public function __construct(TransportInterface $transport, ManagerInterface $manager = null) { $this->transport = $transport; $this->state = static::STATE_PRE_HELLO; $this->sessionId = Utils::getUniqueId(); $this->realm = null; $this->messagesSent = 0; $this->sessionStart = new \DateTime(); $this->authenticationDetails = null; $this->pendingCallCount = 0; $this->dispatcher = new EventDispatcher(); $this->dispatcher->addRealmSubscriber($this); if ($manager === null) { $manager = new ManagerDummy(); } $this->setManager($manager); }
/** * Get Authenticate message from challenge message * * @param \Thruway\Message\ChallengeMessage $msg * @return \Thruway\Message\AuthenticateMessage|boolean */ public function getAuthenticateFromChallenge(ChallengeMessage $msg) { Logger::debug($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; } $details = $msg->getDetails(); if (!is_object($details)) { Logger::debug($this, "No details sent with challenge"); return false; } if (isset($details->challenge)) { $challenge = $details->challenge; } else { Logger::debug($this, "No challenge for wampcra?"); return false; } $keyToUse = $this->key; if (isset($details->salt)) { // we need a salted key $salt = $details->salt; $keyLen = 32; if (isset($details->keylen)) { if (is_numeric($details->keylen)) { $keyLen = $details->keylen; } else { Logger::error($this, "keylen is not numeric."); } } $iterations = 1000; if (isset($details->iterations)) { if (is_numeric($details->iterations)) { $iterations = $details->iterations; } else { Logger::error($this, "iterations is not numeric."); } } $keyToUse = Utils::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; }
/** * Constructor * * @param \Thruway\Session $session * @param string $procedureName */ public function __construct(Session $session, $procedureName) { $this->id = Utils::getUniqueId(); $this->session = $session; $this->procedureName = $procedureName; $this->allowMultipleRegistrations = false; $this->discloseCaller = false; $this->calls = []; $this->registeredAt = new \DateTime(); $this->invocationCount = 0; $this->busyTime = 0; $this->invocationAverageTime = 0; $this->maxSimultaneousCalls = 0; $this->lastCallStartedAt = null; $this->lastIdledAt = $this->registeredAt; $this->busyStart = null; $this->completedCallTimeTotal = 0; }
/** * Process call * * @param \Thruway\Session $session * @param \Thruway\Message\CallMessage $msg * @return boolean */ private function processCall(Session $session, CallMessage $msg) { if (!Utils::uriIsValid($msg->getProcedureName())) { $session->sendMessage(ErrorMessage::createErrorMessageFromMessage($msg, 'wamp.error.invalid_uri')); return; } if (!isset($this->procedures[$msg->getProcedureName()])) { $session->sendMessage(ErrorMessage::createErrorMessageFromMessage($msg, 'wamp.error.no_such_procedure')); return; } /* @var $procedure \Thruway\Procedure */ $procedure = $this->procedures[$msg->getProcedureName()]; $call = new Call($session, $msg, $procedure); $this->callInvocationIndex[$call->getInvocationRequestId()] = $call; $this->callRequestIndex[$msg->getRequestId()] = $call; $keepIndex = $procedure->processCall($session, $call); if (!$keepIndex) { $this->removeCall($call); } }
/** * process publish * * @param \Thruway\ClientSession $session * @param string $topicName * @param mixed $arguments * @param mixed $argumentsKw * @param mixed $options * @return \React\Promise\Promise */ public function publish(ClientSession $session, $topicName, $arguments, $argumentsKw, $options) { $options = (object) $options; $requestId = Utils::getUniqueId(); if (isset($options->acknowledge) && $options->acknowledge === true) { $futureResult = new Deferred(); $this->publishRequests[$requestId] = ['future_result' => $futureResult]; } $publishMsg = new PublishMessage($requestId, $options, $topicName, $arguments, $argumentsKw); $session->sendMessage($publishMsg); return isset($futureResult) ? $futureResult->promise() : false; }
/** * process subscribe * * @param \Thruway\ClientSession $session * @param string $topicName * @param callable $callback * @param $options * @return Promise */ public function subscribe(ClientSession $session, $topicName, $callback, $options = null) { $requestId = Utils::getUniqueId(); $options = $options ? (object) $options : (object) []; $deferred = new Deferred(); $subscription = ["topic_name" => $topicName, "callback" => $callback, "request_id" => $requestId, "options" => $options, "deferred" => $deferred]; array_push($this->subscriptions, $subscription); $subscribeMsg = new SubscribeMessage($requestId, $options, $topicName); $session->sendMessage($subscribeMsg); return $deferred->promise(); }
/** * Create Invocation message from Call message and registration * * @param \Thruway\Message\CallMessage $msg * @param \Thruway\Registration $registration * @return \Thruway\Message\InvocationMessage */ public static function createMessageFrom(CallMessage $msg, Registration $registration) { $requestId = Utils::getUniqueId(); $details = new \stdClass(); return new static($requestId, $registration->getId(), $details, $msg->getArguments(), $msg->getArgumentsKw()); }
/** * Process publish message * * @param \Thruway\Session $session * @param \Thruway\Message\PublishMessage $msg */ protected function processPublish(Session $session, PublishMessage $msg) { if ($msg->getPublicationId() === null) { $msg->setPublicationId(Utils::getUniqueId()); } /** @var SubscriptionGroup $subscriptionGroup */ foreach ($this->subscriptionGroups as $subscriptionGroup) { $subscriptionGroup->processPublish($session, $msg); } if ($msg->acknowledge()) { $session->sendMessage(new PublishedMessage($msg->getRequestId(), $msg->getPublicationId())); } }
/** * Publish meta * * @param string $topicName * @param mixed $arguments * @param mixed $argumentsKw * @param mixed $options */ public function publishMeta($topicName, $arguments, $argumentsKw = null, $options = null) { if ($this->metaSession === null) { // setup a new metaSession $s = new Session(new DummyTransport()); $this->metaSession = $s; } $messageEvent = new MessageEvent($this->metaSession, new PublishMessage(Utils::getUniqueId(), $options, $topicName, $arguments, $argumentsKw)); $this->getBroker()->handlePublishMessage($messageEvent); }
public function testInvocationError() { $dealer = new \Thruway\Role\Dealer(); $callerTransport = new \Thruway\Transport\DummyTransport(); $callerSession = new Session($callerTransport); $calleeTransport = new \Thruway\Transport\DummyTransport(); $calleeSession = new Session($calleeTransport); // register from callee $registerMsg = new \Thruway\Message\RegisterMessage(1, new stdClass(), 'test_proc_name'); $dealer->handleRegisterMessage(new \Thruway\Event\MessageEvent($calleeSession, $registerMsg)); $this->assertInstanceOf('\\Thruway\\Message\\RegisteredMessage', $calleeTransport->getLastMessageSent()); // call from one session $callRequestId = \Thruway\Common\Utils::getUniqueId(); $callMsg = new \Thruway\Message\CallMessage($callRequestId, new stdClass(), 'test_proc_name'); $dealer->handleCallMessage(new \Thruway\Event\MessageEvent($callerSession, $callMsg)); $this->assertInstanceOf('\\Thruway\\Message\\InvocationMessage', $calleeTransport->getLastMessageSent()); $errorMsg = \Thruway\Message\ErrorMessage::createErrorMessageFromMessage($calleeTransport->getLastMessageSent(), 'the.error.uri'); $dealer->handleErrorMessage(new \Thruway\Event\MessageEvent($calleeSession, $errorMsg)); /** @var \Thruway\Message\ErrorMessage $returnedError */ $returnedError = $callerTransport->getLastMessageSent(); $this->assertInstanceOf('\\Thruway\\Message\\ErrorMessage', $returnedError); $this->assertEquals(Message::MSG_CALL, $returnedError->getErrorMsgCode()); $this->assertEquals($callRequestId, $returnedError->getErrorRequestId()); $this->assertEquals('the.error.uri', $returnedError->getErrorURI()); }
private function handleCallHttpRequest($request, $response) { $bodySnatcher = new BodySnatcher($request); $bodySnatcher->promise()->then(function ($body) use($request, $response) { try { //{"procedure": "com.myapp.procedure1", "args": ["Hello, world"], "argsKw": {}, "options": {} } $json = json_decode($body); if (isset($json->procedure) && Utils::uriIsValid($json->procedure) && $this->getCaller() !== null) { $args = isset($json->args) && is_array($json->args) ? $json->args : null; $argsKw = isset($json->argsKw) && is_object($json->argsKw) ? $json->argsKw : null; $options = isset($json->options) && is_object($json->options) ? $json->options : null; $this->getSession()->call($json->procedure, $args, $argsKw, $options)->then(function (CallResult $result) use($response) { $responseObj = new \stdClass(); $responseObj->result = "SUCCESS"; $responseObj->args = $result->getArguments(); $responseObj->argsKw = $result->getArgumentsKw(); $responseObj->details = $result->getDetails(); $response->writeHead(200, ['Content-Type' => 'application/json', 'Connection' => 'close']); $response->end(json_encode($responseObj)); }, function (ErrorMessage $msg) use($response) { $responseObj = new \stdClass(); $responseObj->result = "ERROR"; $responseObj->error_uri = $msg->getErrorURI(); $responseObj->error_args = $msg->getArguments(); $responseObj->error_argskw = $msg->getArgumentsKw(); $responseObj->error_details = $msg->getDetails(); // maybe return an error code here $response->writeHead(200, ['Content-Type' => 'application/json', 'Connection' => 'close']); $response->end(json_encode($responseObj)); }); } else { // maybe return an error code here $response->writeHead(200, ['Content-Type' => 'text/plain', 'Connection' => 'close']); $response->end("No procedure set"); } } catch (\Exception $e) { // maybe return an error code here $response->writeHead(200, ['Content-Type' => 'text/plain', 'Connection' => 'close']); $response->end("Problem"); } }); }
public function xtestUnauthorizedActions() { $this->markTestIncomplete("Authorization cannot be tested here and will be moved to a module"); $session = $this->getMockBuilder('\\Thruway\\Session')->disableOriginalConstructor()->setMethods(["sendMessage"])->getMock(); $authorizationManager = $this->getMockBuilder('\\Thruway\\Authentication\\AuthorizationManagerInterface')->getMock(); $realm = new \Thruway\Realm("some_realm"); $realm->setAuthorizationManager($authorizationManager); $subscribeMsg = new \Thruway\Message\SubscribeMessage(\Thruway\Common\Utils::getUniqueId(), [], "some_topic"); $publishMsg = new \Thruway\Message\PublishMessage(\Thruway\Common\Utils::getUniqueId(), (object) ["acknowledge" => true], "some_topic"); $registerMsg = new \Thruway\Message\RegisterMessage(\Thruway\Common\Utils::getUniqueId(), [], 'some_procedure'); $callMsg = new \Thruway\Message\CallMessage(\Thruway\Common\Utils::getUniqueId(), [], "some_procedure"); $authorizationManager->expects($this->exactly(5))->method("isAuthorizedTo")->withConsecutive([$this->isInstanceOf('\\Thruway\\Session'), $this->isInstanceOf('\\Thruway\\Message\\SubscribeMessage')], [$this->isInstanceOf('\\Thruway\\Session'), $this->isInstanceOf('\\Thruway\\Message\\PublishMessage')], [$this->isInstanceOf('\\Thruway\\Session'), $this->isInstanceOf('\\Thruway\\Message\\RegisterMessage')], [$this->isInstanceOf('\\Thruway\\Session'), $this->isInstanceOf('\\Thruway\\Message\\CallMessage')], [$this->isInstanceOf('\\Thruway\\Session'), $this->isInstanceOf('\\Thruway\\Message\\PublishMessage')])->willReturn(false); $errorCheck = function ($msg) { $this->assertInstanceOf('\\Thruway\\Message\\ErrorMessage', $msg); $this->assertEquals('wamp.error.not_authorized', $msg->getErrorUri()); return true; }; $session->expects($this->exactly(5))->method("sendMessage")->withConsecutive([$this->isInstanceOf('\\Thruway\\Message\\WelcomeMessage')], [$this->callback($errorCheck)], [$this->callback($errorCheck)], [$this->callback($errorCheck)], [$this->callback($errorCheck)]); $helloMsg = new \Thruway\Message\HelloMessage("some_realm", []); $realm->onMessage($session, $helloMsg); $realm->onMessage($session, $subscribeMsg); $realm->onMessage($session, $publishMsg); $realm->onMessage($session, $registerMsg); $realm->onMessage($session, $callMsg); // make sure publish doesn't send error back when ack is false $publishMsg2 = $publishMsg = new \Thruway\Message\PublishMessage(\Thruway\Common\Utils::getUniqueId(), [], "some_topic"); $realm->onMessage($session, $publishMsg2); }
/** * process call * * @param \Thruway\ClientSession $session * @param string $procedureName * @param mixed $arguments * @param mixed $argumentsKw * @param mixed $options * @return \React\Promise\Promise */ public function call(ClientSession $session, $procedureName, $arguments = null, $argumentsKw = null, $options = null) { //This promise gets resolved in Caller::processResult $futureResult = new Deferred(); $requestId = Utils::getUniqueId(); $this->callRequests[$requestId] = ["procedure_name" => $procedureName, "future_result" => $futureResult]; if (is_array($options)) { $options = (object) $options; } if (!is_object($options)) { if ($options !== null) { Logger::warning($this, "Options don't appear to be the correct type."); } $options = new \stdClass(); } $callMsg = new CallMessage($requestId, $options, $procedureName, $arguments, $argumentsKw); $session->sendMessage($callMsg); return $futureResult->promise(); }
public function testRemoveRegistration() { $transport = $this->getMockBuilder('\\Thruway\\Transport\\TransportInterface')->getMock(); $transport->expects($this->any())->method("getTransportDetails")->will($this->returnValue("")); $session = $this->getMockBuilder('\\Thruway\\Session')->setMethods(["sendMessage"])->setConstructorArgs([$transport])->getMock(); /** @var $session \Thruway\Session */ $session->setRealm(new \Thruway\Realm("testrealm")); $broker = new \Thruway\Role\Broker(); $subscribeMsg = new \Thruway\Message\SubscribeMessage(\Thruway\Common\Utils::getUniqueId(), [], "test.topic"); $messageEvent = new \Thruway\Event\MessageEvent($session, $subscribeMsg); $broker->handleSubscribeMessage($messageEvent); $subscriptions = $broker->getSubscriptions(); $this->assertTrue(count($subscriptions) === 1); $subscriptions = array_values($subscriptions); $messageEvent = new \Thruway\Event\MessageEvent($session, new \Thruway\Message\UnsubscribeMessage(\Thruway\Common\Utils::getUniqueId(), $subscriptions[0]->getId())); $broker->handleUnsubscribeMessage($messageEvent); $this->assertTrue(count($broker->getSubscriptions()) === 0); }
/** * Arguments need to be [["role1", "role2"], "publish|subscribe|register|call", "my.uri"] * * @param $args * @return bool|mixed */ public function testAuthorization($args) { if (is_array($args) && count($args) < 3) { return false; } $roles = $args[0]; if (is_string($roles)) { $roles = [$roles]; } $action = $args[1]; if (!static::isValidAction($action)) { return false; } $uriToCheck = $args[2]; if (!Utils::uriIsValid($uriToCheck)) { return false; } return $this->isAuthorizedByRolesActionAndUri($roles, $action, $uriToCheck); }
/** * @param string $handlerUri * @throws \Exception */ public function setStateHandler($handlerUri) { if (!Utils::uriIsValid($handlerUri)) { Logger::error($this, "Invalid URI"); throw new \InvalidArgumentException("Invalid URI"); } $this->stateHandler = $handlerUri; }
/** * Issue 53 - publishing inside of subscription event callback * prevents other internal clients from receiving the published event * * @depends testStart * @param \Thruway\Peer\Router $router */ public function testIssue53(\Thruway\Peer\Router $router) { $this->_callCount = 0; $transport1 = $this->getMockBuilder('\\Thruway\\Transport\\TransportInterface')->getMock(); $transport2 = $this->getMockBuilder('\\Thruway\\Transport\\TransportInterface')->getMock(); $transport2->expects($this->exactly(3))->method('sendMessage')->withConsecutive([$this->isInstanceOf('\\Thruway\\Message\\WelcomeMessage')], [$this->isInstanceOf('\\Thruway\\Message\\SubscribedMessage')], [$this->isInstanceOf('\\Thruway\\Message\\EventMessage')]); $transportPublisher = $this->getMockBuilder('\\Thruway\\Transport\\TransportInterface')->getMock(); $session1 = new \Thruway\Session($transport1); $session2 = new \Thruway\Session($transport2); $sessionPublisher = new \Thruway\Session($transportPublisher); $transport1->expects($this->exactly(3))->method('sendMessage')->withConsecutive([$this->isInstanceOf('\\Thruway\\Message\\WelcomeMessage')], [$this->isInstanceOf('\\Thruway\\Message\\SubscribedMessage')], [$this->callback(function ($arg) use($router, $transport1, $session1) { $this->assertInstanceOf('\\Thruway\\Message\\EventMessage', $arg); // publish while in the callback $publishMsg = new \Thruway\Message\PublishMessage(12346, (object) [], 'com.example.nowhere'); $session1->dispatchMessage($publishMsg); $this->_callCount = $this->_callCount + 1; return true; })]); $router->getEventDispatcher()->dispatch("connection_open", new \Thruway\Event\ConnectionOpenEvent($session1)); $router->getEventDispatcher()->dispatch("connection_open", new \Thruway\Event\ConnectionOpenEvent($session2)); $router->getEventDispatcher()->dispatch("connection_open", new \Thruway\Event\ConnectionOpenEvent($sessionPublisher)); // send in a few hellos $helloMsg = new \Thruway\Message\HelloMessage("realm_issue53", (object) []); $session1->dispatchMessage($helloMsg); $session2->dispatchMessage($helloMsg); $sessionPublisher->dispatchMessage($helloMsg); // subscribe $subscribeMsg = new \Thruway\Message\SubscribeMessage(\Thruway\Common\Utils::getUniqueId(), (object) [], "com.example.issue53"); $session1->dispatchMessage($subscribeMsg); $session2->dispatchMessage($subscribeMsg); // publish to the topic from the publishing transport $publishMsg = new \Thruway\Message\PublishMessage(12345, (object) [], 'com.example.issue53'); $sessionPublisher->dispatchMessage($publishMsg); }
public function testLeave() { $session = $this->getMockBuilder('\\Thruway\\Session')->disableOriginalConstructor()->getMock(); $session->expects($this->once())->method("sendMessage")->with($this->isInstanceOf('\\Thruway\\Message\\RegisteredMessage')); $registerMsg = new \Thruway\Message\RegisterMessage(\Thruway\Common\Utils::getUniqueId(), [], 'test_procedure'); $this->_proc->processRegister($session, $registerMsg); $this->assertEquals(1, count($this->_proc->getRegistrations())); $this->_proc->leave($session); $this->assertEquals(0, count($this->_proc->getRegistrations())); }
/** * @param $uri * @param $options * @return bool */ public function uriIsValid($uri, $options) { return Utils::uriIsValid($uri); }
public function testInvokeRandomOneRegistration() { $transportCaller = new \Thruway\Transport\DummyTransport(); $sessionCaller = new \Thruway\Session($transportCaller); $sessionsToStart = 1; $sessions = array(); for ($i = 0; $i < $sessionsToStart; $i++) { $sessions[] = new \Thruway\Session(new \Thruway\Transport\DummyTransport()); } $proc = new \Thruway\Procedure('random.procedure'); foreach ($sessions as $session) { $registerMsg = new \Thruway\Message\RegisterMessage(\Thruway\Common\Utils::getUniqueId(), ["invoke" => "random"], 'random.procedure'); $proc->processRegister($session, $registerMsg); } //make sure that the registrations have been successful $this->assertEquals(count($sessions), count($proc->getRegistrations())); $calls = 0; for ($i = 0; $i < 10; $i++) { $callMessage = new \Thruway\Message\CallMessage(\Thruway\Common\Utils::getUniqueId(), [], 'random.procedure'); $call = new \Thruway\Call($sessionCaller, $callMessage, $proc); //lets send the call $proc->processCall($sessionCaller, $call); } foreach ($sessions as $session) { $calls += $session->getPendingCallCount(); } $this->assertEquals(10, $calls); }
/** * Constructor * * @param string $realm * @param \React\EventLoop\LoopInterface $loop */ public function __construct($realm, LoopInterface $loop = null) { Utils::checkPrecision(); $this->realm = $realm; $this->loop = $loop ? $loop : Factory::create(); $this->transportProvider = null; $this->roles = []; $this->authMethods = []; $this->session = null; $this->clientAuthenticators = []; $this->authId = "anonymous"; $this->reconnectOptions = ["max_retries" => 15, "initial_retry_delay" => 1.5, "max_retry_delay" => 300, "retry_delay_growth" => 1.5, "retry_delay_jitter" => 0.1]; $this->on('open', [$this, 'onSessionStart']); Logger::info($this, "New client created"); }
/** * 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 = Utils::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(); }