Commit 871772f8 authored by nanahira's avatar nanahira

fix zombie again

parent 5e0de755
Pipeline #43360 passed with stages
in 4 minutes and 51 seconds
...@@ -21,6 +21,7 @@ import { ...@@ -21,6 +21,7 @@ import {
timer, timer,
} from 'rxjs'; } from 'rxjs';
import { YGOProCtosDisconnect } from '../utility/ygopro-ctos-disconnect'; import { YGOProCtosDisconnect } from '../utility/ygopro-ctos-disconnect';
import PQueue from 'p-queue';
export class ClientHandler { export class ClientHandler {
private static readonly CLIENT_IDLE_TIMEOUT_MS = 5 * 60 * 1000; private static readonly CLIENT_IDLE_TIMEOUT_MS = 5 * 60 * 1000;
...@@ -69,6 +70,9 @@ export class ClientHandler { ...@@ -69,6 +70,9 @@ export class ClientHandler {
.middleware( .middleware(
YGOProCtosBase, YGOProCtosBase,
async (msg, client, next) => { async (msg, client, next) => {
if (msg instanceof YGOProCtosDisconnect) {
return next();
}
const bypassEstablished = const bypassEstablished =
msg instanceof YGOProCtosJoinGame && msg.bypassEstablished; msg instanceof YGOProCtosJoinGame && msg.bypassEstablished;
if (bypassEstablished) { if (bypassEstablished) {
...@@ -76,7 +80,7 @@ export class ClientHandler { ...@@ -76,7 +80,7 @@ export class ClientHandler {
return next(); return next();
} }
if (client.established === this.isPreHandshakeMsg(msg)) { if (!client.established && !this.isPreHandshakeMsg(msg)) {
// disallow any messages before handshake is complete, except for the ones needed for handshake // disallow any messages before handshake is complete, except for the ones needed for handshake
return undefined; return undefined;
} }
...@@ -102,23 +106,10 @@ export class ClientHandler { ...@@ -102,23 +106,10 @@ export class ClientHandler {
// 合并 receive$ 和 disconnect$ // 合并 receive$ 和 disconnect$
const receive$ = merge(client.receive$, disconnect$); const receive$ = merge(client.receive$, disconnect$);
const dispatchQueue = new PQueue({ concurrency: 1 });
receive$.subscribe(async (msg) => { receive$.subscribe((msg) => {
this.logger.debug( dispatchQueue.add(async () => this.dispatchClientMessage(client, msg));
{
msgName: msg.constructor.name,
client: client.name || client.loggingIp(),
payload: JSON.stringify(msg),
},
'Received client message',
);
try {
await this.ctx.dispatch(msg, client);
} catch (e) {
this.logger.warn(
`Error dispatching message ${msg.constructor.name} from ${client.loggingIp()}: ${(e as Error).stack}`,
);
}
}); });
const handshake$ = forkJoin([ const handshake$ = forkJoin([
...@@ -159,6 +150,24 @@ export class ClientHandler { ...@@ -159,6 +150,24 @@ export class ClientHandler {
}); });
} }
private async dispatchClientMessage(client: Client, msg: YGOProCtosBase) {
this.logger.debug(
{
msgName: msg.constructor.name,
client: client.name || client.loggingIp(),
payload: JSON.stringify(msg),
},
'Received client message',
);
try {
await this.ctx.dispatch(msg, client);
} catch (e) {
this.logger.warn(
`Error dispatching message ${msg.constructor.name} from ${client.loggingIp()}: ${(e as Error).stack}`,
);
}
}
private installIdleDisconnectGuard(client: Client) { private installIdleDisconnectGuard(client: Client) {
client.receive$ client.receive$
.pipe( .pipe(
......
...@@ -30,6 +30,7 @@ import { ...@@ -30,6 +30,7 @@ import {
resolveColoredMessages, resolveColoredMessages,
splitColoredMessagesByLine, splitColoredMessagesByLine,
} from '../utility'; } from '../utility';
import { RoomManager } from '../room';
export class Client { export class Client {
protected async _send(data: Buffer): Promise<void> { protected async _send(data: Buffer): Promise<void> {
...@@ -68,7 +69,7 @@ export class Client { ...@@ -68,7 +69,7 @@ export class Client {
).pipe( ).pipe(
take(1), take(1),
tap(() => { tap(() => {
this.disconnected = new Date(); this.disconnected ??= new Date();
}), }),
share(), share(),
); );
...@@ -101,6 +102,13 @@ export class Client { ...@@ -101,6 +102,13 @@ export class Client {
disconnected?: Date; disconnected?: Date;
disconnect(): undefined { disconnect(): undefined {
this.disconnected ??= new Date();
if (this.roomName) {
const room = this.ctx.get(() => RoomManager).findByName(this.roomName);
if (room) {
room.removePlayer(this, true);
}
}
this.disconnectSubject.next(); this.disconnectSubject.next();
this.disconnectSubject.complete(); this.disconnectSubject.complete();
this._disconnect().then(); this._disconnect().then();
......
...@@ -51,6 +51,21 @@ export class RoomEventRegister { ...@@ -51,6 +51,21 @@ export class RoomEventRegister {
if (ctosParamIndex === -1 || !ctosParamType) { if (ctosParamIndex === -1 || !ctosParamType) {
continue; continue;
} }
if (clientParamIndex === -1) {
const fallbackClientIndex = paramTypes.findIndex(
(_paramType, index) => index !== ctosParamIndex,
);
if (fallbackClientIndex === -1) {
this.logger.warn(
`Method ${method} has no resolvable client parameter index, skipping`,
);
continue;
}
clientParamIndex = fallbackClientIndex;
this.logger.warn(
`Method ${method} has no explicit Client param metadata, fallback to arg[${clientParamIndex}] for client`,
);
}
// 获取方法选项 // 获取方法选项
const options: RoomMethodOptions = metadata; const options: RoomMethodOptions = metadata;
......
...@@ -582,11 +582,28 @@ export class Room { ...@@ -582,11 +582,28 @@ export class Room {
} }
@RoomMethod() @RoomMethod()
private async onDisconnect(client: Client, _msg: YGOProCtosDisconnect) { private async onDisconnect(client: Client, msg: YGOProCtosDisconnect) {
if (!client) {
return;
}
return this.removePlayer(client, msg.bySystem);
}
async removePlayer(client: Client | undefined, bySystem = false) {
if (!client) {
return;
}
if (this.finalizing) { if (this.finalizing) {
return; return;
} }
const wasObserver = client.pos === NetPlayerType.OBSERVER; const wasObserver = client.pos === NetPlayerType.OBSERVER;
if (wasObserver) {
if (!this.watchers.has(client)) {
return;
}
} else if (this.players[client.pos] !== client) {
return;
}
const oldPos = client.pos; const oldPos = client.pos;
if (wasObserver) { if (wasObserver) {
...@@ -631,7 +648,7 @@ export class Room { ...@@ -631,7 +648,7 @@ export class Room {
new OnRoomLeaveObserver( new OnRoomLeaveObserver(
this, this,
RoomLeaveObserverReason.Disconnect, RoomLeaveObserverReason.Disconnect,
_msg.bySystem, bySystem,
), ),
client, client,
); );
...@@ -641,7 +658,7 @@ export class Room { ...@@ -641,7 +658,7 @@ export class Room {
this, this,
oldPos, oldPos,
RoomLeavePlayerReason.Disconnect, RoomLeavePlayerReason.Disconnect,
_msg.bySystem, bySystem,
), ),
client, client,
); );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment