| '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, |
| }; |