eee
This commit is contained in:
+84
-62
@@ -4,126 +4,148 @@ namespace Coroutine\Server;
|
||||
|
||||
class Transport
|
||||
{
|
||||
|
||||
/**
|
||||
* @var array<Struct>
|
||||
* @var array<int, Struct>
|
||||
*/
|
||||
private array $clients = [];
|
||||
|
||||
|
||||
/**
|
||||
* @param int $userId
|
||||
* @param Struct $data
|
||||
* @return void
|
||||
* @var array<int, int>
|
||||
*/
|
||||
public function add(int $userId, Struct $data): void
|
||||
private array $userIdByFd = [];
|
||||
|
||||
public function add(int $userId, Struct $data): ?Struct
|
||||
{
|
||||
if (isset($this->clients[$userId])) {
|
||||
$this->clients[$userId]->ws->close();
|
||||
}
|
||||
$previous = $this->clients[$userId] ?? null;
|
||||
|
||||
$this->clients[$userId] = $data;
|
||||
if ($data->fd > 0) {
|
||||
$this->userIdByFd[$data->fd] = $userId;
|
||||
}
|
||||
|
||||
if ($previous && $previous->fd !== $data->fd) {
|
||||
unset($this->userIdByFd[$previous->fd]);
|
||||
@$previous->ws->close();
|
||||
}
|
||||
|
||||
return $previous;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $userId
|
||||
* @param mixed $data
|
||||
* @return void
|
||||
*/
|
||||
public function sendUserId(int $userId, mixed $data): void
|
||||
{
|
||||
if (isset($this->clients[$userId])) {
|
||||
$this->clients[$userId]->ws->push($data);
|
||||
$struct = $this->clients[$userId] ?? null;
|
||||
if ($struct === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$struct->touch();
|
||||
@$struct->ws->push($this->normalizePayload($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $fd
|
||||
* @param mixed $data
|
||||
* @return void
|
||||
*/
|
||||
public function sendFd(int $fd, mixed $data): void
|
||||
{
|
||||
$struct = $this->getClientId($fd);
|
||||
$struct?->ws->push($data);
|
||||
if ($struct === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$struct->touch();
|
||||
@$struct->ws->push($this->normalizePayload($data));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $userId
|
||||
* @return void
|
||||
*/
|
||||
public function close(int $userId): void
|
||||
{
|
||||
if (isset($this->clients[$userId])) {
|
||||
$this->clients[$userId]->ws->close();
|
||||
$struct = $this->clients[$userId] ?? null;
|
||||
if ($struct === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@$struct->ws->close();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $userId
|
||||
* @return void
|
||||
*/
|
||||
public function remove(int $userId): void
|
||||
public function remove(int $userId, ?int $fd = null): void
|
||||
{
|
||||
if ($this->has($userId)) {
|
||||
$this->clients[$userId]?->ws->close();
|
||||
$struct = $this->clients[$userId] ?? null;
|
||||
if ($struct === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($fd !== null && $struct->fd !== $fd) {
|
||||
return;
|
||||
}
|
||||
|
||||
unset($this->clients[$userId]);
|
||||
unset($this->userIdByFd[$struct->fd]);
|
||||
|
||||
@$struct->ws->close();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $fd
|
||||
* @return Struct|null
|
||||
*/
|
||||
public function getClientId(int $fd): ?Struct
|
||||
{
|
||||
return array_find($this->clients, fn($client) => $client->fd == $fd);
|
||||
$userId = $this->userIdByFd[$fd] ?? null;
|
||||
if ($userId === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->clients[$userId] ?? null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $userId
|
||||
* @return Struct|null
|
||||
*/
|
||||
public function getUserId(int $userId): ?Struct
|
||||
{
|
||||
return $this->clients[$userId] ?? null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $userId
|
||||
* @return bool
|
||||
*/
|
||||
public function has(int $userId): bool
|
||||
{
|
||||
return isset($this->clients[$userId]);
|
||||
}
|
||||
|
||||
public function touch(int $userId, ?int $fd = null): void
|
||||
{
|
||||
$struct = $this->clients[$userId] ?? null;
|
||||
if ($struct === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($fd !== null && $struct->fd !== $fd) {
|
||||
return;
|
||||
}
|
||||
|
||||
$struct->touch();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getLists(): array
|
||||
{
|
||||
$array = [];
|
||||
foreach ($this->clients as $userId => $client) {
|
||||
$array[] = [
|
||||
'userId' => $userId,
|
||||
'userId' => $userId,
|
||||
'fd' => $client->fd,
|
||||
'nickname' => $client->user->getNickname(),
|
||||
'connectedAt' => $client->connectedAt,
|
||||
'lastSeenAt' => $client->lastSeenAt,
|
||||
];
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function size(): int
|
||||
{
|
||||
return count($this->clients);
|
||||
}
|
||||
|
||||
private function normalizePayload(mixed $data): string
|
||||
{
|
||||
if (is_string($data)) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
if (is_scalar($data) || $data === null) {
|
||||
return (string)$data;
|
||||
}
|
||||
|
||||
$payload = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
return $payload === false ? '' : $payload;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user