meta.gateway.ts 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. import {
  2. SubscribeMessage,
  3. WebSocketGateway,
  4. OnGatewayInit,
  5. WebSocketServer,
  6. OnGatewayConnection,
  7. OnGatewayDisconnect,
  8. } from '@nestjs/websockets';
  9. import { Server } from 'ws';
  10. import * as WebSocket from 'ws';
  11. import { PeerConnection, initLogger, DataChannel } from 'node-datachannel';
  12. import { Buffer } from 'buffer';
  13. import { Logger } from '@nestjs/common';
  14. import * as path from 'path';
  15. import { createReadStream } from 'fs';
  16. initLogger('Debug');
  17. @WebSocketGateway({
  18. transports: ['websocket'],
  19. cors: '*',
  20. // namespace: "ws",
  21. path: '/ws',
  22. })
  23. export class MetaGateway
  24. implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect {
  25. private logger: Logger = new Logger('MetaGateway');
  26. private peer: PeerConnection = null;
  27. private timer: NodeJS.Timeout;
  28. private _webrtcInterval: NodeJS.Timeout;
  29. private heartBeatFlag: number;
  30. private gameChanel: DataChannel;
  31. @WebSocketServer() server: Server;
  32. // @SubscribeMessage('message')
  33. // handleMessage(client: any, payload: any) {
  34. // this.logger.log(`payload: ${JSON.stringify(payload)}`);
  35. // }
  36. @SubscribeMessage('init')
  37. handleInit(client: any, payload: any) {
  38. this.logger.log(`init: ${JSON.stringify(payload)}`);
  39. }
  40. @SubscribeMessage('heartbeat')
  41. handleHeartBeat(client: any, payload: any) {
  42. this.logger.log(`heartbeat: ${JSON.stringify(payload)}`);
  43. // console.log('hb', payload);
  44. this.heartBeatFlag = payload;
  45. const pong = {
  46. channel_id: '',
  47. client_os: '',
  48. data: payload,
  49. fe_version: '',
  50. id: 'heartbeat',
  51. packet_id: '',
  52. room_id: '',
  53. session_id: '',
  54. trace_id: '',
  55. user_id: '',
  56. };
  57. if (this.gameChanel.isOpen()) {
  58. const heartPack = new DataView(new ArrayBuffer(4));
  59. heartPack.setUint32(0, 2009889916);
  60. this.gameChanel.sendMessageBinary(Buffer.from(heartPack.buffer));
  61. }
  62. return pong;
  63. }
  64. @SubscribeMessage('init_webrtc')
  65. handleInitWebRtc(client: any, payload: any): void {
  66. console.log('handleInitWebRtc');
  67. this.peer = new PeerConnection('roomTest', {
  68. iceServers: ['stun:120.24.252.95:3478'],
  69. });
  70. this.peer.onLocalDescription((sdp, type) => {
  71. console.warn('peer SDP:', sdp, ' Type:', type);
  72. const offer = { sdp, type };
  73. const offerFormat = {
  74. id: 'offer',
  75. data: Buffer.from(JSON.stringify(offer)).toString('base64'),
  76. };
  77. console.log('send', offerFormat);
  78. client.send(JSON.stringify(offerFormat));
  79. // return '';
  80. });
  81. this.peer.onLocalCandidate((candidate, mid) => {
  82. console.warn('peer Candidate:', candidate);
  83. const iceRes = {
  84. candidate,
  85. sdpMid: mid,
  86. sdpMLineIndex: 0,
  87. };
  88. const res = {
  89. channel_id: '',
  90. client_os: '',
  91. data: Buffer.from(JSON.stringify(iceRes)).toString('base64'),
  92. fe_version: '',
  93. id: 'ice_candidate',
  94. packet_id: '',
  95. room_id: '',
  96. session_id: '',
  97. trace_id: '',
  98. user_id: '',
  99. };
  100. // client.send(JSON.stringify(res));
  101. });
  102. this.peer.onStateChange((state) => {
  103. console.log('peer-State:', state);
  104. });
  105. this.peer.onGatheringStateChange((state) => {
  106. console.log('GatheringState:', state);
  107. });
  108. this.gameChanel = this.peer.createDataChannel('game-input');
  109. this.peer.onDataChannel((dc) => {
  110. console.log('onDataChannel', dc);
  111. });
  112. this.gameChanel.onOpen(() => {
  113. console.log('channel is open');
  114. clearInterval(this.timer);
  115. let i = 1;
  116. const paths = path.join(__dirname, '../ws/video/v11');
  117. console.error('__dirname', __dirname);
  118. console.error('paths', paths);
  119. if (this.gameChanel.isOpen()) {
  120. console.log('gameChanel', this.gameChanel.isOpen());
  121. this.sendWertcHeartPack(this.gameChanel);
  122. }
  123. this.timer = setInterval(() => {
  124. if (i < 30) {
  125. const steam = createReadStream(paths + `/${i}.h264`);
  126. // const steam = createReadStream(paths + `/test2`);
  127. steam.on('data', (data: Buffer) => {
  128. // console.log(data.buffer);
  129. const frame = new DataView(data.buffer);
  130. frame.setUint32(0, 1437227610);
  131. frame.setUint16(6, 36);
  132. frame.setUint16(24, 0);
  133. frame.setUint16(26, 0);
  134. frame.setUint32(28, 0);
  135. this.gameChanel.sendMessageBinary(Buffer.from(frame.buffer));
  136. });
  137. }
  138. i++;
  139. }, 10);
  140. });
  141. this.gameChanel.onClosed(() => {
  142. console.log('gameChanel close');
  143. this.stopSendWertcHeartPack();
  144. });
  145. this.gameChanel.onMessage((event) => {
  146. console.log('gameChanel onMessage', event);
  147. });
  148. this.gameChanel.onError(() => {
  149. console.log('gameChanel close');
  150. this.stopSendWertcHeartPack();
  151. });
  152. }
  153. sendWertcHeartPack(channel: DataChannel) {
  154. const heartPack = new DataView(new ArrayBuffer(4));
  155. heartPack.setUint32(0, 2009889916);
  156. this._webrtcInterval = setInterval(() => {
  157. if (channel.isOpen()) {
  158. channel.sendMessageBinary(Buffer.from(heartPack.buffer));
  159. }
  160. }, 1e3);
  161. }
  162. stopSendWertcHeartPack(): void {
  163. clearInterval(this._webrtcInterval);
  164. }
  165. @SubscribeMessage('ice_candidate')
  166. handlerIceCandidate(client: any, payload: any) {
  167. const iceCandidate = Buffer.from(payload, 'base64').toString('utf-8');
  168. const candidate = JSON.parse(iceCandidate);
  169. console.error('收到ice_candidate', candidate);
  170. this.peer.addRemoteCandidate(candidate.candidate, candidate.sdpMid);
  171. }
  172. @SubscribeMessage('answer')
  173. handerAnswer(client: any, payload: any) {
  174. const answer = Buffer.from(payload, 'base64').toString('utf-8');
  175. console.log('answer', answer);
  176. const clientAnswer = JSON.parse(answer);
  177. this.peer.setLocalDescription(clientAnswer.sdp);
  178. this.peer.setRemoteDescription(clientAnswer.sdp, clientAnswer.type);
  179. }
  180. @SubscribeMessage('start')
  181. handlerWebrtcStart(client: any, payload: any) {
  182. console.log('start', payload);
  183. }
  184. afterInit(server: Server) {
  185. this.logger.log('Init');
  186. }
  187. handleConnection(client: WebSocket, ...args: any[]) {
  188. this.logger.log(`Client connected: ${args}`);
  189. const connected = {
  190. channel_id: '',
  191. client_os: '',
  192. data: '',
  193. fe_version: '',
  194. id: 'init',
  195. packet_id: '',
  196. room_id: '',
  197. session_id: '',
  198. trace_id: '',
  199. user_id: '',
  200. };
  201. const tt = JSON.stringify(connected);
  202. // console.log('tt', tt);
  203. client.send(tt);
  204. }
  205. handleDisconnect(client: WebSocket) {
  206. this.logger.log(`Client disconnected: ${client.id}`);
  207. this.peer && this.peer.close();
  208. }
  209. }