Created
September 20, 2023 06:26
-
-
Save achingbrain/607cc86e74cf9ab09f7bb5ab115d5686 to your computer and use it in GitHub Desktop.
lib-datachannel large byte transfer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const nodeDataChannel = require('node-datachannel') | |
// Log Level | |
// nodeDataChannel.initLogger("Debug") | |
// increase `messagesToSend` until `Peer2` no longer receives all of the messages | |
const messagesToSend = 5000 | |
// the number of successfully sent messages | |
let messagesSent = 0 | |
// the number of successfully received messages | |
let receivedMessages = 0 | |
// if this many bytes of data has been buffered, wait for the send buffer to empty | |
const maxBufferedAmount = 1024 * 1024 | |
// how many bytes to send in each message | |
const messageSize = 1024 * 64 | |
// if true, the sender will wait for `.bufferedAmount` to be `0` before closing the channel | |
const drainBeforeClose = true | |
const peer1 = new nodeDataChannel.PeerConnection('Peer1', { iceServers: [] }) | |
const peer2 = new nodeDataChannel.PeerConnection('Peer2', { iceServers: [] }) | |
peer1.onLocalDescription((sdp, type) => { | |
peer2.setRemoteDescription(sdp, type) | |
}) | |
peer1.onLocalCandidate((candidate, mid) => { | |
peer2.addRemoteCandidate(candidate, mid) | |
}) | |
peer2.onLocalDescription((sdp, type) => { | |
peer1.setRemoteDescription(sdp, type) | |
}) | |
peer2.onLocalCandidate((candidate, mid) => { | |
peer1.addRemoteCandidate(candidate, mid) | |
}) | |
// necessary to stop dc from being garbage collected | |
let peer2Dc | |
peer2.onDataChannel((dc) => { | |
peer2Dc = dc | |
let lastMessageCount = 0 | |
let lastInterval = Date.now() | |
const interval = setInterval(() => { | |
if (lastMessageCount !== receivedMessages) { | |
const messagesSentInInterval = receivedMessages - lastMessageCount | |
const mBytesPerSecond = calculateTransferSpeed(lastInterval, messagesSentInInterval) | |
lastInterval = Date.now() | |
lastMessageCount = receivedMessages | |
console.info(`Peer2 received ${receivedMessages}/${messagesToSend} messages at ${mBytesPerSecond} MB/s`) | |
} | |
}, 1000) | |
console.log('Peer2 Got DataChannel', dc.getLabel()) | |
const start = Date.now() | |
dc.onMessage(() => { | |
receivedMessages++ | |
if (receivedMessages === messagesToSend) { | |
const mBytesPerSecond = calculateTransferSpeed(start, receivedMessages) | |
console.log(`Peer2 received all ${messagesToSend} messages at ${mBytesPerSecond} MB/s`) | |
clearInterval(interval) | |
peer1.close() | |
peer2.close() | |
nodeDataChannel.cleanup() | |
} | |
}) | |
dc.onClosed(() => { | |
peer2Dc = null | |
}) | |
}) | |
const dc = peer1.createDataChannel('test channel') | |
dc.onOpen(async () => { | |
for (let i = 0; i < messagesToSend; i++) { | |
try { | |
dc.sendMessageBinary(Uint8Array.from(new Array(messageSize).fill(0))) | |
messagesSent++ | |
if (dc.bufferedAmount() > maxBufferedAmount) { | |
// wait for any buffered messages to be sent before sending more messages | |
await drain(dc) | |
} | |
} catch (err) { | |
console.error('error after sending', i, 'messages', err.message, 'buffered amount was', dc.bufferedAmount()) | |
break | |
} | |
} | |
console.info(`Peer1 sent ${messagesSent} messages, buffered amount was`, dc.bufferedAmount()) | |
if (drainBeforeClose && dc.bufferedAmount() > 0) { | |
console.info(`Peer1 drain channel, buffered amount was`, dc.bufferedAmount()) | |
// wait for bufferedAmount to be 0 | |
await drain(dc) | |
} | |
console.info(`Peer1 close channel, buffered amount was`, dc.bufferedAmount()) | |
dc.close() | |
}) | |
async function drain (dc) { | |
if (dc.bufferedAmount() === 0) { | |
return | |
} | |
dc.setBufferedAmountLowThreshold(0) | |
await new Promise((resolve) => { | |
dc.onBufferedAmountLow(() => { | |
resolve() | |
}) | |
}) | |
} | |
function calculateTransferSpeed (start, messagesSent) { | |
const timeTakenMs = Date.now() - start | |
const timeTakenS = timeTakenMs / 1000 | |
const bytesTransferred = messagesSent * messageSize | |
const bytesPerSecond = bytesTransferred / timeTakenS | |
const mBytesPerSecond = bytesPerSecond / (1000 * 1000) | |
return mBytesPerSecond.toFixed(2) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "webrtc-transfer", | |
"version": "1.0.0", | |
"description": "", | |
"main": "index.js", | |
"scripts": { | |
"start": "node index.js" | |
}, | |
"author": "", | |
"license": "ISC", | |
"dependencies": { | |
"node-datachannel": "^0.4.3" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment