/** * @inheritDoc */ public function __invoke(ObservableInterface $observable, ObserverInterface $observer, SchedulerInterface $scheduler = null) { return $observable->subscribe(new CallbackObserver(function ($data) use($observer) { while (strlen($data) > 0) { $frame = $this->frame; $frame->addBuffer($data); $data = ""; if ($frame->isCoalesced()) { $result = $this->validator->validateFrame($frame, $this->previousFrame); if (0 !== $result) { $observer->onError(new WebsocketErrorException($result)); } $data = $frame->extractOverflow(); $frame->unMaskPayload(); $observer->onNext($frame); if ($frame->getOpcode() < 3) { $this->previousFrame = $this->frame; if ($frame->isFinal()) { $this->previousFrame = null; } } $this->frame = new Frame(); } } }, [$observer, 'onError'], [$observer, 'onCompleted'])); }
public function onData($data, ContextInterface $context) { $overflow = ''; $message = $context->getMessage() ?: $context->setMessage($this->newMessage()); $frame = $context->getFrame() ?: $context->setFrame($this->newFrame()); $frame->addBuffer($data); if ($frame->isCoalesced()) { $frameCount = $message->count(); $prevFrame = $frameCount > 0 ? $message[$frameCount - 1] : null; $frameStatus = $this->validator->validateFrame($frame, $prevFrame); if (0 !== $frameStatus) { return $context->onClose($frameStatus); } $opcode = $frame->getOpcode(); if ($opcode > 2) { switch ($opcode) { case Frame::OP_PING: $context->onPing($frame); break; case Frame::OP_PONG: $context->onPong($frame); break; } $overflow = $frame->extractOverflow(); $context->setFrame(null); if (strlen($overflow) > 0) { $this->onData($overflow, $context); } return; } $overflow = $frame->extractOverflow(); $frame->unMaskPayload(); $message->addFrame($frame); $context->setFrame(null); } if ($message->isCoalesced()) { $msgCheck = $this->validator->checkMessage($message); if (true !== $msgCheck) { return $context->onClose($msgCheck); } $context->onMessage($message); $context->setMessage(null); } if (strlen($overflow) > 0) { $this->onData($overflow, $context); } }