|
|
|
@ -1,53 +1,101 @@ |
|
|
|
'use strict'; |
|
|
|
'use strict'; |
|
|
|
|
|
|
|
|
|
|
|
const net = require('net'); |
|
|
|
const net = require('net'); |
|
|
|
|
|
|
|
const stream = require('stream'); |
|
|
|
|
|
|
|
const { types: { isUint8Array } } = require('util'); |
|
|
|
|
|
|
|
|
|
|
|
const nbind = require('@mcesystems/nbind') |
|
|
|
const nbind = require('@mcesystems/nbind') |
|
|
|
const ZeroTier = nbind.init().lib.ZeroTier |
|
|
|
const ZeroTier = nbind.init().lib.ZeroTier |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const { |
|
|
|
|
|
|
|
errnoException, |
|
|
|
|
|
|
|
writevGeneric, |
|
|
|
|
|
|
|
writeGeneric, |
|
|
|
|
|
|
|
onStreamRead, |
|
|
|
|
|
|
|
kAfterAsyncWrite, |
|
|
|
|
|
|
|
kHandle, |
|
|
|
|
|
|
|
kUpdateTimer, |
|
|
|
|
|
|
|
// setStreamTimeout,
|
|
|
|
|
|
|
|
kBuffer, |
|
|
|
|
|
|
|
kBufferCb, |
|
|
|
|
|
|
|
kBufferGen |
|
|
|
|
|
|
|
} = require('./stream_commons'); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const kLastWriteQueueSize = Symbol('lastWriteQueueSize'); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
/* |
|
|
|
* EXAMPLE USAGE |
|
|
|
* EXAMPLE of Low-level usage |
|
|
|
* Usage: `nc -lv 4444` |
|
|
|
* Usage: `nc -lv 4444` |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
function example() { |
|
|
|
function example(nwid, address, port) { |
|
|
|
// Start ZeroTier service
|
|
|
|
// Start ZeroTier service
|
|
|
|
ZeroTier.start(".zerotier", 9994); |
|
|
|
ZeroTier.start(".zerotier", 9994); |
|
|
|
|
|
|
|
|
|
|
|
// Join virtual network
|
|
|
|
// Join virtual network
|
|
|
|
ZeroTier.join("8056c2e21c000001"); |
|
|
|
ZeroTier.join(nwid); |
|
|
|
|
|
|
|
|
|
|
|
// Open the socket
|
|
|
|
// Connect the socket
|
|
|
|
let fd = ZeroTier.connectStream("29.49.7.203", 4444); |
|
|
|
const _connect = (address, port, callback) => { |
|
|
|
|
|
|
|
// Open the socket
|
|
|
|
|
|
|
|
const fd = ZeroTier.openStream(); |
|
|
|
|
|
|
|
if (fd < 0) { callback(new Error('Could not open socket, errno: ' + fd)); return; } |
|
|
|
|
|
|
|
|
|
|
|
// Send some data
|
|
|
|
// Try connect
|
|
|
|
ZeroTier.send(fd, Buffer.from("Name?\n", 'utf8'), 0) |
|
|
|
const status = ZeroTier.connect(fd, address, port); |
|
|
|
|
|
|
|
|
|
|
|
// Set blocking read mode
|
|
|
|
console.log(status); |
|
|
|
// ZeroTier.fcntlSetBlocking(fd, true);
|
|
|
|
if (status === 0) { |
|
|
|
let heartbeat = setInterval(() => process.stderr.write('.'), 100) |
|
|
|
callback(null, fd); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
// Close previous socket
|
|
|
|
|
|
|
|
ZeroTier.close(fd); |
|
|
|
|
|
|
|
setTimeout(_connect, 250, address, port, callback); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Receive some data
|
|
|
|
// Receive some data
|
|
|
|
const _read = () => { |
|
|
|
const _read = (fd, callback) => { |
|
|
|
const buf = Buffer.alloc(32) |
|
|
|
const buf = Buffer.alloc(32) |
|
|
|
let bytes = -1 |
|
|
|
let bytes = -1 |
|
|
|
do { |
|
|
|
do { |
|
|
|
bytes = ZeroTier.recv(fd, buf, 0) |
|
|
|
bytes = ZeroTier.recv(fd, buf, 0) |
|
|
|
if (bytes > 0) { process.stdout.write(buf.toString('utf8')) } |
|
|
|
if (bytes > 0) { callback(null, buf); } |
|
|
|
} while (bytes > 0); |
|
|
|
} while (bytes > 0); |
|
|
|
|
|
|
|
|
|
|
|
if (!ZeroTier.getMyNode().online || buf.toString('utf8').includes("exit")) { |
|
|
|
if (!ZeroTier.getMyNode().online || buf.toString('utf8').includes("exit")) { |
|
|
|
// Close the socket
|
|
|
|
callback('end'); |
|
|
|
ZeroTier.close(fd) |
|
|
|
|
|
|
|
// Stop ZeroTier service
|
|
|
|
|
|
|
|
ZeroTier.stop() |
|
|
|
|
|
|
|
// Clear the interval
|
|
|
|
|
|
|
|
clearInterval(heartbeat) |
|
|
|
|
|
|
|
} else { |
|
|
|
} else { |
|
|
|
setTimeout(_read, 500) |
|
|
|
setTimeout(_read, 500, fd, callback) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
_read() |
|
|
|
|
|
|
|
|
|
|
|
_connect(address, port, (err, fd) => { |
|
|
|
|
|
|
|
if (err) { console.error(err); return; } |
|
|
|
|
|
|
|
console.debug("Connected."); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Send some data
|
|
|
|
|
|
|
|
ZeroTier.send(fd, Buffer.from("Name?\n", 'utf8'), 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Set blocking read mode
|
|
|
|
|
|
|
|
// ZeroTier.setBlocking(fd, true);
|
|
|
|
|
|
|
|
const heartbeat = setInterval(() => process.stderr.write('.'), 100); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_read(fd, (stop, buf) => { |
|
|
|
|
|
|
|
if (stop) { |
|
|
|
|
|
|
|
// Close the socket
|
|
|
|
|
|
|
|
ZeroTier.close(fd); |
|
|
|
|
|
|
|
// Stop ZeroTier service
|
|
|
|
|
|
|
|
ZeroTier.stop(); |
|
|
|
|
|
|
|
// Clear the interval
|
|
|
|
|
|
|
|
clearInterval(heartbeat); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
process.stdout.write(buf.toString('utf8')); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -67,7 +115,8 @@ function connect(...args) { |
|
|
|
const normalized = net._normalizeArgs(args); |
|
|
|
const normalized = net._normalizeArgs(args); |
|
|
|
const options = normalized[0]; |
|
|
|
const options = normalized[0]; |
|
|
|
// debug('createConnection', normalized);
|
|
|
|
// debug('createConnection', normalized);
|
|
|
|
const socket = new Socket(options); |
|
|
|
|
|
|
|
|
|
|
|
const socket = new Socket(Object.assign({ handle: new ZTCP() }, options)); |
|
|
|
|
|
|
|
|
|
|
|
if (options.timeout) { |
|
|
|
if (options.timeout) { |
|
|
|
socket.setTimeout(options.timeout); |
|
|
|
socket.setTimeout(options.timeout); |
|
|
|
@ -76,213 +125,528 @@ function connect(...args) { |
|
|
|
return socket.connect(normalized); |
|
|
|
return socket.connect(normalized); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
|
|
|
* https://github.com/nodejs/node/blob/v12.18.3/lib/net.js#L567
|
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
function tryReadStart(socket) { |
|
|
|
|
|
|
|
// Not already reading, start the flow
|
|
|
|
|
|
|
|
// debug('Socket._handle.readStart');
|
|
|
|
|
|
|
|
socket._handle.reading = true; |
|
|
|
|
|
|
|
const err = socket._handle.readStart(); |
|
|
|
|
|
|
|
if (err) |
|
|
|
|
|
|
|
socket.destroy(errnoException(err, 'read')); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
/* |
|
|
|
* https://github.com/nodejs/node/blob/v12.18.3/lib/net.js#L1107
|
|
|
|
* https://github.com/nodejs/node/blob/v12.18.3/lib/net.js#L1107
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
function afterConnect(status, self, req, readable, writable) { |
|
|
|
// function afterConnect(status, self, req, readable, writable) {
|
|
|
|
// const self = handle[owner_symbol];
|
|
|
|
// // const self = handle[owner_symbol];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // Callback may come after call to destroy
|
|
|
|
|
|
|
|
// if (self.destroyed) {
|
|
|
|
|
|
|
|
// return;
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // debug('afterConnect');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // assert(self.connecting);
|
|
|
|
|
|
|
|
// self.connecting = false;
|
|
|
|
|
|
|
|
// self._sockname = null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if (status === 0) {
|
|
|
|
|
|
|
|
// self.readable = readable;
|
|
|
|
|
|
|
|
// if (!self._writableState.ended)
|
|
|
|
|
|
|
|
// self.writable = writable;
|
|
|
|
|
|
|
|
// self._unrefTimer();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// self.emit('connect');
|
|
|
|
|
|
|
|
// self.emit('ready');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // Start the first read, or get an immediate EOF.
|
|
|
|
|
|
|
|
// // this doesn't actually consume any bytes, because len=0.
|
|
|
|
|
|
|
|
// if (readable && !self.isPaused())
|
|
|
|
|
|
|
|
// self.read(0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
|
|
// self.connecting = false;
|
|
|
|
|
|
|
|
// let details;
|
|
|
|
|
|
|
|
// if (req.localAddress && req.localPort) {
|
|
|
|
|
|
|
|
// details = req.localAddress + ':' + req.localPort;
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// const ex = new Error(status,
|
|
|
|
|
|
|
|
// 'connect',
|
|
|
|
|
|
|
|
// req.address,
|
|
|
|
|
|
|
|
// req.port,
|
|
|
|
|
|
|
|
// details);
|
|
|
|
|
|
|
|
// if (details) {
|
|
|
|
|
|
|
|
// ex.localAddress = req.localAddress;
|
|
|
|
|
|
|
|
// ex.localPort = req.localPort;
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// self.destroy(ex);
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// function afterShutdown(self, _status) {
|
|
|
|
|
|
|
|
// // const self = this.handle[owner_symbol];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // debug('afterShutdown destroyed=%j', self.destroyed,
|
|
|
|
|
|
|
|
// // self._readableState);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// this.callback();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // Callback may come after call to destroy.
|
|
|
|
|
|
|
|
// if (self.destroyed)
|
|
|
|
|
|
|
|
// return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if (!self.readable || self.readableEnded) {
|
|
|
|
|
|
|
|
// // debug('readableState ended, destroying');
|
|
|
|
|
|
|
|
// self.destroy();
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// function writeGeneric(self, chunk, encoding, callback) {
|
|
|
|
|
|
|
|
// const decodeStrings = self._writableState && self._writableState.decodeStrings
|
|
|
|
|
|
|
|
// const buf = (!decodeStrings && !Buffer.isBuffer(chunk)) ? Buffer.from(chunk, encoding) : chunk
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// let bytes
|
|
|
|
|
|
|
|
// const err = ZeroTier.send(self._fd, buf, 0)
|
|
|
|
|
|
|
|
// switch (err) {
|
|
|
|
|
|
|
|
// case -1:
|
|
|
|
|
|
|
|
// callback(new Error("ZeroTier Socket error"))
|
|
|
|
|
|
|
|
// break
|
|
|
|
|
|
|
|
// case -2:
|
|
|
|
|
|
|
|
// callback(new Error("ZeroTier Service error"))
|
|
|
|
|
|
|
|
// break
|
|
|
|
|
|
|
|
// case -3:
|
|
|
|
|
|
|
|
// callback(new Error("ZeroTier Invalid argument"))
|
|
|
|
|
|
|
|
// break
|
|
|
|
|
|
|
|
// default:
|
|
|
|
|
|
|
|
// bytes = err
|
|
|
|
|
|
|
|
// callback()
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// return {
|
|
|
|
|
|
|
|
// async: true,
|
|
|
|
|
|
|
|
// bytes: bytes,
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// function writevGeneric(self, chunks, callback) {
|
|
|
|
|
|
|
|
// const decodeStrings = self._writableState && self._writableState.decodeStrings
|
|
|
|
|
|
|
|
// const bufs = chunks.map(({ chunk, encoding }) => (!decodeStrings && !Buffer.isBuffer(chunk)) ? Buffer.from(chunk, encoding) : chunk)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// let bytes
|
|
|
|
|
|
|
|
// const err = ZeroTier.writev(self._fd, bufs)
|
|
|
|
|
|
|
|
// switch (err) {
|
|
|
|
|
|
|
|
// case -1:
|
|
|
|
|
|
|
|
// callback(new Error("ZeroTier Socket error"))
|
|
|
|
|
|
|
|
// break
|
|
|
|
|
|
|
|
// case -2:
|
|
|
|
|
|
|
|
// callback(new Error("ZeroTier Service error"))
|
|
|
|
|
|
|
|
// break
|
|
|
|
|
|
|
|
// case -3:
|
|
|
|
|
|
|
|
// callback(new Error("ZeroTier Invalid argument"))
|
|
|
|
|
|
|
|
// break
|
|
|
|
|
|
|
|
// default:
|
|
|
|
|
|
|
|
// bytes = err
|
|
|
|
|
|
|
|
// callback()
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// return {
|
|
|
|
|
|
|
|
// async: true,
|
|
|
|
|
|
|
|
// bytes: bytes,
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ZTCP { |
|
|
|
|
|
|
|
bytesRead = 0 |
|
|
|
|
|
|
|
bytesWritten = 0 |
|
|
|
|
|
|
|
writeQueueSize = 0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_fd = null |
|
|
|
|
|
|
|
_reading = false |
|
|
|
|
|
|
|
readTimer = null |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
get reading() { |
|
|
|
|
|
|
|
return this._reading; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Callback may come after call to destroy
|
|
|
|
set reading(val) { |
|
|
|
if (self.destroyed) { |
|
|
|
return this._reading = val; |
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// debug('afterConnect');
|
|
|
|
readStart() { |
|
|
|
|
|
|
|
if (!this._buf) { |
|
|
|
|
|
|
|
this._buf = Buffer.alloc(128); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// assert(self.connecting);
|
|
|
|
let bytes = 0 |
|
|
|
self.connecting = false; |
|
|
|
do { |
|
|
|
self._sockname = null; |
|
|
|
bytes = ZeroTier.read(this._fd, this._buf) |
|
|
|
|
|
|
|
if (bytes >= 0) { |
|
|
|
|
|
|
|
this.bytesRead += bytes; |
|
|
|
|
|
|
|
bytes = 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
switch (bytes) { |
|
|
|
|
|
|
|
case -2: |
|
|
|
|
|
|
|
throw new Error("ZeroTier Service error") |
|
|
|
|
|
|
|
case -3: |
|
|
|
|
|
|
|
throw new Error("ZeroTier Invalid argument") |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
if (bytes > 0) { |
|
|
|
|
|
|
|
this.bytesRead += bytes |
|
|
|
|
|
|
|
this._buf = this.onread(this._buf) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} while (bytes > 0 && this._reading) |
|
|
|
|
|
|
|
|
|
|
|
if (status === 0) { |
|
|
|
if (this._reading) { readTimer = setTimeout(() => this._read(size), 500) } |
|
|
|
self.readable = readable; |
|
|
|
} |
|
|
|
if (!self._writableState.ended) |
|
|
|
|
|
|
|
self.writable = writable; |
|
|
|
|
|
|
|
self._unrefTimer(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.emit('connect'); |
|
|
|
readStop() { |
|
|
|
self.emit('ready'); |
|
|
|
if (readTimer) { |
|
|
|
|
|
|
|
clearTimeout(readTimer); |
|
|
|
|
|
|
|
readTimer = null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
this._reading = false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Start the first read, or get an immediate EOF.
|
|
|
|
writev(req, chunks, allBuffers) { |
|
|
|
// this doesn't actually consume any bytes, because len=0.
|
|
|
|
let bufs = []; |
|
|
|
if (readable && !self.isPaused()) |
|
|
|
|
|
|
|
self.read(0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
if (allBuffers) { |
|
|
|
self.connecting = false; |
|
|
|
bufs = chunks; |
|
|
|
let details; |
|
|
|
} else { |
|
|
|
if (req.localAddress && req.localPort) { |
|
|
|
const arr = chunks; |
|
|
|
details = req.localAddress + ':' + req.localPort; |
|
|
|
for (let i = 0; i < arr.length; i+=2) { |
|
|
|
|
|
|
|
const chunk = arr[i]; |
|
|
|
|
|
|
|
const encoding = arr[i+1]; |
|
|
|
|
|
|
|
chunks.push(Buffer.from(chunk, encoding)); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
const ex = new Error(status, |
|
|
|
|
|
|
|
'connect', |
|
|
|
let bytes = ZeroTier.writev(this._fd, bufs); |
|
|
|
req.address, |
|
|
|
if (bytes >= 0) { |
|
|
|
req.port, |
|
|
|
this.bytesWritten += bytes; |
|
|
|
details); |
|
|
|
bytes = 0; |
|
|
|
if (details) { |
|
|
|
|
|
|
|
ex.localAddress = req.localAddress; |
|
|
|
|
|
|
|
ex.localPort = req.localPort; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
self.destroy(ex); |
|
|
|
|
|
|
|
|
|
|
|
const status = bytes; |
|
|
|
|
|
|
|
// https://github.com/nodejs/node/blob/v12.18.3/lib/internal/stream_base_commons.js#L80
|
|
|
|
|
|
|
|
if (req.oncomplete) { req.oncomplete.call(req, status); } |
|
|
|
|
|
|
|
return status; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function writeGeneric(self, chunk, encoding, callback) { |
|
|
|
writeBuffer(req, buf) { |
|
|
|
const decodeStrings = self._writableState && self._writableState.decodeStrings |
|
|
|
let bytes = ZeroTier.write(this._fd, buf); |
|
|
|
const buf = (!decodeStrings && !Buffer.isBuffer(chunk)) ? Buffer.from(chunk, encoding) : chunk |
|
|
|
if (bytes >= 0) { |
|
|
|
|
|
|
|
this.bytesWritten += bytes; |
|
|
|
let bytes |
|
|
|
bytes = 0; |
|
|
|
const err = ZeroTier.send(self._fd, buf, 0) |
|
|
|
} |
|
|
|
switch (err) { |
|
|
|
|
|
|
|
case -1: |
|
|
|
const status = bytes; |
|
|
|
callback(new Error("ZeroTier Socket error")) |
|
|
|
// https://github.com/nodejs/node/blob/v12.18.3/lib/internal/stream_base_commons.js#L80
|
|
|
|
break |
|
|
|
if (req.oncomplete) { req.oncomplete.call(req, status); } |
|
|
|
case -2: |
|
|
|
return status; |
|
|
|
callback(new Error("ZeroTier Service error")) |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
case -3: |
|
|
|
|
|
|
|
callback(new Error("ZeroTier Invalid argument")) |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
bytes = err |
|
|
|
|
|
|
|
callback(null) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
|
|
|
async: true, |
|
|
|
|
|
|
|
bytes: bytes, |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function writevGeneric(self, chunks, callback) { |
|
|
|
writeLatin1String(req, data) { |
|
|
|
const decodeStrings = self._writableState && self._writableState.decodeStrings |
|
|
|
return this.writeBuffer(req, Buffer.from(data, 'latin1')); |
|
|
|
const bufs = chunks.map(({ chunk, encoding }) => (!decodeStrings && !Buffer.isBuffer(chunk)) ? Buffer.from(chunk, encoding) : chunk) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let bytes |
|
|
|
|
|
|
|
const err = ZeroTier.writev(self._fd, bufs) |
|
|
|
|
|
|
|
switch (err) { |
|
|
|
|
|
|
|
case -1: |
|
|
|
|
|
|
|
callback(new Error("ZeroTier Socket error")) |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
case -2: |
|
|
|
|
|
|
|
callback(new Error("ZeroTier Service error")) |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
case -3: |
|
|
|
|
|
|
|
callback(new Error("ZeroTier Invalid argument")) |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
bytes = err |
|
|
|
|
|
|
|
callback(null) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
|
|
|
async: true, |
|
|
|
|
|
|
|
bytes: bytes, |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Socket extends net.Socket { |
|
|
|
writeUtf8String(req, data) { |
|
|
|
/* |
|
|
|
return this.writeBuffer(req, Buffer.from(data, 'utf8')); |
|
|
|
* https://github.com/nodejs/node/blob/v12.18.3/lib/net.js#L929
|
|
|
|
} |
|
|
|
*/ |
|
|
|
|
|
|
|
connect(...args) { |
|
|
|
writeAsciiString(req, data) { |
|
|
|
let normalized; |
|
|
|
return this.writeBuffer(req, Buffer.from(data, 'ascii')); |
|
|
|
// If passed an array, it's treated as an array of arguments that have
|
|
|
|
} |
|
|
|
// already been normalized (so we don't normalize more than once). This has
|
|
|
|
|
|
|
|
// been solved before in https://github.com/nodejs/node/pull/12342, but was
|
|
|
|
writeUcs2String(req, data) { |
|
|
|
// reverted as it had unintended side effects.
|
|
|
|
return this.writeBuffer(req, Buffer.from(data, 'ucs2')); |
|
|
|
if (Array.isArray(args[0])) { |
|
|
|
} |
|
|
|
normalized = args[0]; |
|
|
|
|
|
|
|
|
|
|
|
getAsyncId() { |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
useUserBuffer(buf) { |
|
|
|
|
|
|
|
this._buf = buf; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setBlocking(newValue) { |
|
|
|
|
|
|
|
return ZeroTier.setBlocking(this._fd, newValue); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setNoDelay(newValue) { |
|
|
|
|
|
|
|
return ZeroTier.setNoDelay(this._fd, newValue); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setKeepalive(enable, initialDelay) { |
|
|
|
|
|
|
|
ZeroTier.setKeepidle(initialDelay); |
|
|
|
|
|
|
|
return ZeroTier.setKeepalive(this._fd, +enable); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bind(localAddress, localPort) { |
|
|
|
|
|
|
|
return ZeroTier.bind(this._fd, localAddress, localPort); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bind6(localAddress, localPort, _flags) { |
|
|
|
|
|
|
|
return ZeroTier.bind6(this._fd, localAddress, localPort); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
open(fd) { |
|
|
|
|
|
|
|
if (fd) { |
|
|
|
|
|
|
|
this._fd = fd; |
|
|
|
|
|
|
|
return 0; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
normalized = net._normalizeArgs(args); |
|
|
|
const err = ZeroTier.openStream(); |
|
|
|
|
|
|
|
if (err < 0) { |
|
|
|
|
|
|
|
return err; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
this._fd = err; |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
const options = normalized[0]; |
|
|
|
} |
|
|
|
const cb = normalized[1]; |
|
|
|
|
|
|
|
|
|
|
|
close(callback) { |
|
|
|
|
|
|
|
const err = ZeroTier.close(this._fd); |
|
|
|
|
|
|
|
this._fd = null; |
|
|
|
|
|
|
|
if (callback) { callback(err); } |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// if (this.write !== net.Socket.prototype.write)
|
|
|
|
shutdown(req) { |
|
|
|
// this.write = net.Socket.prototype.write;
|
|
|
|
const status = ZeroTier.shutdown(this._fd); |
|
|
|
|
|
|
|
// https://github.com/nodejs/node/blob/v12.18.3/test/parallel/test-tcp-wrap-connect.js
|
|
|
|
|
|
|
|
if (req.oncomplete) { req.oncomplete.call(req, status, this); } |
|
|
|
|
|
|
|
return status; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (this.destroyed) { |
|
|
|
connect(req, address, port) { |
|
|
|
this._handle = null; |
|
|
|
let status = ZeroTier.connect(this._fd, address, port); |
|
|
|
this._peername = null; |
|
|
|
|
|
|
|
this._sockname = null; |
|
|
|
// Retries are often required since ZT uses transport-triggered links
|
|
|
|
|
|
|
|
if (status !== 0) { |
|
|
|
|
|
|
|
let count = 0; |
|
|
|
|
|
|
|
while (count < 10) { |
|
|
|
|
|
|
|
// Close previous socket
|
|
|
|
|
|
|
|
this.close(); |
|
|
|
|
|
|
|
status = this.open(); |
|
|
|
|
|
|
|
if (status !== 0) { |
|
|
|
|
|
|
|
// Break if reopen-socket fails
|
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Reconnect
|
|
|
|
|
|
|
|
status = ZeroTier.connect(this._fd, address, port); |
|
|
|
|
|
|
|
if (status === 0) { break; } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
count++; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// const { path } = options;
|
|
|
|
// https://github.com/nodejs/node/blob/v12.18.3/test/parallel/test-tcp-wrap-connect.js
|
|
|
|
// const pipe = !!path;
|
|
|
|
if (req && req.oncomplete) { req.oncomplete.call(status, this, req, true, true); } |
|
|
|
// debug('pipe', pipe, path);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if (!this._handle) {
|
|
|
|
return status; |
|
|
|
// this._handle = pipe ?
|
|
|
|
} |
|
|
|
// new Pipe(PipeConstants.SOCKET) :
|
|
|
|
|
|
|
|
// new TCP(TCPConstants.SOCKET);
|
|
|
|
|
|
|
|
// initSocketHandle(this);
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (cb !== null) { |
|
|
|
connect6(req, address, port) { |
|
|
|
this.once('connect', cb); |
|
|
|
let status = ZeroTier.connect6(this._fd, address, port); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Retries are often required since ZT uses transport-triggered links
|
|
|
|
|
|
|
|
if (status !== 0) { |
|
|
|
|
|
|
|
let count = 0; |
|
|
|
|
|
|
|
while (count < 10) { |
|
|
|
|
|
|
|
// Close previous socket
|
|
|
|
|
|
|
|
this.close(); |
|
|
|
|
|
|
|
status = this.open(); |
|
|
|
|
|
|
|
if (status !== 0) { |
|
|
|
|
|
|
|
// Break if reopen-socket fails
|
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Reconnect
|
|
|
|
|
|
|
|
status = ZeroTier.connect6(this._fd, address, port); |
|
|
|
|
|
|
|
if (status === 0) { break; } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
count++; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
this._unrefTimer(); |
|
|
|
// https://github.com/nodejs/node/blob/v12.18.3/test/parallel/test-tcp-wrap-connect.js
|
|
|
|
|
|
|
|
if (req.oncomplete) { req.oncomplete.call(status, this, req, true, true); } |
|
|
|
|
|
|
|
|
|
|
|
this.connecting = true; |
|
|
|
return status; |
|
|
|
this.writable = true; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// if (pipe) {
|
|
|
|
getpeername(out) { |
|
|
|
// validateString(path, 'options.path');
|
|
|
|
const in4 = ZeroTier.getpeername(this._fd); |
|
|
|
// defaultTriggerAsyncIdScope(
|
|
|
|
out.address = ZeroTier.inet_ntop(in4); |
|
|
|
// this[async_id_symbol], internalConnect, this, path
|
|
|
|
out.family = in4.sin_family; |
|
|
|
// );
|
|
|
|
out.port = in4.sin_port; |
|
|
|
// } else {
|
|
|
|
return 0 |
|
|
|
// lookupAndConnect(this, options);
|
|
|
|
} |
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const { host, port } = options; |
|
|
|
getsockname(out) { |
|
|
|
// If host is an IP, skip performing a lookup
|
|
|
|
const in4 = ZeroTier.getsockname(this._fd); |
|
|
|
const addressType = net.isIP(host); |
|
|
|
out.address = ZeroTier.inet_ntop(in4); |
|
|
|
if (addressType) { |
|
|
|
out.family = in4.sin_family; |
|
|
|
this._fd = ZeroTier.connectStream(host, port); |
|
|
|
out.port = in4.sin_port; |
|
|
|
afterConnect(0, this, {}, true, true); |
|
|
|
return 0; |
|
|
|
} else { |
|
|
|
} |
|
|
|
throw new Error("DNS LOOKUP NOT IMPLEMENTED"); |
|
|
|
|
|
|
|
} |
|
|
|
listen(port) { |
|
|
|
|
|
|
|
// TODO
|
|
|
|
|
|
|
|
// this.onconnection
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return this; |
|
|
|
fchmod(mode) { |
|
|
|
|
|
|
|
// TODO
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Socket extends net.Socket { |
|
|
|
|
|
|
|
[kLastWriteQueueSize] = 0; |
|
|
|
|
|
|
|
[kBuffer] = null; |
|
|
|
|
|
|
|
[kBufferCb] = null; |
|
|
|
|
|
|
|
[kBufferGen] = null; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[kHandle] = null; |
|
|
|
|
|
|
|
get _handle() { return this[kHandle]; } |
|
|
|
|
|
|
|
set _handle(v) { return this[kHandle] = v; } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
|
|
|
* https://github.com/nodejs/node/blob/v12.18.3/lib/net.js#L929
|
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
// connect(...args) {
|
|
|
|
|
|
|
|
// let normalized;
|
|
|
|
|
|
|
|
// // If passed an array, it's treated as an array of arguments that have
|
|
|
|
|
|
|
|
// // already been normalized (so we don't normalize more than once). This has
|
|
|
|
|
|
|
|
// // been solved before in https://github.com/nodejs/node/pull/12342, but was
|
|
|
|
|
|
|
|
// // reverted as it had unintended side effects.
|
|
|
|
|
|
|
|
// if (Array.isArray(args[0])) {
|
|
|
|
|
|
|
|
// normalized = args[0];
|
|
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
|
|
// normalized = net._normalizeArgs(args);
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// const options = normalized[0];
|
|
|
|
|
|
|
|
// const cb = normalized[1];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if (this.write !== net.Socket.prototype.write)
|
|
|
|
|
|
|
|
// this.write = net.Socket.prototype.write;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if (this.destroyed) {
|
|
|
|
|
|
|
|
// this._handle = null;
|
|
|
|
|
|
|
|
// this._peername = null;
|
|
|
|
|
|
|
|
// this._sockname = null;
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if (!this._handle) {
|
|
|
|
|
|
|
|
// this._handle = new ZTCP();
|
|
|
|
|
|
|
|
// initSocketHandle(this);
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if (cb !== null) {
|
|
|
|
|
|
|
|
// this.once('connect', cb);
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// this._unrefTimer();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// this.connecting = true;
|
|
|
|
|
|
|
|
// this.writable = true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// const { host, port } = options;
|
|
|
|
|
|
|
|
// // If host is an IP, skip performing a lookup
|
|
|
|
|
|
|
|
// const addressType = net.isIP(host);
|
|
|
|
|
|
|
|
// if (addressType) {
|
|
|
|
|
|
|
|
// this._fd = ZeroTier.connectStream(host, port);
|
|
|
|
|
|
|
|
// afterConnect(0, this, {}, true, true);
|
|
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
|
|
// throw new Error("DNS LOOKUP NOT IMPLEMENTED");
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// return this;
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
|
|
|
* https://github.com/nodejs/node/blob/v12.18.3/lib/net.js#L596
|
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
pause() { |
|
|
|
|
|
|
|
if (this[kBuffer] && !this.connecting && this._handle && |
|
|
|
|
|
|
|
this._handle.reading) { |
|
|
|
|
|
|
|
this._handle.reading = false; |
|
|
|
|
|
|
|
if (!this.destroyed) { |
|
|
|
|
|
|
|
const err = this._handle.readStop(); |
|
|
|
|
|
|
|
if (err) |
|
|
|
|
|
|
|
this.destroy(errnoException(err, 'read')); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return stream.Duplex.prototype.pause.call(this); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
|
|
|
* https://github.com/nodejs/node/blob/v12.18.3/lib/net.js#L610
|
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
resume() { |
|
|
|
|
|
|
|
if (this[kBuffer] && !this.connecting && this._handle && |
|
|
|
|
|
|
|
!this._handle.reading) { |
|
|
|
|
|
|
|
tryReadStart(this); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return stream.Duplex.prototype.resume.call(this); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
|
|
|
* https://github.com/nodejs/node/blob/v12.18.3/lib/net.js#L619
|
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
read(n) { |
|
|
|
|
|
|
|
if (this[kBuffer] && !this.connecting && this._handle && |
|
|
|
|
|
|
|
!this._handle.reading) { |
|
|
|
|
|
|
|
tryReadStart(this); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return stream.Duplex.prototype.read.call(this, n); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
/* |
|
|
|
* https://nodejs.org/docs/latest-v12.x/api/stream.html#stream_readable_read_size_1
|
|
|
|
* https://nodejs.org/docs/latest-v12.x/api/stream.html#stream_readable_read_size_1
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
_read(size) { |
|
|
|
_read(n) { |
|
|
|
// debug('_read');
|
|
|
|
// debug('_read');
|
|
|
|
|
|
|
|
|
|
|
|
if (this.connecting) { |
|
|
|
if (this.connecting || !this._handle) { |
|
|
|
// debug('_read wait for connection');
|
|
|
|
// debug('_read wait for connection');
|
|
|
|
this.once('connect', () => this._read(size)); |
|
|
|
this.once('connect', () => this._read(n)); |
|
|
|
return |
|
|
|
} else if (!this._handle.reading) { |
|
|
|
} |
|
|
|
tryReadStart(this); |
|
|
|
|
|
|
|
|
|
|
|
if (!this.readChunk || this.readChunk.length < size) { |
|
|
|
|
|
|
|
this.readChunk = Buffer.alloc(size) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let bytes = -1 |
|
|
|
// if (!this.readChunk || this.readChunk.length < n) {
|
|
|
|
let moreData = true |
|
|
|
// this.readChunk = Buffer.alloc(n)
|
|
|
|
do { |
|
|
|
// }
|
|
|
|
bytes = ZeroTier.recv(this._fd, this.readChunk, 0) |
|
|
|
|
|
|
|
switch (bytes) { |
|
|
|
|
|
|
|
case -2: |
|
|
|
|
|
|
|
throw new Error("ZeroTier Service error") |
|
|
|
|
|
|
|
case -3: |
|
|
|
|
|
|
|
throw new Error("ZeroTier Invalid argument") |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
if (bytes > 0) { |
|
|
|
|
|
|
|
// this.bytesRead += bytes
|
|
|
|
|
|
|
|
moreData = this.push(this.readChunk) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} while (bytes > 0 && moreData) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (moreData) { setTimeout(() => this._read(size), 500) } |
|
|
|
// let bytes = -1
|
|
|
|
|
|
|
|
// let moreData = true
|
|
|
|
|
|
|
|
// do {
|
|
|
|
|
|
|
|
// bytes = ZeroTier.recv(this._fd, this.readChunk, 0)
|
|
|
|
|
|
|
|
// switch (bytes) {
|
|
|
|
|
|
|
|
// case -2:
|
|
|
|
|
|
|
|
// throw new Error("ZeroTier Service error")
|
|
|
|
|
|
|
|
// case -3:
|
|
|
|
|
|
|
|
// throw new Error("ZeroTier Invalid argument")
|
|
|
|
|
|
|
|
// default:
|
|
|
|
|
|
|
|
// if (bytes > 0) {
|
|
|
|
|
|
|
|
// // this.bytesRead += bytes
|
|
|
|
|
|
|
|
// moreData = this.push(this.readChunk)
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// } while (bytes > 0 && moreData)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if (moreData) { setTimeout(() => this._read(n), 500) }
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
/* |
|
|
|
@ -302,20 +666,27 @@ class Socket extends net.Socket { |
|
|
|
/* |
|
|
|
/* |
|
|
|
* https://nodejs.org/docs/latest-v12.x/api/stream.html#stream_writable_final_callback
|
|
|
|
* https://nodejs.org/docs/latest-v12.x/api/stream.html#stream_writable_final_callback
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
_final(callback) { |
|
|
|
// _final(cb) {
|
|
|
|
const err = ZeroTier.close(this._fd) |
|
|
|
// // If still connecting - defer handling `_final` until 'connect' will happen
|
|
|
|
|
|
|
|
// if (this.pending) {
|
|
|
|
switch (err) { |
|
|
|
// // debug('_final: not yet connected');
|
|
|
|
case -1: |
|
|
|
// return this.once('connect', () => this._final(cb));
|
|
|
|
return callback(new Error("ZeroTier Socket error")) |
|
|
|
// }
|
|
|
|
break |
|
|
|
|
|
|
|
case -2: |
|
|
|
// if (!this._handle)
|
|
|
|
return callback(new Error("ZeroTier Service error")) |
|
|
|
// return cb();
|
|
|
|
break |
|
|
|
|
|
|
|
default: |
|
|
|
// // debug('_final: not ended, call shutdown()');
|
|
|
|
return super._final(callback) |
|
|
|
|
|
|
|
} |
|
|
|
// // const req = new ShutdownWrap();
|
|
|
|
} |
|
|
|
// const req = {};
|
|
|
|
|
|
|
|
// req.oncomplete = afterShutdown;
|
|
|
|
|
|
|
|
// req.handle = this._handle;
|
|
|
|
|
|
|
|
// req.callback = cb;
|
|
|
|
|
|
|
|
// // const err = this._handle.shutdown(req);
|
|
|
|
|
|
|
|
// const err = ZeroTier.shutdown(this._fd);
|
|
|
|
|
|
|
|
// return afterShutdown.call(req, this, 0);
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
/* |
|
|
|
* https://github.com/nodejs/node/blob/v12.18.3/lib/net.js#L760
|
|
|
|
* https://github.com/nodejs/node/blob/v12.18.3/lib/net.js#L760
|
|
|
|
@ -334,34 +705,74 @@ class Socket extends net.Socket { |
|
|
|
} |
|
|
|
} |
|
|
|
this._pendingData = null; |
|
|
|
this._pendingData = null; |
|
|
|
this._pendingEncoding = ''; |
|
|
|
this._pendingEncoding = ''; |
|
|
|
|
|
|
|
|
|
|
|
// if (!this._handle) {
|
|
|
|
if (!this._handle) { |
|
|
|
// cb(new ERR_SOCKET_CLOSED());
|
|
|
|
cb(new Error('ERR_SOCKET_CLOSED')); |
|
|
|
// return false;
|
|
|
|
return false; |
|
|
|
// }
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
this._unrefTimer(); |
|
|
|
this._unrefTimer(); |
|
|
|
|
|
|
|
|
|
|
|
let req; |
|
|
|
let req; |
|
|
|
if (writev) |
|
|
|
if (writev) |
|
|
|
req = writevGeneric(this, data, cb); |
|
|
|
req = writevGeneric(this, data, cb); |
|
|
|
else |
|
|
|
else |
|
|
|
req = writeGeneric(this, data, encoding, cb); |
|
|
|
req = writeGeneric(this, data, encoding, cb); |
|
|
|
if (req.async) { |
|
|
|
if (req.async) |
|
|
|
// this[kLastWriteQueueSize] = req.bytes;
|
|
|
|
this[kLastWriteQueueSize] = req.bytes; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
|
|
|
* https://github.com/nodejs/node/blob/v12.18.3/lib/net.js#L552
|
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
get bufferSize() { |
|
|
|
|
|
|
|
if (this._handle) { |
|
|
|
|
|
|
|
return this[kLastWriteQueueSize] + this.writableLength; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
|
|
|
* https://github.com/nodejs/node/blob/v12.18.3/lib/net.js#L756
|
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
[kAfterAsyncWrite]() { |
|
|
|
|
|
|
|
this[kLastWriteQueueSize] = 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
|
|
|
* https://github.com/nodejs/node/blob/v12.18.3/lib/net.js#L468
|
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
_onTimeout() { |
|
|
|
|
|
|
|
const handle = this._handle; |
|
|
|
|
|
|
|
const lastWriteQueueSize = this[kLastWriteQueueSize]; |
|
|
|
|
|
|
|
if (lastWriteQueueSize > 0 && handle) { |
|
|
|
|
|
|
|
// `lastWriteQueueSize !== writeQueueSize` means there is
|
|
|
|
|
|
|
|
// an active write in progress, so we suppress the timeout.
|
|
|
|
|
|
|
|
const { writeQueueSize } = handle; |
|
|
|
|
|
|
|
if (lastWriteQueueSize !== writeQueueSize) { |
|
|
|
|
|
|
|
this[kLastWriteQueueSize] = writeQueueSize; |
|
|
|
|
|
|
|
this._unrefTimer(); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// debug('_onTimeout');
|
|
|
|
|
|
|
|
this.emit('timeout'); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
get [kUpdateTimer]() { |
|
|
|
|
|
|
|
return this._unrefTimer; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
module.exports = { |
|
|
|
module.exports = { |
|
|
|
example, |
|
|
|
|
|
|
|
start: ZeroTier.start, |
|
|
|
start: ZeroTier.start, |
|
|
|
join: ZeroTier.join, |
|
|
|
join: ZeroTier.join, |
|
|
|
|
|
|
|
restart: ZeroTier.restart, |
|
|
|
|
|
|
|
stop: ZeroTier.stop, |
|
|
|
|
|
|
|
free: ZeroTier.free, |
|
|
|
|
|
|
|
example, |
|
|
|
connect, |
|
|
|
connect, |
|
|
|
createConnection: connect, |
|
|
|
createConnection: connect, |
|
|
|
Socket, |
|
|
|
Socket, |
|
|
|
Stream: Socket, // Legacy naming
|
|
|
|
Stream: Socket, // Legacy naming
|
|
|
|
restart: ZeroTier.restart, |
|
|
|
TCP: ZTCP, |
|
|
|
stop: ZeroTier.stop, |
|
|
|
|
|
|
|
free: ZeroTier.free, |
|
|
|
|
|
|
|
}; |
|
|
|
}; |
|
|
|
|