client-periodic.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /* eslint-disable @typescript-eslint/no-var-requires */
  2. const nodeDataChannel = require('../../lib/index');
  3. const WebSocket = require('ws');
  4. const readline = require('readline');
  5. // Init Logger
  6. nodeDataChannel.initLogger('Debug');
  7. // PeerConnection Map
  8. const pcMap = {};
  9. // Local ID
  10. const id = randomId(4);
  11. // Message Size
  12. const MESSAGE_SIZE = 500;
  13. // Buffer Size
  14. const BUFFER_SIZE = MESSAGE_SIZE * 10;
  15. // Read Line Interface
  16. const rl = readline.createInterface({
  17. input: process.stdin,
  18. output: process.stdout,
  19. });
  20. // Signaling Server
  21. const WS_URL = process.env.WS_URL || 'ws://localhost:8000';
  22. const ws = new WebSocket(WS_URL + '/' + id, {
  23. perMessageDeflate: false,
  24. });
  25. console.log(`The local ID is: ${id}`);
  26. console.log(`Waiting for signaling to be connected...`);
  27. ws.on('open', () => {
  28. console.log('WebSocket connected, signaling ready');
  29. readUserInput();
  30. });
  31. ws.on('error', (err) => {
  32. console.log('WebSocket Error: ', err);
  33. });
  34. ws.on('message', (msgStr) => {
  35. msg = JSON.parse(msgStr);
  36. switch (msg.type) {
  37. case 'offer':
  38. createPeerConnection(msg.id);
  39. pcMap[msg.id].setRemoteDescription(msg.description, msg.type);
  40. break;
  41. case 'answer':
  42. pcMap[msg.id].setRemoteDescription(msg.description, msg.type);
  43. break;
  44. case 'candidate':
  45. pcMap[msg.id].addRemoteCandidate(msg.candidate, msg.mid);
  46. break;
  47. default:
  48. break;
  49. }
  50. });
  51. function readUserInput() {
  52. rl.question('Enter a remote ID to send an offer: ', (peerId) => {
  53. if (peerId && peerId.length > 2) {
  54. rl.close();
  55. console.log('Offering to ', peerId);
  56. createPeerConnection(peerId);
  57. console.log('Creating DataChannel with label "test"');
  58. let dc = pcMap[peerId].createDataChannel('test');
  59. let msgToSend = randomId(MESSAGE_SIZE);
  60. let bytesSent = 0;
  61. let bytesReceived = 0;
  62. dc.onOpen(() => {
  63. setInterval(() => {
  64. if (dc.bufferedAmount() <= BUFFER_SIZE) {
  65. dc.sendMessage(msgToSend);
  66. bytesSent += msgToSend.length;
  67. }
  68. }, 2);
  69. });
  70. dc.onMessage((msg) => {
  71. bytesReceived += msg.length;
  72. });
  73. // Report
  74. let i = 0;
  75. setInterval(() => {
  76. console.log(
  77. `${i++}# Sent: ${byte2KB(bytesSent)} KB/s / Received: ${byte2KB(
  78. bytesReceived,
  79. )} KB/s / SendBufferAmount: ${dc.bufferedAmount()} / DataChannelOpen: ${dc.isOpen()}`,
  80. );
  81. bytesSent = 0;
  82. bytesReceived = 0;
  83. }, 1000);
  84. setInterval(() => {
  85. console.log(
  86. `Stats# Sent: ${byte2MB(pcMap[peerId].bytesSent())} MB / Received: ${byte2MB(
  87. pcMap[peerId].bytesReceived(),
  88. )} MB / rtt: ${pcMap[peerId].rtt()} ms`,
  89. );
  90. console.log(`Selected Candidates# ${JSON.stringify(pcMap[peerId].getSelectedCandidatePair())}`);
  91. console.log(``);
  92. }, 5 * 1000);
  93. }
  94. });
  95. }
  96. function createPeerConnection(peerId) {
  97. // Create PeerConnection
  98. let peerConnection = new nodeDataChannel.PeerConnection('pc', { iceServers: ['stun:stun.l.google.com:19302'] });
  99. peerConnection.onStateChange((state) => {
  100. console.log('State: ', state);
  101. });
  102. peerConnection.onGatheringStateChange((state) => {
  103. console.log('GatheringState: ', state);
  104. });
  105. peerConnection.onLocalDescription((description, type) => {
  106. ws.send(JSON.stringify({ id: peerId, type, description }));
  107. });
  108. peerConnection.onLocalCandidate((candidate, mid) => {
  109. ws.send(JSON.stringify({ id: peerId, type: 'candidate', candidate, mid }));
  110. });
  111. peerConnection.onDataChannel((dc) => {
  112. rl.close();
  113. console.log('DataChannel from ' + peerId + ' received with label "', dc.getLabel() + '"');
  114. let msgToSend = randomId(MESSAGE_SIZE);
  115. let bytesSent = 0;
  116. let bytesReceived = 0;
  117. setInterval(() => {
  118. if (dc.bufferedAmount() <= BUFFER_SIZE) {
  119. dc.sendMessage(msgToSend);
  120. bytesSent += msgToSend.length;
  121. }
  122. }, 2);
  123. dc.onMessage((msg) => {
  124. bytesReceived += msg.length;
  125. });
  126. // Report
  127. let i = 0;
  128. setInterval(() => {
  129. console.log(
  130. `${i++}# Sent: ${byte2KB(bytesSent)} KB/s / Received: ${byte2KB(
  131. bytesReceived,
  132. )} KB/s / SendBufferAmount: ${dc.bufferedAmount()} / DataChannelOpen: ${dc.isOpen()}`,
  133. );
  134. bytesSent = 0;
  135. bytesReceived = 0;
  136. }, 1000);
  137. setInterval(() => {
  138. console.log(
  139. `Stats# Sent: ${byte2MB(pcMap[peerId].bytesSent())} MB / Received: ${byte2MB(
  140. pcMap[peerId].bytesReceived(),
  141. )} MB / rtt: ${pcMap[peerId].rtt()} ms`,
  142. );
  143. console.log(`Selected Candidates# ${JSON.stringify(pcMap[peerId].getSelectedCandidatePair())}`);
  144. console.log(``);
  145. }, 5 * 1000);
  146. });
  147. pcMap[peerId] = peerConnection;
  148. }
  149. function randomId(length) {
  150. var result = '';
  151. var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  152. var charactersLength = characters.length;
  153. for (var i = 0; i < length; i++) {
  154. result += characters.charAt(Math.floor(Math.random() * charactersLength));
  155. }
  156. return result;
  157. }
  158. function byte2KB(bytes) {
  159. return `${Math.round(bytes / 1024)}`;
  160. }
  161. function byte2MB(bytes) {
  162. return `${Math.round(bytes / (1024 * 1024))}`;
  163. }