public function onMessage(ConnectionInterface $from, $data)
{
$overflow = '';
if (!isset($from->WebSocket->message)) {
$from->WebSocket->message = $this->newMessage();
}
// There is a frame fragment attached to the connection, add to it
if (!isset($from->WebSocket->frame)) {
$from->WebSocket->frame = $this->newFrame();
}
$from->WebSocket->frame->addBuffer($data);
if ($from->WebSocket->frame->isCoalesced()) {
$frame = $from->WebSocket->frame;
if (false !== $frame->getRsv1() || false !== $frame->getRsv2() || false !== $frame->getRsv3()) {
return $from->close($frame::CLOSE_PROTOCOL);
}
if (!$frame->isMasked()) {
return $from->close($frame::CLOSE_PROTOCOL);
}
$opcode = $frame->getOpcode();
if ($opcode > 2) {
if ($frame->getPayloadLength() > 125 || !$frame->isFinal()) {
return $from->close($frame::CLOSE_PROTOCOL);
}
switch ($opcode) {
case $frame::OP_CLOSE:
$closeCode = 0;
$bin = $frame->getPayload();
if (empty($bin)) {
return $from->close();
}
if (strlen($bin) >= 2) {
list($closeCode) = array_merge(unpack('n*', substr($bin, 0, 2)));
}
if (!$this->isValidCloseCode($closeCode)) {
return $from->close($frame::CLOSE_PROTOCOL);
}
if (!$this->validator->checkEncoding(substr($bin, 2), 'UTF-8')) {
return $from->close($frame::CLOSE_BAD_PAYLOAD);
}
$frame->unMaskPayload();
return $from->close($frame);
break;
case $frame::OP_PING:
$from->send($this->newFrame($frame->getPayload(), true, $frame::OP_PONG));
break;
case $frame::OP_PONG:
break;
default:
return $from->close($frame::CLOSE_PROTOCOL);
break;
}
$overflow = $from->WebSocket->frame->extractOverflow();
unset($from->WebSocket->frame, $frame, $opcode);
if (strlen($overflow) > 0) {
$this->onMessage($from, $overflow);
}
return;
}
$overflow = $from->WebSocket->frame->extractOverflow();
if ($frame::OP_CONTINUE == $frame->getOpcode() && 0 == count($from->WebSocket->message)) {
return $from->close($frame::CLOSE_PROTOCOL);
}
if (count($from->WebSocket->message) > 0 && $frame::OP_CONTINUE != $frame->getOpcode()) {
return $from->close($frame::CLOSE_PROTOCOL);
}
$from->WebSocket->message->addFrame($from->WebSocket->frame);
unset($from->WebSocket->frame);
}
if ($from->WebSocket->message->isCoalesced()) {
$parsed = $from->WebSocket->message->getPayload();
unset($from->WebSocket->message);
if (!$this->validator->checkEncoding($parsed, 'UTF-8')) {
return $from->close(Frame::CLOSE_BAD_PAYLOAD);
}
$from->WebSocket->coalescedCallback->onMessage($from, $parsed);
}
if (strlen($overflow) > 0) {
$this->onMessage($from, $overflow);
}
}