1.4.x_branch (#1)
Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
14
.gitignore
vendored
14
.gitignore
vendored
@@ -1,7 +1,7 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
coverage/
|
coverage/
|
||||||
.vscode/
|
.vscode/
|
||||||
dist/
|
dist/
|
||||||
backup/
|
backup/
|
||||||
.idea/
|
.idea/
|
||||||
/package-lock.json
|
/package-lock.json
|
||||||
|
|||||||
6
.nvimrc
6
.nvimrc
@@ -1,3 +1,3 @@
|
|||||||
set path+=.,src/**
|
set path+=.,src/**
|
||||||
let &makeprg="npm run build"
|
let &makeprg="npm run build"
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"trailingComma": "es5",
|
"trailingComma": "es5",
|
||||||
"tabWidth": 2,
|
"tabWidth": 2,
|
||||||
"semi": true,
|
"semi": true,
|
||||||
"singleQuote": true,
|
"singleQuote": true,
|
||||||
"jsxBracketSameLine": true
|
"jsxBracketSameLine": true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
5
.vim/coc-settings.json
Normal file
5
.vim/coc-settings.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"cSpell.words": [
|
||||||
|
"winfsp"
|
||||||
|
]
|
||||||
|
}
|
||||||
28
CHANGELOG.md
28
CHANGELOG.md
@@ -1,14 +1,14 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## 1.4.0-r1
|
## 1.4.0-r1
|
||||||
- Switched packet encryption to XChaCha20-Poly1305
|
- Switched packet encryption to XChaCha20-Poly1305
|
||||||
- Allow external XChaCha20-Poly1305 encryption/decryption
|
- Allow external XChaCha20-Poly1305 encryption/decryption
|
||||||
- Support writing base64 string data
|
- Support writing base64 string data
|
||||||
- Renamed 'delete/delete_file' to 'remove/remove_file'
|
- Renamed 'delete/delete_file' to 'remove/remove_file'
|
||||||
|
|
||||||
## 1.3.1-r3
|
## 1.3.1-r3
|
||||||
- Added directory/file exists
|
- Added directory/file exists
|
||||||
- Fix unit tests
|
- Fix unit tests
|
||||||
|
|
||||||
## 1.3.1-r2
|
## 1.3.1-r2
|
||||||
- Initial release
|
- Initial release
|
||||||
|
|||||||
36
LICENSE.md
36
LICENSE.md
@@ -1,18 +1,18 @@
|
|||||||
# `repertory-js` MIT License
|
# `repertory-js` MIT License
|
||||||
|
|
||||||
### Copyright <2021> <scott.e.graves@protonmail.com>
|
### Copyright <2021> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||||
associated documentation files (the "Software"), to deal in the Software without restriction,
|
associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||||
including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||||
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial
|
The above copyright notice and this permission notice shall be included in all copies or substantial
|
||||||
portions of the Software.
|
portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||||
OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|||||||
394
README.md
394
README.md
@@ -1,197 +1,197 @@
|
|||||||
# About
|
# About
|
||||||
|
|
||||||
`repertory-js` is a Node.js module for interfacing with `repertory's` remote mount API.
|
`repertory-js` is a Node.js module for interfacing with `repertory's` remote mount API.
|
||||||
|
|
||||||
## Installing
|
## Installing
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
npm i @blockstorage/repertory-js
|
npm i @blockstorage/repertory-js
|
||||||
```
|
```
|
||||||
|
|
||||||
## Repertory Configuration
|
## Repertory Configuration
|
||||||
|
|
||||||
A Repertory mount must be active with the `EnableRemoteMount` setting enabled. `RemoteToken` should
|
A Repertory mount must be active with the `EnableRemoteMount` setting enabled. `RemoteToken` should
|
||||||
also be set to a strong, random password.
|
also be set to a strong, random password.
|
||||||
|
|
||||||
### Enabling Sia Remote Mount API on Windows Systems
|
### Enabling Sia Remote Mount API on Windows Systems
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
repertory.exe -unmount
|
repertory.exe -unmount
|
||||||
repertory.exe -set RemoteMount.EnableRemoteMount true
|
repertory.exe -set RemoteMount.EnableRemoteMount true
|
||||||
repertory.exe -set RemoteMount.RemoteToken "my password"
|
repertory.exe -set RemoteMount.RemoteToken "my password"
|
||||||
|
|
||||||
[Optional - change listening port]
|
[Optional - change listening port]
|
||||||
repertory.exe -set RemoteMount.RemotePort 20202
|
repertory.exe -set RemoteMount.RemotePort 20202
|
||||||
```
|
```
|
||||||
|
|
||||||
### Enabling Sia Remote Mount API on *NIX Systems
|
### Enabling Sia Remote Mount API on *NIX Systems
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
./repertory -unmount
|
./repertory -unmount
|
||||||
./repertory -set RemoteMount.EnableRemoteMount true
|
./repertory -set RemoteMount.EnableRemoteMount true
|
||||||
./repertory -set RemoteMount.RemoteToken "my password"
|
./repertory -set RemoteMount.RemoteToken "my password"
|
||||||
|
|
||||||
[Optional - change listening port]
|
[Optional - change listening port]
|
||||||
./repertory -set RemoteMount.RemotePort 20202
|
./repertory -set RemoteMount.RemotePort 20202
|
||||||
```
|
```
|
||||||
|
|
||||||
### Skynet and ScPrime Mounts
|
### Skynet and ScPrime Mounts
|
||||||
|
|
||||||
* For Skynet mounts, add `-sk` argument to all commands listed above.
|
* For Skynet mounts, add `-sk` argument to all commands listed above.
|
||||||
* For ScPrime mounts, add `-sp` argument to all commands listed above.
|
* For ScPrime mounts, add `-sp` argument to all commands listed above.
|
||||||
|
|
||||||
## Module Environment Variables
|
## Module Environment Variables
|
||||||
|
|
||||||
* To successfully complete unit tests, a `repertory` mount supporting remote mount needs to be
|
* To successfully complete unit tests, a `repertory` mount supporting remote mount needs to be
|
||||||
active. Set the following environment variables prior to running tests:
|
active. Set the following environment variables prior to running tests:
|
||||||
* `TEST_HOST`
|
* `TEST_HOST`
|
||||||
* `TEST_PASSWORD`
|
* `TEST_PASSWORD`
|
||||||
* `TEST_PORT`
|
* `TEST_PORT`
|
||||||
|
|
||||||
## Example API Usage
|
## Example API Usage
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import * as rep from "@blockstorage/repertory-js";
|
import * as rep from "@blockstorage/repertory-js";
|
||||||
//const rep = require("@blockstorage/repertory-js");
|
//const rep = require("@blockstorage/repertory-js");
|
||||||
|
|
||||||
|
|
||||||
// Repertory host settings
|
// Repertory host settings
|
||||||
const MY_HOST_OR_IP = 'localhost';
|
const MY_HOST_OR_IP = 'localhost';
|
||||||
const MY_PORT = 20000;
|
const MY_PORT = 20000;
|
||||||
const MY_TOKEN = 'password';
|
const MY_TOKEN = 'password';
|
||||||
|
|
||||||
// Progress callback for uploads / downloads
|
// Progress callback for uploads / downloads
|
||||||
const progress_cb = (local_path, remote_path, progress, completed) => {
|
const progress_cb = (local_path, remote_path, progress, completed) => {
|
||||||
console.log(local_path, remote_path, progress, completed);
|
console.log(local_path, remote_path, progress, completed);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//************************************************************************************************//
|
//************************************************************************************************//
|
||||||
// Step 1. Create a connection pool (recommended) //
|
// Step 1. Create a connection pool (recommended) //
|
||||||
//************************************************************************************************//
|
//************************************************************************************************//
|
||||||
|
|
||||||
const conn = await rep.create_pool(8, MY_HOST_OR_IP, MY_PORT, MY_TOKEN);
|
const conn = await rep.create_pool(8, MY_HOST_OR_IP, MY_PORT, MY_TOKEN);
|
||||||
/* Or create a single connection for light operations
|
/* Or create a single connection for light operations
|
||||||
const conn = await rep.connect(MY_HOST_OR_IP, MY_PORT, MY_TOKEN);
|
const conn = await rep.connect(MY_HOST_OR_IP, MY_PORT, MY_TOKEN);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Disconnect when complete
|
/* Disconnect when complete
|
||||||
await conn.disconnect();
|
await conn.disconnect();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//************************************************************************************************//
|
//************************************************************************************************//
|
||||||
// Step 2. Create an 'api' instance using the connection pool / connection //
|
// Step 2. Create an 'api' instance using the connection pool / connection //
|
||||||
//************************************************************************************************//
|
//************************************************************************************************//
|
||||||
|
|
||||||
const api = rep.create_api(conn);
|
const api = rep.create_api(conn);
|
||||||
|
|
||||||
|
|
||||||
//************************************************************************************************//
|
//************************************************************************************************//
|
||||||
// Step 3. Use 'api' //
|
// Step 3. Use 'api' //
|
||||||
//************************************************************************************************//
|
//************************************************************************************************//
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------//
|
//------------------------------------------------------------------------------------------------//
|
||||||
// *********** Directory Operations *********** //
|
// *********** Directory Operations *********** //
|
||||||
//------------------------------------------------------------------------------------------------//
|
//------------------------------------------------------------------------------------------------//
|
||||||
|
|
||||||
// Check if directory exists
|
// Check if directory exists
|
||||||
const exists = await api.directory.exists('/my_directory');
|
const exists = await api.directory.exists('/my_directory');
|
||||||
|
|
||||||
// List directory contents
|
// List directory contents
|
||||||
await api.directory.list('/', async (remote_path, page_count, get_page) => {
|
await api.directory.list('/', async (remote_path, page_count, get_page) => {
|
||||||
for (let i = 0; i < page_count; i++) {
|
for (let i = 0; i < page_count; i++) {
|
||||||
const items = await get_page(i); // Always 'await'
|
const items = await get_page(i); // Always 'await'
|
||||||
console.log(items);
|
console.log(items);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Asynchronous directory list
|
// Asynchronous directory list
|
||||||
const snap = await api.directory.snapshot('/');
|
const snap = await api.directory.snapshot('/');
|
||||||
try {
|
try {
|
||||||
for (let i = 0; i < snap.page_count; i++) {
|
for (let i = 0; i < snap.page_count; i++) {
|
||||||
const items = await snap.get_page(i); // Always 'await'
|
const items = await snap.get_page(i); // Always 'await'
|
||||||
console.log(items);
|
console.log(items);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
} finally {
|
} finally {
|
||||||
await snap.release();
|
await snap.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new directory
|
// Create new directory
|
||||||
await api.directory.create('/test');
|
await api.directory.create('/test');
|
||||||
|
|
||||||
// Remove existing directory
|
// Remove existing directory
|
||||||
await api.directory.remove('/test')
|
await api.directory.remove('/test')
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------//
|
//------------------------------------------------------------------------------------------------//
|
||||||
// *********** File Operations *********** //
|
// *********** File Operations *********** //
|
||||||
//------------------------------------------------------------------------------------------------//
|
//------------------------------------------------------------------------------------------------//
|
||||||
|
|
||||||
// Check if file exists
|
// Check if file exists
|
||||||
const exists = await api.file.exists('/my_file.txt')
|
const exists = await api.file.exists('/my_file.txt')
|
||||||
|
|
||||||
// Remove a file
|
// Remove a file
|
||||||
await api.file.remove('/my_file.txt')
|
await api.file.remove('/my_file.txt')
|
||||||
|
|
||||||
// Download a remote file
|
// Download a remote file
|
||||||
await api.file.download('/my_file.txt', 'C:\\my_file.txt', progress_cb);
|
await api.file.download('/my_file.txt', 'C:\\my_file.txt', progress_cb);
|
||||||
|
|
||||||
// Download a remote file and overwrite existing local file
|
// Download a remote file and overwrite existing local file
|
||||||
await api.file.download('/my_file.txt', 'C:\\my_file.txt', progress_cb, true);
|
await api.file.download('/my_file.txt', 'C:\\my_file.txt', progress_cb, true);
|
||||||
|
|
||||||
// Resume failed download
|
// Resume failed download
|
||||||
await api.file.download('/my_file.txt', 'C:\\my_file.txt', progress_cb, false, true);
|
await api.file.download('/my_file.txt', 'C:\\my_file.txt', progress_cb, false, true);
|
||||||
|
|
||||||
// Upload a local file
|
// Upload a local file
|
||||||
await api.file.upload('C:\\my_file.txt', '/my_file.txt', progress_cb);
|
await api.file.upload('C:\\my_file.txt', '/my_file.txt', progress_cb);
|
||||||
|
|
||||||
// Upload a local file and overwrite existing remote file
|
// Upload a local file and overwrite existing remote file
|
||||||
await api.file.upload('C:\\my_file.txt', '/my_file.txt', progress_cb, true);
|
await api.file.upload('C:\\my_file.txt', '/my_file.txt', progress_cb, true);
|
||||||
|
|
||||||
// Resume failed upload
|
// Resume failed upload
|
||||||
await api.file.upload('C:\\my_file.txt', '/my_file.txt', progress_cb, false, true);
|
await api.file.upload('C:\\my_file.txt', '/my_file.txt', progress_cb, false, true);
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------//
|
//------------------------------------------------------------------------------------------------//
|
||||||
// *********** Low-Level File Operations *********** //
|
// *********** Low-Level File Operations *********** //
|
||||||
//------------------------------------------------------------------------------------------------//
|
//------------------------------------------------------------------------------------------------//
|
||||||
|
|
||||||
// Create or open a remote file
|
// Create or open a remote file
|
||||||
{
|
{
|
||||||
const f = await api.file.create_or_open('/my_file.txt');
|
const f = await api.file.create_or_open('/my_file.txt');
|
||||||
await f.close();
|
await f.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open an existing remote file
|
// Open an existing remote file
|
||||||
{
|
{
|
||||||
const f = await api.file.open('/my_file.txt');
|
const f = await api.file.open('/my_file.txt');
|
||||||
await f.close();
|
await f.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write to a file
|
// Write to a file
|
||||||
{
|
{
|
||||||
const f = await api.file.create_or_open('/my_file.txt');
|
const f = await api.file.create_or_open('/my_file.txt');
|
||||||
|
|
||||||
const b = Buffer.alloc(1);
|
const b = Buffer.alloc(1);
|
||||||
b[0] = 1;
|
b[0] = 1;
|
||||||
await f.write(0, b); // write '1' byte at file offset '0'
|
await f.write(0, b); // write '1' byte at file offset '0'
|
||||||
|
|
||||||
await f.close();
|
await f.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read from a file
|
// Read from a file
|
||||||
{
|
{
|
||||||
const f = await api.file.create_or_open('/my_file.txt');
|
const f = await api.file.create_or_open('/my_file.txt');
|
||||||
const b = await f.read(0, 1); // read '1' byte from file offset '0'
|
const b = await f.read(0, 1); // read '1' byte from file offset '0'
|
||||||
await f.close();
|
await f.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Truncate / resize file
|
// Truncate / resize file
|
||||||
{
|
{
|
||||||
const f = await api.file.create_or_open('/my_file.txt');
|
const f = await api.file.create_or_open('/my_file.txt');
|
||||||
await f.truncate(10);
|
await f.truncate(10);
|
||||||
await f.close();
|
await f.close();
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
22
fixup
22
fixup
@@ -1,11 +1,11 @@
|
|||||||
cat <<EOF >dist/cjs/package.json
|
cat <<EOF >dist/cjs/package.json
|
||||||
{
|
{
|
||||||
"type": "commonjs"
|
"type": "commonjs"
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
cat <<EOF >dist/mjs/package.json
|
cat <<EOF >dist/mjs/package.json
|
||||||
{
|
{
|
||||||
"type": "module"
|
"type": "module"
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|||||||
138
package.json
138
package.json
@@ -1,69 +1,69 @@
|
|||||||
{
|
{
|
||||||
"name": "@blockstorage/repertory-js",
|
"name": "@blockstorage/repertory-js",
|
||||||
"version": "1.4.0-r1",
|
"version": "2.0.0-r1",
|
||||||
"description": "A Node.js module for interfacing with Repertory's remote mount API",
|
"description": "A Node.js module for interfacing with Repertory's remote mount API",
|
||||||
"author": "scott.e.graves@protonmail.com",
|
"author": "scott.e.graves@protonmail.com",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"homepage": "https://bitbucket.org/blockstorage/repertory-js",
|
"homepage": "https://bitbucket.org/blockstorage/repertory-js",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://bitbucket.org/blockstorage/repertory-js.git"
|
"url": "https://bitbucket.org/blockstorage/repertory-js.git"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"repertory",
|
"repertory",
|
||||||
"repertory-ui",
|
"repertory-ui",
|
||||||
"library",
|
"library",
|
||||||
"mount",
|
"mount",
|
||||||
"fuse",
|
"fuse",
|
||||||
"winfsp",
|
"winfsp",
|
||||||
"blockchain",
|
"blockchain",
|
||||||
"decentralized",
|
"decentralized",
|
||||||
"cloud",
|
"cloud",
|
||||||
"storage",
|
"storage",
|
||||||
"altcoin",
|
"altcoin",
|
||||||
"cryptocurrency"
|
"cryptocurrency"
|
||||||
],
|
],
|
||||||
"main": "dist/cjs/index.js",
|
"main": "dist/cjs/index.js",
|
||||||
"module": "dist/mjs/index.js",
|
"module": "dist/mjs/index.js",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": {
|
".": {
|
||||||
"import": "./dist/mjs/index.js",
|
"import": "./dist/mjs/index.js",
|
||||||
"require": "./dist/cjs/index.js"
|
"require": "./dist/cjs/index.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist/cjs",
|
"dist/cjs",
|
||||||
"dist/mjs"
|
"dist/mjs"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rollup -c && ./fixup",
|
"build": "rollup -c && ./fixup",
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
"prepublish": "rollup -c --silent && ./fixup"
|
"prepublish": "rollup -c --silent && ./fixup"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@stablelib/xchacha20poly1305": "^1.0.1",
|
"@stablelib/xchacha20poly1305": "^1.0.1",
|
||||||
"int64-buffer": "^1.0.0",
|
"int64-buffer": "^1.0.0",
|
||||||
"socket-pool": "^1.2.3",
|
"socket-pool": "^1.2.3",
|
||||||
"text-encoding": "^0.7.0",
|
"text-encoding": "^0.7.0",
|
||||||
"uuid": "^8.3.2"
|
"uuid": "^8.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.14.3",
|
"@babel/core": "^7.14.3",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.13.0",
|
"@babel/plugin-proposal-class-properties": "^7.13.0",
|
||||||
"@babel/plugin-proposal-private-methods": "^7.13.0",
|
"@babel/plugin-proposal-private-methods": "^7.13.0",
|
||||||
"@babel/plugin-transform-async-to-generator": "^7.13.0",
|
"@babel/plugin-transform-async-to-generator": "^7.13.0",
|
||||||
"@babel/plugin-transform-regenerator": "^7.13.15",
|
"@babel/plugin-transform-regenerator": "^7.13.15",
|
||||||
"@babel/plugin-transform-runtime": "^7.14.3",
|
"@babel/plugin-transform-runtime": "^7.14.3",
|
||||||
"@babel/preset-env": "^7.14.2",
|
"@babel/preset-env": "^7.14.2",
|
||||||
"@rollup/plugin-babel": "^5.3.0",
|
"@rollup/plugin-babel": "^5.3.0",
|
||||||
"@rollup/plugin-commonjs": "^15.1.0",
|
"@rollup/plugin-commonjs": "^15.1.0",
|
||||||
"@rollup/plugin-json": "^4.0.0",
|
"@rollup/plugin-json": "^4.0.0",
|
||||||
"@rollup/plugin-node-resolve": "^9.0.0",
|
"@rollup/plugin-node-resolve": "^9.0.0",
|
||||||
"@types/jest": "^26.0.23",
|
"@types/jest": "^26.0.23",
|
||||||
"babel-eslint": "^10.1.0",
|
"babel-eslint": "^10.1.0",
|
||||||
"jest": "^26.6.3",
|
"jest": "^26.6.3",
|
||||||
"rollup": "^2.50.0",
|
"rollup": "^2.50.0",
|
||||||
"rollup-plugin-eslint": "^7.0.0",
|
"rollup-plugin-eslint": "^7.0.0",
|
||||||
"rollup-plugin-terser": "^7.0.2"
|
"rollup-plugin-terser": "^7.0.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
120
rollup.config.js
120
rollup.config.js
@@ -1,60 +1,60 @@
|
|||||||
import resolve from '@rollup/plugin-node-resolve';
|
import resolve from '@rollup/plugin-node-resolve';
|
||||||
import commonjs from '@rollup/plugin-commonjs';
|
import commonjs from '@rollup/plugin-commonjs';
|
||||||
import babel from '@rollup/plugin-babel';
|
import babel from '@rollup/plugin-babel';
|
||||||
import { terser } from 'rollup-plugin-terser';
|
import { terser } from 'rollup-plugin-terser';
|
||||||
import json from '@rollup/plugin-json';
|
import json from '@rollup/plugin-json';
|
||||||
|
|
||||||
const commonConfig = {
|
const commonConfig = {
|
||||||
input: 'src/index.js',
|
input: 'src/index.js',
|
||||||
output: {
|
output: {
|
||||||
name: 'index',
|
name: 'index',
|
||||||
sourcemap: true,
|
sourcemap: true,
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
resolve({
|
resolve({
|
||||||
customResolveOptions: {
|
customResolveOptions: {
|
||||||
moduleDirectory: 'node_modules',
|
moduleDirectory: 'node_modules',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
babel({
|
babel({
|
||||||
exclude: 'node_modules/**',
|
exclude: 'node_modules/**',
|
||||||
babelHelpers: 'runtime',
|
babelHelpers: 'runtime',
|
||||||
}),
|
}),
|
||||||
commonjs(),
|
commonjs(),
|
||||||
json(),
|
json(),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
// ESM config
|
// ESM config
|
||||||
const esmConfig = Object.assign({}, commonConfig);
|
const esmConfig = Object.assign({}, commonConfig);
|
||||||
esmConfig.output = Object.assign({}, commonConfig.output, {
|
esmConfig.output = Object.assign({}, commonConfig.output, {
|
||||||
file: 'dist/mjs/index.js',
|
file: 'dist/mjs/index.js',
|
||||||
format: 'esm',
|
format: 'esm',
|
||||||
});
|
});
|
||||||
|
|
||||||
// ESM prod config
|
// ESM prod config
|
||||||
const esmProdConfig = Object.assign({}, esmConfig);
|
const esmProdConfig = Object.assign({}, esmConfig);
|
||||||
esmProdConfig.output = Object.assign({}, esmConfig.output, {
|
esmProdConfig.output = Object.assign({}, esmConfig.output, {
|
||||||
file: 'dist/mjs/index.min.js',
|
file: 'dist/mjs/index.min.js',
|
||||||
sourcemap: false,
|
sourcemap: false,
|
||||||
});
|
});
|
||||||
esmProdConfig.plugins = [...esmConfig.plugins, terser()];
|
esmProdConfig.plugins = [...esmConfig.plugins, terser()];
|
||||||
|
|
||||||
// CJS config
|
// CJS config
|
||||||
const cjsConfig = Object.assign({}, commonConfig);
|
const cjsConfig = Object.assign({}, commonConfig);
|
||||||
cjsConfig.output = Object.assign({}, commonConfig.output, {
|
cjsConfig.output = Object.assign({}, commonConfig.output, {
|
||||||
file: 'dist/cjs/index.js',
|
file: 'dist/cjs/index.js',
|
||||||
format: 'cjs',
|
format: 'cjs',
|
||||||
});
|
});
|
||||||
|
|
||||||
// CJS prod config
|
// CJS prod config
|
||||||
const cjsProdConfig = Object.assign({}, cjsConfig);
|
const cjsProdConfig = Object.assign({}, cjsConfig);
|
||||||
cjsProdConfig.output = Object.assign({}, cjsConfig.output, {
|
cjsProdConfig.output = Object.assign({}, cjsConfig.output, {
|
||||||
file: 'dist/cjs/index.min.js',
|
file: 'dist/cjs/index.min.js',
|
||||||
sourcemap: false,
|
sourcemap: false,
|
||||||
});
|
});
|
||||||
cjsProdConfig.plugins = [...cjsConfig.plugins, terser()];
|
cjsProdConfig.plugins = [...cjsConfig.plugins, terser()];
|
||||||
let configurations = [];
|
let configurations = [];
|
||||||
configurations.push(esmConfig, esmProdConfig, cjsConfig, cjsProdConfig);
|
configurations.push(esmConfig, esmProdConfig, cjsConfig, cjsProdConfig);
|
||||||
|
|
||||||
export default configurations;
|
export default configurations;
|
||||||
|
|||||||
@@ -1,115 +1,115 @@
|
|||||||
import connection from '../networking/connection';
|
import connection from '../networking/connection';
|
||||||
import packet from '../networking/packet';
|
import packet from '../networking/packet';
|
||||||
import Socket from 'net';
|
import Socket from 'net';
|
||||||
|
|
||||||
test(`connect fails when error occurs during createConnection`, async () => {
|
test(`connect fails when error occurs during createConnection`, async () => {
|
||||||
const mock_create = (port, host, cb) => {
|
const mock_create = (port, host, cb) => {
|
||||||
cb(new Error('mock create error'));
|
cb(new Error('mock create error'));
|
||||||
};
|
};
|
||||||
jest.spyOn(Socket, 'createConnection').mockImplementation(mock_create);
|
jest.spyOn(Socket, 'createConnection').mockImplementation(mock_create);
|
||||||
|
|
||||||
const conn = new connection('localhost', 20000);
|
const conn = new connection('localhost', 20000);
|
||||||
await expect(conn.connect()).rejects.toThrow(Error);
|
await expect(conn.connect()).rejects.toThrow(Error);
|
||||||
});
|
});
|
||||||
|
|
||||||
test(`socket receive data fails when decryption fails`, async () => {
|
test(`socket receive data fails when decryption fails`, async () => {
|
||||||
let cbl = {};
|
let cbl = {};
|
||||||
const socket = {
|
const socket = {
|
||||||
setNoDelay: () => {},
|
setNoDelay: () => {},
|
||||||
setKeepAlive: () => {},
|
setKeepAlive: () => {},
|
||||||
on: (name, cb) => {
|
on: (name, cb) => {
|
||||||
cbl[name] = cb;
|
cbl[name] = cb;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const conn = new connection('', 0, 'b', socket);
|
const conn = new connection('', 0, 'b', socket);
|
||||||
let reject;
|
let reject;
|
||||||
const mock_reject = jest.fn().mockImplementation((e) => reject(e));
|
const mock_reject = jest.fn().mockImplementation((e) => reject(e));
|
||||||
conn.reject = mock_reject;
|
conn.reject = mock_reject;
|
||||||
conn.resolve = jest.fn();
|
conn.resolve = jest.fn();
|
||||||
|
|
||||||
const p = new packet('a');
|
const p = new packet('a');
|
||||||
await p.encrypt();
|
await p.encrypt();
|
||||||
p.encode_top_ui32(p.buffer.length);
|
p.encode_top_ui32(p.buffer.length);
|
||||||
await expect(
|
await expect(
|
||||||
new Promise((_, r) => {
|
new Promise((_, r) => {
|
||||||
reject = r;
|
reject = r;
|
||||||
cbl['data'](Buffer.from(p.buffer));
|
cbl['data'](Buffer.from(p.buffer));
|
||||||
})
|
})
|
||||||
).rejects.toThrow(Error);
|
).rejects.toThrow(Error);
|
||||||
expect(mock_reject.mock.calls.length).toBe(1);
|
expect(mock_reject.mock.calls.length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test(`disconnect succeeds if an error is thrown`, async () => {
|
test(`disconnect succeeds if an error is thrown`, async () => {
|
||||||
const socket = {
|
const socket = {
|
||||||
setNoDelay: () => {},
|
setNoDelay: () => {},
|
||||||
setKeepAlive: () => {},
|
setKeepAlive: () => {},
|
||||||
destroy: () => {
|
destroy: () => {
|
||||||
throw new Error('mock destroy error');
|
throw new Error('mock destroy error');
|
||||||
},
|
},
|
||||||
on: () => {},
|
on: () => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
const conn = new connection('', 0, 'b', socket);
|
const conn = new connection('', 0, 'b', socket);
|
||||||
await conn.disconnect();
|
await conn.disconnect();
|
||||||
});
|
});
|
||||||
|
|
||||||
test(`send fails on socket error`, async () => {
|
test(`send fails on socket error`, async () => {
|
||||||
let cbl = {};
|
let cbl = {};
|
||||||
const socket = {
|
const socket = {
|
||||||
setNoDelay: () => {},
|
setNoDelay: () => {},
|
||||||
setKeepAlive: () => {},
|
setKeepAlive: () => {},
|
||||||
on: (name, cb) => {
|
on: (name, cb) => {
|
||||||
cbl[name] = cb;
|
cbl[name] = cb;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const conn = new connection('', 0, 'b', socket);
|
const conn = new connection('', 0, 'b', socket);
|
||||||
const mock_reject = jest.fn();
|
const mock_reject = jest.fn();
|
||||||
conn.reject = mock_reject;
|
conn.reject = mock_reject;
|
||||||
conn.resolve = jest.fn();
|
conn.resolve = jest.fn();
|
||||||
|
|
||||||
cbl['error']('socket error');
|
cbl['error']('socket error');
|
||||||
expect(mock_reject).toBeCalled();
|
expect(mock_reject).toBeCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
test(`error is thrown when socket is closed`, async () => {
|
test(`error is thrown when socket is closed`, async () => {
|
||||||
let cbl = {};
|
let cbl = {};
|
||||||
const socket = {
|
const socket = {
|
||||||
setNoDelay: () => {},
|
setNoDelay: () => {},
|
||||||
setKeepAlive: () => {},
|
setKeepAlive: () => {},
|
||||||
on: (name, cb) => {
|
on: (name, cb) => {
|
||||||
cbl[name] = cb;
|
cbl[name] = cb;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const conn = new connection('', 0, 'b', socket);
|
const conn = new connection('', 0, 'b', socket);
|
||||||
const mock_reject = jest.fn();
|
const mock_reject = jest.fn();
|
||||||
conn.reject = mock_reject;
|
conn.reject = mock_reject;
|
||||||
conn.resolve = jest.fn();
|
conn.resolve = jest.fn();
|
||||||
|
|
||||||
cbl['close']();
|
cbl['close']();
|
||||||
expect(mock_reject).toBeCalled();
|
expect(mock_reject).toBeCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
test(`send fails when write error occurs`, async () => {
|
test(`send fails when write error occurs`, async () => {
|
||||||
let cbl = {};
|
let cbl = {};
|
||||||
const socket = {
|
const socket = {
|
||||||
setNoDelay: () => {},
|
setNoDelay: () => {},
|
||||||
setKeepAlive: () => {},
|
setKeepAlive: () => {},
|
||||||
on: (name, cb) => {
|
on: (name, cb) => {
|
||||||
cbl[name] = cb;
|
cbl[name] = cb;
|
||||||
},
|
},
|
||||||
write: (b, c, cb) => {
|
write: (b, c, cb) => {
|
||||||
cb('mock write error');
|
cb('mock write error');
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const conn = new connection('', 0, 'b', socket);
|
const conn = new connection('', 0, 'b', socket);
|
||||||
try {
|
try {
|
||||||
await conn.send('c', new packet('b'));
|
await conn.send('c', new packet('b'));
|
||||||
expect('send should fail').toBeNull();
|
expect('send should fail').toBeNull();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
expect(err).toBeDefined();
|
expect(err).toBeDefined();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,59 +1,59 @@
|
|||||||
import connection_pool from '../networking/connection_pool';
|
import connection_pool from '../networking/connection_pool';
|
||||||
import packet from '../networking/packet';
|
import packet from '../networking/packet';
|
||||||
import connection from '../networking/connection';
|
import connection from '../networking/connection';
|
||||||
|
|
||||||
jest.mock('../networking/connection');
|
jest.mock('../networking/connection');
|
||||||
|
|
||||||
test(`construction fails if pool size is <= 1`, () => {
|
test(`construction fails if pool size is <= 1`, () => {
|
||||||
expect(() => new connection_pool(1)).toThrow(Error);
|
expect(() => new connection_pool(1)).toThrow(Error);
|
||||||
expect(() => new connection_pool(0)).toThrow(Error);
|
expect(() => new connection_pool(0)).toThrow(Error);
|
||||||
expect(() => new connection_pool(-1)).toThrow(Error);
|
expect(() => new connection_pool(-1)).toThrow(Error);
|
||||||
});
|
});
|
||||||
|
|
||||||
test(`error on socket release is ignored`, async () => {
|
test(`error on socket release is ignored`, async () => {
|
||||||
const conn = new connection_pool(2, '', 20000);
|
const conn = new connection_pool(2, '', 20000);
|
||||||
let invoked = false;
|
let invoked = false;
|
||||||
jest.spyOn(conn.pool, 'acquire').mockImplementation(() => {
|
jest.spyOn(conn.pool, 'acquire').mockImplementation(() => {
|
||||||
return {
|
return {
|
||||||
release: () => {
|
release: () => {
|
||||||
invoked = true;
|
invoked = true;
|
||||||
throw new Error('mock release error');
|
throw new Error('mock release error');
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const mock_send = jest.fn();
|
const mock_send = jest.fn();
|
||||||
connection.prototype.send = async () => {
|
connection.prototype.send = async () => {
|
||||||
return mock_send();
|
return mock_send();
|
||||||
};
|
};
|
||||||
mock_send.mockResolvedValue(0);
|
mock_send.mockResolvedValue(0);
|
||||||
|
|
||||||
expect(await conn.send('', new packet())).toEqual(0);
|
expect(await conn.send('', new packet())).toEqual(0);
|
||||||
expect(invoked).toBeTruthy();
|
expect(invoked).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test(`connection pool send fails if socket acquire fails`, async () => {
|
test(`connection pool send fails if socket acquire fails`, async () => {
|
||||||
const conn = new connection_pool(2, '', 20000);
|
const conn = new connection_pool(2, '', 20000);
|
||||||
jest.spyOn(conn.pool, 'acquire').mockImplementation(() => {
|
jest.spyOn(conn.pool, 'acquire').mockImplementation(() => {
|
||||||
throw new Error('mock acquire exception');
|
throw new Error('mock acquire exception');
|
||||||
});
|
});
|
||||||
|
|
||||||
await expect(conn.send('', new packet())).rejects.toThrow(Error);
|
await expect(conn.send('', new packet())).rejects.toThrow(Error);
|
||||||
});
|
});
|
||||||
|
|
||||||
test(`connection pool send fails when connection send fails`, async () => {
|
test(`connection pool send fails when connection send fails`, async () => {
|
||||||
const conn = new connection_pool(2, '', 20000);
|
const conn = new connection_pool(2, '', 20000);
|
||||||
jest.spyOn(conn.pool, 'acquire').mockImplementation(() => {
|
jest.spyOn(conn.pool, 'acquire').mockImplementation(() => {
|
||||||
return {
|
return {
|
||||||
release: () => {},
|
release: () => {},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const mock_send = jest.fn();
|
const mock_send = jest.fn();
|
||||||
connection.prototype.send = async () => {
|
connection.prototype.send = async () => {
|
||||||
return mock_send();
|
return mock_send();
|
||||||
};
|
};
|
||||||
mock_send.mockRejectedValue(new Error('mock send failed'));
|
mock_send.mockRejectedValue(new Error('mock send failed'));
|
||||||
|
|
||||||
await expect(conn.send('', new packet())).rejects.toThrow(Error);
|
await expect(conn.send('', new packet())).rejects.toThrow(Error);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import { get_version, instance_id, package_json } from '../utils/constants';
|
import { get_version, instance_id, package_json } from '../utils/constants';
|
||||||
import * as uuid from 'uuid';
|
import * as uuid from 'uuid';
|
||||||
|
|
||||||
test(`can read 'package.json'`, () => {
|
test(`can read 'package.json'`, () => {
|
||||||
console.log(package_json);
|
console.log(package_json);
|
||||||
expect(package_json).toBeDefined();
|
expect(package_json).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
test(`'instance_id' is valid`, () => {
|
test(`'instance_id' is valid`, () => {
|
||||||
console.log(instance_id);
|
console.log(instance_id);
|
||||||
expect(instance_id).toBeDefined();
|
expect(instance_id).toBeDefined();
|
||||||
expect(uuid.parse(instance_id)).toBeInstanceOf(Uint8Array);
|
expect(uuid.parse(instance_id)).toBeInstanceOf(Uint8Array);
|
||||||
});
|
});
|
||||||
|
|
||||||
test(`'version' can be read from 'package.json'`, () => {
|
test(`'version' can be read from 'package.json'`, () => {
|
||||||
console.log(get_version());
|
console.log(get_version());
|
||||||
expect(get_version()).toBe('1.4.0-r1');
|
expect(get_version()).toBe('1.4.0-r1');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,47 +1,47 @@
|
|||||||
import file from '../io/file';
|
import file from '../io/file';
|
||||||
|
|
||||||
jest.mock('../ops/index.js', () => ({
|
jest.mock('../ops/index.js', () => ({
|
||||||
...jest.requireActual('../ops/index.js'),
|
...jest.requireActual('../ops/index.js'),
|
||||||
close_file: jest.fn(),
|
close_file: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
import { close_file } from '../ops/index';
|
import { close_file } from '../ops/index';
|
||||||
|
|
||||||
test(`can close a closed file`, async () => {
|
test(`can close a closed file`, async () => {
|
||||||
const f = new file();
|
const f = new file();
|
||||||
expect(await f.close()).toEqual(0);
|
expect(await f.close()).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test(`'get_size' fails on closed file`, async () => {
|
test(`'get_size' fails on closed file`, async () => {
|
||||||
const f = new file();
|
const f = new file();
|
||||||
await expect(f.get_size()).rejects.toThrow(Error);
|
await expect(f.get_size()).rejects.toThrow(Error);
|
||||||
});
|
});
|
||||||
|
|
||||||
test(`'read' fails on closed file`, async () => {
|
test(`'read' fails on closed file`, async () => {
|
||||||
const f = new file();
|
const f = new file();
|
||||||
await expect(f.read(0, 10)).rejects.toThrow(Error);
|
await expect(f.read(0, 10)).rejects.toThrow(Error);
|
||||||
});
|
});
|
||||||
|
|
||||||
test(`'truncate' fails on closed file`, async () => {
|
test(`'truncate' fails on closed file`, async () => {
|
||||||
const f = new file();
|
const f = new file();
|
||||||
await expect(f.truncate(0)).rejects.toThrow(Error);
|
await expect(f.truncate(0)).rejects.toThrow(Error);
|
||||||
});
|
});
|
||||||
|
|
||||||
test(`'write' fails on closed file`, async () => {
|
test(`'write' fails on closed file`, async () => {
|
||||||
const f = new file();
|
const f = new file();
|
||||||
await expect(f.write(0, Buffer.alloc(2))).rejects.toThrow(Error);
|
await expect(f.write(0, Buffer.alloc(2))).rejects.toThrow(Error);
|
||||||
});
|
});
|
||||||
|
|
||||||
test(`handle is set to null on close`, async () => {
|
test(`handle is set to null on close`, async () => {
|
||||||
const f = new file(null, 1, '/path');
|
const f = new file(null, 1, '/path');
|
||||||
close_file.mockReturnValue(0);
|
close_file.mockReturnValue(0);
|
||||||
expect(await f.close()).toEqual(0);
|
expect(await f.close()).toEqual(0);
|
||||||
expect(f.handle).toBeNull();
|
expect(f.handle).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
test(`handle is not changed on close if return is not 0`, async () => {
|
test(`handle is not changed on close if return is not 0`, async () => {
|
||||||
const f = new file(null, 1, '/path');
|
const f = new file(null, 1, '/path');
|
||||||
close_file.mockReturnValue(1);
|
close_file.mockReturnValue(1);
|
||||||
expect(await f.close()).toEqual(1);
|
expect(await f.close()).toEqual(1);
|
||||||
expect(f.handle).toBe(1);
|
expect(f.handle).toBe(1);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
import packet from '../networking/packet';
|
import packet from '../networking/packet';
|
||||||
|
|
||||||
test('can construct a packet', () => {
|
test('can construct a packet', () => {
|
||||||
const p = new packet('my password');
|
const p = new packet('my password');
|
||||||
console.log(p);
|
console.log(p);
|
||||||
expect(p.token).toEqual('my password');
|
expect(p.token).toEqual('my password');
|
||||||
expect(p.buffer).toEqual(new Uint8Array(0));
|
expect(p.buffer).toEqual(new Uint8Array(0));
|
||||||
expect(p.decode_offset).toEqual(0);
|
expect(p.decode_offset).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('can encrypt and decrypt a packet', async () => {
|
test('can encrypt and decrypt a packet', async () => {
|
||||||
console.log('testing');
|
console.log('testing');
|
||||||
const p = new packet('my password');
|
const p = new packet('my password');
|
||||||
p.encode_utf8('moose');
|
p.encode_utf8('moose');
|
||||||
await p.encrypt();
|
await p.encrypt();
|
||||||
await p.decrypt();
|
await p.decrypt();
|
||||||
const str = p.decode_utf8();
|
const str = p.decode_utf8();
|
||||||
expect(str).toEqual('moose');
|
expect(str).toEqual('moose');
|
||||||
});
|
});
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
188
src/index.js
188
src/index.js
@@ -1,94 +1,94 @@
|
|||||||
import file from './io/file';
|
import file from './io/file';
|
||||||
import connection from './networking/connection';
|
import connection from './networking/connection';
|
||||||
import connection_pool from './networking/connection_pool';
|
import connection_pool from './networking/connection_pool';
|
||||||
import * as ops from './ops';
|
import * as ops from './ops';
|
||||||
|
|
||||||
export * as byte_order from './utils/byte_order';
|
export * as byte_order from './utils/byte_order';
|
||||||
export { getCustomEncryption, setCustomEncryption } from './utils/constants';
|
export { getCustomEncryption, setCustomEncryption } from './utils/constants';
|
||||||
export { default as packet } from './networking/packet';
|
export { default as packet } from './networking/packet';
|
||||||
|
|
||||||
export const connect = async (host_or_ip, port, password) => {
|
export const connect = async (host_or_ip, port, password) => {
|
||||||
const conn = new connection(host_or_ip, port, password);
|
const conn = new connection(host_or_ip, port, password);
|
||||||
await conn.connect();
|
await conn.connect();
|
||||||
return conn;
|
return conn;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const create_api = (conn) => {
|
export const create_api = (conn) => {
|
||||||
return {
|
return {
|
||||||
directory: {
|
directory: {
|
||||||
create: async (remote_path) => ops.create_directory(conn, remote_path),
|
create: async (remote_path) => ops.create_directory(conn, remote_path),
|
||||||
exists: async (remote_path) => {
|
exists: async (remote_path) => {
|
||||||
try {
|
try {
|
||||||
const info = await ops.get_file_attributes2(conn, remote_path);
|
const info = await ops.get_file_attributes2(conn, remote_path);
|
||||||
return info.directory;
|
return info.directory;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.message.split(':')[1].trim() == '-2') {
|
if (e.message.split(':')[1].trim() == '-2') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
throw new Error(e.message);
|
throw new Error(e.message);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
list: async (remote_path, page_reader_cb) =>
|
list: async (remote_path, page_reader_cb) =>
|
||||||
ops.list_directory(conn, remote_path, page_reader_cb),
|
ops.list_directory(conn, remote_path, page_reader_cb),
|
||||||
remove: async (remote_path) => ops.remove_directory(conn, remote_path),
|
remove: async (remote_path) => ops.remove_directory(conn, remote_path),
|
||||||
snapshot: async (remote_path) => {
|
snapshot: async (remote_path) => {
|
||||||
return ops.snapshot_directory(conn, remote_path);
|
return ops.snapshot_directory(conn, remote_path);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
file: {
|
file: {
|
||||||
create_or_open: async (remote_path) =>
|
create_or_open: async (remote_path) =>
|
||||||
new file(
|
new file(
|
||||||
conn,
|
conn,
|
||||||
await ops.create_or_open_file(conn, remote_path),
|
await ops.create_or_open_file(conn, remote_path),
|
||||||
remote_path
|
remote_path
|
||||||
),
|
),
|
||||||
download: async (
|
download: async (
|
||||||
remote_path,
|
remote_path,
|
||||||
local_path,
|
local_path,
|
||||||
progress_cb,
|
progress_cb,
|
||||||
overwrite,
|
overwrite,
|
||||||
resume
|
resume
|
||||||
) =>
|
) =>
|
||||||
ops.download_file(
|
ops.download_file(
|
||||||
conn,
|
conn,
|
||||||
remote_path,
|
remote_path,
|
||||||
local_path,
|
local_path,
|
||||||
progress_cb,
|
progress_cb,
|
||||||
overwrite,
|
overwrite,
|
||||||
resume
|
resume
|
||||||
),
|
),
|
||||||
exists: async (remote_path) => {
|
exists: async (remote_path) => {
|
||||||
try {
|
try {
|
||||||
const info = await ops.get_file_attributes2(conn, remote_path);
|
const info = await ops.get_file_attributes2(conn, remote_path);
|
||||||
return !info.directory;
|
return !info.directory;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.message.split(':')[1].trim() == '-2') {
|
if (e.message.split(':')[1].trim() == '-2') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
throw new Error(e.message);
|
throw new Error(e.message);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
open: async (remote_path) =>
|
open: async (remote_path) =>
|
||||||
new file(conn, await ops.open_file(conn, remote_path), remote_path),
|
new file(conn, await ops.open_file(conn, remote_path), remote_path),
|
||||||
remove: async (remote_path) => ops.remove_file(conn, remote_path),
|
remove: async (remote_path) => ops.remove_file(conn, remote_path),
|
||||||
upload: async (local_path, remote_path, progress_cb, overwrite, resume) =>
|
upload: async (local_path, remote_path, progress_cb, overwrite, resume) =>
|
||||||
ops.upload_file(
|
ops.upload_file(
|
||||||
conn,
|
conn,
|
||||||
local_path,
|
local_path,
|
||||||
remote_path,
|
remote_path,
|
||||||
progress_cb,
|
progress_cb,
|
||||||
overwrite,
|
overwrite,
|
||||||
resume
|
resume
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
get_drive_information: async () => ops.get_drive_information(conn),
|
get_drive_information: async () => ops.get_drive_information(conn),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const create_pool = async (pool_size, host_or_ip, port, password) => {
|
export const create_pool = async (pool_size, host_or_ip, port, password) => {
|
||||||
if (pool_size <= 1) {
|
if (pool_size <= 1) {
|
||||||
return connect(host_or_ip, port, password);
|
return connect(host_or_ip, port, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new connection_pool(pool_size, host_or_ip, port, password);
|
return new connection_pool(pool_size, host_or_ip, port, password);
|
||||||
};
|
};
|
||||||
|
|||||||
216
src/io/file.js
216
src/io/file.js
@@ -1,108 +1,108 @@
|
|||||||
import * as ops from '../ops';
|
import * as ops from '../ops';
|
||||||
|
|
||||||
let next_thread_id = 1;
|
let next_thread_id = 1;
|
||||||
|
|
||||||
export default class file {
|
export default class file {
|
||||||
constructor(conn, handle, remote_path) {
|
constructor(conn, handle, remote_path) {
|
||||||
this.conn = conn;
|
this.conn = conn;
|
||||||
this.handle = handle || null;
|
this.handle = handle || null;
|
||||||
this.remote_path = remote_path;
|
this.remote_path = remote_path;
|
||||||
this.thread_id = next_thread_id++;
|
this.thread_id = next_thread_id++;
|
||||||
}
|
}
|
||||||
|
|
||||||
conn;
|
conn;
|
||||||
handle = null;
|
handle = null;
|
||||||
thread_id;
|
thread_id;
|
||||||
remote_path;
|
remote_path;
|
||||||
|
|
||||||
async close() {
|
async close() {
|
||||||
if (this.handle !== null) {
|
if (this.handle !== null) {
|
||||||
const result = await ops.close_file(
|
const result = await ops.close_file(
|
||||||
this.conn,
|
this.conn,
|
||||||
this.remote_path,
|
this.remote_path,
|
||||||
this.handle,
|
this.handle,
|
||||||
this.thread_id
|
this.thread_id
|
||||||
);
|
);
|
||||||
if (result === 0) {
|
if (result === 0) {
|
||||||
this.handle = null;
|
this.handle = null;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
async get_size() {
|
async get_size() {
|
||||||
if (this.handle === null) {
|
if (this.handle === null) {
|
||||||
return Promise.reject(new Error("'get_size()' failed: invalid handle"));
|
return Promise.reject(new Error("'get_size()' failed: invalid handle"));
|
||||||
}
|
}
|
||||||
|
|
||||||
const attrs = await ops.get_file_attributes(
|
const attrs = await ops.get_file_attributes(
|
||||||
this.conn,
|
this.conn,
|
||||||
this.handle,
|
this.handle,
|
||||||
this.remote_path,
|
this.remote_path,
|
||||||
this.thread_id
|
this.thread_id
|
||||||
);
|
);
|
||||||
return attrs.size;
|
return attrs.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
async read(offset, length) {
|
async read(offset, length) {
|
||||||
if (this.handle === null) {
|
if (this.handle === null) {
|
||||||
return Promise.reject(new Error("'read()' failed: invalid handle"));
|
return Promise.reject(new Error("'read()' failed: invalid handle"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ops.read_file(
|
return ops.read_file(
|
||||||
this.conn,
|
this.conn,
|
||||||
this.handle,
|
this.handle,
|
||||||
this.remote_path,
|
this.remote_path,
|
||||||
offset,
|
offset,
|
||||||
length,
|
length,
|
||||||
this.thread_id
|
this.thread_id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async truncate(length) {
|
async truncate(length) {
|
||||||
if (this.handle === null) {
|
if (this.handle === null) {
|
||||||
return Promise.reject(new Error("'truncate()' failed: invalid handle"));
|
return Promise.reject(new Error("'truncate()' failed: invalid handle"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ops.truncate_file(
|
return ops.truncate_file(
|
||||||
this.conn,
|
this.conn,
|
||||||
this.handle,
|
this.handle,
|
||||||
this.remote_path,
|
this.remote_path,
|
||||||
length,
|
length,
|
||||||
this.thread_id
|
this.thread_id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async write(offset, buffer) {
|
async write(offset, buffer) {
|
||||||
if (this.handle === null) {
|
if (this.handle === null) {
|
||||||
return Promise.reject(new Error("'write()' failed: invalid handle"));
|
return Promise.reject(new Error("'write()' failed: invalid handle"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ops.write_file(
|
return ops.write_file(
|
||||||
this.conn,
|
this.conn,
|
||||||
this.handle,
|
this.handle,
|
||||||
this.remote_path,
|
this.remote_path,
|
||||||
offset,
|
offset,
|
||||||
buffer,
|
buffer,
|
||||||
this.thread_id
|
this.thread_id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async write_base64(offset, base64_string) {
|
async write_base64(offset, base64_string) {
|
||||||
if (this.handle === null) {
|
if (this.handle === null) {
|
||||||
return Promise.reject(
|
return Promise.reject(
|
||||||
new Error("'write_base64()' failed: invalid handle")
|
new Error("'write_base64()' failed: invalid handle")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return ops.write_base64_file(
|
return ops.write_base64_file(
|
||||||
this.conn,
|
this.conn,
|
||||||
this.handle,
|
this.handle,
|
||||||
this.remote_path,
|
this.remote_path,
|
||||||
offset,
|
offset,
|
||||||
base64_string,
|
base64_string,
|
||||||
this.thread_id
|
this.thread_id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,172 +1,177 @@
|
|||||||
import Socket from 'net';
|
import Socket from 'net';
|
||||||
|
|
||||||
import * as constants from '../utils/constants';
|
import * as constants from '../utils/constants';
|
||||||
|
|
||||||
import packet from './packet';
|
import packet from './packet';
|
||||||
|
|
||||||
export default class connection {
|
export default class connection {
|
||||||
constructor(host_or_ip, port, password, socket) {
|
constructor(host_or_ip, port, password, socket) {
|
||||||
this.host_or_ip = host_or_ip;
|
this.host_or_ip = host_or_ip;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
this.password = password;
|
this.password = password;
|
||||||
if (socket) {
|
if (socket) {
|
||||||
this.socket = socket;
|
this.socket = socket;
|
||||||
this.connected = true;
|
this.connected = true;
|
||||||
this.setup_socket();
|
this.setup_socket();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
connected = false;
|
connected = false;
|
||||||
host_or_ip = '';
|
host_or_ip = '';
|
||||||
password = '';
|
nonce = '';
|
||||||
port = 20000;
|
password = '';
|
||||||
reject;
|
port = 20000;
|
||||||
resolve;
|
reject;
|
||||||
socket;
|
resolve;
|
||||||
|
socket;
|
||||||
cleanup_handlers() {
|
|
||||||
this.reject = null;
|
cleanup_handlers() {
|
||||||
this.resolve = null;
|
this.reject = null;
|
||||||
}
|
this.resolve = null;
|
||||||
|
}
|
||||||
async connect() {
|
|
||||||
if (!this.socket) {
|
async connect() {
|
||||||
try {
|
if (!this.socket) {
|
||||||
await new Promise((resolve, reject) => {
|
try {
|
||||||
this.socket = Socket.createConnection(
|
await new Promise((resolve, reject) => {
|
||||||
this.port,
|
this.socket = Socket.createConnection(
|
||||||
this.host_or_ip,
|
this.port,
|
||||||
(err) => {
|
this.host_or_ip,
|
||||||
if (err) {
|
(err) => {
|
||||||
console.log(err);
|
if (err) {
|
||||||
return reject(err);
|
console.log(err);
|
||||||
}
|
return reject(err);
|
||||||
return resolve();
|
}
|
||||||
}
|
|
||||||
);
|
this.reject = reject;
|
||||||
});
|
this.resolve = resolve;
|
||||||
} catch (err) {
|
}
|
||||||
return Promise.reject(new Error(`'connect()' failed: ${err}`));
|
);
|
||||||
}
|
});
|
||||||
|
} catch (err) {
|
||||||
this.connected = true;
|
return Promise.reject(new Error(`'connect()' failed: ${err}`));
|
||||||
this.setup_socket();
|
}
|
||||||
}
|
|
||||||
}
|
this.connected = true;
|
||||||
|
this.setup_socket();
|
||||||
setup_socket() {
|
}
|
||||||
let buffer;
|
}
|
||||||
const cleanup = () => {
|
|
||||||
this.cleanup_handlers();
|
setup_socket() {
|
||||||
buffer = null;
|
let buffer;
|
||||||
};
|
const cleanup = () => {
|
||||||
if (this.socket._socket) {
|
this.cleanup_handlers();
|
||||||
this.socket._socket.setNoDelay(true);
|
buffer = null;
|
||||||
this.socket._socket.setKeepAlive(true);
|
};
|
||||||
} else {
|
if (this.socket._socket) {
|
||||||
this.socket.setNoDelay(true);
|
this.socket._socket.setNoDelay(true);
|
||||||
this.socket.setKeepAlive(true);
|
this.socket._socket.setKeepAlive(true);
|
||||||
}
|
} else {
|
||||||
|
this.socket.setNoDelay(true);
|
||||||
this.socket.on('data', (chunk) => {
|
this.socket.setKeepAlive(true);
|
||||||
buffer = buffer ? Buffer.concat([buffer, chunk]) : chunk;
|
}
|
||||||
if (buffer.length > 4) {
|
|
||||||
const size = buffer.readUInt32BE(0);
|
this.socket.on('data', (chunk) => {
|
||||||
if (buffer.length >= size + 4) {
|
buffer = buffer ? Buffer.concat([buffer, chunk]) : chunk;
|
||||||
const packet_data = buffer.slice(4, 4 + size);
|
if (buffer.length > 4) {
|
||||||
if (this.resolve) {
|
const size = buffer.readUInt32BE(0);
|
||||||
const complete = () => {
|
if (buffer.length >= size + 4) {
|
||||||
const reject = this.reject;
|
const packet_data = buffer.slice(4, 4 + size);
|
||||||
const resolve = this.resolve;
|
if (this.resolve) {
|
||||||
cleanup();
|
const complete = () => {
|
||||||
return {
|
const reject = this.reject;
|
||||||
reject,
|
const resolve = this.resolve;
|
||||||
resolve,
|
cleanup();
|
||||||
};
|
return {
|
||||||
};
|
reject,
|
||||||
|
resolve,
|
||||||
const response = new packet(this.password);
|
};
|
||||||
response.buffer = new Uint8Array(packet_data);
|
};
|
||||||
response
|
|
||||||
.decrypt()
|
const response = new packet(this.password);
|
||||||
.then(() => {
|
response.buffer = new Uint8Array(packet_data);
|
||||||
const { resolve } = complete();
|
response
|
||||||
if (resolve) {
|
.decrypt()
|
||||||
resolve(response);
|
.then(() => {
|
||||||
}
|
this.nonce = response.decode_utf8();
|
||||||
})
|
const { resolve } = complete();
|
||||||
.catch((e) => {
|
if (resolve) {
|
||||||
console.log(e);
|
resolve(response);
|
||||||
const { reject } = complete();
|
}
|
||||||
if (reject) {
|
})
|
||||||
reject(e);
|
.catch((e) => {
|
||||||
}
|
console.log(e);
|
||||||
});
|
const { reject } = complete();
|
||||||
}
|
if (reject) {
|
||||||
}
|
reject(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
this.socket.on('error', (e) => {
|
}
|
||||||
if (this.reject) {
|
}
|
||||||
const reject = this.reject;
|
});
|
||||||
|
|
||||||
cleanup();
|
this.socket.on('error', (e) => {
|
||||||
|
if (this.reject) {
|
||||||
this.connected = false;
|
const reject = this.reject;
|
||||||
console.log(e);
|
|
||||||
if (reject) {
|
cleanup();
|
||||||
reject(e);
|
|
||||||
}
|
this.connected = false;
|
||||||
}
|
console.log(e);
|
||||||
});
|
if (reject) {
|
||||||
|
reject(e);
|
||||||
this.socket.on('close', () => {
|
}
|
||||||
if (this.reject) {
|
}
|
||||||
const reject = this.reject;
|
});
|
||||||
|
|
||||||
cleanup();
|
this.socket.on('close', () => {
|
||||||
|
if (this.reject) {
|
||||||
this.connected = false;
|
const reject = this.reject;
|
||||||
console.log('socket closed');
|
|
||||||
if (reject) {
|
cleanup();
|
||||||
reject(new Error('socket closed'));
|
|
||||||
}
|
this.connected = false;
|
||||||
}
|
console.log('socket closed');
|
||||||
});
|
if (reject) {
|
||||||
}
|
reject(new Error('socket closed'));
|
||||||
|
}
|
||||||
async disconnect() {
|
}
|
||||||
try {
|
});
|
||||||
if (this.socket) {
|
}
|
||||||
this.socket.destroy();
|
|
||||||
this.socket = null;
|
async disconnect() {
|
||||||
this.cleanup_handlers();
|
try {
|
||||||
this.connected = false;
|
if (this.socket) {
|
||||||
}
|
this.socket.destroy();
|
||||||
} catch (e) {
|
this.socket = null;
|
||||||
console.log(e);
|
this.cleanup_handlers();
|
||||||
}
|
this.connected = false;
|
||||||
}
|
}
|
||||||
|
} catch (e) {
|
||||||
async send(method_name, packet, optional_thread_id) {
|
console.log(e);
|
||||||
packet.token = this.password;
|
}
|
||||||
packet.encode_top_utf8(method_name);
|
}
|
||||||
packet.encode_top_ui64(optional_thread_id || 1);
|
|
||||||
packet.encode_top_utf8(constants.instance_id);
|
async send(method_name, packet, optional_thread_id) {
|
||||||
packet.encode_top_ui32(0); // Service flags
|
packet.token = this.password;
|
||||||
packet.encode_top_utf8(constants.get_version());
|
packet.encode_top_utf8(method_name);
|
||||||
await packet.encrypt();
|
packet.encode_top_ui64(optional_thread_id || 1);
|
||||||
packet.encode_top_ui32(packet.buffer.length);
|
packet.encode_top_utf8(constants.instance_id);
|
||||||
return new Promise((resolve, reject) => {
|
packet.encode_top_ui32(0); // Service flags
|
||||||
this.reject = reject;
|
packet.encode_top_utf8(constants.get_version());
|
||||||
this.resolve = resolve;
|
packet.encode_top_utf8(nonce);
|
||||||
this.socket.write(Buffer.from(packet.buffer), null, (err) => {
|
await packet.encrypt();
|
||||||
if (err) {
|
packet.encode_top_ui32(packet.buffer.length);
|
||||||
this.cleanup_handlers();
|
return new Promise((resolve, reject) => {
|
||||||
reject(err);
|
this.reject = reject;
|
||||||
}
|
this.resolve = resolve;
|
||||||
});
|
this.socket.write(Buffer.from(packet.buffer), null, (err) => {
|
||||||
});
|
if (err) {
|
||||||
}
|
this.cleanup_handlers();
|
||||||
}
|
reject(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,69 +1,69 @@
|
|||||||
import Pool from 'socket-pool';
|
import Pool from 'socket-pool';
|
||||||
|
|
||||||
import connection from './connection';
|
import connection from './connection';
|
||||||
|
|
||||||
export default class connection_pool {
|
export default class connection_pool {
|
||||||
constructor(pool_size, host_or_ip, port, password) {
|
constructor(pool_size, host_or_ip, port, password) {
|
||||||
this.host_or_ip = host_or_ip;
|
this.host_or_ip = host_or_ip;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
this.password = password;
|
this.password = password;
|
||||||
if (pool_size > 1) {
|
if (pool_size > 1) {
|
||||||
this.pool = new Pool({
|
this.pool = new Pool({
|
||||||
connect: { host: host_or_ip, port: port },
|
connect: { host: host_or_ip, port: port },
|
||||||
connectTimeout: 5000,
|
connectTimeout: 5000,
|
||||||
pool: { max: pool_size, min: 2 },
|
pool: { max: pool_size, min: 2 },
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
throw new Error("'pool_size' must be > 1");
|
throw new Error("'pool_size' must be > 1");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
host_or_ip = '';
|
host_or_ip = '';
|
||||||
next_thread_id = 1;
|
next_thread_id = 1;
|
||||||
password = '';
|
password = '';
|
||||||
port = 20000;
|
port = 20000;
|
||||||
pool;
|
pool;
|
||||||
shutdown = false;
|
shutdown = false;
|
||||||
|
|
||||||
async disconnect() {
|
async disconnect() {
|
||||||
await this.pool._pool.drain();
|
await this.pool._pool.drain();
|
||||||
await this.pool._pool.clear();
|
await this.pool._pool.clear();
|
||||||
this.pool = null;
|
this.pool = null;
|
||||||
this.shutdown = true;
|
this.shutdown = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async send(method_name, packet, optional_thread_id) {
|
async send(method_name, packet, optional_thread_id) {
|
||||||
try {
|
try {
|
||||||
const socket = await this.pool.acquire();
|
const socket = await this.pool.acquire();
|
||||||
if (!socket.thread_id) {
|
if (!socket.thread_id) {
|
||||||
socket.thread_id = this.next_thread_id++;
|
socket.thread_id = this.next_thread_id++;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cleanup = () => {
|
const cleanup = () => {
|
||||||
try {
|
try {
|
||||||
socket.release();
|
socket.release();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(`'release()' failed: ${err}`);
|
console.log(`'release()' failed: ${err}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await new connection(
|
const result = await new connection(
|
||||||
this.host_or_ip,
|
this.host_or_ip,
|
||||||
this.port,
|
this.port,
|
||||||
this.password,
|
this.password,
|
||||||
socket
|
socket
|
||||||
).send(method_name, packet, optional_thread_id || socket.thread_id);
|
).send(method_name, packet, optional_thread_id || socket.thread_id);
|
||||||
cleanup();
|
cleanup();
|
||||||
return result;
|
return result;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
cleanup();
|
cleanup();
|
||||||
return Promise.reject(
|
return Promise.reject(
|
||||||
new Error(`'send(${method_name})' failed: ${err}`)
|
new Error(`'send(${method_name})' failed: ${err}`)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return Promise.reject(new Error(`'acquire()' socket failed: ${err}`));
|
return Promise.reject(new Error(`'acquire()' socket failed: ${err}`));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,330 +1,330 @@
|
|||||||
import { randomBytes } from 'crypto';
|
import { randomBytes } from 'crypto';
|
||||||
import { Int64BE, Uint64BE } from 'int64-buffer';
|
import { Int64BE, Uint64BE } from 'int64-buffer';
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
import { TextEncoder } from 'text-encoding';
|
import { TextEncoder } from 'text-encoding';
|
||||||
import { getCustomEncryption } from '../utils/constants';
|
import { getCustomEncryption } from '../utils/constants';
|
||||||
import {
|
import {
|
||||||
be_ui8_array_to_i16,
|
be_ui8_array_to_i16,
|
||||||
be_ui8_array_to_i32,
|
be_ui8_array_to_i32,
|
||||||
be_ui8_array_to_ui16,
|
be_ui8_array_to_ui16,
|
||||||
be_ui8_array_to_ui32,
|
be_ui8_array_to_ui32,
|
||||||
i16_to_be_ui8_array,
|
i16_to_be_ui8_array,
|
||||||
i32_to_be_ui8_array,
|
i32_to_be_ui8_array,
|
||||||
i8_to_ui8_array,
|
i8_to_ui8_array,
|
||||||
ui16_to_be_ui8_array,
|
ui16_to_be_ui8_array,
|
||||||
ui32_to_be_ui8_array,
|
ui32_to_be_ui8_array,
|
||||||
ui8_array_to_i8,
|
ui8_array_to_i8,
|
||||||
ui8_array_to_ui8,
|
ui8_array_to_ui8,
|
||||||
ui8_to_ui8_array,
|
ui8_to_ui8_array,
|
||||||
} from '../utils/byte_order';
|
} from '../utils/byte_order';
|
||||||
import { XChaCha20Poly1305 } from '@stablelib/xchacha20poly1305';
|
import { XChaCha20Poly1305 } from '@stablelib/xchacha20poly1305';
|
||||||
|
|
||||||
export default class packet {
|
export default class packet {
|
||||||
constructor(token) {
|
constructor(token) {
|
||||||
this.token = token;
|
this.token = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = new Uint8Array(0);
|
buffer = new Uint8Array(0);
|
||||||
decode_offset = 0;
|
decode_offset = 0;
|
||||||
token;
|
token;
|
||||||
|
|
||||||
append_buffer = (buffer) => {
|
append_buffer = (buffer) => {
|
||||||
if (!(buffer instanceof Uint8Array)) {
|
if (!(buffer instanceof Uint8Array)) {
|
||||||
throw new Error('Buffer must be of type Uint8Array');
|
throw new Error('Buffer must be of type Uint8Array');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.buffer = this.buffer
|
this.buffer = this.buffer
|
||||||
? new Uint8Array([...this.buffer, ...buffer])
|
? new Uint8Array([...this.buffer, ...buffer])
|
||||||
: buffer;
|
: buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
clear = () => {
|
clear = () => {
|
||||||
this.buffer = null;
|
this.buffer = null;
|
||||||
this.decode_offset = 0;
|
this.decode_offset = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
decode_buffer = (length) => {
|
decode_buffer = (length) => {
|
||||||
if (!this.buffer) {
|
if (!this.buffer) {
|
||||||
throw new Error('Invalid buffer');
|
throw new Error('Invalid buffer');
|
||||||
}
|
}
|
||||||
|
|
||||||
const ret = this.buffer.slice(
|
const ret = this.buffer.slice(
|
||||||
this.decode_offset,
|
this.decode_offset,
|
||||||
this.decode_offset + length
|
this.decode_offset + length
|
||||||
);
|
);
|
||||||
this.decode_offset += length;
|
this.decode_offset += length;
|
||||||
return Buffer.from(ret);
|
return Buffer.from(ret);
|
||||||
};
|
};
|
||||||
|
|
||||||
decode_stat = () => {
|
decode_stat = () => {
|
||||||
const mode = this.decode_ui16();
|
const mode = this.decode_ui16();
|
||||||
const nlink = this.decode_ui16();
|
const nlink = this.decode_ui16();
|
||||||
const uid = this.decode_ui32();
|
const uid = this.decode_ui32();
|
||||||
const gid = this.decode_ui32();
|
const gid = this.decode_ui32();
|
||||||
const atime = this.decode_ui64();
|
const atime = this.decode_ui64();
|
||||||
const mtime = this.decode_ui64();
|
const mtime = this.decode_ui64();
|
||||||
const ctime = this.decode_ui64();
|
const ctime = this.decode_ui64();
|
||||||
const birth_time = this.decode_ui64();
|
const birth_time = this.decode_ui64();
|
||||||
const size = this.decode_ui64();
|
const size = this.decode_ui64();
|
||||||
const blocks = this.decode_ui64();
|
const blocks = this.decode_ui64();
|
||||||
const blksize = this.decode_ui32();
|
const blksize = this.decode_ui32();
|
||||||
const flags = this.decode_ui32();
|
const flags = this.decode_ui32();
|
||||||
const directory = !!this.decode_ui8();
|
const directory = !!this.decode_ui8();
|
||||||
return {
|
return {
|
||||||
mode,
|
mode,
|
||||||
nlink,
|
nlink,
|
||||||
uid,
|
uid,
|
||||||
gid,
|
gid,
|
||||||
atime,
|
atime,
|
||||||
mtime,
|
mtime,
|
||||||
ctime,
|
ctime,
|
||||||
birth_time,
|
birth_time,
|
||||||
size,
|
size,
|
||||||
blocks,
|
blocks,
|
||||||
blksize,
|
blksize,
|
||||||
flags,
|
flags,
|
||||||
directory,
|
directory,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
decode_utf8 = () => {
|
decode_utf8 = () => {
|
||||||
if (!this.buffer) {
|
if (!this.buffer) {
|
||||||
throw new Error('Invalid buffer');
|
throw new Error('Invalid buffer');
|
||||||
}
|
}
|
||||||
|
|
||||||
const startIndex = this.decode_offset;
|
const startIndex = this.decode_offset;
|
||||||
const endIndex = this.buffer.indexOf(0, startIndex);
|
const endIndex = this.buffer.indexOf(0, startIndex);
|
||||||
if (endIndex >= 0) {
|
if (endIndex >= 0) {
|
||||||
let ret = '';
|
let ret = '';
|
||||||
for (let i = startIndex; i < endIndex; i++) {
|
for (let i = startIndex; i < endIndex; i++) {
|
||||||
ret += String.fromCharCode(this.buffer[i]);
|
ret += String.fromCharCode(this.buffer[i]);
|
||||||
}
|
}
|
||||||
this.decode_offset = endIndex + 1;
|
this.decode_offset = endIndex + 1;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error('String not found in buffer');
|
throw new Error('String not found in buffer');
|
||||||
};
|
};
|
||||||
|
|
||||||
decode_i8 = () => {
|
decode_i8 = () => {
|
||||||
return ui8_array_to_i8(this.buffer, this.decode_offset++);
|
return ui8_array_to_i8(this.buffer, this.decode_offset++);
|
||||||
};
|
};
|
||||||
|
|
||||||
decode_ui8 = () => {
|
decode_ui8 = () => {
|
||||||
return ui8_array_to_ui8(this.buffer, this.decode_offset++);
|
return ui8_array_to_ui8(this.buffer, this.decode_offset++);
|
||||||
};
|
};
|
||||||
|
|
||||||
decode_i16 = () => {
|
decode_i16 = () => {
|
||||||
const ret = be_ui8_array_to_i16(this.buffer, this.decode_offset);
|
const ret = be_ui8_array_to_i16(this.buffer, this.decode_offset);
|
||||||
this.decode_offset += 2;
|
this.decode_offset += 2;
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
decode_ui16 = () => {
|
decode_ui16 = () => {
|
||||||
const ret = be_ui8_array_to_ui16(this.buffer, this.decode_offset);
|
const ret = be_ui8_array_to_ui16(this.buffer, this.decode_offset);
|
||||||
this.decode_offset += 2;
|
this.decode_offset += 2;
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
decode_i32 = () => {
|
decode_i32 = () => {
|
||||||
const ret = be_ui8_array_to_i32(this.buffer, this.decode_offset);
|
const ret = be_ui8_array_to_i32(this.buffer, this.decode_offset);
|
||||||
this.decode_offset += 4;
|
this.decode_offset += 4;
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
decode_ui32 = () => {
|
decode_ui32 = () => {
|
||||||
const ret = be_ui8_array_to_ui32(this.buffer, this.decode_offset);
|
const ret = be_ui8_array_to_ui32(this.buffer, this.decode_offset);
|
||||||
this.decode_offset += 4;
|
this.decode_offset += 4;
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
decode_i64 = () => {
|
decode_i64 = () => {
|
||||||
const ret = new Int64BE(
|
const ret = new Int64BE(
|
||||||
this.buffer.slice(this.decode_offset, this.decode_offset + 8)
|
this.buffer.slice(this.decode_offset, this.decode_offset + 8)
|
||||||
);
|
);
|
||||||
this.decode_offset += 8;
|
this.decode_offset += 8;
|
||||||
return ret.toString(10);
|
return ret.toString(10);
|
||||||
};
|
};
|
||||||
|
|
||||||
decode_ui64 = () => {
|
decode_ui64 = () => {
|
||||||
const ret = new Uint64BE(
|
const ret = new Uint64BE(
|
||||||
this.buffer.slice(this.decode_offset, this.decode_offset + 8)
|
this.buffer.slice(this.decode_offset, this.decode_offset + 8)
|
||||||
);
|
);
|
||||||
this.decode_offset += 8;
|
this.decode_offset += 8;
|
||||||
return ret.toString(10);
|
return ret.toString(10);
|
||||||
};
|
};
|
||||||
|
|
||||||
decrypt = async () => {
|
decrypt = async () => {
|
||||||
try {
|
try {
|
||||||
let hash = crypto.createHash('sha256');
|
let hash = crypto.createHash('sha256');
|
||||||
hash = hash.update(new TextEncoder().encode(this.token));
|
hash = hash.update(new TextEncoder().encode(this.token));
|
||||||
|
|
||||||
const key = Uint8Array.from(hash.digest());
|
const key = Uint8Array.from(hash.digest());
|
||||||
const nonce = this.buffer.slice(0, 24);
|
const nonce = this.buffer.slice(0, 24);
|
||||||
const mac = this.buffer.slice(24, 16 + 24);
|
const mac = this.buffer.slice(24, 16 + 24);
|
||||||
|
|
||||||
const customEncryption = getCustomEncryption();
|
const customEncryption = getCustomEncryption();
|
||||||
if (customEncryption) {
|
if (customEncryption) {
|
||||||
this.buffer = Buffer.from(
|
this.buffer = Buffer.from(
|
||||||
await customEncryption.decrypt(
|
await customEncryption.decrypt(
|
||||||
Buffer.from(key).toString('base64'),
|
Buffer.from(key).toString('base64'),
|
||||||
Buffer.from(nonce).toString('base64'),
|
Buffer.from(nonce).toString('base64'),
|
||||||
Buffer.from(mac).toString('base64'),
|
Buffer.from(mac).toString('base64'),
|
||||||
Buffer.from(this.buffer.slice(40)).toString('base64')
|
Buffer.from(this.buffer.slice(40)).toString('base64')
|
||||||
),
|
),
|
||||||
'base64'
|
'base64'
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
const aad = ui32_to_be_ui8_array(this.buffer.length);
|
const aad = ui32_to_be_ui8_array(this.buffer.length);
|
||||||
this.buffer = new Uint8Array([
|
this.buffer = new Uint8Array([
|
||||||
...this.buffer.slice(nonce.length + mac.length),
|
...this.buffer.slice(nonce.length + mac.length),
|
||||||
...this.buffer.slice(nonce.length, nonce.length + mac.length),
|
...this.buffer.slice(nonce.length, nonce.length + mac.length),
|
||||||
]);
|
]);
|
||||||
const result = new XChaCha20Poly1305(key).open(nonce, this.buffer, aad);
|
const result = new XChaCha20Poly1305(key).open(nonce, this.buffer, aad);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
throw new Error('decryption failed');
|
throw new Error('decryption failed');
|
||||||
}
|
}
|
||||||
this.buffer = Buffer.from(result);
|
this.buffer = Buffer.from(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.buffer = new Uint8Array(this.buffer);
|
this.buffer = new Uint8Array(this.buffer);
|
||||||
return this.buffer;
|
return this.buffer;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return Promise.reject(e);
|
return Promise.reject(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
encode_buffer = (buffer) => {
|
encode_buffer = (buffer) => {
|
||||||
this.append_buffer(new Uint8Array(buffer));
|
this.append_buffer(new Uint8Array(buffer));
|
||||||
};
|
};
|
||||||
|
|
||||||
encode_i8 = (num) => {
|
encode_i8 = (num) => {
|
||||||
this.append_buffer(i8_to_ui8_array(num));
|
this.append_buffer(i8_to_ui8_array(num));
|
||||||
};
|
};
|
||||||
|
|
||||||
encode_top_i8 = (num) => {
|
encode_top_i8 = (num) => {
|
||||||
this.push_buffer(i8_to_ui8_array(num));
|
this.push_buffer(i8_to_ui8_array(num));
|
||||||
};
|
};
|
||||||
|
|
||||||
encode_u8 = (num) => {
|
encode_u8 = (num) => {
|
||||||
this.append_buffer(ui8_to_ui8_array(num));
|
this.append_buffer(ui8_to_ui8_array(num));
|
||||||
};
|
};
|
||||||
|
|
||||||
encode_top_u8 = (num) => {
|
encode_top_u8 = (num) => {
|
||||||
this.push_buffer(ui8_to_ui8_array(num));
|
this.push_buffer(ui8_to_ui8_array(num));
|
||||||
};
|
};
|
||||||
|
|
||||||
encode_i16 = (num) => {
|
encode_i16 = (num) => {
|
||||||
this.append_buffer(i16_to_be_ui8_array(num));
|
this.append_buffer(i16_to_be_ui8_array(num));
|
||||||
};
|
};
|
||||||
|
|
||||||
encode_top_i16 = (num) => {
|
encode_top_i16 = (num) => {
|
||||||
this.push_buffer(i16_to_be_ui8_array(num));
|
this.push_buffer(i16_to_be_ui8_array(num));
|
||||||
};
|
};
|
||||||
|
|
||||||
encode_ui16 = (num) => {
|
encode_ui16 = (num) => {
|
||||||
this.append_buffer(ui16_to_be_ui8_array(num));
|
this.append_buffer(ui16_to_be_ui8_array(num));
|
||||||
};
|
};
|
||||||
|
|
||||||
encode_top_ui16 = (num) => {
|
encode_top_ui16 = (num) => {
|
||||||
this.push_buffer(ui16_to_be_ui8_array(num));
|
this.push_buffer(ui16_to_be_ui8_array(num));
|
||||||
};
|
};
|
||||||
|
|
||||||
encode_i32 = (num) => {
|
encode_i32 = (num) => {
|
||||||
this.append_buffer(i32_to_be_ui8_array(num));
|
this.append_buffer(i32_to_be_ui8_array(num));
|
||||||
};
|
};
|
||||||
|
|
||||||
encode_top_i32 = (num) => {
|
encode_top_i32 = (num) => {
|
||||||
this.push_buffer(i32_to_be_ui8_array(num));
|
this.push_buffer(i32_to_be_ui8_array(num));
|
||||||
};
|
};
|
||||||
|
|
||||||
encode_ui32 = (num) => {
|
encode_ui32 = (num) => {
|
||||||
this.append_buffer(ui32_to_be_ui8_array(num));
|
this.append_buffer(ui32_to_be_ui8_array(num));
|
||||||
};
|
};
|
||||||
|
|
||||||
encode_top_ui32 = (num) => {
|
encode_top_ui32 = (num) => {
|
||||||
this.push_buffer(ui32_to_be_ui8_array(num));
|
this.push_buffer(ui32_to_be_ui8_array(num));
|
||||||
};
|
};
|
||||||
|
|
||||||
encode_i64 = (num) => {
|
encode_i64 = (num) => {
|
||||||
this.append_buffer(new Uint8Array(new Int64BE(num).toArray()));
|
this.append_buffer(new Uint8Array(new Int64BE(num).toArray()));
|
||||||
};
|
};
|
||||||
|
|
||||||
encode_top_i64 = (num) => {
|
encode_top_i64 = (num) => {
|
||||||
this.push_buffer(new Uint8Array(new Int64BE(num).toArray()));
|
this.push_buffer(new Uint8Array(new Int64BE(num).toArray()));
|
||||||
};
|
};
|
||||||
|
|
||||||
encode_ui64 = (num) => {
|
encode_ui64 = (num) => {
|
||||||
this.append_buffer(new Uint8Array(new Uint64BE(num).toArray()));
|
this.append_buffer(new Uint8Array(new Uint64BE(num).toArray()));
|
||||||
};
|
};
|
||||||
|
|
||||||
encode_top_ui64 = (num) => {
|
encode_top_ui64 = (num) => {
|
||||||
this.push_buffer(new Uint8Array(new Uint64BE(num).toArray()));
|
this.push_buffer(new Uint8Array(new Uint64BE(num).toArray()));
|
||||||
};
|
};
|
||||||
|
|
||||||
encode_utf8 = (str) => {
|
encode_utf8 = (str) => {
|
||||||
if (!(typeof str === 'string' || str instanceof String)) {
|
if (!(typeof str === 'string' || str instanceof String)) {
|
||||||
throw new Error('Value must be of type string');
|
throw new Error('Value must be of type string');
|
||||||
}
|
}
|
||||||
|
|
||||||
const buffer = new Uint8Array([...new TextEncoder().encode(str), 0]);
|
const buffer = new Uint8Array([...new TextEncoder().encode(str), 0]);
|
||||||
this.append_buffer(buffer);
|
this.append_buffer(buffer);
|
||||||
};
|
};
|
||||||
|
|
||||||
encode_top_utf8 = (str) => {
|
encode_top_utf8 = (str) => {
|
||||||
if (!(typeof str === 'string' || str instanceof String)) {
|
if (!(typeof str === 'string' || str instanceof String)) {
|
||||||
throw new Error('Value must be of type string');
|
throw new Error('Value must be of type string');
|
||||||
}
|
}
|
||||||
|
|
||||||
const buffer = new Uint8Array([...new TextEncoder().encode(str), 0]);
|
const buffer = new Uint8Array([...new TextEncoder().encode(str), 0]);
|
||||||
this.push_buffer(buffer);
|
this.push_buffer(buffer);
|
||||||
};
|
};
|
||||||
|
|
||||||
encrypt = async (nonce) => {
|
encrypt = async (nonce) => {
|
||||||
try {
|
try {
|
||||||
let hash = crypto.createHash('sha256');
|
let hash = crypto.createHash('sha256');
|
||||||
hash = hash.update(new TextEncoder().encode(this.token));
|
hash = hash.update(new TextEncoder().encode(this.token));
|
||||||
|
|
||||||
const key = Uint8Array.from(hash.digest());
|
const key = Uint8Array.from(hash.digest());
|
||||||
if (!nonce) {
|
if (!nonce) {
|
||||||
nonce = Uint8Array.from(randomBytes(24));
|
nonce = Uint8Array.from(randomBytes(24));
|
||||||
}
|
}
|
||||||
|
|
||||||
const customEncryption = getCustomEncryption();
|
const customEncryption = getCustomEncryption();
|
||||||
if (customEncryption) {
|
if (customEncryption) {
|
||||||
this.buffer = new Uint8Array(
|
this.buffer = new Uint8Array(
|
||||||
Buffer.from(
|
Buffer.from(
|
||||||
await customEncryption.encrypt(
|
await customEncryption.encrypt(
|
||||||
Buffer.from(key).toString('base64'),
|
Buffer.from(key).toString('base64'),
|
||||||
Buffer.from(nonce).toString('base64'),
|
Buffer.from(nonce).toString('base64'),
|
||||||
Buffer.from(this.buffer).toString('base64')
|
Buffer.from(this.buffer).toString('base64')
|
||||||
),
|
),
|
||||||
'base64'
|
'base64'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
const aad = ui32_to_be_ui8_array(this.buffer.length + 40);
|
const aad = ui32_to_be_ui8_array(this.buffer.length + 40);
|
||||||
this.buffer = new XChaCha20Poly1305(key).seal(nonce, this.buffer, aad);
|
this.buffer = new XChaCha20Poly1305(key).seal(nonce, this.buffer, aad);
|
||||||
this.buffer = new Uint8Array([
|
this.buffer = new Uint8Array([
|
||||||
...this.buffer.slice(this.buffer.length - 16),
|
...this.buffer.slice(this.buffer.length - 16),
|
||||||
...this.buffer.slice(0, this.buffer.length - 16),
|
...this.buffer.slice(0, this.buffer.length - 16),
|
||||||
]);
|
]);
|
||||||
this.push_buffer(nonce);
|
this.push_buffer(nonce);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.buffer;
|
return this.buffer;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return Promise.reject(e);
|
return Promise.reject(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
push_buffer = (buffer) => {
|
push_buffer = (buffer) => {
|
||||||
if (!(buffer instanceof Uint8Array)) {
|
if (!(buffer instanceof Uint8Array)) {
|
||||||
throw new Error('Buffer must be of type Uint8Array');
|
throw new Error('Buffer must be of type Uint8Array');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.buffer = this.buffer
|
this.buffer = this.buffer
|
||||||
? new Uint8Array([...buffer, ...this.buffer])
|
? new Uint8Array([...buffer, ...this.buffer])
|
||||||
: buffer;
|
: buffer;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
1289
src/ops/index.js
1289
src/ops/index.js
File diff suppressed because it is too large
Load Diff
@@ -1,112 +1,112 @@
|
|||||||
export const is_big_endian_system =
|
export const is_big_endian_system =
|
||||||
new Uint8Array(new Uint32Array([0x12345678]).buffer)[0] === 0x12;
|
new Uint8Array(new Uint32Array([0x12345678]).buffer)[0] === 0x12;
|
||||||
|
|
||||||
export const is_little_endian_system =
|
export const is_little_endian_system =
|
||||||
new Uint8Array(new Uint32Array([0x12345678]).buffer)[0] === 0x78;
|
new Uint8Array(new Uint32Array([0x12345678]).buffer)[0] === 0x78;
|
||||||
|
|
||||||
export const i8_to_ui8_array = (num) => {
|
export const i8_to_ui8_array = (num) => {
|
||||||
if (typeof num === 'string' || num instanceof String) {
|
if (typeof num === 'string' || num instanceof String) {
|
||||||
num = parseInt(num, 10);
|
num = parseInt(num, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
const buffer = Buffer.alloc(1);
|
const buffer = Buffer.alloc(1);
|
||||||
buffer.writeInt8(num);
|
buffer.writeInt8(num);
|
||||||
return new Uint8Array(buffer);
|
return new Uint8Array(buffer);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ui8_array_to_i8 = (ar, offset) => {
|
export const ui8_array_to_i8 = (ar, offset) => {
|
||||||
const buffer = Buffer.alloc(1);
|
const buffer = Buffer.alloc(1);
|
||||||
buffer[0] = ar[offset];
|
buffer[0] = ar[offset];
|
||||||
|
|
||||||
return buffer.readInt8(0);
|
return buffer.readInt8(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ui8_to_ui8_array = (num) => {
|
export const ui8_to_ui8_array = (num) => {
|
||||||
if (typeof num === 'string' || num instanceof String) {
|
if (typeof num === 'string' || num instanceof String) {
|
||||||
num = parseInt(num, 10);
|
num = parseInt(num, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
const buffer = Buffer.alloc(1);
|
const buffer = Buffer.alloc(1);
|
||||||
buffer.writeUInt8(num);
|
buffer.writeUInt8(num);
|
||||||
return new Uint8Array(buffer);
|
return new Uint8Array(buffer);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ui8_array_to_ui8 = (ar, offset) => {
|
export const ui8_array_to_ui8 = (ar, offset) => {
|
||||||
const buffer = Buffer.alloc(1);
|
const buffer = Buffer.alloc(1);
|
||||||
buffer[0] = ar[offset];
|
buffer[0] = ar[offset];
|
||||||
|
|
||||||
return buffer.readUInt8(0);
|
return buffer.readUInt8(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const i16_to_be_ui8_array = (num) => {
|
export const i16_to_be_ui8_array = (num) => {
|
||||||
if (typeof num === 'string' || num instanceof String) {
|
if (typeof num === 'string' || num instanceof String) {
|
||||||
num = parseInt(num, 10);
|
num = parseInt(num, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
const buffer = Buffer.alloc(2);
|
const buffer = Buffer.alloc(2);
|
||||||
buffer.writeInt16BE(num);
|
buffer.writeInt16BE(num);
|
||||||
return new Uint8Array(buffer);
|
return new Uint8Array(buffer);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const be_ui8_array_to_i16 = (ar, offset) => {
|
export const be_ui8_array_to_i16 = (ar, offset) => {
|
||||||
const buffer = Buffer.alloc(2);
|
const buffer = Buffer.alloc(2);
|
||||||
for (let i = offset; i < buffer.length + offset; i++) {
|
for (let i = offset; i < buffer.length + offset; i++) {
|
||||||
buffer[i - offset] = ar[i];
|
buffer[i - offset] = ar[i];
|
||||||
}
|
}
|
||||||
return buffer.readInt16BE(0);
|
return buffer.readInt16BE(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ui16_to_be_ui8_array = (num) => {
|
export const ui16_to_be_ui8_array = (num) => {
|
||||||
if (typeof num === 'string' || num instanceof String) {
|
if (typeof num === 'string' || num instanceof String) {
|
||||||
num = parseInt(num, 10);
|
num = parseInt(num, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
const buffer = Buffer.alloc(2);
|
const buffer = Buffer.alloc(2);
|
||||||
buffer.writeUInt16BE(num);
|
buffer.writeUInt16BE(num);
|
||||||
return new Uint8Array(buffer);
|
return new Uint8Array(buffer);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const be_ui8_array_to_ui16 = (ar, offset) => {
|
export const be_ui8_array_to_ui16 = (ar, offset) => {
|
||||||
const buffer = Buffer.alloc(2);
|
const buffer = Buffer.alloc(2);
|
||||||
for (let i = offset; i < buffer.length + offset; i++) {
|
for (let i = offset; i < buffer.length + offset; i++) {
|
||||||
buffer[i - offset] = ar[i];
|
buffer[i - offset] = ar[i];
|
||||||
}
|
}
|
||||||
return buffer.readUInt16BE(0);
|
return buffer.readUInt16BE(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const i32_to_be_ui8_array = (num) => {
|
export const i32_to_be_ui8_array = (num) => {
|
||||||
if (typeof num === 'string' || num instanceof String) {
|
if (typeof num === 'string' || num instanceof String) {
|
||||||
num = parseInt(num, 10);
|
num = parseInt(num, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
const buffer = Buffer.alloc(4);
|
const buffer = Buffer.alloc(4);
|
||||||
buffer.writeInt32BE(num);
|
buffer.writeInt32BE(num);
|
||||||
return new Uint8Array(buffer);
|
return new Uint8Array(buffer);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const be_ui8_array_to_i32 = (ar, offset) => {
|
export const be_ui8_array_to_i32 = (ar, offset) => {
|
||||||
const buffer = Buffer.alloc(4);
|
const buffer = Buffer.alloc(4);
|
||||||
for (let i = offset; i < buffer.length + offset; i++) {
|
for (let i = offset; i < buffer.length + offset; i++) {
|
||||||
buffer[i - offset] = ar[i];
|
buffer[i - offset] = ar[i];
|
||||||
}
|
}
|
||||||
return buffer.readInt32BE(0);
|
return buffer.readInt32BE(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ui32_to_be_ui8_array = (num) => {
|
export const ui32_to_be_ui8_array = (num) => {
|
||||||
if (typeof num === 'string' || num instanceof String) {
|
if (typeof num === 'string' || num instanceof String) {
|
||||||
num = parseInt(num, 10);
|
num = parseInt(num, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
const buffer = Buffer.alloc(4);
|
const buffer = Buffer.alloc(4);
|
||||||
buffer.writeUInt32BE(num);
|
buffer.writeUInt32BE(num);
|
||||||
return new Uint8Array(buffer);
|
return new Uint8Array(buffer);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const be_ui8_array_to_ui32 = (ar, offset) => {
|
export const be_ui8_array_to_ui32 = (ar, offset) => {
|
||||||
const buffer = Buffer.alloc(4);
|
const buffer = Buffer.alloc(4);
|
||||||
for (let i = offset; i < buffer.length + offset; i++) {
|
for (let i = offset; i < buffer.length + offset; i++) {
|
||||||
buffer[i - offset] = ar[i];
|
buffer[i - offset] = ar[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer.readUInt32BE(0);
|
return buffer.readUInt32BE(0);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
import _package_json from '../../package.json';
|
import _package_json from '../../package.json';
|
||||||
|
|
||||||
let customEncryption;
|
let customEncryption;
|
||||||
|
|
||||||
export const getCustomEncryption = () => {
|
export const getCustomEncryption = () => {
|
||||||
return customEncryption;
|
return customEncryption;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const setCustomEncryption = (ce) => {
|
export const setCustomEncryption = (ce) => {
|
||||||
customEncryption = ce;
|
customEncryption = ce;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const instance_id = uuidv4();
|
export const instance_id = uuidv4();
|
||||||
export const package_json = _package_json;
|
export const package_json = _package_json;
|
||||||
export const get_version = () => _package_json.version;
|
export const get_version = () => _package_json.version;
|
||||||
|
|||||||
Reference in New Issue
Block a user