/** * 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; }