/** * Gets the correct messagetype value, based on the current connection object * @param \System\Web\Websocket\Connection The connection object * @param int The requested messagetype * @return int The messagetype value */ public static function getMessageType(\System\Web\Websocket\Connection $connection, $messageType) { switch ($messageType) { case self::TYPE_TEXT: return $connection->isSendingContinuous() ? 0 : self::TYPE_TEXT; case self::TYPE_BINARY: return $connection->isSendingContinuous() ? 0 : self::TYPE_BINARY; default: return $messageType; } }
/** * Performs the handshake between the client and the server. Also checks if * the client is allowed to connect based on its credentials and properties * @param \System\Web\Websocket\Connection The connection to initiate * @param string The buffer */ private function doHandshake(\System\Web\Websocket\Connection $connection, $buffer) { $requestHeaders = array(); $lines = explode("\n", $buffer); foreach ($lines as $line) { //the response to send to the client $response = ''; if (strpos($line, ':') !== false) { $headerLine = explode(':', $line, 2); $requestHeaders[strtolower(trim($headerLine[0]))] = trim($headerLine[1]); } elseif (stripos($line, 'get') !== false) { preg_match("/GET (.*) HTTP/i", $buffer, $requestResource); $requestHeaders['get'] = trim($requestResource[1]); } } if (isset($requestHeaders['get'])) { $connection->setRequestedResource($requestHeaders['get']); } else { $response = self::HTTP_METHOD_NOT_ALLOWED; } if (!isset($requestHeaders['host']) || !$this->hostAllowed($requestHeaders['host'])) { $response = self::HTTP_BAD_REQUEST; } if (!isset($requestHeaders['upgrade']) || strtolower($requestHeaders['upgrade']) != 'websocket') { $response = self::HTTP_BAD_REQUEST; } if (!isset($requestHeaders['connection']) || strpos(strtolower($requestHeaders['connection']), 'upgrade') === false) { $response = self::HTTP_BAD_REQUEST; } if (!isset($requestHeaders['sec-websocket-key'])) { $response = self::HTTP_BAD_REQUEST; } if (!isset($requestHeaders['sec-websocket-version']) || strtolower($requestHeaders['sec-websocket-version']) != 13) { $response = self::HTTP_UPGRADE_REQUIRED; } if ($this->getHeaderOriginRequired() && !isset($requestHeaders['origin']) || $this->getHeaderOriginRequired() && !$this->originAllowed($requestHeaders['origin'])) { $response = self::HTTP_FORBIDDEN; } if ($this->getHeaderSecWebSocketProtocolRequired() && !isset($requestHeaders['sec-websocket-protocol']) || $this->getHeaderSecWebSocketProtocolRequired() && !$this->websocketProtocolAllowed($requestHeaders['sec-websocket-protocol'])) { $response = "HTTP/1.1 400 Bad Request"; } if ($this->getHeaderSecWebSocketExtensionsRequired() && !isset($requestHeaders['sec-websocket-extensions']) || $this->getHeaderSecWebSocketExtensionsRequired() && !$this->websocketExtensionsAllowed($requestHeaders['sec-websocket-extensions'])) { $response = "HTTP/1.1 400 Bad Request"; } if (!empty($response)) { if (@socket_write($connection->getSocket(), $response, strlen($response)) === false) { $this->handleSocketError(false); } $this->disconnect($connection->getSocket()); return; } $connection->setHeaders($requestHeaders); $connection->setHandshake($buffer); $websocketKeyHash = sha1($requestHeaders['sec-websocket-key'] . self::WEBSOCKET_GUID); $rawToken = ''; for ($i = 0; $i < 20; $i++) { $rawToken .= chr(hexdec(substr($websocketKeyHash, $i * 2, 2))); } $handshakeToken = base64_encode($rawToken) . "\r\n"; $subProtocol = isset($requestHeaders['sec-websocket-protocol']) ? $this->processProtocol($requestHeaders['sec-websocket-protocol']) : ""; $extensions = isset($requestHeaders['sec-websocket-extensions']) ? $this->processExtensions($requestHeaders['sec-websocket-extensions']) : ""; $handshakeResponse = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: {$handshakeToken}{$subProtocol}{$extensions}\r\n"; if (@socket_write($connection->getSocket(), $handshakeResponse, strlen($handshakeResponse)) === false) { $this->handleSocketError(false); $this->disconnect($connection->getSocket()); } else { $onConnectedEvent = new \System\Web\Websocket\Event\OnConnectedEvent(); $onConnectedEvent->setServer($this); $onConnectedEvent->setConnection($connection); $onConnectedEvent->raise(); } }