nitro-renderer/src/nitro/communication/demo/NitroCommunicationDemo.ts

199 lines
6.5 KiB
TypeScript

import { NitroLogger } from '../../../core/common/logger/NitroLogger';
import { NitroManager } from '../../../core/common/NitroManager';
import { IConnection } from '../../../core/communication/connections/IConnection';
import { SocketConnectionEvent } from '../../../core/communication/events/SocketConnectionEvent';
import { Nitro } from '../../Nitro';
import { INitroCommunicationManager } from '../INitroCommunicationManager';
import { ClientPingEvent } from '../messages/incoming/client/ClientPingEvent';
import { AuthenticatedEvent } from '../messages/incoming/security/AuthenticatedEvent';
import { ClientHelloMessageComposer } from '../messages/outgoing/handshake/ClientHelloMessageComposer';
import { InfoRetrieveMessageComposer } from '../messages/outgoing/handshake/InfoRetrieveMessageComposer';
import { PongMessageComposer } from '../messages/outgoing/handshake/PongMessageComposer';
import { SSOTicketMessageComposer } from '../messages/outgoing/handshake/SSOTicketMessageComposer';
import { NitroCommunicationDemoEvent } from './NitroCommunicationDemoEvent';
export class NitroCommunicationDemo extends NitroManager
{
private _communication: INitroCommunicationManager;
private _handShaking: boolean;
private _didConnect: boolean;
private _pongInterval: any;
constructor(communication: INitroCommunicationManager)
{
super();
this._communication = communication;
this._handShaking = false;
this._didConnect = false;
this._pongInterval = null;
this.onConnectionOpenedEvent = this.onConnectionOpenedEvent.bind(this);
this.onConnectionClosedEvent = this.onConnectionClosedEvent.bind(this);
this.onConnectionErrorEvent = this.onConnectionErrorEvent.bind(this);
this.sendPong = this.sendPong.bind(this);
}
protected onInit(): void
{
const connection = this._communication.connection;
if(connection)
{
connection.addEventListener(SocketConnectionEvent.CONNECTION_OPENED, this.onConnectionOpenedEvent);
connection.addEventListener(SocketConnectionEvent.CONNECTION_CLOSED, this.onConnectionClosedEvent);
connection.addEventListener(SocketConnectionEvent.CONNECTION_ERROR, this.onConnectionErrorEvent);
}
this._communication.registerMessageEvent(new ClientPingEvent(this.onClientPingEvent.bind(this)));
this._communication.registerMessageEvent(new AuthenticatedEvent(this.onAuthenticatedEvent.bind(this)));
}
protected onDispose(): void
{
const connection = this._communication.connection;
if(connection)
{
connection.removeEventListener(SocketConnectionEvent.CONNECTION_OPENED, this.onConnectionOpenedEvent);
connection.removeEventListener(SocketConnectionEvent.CONNECTION_CLOSED, this.onConnectionClosedEvent);
connection.removeEventListener(SocketConnectionEvent.CONNECTION_ERROR, this.onConnectionErrorEvent);
}
this._handShaking = false;
this.stopPonging();
super.onDispose();
}
private onConnectionOpenedEvent(event: Event): void
{
const connection = this._communication.connection;
if(!connection) return;
this._didConnect = true;
this.dispatchCommunicationDemoEvent(NitroCommunicationDemoEvent.CONNECTION_ESTABLISHED, connection);
if(Nitro.instance.getConfiguration<boolean>('system.pong.manually', false)) this.startPonging();
this.startHandshake(connection);
connection.send(new ClientHelloMessageComposer(null, null, null, null));
this.tryAuthentication(connection);
}
private onConnectionClosedEvent(event: CloseEvent): void
{
const connection = this._communication.connection;
if(!connection) return;
this.stopPonging();
if(this._didConnect) this.dispatchCommunicationDemoEvent(NitroCommunicationDemoEvent.CONNECTION_CLOSED, connection);
}
private onConnectionErrorEvent(event: CloseEvent): void
{
const connection = this._communication.connection;
if(!connection) return;
this.stopPonging();
this.dispatchCommunicationDemoEvent(NitroCommunicationDemoEvent.CONNECTION_ERROR, connection);
}
private tryAuthentication(connection: IConnection): void
{
if(!connection || !this.getSSO())
{
if(!this.getSSO())
{
NitroLogger.log('Login without an SSO ticket is not supported');
}
this.dispatchCommunicationDemoEvent(NitroCommunicationDemoEvent.CONNECTION_HANDSHAKE_FAILED, connection);
return;
}
connection.send(new SSOTicketMessageComposer(this.getSSO(), Nitro.instance.time));
}
private onClientPingEvent(event: ClientPingEvent): void
{
if(!event || !event.connection) return;
this.sendPong(event.connection);
}
private onAuthenticatedEvent(event: AuthenticatedEvent): void
{
if(!event || !event.connection) return;
this.completeHandshake(event.connection);
this.dispatchCommunicationDemoEvent(NitroCommunicationDemoEvent.CONNECTION_AUTHENTICATED, event.connection);
event.connection.send(new InfoRetrieveMessageComposer());
}
private startHandshake(connection: IConnection): void
{
this.dispatchCommunicationDemoEvent(NitroCommunicationDemoEvent.CONNECTION_HANDSHAKING, connection);
this._handShaking = true;
}
private completeHandshake(connection: IConnection): void
{
this.dispatchCommunicationDemoEvent(NitroCommunicationDemoEvent.CONNECTION_HANDSHAKED, connection);
this._handShaking = false;
}
private startPonging(): void
{
this.stopPonging();
this._pongInterval = setInterval(this.sendPong, Nitro.instance.getConfiguration<number>('system.pong.interval.ms', 20000));
}
private stopPonging(): void
{
if(!this._pongInterval) return;
clearInterval(this._pongInterval);
this._pongInterval = null;
}
private sendPong(connection: IConnection = null): void
{
connection = ((connection || this._communication.connection) || null);
if(!connection) return;
connection.send(new PongMessageComposer());
}
private dispatchCommunicationDemoEvent(type: string, connection: IConnection): void
{
Nitro.instance.events.dispatchEvent(new NitroCommunicationDemoEvent(type, connection));
}
private getSSO(): string
{
return Nitro.instance.getConfiguration('sso.ticket', null);
}
}