mirror of
https://github.com/nodejs/node.git
synced 2024-11-30 07:27:22 +01:00
a808cb76ce
Extracted from the QUIC PR. This adds a utility used to deterministically test UDP traffic. It is currently only used by the experimental QUIC implementation. Separated out on request to make review easier. PR-URL: https://github.com/nodejs/node/pull/33380 Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
103 lines
2.5 KiB
JavaScript
103 lines
2.5 KiB
JavaScript
/* eslint-disable node-core/require-common-first, node-core/required-modules */
|
|
'use strict';
|
|
const { internalBinding } = require('internal/test/binding');
|
|
const { JSUDPWrap } = internalBinding('js_udp_wrap');
|
|
const EventEmitter = require('events');
|
|
|
|
// FakeUDPWrap is a testing utility that emulates a UDP connection
|
|
// for the sake of making UDP tests more deterministic.
|
|
class FakeUDPWrap extends EventEmitter {
|
|
constructor() {
|
|
super();
|
|
|
|
this._handle = new JSUDPWrap();
|
|
|
|
this._handle.onreadstart = () => this._startReading();
|
|
this._handle.onreadstop = () => this._stopReading();
|
|
this._handle.onwrite =
|
|
(wrap, buffers, addr) => this._write(wrap, buffers, addr);
|
|
this._handle.getsockname = (obj) => {
|
|
Object.assign(obj, { address: '127.0.0.1', family: 'IPv4', port: 1337 });
|
|
return 0;
|
|
};
|
|
|
|
this.reading = false;
|
|
this.bufferedReceived = [];
|
|
this.emitBufferedImmediate = null;
|
|
}
|
|
|
|
_emitBuffered = () => {
|
|
if (!this.reading) return;
|
|
if (this.bufferedReceived.length > 0) {
|
|
this.emitReceived(this.bufferedReceived.shift());
|
|
this.emitBufferedImmediate = setImmediate(this._emitBuffered);
|
|
} else {
|
|
this.emit('wantRead');
|
|
}
|
|
};
|
|
|
|
_startReading() {
|
|
this.reading = true;
|
|
this.emitBufferedImmediate = setImmediate(this._emitBuffered);
|
|
}
|
|
|
|
_stopReading() {
|
|
this.reading = false;
|
|
clearImmediate(this.emitBufferedImmediate);
|
|
}
|
|
|
|
_write(wrap, buffers, addr) {
|
|
this.emit('send', { buffers, addr });
|
|
setImmediate(() => this._handle.onSendDone(wrap, 0));
|
|
}
|
|
|
|
afterBind() {
|
|
this._handle.onAfterBind();
|
|
}
|
|
|
|
emitReceived(info) {
|
|
if (!this.reading) {
|
|
this.bufferedReceived.push(info);
|
|
return;
|
|
}
|
|
|
|
const {
|
|
buffers,
|
|
addr: {
|
|
family = 4,
|
|
address = '127.0.0.1',
|
|
port = 1337,
|
|
},
|
|
flags = 0
|
|
} = info;
|
|
|
|
let familyInt;
|
|
switch (family) {
|
|
case 'IPv4': familyInt = 4; break;
|
|
case 'IPv6': familyInt = 6; break;
|
|
default: throw new Error('bad family');
|
|
}
|
|
|
|
for (const buffer of buffers) {
|
|
this._handle.emitReceived(buffer, familyInt, address, port, flags);
|
|
}
|
|
}
|
|
}
|
|
|
|
function makeUDPPair() {
|
|
const serverSide = new FakeUDPWrap();
|
|
const clientSide = new FakeUDPWrap();
|
|
|
|
serverSide.on('send',
|
|
(chk) => setImmediate(() => clientSide.emitReceived(chk)));
|
|
clientSide.on('send',
|
|
(chk) => setImmediate(() => serverSide.emitReceived(chk)));
|
|
|
|
return { serverSide, clientSide };
|
|
}
|
|
|
|
module.exports = {
|
|
FakeUDPWrap,
|
|
makeUDPPair
|
|
};
|