This commit is contained in:
2026-05-09 22:17:19 +08:00
parent 4ae3001fe3
commit 3ee115df2e
4 changed files with 168 additions and 10 deletions
+10
View File
@@ -22,6 +22,12 @@ class Struct
public Response $ws; public Response $ws;
/**
* @param AuthorizationInterface $user
* @param Request $request
* @param Response $ws
*/
public function __construct(AuthorizationInterface $user, Request $request, Response $ws) public function __construct(AuthorizationInterface $user, Request $request, Response $ws)
{ {
$this->user = $user; $this->user = $user;
@@ -33,6 +39,10 @@ class Struct
$this->lastSeenAt = $this->connectedAt; $this->lastSeenAt = $this->connectedAt;
} }
/**
* @return void
*/
public function touch(): void public function touch(): void
{ {
$this->lastSeenAt = time(); $this->lastSeenAt = time();
+62
View File
@@ -14,6 +14,12 @@ class Transport
*/ */
private array $userIdByFd = []; private array $userIdByFd = [];
/**
* @param int $userId
* @param Struct $data
* @return Struct|null
*/
public function add(int $userId, Struct $data): ?Struct public function add(int $userId, Struct $data): ?Struct
{ {
$previous = $this->clients[$userId] ?? null; $previous = $this->clients[$userId] ?? null;
@@ -31,6 +37,12 @@ class Transport
return $previous; return $previous;
} }
/**
* @param int $userId
* @param mixed $data
* @return void
*/
public function sendUserId(int $userId, mixed $data): void public function sendUserId(int $userId, mixed $data): void
{ {
$struct = $this->clients[$userId] ?? null; $struct = $this->clients[$userId] ?? null;
@@ -42,6 +54,12 @@ class Transport
@$struct->ws->push($this->normalizePayload($data)); @$struct->ws->push($this->normalizePayload($data));
} }
/**
* @param int $fd
* @param mixed $data
* @return void
*/
public function sendFd(int $fd, mixed $data): void public function sendFd(int $fd, mixed $data): void
{ {
$struct = $this->getClientId($fd); $struct = $this->getClientId($fd);
@@ -53,6 +71,11 @@ class Transport
@$struct->ws->push($this->normalizePayload($data)); @$struct->ws->push($this->normalizePayload($data));
} }
/**
* @param int $userId
* @return void
*/
public function close(int $userId): void public function close(int $userId): void
{ {
$struct = $this->clients[$userId] ?? null; $struct = $this->clients[$userId] ?? null;
@@ -63,6 +86,12 @@ class Transport
@$struct->ws->close(); @$struct->ws->close();
} }
/**
* @param int $userId
* @param int|null $fd
* @return void
*/
public function remove(int $userId, ?int $fd = null): void public function remove(int $userId, ?int $fd = null): void
{ {
$struct = $this->clients[$userId] ?? null; $struct = $this->clients[$userId] ?? null;
@@ -80,6 +109,11 @@ class Transport
@$struct->ws->close(); @$struct->ws->close();
} }
/**
* @param int $fd
* @return Struct|null
*/
public function getClientId(int $fd): ?Struct public function getClientId(int $fd): ?Struct
{ {
$userId = $this->userIdByFd[$fd] ?? null; $userId = $this->userIdByFd[$fd] ?? null;
@@ -90,16 +124,31 @@ class Transport
return $this->clients[$userId] ?? null; return $this->clients[$userId] ?? null;
} }
/**
* @param int $userId
* @return Struct|null
*/
public function getUserId(int $userId): ?Struct public function getUserId(int $userId): ?Struct
{ {
return $this->clients[$userId] ?? null; return $this->clients[$userId] ?? null;
} }
/**
* @param int $userId
* @return bool
*/
public function has(int $userId): bool public function has(int $userId): bool
{ {
return isset($this->clients[$userId]); return isset($this->clients[$userId]);
} }
/**
* @param int $userId
* @param int|null $fd
* @return void
*/
public function touch(int $userId, ?int $fd = null): void public function touch(int $userId, ?int $fd = null): void
{ {
$struct = $this->clients[$userId] ?? null; $struct = $this->clients[$userId] ?? null;
@@ -114,6 +163,10 @@ class Transport
$struct->touch(); $struct->touch();
} }
/**
* @return array
*/
public function getLists(): array public function getLists(): array
{ {
$array = []; $array = [];
@@ -130,11 +183,20 @@ class Transport
return $array; return $array;
} }
/**
* @return int
*/
public function size(): int public function size(): int
{ {
return count($this->clients); return count($this->clients);
} }
/**
* @param mixed $data
* @return string
*/
private function normalizePayload(mixed $data): string private function normalizePayload(mixed $data): string
{ {
if (is_string($data)) { if (is_string($data)) {
+92 -7
View File
@@ -2,8 +2,11 @@
namespace Coroutine\Server; namespace Coroutine\Server;
use Kiri\Di\Context;
use Kiri\Di\Inject\Container; use Kiri\Di\Inject\Container;
use Kiri\Router\Constrict\ConstrictRequest; use Kiri\Router\Constrict\ConstrictRequest;
use Psr\Http\Message\RequestInterface;
use Swoole\Coroutine;
use Swoole\Coroutine\Http\Server; use Swoole\Coroutine\Http\Server;
use Swoole\Http\Request; use Swoole\Http\Request;
use Swoole\Http\Response; use Swoole\Http\Response;
@@ -15,8 +18,17 @@ abstract class Websocket
#[Container(Transport::class)] #[Container(Transport::class)]
public Transport $transport; public Transport $transport;
/**
* @var Config
*/
public Config $config; public Config $config;
/**
* @param Config $config
* @return void
*/
public function start(Config $config): void public function start(Config $config): void
{ {
$this->config = $config; $this->config = $config;
@@ -35,6 +47,12 @@ abstract class Websocket
$server->start(); $server->start();
} }
/**
* @param Request $request
* @param Response $ws
* @return void
*/
public function getLists(Request $request, Response $ws): void public function getLists(Request $request, Response $ws): void
{ {
try { try {
@@ -59,6 +77,12 @@ abstract class Websocket
} }
} }
/**
* @param Request $request
* @param Response $ws
* @return void
*/
public function handler(Request $request, Response $ws): void public function handler(Request $request, Response $ws): void
{ {
$upgraded = false; $upgraded = false;
@@ -115,11 +139,21 @@ abstract class Websocket
} }
} }
/**
* @return void
*/
abstract public function onBeforeMessageLoop(): void; abstract public function onBeforeMessageLoop(): void;
protected function authorizeConnection(Request $request): ConstrictRequest
/**
* @param Request $request
* @return ConstrictRequest
*/
protected function authorizeConnection(Request $request): RequestInterface
{ {
$psr7Request = ConstrictRequest::builder($request); /** @var RequestInterface $psr7Request */
$psr7Request = Context::set(RequestInterface::class, ConstrictRequest::builder($request));
if (!$psr7Request->hasQuery($this->config->authKey)) { if (!$psr7Request->hasQuery($this->config->authKey)) {
throw new \RuntimeException('Missing auth parameter.', 400); throw new \RuntimeException('Missing auth parameter.', 400);
} }
@@ -131,7 +165,12 @@ abstract class Websocket
return $psr7Request; return $psr7Request;
} }
protected function authorizeOnlineListRequest(ConstrictRequest $request): bool
/**
* @param ConstrictRequest $request
* @return bool
*/
protected function authorizeOnlineListRequest(RequestInterface $request): bool
{ {
if (!$request->hasQuery($this->config->authKey)) { if (!$request->hasQuery($this->config->authKey)) {
return false; return false;
@@ -140,20 +179,34 @@ abstract class Websocket
return $this->canViewOnlineLists($request) && $request->getAuthority() !== null; return $this->canViewOnlineLists($request) && $request->getAuthority() !== null;
} }
/**
* @param ConstrictRequest $request
* @return bool
*/
protected function canViewOnlineLists(ConstrictRequest $request): bool protected function canViewOnlineLists(ConstrictRequest $request): bool
{ {
return $this->onConnected($request); return $this->onConnected($request);
} }
/**
* @return void
*/
private function configureRuntime(): void private function configureRuntime(): void
{ {
if ($this->config->maxCoroutine > 0 && class_exists(\Swoole\Coroutine::class)) { if ($this->config->maxCoroutine > 0 && class_exists(Coroutine::class)) {
\Swoole\Coroutine::set([ Coroutine::set([
'max_coroutine' => $this->config->maxCoroutine, 'max_coroutine' => $this->config->maxCoroutine,
]); ]);
} }
} }
/**
* @param Server $server
* @return void
*/
private function configureServer(Server $server): void private function configureServer(Server $server): void
{ {
if (!method_exists($server, 'set')) { if (!method_exists($server, 'set')) {
@@ -173,6 +226,11 @@ abstract class Websocket
} }
} }
/**
* @param string $payload
* @return void
*/
private function assertPayloadSize(string $payload): void private function assertPayloadSize(string $payload): void
{ {
$size = strlen($payload); $size = strlen($payload);
@@ -186,6 +244,13 @@ abstract class Websocket
} }
} }
/**
* @param Response $ws
* @param Throwable $throwable
* @param bool $upgraded
* @return void
*/
private function throwable(Response $ws, Throwable $throwable, bool $upgraded): void private function throwable(Response $ws, Throwable $throwable, bool $upgraded): void
{ {
$status = $throwable->getCode(); $status = $throwable->getCode();
@@ -220,11 +285,31 @@ abstract class Websocket
$ws->end($message); $ws->end($message);
} }
abstract public function onConnected(ConstrictRequest $request): bool;
/**
* @param RequestInterface $request
* @return bool
*/
abstract public function onConnected(RequestInterface $request): bool;
/**
* @return void
*/
abstract public function onStart(): void; abstract public function onStart(): void;
abstract public function onMessage(ConstrictRequest $psr7Request, string $frame): void;
/**
* @param RequestInterface $psr7Request
* @param string $frame
* @return void
*/
abstract public function onMessage(RequestInterface $psr7Request, string $frame): void;
/**
* @param int $userId
* @return void
*/
abstract public function onDisconnect(int $userId): void; abstract public function onDisconnect(int $userId): void;
} }
+4 -3
View File
@@ -4,6 +4,7 @@
use Coroutine\Server\Config; use Coroutine\Server\Config;
use Coroutine\Server\Websocket; use Coroutine\Server\Websocket;
use Kiri\Router\Constrict\ConstrictRequest; use Kiri\Router\Constrict\ConstrictRequest;
use Psr\Http\Message\RequestInterface;
use function Co\run; use function Co\run;
@@ -18,11 +19,11 @@ class Test extends Websocket
* @param ConstrictRequest $request * @param ConstrictRequest $request
* @return bool * @return bool
*/ */
public function onConnected(ConstrictRequest $request): bool public function onConnected(RequestInterface $request): bool
{ {
// TODO: Implement onConnected() method. // TODO: Implement onConnected() method.
// $request->withAuthority($authorization); // $request->withAuthority(null);
return false; return false;
} }
@@ -36,7 +37,7 @@ class Test extends Websocket
* @param string $frame * @param string $frame
* @return void * @return void
*/ */
public function onMessage(ConstrictRequest $psr7Request, string $frame): void public function onMessage(RequestInterface $psr7Request, string $frame): void
{ {
// TODO: Implement onMessage() method. // TODO: Implement onMessage() method.
} }