|
@@ -6,10 +6,17 @@ import {
|
|
OnGatewayConnection,
|
|
OnGatewayConnection,
|
|
OnGatewayDisconnect,
|
|
OnGatewayDisconnect,
|
|
} from '@nestjs/websockets';
|
|
} from '@nestjs/websockets';
|
|
|
|
+
|
|
import { Server } from 'ws';
|
|
import { Server } from 'ws';
|
|
import * as WebSocket from 'ws';
|
|
import * as WebSocket from 'ws';
|
|
|
|
|
|
|
|
+import { PeerConnection, initLogger, DataChannel } from 'node-datachannel';
|
|
|
|
+import { Buffer } from 'buffer';
|
|
import { Logger } from '@nestjs/common';
|
|
import { Logger } from '@nestjs/common';
|
|
|
|
+import * as path from 'path';
|
|
|
|
+import { createReadStream } from 'fs';
|
|
|
|
+
|
|
|
|
+initLogger('Debug');
|
|
|
|
|
|
@WebSocketGateway(3100, {
|
|
@WebSocketGateway(3100, {
|
|
transports: ['websocket'],
|
|
transports: ['websocket'],
|
|
@@ -20,20 +27,194 @@ import { Logger } from '@nestjs/common';
|
|
export class MetaGateway
|
|
export class MetaGateway
|
|
implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect {
|
|
implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect {
|
|
private logger: Logger = new Logger('MetaGateway');
|
|
private logger: Logger = new Logger('MetaGateway');
|
|
- // @WebSocketServer() server;
|
|
|
|
|
|
+ private peer: PeerConnection = null;
|
|
|
|
+ private timer: NodeJS.Timeout;
|
|
|
|
+ private _webrtcInterval: NodeJS.Timeout;
|
|
|
|
+ private heartBeatFlag: number;
|
|
|
|
+ private gameChanel: DataChannel;
|
|
|
|
+ @WebSocketServer() server: Server;
|
|
|
|
+
|
|
// @SubscribeMessage('message')
|
|
// @SubscribeMessage('message')
|
|
- // handleMessage(client: any, payload: any): string {
|
|
|
|
- // console.log('payload', payload);
|
|
|
|
- // return 'Hello world!';
|
|
|
|
|
|
+ // handleMessage(client: any, payload: any) {
|
|
|
|
+ // this.logger.log(`payload: ${JSON.stringify(payload)}`);
|
|
// }
|
|
// }
|
|
|
|
+
|
|
|
|
+ @SubscribeMessage('init')
|
|
|
|
+ handleInit(client: any, payload: any) {
|
|
|
|
+ this.logger.log(`init: ${JSON.stringify(payload)}`);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @SubscribeMessage('heartbeat')
|
|
|
|
+ handleHeartBeat(client: any, payload: any) {
|
|
|
|
+ this.logger.log(`heartbeat: ${JSON.stringify(payload)}`);
|
|
|
|
+ // console.log('hb', payload);
|
|
|
|
+ this.heartBeatFlag = payload;
|
|
|
|
+ const pong = {
|
|
|
|
+ channel_id: '',
|
|
|
|
+ client_os: '',
|
|
|
|
+ data: payload,
|
|
|
|
+ fe_version: '',
|
|
|
|
+ id: 'heartbeat',
|
|
|
|
+ packet_id: '',
|
|
|
|
+ room_id: '',
|
|
|
|
+ session_id: '',
|
|
|
|
+ trace_id: '',
|
|
|
|
+ user_id: '',
|
|
|
|
+ };
|
|
|
|
+ if (this.gameChanel.isOpen) {
|
|
|
|
+ const heartPack = new DataView(new ArrayBuffer(4));
|
|
|
|
+ heartPack.setUint32(0, 2009889916);
|
|
|
|
+ this.gameChanel.sendMessageBinary(Buffer.from(heartPack.buffer));
|
|
|
|
+ }
|
|
|
|
+ return pong;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @SubscribeMessage('init_webrtc')
|
|
|
|
+ handleInitWebRtc(client: any, payload: any): void {
|
|
|
|
+ console.log('handleInitWebRtc');
|
|
|
|
+
|
|
|
|
+ this.peer = new PeerConnection('roomTest', {
|
|
|
|
+ iceServers: ['stun:120.24.252.95:3478'],
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ this.peer.onLocalDescription((sdp, type) => {
|
|
|
|
+ console.warn('peer SDP:', sdp, ' Type:', type);
|
|
|
|
+ const offer = { sdp, type };
|
|
|
|
+ const offerFormat = {
|
|
|
|
+ id: 'offer',
|
|
|
|
+ data: Buffer.from(JSON.stringify(offer)).toString('base64'),
|
|
|
|
+ };
|
|
|
|
+ console.log('send', offerFormat);
|
|
|
|
+ client.send(JSON.stringify(offerFormat));
|
|
|
|
+ // return '';
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ this.peer.onLocalCandidate((candidate, mid) => {
|
|
|
|
+ console.warn('peer Candidate:', candidate);
|
|
|
|
+ const iceRes = {
|
|
|
|
+ candidate,
|
|
|
|
+ sdpMid: mid,
|
|
|
|
+ sdpMLineIndex: 0,
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ const res = {
|
|
|
|
+ channel_id: '',
|
|
|
|
+ client_os: '',
|
|
|
|
+ data: Buffer.from(JSON.stringify(iceRes)).toString('base64'),
|
|
|
|
+ fe_version: '',
|
|
|
|
+ id: 'ice_candidate',
|
|
|
|
+ packet_id: '',
|
|
|
|
+ room_id: '',
|
|
|
|
+ session_id: '',
|
|
|
|
+ trace_id: '',
|
|
|
|
+ user_id: '',
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ // client.send(JSON.stringify(res));
|
|
|
|
+ });
|
|
|
|
+ this.peer.onStateChange((state) => {
|
|
|
|
+ console.log('peer-State:', state);
|
|
|
|
+ });
|
|
|
|
+ this.peer.onGatheringStateChange((state) => {
|
|
|
|
+ console.log('GatheringState:', state);
|
|
|
|
+ });
|
|
|
|
+ this.gameChanel = this.peer.createDataChannel('start-game');
|
|
|
|
+
|
|
|
|
+ this.peer.onDataChannel((dc) => {
|
|
|
|
+ console.log('onDataChannel', dc);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ this.gameChanel.onOpen(() => {
|
|
|
|
+ console.log('channel is open');
|
|
|
|
+ clearInterval(this.timer);
|
|
|
|
+ let i = 0;
|
|
|
|
+ const paths = path.join(__dirname, '../ws/video/earth');
|
|
|
|
+ console.error('__dirname', __dirname);
|
|
|
|
+ console.error('paths', paths);
|
|
|
|
+ if (this.gameChanel.isOpen()) {
|
|
|
|
+ console.log('gameChanel', this.gameChanel.isOpen());
|
|
|
|
+ this.sendWertcHeartPack(this.gameChanel);
|
|
|
|
+ }
|
|
|
|
+ this.timer = setInterval(() => {
|
|
|
|
+ if (i < 10) {
|
|
|
|
+ const steam = createReadStream(paths + `/${i}`);
|
|
|
|
+ steam.on('data', (data: Buffer) => {
|
|
|
|
+ this.gameChanel.sendMessageBinary(data);
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ i++;
|
|
|
|
+ }, 2000);
|
|
|
|
+ });
|
|
|
|
+ this.gameChanel.onClosed(() => {
|
|
|
|
+ console.log('gameChanel close');
|
|
|
|
+ this.stopSendWertcHeartPack();
|
|
|
|
+ });
|
|
|
|
+ this.gameChanel.onError(() => {
|
|
|
|
+ console.log('gameChanel close');
|
|
|
|
+ this.stopSendWertcHeartPack();
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ sendWertcHeartPack(channel: DataChannel) {
|
|
|
|
+ const heartPack = new DataView(new ArrayBuffer(4));
|
|
|
|
+ heartPack.setUint32(0, 2009889916);
|
|
|
|
+ this._webrtcInterval = setInterval(() => {
|
|
|
|
+ channel.sendMessageBinary(Buffer.from(heartPack.buffer));
|
|
|
|
+ }, 100);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ stopSendWertcHeartPack(): void {
|
|
|
|
+ clearInterval(this._webrtcInterval);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @SubscribeMessage('ice_candidate')
|
|
|
|
+ handlerIceCandidate(client: any, payload: any) {
|
|
|
|
+ const iceCandidate = Buffer.from(payload, 'base64').toString('utf-8');
|
|
|
|
+ const candidate = JSON.parse(iceCandidate);
|
|
|
|
+ console.error('收到ice_candidate', candidate);
|
|
|
|
+ this.peer.addRemoteCandidate(candidate.candidate, candidate.sdpMid);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @SubscribeMessage('answer')
|
|
|
|
+ handerAnswer(client: any, payload: any) {
|
|
|
|
+ const answer = Buffer.from(payload, 'base64').toString('utf-8');
|
|
|
|
+ console.log('answer', answer);
|
|
|
|
+ const clientAnswer = JSON.parse(answer);
|
|
|
|
+ this.peer.setLocalDescription(clientAnswer.sdp);
|
|
|
|
+ this.peer.setRemoteDescription(clientAnswer.sdp, clientAnswer.type);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @SubscribeMessage('start')
|
|
|
|
+ handlerWebrtcStart(client: any, payload: any) {
|
|
|
|
+ console.log('start', payload)
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
afterInit(server: Server) {
|
|
afterInit(server: Server) {
|
|
this.logger.log('Init');
|
|
this.logger.log('Init');
|
|
}
|
|
}
|
|
|
|
|
|
handleConnection(client: WebSocket, ...args: any[]) {
|
|
handleConnection(client: WebSocket, ...args: any[]) {
|
|
this.logger.log(`Client connected: ${client.id}`);
|
|
this.logger.log(`Client connected: ${client.id}`);
|
|
|
|
+ const connected = {
|
|
|
|
+ channel_id: '',
|
|
|
|
+ client_os: '',
|
|
|
|
+ data: '',
|
|
|
|
+ fe_version: '',
|
|
|
|
+ id: 'init',
|
|
|
|
+ packet_id: '',
|
|
|
|
+ room_id: '',
|
|
|
|
+ session_id: '',
|
|
|
|
+ trace_id: '',
|
|
|
|
+ user_id: '',
|
|
|
|
+ };
|
|
|
|
+ const tt = JSON.stringify(connected);
|
|
|
|
+ // console.log('tt', tt);
|
|
|
|
+
|
|
|
|
+ client.send(tt);
|
|
}
|
|
}
|
|
handleDisconnect(client: WebSocket) {
|
|
handleDisconnect(client: WebSocket) {
|
|
this.logger.log(`Client disconnected: ${client.id}`);
|
|
this.logger.log(`Client disconnected: ${client.id}`);
|
|
|
|
+ this.peer && this.peer.close();
|
|
}
|
|
}
|
|
}
|
|
}
|