From b15b6cafed9b06ea631e81e8fedfb1ad493b50e5 Mon Sep 17 00:00:00 2001 From: Face Kapow Date: Fri, 8 Jul 2016 11:32:03 -0400 Subject: [PATCH 01/22] Move .eslint* to root, lint & ES6 js/components/dns-client/*, js/index.js, js/version.js, js/__loader.js, switch airbnb eslint config --- .eslintignore | 2 + .eslintrc | 38 +++ js/.eslintignore | 2 - js/.eslintrc | 9 - js/__loader.js | 355 ++++++++++------------- js/component/dns-client/dns-packet.js | 178 ++++++------ js/component/dns-client/index.js | 158 +++++----- js/component/dns-client/is-domain.js | 32 +- js/component/dns-client/packet-reader.js | 58 ++-- js/index.js | 20 +- js/version.js | 13 +- package.json | 8 +- 12 files changed, 407 insertions(+), 466 deletions(-) create mode 100644 .eslintignore create mode 100644 .eslintrc delete mode 100644 js/.eslintignore delete mode 100644 js/.eslintrc diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..cb8a79b79 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +js/deps/ +js/modules/inherits.js diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 000000000..d0094afd8 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,38 @@ +extends: + - airbnb-base + +globals: + debug: true + __SYSCALL: true + runtime: true + +env: + es6: true + node: true + +rules: + strict: + - 2 + - 'global' + max-len: + - 2 + - + code: 100 + tabWidth: 2 + ignoreComments: true + ignoreUrls: true + consistent-return: 1 + no-underscore-dangle: 0 + +parserOptions: + ecmaVersion: 6 + sourceType: 'script' + ecmaFeatures: + modules: false + defaultParams: true + classes: true + arrowFunctions: true + blockBindings: true + forOf: true + spread: true + templateStrings: true diff --git a/js/.eslintignore b/js/.eslintignore deleted file mode 100644 index 9102a60f2..000000000 --- a/js/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -deps/ -modules/inherits.js diff --git a/js/.eslintrc b/js/.eslintrc deleted file mode 100644 index 01df1465c..000000000 --- a/js/.eslintrc +++ /dev/null @@ -1,9 +0,0 @@ -extends: - - runtime - -plugins: - - runtime-internal - -globals: - debug: true - __SYSCALL: true diff --git a/js/__loader.js b/js/__loader.js index f1bc2cc7e..0eae3a288 100644 --- a/js/__loader.js +++ b/js/__loader.js @@ -14,253 +14,209 @@ 'use strict'; -(function() { +(() => { // from https://github.com/runtimejs/runtime-module-loader/blob/master/index.js - function Loader(existsFileFn, readFileFn, evalScriptFn, builtins, builtinsResolveFrom) { - builtinsResolveFrom = builtinsResolveFrom || '/'; - var cache = {}; - var builtinsResolveFromComponents = builtinsResolveFrom.split('/'); - builtins = builtins || {}; - - function throwError(err) { - throw err; - } - - function endsWith(str, suffix) { - return str.indexOf(suffix, str.length - suffix.length) !== -1; - } - - function Module(pathComponents) { - this.dirComponents = pathComponents.slice(0, -1); - this.pathComponents = pathComponents; - this.filename = pathComponents.join('/'); - this.dirname = this.dirComponents.length > 1 ? this.dirComponents.join('/') : '/'; - this.exports = {}; - } - - Module.prototype.require = function require(path) { - var module = this; - var resolvedPath = resolve(module, path); - if (!resolvedPath) { - throwError(new Error("Cannot resolve module '" + path + "' from '" + module.filename + "'")); - } - - // eval file - var pathComponents = resolvedPath.split('/'); - var displayPath = resolvedPath; - var cacheKey = pathComponents.join('/'); - if (cache[cacheKey]) { - return cache[cacheKey].exports; - } - - var currentModule = global.module; - var module = new Module(pathComponents); - cache[cacheKey] = module; - global.module = module; - - if (endsWith(resolvedPath, '.node')) { - throwError(new Error("Native Node.js modules are not supported '" + resolvedPath + "'")); - } - - var content = readFileFn(resolvedPath); - if (!content) { - throwError(new Error("Cannot load module '" + resolvedPath + "'")); - } - - if (endsWith(resolvedPath, '.json')) { - module.exports = JSON.parse(content); - } else { - evalScriptFn( - '(function(require,exports,module,__filename,__dirname){' + - content + - '})((function(m){return function(path){return m.require(path)}})(global.module),global.module.exports,global.module,global.module.filename,global.module.dirname)', - displayPath); - } + class Loader { + constructor(existsFileFn, readFileFn, evalScriptFn, builtins = {}, builtinsResolveFrom = '/') { + const cache = {}; + const builtinsResolveFromComponents = builtinsResolveFrom.split('/'); + + const throwError = (err) => { throw err; }; + const endsWith = (str, suffix) => str.indexOf(suffix, str.length - suffix.length) !== -1; + + const normalizePath = (components) => { + const r = []; + for (const p of components) { + if (p === '') { + if (r.length === 0) r.push(p); + continue; + } - global.module = currentModule; - return module.exports; - }; + if (p === '.') continue; - function normalizePath(components) { - var r = []; - for (var i = 0; i < components.length; ++i) { - var p = components[i]; - if ('' === p) { - if (r.length === 0) { + if (p === '..') { + if (r.length > 0) { + r.pop(); + } else { + return null; + } + } else { r.push(p); } - continue; } - if ('.' === p) { - continue; + return r; + }; + + const loadAsFile = (path) => { + if (existsFileFn(path)) return path; + if (existsFileFn(`${path}.js`)) return `${path}.js`; + if (existsFileFn(`${path}.json`)) return `${path}.json`; + if (existsFileFn(`${path}.node`)) return `${path}.node`; + + return null; + }; + + const getPackageMain = (packageJsonFile) => { + const json = readFileFn(packageJsonFile); + let parsed = null; + try { + parsed = JSON.parse(json); + } catch (e) { + throwError(new Error(`package.json '${packageJsonFile}' parse error`)); } - if ('..' === p) { - if (r.length > 0) { - r.pop(); - } else { - return null; + if (parsed.runtime) { + if (typeof parsed.runtime === 'string') { + return parsed.runtime; } - } else { - r.push(p); + throwError(new Error(`package.json '${packageJsonFile}' runtime field value is invalid`)); } - } - return r; - } + return parsed.main || 'index.js'; + }; - function loadAsFile(path) { - if (existsFileFn(path)) { - return path; - } + const loadAsDirectory = (path, ignoreJson) => { + let mainFile = 'index'; + let dir = false; + if (!ignoreJson && existsFileFn(`${path}/package.json`)) { + mainFile = getPackageMain(`${path}/package.json`) || 'index'; + dir = true; + } - if (existsFileFn(path + '.js')) { - return path + '.js'; - } + const normalizedPath = normalizePath(path.split('/').concat(mainFile.split('/'))); + if (!normalizedPath) return null; - if (existsFileFn(path + '.json')) { - return path + '.json'; - } + const s = normalizedPath.join('/'); + const res = loadAsFile(s); + if (res) return res; - if (existsFileFn(path + '.node')) { - return path + '.node'; - } + if (dir) return loadAsDirectory(s, true); - return null; - } + return null; + }; - function getPackageMain(packageJsonFile) { - var json = readFileFn(packageJsonFile); - var parsed = null; - try { - var parsed = JSON.parse(json); - } catch (e) { - throwError(new Error("package.json '" + packageJsonFile + "' parse error")); - } + const loadNodeModules = (dirComponents, parts) => { + let count = dirComponents.length; - if (parsed.runtime) { - if (typeof parsed.runtime === 'string') { - return parsed.runtime; - } else { - throwError(new Error("package.json '" + packageJsonFile + "' runtime field value is invalid")); - } - } + while (count-- > 0) { + let p = dirComponents.slice(0, count + 1); + if (p.length === 0) continue; - return parsed.main || 'index.js'; - } + if (p[p.length - 1] === 'node_modules') continue; - function loadAsDirectory(path, ignoreJson) { - var mainFile = 'index'; - var dir = false; - if (!ignoreJson && existsFileFn(path + '/package.json')) { - mainFile = getPackageMain(path + '/package.json') || 'index'; - dir = true; - } + p.push('node_modules'); + p = p.concat(parts); - var normalizedPath = normalizePath(path.split('/').concat(mainFile.split('/'))); - if (!normalizedPath) { - return null; - } + const normalizedPath = normalizePath(p); + if (!normalizedPath) continue; - var s = normalizedPath.join('/'); - var res = loadAsFile(s); - if (res) { - return res; - } + const s = normalizedPath.join('/'); + const loadedPath = loadAsFile(s) || loadAsDirectory(s, false) || null; + if (loadedPath) return loadedPath; + } - if (dir) { - return loadAsDirectory(s, true); - } + return null; + }; - return null; - } + const resolve = (module, pathOpt = '') => { + let path = String(pathOpt); - function loadNodeModules(dirComponents, parts) { - var count = dirComponents.length; + let resolveFrom = module.dirComponents; - while (count-- > 0) { - var p = dirComponents.slice(0, count + 1); - if (p.length === 0) { - continue; + if (Object.prototype.hasOwnProperty.call(builtins, path)) { + path = builtins[path]; + resolveFrom = builtinsResolveFromComponents; } - if (p[p.length - 1] === 'node_modules') { - continue; - } + const pathComponents = path.split('/'); + const firstPathComponent = pathComponents[0]; - p.push('node_modules'); - p = p.concat(parts); + // starts with ./ ../ or / + if (firstPathComponent === '.' || + firstPathComponent === '..' || + firstPathComponent === '') { + const combinedPathComponents = (firstPathComponent === '') + ? pathComponents + : resolveFrom.concat(pathComponents); - var normalizedPath = normalizePath(p); - if (!normalizedPath) { - continue; - } + const normalizedPath = normalizePath(combinedPathComponents); + if (!normalizedPath) return null; - var s = normalizedPath.join('/'); - var loadedPath = loadAsFile(s) || loadAsDirectory(s, false) || null; - if (loadedPath) { + const pathStr = normalizedPath.join('/'); + const loadedPath = loadAsFile(pathStr) || loadAsDirectory(pathStr, false) || null; return loadedPath; } - } - return null; - } + return loadNodeModules(resolveFrom, pathComponents); + }; - function resolve(module, path) { - path = String(path || ''); + class Module { + constructor(pathComponents) { + this.dirComponents = pathComponents.slice(0, -1); + this.pathComponents = pathComponents; + this.filename = pathComponents.join('/'); + this.dirname = this.dirComponents.length > 1 ? this.dirComponents.join('/') : '/'; + this.exports = {}; + } + require(path) { + let module = this; + const resolvedPath = resolve(module, path); + if (!resolvedPath) { + throwError(new Error(`Cannot resolve module '${path}' from '${module.filename}'`)); + } - var resolveFrom = module.dirComponents; + // eval file + const pathComponents = resolvedPath.split('/'); + const displayPath = resolvedPath; + const cacheKey = pathComponents.join('/'); + if (cache[cacheKey]) return cache[cacheKey].exports; - if (builtins.hasOwnProperty(path)) { - path = builtins[path]; - resolveFrom = builtinsResolveFromComponents; - } + const currentModule = global.module; + module = new Module(pathComponents); + cache[cacheKey] = module; + global.module = module; - var pathComponents = path.split('/'); - var firstPathComponent = pathComponents[0]; + if (endsWith(resolvedPath, '.node')) { + throwError(new Error(`Native Node.js modules are not supported '${resolvedPath}'`)); + } - // starts with ./ ../ or / - if (firstPathComponent === '.' || - firstPathComponent === '..' || - firstPathComponent === '') { - var combinedPathComponents = (firstPathComponent === '') - ? pathComponents - : resolveFrom.concat(pathComponents); + const content = readFileFn(resolvedPath); + if (!content) throwError(new Error(`Cannot load module '${resolvedPath}'`)); - var normalizedPath = normalizePath(combinedPathComponents); - if (!normalizedPath) { - return null; - } + if (endsWith(resolvedPath, '.json')) { + module.exports = JSON.parse(content); + } else { + /* eslint-disable max-len */ + evalScriptFn( + `(function(require,exports,module,__filename,__dirname){ +${content} +})((function(m){return function(path){return m.require(path)}})(global.module),global.module.exports,global.module,global.module.filename,global.module.dirname)`, + displayPath); + /* eslint-enable max-len */ + } - var pathStr = normalizedPath.join('/'); - var loadedPath = loadAsFile(pathStr) || loadAsDirectory(pathStr, false) || null; - return loadedPath; + global.module = currentModule; + return module.exports; + } } - return loadNodeModules(resolveFrom, pathComponents); + this.require = (path) => { + const rootModule = new Module(['', '']); + global.module = rootModule; + return rootModule.require(path); + }; } - - this.require = function require(path) { - var rootModule = new Module(['', '']); - global.module = rootModule; - return rootModule.require(path); - }; } // end - var files = {}; - __SYSCALL.initrdListFiles().forEach(file => { - files[file] = true; - }); + const files = {}; + for (const file of __SYSCALL.initrdListFiles()) files[file] = true; - function fileExists(path) { - return !!files[path]; - } + const fileExists = path => !!files[path]; - var runtimePackagePath = __SYSCALL.initrdGetKernelIndex().split('/').slice(0, -1).join('/'); - var loader = new Loader(fileExists, __SYSCALL.initrdReadFile, __SYSCALL.eval, { - /* eslint-disable camelcase */ + const runtimePackagePath = __SYSCALL.initrdGetKernelIndex().split('/').slice(0, -1).join('/'); + const loader = new Loader(fileExists, __SYSCALL.initrdReadFile, __SYSCALL.eval, { assert: 'assert', events: 'events', buffer: 'buffer', @@ -280,11 +236,10 @@ stream: './modules/stream.js', inherits: './modules/inherits.js', sys: 'util/util.js', - util: 'util/util.js' - /* eslint-enable camelcase */ + util: 'util/util.js', }, runtimePackagePath); - loader.require(runtimePackagePath + '/index.js'); + loader.require(`${runtimePackagePath}/index.js`); global.process = loader.require('process'); global.Buffer = loader.require('buffer').Buffer; diff --git a/js/component/dns-client/dns-packet.js b/js/component/dns-client/dns-packet.js index 7c0d4d5b8..ddf336497 100644 --- a/js/component/dns-client/dns-packet.js +++ b/js/component/dns-client/dns-packet.js @@ -13,39 +13,35 @@ // limitations under the License. 'use strict'; -var assert = require('assert'); -var isDomain = require('./is-domain'); -var PacketReader = require('./packet-reader'); -var randomId = 0x3322; - -var queries = { - 'A': 0x01, - 'NS': 0x02, - 'CNAME': 0x05, - 'PTR': 0x0C, - 'MX': 0x0F, - 'SRV': 0x21, - 'SOA': 0x06, - 'TXT': 0x0A -} - -exports.getQuery = function(domain, query) { +const assert = require('assert'); +const isDomain = require('./is-domain'); +const PacketReader = require('./packet-reader'); +const randomId = 0x3322; + +const queries = { + A: 0x01, + NS: 0x02, + CNAME: 0x05, + PTR: 0x0C, + MX: 0x0F, + SRV: 0x21, + SOA: 0x06, + TXT: 0x0A, +}; + +exports.getQuery = (domain, query) => { // query isn't used (for now) assert(isDomain(domain)); - var bufferLength = 17; - var i, j, label; + let bufferLength = 17; - var labels = domain.split('.'); - for (i = 0; i < labels.length; ++i) { - label = labels[i]; - bufferLength += label.length + 1; - } + const labels = domain.split('.'); + for (const label of labels) bufferLength += label.length + 1; - var u8 = new Uint8Array(bufferLength); - var view = new DataView(u8.buffer); + const u8 = new Uint8Array(bufferLength); + const view = new DataView(u8.buffer); - var requestFlags = 0x0100; // query, standard, not truncated, recursive + const requestFlags = 0x0100; // query, standard, not truncated, recursive view.setUint16(0, randomId, false); view.setUint16(2, requestFlags, false); @@ -54,14 +50,11 @@ exports.getQuery = function(domain, query) { view.setUint16(8, 0, false); // 0 ns records view.setUint16(10, 0, false); // 0 additional records - var offset = 12; + let offset = 12; - for (i = 0; i < labels.length; ++i) { - label = labels[i]; + for (const label of labels) { view.setUint8(offset++, label.length); - for (j = 0; j < label.length; ++j) { - view.setUint8(offset++, label.charCodeAt(j)); - } + for (let j = 0; j < label.length; ++j) view.setUint8(offset++, label.charCodeAt(j)); } view.setUint8(offset++, 0); // null terminator @@ -70,98 +63,99 @@ exports.getQuery = function(domain, query) { return u8; }; -var POINTER_VALUE = 0xc0; -function isPointer(value) { - return (value & POINTER_VALUE) === POINTER_VALUE; -} +const POINTER_VALUE = 0xc0; +const isPointer = value => (value & POINTER_VALUE) === POINTER_VALUE; -function readHostname(reader) { - var labels = []; +const readHostname = (reader) => { + let labels = []; - for (var z = reader.getOffset(); z < reader.len; ++z) { - var len = reader.readUint8(); - if (0 === len) { - break; - } + for (let z = reader.getOffset(); z < reader.len; ++z) { + const len = reader.readUint8(); + if (len === 0) break; if (isPointer(len)) { - var ptrOffset = ((len - POINTER_VALUE) << 8) + reader.readUint8(); - var pos = reader.getOffset(); + const ptrOffset = ((len - POINTER_VALUE) << 8) + reader.readUint8(); + const pos = reader.getOffset(); reader.setOffset(ptrOffset); labels = labels.concat(readHostname(reader)); reader.setOffset(pos); break; } else { - var label = ''; - for (var i = 0; i < len; ++i) { - label += String.fromCharCode(reader.readUint8()); - } + let label = ''; + for (let i = 0; i < len; ++i) label += String.fromCharCode(reader.readUint8()); labels.push(label); } } return labels; -} +}; -exports.parseResponse = function(u8) { - var reader = new PacketReader(u8.buffer, u8.byteLength, u8.byteOffset); - var responseRandomId = reader.readUint16(); +exports.parseResponse = (u8) => { + const reader = new PacketReader(u8.buffer, u8.byteLength, u8.byteOffset); + const responseRandomId = reader.readUint16(); - if (responseRandomId !== randomId) { - return null; - } + if (responseRandomId !== randomId) return null; - var flags = reader.readUint16(); - var questionsCount = reader.readUint16(); - var answersCount = reader.readUint16(); - var nsRecordsCount = reader.readUint16(); - var additionalCount = reader.readUint16(); + /* eslint-disable no-unused-vars */ + const flags = reader.readUint16(); + const questionsCount = reader.readUint16(); + const answersCount = reader.readUint16(); + const nsRecordsCount = reader.readUint16(); + const additionalCount = reader.readUint16(); + /* eslint-enable no-unused-vars */ - if (1 !== questionsCount) { - return null; - } + if (questionsCount !== 1) return null; // Read question - var hostname = readHostname(reader).join('.'); + const hostname = readHostname(reader).join('.'); reader.readUint16(); // skip type reader.readUint16(); // skip class - var results = []; + const results = []; // Read answers - for (var z = 0; z < answersCount; ++z) { - var host = readHostname(reader).join('.'); + for (let z = 0; z < answersCount; ++z) { + const host = readHostname(reader).join('.'); - var recordType = reader.readUint16(); - var recordClass = reader.readUint16(); - var ttl = reader.readUint32(); - var rdLen = reader.readUint16(); + const recordType = reader.readUint16(); + const recordClass = reader.readUint16(); // eslint-disable-line no-unused-vars + const ttl = reader.readUint32(); + const rdLen = reader.readUint16(); - var bytes = []; + // const bytes = []; switch (recordType) { - case queries.A: // A record - if (4 !== rdLen) { - return null; - } - - results.push({hostname: host, record: 'A', address: [reader.readUint8(), reader.readUint8(), - reader.readUint8(), reader.readUint8()], ttl: ttl }); - break; - case queries.CNAME: // CNAME record - results.push({hostname: host, record: 'CNAME', name: readHostname(reader).join('.')}); - break; - default: - for (var b = 0; b < rdLen; ++b) { - reader.readUint8(); - } - break; + case queries.A: // A record + if (rdLen !== 4) return null; + + results.push({ + hostname: host, + record: 'A', + address: [ + reader.readUint8(), + reader.readUint8(), + reader.readUint8(), + reader.readUint8(), + ], + ttl, + }); + break; + case queries.CNAME: // CNAME record + results.push({ + hostname: host, + record: 'CNAME', + name: readHostname(reader).join('.'), + }); + break; + default: + for (let b = 0; b < rdLen; ++b) reader.readUint8(); + break; } } return { - hostname: hostname, - results: results + hostname, + results, }; }; diff --git a/js/component/dns-client/index.js b/js/component/dns-client/index.js index ef609566a..7fcf6e396 100644 --- a/js/component/dns-client/index.js +++ b/js/component/dns-client/index.js @@ -13,95 +13,81 @@ // limitations under the License. 'use strict'; -var assert = require('assert'); -var typeutils = require('typeutils'); -var dnsPacket = require('./dns-packet'); -var isint = require('isint'); -var runtime = require('../../core'); -var IP4Address = runtime.net.IP4Address; -var UDPSocket = runtime.net.UDPSocket; - -function DNSClient(serverIP, serverPort) { - assert(this instanceof DNSClient); - if (serverIP) { - assert(serverIP instanceof IP4Address); - } - - if (serverPort) { - assert(isint.uint16(serverPort)); - } - - var self = this; - self._socket = new UDPSocket(); - self._serverIP = serverIP || new IP4Address(8, 8, 8, 8); - self._serverPort = serverPort || 53; - self._requests = []; - self._cache = {}; - - self._socket.onmessage = function(ip, port, u8) { - var data = dnsPacket.parseResponse(u8); - if (!data) { - return; - } - - debug('DNS recv', ip, port, JSON.stringify(data)); - - var requests = self._requests; - var domain = data.hostname; - for (var i = 0; i < requests.length; ++i) { - var req = requests[i]; - if (!req) { - continue; - } - - if (req.domain === domain) { - req.cb(null, data); - self._cache[domain] = data; - requests[i] = null; +const assert = require('assert'); +const typeutils = require('typeutils'); +const dnsPacket = require('./dns-packet'); +const isint = require('isint'); +const runtime = require('../../core'); +const { IP4Address, UDPSocket } = runtime.net; + +class DNSClient { + constructor(serverIP, serverPort) { + assert(this instanceof DNSClient); + if (serverIP) assert(serverIP instanceof IP4Address); + if (serverPort) assert(isint.uint16(serverPort)); + + this._socket = new UDPSocket(); + this._serverIP = serverIP || new IP4Address(8, 8, 8, 8); + this._serverPort = serverPort || 53; + this._requests = []; + this._cache = {}; + + this._socket.onmessage = (ip, port, u8) => { + const data = dnsPacket.parseResponse(u8); + if (!data) return; + + debug('DNS recv', ip, port, JSON.stringify(data)); + + const requests = this._requests; + const domain = data.hostname; + for (let i = 0; i < requests.length; i++) { + const req = requests[i]; + if (!req) continue; + + if (req.domain === domain) { + req.cb(null, data); + this._cache[domain] = data; + requests[i] = null; + } } - } - }; - - setInterval(function() { - var requests = self._requests; - - for (var i = 0; i < requests.length; ++i) { - var req = requests[i]; - if (!req) { - continue; + }; + + setInterval(() => { + const requests = this._requests; + + for (let i = 0; i < requests.length; i++) { + const req = requests[i]; + if (!req) continue; + + if (req.retry > 0) { + this._sendQuery(req.domain, req.opts.query || 'A'); + --req.retry; + } else { + req.cb(new Error('E_FAILED')); + requests[i] = null; + } } - if (req.retry > 0) { - self._sendQuery(req.domain, req.opts.query || 'A'); - --req.retry; - } else { - req.cb(new Error('E_FAILED')); - requests[i] = null; - } - } - - self._requests = requests - .filter(function(x) { return x !== null; }); - }, 1000); + this._requests = requests.filter(x => x !== null); + }, 1000); + } + _sendQuery(domain, type) { + const query = dnsPacket.getQuery(domain, type); + this._socket.send(this._serverIP, this._serverPort, query); + } + resolve(domain, opts, cb) { + assert(this instanceof DNSClient); + assert(typeutils.isString(domain)); + assert(typeutils.isFunction(cb)); + + this._sendQuery(domain, opts.query || 'A'); + this._requests.push({ + domain, + retry: 3, + opts, + cb, + }); + } } -DNSClient.prototype._sendQuery = function(domain, type) { - var query = dnsPacket.getQuery(domain, type); - this._socket.send(this._serverIP, this._serverPort, query); -}; - -DNSClient.prototype.resolve = function(domain, opts, cb) { - assert(this instanceof DNSClient); - assert(typeutils.isString(domain)); - assert(typeutils.isFunction(cb)); - - this._sendQuery(domain, opts.query || 'A'); - this._requests.push({ - domain: domain, - retry: 3, - opts: opts, - cb: cb - }); -}; - module.exports = DNSClient; diff --git a/js/component/dns-client/is-domain.js b/js/component/dns-client/is-domain.js index 13efd361e..0cfc53578 100644 --- a/js/component/dns-client/is-domain.js +++ b/js/component/dns-client/is-domain.js @@ -13,32 +13,18 @@ // limitations under the License. 'use strict'; -var assert = require('assert'); -var typeutils = require('typeutils'); -var domainRegex = /^[a-z0-9.-]+$/; +const typeutils = require('typeutils'); +const domainRegex = /^[a-z0-9.-]+$/; -function isDomain(domain) { - if (!typeutils.isString(domain)) { - return false; - } +module.exports = (domain) => { + if (!typeutils.isString(domain)) return false; - if (domain.length > 255) { - return false; - } + if (domain.length > 255) return false; - if (!domainRegex.test(domain)) { - return false; - } + if (!domainRegex.test(domain)) return false; - var labels = domain.split('.'); - for (var i = 0; i < labels.length; ++i) { - var label = labels[i]; - if (label.length < 1 || label.length > 63) { - return false; - } - } + const labels = domain.split('.'); + for (const label of labels) if (label.length < 1 || label.length > 63) return false; return true; -} - -module.exports = isDomain; +}; diff --git a/js/component/dns-client/packet-reader.js b/js/component/dns-client/packet-reader.js index 544ca0316..6e7ce1f11 100644 --- a/js/component/dns-client/packet-reader.js +++ b/js/component/dns-client/packet-reader.js @@ -14,38 +14,32 @@ 'use strict'; -function PacketReader(buf, len, offset) { - this.buf = buf; - this.len = len || buf.byteLength; - this.offset = 0; - this.view = new DataView(buf, offset, len); +class PacketReader { + constructor(buf, len = buf.byteLength, offset) { + this.buf = buf; + this.len = len; + this.offset = 0; + this.view = new DataView(buf, offset, len); + } + readUint8() { + return this.view.getUint8(this.offset++); + } + readUint16() { + const value = this.view.getUint16(this.offset, false); + this.offset += 2; + return value; + } + readUint32() { + const value = this.view.getUint32(this.offset, false); + this.offset += 4; + return value; + } + getOffset() { + return this.offset; + } + setOffset(offset) { + this.offset = offset; + } } -PacketReader.prototype.readUint8 = function() { - /* linter bug ? */ - /* eslint-disable space-unary-ops */ - return this.view.getUint8(this.offset++); - /* eslint-enable space-unary-ops */ -}; - -PacketReader.prototype.readUint16 = function() { - var value = this.view.getUint16(this.offset, false); - this.offset += 2; - return value; -}; - -PacketReader.prototype.readUint32 = function() { - var value = this.view.getUint32(this.offset, false); - this.offset += 4; - return value; -}; - -PacketReader.prototype.getOffset = function() { - return this.offset; -}; - -PacketReader.prototype.setOffset = function(offset) { - this.offset = offset; -}; - module.exports = PacketReader; diff --git a/js/index.js b/js/index.js index ed6ad614b..19995ff24 100644 --- a/js/index.js +++ b/js/index.js @@ -14,18 +14,18 @@ 'use strict'; -var packagejson = require('../package.json'); +const packagejson = require('../package.json'); require('module-singleton')(packagejson); require('./version'); console.log(`runtime.js v${packagejson.version}`); console.log('loading...'); -var isDebug = packagejson.runtimejs.debug; -global.debug = isDebug ? console.log : function() {}; +const isDebug = packagejson.runtimejs.debug; +global.debug = isDebug ? console.log : () => {}; // Load runtime.js core -var runtime = require('./core'); +const runtime = require('./core'); // Start services require('./service/dhcp-client'); @@ -36,24 +36,22 @@ runtime.dns = require('./service/dns-resolver'); runtime.debug = isDebug; // Example shell command -runtime.shell.setCommand('1', function(args, env, cb) { +runtime.shell.setCommand('1', (args, env, cb) => { env.stdio.writeLine('OK.'); - runtime.dns.resolve('www.google.com', {}, function(err, data) { - if (err) { - return cb(1); - } + runtime.dns.resolve('www.google.com', {}, (err, data) => { + if (err) return cb(1); console.log(JSON.stringify(data)); cb(0); }); }); -runtime.shell.setCommand('poweroff', function(args, env, cb) { +runtime.shell.setCommand('poweroff', (args, env, cb) => { env.stdio.writeLine('Going down, now!'); runtime.machine.shutdown(); cb(0); }); -runtime.shell.setCommand('reboot', function(args, env, cb) { +runtime.shell.setCommand('reboot', (args, env, cb) => { env.stdio.writeLine('Restarting, now!'); runtime.machine.reboot(); cb(0); diff --git a/js/version.js b/js/version.js index 9cecec4f3..ba79ef790 100644 --- a/js/version.js +++ b/js/version.js @@ -14,16 +14,15 @@ 'use strict'; -/* global __SYSCALL */ -if (!global.__SYSCALL) { - throw 'error: this program requires runtime.js environment'; -} +if (!global.__SYSCALL) throw new Error('error: this program requires runtime.js environment'); -var requiredKernelVersion = require('../runtimecorelib.json').kernelVersion; -var currentKernelVersion = __SYSCALL.version().kernel; +const requiredKernelVersion = require('../runtimecorelib.json').kernelVersion; +const currentKernelVersion = __SYSCALL.version().kernel; if (currentKernelVersion !== requiredKernelVersion) { - throw `error: required kernel version number ${requiredKernelVersion}, current ${currentKernelVersion}`; + /* eslint-disable max-len */ + throw new Error(`error: required kernel version number ${requiredKernelVersion}, current ${currentKernelVersion}`); + /* eslint-enable max-len */ } console.log(`Kernel build #${currentKernelVersion} (v8 ${__SYSCALL.version().v8})`); diff --git a/package.json b/package.json index 8ba32ea17..055843a90 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "private": true, "scripts": { "postinstall": "node scripts/update-versions.js", - "lint": "eslint .", + "lint": "eslint js", "test": "runtimeify test/unit/index.js -o initrd && runtime-qemu ./initrd", "test-build": "runtimeify test/unit/index.js -o initrd && runtime-qemu ./initrd --kernel ../disk/boot/runtime" }, @@ -21,9 +21,9 @@ }, "homepage": "http://runtimejs.org", "devDependencies": { - "eslint": "^1.8.0", - "eslint-config-runtime": "^1.0.0", - "eslint-plugin-runtime-internal": "^1.0.0", + "eslint": "^3.0.1", + "eslint-config-airbnb-base": "^4.0.0", + "eslint-plugin-import": "^1.10.2", "tape": "^4.0.0" }, "runtimejs": { From ee0f0182dc7f8f8403d15a86c2f87d21dcf4823b Mon Sep 17 00:00:00 2001 From: Face Kapow Date: Fri, 8 Jul 2016 12:05:09 -0400 Subject: [PATCH 02/22] lint & ES6 js/core/*.js, js/core/debug --- js/core/cmos-time.js | 48 ++++++++++++++++++++-------------------- js/core/debug/v8debug.js | 18 +++++++-------- js/core/driver-utils.js | 16 ++++---------- js/core/index.js | 44 ++++++++++++++++++------------------ js/core/polyfill.js | 4 +--- js/core/set-time.js | 48 +++++++++++++++------------------------- js/core/timers.js | 16 +++++--------- 7 files changed, 84 insertions(+), 110 deletions(-) diff --git a/js/core/cmos-time.js b/js/core/cmos-time.js index dd54e53ab..d7b37c612 100644 --- a/js/core/cmos-time.js +++ b/js/core/cmos-time.js @@ -17,41 +17,41 @@ 'use strict'; -var resources = require('./resources'); -var ports = resources.ioRange; +const resources = require('./resources'); +const ports = resources.ioRange; -var second = 0; -var minute = 0; -var hour = 0; -var day = 0; -var month = 0; -var year = 0; +let second = 0; +let minute = 0; +let hour = 0; +let day = 0; +let month = 0; +let year = 0; -var cmosAddress = 0x70; -var cmosData = 0x71; +const cmosAddress = 0x70; +const cmosData = 0x71; -var port = ports.port(cmosAddress); -var dataPort = ports.port(cmosData); +const port = ports.port(cmosAddress); +const dataPort = ports.port(cmosData); -function getUpdateInProgressFlag() { +const getUpdateInProgressFlag = () => { port.write8(0x0A); return (dataPort.read8() & 0x80); -} +}; -function getRTCRegister(reg) { +const getRTCRegister = (reg) => { port.write8(reg); return dataPort.read8(); -} +}; // set the time: -var lastSecond = 0; -var lastMinute = 0; -var lastHour = 0; -var lastDay = 0; -var lastMonth = 0; -var lastYear = 0; -var registerB = 0; +let lastSecond = 0; +let lastMinute = 0; +let lastHour = 0; +let lastDay = 0; +let lastMonth = 0; +let lastYear = 0; +let registerB = 0; while (getUpdateInProgressFlag()) { second = getRTCRegister(0x00); @@ -93,5 +93,5 @@ if (!(registerB & 0x04)) { year = year + 2000; -var utc = Date.UTC(year, month - 1, day, hour, minute, second, 0); +const utc = Date.UTC(year, month - 1, day, hour, minute, second, 0); __SYSCALL.setTime(utc * 1000); diff --git a/js/core/debug/v8debug.js b/js/core/debug/v8debug.js index ba64ac914..b89e00dcb 100644 --- a/js/core/debug/v8debug.js +++ b/js/core/debug/v8debug.js @@ -16,17 +16,17 @@ /* eslint-disable camelcase, no-new-func, new-cap */ // V8 specific code -var NATIVE_GetOptimizationStatus = new Function('f', 'return %GetOptimizationStatus(f)'); -var NATIVE_OptimizeFunctionOnNextCall = new Function('f', '%OptimizeFunctionOnNextCall(f)'); +const NATIVE_GetOptimizationStatus = new Function('f', 'return %GetOptimizationStatus(f)'); +const NATIVE_OptimizeFunctionOnNextCall = new Function('f', '%OptimizeFunctionOnNextCall(f)'); -exports.getOptimizationStatus = function(fn) { +exports.getOptimizationStatus = (fn) => { switch (NATIVE_GetOptimizationStatus(fn)) { - case 1: return 'optimized'; - case 2: return 'not optimized'; - case 3: return 'always optimized'; - case 4: return 'never optimized'; - case 6: return 'maybe deoptimized'; - default: return 'unknown'; + case 1: return 'optimized'; + case 2: return 'not optimized'; + case 3: return 'always optimized'; + case 4: return 'never optimized'; + case 6: return 'maybe deoptimized'; + default: return 'unknown'; } }; diff --git a/js/core/driver-utils.js b/js/core/driver-utils.js index 628923b45..514170122 100644 --- a/js/core/driver-utils.js +++ b/js/core/driver-utils.js @@ -13,16 +13,8 @@ // limitations under the License. 'use strict'; -var resources = require('./resources'); +const resources = require('./resources'); -exports.physicalMemory = function(address, byteLength) { - return resources.memoryRange.block(address >>> 0, byteLength >>> 0); -}; - -exports.irq = function(number) { - return resources.irqRange.irq(number >>> 0); -}; - -exports.ioPort = function(number) { - return resources.ioRange.port(number >>> 0); -}; +exports.physicalMemory = (address, byteLength) => resources.memoryRange.block(address >>> 0, byteLength >>> 0); // eslint-disable-line max-len +exports.irq = number => resources.irqRange.irq(number >>> 0); +exports.ioPort = number => resources.ioRange.port(number >>> 0); diff --git a/js/core/index.js b/js/core/index.js index 39ef77445..ebddb3600 100644 --- a/js/core/index.js +++ b/js/core/index.js @@ -14,30 +14,32 @@ 'use strict'; -var resources = require('./resources'); +const { allocator } = require('./resources'); require('./polyfill'); -var random = require('./random'); -var keyboard = require('./keyboard'); -var ps2 = require('./ps2'); -var pci = require('./pci'); -var net = require('./net'); -var stdio = require('./stdio'); +const random = require('./random'); +const keyboard = require('./keyboard'); +const ps2 = require('./ps2'); +const pci = require('./pci'); +const net = require('./net'); +const stdio = require('./stdio'); -function Runtime() { - this.random = random; - this.keyboard = keyboard; - this.pci = pci; - this.ps2 = ps2; - this.allocator = resources.allocator; - this.net = net; - this.stdio = stdio; - this.machine = { - reboot: __SYSCALL.reboot, - shutdown: function() { - __SYSCALL.acpiEnterSleepState(5); - } - }; +class Runtime { + constructor() { + Object.assign(this, { + random, + keyboard, + pci, + ps2, + allocator, + net, + stdio, + machine: { + reboot: __SYSCALL.reboot, + shutdown: () => __SYSCALL.acpiEnterSleepState(5), + }, + }); + } } global.runtime = module.exports = new Runtime(); diff --git a/js/core/polyfill.js b/js/core/polyfill.js index 5d9cdec2e..ec9ece2b4 100644 --- a/js/core/polyfill.js +++ b/js/core/polyfill.js @@ -15,6 +15,4 @@ 'use strict'; // setImmediate polyfill for kernels < 0.1.9 -global.setImmediate = global.setImmediate || function(f) { - setTimeout(f, 0); -}; +global.setImmediate = global.setImmediate || (f => setTimeout(f, 0)); diff --git a/js/core/set-time.js b/js/core/set-time.js index e4e0acadb..2ad6347ed 100644 --- a/js/core/set-time.js +++ b/js/core/set-time.js @@ -14,45 +14,33 @@ 'use strict'; -/* global runtime */ - -var resources = require('./resources'); -var rawip = null; - -runtime.dns.resolve('pool.ntp.org', {}, function(err, res) { +runtime.dns.resolve('pool.ntp.org', {}, (err, res) => { if (err) return runtime.stdio.defaultStdio.writeError(err); - rawip = res.results[0].address; - - var ip = new runtime.net.IP4Address(rawip[0], rawip[1], rawip[2], rawip[3]); + const rawip = res.results[0].address; - var data = new Uint8Array(48); + const data = new Uint8Array(48); data[0] = 0x1B; - for (var i = 1; i < 48; i++) { - data[i] = 0; - } + let i; + for (i = 1; i < 48; i++) data[i] = 0; - var socket = new runtime.net.UDPSocket(); - socket.onmessage = function(ip, port, u8) { - var offset = 40; - var intpart = 0; - var fractpart = 0; + const socket = new runtime.net.UDPSocket(); + socket.onmessage = (ip, port, u8) => { + const offset = 40; + let intpart = 0; + let fractpart = 0; - for (let i = 0; i <= 3; i++) { - intpart = 256 * intpart + u8[offset + i]; - } + for (i = 0; i <= 3; i++) intpart = (256 * intpart) + u8[offset + i]; + for (i = 4; i <= 7; i++) fractpart = (256 * fractpart) + u8[offset + i]; - for (let i = 4; i <= 7; i++) { - fractpart = 256 * fractpart + u8[offset + i]; - } + const milli = ((intpart * 1000) + ((fractpart * 1000) / 0x100000000)); - var milli = (intpart * 1000 + (fractpart * 1000) / 0x100000000); - - var date = new Date('Jan 01 1900 GMT'); + const date = new Date('Jan 01 1900 GMT'); __SYSCALL.setTime((date.getTime() + milli) * 1000); }; - setTimeout(function() { - socket.send(ip, 123, data); - }, 1000); + + const ip = new runtime.net.IP4Address(rawip[0], rawip[1], rawip[2], rawip[3]); + + setTimeout(() => socket.send(ip, 123, data), 1000); }); diff --git a/js/core/timers.js b/js/core/timers.js index 9c1784a4c..86090831d 100644 --- a/js/core/timers.js +++ b/js/core/timers.js @@ -14,16 +14,12 @@ 'use strict'; -var tasks5s = []; +const tasks5s = []; -setInterval(function() { - if (tasks5s.length === 0) { - return; - } +setInterval(() => { + if (tasks5s.length === 0) return; - for (var i = 0, l = tasks5s.length; i < l; ++i) { - tasks5s[i](); - } + for (const task of tasks5s) task(); }, 5000); /** @@ -31,6 +27,4 @@ setInterval(function() { * * @param {function} fn Function to run */ -exports.scheduleTask5s = function(fn) { - tasks5s.push(fn); -}; +exports.scheduleTask5s = fn => tasks5s.push(fn); From a5f3cbb4a8506539aab8a456b4311ee8e645cbff Mon Sep 17 00:00:00 2001 From: Face Kapow Date: Fri, 8 Jul 2016 13:41:07 -0400 Subject: [PATCH 03/22] lint & ES6 js/core/keyboard, js/core/pci --- .eslintrc | 3 +- js/core/keyboard/index.js | 3 +- js/core/pci/index.js | 51 +- js/core/pci/pci-device.js | 116 +++-- js/core/pci/scan.js | 971 +++++++++++++++++--------------------- 5 files changed, 500 insertions(+), 644 deletions(-) diff --git a/.eslintrc b/.eslintrc index d0094afd8..171b21fb2 100644 --- a/.eslintrc +++ b/.eslintrc @@ -15,7 +15,7 @@ rules: - 2 - 'global' max-len: - - 2 + - 1 - code: 100 tabWidth: 2 @@ -23,6 +23,7 @@ rules: ignoreUrls: true consistent-return: 1 no-underscore-dangle: 0 + global-require: 0 parserOptions: ecmaVersion: 6 diff --git a/js/core/keyboard/index.js b/js/core/keyboard/index.js index fa977f27e..219b3a17a 100644 --- a/js/core/keyboard/index.js +++ b/js/core/keyboard/index.js @@ -13,6 +13,7 @@ // limitations under the License. 'use strict'; -var EventController = require('event-controller'); + +const EventController = require('event-controller'); exports.onKeydown = new EventController(); exports.onKeyup = new EventController(); diff --git a/js/core/pci/index.js b/js/core/pci/index.js index 986dfd40f..874b6ea2c 100644 --- a/js/core/pci/index.js +++ b/js/core/pci/index.js @@ -13,52 +13,35 @@ // limitations under the License. 'use strict'; -var assert = require('assert'); -var scan = require('./scan'); -var PciDevice = require('./pci-device'); -var typeutils = require('typeutils'); -var isint = require('isint'); +const assert = require('assert'); +const scan = require('./scan'); +const PciDevice = require('./pci-device'); +const typeutils = require('typeutils'); +const isint = require('isint'); -var deviceList = []; +const deviceList = []; -function init() { - var pciDataList = scan(); - for (var i = 0, l = pciDataList.length; i < l; ++i) { - var pciData = pciDataList[i]; - deviceList.push(new PciDevice(pciData)); - } -} +const init = () => { + for (const pciData of scan()) deviceList.push(new PciDevice(pciData)); +}; -function setupDeviceDriver(vendorId, deviceId, driver) { +const setupDeviceDriver = (vendorId, deviceId, driver) => { assert(isint.uint16(vendorId)); assert(isint.uint16(deviceId) || typeutils.isFunction(deviceId)); - for (var i = 0, l = deviceList.length; i < l; ++i) { - var device = deviceList[i]; - if (device.hasDriver()) { - continue; - } - - if (device.vendorId !== vendorId) { - continue; - } - + for (const device of deviceList) { + if (device.hasDriver()) continue; + if (device.vendorId !== vendorId) continue; if (typeutils.isFunction(deviceId)) { - if (!deviceId(device.deviceId)) { - continue; - } + if (!deviceId(device.deviceId)) continue; } else { - if (device.deviceId !== deviceId) { - continue; - } + if (device.deviceId !== deviceId) continue; } device.setDriver(driver); } -} +}; init(); -exports.addDriver = function(vendorId, deviceId, opts) { - setupDeviceDriver(vendorId, deviceId, opts); -}; +exports.addDriver = (vendorId, deviceId, opts) => setupDeviceDriver(vendorId, deviceId, opts); diff --git a/js/core/pci/pci-device.js b/js/core/pci/pci-device.js index a7f494eff..16cb406c6 100644 --- a/js/core/pci/pci-device.js +++ b/js/core/pci/pci-device.js @@ -13,68 +13,66 @@ // limitations under the License. 'use strict'; -var assert = require('assert'); -var typeutils = require('typeutils'); -var isint = require('isint'); +const assert = require('assert'); +const typeutils = require('typeutils'); +const isint = require('isint'); -function PciDevice(opts) { - assert(typeutils.isObject(opts)); - assert(isint.uint16(opts.vendorId)); - assert(isint.uint16(opts.deviceId)); - assert(isint.uint8(opts.bus)); - assert(isint.uint8(opts.slot)); - assert(isint.uint8(opts.func)); - assert(typeutils.isObject(opts.pciAccessor)); - assert(typeutils.isArray(opts.bars)); +class PciDevice { + constructor(opts) { + assert(typeutils.isObject(opts)); + assert(isint.uint16(opts.vendorId)); + assert(isint.uint16(opts.deviceId)); + assert(isint.uint8(opts.bus)); + assert(isint.uint8(opts.slot)); + assert(isint.uint8(opts.func)); + assert(typeutils.isObject(opts.pciAccessor)); + assert(typeutils.isArray(opts.bars)); - this.vendorId = opts.vendorId; - this.deviceId = opts.deviceId; - this.pciAccessor = opts.pciAccessor; - this.subsystem = opts.subsystemData; - this.bars = opts.bars; - this.irq = opts.irq; + this.vendorId = opts.vendorId; + this.deviceId = opts.deviceId; + this.pciAccessor = opts.pciAccessor; + this.subsystem = opts.subsystemData; + this.bars = opts.bars; + this.irq = opts.irq; - this.driver = null; + this.driver = null; + } + getBAR(index) { + assert(Number.isInteger(index) && index >= 0 && index <= 6); + return this.bars[index] || null; + } + getIRQ() { + return this.irq; + } + setPciCommandFlag(flag) { + assert(Number.isInteger(flag) && flag >= 0 && flag < 16); + let t = this.pciAccessor.read(this.pciAccessor.fields().COMMAND); + t |= (1 << flag) >>> 0; + this.pciAccessor.write(this.pciAccessor.fields().COMMAND, t); + } + setDriver(driver) { + assert(typeutils.isObject(driver)); + assert(typeutils.isFunction(driver.init)); + this.driver = driver; + driver.init(this); + } + hasDriver() { + return this.driver !== null; + } + static get commandFlag() { + return { + IOSpace: 0, + MemorySpace: 1, + BusMaster: 2, + SpecialCycles: 3, + MemoryWriteInvalidate: 4, + VGAPaletteSnoop: 5, + ParityError: 6, + SERR: 8, + BackToBack: 9, + InterruptDisable: 10, + }; + } } -PciDevice.prototype.getBAR = function(index) { - assert(Number.isInteger(index) && index >= 0 && index <= 6); - return this.bars[index] || null; -}; - -PciDevice.prototype.getIRQ = function() { - return this.irq; -}; - -PciDevice.prototype.setPciCommandFlag = function(flag) { - assert(Number.isInteger(flag) && flag >= 0 && flag < 16); - var t = this.pciAccessor.read(this.pciAccessor.fields().COMMAND); - t |= (1 << flag) >>> 0; - this.pciAccessor.write(this.pciAccessor.fields().COMMAND, t); -}; - -PciDevice.prototype.setDriver = function(driver) { - assert(typeutils.isObject(driver)); - assert(typeutils.isFunction(driver.init)); - this.driver = driver; - driver.init(this); -}; - -PciDevice.prototype.hasDriver = function() { - return null !== this.driver; -}; - -PciDevice.commandFlag = { - IOSpace: 0, - MemorySpace: 1, - BusMaster: 2, - SpecialCycles: 3, - MemoryWriteInvalidate: 4, - VGAPaletteSnoop: 5, - ParityError: 6, - SERR: 8, - BackToBack: 9, - InterruptDisable: 10 -}; - module.exports = PciDevice; diff --git a/js/core/pci/scan.js b/js/core/pci/scan.js index 9c0426d66..dfcc8331f 100644 --- a/js/core/pci/scan.js +++ b/js/core/pci/scan.js @@ -14,221 +14,203 @@ /* eslint-disable key-spacing */ 'use strict'; -var resources = require('../resources'); -var io = resources.ioRange; -var irqRange = resources.irqRange; -var memrange = resources.memoryRange; -var allocator = resources.allocator; -var acpiDevices = __SYSCALL.acpiGetPciDevices(); -var addressPortResource = io.port(0xCF8); -var dataPortResource = io.port(0xCFC); - -var sizeof = { + +const resources = require('../resources'); +const io = resources.ioRange; +const irqRange = resources.irqRange; +const memrange = resources.memoryRange; +const allocator = resources.allocator; +const acpiDevices = __SYSCALL.acpiGetPciDevices(); +const addressPortResource = io.port(0xCF8); +const dataPortResource = io.port(0xCFC); + +const sizeof = { BYTE: 1, UINT8: 1, UINT16: 2, UINT32: 4, - UINT64: 8 + UINT64: 8, }; -var pciAccessorFactory = (function(addressPort, dataPort) { - var accessorCache = new Map(); +const pciAccessorFactory = ((addressPort, dataPort) => { + const accessorCache = new Map(); /** * Available PCI configuration space fields for all types * of devices */ - var fields = { - VENDOR_ID: {offset: 0x00, shift: 0, mask: 0xffff}, - DEVICE_ID: {offset: 0x00, shift: 2, mask: 0xffff}, - - COMMAND: {offset: 0x04, shift: 0, mask: 0xffff}, - STATUS: {offset: 0x04, shift: 2, mask: 0xffff}, - - REVISION_ID: {offset: 0x08, shift: 0, mask: 0xff}, - PROG_IF: {offset: 0x08, shift: 1, mask: 0xff}, - SUBCLASS: {offset: 0x08, shift: 2, mask: 0xff}, - CLASS_CODE: {offset: 0x08, shift: 3, mask: 0xff}, - - CACHE_LINESIZE: {offset: 0x0c, shift: 0, mask: 0xff}, - LATENCY_TIMER: {offset: 0x0c, shift: 1, mask: 0xff}, - HEADER_TYPE: {offset: 0x0c, shift: 2, mask: 0xff}, - BIST: {offset: 0x0c, shift: 3, mask: 0xff} + const fields = { + VENDOR_ID: { offset: 0x00, shift: 0, mask: 0xffff }, + DEVICE_ID: { offset: 0x00, shift: 2, mask: 0xffff }, + + COMMAND: { offset: 0x04, shift: 0, mask: 0xffff }, + STATUS: { offset: 0x04, shift: 2, mask: 0xffff }, + + REVISION_ID: { offset: 0x08, shift: 0, mask: 0xff }, + PROG_IF: { offset: 0x08, shift: 1, mask: 0xff }, + SUBCLASS: { offset: 0x08, shift: 2, mask: 0xff }, + CLASS_CODE: { offset: 0x08, shift: 3, mask: 0xff }, + + CACHE_LINESIZE: { offset: 0x0c, shift: 0, mask: 0xff }, + LATENCY_TIMER: { offset: 0x0c, shift: 1, mask: 0xff }, + HEADER_TYPE: { offset: 0x0c, shift: 2, mask: 0xff }, + BIST: { offset: 0x0c, shift: 3, mask: 0xff }, }; /** * Available PCI configuration space fields for general devices * (header type 0x00) */ - var generalFields = { - BAR: [{offset: 0x10, shift: 0, mask: 0xffffffff}, - {offset: 0x14, shift: 0, mask: 0xffffffff}, - {offset: 0x18, shift: 0, mask: 0xffffffff}, - {offset: 0x1c, shift: 0, mask: 0xffffffff}, - {offset: 0x20, shift: 0, mask: 0xffffffff}, - {offset: 0x24, shift: 0, mask: 0xffffffff}], - - SUBSYS_VENDOR: {offset: 0x2c, shift: 0, mask: 0xffff}, - SUBSYS_ID: {offset: 0x2c, shift: 2, mask: 0xffff}, - - INTERRUPT_LINE: {offset: 0x3c, shift: 0, mask: 0xff}, - INTERRUPT_PIN: {offset: 0x3c, shift: 1, mask: 0xff} + const generalFields = { + BAR: [{ offset: 0x10, shift: 0, mask: 0xffffffff }, + { offset: 0x14, shift: 0, mask: 0xffffffff }, + { offset: 0x18, shift: 0, mask: 0xffffffff }, + { offset: 0x1c, shift: 0, mask: 0xffffffff }, + { offset: 0x20, shift: 0, mask: 0xffffffff }, + { offset: 0x24, shift: 0, mask: 0xffffffff }], + + SUBSYS_VENDOR: { offset: 0x2c, shift: 0, mask: 0xffff }, + SUBSYS_ID: { offset: 0x2c, shift: 2, mask: 0xffff }, + + INTERRUPT_LINE: { offset: 0x3c, shift: 0, mask: 0xff }, + INTERRUPT_PIN: { offset: 0x3c, shift: 1, mask: 0xff }, }; /** * Available PCI configuration space fields for bridge devices * (header type 0x01 or 0x02) */ - var bridgeFields = { - PRIMARY_BUS: {offset: 0x18, shift: 0, mask: 0xff}, - SECONDARY_BUS: {offset: 0x18, shift: 1, mask: 0xff}, - SUBORDINATE: {offset: 0x18, shift: 2, mask: 0xff} + const bridgeFields = { + PRIMARY_BUS: { offset: 0x18, shift: 0, mask: 0xff }, + SECONDARY_BUS: { offset: 0x18, shift: 1, mask: 0xff }, + SUBORDINATE: { offset: 0x18, shift: 2, mask: 0xff }, }; - function setPort(bus, slot, func, offset) { - var addr = ((bus << 16) | (slot << 11) | (func << 8) | + const setPort = (bus, slot, func, offset) => { + const addr = ((bus << 16) | (slot << 11) | (func << 8) | (offset & 0xfc) | 0x80000000) >>> 0; addressPort.write32(addr); - } + }; - function readRaw32(bus, slot, func, offset) { - if (offset % sizeof.UINT32 !== 0) { - throw new Error('unaligned pci space 32 bit read'); - } + const readRaw32 = (bus, slot, func, offset) => { + if (offset % sizeof.UINT32 !== 0) throw new Error('unaligned pci space 32 bit read'); setPort(bus, slot, func, offset); return dataPort.read32(); - } + }; - function dwToFieldValue(value, field) { - return ((value >>> (8 * sizeof.BYTE * field.shift)) & - field.mask) >>> 0; - } + const dwToFieldValue = (value, field) => ((value >>> (8 * sizeof.BYTE * field.shift)) & field.mask) >>> 0; // eslint-disable-line max-len /** * Provides a way to read and write PCI Configuration space registers. * Uses internal cache to speed up reads of the same field. Address * includes bus, slot and func of a device. */ - function PciAccessor(address) { - var bus = address.bus >>> 0, - slot = address.slot >>> 0, - func = address.func >>> 0; - - if (bus > 255) { - throw new Error('invalid bus value (expected 0-255)'); - } + class PciAccessor { + constructor(address) { + const bus = address.bus >>> 0; + const slot = address.slot >>> 0; + const func = address.func >>> 0; - if (slot > 31) { - throw new Error('invalid slot value (expected 0-31)'); - } + if (bus > 255) throw new Error('invalid bus value (expected 0-255)'); + if (slot > 31) throw new Error('invalid slot value (expected 0-31)'); + if (func > 7) throw new Error('invalid func value (expected 0-7)'); - if (func > 7) { - throw new Error('invalid func value (expected 0-7)'); - } + const offsetCache = new Map(); - var offsetCache = new Map(); + const writeRaw32 = (offset, value) => { + if (offset % sizeof.UINT32 !== 0) throw new Error('unaligned pci space 32-bit write'); - function writeRaw32(offset, value) { - if (offset % sizeof.UINT32 !== 0) { - throw new Error('unaligned pci space 32-bit write'); - } - - setPort(bus, slot, func, offset); - return dataPort.write32(value >>> 0); - } - - function writeRaw16(offset, value) { - if (offset % sizeof.UINT16 !== 0) { - throw new Error('unaligned pci space 16-bit write'); - } + setPort(bus, slot, func, offset); + return dataPort.write32(value >>> 0); + }; - setPort(bus, slot, func, offset); - return dataPort.write16((value & 0xffff) >>> 0); - } + const writeRaw16 = (offset, value) => { + if (offset % sizeof.UINT16 !== 0) throw new Error('unaligned pci space 16-bit write'); - function writeRaw8(offset, value) { - setPort(bus, slot, func, offset); - return dataPort.write8((value & 0xff) >>> 0); - } + setPort(bus, slot, func, offset); + return dataPort.write16((value & 0xffff) >>> 0); + }; - /** - * Read PCI configuration space field - */ - this.read = function __read(field) { - var value; + const writeRaw8 = (offset, value) => { + setPort(bus, slot, func, offset); + return dataPort.write8((value & 0xff) >>> 0); + }; - if (offsetCache.has(field.offset)) { - value = offsetCache.get(field.offset); - } else { - value = readRaw32(bus, slot, func, field.offset); - offsetCache.set(field.offset, value); - } + /** + * Read PCI configuration space field + */ + this.read = (field) => { + let value; + + if (offsetCache.has(field.offset)) { + value = offsetCache.get(field.offset); + } else { + value = readRaw32(bus, slot, func, field.offset); + offsetCache.set(field.offset, value); + } - return dwToFieldValue(value, field); - }; + return dwToFieldValue(value, field); + }; - /** - * Write PCI configuration space field - */ - this.write = function __write(field, value) { - offsetCache.delete(field.offset); - - switch (field.mask) { - case 0xffffffff: writeRaw32(field.offset, value); break; - case 0xffff: writeRaw16(field.offset + field.shift, value); break; - case 0xff: writeRaw8(field.offset + field.shift, value); break; - default: - throw new Error('invalid pci space field mask'); - } - }; + /** + * Write PCI configuration space field + */ + this.write = (field, value) => { + offsetCache.delete(field.offset); + + switch (field.mask) { + case 0xffffffff: writeRaw32(field.offset, value); break; + case 0xffff: writeRaw16(field.offset + field.shift, value); break; + case 0xff: writeRaw8(field.offset + field.shift, value); break; + default: + throw new Error('invalid pci space field mask'); + } + }; - /** - * Set of methods to get available accessor fields - */ - this.fields = function __fields() { return fields; }; - this.generalFields = function __generalFields() { return generalFields; }; - this.bridgeFields = function __bridgeFields() { return bridgeFields; }; + /** + * Set of methods to get available accessor fields + */ + this.fields = () => fields; + this.generalFields = () => generalFields; + this.bridgeFields = () => bridgeFields; + } } return { /** * Returns PCI accessor object for provided address */ - get: function __get(address) { - var key = JSON.stringify([address.bus, address.slot, address.func]); - if (accessorCache.has(key)) { - return accessorCache.get(key); - } + get(address) { + const key = JSON.stringify([address.bus, address.slot, address.func]); + if (accessorCache.has(key)) return accessorCache.get(key); - var value = new PciAccessor(address); + const value = new PciAccessor(address); accessorCache.set(key, value); return value; }, /** * Check if PCI device at address exists */ - exists: function __exists(bus, slot, func) { - var field = fields.VENDOR_ID; - var value = readRaw32(bus, slot, func, field.offset); - var vendorId = dwToFieldValue(value, field); - return 0xffff !== vendorId; - } + exists(bus, slot, func) { + const field = fields.VENDOR_ID; + const value = readRaw32(bus, slot, func, field.offset); + const vendorId = dwToFieldValue(value, field); + return vendorId !== 0xffff; + }, }; })(addressPortResource, dataPortResource); /** * Find ACPI PCI device bus, slot and function */ -function locateAcpiDevice(dev) { - if (!dev.isDevice()) { - return null; - } +const locateAcpiDevice = (dev) => { + if (!dev.isDevice()) return null; - var addr = dev.address(); - var slotId = ((addr >>> 16) & 0xffff) >>> 0; - var funcId = (addr & 0xffff) >>> 0; - var busId = 0; + const addr = dev.address(); + const slotId = ((addr >>> 16) & 0xffff) >>> 0; + const funcId = (addr & 0xffff) >>> 0; + let busId = 0; if (dev.isRootBridge()) { busId = dev.getRootBridgeBusNumber(); @@ -236,18 +218,14 @@ function locateAcpiDevice(dev) { return { bus: busId, slot: slotId, - func: funcId + func: funcId, }; } - var parentDev = dev.parent(); - if (null === parentDev) { - return null; - } + const parentDev = dev.parent(); + if (parentDev === null) return null; - if (!parentDev.isDevice()) { - return null; - } + if (!parentDev.isDevice()) return null; if (parentDev.isRootBridge()) { busId = parentDev.getRootBridgeBusNumber(); @@ -255,89 +233,77 @@ function locateAcpiDevice(dev) { return { bus: busId, slot: slotId, - func: funcId + func: funcId, }; } - var parentLocation = locateAcpiDevice(parentDev); - if (null === parentLocation) { - return null; - } + const parentLocation = locateAcpiDevice(parentDev); + if (parentLocation === null) return null; - var pciParent = pciAccessorFactory.get({ + const pciParent = pciAccessorFactory.get({ bus: parentLocation.bus, slot: parentLocation.slot, - func: parentLocation.func + func: parentLocation.func, }); - var header = pciParent.read(pciParent.fields().HEADER_TYPE); + const header = pciParent.read(pciParent.fields().HEADER_TYPE); // Mask multifunction bit - var headerType = (header & 0x7f) >>> 0; - if (0x01 !== headerType && 0x02 !== headerType) { - return null; - } + const headerType = (header & 0x7f) >>> 0; + if (headerType !== 0x01 && headerType !== 0x02) return null; - var bridgeBus = pciParent.read(pciParent.bridgeFields().SECONDARY_BUS); + const bridgeBus = pciParent.read(pciParent.bridgeFields().SECONDARY_BUS); return { bus: bridgeBus, slot: slotId, - func: funcId + func: funcId, }; -} +}; /** * Provides enumeration services for the whole PCI configuration space */ -var pciSpace = (function(pciAccessorFactoryArg) { - function checkDevice(bus, slot, func, fn) { - var addr = {bus: bus, slot:slot, func: func}; - var pciAccessor = pciAccessorFactoryArg.get(addr); - var vendorId = pciAccessor.read(pciAccessor.fields().VENDOR_ID); - - if (0xffff === vendorId) { - return; - } +const pciSpace = ((pciAccessorFactoryArg) => { + const checkDevice = (bus, slot, func, fn) => { + const addr = { bus, slot, func }; + const pciAccessor = pciAccessorFactoryArg.get(addr); + const vendorId = pciAccessor.read(pciAccessor.fields().VENDOR_ID); + + if (vendorId === 0xffff) return; fn(addr, pciAccessor); - } + }; - function checkDeviceFunctions(bus, slot, fn) { - var func = 0; - var pciAccessor = pciAccessorFactoryArg.get({bus: bus, slot:slot, func: func}); - var headerType = pciAccessor.read(pciAccessor.fields().HEADER_TYPE); - var isMultifunc = (headerType & 0x80) >>> 0; - var funcCount = isMultifunc ? 8 : 1; + const checkDeviceFunctions = (bus, slot, fn) => { + let func = 0; + const pciAccessor = pciAccessorFactoryArg.get({ bus, slot, func }); + const headerType = pciAccessor.read(pciAccessor.fields().HEADER_TYPE); + const isMultifunc = (headerType & 0x80) >>> 0; + const funcCount = isMultifunc ? 8 : 1; - for (func = 0; func < funcCount; ++func) { - checkDevice(bus, slot, func, fn); - } - } + for (func = 0; func < funcCount; ++func) checkDevice(bus, slot, func, fn); + }; return { - eachDevice: function(fn) { - var func = 0; - - for (var bus = 0; bus < 255; ++bus) { - for (var slot = 0; slot < 32; ++slot) { - - if (!pciAccessorFactoryArg.exists(bus, slot, func)) { - continue; - } + eachDevice(fn) { + const func = 0; + for (let bus = 0; bus < 255; ++bus) { + for (let slot = 0; slot < 32; ++slot) { + if (!pciAccessorFactoryArg.exists(bus, slot, func)) continue; checkDeviceFunctions(bus, slot, fn); } } - } + }, }; })(pciAccessorFactory); /** * Service for converting PCI data codes to readable names */ -var codeNameResolver = (function() { - var classCodes = [ +const codeNameResolver = (() => { + const classCodes = [ 'Unclassified', 'Mass Storage Controller', 'Network Controller', @@ -355,309 +321,248 @@ var codeNameResolver = (function() { 'Intelligent I/O Controller', 'Satellite Communication Controller', 'Encryption/Decryption Controller', - 'Data Acquisition and Signal Processing Controller' + 'Data Acquisition and Signal Processing Controller', ]; return { /** * Get name for provided PCI device class code */ - classCodeToName: function(code) { - if ('undefined' === typeof classCodes[code]) { - return classCodes[0]; - } - + classCodeToName(code) { + if (typeof classCodes[code] === 'undefined') return classCodes[0]; return classCodes[code]; - } + }, }; })(); /** * Represents PCI device of any type */ -function PciDevice(address, pciAccessor) { - this.pciAccessor = pciAccessor; - var vendorId = pciAccessor.read(pciAccessor.fields().VENDOR_ID); - var deviceId = pciAccessor.read(pciAccessor.fields().DEVICE_ID); - var header = pciAccessor.read(pciAccessor.fields().HEADER_TYPE); - var isBridge = false; - - var headerType = (header & 0x7f) >>> 0; - if (0x01 === headerType || 0x02 === headerType) { - isBridge = true; - } - - var that = { - acpiDevice: null - }; - - var irqVector = null; +class PciDevice { + constructor(address, pciAccessor) { + this.pciAccessor = pciAccessor; + const vendorId = pciAccessor.read(pciAccessor.fields().VENDOR_ID); + const deviceId = pciAccessor.read(pciAccessor.fields().DEVICE_ID); + const header = pciAccessor.read(pciAccessor.fields().HEADER_TYPE); + let isBridge = false; - /** - * Attach ACPI PCI device handle to current PCI device - */ - this.attachAcpiDevice = function __attachAcpiDevice(acpiDevice) { - if (null !== that.acpiDevice) { - return; - } + const headerType = (header & 0x7f) >>> 0; + if (headerType === 0x01 || headerType === 0x02) isBridge = true; - that.acpiDevice = acpiDevice; - }; - - /** - * Get 16bit vendor ID of current device - */ - this.vendorId = function __vendorId() { return vendorId; }; + const that = { acpiDevice: null }; - /** - * Get 16bit device ID of current device - */ - this.deviceId = function __deviceId() { return deviceId; }; + let irqVector = null; - /** - * Check if current device is a PCI-to-PCI or PCI-to-CardBus - * bridge - */ - this.isBridge = function __isBridge() { return isBridge; }; + /** + * Attach ACPI PCI device handle to current PCI device + */ + this.attachAcpiDevice = (acpiDevice) => { + if (that.acpiDevice !== null) return; + that.acpiDevice = acpiDevice; + }; - /** - * Get PCI device address (bus, slot and function) - */ - this.address = function __address() { return address; }; + /** + * Get 16bit vendor ID of current device + */ + this.vendorId = () => vendorId; - /** - * Get bridge secondary bus number (bus number of current bridge) - */ - this.getSecondaryBus = function __getSecondaryBus() { - if (!isBridge) { - throw new Error('device is not a bridge'); - } + /** + * Get 16bit device ID of current device + */ + this.deviceId = () => deviceId; - return pciAccessor.read(pciAccessor.bridgeFields().SECONDARY_BUS); - }; + /** + * Check if current device is a PCI-to-PCI or PCI-to-CardBus + * bridge + */ + this.isBridge = () => isBridge; - this.setCommandFlag = function __setCommandFlag(flag) { - var value = pciAccessor.read(pciAccessor.fields().COMMAND); - value |= (1 << flag) >>> 0; - pciAccessor.write(pciAccessor.fields().COMMAND, value); - }; + /** + * Get PCI device address (bus, slot and function) + */ + this.address = () => address; - /** - * Get current device IRQ vector - */ - this.getIRQVector = function __getIRQVector(vector) { - return irqVector; - }; + /** + * Get bridge secondary bus number (bus number of current bridge) + */ + this.getSecondaryBus = () => { + if (!isBridge) throw new Error('device is not a bridge'); + return pciAccessor.read(pciAccessor.bridgeFields().SECONDARY_BUS); + }; - /** - * Set current device IRQ vector. May be called only once - */ - this.setIRQVector = function __setIRQVector(vector) { - if (null !== irqVector) { - throw new Error('IRQ vector already set'); - } + this.setCommandFlag = (flag) => { + let value = pciAccessor.read(pciAccessor.fields().COMMAND); + value |= (1 << flag) >>> 0; + pciAccessor.write(pciAccessor.fields().COMMAND, value); + }; - irqVector = vector >>> 0; - }; + /** + * Get current device IRQ vector + */ + this.getIRQVector = () => irqVector; - /** - * Get interrupt pin of current device - */ - this.interruptPin = function __interruptPin() { - if (isBridge) { - throw new Error('device is a bridge'); - } + /** + * Set current device IRQ vector. May be called only once + */ + this.setIRQVector = (vector) => { + if (irqVector !== null) throw new Error('IRQ vector already set'); + irqVector = vector >>> 0; + }; - return pciAccessor.read(pciAccessor.generalFields().INTERRUPT_PIN); - }; + /** + * Get interrupt pin of current device + */ + this.interruptPin = () => { + if (isBridge) throw new Error('device is a bridge'); + return pciAccessor.read(pciAccessor.generalFields().INTERRUPT_PIN); + }; - /** - * Get the class data of current device (class code, subclass, - * class name) - */ - this.classData = function __classData() { - var classCode = pciAccessor.read(pciAccessor.fields().CLASS_CODE); - var subclass = pciAccessor.read(pciAccessor.fields().SUBCLASS); - var className = codeNameResolver.classCodeToName(classCode); + /** + * Get the class data of current device (class code, subclass, + * class name) + */ + this.classData = () => { + const classCode = pciAccessor.read(pciAccessor.fields().CLASS_CODE); + return { + classCode, + className: pciAccessor.read(pciAccessor.fields().SUBCLASS), + subclass: codeNameResolver.classCodeToName(classCode), + }; + }; - return { - classCode: classCode, - className: className, - subclass: subclass + this.subsystemData = () => { + if (isBridge) throw new Error('device is a bridge'); + return { + subsystemId: pciAccessor.read(pciAccessor.generalFields().SUBSYS_ID), + subsystemVendor: pciAccessor.read(pciAccessor.generalFields().SUBSYS_VENDOR), + }; }; - }; - this.subsystemData = function __subsystemData() { - if (isBridge) { - throw new Error('device is a bridge'); - } + /** + * Read PCI base address register (BAR) and return resource type, + * offset, size and object. Returns null is BAR is not valid + */ + this.getBAR = (index) => { + if (isBridge) throw new Error('device is a bridge'); - return { - subsystemId: pciAccessor.read(pciAccessor.generalFields().SUBSYS_ID), - subsystemVendor: pciAccessor.read(pciAccessor.generalFields().SUBSYS_VENDOR) - }; - }; + const indexValue = index >>> 0; + if (indexValue > 5) throw new Error('invalid BAR register index (expected 0-5)'); - /** - * Read PCI base address register (BAR) and return resource type, - * offset, size and object. Returns null is BAR is not valid - */ - this.getBAR = function __getBAR(index) { - if (isBridge) { - throw new Error('device is a bridge'); - } + const barFlag = { + BAR_IO: 0x01, + BAR_64: 0x04, + }; - var indexValue = index >>> 0; - if (indexValue > 5) { - throw new Error('invalid BAR register index (expected 0-5)'); - } + const barField = pciAccessor.generalFields().BAR[indexValue]; + const barAddr = pciAccessor.read(barField); + if (!barAddr) return null; - var barFlag = { - BAR_IO: 0x01, - BAR_64: 0x04 - }; + pciAccessor.write(barField, 0xffffffff); + const barSize = pciAccessor.read(barField); - var barField = pciAccessor.generalFields().BAR[indexValue]; - var barAddr = pciAccessor.read(barField); - if (!barAddr) { - return null; - } + // Restore original value + pciAccessor.write(barField, barAddr >>> 0); - pciAccessor.write(barField, 0xffffffff); - var barSize = pciAccessor.read(barField); + if (!barSize) return null; - // Restore original value - pciAccessor.write(barField, barAddr >>> 0); + let base = 0; + let size = 0; + let barType = null; + let obj = null; - if (!barSize) { - return null; - } + if (barAddr & barFlag.BAR_64) { + // TODO: 64bit bar support + barType = 'mem64'; + } else if (barAddr & barFlag.BAR_IO) { + // TODO: verify io base & size + base = ((barAddr & ~0x3) & 0xffff) >>> 0; + size = ((~(barSize & ~0x3) + 1) & 0xffff) >>> 0; + barType = 'io'; + if (size === 0) return null; - var base = 0; - var size = 0; - var barType = null; - var obj = null; - - if (barAddr & barFlag.BAR_64) { - // TODO: 64bit bar support - barType = 'mem64'; - - } else if (barAddr & barFlag.BAR_IO) { - // TODO: verify io base & size - base = ((barAddr & ~0x3) & 0xffff) >>> 0; - size = ((~(barSize & ~0x3) + 1) & 0xffff) >>> 0; - barType = 'io'; - if (0 === size) { - return null; - } + // Base IO address 0 is probably an error, ignore it + if (base === 0) return null; - // Base IO address 0 is probably an error, ignore it - if (0 === base) { - return null; - } + obj = io.subrange(base, (base + size) - 1); + } else { + base = (barAddr & 0xfffffff0) >>> 0; + size = (((~(barSize & 0xfffffff0) >>> 0) + 1) & 0xffffffff) >>> 0; - obj = io.subrange(base, base + size - 1); - } else { - base = (barAddr & 0xfffffff0) >>> 0; - size = (((~(barSize & 0xfffffff0) >>> 0) + 1) & 0xffffffff) >>> 0; + if (size === 0) return null; - if (0 === size) { - return null; + barType = 'mem32'; + obj = memrange.block(base, size); } - barType = 'mem32'; - obj = memrange.block(base, size); - } - - if (null === barType || null === obj) { - return null; - } + if (barType === null || obj === null) return null; + return { + type: barType, + base, + size, + resource: obj, + }; + }; + } + /** + * PCI configuration space command register flags + */ + static get commandFlags() { return { - type: barType, - base: base, - size: size, - resource: obj + IOSpace: 0, + MemorySpace: 1, + BusMaster: 2, + SpecialCycles: 3, + MemoryWriteInvalidate: 4, + VGAPaletteSnoop: 5, + ParityError: 6, + SERR: 8, + BackToBack: 9, + InterruptDisable: 10, }; - }; + } } -/** - * PCI configuration space command register flags - */ -PciDevice.commandFlags = { - IOSpace: 0, - MemorySpace: 1, - BusMaster: 2, - SpecialCycles: 3, - MemoryWriteInvalidate: 4, - VGAPaletteSnoop: 5, - ParityError: 6, - SERR: 8, - BackToBack: 9, - InterruptDisable: 10 -}; - /** * Manages PCI devices */ -var pciManager = (function() { - var devicesMap = new Map(); - - function addressHash(address) { - return JSON.stringify([address.bus, address.slot, address.func]); - } - - function findDevice(address) { - var key = addressHash(address); - - if (!devicesMap.has(key)) { - return null; - } - - return devicesMap.get(key); - } +const pciManager = (() => { + const devicesMap = new Map(); + const addressHash = address => JSON.stringify([address.bus, address.slot, address.func]); return { /** * Add new PCI device using its address (bus, slot and function) and * PCI configuration space accessor */ - addDevice: function(address, pciAccessor) { - var key = addressHash(address); - - if (devicesMap.has(key)) { - throw new Error('device on the same address already exists' + - JSON.stringify(address)); - } - + addDevice(address, pciAccessor) { + const key = addressHash(address); + if (devicesMap.has(key)) throw new Error(`device on the same address already exists ${JSON.stringify(address)}`); // eslint-disable-line max-len devicesMap.set(key, new PciDevice(address, pciAccessor)); }, /** * Search for an existing device by its address */ - findDevice: findDevice, + findDevice(address) { + const key = addressHash(address); + if (!devicesMap.has(key)) return null; + return devicesMap.get(key); + }, /** * Iterates over all devices */ - each: function(fn) { - devicesMap.forEach(function(pciDevice) { - fn(pciDevice); - }); - } + each: (fn) => devicesMap.forEach(fn), }; })(); // Enumerate configuration space and create PCI devices -pciSpace.eachDevice(function(address, pciAccessor) { - pciManager.addDevice(address, pciAccessor); -}); +pciSpace.eachDevice(pciManager.addDevice); // Collect bus ACPI device handles with their bus numbers -var acpiDevicesBuses = []; -acpiDevices.forEach(function(acpiDevice) { - var address = locateAcpiDevice(acpiDevice); - var busId = 0; +const acpiDevicesBuses = []; +acpiDevices.forEach((acpiDevice) => { + const address = locateAcpiDevice(acpiDevice); + let busId = 0; if (acpiDevice.isRootBridge()) { busId = acpiDevice.getRootBridgeBusNumber(); @@ -665,16 +570,12 @@ acpiDevices.forEach(function(acpiDevice) { } // Check if unable to locate ACPI device on PCI bus - if (null === address) { - return; - } + if (address === null) return; - var dev = pciManager.findDevice(address); + const dev = pciManager.findDevice(address); // Check if unable to find device described in ACPI tables - if (null === dev) { - return; - } + if (dev === null) return; dev.attachAcpiDevice(acpiDevice); @@ -685,90 +586,68 @@ acpiDevices.forEach(function(acpiDevice) { }); // Extract IRQ routing information -var busRouting = []; -acpiDevicesBuses.forEach(function(acpiDevice, bus) { - if ('undefined' === typeof acpiDevice) { - return; - } +const busRouting = []; +acpiDevicesBuses.forEach((acpiDevice, bus) => { + if (typeof acpiDevice === 'undefined') return; - var routes = acpiDevice.getIrqRoutingTable(); - if (!Array.isArray(routes)) { - return; - } + const routes = acpiDevice.getIrqRoutingTable(); + if (!Array.isArray(routes)) return; busRouting[bus] = routes; }); // Set IRQs -pciManager.each(function(pciDevice) { - var address = pciDevice.address(); +pciManager.each((pciDevice) => { + const address = pciDevice.address(); // Skip bridges for now - if (pciDevice.isBridge()) { - return; - } + if (pciDevice.isBridge()) return; - if ('undefined' === typeof busRouting[address.bus]) { - // No ACPI routing for this current device bridge - return; - } + if (typeof busRouting[address.bus] === 'undefined') return; // No ACPI routing for this current device bridge - var routing = busRouting[address.bus]; - var devicePin = pciDevice.interruptPin(); - var deviceIRQ = null; + const routing = busRouting[address.bus]; + const devicePin = pciDevice.interruptPin(); + let deviceIRQ = null; // Check if this device does not use an IRQ pin - if (0 === devicePin) { - return; - } + if (devicePin === 0) return; - routing.forEach(function(route) { - if (address.slot !== route.deviceId) { - return; - } + routing.forEach((route) => { + if (address.slot !== route.deviceId) return; // Plus 1 because routing data returns 0-base pin // numbers (0-A, 1-B, 2-C, 3-D) // PCI configuration space returns pins in format // (0-don't use, 1-A, 2-B, 3-C, 4-D) - if (devicePin !== route.pin + 1) { - return; - } + if (devicePin !== route.pin + 1) return; deviceIRQ = route.irq; }); - if (null !== deviceIRQ) { - pciDevice.setIRQVector(deviceIRQ); - } + if (deviceIRQ !== null) pciDevice.setIRQVector(deviceIRQ); }); // Start drivers -pciManager.each(function(pciDevice) { - var vendorId = pciDevice.vendorId(); - var deviceId = pciDevice.deviceId(); - var driverData = null; - - if (null === driverData || 'undefined' === typeof driverData.driver || - !driverData.enabled) { - return; - } +pciManager.each((pciDevice) => { + // const vendorId = pciDevice.vendorId(); + // const deviceId = pciDevice.deviceId(); + const driverData = null; - var irqVector = pciDevice.getIRQVector(); - var irqObject = null; - if (null !== irqVector) { - irqObject = irqRange.irq(irqVector); - } + if (driverData === null || typeof driverData.driver === 'undefined' || !driverData.enabled) return; // eslint-disable-line max-len - var argsBars = []; - for (var i = 0; i < 6; ++i) { - var bar = pciDevice.getBAR(i); - var barData = null; + const irqVector = pciDevice.getIRQVector(); + let irqObject = null; + if (irqVector !== null) irqObject = irqRange.irq(irqVector); - if (null !== bar) { + const argsBars = []; + for (let i = 0; i < 6; ++i) { + const bar = pciDevice.getBAR(i); + let barData = null; + + if (bar !== null) { barData = { type: bar.type, - resource: bar.resource + resource: bar.resource, }; } @@ -780,89 +659,83 @@ pciManager.each(function(pciDevice) { pciDevice.setCommandFlag(PciDevice.commandFlags.MemorySpace); } - var driverArgs = { + const driverArgs = { pci: { bars: argsBars, irq: irqObject, classData: pciDevice.classData(), - subsystemData: pciDevice.subsystemData() + subsystemData: pciDevice.subsystemData(), }, - allocator: allocator + allocator, }; - require('driver/' + driverData.driver)(driverArgs); + require(`driver/${driverData.driver}`)(driverArgs); // Debug - // isolate.log(JSON.stringify(driverData), JSON.stringify(argsBars)); - - // vfs.getInitrdRoot()({ - // action: 'spawn', - // path: '/driver/' + driverData.driver, - // data: driverArgs, - // env: {} - // }).then(function() {}, function(err) { - // isolate.log(err); - // }); + /* + isolate.log(JSON.stringify(driverData), JSON.stringify(argsBars)); + + vfs.getInitrdRoot()({ + action: 'spawn', + path: '/driver/' + driverData.driver, + data: driverArgs, + env: {} + }).then(function() {}, function(err) { + isolate.log(err); + }); + */ }); // Print PCI devices debug info -pciManager.each(function(pciDevice) { - var address = pciDevice.address(); - var vector = pciDevice.getIRQVector(); - var classData = pciDevice.classData(); - - var devicePin = 0; - if (!pciDevice.isBridge()) { - devicePin = pciDevice.interruptPin(); - } +pciManager.each((pciDevice) => { + const address = pciDevice.address(); + const vector = pciDevice.getIRQVector(); + const classData = pciDevice.classData(); - var pins = ['dont use', 'A', 'B', 'C', 'D']; + let devicePin = 0; + if (!pciDevice.isBridge()) devicePin = pciDevice.interruptPin(); - var info = address.bus.toString(16) + ':' + address.slot.toString(16) + '.' + address.func + ' ' + - pciDevice.vendorId().toString(16) + ':' + pciDevice.deviceId().toString(16) + ' ' + - classData.className + ' IRQ: ' + vector + ' PIN: ' + pins[devicePin]; + const pins = ['dont use', 'A', 'B', 'C', 'D']; + + const info = `${address.bus.toString(16)}: ${address.slot.toString(16)}.${address.func} +${pciDevice.vendorId().toString(16)}: ${pciDevice.deviceId().toString(16)} +${classData.className} IRQ: ${vector} PIN: ${pins[devicePin]}`; debug(info); }); -function listPciDevices() { - var results = []; +const listPciDevices = () => { + const results = []; - pciManager.each(function(pciDevice) { - if (pciDevice.isBridge()) { - return; - } + pciManager.each((pciDevice) => { + if (pciDevice.isBridge()) return; - var address = pciDevice.address(); - var irqVector = pciDevice.getIRQVector(); - var classData = pciDevice.classData(); - var subsystemData = pciDevice.subsystemData(); + const address = pciDevice.address(); + const irqVector = pciDevice.getIRQVector(); + const classData = pciDevice.classData(); + const subsystemData = pciDevice.subsystemData(); - var devicePin = 0; - if (!pciDevice.isBridge()) { - devicePin = pciDevice.interruptPin(); - } + let devicePin = 0; + if (!pciDevice.isBridge()) devicePin = pciDevice.interruptPin(); - var irqObject = null; - if (null !== irqVector) { - irqObject = irqRange.irq(irqVector); - } + let irqObject = null; + if (irqVector !== null) irqObject = irqRange.irq(irqVector); - var bars = []; - for (var i = 0; i < 6; ++i) { - var bar = pciDevice.getBAR(i); - var barData = null; + const bars = []; + for (let i = 0; i < 6; ++i) { + const bar = pciDevice.getBAR(i); + let barData = null; - if (null !== bar) { + if (bar !== null) { barData = { type: bar.type, - resource: bar.resource + resource: bar.resource, }; } bars.push(barData); } - var pins = [null, 'A', 'B', 'C', 'D']; + const pins = [null, 'A', 'B', 'C', 'D']; results.push({ bus: address.bus, @@ -871,16 +744,16 @@ function listPciDevices() { vendorId: pciDevice.vendorId(), deviceId: pciDevice.deviceId(), className: classData.className, - subsystemData: subsystemData, - irqVector: irqVector, + subsystemData, + irqVector, pin: pins[devicePin], pciAccessor: pciDevice.pciAccessor, irq: irqObject, - bars: bars + bars, }); }); return results; -} +}; module.exports = listPciDevices; From 48551ddfd808817c8455a08365958b0025153f82 Mon Sep 17 00:00:00 2001 From: Face Kapow Date: Fri, 8 Jul 2016 14:32:45 -0400 Subject: [PATCH 04/22] lint & ES6 js/core/ps2, js/core/random, js/core/stdio, js/core/tty --- js/core/ps2/index.js | 15 ++-- js/core/random/entropy-source.js | 11 +-- js/core/random/index.js | 70 +++++----------- js/core/random/isaac-wrapper.js | 10 +-- js/core/random/js-random-source.js | 14 ++-- js/core/random/sources.js | 16 ++-- js/core/stdio/default.js | 30 +++---- js/core/stdio/interface.js | 41 ++++------ js/core/tty/index.js | 26 +++--- js/core/tty/line-editor.js | 50 +++++------- js/core/tty/printer.js | 77 +++++++---------- js/core/tty/terminal.js | 104 ++++++++++++----------- js/core/tty/vga.js | 127 +++++++++++++---------------- 13 files changed, 241 insertions(+), 350 deletions(-) diff --git a/js/core/ps2/index.js b/js/core/ps2/index.js index e72d9753b..2c607bead 100644 --- a/js/core/ps2/index.js +++ b/js/core/ps2/index.js @@ -13,19 +13,16 @@ // limitations under the License. 'use strict'; -var driverUtils = require('../driver-utils'); -var assert = require('assert'); -var typeutils = require('typeutils'); +const driverUtils = require('../driver-utils'); +const assert = require('assert'); +const typeutils = require('typeutils'); -exports.setKeyboardDriver = function(driver) { +exports.setKeyboardDriver = (driver) => { assert(typeutils.isFunction(driver.init)); assert(typeutils.isFunction(driver.reset)); - var irq = driverUtils.irq(1); - var ioPort = driverUtils.ioPort(0x60); - driver.init({ - irq: irq, - ioPort: ioPort + irq: driverUtils.irq(1), + ioPort: driverUtils.ioPort(0x60), }); }; diff --git a/js/core/random/entropy-source.js b/js/core/random/entropy-source.js index be7fff693..4887eb38b 100644 --- a/js/core/random/entropy-source.js +++ b/js/core/random/entropy-source.js @@ -15,23 +15,18 @@ 'use strict'; class EntropySource { - constructor(name) { - this._name = name || ''; + constructor(name = '') { + this._name = name; this.ongetbytes = null; } - getName() { return this._name; } - /** * Request randomness from this entropy source */ getBytes(u8, cb) { - if (!this.ongetbytes) { - throw new Error('entropy source was not initialized'); - } - + if (!this.ongetbytes) throw new Error('entropy source was not initialized'); this.ongetbytes(u8, cb); } } diff --git a/js/core/random/index.js b/js/core/random/index.js index b051e622a..57c3dd654 100644 --- a/js/core/random/index.js +++ b/js/core/random/index.js @@ -13,11 +13,11 @@ // limitations under the License. 'use strict'; -var isaac = require('./isaac-wrapper'); -var EntropySource = require('./entropy-source'); -var sources = require('./sources'); -var typeutils = require('typeutils'); -var getDefaultSource = sources.getDefaultSource; +const isaac = require('./isaac-wrapper'); +const EntropySource = require('./entropy-source'); +const sources = require('./sources'); +const typeutils = require('typeutils'); +const getDefaultSource = sources.getDefaultSource; require('./js-random-source'); exports.EntropySource = EntropySource; @@ -33,34 +33,20 @@ exports.addEntropySource = sources.addEntropySource; * @param {number|Uint8Array} value Number of bytes to request or buffer to fill * @param {function} cb Callback with the resulting Uint8Array buffer argument */ -exports.getTrueRandomValues = function(value, cb) { - var u8 = null; - if (typeutils.isNumber(value)) { - u8 = new Uint8Array(value); - } +exports.getTrueRandomValues = (value, cb) => { + let u8 = null; + if (typeutils.isNumber(value)) u8 = new Uint8Array(value); + if (value instanceof Uint8Array) u8 = value; - if (value instanceof Uint8Array) { - u8 = value; - } + if (!u8) throw new Error('getTrueRandomValues: argument 0 is not a number or Uint8Array'); + if (u8.length === 0) throw new Error('getTrueRandomValues: buffer length must be greater than 0'); - if (!u8) { - throw new Error('getTrueRandomValues: argument 0 is not a number or Uint8Array'); - } + if (!typeutils.isFunction(cb)) throw new Error('getTrueRandomValues: argument 1 is not a function'); // eslint-disable-line max-len - if (u8.length === 0) { - throw new Error('getTrueRandomValues: buffer length must be greater than 0'); - } + const defaultSource = getDefaultSource(); + if (!defaultSource) throw new Error('getTrueRandomValues: no entropy source available'); - if (!typeutils.isFunction(cb)) { - throw new Error('getTrueRandomValues: argument 1 is not a function'); - } - - var defaultSource = getDefaultSource(); - if (!defaultSource) { - throw new Error('getTrueRandomValues: no entropy source available'); - } - - defaultSource.getBytes(u8, function() { + defaultSource.getBytes(u8, () => { isaac.seed(u8); cb(u8); }); @@ -72,27 +58,15 @@ exports.getTrueRandomValues = function(value, cb) { * @param {number|Uint8Array} value Number of bytes to request or buffer to fill * @return {Uint8Array} Buffer filled with random data */ -exports.getRandomValues = function(value) { - var u8 = null; - if (typeutils.isNumber(value)) { - u8 = new Uint8Array(value); - } - - if (value instanceof Uint8Array) { - u8 = value; - } - - if (!u8) { - throw new Error('getRandomValues: argument 0 is not a number or Uint8Array'); - } +exports.getRandomValues = (value) => { + let u8 = null; + if (typeutils.isNumber(value)) u8 = new Uint8Array(value); + if (value instanceof Uint8Array) u8 = value; - if (u8.length === 0) { - throw new Error('getRandomValues: buffer length must be greater than 0'); - } + if (!u8) throw new Error('getRandomValues: argument 0 is not a number or Uint8Array'); + if (u8.length === 0) throw new Error('getRandomValues: buffer length must be greater than 0'); - for (var i = 0; i < u8.length; i++) { - u8[i] = isaac.getByte(); - } + for (let i = 0; i < u8.length; i++) u8[i] = isaac.getByte(); return u8; }; diff --git a/js/core/random/isaac-wrapper.js b/js/core/random/isaac-wrapper.js index 2f8ec0e08..c4ffb6474 100644 --- a/js/core/random/isaac-wrapper.js +++ b/js/core/random/isaac-wrapper.js @@ -14,7 +14,7 @@ 'use strict'; -var isaac = require('../../deps/isaac/isaac'); +const isaac = require('../../deps/isaac/isaac'); // isaac.js returns crazy numbers, both positive and negative. // This function is called on an isaac.rand() call, @@ -24,11 +24,7 @@ var isaac = require('../../deps/isaac/isaac'); // * 0 < n < 256 // This ensures the numbers are similar to the numbers // generated by VirtioRNG. -function isaacToUint8(n) { - return (n >>> 0) & 0xff; -} +const isaacToUint8 = n => (n >>> 0) & 0xff; exports.seed = isaac.seed; -exports.getByte = function() { - return isaacToUint8(isaac.rand()); -}; +exports.getByte = () => isaacToUint8(isaac.rand()); diff --git a/js/core/random/js-random-source.js b/js/core/random/js-random-source.js index cbf6c7585..b5fa27ab4 100644 --- a/js/core/random/js-random-source.js +++ b/js/core/random/js-random-source.js @@ -13,17 +13,15 @@ // limitations under the License. 'use strict'; -var isaac = require('./isaac-wrapper'); -var EntropySource = require('./entropy-source'); -var sources = require('./sources'); +const isaac = require('./isaac-wrapper'); +const EntropySource = require('./entropy-source'); +const sources = require('./sources'); // Low quality entropy source based on Math.random() seed // and isaac CSPRNG -var source = new EntropySource('js-random'); -source.ongetbytes = function(u8, cb) { - for (var i = 0; i < u8.length; i++) { - u8[i] = isaac.getByte(); - } +const source = new EntropySource('js-random'); +source.ongetbytes = (u8, cb) => { + for (let i = 0; i < u8.length; i++) u8[i] = isaac.getByte(); // eslint-disable-line no-param-reassign cb(); }; diff --git a/js/core/random/sources.js b/js/core/random/sources.js index 0c24b76a7..b112d6338 100644 --- a/js/core/random/sources.js +++ b/js/core/random/sources.js @@ -13,22 +13,20 @@ // limitations under the License. 'use strict'; -var isaac = require('./isaac-wrapper'); -var defaultSource = null; -var availableSources = Object.create(null); +const isaac = require('./isaac-wrapper'); +let defaultSource = null; +const availableSources = Object.create(null); -exports.addEntropySource = function(source) { +exports.addEntropySource = (source) => { availableSources[source.getName()] = source; - source.getBytes(new Uint8Array(8), function(u8) { + source.getBytes(new Uint8Array(8), (u8) => { isaac.seed(u8); - console.log('[random] using entropy source', source.getName()); + console.log(`[random] using entropy source ${source.getName()}`); }); // Set this source as the default one defaultSource = source; }; -exports.getDefaultSource = function() { - return defaultSource; -}; +exports.getDefaultSource = () => defaultSource; diff --git a/js/core/stdio/default.js b/js/core/stdio/default.js index f113d570a..86b1a8d23 100644 --- a/js/core/stdio/default.js +++ b/js/core/stdio/default.js @@ -14,18 +14,16 @@ 'use strict'; -var tty = require('../tty'); -var StdioInterface = require('./interface'); -var defaultStdio = new StdioInterface(); +const tty = require('../tty'); +const StdioInterface = require('./interface'); +const defaultStdio = new StdioInterface(); -var fgcolor = tty.color.WHITE; -var bgcolor = tty.color.BLACK; +let fgcolor = tty.color.WHITE; +let bgcolor = tty.color.BLACK; -defaultStdio.onwrite = function(text) { - tty.print(text, 1, fgcolor, bgcolor); -}; +defaultStdio.onwrite = text => tty.print(text, 1, fgcolor, bgcolor); -defaultStdio.onsetcolor = function(fg) { +defaultStdio.onsetcolor = (fg) => { if (!fg) { fgcolor = tty.color.WHITE; return; @@ -34,7 +32,7 @@ defaultStdio.onsetcolor = function(fg) { fgcolor = tty.color[String(fg).toUpperCase()]; }; -defaultStdio.onsetbackgroundcolor = function(bg) { +defaultStdio.onsetbackgroundcolor = (bg) => { if (!bg) { bgcolor = tty.color.BLACK; return; @@ -43,16 +41,10 @@ defaultStdio.onsetbackgroundcolor = function(bg) { bgcolor = tty.color[String(bg).toUpperCase()]; }; -defaultStdio.onread = function(cb) { - tty.read(cb); -}; +defaultStdio.onread = cb => tty.read(cb); -defaultStdio.onreadline = function(cb) { - tty.readLine(cb); -}; +defaultStdio.onreadline = cb => tty.readLine(cb); -defaultStdio.onwriteerror = function(error) { - tty.print(error, 1, tty.color.RED); -}; +defaultStdio.onwriteerror = error => tty.print(error, 1, tty.color.RED); module.exports = defaultStdio; diff --git a/js/core/stdio/interface.js b/js/core/stdio/interface.js index 605797921..08088822c 100644 --- a/js/core/stdio/interface.js +++ b/js/core/stdio/interface.js @@ -16,28 +16,20 @@ class StdioInterface { constructor() { - this.onread = function() {}; - this.onwrite = function() {}; - this.onwriteerror = function() {}; - this.onsetcolor = function() {}; - this.onsetbackgroundcolor = function() {}; + this.onread = () => {}; + this.onwrite = () => {}; + this.onwriteerror = () => {}; + this.onsetcolor = () => {}; + this.onsetbackgroundcolor = () => {}; } // stdout - write() { - var text = []; - for (var i = 0; i < arguments.length; i++) { - text[i] = String(arguments[i]); - } + write(...text) { this.onwrite(text.join(' ')); } - writeLine() { - var text = []; - for (var i = 0; i < arguments.length; i++) { - text[i] = String(arguments[i]); - } - this.onwrite(text.join(' ') + '\n'); + writeLine(...text) { + this.onwrite(`${text.join(' ')}\n`); } setColor(fg) { @@ -61,28 +53,25 @@ class StdioInterface { // Else, use onread. // Downside: no cusor moving or backspace. // TODO: Fix downside. - var text = ''; - this.onread(function addinput(char) { + let text = ''; + const addinput = (char) => { if (char !== '\n') { text += char; this.onread(addinput); } else { cb(text); } - }); + }; + this.onread(addinput); } } // stderr - writeError() { - if (typeof arguments[0] === 'string') { - var text = []; - for (var i = 0; i < arguments.length; i++) { - text[i] = arguments[i]; - } + writeError(...text) { + if (typeof text[0] === 'string') { this.onwriteerror(text.join(' ')); } else { - this.onwriteerror(arguments[0].stack); + this.onwriteerror(text[0].stack); } } } diff --git a/js/core/tty/index.js b/js/core/tty/index.js index 2581d36d7..6612b7cdf 100644 --- a/js/core/tty/index.js +++ b/js/core/tty/index.js @@ -15,22 +15,20 @@ 'use strict'; /* eslint-disable quotes */ -var terminal = require('./terminal'); -var assert = require('assert'); -var typeutils = require('typeutils'); +const terminal = require('./terminal'); +const { DARKGRAY, LIGHTGRAY, BLACK } = terminal.color; -var color = terminal.color; +terminal.print(` + _ _ _ + _ __ _ _ _ __ | |_(_)_ __ ___ ___ (_)___ + | '__| | | | '_ \\| __| | '_ \` _ \\ / _ \\ | / __| + | | | |_| | | | | |_| | | | | | | __/_ | \\__ \\ + |_| \\__,_|_| |_|\\__|_|_| |_| |_|\\___(_)/ |___/ + |__/ -terminal.print( - "\n _ _ _ \n" - + " _ __ _ _ _ __ | |_(_)_ __ ___ ___ (_)___\n" - + " | '__| | | | '_ \\| __| | '_ ` _ \\ / _ \\ | / __|\n" - + " | | | |_| | | | | |_| | | | | | | __/_ | \\__ \\\n" - + " |_| \\__,_|_| |_|\\__|_|_| |_| |_|\\___(_)/ |___/\n" - + " |__/\n\n"); +`); -terminal.print('\n', 1, color.DARKGRAY, color.BLACK); -terminal.print('# Welcome to ', 1, color.DARKGRAY, color.BLACK); -terminal.print('runtime.js\n\n', 1, color.LIGHTGRAY, color.BLACK); +terminal.print('\n# Welcome to ', 1, DARKGRAY, BLACK); +terminal.print('runtime.js\n\n', 1, LIGHTGRAY, BLACK); module.exports = terminal; diff --git a/js/core/tty/line-editor.js b/js/core/tty/line-editor.js index b1af3a0d0..1dee448a0 100644 --- a/js/core/tty/line-editor.js +++ b/js/core/tty/line-editor.js @@ -14,7 +14,7 @@ 'use strict'; -var printer = require('./printer'); +const printer = require('./printer'); class LineEditor { constructor() { @@ -29,27 +29,23 @@ class LineEditor { drawPrompt() { printer.print('$', 1, printer.color.YELLOW, printer.color.BLACK); printer.print(' ', 1, printer.color.WHITE, printer.color.BLACK); - }; + } drawCursor() { - var char = ' '; - if (this.inputPosition < this.inputText.length) { - char = this.inputText[this.inputPosition]; - } + let char = ' '; + if (this.inputPosition < this.inputText.length) char = this.inputText[this.inputPosition]; printer.print(char, 1, printer.color.WHITE, printer.color.LIGHTGREEN); printer.moveOffset(-1); - }; + } removeCursor() { - var char = ' '; - if (this.inputPosition < this.inputText.length) { - char = this.inputText[this.inputPosition]; - } + let char = ' '; + if (this.inputPosition < this.inputText.length) char = this.inputText[this.inputPosition]; printer.print(char, 1, printer.color.WHITE, printer.color.BLACK); printer.moveOffset(-1); - }; + } putChar(char) { this.removeCursor(); @@ -57,17 +53,15 @@ class LineEditor { this.inputText += char; printer.print(char); } else { - var rightSide = this.inputText.slice(this.inputPosition); + const rightSide = this.inputText.slice(this.inputPosition); this.inputText = this.inputText.slice(0, this.inputPosition) + char + rightSide; printer.print(char); - for (var i = 0; i < rightSide.length; ++i) { - printer.print(rightSide[i]); - } + for (const item of rightSide) printer.print(item); printer.moveOffset(-rightSide.length); } ++this.inputPosition; this.drawCursor(); - }; + } removeChar() { if (this.inputPosition > 0) { @@ -76,19 +70,17 @@ class LineEditor { this.inputText = this.inputText.slice(0, -1); printer.moveOffset(-1); } else { - var rightSide = this.inputText.slice(this.inputPosition); + const rightSide = this.inputText.slice(this.inputPosition); this.inputText = this.inputText.slice(0, this.inputPosition - 1) + rightSide; printer.moveOffset(-1); - for (var i = 0; i < rightSide.length; ++i) { - printer.print(rightSide[i]); - } + for (const item of rightSide) printer.print(item); printer.print(' '); printer.moveOffset(-rightSide.length - 1); } --this.inputPosition; this.drawCursor(); } - }; + } moveCursorLeft() { if (this.inputPosition > 0) { @@ -97,7 +89,7 @@ class LineEditor { printer.moveOffset(-1); this.drawCursor(); } - }; + } moveCursorRight() { if (this.inputPosition < this.inputText.length) { @@ -106,7 +98,7 @@ class LineEditor { printer.moveOffset(1); this.drawCursor(); } - }; + } clearInputBox() { while (this.inputPosition < this.inputText.length) { @@ -115,18 +107,18 @@ class LineEditor { while (this.inputPosition > 0) { this.removeChar(); } - }; + } setInputBox(text) { this.removeCursor(); this.clearInputBox(); - for (var i = 0; i < text.length; ++i) { - this.inputText += text[i]; - printer.print(text[i]); + for (const char of text) { + this.inputText += char; + printer.print(char); ++this.inputPosition; } this.drawCursor(); - }; + } } module.exports = LineEditor; diff --git a/js/core/tty/printer.js b/js/core/tty/printer.js index f8e36c2d3..3c216252f 100644 --- a/js/core/tty/printer.js +++ b/js/core/tty/printer.js @@ -13,53 +13,36 @@ // limitations under the License. 'use strict'; -var vga = require('./vga'); -var buffer = vga.allocBuffer(); +const vga = require('./vga'); +const buffer = vga.allocBuffer(); buffer.clear(vga.color.BLACK); -var posCurrent = 0; -var w = vga.WIDTH; -var h = vga.HEIGHT; +let posCurrent = 0; +const w = vga.WIDTH; +const h = vga.HEIGHT; -function refresh() { - vga.draw(buffer); -} +const refresh = () => vga.draw(buffer); -function scrollUp() { +const scrollUp = () => { buffer.scrollUp(vga.color.BLACK); posCurrent -= w; -} +}; refresh(); exports.color = vga.color; -exports.print = function(text, repeat, fg, bg) { +exports.print = (textOpt = '', repeat = 1, fg = vga.color.WHITE, bg = vga.color.BLACK) => { // fix issue #53 where non-strings (ints, etc...) would not get printed - text = String(text); - - repeat = repeat || 1; - - if (typeof fg === 'undefined') { - fg = vga.color.WHITE; - } + const text = String(textOpt); - if (typeof bg === 'undefined') { - bg = vga.color.BLACK; - } - - for (var j = 0; j < repeat; ++j) { - for (var i = 0, l = text.length; i < l; ++i) { - var c = text.charAt(i); - if ('\n' === c) { - posCurrent -= posCurrent % w - w; - if (posCurrent >= w * h) { - scrollUp(); - } + for (let j = 0; j < repeat; ++j) { + for (const c of text) { + if (c === '\n') { + posCurrent -= (posCurrent % w) - w; + if (posCurrent >= w * h) scrollUp(); } else { - if (posCurrent >= w * h) { - scrollUp(); - } + if (posCurrent >= w * h) scrollUp(); buffer.setOffset(posCurrent++, c, fg, bg); } } @@ -68,24 +51,22 @@ exports.print = function(text, repeat, fg, bg) { refresh(); }; -exports.moveOffset = function(offset) { - offset = offset | 0; - var newPos = posCurrent + offset; - if (newPos < 0) { - newPos = 0; - } +exports.moveOffset = (offsetOpt) => { + const offset = offsetOpt | 0; + let newPos = posCurrent + offset; + if (newPos < 0) newPos = 0; - if (newPos >= w * h) { - newPos = w * h - 1; - } + if (newPos >= w * h) newPos = (w * h) - 1; posCurrent = newPos; }; -exports.moveTo = function(x, y) { - if (x < 0) { x = 0; } - if (x >= w) { x = w - 1; } - if (y < 0) { y = 0; } - if (y >= h) { y = h - 1; } - posCurrent = y * w + x; +exports.moveTo = (xOpt, yOpt) => { + let x = xOpt; + let y = yOpt; + if (x < 0) x = 0; + if (x >= w) x = w - 1; + if (y < 0) y = 0; + if (y >= h) y = h - 1; + posCurrent = (y * w) + x; }; diff --git a/js/core/tty/terminal.js b/js/core/tty/terminal.js index a68b5c41d..87e5f8ce4 100644 --- a/js/core/tty/terminal.js +++ b/js/core/tty/terminal.js @@ -13,82 +13,78 @@ // limitations under the License. 'use strict'; -var keyboard = require('../keyboard'); -var printer = require('./printer'); -var LineEditor = require('./line-editor'); +const keyboard = require('../keyboard'); +const printer = require('./printer'); +const LineEditor = require('./line-editor'); exports.color = printer.color; exports.print = printer.print; exports.moveOffset = printer.moveOffset; exports.moveTo = printer.moveTo; -var isReading = false; +let isReading = false; -exports.read = function(cb) { - if (isReading) { - throw new Error('nested terminal read is not allowed'); - } +exports.read = (cb) => { + if (isReading) throw new Error('nested terminal read is not allowed'); - var editor = new LineEditor(); + const editor = new LineEditor(); isReading = true; - function addinput(keyinfo) { + const addinput = (keyinfo) => { switch (keyinfo.type) { - case 'character': - printer.print(keyinfo.character); - cb(keyinfo.character); - keyboard.onKeydown.remove(addinput); - break; - case 'backspace': - break; - case 'enter': - printer.print('\n'); - isReading = false; - setImmediate(function() { - cb('\n'); - }); - keyboard.onKeydown.remove(addinput); - break; + case 'character': + printer.print(keyinfo.character); + cb(keyinfo.character); + keyboard.onKeydown.remove(addinput); + break; + case 'backspace': + break; + case 'enter': + printer.print('\n'); + isReading = false; + setImmediate(() => cb('\n')); + keyboard.onKeydown.remove(addinput); + break; + default: + break; } - } + }; keyboard.onKeydown.add(addinput); editor.drawCursor(); }; -exports.readLine = function(cb) { - if (isReading) { - throw new Error('nested terminal read is not allowed'); - } +exports.readLine = (cb) => { + if (isReading) throw new Error('nested terminal read is not allowed'); - var editor = new LineEditor(); + const editor = new LineEditor(); isReading = true; - function addinput(keyinfo) { + const addinput = (keyinfo) => { switch (keyinfo.type) { - case 'kpleft': - editor.moveCursorLeft(); - break; - case 'kpright': - editor.moveCursorRight(); - break; - case 'character': - editor.putChar(keyinfo.character); - break; - case 'backspace': - editor.removeChar(); - break; - case 'enter': - editor.removeCursor(); - printer.print('\n'); - isReading = false; - setImmediate(function() { - cb(editor.getText()); - }); - keyboard.onKeydown.remove(addinput); - break; + case 'kpleft': + editor.moveCursorLeft(); + break; + case 'kpright': + editor.moveCursorRight(); + break; + case 'character': + editor.putChar(keyinfo.character); + break; + case 'backspace': + editor.removeChar(); + break; + case 'enter': + editor.removeCursor(); + printer.print('\n'); + isReading = false; + setImmediate(() => cb(editor.getText())); + keyboard.onKeydown.remove(addinput); + break; + default: + break; } - } + }; keyboard.onKeydown.add(addinput); editor.drawCursor(); diff --git a/js/core/tty/vga.js b/js/core/tty/vga.js index a63d6b5cc..273af6896 100644 --- a/js/core/tty/vga.js +++ b/js/core/tty/vga.js @@ -13,21 +13,21 @@ // limitations under the License. 'use strict'; -var driverUtils = require('../driver-utils'); +const driverUtils = require('../driver-utils'); // Take ownership of the display __SYSCALL.stopVideoLog(); -var w = 80; -var h = 25; -var len = w * h; -var buf = driverUtils.physicalMemory(0xb8000, len * 2).buffer(); -var b = new Uint8Array(buf); +const w = 80; +const h = 25; +const len = w * h; +const buf = driverUtils.physicalMemory(0xb8000, len * 2).buffer(); +const b = new Uint8Array(buf); exports.WIDTH = w; exports.HEIGHT = h; -var color = { +const color = { BLACK: 0, BLUE: 1, GREEN: 2, @@ -43,89 +43,74 @@ var color = { LIGHTRED: 12, LIGHTMAGENTA: 13, YELLOW: 14, - WHITE: 15 + WHITE: 15, }; exports.color = color; -function getColor(fg, bg) { - return (((bg & 0xF) << 4) + (fg & 0xF)) >>> 0; -} - -function setCharXY(u8, x, y, char, fg, bg) { - if (x < 0 || x >= w) { - throw new Error('vga error: x is out of bounds'); - } - - if (y < 0 || y >= h) { - throw new Error('vga error: y is out of bounds'); - } - - var offset = y * w + x; - setCharOffset(u8, offset, char, fg >>> 0, bg >>> 0); -} +const getColor = (fg, bg) => (((bg & 0xF) << 4) + (fg & 0xF)) >>> 0; -function setCharOffset(u8, offset, char, fg, bg) { - if (offset < 0 || offset >= w * h) { - throw new Error('vga error: offset is out of bounds'); - } +const setCharOffset = (u8, offset, char, fg, bg) => { + if (offset < 0 || offset >= w * h) throw new Error('vga error: offset is out of bounds'); + /* eslint-disable no-param-reassign */ u8[offset * 2] = char.charCodeAt(0); - u8[offset * 2 + 1] = getColor(fg, bg); -} + u8[(offset * 2) + 1] = getColor(fg, bg); + /* eslint-enable no-param-reassign */ +}; -function VGABuffer() { - this.b = new Uint8Array(len * 2); -} +const setCharXY = (u8, x, y, char, fg, bg) => { + if (x < 0 || x >= w) throw new Error('vga error: x is out of bounds'); -function testInstance(obj) { - if (!(obj instanceof VGABuffer)) { - throw new Error('VGABuffer instance required'); - } -} + if (y < 0 || y >= h) throw new Error('vga error: y is out of bounds'); -function testColor(value, def) { - if ((value >>> 0) !== value) { - throw new Error('invalid color value'); - } -} - -VGABuffer.prototype.setXY = function(x, y, char, fg, bg) { - testInstance(this); - testColor(fg); - testColor(bg); - setCharXY(this.b, x, y, String(char), fg, bg); + const offset = (y * w) + x; + setCharOffset(u8, offset, char, fg >>> 0, bg >>> 0); }; -VGABuffer.prototype.setOffset = function(offset, char, fg, bg) { - testInstance(this); - testColor(fg); - testColor(bg); - setCharOffset(this.b, offset, String(char), fg, bg); -}; +// declare it up here, and define it below VGABuffer, a workaround for no-use-before-define +let testInstance; -VGABuffer.prototype.clear = function(bg) { - testInstance(this); - testColor(bg); - for (var i = 0; i < w * h; ++i) { - setCharOffset(this.b, i, ' ', bg, bg); - } +const testColor = (value) => { + if ((value >>> 0) !== value) throw new Error('invalid color value'); }; -VGABuffer.prototype.scrollUp = function(bg) { - testInstance(this); - testColor(bg); - this.b.set(this.b.subarray(w * 2, w * h * 2)); - for (var t = 0; t < w; ++t) { - setCharXY(this.b, t, h - 1, ' ', bg, bg); +class VGABuffer { + constructor() { + this.b = new Uint8Array(len * 2); + } + setXY(x, y, char, fg, bg) { + testInstance(this); + testColor(fg); + testColor(bg); + setCharXY(this.b, x, y, String(char), fg, bg); } + setOffset(offset, char, fg, bg) { + testInstance(this); + testColor(fg); + testColor(bg); + setCharOffset(this.b, offset, String(char), fg, bg); + } + clear(bg) { + testInstance(this); + testColor(bg); + for (let i = 0; i < w * h; ++i) setCharOffset(this.b, i, ' ', bg, bg); + } + scrollUp(bg) { + testInstance(this); + testColor(bg); + this.b.set(this.b.subarray(w * 2, w * h * 2)); + for (let t = 0; t < w; ++t) setCharXY(this.b, t, h - 1, ' ', bg, bg); + } +} + +testInstance = (obj) => { + if (!(obj instanceof VGABuffer)) throw new Error('VGABuffer instance required'); }; -exports.draw = function(drawbuf) { +exports.draw = (drawbuf) => { testInstance(drawbuf); b.set(drawbuf.b); }; -exports.allocBuffer = function() { - return new VGABuffer(); -}; +exports.allocBuffer = () => new VGABuffer(); From 3581837a4d53d2fc7d2d21915328445a020e1cd1 Mon Sep 17 00:00:00 2001 From: facekapow Date: Fri, 8 Jul 2016 15:31:54 -0400 Subject: [PATCH 05/22] Add a CONTRIBUTING.md --- CONTRIBUTING.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..bd7d46b31 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,25 @@ +# Contributing to runtime.js + +Firstly, thanks for deciding to contribute! :+1: + +## Got an issue? + + * Make sure the issue isn't already reported by checking in [Issues](https://github.com/runtimejs/runtime/issues). + * Include the version of the kernel and JavaScript library in the issue description. + +## Something to improve or add? + +### Kernel change (C++) + +Make sure that: + * the kernel is compilable by running `scons` (more information [here](https://github.com/runtimejs/runtime/wiki/Build)). + * the system can still boot up normally. + * the new/fixed/changed feature/bug works (of course, :smile:). + +### Library change (JavaScript) + +Make sure that: + * you run `npm run lint` at the root of repository (you'll also need to have installed dependencies beforehand with `npm install`) and get rid of any lint. + * the system can still boot up normally. + * the new/fixed/changed feature/bug works. + * the code is written in as much ES6 as possible and it conforms to the style guide found [here](https://github.com/airbnb/javascript) (with a [few exceptions](https://github.com/runtimejs/runtime/docs/code-style-exceptions.md)). From fa765755fa883bca49995d7dd2496cd68f1f6ff1 Mon Sep 17 00:00:00 2001 From: facekapow Date: Fri, 8 Jul 2016 16:03:00 -0400 Subject: [PATCH 06/22] Create code-style-exceptions.md --- docs/code-style-exceptions.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 docs/code-style-exceptions.md diff --git a/docs/code-style-exceptions.md b/docs/code-style-exceptions.md new file mode 100644 index 000000000..24f9270b9 --- /dev/null +++ b/docs/code-style-exceptions.md @@ -0,0 +1,32 @@ +# Code Style Exceptions + +The JavaScript code adheres to the style guide found [here](https://github.com/airbnb/javascript), but with some exceptions: + +## No ES6 Modules + +V8 support for native ES6 modules is under development, so for now use `require` like you would in Node. +All other ES6 features (classes, destructuring, default parameters, etc.) can be used freely. + +## Using `for-of` and `for-in` + +You're free to use `for-of` and `for-in` as necessary, however it's better to use `for (let value of object)` for values and `for (let key of Object.keys(object))` for keys. +You can still use `for-in`, just be sure you know [the catch](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in#Iterating_over_own_properties_only) when using it. + +## Using 'dangling' underscores + +You *can* use 'dangling' underscores to denote a private member on an object or class. +Some APIs were written before this style was adopted which use underscores for private members and probably won't be changed for compatability. +However, for any new APIs, it'd be prefered to use a [`Symbol`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol) instead, like: + +```js +const somePrivateVarName = Symbol('somePrivateVarName'); + +class Demo { + constructor() { + this[somePrivateVarName] = 'my value'; + } + getMyPrivateVar() { + return this[somePrivateVarName]; + } +} +``` From a7d0f73f293fb498217a04a5f843796668b3ad54 Mon Sep 17 00:00:00 2001 From: facekapow Date: Fri, 8 Jul 2016 16:18:06 -0400 Subject: [PATCH 07/22] Add feature request section, update link to code style exceptions --- CONTRIBUTING.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bd7d46b31..f6b97c6ed 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,8 +6,15 @@ Firstly, thanks for deciding to contribute! :+1: * Make sure the issue isn't already reported by checking in [Issues](https://github.com/runtimejs/runtime/issues). * Include the version of the kernel and JavaScript library in the issue description. + * Include a description of what happens or what the issue/bug does and what the expected behavior is. -## Something to improve or add? +## Cool feature request? + + * Make sure the feature isn't already request by checking in [Issues](https://github.com/runtimejs/runtime/issues). + * Include good reasons for why you think it should be added and why it'd be a good feature. + * If possible, include resources for anyone planning to add the feature. + +## Something to improve, add, or fix? ### Kernel change (C++) @@ -22,4 +29,4 @@ Make sure that: * you run `npm run lint` at the root of repository (you'll also need to have installed dependencies beforehand with `npm install`) and get rid of any lint. * the system can still boot up normally. * the new/fixed/changed feature/bug works. - * the code is written in as much ES6 as possible and it conforms to the style guide found [here](https://github.com/airbnb/javascript) (with a [few exceptions](https://github.com/runtimejs/runtime/docs/code-style-exceptions.md)). + * the code is written in as much ES6 as possible and it conforms to the style guide found [here](https://github.com/airbnb/javascript) (with a [few exceptions](docs/code-style-exceptions.md)). From a876725d4c300d7ccd2587a1164e7cf4cd9bb8c2 Mon Sep 17 00:00:00 2001 From: facekapow Date: Fri, 8 Jul 2016 16:35:24 -0400 Subject: [PATCH 08/22] Fix typo, add a note, add some extra wording --- CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f6b97c6ed..dbe86bf20 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,9 +10,9 @@ Firstly, thanks for deciding to contribute! :+1: ## Cool feature request? - * Make sure the feature isn't already request by checking in [Issues](https://github.com/runtimejs/runtime/issues). + * Make sure the feature isn't already requested by checking in [Issues](https://github.com/runtimejs/runtime/issues). * Include good reasons for why you think it should be added and why it'd be a good feature. - * If possible, include resources for anyone planning to add the feature. + * If possible, include resources (links, examples, etc.) for anyone planning to add the feature. ## Something to improve, add, or fix? @@ -26,7 +26,7 @@ Make sure that: ### Library change (JavaScript) Make sure that: - * you run `npm run lint` at the root of repository (you'll also need to have installed dependencies beforehand with `npm install`) and get rid of any lint. + * you run `npm run lint` at the root of repository (you'll also need to have installed dependencies beforehand with `npm install`) and get rid of any lint before commiting. * the system can still boot up normally. * the new/fixed/changed feature/bug works. * the code is written in as much ES6 as possible and it conforms to the style guide found [here](https://github.com/airbnb/javascript) (with a [few exceptions](docs/code-style-exceptions.md)). From 9e6116484e48ce0926cb1dd6fa1225223bd490a5 Mon Sep 17 00:00:00 2001 From: Face Kapow Date: Sat, 9 Jul 2016 07:44:21 -0400 Subject: [PATCH 09/22] js/driver/ps2, js/driver/virtio/*.js, ignore consistent-return --- .eslintrc | 2 +- js/driver/ps2/keyboard.js | 137 +++++++++++----------- js/driver/virtio/device.js | 225 ++++++++++++++++--------------------- js/driver/virtio/index.js | 31 ++--- js/driver/virtio/net.js | 123 +++++++++----------- js/driver/virtio/rng.js | 55 ++++----- 6 files changed, 253 insertions(+), 320 deletions(-) diff --git a/.eslintrc b/.eslintrc index 171b21fb2..89c127ce2 100644 --- a/.eslintrc +++ b/.eslintrc @@ -21,7 +21,7 @@ rules: tabWidth: 2 ignoreComments: true ignoreUrls: true - consistent-return: 1 + consistent-return: 0 no-underscore-dangle: 0 global-require: 0 diff --git a/js/driver/ps2/keyboard.js b/js/driver/ps2/keyboard.js index 75cdc19a0..6b5807811 100644 --- a/js/driver/ps2/keyboard.js +++ b/js/driver/ps2/keyboard.js @@ -14,10 +14,10 @@ 'use strict'; -var runtime = require('../../core'); +const runtime = require('../../core'); -/* eslint-disable no-multi-spaces */ -var controlKeys = [ +/* eslint-disable no-multi-spaces, max-len */ +const controlKeys = [ /* 0x00 */ 0, 'escape', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'backspace', 'tab', /* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'enter', 'leftctrl', 0, 0, /* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'leftshift', 0, 0, 0, 0, 0, @@ -33,35 +33,35 @@ var controlKeys = [ /* 0xC0 */ 0, 0, 0, 0, 0, 0, 0, 'home', 'up', 'pageup', 0, 'left', 0, 'right', 0, 'end', /* 0xD0 */ 'down', 'pagedown', 'insert', 'del', 0, 0, 0, 0, 0, 0, 0, 'leftsup', 'rightsup', 'menu', 0, 0, /* 0xE0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 0xF0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + /* 0xF0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; -var keymapNormal = [ +const keymapNormal = [ '', '', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', '', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', '', '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', '', '', '', ' ', '', '', '', '', '', '', '', '', '', '', '', '', '', '', - '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ]; -var keymapShift = [ +const keymapShift = [ '', '', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '', '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', '', 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', '', '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', '', '', '', ' ', '', '', '', '', '', '', '', '', '', '', - '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ]; -var keymapCaps = [ +const keymapCaps = [ '', '', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '', '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '[', ']', '\n', '', 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', '\'', '`', '', '\\', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', ',', '.', '/', '', '', '', ' ', '', '', '', '', '', '', '', '', '', '', - '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ]; -/* eslint-enable no-multi-spaces */ +/* eslint-enable no-multi-spaces, max-len */ -var statuses = { +const statuses = { leftshift: false, rightshift: false, leftctrl: false, @@ -70,19 +70,18 @@ var statuses = { rightalt: false, capslock: false, numlock: false, - scrllock: false + scrllock: false, }; -function keyEvent(code, isPressed) { - var cmd = controlKeys[code & 0xFF]; - var character = ''; +const keyEvent = (codeOpt, isPressed) => { + let code = codeOpt; + let cmd = controlKeys[code & 0xFF]; + let character = ''; code &= 0x7F; - if (0 === cmd) { - cmd = controlKeys[code]; - } + if (cmd === 0) cmd = controlKeys[code]; - if (0 === cmd) { + if (cmd === 0) { cmd = 'character'; if (statuses.leftshift || statuses.rightshift) { character = keymapShift[code]; @@ -95,48 +94,44 @@ function keyEvent(code, isPressed) { } } else { switch (cmd) { - case 'leftalt': - statuses.leftalt = isPressed; - break; - case 'rightalt': - statuses.rightalt = isPressed; - break; - case 'leftctrl': - statuses.leftctrl = isPressed; - break; - case 'rightctrl': - statuses.rightctrl = isPressed; - break; - case 'leftshift': - statuses.leftshift = isPressed; - break; - case 'rightshift': - statuses.rightshift = isPressed; - break; - case 'capslock': - if (isPressed) { - statuses.capslock = !statuses.capslock; - } - break; - case 'numlock': - if (isPressed) { - statuses.numlock = !statuses.numlock; - } - break; - case 'scrllock': - if (isPressed) { - statuses.scrllock = !statuses.scrllock; - } - break; + case 'leftalt': + statuses.leftalt = isPressed; + break; + case 'rightalt': + statuses.rightalt = isPressed; + break; + case 'leftctrl': + statuses.leftctrl = isPressed; + break; + case 'rightctrl': + statuses.rightctrl = isPressed; + break; + case 'leftshift': + statuses.leftshift = isPressed; + break; + case 'rightshift': + statuses.rightshift = isPressed; + break; + case 'capslock': + if (isPressed) statuses.capslock = !statuses.capslock; + break; + case 'numlock': + if (isPressed) statuses.numlock = !statuses.numlock; + break; + case 'scrllock': + if (isPressed) statuses.scrllock = !statuses.scrllock; + break; + default: + break; } } - var keyinfo = { + const keyinfo = { type: cmd, - character: character, - alt: (statuses.leftalt || statuses.rightalt), + character, + alt: statuses.leftalt || statuses.rightalt, shift: statuses.leftshift || statuses.rightshift, - ctrl: statuses.leftctrl || statuses.rightctrl + ctrl: statuses.leftctrl || statuses.rightctrl, }; if (isPressed) { @@ -144,28 +139,28 @@ function keyEvent(code, isPressed) { } else { runtime.keyboard.onKeyup.dispatch(keyinfo); } -} +}; -var driver = { - init: function(device) { - var irq = device.irq; - var port = device.ioPort; +const driver = { + init(device) { + const irq = device.irq; + const port = device.ioPort; - function init() { - var v1 = port.read8(); - var v2 = 0; + const init = () => { + let v1 = port.read8(); + let v2 = 0; while (v1 !== v2) { v2 = v1; v1 = port.read8(); } - } + }; - var escaped = false; + let escaped = false; - irq.on(function() { - var code = port.read8(); + irq.on(() => { + const code = port.read8(); - if (0xe0 === code) { + if (code === 0xe0) { escaped = true; } else { if (code & 0x80) { @@ -188,7 +183,7 @@ var driver = { init(); }, - reset: function() {} + reset() {}, }; runtime.ps2.setKeyboardDriver(driver); diff --git a/js/driver/virtio/device.js b/js/driver/virtio/device.js index ee10173fe..281afa353 100644 --- a/js/driver/virtio/device.js +++ b/js/driver/virtio/device.js @@ -13,144 +13,115 @@ // limitations under the License. 'use strict'; -var VRing = require('./vring'); - -function VirtioDevice(deviceType, ioSpace) { - this.mem = __SYSCALL.allocDMA(); - this.io = (function(ioSpaceResource) { - var ioPorts = { - // Common - DEVICE_FEATURES: 0x00, // 32 bit r - GUEST_FEATURES: 0x04, // 32 bit r+w - QUEUE_ADDRESS: 0x08, // 32 bit r+w - QUEUE_SIZE: 0x0c, // 16 bit r - QUEUE_SELECT: 0x0e, // 16 bit r+w - QUEUE_NOTIFY: 0x10, // 16 bit r+w - DEVICE_STATUS: 0x12, // 8 bit r+w - ISR_STATUS: 0x13 // 8 bit r - }; - - if ('net' === deviceType) { - // Network card - ioPorts.NETWORK_DEVICE_MAC0 = 0x14; // 8 bit r - ioPorts.NETWORK_DEVICE_MAC1 = 0x15; // 8 bit r - ioPorts.NETWORK_DEVICE_MAC2 = 0x16; // 8 bit r - ioPorts.NETWORK_DEVICE_MAC3 = 0x17; // 8 bit r - ioPorts.NETWORK_DEVICE_MAC4 = 0x18; // 8 bit r - ioPorts.NETWORK_DEVICE_MAC5 = 0x19; // 8 bit r - ioPorts.NETWORK_DEVICE_STATUS = 0x1A; // 16 bit r - } - - var ports = {}; - for (var portName in ioPorts) { - if (!ioPorts.hasOwnProperty(portName)) { - continue; +const VRing = require('./vring'); + +const DEVICE_STATUS_RESET = 0; +const DEVICE_STATUS_ACKNOWLEDGE = 1; +const DEVICE_STATUS_DRIVER = 2; +const DEVICE_STATUS_DRIVER_OK = 4; + +class VirtioDevice { + constructor(deviceType, ioSpace) { + this.mem = __SYSCALL.allocDMA(); + this.io = ((ioSpaceResource) => { + const ioPorts = { + // Common + DEVICE_FEATURES: 0x00, // 32 bit r + GUEST_FEATURES: 0x04, // 32 bit r+w + QUEUE_ADDRESS: 0x08, // 32 bit r+w + QUEUE_SIZE: 0x0c, // 16 bit r + QUEUE_SELECT: 0x0e, // 16 bit r+w + QUEUE_NOTIFY: 0x10, // 16 bit r+w + DEVICE_STATUS: 0x12, // 8 bit r+w + ISR_STATUS: 0x13, // 8 bit r + }; + + if (deviceType === 'net') { + // Network card + ioPorts.NETWORK_DEVICE_MAC0 = 0x14; // 8 bit r + ioPorts.NETWORK_DEVICE_MAC1 = 0x15; // 8 bit r + ioPorts.NETWORK_DEVICE_MAC2 = 0x16; // 8 bit r + ioPorts.NETWORK_DEVICE_MAC3 = 0x17; // 8 bit r + ioPorts.NETWORK_DEVICE_MAC4 = 0x18; // 8 bit r + ioPorts.NETWORK_DEVICE_MAC5 = 0x19; // 8 bit r + ioPorts.NETWORK_DEVICE_STATUS = 0x1A; // 16 bit r } - var portOffset = ioPorts[portName]; - ports[portName] = ioSpaceResource.offsetPort(portOffset); - } - - return ports; - })(ioSpace); - this.nextRingOffset = 0; -} + const ports = {}; + for (const portName of Object.keys(ioPorts)) { + const portOffset = ioPorts[portName]; + ports[portName] = ioSpaceResource.offsetPort(portOffset); + } -VirtioDevice.prototype.readDeviceFeatures = function(features) { - var deviceFeatures = this.io.DEVICE_FEATURES.read32(); - var result = {}; + return ports; + })(ioSpace); + this.nextRingOffset = 0; + } + readDeviceFeatures(features) { + const deviceFeatures = this.io.DEVICE_FEATURES.read32(); + const result = {}; - for (var feature in features) { - if (!features.hasOwnProperty(feature)) { - continue; + for (const feature of Object.keys(features)) { + const mask = 1 << features[feature]; + if (deviceFeatures & mask) result[feature] = true; } - var mask = 1 << features[feature]; - - if (deviceFeatures & mask) { - result[feature] = true; - } + return result; } + writeGuestFeatures(features, driverFeatures, deviceFeatures) { + let value = 0; - return result; -}; - -VirtioDevice.prototype.writeGuestFeatures = function(features, driverFeatures, deviceFeatures) { - var value = 0; - - for (var feature in features) { - if (!features.hasOwnProperty(feature)) { - continue; - } + for (const feature of Object.keys(features)) { + if (!driverFeatures[feature]) continue; + if (!deviceFeatures[feature]) return false; // Device doesn't support required feature - if (!driverFeatures[feature]) { - continue; + const mask = 1 << features[feature]; + value |= mask; } - if (!deviceFeatures[feature]) { - // Device doesn't support required feature - return false; - } - - var mask = 1 << features[feature]; - value |= mask; + this.io.GUEST_FEATURES.write32(value >>> 0); + return true; } - - this.io.GUEST_FEATURES.write32(value >>> 0); - return true; -}; - -VirtioDevice.prototype.queueSetup = function(queueIndex) { - this.io.QUEUE_SELECT.write16(queueIndex >>> 0); - var size = this.io.QUEUE_SIZE.read16(); - var ring = new VRing(this.mem, this.nextRingOffset, size); - this.nextRingOffset += ring.size; - this.io.QUEUE_ADDRESS.write32(ring.address >>> 12); - return ring; -}; - -VirtioDevice.prototype.queueNotify = function(queueIndex) { - return this.io.QUEUE_NOTIFY.write16(queueIndex >>> 0); -}; - -var DEVICE_STATUS_RESET = 0; -var DEVICE_STATUS_ACKNOWLEDGE = 1; -var DEVICE_STATUS_DRIVER = 2; -var DEVICE_STATUS_DRIVER_OK = 4; - -VirtioDevice.prototype.setDriverAck = function() { - this.io.DEVICE_STATUS.write8(DEVICE_STATUS_ACKNOWLEDGE); - this.io.DEVICE_STATUS.write8(DEVICE_STATUS_ACKNOWLEDGE | DEVICE_STATUS_DRIVER); -}; - -VirtioDevice.prototype.setDriverReady = function() { - return this.io.DEVICE_STATUS.write8(DEVICE_STATUS_ACKNOWLEDGE | - DEVICE_STATUS_DRIVER | DEVICE_STATUS_DRIVER_OK); -}; - -VirtioDevice.prototype.resetDevice = function() { - return this.io.DEVICE_STATUS.write8(DEVICE_STATUS_RESET); -}; - -VirtioDevice.prototype.hasPendingIRQ = function() { - return !!(1 & this.io.ISR_STATUS.read8()); -}; - -// [network device] -VirtioDevice.prototype.netReadHWAddress = function() { - return [ - this.io.NETWORK_DEVICE_MAC0.read8(), - this.io.NETWORK_DEVICE_MAC1.read8(), - this.io.NETWORK_DEVICE_MAC2.read8(), - this.io.NETWORK_DEVICE_MAC3.read8(), - this.io.NETWORK_DEVICE_MAC4.read8(), - this.io.NETWORK_DEVICE_MAC5.read8() - ]; -}; - -// [network device] -VirtioDevice.prototype.netReadStatus = function() { - return !!(1 & this.io.NETWORK_DEVICE_STATUS.read16()); -}; + queueSetup(queueIndex) { + this.io.QUEUE_SELECT.write16(queueIndex >>> 0); + const size = this.io.QUEUE_SIZE.read16(); + const ring = new VRing(this.mem, this.nextRingOffset, size); + this.nextRingOffset += ring.size; + this.io.QUEUE_ADDRESS.write32(ring.address >>> 12); + return ring; + } + queueNotify(queueIndex) { + return this.io.QUEUE_NOTIFY.write16(queueIndex >>> 0); + } + setDriverAck() { + this.io.DEVICE_STATUS.write8(DEVICE_STATUS_ACKNOWLEDGE); + this.io.DEVICE_STATUS.write8(DEVICE_STATUS_ACKNOWLEDGE | DEVICE_STATUS_DRIVER); + } + setDriverReady() { + return this.io.DEVICE_STATUS.write8(DEVICE_STATUS_ACKNOWLEDGE | + DEVICE_STATUS_DRIVER | DEVICE_STATUS_DRIVER_OK); + } + resetDevice() { + return this.io.DEVICE_STATUS.write8(DEVICE_STATUS_RESET); + } + hasPendingIRQ() { + return !!(1 & this.io.ISR_STATUS.read8()); + } + // [network device] + netReadHWAddress() { + return [ + this.io.NETWORK_DEVICE_MAC0.read8(), + this.io.NETWORK_DEVICE_MAC1.read8(), + this.io.NETWORK_DEVICE_MAC2.read8(), + this.io.NETWORK_DEVICE_MAC3.read8(), + this.io.NETWORK_DEVICE_MAC4.read8(), + this.io.NETWORK_DEVICE_MAC5.read8(), + ]; + } + // [network device] + netReadStatus() { + return !!(1 & this.io.NETWORK_DEVICE_STATUS.read16()); + } +} module.exports = VirtioDevice; diff --git a/js/driver/virtio/index.js b/js/driver/virtio/index.js index 5bc50ac40..d09c6d2ae 100644 --- a/js/driver/virtio/index.js +++ b/js/driver/virtio/index.js @@ -13,31 +13,24 @@ // limitations under the License. 'use strict'; -var virtioNet = require('./net'); -var virtioRNG = require('./rng'); -var VIRTIO_SUBSYSTEM_NETWORK = 1; -var VIRTIO_SUBSYSTEM_RNG = 4; -var runtime = require('../../core'); +const virtioNet = require('./net'); +const virtioRNG = require('./rng'); +const VIRTIO_SUBSYSTEM_NETWORK = 1; +const VIRTIO_SUBSYSTEM_RNG = 4; +const runtime = require('../../core'); -var driver = { - init: function(pciDevice) { - var subsystemId = pciDevice.subsystem.subsystemId; +const driver = { + init(pciDevice) { + const subsystemId = pciDevice.subsystem.subsystemId; - if (subsystemId === VIRTIO_SUBSYSTEM_NETWORK) { - return virtioNet(pciDevice); - } - - if (subsystemId === VIRTIO_SUBSYSTEM_RNG) { - return virtioRNG(pciDevice); - } + if (subsystemId === VIRTIO_SUBSYSTEM_NETWORK) return virtioNet(pciDevice); + if (subsystemId === VIRTIO_SUBSYSTEM_RNG) return virtioRNG(pciDevice); debug(`[virtio] unknown virtio device (subsystem id ${subsystemId})`); }, - reset: function(pciDevice) {} + reset() {}, }; -function testDeviceId(deviceId) { - return deviceId >= 0x1000 && deviceId <= 0x103f; -} +const testDeviceId = deviceId => deviceId >= 0x1000 && deviceId <= 0x103f; runtime.pci.addDriver(0x1af4, testDeviceId, driver); diff --git a/js/driver/virtio/net.js b/js/driver/virtio/net.js index 9fde71530..8a8df2386 100644 --- a/js/driver/virtio/net.js +++ b/js/driver/virtio/net.js @@ -13,42 +13,38 @@ // limitations under the License. 'use strict'; -var VirtioDevice = require('./device'); -var runtime = require('../../core'); -var MACAddress = runtime.net.MACAddress; -var Interface = runtime.net.Interface; - -var virtioHeader = (function() { - var OFFSET_FLAGS = 0; - var OFFSET_GSO_TYPE = 1; - var OFFSET_HDR_LEN = 2; - var OFFSET_GSO_SIZE = 4; - var OFFSET_CSUM_START = 6; - var OFFSET_CSUM_OFFSET = 8; - var optsEmpty = {}; - var offset = 0; - - function writeVirtioHeader(view, opts) { - opts = opts || optsEmpty; - view.setUint8(offset + OFFSET_FLAGS, opts.flags >>> 0); - view.setUint8(offset + OFFSET_GSO_TYPE, opts.gsoType >>> 0); - // view.setUint16(offset + OFFSET_HDR_LEN, opts.hdrLen >>> 0, true); - // view.setUint16(offset + OFFSET_GSO_SIZE, opts.gsoSize >>> 0, true); - view.setUint16(offset + OFFSET_CSUM_START, opts.csumStart >>> 0, false); - view.setUint16(offset + OFFSET_CSUM_OFFSET, opts.csumOffset >>> 0, false); - } +const VirtioDevice = require('./device'); +const runtime = require('../../core'); +const { MACAddress, Interface } = runtime.net; + +const virtioHeader = (() => { + const OFFSET_FLAGS = 0; + const OFFSET_GSO_TYPE = 1; + // const OFFSET_HDR_LEN = 2; + // const OFFSET_GSO_SIZE = 4; + const OFFSET_CSUM_START = 6; + const OFFSET_CSUM_OFFSET = 8; + const optsEmpty = {}; + const offset = 0; return { - write: writeVirtioHeader, - length: 10 + write(view, opts = optsEmpty) { + view.setUint8(offset + OFFSET_FLAGS, opts.flags >>> 0); + view.setUint8(offset + OFFSET_GSO_TYPE, opts.gsoType >>> 0); + // view.setUint16(offset + OFFSET_HDR_LEN, opts.hdrLen >>> 0, true); + // view.setUint16(offset + OFFSET_GSO_SIZE, opts.gsoSize >>> 0, true); + view.setUint16(offset + OFFSET_CSUM_START, opts.csumStart >>> 0, false); + view.setUint16(offset + OFFSET_CSUM_OFFSET, opts.csumOffset >>> 0, false); + }, + length: 10, }; })(); -function initializeNetworkDevice(pciDevice) { - var ioSpace = pciDevice.getBAR(0).resource; - var irq = pciDevice.getIRQ(); +const initializeNetworkDevice = (pciDevice) => { + const ioSpace = pciDevice.getBAR(0).resource; + const irq = pciDevice.getIRQ(); - var features = { + const features = { // Device specific VIRTIO_NET_F_CSUM: 0, VIRTIO_NET_F_GUEST_CSUM: 1, @@ -71,15 +67,15 @@ function initializeNetworkDevice(pciDevice) { // VRing VIRTIO_RING_F_NOTIFY_ON_EMPTY: 24, - VIRTIO_RING_F_EVENT_IDX: 29 + VIRTIO_RING_F_EVENT_IDX: 29, }; - var dev = new VirtioDevice('net', ioSpace); + const dev = new VirtioDevice('net', ioSpace); dev.setDriverAck(); - var driverFeatures = { + const driverFeatures = { VIRTIO_NET_F_MAC: true, // able to read MAC address - VIRTIO_NET_F_STATUS: true // able to check network status + VIRTIO_NET_F_STATUS: true, // able to check network status // VIRTIO_RING_F_NOTIFY_ON_EMPTY: true // VIRTIO_NET_F_CSUM: true, // checksum offload // VIRTIO_NET_F_GUEST_CSUM: true, // ok without cksum @@ -87,7 +83,7 @@ function initializeNetworkDevice(pciDevice) { // VIRTIO_RING_F_EVENT_IDX: true // using index to suppress interrupts }; - var deviceFeatures = dev.readDeviceFeatures(features); + const deviceFeatures = dev.readDeviceFeatures(features); debug(JSON.stringify(deviceFeatures)); if (deviceFeatures.VIRTIO_NET_F_GSO) { @@ -96,60 +92,47 @@ function initializeNetworkDevice(pciDevice) { } if (!dev.writeGuestFeatures(features, driverFeatures, deviceFeatures)) { - debug('[virtio] driver is unable to start'); - return; + return debug('[virtio] driver is unable to start'); } - var hwAddr = dev.netReadHWAddress(); - var status = dev.netReadStatus(); + const hwAddr = dev.netReadHWAddress(); + const status = dev.netReadStatus(); - if (!status) { - return; - } + if (!status) return; - var QUEUE_ID_RECV = 0; - var QUEUE_ID_TRANSMIT = 1; + const QUEUE_ID_RECV = 0; + const QUEUE_ID_TRANSMIT = 1; - var recvQueue = dev.queueSetup(QUEUE_ID_RECV); - var transmitQueue = dev.queueSetup(QUEUE_ID_TRANSMIT); + const recvQueue = dev.queueSetup(QUEUE_ID_RECV); + const transmitQueue = dev.queueSetup(QUEUE_ID_TRANSMIT); transmitQueue.suppressUsedBuffers(); - function fillReceiveQueue() { + const fillReceiveQueue = () => { while (recvQueue.descriptorTable.descriptorsAvailable) { - if (!recvQueue.placeBuffers([new Uint8Array(1536)], true)) { - break; - } + if (!recvQueue.placeBuffers([new Uint8Array(1536)], true)) break; } - if (recvQueue.isNotificationNeeded()) { - dev.queueNotify(QUEUE_ID_RECV); - } - } + if (recvQueue.isNotificationNeeded()) dev.queueNotify(QUEUE_ID_RECV); + }; - var mac = new MACAddress(hwAddr[0], hwAddr[1], hwAddr[2], - hwAddr[3], hwAddr[4], hwAddr[5]); - var intf = new Interface(mac); + const mac = new MACAddress(hwAddr[0], hwAddr[1], hwAddr[2], + hwAddr[3], hwAddr[4], hwAddr[5]); + const intf = new Interface(mac); intf.setBufferDataOffset(virtioHeader.length); - intf.ontransmit = function(u8headers, u8data) { + intf.ontransmit = (u8headers, u8data) => { if (u8data) { transmitQueue.placeBuffers([u8headers, u8data], false); } else { transmitQueue.placeBuffers([u8headers], false); } - if (transmitQueue.isNotificationNeeded()) { - dev.queueNotify(QUEUE_ID_TRANSMIT); - } + if (transmitQueue.isNotificationNeeded()) dev.queueNotify(QUEUE_ID_TRANSMIT); }; - function recvBuffer(u8) { - intf.receive(u8); - } + const recvBuffer = u8 => intf.receive(u8); - irq.on(function() { - if (!dev.hasPendingIRQ()) { - return; - } + irq.on(() => { + if (!dev.hasPendingIRQ()) return; recvQueue.fetchBuffers(recvBuffer); fillReceiveQueue(); @@ -157,7 +140,7 @@ function initializeNetworkDevice(pciDevice) { // Under high load we're missing interrupts. This needs to be fixed. // This setInterval hack clears pending IRQ flag and rechecks queues. - setInterval(function() { + setInterval(() => { dev.hasPendingIRQ(); recvQueue.fetchBuffers(recvBuffer); fillReceiveQueue(); @@ -167,6 +150,6 @@ function initializeNetworkDevice(pciDevice) { fillReceiveQueue(); runtime.net.interfaceAdd(intf); -} +}; module.exports = initializeNetworkDevice; diff --git a/js/driver/virtio/rng.js b/js/driver/virtio/rng.js index f390fb995..f75caac8e 100644 --- a/js/driver/virtio/rng.js +++ b/js/driver/virtio/rng.js @@ -13,62 +13,53 @@ // limitations under the License. 'use strict'; -var VirtioDevice = require('./device'); -var runtime = require('../../core'); +const VirtioDevice = require('./device'); +const runtime = require('../../core'); -function initializeRNGDevice(pciDevice) { - var ioSpace = pciDevice.getBAR(0).resource; - var irq = pciDevice.getIRQ(); - var allocator = runtime.allocator; +const initializeRNGDevice = (pciDevice) => { + const ioSpace = pciDevice.getBAR(0).resource; + const irq = pciDevice.getIRQ(); + const allocator = runtime.allocator; - var features = {}; + const features = {}; - var dev = new VirtioDevice('rng', ioSpace, allocator); + const dev = new VirtioDevice('rng', ioSpace, allocator); dev.setDriverAck(); - var driverFeatures = {}; - var deviceFeatures = dev.readDeviceFeatures(driverFeatures); + const driverFeatures = {}; + const deviceFeatures = dev.readDeviceFeatures(driverFeatures); if (!dev.writeGuestFeatures(features, driverFeatures, deviceFeatures)) { - debug('[virtio] driver is unable to start'); - return; + return debug('[virtio] driver is unable to start'); } - var QUEUE_ID_REQ = 0; + const QUEUE_ID_REQ = 0; - var reqQueue = dev.queueSetup(QUEUE_ID_REQ); - var cbqueue = []; - - function recvBuffer() { - if (cbqueue.length === 0) { - return; - } + const reqQueue = dev.queueSetup(QUEUE_ID_REQ); + const cbqueue = []; + const recvBuffer = () => { + if (cbqueue.length === 0) return; cbqueue.shift()(); - } - - irq.on(function() { - if (!dev.hasPendingIRQ()) { - return; - } + }; + irq.on(() => { + if (!dev.hasPendingIRQ()) return; reqQueue.fetchBuffers(recvBuffer); }); dev.setDriverReady(); - var source = new runtime.random.EntropySource('virtio-rng'); + const source = new runtime.random.EntropySource('virtio-rng'); - source.ongetbytes = function(u8, cb) { + source.ongetbytes = (u8, cb) => { cbqueue.push(cb); reqQueue.placeBuffers([u8], true); - if (reqQueue.isNotificationNeeded()) { - dev.queueNotify(QUEUE_ID_REQ); - } + if (reqQueue.isNotificationNeeded()) dev.queueNotify(QUEUE_ID_REQ); }; runtime.random.addEntropySource(source); -} +}; module.exports = initializeRNGDevice; From a320c6f08d7c83c274cda931efcf7c88c1c449bf Mon Sep 17 00:00:00 2001 From: Face Kapow Date: Sun, 10 Jul 2016 09:09:03 -0400 Subject: [PATCH 10/22] js/driver/virtio/vring --- js/driver/virtio/vring/available-ring.js | 14 +- js/driver/virtio/vring/descriptor-table.js | 87 +++---- js/driver/virtio/vring/index.js | 251 +++++++++------------ js/driver/virtio/vring/used-ring.js | 22 +- 4 files changed, 164 insertions(+), 210 deletions(-) diff --git a/js/driver/virtio/vring/available-ring.js b/js/driver/virtio/vring/available-ring.js index d0fe4d6b8..2ad512289 100644 --- a/js/driver/virtio/vring/available-ring.js +++ b/js/driver/virtio/vring/available-ring.js @@ -14,10 +14,10 @@ 'use strict'; -var AVAILABLE_RING_INDEX_FLAGS = 0; -var AVAILABLE_RING_INDEX_IDX = 1; -var AVAILABLE_RING_INDEX_RING = 2; -var VRING_AVAIL_F_NO_INTERRUPT = 1; +const AVAILABLE_RING_INDEX_FLAGS = 0; +const AVAILABLE_RING_INDEX_IDX = 1; +const AVAILABLE_RING_INDEX_RING = 2; +const VRING_AVAIL_F_NO_INTERRUPT = 1; class AvailableRing { constructor(buffer, byteOffset, ringSize) { @@ -44,7 +44,7 @@ class AvailableRing { } placeDescriptor(index) { - var available = (this.readIdx() & (this.ringSize - 1)) >>> 0; + const available = (this.readIdx() & (this.ringSize - 1)) >>> 0; this.setRing(available, index); this.incrementIdx(); } @@ -64,9 +64,7 @@ class AvailableRing { printDebug() { console.log('AVAILABLE RING:'); console.log(` idx = ${this.readIdx()}, wrapped ${this.readIdx() & (this.ringSize - 1)}`); - for (var i = 0; i < this.ringSize; ++i) { - console.log(` ${i}: descriptor = ${this.readDescriptorAsDevice(i)}`); - } + for (let i = 0; i < this.ringSize; ++i) console.log(` ${i}: descriptor = ${this.readDescriptorAsDevice(i)}`); // eslint-disable-line max-len } } diff --git a/js/driver/virtio/vring/descriptor-table.js b/js/driver/virtio/vring/descriptor-table.js index b85d3c598..88381d981 100644 --- a/js/driver/virtio/vring/descriptor-table.js +++ b/js/driver/virtio/vring/descriptor-table.js @@ -14,16 +14,14 @@ 'use strict'; -var assert = require('assert'); -var u8view = require('u8-view'); -var runtime = require('../../../core'); -var OFFSET_ADDR = 0; -var OFFSET_LEN = 8; -var OFFSET_FLAGS = 12; -var OFFSET_NEXT = 14; -var SIZE = 16; -var VRING_DESC_F_NEXT = 1; -var VRING_DESC_F_WRITE = 2; +const u8view = require('u8-view'); +const OFFSET_ADDR = 0; +const OFFSET_LEN = 8; +const OFFSET_FLAGS = 12; +const OFFSET_NEXT = 14; +const SIZE = 16; +const VRING_DESC_F_NEXT = 1; +const VRING_DESC_F_WRITE = 2; class DescriptorTable { constructor(buffer, byteOffset, ringSize) { @@ -32,14 +30,9 @@ class DescriptorTable { this.descriptorsAvailable = ringSize; this.descriptorsBuffers = new Array(ringSize); - var i; - for (i = 0; i < ringSize; ++i) { - this.descriptorsBuffers[i] = null; - } - - for (i = 0; i < ringSize - 1; ++i) { - this.setNext(i, i + 1); - } + let i; + for (i = 0; i < ringSize; ++i) this.descriptorsBuffers[i] = null; + for (i = 0; i < ringSize - 1; ++i) this.setNext(i, i + 1); } static getDescriptorSizeBytes() { @@ -47,15 +40,15 @@ class DescriptorTable { } get(descriptorId) { - var base = SIZE * descriptorId; - var len = u8view.getUint32LE(this.mem, base + OFFSET_LEN); - var flags = u8view.getUint16LE(this.mem, base + OFFSET_FLAGS); - var next = u8view.getUint16LE(this.mem, base + OFFSET_NEXT); + const base = SIZE * descriptorId; + const len = u8view.getUint32LE(this.mem, base + OFFSET_LEN); + const flags = u8view.getUint16LE(this.mem, base + OFFSET_FLAGS); + const next = u8view.getUint16LE(this.mem, base + OFFSET_NEXT); return { - len: len, - flags: flags, - next: next + len, + flags, + next, }; } @@ -64,8 +57,8 @@ class DescriptorTable { } setBuffer(descriptorId, buf, len, flags) { - var base = SIZE * descriptorId; - var addr = __SYSCALL.bufferAddress(buf); + const base = SIZE * descriptorId; + const addr = __SYSCALL.bufferAddress(buf); u8view.setUint32LE(this.mem, base + OFFSET_ADDR + 0, addr[1]); // high u8view.setUint32LE(this.mem, base + OFFSET_ADDR + 4, addr[2]); // low u8view.setUint32LE(this.mem, base + OFFSET_LEN, len >>> 0); @@ -73,12 +66,12 @@ class DescriptorTable { } getNext(descriptorId) { - var base = SIZE * descriptorId; + const base = SIZE * descriptorId; return u8view.getUint16LE(this.mem, base + OFFSET_NEXT); } setNext(descriptorId, next) { - var base = SIZE * descriptorId; + const base = SIZE * descriptorId; u8view.setUint16LE(this.mem, base + OFFSET_NEXT, next >>> 0); } @@ -90,22 +83,16 @@ class DescriptorTable { * @param isWriteOnly {bool} set writeOnly flag for each buffer */ placeBuffers(buffers, lengths, isWriteOnly) { - var count = buffers.length; - if (this.descriptorsAvailable < count) { - return -1; - } + const count = buffers.length; + if (this.descriptorsAvailable < count) return -1; - var head = this.freeDescriptorHead; - var first = head; - for (var i = 0; i < count; ++i) { - var d = buffers[i]; - var flags = 0; - if (i + 1 !== count) { - flags |= VRING_DESC_F_NEXT; - } - if (isWriteOnly) { - flags |= VRING_DESC_F_WRITE; - } + let head = this.freeDescriptorHead; + const first = head; + for (let i = 0; i < count; ++i) { + const d = buffers[i]; + let flags = 0; + if (count !== i + 1) flags |= VRING_DESC_F_NEXT; + if (isWriteOnly) flags |= VRING_DESC_F_WRITE; this.setBuffer(head, d, lengths[i], flags); this.descriptorsBuffers[head] = d; @@ -118,11 +105,11 @@ class DescriptorTable { } getBuffer(descriptorId) { - var nextDescriptorId = descriptorId; - var buffer = this.descriptorsBuffers[descriptorId]; + let nextDescriptorId = descriptorId; + const buffer = this.descriptorsBuffers[descriptorId]; this.descriptorsBuffers[descriptorId] = null; - var desc = this.get(descriptorId); + let desc = this.get(descriptorId); while (desc.flags & VRING_DESC_F_NEXT) { nextDescriptorId = desc.next; desc = this.get(nextDescriptorId); @@ -137,11 +124,7 @@ class DescriptorTable { printDebug() { console.log('DESCRIPTOR TABLE:'); - var self = this; - this.descriptorsBuffers.forEach(function(buf, i) { - var next = self.getNext(i); - console.log(` ${i}: ${buf ? ('') : '-'}, next ${next}`); - }); + this.descriptorsBuffers.forEach((buf, i) => console.log(` ${i}: ${buf ? (``) : '-'}, next ${this.getNext(i)}`)); // eslint-disable-line max-len } } diff --git a/js/driver/virtio/vring/index.js b/js/driver/virtio/vring/index.js index bd083e67c..1aa1a1898 100644 --- a/js/driver/virtio/vring/index.js +++ b/js/driver/virtio/vring/index.js @@ -14,163 +14,136 @@ 'use strict'; -var assert = require('assert'); -var u8view = require('u8-view'); -var runtime = require('../../../core'); -var DescriptorTable = require('./descriptor-table'); -var AvailableRing = require('./available-ring'); -var UsedRing = require('./used-ring'); -var memoryBarrier = require('../../../core/atomic').memoryBarrier; -var SIZEOF_UINT16 = 2; - -function VRing(mem, byteOffset, ringSize) { - assert(ringSize !== 0 && (ringSize & (ringSize - 1)) === 0, 'invalid ringSize = ' + ringSize); - function align(value) { - return ((value + 4095) & ~4095) >>> 0; +const assert = require('assert'); +const DescriptorTable = require('./descriptor-table'); +const AvailableRing = require('./available-ring'); +const UsedRing = require('./used-ring'); +const { memoryBarrier } = require('../../../core/atomic'); +const SIZEOF_UINT16 = 2; + +class VRing { + constructor(mem, byteOffset, ringSize) { + assert(ringSize !== 0 && (ringSize & (ringSize - 1)) === 0, `invalid ringSize = ${ringSize}`); + const align = value => ((value + 4095) & ~4095) >>> 0; + + const baseAddress = mem.address + byteOffset; + const offsetAvailableRing = DescriptorTable.getDescriptorSizeBytes() * ringSize; + const offsetUsedRing = align(offsetAvailableRing + (SIZEOF_UINT16 * (3 + ringSize))); + const ringSizeBytes = offsetUsedRing + align(UsedRing.getElementSize() * ringSize); + this.ringSize = ringSize; + this.address = baseAddress; + this.size = ringSizeBytes; + this.suppressInterrupts = false; + this.descriptorTable = new DescriptorTable(mem.buffer, byteOffset, ringSize); + this.availableRing = new AvailableRing(mem.buffer, byteOffset + offsetAvailableRing, ringSize); + this.usedRing = new UsedRing(mem.buffer, byteOffset + offsetUsedRing, ringSize); + this.availableRing.setEventIdx(this.usedRing.lastUsedIndex); + this.availableRing.enableInterrupts(); } + fetchBuffers(fn) { + let count = 0; - var baseAddress = mem.address + byteOffset; - var offsetAvailableRing = DescriptorTable.getDescriptorSizeBytes() * ringSize; - var offsetUsedRing = align(offsetAvailableRing + SIZEOF_UINT16 * (3 + ringSize)); - var ringSizeBytes = offsetUsedRing + align(UsedRing.getElementSize() * ringSize); - this.ringSize = ringSize; - this.address = baseAddress; - this.size = ringSizeBytes; - this.suppressInterrupts = false; - this.descriptorTable = new DescriptorTable(mem.buffer, byteOffset, ringSize); - this.availableRing = new AvailableRing(mem.buffer, byteOffset + offsetAvailableRing, ringSize); - this.usedRing = new UsedRing(mem.buffer, byteOffset + offsetUsedRing, ringSize); - this.availableRing.setEventIdx(this.usedRing.lastUsedIndex); - this.availableRing.enableInterrupts(); -} - -VRing.prototype.fetchBuffers = function(fn) { - var count = 0; + for (;;) { + if (!this.suppressInterrupts) this.availableRing.disableInterrupts(); - for (;;) { - if (!this.suppressInterrupts) { - this.availableRing.disableInterrupts(); - } + for (;;) { + const u8 = this.getBuffer(); + if (u8 === null) break; - for (;;) { - let u8 = this.getBuffer(); - if (null === u8) { - break; + count++; + if (fn) setImmediate(() => fn(u8)); } - count++; - if (fn) { - setImmediate(function() { - fn(u8); - }); - } - } + if (!this.suppressInterrupts) { + this.availableRing.enableInterrupts(); - if (!this.suppressInterrupts) { - this.availableRing.enableInterrupts(); - - // Make sure we read the latest index written by the - // device, otherwise we can miss interrupts - memoryBarrier(); - } + // Make sure we read the latest index written by the + // device, otherwise we can miss interrupts + memoryBarrier(); + } - if (!this.usedRing.hasUnprocessedBuffers()) { - break; + if (!this.usedRing.hasUnprocessedBuffers()) break; } - } - return count; -}; - -/** - * Supply buffers to the device - * - * @param buffers {array} Array of buffers - * @param isWriteOnly {bool} R/W buffers flag - */ -VRing.prototype.placeBuffers = function(buffers, isWriteOnly) { - if (this.suppressInterrupts) { - this.fetchBuffers(null); + return count; } - - var self = this; - - // Single Uint8Array could use multiple physical pages - // as its backing store - var pageSplitBuffers = []; - var lengths = []; - for (var i = 0, l = buffers.length; i < l; ++i) { - var u8 = buffers[i]; - var addr = __SYSCALL.bufferAddress(u8); - if (addr[3] === 0) { - pageSplitBuffers.push(u8); - lengths.push(addr[0]); - } else { - // push entire u8 here but set shorter length - // this way we can receive the same buffer as a single item later - pageSplitBuffers.push(u8); - pageSplitBuffers.push(u8.subarray(addr[0])); - lengths.push(addr[0]); - lengths.push(addr[3]); - debug('virtio: multipage buffer\n'); + /** + * Supply buffers to the device + * + * @param buffers {array} Array of buffers + * @param isWriteOnly {bool} R/W buffers flag + */ + placeBuffers(buffers, isWriteOnly) { + if (this.suppressInterrupts) this.fetchBuffers(null); + + // Single Uint8Array could use multiple physical pages + // as its backing store + const pageSplitBuffers = []; + const lengths = []; + for (const u8 of buffers) { + const addr = __SYSCALL.bufferAddress(u8); + if (addr[3] === 0) { + pageSplitBuffers.push(u8); + lengths.push(addr[0]); + } else { + // push entire u8 here but set shorter length + // this way we can receive the same buffer as a single item later + pageSplitBuffers.push(u8); + pageSplitBuffers.push(u8.subarray(addr[0])); + lengths.push(addr[0]); + lengths.push(addr[3]); + debug('virtio: multipage buffer\n'); + } } - } - - var first = self.descriptorTable.placeBuffers(pageSplitBuffers, lengths, isWriteOnly); - if (first < 0) { - debug('virtio: no descriptors\n'); - return false; - } - // Barrier is needed to make sure device would be able to see - // updated descriptors in descriptor table before we're going - // to update index - memoryBarrier(); + const first = this.descriptorTable.placeBuffers(pageSplitBuffers, lengths, isWriteOnly); + if (first < 0) { + debug('virtio: no descriptors\n'); + return false; + } - self.availableRing.placeDescriptor(first); - return true; -}; + // Barrier is needed to make sure device would be able to see + // updated descriptors in descriptor table before we're going + // to update index + memoryBarrier(); -VRing.prototype.getBuffer = function() { - var self = this; - var hasUnprocessed = self.usedRing.hasUnprocessedBuffers(); - if (!hasUnprocessed) { - return null; + this.availableRing.placeDescriptor(first); + return true; } + getBuffer() { + const hasUnprocessed = self.usedRing.hasUnprocessedBuffers(); + if (!hasUnprocessed) return null; + + const used = this.usedRing.getUsedDescriptor(); + if (used === null) return null; + + const descriptorId = used.id; + const buffer = self.descriptorTable.getBuffer(descriptorId); + const len = used.len; + + this.availableRing.setEventIdx(this.usedRing.lastUsedIndex + 1); + + if (!(buffer instanceof Uint8Array)) { + // TODO: global vring errors handler + console.log('VRING ERROR: buffer is not a Uint8Array'); + console.log('used.descriptor id ', descriptorId); + console.log('used.len ', len); + console.log('last used index ', self.usedRing.lastUsedIndex); + return null; + } - var used = self.usedRing.getUsedDescriptor(); - if (null === used) { - return null; + return buffer.subarray(0, len); } - - var descriptorId = used.id; - var buffer = self.descriptorTable.getBuffer(descriptorId); - var len = used.len; - - this.availableRing.setEventIdx(this.usedRing.lastUsedIndex + 1); - - if (!(buffer instanceof Uint8Array)) { - // TODO: global vring errors handler - console.log('VRING ERROR: buffer is not a Uint8Array'); - console.log('used.descriptor id ', descriptorId); - console.log('used.len ', len); - console.log('last used index ', self.usedRing.lastUsedIndex); - return null; + isNotificationNeeded() { + // Barrier to make sure we've updated index before + // checking notifications flag + memoryBarrier(); + return this.usedRing.isNotificationNeeded(); } - - return buffer.subarray(0, len); -}; - -VRing.prototype.isNotificationNeeded = function() { - // Barrier to make sure we've updated index before - // checking notifications flag - memoryBarrier(); - return this.usedRing.isNotificationNeeded(); -}; - -VRing.prototype.suppressUsedBuffers = function() { - this.availableRing.disableInterrupts(); - this.suppressInterrupts = true; -}; + suppressUsedBuffers() { + this.availableRing.disableInterrupts(); + this.suppressInterrupts = true; + } +} module.exports = VRing; diff --git a/js/driver/virtio/vring/used-ring.js b/js/driver/virtio/vring/used-ring.js index 976a94e59..b6c5b42b2 100644 --- a/js/driver/virtio/vring/used-ring.js +++ b/js/driver/virtio/vring/used-ring.js @@ -14,11 +14,11 @@ 'use strict'; -var ELEMENT_SIZE = 8; -var OFFSET_BYTES_RING = 4; -var INDEX_FLAGS = 0; -var INDEX_IDX = 1; -var VRING_USED_F_NO_NOTIFY = 1; +const ELEMENT_SIZE = 8; +const OFFSET_BYTES_RING = 4; +const INDEX_FLAGS = 0; +const INDEX_IDX = 1; +const VRING_USED_F_NO_NOTIFY = 1; class UsedRing { constructor(buffer, byteOffset, ringSize) { @@ -36,7 +36,7 @@ class UsedRing { readElement(index) { return { id: this.ringElements[index * 2], - len: this.ringElements[index * 2 + 1] + len: this.ringElements[(index * 2) + 1], }; } @@ -45,9 +45,9 @@ class UsedRing { } placeDescriptorAsDevice(index, bufferLength) { - var used = (this.readIdx() & (this.ringSize - 1)) >>> 0; + const used = (this.readIdx() & (this.ringSize - 1)) >>> 0; this.ringElements[index * 2] = used; - this.ringElements[index * 2 + 1] = bufferLength; + this.ringElements[(index * 2) + 1] = bufferLength; ++this.ringData[INDEX_IDX]; } @@ -56,8 +56,8 @@ class UsedRing { } getUsedDescriptor() { - var last = (this.lastUsedIndex & (this.ringSize - 1)) >>> 0; - var descriptorData = this.readElement(last); + const last = (this.lastUsedIndex & (this.ringSize - 1)) >>> 0; + const descriptorData = this.readElement(last); this.lastUsedIndex = (this.lastUsedIndex + 1) & 0xffff; return descriptorData; } @@ -69,7 +69,7 @@ class UsedRing { printDebug() { console.log('USED RING:'); console.log(` idx = ${this.readIdx()}, wrapped ${this.readIdx() & (this.ringSize - 1)}`); - console.log(` last_used_index = ${this.lastUsedIndex}, wrapped ${this.lastUsedIndex & (this.ringSize - 1)}`); + console.log(` last_used_index = ${this.lastUsedIndex}, wrapped ${this.lastUsedIndex & (this.ringSize - 1)}`); // eslint-disable-line max-len console.log(` has_unproc_buffers = ${this.hasUnprocessedBuffers()}`); console.log(` notif_needed = ${this.isNotificationNeeded()}`); } From 217821043ef4db124ed20f754613906a40cd6fed Mon Sep 17 00:00:00 2001 From: Face Kapow Date: Sun, 10 Jul 2016 16:10:27 -0400 Subject: [PATCH 11/22] js/modules, fix 'self', change some of the wording in the docs --- CONTRIBUTING.md | 4 +- docs/code-style-exceptions.md | 6 +- js/__loader.js | 2 - js/driver/virtio/vring/index.js | 6 +- js/modules/console.js | 43 +++++-- js/modules/dns.js | 138 +++++++++++----------- js/modules/errors.js | 4 +- js/modules/fs.js | 90 ++++++--------- js/modules/net.js | 197 +++++++++++++++++--------------- js/modules/os.js | 95 ++++++--------- js/modules/process.js | 155 +++++++++++++------------ js/modules/stream.js | 6 +- 12 files changed, 367 insertions(+), 379 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dbe86bf20..8d8aaeeaa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,12 +1,12 @@ # Contributing to runtime.js -Firstly, thanks for deciding to contribute! :+1: +First off, thanks for deciding to contribute! :+1: ## Got an issue? * Make sure the issue isn't already reported by checking in [Issues](https://github.com/runtimejs/runtime/issues). * Include the version of the kernel and JavaScript library in the issue description. - * Include a description of what happens or what the issue/bug does and what the expected behavior is. + * Include a description of what happens and what the expected behavior is. ## Cool feature request? diff --git a/docs/code-style-exceptions.md b/docs/code-style-exceptions.md index 24f9270b9..b1be5d0e4 100644 --- a/docs/code-style-exceptions.md +++ b/docs/code-style-exceptions.md @@ -16,7 +16,7 @@ You can still use `for-in`, just be sure you know [the catch](https://developer. You *can* use 'dangling' underscores to denote a private member on an object or class. Some APIs were written before this style was adopted which use underscores for private members and probably won't be changed for compatability. -However, for any new APIs, it'd be prefered to use a [`Symbol`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol) instead, like: +However, for any new APIs, it'd be preferred to use a [`Symbol`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol) instead, like: ```js const somePrivateVarName = Symbol('somePrivateVarName'); @@ -30,3 +30,7 @@ class Demo { } } ``` + +## Using `get` and `set` + +You can (and should) use ES6 `get` and `set`, it's already used in various runtime.js APIs. diff --git a/js/__loader.js b/js/__loader.js index 0eae3a288..6def514ac 100644 --- a/js/__loader.js +++ b/js/__loader.js @@ -225,7 +225,6 @@ ${content} constants: 'constants-browserify', fs: './modules/fs.js', os: './modules/os.js', - __errors__: './modules/errors.js', net: './modules/net.js', dns: './modules/dns.js', punycode: 'punycode', @@ -273,6 +272,5 @@ ${content} process.termout = new TermoutStream(); process.termerr = new TermerrStream(); loader.require('console'); - Object.assign(global, loader.require('__errors__')); loader.require('/'); })(); diff --git a/js/driver/virtio/vring/index.js b/js/driver/virtio/vring/index.js index 1aa1a1898..8a348d9e8 100644 --- a/js/driver/virtio/vring/index.js +++ b/js/driver/virtio/vring/index.js @@ -111,14 +111,14 @@ class VRing { return true; } getBuffer() { - const hasUnprocessed = self.usedRing.hasUnprocessedBuffers(); + const hasUnprocessed = this.usedRing.hasUnprocessedBuffers(); if (!hasUnprocessed) return null; const used = this.usedRing.getUsedDescriptor(); if (used === null) return null; const descriptorId = used.id; - const buffer = self.descriptorTable.getBuffer(descriptorId); + const buffer = this.descriptorTable.getBuffer(descriptorId); const len = used.len; this.availableRing.setEventIdx(this.usedRing.lastUsedIndex + 1); @@ -128,7 +128,7 @@ class VRing { console.log('VRING ERROR: buffer is not a Uint8Array'); console.log('used.descriptor id ', descriptorId); console.log('used.len ', len); - console.log('last used index ', self.usedRing.lastUsedIndex); + console.log('last used index ', this.usedRing.lastUsedIndex); return null; } diff --git a/js/modules/console.js b/js/modules/console.js index 5f961e1b2..5320e8831 100644 --- a/js/modules/console.js +++ b/js/modules/console.js @@ -14,19 +14,27 @@ 'use strict'; const util = require('util'); +const stream = require('stream'); class Console { constructor(stdout, stderr) { - if (!stdout) throw new Error('Console: Must provide a stdout stream to the constructor.'); + if (!stdout || (!(stdout instanceof stream.Writable) && !(stdout instanceof stream.Duplex))) { + throw new TypeError('Console expects a writable stream instance'); + } this._stdout = stdout; - if (stderr) this._stderr = stderr; + if (stderr) { + if (!(stderr instanceof stream.Writable) && !(stderr instanceof stream.Duplex)) { + throw new TypeError('Console expects writable stream instances'); + } + this._stderr = stderr; + } this._labels = {}; } assert(val, ...data) { if (!val) throw new Error(util.format(...data)); } - dir(obj, opts) { - opts = opts || {}; + dir(obj, optsOpt = {}) { + const opts = optsOpt; opts.customInspect = true; this._stdout.write(util.inspect(obj, opts)); } @@ -37,18 +45,16 @@ class Console { log(...data) { this._stdout.write(`${util.format(...data)}\n`); } - time(label) { - if (!label) label = 'undefined'; + time(label = 'undefined') { this._labels[label] = Date.now(); } - timeEnd(label) { - if (!label) label = 'undefined' - if (!this._labels[label]) throw new Error('Console.timeEnd: Label does not exist.'); - this._stdout.write(`${label}: ${Date.now()-this._labels[label]}ms\n`); + timeEnd(label = 'undefined') { + if (!this._labels[label]) process.emitWarning(`No such label ${label} for console.timeEnd()`); + this._stdout.write(`${label}: ${Date.now() - this._labels[label]}ms\n`); } trace(...data) { let trace = (new Error()).stack; - let arr = trace.split('\n'); + const arr = trace.split('\n'); arr[0] = 'Trace'; if (data.length > 0) arr[0] += `: ${util.format(...data)}`; trace = arr.join('\n'); @@ -62,5 +68,18 @@ class Console { } } -module.exports = Console; global.console = new Console(process.stdout, process.stderr); + +const bound = [ + 'assert', + 'dir', + 'error', + 'log', + 'time', + 'timeEnd', + 'trace', + 'info', + 'warn', +]; +for (const item of bound) module.exports[item] = console[item].bind(console); +module.exports.Console = Console; diff --git a/js/modules/dns.js b/js/modules/dns.js index 2e44d22b4..275e2a32e 100644 --- a/js/modules/dns.js +++ b/js/modules/dns.js @@ -13,38 +13,48 @@ // limitations under the License. 'use strict'; -Object.assign(exports, { - NODATA: 'ENODATA', - BADFAMILY: 'EBADFAMILY', - FORMERR: 'EFORMERR', - SERVFAIL: 'ESERVFAIL', - NOTFOUND: 'ENOTFOUND', - NOTIMP: 'ENOTIMP', - REFUSED: 'EREFUSED', - BADQUERY: 'EBADQUERY', - BADNAME: 'EBADNAME', - BADRESP: 'EBADRESP', - CONNREFUSED: 'ECONNREFUSED', - TIMEOUT: 'ETIMEOUT', - EOF: 'EEOF', - FILE: 'EFILE', - NOMEM: 'ENOMEM', - DESTRUCTION: 'EDESTRUCTION', - BADSTR: 'EBADSTR', - BADFLAGS: 'EBADFLAGS', - NONAME: 'ENONAME', - BADHINTS: 'EBADHINTS', - NOTINITIALIZED: 'ENOTINITIALIZED', - LOADIPHLPAPI: 'ELOADIPHLPAPI', - ADDRGETNETWORKPARAMS: 'EADDRGETNETWORKPARAMS', - CANCELLED: 'ECANCELLED' -}); +const { SystemError } = require('./errors'); -let servers = [ - '8.8.8.8' +const names = [ + 'NODATA', + 'BADFAMILY', + 'FORMERR', + 'SERVFAIL', + 'NOTFOUND', + 'NOTIMP', + 'REFUSED', + 'BADQUERY', + 'BADNAME', + 'BADRESP', + 'CONNREFUSED', + 'TIMEOUT', + 'EOF', + 'FILE', + 'NOMEM', + 'DESTRUCTION', + 'BADSTR', + 'BADFLAGS', + 'NONAME', + 'BADHINTS', + 'NOTINITIALIZED', + 'LOADIPHLPAPI', + 'ADDRGETNETWORKPARAMS', + 'CANCELLED', ]; +for (const name of names) exports[name] = `E${name}`; -function lookup(hostname, opts, cb) { +const servers = [ + '8.8.8.8', +]; + +const throwIPv6Err = (cb) => { + const err = new SystemError('runtime doesn\'t support IPv6', exports.BADFAMILY); + if (cb) return cb(err); + throw err; +}; + +const lookup = (hostname, optsOpt, cb) => { + const opts = optsOpt; if (opts.family && opts.family === 6) return throwIPv6Err(cb); opts.query = opts.query || 'A'; if (hostname === 'localhost' && opts.query === 'A') { @@ -54,24 +64,23 @@ function lookup(hostname, opts, cb) { if (opts.addrOnly) { if (cb) cb(null, ['127.0.0.1']); } else { - if (cb) cb(null, [{address: '127.0.0.1', family: 4}]); + if (cb) cb(null, [{ address: '127.0.0.1', family: 4 }]); } } return; } runtime.dns.resolve(hostname, { - query: opts.query - }, function(err, data) { + query: opts.query, + }, (err, data) => { if (err) { if (cb) cb(err, null, null); return; } - var res; - var ret = []; - for (var i = 0; i < data.results.length; i++) { - res = data.results[i]; + const ret = []; + for (const i of Object.keys(data.results)) { + const res = data.results[i]; if (!opts.all && i === 0) { - var addr = res.address.join('.'); + const addr = res.address.join('.'); if (cb) cb(null, addr, 4); break; } else { @@ -82,10 +91,12 @@ function lookup(hostname, opts, cb) { } else { ret.push({ address: res.address.join('.'), - family: 4 + family: 4, }); } break; + default: + break; } } } @@ -95,19 +106,13 @@ function lookup(hostname, opts, cb) { } if (cb) cb(null, ret); }); -} - -function throwIPv6Err(cb) { - var err = new SystemError('runtime doesn\'t support IPv6', exports.BADFAMILY); - if (cb) return cb(err); - throw err; -} +}; -exports.getServers = function() { - return servers; -} +exports.getServers = () => servers; -exports.lookup = function(hostname, opts, cb) { +exports.lookup = (hostname, optsOpt, cbOpt) => { + let opts = optsOpt; + let cb = cbOpt; if (typeof opts === 'function') { cb = opts; opts = null; @@ -115,36 +120,31 @@ exports.lookup = function(hostname, opts, cb) { if (typeof opts === 'undefined' || opts === null) opts = {}; if (typeof opts === 'number' || opts instanceof Number) { opts = { - family: opts + family: opts, }; } return lookup(hostname, opts, cb); -} +}; -exports.resolve4 = function(hostname, cb) { - return lookup(hostname, { - all: true, - addrOnly: true - }, cb); -} +exports.resolve4 = (hostname, cb) => lookup(hostname, { + all: true, + addrOnly: true, +}, cb); -exports.resolve6 = function(hostname, cb) { - throwIPv6Err(cb); -} +exports.resolve6 = (hostname, cb) => throwIPv6Err(cb); -exports.resolve = function(hostname, rrtype, cb) { +exports.resolve = (hostname, rrtypeOpt, cbOpt) => { + let rrtype = rrtypeOpt; + let cb = cbOpt; if (typeof rrtype === 'function') { cb = rrtype; rrtype = null; } if (typeof rrtype === 'undefined' || rrtype === null) rrtype = 'A'; - switch (rrtype) { - case 'A': - return exports.resolve4(hostname, cb); - break; - case 'AAAA': - return exports.resolve6(hostname, cb); - break; + if (rrtype === 'A') { + return exports.resolve4(hostname, cb); + } else if (rrtype === 'AAAA') { + return exports.resolve6(hostname, cb); } -} +}; diff --git a/js/modules/errors.js b/js/modules/errors.js index 2d9431abd..49fc53606 100644 --- a/js/modules/errors.js +++ b/js/modules/errors.js @@ -17,11 +17,11 @@ exports.Error = Error; class SystemError { constructor(message, errcode, call) { - var msg = ''; + let msg = ''; if (errcode) msg += `${errcode}: `; if (message) msg += message; if (call) msg += `, ${call}`; - var err = new Error(msg); + const err = new Error(msg); err.code = errcode || ''; err.syscall = call || ''; return err; diff --git a/js/modules/fs.js b/js/modules/fs.js index da1c863e0..252d06233 100644 --- a/js/modules/fs.js +++ b/js/modules/fs.js @@ -13,21 +13,17 @@ // limitations under the License. 'use strict'; -var typeutils = require('typeutils'); - -function makeErrorNotFound(path, op) { - return new Error('ENOENT: no such file or directory, ' + op + ' \'' + path + '\''); -} - -function normalizePath(components) { - var r = []; - for (var i = 0; i < components.length; ++i) { - var p = components[i]; - if ('' === p || '.' === p) { - continue; - } +const typeutils = require('typeutils'); +const { SystemError } = require('./errors'); + +const makeErrorNotFound = (path, op) => new SystemError(`no such file or directory, ${op} '${path}'`, 'ENOENT'); // eslint-disable-line max-len - if ('..' === p) { +const normalizePath = (components) => { + const r = []; + for (const p of components) { + if (p === '' || p === '.') continue; + + if (p === '..') { if (r.length > 0) { r.pop(); } else { @@ -39,70 +35,54 @@ function normalizePath(components) { } return r; -} +}; // This function assumes current directory '/'. It is not // possible to change it. -function toAbsolutePath(path) { - if (typeof path !== 'string') { - return null; - } +const toAbsolutePath = (path) => { + if (typeof path !== 'string') return null; - var parts = path.split('/'); - var n = normalizePath(parts); - if (!n) { - return null; - } + const parts = path.split('/'); + const n = normalizePath(parts); + if (!n) return null; - return '/' + n.join('/'); -} + return `/${n.join('/')}`; +}; -function readFileImpl(fnName, path, opts) { - if (!typeutils.isString(path)) { - throw new Error('path is not a string'); - } +const readFileImpl = (fnName, path, opts) => { + if (!typeutils.isString(path)) throw new Error('path is not a string'); - var encoding = null; + let encoding = null; if (typeutils.isString(opts)) { encoding = opts; } else if (typeutils.isObject(opts)) { encoding = opts.encoding; } - var absolute = toAbsolutePath(path); - if (!absolute) { - return [makeErrorNotFound(path, fnName), null]; - } + const absolute = toAbsolutePath(path); + if (!absolute) return [makeErrorNotFound(path, fnName), null]; - var buf = __SYSCALL.initrdReadFileBuffer(absolute); - if (!buf) { - return [makeErrorNotFound(path, fnName), null]; - } + const buf = __SYSCALL.initrdReadFileBuffer(absolute); + if (!buf) return [makeErrorNotFound(path, fnName), null]; - if (encoding) { - return [null, new Buffer(buf).toString(encoding)]; - } + if (encoding) return [null, new Buffer(buf).toString(encoding)]; return [null, new Buffer(buf)]; -} +}; -exports.readFile = function(path, opts, cb) { - var options = typeutils.isFunction(opts) ? null : opts; - var callback = typeutils.isFunction(opts) ? opts : cb; +exports.readFile = (path, opts, cb) => { + // const options = typeutils.isFunction(opts) ? null : opts; + const callback = typeutils.isFunction(opts) ? opts : cb; - if (!typeutils.isFunction(callback)) { - throw new Error('callback is not a function'); - } + if (!typeutils.isFunction(callback)) throw new Error('callback is not a function'); - var [err, buf] = readFileImpl('readFile', path, opts); + const [err, buf] = readFileImpl('readFile', path, opts); setImmediate(() => callback(err, buf)); }; -exports.readFileSync = function(path, opts) { - var [err, buf] = readFileImpl('readFileSync', path, opts); - if (err) { - throw err; - } +exports.readFileSync = (path, opts) => { + const [err, buf] = readFileImpl('readFileSync', path, opts); + if (err) throw err; return buf; }; diff --git a/js/modules/net.js b/js/modules/net.js index 0dce5f812..cb12ac1ad 100644 --- a/js/modules/net.js +++ b/js/modules/net.js @@ -17,77 +17,16 @@ const EventEmitter = require('events'); const Duplex = require('stream').Duplex; const dns = require('dns'); -function rmFromArrayByVal(array, val) { +const rmFromArrayByVal = (array, val) => { const i = array.indexOf(val); if (i !== -1) array.splice(i, 1); -} - -class Server extends EventEmitter { - constructor(runtimeServer) { - super(); - this._handle = runtimeServer || new runtime.net.TCPServerSocket(); - this._connections = []; - this._handle.onconnect = (runtimeSocket) => { - const socket = new Socket(runtimeSocket); - this.emit('connection', socket); - socket.once('close', () => rmFromArrayByVal(this._connections, socket)); - this._connections.push(socket); - } - this._handle.onclose = () => this.emit('close'); - this._handle.onerror = (err) => { - this.emit('error', err); - this.close(); - } - this._handle.onlisten = () => this.emit('listening'); - } - address() { - return { - port: this._handle.localPort, - family: 'IPv4', - address: '127.0.0.1' - } - } - close(cb) { - this.once('close', cb); - this._handle.close(); - } - get connections() { - return this._connections.length; - } - getConnections(cb) { - if (cb) cb(null, this._connections.length); - } - listen(port, hostname, backlog, callback) { - let options = {}; - if (typeof hostname === 'function') { - callback = hostname; - hostname = null; - } - if (typeof backlog === 'function') { - callback = backlog; - backlog = null; - } - if (typeof port === 'object') { - options = port; - port = options.port || null; - } - if (typeof port === 'function') { - callback = port; - port = null; - } - options.port = port; - this.once('listening', callback); - this._handle.listen(options.port); - } - - // ref and unref do nothing, since runtime isn't a process - ref() {} - unref() {} -} +}; class Socket extends Duplex { - constructor(opts, runtimeSocket) { + constructor(optsOpt, runtimeSocketOpt) { super(); + let opts = optsOpt; + let runtimeSocket = runtimeSocketOpt; if (opts instanceof runtime.net.TCPSocket) { runtimeSocket = opts; opts = null; @@ -98,18 +37,21 @@ class Socket extends Duplex { this._handle.onend = () => this.push(null); this._handle.onclose = () => this.emit('close', false); this.bufferSize = 0; - this.bytesRead = 0 + this.bytesRead = 0; this.bytesWritten = 0; } address() { return { port: null, family: null, - address: null - } + address: null, + }; } - connect(port, host, cb) { + connect(portOpt, hostOpt, cbOpt) { let opts = {}; + let port = portOpt; + let host = hostOpt; + let cb = cbOpt; if (typeof port === 'object') { opts = port; port = opts.port || 80; @@ -128,12 +70,12 @@ class Socket extends Duplex { if (cb) this.once('connect', cb); if (exports.isIP(host) !== 0) { this.emit('lookup', null, host, exports.isIP(host)); - this._handle.open(host, parseInt(port)); + this._handle.open(host, parseInt(port, 10)); } else { dns.lookup(host, (err, addr, family) => { if (err) return this.emit('lookup', err, null, null); this.emit('lookup', null, addr, family); - this._handle.open(addr, parseInt(port)); + this._handle.open(addr, parseInt(port, 10)); }); } } @@ -166,59 +108,124 @@ class Socket extends Duplex { setNoDelay() {} setTimeout() {} unref() {} - _read(size) { - // can't force a read. do nothing. - } - _write(chunk, encoding, callback) { - if (!(chunk instanceof Buffer)) { - chunk = new Buffer(chunk); - } + _read() {} // can't force a read. do nothing. + _write(chunkOpt, encoding, callback) { + let chunk = chunkOpt; + if (!(chunk instanceof Buffer)) chunk = new Buffer(chunk); this._handle.send(new Uint8Array(chunk)); callback(null); } } -exports.Server = Server; +class Server extends EventEmitter { + constructor(runtimeServer) { + super(); + this._handle = runtimeServer || new runtime.net.TCPServerSocket(); + this._connections = []; + this._handle.onconnect = (runtimeSocket) => { + const socket = new Socket(runtimeSocket); + this.emit('connection', socket); + socket.once('close', () => rmFromArrayByVal(this._connections, socket)); + this._connections.push(socket); + }; + this._handle.onclose = () => this.emit('close'); + this._handle.onerror = (err) => { + this.emit('error', err); + this.close(); + }; + this._handle.onlisten = () => this.emit('listening'); + } + address() { + return { + port: this._handle.localPort, + family: 'IPv4', + address: '127.0.0.1', + }; + } + close(cb) { + this.once('close', cb); + this._handle.close(); + } + get connections() { + return this._connections.length; + } + getConnections(cb) { + if (cb) cb(null, this._connections.length); + } + listen(portOpt, hostnameOpt, backlogOpt, callbackOpt) { + let options = {}; + let port = portOpt; + let hostname = hostnameOpt; + let backlog = backlogOpt; + let callback = callbackOpt; + if (typeof hostname === 'function') { + callback = hostname; + hostname = null; + } + if (typeof backlog === 'function') { + callback = backlog; + backlog = null; + } + if (typeof port === 'object') { + options = port; + port = options.port || null; + } + if (typeof port === 'function') { + callback = port; + port = null; + } + options.port = port; + this.once('listening', callback); + this._handle.listen(options.port); + } + + // ref and unref do nothing, since runtime isn't a process + ref() {} + unref() {} +} + exports.Socket = Socket; +exports.Server = Server; -exports.createConnection = function(port, host, cb) { +exports.createConnection = (port, host, cb) => { const socket = new Socket(); socket.connect(port, host, cb); return socket; -} +}; -exports.createServer = function(opts, cb) { +exports.createServer = (optsOpt = {}, cbOpt) => { + let opts = optsOpt; + let cb = cbOpt; if (typeof opts === 'function') { cb = opts; opts = {}; } - opts = opts || {}; const server = new Server(); if (cb) server.on('connection', cb); return server; -} +}; -exports.isIPv4 = function(ip) { - var arr = ip.split('.'); +exports.isIPv4 = (ip) => { + const arr = ip.split('.'); if (arr.length !== 4) return false; // check if it contains non-number characters or exceeds the maximum length: - for (var i = 0, len = arr.length; i < len; i++) if (parseInt(arr[i]) === NaN || arr[i].length > 3) return false; + for (const item of arr) if (isNaN(parseInt(item, 10)) || item.length > 3) return false; return true; -} +}; -exports.isIPv6 = function(ip) { +exports.isIPv6 = (ip) => { if (ip.length > 45) return false; - var arr = ip.split(':'); + const arr = ip.split(':'); if (arr.length !== 6) return false; // check if it contains only letters and numbers (or is empty): - for (var i = 0, len = arr.length; i < len; i++) if (arr[i].search(/[a-zA-Z0-9]*/) === -1) return false; + for (const item of arr) if (item.search(/[a-zA-Z0-9]*/) === -1) return false; return true; -} +}; -exports.isIP = function(ip) { +exports.isIP = (ip) => { if (exports.isIPv4(ip)) return 4; if (exports.isIPv6(ip)) return 6; return 0; -} +}; exports.connect = exports.createConnection; diff --git a/js/modules/os.js b/js/modules/os.js index dabbdd196..366eb4bcc 100644 --- a/js/modules/os.js +++ b/js/modules/os.js @@ -13,66 +13,35 @@ // limitations under the License. 'use strict'; -var interfaces = require('../core/net/interfaces'); - -exports.EOL = '\n'; - -exports.arch = function() { - return process.arch; -}; - -exports.cpus = function() { - return []; -}; - -exports.endianness = function() { - return 'LE'; -}; - -exports.freemem = exports.totalmem = function() { - return Math.pow(2, 32); -}; - -exports.homedir = function() { - return '/'; -}; - -exports.hostname = function() { - return 'runtime'; -}; - -exports.loadavg = function() { - return [0, 0, 0]; -}; - -exports.networkInterfaces = function() { - var ret = {}; - for (var intf of interfaces.getAll()) { - ret[intf.name] = [{ - address: intf.ipAddr.toString(), - netmask: intf.netmask.toString(), - family: 'IPv4', - mac: intf.macAddr.toString(), - internal: false // since it's unknown whether it's internal, let's go with false by default - }]; - } - return ret; -}; - -exports.platform = function() { - return process.platform; -}; - -exports.release = function() { - return __SYSCALL.version().kernel; -}; - -exports.tmpdir = function() { - return '/tmp'; -}; - -exports.type = function() { - return 'runtime'; -}; - -exports.uptime = process.uptime; +const interfaces = require('../core/net/interfaces'); +const mem = () => Math.pow(2, 32); + +Object.assign(exports, { + EOL: '\n', + arch: () => process.arch, + cpus: () => [], + endianness: () => 'LE', + freemem: mem, + totalmem: mem, + homedir: () => '/', + hostname: () => 'runtime', + loadavg: () => [0, 0, 0], + networkInterfaces() { + const ret = {}; + for (const intf of interfaces.getAll()) { + ret[intf.name] = [{ + address: intf.ipAddr.toString(), + netmask: intf.netmask.toString(), + family: 'IPv4', + mac: intf.macAddr.toString(), + internal: false, // since it's unknown whether it's internal, let's go with false by default + }]; + } + return ret; + }, + platform: () => process.platform, + release: () => __SYSCALL.version().kernel, + uptime: process.uptime, + tmpdir: () => '/tmp', + type: () => 'runtime', +}); diff --git a/js/modules/process.js b/js/modules/process.js index 9f229ce9d..47220b410 100644 --- a/js/modules/process.js +++ b/js/modules/process.js @@ -13,78 +13,89 @@ // limitations under the License. 'use strict'; -module.exports = { - abort: function() { - throw new Error('abort()'); - }, - arch: 'x64', // since runtime.js only runs in qemu-system-x86_64, it's an x64 system. - argv: [], - binding: function(name) { - throw new Error('no such module: ' + name); - }, - chdir: function() { - throw new Error('chdir is not supported'); - }, - config: {}, - connected: false, - cwd: function() { - return '/'; - }, - disconnect: function() {}, - env: {}, - execArgv: [], - execPath: '', - exit: function() { - throw new Error('exit()'); - }, - exitCode: 0, - hrtime: function(prev) { - var now = performance.now(); - var time = now / 1000; - var seconds = Math.round(time); - var nanoseconds = Math.floor((time % 1) * 1e9); +const EventEmitter = require('events'); - if (prev) { - seconds -= prev[0]; - nanoseconds -= prev[1]; - if (nanoseconds < 0) { - seconds -= 1; - nanoseconds += 1e9; - } - } +class Warning extends Error { + constructor(msg, name) { + super(); + this.name = name; + this.message = msg; + } +} - return [seconds, nanoseconds]; - }, - kill: function() {}, - mainModule: void 0, - memoryUsage: function() { - return { - rss: 0, - heapTotal: 0, - heapUsed: 0 - }; - }, - nextTick: function nextTick(fn, ...args) { - setImmediate(function() { - fn(...args); +class Process extends EventEmitter { + constructor() { + super(); + Object.assign(this, { + abort() { + throw new Error('abort()'); + }, + arch: 'x64', // since runtime.js only runs in qemu-system-x86_64, it's an x64 system. + argv: [], + binding(name) { + throw new Error(`no such module: ${name}`); + }, + chdir() { + throw new Error('chdir is not supported'); + }, + config: {}, + connected: false, + cwd: () => '/', + disconnect() {}, + emitWarning: (msgOpt, name = 'Warning') => { + let msg = msgOpt; + if (!(msg instanceof Error)) msg = new Warning(msg, name); + if (this.listenerCount('warning') !== 0) return this.emit('warning', msg); + console.error(`(runtime) ${msg.name}${msg.message ? `: ${msg.message}` : ''}`); + }, + env: {}, + execArgv: [], + execPath: '', + exit() { + throw new Error('exit()'); + }, + exitCode: 0, + hrtime(prev) { + const now = performance.now(); + const time = now / 1000; + let seconds = Math.round(time); + let nanoseconds = Math.floor((time % 1) * 1e9); + + if (prev) { + seconds -= prev[0]; + nanoseconds -= prev[1]; + if (nanoseconds < 0) { + seconds -= 1; + nanoseconds += 1e9; + } + } + + return [seconds, nanoseconds]; + }, + kill() {}, + mainModule: void 0, + memoryUsage: () => ({ + rss: 0, + heapTotal: 0, + heapUsed: 0, + }), + nextTick: (fn, ...args) => setImmediate(() => fn(...args)), + pid: 1, + platform: 'runtime', + release: { + name: 'runtime', + }, + send: void 0, + stderr: null, + stdin: null, + stdout: null, + title: '', + umask: () => 0, + uptime: () => Math.round(performance.now() / 1000), + version: '0.0.0', + versions: {}, }); - }, - pid: 1, - platform: 'runtime', - release: { - name: 'runtime', - }, - send: void 0, - stderr: null, - stdin: null, - stdout: null, - title: '', - umask: function() { - return 0; - }, - uptime: function() { - return Math.round(performance.now() / 1000); - }, - version: '0.0.0', - versions: {} -}; + } +} + +module.exports = new Process(); diff --git a/js/modules/stream.js b/js/modules/stream.js index 490a0329a..b776b0d93 100644 --- a/js/modules/stream.js +++ b/js/modules/stream.js @@ -14,13 +14,13 @@ 'use strict'; -var EventEmitter = require('events').EventEmitter; -var inherits = require('inherits'); +const EventEmitter = require('events'); +const inherits = require('inherits'); +// gotta stick with an ES5 class, because readable-stream doesn't use 'new' function Stream() { EventEmitter.call(this); } - inherits(Stream, EventEmitter); module.exports = Stream; From fecb02e6155cb78d93b811f4a0b01c341310745f Mon Sep 17 00:00:00 2001 From: Face Kapow Date: Sun, 10 Jul 2016 16:55:32 -0400 Subject: [PATCH 12/22] js/service/*, js/utils --- js/service/dhcp-client/dhcp-options.js | 24 ++-- js/service/dhcp-client/dhcp-packet.js | 89 +++++---------- js/service/dhcp-client/index.js | 151 +++++++++++-------------- js/service/dns-resolver/index.js | 2 +- js/service/shell/index.js | 51 ++++----- js/utils/index.js | 18 +-- 6 files changed, 133 insertions(+), 202 deletions(-) diff --git a/js/service/dhcp-client/dhcp-options.js b/js/service/dhcp-client/dhcp-options.js index 367d09475..dc970c92d 100644 --- a/js/service/dhcp-client/dhcp-options.js +++ b/js/service/dhcp-client/dhcp-options.js @@ -20,27 +20,19 @@ exports.OPTION_ADDRESS_TIME = 51; exports.OPTION_MESSAGE_TYPE = 53; exports.OPTION_SERVER_ID = 54; -exports.find = function(options, id, minLength) { - minLength = minLength || 0; - - for (var i = 0; i < options.length; ++i) { - if (options[i].id === id && options[i].bytes.length >= minLength) { - return options[i].bytes; - } +exports.find = (options, id, minLength = 0) => { + for (const opt of options) { + if (opt.id === id && opt.bytes.length >= minLength) return opt.bytes; } - return null; }; -exports.findAll = function(options, id, minLength) { - minLength = minLength || 0; - var result = []; - - for (var i = 0; i < options.length; ++i) { - if (options[i].id === id && options[i].bytes.length >= minLength) { - result.push(options[i].bytes); +exports.findAll = (options, id, minLength = 0) => { + const result = []; + for (const opt of options) { + if (opt.id === id && opt.bytes.length >= minLength) { + result.push(opt.bytes); } } - return result; }; diff --git a/js/service/dhcp-client/dhcp-packet.js b/js/service/dhcp-client/dhcp-packet.js index db6fa917b..63e23b2f7 100644 --- a/js/service/dhcp-client/dhcp-packet.js +++ b/js/service/dhcp-client/dhcp-packet.js @@ -13,15 +13,14 @@ // limitations under the License. 'use strict'; -var u8view = require('u8-view'); -var runtime = require('../../core'); -var IP4Address = runtime.net.IP4Address; +const u8view = require('u8-view'); +const { IP4Address } = require('../../core').net; -var OPERATION_REQUEST = 1; -var OPERATION_RESPONSE = 2; +const OPERATION_REQUEST = 1; +const OPERATION_RESPONSE = 2; -var OPTIONS_OFFSET = 28 + 16 + 192; -var magicCookie = 0x63825363; +const OPTIONS_OFFSET = 28 + 16 + 192; +const magicCookie = 0x63825363; exports.packetType = { DISCOVER: 1, @@ -31,19 +30,14 @@ exports.packetType = { ACK: 5, NAK: 6, RELEASE: 7, - INFORM: 8 + INFORM: 8, }; -exports.create = function(type, srcMAC, options) { - var i, j; - options = options || []; +exports.create = (type, srcMAC, options = []) => { + let optionsLength = 8; // cookie (4b), type (3b) and 0xff (1b) + for (const opt of options) optionsLength += opt.bytes.length + 2; // id (1b) and len (1b) - var optionsLength = 8; // cookie (4b), type (3b) and 0xff (1b) - for (i = 0; i < options.length; ++i) { - optionsLength += options[i].bytes.length + 2; // id (1b) and len (1b) - } - - var u8 = new Uint8Array(OPTIONS_OFFSET + optionsLength); + const u8 = new Uint8Array(OPTIONS_OFFSET + optionsLength); u8[0] = OPERATION_REQUEST; // request u8[1] = 1; // over ethernet u8[2] = 6; // hw address 6 bytes @@ -63,7 +57,7 @@ exports.create = function(type, srcMAC, options) { u8[33] = srcMAC.f; u8view.setUint32BE(u8, OPTIONS_OFFSET, magicCookie); - var optionsOffset = OPTIONS_OFFSET + 4; + let optionsOffset = OPTIONS_OFFSET + 4; // Option: DHCP Message u8[optionsOffset++] = 53; // id @@ -71,62 +65,39 @@ exports.create = function(type, srcMAC, options) { u8[optionsOffset++] = type; // Other options - for (i = 0; i < options.length; ++i) { - var option = options[i]; + for (const option of options) { u8[optionsOffset++] = option.id; // id u8[optionsOffset++] = option.bytes.length & 0xff; // len - for (j = 0; j < option.bytes.length; ++j) { - u8[optionsOffset++] = option.bytes[j] >>> 0; - } + for (const byte of option.bytes) u8[optionsOffset++] = byte >>> 0; } u8[optionsOffset] = 255; // end of option list return u8; }; -exports.getOperation = function(u8) { - return u8[0]; -}; - -exports.getRequestId = function(u8) { - return u8view.getUint32BE(u8, 4); -}; - -exports.getYourIP = function(u8) { - return new IP4Address(u8[16], u8[17], u8[18], u8[19]); -}; - -exports.getServerIP = function(u8) { - return new IP4Address(u8[20], u8[21], u8[22], u8[23]); -}; +exports.getOperation = u8 => u8[0]; +exports.getRequestId = u8 => u8view.getUint32BE(u8, 4); +exports.getYourIP = u8 => new IP4Address(u8[16], u8[17], u8[18], u8[19]); +exports.getServerIP = u8 => new IP4Address(u8[20], u8[21], u8[22], u8[23]); +exports.isValidMagicCookie = u8 => magicCookie === u8view.getUint32BE(u8, OPTIONS_OFFSET); -exports.isValidMagicCookie = function(u8) { - return magicCookie === u8view.getUint32BE(u8, OPTIONS_OFFSET); -}; - -exports.getOptions = function(u8) { - var i, j; - var options = []; +exports.getOptions = (u8) => { + let i; + let j; + const options = []; for (i = OPTIONS_OFFSET + 4; i < u8.length; ++i) { - var optId = u8[i++]; - var optLen = u8[i++]; - - if (0xff === optId) { - break; - } + const optId = u8[i++]; + const optLen = u8[i++]; - if (0x00 === optId) { - continue; - } + if (optId === 0xff) break; + if (optId === 0x00) continue; - var bytes = []; - for (j = 0; j < optLen; ++j) { - bytes.push(u8[i++]); - } + const bytes = []; + for (j = 0; j < optLen; ++j) bytes.push(u8[i++]); options.push({ id: optId, - bytes: bytes + bytes, }); --i; diff --git a/js/service/dhcp-client/index.js b/js/service/dhcp-client/index.js index 46e4d5da3..4d6c573f0 100644 --- a/js/service/dhcp-client/index.js +++ b/js/service/dhcp-client/index.js @@ -13,118 +13,103 @@ // limitations under the License. 'use strict'; -var dhcpPacket = require('./dhcp-packet'); -var dhcpOptions = require('./dhcp-options'); -var runtime = require('../../core'); -var IP4Address = runtime.net.IP4Address; - -var STATE_IDLE = 0; -var STATE_DISCOVER_SENT = 1; -var STATE_REQUEST_SENT = 2; -var STATE_ACK_RECEIVED = 2; -var STATE_ERROR = 3; - -function sendPacket(socket, srcMAC, type, serverIP, yourIP) { +const dhcpPacket = require('./dhcp-packet'); +const dhcpOptions = require('./dhcp-options'); +const runtime = require('../../core'); +const { IP4Address } = runtime.net; + +const STATE_IDLE = 0; +const STATE_DISCOVER_SENT = 1; +const STATE_REQUEST_SENT = 2; +const STATE_ACK_RECEIVED = 2; +// const STATE_ERROR = 3; + +const sendPacket = (socket, srcMAC, type, serverIP, yourIP) => { // Request info option - var opt55 = {id: 55, bytes: [ - 1, // subnet - 3, // router - 6 // dns - ]}; + const opt55 = { + id: 55, + bytes: [ + 1, // subnet + 3, // router + 6, // dns + ], + }; - var options; + let options; if (serverIP && yourIP) { - var opt54 = {id: 54, bytes: [serverIP.a, serverIP.b, serverIP.c, serverIP.d]}; - var opt50 = {id: 50, bytes: [yourIP.a, yourIP.b, yourIP.c, yourIP.d]}; + const opt54 = { id: 54, bytes: [serverIP.a, serverIP.b, serverIP.c, serverIP.d] }; + const opt50 = { id: 50, bytes: [yourIP.a, yourIP.b, yourIP.c, yourIP.d] }; options = [opt55, opt54, opt50]; } else { options = [opt55]; } - var u8 = dhcpPacket.create(type, srcMAC, options); + const u8 = dhcpPacket.create(type, srcMAC, options); socket.send(IP4Address.BROADCAST, 67, u8); -} +}; -function checkPacket(u8) { - var op = dhcpPacket.getOperation(u8); - if (op !== dhcpPacket.OPERATION_RESPONSE) { - return false; - } +const checkPacket = (u8) => { + const op = dhcpPacket.getOperation(u8); - if (!dhcpPacket.isValidMagicCookie(u8)) { - return false; - } + if (op !== dhcpPacket.OPERATION_RESPONSE) return false; + if (!dhcpPacket.isValidMagicCookie(u8)) return false; return true; -} +}; -function optionToIP(options, id) { - var option = dhcpOptions.find(options, id, 4); - if (!option) { - return IP4Address.ANY; - } +const optionToIP = (options, id) => { + const option = dhcpOptions.find(options, id, 4); + if (!option) return IP4Address.ANY; return new IP4Address(option[0], option[1], option[2], option[3]); -} +}; -function optionToIPsArray(options, id) { - var selected = dhcpOptions.findAll(options, id, 4); - var result = []; - for (var i = 0, l = selected.length; i < l; ++i) { - result.push(new IP4Address(selected[i][0], selected[i][1], selected[i][2], selected[i][3])); - } +const optionToIPsArray = (options, id) => { + const selected = dhcpOptions.findAll(options, id, 4); + const result = []; + for (const sel of selected) result.push(new IP4Address(sel[0], sel[1], sel[2], sel[3])); return result; -} +}; -function dhcpConfigure(intf, cb) { - var macAddress = intf.getMACAddress(); - var socket = new runtime.net.UDPSocket(); - var clientState = STATE_IDLE; +const dhcpConfigure = (intf, cb) => { + const macAddress = intf.getMACAddress(); + const socket = new runtime.net.UDPSocket(); + let clientState = STATE_IDLE; - function handleOffer(serverIP, yourIP, options) { - var serverId = optionToIP(options, dhcpOptions.OPTION_SERVER_ID); - if (serverId.isAny()) { - serverId = serverIP; - } + const handleOffer = (serverIP, yourIP, options) => { + let serverId = optionToIP(options, dhcpOptions.OPTION_SERVER_ID); + if (serverId.isAny()) serverId = serverIP; sendPacket(socket, macAddress, dhcpPacket.packetType.REQUEST, serverId, yourIP); clientState = STATE_REQUEST_SENT; - } + }; - function handleAck(serverIP, yourIP, options) { + const handleAck = (serverIP, yourIP, options) => { clientState = STATE_ACK_RECEIVED; - var subnetMask = optionToIP(options, dhcpOptions.OPTION_SUBNET_MASK); - var routerIPs = optionToIPsArray(options, dhcpOptions.OPTION_ROUTER); - var dnsIPs = optionToIPsArray(options, dhcpOptions.OPTION_DOMAIN); return cb({ ip: yourIP, - mask: subnetMask, - routers: routerIPs, - dns: dnsIPs + mask: optionToIP(options, dhcpOptions.OPTION_SUBNET_MASK), + routers: optionToIPsArray(options, dhcpOptions.OPTION_ROUTER), + dns: optionToIPsArray(options, dhcpOptions.OPTION_DOMAIN), }); - } + }; - function parseMessage(serverIP, u8) { - if (!checkPacket(u8)) { - return; - } + const parseMessage = (serverIP, u8) => { + if (!checkPacket(u8)) return; - var options = dhcpPacket.getOptions(u8); - var messageTypeOption = dhcpOptions.find(options, dhcpOptions.OPTION_MESSAGE_TYPE, 1); + const options = dhcpPacket.getOptions(u8); + const messageTypeOption = dhcpOptions.find(options, dhcpOptions.OPTION_MESSAGE_TYPE, 1); - if (!messageTypeOption) { - return; - } + if (!messageTypeOption) return; - var messageType = messageTypeOption[0]; - var yourIP = dhcpPacket.getYourIP(u8); + const messageType = messageTypeOption[0]; + const yourIP = dhcpPacket.getYourIP(u8); // debug('GOT response', messageType, JSON.stringify(options)); - if (clientState === STATE_DISCOVER_SENT && - messageType === dhcpPacket.packetType.OFFER) { + if (clientState === STATE_DISCOVER_SENT && messageType === dhcpPacket.packetType.OFFER) { handleOffer(serverIP, yourIP, options); return; } @@ -133,14 +118,14 @@ function dhcpConfigure(intf, cb) { handleAck(serverIP, yourIP, options); return; } - } + }; - function err(e) { + /* const err = (e) => { clientState = STATE_ERROR; debug(e.stack); - } + }; */ - socket.onmessage = function(ip, port, u8) { + socket.onmessage = (ip, port, u8) => { debug('CLIENT OK', ip, port, u8); parseMessage(ip, u8); }; @@ -148,16 +133,16 @@ function dhcpConfigure(intf, cb) { socket.bindToInterface(intf, 68); sendPacket(socket, macAddress, dhcpPacket.packetType.DISCOVER, null, null); clientState = STATE_DISCOVER_SENT; -} +}; -runtime.net.onInterfaceAdded.add(function(intf) { +runtime.net.onInterfaceAdded.add((intf) => { debug('intf add'); - dhcpConfigure(intf, function(config) { + dhcpConfigure(intf, (config) => { debug('configure dhcp ok', JSON.stringify(config)); intf.configure(config.ip, config.mask); - var subnet = config.ip.and(config.mask); + const subnet = config.ip.and(config.mask); runtime.net.route.addSubnet(subnet, config.mask, null, intf); runtime.net.route.addDefault(config.routers[0], intf); intf.setNetworkEnabled(true); diff --git a/js/service/dns-resolver/index.js b/js/service/dns-resolver/index.js index 19a28b568..b9bfe7792 100644 --- a/js/service/dns-resolver/index.js +++ b/js/service/dns-resolver/index.js @@ -13,5 +13,5 @@ // limitations under the License. 'use strict'; -var DNSClient = require('../../component/dns-client'); +const DNSClient = require('../../component/dns-client'); module.exports = new DNSClient(); diff --git a/js/service/shell/index.js b/js/service/shell/index.js index d1c2f2114..0247b0179 100644 --- a/js/service/shell/index.js +++ b/js/service/shell/index.js @@ -15,20 +15,20 @@ 'use strict'; /* eslint-disable no-alert */ -var typeutils = require('typeutils'); -var assert = require('assert'); -var runtime = require('../../core'); -var commands = new Map(); -var stdio = runtime.stdio.defaultStdio; +const typeutils = require('typeutils'); +const assert = require('assert'); +const runtime = require('../../core'); +const commands = new Map(); +const stdio = runtime.stdio.defaultStdio; -exports.setCommand = function(name, cb) { +exports.setCommand = (name, cb) => { assert(typeutils.isString(name)); assert(typeutils.isFunction(cb)); commands.set(name, cb); }; -exports.runCommand = function(name, args, done) { - var opts = {}; +exports.runCommand = (name, args, done) => { + let opts = {}; assert(typeutils.isString(name)); @@ -39,25 +39,21 @@ exports.runCommand = function(name, args, done) { opts.args = opts.args || []; } - var stringargs = opts.args.join(' '); - + const stringargs = opts.args.join(' '); opts.stdio = opts.stdio || runtime.stdio.defaultStdio; - - commands.get(name)(stringargs, { - stdio: opts.stdio - }, done); + commands.get(name)(stringargs, { stdio: opts.stdio }, done); }; -function prompt() { +const prompt = () => { stdio.setColor('yellow'); stdio.write('$'); stdio.setColor('white'); stdio.write(' '); - stdio.readLine(function(text) { - var name = ''; - var args = ''; + stdio.readLine((text) => { + let name = ''; + let args = ''; - var split = text.indexOf(' '); + const split = text.indexOf(' '); if (split >= 0) { name = text.slice(0, split); args = text.slice(split); @@ -65,18 +61,15 @@ function prompt() { name = text; } - if (!name) { - return prompt(); - } + if (!name) return prompt(); if (commands.has(name)) { - return exports.runCommand(name, args.substr(1).split(' '), function(rescode) { - var printx = false; + return exports.runCommand(name, args.substr(1).split(' '), (rescode) => { + let printx = false; stdio.write('\n'); + // Since 0 == false and other numbers == true, just check for true. - if (rescode) { - printx = true; - } + if (rescode) printx = true; if (printx) { stdio.setColor('red'); @@ -88,9 +81,9 @@ function prompt() { } stdio.setColor('lightred'); - stdio.writeLine('Command "' + name + '" not found.'); + stdio.writeLine(`Command '${name}' not found.`); prompt(); }); -} +}; prompt(); diff --git a/js/utils/index.js b/js/utils/index.js index 2f6366096..07c488ae0 100644 --- a/js/utils/index.js +++ b/js/utils/index.js @@ -14,22 +14,12 @@ 'use strict'; -exports.getRandomUint32 = function() { - return Math.floor(Math.random() * 0x100000000) >>> 0; -}; - -exports.getRandomUint16 = function() { - return Math.floor(Math.random() * 0x10000) >>> 0; -}; - -exports.getRandomUint8 = function() { - return Math.floor(Math.random() * 0x100) >>> 0; -}; +exports.getRandomUint32 = () => Math.floor(Math.random() * 0x100000000) >>> 0; +exports.getRandomUint16 = () => Math.floor(Math.random() * 0x10000) >>> 0; +exports.getRandomUint8 = () => Math.floor(Math.random() * 0x100) >>> 0; /** * Get linearly increasing counter value in ms * (monotonic clock) */ -exports.timeNow = function() { - return Math.floor(performance.now()); -}; +exports.timeNow = () => Math.floor(performance.now()); From ae461ee92b81a591a917af25e62050bb14d921c1 Mon Sep 17 00:00:00 2001 From: Face Kapow Date: Sun, 10 Jul 2016 21:15:46 -0400 Subject: [PATCH 13/22] js/test/unit/buffers, js/test/unit/lib, js/test/unit/net, js/test/unit/*.js --- .eslintrc | 3 + js/test/unit/buffers/physical-address.js | 35 +-- js/test/unit/index.js | 15 +- js/test/unit/lib/buffer-builder.js | 41 +-- js/test/unit/lib/interface-mock.js | 19 +- js/test/unit/lib/packet-builder.js | 139 ++++----- js/test/unit/lib/test.js | 41 ++- js/test/unit/net/interface.js | 18 +- js/test/unit/net/ip4.js | 116 ++++--- js/test/unit/net/port-allocator.js | 114 +++---- js/test/unit/net/tcp-receive.js | 182 ++++++----- js/test/unit/net/tcp.js | 369 +++++++++++------------ 12 files changed, 493 insertions(+), 599 deletions(-) diff --git a/.eslintrc b/.eslintrc index 89c127ce2..364bc42af 100644 --- a/.eslintrc +++ b/.eslintrc @@ -24,6 +24,9 @@ rules: consistent-return: 0 no-underscore-dangle: 0 global-require: 0 + import/no-extraneous-dependencies: 0 + no-param-reassign: 1 + no-return-assign: 1 parserOptions: ecmaVersion: 6 diff --git a/js/test/unit/buffers/physical-address.js b/js/test/unit/buffers/physical-address.js index 82815ba6c..0f0c9aedd 100644 --- a/js/test/unit/buffers/physical-address.js +++ b/js/test/unit/buffers/physical-address.js @@ -13,21 +13,18 @@ // limitations under the License. 'use strict'; -var test = require('tape'); -var runtime = require('../../../core'); -var resources = require('../../../core/resources'); +const test = require('tape'); +const resources = require('../../../core/resources'); -test('buffer crosses page boundary', function(t) { +test('buffer crosses page boundary', (t) => { // allocate on page boundary - var buf = resources.memoryRange.block(0x3200000 - 12, 24).buffer(); - var u8 = new Uint8Array(buf); - for (var i = 0; i < u8.length; i++) { - u8[i] = i; - } + const buf = resources.memoryRange.block(0x3200000 - 12, 24).buffer(); + const u8 = new Uint8Array(buf); + for (let i = 0; i < u8.length; i++) u8[i] = i; - var addr = __SYSCALL.bufferAddress(u8); - var b1 = u8.subarray(0, addr[0]); - var b2 = u8.subarray(addr[0]); + const addr = __SYSCALL.bufferAddress(u8); + const b1 = u8.subarray(0, addr[0]); + const b2 = u8.subarray(addr[0]); t.equal(b1.length, 12); t.equal(b1[0], 0); t.equal(b2.length, 12); @@ -35,15 +32,13 @@ test('buffer crosses page boundary', function(t) { t.end(); }); -test('buffer does not cross page boundary', function(t) { - var buf = resources.memoryRange.block(0x3200000, 24).buffer(); - var u8 = new Uint8Array(buf); - for (var i = 0; i < u8.length; i++) { - u8[i] = i; - } +test('buffer does not cross page boundary', (t) => { + const buf = resources.memoryRange.block(0x3200000, 24).buffer(); + const u8 = new Uint8Array(buf); + for (let i = 0; i < u8.length; i++) u8[i] = i; - var addr = __SYSCALL.bufferAddress(u8); - var b1 = u8.subarray(0, addr[0]); + const addr = __SYSCALL.bufferAddress(u8); + const b1 = u8.subarray(0, addr[0]); t.equal(b1.length, u8.length); t.equal(addr[3], 0); t.end(); diff --git a/js/test/unit/index.js b/js/test/unit/index.js index 0a412af39..3030241b8 100644 --- a/js/test/unit/index.js +++ b/js/test/unit/index.js @@ -13,15 +13,14 @@ // limitations under the License. 'use strict'; -var runtime = require('../../'); -var test = require('tape'); -var stream = test.createStream(); -var shutdown = runtime.machine.shutdown; -stream.on('data', function(v) { - if (v[v.length - 1] === '\n') { - v = v.slice(0, -1); - } +const test = require('tape'); +const stream = test.createStream(); +const { shutdown } = require('../../').machine; + +stream.on('data', (vOpt) => { + let v = vOpt; + if (v[v.length - 1] === '\n') v = v.slice(0, -1); console.log(v); }); diff --git a/js/test/unit/lib/buffer-builder.js b/js/test/unit/lib/buffer-builder.js index 183cb9f4a..fa6b7d232 100644 --- a/js/test/unit/lib/buffer-builder.js +++ b/js/test/unit/lib/buffer-builder.js @@ -25,16 +25,16 @@ class BufferBuilder { this._checksumOffset = 0; } - uint8(value) { - value = (value >>> 0) & 0xff; + uint8(valueOpt) { + const value = (valueOpt >>> 0) & 0xff; this._p.push(value); this._repeatFirst = this._p.length - 1; this._repeatLast = this._p.length; return this; } - uint16(value) { - value = value >>> 0; + uint16(valueOpt) { + const value = valueOpt >>> 0; this.uint8((value >>> 8) & 0xff); this.uint8(value & 0xff); this._repeatFirst = this._p.length - 2; @@ -58,8 +58,8 @@ class BufferBuilder { return this.uint16(0); } - uint32(value) { - value = value >>> 0; + uint32(valueOpt) { + const value = valueOpt >>> 0; this.uint8((value >>> 24) & 0xff); this.uint8((value >>> 16) & 0xff); this.uint8((value >>> 8) & 0xff); @@ -69,28 +69,21 @@ class BufferBuilder { return this; } - align(alignment, value) { - alignment = alignment || 0; - value = value || 0; - while ((this._p.length % alignment) !== 0) { - this.uint8(value); - } + align(alignment = 0, value = 0) { + while ((this._p.length % alignment) !== 0) this.uint8(value); return this; } array(u8) { - for (var i = 0; i < u8.length; ++i) { - this.uint8(u8[i] & 0xff); - } + for (const item of u8) this.uint8(item & 0xff); this._repeatFirst = this._p.length - u8.length; this._repeatLast = this._p.length; return this; } - repeat(times) { - times = times || 0; - for (var t = 0; t < times; ++t) { - for (var i = this._repeatFirst; i < this._repeatLast; ++i) { + repeat(times = 0) { + for (let t = 0; t < times; ++t) { + for (let i = this._repeatFirst; i < this._repeatLast; ++i) { this._p.push(this._p[i]); } } @@ -98,13 +91,11 @@ class BufferBuilder { } buffer() { - var buf = new Uint8Array(this._p); + const buf = new Uint8Array(this._p); if (this._ck) { - if (this._checksumLast === 0) { - this._checksumLast = this._p.length; - } - var sub = buf.subarray(this._checksumFirst, this._checksumLast); - var cksum = this._ck(sub); + if (this._checksumLast === 0) this._checksumLast = this._p.length; + const sub = buf.subarray(this._checksumFirst, this._checksumLast); + const cksum = this._ck(sub); buf[this._checksumOffset] = (cksum >>> 8) & 0xff; buf[this._checksumOffset + 1] = cksum & 0xff; } diff --git a/js/test/unit/lib/interface-mock.js b/js/test/unit/lib/interface-mock.js index f09192055..4cbe64a67 100644 --- a/js/test/unit/lib/interface-mock.js +++ b/js/test/unit/lib/interface-mock.js @@ -14,18 +14,17 @@ 'use strict'; -var Interface = require('../../../core/net/interface'); -var MACAddress = require('../../../core/net/mac-address'); -var IP4Address = require('../../../core/net/ip4-address'); +const Interface = require('../../../core/net/interface'); +const MACAddress = require('../../../core/net/mac-address'); +const IP4Address = require('../../../core/net/ip4-address'); -module.exports = function(opts) { - opts = opts || {}; - var ip = opts.ip || new IP4Address(127, 0, 0, 1); - var mask = opts.mask || new IP4Address(255, 0, 0, 0); - var mac = opts.mac || new MACAddress(1, 2, 3, 4, 5, 6); - var intf = new Interface(mac); +module.exports = (opts = {}) => { + const ip = opts.ip || new IP4Address(127, 0, 0, 1); + const mask = opts.mask || new IP4Address(255, 0, 0, 0); + const mac = opts.mac || new MACAddress(1, 2, 3, 4, 5, 6); + const intf = new Interface(mac); intf.disableArp(); intf.configure(ip, mask); - intf.ontransmit = function() {}; + intf.ontransmit = () => {}; return intf; }; diff --git a/js/test/unit/lib/packet-builder.js b/js/test/unit/lib/packet-builder.js index 6ec2d6ea4..0ea078cb6 100644 --- a/js/test/unit/lib/packet-builder.js +++ b/js/test/unit/lib/packet-builder.js @@ -14,49 +14,41 @@ 'use strict'; -var BufferBuilder = require('./buffer-builder'); -var IP4Address = require('../../../core/net/ip4-address'); -var MACAddress = require('../../../core/net/mac-address'); -var checksum = require('../../../core/net/checksum'); - -function cksum(u8) { - return checksum(u8, 0, u8.length, 0); -} - -exports.createEthernetIP4 = function(protocol, payload, opts) { - opts = opts || {}; - var srcIP = IP4Address.parse(opts.srcIP) || new IP4Address(127, 0, 0, 1); - var destIP = IP4Address.parse(opts.destIP) || IP4Address.ANY; - var srcMAC = MACAddress.parse(opts.srcMAC) || MACAddress.ZERO; - var destMAC = MACAddress.parse(opts.destMAC) || MACAddress.ZERO; - var etherType = opts.etherType || 0x0800; - var tos = opts.tos || 0; - var id = opts.id || 0; - var dontFragment = opts.dontFragment || false; - var moreFragments = opts.moreFragments || false; - var fragmentOffsetBytes = opts.fragmentOffsetBytes || 0; - var ttl = opts.ttl || 64; - - var fragmentData = (opts.fragmentOffsetBytes >>> 3) & 0x1fff; +const BufferBuilder = require('./buffer-builder'); +const IP4Address = require('../../../core/net/ip4-address'); +const MACAddress = require('../../../core/net/mac-address'); +const checksum = require('../../../core/net/checksum'); + +const cksum = u8 => checksum(u8, 0, u8.length, 0); + +exports.createEthernetIP4 = (protocol, payload, opts = {}) => { + const srcIP = IP4Address.parse(opts.srcIP) || new IP4Address(127, 0, 0, 1); + const destIP = IP4Address.parse(opts.destIP) || IP4Address.ANY; + const srcMAC = MACAddress.parse(opts.srcMAC) || MACAddress.ZERO; + const destMAC = MACAddress.parse(opts.destMAC) || MACAddress.ZERO; + const etherType = opts.etherType || 0x0800; + const tos = opts.tos || 0; + const id = opts.id || 0; + const dontFragment = opts.dontFragment || false; + const moreFragments = opts.moreFragments || false; + const fragmentOffsetBytes = opts.fragmentOffsetBytes || 0; + const ttl = opts.ttl || 64; + + let fragmentData = (opts.fragmentOffsetBytes >>> 3) & 0x1fff; if ((fragmentData << 3) !== fragmentOffsetBytes) { - throw new Error('invalid fragment offset ' + fragmentOffsetBytes + ' byte(s)'); + throw new Error(`invalid fragment offset ${fragmentOffsetBytes} byte(s)`); } - if (dontFragment) { - fragmentData |= (1 << 14); - } - - if (moreFragments) { - fragmentData |= (1 << 13); - } + if (dontFragment) fragmentData |= (1 << 14); + if (moreFragments) fragmentData |= (1 << 13); - var protocolId = 0; + let protocolId = 0; switch (protocol) { - case 'icmp': protocolId = 0x01; break; - case 'tcp': protocolId = 0x06; break; - case 'udp': protocolId = 0x11; break; - default: throw new Error('unknown protocol'); + case 'icmp': protocolId = 0x01; break; + case 'tcp': protocolId = 0x06; break; + case 'udp': protocolId = 0x11; break; + default: throw new Error('unknown protocol'); } return new BufferBuilder() @@ -95,10 +87,9 @@ exports.createEthernetIP4 = function(protocol, payload, opts) { .buffer(); }; -exports.createUDP = function(payload, opts) { - opts = opts || {}; - var srcPort = opts.srcPort || 1; - var destPort = opts.destPort || 1; +exports.createUDP = (payload, opts = {}) => { + const srcPort = opts.srcPort || 1; + const destPort = opts.destPort || 1; return new BufferBuilder() .uint16(srcPort) @@ -109,10 +100,10 @@ exports.createUDP = function(payload, opts) { .buffer(); }; -exports.splitBuffer = function(u8, chunks) { - var results = []; - for (var i = 0; i < chunks.length; ++i) { - var chunkLength = chunks[i]; +exports.splitBuffer = (u8Opt, chunks) => { + let u8 = u8Opt; + const results = []; + for (const chunkLength of chunks) { if (u8.length < chunkLength) { throw new Error('need bigger buffer to produce chunks'); } @@ -120,60 +111,44 @@ exports.splitBuffer = function(u8, chunks) { u8 = u8.subarray(chunkLength); } - if (u8.length > 0) { - results.push(u8); - } + if (u8.length > 0) results.push(u8); return results; }; -exports.makeBuffer = function(length, firstValue) { - firstValue = firstValue || 0; - var u8 = new Uint8Array(length); - for (var i = 0; i < u8.length; ++i) { - u8[i] = firstValue++; - } +exports.makeBuffer = (length, firstValueOpt = 0) => { + let firstValue = firstValueOpt; + const u8 = new Uint8Array(length); + for (let i = 0; i < u8.length; ++i) u8[i] = firstValue++; return u8; }; -exports.buffersEqual = function(a, b) { - if (!(a instanceof Uint8Array) || !(b instanceof Uint8Array)) { - return false; - } - - if (a.length !== b.length) { - return false; - } +exports.buffersEqual = (a, b) => { + if (!(a instanceof Uint8Array) || !(b instanceof Uint8Array)) return false; + if (a.length !== b.length) return false; - for (var i = 0; i < a.length; ++i) { - if (a[i] !== b[i]) { - return false; - } - } + for (let i = 0; i < a.length; ++i) if (a[i] !== b[i]) return false; return true; }; -exports.makeBufferSlices = function(u8, slices) { - var results = []; - for (var i = 0; i < slices.length; ++i) { - results.push(u8.subarray(slices[i].offset, slices[i].offset + slices[i].len)); - } +exports.makeBufferSlices = (u8, slices) => { + const results = []; + for (const slice of slices) results.push(u8.subarray(slice.offset, slice.offset + slice.len)); return results; }; -exports.createFragmentedIP4 = function(opts, payloadLength, slices) { - if (payloadLength < 8) { - throw new Error('no space for udp header in fragmented buffers'); - } +exports.createFragmentedIP4 = (optsOpt, payloadLength, slices) => { + const opts = optsOpt; + if (payloadLength < 8) throw new Error('no space for udp header in fragmented buffers'); - var dataBuffer = exports.makeBuffer(payloadLength - 8); - var udp = exports.createUDP(dataBuffer, opts); - var fragments = exports.makeBufferSlices(udp, slices); + const dataBuffer = exports.makeBuffer(payloadLength - 8); + const udp = exports.createUDP(dataBuffer, opts); + const fragments = exports.makeBufferSlices(udp, slices); - var ip4fragments = []; - for (var i = 0; i < fragments.length; ++i) { - var fragment = fragments[i]; + const ip4fragments = []; + for (let i = 0; i < fragments.length; ++i) { + const fragment = fragments[i]; opts.fragmentOffsetBytes = slices[i].offset; opts.moreFragments = payloadLength !== slices[i].offset + slices[i].len; ip4fragments.push(exports.createEthernetIP4('udp', fragment, opts)); diff --git a/js/test/unit/lib/test.js b/js/test/unit/lib/test.js index c4caf0043..21c5f0654 100644 --- a/js/test/unit/lib/test.js +++ b/js/test/unit/lib/test.js @@ -14,11 +14,11 @@ 'use strict'; -var test = require('tape'); -var BufferBuilder = require('./buffer-builder'); +const test = require('tape'); +const BufferBuilder = require('./buffer-builder'); -test('build simple buffer', function(t) { - var b = new BufferBuilder() +test('build simple buffer', (t) => { + const b = new BufferBuilder() .uint8(5) .uint8(10) .uint32(0xCCAAFFEE) @@ -26,61 +26,60 @@ test('build simple buffer', function(t) { .uint16(0xAABB) .buffer(); - var ab = new Uint8Array([5, 10, 0xCC, 0xAA, 0xFF, 0xEE, 15, 0xAA, 0xBB]); + const ab = new Uint8Array([5, 10, 0xCC, 0xAA, 0xFF, 0xEE, 15, 0xAA, 0xBB]); t.deepEqual(b, ab); t.end(); }); -test('empty buffer', function(t) { - var b = new BufferBuilder() - .buffer(); +test('empty buffer', (t) => { + const b = new BufferBuilder().buffer(); - var ab = new Uint8Array(0); + const ab = new Uint8Array(0); t.deepEqual(b, ab); t.end(); }); -test('repeat uint8', function(t) { - var b = new BufferBuilder() +test('repeat uint8', (t) => { + const b = new BufferBuilder() .uint8(5) .uint8(10) .repeat(4) .uint8(15) .buffer(); - var ab = new Uint8Array([5, 10, 10, 10, 10, 10, 15]); + const ab = new Uint8Array([5, 10, 10, 10, 10, 10, 15]); t.deepEqual(b, ab); t.end(); }); -test('repeat uint16', function(t) { - var b = new BufferBuilder() +test('repeat uint16', (t) => { + const b = new BufferBuilder() .uint8(5) .uint16(0xFFAA) .repeat(2) .uint8(15) .buffer(); - var ab = new Uint8Array([5, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 15]); + const ab = new Uint8Array([5, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 15]); t.deepEqual(b, ab); t.end(); }); -test('repeat uint32', function(t) { - var b = new BufferBuilder() +test('repeat uint32', (t) => { + const b = new BufferBuilder() .uint8(5) .uint32(0xAABBCCDD) .repeat(1) .uint8(15) .buffer(); - var ab = new Uint8Array([5, 0xAA, 0xBB, 0xCC, 0xDD, 0xAA, 0xBB, 0xCC, 0xDD, 15]); + const ab = new Uint8Array([5, 0xAA, 0xBB, 0xCC, 0xDD, 0xAA, 0xBB, 0xCC, 0xDD, 15]); t.deepEqual(b, ab); t.end(); }); -test('align', function(t) { - var b = new BufferBuilder() +test('align', (t) => { + const b = new BufferBuilder() .uint8(5) .uint8(6) .uint8(7) @@ -90,7 +89,7 @@ test('align', function(t) { .align(4, 8) .buffer(); - var ab = new Uint8Array([5, 6, 7, 0, 0, 0, 0, 0, 1, 0, 2, 8]); + const ab = new Uint8Array([5, 6, 7, 0, 0, 0, 0, 0, 1, 0, 2, 8]); t.deepEqual(b, ab); t.end(); }); diff --git a/js/test/unit/net/interface.js b/js/test/unit/net/interface.js index 3e81263d9..6ba528577 100644 --- a/js/test/unit/net/interface.js +++ b/js/test/unit/net/interface.js @@ -14,16 +14,16 @@ 'use strict'; -var test = require('tape'); -var Interface = require('../../../core/net/interface'); -var MACAddress = require('../../../core/net/mac-address'); -var IP4Address = require('../../../core/net/ip4-address'); -var checksum = require('../../../core/net/checksum'); -var BufferBuilder = require('../lib/buffer-builder'); +const test = require('tape'); +const Interface = require('../../../core/net/interface'); +const MACAddress = require('../../../core/net/mac-address'); +// const IP4Address = require('../../../core/net/ip4-address'); +// const checksum = require('../../../core/net/checksum'); +// const BufferBuilder = require('../lib/buffer-builder'); -test('create interface', function(t) { - var intf = new Interface(MACAddress.ZERO); - intf.ontransmit = function() {}; +test('create interface', (t) => { + const intf = new Interface(MACAddress.ZERO); + intf.ontransmit = () => {}; t.end(); }); diff --git a/js/test/unit/net/ip4.js b/js/test/unit/net/ip4.js index 4158e3419..763cc6790 100644 --- a/js/test/unit/net/ip4.js +++ b/js/test/unit/net/ip4.js @@ -14,58 +14,56 @@ 'use strict'; -var test = require('tape'); -var runtime = require('../../..'); -var ip4fragments = require('../../../core/net/ip4-fragments'); -var interfaceMock = require('../lib/interface-mock'); -var packetBuilder = require('../lib/packet-builder'); +const test = require('tape'); +const runtime = require('../../..'); +const ip4fragments = require('../../../core/net/ip4-fragments'); +const interfaceMock = require('../lib/interface-mock'); +const packetBuilder = require('../lib/packet-builder'); -test('receive ip4 udp', function(t) { +test('receive ip4 udp', (t) => { t.timeoutAfter(1000); t.plan(3); - var intf = interfaceMock(); + const intf = interfaceMock(); - var socket = new runtime.net.UDPSocket(); + const socket = new runtime.net.UDPSocket(); socket.bind(65432); t.on('end', socket.close.bind(socket)); - socket.onmessage = function(ip, port, u8) { + socket.onmessage = (ip, port, u8) => { t.equal(ip.toString(), '33.44.55.66'); t.equal(port, 999); t.deepEqual(u8, new Uint8Array([1, 2, 3, 4, 5])); }; - var udp = packetBuilder.createUDP(new Uint8Array([1, 2, 3, 4, 5]), { srcPort: 999, destPort: 65432 }); - var ip4 = packetBuilder.createEthernetIP4('udp', udp, { srcIP: '33.44.55.66' }); + const udp = packetBuilder.createUDP(new Uint8Array([1, 2, 3, 4, 5]), { srcPort: 999, destPort: 65432 }); + const ip4 = packetBuilder.createEthernetIP4('udp', udp, { srcIP: '33.44.55.66' }); intf.receive(ip4); }); -function ipFragmentsTest(t, name, length, slices, order, norecv) { - t.test(name, function(t2) { +const ipFragmentsTest = (t, name, length, slices, order, norecv) => { + t.test(name, (t2) => { t2.timeoutAfter(1000); t2.plan(norecv ? 1 : 4); - var intf = interfaceMock(); - var socket = new runtime.net.UDPSocket(); + const intf = interfaceMock(); + const socket = new runtime.net.UDPSocket(); socket.bind(65432); - socket.onmessage = function(ip, port, u8) { + socket.onmessage = (ip, port, u8) => { t2.equal(ip.toString(), '33.44.55.66'); t2.equal(port, 999); t2.ok(packetBuilder.buffersEqual(u8, packetBuilder.makeBuffer(length))); socket.close(); }; - var fragments = packetBuilder.createFragmentedIP4({ + const fragments = packetBuilder.createFragmentedIP4({ srcPort: 999, destPort: 65432, - srcIP: '33.44.55.66' + srcIP: '33.44.55.66', }, length + 8 /* 8 bytes udp header */, slices); - order.forEach(function(index) { - intf.receive(fragments[index]); - }); + order.forEach((index) => intf.receive(fragments[index])); if (norecv) { t2.ok(intf.fragments.size > 0); @@ -73,15 +71,15 @@ function ipFragmentsTest(t, name, length, slices, order, norecv) { t2.equal(intf.fragments.size, 0); } }); -} +}; -test('receive ip4 fragmented non overlapped', function(t) { - var slices = [ +test('receive ip4 fragmented non overlapped', (t) => { + const slices = [ { offset: 0, len: 8 }, { offset: 8, len: 8 }, { offset: 16, len: 16 }, { offset: 32, len: 16 }, - { offset: 48, len: 24 } + { offset: 48, len: 24 }, ]; ipFragmentsTest(t, 'normal ordered', 64, slices, [0, 1, 2, 3, 4]); ipFragmentsTest(t, 'reverse ordered', 64, slices, [4, 3, 2, 1, 0]); @@ -91,13 +89,13 @@ test('receive ip4 fragmented non overlapped', function(t) { t.end(); }); -test('receive ip4 fragmented overlapped fragments', function(t) { - var slices = [ +test('receive ip4 fragmented overlapped fragments', (t) => { + const slices = [ { offset: 0, len: 8 }, { offset: 8, len: 8 }, { offset: 16, len: 16 }, { offset: 24, len: 16 }, - { offset: 24, len: 48 } + { offset: 24, len: 48 }, ]; ipFragmentsTest(t, 'fragments left edge overlap', 64, slices, [0, 1, 2, 3, 4]); ipFragmentsTest(t, 'fragments full and right edge overlap', 64, slices, [4, 3, 2, 1, 0]); @@ -109,8 +107,8 @@ test('receive ip4 fragmented overlapped fragments', function(t) { t.end(); }); -test('receive ip4 fragmented overlapped fragments ladder 1', function(t) { - var slices = [ +test('receive ip4 fragmented overlapped fragments ladder 1', (t) => { + const slices = [ { offset: 8, len: 64 }, // [ ========] { offset: 16, len: 56 }, // [ =======] { offset: 24, len: 48 }, // [ ======] @@ -119,7 +117,7 @@ test('receive ip4 fragmented overlapped fragments ladder 1', function(t) { { offset: 48, len: 24 }, // [ ===] { offset: 56, len: 16 }, // [ ==] { offset: 64, len: 8 }, // [ =] - { offset: 0, len: 8 } // [= ] (last piece) + { offset: 0, len: 8 }, // [= ] (last piece) ]; ipFragmentsTest(t, 'normal order', 64, slices, [0, 1, 2, 3, 4, 5, 6, 7, 8]); ipFragmentsTest(t, 'reverse order except last', 64, slices, [7, 6, 5, 4, 3, 2, 1, 0, 8]); @@ -130,8 +128,8 @@ test('receive ip4 fragmented overlapped fragments ladder 1', function(t) { t.end(); }); -test('receive ip4 fragmented overlapped fragments ladder 2', function(t) { - var slices = [ +test('receive ip4 fragmented overlapped fragments ladder 2', (t) => { + const slices = [ { offset: 0, len: 64 }, // [======== ] { offset: 0, len: 56 }, // [======= ] { offset: 0, len: 48 }, // [====== ] @@ -140,7 +138,7 @@ test('receive ip4 fragmented overlapped fragments ladder 2', function(t) { { offset: 0, len: 24 }, // [=== ] { offset: 0, len: 16 }, // [== ] { offset: 0, len: 8 }, // [= ] - { offset: 64, len: 8 } // [ =] (last piece) + { offset: 64, len: 8 }, // [ =] (last piece) ]; ipFragmentsTest(t, 'normal order', 64, slices, [0, 1, 2, 3, 4, 5, 6, 7, 8]); ipFragmentsTest(t, 'reverse order except last', 64, slices, [7, 6, 5, 4, 3, 2, 1, 0, 8]); @@ -151,14 +149,14 @@ test('receive ip4 fragmented overlapped fragments ladder 2', function(t) { t.end(); }); -test('receive ip4 fragmented overlapped fragments pyramid', function(t) { - var slices = [ +test('receive ip4 fragmented overlapped fragments pyramid', (t) => { + const slices = [ { offset: 8, len: 56 }, // [ ======= ] { offset: 16, len: 40 }, // [ ===== ] { offset: 24, len: 24 }, // [ === ] { offset: 32, len: 8 }, // [ = ] { offset: 64, len: 8 }, // [ =] - { offset: 0, len: 8 } // [= ] + { offset: 0, len: 8 }, // [= ] ]; ipFragmentsTest(t, 'normal order', 64, slices, [0, 1, 2, 3, 4, 5]); ipFragmentsTest(t, 'reverse order except last two 1', 64, slices, [3, 2, 1, 0, 4, 5]); @@ -168,14 +166,14 @@ test('receive ip4 fragmented overlapped fragments pyramid', function(t) { t.end(); }); -test('receive ip4 fragmented overlapped fragments small chunks', function(t) { - var slices = [ +test('receive ip4 fragmented overlapped fragments small chunks', (t) => { + const slices = [ { offset: 0, len: 8 }, // [= ] { offset: 16, len: 8 }, // [ = ] { offset: 32, len: 8 }, // [ = ] { offset: 48, len: 8 }, // [ = ] { offset: 64, len: 8 }, // [ =] - { offset: 8, len: 56 } // [ ======= ] + { offset: 8, len: 56 }, // [ ======= ] ]; ipFragmentsTest(t, 'normal order', 64, slices, [0, 1, 2, 3, 4, 5]); ipFragmentsTest(t, 'reverse order', 64, slices, [5, 4, 3, 2, 1, 0]); @@ -184,54 +182,48 @@ test('receive ip4 fragmented overlapped fragments small chunks', function(t) { t.end(); }); -test('receive ip4 fragmented max offset and size', function(t) { - var slices = [ +test('receive ip4 fragmented max offset and size', (t) => { + const slices = [ { offset: 0, len: 65528 }, - { offset: 65528, len: 7 } + { offset: 65528, len: 7 }, ]; ipFragmentsTest(t, 'max size', 65535 - 8, slices, [0, 1]); t.end(); }); -test('receive ip4 fragmented too big', function(t) { - var slices = [ +test('receive ip4 fragmented too big', (t) => { + const slices = [ { offset: 0, len: 65528 }, - { offset: 65528, len: 7 + 1 } + { offset: 65528, len: 7 + 1 }, ]; - ipFragmentsTest(t, 'max-size + 1', 65535 - 8 + 1, slices, [0, 1], true); + ipFragmentsTest(t, 'max-size + 1', (65535 - 8) + 1, slices, [0, 1], true); t.end(); }); -test('too many fragment queues and timeouts', function(t) { +test('too many fragment queues and timeouts', (t) => { t.timeoutAfter(1000); - var intf = interfaceMock(); - var originalNow = performance.now; + const intf = interfaceMock(); + const originalNow = performance.now; - performance.now = function() { - return 100; - }; + performance.now = () => 100; - for (var i = 0; i < 150; ++i) { - var fragments = packetBuilder.createFragmentedIP4({ + for (let i = 0; i < 150; ++i) { + const fragments = packetBuilder.createFragmentedIP4({ srcPort: 999, destPort: 65432, - srcIP: '33.44.55.' + String(i) + srcIP: `33.44.55.${String(i)}`, }, 64 + 8 /* 8 bytes udp header */, [{ offset: 0, len: 8 }]); intf.receive(fragments[0]); } t.equal(intf.fragments.size, 100); - performance.now = function() { - return 20100; - }; + performance.now = () => 20100; ip4fragments.tick(intf); t.equal(intf.fragments.size, 100); - performance.now = function() { - return 30100; - }; + performance.now = () => 30100; ip4fragments.tick(intf); t.equal(intf.fragments.size, 0); diff --git a/js/test/unit/net/port-allocator.js b/js/test/unit/net/port-allocator.js index b7003d366..fd3f0dc44 100644 --- a/js/test/unit/net/port-allocator.js +++ b/js/test/unit/net/port-allocator.js @@ -14,19 +14,17 @@ 'use strict'; -var test = require('tape'); -var assert = require('assert'); -var PortAllocator = require('../../../core/net/port-allocator'); -var EPHEMERAL_PORT_FIRST = 49152; +const test = require('tape'); +// const assert = require('assert'); +const PortAllocator = require('../../../core/net/port-allocator'); +const EPHEMERAL_PORT_FIRST = 49152; -test('ephemeral only: simple allocation', function(t) { - var allocator = new PortAllocator(); - var socket = {}; +test('ephemeral only: simple allocation', (t) => { + const allocator = new PortAllocator(); + const socket = {}; // alloc 10 ports - for (let i = 0; i < 10; ++i) { - t.equal(allocator.allocEphemeral(socket), EPHEMERAL_PORT_FIRST + i); - } + for (let i = 0; i < 10; ++i) t.equal(allocator.allocEphemeral(socket), EPHEMERAL_PORT_FIRST + i); // free first 3 ports allocator.free(EPHEMERAL_PORT_FIRST + 0); @@ -49,48 +47,38 @@ test('ephemeral only: simple allocation', function(t) { t.end(); }); -test('ephemeral only: allocate and free all ports', function(t) { - var allocator = new PortAllocator(); - var socket = {}; +test('ephemeral only: allocate and free all ports', (t) => { + const allocator = new PortAllocator(); + const socket = {}; - var next = 0; + let next = 0; for (;;) { - let port = allocator.allocEphemeral(socket); - - if (port === 0) { - break; - } + const port = allocator.allocEphemeral(socket); + if (port === 0) break; - if (port !== EPHEMERAL_PORT_FIRST + next++) { - t.equal(port, EPHEMERAL_PORT_FIRST + next++); - } + if (port !== EPHEMERAL_PORT_FIRST + next++) t.equal(port, EPHEMERAL_PORT_FIRST + next++); } t.equal(next, 16000); t.equal(allocator.allocatedCount, 16000); - while (next-- > 0) { - allocator.free(16000 - next - 1 + EPHEMERAL_PORT_FIRST); - } + while (next-- > 0) allocator.free(((16000 - next) - 1) + EPHEMERAL_PORT_FIRST); t.equal(allocator.allocatedCount, 0); t.equal(allocator._sockets.length, 0); for (;;) { - let port = allocator.allocEphemeral(socket); - - if (port === 0) { - break; - } + const port = allocator.allocEphemeral(socket); + if (port === 0) break; } t.equal(allocator.allocatedCount, 16000); t.end(); }); -test('ephemeral only: handle double free', function(t) { - var allocator = new PortAllocator(); - var socket = {}; +test('ephemeral only: handle double free', (t) => { + const allocator = new PortAllocator(); + const socket = {}; t.equal(allocator.allocatedCount, 0); t.equal(allocator.allocEphemeral(socket), EPHEMERAL_PORT_FIRST + 0); t.equal(allocator.allocEphemeral(socket), EPHEMERAL_PORT_FIRST + 1); @@ -103,9 +91,9 @@ test('ephemeral only: handle double free', function(t) { t.end(); }); -test('alloc port', function(t) { - var allocator = new PortAllocator(); - var socket = {}; +test('alloc port', (t) => { + const allocator = new PortAllocator(); + const socket = {}; t.equal(allocator.allocPort(80, socket), true); t.equal(allocator.allocatedCount, 1); t.equal(allocator.allocPort(8080, socket), true); @@ -117,31 +105,25 @@ test('alloc port', function(t) { t.end(); }); -test('directly alloc and free all ports', function(t) { - var allocator = new PortAllocator(); - var socket = {}; +test('directly alloc and free all ports', (t) => { + const allocator = new PortAllocator(); + const socket = {}; - for (let i = 1; i < 65536; ++i) { - allocator.allocPort(i, socket); - } + for (let i = 1; i < 65536; ++i) allocator.allocPort(i, socket); t.equal(allocator.allocatedCount, 65535); - for (let i = 1; i < 65536; ++i) { - allocator.free(i); - } + for (let i = 1; i < 65536; ++i) allocator.free(i); t.equal(allocator.allocatedCount, 0); t.end(); }); -test('directly alloc all ports and try to get ephemeral', function(t) { - var allocator = new PortAllocator(); - var socket = {}; +test('directly alloc all ports and try to get ephemeral', (t) => { + const allocator = new PortAllocator(); + const socket = {}; - for (let i = 1; i < 65536; ++i) { - allocator.allocPort(i, socket); - } + for (let i = 1; i < 65536; ++i) allocator.allocPort(i, socket); t.equal(allocator.allocatedCount, 65535); t.equal(allocator.allocEphemeral(socket), 0); @@ -160,17 +142,15 @@ test('directly alloc all ports and try to get ephemeral', function(t) { t.equal(allocator.allocEphemeral(socket), EPHEMERAL_PORT_FIRST); t.equal(allocator.allocatedCount, 65534); - for (let i = 1; i < 65536; ++i) { - allocator.free(i); - } + for (let i = 1; i < 65536; ++i) allocator.free(i); t.equal(allocator.allocatedCount, 0); t.end(); }); -test('cannot allocate port twice', function(t) { - var allocator = new PortAllocator(); - var socket = {}; +test('cannot allocate port twice', (t) => { + const allocator = new PortAllocator(); + const socket = {}; t.equal(allocator.allocatedCount, 0); t.equal(allocator.allocPort(EPHEMERAL_PORT_FIRST + 2, socket), true); t.equal(allocator.allocPort(EPHEMERAL_PORT_FIRST + 2, socket), false); @@ -185,9 +165,9 @@ test('cannot allocate port twice', function(t) { t.end(); }); -test('skip directly allocated ephemeral port', function(t) { - var allocator = new PortAllocator(); - var socket = {}; +test('skip directly allocated ephemeral port', (t) => { + const allocator = new PortAllocator(); + const socket = {}; t.equal(allocator.allocatedCount, 0); t.equal(allocator.allocPort(EPHEMERAL_PORT_FIRST, socket), true); t.equal(allocator.allocEphemeral(socket), EPHEMERAL_PORT_FIRST + 1); @@ -222,15 +202,15 @@ test('skip directly allocated ephemeral port', function(t) { t.end(); }); -test('lookups', function(t) { - var allocator = new PortAllocator(); - var socket1 = 'socket1'; - var socket2 = 'socket2'; - var socket3 = 'socket3'; +test('lookups', (t) => { + const allocator = new PortAllocator(); + const socket1 = 'socket1'; + const socket2 = 'socket2'; + const socket3 = 'socket3'; allocator.allocPort(EPHEMERAL_PORT_FIRST + 1, socket1); t.equal(allocator.lookup(EPHEMERAL_PORT_FIRST + 1), socket1); - var port1 = allocator.allocEphemeral(socket2); - var port2 = allocator.allocEphemeral(socket3); + const port1 = allocator.allocEphemeral(socket2); + const port2 = allocator.allocEphemeral(socket3); t.equal(port1, EPHEMERAL_PORT_FIRST + 0); t.equal(port2, EPHEMERAL_PORT_FIRST + 2); t.equal(allocator.lookup(port1), socket2); diff --git a/js/test/unit/net/tcp-receive.js b/js/test/unit/net/tcp-receive.js index a5d6caf5b..88b06fa23 100644 --- a/js/test/unit/net/tcp-receive.js +++ b/js/test/unit/net/tcp-receive.js @@ -14,113 +14,103 @@ 'use strict'; -var test = require('tape'); -var assert = require('assert'); -var TCPSocket = require('../../../core/net/tcp-socket'); +const test = require('tape'); +// const assert = require('assert'); +const TCPSocket = require('../../../core/net/tcp-socket'); -function receiveTest(opts, cb) { - var initialSequenceNumber = opts.initialSequenceNumber; - var bufs = opts.bufs; +const receiveTest = (opts, cb) => { + const initialSequenceNumber = opts.initialSequenceNumber; + const bufs = opts.bufs; - var socket = new TCPSocket(); - var next = 0; + const socket = new TCPSocket(); + let next = 0; - var count = 0; + let count = 0; for (let i = 0; i < bufs.length; ++i) { - let seqOffset = bufs[i].seqOffset; - let len = bufs[i].len; - var maxSeq = seqOffset + len; - if (maxSeq > count) { - count = maxSeq; - } + const seqOffset = bufs[i].seqOffset; + const len = bufs[i].len; + const maxSeq = seqOffset + len; + if (maxSeq > count) count = maxSeq; } - socket._transmit = function() {}; - socket.ondata = function(u8) { - for (var z = 0; z < u8.length; ++z) { + socket._transmit = () => {}; + socket.ondata = (u8) => { + for (let z = 0; z < u8.length; ++z) { if (u8[z] !== ++next) { - throw new Error('invalid byte received ' + u8[z] + ', expected ' + next); + throw new Error(`invalid byte received ${u8[z]}, expected ${next}`); } - if (next === count) { - cb(); - } + if (next === count) cb(); } }; socket._receiveWindowEdge = initialSequenceNumber; - var packets = []; + const packets = []; for (let i = 0; i < bufs.length; ++i) { - let seqOffset = bufs[i].seqOffset; - let len = bufs[i].len; + const seqOffset = bufs[i].seqOffset; + const len = bufs[i].len; - var b = new Uint8Array(len); - for (var j = 0; j < len; ++j) { - b[j] = seqOffset + j + 1; - } + const b = new Uint8Array(len); + for (let j = 0; j < len; ++j) b[j] = seqOffset + j + 1; packets.push({ seq: (initialSequenceNumber + seqOffset) >>> 0, - len: len, - buf: b + len, + buf: b, }); } - packets.forEach(function(pck) { - socket._insertReceiveQueue(pck.seq, pck.len, pck.buf); - }); + packets.forEach((pck) => socket._insertReceiveQueue(pck.seq, pck.len, pck.buf)); if (socket._receiveQueue.length !== 0) { console.log('='.repeat(50)); console.log('Receive queue:'); - socket._receiveQueue.map(function(x) { - console.log(`>> seq ${x[0]} len ${x[1]} buf ${JSON.stringify(x[2])}`); - }); + socket._receiveQueue.map((x) => console.log(`>> seq ${x[0]} len ${x[1]} buf ${JSON.stringify(x[2])}`)); console.log('='.repeat(50)); throw new Error('receive queue should be empty'); } -} +}; -function receiveTestBatch(t, seqList, bufs) { +const receiveTestBatch = (t, seqList, bufs) => { t.plan(3 * seqList.length); - seqList.forEach(function(seq) { - var reversed = bufs.slice(0); - var shuffled = bufs.slice(0); + seqList.forEach((seq) => { + const reversed = bufs.slice(0); + const shuffled = bufs.slice(0); reversed.reverse(); - shuffled.sort(function() { return .5 - Math.random(); }); + shuffled.sort(() => 0.5 - Math.random()); receiveTest({ initialSequenceNumber: seq, - bufs: bufs - }, function() { t.ok(true, 'default ordered, initial sequence number ' + seq); }); + bufs, + }, () => t.ok(true, `default ordered, initial sequence number ${seq}`)); receiveTest({ initialSequenceNumber: seq, - bufs: reversed - }, function() { t.ok(true, 'reverse ordered, initial sequence number ' + seq); }); + bufs: reversed, + }, () => t.ok(true, `reverse ordered, initial sequence number ${seq}`)); receiveTest({ initialSequenceNumber: seq, - bufs: shuffled - }, function() { t.ok(true, 'random ordered, initial sequence number ' + seq); }); + bufs: shuffled, + }, () => t.ok(true, `random ordered, initial sequence number ${seq}`)); }); -} +}; -var sequenceNumbersList = [ - 0, 1, Math.pow(2, 32) - 1, Math.pow(2, 32) - 2, Math.pow(2, 32) - 3, Math.pow(2, 32) - 9999 +const sequenceNumbersList = [ + 0, 1, Math.pow(2, 32) - 1, Math.pow(2, 32) - 2, Math.pow(2, 32) - 3, Math.pow(2, 32) - 9999, ]; -test('receive fast path (small sequence numbers)', function(t) { +test('receive fast path (small sequence numbers)', (t) => { receiveTest({ initialSequenceNumber: 1, bufs: [ { seqOffset: 0, len: 3 }, { seqOffset: 3, len: 2 }, - { seqOffset: 5, len: 1 } - ] + { seqOffset: 5, len: 1 }, + ], }, t.end.bind(t)); }); -test('receive fast path (large sequence numbers) #1', function(t) { +test('receive fast path (large sequence numbers) #1', (t) => { receiveTest({ initialSequenceNumber: Math.pow(2, 32) - 4, bufs: [ @@ -132,57 +122,57 @@ test('receive fast path (large sequence numbers) #1', function(t) { { seqOffset: 15, len: 1 }, { seqOffset: 16, len: 8 }, { seqOffset: 24, len: 1 }, - { seqOffset: 25, len: 1 } - ] + { seqOffset: 25, len: 1 }, + ], }, t.end.bind(t)); }); -test('receive fast path (large sequence numbers) #2', function(t) { +test('receive fast path (large sequence numbers) #2', (t) => { receiveTest({ initialSequenceNumber: Math.pow(2, 32) - 3, bufs: [ { seqOffset: 0, len: 3 }, { seqOffset: 3, len: 2 }, { seqOffset: 5, len: 1 }, - { seqOffset: 6, len: 4 } - ] + { seqOffset: 6, len: 4 }, + ], }, t.end.bind(t)); }); -test('receive fast path (large sequence numbers) #3', function(t) { +test('receive fast path (large sequence numbers) #3', (t) => { receiveTest({ initialSequenceNumber: Math.pow(2, 32) - 1, bufs: [ { seqOffset: 0, len: 1 }, { seqOffset: 1, len: 2 }, { seqOffset: 3, len: 3 }, - { seqOffset: 6, len: 4 } - ] + { seqOffset: 6, len: 4 }, + ], }, t.end.bind(t)); }); -test('receive fast path (large sequence numbers) #4', function(t) { +test('receive fast path (large sequence numbers) #4', (t) => { receiveTest({ initialSequenceNumber: Math.pow(2, 32) - 1, bufs: [ { seqOffset: 0, len: 10 }, - { seqOffset: 10, len: 1 } - ] + { seqOffset: 10, len: 1 }, + ], }, t.end.bind(t)); }); -test('receive reverse order (small sequence numbers) #1', function(t) { +test('receive reverse order (small sequence numbers) #1', (t) => { receiveTest({ initialSequenceNumber: 1, bufs: [ { seqOffset: 0, len: 3 }, { seqOffset: 3, len: 2 }, - { seqOffset: 5, len: 1 } - ].reverse() + { seqOffset: 5, len: 1 }, + ].reverse(), }, t.end.bind(t)); }); -test('receive reverse order (small sequence numbers) #2', function(t) { +test('receive reverse order (small sequence numbers) #2', (t) => { receiveTest({ initialSequenceNumber: 1, bufs: [ @@ -194,24 +184,24 @@ test('receive reverse order (small sequence numbers) #2', function(t) { { seqOffset: 15, len: 1 }, { seqOffset: 16, len: 8 }, { seqOffset: 24, len: 1 }, - { seqOffset: 25, len: 1 } - ].reverse() + { seqOffset: 25, len: 1 }, + ].reverse(), }, t.end.bind(t)); }); -test('receive reverse order (large sequence numbers) #1', function(t) { +test('receive reverse order (large sequence numbers) #1', (t) => { receiveTest({ initialSequenceNumber: Math.pow(2, 32) - 4, bufs: [ { seqOffset: 0, len: 1 }, { seqOffset: 1, len: 3 }, { seqOffset: 4, len: 5 }, - { seqOffset: 9, len: 2 } - ].reverse() + { seqOffset: 9, len: 2 }, + ].reverse(), }, t.end.bind(t)); }); -test('receive reverse order (large sequence numbers) #2', function(t) { +test('receive reverse order (large sequence numbers) #2', (t) => { receiveTest({ initialSequenceNumber: Math.pow(2, 32) - 4, bufs: [ @@ -223,46 +213,46 @@ test('receive reverse order (large sequence numbers) #2', function(t) { { seqOffset: 15, len: 1 }, { seqOffset: 16, len: 8 }, { seqOffset: 24, len: 1 }, - { seqOffset: 25, len: 1 } - ].reverse() + { seqOffset: 25, len: 1 }, + ].reverse(), }, t.end.bind(t)); }); -test('receive reverse order (large sequence numbers) #3', function(t) { +test('receive reverse order (large sequence numbers) #3', (t) => { receiveTest({ initialSequenceNumber: Math.pow(2, 32) - 3, bufs: [ { seqOffset: 0, len: 3 }, { seqOffset: 3, len: 2 }, { seqOffset: 5, len: 1 }, - { seqOffset: 6, len: 4 } - ].reverse() + { seqOffset: 6, len: 4 }, + ].reverse(), }, t.end.bind(t)); }); -test('receive reverse order (large sequence numbers) #4', function(t) { +test('receive reverse order (large sequence numbers) #4', (t) => { receiveTest({ initialSequenceNumber: Math.pow(2, 32) - 1, bufs: [ { seqOffset: 0, len: 1 }, { seqOffset: 1, len: 2 }, { seqOffset: 3, len: 3 }, - { seqOffset: 6, len: 4 } - ].reverse() + { seqOffset: 6, len: 4 }, + ].reverse(), }, t.end.bind(t)); }); -test('receive reverse order (large sequence numbers) #5', function(t) { +test('receive reverse order (large sequence numbers) #5', (t) => { receiveTest({ initialSequenceNumber: Math.pow(2, 32) - 1, bufs: [ { seqOffset: 0, len: 10 }, - { seqOffset: 10, len: 1 } - ].reverse() + { seqOffset: 10, len: 1 }, + ].reverse(), }, t.end.bind(t)); }); -test('receive mixed fast path and reverse order', function(t) { +test('receive mixed fast path and reverse order', (t) => { receiveTestBatch(t, sequenceNumbersList, [ { seqOffset: 25, len: 1 }, { seqOffset: 24, len: 1 }, @@ -272,11 +262,11 @@ test('receive mixed fast path and reverse order', function(t) { { seqOffset: 6, len: 4 }, { seqOffset: 10, len: 5 }, { seqOffset: 3, len: 2 }, - { seqOffset: 15, len: 1 } + { seqOffset: 15, len: 1 }, ]); }); -test('receive fast path duplicates', function(t) { +test('receive fast path duplicates', (t) => { receiveTestBatch(t, sequenceNumbersList, [ { seqOffset: 0, len: 1 }, { seqOffset: 0, len: 1 }, @@ -287,11 +277,11 @@ test('receive fast path duplicates', function(t) { { seqOffset: 3, len: 3 }, { seqOffset: 6, len: 4 }, { seqOffset: 6, len: 4 }, - { seqOffset: 6, len: 4 } + { seqOffset: 6, len: 4 }, ]); }); -test('receive overlapped duplicated data', function(t) { +test('receive overlapped duplicated data', (t) => { receiveTestBatch(t, sequenceNumbersList, [ { seqOffset: 0, len: 8 }, { seqOffset: 1, len: 7 }, @@ -300,11 +290,11 @@ test('receive overlapped duplicated data', function(t) { { seqOffset: 4, len: 4 }, { seqOffset: 5, len: 3 }, { seqOffset: 6, len: 2 }, - { seqOffset: 7, len: 1 } + { seqOffset: 7, len: 1 }, ]); }); -test('receive mixed overlapped duplicated and non-duplicated data', function(t) { +test('receive mixed overlapped duplicated and non-duplicated data', (t) => { receiveTestBatch(t, sequenceNumbersList, [ { seqOffset: 0, len: 8 }, { seqOffset: 1, len: 7 }, @@ -317,6 +307,6 @@ test('receive mixed overlapped duplicated and non-duplicated data', function(t) { seqOffset: 6, len: 2 }, { seqOffset: 7, len: 1 }, { seqOffset: 8, len: 5 }, - { seqOffset: 13, len: 2 } + { seqOffset: 13, len: 2 }, ]); }); diff --git a/js/test/unit/net/tcp.js b/js/test/unit/net/tcp.js index fad3ab028..614d52c44 100644 --- a/js/test/unit/net/tcp.js +++ b/js/test/unit/net/tcp.js @@ -12,96 +12,89 @@ // See the License for the specific language governing permissions and // limitations under the License. +/* eslint-disable no-param-reassign */ + 'use strict'; -var test = require('tape'); -var assert = require('assert'); -var TCPSocket = require('../../../core/net/tcp-socket'); -var TCPServerSocket = require('../../../core/net/tcp-server-socket'); -var IP4Address = require('../../../core/net/ip4-address'); -var tcpHeader = require('../../../core/net/tcp-header'); -var tcpSocketState = require('../../../core/net/tcp-socket-state'); - -function createTcpPacket(seq, ack, flags, window, u8data) { - window = window || 8192; - u8data = u8data || null; - var u8 = new Uint8Array(tcpHeader.headerLength + (u8data ? u8data.length : 0)); +const test = require('tape'); +const assert = require('assert'); +const TCPSocket = require('../../../core/net/tcp-socket'); +const TCPServerSocket = require('../../../core/net/tcp-server-socket'); +const IP4Address = require('../../../core/net/ip4-address'); +const tcpHeader = require('../../../core/net/tcp-header'); +const tcpSocketState = require('../../../core/net/tcp-socket-state'); + +const createTcpPacket = (seq, ack, flags, window = 8192, u8data = null) => { + const u8 = new Uint8Array(tcpHeader.headerLength + (u8data ? u8data.length : 0)); tcpHeader.write(u8, 0, 55, 55, seq, ack, flags, window); - if (u8data) { - u8.set(u8data, tcpHeader.headerLength); - } + if (u8data) u8.set(u8data, tcpHeader.headerLength); return u8; -} - -function getEstablished(cb) { - var socket = new TCPSocket(); - var txSeq = 1; - var rxSeq = 0; - - function SYN(seq, ack, flags, window, u8) { - assert.equal(flags, tcpHeader.FLAG_SYN); - assert.equal(u8, null); - socket._transmit = ACK; +}; - var synack = createTcpPacket(txSeq, seq + 1, tcpHeader.FLAG_SYN | tcpHeader.FLAG_ACK); - rxSeq = seq + 1; - socket._receive(synack, IP4Address.ANY, 45001, 0); - } +const getEstablished = (cb) => { + const socket = new TCPSocket(); + const txSeq = 1; + let rxSeq = 0; - function ACK(seq, ack, flags, window, u8) { + const ACK = (seq, ack, flags, window, u8) => { assert.equal(flags, tcpHeader.FLAG_ACK); assert.equal(u8, null); assert.equal(ack, txSeq + 1); - socket._transmit = function() {}; + socket._transmit = () => {}; socket._state = tcpSocketState.STATE_ESTABLISHED; - cb(socket, txSeq, rxSeq, function() { + cb(socket, txSeq, rxSeq, () => { socket._destroy(); }); - } + }; + + const SYN = (seq, ack, flags, window, u8) => { + assert.equal(flags, tcpHeader.FLAG_SYN); + assert.equal(u8, null); + socket._transmit = ACK; + + const synack = createTcpPacket(txSeq, seq + 1, tcpHeader.FLAG_SYN | tcpHeader.FLAG_ACK); + rxSeq = seq + 1; + socket._receive(synack, IP4Address.ANY, 45001, 0); + }; assert.equal(socket._state, tcpSocketState.STATE_CLOSED); socket._transmit = SYN; socket.open('127.0.0.1', 80); -} +}; -test('tcp connect', function(t) { +test('tcp connect', (t) => { t.plan(6); - var socket = new TCPSocket(); - var serverSeq = 1; + const socket = new TCPSocket(); + const serverSeq = 1; - function testSYN(seq, ack, flags, window, u8) { + const testACK = (seq, ack, flags, window, u8) => { + t.equal(flags, tcpHeader.FLAG_ACK, 'ACK flag set'); + t.equal(u8, null, 'no buffer in ACK packet'); + t.equal(ack, serverSeq + 1, 'seq number is valid'); + socket._destroy(); + }; + + const testSYN = (seq, ack, flags, window, u8) => { t.equal(flags, tcpHeader.FLAG_SYN, 'SYN flag set'); t.equal(u8, null, 'no buffer in SYN packet'); socket._transmit = testACK; - var synack = createTcpPacket(serverSeq, seq + 1, tcpHeader.FLAG_SYN | tcpHeader.FLAG_ACK); + const synack = createTcpPacket(serverSeq, seq + 1, tcpHeader.FLAG_SYN | tcpHeader.FLAG_ACK); socket._receive(synack, IP4Address.ANY, 45001, 0); - } - - function testACK(seq, ack, flags, window, u8) { - t.equal(flags, tcpHeader.FLAG_ACK, 'ACK flag set'); - t.equal(u8, null, 'no buffer in ACK packet'); - t.equal(ack, serverSeq + 1, 'seq number is valid'); - socket._destroy(); - } + }; t.equal(socket._state, tcpSocketState.STATE_CLOSED, 'initial state is closed'); socket._transmit = testSYN; socket.open('127.0.0.1', 80); }); -function transmitQueueItemLength(a) { - return a[3]; -} - -function transmitQueueItemBuffer(a) { - return a[4]; -} +const transmitQueueItemLength = (a) => a[3]; +const transmitQueueItemBuffer = (a) => a[4]; -test('tcp transmit queue', function(t) { - var socket = new TCPSocket(); - socket._transmit = function() {}; +test('tcp transmit queue', (t) => { + const socket = new TCPSocket(); + socket._transmit = () => {}; socket._state = tcpSocketState.STATE_ESTABLISHED; socket._transmitWindowSize = 20; socket.send(new Uint8Array(1)); @@ -116,87 +109,85 @@ test('tcp transmit queue', function(t) { t.end(); }); -test('tcp receive', function(t) { +test('tcp receive', (t) => { t.plan(4); - getEstablished(function(socket, txSeq, rxSeq, done) { + getEstablished((socket, txSeq, rxSeq, done) => { t.on('end', done); - var data = new Uint8Array([1, 2, 3]); + const data = new Uint8Array([1, 2, 3]); - socket.ondata = function(u8) { + socket.ondata = (u8) => { t.ok(u8 instanceof Uint8Array); t.equal(u8[0], 1); t.equal(u8[1], 2); t.equal(u8[2], 3); }; - var packet = createTcpPacket(txSeq + 1, rxSeq, tcpHeader.FLAG_PSH | tcpHeader.FLAG_ACK, 8192, data); + const packet = createTcpPacket(txSeq + 1, rxSeq, tcpHeader.FLAG_PSH | tcpHeader.FLAG_ACK, 8192, data); socket._receive(packet, IP4Address.ANY, 45001, 0); }); }); -test('tcp receive filter full duplicates', function(t) { +test('tcp receive filter full duplicates', (t) => { t.plan(4); - getEstablished(function(socket, txSeq, rxSeq, done) { + getEstablished((socket, txSeq, rxSeq, done) => { t.on('end', done); - var data = new Uint8Array([1, 2, 3]); + const data = new Uint8Array([1, 2, 3]); - socket.ondata = function(u8) { + socket.ondata = (u8) => { t.ok(u8 instanceof Uint8Array); t.equal(u8[0], 1); t.equal(u8[1], 2); t.equal(u8[2], 3); }; - var packet = createTcpPacket(txSeq + 1, rxSeq, tcpHeader.FLAG_PSH | tcpHeader.FLAG_ACK, 8192, data); + const packet = createTcpPacket(txSeq + 1, rxSeq, tcpHeader.FLAG_PSH | tcpHeader.FLAG_ACK, 8192, data); socket._receive(packet, IP4Address.ANY, 45001, 0); socket._receive(packet, IP4Address.ANY, 45001, 0); }); }); -test('tcp receive in order', function(t) { +test('tcp receive in order', (t) => { t.plan(8); - getEstablished(function(socket, txSeq, rxSeq, done) { + getEstablished((socket, txSeq, rxSeq, done) => { t.on('end', done); - var data1 = new Uint8Array([1, 2, 3]); - var data2 = new Uint8Array([4, 5, 6]); + const data1 = new Uint8Array([1, 2, 3]); + const data2 = new Uint8Array([4, 5, 6]); - var index = 0; - socket.ondata = function(u8) { + let index = 0; + socket.ondata = (u8) => { t.ok(u8 instanceof Uint8Array); t.equal(u8[0], ++index); t.equal(u8[1], ++index); t.equal(u8[2], ++index); }; - var packet1 = createTcpPacket(txSeq + 1, rxSeq, tcpHeader.FLAG_PSH | tcpHeader.FLAG_ACK, 8192, data1); - var packet2 = createTcpPacket(txSeq + 4, rxSeq, tcpHeader.FLAG_PSH | tcpHeader.FLAG_ACK, 8192, data2); + const packet1 = createTcpPacket(txSeq + 1, rxSeq, tcpHeader.FLAG_PSH | tcpHeader.FLAG_ACK, 8192, data1); + const packet2 = createTcpPacket(txSeq + 4, rxSeq, tcpHeader.FLAG_PSH | tcpHeader.FLAG_ACK, 8192, data2); socket._receive(packet2, IP4Address.ANY, 45001, 0); socket._receive(packet1, IP4Address.ANY, 45001, 0); }); }); -test('tcp receive in order and filter full duplicates', function(t) { +test('tcp receive in order and filter full duplicates', (t) => { t.plan(9); - getEstablished(function(socket, txSeq, rxSeq, done) { + getEstablished((socket, txSeq, rxSeq, done) => { t.on('end', done); - var data1 = new Uint8Array([1, 2, 3]); - var data2 = new Uint8Array([4, 5, 6]); + const data1 = new Uint8Array([1, 2, 3]); + const data2 = new Uint8Array([4, 5, 6]); - var lastAck = 0; - socket._transmit = function(seq, ack, flags, window, u8) { - lastAck = ack; - }; + let lastAck = 0; + socket._transmit = (seq, ack) => { lastAck = ack; }; - var index = 0; - socket.ondata = function(u8) { + let index = 0; + socket.ondata = (u8) => { t.ok(u8 instanceof Uint8Array); t.equal(u8[0], ++index); t.equal(u8[1], ++index); t.equal(u8[2], ++index); }; - var packet1 = createTcpPacket(txSeq + 1, rxSeq, tcpHeader.FLAG_PSH | tcpHeader.FLAG_ACK, 8192, data1); - var packet2 = createTcpPacket(txSeq + 4, rxSeq, tcpHeader.FLAG_PSH | tcpHeader.FLAG_ACK, 8192, data2); + const packet1 = createTcpPacket(txSeq + 1, rxSeq, tcpHeader.FLAG_PSH | tcpHeader.FLAG_ACK, 8192, data1); + const packet2 = createTcpPacket(txSeq + 4, rxSeq, tcpHeader.FLAG_PSH | tcpHeader.FLAG_ACK, 8192, data2); socket._receive(packet2, IP4Address.ANY, 45001, 0); socket._receive(packet2, IP4Address.ANY, 45001, 0); socket._receive(packet2, IP4Address.ANY, 45001, 0); @@ -206,30 +197,28 @@ test('tcp receive in order and filter full duplicates', function(t) { }); }); -test('tcp receive partial duplicates', function(t) { +test('tcp receive partial duplicates', (t) => { t.plan(9); - getEstablished(function(socket, txSeq, rxSeq, done) { + getEstablished((socket, txSeq, rxSeq, done) => { t.on('end', done); - var data1 = new Uint8Array([1, 2, 3]); - var data2 = new Uint8Array([3, 4, 5, 6]); - var data3 = new Uint8Array([2, 3]); + const data1 = new Uint8Array([1, 2, 3]); + const data2 = new Uint8Array([3, 4, 5, 6]); + const data3 = new Uint8Array([2, 3]); - var lastAck = 0; - socket._transmit = function(seq, ack, flags, window, u8) { - lastAck = ack; - }; + let lastAck = 0; + socket._transmit = (seq, ack) => { lastAck = ack; }; - var index = 0; - socket.ondata = function(u8) { + let index = 0; + socket.ondata = (u8) => { t.ok(u8 instanceof Uint8Array); t.equal(u8[0], ++index); t.equal(u8[1], ++index); t.equal(u8[2], ++index); }; - var packet1 = createTcpPacket(txSeq + 1, rxSeq, tcpHeader.FLAG_PSH | tcpHeader.FLAG_ACK, 8192, data1); - var packet2 = createTcpPacket(txSeq + 3, rxSeq, tcpHeader.FLAG_PSH | tcpHeader.FLAG_ACK, 8192, data2); - var packet3 = createTcpPacket(txSeq + 2, rxSeq, tcpHeader.FLAG_PSH | tcpHeader.FLAG_ACK, 8192, data3); + const packet1 = createTcpPacket(txSeq + 1, rxSeq, tcpHeader.FLAG_PSH | tcpHeader.FLAG_ACK, 8192, data1); + const packet2 = createTcpPacket(txSeq + 3, rxSeq, tcpHeader.FLAG_PSH | tcpHeader.FLAG_ACK, 8192, data2); + const packet3 = createTcpPacket(txSeq + 2, rxSeq, tcpHeader.FLAG_PSH | tcpHeader.FLAG_ACK, 8192, data3); socket._receive(packet2, IP4Address.ANY, 45001, 0); socket._receive(packet1, IP4Address.ANY, 45001, 0); socket._receive(packet3, IP4Address.ANY, 45001, 0); @@ -238,28 +227,26 @@ test('tcp receive partial duplicates', function(t) { }); }); -test('tcp receive partial duplicate with acked data and small window', function(t) { +test('tcp receive partial duplicate with acked data and small window', (t) => { t.plan(9); - getEstablished(function(socket, txSeq, rxSeq, done) { + getEstablished((socket, txSeq, rxSeq, done) => { t.on('end', done); - var data1 = new Uint8Array([1, 2, 3]); - var data2 = new Uint8Array([1, 2, 3, 4, 5, 6]); + const data1 = new Uint8Array([1, 2, 3]); + const data2 = new Uint8Array([1, 2, 3, 4, 5, 6]); - var lastAck = 0; - socket._transmit = function(seq, ack, flags, window, u8) { - lastAck = ack; - }; + let lastAck = 0; + socket._transmit = (seq, ack) => { lastAck = ack; }; - var index = 0; - socket.ondata = function(u8) { + let index = 0; + socket.ondata = (u8) => { t.ok(u8 instanceof Uint8Array); t.equal(u8[0], ++index); t.equal(u8[1], ++index); t.equal(u8[2], ++index); }; - var packet1 = createTcpPacket(txSeq + 1, rxSeq, tcpHeader.FLAG_PSH | tcpHeader.FLAG_ACK, 8192, data1); - var packet2 = createTcpPacket(txSeq + 1, rxSeq, tcpHeader.FLAG_PSH | tcpHeader.FLAG_ACK, 8192, data2); + const packet1 = createTcpPacket(txSeq + 1, rxSeq, tcpHeader.FLAG_PSH | tcpHeader.FLAG_ACK, 8192, data1); + const packet2 = createTcpPacket(txSeq + 1, rxSeq, tcpHeader.FLAG_PSH | tcpHeader.FLAG_ACK, 8192, data2); socket._receiveWindowSize = 6; socket._receive(packet1, IP4Address.ANY, 45001, 0); socket._receiveWindowSize = 3; @@ -268,13 +255,15 @@ test('tcp receive partial duplicate with acked data and small window', function( }); }); -test('tcp send FIN', function(t) { +test('tcp send FIN', (t) => { t.plan(6); - getEstablished(function(socket, txSeq, rxSeq, done) { + getEstablished((socket, txSeq, rxSeq, done) => { t.on('end', done); - function recvACKFIN(seq, ack, flags, window, u8) { - var packet; + const recvACK = (seq, ack, flags) => t.ok(flags & tcpHeader.FLAG_ACK); + + const recvACKFIN = (seq, ack, flags) => { + let packet; socket._transmit = recvACK; t.ok(flags & tcpHeader.FLAG_FIN); t.equal(socket._state, tcpSocketState.STATE_FIN_WAIT_1); @@ -284,11 +273,7 @@ test('tcp send FIN', function(t) { packet = createTcpPacket(txSeq, seq + 1, tcpHeader.FLAG_FIN); socket._receive(packet, IP4Address.ANY, 45001, 0); t.equal(socket._state, tcpSocketState.STATE_TIME_WAIT); - } - - function recvACK(seq, ack, flags, window, u8) { - t.ok(flags & tcpHeader.FLAG_ACK); - } + }; socket._transmit = recvACKFIN; socket.close(); @@ -296,26 +281,26 @@ test('tcp send FIN', function(t) { }); }); -test('tcp receive FIN', function(t) { +test('tcp receive FIN', (t) => { t.plan(5); - getEstablished(function(socket, txSeq, rxSeq, done) { + getEstablished((socket, txSeq, rxSeq, done) => { t.on('end', done); - function onRecvFIN(seq, ack, flags, window, u8) { - socket._transmit = function() {}; + const onRecvFIN = (seq, ack, flags) => { + socket._transmit = () => {}; t.ok(flags & tcpHeader.FLAG_ACK); - } + }; - function onSentFIN(seq, ack, flags, window, u8) { - socket._transmit = function() {}; + const onSentFIN = (seq, ack, flags) => { + socket._transmit = () => {}; t.ok(flags & tcpHeader.FLAG_FIN); t.equal(socket._state, tcpSocketState.STATE_LAST_ACK); - var packet = createTcpPacket(txSeq, seq + 1, tcpHeader.FLAG_ACK); + const packet = createTcpPacket(txSeq, seq + 1, tcpHeader.FLAG_ACK); socket._receive(packet, IP4Address.ANY, 45001, 0); - } + }; socket._transmit = onRecvFIN; - var packet = createTcpPacket(txSeq, rxSeq, tcpHeader.FLAG_FIN | tcpHeader.FLAG_ACK); + const packet = createTcpPacket(txSeq, rxSeq, tcpHeader.FLAG_FIN | tcpHeader.FLAG_ACK); socket._receive(packet, IP4Address.ANY, 45001, 0); t.equal(socket._state, tcpSocketState.STATE_CLOSE_WAIT); socket._transmit = onSentFIN; @@ -324,22 +309,22 @@ test('tcp receive FIN', function(t) { }); }); -test('tcp receive FIN, then send more data', function(t) { +test('tcp receive FIN, then send more data', (t) => { t.plan(4); - getEstablished(function(socket, txSeq, rxSeq, done) { + getEstablished((socket, txSeq, rxSeq, done) => { t.on('end', done); - function handleLastAck(seq, ack, flags, window, u8) { - socket._transmit = function() {}; + const handleLastAck = (seq, ack, flags) => { + socket._transmit = () => {}; t.ok(flags & tcpHeader.FLAG_FIN); t.equal(socket._state, tcpSocketState.STATE_LAST_ACK); - var packet = createTcpPacket(txSeq, seq + 1, tcpHeader.FLAG_ACK); + const packet = createTcpPacket(txSeq, seq + 1, tcpHeader.FLAG_ACK); socket._receive(packet, IP4Address.ANY, 45001, 0); - } + }; - socket._transmit = function() {}; + socket._transmit = () => {}; socket.send(new Uint8Array([1, 2, 3])); - var packet = createTcpPacket(txSeq, rxSeq, tcpHeader.FLAG_FIN | tcpHeader.FLAG_ACK); + const packet = createTcpPacket(txSeq, rxSeq, tcpHeader.FLAG_FIN | tcpHeader.FLAG_ACK); socket._receive(packet, IP4Address.ANY, 45001, 0); t.equal(socket._state, tcpSocketState.STATE_CLOSE_WAIT); socket.send(new Uint8Array([4, 5, 6])); @@ -350,91 +335,79 @@ test('tcp receive FIN, then send more data', function(t) { }); }); -test('cannot send more data after close', function(t) { - getEstablished(function(socket, txSeq, rxSeq, done) { +test('cannot send more data after close', (t) => { + getEstablished((socket, txSeq, rxSeq, done) => { t.on('end', done); - socket._transmit = function() {}; + socket._transmit = () => {}; socket.send(new Uint8Array([1, 2, 3])); socket.close(); - t.throws(function() { - socket.send(new Uint8Array([4, 5, 6])); - }); + t.throws(() => socket.send(new Uint8Array([4, 5, 6]))); t.end(); }); }); -test('server socket listening', function(t) { +test('server socket listening', (t) => { t.plan(6); - var socket = new TCPServerSocket(); + const socket = new TCPServerSocket(); - socket.onlisten = function(port) { + socket.onlisten = (port) => { t.equal(port, 100); t.ok(true); }; - socket.onclose = function() { - t.ok(true); - }; + socket.onclose = () => t.ok(true); socket.listen(100); t.equal(socket.localPort, 100); - t.throws(function() { - socket.localPort = 200; - }); + t.throws(() => { socket.localPort = 200; }); t.equal(socket.localPort, 100); socket.close(); }); -test('server socket can reuse port', function(t) { - var socket = new TCPServerSocket(); +test('server socket can reuse port', (t) => { + const socket = new TCPServerSocket(); socket.listen(200); socket.close(); socket.listen(200); socket.close(); - var socket2 = new TCPServerSocket(); + // const socket2 = new TCPServerSocket(); socket.listen(200); socket.close(); t.end(); }); -test('server socket can listen to random port', function(t) { +test('server socket can listen to random port', (t) => { t.plan(2); - var socket = new TCPServerSocket(); - socket.onlisten = function(port) { - t.ok(port > 0); - }; + const socket = new TCPServerSocket(); + socket.onlisten = (port) => t.ok(port > 0); socket.listen(0); t.ok(socket.localPort > 0); socket.close(); }); -test('localhost echo server', function(t) { +test('localhost echo server', (t) => { t.plan(8); - var server = new TCPServerSocket(); + const server = new TCPServerSocket(); server.listen(71); - server.onconnect = function(socket) { - socket.ondata = function(u8) { - socket.send(u8); - }; - socket.onend = function() { + server.onconnect = (socket) => { + socket.ondata = (u8) => socket.send(u8); + socket.onend = () => { socket.close(); server.close(); t.ok(true); }; }; - var client = new TCPSocket(); - var recvIndex = 0; - client.onopen = function() { + const client = new TCPSocket(); + let recvIndex = 0; + client.onopen = () => { client.send(new Uint8Array([1, 2, 3])); client.send(new Uint8Array([4, 5, 6])); }; - client.ondata = function(u8) { - for (var i = 0; i < u8.length; ++i) { - t.equal(u8[i], ++recvIndex); - } + client.ondata = (u8) => { + for (let i = 0; i < u8.length; ++i) t.equal(u8[i], ++recvIndex); - if (6 === recvIndex) { + if (recvIndex === 6) { client.close(); t.ok(true); } @@ -442,28 +415,26 @@ test('localhost echo server', function(t) { client.open('127.0.0.1', 71); }); -test('small sequence numbers', function(t) { +test('small sequence numbers', (t) => { t.plan(4); - var server = new TCPServerSocket(); + const server = new TCPServerSocket(); t.on('end', server.close.bind(server)); - var next = 0; - server.onconnect = function(socket) { - socket.ondata = function(u8) { - for (var i = 0; i < u8.length; ++i) { - t.equal(u8[i], ++next); - } + let next = 0; + server.onconnect = (socket) => { + socket.ondata = (u8) => { + for (let i = 0; i < u8.length; ++i) t.equal(u8[i], ++next); }; }; server.listen(71); - var client = new TCPSocket(); + const client = new TCPSocket(); client._transmitWindowEdge = 1; client._transmitPosition = 1; - client.onopen = function() { + client.onopen = () => { client.send(new Uint8Array([1, 2, 3])); client.close(); t.ok(true); @@ -472,28 +443,26 @@ test('small sequence numbers', function(t) { client.open('127.0.0.1', 71); }); -test('large sequence numbers and wrap around', function(t) { +test('large sequence numbers and wrap around', (t) => { t.plan(4); - var server = new TCPServerSocket(); + const server = new TCPServerSocket(); t.on('end', server.close.bind(server)); - var next = 0; - server.onconnect = function(socket) { - socket.ondata = function(u8) { - for (var i = 0; i < u8.length; ++i) { - t.equal(u8[i], ++next); - } + let next = 0; + server.onconnect = (socket) => { + socket.ondata = (u8) => { + for (let i = 0; i < u8.length; ++i) t.equal(u8[i], ++next); }; }; server.listen(71); - var client = new TCPSocket(); + const client = new TCPSocket(); client._transmitWindowEdge = Math.pow(2, 32) - 1; client._transmitPosition = Math.pow(2, 32) - 1; - client.onopen = function() { + client.onopen = () => { client.send(new Uint8Array([1, 2, 3])); client.close(); t.ok(true); @@ -501,3 +470,5 @@ test('large sequence numbers and wrap around', function(t) { client.open('127.0.0.1', 71); }); + +/* eslint-enable no-param-reassign */ From f94b97b6f117ee381a99afa3f099d9a2e1283104 Mon Sep 17 00:00:00 2001 From: Face Kapow Date: Sun, 10 Jul 2016 21:40:22 -0400 Subject: [PATCH 14/22] everything except js/core/net --- js/test/unit/platform/index.js | 28 ++++----- js/test/unit/random/index.js | 41 +++++++------ js/test/unit/script/index.js | 12 ++-- js/test/unit/timers/index.js | 18 +++--- js/test/unit/virtio/index.js | 103 ++++++++++++++++----------------- 5 files changed, 93 insertions(+), 109 deletions(-) diff --git a/js/test/unit/platform/index.js b/js/test/unit/platform/index.js index efa82d5c1..53d2f9c56 100644 --- a/js/test/unit/platform/index.js +++ b/js/test/unit/platform/index.js @@ -13,19 +13,19 @@ // limitations under the License. 'use strict'; -var test = require('tape'); +const test = require('tape'); /* global TextEncoder */ /* global TextDecoder */ -test('__SYSCALL.eval valid code', function(t) { +test('__SYSCALL.eval valid code', (t) => { global.a = 10; __SYSCALL.eval('a++'); t.equal(global.a, 11); t.end(); }); -test('__SYSCALL.eval invalid code', function(t) { +test('__SYSCALL.eval invalid code', (t) => { t.plan(1); try { @@ -35,7 +35,7 @@ test('__SYSCALL.eval invalid code', function(t) { } }); -test('__SYSCALL.eval throws', function(t) { +test('__SYSCALL.eval throws', (t) => { t.plan(2); try { @@ -46,23 +46,17 @@ test('__SYSCALL.eval throws', function(t) { } }); -test('TextEncoder and TextDecoder', function(t) { - var encoder = new TextEncoder('utf-8'); - var decoder = new TextDecoder('utf-8'); - var u8 = encoder.encode('test string'); +test('TextEncoder and TextDecoder', (t) => { + const encoder = new TextEncoder('utf-8'); + const decoder = new TextDecoder('utf-8'); + const u8 = encoder.encode('test string'); t.ok(u8 instanceof Uint8Array); t.equal(decoder.decode(u8), 'test string'); t.end(); }); -test('TextEncoder and TextDecoder call as a function', function(t) { - t.throws(function() { - TextEncoder('utf-8'); - }); - - t.throws(function() { - TextDecoder('utf-8'); - }); - +test('TextEncoder and TextDecoder call as a function', (t) => { + t.throws(() => TextEncoder('utf-8')); // eslint-disable-line new-cap + t.throws(() => TextDecoder('utf-8')); // eslint-disable-line new-cap t.end(); }); diff --git a/js/test/unit/random/index.js b/js/test/unit/random/index.js index 24d61b372..0a5255a39 100644 --- a/js/test/unit/random/index.js +++ b/js/test/unit/random/index.js @@ -13,23 +13,22 @@ // limitations under the License. 'use strict'; -var test = require('tape'); -var runtime = require('../../../core'); -var EntropySource = require('../../../core/random/entropy-source'); -test('EntropySource', function(t) { +const test = require('tape'); +const runtime = require('../../../core'); +const EntropySource = require('../../../core/random/entropy-source'); + +test('EntropySource', (t) => { t.timeoutAfter(1000); - var source = new EntropySource('test-source'); - source.ongetbytes = function(u8, cb) { - for (var i = 0; i < u8.length; ++i) { - u8[i] = 0x33 + i; - } + const source = new EntropySource('test-source'); + source.ongetbytes = (u8, cb) => { + for (let i = 0; i < u8.length; ++i) u8[i] = 0x33 + i; cb(); }; - var u8 = new Uint8Array(3); - source.getBytes(u8, function() { + const u8 = new Uint8Array(3); + source.getBytes(u8, () => { t.equal(u8[0], 0x33); t.equal(u8[1], 0x34); t.equal(u8[2], 0x35); @@ -37,33 +36,33 @@ test('EntropySource', function(t) { }); }); -test('getTrueRandomValues buffer', function(t) { +test('getTrueRandomValues buffer', (t) => { t.timeoutAfter(1000); - var u8 = new Uint8Array([0, 0, 0]); - runtime.random.getTrueRandomValues(u8, function(u8out) { + const u8 = new Uint8Array([0, 0, 0]); + runtime.random.getTrueRandomValues(u8, (u8out) => { t.equal(u8, u8out); t.end(); }); }); -test('getTrueRandomValues length', function(t) { +test('getTrueRandomValues length', (t) => { t.timeoutAfter(1000); - runtime.random.getTrueRandomValues(4, function(u8) { + runtime.random.getTrueRandomValues(4, (u8) => { t.ok(u8 instanceof Uint8Array); t.equal(u8.length, 4); t.end(); }); }); -test('getRandomValues buffer', function(t) { - var u8 = new Uint8Array([0, 0, 0]); - var u8out = runtime.random.getRandomValues(u8); +test('getRandomValues buffer', (t) => { + const u8 = new Uint8Array([0, 0, 0]); + const u8out = runtime.random.getRandomValues(u8); t.equal(u8, u8out); t.end(); }); -test('getRandomValues length', function(t) { - var u8 = runtime.random.getRandomValues(10); +test('getRandomValues length', (t) => { + const u8 = runtime.random.getRandomValues(10); t.ok(u8 instanceof Uint8Array); t.equal(u8.length, 10); t.end(); diff --git a/js/test/unit/script/index.js b/js/test/unit/script/index.js index 5e1466c1c..dee96b908 100644 --- a/js/test/unit/script/index.js +++ b/js/test/unit/script/index.js @@ -14,15 +14,15 @@ 'use strict'; -var test = require('tape'); +const test = require('tape'); -test('div by zero should not trigger CPU Divide Error exception', function(t) { - var v = 10; +test('div by zero should not trigger CPU Divide Error exception', (t) => { + const v = 10; t.equal(v / 0, Infinity); t.end(); }); -test('some math functions (in case they rely on embedded libc)', function(t) { +test('some math functions (in case they rely on embedded libc)', (t) => { t.equal(Math.abs(-45.4), 45.4); t.equal(Math.acos(-0.2).toFixed(2), '1.77'); t.equal((Math.atan2(1, 0) * 2).toFixed(2), '3.14'); @@ -33,12 +33,12 @@ test('some math functions (in case they rely on embedded libc)', function(t) { t.end(); }); -test('Math.random', function(t) { +test('Math.random', (t) => { t.equal(typeof Math.random(), 'number'); t.end(); }); -test('Date object', function(t) { +test('Date object', (t) => { t.equal(typeof new Date(), 'object'); t.end(); }); diff --git a/js/test/unit/timers/index.js b/js/test/unit/timers/index.js index 6a432381d..7d33d366d 100644 --- a/js/test/unit/timers/index.js +++ b/js/test/unit/timers/index.js @@ -14,18 +14,14 @@ 'use strict'; -var test = require('tape'); +const test = require('tape'); -test('setTimeout', function(t) { - setTimeout(t.end.bind(t), 0); -}); +test('setTimeout', t => setTimeout(t.end.bind(t), 0)); -test('setImmediate', function(t) { - setImmediate(t.end.bind(t)); -}); +test('setImmediate', t => setImmediate(t.end.bind(t))); -test('clearTimeout', function(t) { - var timer = setTimeout(function() { +test('clearTimeout', (t) => { + const timer = setTimeout(() => { t.fail('should not call callback'); throw new Error('should not call callback'); }, 0); @@ -33,8 +29,8 @@ test('clearTimeout', function(t) { setTimeout(t.end.bind(t), 0); }); -test('clearInterval', function(t) { - var timer = setInterval(function() { +test('clearInterval', (t) => { + const timer = setInterval(() => { t.fail('should not call callback'); throw new Error('should not call callback'); }, 0); diff --git a/js/test/unit/virtio/index.js b/js/test/unit/virtio/index.js index f0131b354..751422df3 100644 --- a/js/test/unit/virtio/index.js +++ b/js/test/unit/virtio/index.js @@ -13,49 +13,45 @@ // limitations under the License. 'use strict'; -var test = require('tape'); -var resources = require('../../../core/resources'); -var mem = __SYSCALL.allocDMA(); -var VRing = require('../../../driver/virtio/vring'); -var DescriptorTable = require('../../../driver/virtio/vring/descriptor-table'); +const test = require('tape'); +const resources = require('../../../core/resources'); +const mem = __SYSCALL.allocDMA(); +const VRing = require('../../../driver/virtio/vring'); +// const DescriptorTable = require('../../../driver/virtio/vring/descriptor-table'); -function clearBuffer(u8) { - for (var i = 0; i < u8.length; ++i) { - u8[i] = 0; - } -} +const clearBuffer = (u8) => { + for (let i = 0; i < u8.length; ++i) u8[i] = 0; +}; -function bufferWriteNumbers(u8, value) { - for (var i = 0; i < u8.length; ++i) { - u8[i] = i + value; - } +const bufferWriteNumbers = (u8, value) => { + for (let i = 0; i < u8.length; ++i) u8[i] = i + value; return u8; -} +}; -function getOnePageBuffer(index) { +const getOnePageBuffer = (index) => { index = index | 0; - var b = new Uint8Array(resources.memoryRange.block(0x2000000 + index * 22, 22).buffer()); + const b = new Uint8Array(resources.memoryRange.block(0x2000000 + (index * 22), 22).buffer()); clearBuffer(b); return b; -} +}; -function getTwoPageBuffer() { - var b = new Uint8Array(resources.memoryRange.block(0x2000000 - 12, 22).buffer()); +const getTwoPageBuffer = () => { + const b = new Uint8Array(resources.memoryRange.block(0x2000000 - 12, 22).buffer()); clearBuffer(b); return b; -} +}; -test('ring place one physical page buffer', function(t) { - var ring = new VRing(mem, 0, 16); +test('ring place one physical page buffer', (t) => { + const ring = new VRing(mem, 0, 16); t.equal(ring.descriptorTable.descriptorsAvailable, 16); t.equal(ring.availableRing.readIdx(), 0); ring.placeBuffers([getOnePageBuffer()], true); t.equal(ring.descriptorTable.descriptorsAvailable, 15); t.equal(ring.availableRing.readIdx(), 1); - var descId = ring.availableRing.readDescriptorAsDevice(0); + const descId = ring.availableRing.readDescriptorAsDevice(0); t.equal(descId, 0); - var firstDesc = ring.descriptorTable.get(descId); - var u8devWrite = ring.descriptorTable.getDescriptorBuffer(descId); + const firstDesc = ring.descriptorTable.get(descId); + const u8devWrite = ring.descriptorTable.getDescriptorBuffer(descId); bufferWriteNumbers(u8devWrite, 4); t.equal(firstDesc.flags, 2 /* no next flag, write only flag */); t.equal(firstDesc.len, 22); @@ -63,7 +59,7 @@ test('ring place one physical page buffer', function(t) { t.equal(ring.usedRing.readIdx(), 0); ring.usedRing.placeDescriptorAsDevice(descId, 5 /* bytes written */); t.equal(ring.usedRing.readIdx(), 1); - var u8 = ring.getBuffer(); + const u8 = ring.getBuffer(); t.equal(ring.descriptorTable.descriptorsAvailable, 16); t.ok(u8 instanceof Uint8Array); t.equal(u8.length, 5); @@ -75,24 +71,24 @@ test('ring place one physical page buffer', function(t) { t.end(); }); -test('ring place two physical page buffer', function(t) { - var ring = new VRing(mem, 0, 16); +test('ring place two physical page buffer', (t) => { + const ring = new VRing(mem, 0, 16); t.equal(ring.descriptorTable.descriptorsAvailable, 16); t.equal(ring.availableRing.readIdx(), 0); ring.placeBuffers([getTwoPageBuffer()], false); t.equal(ring.descriptorTable.descriptorsAvailable, 14); t.equal(ring.availableRing.readIdx(), 1); - var descId = ring.availableRing.readDescriptorAsDevice(0); + const descId = ring.availableRing.readDescriptorAsDevice(0); t.equal(descId, 0); - var firstDesc = ring.descriptorTable.get(descId); - var u8devWrite = ring.descriptorTable.getDescriptorBuffer(descId); + const firstDesc = ring.descriptorTable.get(descId); + const u8devWrite = ring.descriptorTable.getDescriptorBuffer(descId); bufferWriteNumbers(u8devWrite, 4); t.equal(firstDesc.flags, 1 /* next flag */); t.equal(firstDesc.len, 12); t.equal(firstDesc.next, 1); - var nextDescId = firstDesc.next; - var secondDesc = ring.descriptorTable.get(nextDescId); - var u8devWrite2 = ring.descriptorTable.getDescriptorBuffer(nextDescId); + const nextDescId = firstDesc.next; + const secondDesc = ring.descriptorTable.get(nextDescId); + const u8devWrite2 = ring.descriptorTable.getDescriptorBuffer(nextDescId); bufferWriteNumbers(u8devWrite2, 0); t.equal(secondDesc.flags, 0 /* no next flag */); t.equal(secondDesc.len, 10); @@ -100,7 +96,7 @@ test('ring place two physical page buffer', function(t) { t.equal(ring.usedRing.readIdx(), 0); ring.usedRing.placeDescriptorAsDevice(descId, 15 /* bytes written */); t.equal(ring.usedRing.readIdx(), 1); - var u8 = ring.getBuffer(); + const u8 = ring.getBuffer(); t.equal(ring.descriptorTable.descriptorsAvailable, 16); t.ok(u8 instanceof Uint8Array); t.equal(u8.length, 15); @@ -112,16 +108,17 @@ test('ring place two physical page buffer', function(t) { t.end(); }); -test('ring fill all slots and process', function(t) { - var ring = new VRing(mem, 0, 4 /* slots */); - var i, descId; +test('ring fill all slots and process', (t) => { + const ring = new VRing(mem, 0, 4 /* slots */); + let i; + let descId; t.ok(ring.placeBuffers([bufferWriteNumbers(getOnePageBuffer(0), 1)], true)); t.ok(ring.placeBuffers([bufferWriteNumbers(getOnePageBuffer(1), 2)], true)); t.ok(ring.placeBuffers([bufferWriteNumbers(getOnePageBuffer(2), 3)], true)); t.ok(ring.placeBuffers([bufferWriteNumbers(getOnePageBuffer(3), 4)], true)); t.equal(ring.placeBuffers([getOnePageBuffer(4)], true), false); - var currentIdx = ring.availableRing.readIdx(); + const currentIdx = ring.availableRing.readIdx(); t.equal(currentIdx, 4); for (i = 0; i < 3; ++i) { descId = ring.availableRing.readDescriptorAsDevice(i); @@ -141,34 +138,32 @@ test('ring fill all slots and process', function(t) { t.end(); }); -test('vring operation', function(t) { - var ring = new VRing(mem, 0, 4); - var devIndex = 0; - var count = 0; +test('vring operation', (t) => { + const ring = new VRing(mem, 0, 4); + let devIndex = 0; + let count = 0; - function devProcessAll() { - var bytesWritten = 3; - var descId = 0; + const devProcessAll = () => { + const bytesWritten = 3; + let descId = 0; while (devIndex < ring.availableRing.readIdx()) { descId = ring.availableRing.readDescriptorAsDevice(); ring.usedRing.placeDescriptorAsDevice(descId, bytesWritten); --count; ++devIndex; } - } + }; - function driverProcessAll() { + const driverProcessAll = () => { ring.fetchBuffers(null); while (ring.descriptorTable.descriptorsAvailable) { - if (!ring.placeBuffers([getOnePageBuffer(0)], true)) { - break; - } + if (!ring.placeBuffers([getOnePageBuffer(0)], true)) break; ++count; } - } + }; t.equal(count, 0); - for (var i = 0; i < 4; ++i) { + for (let i = 0; i < 4; ++i) { driverProcessAll(); t.ok(count > 0); devProcessAll(); From 0562cb0600ece705f10a10115079c41d2707d353 Mon Sep 17 00:00:00 2001 From: Face Kapow Date: Mon, 11 Jul 2016 17:51:31 -0400 Subject: [PATCH 15/22] Finish linting! :tada: --- .eslintrc | 2 + docs/code-style-exceptions.md | 31 +- js/core/net/arp-header.js | 64 ++-- js/core/net/arp-resolver.js | 87 +++--- js/core/net/arp-transmit.js | 16 +- js/core/net/checksum.js | 34 +- js/core/net/ethernet.js | 40 +-- js/core/net/icmp-header.js | 32 +- js/core/net/icmp-transmit.js | 28 +- js/core/net/icmp.js | 46 ++- js/core/net/index.js | 34 +- js/core/net/interface.js | 194 ++++++------ js/core/net/interfaces.js | 30 +- js/core/net/ip4-address.js | 115 ++++--- js/core/net/ip4-fragments.js | 163 ++++------ js/core/net/ip4-header.js | 72 ++--- js/core/net/ip4-receive.js | 16 +- js/core/net/ip4.js | 38 ++- js/core/net/loopback.js | 22 +- js/core/net/mac-address.js | 84 +++-- js/core/net/net-error.js | 22 +- js/core/net/ping.js | 70 ++--- js/core/net/port-allocator.js | 54 ++-- js/core/net/port-utils.js | 7 +- js/core/net/route.js | 60 ++-- js/core/net/tcp-hash.js | 8 +- js/core/net/tcp-header.js | 44 +-- js/core/net/tcp-server-socket.js | 31 +- js/core/net/tcp-socket-state.js | 27 +- js/core/net/tcp-socket.js | 516 +++++++++++++------------------ js/core/net/tcp-timer.js | 26 +- js/core/net/tcp-transmit.js | 38 +-- js/core/net/tcp.js | 38 +-- js/core/net/udp-header.js | 22 +- js/core/net/udp-socket.js | 60 ++-- js/core/net/udp-transmit.js | 28 +- js/core/net/udp.js | 38 +-- js/test/unit/virtio/index.js | 4 +- 38 files changed, 962 insertions(+), 1279 deletions(-) diff --git a/.eslintrc b/.eslintrc index 364bc42af..28d038bf0 100644 --- a/.eslintrc +++ b/.eslintrc @@ -27,6 +27,8 @@ rules: import/no-extraneous-dependencies: 0 no-param-reassign: 1 no-return-assign: 1 + new-cap: 1 + no-console: 0 parserOptions: ecmaVersion: 6 diff --git a/docs/code-style-exceptions.md b/docs/code-style-exceptions.md index b1be5d0e4..f8d30b588 100644 --- a/docs/code-style-exceptions.md +++ b/docs/code-style-exceptions.md @@ -15,7 +15,7 @@ You can still use `for-in`, just be sure you know [the catch](https://developer. ## Using 'dangling' underscores You *can* use 'dangling' underscores to denote a private member on an object or class. -Some APIs were written before this style was adopted which use underscores for private members and probably won't be changed for compatability. +Some APIs were written before this style was adopted which use underscores for private members and probably won't be changed for compatibility. However, for any new APIs, it'd be preferred to use a [`Symbol`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol) instead, like: ```js @@ -33,4 +33,31 @@ class Demo { ## Using `get` and `set` -You can (and should) use ES6 `get` and `set`, it's already used in various runtime.js APIs. +You can (and should) use ES6 `get` and `set` in new APIs, it's already used in various runtime.js APIs. + +## Assigning to functions parameters + +You cannot *reassign* functions parameters, but you can assign to *properties of* function parameters. +```js +// yes +const demo = (myObject) => { + myObject.someProperty = 'my value'; + // ... +} + +// no +const demo = (myUint8Array) => { + myUint8Array = { + someProperty: 'my value' + }; + // ... +} +``` + +If you get this warning, it's ok: + +> Assignment to **property of** function parameter 'parameter-name' + +But this is not: + +> Assignment to function parameter 'parameter-name' diff --git a/js/core/net/arp-header.js b/js/core/net/arp-header.js index 8c46f2d95..4ce4697e8 100644 --- a/js/core/net/arp-header.js +++ b/js/core/net/arp-header.js @@ -13,53 +13,43 @@ // limitations under the License. 'use strict'; -var u8view = require('u8-view'); -var IP4Address = require('./ip4-address'); -var MACAddress = require('./mac-address'); +const u8view = require('u8-view'); +const IP4Address = require('./ip4-address'); +const MACAddress = require('./mac-address'); -var HARDWARE_TYPE_ETHERNET = 1; -var PROTOCOL_IP4 = 0x0800; +const HARDWARE_TYPE_ETHERNET = 1; +const PROTOCOL_IP4 = 0x0800; exports.OPERATION_REQEUST = 1; exports.OPERATION_REPLY = 2; -exports.getSrcMAC = function(u8, headerOffset) { - return new MACAddress(u8[headerOffset + 8], - u8[headerOffset + 9], - u8[headerOffset + 10], - u8[headerOffset + 11], - u8[headerOffset + 12], - u8[headerOffset + 13]); -}; +exports.getSrcMAC = (u8, headerOffset) => (new MACAddress(u8[headerOffset + 8], + u8[headerOffset + 9], + u8[headerOffset + 10], + u8[headerOffset + 11], + u8[headerOffset + 12], + u8[headerOffset + 13])); -exports.getSrcIP = function(u8, headerOffset) { - return new IP4Address(u8[headerOffset + 14], - u8[headerOffset + 15], - u8[headerOffset + 16], - u8[headerOffset + 17]); -}; +exports.getSrcIP = (u8, headerOffset) => (new IP4Address(u8[headerOffset + 14], + u8[headerOffset + 15], + u8[headerOffset + 16], + u8[headerOffset + 17])); -exports.getTargetMAC = function(u8, headerOffset) { - return new MACAddress(u8[headerOffset + 18], - u8[headerOffset + 19], - u8[headerOffset + 20], - u8[headerOffset + 21], - u8[headerOffset + 22], - u8[headerOffset + 23]); -}; +exports.getTargetMAC = (u8, headerOffset) => (new MACAddress(u8[headerOffset + 18], + u8[headerOffset + 19], + u8[headerOffset + 20], + u8[headerOffset + 21], + u8[headerOffset + 22], + u8[headerOffset + 23])); -exports.getTargetIP = function(u8, headerOffset) { - return new IP4Address(u8[headerOffset + 24], - u8[headerOffset + 25], - u8[headerOffset + 26], - u8[headerOffset + 27]); -}; +exports.getTargetIP = (u8, headerOffset) => (new IP4Address(u8[headerOffset + 24], + u8[headerOffset + 25], + u8[headerOffset + 26], + u8[headerOffset + 27])); -exports.getOperation = function(u8, headerOffset) { - return u8view.getUint16BE(u8, headerOffset + 6); -}; +exports.getOperation = (u8, headerOffset) => u8view.getUint16BE(u8, headerOffset + 6); -exports.write = function(u8, headerOffset, operation, srcMAC, srcIP, targetMAC, targetIP) { +exports.write = (u8, headerOffset, operation, srcMAC, srcIP, targetMAC, targetIP) => { u8view.setUint16BE(u8, headerOffset, HARDWARE_TYPE_ETHERNET); u8view.setUint16BE(u8, headerOffset + 2, PROTOCOL_IP4); u8[headerOffset + 4] = 6; diff --git a/js/core/net/arp-resolver.js b/js/core/net/arp-resolver.js index da509b917..f419e4493 100644 --- a/js/core/net/arp-resolver.js +++ b/js/core/net/arp-resolver.js @@ -13,55 +13,52 @@ // limitations under the License. 'use strict'; -var assert = require('assert'); -var MACAddress = require('./mac-address'); -var IP4Address = require('./ip4-address'); -var arpTransmit = require('./arp-transmit'); -var arpHeader = require('./arp-header'); +// const assert = require('assert'); +const MACAddress = require('./mac-address'); +const IP4Address = require('./ip4-address'); +const arpTransmit = require('./arp-transmit'); +const arpHeader = require('./arp-header'); -function ARPResolver(intf) { - this.intf = intf; - this.table = new Map(); -} - -ARPResolver.prototype.receive = function(u8, headerOffset) { - var operation = arpHeader.getOperation(u8, headerOffset); - var srcMAC = arpHeader.getSrcMAC(u8, headerOffset); - var srcIP = arpHeader.getSrcIP(u8, headerOffset); - var targetMAC = arpHeader.getTargetMAC(u8, headerOffset); - var targetIP = arpHeader.getTargetIP(u8, headerOffset); - var selfIP = this.intf.ipAddr; +class ARPResolver { + constructor(intf) { + this.intf = intf; + this.table = new Map(); + } + receive(u8, headerOffset) { + const operation = arpHeader.getOperation(u8, headerOffset); + const srcMAC = arpHeader.getSrcMAC(u8, headerOffset); + const srcIP = arpHeader.getSrcIP(u8, headerOffset); + const targetMAC = arpHeader.getTargetMAC(u8, headerOffset); + const targetIP = arpHeader.getTargetIP(u8, headerOffset); + const selfIP = this.intf.ipAddr; - debug('recv ARP', operation, srcMAC, srcIP, targetMAC, targetIP, selfIP); + debug('recv ARP', operation, srcMAC, srcIP, targetMAC, targetIP, selfIP); - switch (operation) { - case arpHeader.OPERATION_REQEUST: - // Somebody requested this machine IP - if (!selfIP.equals(IP4Address.ANY) && selfIP.equals(targetIP)) { - this.reply(srcMAC, targetIP); + switch (operation) { + case arpHeader.OPERATION_REQEUST: + // Somebody requested this machine IP + if (!selfIP.equals(IP4Address.ANY) && selfIP.equals(targetIP)) this.reply(srcMAC, targetIP); + break; + case arpHeader.OPERATION_REPLY: + this.table.set(srcIP.hash(), srcMAC); + break; + default: + break; } - break; - case arpHeader.OPERATION_REPLY: - var key = srcIP.hash(); - this.table.set(key, srcMAC); - break; } -}; - -ARPResolver.prototype.request = function(targetIP) { - arpTransmit(this.intf, arpHeader.OPERATION_REQEUST, - this.intf.macAddr, this.intf.ipAddr, - MACAddress.ZERO, targetIP); -}; - -ARPResolver.prototype.reply = function(targetMAC, targetIP) { - arpTransmit(this.intf, arpHeader.OPERATION_REPLY, - this.intf.macAddr, this.intf.ipAddr, - targetMAC, targetIP); -}; - -ARPResolver.prototype.get = function(ip) { - return this.table.get(ip.hash()) || null; -}; + request(targetIP) { + arpTransmit(this.intf, arpHeader.OPERATION_REQEUST, + this.intf.macAddr, this.intf.ipAddr, + MACAddress.ZERO, targetIP); + } + reply(targetMAC, targetIP) { + arpTransmit(this.intf, arpHeader.OPERATION_REPLY, + this.intf.macAddr, this.intf.ipAddr, + targetMAC, targetIP); + } + get(ip) { + return this.table.get(ip.hash()) || null; + } +} module.exports = ARPResolver; diff --git a/js/core/net/arp-transmit.js b/js/core/net/arp-transmit.js index acbe79da4..c88d16f46 100644 --- a/js/core/net/arp-transmit.js +++ b/js/core/net/arp-transmit.js @@ -13,15 +13,15 @@ // limitations under the License. 'use strict'; -var ethernet = require('./ethernet'); -var arpHeader = require('./arp-header'); -var MACAddress = require('./mac-address'); +const ethernet = require('./ethernet'); +const arpHeader = require('./arp-header'); +const MACAddress = require('./mac-address'); -module.exports = function(intf, operation, srcMAC, srcIP, targetMAC, targetIP) { - var ethOffset = intf.bufferDataOffset; - var arpOffset = ethOffset + ethernet.headerLength; - var len = arpOffset + arpHeader.headerLength; - var u8 = new Uint8Array(len); +module.exports = (intf, operation, srcMAC, srcIP, targetMAC, targetIP) => { + const ethOffset = intf.bufferDataOffset; + const arpOffset = ethOffset + ethernet.headerLength; + const len = arpOffset + arpHeader.headerLength; + const u8 = new Uint8Array(len); ethernet.write(u8, ethOffset, MACAddress.BROADCAST, intf.macAddr, ethernet.ETHERTYPE_ARP); arpHeader.write(u8, arpOffset, operation, srcMAC, srcIP, targetMAC, targetIP); diff --git a/js/core/net/checksum.js b/js/core/net/checksum.js index 3be17409c..82d91abef 100644 --- a/js/core/net/checksum.js +++ b/js/core/net/checksum.js @@ -14,40 +14,32 @@ 'use strict'; -function checksum(u8, offset, len, extraSum) { - var count = len >>> 1; - var acc = (extraSum >>> 0); - for (var i = 0; i < count; ++i) { - acc += (u8[offset + i * 2] << 8) + u8[offset + i * 2 + 1]; - } +const checksum = (u8, offset, len, extraSum) => { + const count = len >>> 1; + let acc = (extraSum >>> 0); + for (let i = 0; i < count; ++i) acc += (u8[offset + (i * 2)] << 8) + u8[(offset + (i * 2)) + 1]; - if (count * 2 !== len) { - acc += u8[offset + count * 2] << 8; - } + if (count * 2 !== len) acc += u8[offset + (count * 2)] << 8; acc = (acc & 0xffff) + (acc >>> 16); acc += (acc >>> 16); return ((~acc) & 0xffff) >>> 0; -} +}; module.exports = checksum; -module.exports.buffer = function(u8, offset, len) { - var count = len >>> 1; - var acc = 0; - for (var i = 0; i < count; ++i) { - acc += (u8[offset + i * 2] << 8) + u8[offset + i * 2 + 1]; - } +module.exports.buffer = (u8, offset, len) => { + const count = len >>> 1; + let acc = 0; + for (let i = 0; i < count; ++i) acc += (u8[offset + (i * 2)] << 8) + u8[(offset + (i * 2)) + 1]; - if (count * 2 !== len) { - acc += u8[offset + count * 2] << 8; - } + if (count * 2 !== len) acc += u8[offset + (count * 2)] << 8; return acc; }; -module.exports.result = function(acc) { - acc = (acc & 0xffff) + (acc >>> 16); +module.exports.result = (accOpt) => { + let acc = (accOpt & 0xffff) + (accOpt >>> 16); acc += (acc >>> 16); return ((~acc) & 0xffff) >>> 0; }; diff --git a/js/core/net/ethernet.js b/js/core/net/ethernet.js index 0a0dc97de..528d935bc 100644 --- a/js/core/net/ethernet.js +++ b/js/core/net/ethernet.js @@ -13,36 +13,30 @@ // limitations under the License. 'use strict'; -var assert = require('assert'); -var MACAddress = require('./mac-address'); -var u8view = require('u8-view'); +// const assert = require('assert'); +const MACAddress = require('./mac-address'); +const u8view = require('u8-view'); exports.ETHERTYPE_IP4 = 0x0800; exports.ETHERTYPE_ARP = 0x0806; -exports.getDestMAC = function(u8, headerOffset) { - return new MACAddress(u8[headerOffset + 0], - u8[headerOffset + 1], - u8[headerOffset + 2], - u8[headerOffset + 3], - u8[headerOffset + 4], - u8[headerOffset + 5]); -}; +exports.getDestMAC = (u8, headerOffset) => (new MACAddress(u8[headerOffset + 0], + u8[headerOffset + 1], + u8[headerOffset + 2], + u8[headerOffset + 3], + u8[headerOffset + 4], + u8[headerOffset + 5])); -exports.getSrcMAC = function(u8, headerOffset) { - return new MACAddress(u8[headerOffset + 6], - u8[headerOffset + 7], - u8[headerOffset + 8], - u8[headerOffset + 9], - u8[headerOffset + 10], - u8[headerOffset + 11]); -}; +exports.getSrcMAC = (u8, headerOffset) => (new MACAddress(u8[headerOffset + 6], + u8[headerOffset + 7], + u8[headerOffset + 8], + u8[headerOffset + 9], + u8[headerOffset + 10], + u8[headerOffset + 11])); -exports.getEtherType = function(u8, headerOffset) { - return ((u8[headerOffset + 12] << 8) + u8[headerOffset + 13]) >>> 0; -}; +exports.getEtherType = (u8, headerOffset) => ((u8[headerOffset + 12] << 8) + u8[headerOffset + 13]) >>> 0; -exports.write = function(u8, headerOffset, destMAC, srcMAC, etherType) { +exports.write = (u8, headerOffset, destMAC, srcMAC, etherType) => { u8[headerOffset + 0] = destMAC.a; u8[headerOffset + 1] = destMAC.b; u8[headerOffset + 2] = destMAC.c; diff --git a/js/core/net/icmp-header.js b/js/core/net/icmp-header.js index d39ddd1b7..f282d8448 100644 --- a/js/core/net/icmp-header.js +++ b/js/core/net/icmp-header.js @@ -13,39 +13,23 @@ // limitations under the License. 'use strict'; -var u8view = require('u8-view'); +const u8view = require('u8-view'); exports.headerLength = 8; exports.ICMP_TYPE_ECHO_REPLY = 0; exports.ICMP_TYPE_ECHO_REQUEST = 8; -exports.getType = function(u8, headerOffset) { - return u8[headerOffset]; -}; - -exports.getCode = function(u8, headerOffset) { - return u8[headerOffset + 1]; -}; - -exports.getEchoRequestIdentifier = function(u8, headerOffset) { - return u8view.getUint16BE(u8, headerOffset + 4); -}; +exports.getType = (u8, headerOffset) => u8[headerOffset]; +exports.getCode = (u8, headerOffset) => u8[headerOffset + 1]; +exports.getEchoRequestIdentifier = (u8, headerOffset) => u8view.getUint16BE(u8, headerOffset + 4); +exports.getEchoRequestSequence = (u8, headerOffset) => u8view.getUint16BE(u8, headerOffset + 6); -exports.getEchoRequestSequence = function(u8, headerOffset) { - return u8view.getUint16BE(u8, headerOffset + 6); -}; - -exports.write = function(u8, headerOffset, type, code, headerValue) { +exports.write = (u8, headerOffset, type, code, headerValue) => { u8[headerOffset] = type; u8[headerOffset + 1] = code; u8view.setUint32BE(u8, headerOffset + 4, headerValue); }; -exports.writeChecksum = function(u8, headerOffset, checksum) { - u8view.setUint16BE(u8, headerOffset + 2, checksum); -}; - -exports.headerValueEcho = function(id, seq) { - return (((id & 0xffff) << 16) | (seq & 0xffff)) >>> 0; -}; +exports.writeChecksum = (u8, headerOffset, checksum) => u8view.setUint16BE(u8, headerOffset + 2, checksum); +exports.headerValueEcho = (id, seq) => (((id & 0xffff) << 16) | (seq & 0xffff)) >>> 0; diff --git a/js/core/net/icmp-transmit.js b/js/core/net/icmp-transmit.js index c0c67b5ad..8230ee07e 100644 --- a/js/core/net/icmp-transmit.js +++ b/js/core/net/icmp-transmit.js @@ -13,27 +13,27 @@ // limitations under the License. 'use strict'; -var checksum = require('./checksum'); -var ethernet = require('./ethernet'); -var ip4header = require('./ip4-header'); -var icmpHeader = require('./icmp-header'); -var route = require('./route'); +const checksum = require('./checksum'); +const ethernet = require('./ethernet'); +const ip4header = require('./ip4-header'); +const icmpHeader = require('./icmp-header'); +// const route = require('./route'); -module.exports = function(intf, destIP, viaIP, type, code, headerValue, u8data) { - var ipOffset = intf.bufferDataOffset + ethernet.headerLength; - var icmpOffset = ipOffset + ip4header.minHeaderLength; - var headerLength = icmpOffset + icmpHeader.headerLength; - var u8headers = new Uint8Array(headerLength); +module.exports = (intf, destIP, viaIP, type, code, headerValue, u8data) => { + const ipOffset = intf.bufferDataOffset + ethernet.headerLength; + const icmpOffset = ipOffset + ip4header.minHeaderLength; + const headerLength = icmpOffset + icmpHeader.headerLength; + const u8headers = new Uint8Array(headerLength); - var srcIP = intf.ipAddr; + const srcIP = intf.ipAddr; ip4header.write(u8headers, ipOffset, ip4header.PROTOCOL_ICMP, srcIP, destIP, ip4header.minHeaderLength + icmpHeader.headerLength + u8data.length); icmpHeader.write(u8headers, icmpOffset, type, code, headerValue); - var ckHeader = checksum.buffer(u8headers, icmpOffset, icmpHeader.headerLength); - var ckData = u8data ? checksum.buffer(u8data, 0, u8data.length) : 0; - var ck = checksum.result(ckHeader + ckData); + const ckHeader = checksum.buffer(u8headers, icmpOffset, icmpHeader.headerLength); + const ckData = u8data ? checksum.buffer(u8data, 0, u8data.length) : 0; + const ck = checksum.result(ckHeader + ckData); icmpHeader.writeChecksum(u8headers, icmpOffset, ck); intf.sendIP4(viaIP || destIP, u8headers, u8data); diff --git a/js/core/net/icmp.js b/js/core/net/icmp.js index 9029628d7..70d977a7b 100644 --- a/js/core/net/icmp.js +++ b/js/core/net/icmp.js @@ -14,45 +14,41 @@ 'use strict'; -var icmpHeader = require('./icmp-header'); -var icmpTransmit = require('./icmp-transmit'); -var route = require('./route'); -var Ping = require('./ping'); +const icmpHeader = require('./icmp-header'); +const icmpTransmit = require('./icmp-transmit'); +const route = require('./route'); +const Ping = require('./ping'); -function handleEchoRequest(intf, srcIP, u8, headerOffset) { - if (srcIP.isBroadcast() || srcIP.isAny()) { - return; - } +const handleEchoRequest = (intf, srcIP, u8, headerOffset) => { + if (srcIP.isBroadcast() || srcIP.isAny()) return; - var routingEntry = route.lookup(srcIP); + const routingEntry = route.lookup(srcIP); if (!routingEntry) { - debug('[ICMP] no route for ICMP reply to ' + srcIP); + debug(`[ICMP] no route for ICMP reply to ${srcIP}`); return; } - var viaIP = routingEntry.gateway; - var id = icmpHeader.getEchoRequestIdentifier(u8, headerOffset); - var seq = icmpHeader.getEchoRequestSequence(u8, headerOffset); + const viaIP = routingEntry.gateway; + const id = icmpHeader.getEchoRequestIdentifier(u8, headerOffset); + const seq = icmpHeader.getEchoRequestSequence(u8, headerOffset); icmpTransmit(intf, srcIP, viaIP, icmpHeader.ICMP_TYPE_ECHO_REPLY, 0, icmpHeader.headerValueEcho(id, seq), u8.subarray(headerOffset + icmpHeader.headerLength)); -} +}; -function handleEchoReply(intf, srcIP, u8, headerOffset) { - var id = icmpHeader.getEchoRequestIdentifier(u8, headerOffset); - var seq = icmpHeader.getEchoRequestSequence(u8, headerOffset); - var ping = Ping._receiveLookup(id); - if (ping) { - ping._receive(srcIP, seq, u8, headerOffset + icmpHeader.headerLength); - } -} +const handleEchoReply = (intf, srcIP, u8, headerOffset) => { + const id = icmpHeader.getEchoRequestIdentifier(u8, headerOffset); + const seq = icmpHeader.getEchoRequestSequence(u8, headerOffset); + const ping = Ping._receiveLookup(id); + if (ping) ping._receive(srcIP, seq, u8, headerOffset + icmpHeader.headerLength); +}; -exports.receive = function(intf, srcIP, destIP, u8, headerOffset) { +exports.receive = (intf, srcIP, destIP, u8, headerOffset) => { debug('recv ICMP over IP4'); - var type = icmpHeader.getType(u8, headerOffset); - var code = icmpHeader.getCode(u8, headerOffset); + const type = icmpHeader.getType(u8, headerOffset); + // const code = icmpHeader.getCode(u8, headerOffset); if (type === icmpHeader.ICMP_TYPE_ECHO_REQUEST) { handleEchoRequest(intf, srcIP, u8, headerOffset); diff --git a/js/core/net/index.js b/js/core/net/index.js index 362f69eeb..97233bc1c 100644 --- a/js/core/net/index.js +++ b/js/core/net/index.js @@ -13,29 +13,29 @@ // limitations under the License. 'use strict'; -var assert = require('assert'); -var Interface = require('./interface'); -var interfaces = require('./interfaces'); -var route = require('./route'); -var MACAddress = require('./mac-address'); -var EventController = require('event-controller'); -var UDPSocket = require('./udp-socket'); -var IP4Address = require('./ip4-address'); -var loopback = require('./loopback'); -var TCPSocket = require('./tcp-socket'); -var TCPServerSocket = require('./tcp-server-socket'); -var Ping = require('./ping'); -var stat = require('./net-stat'); +const assert = require('assert'); +const Interface = require('./interface'); +const interfaces = require('./interfaces'); +const route = require('./route'); +const MACAddress = require('./mac-address'); +const EventController = require('event-controller'); +const UDPSocket = require('./udp-socket'); +const IP4Address = require('./ip4-address'); +const loopback = require('./loopback'); +const TCPSocket = require('./tcp-socket'); +const TCPServerSocket = require('./tcp-server-socket'); +const Ping = require('./ping'); +const stat = require('./net-stat'); -var onInterfaceAdded = new EventController(); -var onInterfaceRemoved = new EventController(); +const onInterfaceAdded = new EventController(); +const onInterfaceRemoved = new EventController(); -function interfaceAdd(intf) { +const interfaceAdd = (intf) => { assert(intf instanceof Interface); interfaces.add(intf); onInterfaceAdded.dispatch(intf); return intf; -} +}; // Add loopback interface interfaces.add(loopback); diff --git a/js/core/net/interface.js b/js/core/net/interface.js index e374936e8..138faa245 100644 --- a/js/core/net/interface.js +++ b/js/core/net/interface.js @@ -13,115 +13,105 @@ // limitations under the License. 'use strict'; -var assert = require('assert'); -var MACAddress = require('./mac-address'); -var ARPResolver = require('./arp-resolver'); -var ethernet = require('./ethernet'); -var ip4 = require('./ip4'); -var IP4Address = require('./ip4-address'); -var EventController = require('event-controller'); -var typeutils = require('typeutils'); -var stat = require('./net-stat'); - -function Interface(macAddr) { - assert(macAddr instanceof MACAddress); - this.macAddr = macAddr; - this.ontransmit = null; - this.onNetworkUp = new EventController(); - this.onNetworkDown = new EventController(); - this.ipAddr = IP4Address.ANY; - this.netmask = IP4Address.ANY; - this.name = ''; - this.bufferDataOffset = 0; - this.arp = new ARPResolver(this); - this.isNetworkEnabled = false; - this.fragments = new Map(); -} - -Interface.prototype.disableArp = function() { - this.arp = null; -}; - -Interface.prototype.setNetworkEnabled = function(value) { - assert(typeutils.isBoolean(value)); - if (this.isNetworkEnabled === value) { - return; +const assert = require('assert'); +const MACAddress = require('./mac-address'); +const ARPResolver = require('./arp-resolver'); +const ethernet = require('./ethernet'); +const ip4 = require('./ip4'); +const IP4Address = require('./ip4-address'); +const EventController = require('event-controller'); +const typeutils = require('typeutils'); +const stat = require('./net-stat'); + +class Interface { + constructor(macAddr) { + assert(macAddr instanceof MACAddress); + this.macAddr = macAddr; + this.ontransmit = null; + this.onNetworkUp = new EventController(); + this.onNetworkDown = new EventController(); + this.ipAddr = IP4Address.ANY; + this.netmask = IP4Address.ANY; + this.name = ''; + this.bufferDataOffset = 0; + this.arp = new ARPResolver(this); + this.isNetworkEnabled = false; + this.fragments = new Map(); } - - this.isNetworkEnabled = value; - if (value) { - this.onNetworkUp.dispatch(); - } else { - this.onNetworkDown.dispatch(); + disableArp() { + this.arp = null; } -}; - -Interface.prototype.getMACAddress = function() { - return this.macAddr; -}; - -Interface.prototype.setName = function(name) { - this.name = String(name); -}; - -Interface.prototype.setBufferDataOffset = function(offset) { - assert((offset | 0) >= 0); - this.bufferDataOffset = offset | 0; -}; - -Interface.prototype.configure = function(ip, mask) { - assert(ip instanceof IP4Address); - assert(mask instanceof IP4Address); - this.ipAddr = ip; - this.netmask = mask; -}; - -Interface.prototype.hasIP = function() { - return !this.ipAddr.equals(IP4Address.ANY); -}; - -Interface.prototype.receive = function(u8) { - ++stat.receiveCount; - var etherType = ethernet.getEtherType(u8, this.bufferDataOffset); - var nextOffset = this.bufferDataOffset + ethernet.headerLength; - - switch (etherType) { - case 0x0800: return ip4.receive(this, u8, nextOffset); - case 0x0806: return this.arp ? this.arp.receive(u8, nextOffset) : void 0; - // case 0x8100: // 802.1Q - // case 0x86dd: // ipv6 + setNetworkEnabled(value) { + assert(typeutils.isBoolean(value)); + if (this.isNetworkEnabled === value) return; + + this.isNetworkEnabled = value; + if (value) { + this.onNetworkUp.dispatch(); + } else { + this.onNetworkDown.dispatch(); + } } - - debug('receive called', etherType.toString(16)); -}; - -Interface.prototype.sendRaw = function(u8) { - ++stat.transmitCount; - if (this.ontransmit) { - this.ontransmit(u8, null); + getMACAddress() { + return this.macAddr; } -}; - -Interface.prototype.sendIP4 = function(viaIP, u8headers, u8data) { - ++stat.transmitCount; - var targetMAC; - if (viaIP.isBroadcast()) { - targetMAC = MACAddress.BROADCAST; - } else if (this.arp) { - targetMAC = this.arp.get(viaIP); - if (!targetMAC) { - this.arp.request(viaIP); - return; + setName(name) { + this.name = String(name); + } + setBufferDataOffset(offset) { + assert((offset | 0) >= 0); + this.bufferDataOffset = offset | 0; + } + configure(ip, mask) { + assert(ip instanceof IP4Address); + assert(mask instanceof IP4Address); + this.ipAddr = ip; + this.netmask = mask; + } + hasIP() { + return !this.ipAddr.equals(IP4Address.ANY); + } + receive(u8) { + ++stat.receiveCount; + const etherType = ethernet.getEtherType(u8, this.bufferDataOffset); + const nextOffset = this.bufferDataOffset + ethernet.headerLength; + + switch (etherType) { + case 0x0800: return ip4.receive(this, u8, nextOffset); + case 0x0806: return this.arp ? this.arp.receive(u8, nextOffset) : void 0; + // case 0x8100: // 802.1Q + // case 0x86dd: // ipv6 + default: + break; } - } else { - targetMAC = MACAddress.ZERO; + + debug('receive called', etherType.toString(16)); + } + sendRaw(u8) { + ++stat.transmitCount; + if (this.ontransmit) this.ontransmit(u8, null); } + sendIP4(viaIP, u8headers, u8data) { + ++stat.transmitCount; + let targetMAC; + if (viaIP.isBroadcast()) { + targetMAC = MACAddress.BROADCAST; + } else if (this.arp) { + targetMAC = this.arp.get(viaIP); + if (!targetMAC) { + this.arp.request(viaIP); + return; + } + } else { + targetMAC = MACAddress.ZERO; + } - ethernet.write(u8headers, this.bufferDataOffset, targetMAC, - this.macAddr, 0x0800); - if (this.ontransmit) { - this.ontransmit(u8headers, u8data); + ethernet.write(u8headers, this.bufferDataOffset, targetMAC, + this.macAddr, 0x0800); + if (this.ontransmit) { + this.ontransmit(u8headers, u8data); + } } -}; +} module.exports = Interface; diff --git a/js/core/net/interfaces.js b/js/core/net/interfaces.js index 90bcd37d3..bb63ce58d 100644 --- a/js/core/net/interfaces.js +++ b/js/core/net/interfaces.js @@ -13,31 +13,19 @@ // limitations under the License. 'use strict'; -var assert = require('assert'); -var intfs = []; +// const assert = require('assert'); +const intfs = []; -exports.add = function(intf) { - intfs.push(intf); -}; - -exports.count = function() { - return intfs.length; -}; +exports.add = (intf) => intfs.push(intf); +exports.count = () => intfs.length; -exports.getByName = function(intfName) { - for (var i = 0, l = intfs.length; i < l; ++i) { - if (intfName === intfs[i].name) { - return intfs[i]; - } +exports.getByName = (intfName) => { + for (const intf of intfs) { + if (intfName === intf.name) return intf; } return null; }; -exports.forEach = function(fn) { - intfs.forEach(fn); -}; - -exports.getAll = function() { - return intfs; -} +exports.forEach = (fn) => intfs.forEach(fn); +exports.getAll = () => intfs; diff --git a/js/core/net/ip4-address.js b/js/core/net/ip4-address.js index 8892dfa34..a698aacb0 100644 --- a/js/core/net/ip4-address.js +++ b/js/core/net/ip4-address.js @@ -14,74 +14,63 @@ 'use strict'; -function IP4Address(a, b, c, d) { - this.a = (a & 0xff) >>> 0; - this.b = (b & 0xff) >>> 0; - this.c = (c & 0xff) >>> 0; - this.d = (d & 0xff) >>> 0; -} - -IP4Address.prototype.toString = function() { - return this.a + '.' + this.b + '.' + this.c + '.' + this.d; -}; - -IP4Address.prototype.toInteger = function() { - return ((this.a << 24) | (this.b << 16) | (this.c << 8) | this.d) >>> 0; -}; - -IP4Address.prototype.equals = function(that) { - return this.a === that.a && this.b === that.b && - this.c === that.c && this.d === that.d; -}; - -IP4Address.prototype.and = function(that) { - return new IP4Address(this.a & that.a, this.b & that.b, - this.c & that.c, this.d & that.d); -}; - -IP4Address.prototype.hash = function() { - return (this.a | (this.b << 8) | (this.c << 16) | (this.d << 24)) >>> 0; -}; - -IP4Address.prototype.isBroadcast = function() { - return 255 === this.a && 255 === this.b && - 255 === this.c && 255 === this.d; -}; - -IP4Address.prototype.isAny = function() { - return 0 === this.a && 0 === this.b && - 0 === this.c && 0 === this.d; -}; - -IP4Address.ANY = new IP4Address(0, 0, 0, 0); -IP4Address.BROADCAST = new IP4Address(255, 255, 255, 255); -IP4Address.LOOPBACK = new IP4Address(127, 0, 0, 1); - -IP4Address.parse = function(str) { - if (str instanceof IP4Address) { - return str; +class IP4Address { + constructor(a, b, c, d) { + this.a = (a & 0xff) >>> 0; + this.b = (b & 0xff) >>> 0; + this.c = (c & 0xff) >>> 0; + this.d = (d & 0xff) >>> 0; } - - if ('string' !== typeof str) { - return null; + toString() { + return `${this.a}.${this.b}.${this.c}.${this.d}`; } - - var p = str.trim().split('.'); - if (4 !== p.length) { - return null; + toInteger() { + return ((this.a << 24) | (this.b << 16) | (this.c << 8) | this.d) >>> 0; } - - var a = new Array(4); - for (var i = 0; i < 4; ++i) { - var v = p[i] | 0; - if (v !== +p[i] || v < 0 || v > 255) { - return null; + equals(that) { + return this.a === that.a && this.b === that.b && + this.c === that.c && this.d === that.d; + } + and(that) { + return new IP4Address(this.a & that.a, this.b & that.b, + this.c & that.c, this.d & that.d); + } + hash() { + return (this.a | (this.b << 8) | (this.c << 16) | (this.d << 24)) >>> 0; + } + isBroadcast() { + return this.a === 255 && this.b === 255 && + this.c === 255 && this.d === 255; + } + isAny() { + return this.a === 0 && this.b === 0 && + this.c === 0 && this.d === 0; + } + static parse(str) { + if (str instanceof IP4Address) return str; + if (typeof str !== 'string') return null; + + const p = str.trim().split('.'); + if (p.length !== 4) return null; + + const a = new Array(4); + for (let i = 0; i < 4; ++i) { + const v = p[i] | 0; + if (v !== +p[i] || v < 0 || v > 255) return null; + a[i] = v; } - a[i] = v; + return new IP4Address(a[0], a[1], a[2], a[3]); } - - return new IP4Address(a[0], a[1], a[2], a[3]); -}; + static get ANY() { + return new IP4Address(0, 0, 0, 0); + } + static get BROADCAST() { + return new IP4Address(255, 255, 255, 255); + } + static get LOOPBACK() { + return new IP4Address(127, 0, 0, 1); + } +} module.exports = IP4Address; diff --git a/js/core/net/ip4-fragments.js b/js/core/net/ip4-fragments.js index 451c1202c..b82929ed8 100644 --- a/js/core/net/ip4-fragments.js +++ b/js/core/net/ip4-fragments.js @@ -14,79 +14,61 @@ 'use strict'; -var ip4header = require('./ip4-header'); -var ip4receive = require('./ip4-receive'); -var timeNow = require('../../utils').timeNow; -var FRAGMENT_QUEUE_MAX_AGE_MS = 30000; -var FRAGMENT_QUEUE_MAX_COUNT = 100; - -function fragmentHash(srcIP, destIP, protocolId, packetId) { - return srcIP.toInteger() + '-' + destIP.toInteger() + '-' + (packetId + (protocolId << 16)); -} - -function dropFragmentQueue(intf, hash) { - intf.fragments.delete(hash); -} - -exports.addFragment = function(intf, u8, headerOffset, fragmentOffset, isMoreFragments) { - var headerLength = ip4header.getHeaderLength(u8, headerOffset); - var protocolId = ip4header.getProtocolId(u8, headerOffset); - var srcIP = ip4header.getSrcIP(u8, headerOffset); - var destIP = ip4header.getDestIP(u8, headerOffset); - var packetId = ip4header.getIdentification(u8, headerOffset); - var nextOffset = headerOffset + headerLength; - - var hash = fragmentHash(srcIP, destIP, packetId, protocolId); - - var firstFragment = false; - var fragmentQueue = intf.fragments.get(hash); +const ip4header = require('./ip4-header'); +const ip4receive = require('./ip4-receive'); +const { timeNow } = require('../../utils'); +const FRAGMENT_QUEUE_MAX_AGE_MS = 30000; +const FRAGMENT_QUEUE_MAX_COUNT = 100; + +const fragmentHash = (srcIP, destIP, protocolId, packetId) => `${srcIP.toInteger()}-${destIP.toInteger()}-${(packetId + (protocolId << 16))}`; +const dropFragmentQueue = (intf, hash) => intf.fragments.delete(hash); + +exports.addFragment = (intf, u8, headerOffset, fragmentOffset, isMoreFragments) => { + const headerLength = ip4header.getHeaderLength(u8, headerOffset); + const protocolId = ip4header.getProtocolId(u8, headerOffset); + const srcIP = ip4header.getSrcIP(u8, headerOffset); + const destIP = ip4header.getDestIP(u8, headerOffset); + const packetId = ip4header.getIdentification(u8, headerOffset); + const nextOffset = headerOffset + headerLength; + + const hash = fragmentHash(srcIP, destIP, packetId, protocolId); + + let firstFragment = false; + let fragmentQueue = intf.fragments.get(hash); if (!fragmentQueue) { - if (intf.fragments.size >= FRAGMENT_QUEUE_MAX_COUNT) { - // too many fragment queues - return; - } + if (intf.fragments.size >= FRAGMENT_QUEUE_MAX_COUNT) return; // too many fragment queues firstFragment = true; fragmentQueue = { receivedLength: 0, totalLength: 0, createdAt: timeNow(), - fragments: [] + fragments: [], }; } - var fragmentLength = u8.length - nextOffset; - if (fragmentLength <= 0) { - return; - } - - var fragmentEnd = fragmentOffset + fragmentLength; + const fragmentLength = u8.length - nextOffset; + if (fragmentLength <= 0) return; - if (fragmentEnd > 0xffff) { - return; - } + const fragmentEnd = fragmentOffset + fragmentLength; + if (fragmentEnd > 0xffff) return; // Locate non overlapping portion of new fragment - var newOffset = fragmentOffset; - var newEnd = fragmentEnd; - var newNextOffset = nextOffset; - for (var i = 0, l = fragmentQueue.fragments.length; i < l; ++i) { - var fragment = fragmentQueue.fragments[i]; - if (!fragment) { - continue; - } + let newOffset = fragmentOffset; + let newEnd = fragmentEnd; + let newNextOffset = nextOffset; + for (const fragment of fragmentQueue.fragments) { + if (!fragment) continue; - var fragBegin = fragment[0]; - var fragEnd = fragBegin + fragment[1]; + const fragBegin = fragment[0]; + const fragEnd = fragBegin + fragment[1]; - var overlapOffset = newOffset >= fragBegin && newOffset <= fragEnd; - var overlapEnd = newEnd >= fragBegin && newEnd <= fragEnd; + const overlapOffset = newOffset >= fragBegin && newOffset <= fragEnd; + const overlapEnd = newEnd >= fragBegin && newEnd <= fragEnd; // New fragment is fully contained within another fragment, // just ignore it - if (overlapOffset && overlapEnd) { - return; - } + if (overlapOffset && overlapEnd) return; // First fragment byte is somewhere withing existing fragment if (overlapOffset && newOffset < fragEnd) { @@ -95,26 +77,21 @@ exports.addFragment = function(intf, u8, headerOffset, fragmentOffset, isMoreFra } // Last fragment byte is somewhere withing existing fragment - if (overlapEnd && newEnd > fragBegin) { - newEnd = fragBegin; - } + if (overlapEnd && newEnd > fragBegin) newEnd = fragBegin; } // Remove old fragments fully contained within the new one // By doing this we can avoid splitting big new fragments into // smaller chunks - var removedIndex = -1; - for (var i = 0, l = fragmentQueue.fragments.length; i < l; ++i) { - var fragment = fragmentQueue.fragments[i]; - if (!fragment) { - continue; - } + let removedIndex = -1; + for (let i = 0, l = fragmentQueue.fragments.length; i < l; ++i) { + const fragment = fragmentQueue.fragments[i]; + if (!fragment) continue; - var fragBegin = fragment[0]; - var fragEnd = fragBegin + fragment[1]; + const fragBegin = fragment[0]; + const fragEnd = fragBegin + fragment[1]; - if (fragBegin >= newOffset && fragBegin <= newEnd && - fragEnd >= newOffset && fragEnd <= newEnd) { + if (fragBegin >= newOffset && fragBegin <= newEnd && fragEnd >= newOffset && fragEnd <= newEnd) { // remove this old fragment fragmentQueue.fragments[i] = null; fragmentQueue.receivedLength -= fragment[1]; @@ -122,10 +99,10 @@ exports.addFragment = function(intf, u8, headerOffset, fragmentOffset, isMoreFra } } - var newLength = newEnd - newOffset; + const newLength = newEnd - newOffset; // fragment offset - fragement length - buffer data offset - buffer - var newFragment = [newOffset, newLength, newNextOffset, u8]; + const newFragment = [newOffset, newLength, newNextOffset, u8]; if (removedIndex >= 0) { fragmentQueue.fragments[removedIndex] = newFragment; @@ -137,32 +114,22 @@ exports.addFragment = function(intf, u8, headerOffset, fragmentOffset, isMoreFra // Last fragment? if (!isMoreFragments) { - // Another last fragment? - if (fragmentQueue.totalLength > fragmentEnd) { - // Wrong len - return; - } - + if (fragmentQueue.totalLength > fragmentEnd) return; // Wrong len fragmentQueue.totalLength = fragmentEnd; } - if (firstFragment) { - intf.fragments.set(hash, fragmentQueue); - } + if (firstFragment) intf.fragments.set(hash, fragmentQueue); if (fragmentQueue.totalLength === fragmentQueue.receivedLength) { - var u8asm = new Uint8Array(fragmentQueue.totalLength); - for (var i = 0, l = fragmentQueue.fragments.length; i < l; ++i) { - var fragment = fragmentQueue.fragments[i]; - if (!fragment) { - continue; - } - - var itemOffset = fragment[0]; - var itemLength = fragment[1]; - var itemNextOffset = fragment[2]; - var itemBuffer = fragment[3]; + const u8asm = new Uint8Array(fragmentQueue.totalLength); + for (const fragment of fragmentQueue.fragments) { + if (!fragment) continue; + + const itemOffset = fragment[0]; + const itemLength = fragment[1]; + const itemNextOffset = fragment[2]; + const itemBuffer = fragment[3]; u8asm.set(itemBuffer.subarray(itemNextOffset, itemNextOffset + itemLength), itemOffset); } @@ -177,14 +144,12 @@ exports.addFragment = function(intf, u8, headerOffset, fragmentOffset, isMoreFra * * @param {Interface} intf Network interface */ -exports.tick = function(intf) { - var time = timeNow(); - - for (var pair of intf.fragments) { - var hash = pair[0]; - var fragmentQueue = pair[1]; - if (fragmentQueue.createdAt + FRAGMENT_QUEUE_MAX_AGE_MS <= time) { - dropFragmentQueue(intf, hash); - } +exports.tick = (intf) => { + const time = timeNow(); + + for (const pair of intf.fragments) { + const hash = pair[0]; + const fragmentQueue = pair[1]; + if (fragmentQueue.createdAt + FRAGMENT_QUEUE_MAX_AGE_MS <= time) dropFragmentQueue(intf, hash); } }; diff --git a/js/core/net/ip4-header.js b/js/core/net/ip4-header.js index 88387c8ed..16376deae 100644 --- a/js/core/net/ip4-header.js +++ b/js/core/net/ip4-header.js @@ -13,65 +13,41 @@ // limitations under the License. 'use strict'; -var IP4Address = require('./ip4-address'); -var checksum = require('./checksum'); -var u8view = require('u8-view'); -var minHeaderLength = 20; +const IP4Address = require('./ip4-address'); +const checksum = require('./checksum'); +const u8view = require('u8-view'); +const minHeaderLength = 20; -var nextId = 1; +let nextId = 1; exports.PROTOCOL_ICMP = 0x01; exports.PROTOCOL_TCP = 0x06; exports.PROTOCOL_UDP = 0x11; -exports.getSrcIP = function(u8, headerOffset) { - return new IP4Address(u8[headerOffset + 12], - u8[headerOffset + 13], - u8[headerOffset + 14], - u8[headerOffset + 15]); -}; - -exports.getDestIP = function(u8, headerOffset) { - return new IP4Address(u8[headerOffset + 16], - u8[headerOffset + 17], - u8[headerOffset + 18], - u8[headerOffset + 19]); -}; - -exports.getProtocolId = function(u8, headerOffset) { - return u8[headerOffset + 9]; -}; - -exports.getHeaderLength = function(u8, headerOffset) { - return (u8[headerOffset] & 0xf) << 2; -}; +exports.getSrcIP = (u8, headerOffset) => (new IP4Address(u8[headerOffset + 12], + u8[headerOffset + 13], + u8[headerOffset + 14], + u8[headerOffset + 15])); -exports.getFragmentationData = function(u8, headerOffset) { - return u8view.getUint16BE(u8, headerOffset + 6); -}; +exports.getDestIP = (u8, headerOffset) => (new IP4Address(u8[headerOffset + 16], + u8[headerOffset + 17], + u8[headerOffset + 18], + u8[headerOffset + 19])); -exports.getIdentification = function(u8, headerOffset) { - return u8view.getUint16BE(u8, headerOffset + 4); -}; - -exports.fragmentationDataIsMoreFragments = function(value) { - return !!((value >>> 13) & 0x1); -}; - -exports.fragmentationDataIsDontFragment = function(value) { - return !!((value >>> 14) & 0x1); -}; - -exports.fragmentationDataOffset = function(value) { - return (value & 0x1fff) * 8; -}; +exports.getProtocolId = (u8, headerOffset) => u8[headerOffset + 9]; +exports.getHeaderLength = (u8, headerOffset) => (u8[headerOffset] & 0xf) << 2; +exports.getFragmentationData = (u8, headerOffset) => u8view.getUint16BE(u8, headerOffset + 6); +exports.getIdentification = (u8, headerOffset) => u8view.getUint16BE(u8, headerOffset + 4); +exports.fragmentationDataIsMoreFragments = (value) => !!((value >>> 13) & 0x1); +exports.fragmentationDataIsDontFragment = (value) => !!((value >>> 14) & 0x1); +exports.fragmentationDataOffset = (value) => (value & 0x1fff) * 8; exports.minHeaderLength = minHeaderLength; -exports.write = function(u8, headerOffset, protocolId, srcIP, destIP, packetLength) { - var version = 4; // IPv4 - var IHL = minHeaderLength >>> 2; - var byte0 = ((version << 4) | IHL) >>> 0; +exports.write = (u8, headerOffset, protocolId, srcIP, destIP, packetLength) => { + const version = 4; // IPv4 + const IHL = minHeaderLength >>> 2; + const byte0 = ((version << 4) | IHL) >>> 0; u8[headerOffset] = byte0; u8[headerOffset + 1] = 0; // ToS diff --git a/js/core/net/ip4-receive.js b/js/core/net/ip4-receive.js index 4fc63b16e..4de18aaf5 100644 --- a/js/core/net/ip4-receive.js +++ b/js/core/net/ip4-receive.js @@ -14,14 +14,16 @@ 'use strict'; -var udp = require('./udp'); -var tcp = require('./tcp'); -var icmp = require('./icmp'); +const udp = require('./udp'); +const tcp = require('./tcp'); +const icmp = require('./icmp'); -module.exports = function(intf, srcIP, destIP, protocolId, u8, nextOffset) { +module.exports = (intf, srcIP, destIP, protocolId, u8, nextOffset) => { switch (protocolId) { - case 0x01: return icmp.receive(intf, srcIP, destIP, u8, nextOffset); - case 0x06: return tcp.receive(intf, srcIP, destIP, u8, nextOffset); - case 0x11: return udp.receive(intf, srcIP, destIP, u8, nextOffset); + case 0x01: return icmp.receive(intf, srcIP, destIP, u8, nextOffset); + case 0x06: return tcp.receive(intf, srcIP, destIP, u8, nextOffset); + case 0x11: return udp.receive(intf, srcIP, destIP, u8, nextOffset); + default: + break; } }; diff --git a/js/core/net/ip4.js b/js/core/net/ip4.js index 43922c99b..2fa60f670 100644 --- a/js/core/net/ip4.js +++ b/js/core/net/ip4.js @@ -13,30 +13,28 @@ // limitations under the License. 'use strict'; -var IP4Address = require('./ip4-address'); -var ip4header = require('./ip4-header'); -var ip4fragments = require('./ip4-fragments'); -var ip4receive = require('./ip4-receive'); -var timers = require('../timers'); -var interfaces = require('./interfaces'); +// const IP4Address = require('./ip4-address'); +const ip4header = require('./ip4-header'); +const ip4fragments = require('./ip4-fragments'); +const ip4receive = require('./ip4-receive'); +const timers = require('../timers'); +const interfaces = require('./interfaces'); -timers.scheduleTask5s(function() { - interfaces.forEach(ip4fragments.tick); -}); +timers.scheduleTask5s(() => interfaces.forEach(ip4fragments.tick)); -function handleReceive(intf, u8, headerOffset) { - var headerLength = ip4header.getHeaderLength(u8, headerOffset); - var protocolId = ip4header.getProtocolId(u8, headerOffset); - var srcIP = ip4header.getSrcIP(u8, headerOffset); - var destIP = ip4header.getDestIP(u8, headerOffset); - var nextOffset = headerOffset + headerLength; +const handleReceive = (intf, u8, headerOffset) => { + const headerLength = ip4header.getHeaderLength(u8, headerOffset); + const protocolId = ip4header.getProtocolId(u8, headerOffset); + const srcIP = ip4header.getSrcIP(u8, headerOffset); + const destIP = ip4header.getDestIP(u8, headerOffset); + const nextOffset = headerOffset + headerLength; ip4receive(intf, srcIP, destIP, protocolId, u8, nextOffset); -} +}; -exports.receive = function(intf, u8, headerOffset) { - var fragmentData = ip4header.getFragmentationData(u8, headerOffset); - var isMoreFragments = ip4header.fragmentationDataIsMoreFragments(fragmentData); - var fragmentOffset = ip4header.fragmentationDataOffset(fragmentData); +exports.receive = (intf, u8, headerOffset) => { + const fragmentData = ip4header.getFragmentationData(u8, headerOffset); + const isMoreFragments = ip4header.fragmentationDataIsMoreFragments(fragmentData); + const fragmentOffset = ip4header.fragmentationDataOffset(fragmentData); if (!isMoreFragments && fragmentOffset === 0) { handleReceive(intf, u8, headerOffset); diff --git a/js/core/net/loopback.js b/js/core/net/loopback.js index 923242aab..986b42301 100644 --- a/js/core/net/loopback.js +++ b/js/core/net/loopback.js @@ -13,22 +13,22 @@ // limitations under the License. 'use strict'; -var MACAddress = require('./mac-address'); -var Interface = require('./interface'); -var IP4Address = require('./ip4-address'); -var route = require('./route'); +const MACAddress = require('./mac-address'); +const Interface = require('./interface'); +const IP4Address = require('./ip4-address'); +const route = require('./route'); -var intf = new Interface(MACAddress.ZERO); -var ip = new IP4Address(127, 0, 0, 1); -var mask = new IP4Address(255, 0, 0, 0); +const intf = new Interface(MACAddress.ZERO); +const ip = new IP4Address(127, 0, 0, 1); +const mask = new IP4Address(255, 0, 0, 0); intf.disableArp(); intf.setName('loopback'); intf.configure(ip, mask); -intf.ontransmit = function(u8headers, u8data) { - setTimeout(function() { +intf.ontransmit = (u8headers, u8data) => { + setTimeout(() => { if (u8data) { - var u8 = new Uint8Array(u8headers.length + u8data.length); + const u8 = new Uint8Array(u8headers.length + u8data.length); u8.set(u8headers, 0); u8.set(u8data, u8headers.length); intf.receive(u8); @@ -38,7 +38,7 @@ intf.ontransmit = function(u8headers, u8data) { }, 0); }; -var subnet = ip.and(mask); +const subnet = ip.and(mask); route.addSubnet(subnet, mask, null, intf); module.exports = intf; diff --git a/js/core/net/mac-address.js b/js/core/net/mac-address.js index a7d783c7d..632bed583 100644 --- a/js/core/net/mac-address.js +++ b/js/core/net/mac-address.js @@ -14,59 +14,47 @@ 'use strict'; -function MACAddress(a, b, c, d, e, f) { - this.a = (a & 0xff) >>> 0; - this.b = (b & 0xff) >>> 0; - this.c = (c & 0xff) >>> 0; - this.d = (d & 0xff) >>> 0; - this.e = (e & 0xff) >>> 0; - this.f = (f & 0xff) >>> 0; -} - -function valueString(x) { - return (x < 0x10) ? '0' + x.toString(16) : x.toString(16); -} - -MACAddress.prototype.toString = function() { - return valueString(this.a) + ':' + valueString(this.b) + ':' + - valueString(this.c) + ':' + valueString(this.d) + ':' + - valueString(this.e) + ':' + valueString(this.f); -}; - -MACAddress.prototype.equals = function(that) { - return this.a === that.a && this.b === that.b && - this.c === that.c && this.d === that.d && - this.e === that.e && this.f === that.f; -}; - -MACAddress.BROADCAST = new MACAddress(0xff, 0xff, 0xff, 0xff, 0xff, 0xff); -MACAddress.ZERO = new MACAddress(0, 0, 0, 0, 0, 0); - -MACAddress.parse = function(str) { - if (str instanceof MACAddress) { - return str; +const valueString = (x) => ((x < 0x10) ? `0${x.toString(16)}` : x.toString(16)); + +class MACAddress { + constructor(a, b, c, d, e, f) { + this.a = (a & 0xff) >>> 0; + this.b = (b & 0xff) >>> 0; + this.c = (c & 0xff) >>> 0; + this.d = (d & 0xff) >>> 0; + this.e = (e & 0xff) >>> 0; + this.f = (f & 0xff) >>> 0; } - - if ('string' !== typeof str) { - return null; + toString() { + return `${valueString(this.a)}:${valueString(this.b)}:${valueString(this.c)}:${valueString(this.d)}:${valueString(this.e)}:${valueString(this.f)}`; } - - var p = str.trim().split(':'); - if (6 !== p.length) { - return null; + equals(that) { + return this.a === that.a && this.b === that.b && + this.c === that.c && this.d === that.d && + this.e === that.e && this.f === that.f; } - - var a = new Array(6); - for (var i = 0; i < 6; ++i) { - var v = parseInt(p[i], 16) | 0; - if (v !== parseInt(p[i], 16) || v < 0 || v > 255) { - return null; + static get BROADCAST() { + return new MACAddress(0xff, 0xff, 0xff, 0xff, 0xff, 0xff); + } + static get ZERO() { + return new MACAddress(0, 0, 0, 0, 0, 0); + } + static parse(str) { + if (str instanceof MACAddress) return str; + if (typeof str !== 'string') return null; + + const p = str.trim().split(':'); + if (p.length !== 6) return null; + + const a = new Array(6); + for (let i = 0; i < 6; ++i) { + const v = parseInt(p[i], 16) | 0; + if (v !== parseInt(p[i], 16) || v < 0 || v > 255) return null; + a[i] = v; } - a[i] = v; + return new MACAddress(a[0], a[1], a[2], a[3], a[4], a[5]); } - - return new MACAddress(a[0], a[1], a[2], a[3], a[4], a[5]); -}; +} module.exports = MACAddress; diff --git a/js/core/net/net-error.js b/js/core/net/net-error.js index 35509effc..bf205a2c9 100644 --- a/js/core/net/net-error.js +++ b/js/core/net/net-error.js @@ -14,12 +14,16 @@ 'use strict'; -exports.E_NO_INTERFACE = new Error('E_NO_INTERFACE'); -exports.E_INVALID_PORT = new Error('E_INVALID_PORT'); -exports.E_NO_FREE_PORT = new Error('E_NO_FREE_PORT'); -exports.E_ADDRESS_IN_USE = new Error('E_ADDRESS_IN_USE'); -exports.E_NO_ROUTE_TO_HOST = new Error('E_NO_ROUTE_TO_HOST'); -exports.E_TYPEDARRAY_EXPECTED = new Error('E_BUFFER_EXPECTED'); -exports.E_IPADDRESS_EXPECTED = new Error('E_IPADDRESS_EXPECTED'); -exports.E_INTERFACE_EXPECTED = new Error('E_INTERFACE_EXPECTED'); -exports.E_CANNOT_CLOSE = new Error('E_CANNOT_CLOSE'); +const errs = [ + 'E_NO_INTERFACE', + 'E_INVALID_PORT', + 'E_NO_FREE_PORT', + 'E_ADDRESS_IN_USE', + 'E_NO_ROUTE_TO_HOST', + 'E_TYPEDARRAY_EXPECTED', + 'E_IPADDRESS_EXPECTED', + 'E_INTERFACE_EXPECTED', + 'E_CANNOT_CLOSE', +]; + +for (const err of errs) exports[err] = new Error(err); diff --git a/js/core/net/ping.js b/js/core/net/ping.js index 74281112b..1f0b83503 100644 --- a/js/core/net/ping.js +++ b/js/core/net/ping.js @@ -14,24 +14,22 @@ 'use strict'; -var assertError = require('assert-error'); -var IP4Address = require('./ip4-address'); -var icmpTransmit = require('./icmp-transmit'); -var icmpHeader = require('./icmp-header'); -var route = require('./route'); -var netError = require('./net-error'); -var pingListeners = new Map(); - -function createPingBuffer(size) { - var u8 = new Uint8Array(size); - for (var i = 0; i < size; ++i) { - u8[i] = 0x61 + (i % 26); // ASCII a-z - } +const assertError = require('assert-error'); +const IP4Address = require('./ip4-address'); +const icmpTransmit = require('./icmp-transmit'); +const icmpHeader = require('./icmp-header'); +const route = require('./route'); +const netError = require('./net-error'); +const pingListeners = new Map(); + +const createPingBuffer = (size) => { + const u8 = new Uint8Array(size); + for (let i = 0; i < size; ++i) u8[i] = 0x61 + (i % 26); // ASCII a-z return u8; -} +}; -var nextPingId = 1; -var defaultPingData = createPingBuffer(56); +let nextPingId = 1; +const defaultPingData = createPingBuffer(56); class Ping { constructor() { @@ -46,26 +44,22 @@ class Ping { * sequence number. */ send(ip) { - var destIP = IP4Address.parse(ip); + const destIP = IP4Address.parse(ip); assertError(destIP instanceof IP4Address, netError.E_IPADDRESS_EXPECTED); - var seq = this._nextSeq++; - if (this._nextSeq > 0xffff) { - this._nextSeq = 0; - } + const seq = this._nextSeq++; + if (this._nextSeq > 0xffff) this._nextSeq = 0; - var routingEntry = route.lookup(destIP); + const routingEntry = route.lookup(destIP); if (!routingEntry) { - debug('[ICMP] no route to send ICMP request to ' + destIP); + debug(`[ICMP] no route to send ICMP request to ${destIP}`); return seq; } - if (!pingListeners.has(this._pingId)) { - pingListeners.set(this._pingId, this); - } + if (!pingListeners.has(this._pingId)) pingListeners.set(this._pingId, this); - var intf = routingEntry.intf; - var viaIP = routingEntry.gateway; + const intf = routingEntry.intf; + const viaIP = routingEntry.gateway; icmpTransmit(intf, destIP, viaIP, icmpHeader.ICMP_TYPE_ECHO_REQUEST, 0, icmpHeader.headerValueEcho(this._pingId, seq), this._data); @@ -73,29 +67,21 @@ class Ping { } _receive(srcIP, seq, u8, dataOffset) { - var dataLength = u8.length - dataOffset; - if (dataLength !== this._data.length) { - return; - } + const dataLength = u8.length - dataOffset; + if (dataLength !== this._data.length) return; - for (var i = 0, l = dataLength; i < l; ++i) { - if (u8[dataOffset + i] !== this._data[i]) { - return; - } + for (let i = 0, l = dataLength; i < l; ++i) { + if (u8[dataOffset + i] !== this._data[i]) return; } - if (this.onreply) { - this.onreply(srcIP, seq); - } + if (this.onreply) this.onreply(srcIP, seq); } /** * Stop listening to echo replies. */ close() { - if (pingListeners.has(this._pingId)) { - pingListeners.delete(this._pingId); - } + if (pingListeners.has(this._pingId)) pingListeners.delete(this._pingId); } static _receiveLookup(pingId) { diff --git a/js/core/net/port-allocator.js b/js/core/net/port-allocator.js index e113eecf9..e162fa58e 100644 --- a/js/core/net/port-allocator.js +++ b/js/core/net/port-allocator.js @@ -14,12 +14,12 @@ 'use strict'; -var assert = require('assert'); -var isint = require('isint'); -var portUtils = require('./port-utils'); +const assert = require('assert'); +const isint = require('isint'); +const portUtils = require('./port-utils'); -var EPHEMERAL_PORT_FIRST = 49152; -var EPHEMERAL_PORT_COUNT = 16000; +const EPHEMERAL_PORT_FIRST = 49152; +const EPHEMERAL_PORT_COUNT = 16000; assert(isint.uint16(EPHEMERAL_PORT_FIRST + EPHEMERAL_PORT_COUNT)); class PortAllocator { @@ -41,7 +41,7 @@ class PortAllocator { allocEphemeral(socket) { if (this._searchStart < this._sockets.length) { for (let i = this._searchStart, l = this._sockets.length; i < l; ++i) { - if ((null === this._sockets[i]) && ((null !== this._map) ? !this._map.has(EPHEMERAL_PORT_FIRST + i) : true)) { + if ((this._sockets[i] === null) && ((this._map !== null) ? !this._map.has(EPHEMERAL_PORT_FIRST + i) : true)) { this._sockets[i] = socket; ++this._allocated; this._searchStart = i + 1; @@ -51,7 +51,7 @@ class PortAllocator { } while (this._sockets.length < EPHEMERAL_PORT_COUNT) { - if (null !== this._map && this._map.has(EPHEMERAL_PORT_FIRST + this._sockets.length)) { + if (this._map !== null && this._map.has(EPHEMERAL_PORT_FIRST + this._sockets.length)) { this._sockets.push(null); continue; } @@ -59,7 +59,7 @@ class PortAllocator { this._sockets.push(socket); ++this._allocated; this._searchStart = this._sockets.length; - return EPHEMERAL_PORT_FIRST + this._sockets.length - 1; + return (EPHEMERAL_PORT_FIRST + this._sockets.length) - 1; } return 0; @@ -67,13 +67,8 @@ class PortAllocator { allocPort(port, socket) { assert(portUtils.isPort(port)); - if (this.lookup(port)) { - return false; - } - - if (null === this._map) { - this._map = new Map(); - } + if (this.lookup(port)) return false; + if (this._map === null) this._map = new Map(); this._map.set(port, socket); ++this._allocated; @@ -83,7 +78,7 @@ class PortAllocator { free(port) { assert(portUtils.isPort(port)); - if ((null !== this._map) && this._map.has(port)) { + if ((this._map !== null) && this._map.has(port)) { this._map.delete(port); --this._allocated; if (this.isEphemeralRange(port)) { @@ -95,21 +90,15 @@ class PortAllocator { } if (this.isEphemeralRange(port)) { - var index = port - EPHEMERAL_PORT_FIRST; - if (index >= this._sockets.length) { - return; - } + const index = port - EPHEMERAL_PORT_FIRST; + if (index >= this._sockets.length) return; - if (null === this._sockets[index]) { - return; - } + if (this._sockets[index] === null) return; this._sockets[index] = null; - if (index < this._searchStart) { - this._searchStart = index; - } + if (index < this._searchStart) this._searchStart = index; --this._allocated; - if (0 === this._allocated) { + if (this._allocated === 0) { this._sockets = []; this._searchStart = 0; } @@ -117,16 +106,11 @@ class PortAllocator { } lookup(port) { - if ((null !== this._map) && this._map.has(port)) { - return this._map.get(port); - } + if ((this._map !== null) && this._map.has(port)) return this._map.get(port); if (this.isEphemeralRange(port)) { - var index = port - EPHEMERAL_PORT_FIRST; - if (index >= this._sockets.length) { - return null; - } - + const index = port - EPHEMERAL_PORT_FIRST; + if (index >= this._sockets.length) return null; return this._sockets[index]; } diff --git a/js/core/net/port-utils.js b/js/core/net/port-utils.js index f02b9d296..521aaabe7 100644 --- a/js/core/net/port-utils.js +++ b/js/core/net/port-utils.js @@ -13,8 +13,7 @@ // limitations under the License. 'use strict'; -var isint = require('isint'); -exports.isPort = function(port) { - return isint.uint16(port) && port !== 0; -}; +const isint = require('isint'); + +exports.isPort = (port) => isint.uint16(port) && port !== 0; diff --git a/js/core/net/route.js b/js/core/net/route.js index 458dfba18..56fd05c08 100644 --- a/js/core/net/route.js +++ b/js/core/net/route.js @@ -13,43 +13,37 @@ // limitations under the License. 'use strict'; -var IP4Address = require('./ip4-address'); -var interfaces = require('./interfaces'); -var assert = require('assert'); -var bitTwiddle = require('bit-twiddle'); -var table = []; - -function Entry(ip, mask, gateway, intf) { - assert(ip instanceof IP4Address); - assert(mask instanceof IP4Address); - assert(null === gateway || (gateway instanceof IP4Address)); - - this.ip = ip; - this.mask = mask; - this.maskBits = bitTwiddle.popCount(mask.toInteger()); - this.gateway = gateway; - this.intf = intf; - - debug('[ ADD ROUTE', ip.toString() + '/' + this.maskBits, 'via', gateway, intf.name, ']'); +const IP4Address = require('./ip4-address'); +// const interfaces = require('./interfaces'); +const assert = require('assert'); +const bitTwiddle = require('bit-twiddle'); +const table = []; + +class Entry { + constructor(ip, mask, gateway, intf) { + assert(ip instanceof IP4Address); + assert(mask instanceof IP4Address); + assert(gateway === null || (gateway instanceof IP4Address)); + + this.ip = ip; + this.mask = mask; + this.maskBits = bitTwiddle.popCount(mask.toInteger()); + this.gateway = gateway; + this.intf = intf; + + debug(`[ ADD ROUTE ${ip.toString()}/${this.maskBits} via ${gateway} ${intf.name} ]`); + } } -exports.addSubnet = function(ip, mask, gateway, intf) { - table.push(new Entry(ip, mask, gateway, intf)); -}; +exports.addSubnet = (ip, mask, gateway, intf) => table.push(new Entry(ip, mask, gateway, intf)); -exports.addDefault = function(gateway, intf) { - table.push(new Entry(IP4Address.ANY, IP4Address.ANY, gateway, intf)); -}; +exports.addDefault = (gateway, intf) => table.push(new Entry(IP4Address.ANY, IP4Address.ANY, gateway, intf)); -exports.lookup = function(destIP, intf) { - var result = null; - var maxMaskBits = 0; - for (var i = 0, l = table.length; i < l; ++i) { - var entry = table[i]; - - if (intf && entry.intf !== intf) { - continue; - } +exports.lookup = (destIP, intf) => { + let result = null; + let maxMaskBits = 0; + for (const entry of table) { + if (intf && entry.intf !== intf) continue; if (destIP.and(entry.mask).equals(entry.ip) && entry.maskBits >= maxMaskBits) { result = entry; diff --git a/js/core/net/tcp-hash.js b/js/core/net/tcp-hash.js index 30d891462..c1991b5c6 100644 --- a/js/core/net/tcp-hash.js +++ b/js/core/net/tcp-hash.js @@ -14,10 +14,6 @@ 'use strict'; -var pow32 = Math.pow(2, 32); +const pow32 = Math.pow(2, 32); -function connHash(ip, port) { - return pow32 * port + (((ip.a << 24) | (ip.b << 16) | (ip.c << 8) | ip.d) >>> 0); -} - -module.exports = connHash; +module.exports = (ip, port) => (pow32 * port) + (((ip.a << 24) | (ip.b << 16) | (ip.c << 8) | ip.d) >>> 0); diff --git a/js/core/net/tcp-header.js b/js/core/net/tcp-header.js index f66bde4c7..824b414f3 100644 --- a/js/core/net/tcp-header.js +++ b/js/core/net/tcp-header.js @@ -13,35 +13,15 @@ // limitations under the License. 'use strict'; -var u8view = require('u8-view'); +const u8view = require('u8-view'); -exports.getSrcPort = function(u8, headerOffset) { - return u8view.getUint16BE(u8, headerOffset); -}; - -exports.getDestPort = function(u8, headerOffset) { - return u8view.getUint16BE(u8, headerOffset + 2); -}; - -exports.getSeqNumber = function(u8, headerOffset) { - return u8view.getUint32BE(u8, headerOffset + 4) >>> 0; -}; - -exports.getAckNumber = function(u8, headerOffset) { - return u8view.getUint32BE(u8, headerOffset + 8); -}; - -exports.getDataOffset = function(u8, headerOffset) { - return (u8[headerOffset + 12] >>> 4) * 4; -}; - -exports.getFlags = function(u8, headerOffset) { - return u8[headerOffset + 13]; -}; - -exports.getWindowSize = function(u8, headerOffset) { - return u8view.getUint16BE(u8, headerOffset + 14); -}; +exports.getSrcPort = (u8, headerOffset) => u8view.getUint16BE(u8, headerOffset); +exports.getDestPort = (u8, headerOffset) => u8view.getUint16BE(u8, headerOffset + 2); +exports.getSeqNumber = (u8, headerOffset) => u8view.getUint32BE(u8, headerOffset + 4) >>> 0; +exports.getAckNumber = (u8, headerOffset) => u8view.getUint32BE(u8, headerOffset + 8); +exports.getDataOffset = (u8, headerOffset) => (u8[headerOffset + 12] >>> 4) * 4; +exports.getFlags = (u8, headerOffset) => u8[headerOffset + 13]; +exports.getWindowSize = (u8, headerOffset) => u8view.getUint16BE(u8, headerOffset + 14); exports.headerLength = 20; @@ -52,8 +32,8 @@ exports.FLAG_PSH = 1 << 3; // Push exports.FLAG_ACK = 1 << 4; // Ack exports.FLAG_URG = 1 << 5; // Urgent -exports.write = function(u8, headerOffset, srcPort, destPort, seqNumber, ackNumber, flags, windowSize) { - var dataOffsetWords = 5; +exports.write = (u8, headerOffset, srcPort, destPort, seqNumber, ackNumber, flags, windowSize) => { + const dataOffsetWords = 5; u8view.setUint16BE(u8, headerOffset, srcPort); u8view.setUint16BE(u8, headerOffset + 2, destPort); u8view.setUint32BE(u8, headerOffset + 4, seqNumber); @@ -65,6 +45,4 @@ exports.write = function(u8, headerOffset, srcPort, destPort, seqNumber, ackNumb u8view.setUint16BE(u8, headerOffset + 18, 0); // urgent ptr }; -exports.writeChecksum = function(u8, headerOffset, checksum) { - u8view.setUint16BE(u8, headerOffset + 16, checksum); -}; +exports.writeChecksum = (u8, headerOffset, checksum) => u8view.setUint16BE(u8, headerOffset + 16, checksum); diff --git a/js/core/net/tcp-server-socket.js b/js/core/net/tcp-server-socket.js index 42c2d3d3b..e085668dd 100644 --- a/js/core/net/tcp-server-socket.js +++ b/js/core/net/tcp-server-socket.js @@ -13,7 +13,7 @@ // limitations under the License. 'use strict'; -var TCPSocket = require('./tcp-socket'); +const TCPSocket = require('./tcp-socket'); class TCPServerSocket { constructor() { @@ -23,39 +23,20 @@ class TCPServerSocket { this.onerror = null; this._port = 0; - var that = this; - this.listeningSocket._onconnect = function(socket) { - socket.onopen = function() { - if (that.onconnect) { - that.onconnect(socket); - } - }; - }; - this.listeningSocket.onerror = function(err) { - if (that.onerror) { - that.onerror(err); - } - }; - - this.listeningSocket.onclose = function() { - if (that.onclose) { - that.onclose(); - } + this.listeningSocket._onconnect = (socket) => { + socket.onopen = () => (this.onconnect) && this.onconnect(socket); }; + this.listeningSocket.onerror = err => (this.onerror) && this.onerror(err); + this.listeningSocket.onclose = () => (this.onclose) && this.onclose(); } - get localPort() { return this._port; } - listen(port) { this.listeningSocket._listen(port); this._port = this.listeningSocket._port; - if (this.onlisten) { - this.onlisten(this._port); - } + if (this.onlisten) this.onlisten(this._port); } - close() { this.listeningSocket.close(); } diff --git a/js/core/net/tcp-socket-state.js b/js/core/net/tcp-socket-state.js index 3b08ed26e..bf0f2c7dd 100644 --- a/js/core/net/tcp-socket-state.js +++ b/js/core/net/tcp-socket-state.js @@ -13,14 +13,19 @@ // limitations under the License. 'use strict'; -exports.STATE_CLOSED = 0; -exports.STATE_LISTEN = 1; -exports.STATE_SYN_SENT = 2; -exports.STATE_SYN_RECEIVED = 3; -exports.STATE_ESTABLISHED = 4; -exports.STATE_FIN_WAIT_1 = 5; -exports.STATE_FIN_WAIT_2 = 6; -exports.STATE_CLOSE_WAIT = 7; -exports.STATE_CLOSING = 8; -exports.STATE_LAST_ACK = 9; -exports.STATE_TIME_WAIT = 10; + +const states = [ + 'STATE_CLOSED', + 'STATE_LISTEN', + 'STATE_SYN_SENT', + 'STATE_SYN_RECEIVED', + 'STATE_ESTABLISHED', + 'STATE_FIN_WAIT_1', + 'STATE_FIN_WAIT_2', + 'STATE_CLOSE_WAIT', + 'STATE_CLOSING', + 'STATE_LAST_ACK', + 'STATE_TIME_WAIT', +]; + +for (const num of Object.keys(states)) exports[states[num]] = num; diff --git a/js/core/net/tcp-socket.js b/js/core/net/tcp-socket.js index 0f660dd5c..6d5642dca 100644 --- a/js/core/net/tcp-socket.js +++ b/js/core/net/tcp-socket.js @@ -12,41 +12,43 @@ // See the License for the specific language governing permissions and // limitations under the License. +/* eslint-disable new-cap */ + 'use strict'; -var assertError = require('assert-error'); -var typeutils = require('typeutils'); -var IP4Address = require('./ip4-address'); -var portUtils = require('./port-utils'); -var PortAllocator = require('./port-allocator'); -var tcpTransmit = require('./tcp-transmit'); -var route = require('./route'); -var tcpHeader = require('./tcp-header'); -var netError = require('./net-error'); -var tcpTimer = require('./tcp-timer'); -var tcpSocketState = require('./tcp-socket-state'); -var connHash = require('./tcp-hash'); -var tcpStat = require('./tcp-stat'); -var timeNow = require('../../utils').timeNow; - -var ports = new PortAllocator(); - -var STATE_CLOSED = tcpSocketState.STATE_CLOSED; -var STATE_LISTEN = tcpSocketState.STATE_LISTEN; -var STATE_SYN_SENT = tcpSocketState.STATE_SYN_SENT; -var STATE_SYN_RECEIVED = tcpSocketState.STATE_SYN_RECEIVED; -var STATE_ESTABLISHED = tcpSocketState.STATE_ESTABLISHED; -var STATE_FIN_WAIT_1 = tcpSocketState.STATE_FIN_WAIT_1; -var STATE_FIN_WAIT_2 = tcpSocketState.STATE_FIN_WAIT_2; -var STATE_CLOSE_WAIT = tcpSocketState.STATE_CLOSE_WAIT; -var STATE_CLOSING = tcpSocketState.STATE_CLOSING; -var STATE_LAST_ACK = tcpSocketState.STATE_LAST_ACK; -var STATE_TIME_WAIT = tcpSocketState.STATE_TIME_WAIT; - -function SEQ_INC(seq, value) { return (seq + (value >>> 0)) >>> 0; } -function SEQ_OFFSET(a, b) { return ((a - b) | 0); } - -var MSL_TIME = 15000; -var bufferedLimitHint = 64 * 1024; /* 64 KiB */ +const assertError = require('assert-error'); +const typeutils = require('typeutils'); +const IP4Address = require('./ip4-address'); +const portUtils = require('./port-utils'); +const PortAllocator = require('./port-allocator'); +const tcpTransmit = require('./tcp-transmit'); +const route = require('./route'); +const tcpHeader = require('./tcp-header'); +const netError = require('./net-error'); +const tcpTimer = require('./tcp-timer'); +const { + STATE_CLOSED, + STATE_LISTEN, + STATE_SYN_SENT, + STATE_SYN_RECEIVED, + STATE_ESTABLISHED, + STATE_FIN_WAIT_1, + STATE_FIN_WAIT_2, + STATE_CLOSE_WAIT, + STATE_CLOSING, + STATE_LAST_ACK, + STATE_TIME_WAIT, +} = require('./tcp-socket-state'); +const connHash = require('./tcp-hash'); +const tcpStat = require('./tcp-stat'); +const { timeNow } = require('../../utils'); + +const ports = new PortAllocator(); + +const SEQ_INC = (seq, value) => (seq + (value >>> 0)) >>> 0; +const SEQ_OFFSET = (a, b) => (a - b) | 0; + +const MSL_TIME = 15000; +const bufferedLimitHint = 64 * 1024; /* 64 KiB */ class TCPSocket { constructor() { @@ -100,28 +102,29 @@ class TCPSocket { get readyState() { switch (this._state) { - case STATE_CLOSED: - case STATE_TIME_WAIT: - return 'closed'; - case STATE_LISTEN: - case STATE_ESTABLISHED: - return 'open'; - case STATE_SYN_SENT: - case STATE_SYN_RECEIVED: - return 'connecting'; - case STATE_FIN_WAIT_1: - case STATE_FIN_WAIT_2: - case STATE_CLOSE_WAIT: - case STATE_CLOSING: - case STATE_LAST_ACK: - return 'closing'; + case STATE_CLOSED: + case STATE_TIME_WAIT: + return 'closed'; + case STATE_LISTEN: + case STATE_ESTABLISHED: + return 'open'; + case STATE_SYN_SENT: + case STATE_SYN_RECEIVED: + return 'connecting'; + case STATE_FIN_WAIT_1: + case STATE_FIN_WAIT_2: + case STATE_CLOSE_WAIT: + case STATE_CLOSING: + case STATE_LAST_ACK: + return 'closing'; + default: + break; } } - open(ip, port) { - if (typeutils.isString(ip)) { - ip = IP4Address.parse(ip); - } + open(ipOpt, port) { + let ip = ipOpt; + if (typeutils.isString(ip)) ip = IP4Address.parse(ip); assertError(ip instanceof IP4Address, netError.E_IPADDRESS_EXPECTED); assertError(portUtils.isPort(port), netError.E_INVALID_PORT); @@ -133,20 +136,16 @@ class TCPSocket { tcpTimer.addConnectionSocket(this); } - suspend() { - } - - resume() { - } + suspend() {} + resume() {} - _listen(port) { + _listen(portOpt) { + let port = portOpt; if (!port) { port = ports.allocEphemeral(this); } else { assertError(portUtils.isPort(port), netError.E_INVALID_PORT); - if (!ports.allocPort(port, this)) { - throw netError.E_ADDRESS_IN_USE; - } + if (!ports.allocPort(port, this)) throw netError.E_ADDRESS_IN_USE; } this._port = port; @@ -157,7 +156,7 @@ class TCPSocket { _destroy() { tcpTimer.removeConnectionSocket(this); if (this._serverSocket) { - var hash = connHash(this._destIP, this._destPort); + const hash = connHash(this._destIP, this._destPort); this._serverSocket._connections.delete(hash); } this._transmitQueue = []; @@ -172,28 +171,19 @@ class TCPSocket { } _configure() { - var intf = this._intf || null; - var viaIP; + let intf = this._intf || null; - if (this._destIP.isBroadcast()) { - return false; - } + if (this._destIP.isBroadcast()) return false; - var routingEntry = route.lookup(this._destIP, intf); - if (!routingEntry) { - return false; - } + const routingEntry = route.lookup(this._destIP, intf); + if (!routingEntry) return false; - viaIP = routingEntry.gateway; - if (!intf) { - intf = routingEntry.intf; - } + const viaIP = routingEntry.gateway; + if (!intf) intf = routingEntry.intf; if (!this._port) { this._port = ports.allocEphemeral(this); - if (!this._port) { - return false; - } + if (!this._port) return false; } this._intf = intf; @@ -202,17 +192,11 @@ class TCPSocket { } _emitData(u8) { - var ondata = this.ondata; - setImmediate(function() { - ondata(u8); - }); + setImmediate(() => this.ondata(u8)); } _emitEnd() { - var onend = this.onend; - setImmediate(function() { - onend(); - }); + setImmediate(() => this.onend()); } _emitOpen() { @@ -220,24 +204,17 @@ class TCPSocket { } _emitClose() { - var onclose = this.onclose; - setImmediate(function() { - onclose(); - }); + setImmediate(() => this.onclose()); } _sendSYN(isAck) { - var flags = tcpHeader.FLAG_SYN; - if (isAck) { - flags |= tcpHeader.FLAG_ACK; - } + let flags = tcpHeader.FLAG_SYN; + if (isAck) flags |= tcpHeader.FLAG_ACK; this._transmitQueue.push([0, timeNow(), this._getTransmitPosition(), 1, null, flags]); this._incTransmitPosition(); - if (!this._configure()) { - return; - } + if (!this._configure()) return; this._sendTransmitQueue(); } @@ -247,9 +224,9 @@ class TCPSocket { } _allocTransmitPosition(length) { - var end = SEQ_INC(this._transmitWindowEdge, this._transmitWindowSize); - var spaceLeft = SEQ_OFFSET(end, this._transmitPosition); - var spaceReserved = Math.min(spaceLeft, length, 536); /* TODO: move MSS (max segment size, data size) somewhere */ + const end = SEQ_INC(this._transmitWindowEdge, this._transmitWindowSize); + const spaceLeft = SEQ_OFFSET(end, this._transmitPosition); + const spaceReserved = Math.min(spaceLeft, length, 536); /* TODO: move MSS (max segment size, data size) somewhere */ this._transmitPosition = SEQ_INC(this._transmitPosition, spaceReserved); return spaceReserved; } @@ -267,33 +244,26 @@ class TCPSocket { } _receiveWindowIsWithin(seq, edge) { - if (0 === this._receiveWindowSize) { - return false; - } + if (this._receiveWindowSize === 0) return false; - var leftEdge = edge; - var rightEdge = SEQ_INC(edge, this._receiveWindowSize); - if (leftEdge < rightEdge) { - return seq >= leftEdge && seq < rightEdge; - } else { - return seq >= leftEdge || seq < rightEdge; - } + const leftEdge = edge; + const rightEdge = SEQ_INC(edge, this._receiveWindowSize); + if (leftEdge < rightEdge) return seq >= leftEdge && seq < rightEdge; + return seq >= leftEdge || seq < rightEdge; } _fillTransmitQueue() { - var remove = 0; + let remove = 0; - for (var i = 0, l = this._queueTx.length; i < l; ++i) { - var buf = this._queueTx[i]; - var position = this._getTransmitPosition(); + for (let i = 0, l = this._queueTx.length; i < l; ++i) { + const buf = this._queueTx[i]; + const position = this._getTransmitPosition(); if (buf) { - var length = buf.length; - var reserved = this._allocTransmitPosition(length); + const length = buf.length; + const reserved = this._allocTransmitPosition(length); debug('send at ', position, 'len', reserved); - if (0 === reserved) { - break; - } + if (reserved === 0) break; if (length === reserved) { this._transmitQueue.push([0, timeNow(), position, reserved, buf, tcpHeader.FLAG_ACK | tcpHeader.FLAG_PSH]); @@ -306,58 +276,52 @@ class TCPSocket { break; } - if (0 === this._bufferedAmount && this.ondrain) { - this.ondrain(); - } + if (this._bufferedAmount === 0 && this.ondrain) this.ondrain(); } else { debug('fill pos', position, 'fin'); this._incTransmitPosition(); this._transmitQueue.push([0, timeNow(), position, 1, null, tcpHeader.FLAG_ACK | tcpHeader.FLAG_FIN]); ++remove; } - } - while (remove-- > 0) { - this._queueTx.shift(); - } + while (remove-- > 0) this._queueTx.shift(); this._sendTransmitQueue(); } _timerTick() { switch (this._state) { - case STATE_TIME_WAIT: - if (timeNow() > this._timeWaitTime + 2 * MSL_TIME) { - this._state = STATE_CLOSED; - this._destroy(); - } - break; - case STATE_SYN_SENT: - case STATE_SYN_RECEIVED: - if (!this._configure()) { - return; - } + case STATE_TIME_WAIT: + if (timeNow() > this._timeWaitTime + (2 * MSL_TIME)) { + this._state = STATE_CLOSED; + this._destroy(); + } + break; + case STATE_SYN_SENT: + case STATE_SYN_RECEIVED: + if (!this._configure()) return; /* fall through */ - case STATE_ESTABLISHED: - case STATE_FIN_WAIT_1: - this._sendTransmitQueue(); - break; + case STATE_ESTABLISHED: + case STATE_FIN_WAIT_1: + this._sendTransmitQueue(); + break; + default: + break; } } _sendTransmitQueue() { - var now = timeNow(); + const now = timeNow(); if (this._transmitQueue.length > 0) { - for (var i = 0, l = this._transmitQueue.length; i < l; ++i) { - var item = this._transmitQueue[i]; - var retransmits = item[0]; - var timeAdded = item[1]; - var seq = item[2]; - var u8 = item[4]; - var flags = item[5]; - var interval = retransmits * 2000; /* 2 seconds each time in ms */ + for (const item of this._transmitQueue) { + const retransmits = item[0]; + const timeAdded = item[1]; + const seq = item[2]; + const u8 = item[4]; + const flags = item[5]; + const interval = retransmits * 2000; // 2 seconds each time in ms if (retransmits > 7) { this._resetConnection(); @@ -379,18 +343,15 @@ class TCPSocket { } } - _cleanupTransmitQueue(ackNumber) { - var deleteCount = 0; + _cleanupTransmitQueue() { + let deleteCount = 0; - if (this._transmitQueue.length === 0) { - return; - } + if (this._transmitQueue.length === 0) return; - for (var i = 0, l = this._transmitQueue.length; i < l; ++i) { - var item = this._transmitQueue[i]; - var seq = item[2]; - var len = item[3]; - var end = SEQ_INC(seq, len); + for (const item of this._transmitQueue) { + const seq = item[2]; + const len = item[3]; + const end = SEQ_INC(seq, len); if (!this._isTransmittedUnacked(end)) { ++deleteCount; @@ -399,9 +360,7 @@ class TCPSocket { } } - while (deleteCount-- > 0) { - this._transmitQueue.shift(); - } + while (deleteCount-- > 0) this._transmitQueue.shift(); } _resetConnection() { @@ -410,12 +369,8 @@ class TCPSocket { } send(u8) { - if (!(u8 instanceof Uint8Array)) { - throw new Error('argument 0 is not a Uint8Array'); - } - if (this._state !== STATE_ESTABLISHED && this._state !== STATE_CLOSE_WAIT) { - throw new Error('socket is not connected'); - } + if (!(u8 instanceof Uint8Array)) throw new Error('argument 0 is not a Uint8Array'); + if (this._state !== STATE_ESTABLISHED && this._state !== STATE_CLOSE_WAIT) throw new Error('socket is not connected'); this._bufferedAmount += u8.length; this._queueTx.push(u8); this._fillTransmitQueue(); @@ -427,14 +382,14 @@ class TCPSocket { */ halfclose() { switch (this._state) { - case STATE_ESTABLISHED: - this._state = STATE_FIN_WAIT_1; - break; - case STATE_CLOSE_WAIT: - this._state = STATE_LAST_ACK; - break; - default: - throw netError.E_CANNOT_CLOSE; + case STATE_ESTABLISHED: + this._state = STATE_FIN_WAIT_1; + break; + case STATE_CLOSE_WAIT: + this._state = STATE_LAST_ACK; + break; + default: + throw netError.E_CANNOT_CLOSE; } this._queueTx.push(null); @@ -451,21 +406,19 @@ class TCPSocket { ports.free(this._port); this._destroy(); // TODO: close all connections - if (this.onclose) { - this._emitClose(); - } + if (this.onclose) this._emitClose(); return; } switch (this._state) { - case STATE_ESTABLISHED: - this._state = STATE_FIN_WAIT_1; - break; - case STATE_CLOSE_WAIT: - this._state = STATE_LAST_ACK; - break; - default: - throw netError.E_CANNOT_CLOSE; + case STATE_ESTABLISHED: + this._state = STATE_FIN_WAIT_1; + break; + case STATE_CLOSE_WAIT: + this._state = STATE_LAST_ACK; + break; + default: + throw netError.E_CANNOT_CLOSE; } this._queueTx.push(null); @@ -475,17 +428,13 @@ class TCPSocket { _insertReceiveQueue(seq, len, u8) { // Fast path for ordered data if (seq === this._receiveWindowEdge) { - if (u8 && this.ondata) { - this._emitData(u8); - } + if (u8 && this.ondata) this._emitData(u8); this._receiveWindowSlideTo(SEQ_INC(seq, len)); this._ackRequired = true; this._sendTransmitQueue(); - if (this._receiveQueue.length === 0) { - return; - } + if (this._receiveQueue.length === 0) return; } else { this._receiveQueue.push([seq, len, u8]); } @@ -494,27 +443,25 @@ class TCPSocket { } _processReceiveQueue() { - var lastAck = this._receiveWindowEdge; - var removed = 0; - var queueLength = this._receiveQueue.length; - - for (var j = 0; j < queueLength; ++j) { - var iterRemoved = false; - for (var i = 0; i < queueLength - removed; ++i) { - var item = this._receiveQueue[i]; - var seqNumber = item[0]; - var length = item[1]; - var removeItem = false; - if (length === 0) { - continue; - } + let lastAck = this._receiveWindowEdge; + let removed = 0; + const queueLength = this._receiveQueue.length; + + for (let j = 0; j < queueLength; ++j) { + let iterRemoved = false; + for (let i = 0; i < queueLength - removed; ++i) { + const item = this._receiveQueue[i]; + const seqNumber = item[0]; + const length = item[1]; + let removeItem = false; + if (length === 0) continue; if (lastAck === seqNumber) { lastAck = SEQ_INC(lastAck, length); removeItem = true; } else if (!this._receiveWindowIsWithin(seqNumber, lastAck)) { // order [ seqNumber -- lastAck -- seqNumberEnd ] - var diff = ((lastAck - seqNumber) >>> 0); + const diff = ((lastAck - seqNumber) >>> 0); if (diff < length) { item[0] = SEQ_INC(seqNumber, diff); item[1] = length - diff; @@ -530,7 +477,7 @@ class TCPSocket { ++removed; if (i < queueLength - removed) { - var t = this._receiveQueue[i]; + const t = this._receiveQueue[i]; this._receiveQueue[i] = this._receiveQueue[queueLength - removed]; this._receiveQueue[queueLength - removed] = t; } @@ -540,18 +487,13 @@ class TCPSocket { } } - if (!iterRemoved) { - break; - } + if (!iterRemoved) break; } if (removed > 0) { - var self = this; while (removed-- > 0) { - let removedItem = this._receiveQueue.pop(); - if (removedItem[2] && this.ondata) { - this._emitData(removedItem[2]); - } + const removedItem = this._receiveQueue.pop(); + if (removedItem[2] && this.ondata) this._emitData(removedItem[2]); } this._receiveWindowSlideTo(lastAck); @@ -561,18 +503,13 @@ class TCPSocket { } _isTransmittedUnacked(seq) { - var leftEdge = this._transmitWindowEdge; - var rightEdge = this._transmitPosition; + const leftEdge = this._transmitWindowEdge; + const rightEdge = this._transmitPosition; - if (leftEdge === rightEdge) { - return false; - } + if (leftEdge === rightEdge) return false; - if (leftEdge < rightEdge) { - return seq > leftEdge && seq <= rightEdge; - } else { - return seq > leftEdge || seq <= rightEdge; - } + if (leftEdge < rightEdge) return seq > leftEdge && seq <= rightEdge; + return seq > leftEdge || seq <= rightEdge; } _acceptACK(ackNumber, windowSize) { @@ -585,21 +522,21 @@ class TCPSocket { } _receive(u8, srcIP, srcPort, headerOffset) { - var dataOffset = headerOffset + tcpHeader.getDataOffset(u8, headerOffset); - var flags = tcpHeader.getFlags(u8, headerOffset); - var seqNumber = tcpHeader.getSeqNumber(u8, headerOffset); - var ackNumber = tcpHeader.getAckNumber(u8, headerOffset); - var windowSize = tcpHeader.getWindowSize(u8, headerOffset); - var dataLength = u8.length - dataOffset; + const dataOffset = headerOffset + tcpHeader.getDataOffset(u8, headerOffset); + const flags = tcpHeader.getFlags(u8, headerOffset); + const seqNumber = tcpHeader.getSeqNumber(u8, headerOffset); + const ackNumber = tcpHeader.getAckNumber(u8, headerOffset); + const windowSize = tcpHeader.getWindowSize(u8, headerOffset); + const dataLength = u8.length - dataOffset; switch (this._state) { - case STATE_LISTEN: - var hash = connHash(srcIP, srcPort); - var socket = this._connections.get(hash); - if (socket) { - socket._receive(u8, srcIP, srcPort, headerOffset); - return; - } else { + case STATE_LISTEN: { + const hash = connHash(srcIP, srcPort); + let socket = this._connections.get(hash); + if (socket) { + socket._receive(u8, srcIP, srcPort, headerOffset); + return; + } if (flags & tcpHeader.FLAG_SYN) { socket = new TCPSocket(); socket._serverSocket = this; @@ -616,54 +553,47 @@ class TCPSocket { this._connections.set(hash, socket); this._onconnect(socket); } + return; } - return; - break; - case STATE_SYN_SENT: - this._acceptACK(ackNumber, windowSize); - if (flags & (tcpHeader.FLAG_SYN | tcpHeader.FLAG_ACK)) { - this._receiveWindowSlideTo(seqNumber); - this._receiveWindowSlideInc(); // SYN counts as 1 byte - this._ackRequired = true; - this._sendTransmitQueue(); - this._state = STATE_ESTABLISHED; - if (this.onopen) { - this._emitOpen(); + case STATE_SYN_SENT: + this._acceptACK(ackNumber, windowSize); + if (flags & (tcpHeader.FLAG_SYN | tcpHeader.FLAG_ACK)) { + this._receiveWindowSlideTo(seqNumber); + this._receiveWindowSlideInc(); // SYN counts as 1 byte + this._ackRequired = true; + this._sendTransmitQueue(); + this._state = STATE_ESTABLISHED; + if (this.onopen) this._emitOpen(); } - } - break; - case STATE_SYN_RECEIVED: - this._acceptACK(ackNumber, windowSize); - if (flags & tcpHeader.FLAG_ACK) { - this._state = STATE_ESTABLISHED; - if (this.onopen) { - this._emitOpen(); + break; + case STATE_SYN_RECEIVED: + this._acceptACK(ackNumber, windowSize); + if (flags & tcpHeader.FLAG_ACK) { + this._state = STATE_ESTABLISHED; + if (this.onopen) this._emitOpen(); } - } - break; - case STATE_LAST_ACK: - this._acceptACK(ackNumber, windowSize); - if (this._getTransmitPosition() === ackNumber) { - this._state = STATE_CLOSED; - if (this.onclose) { - this._emitClose(); + break; + case STATE_LAST_ACK: + this._acceptACK(ackNumber, windowSize); + if (this._getTransmitPosition() === ackNumber) { + this._state = STATE_CLOSED; + if (this.onclose) this._emitClose(); + this._destroy(); } - this._destroy(); - } - break; - case STATE_FIN_WAIT_1: - this._acceptACK(ackNumber, windowSize); - if (this._getTransmitPosition() === ackNumber) { - this._state = STATE_FIN_WAIT_2; - } - /* fall through */ - case STATE_FIN_WAIT_2: - case STATE_ESTABLISHED: - this._acceptACK(ackNumber, windowSize); - if (dataLength > 0 && this._receiveWindowIsWithin(SEQ_INC(seqNumber, dataLength - 1), this._receiveWindowEdge)) { - this._insertReceiveQueue(seqNumber, dataLength, u8.subarray(dataOffset)); - } - break; + break; + case STATE_FIN_WAIT_1: + this._acceptACK(ackNumber, windowSize); + if (this._getTransmitPosition() === ackNumber) this._state = STATE_FIN_WAIT_2; + /* fall through */ + case STATE_FIN_WAIT_2: + case STATE_ESTABLISHED: + this._acceptACK(ackNumber, windowSize); + if (dataLength > 0 && this._receiveWindowIsWithin(SEQ_INC(seqNumber, dataLength - 1), this._receiveWindowEdge)) { + this._insertReceiveQueue(seqNumber, dataLength, u8.subarray(dataOffset)); + } + break; + default: + break; } if (flags & tcpHeader.FLAG_FIN) { @@ -672,19 +602,13 @@ class TCPSocket { if (this._state === STATE_FIN_WAIT_2) { this._state = STATE_TIME_WAIT; this._timeWaitTime = timeNow(); - if (this.onend) { - this._emitEnd(); - } - if (this.onclose) { - this._emitClose(); - } + if (this.onend) this._emitEnd(); + if (this.onclose) this._emitClose(); } if (this._state === STATE_ESTABLISHED) { this._state = STATE_CLOSE_WAIT; - if (this.onend) { - this._emitEnd(); - } + if (this.onend) this._emitEnd(); } } } @@ -695,3 +619,5 @@ class TCPSocket { } module.exports = TCPSocket; + +/* eslint-enable new-cap */ diff --git a/js/core/net/tcp-timer.js b/js/core/net/tcp-timer.js index 8520a625a..d89d87ee8 100644 --- a/js/core/net/tcp-timer.js +++ b/js/core/net/tcp-timer.js @@ -13,27 +13,19 @@ // limitations under the License. 'use strict'; -var tcpSocketState = require('./tcp-socket-state'); -var connections = new Set(); +// const tcpSocketState = require('./tcp-socket-state'); +const connections = new Set(); -function timeoutHandler() { - for (var connSocket of connections) { - connSocket._timerTick(); - } +let initTimeout; +const timeoutHandler = () => { + for (const connSocket of connections) connSocket._timerTick(); initTimeout(); -} +}; -function initTimeout() { - setTimeout(timeoutHandler, 500); -} +initTimeout = () => setTimeout(timeoutHandler, 500); initTimeout(); -exports.addConnectionSocket = function(connSocket) { - connections.add(connSocket); -}; - -exports.removeConnectionSocket = function(connSocket) { - connections.delete(connSocket); -}; +exports.addConnectionSocket = (connSocket) => connections.add(connSocket); +exports.removeConnectionSocket = (connSocket) => connections.delete(connSocket); diff --git a/js/core/net/tcp-transmit.js b/js/core/net/tcp-transmit.js index 3f9daff67..b47bc93e1 100644 --- a/js/core/net/tcp-transmit.js +++ b/js/core/net/tcp-transmit.js @@ -13,33 +13,33 @@ // limitations under the License. 'use strict'; -var checksum = require('./checksum'); -var ethernet = require('./ethernet'); -var ip4header = require('./ip4-header'); -var tcpHeader = require('./tcp-header'); -var route = require('./route'); - -module.exports = function(intf, destIP, viaIP, srcPort, destPort, seqNumber, ackNumber, flags, windowSize, u8data) { - var ipOffset = intf.bufferDataOffset + ethernet.headerLength; - var tcpOffset = ipOffset + ip4header.minHeaderLength; - var headerLength = tcpOffset + tcpHeader.headerLength; - var u8headers = new Uint8Array(headerLength); - var dataLength = u8data ? u8data.length : 0; - var datagramLength = dataLength + tcpHeader.headerLength; - - var srcIP = intf.ipAddr; +const checksum = require('./checksum'); +const ethernet = require('./ethernet'); +const ip4header = require('./ip4-header'); +const tcpHeader = require('./tcp-header'); +// const route = require('./route'); + +module.exports = (intf, destIP, viaIP, srcPort, destPort, seqNumber, ackNumber, flags, windowSize, u8data) => { + const ipOffset = intf.bufferDataOffset + ethernet.headerLength; + const tcpOffset = ipOffset + ip4header.minHeaderLength; + const headerLength = tcpOffset + tcpHeader.headerLength; + const u8headers = new Uint8Array(headerLength); + const dataLength = u8data ? u8data.length : 0; + const datagramLength = dataLength + tcpHeader.headerLength; + + const srcIP = intf.ipAddr; ip4header.write(u8headers, ipOffset, ip4header.PROTOCOL_TCP, srcIP, destIP, ip4header.minHeaderLength + tcpHeader.headerLength + dataLength); tcpHeader.write(u8headers, tcpOffset, srcPort, destPort, seqNumber, ackNumber, flags, windowSize); - var sum = ((destIP.a << 8) | destIP.b) + ((destIP.c << 8) | destIP.d) + + const sum = ((destIP.a << 8) | destIP.b) + ((destIP.c << 8) | destIP.d) + ((srcIP.a << 8) | srcIP.b) + ((srcIP.c << 8) | srcIP.d) + datagramLength + ip4header.PROTOCOL_TCP; - var ckHeader = checksum.buffer(u8headers, tcpOffset, tcpHeader.headerLength); - var ckData = u8data ? checksum.buffer(u8data, 0, u8data.length) : 0; - var ck = checksum.result(ckHeader + ckData + sum); + const ckHeader = checksum.buffer(u8headers, tcpOffset, tcpHeader.headerLength); + const ckData = u8data ? checksum.buffer(u8data, 0, u8data.length) : 0; + const ck = checksum.result(ckHeader + ckData + sum); tcpHeader.writeChecksum(u8headers, tcpOffset, ck); diff --git a/js/core/net/tcp.js b/js/core/net/tcp.js index 208ce2849..cc1127fb1 100644 --- a/js/core/net/tcp.js +++ b/js/core/net/tcp.js @@ -13,34 +13,24 @@ // limitations under the License. 'use strict'; -var tcpHeader = require('./tcp-header'); -var TCPSocket = require('./tcp-socket'); -var tcpSocketState = require('./tcp-socket-state'); -var connHash = require('./tcp-hash'); -var STATE_LISTEN = tcpSocketState.STATE_LISTEN; +const tcpHeader = require('./tcp-header'); +const TCPSocket = require('./tcp-socket'); +const tcpSocketState = require('./tcp-socket-state'); +const connHash = require('./tcp-hash'); +const STATE_LISTEN = tcpSocketState.STATE_LISTEN; -function connectionSocket(socket, srcIP, srcPort) { - var hash = connHash(srcIP, srcPort); - return socket._connections.get(hash) || socket; -} +const connectionSocket = (socket, srcIP, srcPort) => socket._connections.get(connHash(srcIP, srcPort)) || socket; -exports.receive = function(intf, srcIP, destIP, u8, headerOffset) { - var srcPort = tcpHeader.getSrcPort(u8, headerOffset); - var destPort = tcpHeader.getDestPort(u8, headerOffset); - var dataOffset = headerOffset + tcpHeader.getDataOffset(u8, headerOffset); +exports.receive = (intf, srcIP, destIP, u8, headerOffset) => { + const srcPort = tcpHeader.getSrcPort(u8, headerOffset); + const destPort = tcpHeader.getDestPort(u8, headerOffset); + // const dataOffset = headerOffset + tcpHeader.getDataOffset(u8, headerOffset); - var socket = TCPSocket.lookupReceive(destPort); - if (!socket) { - return; - } + let socket = TCPSocket.lookupReceive(destPort); - if (socket._state === STATE_LISTEN) { - socket = connectionSocket(socket, srcIP, srcPort); - } - - if (!socket._intf) { - socket._intf = intf; - } + if (!socket) return; + if (socket._state === STATE_LISTEN) socket = connectionSocket(socket, srcIP, srcPort); + if (!socket._intf) socket._intf = intf; socket._receive(u8, srcIP, srcPort, headerOffset); }; diff --git a/js/core/net/udp-header.js b/js/core/net/udp-header.js index 40086258f..c875f04c4 100644 --- a/js/core/net/udp-header.js +++ b/js/core/net/udp-header.js @@ -13,29 +13,19 @@ // limitations under the License. 'use strict'; -var u8view = require('u8-view'); +const u8view = require('u8-view'); -exports.getSrcPort = function(u8, headerOffset) { - return ((u8[headerOffset] << 8) + u8[headerOffset + 1]) >>> 0; -}; - -exports.getDestPort = function(u8, headerOffset) { - return ((u8[headerOffset + 2] << 8) + u8[headerOffset + 3]) >>> 0; -}; - -exports.getDataLength = function(u8, headerOffset) { - return ((u8[headerOffset + 4] << 8) + u8[headerOffset + 5]) >>> 0; -}; +exports.getSrcPort = (u8, headerOffset) => ((u8[headerOffset] << 8) + u8[headerOffset + 1]) >>> 0; +exports.getDestPort = (u8, headerOffset) => ((u8[headerOffset + 2] << 8) + u8[headerOffset + 3]) >>> 0; +exports.getDataLength = (u8, headerOffset) => ((u8[headerOffset + 4] << 8) + u8[headerOffset + 5]) >>> 0; exports.headerLength = 8; -exports.write = function(u8, headerOffset, srcPort, destPort, dataLength) { +exports.write = (u8, headerOffset, srcPort, destPort, dataLength) => { u8view.setUint16BE(u8, headerOffset, srcPort); u8view.setUint16BE(u8, headerOffset + 2, destPort); u8view.setUint16BE(u8, headerOffset + 4, dataLength); u8view.setUint16BE(u8, headerOffset + 6, 0); }; -exports.writeChecksum = function(u8, headerOffset, checksum) { - u8view.setUint16BE(u8, headerOffset + 6, checksum); -}; +exports.writeChecksum = (u8, headerOffset, checksum) => u8view.setUint16BE(u8, headerOffset + 6, checksum); diff --git a/js/core/net/udp-socket.js b/js/core/net/udp-socket.js index 50c0c24df..32e182469 100644 --- a/js/core/net/udp-socket.js +++ b/js/core/net/udp-socket.js @@ -13,57 +13,49 @@ // limitations under the License. 'use strict'; -var assertError = require('assert-error'); -var IP4Address = require('./ip4-address'); -var portUtils = require('./port-utils'); -var PortAllocator = require('./port-allocator'); -var udpTransmit = require('./udp-transmit'); -var netError = require('./net-error'); -var typeutils = require('typeutils'); -var route = require('./route'); +const assertError = require('assert-error'); +const IP4Address = require('./ip4-address'); +const portUtils = require('./port-utils'); +const PortAllocator = require('./port-allocator'); +const udpTransmit = require('./udp-transmit'); +const netError = require('./net-error'); +const typeutils = require('typeutils'); +const route = require('./route'); -var ports = new PortAllocator(); +const ports = new PortAllocator(); class UDPSocket { - constructor(protocol) { - this._protocol = protocol || 'ip4'; + constructor(protocol = 'ip4') { + this._protocol = protocol; this._intf = null; this._port = 0; this.onmessage = null; } - send(ip, port, u8) { - if (typeutils.isString(ip)) { - ip = IP4Address.parse(ip); - } + send(ipOpt, port, u8) { + let ip = ipOpt; + if (typeutils.isString(ip)) ip = IP4Address.parse(ip); assertError(ip instanceof IP4Address, netError.E_IPADDRESS_EXPECTED); assertError(portUtils.isPort(port), netError.E_INVALID_PORT); assertError(u8 instanceof Uint8Array, netError.E_TYPEDARRAY_EXPECTED); - var intf = this._intf || null; + let intf = this._intf || null; - var viaIP; + let viaIP; if (ip.isBroadcast()) { viaIP = ip; } else { - var routingEntry = route.lookup(ip); - if (!routingEntry) { - console.log('[UDP] no route to ' + ip); - return; - } + const routingEntry = route.lookup(ip); + if (!routingEntry) return console.log(`[UDP] no route to ${ip}`); viaIP = routingEntry.gateway; - if (!intf) { - intf = routingEntry.intf; - } + if (!intf) intf = routingEntry.intf; } if (!this._port) { this._port = ports.allocEphemeral(this); - if (!this._port) { - throw netError.E_NO_FREE_PORT; - } + if (!this._port) throw netError.E_NO_FREE_PORT; } udpTransmit(intf, ip, viaIP, this._port, port, u8); @@ -72,9 +64,7 @@ class UDPSocket { bind(port) { assertError(portUtils.isPort(port), netError.E_INVALID_PORT); - if (!ports.allocPort(port, this)) { - throw netError.E_ADDRESS_IN_USE; - } + if (!ports.allocPort(port, this)) throw netError.E_ADDRESS_IN_USE; this._port = port; } @@ -85,15 +75,11 @@ class UDPSocket { } this._intf = intf; - if (port) { - this.bind(port); - } + if (port) this.bind(port); } close() { - if (this._port) { - ports.free(this._port); - } + if (this._port) ports.free(this._port); } static lookupReceive(destPort) { diff --git a/js/core/net/udp-transmit.js b/js/core/net/udp-transmit.js index 3f3e54c45..d34958a10 100644 --- a/js/core/net/udp-transmit.js +++ b/js/core/net/udp-transmit.js @@ -13,31 +13,31 @@ // limitations under the License. 'use strict'; -var checksum = require('./checksum'); -var ethernet = require('./ethernet'); -var ip4header = require('./ip4-header'); -var udpHeader = require('./udp-header'); -var route = require('./route'); +const checksum = require('./checksum'); +const ethernet = require('./ethernet'); +const ip4header = require('./ip4-header'); +const udpHeader = require('./udp-header'); +// const route = require('./route'); -module.exports = function(intf, destIP, viaIP, srcPort, destPort, u8data) { - var ipOffset = intf.bufferDataOffset + ethernet.headerLength; - var udpOffset = ipOffset + ip4header.minHeaderLength; - var headerLength = udpOffset + udpHeader.headerLength; - var u8headers = new Uint8Array(headerLength); - var datagramLength = u8data.length + udpHeader.headerLength; +module.exports = (intf, destIP, viaIP, srcPort, destPort, u8data) => { + const ipOffset = intf.bufferDataOffset + ethernet.headerLength; + const udpOffset = ipOffset + ip4header.minHeaderLength; + const headerLength = udpOffset + udpHeader.headerLength; + const u8headers = new Uint8Array(headerLength); + const datagramLength = u8data.length + udpHeader.headerLength; - var srcIP = intf.ipAddr; + const srcIP = intf.ipAddr; ip4header.write(u8headers, ipOffset, ip4header.PROTOCOL_UDP, srcIP, destIP, ip4header.minHeaderLength + udpHeader.headerLength + u8data.length); udpHeader.write(u8headers, udpOffset, srcPort, destPort, datagramLength); - var sum = ((destIP.a << 8) | destIP.b) + ((destIP.c << 8) | destIP.d) + + const sum = ((destIP.a << 8) | destIP.b) + ((destIP.c << 8) | destIP.d) + ((srcIP.a << 8) | srcIP.b) + ((srcIP.c << 8) | srcIP.d) + datagramLength + ip4header.PROTOCOL_UDP + srcPort + destPort + datagramLength; - var ck = checksum(u8data, 0, u8data.length, sum); + const ck = checksum(u8data, 0, u8data.length, sum); udpHeader.writeChecksum(u8headers, udpOffset, ck); intf.sendIP4(viaIP || destIP, u8headers, u8data); diff --git a/js/core/net/udp.js b/js/core/net/udp.js index c0d173189..08c88c93d 100644 --- a/js/core/net/udp.js +++ b/js/core/net/udp.js @@ -13,31 +13,25 @@ // limitations under the License. 'use strict'; -var udpHeader = require('./udp-header'); -var UDPSocket = require('./udp-socket'); -var portUtils = require('./port-utils'); -var IP4Address = require('./ip4-address'); -var interfaces = require('./interfaces'); -var netError = require('./net-error'); +const udpHeader = require('./udp-header'); +const UDPSocket = require('./udp-socket'); +// const portUtils = require('./port-utils'); +// const IP4Address = require('./ip4-address'); +// const interfaces = require('./interfaces'); +// const netError = require('./net-error'); -function receive(intf, srcIP, destIP, u8, headerOffset) { - var srcPort = udpHeader.getSrcPort(u8, headerOffset); - var destPort = udpHeader.getDestPort(u8, headerOffset); - var dataLength = udpHeader.getDataLength(u8, headerOffset) - udpHeader.headerLength; - var dataOffset = headerOffset + udpHeader.headerLength; +const receive = (intf, srcIP, destIP, u8, headerOffset) => { + const srcPort = udpHeader.getSrcPort(u8, headerOffset); + const destPort = udpHeader.getDestPort(u8, headerOffset); + const dataLength = udpHeader.getDataLength(u8, headerOffset) - udpHeader.headerLength; + const dataOffset = headerOffset + udpHeader.headerLength; debug('recv UDP over IP4', srcPort, destPort, dataLength); - var socket = UDPSocket.lookupReceive(destPort); - if (!socket) { - return; - } + const socket = UDPSocket.lookupReceive(destPort); + if (!socket) return; - var u8data = u8.subarray(dataOffset); - if (socket.onmessage) { - setImmediate(function() { - socket.onmessage(srcIP, srcPort, u8data); - }); - } -} + const u8data = u8.subarray(dataOffset); + if (socket.onmessage) setImmediate(() => socket.onmessage(srcIP, srcPort, u8data)); +}; exports.receive = receive; diff --git a/js/test/unit/virtio/index.js b/js/test/unit/virtio/index.js index 751422df3..ecbeb5152 100644 --- a/js/test/unit/virtio/index.js +++ b/js/test/unit/virtio/index.js @@ -28,8 +28,8 @@ const bufferWriteNumbers = (u8, value) => { return u8; }; -const getOnePageBuffer = (index) => { - index = index | 0; +const getOnePageBuffer = (indexOpt) => { + const index = indexOpt | 0; const b = new Uint8Array(resources.memoryRange.block(0x2000000 + (index * 22), 22).buffer()); clearBuffer(b); return b; From 7c160162b6ced41079ba5e4717f25dac7b0b6bf4 Mon Sep 17 00:00:00 2001 From: Face Kapow Date: Mon, 11 Jul 2016 19:08:48 -0400 Subject: [PATCH 16/22] Code fix --- js/modules/dns.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/modules/dns.js b/js/modules/dns.js index 275e2a32e..39b93ae6e 100644 --- a/js/modules/dns.js +++ b/js/modules/dns.js @@ -77,12 +77,12 @@ const lookup = (hostname, optsOpt, cb) => { return; } const ret = []; - for (const i of Object.keys(data.results)) { + for (const i of [...data.results.keys()])) { const res = data.results[i]; if (!opts.all && i === 0) { const addr = res.address.join('.'); if (cb) cb(null, addr, 4); - break; + return; } else { switch (res.record) { case 'A': From c8d8fd0e5979f485f48b4d96a4e87b8919dd64a8 Mon Sep 17 00:00:00 2001 From: Face Kapow Date: Mon, 11 Jul 2016 19:11:07 -0400 Subject: [PATCH 17/22] Code fix (again) --- js/modules/dns.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/js/modules/dns.js b/js/modules/dns.js index 39b93ae6e..371d6228a 100644 --- a/js/modules/dns.js +++ b/js/modules/dns.js @@ -53,8 +53,7 @@ const throwIPv6Err = (cb) => { throw err; }; -const lookup = (hostname, optsOpt, cb) => { - const opts = optsOpt; +const lookup = (hostname, opts, cb) => { if (opts.family && opts.family === 6) return throwIPv6Err(cb); opts.query = opts.query || 'A'; if (hostname === 'localhost' && opts.query === 'A') { @@ -77,7 +76,7 @@ const lookup = (hostname, optsOpt, cb) => { return; } const ret = []; - for (const i of [...data.results.keys()])) { + for (const i of [...data.results.keys()]) { const res = data.results[i]; if (!opts.all && i === 0) { const addr = res.address.join('.'); From 51a90e7dc0d0c4aae613474be85d7557601281ec Mon Sep 17 00:00:00 2001 From: Face Kapow Date: Sun, 24 Jul 2016 18:00:50 -0400 Subject: [PATCH 18/22] Update style --- .eslintrc | 8 + docs/code-style-exceptions.md | 22 +- js/__loader.js | 101 ++-- js/component/dns-client/dns-packet.js | 41 +- js/component/dns-client/index.js | 20 +- js/component/dns-client/is-domain.js | 20 +- js/core/cmos-time.js | 10 +- js/core/net/arp-resolver.js | 4 +- js/core/net/checksum.js | 20 +- js/core/net/icmp.js | 20 +- js/core/net/index.js | 4 +- js/core/net/interface.js | 18 +- js/core/net/interfaces.js | 4 +- js/core/net/ip4-address.js | 37 +- js/core/net/ip4-fragments.js | 53 ++- js/core/net/ip4.js | 4 +- js/core/net/mac-address.js | 33 +- js/core/net/net-error.js | 4 +- js/core/net/ping.js | 32 +- js/core/net/port-allocator.js | 28 +- js/core/net/route.js | 4 +- js/core/net/tcp-server-socket.js | 4 +- js/core/net/tcp-socket-state.js | 26 +- js/core/net/tcp-socket.js | 216 ++++++--- js/core/net/tcp-timer.js | 14 +- js/core/net/tcp.js | 16 +- js/core/net/udp-socket.js | 24 +- js/core/net/udp.js | 8 +- js/core/pci/index.js | 28 +- js/core/pci/scan.js | 508 +++++++++++++++------ js/core/random/entropy-source.js | 10 +- js/core/random/index.js | 44 +- js/core/random/isaac-wrapper.js | 4 +- js/core/random/js-random-source.js | 4 +- js/core/set-time.js | 16 +- js/core/stdio/interface.js | 19 +- js/core/timers.js | 8 +- js/core/tty/line-editor.js | 16 +- js/core/tty/printer.js | 40 +- js/core/tty/terminal.js | 16 +- js/core/tty/vga.js | 51 ++- js/driver/ps2/keyboard.js | 56 ++- js/driver/virtio/device.js | 42 +- js/driver/virtio/index.js | 12 +- js/driver/virtio/net.js | 45 +- js/driver/virtio/rng.js | 20 +- js/driver/virtio/vring/descriptor-table.js | 21 +- js/driver/virtio/vring/index.js | 29 +- js/index.js | 4 +- js/modules/console.js | 8 +- js/modules/dns.js | 80 ++-- js/modules/errors.js | 4 +- js/modules/fs.js | 52 ++- js/modules/net.js | 68 ++- js/modules/os.js | 5 +- js/modules/process.js | 8 +- js/service/dhcp-client/dhcp-options.js | 4 +- js/service/dhcp-client/dhcp-packet.js | 28 +- js/service/dhcp-client/index.js | 80 ++-- js/service/shell/index.js | 16 +- js/test/unit/buffers/physical-address.js | 8 +- js/test/unit/index.js | 4 +- js/test/unit/lib/buffer-builder.js | 12 +- js/test/unit/lib/packet-builder.js | 119 +++-- js/test/unit/net/ip4.js | 240 +++++++--- js/test/unit/net/port-allocator.js | 36 +- js/test/unit/net/tcp-receive.js | 456 ++++++++++++------ js/test/unit/net/tcp.js | 101 ++-- js/test/unit/random/index.js | 4 +- js/test/unit/timers/index.js | 10 +- js/test/unit/virtio/index.js | 36 +- js/version.js | 4 +- package.json | 1 + 73 files changed, 2169 insertions(+), 1003 deletions(-) diff --git a/.eslintrc b/.eslintrc index 28d038bf0..0336bf637 100644 --- a/.eslintrc +++ b/.eslintrc @@ -29,6 +29,14 @@ rules: no-return-assign: 1 new-cap: 1 no-console: 0 + wrap-iife: + - 2 + - 'inside' + no-use-before-define: + - 2 + - + functions: false + classes: true parserOptions: ecmaVersion: 6 diff --git a/docs/code-style-exceptions.md b/docs/code-style-exceptions.md index f8d30b588..54c6e292e 100644 --- a/docs/code-style-exceptions.md +++ b/docs/code-style-exceptions.md @@ -37,7 +37,7 @@ You can (and should) use ES6 `get` and `set` in new APIs, it's already used in v ## Assigning to functions parameters -You cannot *reassign* functions parameters, but you can assign to *properties of* function parameters. +You cannot reassign *functions parameters*, but you can assign to *properties of* function parameters. ```js // yes const demo = (myObject) => { @@ -46,8 +46,8 @@ const demo = (myObject) => { } // no -const demo = (myUint8Array) => { - myUint8Array = { +const demo = (myObject) => { + myObject = { someProperty: 'my value' }; // ... @@ -61,3 +61,19 @@ If you get this warning, it's ok: But this is not: > Assignment to function parameter 'parameter-name' + +## Wrapping an IIFE + +The invocation should be *outside* the parentheses, not inside. + +```js +// yes +(function() { + // ... +})(); + +// no +(function() { + +}()); +``` diff --git a/js/__loader.js b/js/__loader.js index 6def514ac..bb188d0fe 100644 --- a/js/__loader.js +++ b/js/__loader.js @@ -21,18 +21,27 @@ const cache = {}; const builtinsResolveFromComponents = builtinsResolveFrom.split('/'); - const throwError = (err) => { throw err; }; - const endsWith = (str, suffix) => str.indexOf(suffix, str.length - suffix.length) !== -1; + function throwError(err) { + throw err; + } + + function endsWith(str, suffix) { + return str.indexOf(suffix, str.length - suffix.length) !== -1; + } - const normalizePath = (components) => { + function normalizePath(components) { const r = []; for (const p of components) { if (p === '') { - if (r.length === 0) r.push(p); + if (r.length === 0) { + r.push(p); + } continue; } - if (p === '.') continue; + if (p === '.') { + continue; + } if (p === '..') { if (r.length > 0) { @@ -46,18 +55,18 @@ } return r; - }; + } - const loadAsFile = (path) => { + function loadAsFile(path) { if (existsFileFn(path)) return path; if (existsFileFn(`${path}.js`)) return `${path}.js`; if (existsFileFn(`${path}.json`)) return `${path}.json`; if (existsFileFn(`${path}.node`)) return `${path}.node`; return null; - }; + } - const getPackageMain = (packageJsonFile) => { + function getPackageMain(packageJsonFile) { const json = readFileFn(packageJsonFile); let parsed = null; try { @@ -74,9 +83,9 @@ } return parsed.main || 'index.js'; - }; + } - const loadAsDirectory = (path, ignoreJson) => { + function loadAsDirectory(path, ignoreJson) { let mainFile = 'index'; let dir = false; if (!ignoreJson && existsFileFn(`${path}/package.json`)) { @@ -85,41 +94,55 @@ } const normalizedPath = normalizePath(path.split('/').concat(mainFile.split('/'))); - if (!normalizedPath) return null; + if (!normalizedPath) { + return null; + } const s = normalizedPath.join('/'); const res = loadAsFile(s); - if (res) return res; + if (res) { + return res; + } - if (dir) return loadAsDirectory(s, true); + if (dir) { + return loadAsDirectory(s, true); + } return null; - }; + } - const loadNodeModules = (dirComponents, parts) => { + function loadNodeModules(dirComponents, parts) { let count = dirComponents.length; while (count-- > 0) { let p = dirComponents.slice(0, count + 1); - if (p.length === 0) continue; + if (p.length === 0) { + continue; + } - if (p[p.length - 1] === 'node_modules') continue; + if (p[p.length - 1] === 'node_modules') { + continue; + } p.push('node_modules'); p = p.concat(parts); const normalizedPath = normalizePath(p); - if (!normalizedPath) continue; + if (!normalizedPath) { + continue; + } const s = normalizedPath.join('/'); const loadedPath = loadAsFile(s) || loadAsDirectory(s, false) || null; - if (loadedPath) return loadedPath; + if (loadedPath) { + return loadedPath; + } } return null; - }; + } - const resolve = (module, pathOpt = '') => { + function resolve(module, pathOpt = '') { let path = String(pathOpt); let resolveFrom = module.dirComponents; @@ -134,14 +157,16 @@ // starts with ./ ../ or / if (firstPathComponent === '.' || - firstPathComponent === '..' || - firstPathComponent === '') { - const combinedPathComponents = (firstPathComponent === '') - ? pathComponents - : resolveFrom.concat(pathComponents); + firstPathComponent === '..' || + firstPathComponent === '') { + const combinedPathComponents = (firstPathComponent === '') ? + pathComponents : + resolveFrom.concat(pathComponents); const normalizedPath = normalizePath(combinedPathComponents); - if (!normalizedPath) return null; + if (!normalizedPath) { + return null; + } const pathStr = normalizedPath.join('/'); const loadedPath = loadAsFile(pathStr) || loadAsDirectory(pathStr, false) || null; @@ -149,7 +174,7 @@ } return loadNodeModules(resolveFrom, pathComponents); - }; + } class Module { constructor(pathComponents) { @@ -170,7 +195,9 @@ const pathComponents = resolvedPath.split('/'); const displayPath = resolvedPath; const cacheKey = pathComponents.join('/'); - if (cache[cacheKey]) return cache[cacheKey].exports; + if (cache[cacheKey]) { + return cache[cacheKey].exports; + } const currentModule = global.module; module = new Module(pathComponents); @@ -189,10 +216,8 @@ } else { /* eslint-disable max-len */ evalScriptFn( - `(function(require,exports,module,__filename,__dirname){ -${content} -})((function(m){return function(path){return m.require(path)}})(global.module),global.module.exports,global.module,global.module.filename,global.module.dirname)`, - displayPath); + `(function(require,exports,module,__filename,__dirname){${content}})((function(m){return function(path){return m.require(path)}})(global.module),global.module.exports,global.module,global.module.filename,global.module.dirname)`, + displayPath); /* eslint-enable max-len */ } @@ -211,9 +236,13 @@ ${content} // end const files = {}; - for (const file of __SYSCALL.initrdListFiles()) files[file] = true; + for (const file of __SYSCALL.initrdListFiles()) { + files[file] = true; + } - const fileExists = path => !!files[path]; + function fileExists(path) { + return !!files[path]; + } const runtimePackagePath = __SYSCALL.initrdGetKernelIndex().split('/').slice(0, -1).join('/'); const loader = new Loader(fileExists, __SYSCALL.initrdReadFile, __SYSCALL.eval, { diff --git a/js/component/dns-client/dns-packet.js b/js/component/dns-client/dns-packet.js index ddf336497..315465c20 100644 --- a/js/component/dns-client/dns-packet.js +++ b/js/component/dns-client/dns-packet.js @@ -36,7 +36,9 @@ exports.getQuery = (domain, query) => { let bufferLength = 17; const labels = domain.split('.'); - for (const label of labels) bufferLength += label.length + 1; + for (const label of labels) { + bufferLength += label.length + 1; + } const u8 = new Uint8Array(bufferLength); const view = new DataView(u8.buffer); @@ -54,7 +56,9 @@ exports.getQuery = (domain, query) => { for (const label of labels) { view.setUint8(offset++, label.length); - for (let j = 0; j < label.length; ++j) view.setUint8(offset++, label.charCodeAt(j)); + for (let j = 0; j < label.length; ++j) { + view.setUint8(offset++, label.charCodeAt(j)); + } } view.setUint8(offset++, 0); // null terminator @@ -64,14 +68,19 @@ exports.getQuery = (domain, query) => { }; const POINTER_VALUE = 0xc0; -const isPointer = value => (value & POINTER_VALUE) === POINTER_VALUE; -const readHostname = (reader) => { +function isPointer(value) { + return (value & POINTER_VALUE) === POINTER_VALUE; +} + +function readHostname(reader) { let labels = []; for (let z = reader.getOffset(); z < reader.len; ++z) { const len = reader.readUint8(); - if (len === 0) break; + if (len === 0) { + break; + } if (isPointer(len)) { const ptrOffset = ((len - POINTER_VALUE) << 8) + reader.readUint8(); @@ -82,20 +91,24 @@ const readHostname = (reader) => { break; } else { let label = ''; - for (let i = 0; i < len; ++i) label += String.fromCharCode(reader.readUint8()); + for (let i = 0; i < len; ++i) { + label += String.fromCharCode(reader.readUint8()); + } labels.push(label); } } return labels; -}; +} exports.parseResponse = (u8) => { const reader = new PacketReader(u8.buffer, u8.byteLength, u8.byteOffset); const responseRandomId = reader.readUint16(); - if (responseRandomId !== randomId) return null; + if (responseRandomId !== randomId) { + return null; + } /* eslint-disable no-unused-vars */ const flags = reader.readUint16(); @@ -105,7 +118,9 @@ exports.parseResponse = (u8) => { const additionalCount = reader.readUint16(); /* eslint-enable no-unused-vars */ - if (questionsCount !== 1) return null; + if (questionsCount !== 1) { + return null; + } // Read question const hostname = readHostname(reader).join('.'); @@ -127,7 +142,9 @@ exports.parseResponse = (u8) => { switch (recordType) { case queries.A: // A record - if (rdLen !== 4) return null; + if (rdLen !== 4) { + return null; + } results.push({ hostname: host, @@ -149,7 +166,9 @@ exports.parseResponse = (u8) => { }); break; default: - for (let b = 0; b < rdLen; ++b) reader.readUint8(); + for (let b = 0; b < rdLen; ++b) { + reader.readUint8(); + } break; } } diff --git a/js/component/dns-client/index.js b/js/component/dns-client/index.js index 7fcf6e396..4d14af1bd 100644 --- a/js/component/dns-client/index.js +++ b/js/component/dns-client/index.js @@ -23,8 +23,12 @@ const { IP4Address, UDPSocket } = runtime.net; class DNSClient { constructor(serverIP, serverPort) { assert(this instanceof DNSClient); - if (serverIP) assert(serverIP instanceof IP4Address); - if (serverPort) assert(isint.uint16(serverPort)); + if (serverIP) { + assert(serverIP instanceof IP4Address); + } + if (serverPort) { + assert(isint.uint16(serverPort)); + } this._socket = new UDPSocket(); this._serverIP = serverIP || new IP4Address(8, 8, 8, 8); @@ -34,7 +38,9 @@ class DNSClient { this._socket.onmessage = (ip, port, u8) => { const data = dnsPacket.parseResponse(u8); - if (!data) return; + if (!data) { + return; + } debug('DNS recv', ip, port, JSON.stringify(data)); @@ -42,7 +48,9 @@ class DNSClient { const domain = data.hostname; for (let i = 0; i < requests.length; i++) { const req = requests[i]; - if (!req) continue; + if (!req) { + continue; + } if (req.domain === domain) { req.cb(null, data); @@ -57,7 +65,9 @@ class DNSClient { for (let i = 0; i < requests.length; i++) { const req = requests[i]; - if (!req) continue; + if (!req) { + continue; + } if (req.retry > 0) { this._sendQuery(req.domain, req.opts.query || 'A'); diff --git a/js/component/dns-client/is-domain.js b/js/component/dns-client/is-domain.js index 0cfc53578..b19000899 100644 --- a/js/component/dns-client/is-domain.js +++ b/js/component/dns-client/is-domain.js @@ -17,14 +17,24 @@ const typeutils = require('typeutils'); const domainRegex = /^[a-z0-9.-]+$/; module.exports = (domain) => { - if (!typeutils.isString(domain)) return false; + if (!typeutils.isString(domain)) { + return false; + } - if (domain.length > 255) return false; + if (domain.length > 255) { + return false; + } - if (!domainRegex.test(domain)) return false; + if (!domainRegex.test(domain)) { + return false; + } const labels = domain.split('.'); - for (const label of labels) if (label.length < 1 || label.length > 63) return false; + for (const label of labels) { + if (label.length < 1 || label.length > 63) { + return false; + } - return true; + return true; + } }; diff --git a/js/core/cmos-time.js b/js/core/cmos-time.js index d7b37c612..691e8cb73 100644 --- a/js/core/cmos-time.js +++ b/js/core/cmos-time.js @@ -33,15 +33,15 @@ const cmosData = 0x71; const port = ports.port(cmosAddress); const dataPort = ports.port(cmosData); -const getUpdateInProgressFlag = () => { +function getUpdateInProgressFlag() { port.write8(0x0A); return (dataPort.read8() & 0x80); -}; +} -const getRTCRegister = (reg) => { +function getRTCRegister(reg) { port.write8(reg); return dataPort.read8(); -}; +} // set the time: @@ -78,7 +78,7 @@ do { month = getRTCRegister(0x08); year = getRTCRegister(0x09); } while ((lastSecond !== second) || (lastMinute !== minute) || (lastHour !== hour) || - (lastDay !== day) || (lastMonth !== month) || (lastYear !== year)); + (lastDay !== day) || (lastMonth !== month) || (lastYear !== year)); registerB = getRTCRegister(0x0B); diff --git a/js/core/net/arp-resolver.js b/js/core/net/arp-resolver.js index f419e4493..96739eeb8 100644 --- a/js/core/net/arp-resolver.js +++ b/js/core/net/arp-resolver.js @@ -37,7 +37,9 @@ class ARPResolver { switch (operation) { case arpHeader.OPERATION_REQEUST: // Somebody requested this machine IP - if (!selfIP.equals(IP4Address.ANY) && selfIP.equals(targetIP)) this.reply(srcMAC, targetIP); + if (!selfIP.equals(IP4Address.ANY) && selfIP.equals(targetIP)) { + this.reply(srcMAC, targetIP); + } break; case arpHeader.OPERATION_REPLY: this.table.set(srcIP.hash(), srcMAC); diff --git a/js/core/net/checksum.js b/js/core/net/checksum.js index 82d91abef..c92cd89f7 100644 --- a/js/core/net/checksum.js +++ b/js/core/net/checksum.js @@ -14,26 +14,34 @@ 'use strict'; -const checksum = (u8, offset, len, extraSum) => { +function checksum(u8, offset, len, extraSum) { const count = len >>> 1; let acc = (extraSum >>> 0); - for (let i = 0; i < count; ++i) acc += (u8[offset + (i * 2)] << 8) + u8[(offset + (i * 2)) + 1]; + for (let i = 0; i < count; ++i) { + acc += (u8[offset + (i * 2)] << 8) + u8[(offset + (i * 2)) + 1]; + } - if (count * 2 !== len) acc += u8[offset + (count * 2)] << 8; + if (count * 2 !== len) { + acc += u8[offset + (count * 2)] << 8; + } acc = (acc & 0xffff) + (acc >>> 16); acc += (acc >>> 16); return ((~acc) & 0xffff) >>> 0; -}; +} module.exports = checksum; module.exports.buffer = (u8, offset, len) => { const count = len >>> 1; let acc = 0; - for (let i = 0; i < count; ++i) acc += (u8[offset + (i * 2)] << 8) + u8[(offset + (i * 2)) + 1]; + for (let i = 0; i < count; ++i) { + acc += (u8[offset + (i * 2)] << 8) + u8[(offset + (i * 2)) + 1]; + } - if (count * 2 !== len) acc += u8[offset + (count * 2)] << 8; + if (count * 2 !== len) { + acc += u8[offset + (count * 2)] << 8; + } return acc; }; diff --git a/js/core/net/icmp.js b/js/core/net/icmp.js index 70d977a7b..f9b637c4d 100644 --- a/js/core/net/icmp.js +++ b/js/core/net/icmp.js @@ -19,8 +19,10 @@ const icmpTransmit = require('./icmp-transmit'); const route = require('./route'); const Ping = require('./ping'); -const handleEchoRequest = (intf, srcIP, u8, headerOffset) => { - if (srcIP.isBroadcast() || srcIP.isAny()) return; +function handleEchoRequest(intf, srcIP, u8, headerOffset) { + if (srcIP.isBroadcast() || srcIP.isAny()) { + return; + } const routingEntry = route.lookup(srcIP); if (!routingEntry) { @@ -33,16 +35,18 @@ const handleEchoRequest = (intf, srcIP, u8, headerOffset) => { const seq = icmpHeader.getEchoRequestSequence(u8, headerOffset); icmpTransmit(intf, srcIP, viaIP, icmpHeader.ICMP_TYPE_ECHO_REPLY, 0, - icmpHeader.headerValueEcho(id, seq), - u8.subarray(headerOffset + icmpHeader.headerLength)); -}; + icmpHeader.headerValueEcho(id, seq), + u8.subarray(headerOffset + icmpHeader.headerLength)); +} -const handleEchoReply = (intf, srcIP, u8, headerOffset) => { +function handleEchoReply(intf, srcIP, u8, headerOffset) { const id = icmpHeader.getEchoRequestIdentifier(u8, headerOffset); const seq = icmpHeader.getEchoRequestSequence(u8, headerOffset); const ping = Ping._receiveLookup(id); - if (ping) ping._receive(srcIP, seq, u8, headerOffset + icmpHeader.headerLength); -}; + if (ping) { + ping._receive(srcIP, seq, u8, headerOffset + icmpHeader.headerLength); + } +} exports.receive = (intf, srcIP, destIP, u8, headerOffset) => { debug('recv ICMP over IP4'); diff --git a/js/core/net/index.js b/js/core/net/index.js index 97233bc1c..a8eff5cf1 100644 --- a/js/core/net/index.js +++ b/js/core/net/index.js @@ -30,12 +30,12 @@ const stat = require('./net-stat'); const onInterfaceAdded = new EventController(); const onInterfaceRemoved = new EventController(); -const interfaceAdd = (intf) => { +function interfaceAdd(intf) { assert(intf instanceof Interface); interfaces.add(intf); onInterfaceAdded.dispatch(intf); return intf; -}; +} // Add loopback interface interfaces.add(loopback); diff --git a/js/core/net/interface.js b/js/core/net/interface.js index 138faa245..c143ae60c 100644 --- a/js/core/net/interface.js +++ b/js/core/net/interface.js @@ -43,7 +43,9 @@ class Interface { } setNetworkEnabled(value) { assert(typeutils.isBoolean(value)); - if (this.isNetworkEnabled === value) return; + if (this.isNetworkEnabled === value) { + return; + } this.isNetworkEnabled = value; if (value) { @@ -77,10 +79,12 @@ class Interface { const nextOffset = this.bufferDataOffset + ethernet.headerLength; switch (etherType) { - case 0x0800: return ip4.receive(this, u8, nextOffset); - case 0x0806: return this.arp ? this.arp.receive(u8, nextOffset) : void 0; - // case 0x8100: // 802.1Q - // case 0x86dd: // ipv6 + case 0x0800: + return ip4.receive(this, u8, nextOffset); + case 0x0806: + return this.arp ? this.arp.receive(u8, nextOffset) : void 0; + // case 0x8100: // 802.1Q + // case 0x86dd: // ipv6 default: break; } @@ -89,7 +93,9 @@ class Interface { } sendRaw(u8) { ++stat.transmitCount; - if (this.ontransmit) this.ontransmit(u8, null); + if (this.ontransmit) { + this.ontransmit(u8, null); + } } sendIP4(viaIP, u8headers, u8data) { ++stat.transmitCount; diff --git a/js/core/net/interfaces.js b/js/core/net/interfaces.js index bb63ce58d..7b31ad15c 100644 --- a/js/core/net/interfaces.js +++ b/js/core/net/interfaces.js @@ -21,7 +21,9 @@ exports.count = () => intfs.length; exports.getByName = (intfName) => { for (const intf of intfs) { - if (intfName === intf.name) return intf; + if (intfName === intf.name) { + return intf; + } } return null; diff --git a/js/core/net/ip4-address.js b/js/core/net/ip4-address.js index a698aacb0..0e0a5d0c0 100644 --- a/js/core/net/ip4-address.js +++ b/js/core/net/ip4-address.js @@ -29,48 +29,51 @@ class IP4Address { } equals(that) { return this.a === that.a && this.b === that.b && - this.c === that.c && this.d === that.d; + this.c === that.c && this.d === that.d; } and(that) { return new IP4Address(this.a & that.a, this.b & that.b, - this.c & that.c, this.d & that.d); + this.c & that.c, this.d & that.d); } hash() { return (this.a | (this.b << 8) | (this.c << 16) | (this.d << 24)) >>> 0; } isBroadcast() { return this.a === 255 && this.b === 255 && - this.c === 255 && this.d === 255; + this.c === 255 && this.d === 255; } isAny() { return this.a === 0 && this.b === 0 && - this.c === 0 && this.d === 0; + this.c === 0 && this.d === 0; } static parse(str) { - if (str instanceof IP4Address) return str; - if (typeof str !== 'string') return null; + if (str instanceof IP4Address) { + return str; + } + if (typeof str !== 'string') { + return null; + } const p = str.trim().split('.'); - if (p.length !== 4) return null; + if (p.length !== 4) { + return null; + } const a = new Array(4); for (let i = 0; i < 4; ++i) { const v = p[i] | 0; - if (v !== +p[i] || v < 0 || v > 255) return null; + if (v !== +p[i] || v < 0 || v > 255) { + return null; + } a[i] = v; } return new IP4Address(a[0], a[1], a[2], a[3]); } - static get ANY() { - return new IP4Address(0, 0, 0, 0); - } - static get BROADCAST() { - return new IP4Address(255, 255, 255, 255); - } - static get LOOPBACK() { - return new IP4Address(127, 0, 0, 1); - } } +IP4Address.ANY = new IP4Address(0, 0, 0, 0); +IP4Address.BROADCAST = new IP4Address(255, 255, 255, 255); +IP4Address.LOOPBACK = new IP4Address(127, 0, 0, 1); + module.exports = IP4Address; diff --git a/js/core/net/ip4-fragments.js b/js/core/net/ip4-fragments.js index b82929ed8..992c90580 100644 --- a/js/core/net/ip4-fragments.js +++ b/js/core/net/ip4-fragments.js @@ -20,8 +20,13 @@ const { timeNow } = require('../../utils'); const FRAGMENT_QUEUE_MAX_AGE_MS = 30000; const FRAGMENT_QUEUE_MAX_COUNT = 100; -const fragmentHash = (srcIP, destIP, protocolId, packetId) => `${srcIP.toInteger()}-${destIP.toInteger()}-${(packetId + (protocolId << 16))}`; -const dropFragmentQueue = (intf, hash) => intf.fragments.delete(hash); +function fragmentHash(srcIP, destIP, protocolId, packetId) { + return `${srcIP.toInteger()}-${destIP.toInteger()}-${(packetId + (protocolId << 16))}`; +} + +function dropFragmentQueue(intf, hash) { + return intf.fragments.delete(hash); +} exports.addFragment = (intf, u8, headerOffset, fragmentOffset, isMoreFragments) => { const headerLength = ip4header.getHeaderLength(u8, headerOffset); @@ -36,7 +41,9 @@ exports.addFragment = (intf, u8, headerOffset, fragmentOffset, isMoreFragments) let firstFragment = false; let fragmentQueue = intf.fragments.get(hash); if (!fragmentQueue) { - if (intf.fragments.size >= FRAGMENT_QUEUE_MAX_COUNT) return; // too many fragment queues + if (intf.fragments.size >= FRAGMENT_QUEUE_MAX_COUNT) { + return; + } // too many fragment queues firstFragment = true; fragmentQueue = { @@ -48,17 +55,23 @@ exports.addFragment = (intf, u8, headerOffset, fragmentOffset, isMoreFragments) } const fragmentLength = u8.length - nextOffset; - if (fragmentLength <= 0) return; + if (fragmentLength <= 0) { + return; + } const fragmentEnd = fragmentOffset + fragmentLength; - if (fragmentEnd > 0xffff) return; + if (fragmentEnd > 0xffff) { + return; + } // Locate non overlapping portion of new fragment let newOffset = fragmentOffset; let newEnd = fragmentEnd; let newNextOffset = nextOffset; for (const fragment of fragmentQueue.fragments) { - if (!fragment) continue; + if (!fragment) { + continue; + } const fragBegin = fragment[0]; const fragEnd = fragBegin + fragment[1]; @@ -68,7 +81,9 @@ exports.addFragment = (intf, u8, headerOffset, fragmentOffset, isMoreFragments) // New fragment is fully contained within another fragment, // just ignore it - if (overlapOffset && overlapEnd) return; + if (overlapOffset && overlapEnd) { + return; + } // First fragment byte is somewhere withing existing fragment if (overlapOffset && newOffset < fragEnd) { @@ -77,7 +92,9 @@ exports.addFragment = (intf, u8, headerOffset, fragmentOffset, isMoreFragments) } // Last fragment byte is somewhere withing existing fragment - if (overlapEnd && newEnd > fragBegin) newEnd = fragBegin; + if (overlapEnd && newEnd > fragBegin) { + newEnd = fragBegin; + } } // Remove old fragments fully contained within the new one @@ -86,7 +103,9 @@ exports.addFragment = (intf, u8, headerOffset, fragmentOffset, isMoreFragments) let removedIndex = -1; for (let i = 0, l = fragmentQueue.fragments.length; i < l; ++i) { const fragment = fragmentQueue.fragments[i]; - if (!fragment) continue; + if (!fragment) { + continue; + } const fragBegin = fragment[0]; const fragEnd = fragBegin + fragment[1]; @@ -115,16 +134,22 @@ exports.addFragment = (intf, u8, headerOffset, fragmentOffset, isMoreFragments) // Last fragment? if (!isMoreFragments) { // Another last fragment? - if (fragmentQueue.totalLength > fragmentEnd) return; // Wrong len + if (fragmentQueue.totalLength > fragmentEnd) { + return; + } // Wrong len fragmentQueue.totalLength = fragmentEnd; } - if (firstFragment) intf.fragments.set(hash, fragmentQueue); + if (firstFragment) { + intf.fragments.set(hash, fragmentQueue); + } if (fragmentQueue.totalLength === fragmentQueue.receivedLength) { const u8asm = new Uint8Array(fragmentQueue.totalLength); for (const fragment of fragmentQueue.fragments) { - if (!fragment) continue; + if (!fragment) { + continue; + } const itemOffset = fragment[0]; const itemLength = fragment[1]; @@ -150,6 +175,8 @@ exports.tick = (intf) => { for (const pair of intf.fragments) { const hash = pair[0]; const fragmentQueue = pair[1]; - if (fragmentQueue.createdAt + FRAGMENT_QUEUE_MAX_AGE_MS <= time) dropFragmentQueue(intf, hash); + if (fragmentQueue.createdAt + FRAGMENT_QUEUE_MAX_AGE_MS <= time) { + dropFragmentQueue(intf, hash); + } } }; diff --git a/js/core/net/ip4.js b/js/core/net/ip4.js index 2fa60f670..6f9e1502e 100644 --- a/js/core/net/ip4.js +++ b/js/core/net/ip4.js @@ -22,14 +22,14 @@ const interfaces = require('./interfaces'); timers.scheduleTask5s(() => interfaces.forEach(ip4fragments.tick)); -const handleReceive = (intf, u8, headerOffset) => { +function handleReceive(intf, u8, headerOffset) { const headerLength = ip4header.getHeaderLength(u8, headerOffset); const protocolId = ip4header.getProtocolId(u8, headerOffset); const srcIP = ip4header.getSrcIP(u8, headerOffset); const destIP = ip4header.getDestIP(u8, headerOffset); const nextOffset = headerOffset + headerLength; ip4receive(intf, srcIP, destIP, protocolId, u8, nextOffset); -}; +} exports.receive = (intf, u8, headerOffset) => { const fragmentData = ip4header.getFragmentationData(u8, headerOffset); diff --git a/js/core/net/mac-address.js b/js/core/net/mac-address.js index 632bed583..2817d878b 100644 --- a/js/core/net/mac-address.js +++ b/js/core/net/mac-address.js @@ -14,7 +14,9 @@ 'use strict'; -const valueString = (x) => ((x < 0x10) ? `0${x.toString(16)}` : x.toString(16)); +function valueString(x) { + return ((x < 0x10) ? `0${x.toString(16)}` : x.toString(16)); +} class MACAddress { constructor(a, b, c, d, e, f) { @@ -30,26 +32,28 @@ class MACAddress { } equals(that) { return this.a === that.a && this.b === that.b && - this.c === that.c && this.d === that.d && - this.e === that.e && this.f === that.f; - } - static get BROADCAST() { - return new MACAddress(0xff, 0xff, 0xff, 0xff, 0xff, 0xff); - } - static get ZERO() { - return new MACAddress(0, 0, 0, 0, 0, 0); + this.c === that.c && this.d === that.d && + this.e === that.e && this.f === that.f; } static parse(str) { - if (str instanceof MACAddress) return str; - if (typeof str !== 'string') return null; + if (str instanceof MACAddress) { + return str; + } + if (typeof str !== 'string') { + return null; + } const p = str.trim().split(':'); - if (p.length !== 6) return null; + if (p.length !== 6) { + return null; + } const a = new Array(6); for (let i = 0; i < 6; ++i) { const v = parseInt(p[i], 16) | 0; - if (v !== parseInt(p[i], 16) || v < 0 || v > 255) return null; + if (v !== parseInt(p[i], 16) || v < 0 || v > 255) { + return null; + } a[i] = v; } @@ -57,4 +61,7 @@ class MACAddress { } } +MACAddress.BROADCAST = new MACAddress(0xff, 0xff, 0xff, 0xff, 0xff, 0xff); +MACAddress.ZERO = new MACAddress(0, 0, 0, 0, 0, 0); + module.exports = MACAddress; diff --git a/js/core/net/net-error.js b/js/core/net/net-error.js index bf205a2c9..1cbe14c2e 100644 --- a/js/core/net/net-error.js +++ b/js/core/net/net-error.js @@ -26,4 +26,6 @@ const errs = [ 'E_CANNOT_CLOSE', ]; -for (const err of errs) exports[err] = new Error(err); +for (const err of errs) { + exports[err] = new Error(err); +} diff --git a/js/core/net/ping.js b/js/core/net/ping.js index 1f0b83503..1cbdb667d 100644 --- a/js/core/net/ping.js +++ b/js/core/net/ping.js @@ -22,11 +22,13 @@ const route = require('./route'); const netError = require('./net-error'); const pingListeners = new Map(); -const createPingBuffer = (size) => { +function createPingBuffer(size) { const u8 = new Uint8Array(size); - for (let i = 0; i < size; ++i) u8[i] = 0x61 + (i % 26); // ASCII a-z + for (let i = 0; i < size; ++i) { + u8[i] = 0x61 + (i % 26); + } // ASCII a-z return u8; -}; +} let nextPingId = 1; const defaultPingData = createPingBuffer(56); @@ -48,7 +50,9 @@ class Ping { assertError(destIP instanceof IP4Address, netError.E_IPADDRESS_EXPECTED); const seq = this._nextSeq++; - if (this._nextSeq > 0xffff) this._nextSeq = 0; + if (this._nextSeq > 0xffff) { + this._nextSeq = 0; + } const routingEntry = route.lookup(destIP); if (!routingEntry) { @@ -56,7 +60,9 @@ class Ping { return seq; } - if (!pingListeners.has(this._pingId)) pingListeners.set(this._pingId, this); + if (!pingListeners.has(this._pingId)) { + pingListeners.set(this._pingId, this); + } const intf = routingEntry.intf; const viaIP = routingEntry.gateway; @@ -68,20 +74,28 @@ class Ping { _receive(srcIP, seq, u8, dataOffset) { const dataLength = u8.length - dataOffset; - if (dataLength !== this._data.length) return; + if (dataLength !== this._data.length) { + return; + } for (let i = 0, l = dataLength; i < l; ++i) { - if (u8[dataOffset + i] !== this._data[i]) return; + if (u8[dataOffset + i] !== this._data[i]) { + return; + } } - if (this.onreply) this.onreply(srcIP, seq); + if (this.onreply) { + this.onreply(srcIP, seq); + } } /** * Stop listening to echo replies. */ close() { - if (pingListeners.has(this._pingId)) pingListeners.delete(this._pingId); + if (pingListeners.has(this._pingId)) { + pingListeners.delete(this._pingId); + } } static _receiveLookup(pingId) { diff --git a/js/core/net/port-allocator.js b/js/core/net/port-allocator.js index e162fa58e..15b2c9884 100644 --- a/js/core/net/port-allocator.js +++ b/js/core/net/port-allocator.js @@ -67,8 +67,12 @@ class PortAllocator { allocPort(port, socket) { assert(portUtils.isPort(port)); - if (this.lookup(port)) return false; - if (this._map === null) this._map = new Map(); + if (this.lookup(port)) { + return false; + } + if (this._map === null) { + this._map = new Map(); + } this._map.set(port, socket); ++this._allocated; @@ -91,12 +95,18 @@ class PortAllocator { if (this.isEphemeralRange(port)) { const index = port - EPHEMERAL_PORT_FIRST; - if (index >= this._sockets.length) return; + if (index >= this._sockets.length) { + return; + } - if (this._sockets[index] === null) return; + if (this._sockets[index] === null) { + return; + } this._sockets[index] = null; - if (index < this._searchStart) this._searchStart = index; + if (index < this._searchStart) { + this._searchStart = index; + } --this._allocated; if (this._allocated === 0) { this._sockets = []; @@ -106,11 +116,15 @@ class PortAllocator { } lookup(port) { - if ((this._map !== null) && this._map.has(port)) return this._map.get(port); + if ((this._map !== null) && this._map.has(port)) { + return this._map.get(port); + } if (this.isEphemeralRange(port)) { const index = port - EPHEMERAL_PORT_FIRST; - if (index >= this._sockets.length) return null; + if (index >= this._sockets.length) { + return null; + } return this._sockets[index]; } diff --git a/js/core/net/route.js b/js/core/net/route.js index 56fd05c08..5fbe7f86f 100644 --- a/js/core/net/route.js +++ b/js/core/net/route.js @@ -43,7 +43,9 @@ exports.lookup = (destIP, intf) => { let result = null; let maxMaskBits = 0; for (const entry of table) { - if (intf && entry.intf !== intf) continue; + if (intf && entry.intf !== intf) { + continue; + } if (destIP.and(entry.mask).equals(entry.ip) && entry.maskBits >= maxMaskBits) { result = entry; diff --git a/js/core/net/tcp-server-socket.js b/js/core/net/tcp-server-socket.js index e085668dd..939f3d55d 100644 --- a/js/core/net/tcp-server-socket.js +++ b/js/core/net/tcp-server-socket.js @@ -35,7 +35,9 @@ class TCPServerSocket { listen(port) { this.listeningSocket._listen(port); this._port = this.listeningSocket._port; - if (this.onlisten) this.onlisten(this._port); + if (this.onlisten) { + this.onlisten(this._port); + } } close() { this.listeningSocket.close(); diff --git a/js/core/net/tcp-socket-state.js b/js/core/net/tcp-socket-state.js index bf0f2c7dd..9fbcb3494 100644 --- a/js/core/net/tcp-socket-state.js +++ b/js/core/net/tcp-socket-state.js @@ -14,18 +14,14 @@ 'use strict'; -const states = [ - 'STATE_CLOSED', - 'STATE_LISTEN', - 'STATE_SYN_SENT', - 'STATE_SYN_RECEIVED', - 'STATE_ESTABLISHED', - 'STATE_FIN_WAIT_1', - 'STATE_FIN_WAIT_2', - 'STATE_CLOSE_WAIT', - 'STATE_CLOSING', - 'STATE_LAST_ACK', - 'STATE_TIME_WAIT', -]; - -for (const num of Object.keys(states)) exports[states[num]] = num; +exports.STATE_CLOSED = 0; +exports.STATE_LISTEN = 1; +exports.STATE_SYN_SENT = 2; +exports.STATE_SYN_RECEIVED = 3; +exports.STATE_ESTABLISHED = 4; +exports.STATE_FIN_WAIT_1 = 5; +exports.STATE_FIN_WAIT_2 = 6; +exports.STATE_CLOSE_WAIT = 7; +exports.STATE_CLOSING = 8; +exports.STATE_LAST_ACK = 9; +exports.STATE_TIME_WAIT = 10; diff --git a/js/core/net/tcp-socket.js b/js/core/net/tcp-socket.js index 6d5642dca..901dbde20 100644 --- a/js/core/net/tcp-socket.js +++ b/js/core/net/tcp-socket.js @@ -44,8 +44,13 @@ const { timeNow } = require('../../utils'); const ports = new PortAllocator(); -const SEQ_INC = (seq, value) => (seq + (value >>> 0)) >>> 0; -const SEQ_OFFSET = (a, b) => (a - b) | 0; +function SEQ_INC(seq, value) { + return (seq + (value >>> 0)) >>> 0; +} + +function SEQ_OFFSET(a, b) { + return (a - b) | 0; +} const MSL_TIME = 15000; const bufferedLimitHint = 64 * 1024; /* 64 KiB */ @@ -94,11 +99,21 @@ class TCPSocket { ++tcpStat.socketsCreated; } - get bufferedAmount() { return this._bufferedAmount; } - get remoteAddress() { return this._destIP ? this._destIP.toString() : '0.0.0.0'; } - get remotePort() { return this._destPort; } - get localAddress() { return '0.0.0.0'; } - get localPort() { return this._port; } + get bufferedAmount() { + return this._bufferedAmount; + } + get remoteAddress() { + return this._destIP ? this._destIP.toString() : '0.0.0.0'; + } + get remotePort() { + return this._destPort; + } + get localAddress() { + return '0.0.0.0'; + } + get localPort() { + return this._port; + } get readyState() { switch (this._state) { @@ -124,7 +139,9 @@ class TCPSocket { open(ipOpt, port) { let ip = ipOpt; - if (typeutils.isString(ip)) ip = IP4Address.parse(ip); + if (typeutils.isString(ip)) { + ip = IP4Address.parse(ip); + } assertError(ip instanceof IP4Address, netError.E_IPADDRESS_EXPECTED); assertError(portUtils.isPort(port), netError.E_INVALID_PORT); @@ -145,7 +162,9 @@ class TCPSocket { port = ports.allocEphemeral(this); } else { assertError(portUtils.isPort(port), netError.E_INVALID_PORT); - if (!ports.allocPort(port, this)) throw netError.E_ADDRESS_IN_USE; + if (!ports.allocPort(port, this)) { + throw netError.E_ADDRESS_IN_USE; + } } this._port = port; @@ -166,24 +185,32 @@ class TCPSocket { _transmit(seq, ack, flags, window, u8) { tcpTransmit(this._intf, this._destIP, this._viaIP, - this._port, this._destPort, - seq, ack, flags, window, u8); + this._port, this._destPort, + seq, ack, flags, window, u8); } _configure() { let intf = this._intf || null; - if (this._destIP.isBroadcast()) return false; + if (this._destIP.isBroadcast()) { + return false; + } const routingEntry = route.lookup(this._destIP, intf); - if (!routingEntry) return false; + if (!routingEntry) { + return false; + } const viaIP = routingEntry.gateway; - if (!intf) intf = routingEntry.intf; + if (!intf) { + intf = routingEntry.intf; + } if (!this._port) { this._port = ports.allocEphemeral(this); - if (!this._port) return false; + if (!this._port) { + return false; + } } this._intf = intf; @@ -209,12 +236,16 @@ class TCPSocket { _sendSYN(isAck) { let flags = tcpHeader.FLAG_SYN; - if (isAck) flags |= tcpHeader.FLAG_ACK; + if (isAck) { + flags |= tcpHeader.FLAG_ACK; + } this._transmitQueue.push([0, timeNow(), this._getTransmitPosition(), 1, null, flags]); this._incTransmitPosition(); - if (!this._configure()) return; + if (!this._configure()) { + return; + } this._sendTransmitQueue(); } @@ -244,11 +275,15 @@ class TCPSocket { } _receiveWindowIsWithin(seq, edge) { - if (this._receiveWindowSize === 0) return false; + if (this._receiveWindowSize === 0) { + return false; + } const leftEdge = edge; const rightEdge = SEQ_INC(edge, this._receiveWindowSize); - if (leftEdge < rightEdge) return seq >= leftEdge && seq < rightEdge; + if (leftEdge < rightEdge) { + return seq >= leftEdge && seq < rightEdge; + } return seq >= leftEdge || seq < rightEdge; } @@ -263,7 +298,9 @@ class TCPSocket { const length = buf.length; const reserved = this._allocTransmitPosition(length); debug('send at ', position, 'len', reserved); - if (reserved === 0) break; + if (reserved === 0) { + break; + } if (length === reserved) { this._transmitQueue.push([0, timeNow(), position, reserved, buf, tcpHeader.FLAG_ACK | tcpHeader.FLAG_PSH]); @@ -276,7 +313,9 @@ class TCPSocket { break; } - if (this._bufferedAmount === 0 && this.ondrain) this.ondrain(); + if (this._bufferedAmount === 0 && this.ondrain) { + this.ondrain(); + } } else { debug('fill pos', position, 'fin'); this._incTransmitPosition(); @@ -285,7 +324,9 @@ class TCPSocket { } } - while (remove-- > 0) this._queueTx.shift(); + while (remove-- > 0) { + this._queueTx.shift(); + } this._sendTransmitQueue(); } @@ -300,8 +341,10 @@ class TCPSocket { break; case STATE_SYN_SENT: case STATE_SYN_RECEIVED: - if (!this._configure()) return; - /* fall through */ + if (!this._configure()) { + return; + } + /* fall through */ case STATE_ESTABLISHED: case STATE_FIN_WAIT_1: this._sendTransmitQueue(); @@ -339,14 +382,16 @@ class TCPSocket { if (this._ackRequired) { this._ackRequired = false; this._transmit(this._getTransmitPosition(), this._receiveWindowEdge, - tcpHeader.FLAG_ACK, this._receiveWindowSize, null); + tcpHeader.FLAG_ACK, this._receiveWindowSize, null); } } _cleanupTransmitQueue() { let deleteCount = 0; - if (this._transmitQueue.length === 0) return; + if (this._transmitQueue.length === 0) { + return; + } for (const item of this._transmitQueue) { const seq = item[2]; @@ -360,7 +405,9 @@ class TCPSocket { } } - while (deleteCount-- > 0) this._transmitQueue.shift(); + while (deleteCount-- > 0) { + this._transmitQueue.shift(); + } } _resetConnection() { @@ -369,8 +416,12 @@ class TCPSocket { } send(u8) { - if (!(u8 instanceof Uint8Array)) throw new Error('argument 0 is not a Uint8Array'); - if (this._state !== STATE_ESTABLISHED && this._state !== STATE_CLOSE_WAIT) throw new Error('socket is not connected'); + if (!(u8 instanceof Uint8Array)) { + throw new Error('argument 0 is not a Uint8Array'); + } + if (this._state !== STATE_ESTABLISHED && this._state !== STATE_CLOSE_WAIT) { + throw new Error('socket is not connected'); + } this._bufferedAmount += u8.length; this._queueTx.push(u8); this._fillTransmitQueue(); @@ -406,7 +457,9 @@ class TCPSocket { ports.free(this._port); this._destroy(); // TODO: close all connections - if (this.onclose) this._emitClose(); + if (this.onclose) { + this._emitClose(); + } return; } @@ -428,13 +481,17 @@ class TCPSocket { _insertReceiveQueue(seq, len, u8) { // Fast path for ordered data if (seq === this._receiveWindowEdge) { - if (u8 && this.ondata) this._emitData(u8); + if (u8 && this.ondata) { + this._emitData(u8); + } this._receiveWindowSlideTo(SEQ_INC(seq, len)); this._ackRequired = true; this._sendTransmitQueue(); - if (this._receiveQueue.length === 0) return; + if (this._receiveQueue.length === 0) { + return; + } } else { this._receiveQueue.push([seq, len, u8]); } @@ -454,7 +511,9 @@ class TCPSocket { const seqNumber = item[0]; const length = item[1]; let removeItem = false; - if (length === 0) continue; + if (length === 0) { + continue; + } if (lastAck === seqNumber) { lastAck = SEQ_INC(lastAck, length); @@ -487,13 +546,17 @@ class TCPSocket { } } - if (!iterRemoved) break; + if (!iterRemoved) { + break; + } } if (removed > 0) { while (removed-- > 0) { const removedItem = this._receiveQueue.pop(); - if (removedItem[2] && this.ondata) this._emitData(removedItem[2]); + if (removedItem[2] && this.ondata) { + this._emitData(removedItem[2]); + } } this._receiveWindowSlideTo(lastAck); @@ -506,9 +569,13 @@ class TCPSocket { const leftEdge = this._transmitWindowEdge; const rightEdge = this._transmitPosition; - if (leftEdge === rightEdge) return false; + if (leftEdge === rightEdge) { + return false; + } - if (leftEdge < rightEdge) return seq > leftEdge && seq <= rightEdge; + if (leftEdge < rightEdge) { + return seq > leftEdge && seq <= rightEdge; + } return seq > leftEdge || seq <= rightEdge; } @@ -530,31 +597,32 @@ class TCPSocket { const dataLength = u8.length - dataOffset; switch (this._state) { - case STATE_LISTEN: { - const hash = connHash(srcIP, srcPort); - let socket = this._connections.get(hash); - if (socket) { - socket._receive(u8, srcIP, srcPort, headerOffset); + case STATE_LISTEN: + { + const hash = connHash(srcIP, srcPort); + let socket = this._connections.get(hash); + if (socket) { + socket._receive(u8, srcIP, srcPort, headerOffset); + return; + } + if (flags & tcpHeader.FLAG_SYN) { + socket = new TCPSocket(); + socket._serverSocket = this; + socket._intf = this._intf; + socket._viaIP = this._viaIP; + socket._receiveWindowSlideTo(seqNumber); + socket._receiveWindowSlideInc(); // SYN counts as 1 byte + socket._state = STATE_SYN_RECEIVED; + socket._destIP = srcIP; + socket._destPort = srcPort; + socket._port = this._port; + socket._sendSYN(true); + tcpTimer.addConnectionSocket(socket); + this._connections.set(hash, socket); + this._onconnect(socket); + } return; } - if (flags & tcpHeader.FLAG_SYN) { - socket = new TCPSocket(); - socket._serverSocket = this; - socket._intf = this._intf; - socket._viaIP = this._viaIP; - socket._receiveWindowSlideTo(seqNumber); - socket._receiveWindowSlideInc(); // SYN counts as 1 byte - socket._state = STATE_SYN_RECEIVED; - socket._destIP = srcIP; - socket._destPort = srcPort; - socket._port = this._port; - socket._sendSYN(true); - tcpTimer.addConnectionSocket(socket); - this._connections.set(hash, socket); - this._onconnect(socket); - } - return; - } case STATE_SYN_SENT: this._acceptACK(ackNumber, windowSize); if (flags & (tcpHeader.FLAG_SYN | tcpHeader.FLAG_ACK)) { @@ -563,27 +631,35 @@ class TCPSocket { this._ackRequired = true; this._sendTransmitQueue(); this._state = STATE_ESTABLISHED; - if (this.onopen) this._emitOpen(); + if (this.onopen) { + this._emitOpen(); + } } break; case STATE_SYN_RECEIVED: this._acceptACK(ackNumber, windowSize); if (flags & tcpHeader.FLAG_ACK) { this._state = STATE_ESTABLISHED; - if (this.onopen) this._emitOpen(); + if (this.onopen) { + this._emitOpen(); + } } break; case STATE_LAST_ACK: this._acceptACK(ackNumber, windowSize); if (this._getTransmitPosition() === ackNumber) { this._state = STATE_CLOSED; - if (this.onclose) this._emitClose(); + if (this.onclose) { + this._emitClose(); + } this._destroy(); } break; case STATE_FIN_WAIT_1: this._acceptACK(ackNumber, windowSize); - if (this._getTransmitPosition() === ackNumber) this._state = STATE_FIN_WAIT_2; + if (this._getTransmitPosition() === ackNumber) { + this._state = STATE_FIN_WAIT_2; + } /* fall through */ case STATE_FIN_WAIT_2: case STATE_ESTABLISHED: @@ -602,13 +678,19 @@ class TCPSocket { if (this._state === STATE_FIN_WAIT_2) { this._state = STATE_TIME_WAIT; this._timeWaitTime = timeNow(); - if (this.onend) this._emitEnd(); - if (this.onclose) this._emitClose(); + if (this.onend) { + this._emitEnd(); + } + if (this.onclose) { + this._emitClose(); + } } if (this._state === STATE_ESTABLISHED) { this._state = STATE_CLOSE_WAIT; - if (this.onend) this._emitEnd(); + if (this.onend) { + this._emitEnd(); + } } } } diff --git a/js/core/net/tcp-timer.js b/js/core/net/tcp-timer.js index d89d87ee8..df8537ae8 100644 --- a/js/core/net/tcp-timer.js +++ b/js/core/net/tcp-timer.js @@ -16,14 +16,16 @@ // const tcpSocketState = require('./tcp-socket-state'); const connections = new Set(); -let initTimeout; - -const timeoutHandler = () => { - for (const connSocket of connections) connSocket._timerTick(); +function timeoutHandler() { + for (const connSocket of connections) { + connSocket._timerTick(); + } initTimeout(); -}; +} -initTimeout = () => setTimeout(timeoutHandler, 500); +function initTimeout() { + setTimeout(timeoutHandler, 500); +} initTimeout(); diff --git a/js/core/net/tcp.js b/js/core/net/tcp.js index cc1127fb1..866f6e680 100644 --- a/js/core/net/tcp.js +++ b/js/core/net/tcp.js @@ -19,7 +19,9 @@ const tcpSocketState = require('./tcp-socket-state'); const connHash = require('./tcp-hash'); const STATE_LISTEN = tcpSocketState.STATE_LISTEN; -const connectionSocket = (socket, srcIP, srcPort) => socket._connections.get(connHash(srcIP, srcPort)) || socket; +function connectionSocket(socket, srcIP, srcPort) { + return socket._connections.get(connHash(srcIP, srcPort)) || socket; +} exports.receive = (intf, srcIP, destIP, u8, headerOffset) => { const srcPort = tcpHeader.getSrcPort(u8, headerOffset); @@ -28,9 +30,15 @@ exports.receive = (intf, srcIP, destIP, u8, headerOffset) => { let socket = TCPSocket.lookupReceive(destPort); - if (!socket) return; - if (socket._state === STATE_LISTEN) socket = connectionSocket(socket, srcIP, srcPort); - if (!socket._intf) socket._intf = intf; + if (!socket) { + return; + } + if (socket._state === STATE_LISTEN) { + socket = connectionSocket(socket, srcIP, srcPort); + } + if (!socket._intf) { + socket._intf = intf; + } socket._receive(u8, srcIP, srcPort, headerOffset); }; diff --git a/js/core/net/udp-socket.js b/js/core/net/udp-socket.js index 32e182469..a0fe21c68 100644 --- a/js/core/net/udp-socket.js +++ b/js/core/net/udp-socket.js @@ -34,7 +34,9 @@ class UDPSocket { send(ipOpt, port, u8) { let ip = ipOpt; - if (typeutils.isString(ip)) ip = IP4Address.parse(ip); + if (typeutils.isString(ip)) { + ip = IP4Address.parse(ip); + } assertError(ip instanceof IP4Address, netError.E_IPADDRESS_EXPECTED); assertError(portUtils.isPort(port), netError.E_INVALID_PORT); @@ -50,12 +52,16 @@ class UDPSocket { if (!routingEntry) return console.log(`[UDP] no route to ${ip}`); viaIP = routingEntry.gateway; - if (!intf) intf = routingEntry.intf; + if (!intf) { + intf = routingEntry.intf; + } } if (!this._port) { this._port = ports.allocEphemeral(this); - if (!this._port) throw netError.E_NO_FREE_PORT; + if (!this._port) { + throw netError.E_NO_FREE_PORT; + } } udpTransmit(intf, ip, viaIP, this._port, port, u8); @@ -64,7 +70,9 @@ class UDPSocket { bind(port) { assertError(portUtils.isPort(port), netError.E_INVALID_PORT); - if (!ports.allocPort(port, this)) throw netError.E_ADDRESS_IN_USE; + if (!ports.allocPort(port, this)) { + throw netError.E_ADDRESS_IN_USE; + } this._port = port; } @@ -75,11 +83,15 @@ class UDPSocket { } this._intf = intf; - if (port) this.bind(port); + if (port) { + this.bind(port); + } } close() { - if (this._port) ports.free(this._port); + if (this._port) { + ports.free(this._port); + } } static lookupReceive(destPort) { diff --git a/js/core/net/udp.js b/js/core/net/udp.js index 08c88c93d..3f8dafb9d 100644 --- a/js/core/net/udp.js +++ b/js/core/net/udp.js @@ -20,7 +20,7 @@ const UDPSocket = require('./udp-socket'); // const interfaces = require('./interfaces'); // const netError = require('./net-error'); -const receive = (intf, srcIP, destIP, u8, headerOffset) => { +function receive(intf, srcIP, destIP, u8, headerOffset) { const srcPort = udpHeader.getSrcPort(u8, headerOffset); const destPort = udpHeader.getDestPort(u8, headerOffset); const dataLength = udpHeader.getDataLength(u8, headerOffset) - udpHeader.headerLength; @@ -28,10 +28,12 @@ const receive = (intf, srcIP, destIP, u8, headerOffset) => { debug('recv UDP over IP4', srcPort, destPort, dataLength); const socket = UDPSocket.lookupReceive(destPort); - if (!socket) return; + if (!socket) { + return; + } const u8data = u8.subarray(dataOffset); if (socket.onmessage) setImmediate(() => socket.onmessage(srcIP, srcPort, u8data)); -}; +} exports.receive = receive; diff --git a/js/core/pci/index.js b/js/core/pci/index.js index 874b6ea2c..254c14bd0 100644 --- a/js/core/pci/index.js +++ b/js/core/pci/index.js @@ -21,26 +21,36 @@ const isint = require('isint'); const deviceList = []; -const init = () => { - for (const pciData of scan()) deviceList.push(new PciDevice(pciData)); -}; +function init() { + for (const pciData of scan()) { + deviceList.push(new PciDevice(pciData)); + } +} -const setupDeviceDriver = (vendorId, deviceId, driver) => { +function setupDeviceDriver(vendorId, deviceId, driver) { assert(isint.uint16(vendorId)); assert(isint.uint16(deviceId) || typeutils.isFunction(deviceId)); for (const device of deviceList) { - if (device.hasDriver()) continue; - if (device.vendorId !== vendorId) continue; + if (device.hasDriver()) { + continue; + } + if (device.vendorId !== vendorId) { + continue; + } if (typeutils.isFunction(deviceId)) { - if (!deviceId(device.deviceId)) continue; + if (!deviceId(device.deviceId)) { + continue; + } } else { - if (device.deviceId !== deviceId) continue; + if (device.deviceId !== deviceId) { + continue; + } } device.setDriver(driver); } -}; +} init(); diff --git a/js/core/pci/scan.js b/js/core/pci/scan.js index dfcc8331f..6d8031229 100644 --- a/js/core/pci/scan.js +++ b/js/core/pci/scan.js @@ -32,7 +32,7 @@ const sizeof = { UINT64: 8, }; -const pciAccessorFactory = ((addressPort, dataPort) => { +const pciAccessorFactory = (function (addressPort, dataPort) { const accessorCache = new Map(); /** @@ -40,21 +40,69 @@ const pciAccessorFactory = ((addressPort, dataPort) => { * of devices */ const fields = { - VENDOR_ID: { offset: 0x00, shift: 0, mask: 0xffff }, - DEVICE_ID: { offset: 0x00, shift: 2, mask: 0xffff }, + VENDOR_ID: { + offset: 0x00, + shift: 0, + mask: 0xffff, + }, + DEVICE_ID: { + offset: 0x00, + shift: 2, + mask: 0xffff, + }, - COMMAND: { offset: 0x04, shift: 0, mask: 0xffff }, - STATUS: { offset: 0x04, shift: 2, mask: 0xffff }, + COMMAND: { + offset: 0x04, + shift: 0, + mask: 0xffff, + }, + STATUS: { + offset: 0x04, + shift: 2, + mask: 0xffff, + }, - REVISION_ID: { offset: 0x08, shift: 0, mask: 0xff }, - PROG_IF: { offset: 0x08, shift: 1, mask: 0xff }, - SUBCLASS: { offset: 0x08, shift: 2, mask: 0xff }, - CLASS_CODE: { offset: 0x08, shift: 3, mask: 0xff }, + REVISION_ID: { + offset: 0x08, + shift: 0, + mask: 0xff, + }, + PROG_IF: { + offset: 0x08, + shift: 1, + mask: 0xff, + }, + SUBCLASS: { + offset: 0x08, + shift: 2, + mask: 0xff, + }, + CLASS_CODE: { + offset: 0x08, + shift: 3, + mask: 0xff, + }, - CACHE_LINESIZE: { offset: 0x0c, shift: 0, mask: 0xff }, - LATENCY_TIMER: { offset: 0x0c, shift: 1, mask: 0xff }, - HEADER_TYPE: { offset: 0x0c, shift: 2, mask: 0xff }, - BIST: { offset: 0x0c, shift: 3, mask: 0xff }, + CACHE_LINESIZE: { + offset: 0x0c, + shift: 0, + mask: 0xff, + }, + LATENCY_TIMER: { + offset: 0x0c, + shift: 1, + mask: 0xff, + }, + HEADER_TYPE: { + offset: 0x0c, + shift: 2, + mask: 0xff, + }, + BIST: { + offset: 0x0c, + shift: 3, + mask: 0xff, + }, }; /** @@ -62,18 +110,53 @@ const pciAccessorFactory = ((addressPort, dataPort) => { * (header type 0x00) */ const generalFields = { - BAR: [{ offset: 0x10, shift: 0, mask: 0xffffffff }, - { offset: 0x14, shift: 0, mask: 0xffffffff }, - { offset: 0x18, shift: 0, mask: 0xffffffff }, - { offset: 0x1c, shift: 0, mask: 0xffffffff }, - { offset: 0x20, shift: 0, mask: 0xffffffff }, - { offset: 0x24, shift: 0, mask: 0xffffffff }], - - SUBSYS_VENDOR: { offset: 0x2c, shift: 0, mask: 0xffff }, - SUBSYS_ID: { offset: 0x2c, shift: 2, mask: 0xffff }, - - INTERRUPT_LINE: { offset: 0x3c, shift: 0, mask: 0xff }, - INTERRUPT_PIN: { offset: 0x3c, shift: 1, mask: 0xff }, + BAR: [{ + offset: 0x10, + shift: 0, + mask: 0xffffffff, + }, { + offset: 0x14, + shift: 0, + mask: 0xffffffff, + }, { + offset: 0x18, + shift: 0, + mask: 0xffffffff, + }, { + offset: 0x1c, + shift: 0, + mask: 0xffffffff, + }, { + offset: 0x20, + shift: 0, + mask: 0xffffffff, + }, { + offset: 0x24, + shift: 0, + mask: 0xffffffff, + }], + + SUBSYS_VENDOR: { + offset: 0x2c, + shift: 0, + mask: 0xffff, + }, + SUBSYS_ID: { + offset: 0x2c, + shift: 2, + mask: 0xffff, + }, + + INTERRUPT_LINE: { + offset: 0x3c, + shift: 0, + mask: 0xff, + }, + INTERRUPT_PIN: { + offset: 0x3c, + shift: 1, + mask: 0xff, + }, }; /** @@ -81,25 +164,41 @@ const pciAccessorFactory = ((addressPort, dataPort) => { * (header type 0x01 or 0x02) */ const bridgeFields = { - PRIMARY_BUS: { offset: 0x18, shift: 0, mask: 0xff }, - SECONDARY_BUS: { offset: 0x18, shift: 1, mask: 0xff }, - SUBORDINATE: { offset: 0x18, shift: 2, mask: 0xff }, + PRIMARY_BUS: { + offset: 0x18, + shift: 0, + mask: 0xff, + }, + SECONDARY_BUS: { + offset: 0x18, + shift: 1, + mask: 0xff, + }, + SUBORDINATE: { + offset: 0x18, + shift: 2, + mask: 0xff, + }, }; - const setPort = (bus, slot, func, offset) => { + function setPort(bus, slot, func, offset) { const addr = ((bus << 16) | (slot << 11) | (func << 8) | (offset & 0xfc) | 0x80000000) >>> 0; addressPort.write32(addr); - }; + } - const readRaw32 = (bus, slot, func, offset) => { - if (offset % sizeof.UINT32 !== 0) throw new Error('unaligned pci space 32 bit read'); + function readRaw32(bus, slot, func, offset) { + if (offset % sizeof.UINT32 !== 0) { + throw new Error('unaligned pci space 32 bit read'); + } setPort(bus, slot, func, offset); return dataPort.read32(); - }; + } - const dwToFieldValue = (value, field) => ((value >>> (8 * sizeof.BYTE * field.shift)) & field.mask) >>> 0; // eslint-disable-line max-len + function dwToFieldValue(value, field) { + return ((value >>> (8 * sizeof.BYTE * field.shift)) & field.mask) >>> 0; + } // eslint-disable-line max-len /** * Provides a way to read and write PCI Configuration space registers. @@ -112,30 +211,40 @@ const pciAccessorFactory = ((addressPort, dataPort) => { const slot = address.slot >>> 0; const func = address.func >>> 0; - if (bus > 255) throw new Error('invalid bus value (expected 0-255)'); - if (slot > 31) throw new Error('invalid slot value (expected 0-31)'); - if (func > 7) throw new Error('invalid func value (expected 0-7)'); + if (bus > 255) { + throw new Error('invalid bus value (expected 0-255)'); + } + if (slot > 31) { + throw new Error('invalid slot value (expected 0-31)'); + } + if (func > 7) { + throw new Error('invalid func value (expected 0-7)'); + } const offsetCache = new Map(); - const writeRaw32 = (offset, value) => { - if (offset % sizeof.UINT32 !== 0) throw new Error('unaligned pci space 32-bit write'); + function writeRaw32(offset, value) { + if (offset % sizeof.UINT32 !== 0) { + throw new Error('unaligned pci space 32-bit write'); + } setPort(bus, slot, func, offset); return dataPort.write32(value >>> 0); - }; + } - const writeRaw16 = (offset, value) => { - if (offset % sizeof.UINT16 !== 0) throw new Error('unaligned pci space 16-bit write'); + function writeRaw16(offset, value) { + if (offset % sizeof.UINT16 !== 0) { + throw new Error('unaligned pci space 16-bit write'); + } setPort(bus, slot, func, offset); return dataPort.write16((value & 0xffff) >>> 0); - }; + } - const writeRaw8 = (offset, value) => { + function writeRaw8(offset, value) { setPort(bus, slot, func, offset); return dataPort.write8((value & 0xff) >>> 0); - }; + } /** * Read PCI configuration space field @@ -160,9 +269,15 @@ const pciAccessorFactory = ((addressPort, dataPort) => { offsetCache.delete(field.offset); switch (field.mask) { - case 0xffffffff: writeRaw32(field.offset, value); break; - case 0xffff: writeRaw16(field.offset + field.shift, value); break; - case 0xff: writeRaw8(field.offset + field.shift, value); break; + case 0xffffffff: + writeRaw32(field.offset, value); + break; + case 0xffff: + writeRaw16(field.offset + field.shift, value); + break; + case 0xff: + writeRaw8(field.offset + field.shift, value); + break; default: throw new Error('invalid pci space field mask'); } @@ -183,7 +298,9 @@ const pciAccessorFactory = ((addressPort, dataPort) => { */ get(address) { const key = JSON.stringify([address.bus, address.slot, address.func]); - if (accessorCache.has(key)) return accessorCache.get(key); + if (accessorCache.has(key)) { + return accessorCache.get(key); + } const value = new PciAccessor(address); accessorCache.set(key, value); @@ -204,8 +321,10 @@ const pciAccessorFactory = ((addressPort, dataPort) => { /** * Find ACPI PCI device bus, slot and function */ -const locateAcpiDevice = (dev) => { - if (!dev.isDevice()) return null; +function locateAcpiDevice(dev) { + if (!dev.isDevice()) { + return null; + } const addr = dev.address(); const slotId = ((addr >>> 16) & 0xffff) >>> 0; @@ -223,9 +342,13 @@ const locateAcpiDevice = (dev) => { } const parentDev = dev.parent(); - if (parentDev === null) return null; + if (parentDev === null) { + return null; + } - if (!parentDev.isDevice()) return null; + if (!parentDev.isDevice()) { + return null; + } if (parentDev.isRootBridge()) { busId = parentDev.getRootBridgeBusNumber(); @@ -238,7 +361,9 @@ const locateAcpiDevice = (dev) => { } const parentLocation = locateAcpiDevice(parentDev); - if (parentLocation === null) return null; + if (parentLocation === null) { + return null; + } const pciParent = pciAccessorFactory.get({ bus: parentLocation.bus, @@ -250,7 +375,9 @@ const locateAcpiDevice = (dev) => { // Mask multifunction bit const headerType = (header & 0x7f) >>> 0; - if (headerType !== 0x01 && headerType !== 0x02) return null; + if (headerType !== 0x01 && headerType !== 0x02) { + return null; + } const bridgeBus = pciParent.read(pciParent.bridgeFields().SECONDARY_BUS); @@ -259,31 +386,43 @@ const locateAcpiDevice = (dev) => { slot: slotId, func: funcId, }; -}; +} /** * Provides enumeration services for the whole PCI configuration space */ -const pciSpace = ((pciAccessorFactoryArg) => { - const checkDevice = (bus, slot, func, fn) => { - const addr = { bus, slot, func }; +const pciSpace = (function (pciAccessorFactoryArg) { + function checkDevice(bus, slot, func, fn) { + const addr = { + bus, + slot, + func, + }; const pciAccessor = pciAccessorFactoryArg.get(addr); const vendorId = pciAccessor.read(pciAccessor.fields().VENDOR_ID); - if (vendorId === 0xffff) return; + if (vendorId === 0xffff) { + return; + } fn(addr, pciAccessor); - }; + } - const checkDeviceFunctions = (bus, slot, fn) => { + function checkDeviceFunctions(bus, slot, fn) { let func = 0; - const pciAccessor = pciAccessorFactoryArg.get({ bus, slot, func }); + const pciAccessor = pciAccessorFactoryArg.get({ + bus, + slot, + func, + }); const headerType = pciAccessor.read(pciAccessor.fields().HEADER_TYPE); const isMultifunc = (headerType & 0x80) >>> 0; const funcCount = isMultifunc ? 8 : 1; - for (func = 0; func < funcCount; ++func) checkDevice(bus, slot, func, fn); - }; + for (func = 0; func < funcCount; ++func) { + checkDevice(bus, slot, func, fn); + } + } return { eachDevice(fn) { @@ -291,7 +430,9 @@ const pciSpace = ((pciAccessorFactoryArg) => { for (let bus = 0; bus < 255; ++bus) { for (let slot = 0; slot < 32; ++slot) { - if (!pciAccessorFactoryArg.exists(bus, slot, func)) continue; + if (!pciAccessorFactoryArg.exists(bus, slot, func)) { + continue; + } checkDeviceFunctions(bus, slot, fn); } } @@ -302,7 +443,7 @@ const pciSpace = ((pciAccessorFactoryArg) => { /** * Service for converting PCI data codes to readable names */ -const codeNameResolver = (() => { +const codeNameResolver = (function () { const classCodes = [ 'Unclassified', 'Mass Storage Controller', @@ -329,7 +470,9 @@ const codeNameResolver = (() => { * Get name for provided PCI device class code */ classCodeToName(code) { - if (typeof classCodes[code] === 'undefined') return classCodes[0]; + if (typeof classCodes[code] === 'undefined') { + return classCodes[0]; + } return classCodes[code]; }, }; @@ -347,46 +490,54 @@ class PciDevice { let isBridge = false; const headerType = (header & 0x7f) >>> 0; - if (headerType === 0x01 || headerType === 0x02) isBridge = true; + if (headerType === 0x01 || headerType === 0x02) { + isBridge = true; + } - const that = { acpiDevice: null }; + const that = { + acpiDevice: null, + }; let irqVector = null; - /** - * Attach ACPI PCI device handle to current PCI device - */ + /** + * Attach ACPI PCI device handle to current PCI device + */ this.attachAcpiDevice = (acpiDevice) => { - if (that.acpiDevice !== null) return; + if (that.acpiDevice !== null) { + return; + } that.acpiDevice = acpiDevice; }; - /** - * Get 16bit vendor ID of current device - */ + /** + * Get 16bit vendor ID of current device + */ this.vendorId = () => vendorId; - /** - * Get 16bit device ID of current device - */ + /** + * Get 16bit device ID of current device + */ this.deviceId = () => deviceId; - /** - * Check if current device is a PCI-to-PCI or PCI-to-CardBus - * bridge - */ + /** + * Check if current device is a PCI-to-PCI or PCI-to-CardBus + * bridge + */ this.isBridge = () => isBridge; - /** - * Get PCI device address (bus, slot and function) - */ + /** + * Get PCI device address (bus, slot and function) + */ this.address = () => address; - /** - * Get bridge secondary bus number (bus number of current bridge) - */ + /** + * Get bridge secondary bus number (bus number of current bridge) + */ this.getSecondaryBus = () => { - if (!isBridge) throw new Error('device is not a bridge'); + if (!isBridge) { + throw new Error('device is not a bridge'); + } return pciAccessor.read(pciAccessor.bridgeFields().SECONDARY_BUS); }; @@ -396,31 +547,35 @@ class PciDevice { pciAccessor.write(pciAccessor.fields().COMMAND, value); }; - /** - * Get current device IRQ vector - */ + /** + * Get current device IRQ vector + */ this.getIRQVector = () => irqVector; - /** - * Set current device IRQ vector. May be called only once - */ + /** + * Set current device IRQ vector. May be called only once + */ this.setIRQVector = (vector) => { - if (irqVector !== null) throw new Error('IRQ vector already set'); + if (irqVector !== null) { + throw new Error('IRQ vector already set'); + } irqVector = vector >>> 0; }; - /** - * Get interrupt pin of current device - */ + /** + * Get interrupt pin of current device + */ this.interruptPin = () => { - if (isBridge) throw new Error('device is a bridge'); + if (isBridge) { + throw new Error('device is a bridge'); + } return pciAccessor.read(pciAccessor.generalFields().INTERRUPT_PIN); }; - /** - * Get the class data of current device (class code, subclass, - * class name) - */ + /** + * Get the class data of current device (class code, subclass, + * class name) + */ this.classData = () => { const classCode = pciAccessor.read(pciAccessor.fields().CLASS_CODE); return { @@ -431,22 +586,28 @@ class PciDevice { }; this.subsystemData = () => { - if (isBridge) throw new Error('device is a bridge'); + if (isBridge) { + throw new Error('device is a bridge'); + } return { subsystemId: pciAccessor.read(pciAccessor.generalFields().SUBSYS_ID), subsystemVendor: pciAccessor.read(pciAccessor.generalFields().SUBSYS_VENDOR), }; }; - /** - * Read PCI base address register (BAR) and return resource type, - * offset, size and object. Returns null is BAR is not valid - */ + /** + * Read PCI base address register (BAR) and return resource type, + * offset, size and object. Returns null is BAR is not valid + */ this.getBAR = (index) => { - if (isBridge) throw new Error('device is a bridge'); + if (isBridge) { + throw new Error('device is a bridge'); + } const indexValue = index >>> 0; - if (indexValue > 5) throw new Error('invalid BAR register index (expected 0-5)'); + if (indexValue > 5) { + throw new Error('invalid BAR register index (expected 0-5)'); + } const barFlag = { BAR_IO: 0x01, @@ -455,15 +616,19 @@ class PciDevice { const barField = pciAccessor.generalFields().BAR[indexValue]; const barAddr = pciAccessor.read(barField); - if (!barAddr) return null; + if (!barAddr) { + return null; + } pciAccessor.write(barField, 0xffffffff); const barSize = pciAccessor.read(barField); - // Restore original value + // Restore original value pciAccessor.write(barField, barAddr >>> 0); - if (!barSize) return null; + if (!barSize) { + return null; + } let base = 0; let size = 0; @@ -471,30 +636,38 @@ class PciDevice { let obj = null; if (barAddr & barFlag.BAR_64) { - // TODO: 64bit bar support + // TODO: 64bit bar support barType = 'mem64'; } else if (barAddr & barFlag.BAR_IO) { - // TODO: verify io base & size + // TODO: verify io base & size base = ((barAddr & ~0x3) & 0xffff) >>> 0; size = ((~(barSize & ~0x3) + 1) & 0xffff) >>> 0; barType = 'io'; - if (size === 0) return null; + if (size === 0) { + return null; + } - // Base IO address 0 is probably an error, ignore it - if (base === 0) return null; + // Base IO address 0 is probably an error, ignore it + if (base === 0) { + return null; + } obj = io.subrange(base, (base + size) - 1); } else { base = (barAddr & 0xfffffff0) >>> 0; size = (((~(barSize & 0xfffffff0) >>> 0) + 1) & 0xffffffff) >>> 0; - if (size === 0) return null; + if (size === 0) { + return null; + } barType = 'mem32'; obj = memrange.block(base, size); } - if (barType === null || obj === null) return null; + if (barType === null || obj === null) { + return null; + } return { type: barType, @@ -504,9 +677,9 @@ class PciDevice { }; }; } - /** - * PCI configuration space command register flags - */ + /** + * PCI configuration space command register flags + */ static get commandFlags() { return { IOSpace: 0, @@ -526,9 +699,12 @@ class PciDevice { /** * Manages PCI devices */ -const pciManager = (() => { +const pciManager = (function () { const devicesMap = new Map(); - const addressHash = address => JSON.stringify([address.bus, address.slot, address.func]); + + function addressHash(address) { + return JSON.stringify([address.bus, address.slot, address.func]); + } return { /** @@ -545,7 +721,9 @@ const pciManager = (() => { */ findDevice(address) { const key = addressHash(address); - if (!devicesMap.has(key)) return null; + if (!devicesMap.has(key)) { + return null; + } return devicesMap.get(key); }, /** @@ -570,12 +748,16 @@ acpiDevices.forEach((acpiDevice) => { } // Check if unable to locate ACPI device on PCI bus - if (address === null) return; + if (address === null) { + return; + } const dev = pciManager.findDevice(address); // Check if unable to find device described in ACPI tables - if (dev === null) return; + if (dev === null) { + return; + } dev.attachAcpiDevice(acpiDevice); @@ -588,10 +770,14 @@ acpiDevices.forEach((acpiDevice) => { // Extract IRQ routing information const busRouting = []; acpiDevicesBuses.forEach((acpiDevice, bus) => { - if (typeof acpiDevice === 'undefined') return; + if (typeof acpiDevice === 'undefined') { + return; + } const routes = acpiDevice.getIrqRoutingTable(); - if (!Array.isArray(routes)) return; + if (!Array.isArray(routes)) { + return; + } busRouting[bus] = routes; }); @@ -601,30 +787,42 @@ pciManager.each((pciDevice) => { const address = pciDevice.address(); // Skip bridges for now - if (pciDevice.isBridge()) return; + if (pciDevice.isBridge()) { + return; + } - if (typeof busRouting[address.bus] === 'undefined') return; // No ACPI routing for this current device bridge + if (typeof busRouting[address.bus] === 'undefined') { + return; + } // No ACPI routing for this current device bridge const routing = busRouting[address.bus]; const devicePin = pciDevice.interruptPin(); let deviceIRQ = null; // Check if this device does not use an IRQ pin - if (devicePin === 0) return; + if (devicePin === 0) { + return; + } routing.forEach((route) => { - if (address.slot !== route.deviceId) return; + if (address.slot !== route.deviceId) { + return; + } // Plus 1 because routing data returns 0-base pin // numbers (0-A, 1-B, 2-C, 3-D) // PCI configuration space returns pins in format // (0-don't use, 1-A, 2-B, 3-C, 4-D) - if (devicePin !== route.pin + 1) return; + if (devicePin !== route.pin + 1) { + return; + } deviceIRQ = route.irq; }); - if (deviceIRQ !== null) pciDevice.setIRQVector(deviceIRQ); + if (deviceIRQ !== null) { + pciDevice.setIRQVector(deviceIRQ); + } }); // Start drivers @@ -633,11 +831,15 @@ pciManager.each((pciDevice) => { // const deviceId = pciDevice.deviceId(); const driverData = null; - if (driverData === null || typeof driverData.driver === 'undefined' || !driverData.enabled) return; // eslint-disable-line max-len + if (driverData === null || typeof driverData.driver === 'undefined' || !driverData.enabled) { + return; + } // eslint-disable-line max-len const irqVector = pciDevice.getIRQVector(); let irqObject = null; - if (irqVector !== null) irqObject = irqRange.irq(irqVector); + if (irqVector !== null) { + irqObject = irqRange.irq(irqVector); + } const argsBars = []; for (let i = 0; i < 6; ++i) { @@ -693,21 +895,23 @@ pciManager.each((pciDevice) => { const classData = pciDevice.classData(); let devicePin = 0; - if (!pciDevice.isBridge()) devicePin = pciDevice.interruptPin(); + if (!pciDevice.isBridge()) { + devicePin = pciDevice.interruptPin(); + } const pins = ['dont use', 'A', 'B', 'C', 'D']; - const info = `${address.bus.toString(16)}: ${address.slot.toString(16)}.${address.func} -${pciDevice.vendorId().toString(16)}: ${pciDevice.deviceId().toString(16)} -${classData.className} IRQ: ${vector} PIN: ${pins[devicePin]}`; + const info = `${address.bus.toString(16)}: ${address.slot.toString(16)}.${address.func} ${pciDevice.vendorId().toString(16)}: ${pciDevice.deviceId().toString(16)} ${classData.className} IRQ: ${vector} PIN: ${pins[devicePin]}`; debug(info); }); -const listPciDevices = () => { +function listPciDevices() { const results = []; pciManager.each((pciDevice) => { - if (pciDevice.isBridge()) return; + if (pciDevice.isBridge()) { + return; + } const address = pciDevice.address(); const irqVector = pciDevice.getIRQVector(); @@ -715,10 +919,14 @@ const listPciDevices = () => { const subsystemData = pciDevice.subsystemData(); let devicePin = 0; - if (!pciDevice.isBridge()) devicePin = pciDevice.interruptPin(); + if (!pciDevice.isBridge()) { + devicePin = pciDevice.interruptPin(); + } let irqObject = null; - if (irqVector !== null) irqObject = irqRange.irq(irqVector); + if (irqVector !== null) { + irqObject = irqRange.irq(irqVector); + } const bars = []; for (let i = 0; i < 6; ++i) { @@ -754,6 +962,6 @@ const listPciDevices = () => { }); return results; -}; +} module.exports = listPciDevices; diff --git a/js/core/random/entropy-source.js b/js/core/random/entropy-source.js index 4887eb38b..2f2ac3d4f 100644 --- a/js/core/random/entropy-source.js +++ b/js/core/random/entropy-source.js @@ -22,11 +22,13 @@ class EntropySource { getName() { return this._name; } - /** - * Request randomness from this entropy source - */ + /** + * Request randomness from this entropy source + */ getBytes(u8, cb) { - if (!this.ongetbytes) throw new Error('entropy source was not initialized'); + if (!this.ongetbytes) { + throw new Error('entropy source was not initialized'); + } this.ongetbytes(u8, cb); } } diff --git a/js/core/random/index.js b/js/core/random/index.js index 57c3dd654..08ea96455 100644 --- a/js/core/random/index.js +++ b/js/core/random/index.js @@ -35,16 +35,28 @@ exports.addEntropySource = sources.addEntropySource; */ exports.getTrueRandomValues = (value, cb) => { let u8 = null; - if (typeutils.isNumber(value)) u8 = new Uint8Array(value); - if (value instanceof Uint8Array) u8 = value; + if (typeutils.isNumber(value)) { + u8 = new Uint8Array(value); + } + if (value instanceof Uint8Array) { + u8 = value; + } - if (!u8) throw new Error('getTrueRandomValues: argument 0 is not a number or Uint8Array'); - if (u8.length === 0) throw new Error('getTrueRandomValues: buffer length must be greater than 0'); + if (!u8) { + throw new Error('getTrueRandomValues: argument 0 is not a number or Uint8Array'); + } + if (u8.length === 0) { + throw new Error('getTrueRandomValues: buffer length must be greater than 0'); + } - if (!typeutils.isFunction(cb)) throw new Error('getTrueRandomValues: argument 1 is not a function'); // eslint-disable-line max-len + if (!typeutils.isFunction(cb)) { + throw new Error('getTrueRandomValues: argument 1 is not a function'); + } // eslint-disable-line max-len const defaultSource = getDefaultSource(); - if (!defaultSource) throw new Error('getTrueRandomValues: no entropy source available'); + if (!defaultSource) { + throw new Error('getTrueRandomValues: no entropy source available'); + } defaultSource.getBytes(u8, () => { isaac.seed(u8); @@ -60,13 +72,23 @@ exports.getTrueRandomValues = (value, cb) => { */ exports.getRandomValues = (value) => { let u8 = null; - if (typeutils.isNumber(value)) u8 = new Uint8Array(value); - if (value instanceof Uint8Array) u8 = value; + if (typeutils.isNumber(value)) { + u8 = new Uint8Array(value); + } + if (value instanceof Uint8Array) { + u8 = value; + } - if (!u8) throw new Error('getRandomValues: argument 0 is not a number or Uint8Array'); - if (u8.length === 0) throw new Error('getRandomValues: buffer length must be greater than 0'); + if (!u8) { + throw new Error('getRandomValues: argument 0 is not a number or Uint8Array'); + } + if (u8.length === 0) { + throw new Error('getRandomValues: buffer length must be greater than 0'); + } - for (let i = 0; i < u8.length; i++) u8[i] = isaac.getByte(); + for (let i = 0; i < u8.length; i++) { + u8[i] = isaac.getByte(); + } return u8; }; diff --git a/js/core/random/isaac-wrapper.js b/js/core/random/isaac-wrapper.js index c4ffb6474..5887f2fc6 100644 --- a/js/core/random/isaac-wrapper.js +++ b/js/core/random/isaac-wrapper.js @@ -24,7 +24,9 @@ const isaac = require('../../deps/isaac/isaac'); // * 0 < n < 256 // This ensures the numbers are similar to the numbers // generated by VirtioRNG. -const isaacToUint8 = n => (n >>> 0) & 0xff; +function isaacToUint8(n) { + return (n >>> 0) & 0xff; +} exports.seed = isaac.seed; exports.getByte = () => isaacToUint8(isaac.rand()); diff --git a/js/core/random/js-random-source.js b/js/core/random/js-random-source.js index b5fa27ab4..f95743016 100644 --- a/js/core/random/js-random-source.js +++ b/js/core/random/js-random-source.js @@ -21,7 +21,9 @@ const sources = require('./sources'); // and isaac CSPRNG const source = new EntropySource('js-random'); source.ongetbytes = (u8, cb) => { - for (let i = 0; i < u8.length; i++) u8[i] = isaac.getByte(); // eslint-disable-line no-param-reassign + for (let i = 0; i < u8.length; i++) { + u8[i] = isaac.getByte(); + } // eslint-disable-line no-param-reassign cb(); }; diff --git a/js/core/set-time.js b/js/core/set-time.js index 2ad6347ed..f9190034f 100644 --- a/js/core/set-time.js +++ b/js/core/set-time.js @@ -15,14 +15,18 @@ 'use strict'; runtime.dns.resolve('pool.ntp.org', {}, (err, res) => { - if (err) return runtime.stdio.defaultStdio.writeError(err); + if (err) { + return runtime.stdio.defaultStdio.writeError(err); + } const rawip = res.results[0].address; const data = new Uint8Array(48); data[0] = 0x1B; let i; - for (i = 1; i < 48; i++) data[i] = 0; + for (i = 1; i < 48; i++) { + data[i] = 0; + } const socket = new runtime.net.UDPSocket(); socket.onmessage = (ip, port, u8) => { @@ -30,8 +34,12 @@ runtime.dns.resolve('pool.ntp.org', {}, (err, res) => { let intpart = 0; let fractpart = 0; - for (i = 0; i <= 3; i++) intpart = (256 * intpart) + u8[offset + i]; - for (i = 4; i <= 7; i++) fractpart = (256 * fractpart) + u8[offset + i]; + for (i = 0; i <= 3; i++) { + intpart = (256 * intpart) + u8[offset + i]; + } + for (i = 4; i <= 7; i++) { + fractpart = (256 * fractpart) + u8[offset + i]; + } const milli = ((intpart * 1000) + ((fractpart * 1000) / 0x100000000)); diff --git a/js/core/stdio/interface.js b/js/core/stdio/interface.js index 08088822c..1563030ba 100644 --- a/js/core/stdio/interface.js +++ b/js/core/stdio/interface.js @@ -46,6 +46,16 @@ class StdioInterface { } readLine(cb) { + let text = ''; + function addinput(char) { + if (char !== '\n') { + text += char; + this.onread(addinput); + } else { + cb(text); + } + } + // If there's onreadline, use it. if (this.onreadline) { this.onreadline(cb); @@ -53,15 +63,6 @@ class StdioInterface { // Else, use onread. // Downside: no cusor moving or backspace. // TODO: Fix downside. - let text = ''; - const addinput = (char) => { - if (char !== '\n') { - text += char; - this.onread(addinput); - } else { - cb(text); - } - }; this.onread(addinput); } } diff --git a/js/core/timers.js b/js/core/timers.js index 86090831d..6139f5998 100644 --- a/js/core/timers.js +++ b/js/core/timers.js @@ -17,9 +17,13 @@ const tasks5s = []; setInterval(() => { - if (tasks5s.length === 0) return; + if (tasks5s.length === 0) { + return; + } - for (const task of tasks5s) task(); + for (const task of tasks5s) { + task(); + } }, 5000); /** diff --git a/js/core/tty/line-editor.js b/js/core/tty/line-editor.js index 1dee448a0..28c4a6e88 100644 --- a/js/core/tty/line-editor.js +++ b/js/core/tty/line-editor.js @@ -33,7 +33,9 @@ class LineEditor { drawCursor() { let char = ' '; - if (this.inputPosition < this.inputText.length) char = this.inputText[this.inputPosition]; + if (this.inputPosition < this.inputText.length) { + char = this.inputText[this.inputPosition]; + } printer.print(char, 1, printer.color.WHITE, printer.color.LIGHTGREEN); printer.moveOffset(-1); @@ -41,7 +43,9 @@ class LineEditor { removeCursor() { let char = ' '; - if (this.inputPosition < this.inputText.length) char = this.inputText[this.inputPosition]; + if (this.inputPosition < this.inputText.length) { + char = this.inputText[this.inputPosition]; + } printer.print(char, 1, printer.color.WHITE, printer.color.BLACK); printer.moveOffset(-1); @@ -56,7 +60,9 @@ class LineEditor { const rightSide = this.inputText.slice(this.inputPosition); this.inputText = this.inputText.slice(0, this.inputPosition) + char + rightSide; printer.print(char); - for (const item of rightSide) printer.print(item); + for (const item of rightSide) { + printer.print(item); + } printer.moveOffset(-rightSide.length); } ++this.inputPosition; @@ -73,7 +79,9 @@ class LineEditor { const rightSide = this.inputText.slice(this.inputPosition); this.inputText = this.inputText.slice(0, this.inputPosition - 1) + rightSide; printer.moveOffset(-1); - for (const item of rightSide) printer.print(item); + for (const item of rightSide) { + printer.print(item); + } printer.print(' '); printer.moveOffset(-rightSide.length - 1); } diff --git a/js/core/tty/printer.js b/js/core/tty/printer.js index 3c216252f..1d96a747f 100644 --- a/js/core/tty/printer.js +++ b/js/core/tty/printer.js @@ -21,12 +21,14 @@ let posCurrent = 0; const w = vga.WIDTH; const h = vga.HEIGHT; -const refresh = () => vga.draw(buffer); +function refresh() { + vga.draw(buffer); +} -const scrollUp = () => { +function scrollUp() { buffer.scrollUp(vga.color.BLACK); posCurrent -= w; -}; +} refresh(); @@ -40,9 +42,13 @@ exports.print = (textOpt = '', repeat = 1, fg = vga.color.WHITE, bg = vga.color. for (const c of text) { if (c === '\n') { posCurrent -= (posCurrent % w) - w; - if (posCurrent >= w * h) scrollUp(); + if (posCurrent >= w * h) { + scrollUp(); + } } else { - if (posCurrent >= w * h) scrollUp(); + if (posCurrent >= w * h) { + scrollUp(); + } buffer.setOffset(posCurrent++, c, fg, bg); } } @@ -54,9 +60,13 @@ exports.print = (textOpt = '', repeat = 1, fg = vga.color.WHITE, bg = vga.color. exports.moveOffset = (offsetOpt) => { const offset = offsetOpt | 0; let newPos = posCurrent + offset; - if (newPos < 0) newPos = 0; + if (newPos < 0) { + newPos = 0; + } - if (newPos >= w * h) newPos = (w * h) - 1; + if (newPos >= w * h) { + newPos = (w * h) - 1; + } posCurrent = newPos; }; @@ -64,9 +74,17 @@ exports.moveOffset = (offsetOpt) => { exports.moveTo = (xOpt, yOpt) => { let x = xOpt; let y = yOpt; - if (x < 0) x = 0; - if (x >= w) x = w - 1; - if (y < 0) y = 0; - if (y >= h) y = h - 1; + if (x < 0) { + x = 0; + } + if (x >= w) { + x = w - 1; + } + if (y < 0) { + y = 0; + } + if (y >= h) { + y = h - 1; + } posCurrent = (y * w) + x; }; diff --git a/js/core/tty/terminal.js b/js/core/tty/terminal.js index 87e5f8ce4..5e51fb31b 100644 --- a/js/core/tty/terminal.js +++ b/js/core/tty/terminal.js @@ -25,12 +25,14 @@ exports.moveTo = printer.moveTo; let isReading = false; exports.read = (cb) => { - if (isReading) throw new Error('nested terminal read is not allowed'); + if (isReading) { + throw new Error('nested terminal read is not allowed'); + } const editor = new LineEditor(); isReading = true; - const addinput = (keyinfo) => { + function addinput(keyinfo) { switch (keyinfo.type) { case 'character': printer.print(keyinfo.character); @@ -48,19 +50,21 @@ exports.read = (cb) => { default: break; } - }; + } keyboard.onKeydown.add(addinput); editor.drawCursor(); }; exports.readLine = (cb) => { - if (isReading) throw new Error('nested terminal read is not allowed'); + if (isReading) { + throw new Error('nested terminal read is not allowed'); + } const editor = new LineEditor(); isReading = true; - const addinput = (keyinfo) => { + function addinput(keyinfo) { switch (keyinfo.type) { case 'kpleft': editor.moveCursorLeft(); @@ -84,7 +88,7 @@ exports.readLine = (cb) => { default: break; } - }; + } keyboard.onKeydown.add(addinput); editor.drawCursor(); diff --git a/js/core/tty/vga.js b/js/core/tty/vga.js index 273af6896..e99582dac 100644 --- a/js/core/tty/vga.js +++ b/js/core/tty/vga.js @@ -48,32 +48,39 @@ const color = { exports.color = color; -const getColor = (fg, bg) => (((bg & 0xF) << 4) + (fg & 0xF)) >>> 0; +function getColor(fg, bg) { + return (((bg & 0xF) << 4) + (fg & 0xF)) >>> 0; +} -const setCharOffset = (u8, offset, char, fg, bg) => { - if (offset < 0 || offset >= w * h) throw new Error('vga error: offset is out of bounds'); +function setCharOffset(u8, offset, char, fg, bg) { + if (offset < 0 || offset >= w * h) { + throw new Error('vga error: offset is out of bounds'); + } /* eslint-disable no-param-reassign */ u8[offset * 2] = char.charCodeAt(0); u8[(offset * 2) + 1] = getColor(fg, bg); /* eslint-enable no-param-reassign */ -}; +} -const setCharXY = (u8, x, y, char, fg, bg) => { - if (x < 0 || x >= w) throw new Error('vga error: x is out of bounds'); +function setCharXY(u8, x, y, char, fg, bg) { + if (x < 0 || x >= w) { + throw new Error('vga error: x is out of bounds'); + } - if (y < 0 || y >= h) throw new Error('vga error: y is out of bounds'); + if (y < 0 || y >= h) { + throw new Error('vga error: y is out of bounds'); + } const offset = (y * w) + x; setCharOffset(u8, offset, char, fg >>> 0, bg >>> 0); -}; - -// declare it up here, and define it below VGABuffer, a workaround for no-use-before-define -let testInstance; +} -const testColor = (value) => { - if ((value >>> 0) !== value) throw new Error('invalid color value'); -}; +function testColor(value) { + if ((value >>> 0) !== value) { + throw new Error('invalid color value'); + } +} class VGABuffer { constructor() { @@ -94,19 +101,25 @@ class VGABuffer { clear(bg) { testInstance(this); testColor(bg); - for (let i = 0; i < w * h; ++i) setCharOffset(this.b, i, ' ', bg, bg); + for (let i = 0; i < w * h; ++i) { + setCharOffset(this.b, i, ' ', bg, bg); + } } scrollUp(bg) { testInstance(this); testColor(bg); this.b.set(this.b.subarray(w * 2, w * h * 2)); - for (let t = 0; t < w; ++t) setCharXY(this.b, t, h - 1, ' ', bg, bg); + for (let t = 0; t < w; ++t) { + setCharXY(this.b, t, h - 1, ' ', bg, bg); + } } } -testInstance = (obj) => { - if (!(obj instanceof VGABuffer)) throw new Error('VGABuffer instance required'); -}; +function testInstance(obj) { + if (!(obj instanceof VGABuffer)) { + throw new Error('VGABuffer instance required'); + } +} exports.draw = (drawbuf) => { testInstance(drawbuf); diff --git a/js/driver/ps2/keyboard.js b/js/driver/ps2/keyboard.js index 6b5807811..a8a2b46f9 100644 --- a/js/driver/ps2/keyboard.js +++ b/js/driver/ps2/keyboard.js @@ -18,22 +18,22 @@ const runtime = require('../../core'); /* eslint-disable no-multi-spaces, max-len */ const controlKeys = [ - /* 0x00 */ 0, 'escape', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'backspace', 'tab', - /* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'enter', 'leftctrl', 0, 0, - /* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'leftshift', 0, 0, 0, 0, 0, - /* 0x30 */ 0, 0, 0, 0, 0, 0, 'rightshift', 0, 'leftalt', 0, 'capslock', 'f1', 'f2', 'f3', 'f4', 'f5', - /* 0x40 */ 'f6', 'f7', 'f8', 'f9', 'f10', 'numlock', 'scrllock', 'kphome', 'kpup', 'kppageup', 0, 'kpleft', 'kp5', 'kpright', 0, 'kpend', - /* 0x50 */ 'kpdown', 'kppagedown', 'kpinsert', 'kpdel', 'sysreq', 0, 0, 'f11', 'f12', 0, 0, 0, 0, 0, 0, 0, - /* 0x60 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x70 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'enter', 'rightctrl', 0, 0, - /* 0xA0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 0xB0 */ 0, 0, 0, 0, 0, 'kpslash', 0, 'prntscrn', 'rightalt', 0, 0, 0, 0, 0, 0, 0, - /* 0xC0 */ 0, 0, 0, 0, 0, 0, 0, 'home', 'up', 'pageup', 0, 'left', 0, 'right', 0, 'end', - /* 0xD0 */ 'down', 'pagedown', 'insert', 'del', 0, 0, 0, 0, 0, 0, 0, 'leftsup', 'rightsup', 'menu', 0, 0, - /* 0xE0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 0xF0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x00 */ 0, 'escape', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'backspace', 'tab', + /* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'enter', 'leftctrl', 0, 0, + /* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'leftshift', 0, 0, 0, 0, 0, + /* 0x30 */ 0, 0, 0, 0, 0, 0, 'rightshift', 0, 'leftalt', 0, 'capslock', 'f1', 'f2', 'f3', 'f4', 'f5', + /* 0x40 */ 'f6', 'f7', 'f8', 'f9', 'f10', 'numlock', 'scrllock', 'kphome', 'kpup', 'kppageup', 0, 'kpleft', 'kp5', 'kpright', 0, 'kpend', + /* 0x50 */ 'kpdown', 'kppagedown', 'kpinsert', 'kpdel', 'sysreq', 0, 0, 'f11', 'f12', 0, 0, 0, 0, 0, 0, 0, + /* 0x60 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x70 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'enter', 'rightctrl', 0, 0, + /* 0xA0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0xB0 */ 0, 0, 0, 0, 0, 'kpslash', 0, 'prntscrn', 'rightalt', 0, 0, 0, 0, 0, 0, 0, + /* 0xC0 */ 0, 0, 0, 0, 0, 0, 0, 'home', 'up', 'pageup', 0, 'left', 0, 'right', 0, 'end', + /* 0xD0 */ 'down', 'pagedown', 'insert', 'del', 0, 0, 0, 0, 0, 0, 0, 'leftsup', 'rightsup', 'menu', 0, 0, + /* 0xE0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0xF0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; const keymapNormal = [ @@ -73,13 +73,15 @@ const statuses = { scrllock: false, }; -const keyEvent = (codeOpt, isPressed) => { +function keyEvent(codeOpt, isPressed) { let code = codeOpt; let cmd = controlKeys[code & 0xFF]; let character = ''; code &= 0x7F; - if (cmd === 0) cmd = controlKeys[code]; + if (cmd === 0) { + cmd = controlKeys[code]; + } if (cmd === 0) { cmd = 'character'; @@ -113,13 +115,19 @@ const keyEvent = (codeOpt, isPressed) => { statuses.rightshift = isPressed; break; case 'capslock': - if (isPressed) statuses.capslock = !statuses.capslock; + if (isPressed) { + statuses.capslock = !statuses.capslock; + } break; case 'numlock': - if (isPressed) statuses.numlock = !statuses.numlock; + if (isPressed) { + statuses.numlock = !statuses.numlock; + } break; case 'scrllock': - if (isPressed) statuses.scrllock = !statuses.scrllock; + if (isPressed) { + statuses.scrllock = !statuses.scrllock; + } break; default: break; @@ -139,21 +147,21 @@ const keyEvent = (codeOpt, isPressed) => { } else { runtime.keyboard.onKeyup.dispatch(keyinfo); } -}; +} const driver = { init(device) { const irq = device.irq; const port = device.ioPort; - const init = () => { + function init() { let v1 = port.read8(); let v2 = 0; while (v1 !== v2) { v2 = v1; v1 = port.read8(); } - }; + } let escaped = false; diff --git a/js/driver/virtio/device.js b/js/driver/virtio/device.js index 281afa353..c7f900b00 100644 --- a/js/driver/virtio/device.js +++ b/js/driver/virtio/device.js @@ -27,23 +27,23 @@ class VirtioDevice { const ioPorts = { // Common DEVICE_FEATURES: 0x00, // 32 bit r - GUEST_FEATURES: 0x04, // 32 bit r+w - QUEUE_ADDRESS: 0x08, // 32 bit r+w - QUEUE_SIZE: 0x0c, // 16 bit r - QUEUE_SELECT: 0x0e, // 16 bit r+w - QUEUE_NOTIFY: 0x10, // 16 bit r+w - DEVICE_STATUS: 0x12, // 8 bit r+w - ISR_STATUS: 0x13, // 8 bit r + GUEST_FEATURES: 0x04, // 32 bit r+w + QUEUE_ADDRESS: 0x08, // 32 bit r+w + QUEUE_SIZE: 0x0c, // 16 bit r + QUEUE_SELECT: 0x0e, // 16 bit r+w + QUEUE_NOTIFY: 0x10, // 16 bit r+w + DEVICE_STATUS: 0x12, // 8 bit r+w + ISR_STATUS: 0x13, // 8 bit r }; if (deviceType === 'net') { // Network card - ioPorts.NETWORK_DEVICE_MAC0 = 0x14; // 8 bit r - ioPorts.NETWORK_DEVICE_MAC1 = 0x15; // 8 bit r - ioPorts.NETWORK_DEVICE_MAC2 = 0x16; // 8 bit r - ioPorts.NETWORK_DEVICE_MAC3 = 0x17; // 8 bit r - ioPorts.NETWORK_DEVICE_MAC4 = 0x18; // 8 bit r - ioPorts.NETWORK_DEVICE_MAC5 = 0x19; // 8 bit r + ioPorts.NETWORK_DEVICE_MAC0 = 0x14; // 8 bit r + ioPorts.NETWORK_DEVICE_MAC1 = 0x15; // 8 bit r + ioPorts.NETWORK_DEVICE_MAC2 = 0x16; // 8 bit r + ioPorts.NETWORK_DEVICE_MAC3 = 0x17; // 8 bit r + ioPorts.NETWORK_DEVICE_MAC4 = 0x18; // 8 bit r + ioPorts.NETWORK_DEVICE_MAC5 = 0x19; // 8 bit r ioPorts.NETWORK_DEVICE_STATUS = 0x1A; // 16 bit r } @@ -63,7 +63,9 @@ class VirtioDevice { for (const feature of Object.keys(features)) { const mask = 1 << features[feature]; - if (deviceFeatures & mask) result[feature] = true; + if (deviceFeatures & mask) { + result[feature] = true; + } } return result; @@ -72,8 +74,12 @@ class VirtioDevice { let value = 0; for (const feature of Object.keys(features)) { - if (!driverFeatures[feature]) continue; - if (!deviceFeatures[feature]) return false; // Device doesn't support required feature + if (!driverFeatures[feature]) { + continue; + } + if (!deviceFeatures[feature]) { + return false; + } // Device doesn't support required feature const mask = 1 << features[feature]; value |= mask; @@ -107,7 +113,7 @@ class VirtioDevice { hasPendingIRQ() { return !!(1 & this.io.ISR_STATUS.read8()); } - // [network device] + // [network device] netReadHWAddress() { return [ this.io.NETWORK_DEVICE_MAC0.read8(), @@ -118,7 +124,7 @@ class VirtioDevice { this.io.NETWORK_DEVICE_MAC5.read8(), ]; } - // [network device] + // [network device] netReadStatus() { return !!(1 & this.io.NETWORK_DEVICE_STATUS.read16()); } diff --git a/js/driver/virtio/index.js b/js/driver/virtio/index.js index d09c6d2ae..7bdd7c98e 100644 --- a/js/driver/virtio/index.js +++ b/js/driver/virtio/index.js @@ -23,14 +23,20 @@ const driver = { init(pciDevice) { const subsystemId = pciDevice.subsystem.subsystemId; - if (subsystemId === VIRTIO_SUBSYSTEM_NETWORK) return virtioNet(pciDevice); - if (subsystemId === VIRTIO_SUBSYSTEM_RNG) return virtioRNG(pciDevice); + if (subsystemId === VIRTIO_SUBSYSTEM_NETWORK) { + return virtioNet(pciDevice); + } + if (subsystemId === VIRTIO_SUBSYSTEM_RNG) { + return virtioRNG(pciDevice); + } debug(`[virtio] unknown virtio device (subsystem id ${subsystemId})`); }, reset() {}, }; -const testDeviceId = deviceId => deviceId >= 0x1000 && deviceId <= 0x103f; +function testDeviceId(deviceId) { + return deviceId >= 0x1000 && deviceId <= 0x103f; +} runtime.pci.addDriver(0x1af4, testDeviceId, driver); diff --git a/js/driver/virtio/net.js b/js/driver/virtio/net.js index 8a8df2386..169116f42 100644 --- a/js/driver/virtio/net.js +++ b/js/driver/virtio/net.js @@ -17,7 +17,7 @@ const VirtioDevice = require('./device'); const runtime = require('../../core'); const { MACAddress, Interface } = runtime.net; -const virtioHeader = (() => { +const virtioHeader = (function () { // eslint-disable-line wrap-iife const OFFSET_FLAGS = 0; const OFFSET_GSO_TYPE = 1; // const OFFSET_HDR_LEN = 2; @@ -40,7 +40,7 @@ const virtioHeader = (() => { }; })(); -const initializeNetworkDevice = (pciDevice) => { +function initializeNetworkDevice(pciDevice) { const ioSpace = pciDevice.getBAR(0).resource; const irq = pciDevice.getIRQ(); @@ -74,7 +74,7 @@ const initializeNetworkDevice = (pciDevice) => { dev.setDriverAck(); const driverFeatures = { - VIRTIO_NET_F_MAC: true, // able to read MAC address + VIRTIO_NET_F_MAC: true, // able to read MAC address VIRTIO_NET_F_STATUS: true, // able to check network status // VIRTIO_RING_F_NOTIFY_ON_EMPTY: true // VIRTIO_NET_F_CSUM: true, // checksum offload @@ -92,13 +92,16 @@ const initializeNetworkDevice = (pciDevice) => { } if (!dev.writeGuestFeatures(features, driverFeatures, deviceFeatures)) { - return debug('[virtio] driver is unable to start'); + debug('[virtio] driver is unable to start'); + return; } const hwAddr = dev.netReadHWAddress(); const status = dev.netReadStatus(); - if (!status) return; + if (!status) { + return; + } const QUEUE_ID_RECV = 0; const QUEUE_ID_TRANSMIT = 1; @@ -107,16 +110,20 @@ const initializeNetworkDevice = (pciDevice) => { const transmitQueue = dev.queueSetup(QUEUE_ID_TRANSMIT); transmitQueue.suppressUsedBuffers(); - const fillReceiveQueue = () => { + function fillReceiveQueue() { while (recvQueue.descriptorTable.descriptorsAvailable) { - if (!recvQueue.placeBuffers([new Uint8Array(1536)], true)) break; + if (!recvQueue.placeBuffers([new Uint8Array(1536)], true)) { + break; + } } - if (recvQueue.isNotificationNeeded()) dev.queueNotify(QUEUE_ID_RECV); - }; + if (recvQueue.isNotificationNeeded()) { + dev.queueNotify(QUEUE_ID_RECV); + } + } const mac = new MACAddress(hwAddr[0], hwAddr[1], hwAddr[2], - hwAddr[3], hwAddr[4], hwAddr[5]); + hwAddr[3], hwAddr[4], hwAddr[5]); const intf = new Interface(mac); intf.setBufferDataOffset(virtioHeader.length); intf.ontransmit = (u8headers, u8data) => { @@ -126,20 +133,26 @@ const initializeNetworkDevice = (pciDevice) => { transmitQueue.placeBuffers([u8headers], false); } - if (transmitQueue.isNotificationNeeded()) dev.queueNotify(QUEUE_ID_TRANSMIT); + if (transmitQueue.isNotificationNeeded()) { + dev.queueNotify(QUEUE_ID_TRANSMIT); + } }; - const recvBuffer = u8 => intf.receive(u8); + function recvBuffer(u8) { + intf.receive(u8); + } irq.on(() => { - if (!dev.hasPendingIRQ()) return; + if (!dev.hasPendingIRQ()) { + return; + } recvQueue.fetchBuffers(recvBuffer); fillReceiveQueue(); }); - // Under high load we're missing interrupts. This needs to be fixed. - // This setInterval hack clears pending IRQ flag and rechecks queues. +// Under high load we're missing interrupts. This needs to be fixed. +// This setInterval hack clears pending IRQ flag and rechecks queues. setInterval(() => { dev.hasPendingIRQ(); recvQueue.fetchBuffers(recvBuffer); @@ -150,6 +163,6 @@ const initializeNetworkDevice = (pciDevice) => { fillReceiveQueue(); runtime.net.interfaceAdd(intf); -}; +} module.exports = initializeNetworkDevice; diff --git a/js/driver/virtio/rng.js b/js/driver/virtio/rng.js index f75caac8e..1995c2779 100644 --- a/js/driver/virtio/rng.js +++ b/js/driver/virtio/rng.js @@ -16,7 +16,7 @@ const VirtioDevice = require('./device'); const runtime = require('../../core'); -const initializeRNGDevice = (pciDevice) => { +function initializeRNGDevice(pciDevice) { const ioSpace = pciDevice.getBAR(0).resource; const irq = pciDevice.getIRQ(); const allocator = runtime.allocator; @@ -38,13 +38,17 @@ const initializeRNGDevice = (pciDevice) => { const reqQueue = dev.queueSetup(QUEUE_ID_REQ); const cbqueue = []; - const recvBuffer = () => { - if (cbqueue.length === 0) return; + function recvBuffer() { + if (cbqueue.length === 0) { + return; + } cbqueue.shift()(); - }; + } irq.on(() => { - if (!dev.hasPendingIRQ()) return; + if (!dev.hasPendingIRQ()) { + return; + } reqQueue.fetchBuffers(recvBuffer); }); @@ -56,10 +60,12 @@ const initializeRNGDevice = (pciDevice) => { cbqueue.push(cb); reqQueue.placeBuffers([u8], true); - if (reqQueue.isNotificationNeeded()) dev.queueNotify(QUEUE_ID_REQ); + if (reqQueue.isNotificationNeeded()) { + dev.queueNotify(QUEUE_ID_REQ); + } }; runtime.random.addEntropySource(source); -}; +} module.exports = initializeRNGDevice; diff --git a/js/driver/virtio/vring/descriptor-table.js b/js/driver/virtio/vring/descriptor-table.js index 88381d981..e6e990b6f 100644 --- a/js/driver/virtio/vring/descriptor-table.js +++ b/js/driver/virtio/vring/descriptor-table.js @@ -30,9 +30,12 @@ class DescriptorTable { this.descriptorsAvailable = ringSize; this.descriptorsBuffers = new Array(ringSize); - let i; - for (i = 0; i < ringSize; ++i) this.descriptorsBuffers[i] = null; - for (i = 0; i < ringSize - 1; ++i) this.setNext(i, i + 1); + for (let i = 0; i < ringSize; ++i) { + this.descriptorsBuffers[i] = null; + } + for (let i = 0; i < ringSize - 1; ++i) { + this.setNext(i, i + 1); + } } static getDescriptorSizeBytes() { @@ -84,15 +87,21 @@ class DescriptorTable { */ placeBuffers(buffers, lengths, isWriteOnly) { const count = buffers.length; - if (this.descriptorsAvailable < count) return -1; + if (this.descriptorsAvailable < count) { + return -1; + } let head = this.freeDescriptorHead; const first = head; for (let i = 0; i < count; ++i) { const d = buffers[i]; let flags = 0; - if (count !== i + 1) flags |= VRING_DESC_F_NEXT; - if (isWriteOnly) flags |= VRING_DESC_F_WRITE; + if (count !== i + 1) { + flags |= VRING_DESC_F_NEXT; + } + if (isWriteOnly) { + flags |= VRING_DESC_F_WRITE; + } this.setBuffer(head, d, lengths[i], flags); this.descriptorsBuffers[head] = d; diff --git a/js/driver/virtio/vring/index.js b/js/driver/virtio/vring/index.js index 8a348d9e8..6b84ebcc0 100644 --- a/js/driver/virtio/vring/index.js +++ b/js/driver/virtio/vring/index.js @@ -24,7 +24,10 @@ const SIZEOF_UINT16 = 2; class VRing { constructor(mem, byteOffset, ringSize) { assert(ringSize !== 0 && (ringSize & (ringSize - 1)) === 0, `invalid ringSize = ${ringSize}`); - const align = value => ((value + 4095) & ~4095) >>> 0; + + function align(value) { + return ((value + 4095) & ~4095) >>> 0; + } const baseAddress = mem.address + byteOffset; const offsetAvailableRing = DescriptorTable.getDescriptorSizeBytes() * ringSize; @@ -44,11 +47,15 @@ class VRing { let count = 0; for (;;) { - if (!this.suppressInterrupts) this.availableRing.disableInterrupts(); + if (!this.suppressInterrupts) { + this.availableRing.disableInterrupts(); + } for (;;) { const u8 = this.getBuffer(); - if (u8 === null) break; + if (u8 === null) { + break; + } count++; if (fn) setImmediate(() => fn(u8)); @@ -62,7 +69,9 @@ class VRing { memoryBarrier(); } - if (!this.usedRing.hasUnprocessedBuffers()) break; + if (!this.usedRing.hasUnprocessedBuffers()) { + break; + } } return count; @@ -74,7 +83,9 @@ class VRing { * @param isWriteOnly {bool} R/W buffers flag */ placeBuffers(buffers, isWriteOnly) { - if (this.suppressInterrupts) this.fetchBuffers(null); + if (this.suppressInterrupts) { + this.fetchBuffers(null); + } // Single Uint8Array could use multiple physical pages // as its backing store @@ -112,10 +123,14 @@ class VRing { } getBuffer() { const hasUnprocessed = this.usedRing.hasUnprocessedBuffers(); - if (!hasUnprocessed) return null; + if (!hasUnprocessed) { + return null; + } const used = this.usedRing.getUsedDescriptor(); - if (used === null) return null; + if (used === null) { + return null; + } const descriptorId = used.id; const buffer = this.descriptorTable.getBuffer(descriptorId); diff --git a/js/index.js b/js/index.js index 19995ff24..fd76ddecd 100644 --- a/js/index.js +++ b/js/index.js @@ -39,7 +39,9 @@ runtime.debug = isDebug; runtime.shell.setCommand('1', (args, env, cb) => { env.stdio.writeLine('OK.'); runtime.dns.resolve('www.google.com', {}, (err, data) => { - if (err) return cb(1); + if (err) { + return cb(1); + } console.log(JSON.stringify(data)); cb(0); }); diff --git a/js/modules/console.js b/js/modules/console.js index 5320e8831..30e9c511d 100644 --- a/js/modules/console.js +++ b/js/modules/console.js @@ -31,7 +31,9 @@ class Console { this._labels = {}; } assert(val, ...data) { - if (!val) throw new Error(util.format(...data)); + if (!val) { + throw new Error(util.format(...data)); + } } dir(obj, optsOpt = {}) { const opts = optsOpt; @@ -81,5 +83,7 @@ const bound = [ 'info', 'warn', ]; -for (const item of bound) module.exports[item] = console[item].bind(console); +for (const item of bound) { + module.exports[item] = console[item].bind(console); +} module.exports.Console = Console; diff --git a/js/modules/dns.js b/js/modules/dns.js index 371d6228a..a94b33add 100644 --- a/js/modules/dns.js +++ b/js/modules/dns.js @@ -47,23 +47,36 @@ const servers = [ '8.8.8.8', ]; -const throwIPv6Err = (cb) => { +function throwIPv6Err(cb) { const err = new SystemError('runtime doesn\'t support IPv6', exports.BADFAMILY); - if (cb) return cb(err); + if (cb) { + return cb(err); + } throw err; -}; +} -const lookup = (hostname, opts, cb) => { - if (opts.family && opts.family === 6) return throwIPv6Err(cb); +function lookup(hostname, opts, cb) { + if (opts.family && opts.family === 6) { + return throwIPv6Err(cb); + } opts.query = opts.query || 'A'; if (hostname === 'localhost' && opts.query === 'A') { if (!opts.all) { - if (cb) cb(null, '127.0.0.1', 4); + if (cb) { + cb(null, '127.0.0.1', 4); + } } else { if (opts.addrOnly) { - if (cb) cb(null, ['127.0.0.1']); + if (cb) { + cb(null, ['127.0.0.1']); + } } else { - if (cb) cb(null, [{ address: '127.0.0.1', family: 4 }]); + if (cb) { + cb(null, [{ + address: '127.0.0.1', + family: 4, + }]); + } } } return; @@ -72,7 +85,9 @@ const lookup = (hostname, opts, cb) => { query: opts.query, }, (err, data) => { if (err) { - if (cb) cb(err, null, null); + if (cb) { + cb(err, null, null); + } return; } const ret = []; @@ -80,32 +95,37 @@ const lookup = (hostname, opts, cb) => { const res = data.results[i]; if (!opts.all && i === 0) { const addr = res.address.join('.'); - if (cb) cb(null, addr, 4); - return; - } else { - switch (res.record) { - case 'A': - if (opts.addrOnly) { - ret.push(res.address.join('.')); - } else { - ret.push({ - address: res.address.join('.'), - family: 4, - }); - } - break; - default: - break; + if (cb) { + cb(null, addr, 4); } + return; + } + switch (res.record) { + case 'A': + if (opts.addrOnly) { + ret.push(res.address.join('.')); + } else { + ret.push({ + address: res.address.join('.'), + family: 4, + }); + } + break; + default: + break; } } if (ret.length === 0) { - if (cb) cb(new SystemError('dns query failed', exports.NODATA, 'runtime.dns.resolve'), null); + if (cb) { + cb(new SystemError('dns query failed', exports.NODATA, 'runtime.dns.resolve'), null); + } return; } - if (cb) cb(null, ret); + if (cb) { + cb(null, ret); + } }); -}; +} exports.getServers = () => servers; @@ -140,7 +160,9 @@ exports.resolve = (hostname, rrtypeOpt, cbOpt) => { cb = rrtype; rrtype = null; } - if (typeof rrtype === 'undefined' || rrtype === null) rrtype = 'A'; + if (typeof rrtype === 'undefined' || rrtype === null) { + rrtype = 'A'; + } if (rrtype === 'A') { return exports.resolve4(hostname, cb); } else if (rrtype === 'AAAA') { diff --git a/js/modules/errors.js b/js/modules/errors.js index 49fc53606..f1c9134b5 100644 --- a/js/modules/errors.js +++ b/js/modules/errors.js @@ -19,7 +19,9 @@ class SystemError { constructor(message, errcode, call) { let msg = ''; if (errcode) msg += `${errcode}: `; - if (message) msg += message; + if (message) { + msg += message; + } if (call) msg += `, ${call}`; const err = new Error(msg); err.code = errcode || ''; diff --git a/js/modules/fs.js b/js/modules/fs.js index 252d06233..108057ab9 100644 --- a/js/modules/fs.js +++ b/js/modules/fs.js @@ -16,12 +16,16 @@ const typeutils = require('typeutils'); const { SystemError } = require('./errors'); -const makeErrorNotFound = (path, op) => new SystemError(`no such file or directory, ${op} '${path}'`, 'ENOENT'); // eslint-disable-line max-len +function makeErrorNotFound(path, op) { + return new SystemError(`no such file or directory, ${op} '${path}'`, 'ENOENT'); +} -const normalizePath = (components) => { +function normalizePath(components) { const r = []; for (const p of components) { - if (p === '' || p === '.') continue; + if (p === '' || p === '.') { + continue; + } if (p === '..') { if (r.length > 0) { @@ -35,22 +39,28 @@ const normalizePath = (components) => { } return r; -}; +} // This function assumes current directory '/'. It is not // possible to change it. -const toAbsolutePath = (path) => { - if (typeof path !== 'string') return null; +function toAbsolutePath(path) { + if (typeof path !== 'string') { + return null; + } const parts = path.split('/'); const n = normalizePath(parts); - if (!n) return null; + if (!n) { + return null; + } return `/${n.join('/')}`; -}; +} -const readFileImpl = (fnName, path, opts) => { - if (!typeutils.isString(path)) throw new Error('path is not a string'); +function readFileImpl(fnName, path, opts) { + if (!typeutils.isString(path)) { + throw new Error('path is not a string'); + } let encoding = null; if (typeutils.isString(opts)) { @@ -60,21 +70,29 @@ const readFileImpl = (fnName, path, opts) => { } const absolute = toAbsolutePath(path); - if (!absolute) return [makeErrorNotFound(path, fnName), null]; + if (!absolute) { + return [makeErrorNotFound(path, fnName), null]; + } const buf = __SYSCALL.initrdReadFileBuffer(absolute); - if (!buf) return [makeErrorNotFound(path, fnName), null]; + if (!buf) { + return [makeErrorNotFound(path, fnName), null]; + } - if (encoding) return [null, new Buffer(buf).toString(encoding)]; + if (encoding) { + return [null, new Buffer(buf).toString(encoding)]; + } return [null, new Buffer(buf)]; -}; +} exports.readFile = (path, opts, cb) => { // const options = typeutils.isFunction(opts) ? null : opts; const callback = typeutils.isFunction(opts) ? opts : cb; - if (!typeutils.isFunction(callback)) throw new Error('callback is not a function'); + if (!typeutils.isFunction(callback)) { + throw new Error('callback is not a function'); + } const [err, buf] = readFileImpl('readFile', path, opts); setImmediate(() => callback(err, buf)); @@ -82,7 +100,9 @@ exports.readFile = (path, opts, cb) => { exports.readFileSync = (path, opts) => { const [err, buf] = readFileImpl('readFileSync', path, opts); - if (err) throw err; + if (err) { + throw err; + } return buf; }; diff --git a/js/modules/net.js b/js/modules/net.js index cb12ac1ad..c1afd17ad 100644 --- a/js/modules/net.js +++ b/js/modules/net.js @@ -17,10 +17,12 @@ const EventEmitter = require('events'); const Duplex = require('stream').Duplex; const dns = require('dns'); -const rmFromArrayByVal = (array, val) => { +function rmFromArrayByVal(array, val) { const i = array.indexOf(val); - if (i !== -1) array.splice(i, 1); -}; + if (i !== -1) { + array.splice(i, 1); + } +} class Socket extends Duplex { constructor(optsOpt, runtimeSocketOpt) { @@ -63,17 +65,23 @@ class Socket extends Duplex { } if (!port || typeof port === 'function' || port === null) { const err = new Error('Socket.connect: Must provide a port.'); - if (cb) cb(err); + if (cb) { + cb(err); + } return; } host = host || 'localhost'; - if (cb) this.once('connect', cb); + if (cb) { + this.once('connect', cb); + } if (exports.isIP(host) !== 0) { this.emit('lookup', null, host, exports.isIP(host)); this._handle.open(host, parseInt(port, 10)); } else { dns.lookup(host, (err, addr, family) => { - if (err) return this.emit('lookup', err, null, null); + if (err) { + return this.emit('lookup', err, null, null); + } this.emit('lookup', null, addr, family); this._handle.open(addr, parseInt(port, 10)); }); @@ -111,7 +119,9 @@ class Socket extends Duplex { _read() {} // can't force a read. do nothing. _write(chunkOpt, encoding, callback) { let chunk = chunkOpt; - if (!(chunk instanceof Buffer)) chunk = new Buffer(chunk); + if (!(chunk instanceof Buffer)) { + chunk = new Buffer(chunk); + } this._handle.send(new Uint8Array(chunk)); callback(null); } @@ -150,7 +160,9 @@ class Server extends EventEmitter { return this._connections.length; } getConnections(cb) { - if (cb) cb(null, this._connections.length); + if (cb) { + cb(null, this._connections.length); + } } listen(portOpt, hostnameOpt, backlogOpt, callbackOpt) { let options = {}; @@ -201,30 +213,50 @@ exports.createServer = (optsOpt = {}, cbOpt) => { opts = {}; } const server = new Server(); - if (cb) server.on('connection', cb); + if (cb) { + server.on('connection', cb); + } return server; }; exports.isIPv4 = (ip) => { const arr = ip.split('.'); - if (arr.length !== 4) return false; + if (arr.length !== 4) { + return false; + } // check if it contains non-number characters or exceeds the maximum length: - for (const item of arr) if (isNaN(parseInt(item, 10)) || item.length > 3) return false; - return true; + for (const item of arr) { + if (isNaN(parseInt(item, 10)) || item.length > 3) { + return false; + } + return true; + } }; exports.isIPv6 = (ip) => { - if (ip.length > 45) return false; + if (ip.length > 45) { + return false; + } const arr = ip.split(':'); - if (arr.length !== 6) return false; + if (arr.length !== 6) { + return false; + } // check if it contains only letters and numbers (or is empty): - for (const item of arr) if (item.search(/[a-zA-Z0-9]*/) === -1) return false; - return true; + for (const item of arr) { + if (item.search(/[a-zA-Z0-9]*/) === -1) { + return false; + } + return true; + } }; exports.isIP = (ip) => { - if (exports.isIPv4(ip)) return 4; - if (exports.isIPv6(ip)) return 6; + if (exports.isIPv4(ip)) { + return 4; + } + if (exports.isIPv6(ip)) { + return 6; + } return 0; }; diff --git a/js/modules/os.js b/js/modules/os.js index 366eb4bcc..83e66de2c 100644 --- a/js/modules/os.js +++ b/js/modules/os.js @@ -14,7 +14,10 @@ 'use strict'; const interfaces = require('../core/net/interfaces'); -const mem = () => Math.pow(2, 32); + +function mem() { + return Math.pow(2, 32); +} Object.assign(exports, { EOL: '\n', diff --git a/js/modules/process.js b/js/modules/process.js index 47220b410..536dd062a 100644 --- a/js/modules/process.js +++ b/js/modules/process.js @@ -44,8 +44,12 @@ class Process extends EventEmitter { disconnect() {}, emitWarning: (msgOpt, name = 'Warning') => { let msg = msgOpt; - if (!(msg instanceof Error)) msg = new Warning(msg, name); - if (this.listenerCount('warning') !== 0) return this.emit('warning', msg); + if (!(msg instanceof Error)) { + msg = new Warning(msg, name); + } + if (this.listenerCount('warning') !== 0) { + return this.emit('warning', msg); + } console.error(`(runtime) ${msg.name}${msg.message ? `: ${msg.message}` : ''}`); }, env: {}, diff --git a/js/service/dhcp-client/dhcp-options.js b/js/service/dhcp-client/dhcp-options.js index dc970c92d..4e1bb77e9 100644 --- a/js/service/dhcp-client/dhcp-options.js +++ b/js/service/dhcp-client/dhcp-options.js @@ -22,7 +22,9 @@ exports.OPTION_SERVER_ID = 54; exports.find = (options, id, minLength = 0) => { for (const opt of options) { - if (opt.id === id && opt.bytes.length >= minLength) return opt.bytes; + if (opt.id === id && opt.bytes.length >= minLength) { + return opt.bytes; + } } return null; }; diff --git a/js/service/dhcp-client/dhcp-packet.js b/js/service/dhcp-client/dhcp-packet.js index 63e23b2f7..e519edab7 100644 --- a/js/service/dhcp-client/dhcp-packet.js +++ b/js/service/dhcp-client/dhcp-packet.js @@ -35,7 +35,9 @@ exports.packetType = { exports.create = (type, srcMAC, options = []) => { let optionsLength = 8; // cookie (4b), type (3b) and 0xff (1b) - for (const opt of options) optionsLength += opt.bytes.length + 2; // id (1b) and len (1b) + for (const opt of options) { + optionsLength += opt.bytes.length + 2; + } // id (1b) and len (1b) const u8 = new Uint8Array(OPTIONS_OFFSET + optionsLength); u8[0] = OPERATION_REQUEST; // request @@ -61,14 +63,16 @@ exports.create = (type, srcMAC, options = []) => { // Option: DHCP Message u8[optionsOffset++] = 53; // id - u8[optionsOffset++] = 1; // len + u8[optionsOffset++] = 1; // len u8[optionsOffset++] = type; // Other options for (const option of options) { u8[optionsOffset++] = option.id; // id - u8[optionsOffset++] = option.bytes.length & 0xff; // len - for (const byte of option.bytes) u8[optionsOffset++] = byte >>> 0; + u8[optionsOffset++] = option.bytes.length & 0xff; // len + for (const byte of option.bytes) { + u8[optionsOffset++] = byte >>> 0; + } } u8[optionsOffset] = 255; // end of option list @@ -82,18 +86,22 @@ exports.getServerIP = u8 => new IP4Address(u8[20], u8[21], u8[22], u8[23]); exports.isValidMagicCookie = u8 => magicCookie === u8view.getUint32BE(u8, OPTIONS_OFFSET); exports.getOptions = (u8) => { - let i; - let j; const options = []; - for (i = OPTIONS_OFFSET + 4; i < u8.length; ++i) { + for (let i = OPTIONS_OFFSET + 4; i < u8.length; ++i) { const optId = u8[i++]; const optLen = u8[i++]; - if (optId === 0xff) break; - if (optId === 0x00) continue; + if (optId === 0xff) { + break; + } + if (optId === 0x00) { + continue; + } const bytes = []; - for (j = 0; j < optLen; ++j) bytes.push(u8[i++]); + for (let j = 0; j < optLen; ++j) { + bytes.push(u8[i++]); + } options.push({ id: optId, diff --git a/js/service/dhcp-client/index.js b/js/service/dhcp-client/index.js index 4d6c573f0..e84fd6cd2 100644 --- a/js/service/dhcp-client/index.js +++ b/js/service/dhcp-client/index.js @@ -24,7 +24,7 @@ const STATE_REQUEST_SENT = 2; const STATE_ACK_RECEIVED = 2; // const STATE_ERROR = 3; -const sendPacket = (socket, srcMAC, type, serverIP, yourIP) => { +function sendPacket(socket, srcMAC, type, serverIP, yourIP) { // Request info option const opt55 = { id: 55, @@ -37,8 +37,14 @@ const sendPacket = (socket, srcMAC, type, serverIP, yourIP) => { let options; if (serverIP && yourIP) { - const opt54 = { id: 54, bytes: [serverIP.a, serverIP.b, serverIP.c, serverIP.d] }; - const opt50 = { id: 50, bytes: [yourIP.a, yourIP.b, yourIP.c, yourIP.d] }; + const opt54 = { + id: 54, + bytes: [serverIP.a, serverIP.b, serverIP.c, serverIP.d], + }; + const opt50 = { + id: 50, + bytes: [yourIP.a, yourIP.b, yourIP.c, yourIP.d], + }; options = [opt55, opt54, opt50]; } else { options = [opt55]; @@ -46,46 +52,56 @@ const sendPacket = (socket, srcMAC, type, serverIP, yourIP) => { const u8 = dhcpPacket.create(type, srcMAC, options); socket.send(IP4Address.BROADCAST, 67, u8); -}; +} -const checkPacket = (u8) => { +function checkPacket(u8) { const op = dhcpPacket.getOperation(u8); - if (op !== dhcpPacket.OPERATION_RESPONSE) return false; - if (!dhcpPacket.isValidMagicCookie(u8)) return false; + if (op !== dhcpPacket.OPERATION_RESPONSE) { + return false; + } + if (!dhcpPacket.isValidMagicCookie(u8)) { + return false; + } return true; -}; +} -const optionToIP = (options, id) => { +function optionToIP(options, id) { const option = dhcpOptions.find(options, id, 4); - if (!option) return IP4Address.ANY; + if (!option) { + return IP4Address.ANY; + } return new IP4Address(option[0], option[1], option[2], option[3]); -}; +} -const optionToIPsArray = (options, id) => { +function optionToIPsArray(options, id) { const selected = dhcpOptions.findAll(options, id, 4); const result = []; - for (const sel of selected) result.push(new IP4Address(sel[0], sel[1], sel[2], sel[3])); + for (const sel of selected) { + result.push(new IP4Address(sel[0], sel[1], sel[2], sel[3])); + } return result; -}; +} -const dhcpConfigure = (intf, cb) => { +function dhcpConfigure(intf, cb) { const macAddress = intf.getMACAddress(); const socket = new runtime.net.UDPSocket(); let clientState = STATE_IDLE; - const handleOffer = (serverIP, yourIP, options) => { + function handleOffer(serverIP, yourIP, options) { let serverId = optionToIP(options, dhcpOptions.OPTION_SERVER_ID); - if (serverId.isAny()) serverId = serverIP; + if (serverId.isAny()) { + serverId = serverIP; + } sendPacket(socket, macAddress, dhcpPacket.packetType.REQUEST, serverId, yourIP); clientState = STATE_REQUEST_SENT; - }; + } - const handleAck = (serverIP, yourIP, options) => { + function handleAck(serverIP, yourIP, options) { clientState = STATE_ACK_RECEIVED; return cb({ @@ -94,20 +110,24 @@ const dhcpConfigure = (intf, cb) => { routers: optionToIPsArray(options, dhcpOptions.OPTION_ROUTER), dns: optionToIPsArray(options, dhcpOptions.OPTION_DOMAIN), }); - }; + } - const parseMessage = (serverIP, u8) => { - if (!checkPacket(u8)) return; + function parseMessage(serverIP, u8) { + if (!checkPacket(u8)) { + return; + } const options = dhcpPacket.getOptions(u8); const messageTypeOption = dhcpOptions.find(options, dhcpOptions.OPTION_MESSAGE_TYPE, 1); - if (!messageTypeOption) return; + if (!messageTypeOption) { + return; + } const messageType = messageTypeOption[0]; const yourIP = dhcpPacket.getYourIP(u8); - // debug('GOT response', messageType, JSON.stringify(options)); + // debug('GOT response', messageType, JSON.stringify(options)); if (clientState === STATE_DISCOVER_SENT && messageType === dhcpPacket.packetType.OFFER) { handleOffer(serverIP, yourIP, options); @@ -118,12 +138,12 @@ const dhcpConfigure = (intf, cb) => { handleAck(serverIP, yourIP, options); return; } - }; + } - /* const err = (e) => { - clientState = STATE_ERROR; - debug(e.stack); - }; */ +/* function err(e) { + clientState = STATE_ERROR; + debug(e.stack); +}; */ socket.onmessage = (ip, port, u8) => { debug('CLIENT OK', ip, port, u8); @@ -133,7 +153,7 @@ const dhcpConfigure = (intf, cb) => { socket.bindToInterface(intf, 68); sendPacket(socket, macAddress, dhcpPacket.packetType.DISCOVER, null, null); clientState = STATE_DISCOVER_SENT; -}; +} runtime.net.onInterfaceAdded.add((intf) => { debug('intf add'); diff --git a/js/service/shell/index.js b/js/service/shell/index.js index 0247b0179..30ed9ed66 100644 --- a/js/service/shell/index.js +++ b/js/service/shell/index.js @@ -41,10 +41,12 @@ exports.runCommand = (name, args, done) => { const stringargs = opts.args.join(' '); opts.stdio = opts.stdio || runtime.stdio.defaultStdio; - commands.get(name)(stringargs, { stdio: opts.stdio }, done); + commands.get(name)(stringargs, { + stdio: opts.stdio, + }, done); }; -const prompt = () => { +function prompt() { stdio.setColor('yellow'); stdio.write('$'); stdio.setColor('white'); @@ -61,7 +63,9 @@ const prompt = () => { name = text; } - if (!name) return prompt(); + if (!name) { + return prompt(); + } if (commands.has(name)) { return exports.runCommand(name, args.substr(1).split(' '), (rescode) => { @@ -69,7 +73,9 @@ const prompt = () => { stdio.write('\n'); // Since 0 == false and other numbers == true, just check for true. - if (rescode) printx = true; + if (rescode) { + printx = true; + } if (printx) { stdio.setColor('red'); @@ -84,6 +90,6 @@ const prompt = () => { stdio.writeLine(`Command '${name}' not found.`); prompt(); }); -}; +} prompt(); diff --git a/js/test/unit/buffers/physical-address.js b/js/test/unit/buffers/physical-address.js index 0f0c9aedd..195184a06 100644 --- a/js/test/unit/buffers/physical-address.js +++ b/js/test/unit/buffers/physical-address.js @@ -20,7 +20,9 @@ test('buffer crosses page boundary', (t) => { // allocate on page boundary const buf = resources.memoryRange.block(0x3200000 - 12, 24).buffer(); const u8 = new Uint8Array(buf); - for (let i = 0; i < u8.length; i++) u8[i] = i; + for (let i = 0; i < u8.length; i++) { + u8[i] = i; + } const addr = __SYSCALL.bufferAddress(u8); const b1 = u8.subarray(0, addr[0]); @@ -35,7 +37,9 @@ test('buffer crosses page boundary', (t) => { test('buffer does not cross page boundary', (t) => { const buf = resources.memoryRange.block(0x3200000, 24).buffer(); const u8 = new Uint8Array(buf); - for (let i = 0; i < u8.length; i++) u8[i] = i; + for (let i = 0; i < u8.length; i++) { + u8[i] = i; + } const addr = __SYSCALL.bufferAddress(u8); const b1 = u8.subarray(0, addr[0]); diff --git a/js/test/unit/index.js b/js/test/unit/index.js index 3030241b8..0484ecee6 100644 --- a/js/test/unit/index.js +++ b/js/test/unit/index.js @@ -20,7 +20,9 @@ const { shutdown } = require('../../').machine; stream.on('data', (vOpt) => { let v = vOpt; - if (v[v.length - 1] === '\n') v = v.slice(0, -1); + if (v[v.length - 1] === '\n') { + v = v.slice(0, -1); + } console.log(v); }); diff --git a/js/test/unit/lib/buffer-builder.js b/js/test/unit/lib/buffer-builder.js index fa6b7d232..47516084f 100644 --- a/js/test/unit/lib/buffer-builder.js +++ b/js/test/unit/lib/buffer-builder.js @@ -70,12 +70,16 @@ class BufferBuilder { } align(alignment = 0, value = 0) { - while ((this._p.length % alignment) !== 0) this.uint8(value); + while ((this._p.length % alignment) !== 0) { + this.uint8(value); + } return this; } array(u8) { - for (const item of u8) this.uint8(item & 0xff); + for (const item of u8) { + this.uint8(item & 0xff); + } this._repeatFirst = this._p.length - u8.length; this._repeatLast = this._p.length; return this; @@ -93,7 +97,9 @@ class BufferBuilder { buffer() { const buf = new Uint8Array(this._p); if (this._ck) { - if (this._checksumLast === 0) this._checksumLast = this._p.length; + if (this._checksumLast === 0) { + this._checksumLast = this._p.length; + } const sub = buf.subarray(this._checksumFirst, this._checksumLast); const cksum = this._ck(sub); buf[this._checksumOffset] = (cksum >>> 8) & 0xff; diff --git a/js/test/unit/lib/packet-builder.js b/js/test/unit/lib/packet-builder.js index 0ea078cb6..7d5155dd8 100644 --- a/js/test/unit/lib/packet-builder.js +++ b/js/test/unit/lib/packet-builder.js @@ -19,7 +19,9 @@ const IP4Address = require('../../../core/net/ip4-address'); const MACAddress = require('../../../core/net/mac-address'); const checksum = require('../../../core/net/checksum'); -const cksum = u8 => checksum(u8, 0, u8.length, 0); +function cksum(u8) { + return checksum(u8, 0, u8.length, 0); +} exports.createEthernetIP4 = (protocol, payload, opts = {}) => { const srcIP = IP4Address.parse(opts.srcIP) || new IP4Address(127, 0, 0, 1); @@ -40,48 +42,59 @@ exports.createEthernetIP4 = (protocol, payload, opts = {}) => { throw new Error(`invalid fragment offset ${fragmentOffsetBytes} byte(s)`); } - if (dontFragment) fragmentData |= (1 << 14); - if (moreFragments) fragmentData |= (1 << 13); + if (dontFragment) { + fragmentData |= (1 << 14); + } + if (moreFragments) { + fragmentData |= (1 << 13); + } let protocolId = 0; switch (protocol) { - case 'icmp': protocolId = 0x01; break; - case 'tcp': protocolId = 0x06; break; - case 'udp': protocolId = 0x11; break; - default: throw new Error('unknown protocol'); + case 'icmp': + protocolId = 0x01; + break; + case 'tcp': + protocolId = 0x06; + break; + case 'udp': + protocolId = 0x11; + break; + default: + throw new Error('unknown protocol'); } return new BufferBuilder() - .uint8(destMAC.a) // ethernet destMAC - .uint8(destMAC.b) // ethernet destMAC - .uint8(destMAC.c) // ethernet destMAC - .uint8(destMAC.d) // ethernet destMAC - .uint8(destMAC.e) // ethernet destMAC - .uint8(destMAC.f) // ethernet destMAC - .uint8(srcMAC.a) // ethernet srcMAC - .uint8(srcMAC.b) // ethernet srcMAC - .uint8(srcMAC.c) // ethernet srcMAC - .uint8(srcMAC.d) // ethernet srcMAC - .uint8(srcMAC.e) // ethernet srcMAC - .uint8(srcMAC.f) // ethernet srcMAC - .uint16(etherType) // ethernet etherType + .uint8(destMAC.a) // ethernet destMAC + .uint8(destMAC.b) // ethernet destMAC + .uint8(destMAC.c) // ethernet destMAC + .uint8(destMAC.d) // ethernet destMAC + .uint8(destMAC.e) // ethernet destMAC + .uint8(destMAC.f) // ethernet destMAC + .uint8(srcMAC.a) // ethernet srcMAC + .uint8(srcMAC.b) // ethernet srcMAC + .uint8(srcMAC.c) // ethernet srcMAC + .uint8(srcMAC.d) // ethernet srcMAC + .uint8(srcMAC.e) // ethernet srcMAC + .uint8(srcMAC.f) // ethernet srcMAC + .uint16(etherType) // ethernet etherType .beginChecksum() - .uint8((4 << 4) | (20 >>> 2)) // ip4 version & header length - .uint8(tos) // ip4 ToS - .uint16(payload.length) // ip4 length - .uint16(id) // ip4 ID - .uint16(fragmentData) // ip4 fragmentation - .uint8(ttl) // ip4 TTL - .uint8(protocolId) // ip4 protocol ID - .checksum(cksum) // ip4 checksum - .uint8(srcIP.a) // ip4 src ip - .uint8(srcIP.b) // ip4 src ip - .uint8(srcIP.c) // ip4 src ip - .uint8(srcIP.d) // ip4 src ip - .uint8(destIP.a) // ip4 dest ip - .uint8(destIP.b) // ip4 dest ip - .uint8(destIP.c) // ip4 dest ip - .uint8(destIP.d) // ip4 dest ip + .uint8((4 << 4) | (20 >>> 2)) // ip4 version & header length + .uint8(tos) // ip4 ToS + .uint16(payload.length) // ip4 length + .uint16(id) // ip4 ID + .uint16(fragmentData) // ip4 fragmentation + .uint8(ttl) // ip4 TTL + .uint8(protocolId) // ip4 protocol ID + .checksum(cksum) // ip4 checksum + .uint8(srcIP.a) // ip4 src ip + .uint8(srcIP.b) // ip4 src ip + .uint8(srcIP.c) // ip4 src ip + .uint8(srcIP.d) // ip4 src ip + .uint8(destIP.a) // ip4 dest ip + .uint8(destIP.b) // ip4 dest ip + .uint8(destIP.c) // ip4 dest ip + .uint8(destIP.d) // ip4 dest ip .endChecksum() .array(payload) .buffer(); @@ -95,7 +108,7 @@ exports.createUDP = (payload, opts = {}) => { .uint16(srcPort) .uint16(destPort) .uint16(payload.length) - .uint16(0) // skip checksum + .uint16(0) // skip checksum .array(payload) .buffer(); }; @@ -111,7 +124,9 @@ exports.splitBuffer = (u8Opt, chunks) => { u8 = u8.subarray(chunkLength); } - if (u8.length > 0) results.push(u8); + if (u8.length > 0) { + results.push(u8); + } return results; }; @@ -119,28 +134,42 @@ exports.splitBuffer = (u8Opt, chunks) => { exports.makeBuffer = (length, firstValueOpt = 0) => { let firstValue = firstValueOpt; const u8 = new Uint8Array(length); - for (let i = 0; i < u8.length; ++i) u8[i] = firstValue++; + for (let i = 0; i < u8.length; ++i) { + u8[i] = firstValue++; + } return u8; }; exports.buffersEqual = (a, b) => { - if (!(a instanceof Uint8Array) || !(b instanceof Uint8Array)) return false; - if (a.length !== b.length) return false; + if (!(a instanceof Uint8Array) || !(b instanceof Uint8Array)) { + return false; + } + if (a.length !== b.length) { + return false; + } - for (let i = 0; i < a.length; ++i) if (a[i] !== b[i]) return false; + for (let i = 0; i < a.length; ++i) { + if (a[i] !== b[i]) { + return false; + } - return true; + return true; + } }; exports.makeBufferSlices = (u8, slices) => { const results = []; - for (const slice of slices) results.push(u8.subarray(slice.offset, slice.offset + slice.len)); + for (const slice of slices) { + results.push(u8.subarray(slice.offset, slice.offset + slice.len)); + } return results; }; exports.createFragmentedIP4 = (optsOpt, payloadLength, slices) => { const opts = optsOpt; - if (payloadLength < 8) throw new Error('no space for udp header in fragmented buffers'); + if (payloadLength < 8) { + throw new Error('no space for udp header in fragmented buffers'); + } const dataBuffer = exports.makeBuffer(payloadLength - 8); const udp = exports.createUDP(dataBuffer, opts); diff --git a/js/test/unit/net/ip4.js b/js/test/unit/net/ip4.js index 763cc6790..6b98e2fa6 100644 --- a/js/test/unit/net/ip4.js +++ b/js/test/unit/net/ip4.js @@ -36,12 +36,17 @@ test('receive ip4 udp', (t) => { t.deepEqual(u8, new Uint8Array([1, 2, 3, 4, 5])); }; - const udp = packetBuilder.createUDP(new Uint8Array([1, 2, 3, 4, 5]), { srcPort: 999, destPort: 65432 }); - const ip4 = packetBuilder.createEthernetIP4('udp', udp, { srcIP: '33.44.55.66' }); + const udp = packetBuilder.createUDP(new Uint8Array([1, 2, 3, 4, 5]), { + srcPort: 999, + destPort: 65432, + }); + const ip4 = packetBuilder.createEthernetIP4('udp', udp, { + srcIP: '33.44.55.66', + }); intf.receive(ip4); }); -const ipFragmentsTest = (t, name, length, slices, order, norecv) => { +function ipFragmentsTest(t, name, length, slices, order, norecv) { t.test(name, (t2) => { t2.timeoutAfter(1000); t2.plan(norecv ? 1 : 4); @@ -71,16 +76,25 @@ const ipFragmentsTest = (t, name, length, slices, order, norecv) => { t2.equal(intf.fragments.size, 0); } }); -}; +} test('receive ip4 fragmented non overlapped', (t) => { - const slices = [ - { offset: 0, len: 8 }, - { offset: 8, len: 8 }, - { offset: 16, len: 16 }, - { offset: 32, len: 16 }, - { offset: 48, len: 24 }, - ]; + const slices = [{ + offset: 0, + len: 8, + }, { + offset: 8, + len: 8, + }, { + offset: 16, + len: 16, + }, { + offset: 32, + len: 16, + }, { + offset: 48, + len: 24, + }]; ipFragmentsTest(t, 'normal ordered', 64, slices, [0, 1, 2, 3, 4]); ipFragmentsTest(t, 'reverse ordered', 64, slices, [4, 3, 2, 1, 0]); ipFragmentsTest(t, 'mixed ordered', 64, slices, [2, 1, 4, 0, 3]); @@ -90,13 +104,22 @@ test('receive ip4 fragmented non overlapped', (t) => { }); test('receive ip4 fragmented overlapped fragments', (t) => { - const slices = [ - { offset: 0, len: 8 }, - { offset: 8, len: 8 }, - { offset: 16, len: 16 }, - { offset: 24, len: 16 }, - { offset: 24, len: 48 }, - ]; + const slices = [{ + offset: 0, + len: 8, + }, { + offset: 8, + len: 8, + }, { + offset: 16, + len: 16, + }, { + offset: 24, + len: 16, + }, { + offset: 24, + len: 48, + }]; ipFragmentsTest(t, 'fragments left edge overlap', 64, slices, [0, 1, 2, 3, 4]); ipFragmentsTest(t, 'fragments full and right edge overlap', 64, slices, [4, 3, 2, 1, 0]); ipFragmentsTest(t, 'mixed ordered (fragment 3 is unnecessary)', 64, slices, [2, 1, 4, 0]); @@ -108,16 +131,42 @@ test('receive ip4 fragmented overlapped fragments', (t) => { }); test('receive ip4 fragmented overlapped fragments ladder 1', (t) => { - const slices = [ - { offset: 8, len: 64 }, // [ ========] - { offset: 16, len: 56 }, // [ =======] - { offset: 24, len: 48 }, // [ ======] - { offset: 32, len: 40 }, // [ =====] - { offset: 40, len: 32 }, // [ ====] - { offset: 48, len: 24 }, // [ ===] - { offset: 56, len: 16 }, // [ ==] - { offset: 64, len: 8 }, // [ =] - { offset: 0, len: 8 }, // [= ] (last piece) + const slices = [{ + offset: 8, + len: 64, + }, // [ ========] + { + offset: 16, + len: 56, + }, // [ =======] + { + offset: 24, + len: 48, + }, // [ ======] + { + offset: 32, + len: 40, + }, // [ =====] + { + offset: 40, + len: 32, + }, // [ ====] + { + offset: 48, + len: 24, + }, // [ ===] + { + offset: 56, + len: 16, + }, // [ ==] + { + offset: 64, + len: 8, + }, // [ =] + { + offset: 0, + len: 8, + }, // [= ] (last piece) ]; ipFragmentsTest(t, 'normal order', 64, slices, [0, 1, 2, 3, 4, 5, 6, 7, 8]); ipFragmentsTest(t, 'reverse order except last', 64, slices, [7, 6, 5, 4, 3, 2, 1, 0, 8]); @@ -129,16 +178,42 @@ test('receive ip4 fragmented overlapped fragments ladder 1', (t) => { }); test('receive ip4 fragmented overlapped fragments ladder 2', (t) => { - const slices = [ - { offset: 0, len: 64 }, // [======== ] - { offset: 0, len: 56 }, // [======= ] - { offset: 0, len: 48 }, // [====== ] - { offset: 0, len: 40 }, // [===== ] - { offset: 0, len: 32 }, // [==== ] - { offset: 0, len: 24 }, // [=== ] - { offset: 0, len: 16 }, // [== ] - { offset: 0, len: 8 }, // [= ] - { offset: 64, len: 8 }, // [ =] (last piece) + const slices = [{ + offset: 0, + len: 64, + }, // [======== ] + { + offset: 0, + len: 56, + }, // [======= ] + { + offset: 0, + len: 48, + }, // [====== ] + { + offset: 0, + len: 40, + }, // [===== ] + { + offset: 0, + len: 32, + }, // [==== ] + { + offset: 0, + len: 24, + }, // [=== ] + { + offset: 0, + len: 16, + }, // [== ] + { + offset: 0, + len: 8, + }, // [= ] + { + offset: 64, + len: 8, + }, // [ =] (last piece) ]; ipFragmentsTest(t, 'normal order', 64, slices, [0, 1, 2, 3, 4, 5, 6, 7, 8]); ipFragmentsTest(t, 'reverse order except last', 64, slices, [7, 6, 5, 4, 3, 2, 1, 0, 8]); @@ -150,13 +225,30 @@ test('receive ip4 fragmented overlapped fragments ladder 2', (t) => { }); test('receive ip4 fragmented overlapped fragments pyramid', (t) => { - const slices = [ - { offset: 8, len: 56 }, // [ ======= ] - { offset: 16, len: 40 }, // [ ===== ] - { offset: 24, len: 24 }, // [ === ] - { offset: 32, len: 8 }, // [ = ] - { offset: 64, len: 8 }, // [ =] - { offset: 0, len: 8 }, // [= ] + const slices = [{ + offset: 8, + len: 56, + }, // [ ======= ] + { + offset: 16, + len: 40, + }, // [ ===== ] + { + offset: 24, + len: 24, + }, // [ === ] + { + offset: 32, + len: 8, + }, // [ = ] + { + offset: 64, + len: 8, + }, // [ =] + { + offset: 0, + len: 8, + }, // [= ] ]; ipFragmentsTest(t, 'normal order', 64, slices, [0, 1, 2, 3, 4, 5]); ipFragmentsTest(t, 'reverse order except last two 1', 64, slices, [3, 2, 1, 0, 4, 5]); @@ -167,13 +259,30 @@ test('receive ip4 fragmented overlapped fragments pyramid', (t) => { }); test('receive ip4 fragmented overlapped fragments small chunks', (t) => { - const slices = [ - { offset: 0, len: 8 }, // [= ] - { offset: 16, len: 8 }, // [ = ] - { offset: 32, len: 8 }, // [ = ] - { offset: 48, len: 8 }, // [ = ] - { offset: 64, len: 8 }, // [ =] - { offset: 8, len: 56 }, // [ ======= ] + const slices = [{ + offset: 0, + len: 8, + }, // [= ] + { + offset: 16, + len: 8, + }, // [ = ] + { + offset: 32, + len: 8, + }, // [ = ] + { + offset: 48, + len: 8, + }, // [ = ] + { + offset: 64, + len: 8, + }, // [ =] + { + offset: 8, + len: 56, + }, // [ ======= ] ]; ipFragmentsTest(t, 'normal order', 64, slices, [0, 1, 2, 3, 4, 5]); ipFragmentsTest(t, 'reverse order', 64, slices, [5, 4, 3, 2, 1, 0]); @@ -183,19 +292,25 @@ test('receive ip4 fragmented overlapped fragments small chunks', (t) => { }); test('receive ip4 fragmented max offset and size', (t) => { - const slices = [ - { offset: 0, len: 65528 }, - { offset: 65528, len: 7 }, - ]; + const slices = [{ + offset: 0, + len: 65528, + }, { + offset: 65528, + len: 7, + }]; ipFragmentsTest(t, 'max size', 65535 - 8, slices, [0, 1]); t.end(); }); test('receive ip4 fragmented too big', (t) => { - const slices = [ - { offset: 0, len: 65528 }, - { offset: 65528, len: 7 + 1 }, - ]; + const slices = [{ + offset: 0, + len: 65528, + }, { + offset: 65528, + len: 7 + 1, + }]; ipFragmentsTest(t, 'max-size + 1', (65535 - 8) + 1, slices, [0, 1], true); t.end(); }); @@ -212,7 +327,10 @@ test('too many fragment queues and timeouts', (t) => { srcPort: 999, destPort: 65432, srcIP: `33.44.55.${String(i)}`, - }, 64 + 8 /* 8 bytes udp header */, [{ offset: 0, len: 8 }]); + }, 64 + 8 /* 8 bytes udp header */, [{ + offset: 0, + len: 8, + }]); intf.receive(fragments[0]); } diff --git a/js/test/unit/net/port-allocator.js b/js/test/unit/net/port-allocator.js index fd3f0dc44..32945553e 100644 --- a/js/test/unit/net/port-allocator.js +++ b/js/test/unit/net/port-allocator.js @@ -24,7 +24,9 @@ test('ephemeral only: simple allocation', (t) => { const socket = {}; // alloc 10 ports - for (let i = 0; i < 10; ++i) t.equal(allocator.allocEphemeral(socket), EPHEMERAL_PORT_FIRST + i); + for (let i = 0; i < 10; ++i) { + t.equal(allocator.allocEphemeral(socket), EPHEMERAL_PORT_FIRST + i); + } // free first 3 ports allocator.free(EPHEMERAL_PORT_FIRST + 0); @@ -54,22 +56,30 @@ test('ephemeral only: allocate and free all ports', (t) => { let next = 0; for (;;) { const port = allocator.allocEphemeral(socket); - if (port === 0) break; + if (port === 0) { + break; + } - if (port !== EPHEMERAL_PORT_FIRST + next++) t.equal(port, EPHEMERAL_PORT_FIRST + next++); + if (port !== EPHEMERAL_PORT_FIRST + next++) { + t.equal(port, EPHEMERAL_PORT_FIRST + next++); + } } t.equal(next, 16000); t.equal(allocator.allocatedCount, 16000); - while (next-- > 0) allocator.free(((16000 - next) - 1) + EPHEMERAL_PORT_FIRST); + while (next-- > 0) { + allocator.free(((16000 - next) - 1) + EPHEMERAL_PORT_FIRST); + } t.equal(allocator.allocatedCount, 0); t.equal(allocator._sockets.length, 0); for (;;) { const port = allocator.allocEphemeral(socket); - if (port === 0) break; + if (port === 0) { + break; + } } t.equal(allocator.allocatedCount, 16000); @@ -109,11 +119,15 @@ test('directly alloc and free all ports', (t) => { const allocator = new PortAllocator(); const socket = {}; - for (let i = 1; i < 65536; ++i) allocator.allocPort(i, socket); + for (let i = 1; i < 65536; ++i) { + allocator.allocPort(i, socket); + } t.equal(allocator.allocatedCount, 65535); - for (let i = 1; i < 65536; ++i) allocator.free(i); + for (let i = 1; i < 65536; ++i) { + allocator.free(i); + } t.equal(allocator.allocatedCount, 0); t.end(); @@ -123,7 +137,9 @@ test('directly alloc all ports and try to get ephemeral', (t) => { const allocator = new PortAllocator(); const socket = {}; - for (let i = 1; i < 65536; ++i) allocator.allocPort(i, socket); + for (let i = 1; i < 65536; ++i) { + allocator.allocPort(i, socket); + } t.equal(allocator.allocatedCount, 65535); t.equal(allocator.allocEphemeral(socket), 0); @@ -142,7 +158,9 @@ test('directly alloc all ports and try to get ephemeral', (t) => { t.equal(allocator.allocEphemeral(socket), EPHEMERAL_PORT_FIRST); t.equal(allocator.allocatedCount, 65534); - for (let i = 1; i < 65536; ++i) allocator.free(i); + for (let i = 1; i < 65536; ++i) { + allocator.free(i); + } t.equal(allocator.allocatedCount, 0); t.end(); diff --git a/js/test/unit/net/tcp-receive.js b/js/test/unit/net/tcp-receive.js index 88b06fa23..6240ae998 100644 --- a/js/test/unit/net/tcp-receive.js +++ b/js/test/unit/net/tcp-receive.js @@ -14,11 +14,13 @@ 'use strict'; +/* eslint-disable comma-dangle, array-bracket-spacing */ + const test = require('tape'); // const assert = require('assert'); const TCPSocket = require('../../../core/net/tcp-socket'); -const receiveTest = (opts, cb) => { +function receiveTest(opts, cb) { const initialSequenceNumber = opts.initialSequenceNumber; const bufs = opts.bufs; @@ -30,7 +32,9 @@ const receiveTest = (opts, cb) => { const seqOffset = bufs[i].seqOffset; const len = bufs[i].len; const maxSeq = seqOffset + len; - if (maxSeq > count) count = maxSeq; + if (maxSeq > count) { + count = maxSeq; + } } socket._transmit = () => {}; @@ -40,7 +44,9 @@ const receiveTest = (opts, cb) => { throw new Error(`invalid byte received ${u8[z]}, expected ${next}`); } - if (next === count) cb(); + if (next === count) { + cb(); + } } }; @@ -52,7 +58,9 @@ const receiveTest = (opts, cb) => { const len = bufs[i].len; const b = new Uint8Array(len); - for (let j = 0; j < len; ++j) b[j] = seqOffset + j + 1; + for (let j = 0; j < len; ++j) { + b[j] = seqOffset + j + 1; + } packets.push({ seq: (initialSequenceNumber + seqOffset) >>> 0, @@ -70,9 +78,9 @@ const receiveTest = (opts, cb) => { console.log('='.repeat(50)); throw new Error('receive queue should be empty'); } -}; +} -const receiveTestBatch = (t, seqList, bufs) => { +function receiveTestBatch(t, seqList, bufs) { t.plan(3 * seqList.length); seqList.forEach((seq) => { const reversed = bufs.slice(0); @@ -93,7 +101,7 @@ const receiveTestBatch = (t, seqList, bufs) => { bufs: shuffled, }, () => t.ok(true, `random ordered, initial sequence number ${seq}`)); }); -}; +} const sequenceNumbersList = [ 0, 1, Math.pow(2, 32) - 1, Math.pow(2, 32) - 2, Math.pow(2, 32) - 3, Math.pow(2, 32) - 9999, @@ -102,211 +110,389 @@ const sequenceNumbersList = [ test('receive fast path (small sequence numbers)', (t) => { receiveTest({ initialSequenceNumber: 1, - bufs: [ - { seqOffset: 0, len: 3 }, - { seqOffset: 3, len: 2 }, - { seqOffset: 5, len: 1 }, - ], + bufs: [{ + seqOffset: 0, + len: 3, + }, { + seqOffset: 3, + len: 2, + }, { + seqOffset: 5, + len: 1, + }, ], }, t.end.bind(t)); }); test('receive fast path (large sequence numbers) #1', (t) => { receiveTest({ initialSequenceNumber: Math.pow(2, 32) - 4, - bufs: [ - { seqOffset: 0, len: 3 }, - { seqOffset: 3, len: 2 }, - { seqOffset: 5, len: 1 }, - { seqOffset: 6, len: 4 }, - { seqOffset: 10, len: 5 }, - { seqOffset: 15, len: 1 }, - { seqOffset: 16, len: 8 }, - { seqOffset: 24, len: 1 }, - { seqOffset: 25, len: 1 }, - ], + bufs: [{ + seqOffset: 0, + len: 3, + }, { + seqOffset: 3, + len: 2, + }, { + seqOffset: 5, + len: 1, + }, { + seqOffset: 6, + len: 4, + }, { + seqOffset: 10, + len: 5, + }, { + seqOffset: 15, + len: 1, + }, { + seqOffset: 16, + len: 8, + }, { + seqOffset: 24, + len: 1, + }, { + seqOffset: 25, + len: 1, + }, ], }, t.end.bind(t)); }); test('receive fast path (large sequence numbers) #2', (t) => { receiveTest({ initialSequenceNumber: Math.pow(2, 32) - 3, - bufs: [ - { seqOffset: 0, len: 3 }, - { seqOffset: 3, len: 2 }, - { seqOffset: 5, len: 1 }, - { seqOffset: 6, len: 4 }, - ], + bufs: [{ + seqOffset: 0, + len: 3, + }, { + seqOffset: 3, + len: 2, + }, { + seqOffset: 5, + len: 1, + }, { + seqOffset: 6, + len: 4, + }, ], }, t.end.bind(t)); }); test('receive fast path (large sequence numbers) #3', (t) => { receiveTest({ initialSequenceNumber: Math.pow(2, 32) - 1, - bufs: [ - { seqOffset: 0, len: 1 }, - { seqOffset: 1, len: 2 }, - { seqOffset: 3, len: 3 }, - { seqOffset: 6, len: 4 }, - ], + bufs: [{ + seqOffset: 0, + len: 1, + }, { + seqOffset: 1, + len: 2, + }, { + seqOffset: 3, + len: 3, + }, { + seqOffset: 6, + len: 4, + }, ], }, t.end.bind(t)); }); test('receive fast path (large sequence numbers) #4', (t) => { receiveTest({ initialSequenceNumber: Math.pow(2, 32) - 1, - bufs: [ - { seqOffset: 0, len: 10 }, - { seqOffset: 10, len: 1 }, - ], + bufs: [{ + seqOffset: 0, + len: 10, + }, { + seqOffset: 10, + len: 1, + }, ], }, t.end.bind(t)); }); test('receive reverse order (small sequence numbers) #1', (t) => { receiveTest({ initialSequenceNumber: 1, - bufs: [ - { seqOffset: 0, len: 3 }, - { seqOffset: 3, len: 2 }, - { seqOffset: 5, len: 1 }, - ].reverse(), + bufs: [{ + seqOffset: 0, + len: 3, + }, { + seqOffset: 3, + len: 2, + }, { + seqOffset: 5, + len: 1, + }, ].reverse(), }, t.end.bind(t)); }); test('receive reverse order (small sequence numbers) #2', (t) => { receiveTest({ initialSequenceNumber: 1, - bufs: [ - { seqOffset: 0, len: 3 }, - { seqOffset: 3, len: 2 }, - { seqOffset: 5, len: 1 }, - { seqOffset: 6, len: 4 }, - { seqOffset: 10, len: 5 }, - { seqOffset: 15, len: 1 }, - { seqOffset: 16, len: 8 }, - { seqOffset: 24, len: 1 }, - { seqOffset: 25, len: 1 }, - ].reverse(), + bufs: [{ + seqOffset: 0, + len: 3, + }, { + seqOffset: 3, + len: 2, + }, { + seqOffset: 5, + len: 1, + }, { + seqOffset: 6, + len: 4, + }, { + seqOffset: 10, + len: 5, + }, { + seqOffset: 15, + len: 1, + }, { + seqOffset: 16, + len: 8, + }, { + seqOffset: 24, + len: 1, + }, { + seqOffset: 25, + len: 1, + }, ].reverse(), }, t.end.bind(t)); }); test('receive reverse order (large sequence numbers) #1', (t) => { receiveTest({ initialSequenceNumber: Math.pow(2, 32) - 4, - bufs: [ - { seqOffset: 0, len: 1 }, - { seqOffset: 1, len: 3 }, - { seqOffset: 4, len: 5 }, - { seqOffset: 9, len: 2 }, - ].reverse(), + bufs: [{ + seqOffset: 0, + len: 1, + }, { + seqOffset: 1, + len: 3, + }, { + seqOffset: 4, + len: 5, + }, { + seqOffset: 9, + len: 2, + }, ].reverse(), }, t.end.bind(t)); }); test('receive reverse order (large sequence numbers) #2', (t) => { receiveTest({ initialSequenceNumber: Math.pow(2, 32) - 4, - bufs: [ - { seqOffset: 0, len: 3 }, - { seqOffset: 3, len: 2 }, - { seqOffset: 5, len: 1 }, - { seqOffset: 6, len: 4 }, - { seqOffset: 10, len: 5 }, - { seqOffset: 15, len: 1 }, - { seqOffset: 16, len: 8 }, - { seqOffset: 24, len: 1 }, - { seqOffset: 25, len: 1 }, - ].reverse(), + bufs: [{ + seqOffset: 0, + len: 3, + }, { + seqOffset: 3, + len: 2, + }, { + seqOffset: 5, + len: 1, + }, { + seqOffset: 6, + len: 4, + }, { + seqOffset: 10, + len: 5, + }, { + seqOffset: 15, + len: 1, + }, { + seqOffset: 16, + len: 8, + }, { + seqOffset: 24, + len: 1, + }, { + seqOffset: 25, + len: 1, + }, ].reverse(), }, t.end.bind(t)); }); test('receive reverse order (large sequence numbers) #3', (t) => { receiveTest({ initialSequenceNumber: Math.pow(2, 32) - 3, - bufs: [ - { seqOffset: 0, len: 3 }, - { seqOffset: 3, len: 2 }, - { seqOffset: 5, len: 1 }, - { seqOffset: 6, len: 4 }, - ].reverse(), + bufs: [{ + seqOffset: 0, + len: 3, + }, { + seqOffset: 3, + len: 2, + }, { + seqOffset: 5, + len: 1, + }, { + seqOffset: 6, + len: 4, + }, ].reverse(), }, t.end.bind(t)); }); test('receive reverse order (large sequence numbers) #4', (t) => { receiveTest({ initialSequenceNumber: Math.pow(2, 32) - 1, - bufs: [ - { seqOffset: 0, len: 1 }, - { seqOffset: 1, len: 2 }, - { seqOffset: 3, len: 3 }, - { seqOffset: 6, len: 4 }, - ].reverse(), + bufs: [{ + seqOffset: 0, + len: 1, + }, { + seqOffset: 1, + len: 2, + }, { + seqOffset: 3, + len: 3, + }, { + seqOffset: 6, + len: 4, + }, ].reverse(), }, t.end.bind(t)); }); test('receive reverse order (large sequence numbers) #5', (t) => { receiveTest({ initialSequenceNumber: Math.pow(2, 32) - 1, - bufs: [ - { seqOffset: 0, len: 10 }, - { seqOffset: 10, len: 1 }, - ].reverse(), + bufs: [{ + seqOffset: 0, + len: 10, + }, { + seqOffset: 10, + len: 1, + }, ].reverse(), }, t.end.bind(t)); }); test('receive mixed fast path and reverse order', (t) => { - receiveTestBatch(t, sequenceNumbersList, [ - { seqOffset: 25, len: 1 }, - { seqOffset: 24, len: 1 }, - { seqOffset: 0, len: 3 }, - { seqOffset: 5, len: 1 }, - { seqOffset: 16, len: 8 }, - { seqOffset: 6, len: 4 }, - { seqOffset: 10, len: 5 }, - { seqOffset: 3, len: 2 }, - { seqOffset: 15, len: 1 }, - ]); + receiveTestBatch(t, sequenceNumbersList, [{ + seqOffset: 25, + len: 1, + }, { + seqOffset: 24, + len: 1, + }, { + seqOffset: 0, + len: 3, + }, { + seqOffset: 5, + len: 1, + }, { + seqOffset: 16, + len: 8, + }, { + seqOffset: 6, + len: 4, + }, { + seqOffset: 10, + len: 5, + }, { + seqOffset: 3, + len: 2, + }, { + seqOffset: 15, + len: 1, + }, ]); }); test('receive fast path duplicates', (t) => { - receiveTestBatch(t, sequenceNumbersList, [ - { seqOffset: 0, len: 1 }, - { seqOffset: 0, len: 1 }, - { seqOffset: 0, len: 1 }, - { seqOffset: 1, len: 2 }, - { seqOffset: 1, len: 2 }, - { seqOffset: 3, len: 3 }, - { seqOffset: 3, len: 3 }, - { seqOffset: 6, len: 4 }, - { seqOffset: 6, len: 4 }, - { seqOffset: 6, len: 4 }, - ]); + receiveTestBatch(t, sequenceNumbersList, [{ + seqOffset: 0, + len: 1, + }, { + seqOffset: 0, + len: 1, + }, { + seqOffset: 0, + len: 1, + }, { + seqOffset: 1, + len: 2, + }, { + seqOffset: 1, + len: 2, + }, { + seqOffset: 3, + len: 3, + }, { + seqOffset: 3, + len: 3, + }, { + seqOffset: 6, + len: 4, + }, { + seqOffset: 6, + len: 4, + }, { + seqOffset: 6, + len: 4, + }, ]); }); test('receive overlapped duplicated data', (t) => { - receiveTestBatch(t, sequenceNumbersList, [ - { seqOffset: 0, len: 8 }, - { seqOffset: 1, len: 7 }, - { seqOffset: 2, len: 6 }, - { seqOffset: 3, len: 5 }, - { seqOffset: 4, len: 4 }, - { seqOffset: 5, len: 3 }, - { seqOffset: 6, len: 2 }, - { seqOffset: 7, len: 1 }, - ]); + receiveTestBatch(t, sequenceNumbersList, [{ + seqOffset: 0, + len: 8, + }, { + seqOffset: 1, + len: 7, + }, { + seqOffset: 2, + len: 6, + }, { + seqOffset: 3, + len: 5, + }, { + seqOffset: 4, + len: 4, + }, { + seqOffset: 5, + len: 3, + }, { + seqOffset: 6, + len: 2, + }, { + seqOffset: 7, + len: 1, + }, ]); }); test('receive mixed overlapped duplicated and non-duplicated data', (t) => { - receiveTestBatch(t, sequenceNumbersList, [ - { seqOffset: 0, len: 8 }, - { seqOffset: 1, len: 7 }, - { seqOffset: 2, len: 6 }, - { seqOffset: 2, len: 6 }, - { seqOffset: 3, len: 5 }, - { seqOffset: 4, len: 4 }, - { seqOffset: 5, len: 3 }, - { seqOffset: 5, len: 3 }, - { seqOffset: 6, len: 2 }, - { seqOffset: 7, len: 1 }, - { seqOffset: 8, len: 5 }, - { seqOffset: 13, len: 2 }, - ]); + receiveTestBatch(t, sequenceNumbersList, [{ + seqOffset: 0, + len: 8, + }, { + seqOffset: 1, + len: 7, + }, { + seqOffset: 2, + len: 6, + }, { + seqOffset: 2, + len: 6, + }, { + seqOffset: 3, + len: 5, + }, { + seqOffset: 4, + len: 4, + }, { + seqOffset: 5, + len: 3, + }, { + seqOffset: 5, + len: 3, + }, { + seqOffset: 6, + len: 2, + }, { + seqOffset: 7, + len: 1, + }, { + seqOffset: 8, + len: 5, + }, { + seqOffset: 13, + len: 2, + }, ]); }); + +/* eslint-enable comma-dangle, array-bracket-spacing */ diff --git a/js/test/unit/net/tcp.js b/js/test/unit/net/tcp.js index 614d52c44..a704b6fda 100644 --- a/js/test/unit/net/tcp.js +++ b/js/test/unit/net/tcp.js @@ -24,20 +24,22 @@ const IP4Address = require('../../../core/net/ip4-address'); const tcpHeader = require('../../../core/net/tcp-header'); const tcpSocketState = require('../../../core/net/tcp-socket-state'); -const createTcpPacket = (seq, ack, flags, window = 8192, u8data = null) => { +function createTcpPacket(seq, ack, flags, window = 8192, u8data = null) { const u8 = new Uint8Array(tcpHeader.headerLength + (u8data ? u8data.length : 0)); tcpHeader.write(u8, 0, 55, 55, seq, ack, flags, window); - if (u8data) u8.set(u8data, tcpHeader.headerLength); + if (u8data) { + u8.set(u8data, tcpHeader.headerLength); + } return u8; -}; +} -const getEstablished = (cb) => { +function getEstablished(cb) { const socket = new TCPSocket(); const txSeq = 1; let rxSeq = 0; - const ACK = (seq, ack, flags, window, u8) => { + function ACK(seq, ack, flags, window, u8) { assert.equal(flags, tcpHeader.FLAG_ACK); assert.equal(u8, null); assert.equal(ack, txSeq + 1); @@ -46,9 +48,9 @@ const getEstablished = (cb) => { cb(socket, txSeq, rxSeq, () => { socket._destroy(); }); - }; + } - const SYN = (seq, ack, flags, window, u8) => { + function SYN(seq, ack, flags, window, u8) { assert.equal(flags, tcpHeader.FLAG_SYN); assert.equal(u8, null); socket._transmit = ACK; @@ -56,41 +58,46 @@ const getEstablished = (cb) => { const synack = createTcpPacket(txSeq, seq + 1, tcpHeader.FLAG_SYN | tcpHeader.FLAG_ACK); rxSeq = seq + 1; socket._receive(synack, IP4Address.ANY, 45001, 0); - }; + } assert.equal(socket._state, tcpSocketState.STATE_CLOSED); socket._transmit = SYN; socket.open('127.0.0.1', 80); -}; +} test('tcp connect', (t) => { t.plan(6); const socket = new TCPSocket(); const serverSeq = 1; - const testACK = (seq, ack, flags, window, u8) => { + function testACK(seq, ack, flags, window, u8) { t.equal(flags, tcpHeader.FLAG_ACK, 'ACK flag set'); t.equal(u8, null, 'no buffer in ACK packet'); t.equal(ack, serverSeq + 1, 'seq number is valid'); socket._destroy(); - }; + } - const testSYN = (seq, ack, flags, window, u8) => { + function testSYN(seq, ack, flags, window, u8) { t.equal(flags, tcpHeader.FLAG_SYN, 'SYN flag set'); t.equal(u8, null, 'no buffer in SYN packet'); socket._transmit = testACK; const synack = createTcpPacket(serverSeq, seq + 1, tcpHeader.FLAG_SYN | tcpHeader.FLAG_ACK); socket._receive(synack, IP4Address.ANY, 45001, 0); - }; + } t.equal(socket._state, tcpSocketState.STATE_CLOSED, 'initial state is closed'); socket._transmit = testSYN; socket.open('127.0.0.1', 80); }); -const transmitQueueItemLength = (a) => a[3]; -const transmitQueueItemBuffer = (a) => a[4]; +function transmitQueueItemLength(a) { + return a[3]; +} + +function transmitQueueItemBuffer(a) { + return a[4]; +} test('tcp transmit queue', (t) => { const socket = new TCPSocket(); @@ -176,7 +183,9 @@ test('tcp receive in order and filter full duplicates', (t) => { const data2 = new Uint8Array([4, 5, 6]); let lastAck = 0; - socket._transmit = (seq, ack) => { lastAck = ack; }; + socket._transmit = (seq, ack) => { + lastAck = ack; + }; let index = 0; socket.ondata = (u8) => { @@ -206,7 +215,9 @@ test('tcp receive partial duplicates', (t) => { const data3 = new Uint8Array([2, 3]); let lastAck = 0; - socket._transmit = (seq, ack) => { lastAck = ack; }; + socket._transmit = (seq, ack) => { + lastAck = ack; + }; let index = 0; socket.ondata = (u8) => { @@ -235,7 +246,9 @@ test('tcp receive partial duplicate with acked data and small window', (t) => { const data2 = new Uint8Array([1, 2, 3, 4, 5, 6]); let lastAck = 0; - socket._transmit = (seq, ack) => { lastAck = ack; }; + socket._transmit = (seq, ack) => { + lastAck = ack; + }; let index = 0; socket.ondata = (u8) => { @@ -260,9 +273,11 @@ test('tcp send FIN', (t) => { getEstablished((socket, txSeq, rxSeq, done) => { t.on('end', done); - const recvACK = (seq, ack, flags) => t.ok(flags & tcpHeader.FLAG_ACK); + function recvACK(seq, ack, flags) { + t.ok(flags & tcpHeader.FLAG_ACK); + } - const recvACKFIN = (seq, ack, flags) => { + function recvACKFIN(seq, ack, flags) { let packet; socket._transmit = recvACK; t.ok(flags & tcpHeader.FLAG_FIN); @@ -273,11 +288,9 @@ test('tcp send FIN', (t) => { packet = createTcpPacket(txSeq, seq + 1, tcpHeader.FLAG_FIN); socket._receive(packet, IP4Address.ANY, 45001, 0); t.equal(socket._state, tcpSocketState.STATE_TIME_WAIT); - }; + } - socket._transmit = recvACKFIN; - socket.close(); - t.equal(socket._state, tcpSocketState.STATE_TIME_WAIT); + socket._transmit = recvACKFIN; socket.close(); t.equal(socket._state, tcpSocketState.STATE_TIME_WAIT); }); }); @@ -286,18 +299,18 @@ test('tcp receive FIN', (t) => { getEstablished((socket, txSeq, rxSeq, done) => { t.on('end', done); - const onRecvFIN = (seq, ack, flags) => { + function onRecvFIN(seq, ack, flags) { socket._transmit = () => {}; t.ok(flags & tcpHeader.FLAG_ACK); - }; + } - const onSentFIN = (seq, ack, flags) => { + function onSentFIN(seq, ack, flags) { socket._transmit = () => {}; t.ok(flags & tcpHeader.FLAG_FIN); t.equal(socket._state, tcpSocketState.STATE_LAST_ACK); const packet = createTcpPacket(txSeq, seq + 1, tcpHeader.FLAG_ACK); socket._receive(packet, IP4Address.ANY, 45001, 0); - }; + } socket._transmit = onRecvFIN; const packet = createTcpPacket(txSeq, rxSeq, tcpHeader.FLAG_FIN | tcpHeader.FLAG_ACK); @@ -314,24 +327,16 @@ test('tcp receive FIN, then send more data', (t) => { getEstablished((socket, txSeq, rxSeq, done) => { t.on('end', done); - const handleLastAck = (seq, ack, flags) => { + function handleLastAck(seq, ack, flags) { socket._transmit = () => {}; t.ok(flags & tcpHeader.FLAG_FIN); t.equal(socket._state, tcpSocketState.STATE_LAST_ACK); const packet = createTcpPacket(txSeq, seq + 1, tcpHeader.FLAG_ACK); socket._receive(packet, IP4Address.ANY, 45001, 0); - }; + } - socket._transmit = () => {}; - socket.send(new Uint8Array([1, 2, 3])); - const packet = createTcpPacket(txSeq, rxSeq, tcpHeader.FLAG_FIN | tcpHeader.FLAG_ACK); - socket._receive(packet, IP4Address.ANY, 45001, 0); - t.equal(socket._state, tcpSocketState.STATE_CLOSE_WAIT); - socket.send(new Uint8Array([4, 5, 6])); - socket.send(new Uint8Array([7, 8, 9])); - socket._transmit = handleLastAck; - socket.close(); - t.equal(socket._state, tcpSocketState.STATE_CLOSED); + socket._transmit = () => {}; socket.send(new Uint8Array([1, 2, 3])); + const packet = createTcpPacket(txSeq, rxSeq, tcpHeader.FLAG_FIN | tcpHeader.FLAG_ACK); socket._receive(packet, IP4Address.ANY, 45001, 0); t.equal(socket._state, tcpSocketState.STATE_CLOSE_WAIT); socket.send(new Uint8Array([4, 5, 6])); socket.send(new Uint8Array([7, 8, 9])); socket._transmit = handleLastAck; socket.close(); t.equal(socket._state, tcpSocketState.STATE_CLOSED); }); }); @@ -359,7 +364,9 @@ test('server socket listening', (t) => { socket.listen(100); t.equal(socket.localPort, 100); - t.throws(() => { socket.localPort = 200; }); + t.throws(() => { + socket.localPort = 200; + }); t.equal(socket.localPort, 100); socket.close(); }); @@ -405,7 +412,9 @@ test('localhost echo server', (t) => { client.send(new Uint8Array([4, 5, 6])); }; client.ondata = (u8) => { - for (let i = 0; i < u8.length; ++i) t.equal(u8[i], ++recvIndex); + for (let i = 0; i < u8.length; ++i) { + t.equal(u8[i], ++recvIndex); + } if (recvIndex === 6) { client.close(); @@ -424,7 +433,9 @@ test('small sequence numbers', (t) => { let next = 0; server.onconnect = (socket) => { socket.ondata = (u8) => { - for (let i = 0; i < u8.length; ++i) t.equal(u8[i], ++next); + for (let i = 0; i < u8.length; ++i) { + t.equal(u8[i], ++next); + } }; }; @@ -452,7 +463,9 @@ test('large sequence numbers and wrap around', (t) => { let next = 0; server.onconnect = (socket) => { socket.ondata = (u8) => { - for (let i = 0; i < u8.length; ++i) t.equal(u8[i], ++next); + for (let i = 0; i < u8.length; ++i) { + t.equal(u8[i], ++next); + } }; }; diff --git a/js/test/unit/random/index.js b/js/test/unit/random/index.js index 0a5255a39..48b78496d 100644 --- a/js/test/unit/random/index.js +++ b/js/test/unit/random/index.js @@ -23,7 +23,9 @@ test('EntropySource', (t) => { const source = new EntropySource('test-source'); source.ongetbytes = (u8, cb) => { - for (let i = 0; i < u8.length; ++i) u8[i] = 0x33 + i; + for (let i = 0; i < u8.length; ++i) { + u8[i] = 0x33 + i; + } cb(); }; diff --git a/js/test/unit/timers/index.js b/js/test/unit/timers/index.js index 7d33d366d..c6fd64a8b 100644 --- a/js/test/unit/timers/index.js +++ b/js/test/unit/timers/index.js @@ -30,10 +30,12 @@ test('clearTimeout', (t) => { }); test('clearInterval', (t) => { - const timer = setInterval(() => { - t.fail('should not call callback'); - throw new Error('should not call callback'); - }, 0); + function timer() { + setInterval(() => { + t.fail('should not call callback'); + throw new Error('should not call callback'); + }, 0); + } clearInterval(timer); setTimeout(t.end.bind(t), 0); }); diff --git a/js/test/unit/virtio/index.js b/js/test/unit/virtio/index.js index ecbeb5152..8edf8343f 100644 --- a/js/test/unit/virtio/index.js +++ b/js/test/unit/virtio/index.js @@ -19,27 +19,31 @@ const mem = __SYSCALL.allocDMA(); const VRing = require('../../../driver/virtio/vring'); // const DescriptorTable = require('../../../driver/virtio/vring/descriptor-table'); -const clearBuffer = (u8) => { - for (let i = 0; i < u8.length; ++i) u8[i] = 0; -}; +function clearBuffer(u8) { + for (let i = 0; i < u8.length; ++i) { + u8[i] = 0; + } +} -const bufferWriteNumbers = (u8, value) => { - for (let i = 0; i < u8.length; ++i) u8[i] = i + value; +function bufferWriteNumbers(u8, value) { + for (let i = 0; i < u8.length; ++i) { + u8[i] = i + value; + } return u8; -}; +} -const getOnePageBuffer = (indexOpt) => { +function getOnePageBuffer(indexOpt) { const index = indexOpt | 0; const b = new Uint8Array(resources.memoryRange.block(0x2000000 + (index * 22), 22).buffer()); clearBuffer(b); return b; -}; +} -const getTwoPageBuffer = () => { +function getTwoPageBuffer() { const b = new Uint8Array(resources.memoryRange.block(0x2000000 - 12, 22).buffer()); clearBuffer(b); return b; -}; +} test('ring place one physical page buffer', (t) => { const ring = new VRing(mem, 0, 16); @@ -143,7 +147,7 @@ test('vring operation', (t) => { let devIndex = 0; let count = 0; - const devProcessAll = () => { + function devProcessAll() { const bytesWritten = 3; let descId = 0; while (devIndex < ring.availableRing.readIdx()) { @@ -152,15 +156,17 @@ test('vring operation', (t) => { --count; ++devIndex; } - }; + } - const driverProcessAll = () => { + function driverProcessAll() { ring.fetchBuffers(null); while (ring.descriptorTable.descriptorsAvailable) { - if (!ring.placeBuffers([getOnePageBuffer(0)], true)) break; + if (!ring.placeBuffers([getOnePageBuffer(0)], true)) { + break; + } ++count; } - }; + } t.equal(count, 0); for (let i = 0; i < 4; ++i) { diff --git a/js/version.js b/js/version.js index ba79ef790..c55684ad6 100644 --- a/js/version.js +++ b/js/version.js @@ -14,7 +14,9 @@ 'use strict'; -if (!global.__SYSCALL) throw new Error('error: this program requires runtime.js environment'); +if (!global.__SYSCALL) { + throw new Error('error: this program requires runtime.js environment'); +} const requiredKernelVersion = require('../runtimecorelib.json').kernelVersion; const currentKernelVersion = __SYSCALL.version().kernel; diff --git a/package.json b/package.json index 055843a90..d7959376b 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "eslint": "^3.0.1", "eslint-config-airbnb-base": "^4.0.0", "eslint-plugin-import": "^1.10.2", + "eslint-plugin-runtime-internal": "^1.0.0", "tape": "^4.0.0" }, "runtimejs": { From 0cc5b4db38b94b7aea7736274be2a9faef85c421 Mon Sep 17 00:00:00 2001 From: facekapow Date: Sun, 24 Jul 2016 22:46:52 -0400 Subject: [PATCH 19/22] Update .eslintrc --- .eslintrc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.eslintrc b/.eslintrc index 0336bf637..4d8f10ab4 100644 --- a/.eslintrc +++ b/.eslintrc @@ -25,7 +25,6 @@ rules: no-underscore-dangle: 0 global-require: 0 import/no-extraneous-dependencies: 0 - no-param-reassign: 1 no-return-assign: 1 new-cap: 1 no-console: 0 @@ -37,6 +36,10 @@ rules: - functions: false classes: true + no-paran-reassign: + - 2 + - + props: false parserOptions: ecmaVersion: 6 From dd1c074dd1c013925ea28a6ef2b20cbb87d955df Mon Sep 17 00:00:00 2001 From: facekapow Date: Sun, 24 Jul 2016 22:47:48 -0400 Subject: [PATCH 20/22] Update code-style-exceptions.md --- docs/code-style-exceptions.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/docs/code-style-exceptions.md b/docs/code-style-exceptions.md index 54c6e292e..508a42a8d 100644 --- a/docs/code-style-exceptions.md +++ b/docs/code-style-exceptions.md @@ -54,14 +54,6 @@ const demo = (myObject) => { } ``` -If you get this warning, it's ok: - -> Assignment to **property of** function parameter 'parameter-name' - -But this is not: - -> Assignment to function parameter 'parameter-name' - ## Wrapping an IIFE The invocation should be *outside* the parentheses, not inside. From 9e7368eb1bd237a7143e08b19a55060acba410c7 Mon Sep 17 00:00:00 2001 From: Face Kapow Date: Mon, 25 Jul 2016 08:31:10 -0400 Subject: [PATCH 21/22] IIFE function -> IIFE arrow function, fix style issues --- .eslintrc | 2 +- js/__loader.js | 2 +- js/core/pci/scan.js | 10 +- js/driver/virtio/net.js | 2 +- js/test/unit/net/ip4.js | 222 ++++++++++------------------------------ 5 files changed, 64 insertions(+), 174 deletions(-) diff --git a/.eslintrc b/.eslintrc index 4d8f10ab4..7bcee1db1 100644 --- a/.eslintrc +++ b/.eslintrc @@ -36,7 +36,7 @@ rules: - functions: false classes: true - no-paran-reassign: + no-param-reassign: - 2 - props: false diff --git a/js/__loader.js b/js/__loader.js index bb188d0fe..2e9ac3f60 100644 --- a/js/__loader.js +++ b/js/__loader.js @@ -216,7 +216,7 @@ } else { /* eslint-disable max-len */ evalScriptFn( - `(function(require,exports,module,__filename,__dirname){${content}})((function(m){return function(path){return m.require(path)}})(global.module),global.module.exports,global.module,global.module.filename,global.module.dirname)`, + `((require,exports,module,__filename,__dirname) => {${content}})(((m) => {return function(path){return m.require(path)}})(global.module),global.module.exports,global.module,global.module.filename,global.module.dirname)`, displayPath); /* eslint-enable max-len */ } diff --git a/js/core/pci/scan.js b/js/core/pci/scan.js index 6d8031229..19c526e8b 100644 --- a/js/core/pci/scan.js +++ b/js/core/pci/scan.js @@ -32,7 +32,7 @@ const sizeof = { UINT64: 8, }; -const pciAccessorFactory = (function (addressPort, dataPort) { +const pciAccessorFactory = ((addressPort, dataPort) => { const accessorCache = new Map(); /** @@ -391,7 +391,7 @@ function locateAcpiDevice(dev) { /** * Provides enumeration services for the whole PCI configuration space */ -const pciSpace = (function (pciAccessorFactoryArg) { +const pciSpace = ((pciAccessorFactoryArg) => { function checkDevice(bus, slot, func, fn) { const addr = { bus, @@ -443,7 +443,7 @@ const pciSpace = (function (pciAccessorFactoryArg) { /** * Service for converting PCI data codes to readable names */ -const codeNameResolver = (function () { +const codeNameResolver = (() => { const classCodes = [ 'Unclassified', 'Mass Storage Controller', @@ -699,7 +699,7 @@ class PciDevice { /** * Manages PCI devices */ -const pciManager = (function () { +const pciManager = (() => { const devicesMap = new Map(); function addressHash(address) { @@ -882,7 +882,7 @@ pciManager.each((pciDevice) => { path: '/driver/' + driverData.driver, data: driverArgs, env: {} - }).then(function() {}, function(err) { + }).then(() => {}, function(err) { isolate.log(err); }); */ diff --git a/js/driver/virtio/net.js b/js/driver/virtio/net.js index 169116f42..8ad600ec7 100644 --- a/js/driver/virtio/net.js +++ b/js/driver/virtio/net.js @@ -17,7 +17,7 @@ const VirtioDevice = require('./device'); const runtime = require('../../core'); const { MACAddress, Interface } = runtime.net; -const virtioHeader = (function () { // eslint-disable-line wrap-iife +const virtioHeader = (() => { const OFFSET_FLAGS = 0; const OFFSET_GSO_TYPE = 1; // const OFFSET_HDR_LEN = 2; diff --git a/js/test/unit/net/ip4.js b/js/test/unit/net/ip4.js index 6b98e2fa6..2eaf6430e 100644 --- a/js/test/unit/net/ip4.js +++ b/js/test/unit/net/ip4.js @@ -79,22 +79,13 @@ function ipFragmentsTest(t, name, length, slices, order, norecv) { } test('receive ip4 fragmented non overlapped', (t) => { - const slices = [{ - offset: 0, - len: 8, - }, { - offset: 8, - len: 8, - }, { - offset: 16, - len: 16, - }, { - offset: 32, - len: 16, - }, { - offset: 48, - len: 24, - }]; + const slices = [ + { offset: 0, len: 8 }, + { offset: 8, len: 8 }, + { offset: 16, len: 16 }, + { offset: 32, len: 16 }, + { offset: 48, len: 24 }, + ]; ipFragmentsTest(t, 'normal ordered', 64, slices, [0, 1, 2, 3, 4]); ipFragmentsTest(t, 'reverse ordered', 64, slices, [4, 3, 2, 1, 0]); ipFragmentsTest(t, 'mixed ordered', 64, slices, [2, 1, 4, 0, 3]); @@ -104,22 +95,13 @@ test('receive ip4 fragmented non overlapped', (t) => { }); test('receive ip4 fragmented overlapped fragments', (t) => { - const slices = [{ - offset: 0, - len: 8, - }, { - offset: 8, - len: 8, - }, { - offset: 16, - len: 16, - }, { - offset: 24, - len: 16, - }, { - offset: 24, - len: 48, - }]; + const slices = [ + { offset: 0, len: 8 }, + { offset: 8, len: 8 }, + { offset: 16, len: 16 }, + { offset: 24, len: 16 }, + { offset: 24, len: 48 }, + ]; ipFragmentsTest(t, 'fragments left edge overlap', 64, slices, [0, 1, 2, 3, 4]); ipFragmentsTest(t, 'fragments full and right edge overlap', 64, slices, [4, 3, 2, 1, 0]); ipFragmentsTest(t, 'mixed ordered (fragment 3 is unnecessary)', 64, slices, [2, 1, 4, 0]); @@ -131,42 +113,16 @@ test('receive ip4 fragmented overlapped fragments', (t) => { }); test('receive ip4 fragmented overlapped fragments ladder 1', (t) => { - const slices = [{ - offset: 8, - len: 64, - }, // [ ========] - { - offset: 16, - len: 56, - }, // [ =======] - { - offset: 24, - len: 48, - }, // [ ======] - { - offset: 32, - len: 40, - }, // [ =====] - { - offset: 40, - len: 32, - }, // [ ====] - { - offset: 48, - len: 24, - }, // [ ===] - { - offset: 56, - len: 16, - }, // [ ==] - { - offset: 64, - len: 8, - }, // [ =] - { - offset: 0, - len: 8, - }, // [= ] (last piece) + const slices = [ + { offset: 8, len: 64 }, // [ ========] + { offset: 16, len: 56 }, // [ =======] + { offset: 24, len: 48 }, // [ ======] + { offset: 32, len: 40 }, // [ =====] + { offset: 40, len: 32 }, // [ ====] + { offset: 48, len: 24 }, // [ ===] + { offset: 56, len: 16 }, // [ ==] + { offset: 64, len: 8 }, // [ =] + { offset: 0, len: 8 }, // [= ] (last piece) ]; ipFragmentsTest(t, 'normal order', 64, slices, [0, 1, 2, 3, 4, 5, 6, 7, 8]); ipFragmentsTest(t, 'reverse order except last', 64, slices, [7, 6, 5, 4, 3, 2, 1, 0, 8]); @@ -178,42 +134,16 @@ test('receive ip4 fragmented overlapped fragments ladder 1', (t) => { }); test('receive ip4 fragmented overlapped fragments ladder 2', (t) => { - const slices = [{ - offset: 0, - len: 64, - }, // [======== ] - { - offset: 0, - len: 56, - }, // [======= ] - { - offset: 0, - len: 48, - }, // [====== ] - { - offset: 0, - len: 40, - }, // [===== ] - { - offset: 0, - len: 32, - }, // [==== ] - { - offset: 0, - len: 24, - }, // [=== ] - { - offset: 0, - len: 16, - }, // [== ] - { - offset: 0, - len: 8, - }, // [= ] - { - offset: 64, - len: 8, - }, // [ =] (last piece) + const slices = [ + { offset: 0, len: 64 }, // [======== ] + { offset: 0, len: 56 }, // [======= ] + { offset: 0, len: 48 }, // [====== ] + { offset: 0, len: 40 }, // [===== ] + { offset: 0, len: 32 }, // [==== ] + { offset: 0, len: 24 }, // [=== ] + { offset: 0, len: 16 }, // [== ] + { offset: 0, len: 8 }, // [= ] + { offset: 64, len: 8 }, // [ =] (last piece) ]; ipFragmentsTest(t, 'normal order', 64, slices, [0, 1, 2, 3, 4, 5, 6, 7, 8]); ipFragmentsTest(t, 'reverse order except last', 64, slices, [7, 6, 5, 4, 3, 2, 1, 0, 8]); @@ -225,30 +155,13 @@ test('receive ip4 fragmented overlapped fragments ladder 2', (t) => { }); test('receive ip4 fragmented overlapped fragments pyramid', (t) => { - const slices = [{ - offset: 8, - len: 56, - }, // [ ======= ] - { - offset: 16, - len: 40, - }, // [ ===== ] - { - offset: 24, - len: 24, - }, // [ === ] - { - offset: 32, - len: 8, - }, // [ = ] - { - offset: 64, - len: 8, - }, // [ =] - { - offset: 0, - len: 8, - }, // [= ] + const slices = [ + { offset: 8, len: 56 }, // [ ======= ] + { offset: 16, len: 40 }, // [ ===== ] + { offset: 24, len: 24 }, // [ === ] + { offset: 32, len: 8 }, // [ = ] + { offset: 64, len: 8 }, // [ =] + { offset: 0, len: 8 }, // [= ] ]; ipFragmentsTest(t, 'normal order', 64, slices, [0, 1, 2, 3, 4, 5]); ipFragmentsTest(t, 'reverse order except last two 1', 64, slices, [3, 2, 1, 0, 4, 5]); @@ -259,30 +172,13 @@ test('receive ip4 fragmented overlapped fragments pyramid', (t) => { }); test('receive ip4 fragmented overlapped fragments small chunks', (t) => { - const slices = [{ - offset: 0, - len: 8, - }, // [= ] - { - offset: 16, - len: 8, - }, // [ = ] - { - offset: 32, - len: 8, - }, // [ = ] - { - offset: 48, - len: 8, - }, // [ = ] - { - offset: 64, - len: 8, - }, // [ =] - { - offset: 8, - len: 56, - }, // [ ======= ] + const slices = [ + { offset: 0, len: 8 }, // [= ] + { offset: 16, len: 8 }, // [ = ] + { offset: 32, len: 8 }, // [ = ] + { offset: 48, len: 8 }, // [ = ] + { offset: 64, len: 8 }, // [ =] + { offset: 8, len: 56 }, // [ ======= ] ]; ipFragmentsTest(t, 'normal order', 64, slices, [0, 1, 2, 3, 4, 5]); ipFragmentsTest(t, 'reverse order', 64, slices, [5, 4, 3, 2, 1, 0]); @@ -292,25 +188,19 @@ test('receive ip4 fragmented overlapped fragments small chunks', (t) => { }); test('receive ip4 fragmented max offset and size', (t) => { - const slices = [{ - offset: 0, - len: 65528, - }, { - offset: 65528, - len: 7, - }]; + const slices = [ + { offset: 0, len: 65528 }, + { offset: 65528, len: 7 }, + ]; ipFragmentsTest(t, 'max size', 65535 - 8, slices, [0, 1]); t.end(); }); test('receive ip4 fragmented too big', (t) => { - const slices = [{ - offset: 0, - len: 65528, - }, { - offset: 65528, - len: 7 + 1, - }]; + const slices = [ + { offset: 0, len: 65528 }, + { offset: 65528, len: 7 + 1 }, + ]; ipFragmentsTest(t, 'max-size + 1', (65535 - 8) + 1, slices, [0, 1], true); t.end(); }); From a6241b04318bc3f0f9b40744608dcae2e40c212e Mon Sep 17 00:00:00 2001 From: Face Kapow Date: Mon, 25 Jul 2016 17:12:07 -0400 Subject: [PATCH 22/22] Fix some more style --- js/test/unit/net/tcp.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/js/test/unit/net/tcp.js b/js/test/unit/net/tcp.js index a704b6fda..bfd737698 100644 --- a/js/test/unit/net/tcp.js +++ b/js/test/unit/net/tcp.js @@ -290,7 +290,9 @@ test('tcp send FIN', (t) => { t.equal(socket._state, tcpSocketState.STATE_TIME_WAIT); } - socket._transmit = recvACKFIN; socket.close(); t.equal(socket._state, tcpSocketState.STATE_TIME_WAIT); + socket._transmit = recvACKFIN; + socket.close(); + t.equal(socket._state, tcpSocketState.STATE_TIME_WAIT); }); }); @@ -335,8 +337,16 @@ test('tcp receive FIN, then send more data', (t) => { socket._receive(packet, IP4Address.ANY, 45001, 0); } - socket._transmit = () => {}; socket.send(new Uint8Array([1, 2, 3])); - const packet = createTcpPacket(txSeq, rxSeq, tcpHeader.FLAG_FIN | tcpHeader.FLAG_ACK); socket._receive(packet, IP4Address.ANY, 45001, 0); t.equal(socket._state, tcpSocketState.STATE_CLOSE_WAIT); socket.send(new Uint8Array([4, 5, 6])); socket.send(new Uint8Array([7, 8, 9])); socket._transmit = handleLastAck; socket.close(); t.equal(socket._state, tcpSocketState.STATE_CLOSED); + socket._transmit = () => {}; + socket.send(new Uint8Array([1, 2, 3])); + const packet = createTcpPacket(txSeq, rxSeq, tcpHeader.FLAG_FIN | tcpHeader.FLAG_ACK); + socket._receive(packet, IP4Address.ANY, 45001, 0); + t.equal(socket._state, tcpSocketState.STATE_CLOSE_WAIT); + socket.send(new Uint8Array([4, 5, 6])); + socket.send(new Uint8Array([7, 8, 9])); + socket._transmit = handleLastAck; + socket.close(); + t.equal(socket._state, tcpSocketState.STATE_CLOSED); }); });