/** {@inheritdoc} */ protected function handleOperation(RequestDescriptor $descriptor, RequestExecutorInterface $executor, EventHandlerInterface $eventHandler) { $operation = $descriptor->getOperation(); $socket = $descriptor->getSocket(); /** @var SslHandshakeOperation $operation */ $resource = $descriptor->getSocket()->getStreamResource(); $result = stream_socket_enable_crypto($resource, true, $operation->getCipher()); if ($result === true) { return $operation->getNextOperation(); } elseif ($result === false) { throw new SslHandshakeException($socket, 'SSL handshake failed.'); } return $operation; }
/** * Fire timeout event and processes user response * * @param RequestDescriptor $descriptor * * @return bool True if we may do one more attempt, false otherwise */ public function handleTimeoutOnDescriptor(RequestDescriptor $descriptor) { $meta = $descriptor->getMetadata(); $event = new TimeoutEvent($this->executor, $descriptor->getSocket(), $meta[RequestExecutorInterface::META_USER_CONTEXT], $meta[RequestExecutorInterface::META_CONNECTION_FINISH_TIME] !== null && !$descriptor->getSocket() instanceof ServerSocket ? TimeoutEvent::DURING_IO : TimeoutEvent::DURING_CONNECTION); try { $this->callSocketSubscribers($descriptor, $event); $result = $event->isNextAttemptEnabled(); } catch (SocketException $e) { $this->callExceptionSubscribers($descriptor, $e); $result = false; } if ($result) { $this->updateMetadataForAttempt($descriptor, $event->when()); } return $result; }
/** {@inheritdoc} */ protected function handleOperation(RequestDescriptor $descriptor, RequestExecutorInterface $executor, EventHandlerInterface $eventHandler) { $operation = $descriptor->getOperation(); $socket = $descriptor->getSocket(); $meta = $executor->socketBag()->getSocketMetaData($socket); $context = $meta[RequestExecutorInterface::META_USER_CONTEXT]; try { /** @var ReadOperation $operation */ $response = $socket->read($operation->getFramePicker()); switch (true) { case $response instanceof PartialFrame: return $operation; case $response instanceof AcceptedFrame: $event = new AcceptEvent($executor, $socket, $context, $response->getClientSocket(), $response->getRemoteAddress()); $eventHandler->invokeEvent($event); return new ReadOperation(); default: $event = new ReadEvent($executor, $socket, $context, $response, false); $eventHandler->invokeEvent($event); return $event->getNextOperation(); } } catch (AcceptException $e) { return new ReadOperation(); } }
/** * Check whether socket waiting is finished * * @param RequestDescriptor $descriptor Request descriptor to test * * @return bool True if delay is complete, false otherwise */ private function checkDelayIsFinished(RequestDescriptor $descriptor) { /** @var DelayedOperation $socketOperation */ $socketOperation = $descriptor->getOperation(); $arguments = $socketOperation->getArguments(); array_unshift($arguments, $descriptor->getSocket(), $this->executor); return !call_user_func_array($socketOperation->getCallable(), $arguments); }
/** * Handle OOB data * * @param RequestDescriptor $descriptor Request descriptor * @param RequestExecutorInterface $executor Executor, processing operation * @param EventHandlerInterface $eventHandler Event handler for this operation * * @return OperationInterface|null Operation to return to user or null to continue normal processing */ private function handleOobData(RequestDescriptor $descriptor, RequestExecutorInterface $executor, EventHandlerInterface $eventHandler) { if (!$descriptor->hasState(RequestDescriptor::RDS_OOB)) { return null; } $descriptor->clearState(RequestDescriptor::RDS_OOB); $picker = new RawFramePicker(); $socket = $descriptor->getSocket(); $meta = $descriptor->getMetadata(); $frame = $socket->read($picker, true); $event = new ReadEvent($executor, $socket, $meta[RequestExecutorInterface::META_USER_CONTEXT], $frame, true); $eventHandler->invokeEvent($event); return $event->getNextOperation(); }
/** * Disconnects given socket descriptor * * @param RequestDescriptor $descriptor Socket descriptor * * @return void */ public function disconnect(RequestDescriptor $descriptor) { $meta = $descriptor->getMetadata(); $socket = $descriptor->getSocket(); $descriptor->setMetadata(RequestExecutorInterface::META_REQUEST_COMPLETE, true); try { $socket->close(); if ($meta[RequestExecutorInterface::META_CONNECTION_FINISH_TIME] !== null) { $this->callSocketSubscribers($descriptor, $this->createEvent($descriptor, EventType::DISCONNECTED)); } } catch (SocketException $e) { $this->callExceptionSubscribers($descriptor, $e); } $this->callSocketSubscribers($descriptor, $this->createEvent($descriptor, EventType::FINALIZE)); $this->removeOperationsFromSelector($descriptor); }
/** {@inheritdoc} */ protected function handleOperation(RequestDescriptor $descriptor, RequestExecutorInterface $executor, EventHandlerInterface $eventHandler) { $operation = $descriptor->getOperation(); $socket = $descriptor->getSocket(); /** @var WriteOperation $operation */ $fireEvent = !$operation instanceof InProgressWriteOperation; if ($fireEvent) { $meta = $executor->socketBag()->getSocketMetaData($socket); $event = new WriteEvent($operation, $executor, $socket, $meta[RequestExecutorInterface::META_USER_CONTEXT]); $eventHandler->invokeEvent($event); $nextOperation = $event->getNextOperation(); } else { $nextOperation = $operation; } return $this->writeDataToSocket($operation, $socket, $nextOperation); }
/** * Start connecting process * * @param RequestDescriptor $descriptor Socket operation data * * @return bool True if successfully connected, false otherwise */ private function connectSocket(RequestDescriptor $descriptor) { $descriptor->initialize(); $socket = $descriptor->getSocket(); $event = $this->createEvent($descriptor, EventType::INITIALIZE); try { $this->callSocketSubscribers($descriptor, $event); $this->setSocketOperationTime($descriptor, RequestExecutorInterface::META_CONNECTION_START_TIME); $meta = $descriptor->getMetadata(); $socket->open($meta[RequestExecutorInterface::META_ADDRESS], $this->getStreamContextFromMetaData($meta)); $descriptor->setRunning(true); $result = true; } catch (SocketException $e) { $descriptor->setMetadata(RequestExecutorInterface::META_REQUEST_COMPLETE, true); $this->callExceptionSubscribers($descriptor, $e); $result = false; } return $result; }
/** * Notify handlers about exception * * @param RequestDescriptor $requestDescriptor Socket operation object * @param SocketException $exception Thrown exception * * @return void */ public function callExceptionSubscribers(RequestDescriptor $requestDescriptor, SocketException $exception) { if ($exception instanceof StopSocketOperationException) { return; } $meta = $requestDescriptor->getMetadata(); $exceptionEvent = new SocketExceptionEvent($exception, $this->executor, $requestDescriptor->getSocket(), $meta[RequestExecutorInterface::META_USER_CONTEXT]); $this->callSocketSubscribers($requestDescriptor, $exceptionEvent); }
/** * Notify client about unhandled data in socket * * @param RequestDescriptor $descriptor Socket operation descriptor * @param int $attempt Current attempt number from 1 * @param int $totalAttempts Total attempts * * @return void */ private function notifyDataAlert(RequestDescriptor $descriptor, $attempt, $totalAttempts) { $socket = $descriptor->getSocket(); $meta = $this->executor->socketBag()->getSocketMetaData($socket); $event = new DataAlertEvent($this->executor, $socket, $meta[RequestExecutorInterface::META_USER_CONTEXT], $attempt, $totalAttempts); $this->callSocketSubscribers($descriptor, $event); $operation = $event->getNextOperation(); if ($operation) { $descriptor->setOperation($operation); } }
/** * Create simple event * * @param RequestDescriptor $operation Operation item * @param string $eventName Event name for object * * @return Event */ protected function createEvent(RequestDescriptor $operation, $eventName) { $meta = $operation->getMetadata(); return new Event($this->executor, $operation->getSocket(), $meta[RequestExecutorInterface::META_USER_CONTEXT], $eventName); }
/** {@inheritdoc} */ public function isSatisfiedBy(RequestDescriptor $requestDescriptor) { return $requestDescriptor->getSocket() instanceof UdpClientSocket && $requestDescriptor->getOperation() instanceof ReadOperation; }