/** * NOT idempotent, call once per disconnection * * @param Connection $connection */ protected function releaseConnection($connection) { $ip = $connection->getIp(); if (!$ip) { $this->logger->warn('Cannot release connection'); return; } if (!isset($this->ips[$ip])) { $this->ips[$ip] = 0; } else { $this->ips[$ip] = max(0, $this->ips[$ip] - 1); } unset($this->requests[$connection->getId()]); }
/** * Removes a connection * * @param Connection $connection */ public function removeConnection(Connection $connection) { $socket = $connection->getSocket(); if ($socket->getResource()) { $index = $socket->getResourceId(); } else { $index = array_search($connection, $this->connections); } if (!$index) { $this->logger->warn('Could not remove connection: not found'); } unset($this->connections[$index]); unset($this->resources[$index]); $this->server->notify(Server::EVENT_SOCKET_DISCONNECT, array($connection->getSocket(), $connection)); }
/** * Closes the connection according to the WebSocket protocol * * If an endpoint receives a Close frame and that endpoint did not * previously send a Close frame, the endpoint MUST send a Close frame * in response. It SHOULD do so as soon as is practical. An endpoint * MAY delay sending a close frame until its current message is sent * (for instance, if the majority of a fragmented message is already * sent, an endpoint MAY send the remaining fragments before sending a * Close frame). However, there is no guarantee that the endpoint which * has already sent a Close frame will continue to process data. * After both sending and receiving a close message, an endpoint * considers the WebSocket connection closed, and MUST close the * underlying TCP connection. The server MUST close the underlying TCP * connection immediately; the client SHOULD wait for the server to * close the connection but MAY close the connection at any time after * sending and receiving a close message, e.g. if it has not received a * TCP close from the server in a reasonable time period. * * @param int|Exception $statusCode * @return boolean */ public function close($code = Protocol::CLOSE_NORMAL) { try { if (!$this->handshaked) { $response = $this->protocol->getResponseError($code); $this->socket->send($response); } else { $response = $this->protocol->getCloseFrame($code); $this->socket->send($response); } } catch (Exception $e) { $this->logger->warn('Unable to send close message'); } if ($this->application && method_exists($this->application, 'onDisconnect')) { $this->application->onDisconnect($this); } $this->socket->disconnect(); $this->manager->removeConnection($this); }