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..7bcee1db1 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,55 @@ +extends: + - airbnb-base + +globals: + debug: true + __SYSCALL: true + runtime: true + +env: + es6: true + node: true + +rules: + strict: + - 2 + - 'global' + max-len: + - 1 + - + code: 100 + tabWidth: 2 + ignoreComments: true + ignoreUrls: true + consistent-return: 0 + no-underscore-dangle: 0 + global-require: 0 + import/no-extraneous-dependencies: 0 + no-return-assign: 1 + new-cap: 1 + no-console: 0 + wrap-iife: + - 2 + - 'inside' + no-use-before-define: + - 2 + - + functions: false + classes: true + no-param-reassign: + - 2 + - + props: false + +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/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..8d8aaeeaa --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,32 @@ +# Contributing to runtime.js + +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 and what the expected behavior is. + +## Cool feature request? + + * 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 (links, examples, etc.) for anyone planning to add the feature. + +## Something to improve, add, or fix? + +### 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 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)). diff --git a/docs/code-style-exceptions.md b/docs/code-style-exceptions.md new file mode 100644 index 000000000..508a42a8d --- /dev/null +++ b/docs/code-style-exceptions.md @@ -0,0 +1,71 @@ +# 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 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 +const somePrivateVarName = Symbol('somePrivateVarName'); + +class Demo { + constructor() { + this[somePrivateVarName] = 'my value'; + } + getMyPrivateVar() { + return this[somePrivateVarName]; + } +} +``` + +## Using `get` and `set` + +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 = (myObject) => { + myObject = { + someProperty: 'my value' + }; + // ... +} +``` + +## Wrapping an IIFE + +The invocation should be *outside* the parentheses, not inside. + +```js +// yes +(function() { + // ... +})(); + +// no +(function() { + +}()); +``` 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..2e9ac3f60 100644 --- a/js/__loader.js +++ b/js/__loader.js @@ -14,253 +14,238 @@ '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 = {}; - } + class Loader { + constructor(existsFileFn, readFileFn, evalScriptFn, builtins = {}, builtinsResolveFrom = '/') { + const cache = {}; + const builtinsResolveFromComponents = builtinsResolveFrom.split('/'); - 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 + "'")); + function throwError(err) { + throw err; } - // eval file - var pathComponents = resolvedPath.split('/'); - var displayPath = resolvedPath; - var cacheKey = pathComponents.join('/'); - if (cache[cacheKey]) { - return cache[cacheKey].exports; + function endsWith(str, suffix) { + return str.indexOf(suffix, str.length - suffix.length) !== -1; } - var currentModule = global.module; - var module = new Module(pathComponents); - cache[cacheKey] = module; - global.module = module; + function normalizePath(components) { + const r = []; + for (const p of components) { + if (p === '') { + if (r.length === 0) { + r.push(p); + } + continue; + } - if (endsWith(resolvedPath, '.node')) { - throwError(new Error("Native Node.js modules are not supported '" + resolvedPath + "'")); - } + if (p === '.') { + continue; + } - var content = readFileFn(resolvedPath); - if (!content) { - throwError(new Error("Cannot load module '" + resolvedPath + "'")); - } + if (p === '..') { + if (r.length > 0) { + r.pop(); + } else { + return null; + } + } else { + r.push(p); + } + } - 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); + return r; } - global.module = currentModule; - return module.exports; - }; + 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`; - function normalizePath(components) { - var r = []; - for (var i = 0; i < components.length; ++i) { - var p = components[i]; - if ('' === p) { - if (r.length === 0) { - r.push(p); - } - continue; - } + return null; + } - if ('.' === p) { - continue; + function 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; - } - function loadAsFile(path) { - if (existsFileFn(path)) { - return path; + return parsed.main || 'index.js'; } - if (existsFileFn(path + '.js')) { - return path + '.js'; - } + function 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 + '.json')) { - return path + '.json'; - } + const normalizedPath = normalizePath(path.split('/').concat(mainFile.split('/'))); + if (!normalizedPath) { + return null; + } - if (existsFileFn(path + '.node')) { - return path + '.node'; - } + const s = normalizedPath.join('/'); + const res = loadAsFile(s); + if (res) { + return res; + } - return null; - } + if (dir) { + return loadAsDirectory(s, true); + } - 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")); + return null; } - if (parsed.runtime) { - if (typeof parsed.runtime === 'string') { - return parsed.runtime; - } else { - throwError(new Error("package.json '" + packageJsonFile + "' runtime field value is invalid")); - } - } + function loadNodeModules(dirComponents, parts) { + let count = dirComponents.length; - return parsed.main || 'index.js'; - } + while (count-- > 0) { + let p = dirComponents.slice(0, count + 1); + if (p.length === 0) { + 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; - } + if (p[p.length - 1] === 'node_modules') { + continue; + } - var normalizedPath = normalizePath(path.split('/').concat(mainFile.split('/'))); - if (!normalizedPath) { - return null; - } + p.push('node_modules'); + p = p.concat(parts); - var s = normalizedPath.join('/'); - var res = loadAsFile(s); - if (res) { - return res; - } + const normalizedPath = normalizePath(p); + if (!normalizedPath) { + continue; + } + + 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; - } + function 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 loadNodeModules(resolveFrom, pathComponents); } - return null; - } + 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}'`)); + } - function resolve(module, path) { - path = String(path || ''); + // eval file + const pathComponents = resolvedPath.split('/'); + const displayPath = resolvedPath; + const cacheKey = pathComponents.join('/'); + if (cache[cacheKey]) { + return cache[cacheKey].exports; + } - var resolveFrom = module.dirComponents; + const currentModule = global.module; + module = new Module(pathComponents); + cache[cacheKey] = module; + global.module = module; - if (builtins.hasOwnProperty(path)) { - path = builtins[path]; - resolveFrom = builtinsResolveFromComponents; - } + if (endsWith(resolvedPath, '.node')) { + throwError(new Error(`Native Node.js modules are not supported '${resolvedPath}'`)); + } - var pathComponents = path.split('/'); - var firstPathComponent = pathComponents[0]; + const content = readFileFn(resolvedPath); + if (!content) throwError(new Error(`Cannot load module '${resolvedPath}'`)); - // starts with ./ ../ or / - if (firstPathComponent === '.' || - firstPathComponent === '..' || - firstPathComponent === '') { - var combinedPathComponents = (firstPathComponent === '') - ? pathComponents - : resolveFrom.concat(pathComponents); + if (endsWith(resolvedPath, '.json')) { + module.exports = JSON.parse(content); + } else { + /* eslint-disable max-len */ + evalScriptFn( + `((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 */ + } - var normalizedPath = normalizePath(combinedPathComponents); - if (!normalizedPath) { - return null; + global.module = currentModule; + return module.exports; } - - var pathStr = normalizedPath.join('/'); - var loadedPath = loadAsFile(pathStr) || loadAsDirectory(pathStr, false) || null; - return loadedPath; } - 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 => { + const files = {}; + for (const file of __SYSCALL.initrdListFiles()) { files[file] = true; - }); + } function fileExists(path) { return !!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', @@ -269,7 +254,6 @@ 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', @@ -280,11 +264,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; @@ -318,6 +301,5 @@ process.termout = new TermoutStream(); process.termerr = new TermerrStream(); loader.require('console'); - Object.assign(global, loader.require('__errors__')); loader.require('/'); })(); diff --git a/js/component/dns-client/dns-packet.js b/js/component/dns-client/dns-packet.js index 7c0d4d5b8..315465c20 100644 --- a/js/component/dns-client/dns-packet.js +++ b/js/component/dns-client/dns-packet.js @@ -13,39 +13,37 @@ // 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 -} +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 = function(domain, query) { +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]; + 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,12 +52,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) { + for (let j = 0; j < label.length; ++j) { view.setUint8(offset++, label.charCodeAt(j)); } } @@ -70,30 +67,31 @@ exports.getQuery = function(domain, query) { return u8; }; -var POINTER_VALUE = 0xc0; +const POINTER_VALUE = 0xc0; + function isPointer(value) { return (value & POINTER_VALUE) === POINTER_VALUE; } function readHostname(reader) { - var labels = []; + let labels = []; - for (var z = reader.getOffset(); z < reader.len; ++z) { - var len = reader.readUint8(); - if (0 === len) { + 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) { + let label = ''; + for (let i = 0; i < len; ++i) { label += String.fromCharCode(reader.readUint8()); } @@ -104,64 +102,79 @@ function readHostname(reader) { 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; } - 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) { + 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..4d14af1bd 100644 --- a/js/component/dns-client/index.js +++ b/js/component/dns-client/index.js @@ -13,95 +13,91 @@ // 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; +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); } - - 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; - } + if (serverPort) { + assert(isint.uint16(serverPort)); } - }; - setInterval(function() { - var requests = self._requests; + this._socket = new UDPSocket(); + this._serverIP = serverIP || new IP4Address(8, 8, 8, 8); + this._serverPort = serverPort || 53; + this._requests = []; + this._cache = {}; - for (var i = 0; i < requests.length; ++i) { - var req = requests[i]; - if (!req) { - continue; + this._socket.onmessage = (ip, port, u8) => { + const data = dnsPacket.parseResponse(u8); + if (!data) { + return; } - if (req.retry > 0) { - self._sendQuery(req.domain, req.opts.query || 'A'); - --req.retry; - } else { - req.cb(new Error('E_FAILED')); - requests[i] = null; + 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(() => { + 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; + } } - } - 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..b19000899 100644 --- a/js/component/dns-client/is-domain.js +++ b/js/component/dns-client/is-domain.js @@ -13,11 +13,10 @@ // 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) { +module.exports = (domain) => { if (!typeutils.isString(domain)) { return false; } @@ -30,15 +29,12 @@ function isDomain(domain) { return false; } - var labels = domain.split('.'); - for (var i = 0; i < labels.length; ++i) { - var label = labels[i]; + const labels = domain.split('.'); + for (const label of labels) { if (label.length < 1 || label.length > 63) { return false; } - } - - return true; -} -module.exports = isDomain; + return true; + } +}; 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/core/cmos-time.js b/js/core/cmos-time.js index dd54e53ab..691e8cb73 100644 --- a/js/core/cmos-time.js +++ b/js/core/cmos-time.js @@ -17,21 +17,21 @@ '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() { port.write8(0x0A); @@ -45,13 +45,13 @@ function getRTCRegister(reg) { // 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); @@ -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); @@ -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/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/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..96739eeb8 100644 --- a/js/core/net/arp-resolver.js +++ b/js/core/net/arp-resolver.js @@ -13,55 +13,54 @@ // 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..c92cd89f7 100644 --- a/js/core/net/checksum.js +++ b/js/core/net/checksum.js @@ -15,14 +15,14 @@ '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 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; + acc += u8[offset + (count * 2)] << 8; } acc = (acc & 0xffff) + (acc >>> 16); @@ -32,22 +32,22 @@ function checksum(u8, offset, len, extraSum) { 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; + 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..f9b637c4d 100644 --- a/js/core/net/icmp.js +++ b/js/core/net/icmp.js @@ -14,45 +14,45 @@ '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; } - 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)); + 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); + 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..a8eff5cf1 100644 --- a/js/core/net/index.js +++ b/js/core/net/index.js @@ -13,22 +13,22 @@ // 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) { assert(intf instanceof Interface); diff --git a/js/core/net/interface.js b/js/core/net/interface.js index e374936e8..c143ae60c 100644 --- a/js/core/net/interface.js +++ b/js/core/net/interface.js @@ -13,115 +13,111 @@ // 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; + setNetworkEnabled(value) { + assert(typeutils.isBoolean(value)); + if (this.isNetworkEnabled === value) { + return; + } - 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 + 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; + } + 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; + } -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; + debug('receive called', etherType.toString(16)); + } + sendRaw(u8) { + ++stat.transmitCount; + if (this.ontransmit) { + this.ontransmit(u8, null); } - } else { - targetMAC = MACAddress.ZERO; } + 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..7b31ad15c 100644 --- a/js/core/net/interfaces.js +++ b/js/core/net/interfaces.js @@ -13,31 +13,21 @@ // 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..0e0a5d0c0 100644 --- a/js/core/net/ip4-address.js +++ b/js/core/net/ip4-address.js @@ -14,74 +14,66 @@ '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; } + 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; + } - 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) { + const p = str.trim().split('.'); + if (p.length !== 4) { return null; } - a[i] = v; + 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; + } + + return new IP4Address(a[0], a[1], a[2], a[3]); } +} - return new IP4Address(a[0], a[1], a[2], a[3]); -}; +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 451c1202c..992c90580 100644 --- a/js/core/net/ip4-fragments.js +++ b/js/core/net/ip4-fragments.js @@ -14,73 +14,70 @@ '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; +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; function fragmentHash(srcIP, destIP, protocolId, packetId) { - return srcIP.toInteger() + '-' + destIP.toInteger() + '-' + (packetId + (protocolId << 16)); + return `${srcIP.toInteger()}-${destIP.toInteger()}-${(packetId + (protocolId << 16))}`; } function dropFragmentQueue(intf, hash) { - intf.fragments.delete(hash); + return 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; +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; - var hash = fragmentHash(srcIP, destIP, packetId, protocolId); + const hash = fragmentHash(srcIP, destIP, packetId, protocolId); - var firstFragment = false; - var fragmentQueue = intf.fragments.get(hash); + let firstFragment = false; + let fragmentQueue = intf.fragments.get(hash); if (!fragmentQueue) { if (intf.fragments.size >= FRAGMENT_QUEUE_MAX_COUNT) { - // too many fragment queues return; - } + } // too many fragment queues firstFragment = true; fragmentQueue = { receivedLength: 0, totalLength: 0, createdAt: timeNow(), - fragments: [] + fragments: [], }; } - var fragmentLength = u8.length - nextOffset; + const fragmentLength = u8.length - nextOffset; if (fragmentLength <= 0) { return; } - var fragmentEnd = fragmentOffset + fragmentLength; - + 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]; + 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 @@ -103,18 +100,17 @@ exports.addFragment = function(intf, u8, headerOffset, fragmentOffset, isMoreFra // 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]; + 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 +118,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,13 +133,10 @@ exports.addFragment = function(intf, u8, headerOffset, fragmentOffset, isMoreFra // Last fragment? if (!isMoreFragments) { - // Another last fragment? if (fragmentQueue.totalLength > fragmentEnd) { - // Wrong len return; - } - + } // Wrong len fragmentQueue.totalLength = fragmentEnd; } @@ -152,17 +145,16 @@ exports.addFragment = function(intf, u8, headerOffset, fragmentOffset, isMoreFra } 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]; + const u8asm = new Uint8Array(fragmentQueue.totalLength); + for (const fragment of fragmentQueue.fragments) { if (!fragment) { continue; } - var itemOffset = fragment[0]; - var itemLength = fragment[1]; - var itemNextOffset = fragment[2]; - var itemBuffer = fragment[3]; + 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,12 +169,12 @@ exports.addFragment = function(intf, u8, headerOffset, fragmentOffset, isMoreFra * * @param {Interface} intf Network interface */ -exports.tick = function(intf) { - var time = timeNow(); +exports.tick = (intf) => { + const time = timeNow(); - for (var pair of intf.fragments) { - var hash = pair[0]; - var fragmentQueue = pair[1]; + 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..6f9e1502e 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 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..2817d878b 100644 --- a/js/core/net/mac-address.js +++ b/js/core/net/mac-address.js @@ -14,59 +14,54 @@ '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); + 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; +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; } + static parse(str) { + if (str instanceof MACAddress) { + return str; + } + if (typeof str !== 'string') { + return null; + } - 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) { + const p = str.trim().split(':'); + if (p.length !== 6) { return null; } - a[i] = v; + 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; + } + + 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]); -}; +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 35509effc..1cbe14c2e 100644 --- a/js/core/net/net-error.js +++ b/js/core/net/net-error.js @@ -14,12 +14,18 @@ '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..1cbdb667d 100644 --- a/js/core/net/ping.js +++ b/js/core/net/ping.js @@ -14,24 +14,24 @@ '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(); +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(); function createPingBuffer(size) { - var u8 = new Uint8Array(size); - for (var i = 0; i < size; ++i) { - u8[i] = 0x61 + (i % 26); // ASCII a-z - } + 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,17 +46,17 @@ 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++; + 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; } @@ -64,8 +64,8 @@ class Ping { 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,12 +73,12 @@ class Ping { } _receive(srcIP, seq, u8, dataOffset) { - var dataLength = u8.length - dataOffset; + const dataLength = u8.length - dataOffset; if (dataLength !== this._data.length) { return; } - for (var i = 0, l = dataLength; i < l; ++i) { + for (let i = 0, l = dataLength; i < l; ++i) { if (u8[dataOffset + i] !== this._data[i]) { return; } diff --git a/js/core/net/port-allocator.js b/js/core/net/port-allocator.js index e113eecf9..15b2c9884 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; @@ -70,8 +70,7 @@ class PortAllocator { if (this.lookup(port)) { return false; } - - if (null === this._map) { + if (this._map === null) { this._map = new Map(); } @@ -83,7 +82,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,12 +94,12 @@ class PortAllocator { } if (this.isEphemeralRange(port)) { - var index = port - EPHEMERAL_PORT_FIRST; + const index = port - EPHEMERAL_PORT_FIRST; if (index >= this._sockets.length) { return; } - if (null === this._sockets[index]) { + if (this._sockets[index] === null) { return; } @@ -109,7 +108,7 @@ class PortAllocator { this._searchStart = index; } --this._allocated; - if (0 === this._allocated) { + if (this._allocated === 0) { this._sockets = []; this._searchStart = 0; } @@ -117,16 +116,15 @@ class PortAllocator { } lookup(port) { - if ((null !== this._map) && this._map.has(port)) { + if ((this._map !== null) && this._map.has(port)) { return this._map.get(port); } if (this.isEphemeralRange(port)) { - var index = port - EPHEMERAL_PORT_FIRST; + 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..5fbe7f86f 100644 --- a/js/core/net/route.js +++ b/js/core/net/route.js @@ -13,40 +13,36 @@ // 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.addDefault = function(gateway, intf) { - table.push(new Entry(IP4Address.ANY, IP4Address.ANY, gateway, intf)); -}; +exports.addSubnet = (ip, mask, gateway, intf) => table.push(new Entry(ip, mask, 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]; +exports.addDefault = (gateway, intf) => table.push(new Entry(IP4Address.ANY, IP4Address.ANY, gateway, intf)); +exports.lookup = (destIP, intf) => { + let result = null; + let maxMaskBits = 0; + for (const entry of table) { if (intf && entry.intf !== intf) { continue; } 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..939f3d55d 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,31 +23,15 @@ 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; @@ -55,7 +39,6 @@ class TCPServerSocket { 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..9fbcb3494 100644 --- a/js/core/net/tcp-socket-state.js +++ b/js/core/net/tcp-socket-state.js @@ -13,6 +13,7 @@ // limitations under the License. 'use strict'; + exports.STATE_CLOSED = 0; exports.STATE_LISTEN = 1; exports.STATE_SYN_SENT = 2; diff --git a/js/core/net/tcp-socket.js b/js/core/net/tcp-socket.js index 0f660dd5c..901dbde20 100644 --- a/js/core/net/tcp-socket.js +++ b/js/core/net/tcp-socket.js @@ -12,41 +12,48 @@ // 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(); + +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 */ class TCPSocket { constructor() { @@ -92,33 +99,46 @@ 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) { - 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'; - } - } - - open(ip, port) { + 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(ipOpt, port) { + let ip = ipOpt; if (typeutils.isString(ip)) { ip = IP4Address.parse(ip); } @@ -133,13 +153,11 @@ class TCPSocket { tcpTimer.addConnectionSocket(this); } - suspend() { - } + suspend() {} + resume() {} - resume() { - } - - _listen(port) { + _listen(portOpt) { + let port = portOpt; if (!port) { port = ports.allocEphemeral(this); } else { @@ -157,7 +175,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 = []; @@ -167,24 +185,23 @@ 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() { - var intf = this._intf || null; - var viaIP; + let intf = this._intf || null; if (this._destIP.isBroadcast()) { return false; } - var routingEntry = route.lookup(this._destIP, intf); + const routingEntry = route.lookup(this._destIP, intf); if (!routingEntry) { return false; } - viaIP = routingEntry.gateway; + const viaIP = routingEntry.gateway; if (!intf) { intf = routingEntry.intf; } @@ -202,17 +219,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,14 +231,11 @@ class TCPSocket { } _emitClose() { - var onclose = this.onclose; - setImmediate(function() { - onclose(); - }); + setImmediate(() => this.onclose()); } _sendSYN(isAck) { - var flags = tcpHeader.FLAG_SYN; + let flags = tcpHeader.FLAG_SYN; if (isAck) { flags |= tcpHeader.FLAG_ACK; } @@ -247,9 +255,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,31 +275,30 @@ class TCPSocket { } _receiveWindowIsWithin(seq, edge) { - if (0 === this._receiveWindowSize) { + if (this._receiveWindowSize === 0) { return false; } - var leftEdge = edge; - var rightEdge = SEQ_INC(edge, this._receiveWindowSize); + const leftEdge = edge; + const rightEdge = SEQ_INC(edge, this._receiveWindowSize); if (leftEdge < rightEdge) { return seq >= leftEdge && seq < rightEdge; - } else { - 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) { + if (reserved === 0) { break; } @@ -306,7 +313,7 @@ class TCPSocket { break; } - if (0 === this._bufferedAmount && this.ondrain) { + if (this._bufferedAmount === 0 && this.ondrain) { this.ondrain(); } } else { @@ -315,7 +322,6 @@ class TCPSocket { this._transmitQueue.push([0, timeNow(), position, 1, null, tcpHeader.FLAG_ACK | tcpHeader.FLAG_FIN]); ++remove; } - } while (remove-- > 0) { @@ -327,37 +333,38 @@ class TCPSocket { _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; - } - /* fall through */ - case STATE_ESTABLISHED: - case STATE_FIN_WAIT_1: - this._sendTransmitQueue(); - break; + 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; + 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(); @@ -375,22 +382,21 @@ 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(ackNumber) { - var deleteCount = 0; + _cleanupTransmitQueue() { + let deleteCount = 0; 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; @@ -427,14 +433,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); @@ -458,14 +464,14 @@ class TCPSocket { } 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); @@ -494,17 +500,17 @@ 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; + 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; } @@ -514,7 +520,7 @@ class TCPSocket { 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 +536,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; } @@ -546,9 +552,8 @@ class TCPSocket { } if (removed > 0) { - var self = this; while (removed-- > 0) { - let removedItem = this._receiveQueue.pop(); + const removedItem = this._receiveQueue.pop(); if (removedItem[2] && this.ondata) { this._emitData(removedItem[2]); } @@ -561,8 +566,8 @@ 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; @@ -570,9 +575,8 @@ class TCPSocket { if (leftEdge < rightEdge) { return seq > leftEdge && seq <= rightEdge; - } else { - return seq > leftEdge || seq <= rightEdge; } + return seq > leftEdge || seq <= rightEdge; } _acceptACK(ackNumber, windowSize) { @@ -585,85 +589,87 @@ 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 { - 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); + 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; } - } - 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) { @@ -695,3 +701,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..df8537ae8 100644 --- a/js/core/net/tcp-timer.js +++ b/js/core/net/tcp-timer.js @@ -13,14 +13,13 @@ // 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) { + for (const connSocket of connections) { connSocket._timerTick(); } - initTimeout(); } @@ -30,10 +29,5 @@ function initTimeout() { 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..866f6e680 100644 --- a/js/core/net/tcp.js +++ b/js/core/net/tcp.js @@ -13,31 +13,29 @@ // 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; + return 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); + + let socket = TCPSocket.lookupReceive(destPort); - var socket = TCPSocket.lookupReceive(destPort); if (!socket) { return; } - if (socket._state === STATE_LISTEN) { socket = connectionSocket(socket, srcIP, srcPort); } - if (!socket._intf) { socket._intf = intf; } 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..a0fe21c68 100644 --- a/js/core/net/udp-socket.js +++ b/js/core/net/udp-socket.js @@ -13,26 +13,27 @@ // 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) { + send(ipOpt, port, u8) { + let ip = ipOpt; if (typeutils.isString(ip)) { ip = IP4Address.parse(ip); } @@ -41,17 +42,14 @@ class UDPSocket { 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) { 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..3f8dafb9d 100644 --- a/js/core/net/udp.js +++ b/js/core/net/udp.js @@ -13,31 +13,27 @@ // 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 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); + 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/core/pci/index.js b/js/core/pci/index.js index 986dfd40f..254c14bd0 100644 --- a/js/core/pci/index.js +++ b/js/core/pci/index.js @@ -13,18 +13,16 @@ // 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]; + for (const pciData of scan()) { deviceList.push(new PciDevice(pciData)); } } @@ -33,16 +31,13 @@ function 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]; + for (const device of deviceList) { if (device.hasDriver()) { continue; } - if (device.vendorId !== vendorId) { continue; } - if (typeutils.isFunction(deviceId)) { if (!deviceId(device.deviceId)) { continue; @@ -59,6 +54,4 @@ function setupDeviceDriver(vendorId, deviceId, 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..19c526e8b 100644 --- a/js/core/pci/scan.js +++ b/js/core/pci/scan.js @@ -14,79 +14,175 @@ /* 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 addr = ((bus << 16) | (slot << 11) | (func << 8) | (offset & 0xfc) | 0x80000000) >>> 0; addressPort.write32(addr); } @@ -101,119 +197,124 @@ var pciAccessorFactory = (function(addressPort, dataPort) { } function dwToFieldValue(value, field) { - return ((value >>> (8 * sizeof.BYTE * field.shift)) & - field.mask) >>> 0; - } + 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. * 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)'); - } - - if (slot > 31) { - throw new Error('invalid slot value (expected 0-31)'); - } + class PciAccessor { + constructor(address) { + const bus = address.bus >>> 0; + 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 (func > 7) { - throw new Error('invalid func value (expected 0-7)'); - } + const offsetCache = new Map(); - var offsetCache = new Map(); + function 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); } - 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'); + } - 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); } - setPort(bus, slot, func, offset); - return dataPort.write16((value & 0xffff) >>> 0); - } - - function writeRaw8(offset, value) { - setPort(bus, slot, func, offset); - return dataPort.write8((value & 0xff) >>> 0); - } - - /** - * Read PCI configuration space field - */ - this.read = function __read(field) { - var value; - - if (offsetCache.has(field.offset)) { - value = offsetCache.get(field.offset); - } else { - value = readRaw32(bus, slot, func, field.offset); - offsetCache.set(field.offset, value); + function writeRaw8(offset, value) { + setPort(bus, slot, func, offset); + return dataPort.write8((value & 0xff) >>> 0); } - return dwToFieldValue(value, field); - }; + /** + * 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); + } - /** - * 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'); - } - }; + return dwToFieldValue(value, field); + }; - /** - * 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; }; + /** + * 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 = () => 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]); + 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); @@ -225,10 +326,10 @@ function locateAcpiDevice(dev) { 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,12 +337,12 @@ function locateAcpiDevice(dev) { return { bus: busId, slot: slotId, - func: funcId + func: funcId, }; } - var parentDev = dev.parent(); - if (null === parentDev) { + const parentDev = dev.parent(); + if (parentDev === null) { return null; } @@ -255,48 +356,52 @@ function locateAcpiDevice(dev) { return { bus: busId, slot: slotId, - func: funcId + func: funcId, }; } - var parentLocation = locateAcpiDevice(parentDev); - if (null === parentLocation) { + 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) { + 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) { +const pciSpace = ((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); + const addr = { + bus, + slot, + func, + }; + const pciAccessor = pciAccessorFactoryArg.get(addr); + const vendorId = pciAccessor.read(pciAccessor.fields().VENDOR_ID); - if (0xffff === vendorId) { + if (vendorId === 0xffff) { return; } @@ -304,11 +409,15 @@ var pciSpace = (function(pciAccessorFactoryArg) { } 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; + 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); @@ -316,28 +425,26 @@ var pciSpace = (function(pciAccessorFactoryArg) { } return { - eachDevice: function(fn) { - var func = 0; - - for (var bus = 0; bus < 255; ++bus) { - for (var slot = 0; slot < 32; ++slot) { + 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 +462,285 @@ 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]) { + 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 - }; +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; - var irqVector = null; - - /** - * 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; }; - - /** - * Get 16bit device ID of current device - */ - this.deviceId = function __deviceId() { return deviceId; }; - - /** - * Check if current device is a PCI-to-PCI or PCI-to-CardBus - * bridge - */ - this.isBridge = function __isBridge() { return isBridge; }; - - /** - * Get PCI device address (bus, slot and function) - */ - this.address = function __address() { return address; }; - - /** - * Get bridge secondary bus number (bus number of current bridge) - */ - this.getSecondaryBus = function __getSecondaryBus() { - if (!isBridge) { - throw new Error('device is not a bridge'); - } - - return pciAccessor.read(pciAccessor.bridgeFields().SECONDARY_BUS); - }; - - this.setCommandFlag = function __setCommandFlag(flag) { - var value = pciAccessor.read(pciAccessor.fields().COMMAND); - value |= (1 << flag) >>> 0; - pciAccessor.write(pciAccessor.fields().COMMAND, value); - }; - - /** - * Get current device IRQ vector - */ - this.getIRQVector = function __getIRQVector(vector) { - return irqVector; - }; - - /** - * 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'); - } - - irqVector = vector >>> 0; - }; - - /** - * Get interrupt pin of current device - */ - this.interruptPin = function __interruptPin() { - if (isBridge) { - throw new Error('device is a bridge'); - } - - return pciAccessor.read(pciAccessor.generalFields().INTERRUPT_PIN); - }; + const that = { + acpiDevice: null, + }; - /** - * 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); + let irqVector = null; - return { - classCode: classCode, - className: className, - subclass: subclass + /** + * Attach ACPI PCI device handle to current PCI device + */ + this.attachAcpiDevice = (acpiDevice) => { + if (that.acpiDevice !== null) { + return; + } + that.acpiDevice = acpiDevice; }; - }; - this.subsystemData = function __subsystemData() { - if (isBridge) { - throw new Error('device is a bridge'); - } + /** + * Get 16bit vendor ID of current device + */ + this.vendorId = () => vendorId; + + /** + * Get 16bit device ID of current device + */ + this.deviceId = () => deviceId; + + /** + * 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) + */ + this.address = () => address; + + /** + * 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); + }; - return { - subsystemId: pciAccessor.read(pciAccessor.generalFields().SUBSYS_ID), - subsystemVendor: pciAccessor.read(pciAccessor.generalFields().SUBSYS_VENDOR) + this.setCommandFlag = (flag) => { + let value = pciAccessor.read(pciAccessor.fields().COMMAND); + value |= (1 << flag) >>> 0; + pciAccessor.write(pciAccessor.fields().COMMAND, value); }; - }; - /** - * 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'); - } + /** + * Get current device IRQ vector + */ + this.getIRQVector = () => irqVector; + + /** + * 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; + }; - var indexValue = index >>> 0; - if (indexValue > 5) { - throw new Error('invalid BAR register index (expected 0-5)'); - } + /** + * Get interrupt pin of current device + */ + this.interruptPin = () => { + if (isBridge) { + throw new Error('device is a bridge'); + } + return pciAccessor.read(pciAccessor.generalFields().INTERRUPT_PIN); + }; - var barFlag = { - BAR_IO: 0x01, - BAR_64: 0x04 + /** + * 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), + }; }; - var barField = pciAccessor.generalFields().BAR[indexValue]; - var barAddr = pciAccessor.read(barField); - if (!barAddr) { - return null; - } + 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), + }; + }; - pciAccessor.write(barField, 0xffffffff); - var barSize = pciAccessor.read(barField); + /** + * 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'); + } - // Restore original value - pciAccessor.write(barField, barAddr >>> 0); + const indexValue = index >>> 0; + if (indexValue > 5) { + throw new Error('invalid BAR register index (expected 0-5)'); + } - if (!barSize) { - return null; - } + const barFlag = { + BAR_IO: 0x01, + BAR_64: 0x04, + }; - 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) { + const barField = pciAccessor.generalFields().BAR[indexValue]; + const barAddr = pciAccessor.read(barField); + if (!barAddr) { return null; } - // Base IO address 0 is probably an error, ignore it - if (0 === base) { - return null; - } + pciAccessor.write(barField, 0xffffffff); + const barSize = pciAccessor.read(barField); - obj = io.subrange(base, base + size - 1); - } else { - base = (barAddr & 0xfffffff0) >>> 0; - size = (((~(barSize & 0xfffffff0) >>> 0) + 1) & 0xffffffff) >>> 0; + // Restore original value + pciAccessor.write(barField, barAddr >>> 0); - if (0 === size) { + if (!barSize) { return null; } - barType = 'mem32'; - obj = memrange.block(base, size); - } + let base = 0; + let size = 0; + let barType = null; + let 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 (size === 0) { + return null; + } - if (null === barType || null === obj) { - 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; + } + + barType = 'mem32'; + obj = memrange.block(base, size); + } + + 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(); +const pciManager = (() => { + const 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); - } - 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,14 +748,14 @@ acpiDevices.forEach(function(acpiDevice) { } // Check if unable to locate ACPI device on PCI bus - if (null === address) { + 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) { + if (dev === null) { return; } @@ -685,13 +768,13 @@ acpiDevices.forEach(function(acpiDevice) { }); // Extract IRQ routing information -var busRouting = []; -acpiDevicesBuses.forEach(function(acpiDevice, bus) { - if ('undefined' === typeof acpiDevice) { +const busRouting = []; +acpiDevicesBuses.forEach((acpiDevice, bus) => { + if (typeof acpiDevice === 'undefined') { return; } - var routes = acpiDevice.getIrqRoutingTable(); + const routes = acpiDevice.getIrqRoutingTable(); if (!Array.isArray(routes)) { return; } @@ -700,29 +783,28 @@ acpiDevicesBuses.forEach(function(acpiDevice, bus) { }); // 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 ('undefined' === typeof busRouting[address.bus]) { - // No ACPI routing for this current device bridge + 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) { + if (devicePin === 0) { return; } - routing.forEach(function(route) { + routing.forEach((route) => { if (address.slot !== route.deviceId) { return; } @@ -738,37 +820,36 @@ pciManager.each(function(pciDevice) { deviceIRQ = route.irq; }); - if (null !== deviceIRQ) { + if (deviceIRQ !== null) { pciDevice.setIRQVector(deviceIRQ); } }); // Start drivers -pciManager.each(function(pciDevice) { - var vendorId = pciDevice.vendorId(); - var deviceId = pciDevice.deviceId(); - var driverData = null; +pciManager.each((pciDevice) => { + // const vendorId = pciDevice.vendorId(); + // const deviceId = pciDevice.deviceId(); + const driverData = null; - if (null === driverData || 'undefined' === typeof driverData.driver || - !driverData.enabled) { + if (driverData === null || typeof driverData.driver === 'undefined' || !driverData.enabled) { return; - } + } // eslint-disable-line max-len - var irqVector = pciDevice.getIRQVector(); - var irqObject = null; - if (null !== irqVector) { + const irqVector = pciDevice.getIRQVector(); + let irqObject = null; + if (irqVector !== null) { irqObject = irqRange.irq(irqVector); } - var argsBars = []; - for (var i = 0; i < 6; ++i) { - var bar = pciDevice.getBAR(i); - var barData = null; + const argsBars = []; + 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, }; } @@ -780,89 +861,89 @@ 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(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(); +pciManager.each((pciDevice) => { + const address = pciDevice.address(); + const vector = pciDevice.getIRQVector(); + const classData = pciDevice.classData(); - var devicePin = 0; + let devicePin = 0; if (!pciDevice.isBridge()) { devicePin = pciDevice.interruptPin(); } - var pins = ['dont use', 'A', 'B', 'C', 'D']; + const pins = ['dont use', 'A', 'B', 'C', 'D']; - 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 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 results = []; - pciManager.each(function(pciDevice) { + 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; + let devicePin = 0; if (!pciDevice.isBridge()) { devicePin = pciDevice.interruptPin(); } - var irqObject = null; - if (null !== 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,12 +952,12 @@ 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, }); }); 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/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..2f2ac3d4f 100644 --- a/js/core/random/entropy-source.js +++ b/js/core/random/entropy-source.js @@ -15,23 +15,20 @@ '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 - */ + /** + * Request randomness from this entropy source + */ getBytes(u8, cb) { 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..08ea96455 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,12 +33,11 @@ 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; +exports.getTrueRandomValues = (value, cb) => { + let u8 = null; if (typeutils.isNumber(value)) { u8 = new Uint8Array(value); } - if (value instanceof Uint8Array) { u8 = value; } @@ -46,21 +45,20 @@ exports.getTrueRandomValues = function(value, cb) { 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 - var defaultSource = getDefaultSource(); + const 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,12 +70,11 @@ 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; +exports.getRandomValues = (value) => { + let u8 = null; if (typeutils.isNumber(value)) { u8 = new Uint8Array(value); } - if (value instanceof Uint8Array) { u8 = value; } @@ -85,12 +82,11 @@ exports.getRandomValues = function(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'); } - for (var i = 0; i < u8.length; i++) { + for (let i = 0; i < u8.length; i++) { u8[i] = isaac.getByte(); } diff --git a/js/core/random/isaac-wrapper.js b/js/core/random/isaac-wrapper.js index 2f8ec0e08..5887f2fc6 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, @@ -29,6 +29,4 @@ function isaacToUint8(n) { } 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..f95743016 100644 --- a/js/core/random/js-random-source.js +++ b/js/core/random/js-random-source.js @@ -13,17 +13,17 @@ // 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++) { +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/set-time.js b/js/core/set-time.js index e4e0acadb..f9190034f 100644 --- a/js/core/set-time.js +++ b/js/core/set-time.js @@ -14,45 +14,41 @@ 'use strict'; -/* global runtime */ - -var resources = require('./resources'); -var rawip = null; - -runtime.dns.resolve('pool.ntp.org', {}, function(err, res) { - if (err) return runtime.stdio.defaultStdio.writeError(err); - - rawip = res.results[0].address; +runtime.dns.resolve('pool.ntp.org', {}, (err, res) => { + if (err) { + return runtime.stdio.defaultStdio.writeError(err); + } - 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++) { + 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 (let i = 4; i <= 7; i++) { - fractpart = 256 * fractpart + u8[offset + i]; + for (i = 4; i <= 7; i++) { + fractpart = (256 * fractpart) + u8[offset + i]; } - var milli = (intpart * 1000 + (fractpart * 1000) / 0x100000000); + const 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/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..1563030ba 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) { @@ -54,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); @@ -61,28 +63,16 @@ class StdioInterface { // Else, use onread. // Downside: no cusor moving or backspace. // TODO: Fix downside. - var text = ''; - this.onread(function 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/timers.js b/js/core/timers.js index 9c1784a4c..6139f5998 100644 --- a/js/core/timers.js +++ b/js/core/timers.js @@ -14,15 +14,15 @@ 'use strict'; -var tasks5s = []; +const tasks5s = []; -setInterval(function() { +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 +31,4 @@ setInterval(function() { * * @param {function} fn Function to run */ -exports.scheduleTask5s = function(fn) { - tasks5s.push(fn); -}; +exports.scheduleTask5s = fn => tasks5s.push(fn); 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..28c4a6e88 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,27 @@ class LineEditor { drawPrompt() { printer.print('$', 1, printer.color.YELLOW, printer.color.BLACK); printer.print(' ', 1, printer.color.WHITE, printer.color.BLACK); - }; + } drawCursor() { - var char = ' '; + 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 = ' '; + 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 +57,17 @@ 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,11 +76,11 @@ 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); @@ -88,7 +88,7 @@ class LineEditor { --this.inputPosition; this.drawCursor(); } - }; + } moveCursorLeft() { if (this.inputPosition > 0) { @@ -97,7 +97,7 @@ class LineEditor { printer.moveOffset(-1); this.drawCursor(); } - }; + } moveCursorRight() { if (this.inputPosition < this.inputText.length) { @@ -106,7 +106,7 @@ class LineEditor { printer.moveOffset(1); this.drawCursor(); } - }; + } clearInputBox() { while (this.inputPosition < this.inputText.length) { @@ -115,18 +115,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..1d96a747f 100644 --- a/js/core/tty/printer.js +++ b/js/core/tty/printer.js @@ -13,13 +13,13 @@ // 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); @@ -34,25 +34,14 @@ 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); + const text = String(textOpt); - repeat = repeat || 1; - - if (typeof fg === 'undefined') { - fg = vga.color.WHITE; - } - - 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; + for (let j = 0; j < repeat; ++j) { + for (const c of text) { + if (c === '\n') { + posCurrent -= (posCurrent % w) - w; if (posCurrent >= w * h) { scrollUp(); } @@ -68,24 +57,34 @@ exports.print = function(text, repeat, fg, bg) { refresh(); }; -exports.moveOffset = function(offset) { - offset = offset | 0; - var newPos = posCurrent + offset; +exports.moveOffset = (offsetOpt) => { + const offset = offsetOpt | 0; + let newPos = posCurrent + offset; if (newPos < 0) { newPos = 0; } if (newPos >= w * h) { - newPos = w * h - 1; + 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..5e51fb31b 100644 --- a/js/core/tty/terminal.js +++ b/js/core/tty/terminal.js @@ -13,42 +13,42 @@ // 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) { +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) { 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; } } @@ -56,37 +56,37 @@ exports.read = function(cb) { editor.drawCursor(); }; -exports.readLine = function(cb) { +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) { 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; } } diff --git a/js/core/tty/vga.js b/js/core/tty/vga.js index a63d6b5cc..e99582dac 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,7 +43,7 @@ var color = { LIGHTRED: 12, LIGHTMAGENTA: 13, YELLOW: 14, - WHITE: 15 + WHITE: 15, }; exports.color = color; @@ -52,6 +52,17 @@ function getColor(fg, bg) { return (((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'); + } + + /* eslint-disable no-param-reassign */ + u8[offset * 2] = char.charCodeAt(0); + u8[(offset * 2) + 1] = getColor(fg, bg); + /* eslint-enable no-param-reassign */ +} + function setCharXY(u8, x, y, char, fg, bg) { if (x < 0 || x >= w) { throw new Error('vga error: x is out of bounds'); @@ -61,21 +72,47 @@ function setCharXY(u8, x, y, char, fg, bg) { throw new Error('vga error: y is out of bounds'); } - var offset = y * w + x; + const offset = (y * w) + x; setCharOffset(u8, offset, char, fg >>> 0, bg >>> 0); } -function setCharOffset(u8, offset, char, fg, bg) { - if (offset < 0 || offset >= w * h) { - throw new Error('vga error: offset is out of bounds'); +function testColor(value) { + if ((value >>> 0) !== value) { + throw new Error('invalid color value'); } - - u8[offset * 2] = char.charCodeAt(0); - u8[offset * 2 + 1] = getColor(fg, bg); } -function VGABuffer() { - this.b = new Uint8Array(len * 2); +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); + } + } } function testInstance(obj) { @@ -84,48 +121,9 @@ function testInstance(obj) { } } -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); -}; - -VGABuffer.prototype.setOffset = function(offset, char, fg, bg) { - testInstance(this); - testColor(fg); - testColor(bg); - setCharOffset(this.b, offset, String(char), fg, bg); -}; - -VGABuffer.prototype.clear = function(bg) { - testInstance(this); - testColor(bg); - for (var i = 0; i < w * h; ++i) { - setCharOffset(this.b, i, ' ', bg, bg); - } -}; - -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); - } -}; - -exports.draw = function(drawbuf) { +exports.draw = (drawbuf) => { testInstance(drawbuf); b.set(drawbuf.b); }; -exports.allocBuffer = function() { - return new VGABuffer(); -}; +exports.allocBuffer = () => new VGABuffer(); diff --git a/js/driver/ps2/keyboard.js b/js/driver/ps2/keyboard.js index 75cdc19a0..a8a2b46f9 100644 --- a/js/driver/ps2/keyboard.js +++ b/js/driver/ps2/keyboard.js @@ -14,54 +14,54 @@ 'use strict'; -var runtime = require('../../core'); - -/* eslint-disable no-multi-spaces */ -var 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 +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, ]; -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,20 @@ var statuses = { rightalt: false, capslock: false, numlock: false, - scrllock: false + scrllock: false, }; -function keyEvent(code, isPressed) { - var cmd = controlKeys[code & 0xFF]; - var character = ''; +function keyEvent(codeOpt, isPressed) { + let code = codeOpt; + let cmd = controlKeys[code & 0xFF]; + let character = ''; code &= 0x7F; - if (0 === cmd) { + if (cmd === 0) { cmd = controlKeys[code]; } - if (0 === cmd) { + if (cmd === 0) { cmd = 'character'; if (statuses.leftshift || statuses.rightshift) { character = keymapShift[code]; @@ -95,48 +96,50 @@ 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) { @@ -146,26 +149,26 @@ function keyEvent(code, isPressed) { } } -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; + 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 +191,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..c7f900b00 100644 --- a/js/driver/virtio/device.js +++ b/js/driver/virtio/device.js @@ -13,144 +13,121 @@ // 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; -} - -VirtioDevice.prototype.readDeviceFeatures = function(features) { - var deviceFeatures = this.io.DEVICE_FEATURES.read32(); - var result = {}; + const ports = {}; + for (const portName of Object.keys(ioPorts)) { + const portOffset = ioPorts[portName]; + ports[portName] = ioSpaceResource.offsetPort(portOffset); + } - for (var feature in features) { - if (!features.hasOwnProperty(feature)) { - continue; + return ports; + })(ioSpace); + this.nextRingOffset = 0; + } + readDeviceFeatures(features) { + const deviceFeatures = this.io.DEVICE_FEATURES.read32(); + const result = {}; + + 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; - } - - if (!driverFeatures[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 (!deviceFeatures[feature]) { - // Device doesn't support required feature - return false; + const mask = 1 << features[feature]; + value |= mask; } - 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..7bdd7c98e 100644 --- a/js/driver/virtio/index.js +++ b/js/driver/virtio/index.js @@ -13,27 +13,26 @@ // 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); } debug(`[virtio] unknown virtio device (subsystem id ${subsystemId})`); }, - reset: function(pciDevice) {} + reset() {}, }; function testDeviceId(deviceId) { diff --git a/js/driver/virtio/net.js b/js/driver/virtio/net.js index 9fde71530..8ad600ec7 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 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 = { - VIRTIO_NET_F_MAC: true, // able to read MAC address - VIRTIO_NET_F_STATUS: true // able to check network status + const driverFeatures = { + 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 // 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) { @@ -100,18 +96,18 @@ function initializeNetworkDevice(pciDevice) { return; } - var hwAddr = dev.netReadHWAddress(); - var status = dev.netReadStatus(); + const hwAddr = dev.netReadHWAddress(); + const status = dev.netReadStatus(); 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() { @@ -126,11 +122,11 @@ function initializeNetworkDevice(pciDevice) { } } - 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 { @@ -146,7 +142,7 @@ function initializeNetworkDevice(pciDevice) { intf.receive(u8); } - irq.on(function() { + irq.on(() => { if (!dev.hasPendingIRQ()) { return; } @@ -155,9 +151,9 @@ function initializeNetworkDevice(pciDevice) { fillReceiveQueue(); }); - // Under high load we're missing interrupts. This needs to be fixed. - // This setInterval hack clears pending IRQ flag and rechecks queues. - setInterval(function() { +// 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); fillReceiveQueue(); diff --git a/js/driver/virtio/rng.js b/js/driver/virtio/rng.js index f390fb995..1995c2779 100644 --- a/js/driver/virtio/rng.js +++ b/js/driver/virtio/rng.js @@ -13,53 +13,50 @@ // 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 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 = []; + const reqQueue = dev.queueSetup(QUEUE_ID_REQ); + const cbqueue = []; function recvBuffer() { if (cbqueue.length === 0) { return; } - cbqueue.shift()(); } - irq.on(function() { + 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); 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..e6e990b6f 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,12 +30,10 @@ class DescriptorTable { this.descriptorsAvailable = ringSize; this.descriptorsBuffers = new Array(ringSize); - var i; - for (i = 0; i < ringSize; ++i) { + for (let i = 0; i < ringSize; ++i) { this.descriptorsBuffers[i] = null; } - - for (i = 0; i < ringSize - 1; ++i) { + for (let i = 0; i < ringSize - 1; ++i) { this.setNext(i, i + 1); } } @@ -47,15 +43,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 +60,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 +69,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,17 +86,17 @@ class DescriptorTable { * @param isWriteOnly {bool} set writeOnly flag for each buffer */ placeBuffers(buffers, lengths, isWriteOnly) { - var count = buffers.length; + 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) { + 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) { @@ -118,11 +114,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 +133,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..6b84ebcc0 100644 --- a/js/driver/virtio/vring/index.js +++ b/js/driver/virtio/vring/index.js @@ -14,163 +14,151 @@ '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}`); + + function align(value) { + return ((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(); -} + for (;;) { + if (!this.suppressInterrupts) { + this.availableRing.disableInterrupts(); + } -VRing.prototype.fetchBuffers = function(fn) { - var count = 0; + for (;;) { + const u8 = this.getBuffer(); + if (u8 === null) { + break; + } - for (;;) { - if (!this.suppressInterrupts) { - this.availableRing.disableInterrupts(); - } + count++; + if (fn) setImmediate(() => fn(u8)); + } - for (;;) { - let u8 = this.getBuffer(); - if (null === u8) { - break; + if (!this.suppressInterrupts) { + this.availableRing.enableInterrupts(); + + // Make sure we read the latest index written by the + // device, otherwise we can miss interrupts + memoryBarrier(); } - count++; - if (fn) { - setImmediate(function() { - fn(u8); - }); + if (!this.usedRing.hasUnprocessedBuffers()) { + break; } } - if (!this.suppressInterrupts) { - this.availableRing.enableInterrupts(); + return count; + } + /** + * 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); + } - // Make sure we read the latest index written by the - // device, otherwise we can miss interrupts - memoryBarrier(); + // 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'); + } } - if (!this.usedRing.hasUnprocessedBuffers()) { - break; + const first = this.descriptorTable.placeBuffers(pageSplitBuffers, lengths, isWriteOnly); + if (first < 0) { + debug('virtio: no descriptors\n'); + return false; } - } - 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); + // 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(); + + this.availableRing.placeDescriptor(first); + return true; } + getBuffer() { + const hasUnprocessed = this.usedRing.hasUnprocessedBuffers(); + if (!hasUnprocessed) { + return null; + } - 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'); + const used = this.usedRing.getUsedDescriptor(); + if (used === null) { + return null; } - } - var first = self.descriptorTable.placeBuffers(pageSplitBuffers, lengths, isWriteOnly); - if (first < 0) { - debug('virtio: no descriptors\n'); - return false; - } + const descriptorId = used.id; + const buffer = this.descriptorTable.getBuffer(descriptorId); + const len = used.len; - // 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(); + this.availableRing.setEventIdx(this.usedRing.lastUsedIndex + 1); - self.availableRing.placeDescriptor(first); - return true; -}; + 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 ', this.usedRing.lastUsedIndex); + return null; + } -VRing.prototype.getBuffer = function() { - var self = this; - var hasUnprocessed = self.usedRing.hasUnprocessedBuffers(); - if (!hasUnprocessed) { - return null; + return buffer.subarray(0, len); } - - var used = self.usedRing.getUsedDescriptor(); - if (null === used) { - return null; + isNotificationNeeded() { + // Barrier to make sure we've updated index before + // checking notifications flag + memoryBarrier(); + return this.usedRing.isNotificationNeeded(); } - - 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; + suppressUsedBuffers() { + this.availableRing.disableInterrupts(); + this.suppressInterrupts = true; } - - 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; -}; +} 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()}`); } diff --git a/js/index.js b/js/index.js index ed6ad614b..fd76ddecd 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,9 +36,9 @@ 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) { + runtime.dns.resolve('www.google.com', {}, (err, data) => { if (err) { return cb(1); } @@ -47,13 +47,13 @@ runtime.shell.setCommand('1', function(args, env, cb) { }); }); -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/modules/console.js b/js/modules/console.js index 5f961e1b2..30e9c511d 100644 --- a/js/modules/console.js +++ b/js/modules/console.js @@ -14,19 +14,29 @@ '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)); + 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 +47,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 +70,20 @@ 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..a94b33add 100644 --- a/js/modules/dns.js +++ b/js/modules/dns.js @@ -13,101 +13,125 @@ // 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}`; + +const servers = [ + '8.8.8.8', +]; + +function throwIPv6Err(cb) { + const err = new SystemError('runtime doesn\'t support IPv6', exports.BADFAMILY); + if (cb) { + return cb(err); + } + throw err; +} function lookup(hostname, opts, cb) { - if (opts.family && opts.family === 6) return throwIPv6Err(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; } runtime.dns.resolve(hostname, { - query: opts.query - }, function(err, data) { + query: opts.query, + }, (err, data) => { if (err) { - if (cb) cb(err, null, null); + 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 [...data.results.keys()]) { + const res = data.results[i]; if (!opts.all && i === 0) { - var addr = res.address.join('.'); - if (cb) cb(null, addr, 4); - break; - } else { - switch (res.record) { - case 'A': - if (opts.addrOnly) { - ret.push(res.address.join('.')); - } else { - ret.push({ - address: res.address.join('.'), - family: 4 - }); - } - break; + const addr = res.address.join('.'); + 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); + } }); } -function throwIPv6Err(cb) { - var err = new SystemError('runtime doesn\'t support IPv6', exports.BADFAMILY); - if (cb) return cb(err); - throw err; -} +exports.getServers = () => servers; -exports.getServers = function() { - return 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 +139,33 @@ 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 (typeof rrtype === 'undefined' || rrtype === null) { + rrtype = 'A'; } -} + 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..f1c9134b5 100644 --- a/js/modules/errors.js +++ b/js/modules/errors.js @@ -17,11 +17,13 @@ exports.Error = Error; class SystemError { constructor(message, errcode, call) { - var msg = ''; + let msg = ''; if (errcode) msg += `${errcode}: `; - if (message) msg += message; + 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..108057ab9 100644 --- a/js/modules/fs.js +++ b/js/modules/fs.js @@ -13,21 +13,21 @@ // limitations under the License. 'use strict'; -var typeutils = require('typeutils'); +const typeutils = require('typeutils'); +const { SystemError } = require('./errors'); function makeErrorNotFound(path, op) { - return new Error('ENOENT: no such file or directory, ' + op + ' \'' + path + '\''); + return new SystemError(`no such file or directory, ${op} '${path}'`, 'ENOENT'); } function normalizePath(components) { - var r = []; - for (var i = 0; i < components.length; ++i) { - var p = components[i]; - if ('' === p || '.' === p) { + const r = []; + for (const p of components) { + if (p === '' || p === '.') { continue; } - if ('..' === p) { + if (p === '..') { if (r.length > 0) { r.pop(); } else { @@ -48,13 +48,13 @@ function toAbsolutePath(path) { return null; } - var parts = path.split('/'); - var n = normalizePath(parts); + const parts = path.split('/'); + const n = normalizePath(parts); if (!n) { return null; } - return '/' + n.join('/'); + return `/${n.join('/')}`; } function readFileImpl(fnName, path, opts) { @@ -62,19 +62,19 @@ function readFileImpl(fnName, path, opts) { 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); + const absolute = toAbsolutePath(path); if (!absolute) { return [makeErrorNotFound(path, fnName), null]; } - var buf = __SYSCALL.initrdReadFileBuffer(absolute); + const buf = __SYSCALL.initrdReadFileBuffer(absolute); if (!buf) { return [makeErrorNotFound(path, fnName), null]; } @@ -86,20 +86,20 @@ function readFileImpl(fnName, path, opts) { 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'); } - 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); +exports.readFileSync = (path, opts) => { + const [err, buf] = readFileImpl('readFileSync', path, opts); if (err) { throw err; } diff --git a/js/modules/net.js b/js/modules/net.js index 0dce5f812..c1afd17ad 100644 --- a/js/modules/net.js +++ b/js/modules/net.js @@ -19,75 +19,16 @@ const dns = require('dns'); function 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'); + if (i !== -1) { + array.splice(i, 1); } - 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 +39,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; @@ -121,19 +65,25 @@ 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)); + 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)); + this._handle.open(addr, parseInt(port, 10)); }); } } @@ -166,10 +116,9 @@ class Socket extends Duplex { setNoDelay() {} setTimeout() {} unref() {} - _read(size) { - // can't force a read. do nothing. - } - _write(chunk, encoding, callback) { + _read() {} // can't force a read. do nothing. + _write(chunkOpt, encoding, callback) { + let chunk = chunkOpt; if (!(chunk instanceof Buffer)) { chunk = new Buffer(chunk); } @@ -178,47 +127,137 @@ class Socket extends Duplex { } } -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); + if (cb) { + server.on('connection', cb); + } return server; -} +}; -exports.isIPv4 = function(ip) { - var arr = ip.split('.'); - if (arr.length !== 4) return false; +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; - return true; -} + for (const item of arr) { + if (isNaN(parseInt(item, 10)) || item.length > 3) { + return false; + } + return true; + } +}; -exports.isIPv6 = function(ip) { - if (ip.length > 45) return false; - var arr = ip.split(':'); - if (arr.length !== 6) return false; +exports.isIPv6 = (ip) => { + if (ip.length > 45) { + return false; + } + 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; - return true; -} + for (const item of arr) { + if (item.search(/[a-zA-Z0-9]*/) === -1) { + return false; + } + return true; + } +}; -exports.isIP = function(ip) { - if (exports.isIPv4(ip)) return 4; - if (exports.isIPv6(ip)) return 6; +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..83e66de2c 100644 --- a/js/modules/os.js +++ b/js/modules/os.js @@ -13,66 +13,38 @@ // limitations under the License. 'use strict'; -var interfaces = require('../core/net/interfaces'); +const 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() { +function mem() { 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; +} + +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..536dd062a 100644 --- a/js/modules/process.js +++ b/js/modules/process.js @@ -13,78 +13,93 @@ // 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; diff --git a/js/service/dhcp-client/dhcp-options.js b/js/service/dhcp-client/dhcp-options.js index 367d09475..4e1bb77e9 100644 --- a/js/service/dhcp-client/dhcp-options.js +++ b/js/service/dhcp-client/dhcp-options.js @@ -20,27 +20,21 @@ 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..e519edab7 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,16 @@ 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,20 +59,19 @@ 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 - u8[optionsOffset++] = 1; // len + u8[optionsOffset++] = 1; // len 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; + u8[optionsOffset++] = option.bytes.length & 0xff; // len + for (const byte of option.bytes) { + u8[optionsOffset++] = byte >>> 0; } } @@ -84,49 +79,33 @@ exports.create = function(type, srcMAC, options) { 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 = []; - for (i = OPTIONS_OFFSET + 4; i < u8.length; ++i) { - var optId = u8[i++]; - var optLen = u8[i++]; +exports.getOptions = (u8) => { + const options = []; + for (let i = OPTIONS_OFFSET + 4; i < u8.length; ++i) { + const optId = u8[i++]; + const optLen = u8[i++]; - if (0xff === optId) { + if (optId === 0xff) { break; } - - if (0x00 === optId) { + if (optId === 0x00) { continue; } - var bytes = []; - for (j = 0; j < optLen; ++j) { + const bytes = []; + for (let 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..e84fd6cd2 100644 --- a/js/service/dhcp-client/index.js +++ b/js/service/dhcp-client/index.js @@ -13,44 +13,53 @@ // 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; +const dhcpPacket = require('./dhcp-packet'); +const dhcpOptions = require('./dhcp-options'); +const runtime = require('../../core'); +const { IP4Address } = runtime.net; -var STATE_IDLE = 0; -var STATE_DISCOVER_SENT = 1; -var STATE_REQUEST_SENT = 2; -var STATE_ACK_RECEIVED = 2; -var STATE_ERROR = 3; +const STATE_IDLE = 0; +const STATE_DISCOVER_SENT = 1; +const STATE_REQUEST_SENT = 2; +const STATE_ACK_RECEIVED = 2; +// const STATE_ERROR = 3; function 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); + const op = dhcpPacket.getOperation(u8); + if (op !== dhcpPacket.OPERATION_RESPONSE) { return false; } - if (!dhcpPacket.isValidMagicCookie(u8)) { return false; } @@ -59,7 +68,7 @@ function checkPacket(u8) { } function optionToIP(options, id) { - var option = dhcpOptions.find(options, id, 4); + const option = dhcpOptions.find(options, id, 4); if (!option) { return IP4Address.ANY; } @@ -68,22 +77,22 @@ function optionToIP(options, id) { } 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 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 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); + let serverId = optionToIP(options, dhcpOptions.OPTION_SERVER_ID); if (serverId.isAny()) { serverId = serverIP; } @@ -94,15 +103,12 @@ function dhcpConfigure(intf, cb) { function 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), }); } @@ -111,20 +117,19 @@ function dhcpConfigure(intf, cb) { 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; } - 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)); + // 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; } @@ -135,12 +140,12 @@ function dhcpConfigure(intf, cb) { } } - function err(e) { - clientState = STATE_ERROR; - debug(e.stack); - } +/* function 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); }; @@ -150,14 +155,14 @@ function dhcpConfigure(intf, cb) { 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..30ed9ed66 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,12 +39,10 @@ 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 + stdio: opts.stdio, }, done); }; @@ -53,11 +51,11 @@ function prompt() { 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); @@ -70,9 +68,10 @@ function 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; @@ -88,7 +87,7 @@ function prompt() { } stdio.setColor('lightred'); - stdio.writeLine('Command "' + name + '" not found.'); + stdio.writeLine(`Command '${name}' not found.`); prompt(); }); } diff --git a/js/test/unit/buffers/physical-address.js b/js/test/unit/buffers/physical-address.js index 82815ba6c..195184a06 100644 --- a/js/test/unit/buffers/physical-address.js +++ b/js/test/unit/buffers/physical-address.js @@ -13,21 +13,20 @@ // 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++) { + 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 +34,15 @@ 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++) { +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..0484ecee6 100644 --- a/js/test/unit/index.js +++ b/js/test/unit/index.js @@ -13,12 +13,13 @@ // 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) { +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); } diff --git a/js/test/unit/lib/buffer-builder.js b/js/test/unit/lib/buffer-builder.js index 183cb9f4a..47516084f 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,9 +69,7 @@ class BufferBuilder { return this; } - align(alignment, value) { - alignment = alignment || 0; - value = value || 0; + align(alignment = 0, value = 0) { while ((this._p.length % alignment) !== 0) { this.uint8(value); } @@ -79,18 +77,17 @@ class BufferBuilder { } 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 +95,13 @@ 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); + 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..7d5155dd8 100644 --- a/js/test/unit/lib/packet-builder.js +++ b/js/test/unit/lib/packet-builder.js @@ -14,105 +14,109 @@ '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'); +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'); 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; +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); } - 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() - .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(); }; -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) .uint16(destPort) .uint16(payload.length) - .uint16(0) // skip checksum + .uint16(0) // skip checksum .array(payload) .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'); } @@ -127,53 +131,53 @@ exports.splitBuffer = function(u8, chunks) { return results; }; -exports.makeBuffer = function(length, firstValue) { - firstValue = firstValue || 0; - var u8 = new Uint8Array(length); - for (var i = 0; i < u8.length; ++i) { +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) { +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) { + for (let i = 0; i < a.length; ++i) { if (a[i] !== b[i]) { return false; } - } - return true; + 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) { +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..2eaf6430e 100644 --- a/js/test/unit/net/ip4.js +++ b/js/test/unit/net/ip4.js @@ -14,58 +14,61 @@ '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) { + 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); @@ -75,13 +78,13 @@ function ipFragmentsTest(t, name, length, slices, order, norecv) { }); } -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 +94,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,17 +112,17 @@ test('receive ip4 fragmented overlapped fragments', function(t) { t.end(); }); -test('receive ip4 fragmented overlapped fragments ladder 1', function(t) { - var 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) +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) ]; 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 +133,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 +143,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 +154,14 @@ test('receive ip4 fragmented overlapped fragments ladder 2', function(t) { t.end(); }); -test('receive ip4 fragmented overlapped fragments pyramid', function(t) { - var 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 } // [= ] +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 }, // [= ] ]; 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 +171,14 @@ test('receive ip4 fragmented overlapped fragments pyramid', function(t) { t.end(); }); -test('receive ip4 fragmented overlapped fragments small chunks', function(t) { - var 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 } // [ ======= ] +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 }, // [ ======= ] ]; 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 +187,51 @@ 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) - }, 64 + 8 /* 8 bytes udp header */, [{ offset: 0, len: 8 }]); + 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..32945553e 100644 --- a/js/test/unit/net/port-allocator.js +++ b/js/test/unit/net/port-allocator.js @@ -14,14 +14,14 @@ '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) { @@ -49,14 +49,13 @@ 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); - + const port = allocator.allocEphemeral(socket); if (port === 0) { break; } @@ -70,15 +69,14 @@ test('ephemeral only: allocate and free all ports', function(t) { t.equal(allocator.allocatedCount, 16000); while (next-- > 0) { - allocator.free(16000 - next - 1 + EPHEMERAL_PORT_FIRST); + 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); - + const port = allocator.allocEphemeral(socket); if (port === 0) { break; } @@ -88,9 +86,9 @@ test('ephemeral only: allocate and free all ports', function(t) { 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 +101,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,9 +115,9 @@ 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); @@ -135,9 +133,9 @@ test('directly alloc and free all ports', function(t) { 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); @@ -168,9 +166,9 @@ test('directly alloc all ports and try to get ephemeral', function(t) { 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 +183,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 +220,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..6240ae998 100644 --- a/js/test/unit/net/tcp-receive.js +++ b/js/test/unit/net/tcp-receive.js @@ -14,32 +14,34 @@ 'use strict'; -var test = require('tape'); -var assert = require('assert'); -var TCPSocket = require('../../../core/net/tcp-socket'); +/* eslint-disable comma-dangle, array-bracket-spacing */ + +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 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; + 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) { @@ -50,33 +52,29 @@ function receiveTest(opts, 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) { + 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'); } @@ -84,239 +82,417 @@ function receiveTest(opts, cb) { function 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 } - ] + 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', function(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', 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 } - ] + 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', 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 } - ] + 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', 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 } - ] + bufs: [{ + seqOffset: 0, + len: 10, + }, { + 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() + 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', function(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', 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() + 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', function(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', 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() + 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', 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() + 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', 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() + bufs: [{ + seqOffset: 0, + len: 10, + }, { + seqOffset: 10, + len: 1, + }, ].reverse(), }, t.end.bind(t)); }); -test('receive mixed fast path and reverse order', function(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 } - ]); +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, + }, ]); }); -test('receive fast path duplicates', function(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 } - ]); +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, + }, ]); }); -test('receive overlapped duplicated data', function(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 } - ]); +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, + }, ]); }); -test('receive mixed overlapped duplicated and non-duplicated data', function(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 } - ]); +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, + }, ]); }); + +/* eslint-enable comma-dangle, array-bracket-spacing */ diff --git a/js/test/unit/net/tcp.js b/js/test/unit/net/tcp.js index fad3ab028..bfd737698 100644 --- a/js/test/unit/net/tcp.js +++ b/js/test/unit/net/tcp.js @@ -12,20 +12,20 @@ // 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'); + +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); @@ -35,57 +35,57 @@ function createTcpPacket(seq, ack, flags, window, u8data) { } 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 socket = new TCPSocket(); + const txSeq = 1; + let rxSeq = 0; function 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(); }); } + function 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 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(); + } 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; - 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); @@ -99,9 +99,9 @@ function transmitQueueItemBuffer(a) { return 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 +116,87 @@ 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) { + 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 +206,30 @@ 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) { + 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 +238,28 @@ 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) { + 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 +268,17 @@ 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; + function recvACK(seq, ack, flags) { + t.ok(flags & tcpHeader.FLAG_ACK); + } + + function recvACKFIN(seq, ack, flags) { + let packet; socket._transmit = recvACK; t.ok(flags & tcpHeader.FLAG_FIN); t.equal(socket._state, tcpSocketState.STATE_FIN_WAIT_1); @@ -286,36 +290,32 @@ test('tcp send FIN', function(t) { 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(); t.equal(socket._state, tcpSocketState.STATE_TIME_WAIT); }); }); -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() {}; + function onRecvFIN(seq, ack, flags) { + socket._transmit = () => {}; t.ok(flags & tcpHeader.FLAG_ACK); } - function onSentFIN(seq, ack, flags, window, u8) { - socket._transmit = function() {}; + function 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 +324,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() {}; + function 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 +350,83 @@ 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() { + 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) { + 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,16 +434,16 @@ 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) { + let next = 0; + server.onconnect = (socket) => { + socket.ondata = (u8) => { + for (let i = 0; i < u8.length; ++i) { t.equal(u8[i], ++next); } }; @@ -459,11 +451,11 @@ test('small sequence numbers', function(t) { 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,16 +464,16 @@ 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) { + let next = 0; + server.onconnect = (socket) => { + socket.ondata = (u8) => { + for (let i = 0; i < u8.length; ++i) { t.equal(u8[i], ++next); } }; @@ -489,11 +481,11 @@ test('large sequence numbers and wrap around', function(t) { 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 +493,5 @@ test('large sequence numbers and wrap around', function(t) { client.open('127.0.0.1', 71); }); + +/* eslint-enable no-param-reassign */ 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..48b78496d 100644 --- a/js/test/unit/random/index.js +++ b/js/test/unit/random/index.js @@ -13,23 +13,24 @@ // 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) { + 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 +38,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..c6fd64a8b 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,11 +29,13 @@ test('clearTimeout', function(t) { setTimeout(t.end.bind(t), 0); }); -test('clearInterval', function(t) { - var timer = setInterval(function() { - t.fail('should not call callback'); - throw new Error('should not call callback'); - }, 0); +test('clearInterval', (t) => { + 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 f0131b354..8edf8343f 100644 --- a/js/test/unit/virtio/index.js +++ b/js/test/unit/virtio/index.js @@ -13,49 +13,49 @@ // 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) { + for (let i = 0; i < u8.length; ++i) { u8[i] = 0; } } function bufferWriteNumbers(u8, value) { - for (var i = 0; i < u8.length; ++i) { + for (let i = 0; i < u8.length; ++i) { u8[i] = i + value; } return u8; } -function getOnePageBuffer(index) { - index = index | 0; - var b = new Uint8Array(resources.memoryRange.block(0x2000000 + index * 22, 22).buffer()); +function getOnePageBuffer(indexOpt) { + const index = indexOpt | 0; + 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 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 +63,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 +75,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 +100,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 +112,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,14 +142,14 @@ 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 bytesWritten = 3; + let descId = 0; while (devIndex < ring.availableRing.readIdx()) { descId = ring.availableRing.readDescriptorAsDevice(); ring.usedRing.placeDescriptorAsDevice(descId, bytesWritten); @@ -168,7 +169,7 @@ test('vring operation', function(t) { } t.equal(count, 0); - for (var i = 0; i < 4; ++i) { + for (let i = 0; i < 4; ++i) { driverProcessAll(); t.ok(count > 0); devProcessAll(); 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()); diff --git a/js/version.js b/js/version.js index 9cecec4f3..c55684ad6 100644 --- a/js/version.js +++ b/js/version.js @@ -14,16 +14,17 @@ 'use strict'; -/* global __SYSCALL */ if (!global.__SYSCALL) { - throw 'error: this program requires runtime.js environment'; + 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..d7959376b 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,8 +21,9 @@ }, "homepage": "http://runtimejs.org", "devDependencies": { - "eslint": "^1.8.0", - "eslint-config-runtime": "^1.0.0", + "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" },