public function onRead()
{
if ($this->state === self::STATE_PREHANDSHAKE) {
if (!$this->handshake()) {
return;
}
}
if ($this->state === self::STATE_HANDSHAKED) {
while (($buflen = $this->getInputLength()) >= 2) {
$first = ord($this->look(1));
// first byte integer (fin, opcode)
$firstBits = decbin($first);
$opcode = (int) bindec(substr($firstBits, 4, 4));
if ($opcode === 0x8) {
// CLOSE
$this->finish();
return;
}
$opcodeName = isset(static::$opcodes[$opcode]) ? static::$opcodes[$opcode] : false;
if (!$opcodeName) {
Daemon::log(get_class($this) . ': Undefined opcode ' . $opcode);
$this->finish();
return;
}
$second = ord($this->look(1, 1));
// second byte integer (masked, payload length)
$fin = (bool) ($first >> 7);
$isMasked = (bool) ($second >> 7);
$dataLength = $second & 0x7f;
$p = 2;
if ($dataLength === 0x7e) {
// 2 bytes-length
if ($buflen < $p + 2) {
return;
// not enough data yet
}
$dataLength = Binary::bytes2int($this->look(2, $p), false);
$p += 2;
} elseif ($dataLength === 0x7f) {
// 8 bytes-length
if ($buflen < $p + 8) {
return;
// not enough data yet
}
$dataLength = Binary::bytes2int($this->look(8, $p));
$p += 8;
}
if ($this->pool->maxAllowedPacket <= $dataLength) {
// Too big packet
$this->finish();
return;
}
if ($isMasked) {
if ($buflen < $p + 4) {
return;
// not enough data yet
}
$mask = $this->look(4, $p);
$p += 4;
}
if ($buflen < $p + $dataLength) {
return;
// not enough data yet
}
$this->drain($p);
$data = $this->read($dataLength);
if ($isMasked) {
$data = $this->mask($data, $mask);
}
//Daemon::log(Debug::dump(array('ext' => $this->extensions, 'rsv1' => $firstBits[1], 'data' => Debug::exportBytes($data))));
/*if ($firstBits[1] && in_array('deflate-frame', $this->extensions)) { // deflate frame
$data = gzuncompress($data, $this->pool->maxAllowedPacket);
}*/
if (!$fin) {
$this->framebuf .= $data;
} else {
$this->onFrame($this->framebuf . $data, $opcodeName);
$this->framebuf = '';
}
}
}
}