/**
* Called when new data received
* @return void
*/
public function onRead()
{
start:
if ($this->state === static::STATE_HEADER) {
$l = $this->getInputLength();
if ($l < 2) {
return;
}
$hdr = $this->look(2);
$fb = Binary::getbitmap(ord($hdr));
$fin = (bool) $fb[0];
$opCode = bindec(substr($fb, 4, 4));
if (isset($this->opCodes[$opCode])) {
$this->type = $this->opCodes[$opCode];
} else {
$this->log('opCode: ' . $opCode . ': unknown frame type');
$this->finish();
return;
}
$sb = ord(binarySubstr($hdr, 1));
$sbm = Binary::getbitmap($sb);
$this->isMasked = (bool) $sbm[0];
$payloadLength = $sb & 127;
if ($payloadLength <= 125) {
$this->drain(2);
$this->pctLength = $payloadLength;
} elseif ($payloadLength === 126) {
if ($l < 4) {
return;
}
$this->drain(2);
$this->pctLength = Binary::b2i($this->read(2));
} elseif ($payloadLength === 127) {
if ($l < 10) {
return;
}
$this->drain(2);
$this->pctLength = Binary::b2i($this->read(8));
}
if ($this->pool->maxAllowedPacket < $this->pctLength) {
Daemon::$process->log('max-allowed-packet (' . $this->pool->config->maxallowedpacket->getHumanValue() . ') exceed, aborting connection');
$this->finish();
return;
}
$this->setWatermark($this->pctLength + ($this->isMasked ? 4 : 0));
$this->state = static::STATE_DATA;
}
if ($this->state === static::STATE_DATA) {
if ($this->getInputLength() < $this->pctLength + ($this->isMasked ? 4 : 0)) {
return;
}
$this->state = static::STATE_HEADER;
$this->setWatermark(2);
if ($this->isMasked) {
$this->trigger('frame', static::mask($this->read(4), $this->read($this->pctLength)));
} else {
$this->trigger('frame', $this->read($this->pctLength));
}
}
if ($this->state == static::STATE_STANDBY) {
while (($line = $this->readLine()) !== null) {
$line = trim($line);
if ($line == '') {
$expectedKey = base64_encode(pack('H*', sha1($this->key . static::GUID)));
if (isset($this->headers['HTTP_SEC_WEBSOCKET_ACCEPT']) && $expectedKey == $this->headers['HTTP_SEC_WEBSOCKET_ACCEPT']) {
$this->state = static::STATE_HEADER;
if ($this->onConnected) {
$this->connected = true;
$this->onConnected->executeAll($this);
$this->onConnected = null;
}
$this->trigger('connected');
goto start;
} else {
Daemon::$process->log(__METHOD__ . ': Handshake failed. Connection to ' . $this->url . ' failed.');
$this->finish();
}
} else {
$e = explode(': ', $line);
if (isset($e[1])) {
$this->headers['HTTP_' . strtoupper(strtr($e[0], ['-' => '_']))] = $e[1];
}
}
}
return;
}
goto start;
}