You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

101 lines
3.5 KiB

'use strict';
const common = require('../common');
if (common.isWindows)
common.skip('Does not support wrapping sockets with fd on Windows');
const assert = require('assert');
const net = require('net');
const path = require('path');
const Pipe = process.binding('pipe_wrap').Pipe;
common.refreshTmpDir();
function testClients(getSocketOpt, getConnectOpt, getConnectCb) {
const cloneOptions = (index) =>
Object.assign({}, getSocketOpt(index), getConnectOpt(index));
return [
net.connect(cloneOptions(0), getConnectCb(0)),
net.connect(cloneOptions(1))
.on('connect', getConnectCb(1)),
net.createConnection(cloneOptions(2), getConnectCb(2)),
net.createConnection(cloneOptions(3))
.on('connect', getConnectCb(3)),
new net.Socket(getSocketOpt(4)).connect(getConnectOpt(4), getConnectCb(4)),
new net.Socket(getSocketOpt(5)).connect(getConnectOpt(5))
.on('connect', getConnectCb(5))
];
}
const CLIENT_VARIANTS = 6; // Same length as array above
const forAllClients = (cb) => common.mustCall(cb, CLIENT_VARIANTS);
// Test Pipe fd is wrapped correctly
{
// Use relative path to avoid hitting 108-char length limit
// for socket paths in libuv.
const prefix = path.relative('.', `${common.PIPE}-net-connect-options-fd`);
const serverPath = `${prefix}-server`;
let counter = 0;
let socketCounter = 0;
const handleMap = new Map();
const server = net.createServer()
.on('connection', forAllClients(function serverOnConnection(socket) {
let clientFd;
socket.on('data', common.mustCall(function(data) {
clientFd = data.toString();
console.error(`[Pipe]Received data from fd ${clientFd}`);
socket.end();
}));
socket.on('end', common.mustCall(function() {
counter++;
console.error(`[Pipe]Received end from fd ${clientFd}, total ${counter}`);
if (counter === CLIENT_VARIANTS) {
setTimeout(() => {
console.error(`[Pipe]Server closed by fd ${clientFd}`);
server.close();
}, 10);
}
}, 1));
}))
.on('close', function() {
setTimeout(() => {
for (const pair of handleMap) {
console.error(`[Pipe]Clean up handle with fd ${pair[1].fd}`);
pair[1].close(); // clean up handles
}
}, 10);
})
.on('error', function(err) {
console.error(err);
assert.fail(null, null, `[Pipe server]${err}`);
})
.listen({ path: serverPath }, common.mustCall(function serverOnListen() {
const getSocketOpt = (index) => {
const handle = new Pipe();
const err = handle.bind(`${prefix}-client-${socketCounter++}`);
assert(err >= 0, String(err));
assert.notStrictEqual(handle.fd, -1);
handleMap.set(index, handle);
console.error(`[Pipe]Bound handle with Pipe ${handle.fd}`);
return { fd: handle.fd, readable: true, writable: true };
};
const getConnectOpt = () => ({
path: serverPath
});
const getConnectCb = (index) => common.mustCall(function clientOnConnect() {
const client = this;
// Test if it's wrapping an existing fd
assert(handleMap.has(index));
const oldHandle = handleMap.get(index);
assert.strictEqual(oldHandle.fd, this._handle.fd);
client.write(String(oldHandle.fd));
console.error(`[Pipe]Sending data through fd ${oldHandle.fd}`);
client.on('error', function(err) {
console.error(err);
assert.fail(null, null, `[Pipe Client]${err}`);
});
});
testClients(getSocketOpt, getConnectOpt, getConnectCb);
}));
}