client-benchmark.js 7.0 KB

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