added prettier
This commit is contained in:
6
.prettierrc.json
Normal file
6
.prettierrc.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"tabWidth": 2,
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": true
|
||||||
|
}
|
||||||
@@ -19,21 +19,23 @@ test(`socket receive data fails when decryption fails`, async () => {
|
|||||||
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(new Promise((_, r) => {
|
await expect(
|
||||||
reject = r;
|
new Promise((_, r) => {
|
||||||
cbl['data'](Buffer.from(p.buffer));
|
reject = r;
|
||||||
})).rejects.toThrow(Error);
|
cbl['data'](Buffer.from(p.buffer));
|
||||||
|
})
|
||||||
|
).rejects.toThrow(Error);
|
||||||
expect(mock_reject.mock.calls.length).toBe(1);
|
expect(mock_reject.mock.calls.length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -42,8 +44,7 @@ test(`disconnect succeeds if an error is thrown`, async () => {
|
|||||||
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);
|
||||||
@@ -56,7 +57,7 @@ test(`send fails on socket error`, async () => {
|
|||||||
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();
|
||||||
@@ -73,7 +74,7 @@ test(`error is thrown when socket is closed`, async () => {
|
|||||||
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();
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ test(`error on socket release is ignored`, async () => {
|
|||||||
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();
|
||||||
@@ -45,9 +45,8 @@ 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();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {get_version, instance_id, package_json} from '../utils/constants'
|
import { get_version, instance_id, package_json } from '../utils/constants';
|
||||||
|
|
||||||
const uuid = require('uuid');
|
const uuid = require('uuid');
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
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();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import {Uint64BE} from 'int64-buffer';
|
import { Uint64BE } from 'int64-buffer';
|
||||||
|
|
||||||
import * as repertory from '../index.js';
|
import * as repertory from '../index.js';
|
||||||
import connection from '../networking/connection';
|
import connection from '../networking/connection';
|
||||||
@@ -10,18 +10,18 @@ const TEST_HOST = process.env.TEST_HOST || 'localhost';
|
|||||||
const TEST_PASSWORD = process.env.TEST_PASSWORD || '';
|
const TEST_PASSWORD = process.env.TEST_PASSWORD || '';
|
||||||
const TEST_PORT = process.env.TEST_PORT || 20000;
|
const TEST_PORT = process.env.TEST_PORT || 20000;
|
||||||
|
|
||||||
const calculate_sha256 = path => {
|
const calculate_sha256 = (path) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const hash = crypto.createHash('sha256');
|
const hash = crypto.createHash('sha256');
|
||||||
|
|
||||||
fs.createReadStream(path)
|
fs.createReadStream(path)
|
||||||
.on('data', data => hash.update(data))
|
.on('data', (data) => hash.update(data))
|
||||||
.on('error', err => reject(err))
|
.on('error', (err) => reject(err))
|
||||||
.on('end', () => {
|
.on('end', () => {
|
||||||
const h = hash.digest('hex');
|
const h = hash.digest('hex');
|
||||||
console.log(path, h);
|
console.log(path, h);
|
||||||
resolve(h);
|
resolve(h);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -43,8 +43,12 @@ test('can create a connection to repertory api', async () => {
|
|||||||
|
|
||||||
test('create_pool returns a connection if pool size is <=1', async () => {
|
test('create_pool returns a connection if pool size is <=1', async () => {
|
||||||
for (let i = 0; i < 2; i++) {
|
for (let i = 0; i < 2; i++) {
|
||||||
const conn =
|
const conn = await repertory.create_pool(
|
||||||
await repertory.create_pool(i, TEST_HOST, TEST_PORT, TEST_PASSWORD);
|
i,
|
||||||
|
TEST_HOST,
|
||||||
|
TEST_PORT,
|
||||||
|
TEST_PASSWORD
|
||||||
|
);
|
||||||
expect(conn).toBeInstanceOf(connection);
|
expect(conn).toBeInstanceOf(connection);
|
||||||
test_connection(conn, true);
|
test_connection(conn, true);
|
||||||
|
|
||||||
@@ -53,8 +57,12 @@ test('create_pool returns a connection if pool size is <=1', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('can create a connection pool', async () => {
|
test('can create a connection pool', async () => {
|
||||||
const conn =
|
const conn = await repertory.create_pool(
|
||||||
await repertory.create_pool(2, TEST_HOST, TEST_PORT, TEST_PASSWORD);
|
2,
|
||||||
|
TEST_HOST,
|
||||||
|
TEST_PORT,
|
||||||
|
TEST_PASSWORD
|
||||||
|
);
|
||||||
console.log(conn);
|
console.log(conn);
|
||||||
expect(conn).toBeInstanceOf(connection_pool);
|
expect(conn).toBeInstanceOf(connection_pool);
|
||||||
expect(conn.host_or_ip).toEqual(TEST_HOST);
|
expect(conn.host_or_ip).toEqual(TEST_HOST);
|
||||||
@@ -68,8 +76,12 @@ test('can create a connection pool', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('can get drive information using api', async () => {
|
test('can get drive information using api', async () => {
|
||||||
const conn =
|
const conn = await repertory.create_pool(
|
||||||
await repertory.create_pool(2, TEST_HOST, TEST_PORT, TEST_PASSWORD);
|
2,
|
||||||
|
TEST_HOST,
|
||||||
|
TEST_PORT,
|
||||||
|
TEST_PASSWORD
|
||||||
|
);
|
||||||
const api = repertory.create_api(conn);
|
const api = repertory.create_api(conn);
|
||||||
const di = await api.get_drive_information();
|
const di = await api.get_drive_information();
|
||||||
console.log(di);
|
console.log(di);
|
||||||
@@ -82,8 +94,12 @@ test('can get drive information using api', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('can create and remove a directory using api', async () => {
|
test('can create and remove a directory using api', async () => {
|
||||||
const conn =
|
const conn = await repertory.create_pool(
|
||||||
await repertory.create_pool(2, TEST_HOST, TEST_PORT, TEST_PASSWORD);
|
2,
|
||||||
|
TEST_HOST,
|
||||||
|
TEST_PORT,
|
||||||
|
TEST_PASSWORD
|
||||||
|
);
|
||||||
const api = repertory.create_api(conn);
|
const api = repertory.create_api(conn);
|
||||||
expect(await api.directory.create('/repertory_js')).toEqual(0);
|
expect(await api.directory.create('/repertory_js')).toEqual(0);
|
||||||
expect(await api.directory.remove('/repertory_js')).toEqual(0);
|
expect(await api.directory.remove('/repertory_js')).toEqual(0);
|
||||||
@@ -92,8 +108,12 @@ test('can create and remove a directory using api', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('can get directory list and snapshot using api', async () => {
|
test('can get directory list and snapshot using api', async () => {
|
||||||
const conn =
|
const conn = await repertory.create_pool(
|
||||||
await repertory.create_pool(2, TEST_HOST, TEST_PORT, TEST_PASSWORD);
|
2,
|
||||||
|
TEST_HOST,
|
||||||
|
TEST_PORT,
|
||||||
|
TEST_PASSWORD
|
||||||
|
);
|
||||||
const api = repertory.create_api(conn);
|
const api = repertory.create_api(conn);
|
||||||
|
|
||||||
const test_results = async (remote_path, page_count, get_page) => {
|
const test_results = async (remote_path, page_count, get_page) => {
|
||||||
@@ -131,8 +151,12 @@ test('can get directory list and snapshot using api', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('can create, close and delete a file using api', async () => {
|
test('can create, close and delete a file using api', async () => {
|
||||||
const conn =
|
const conn = await repertory.create_pool(
|
||||||
await repertory.create_pool(2, TEST_HOST, TEST_PORT, TEST_PASSWORD);
|
2,
|
||||||
|
TEST_HOST,
|
||||||
|
TEST_PORT,
|
||||||
|
TEST_PASSWORD
|
||||||
|
);
|
||||||
const api = repertory.create_api(conn);
|
const api = repertory.create_api(conn);
|
||||||
const f = await api.file.create_or_open('/repertory_file.dat');
|
const f = await api.file.create_or_open('/repertory_file.dat');
|
||||||
console.log(f);
|
console.log(f);
|
||||||
@@ -149,8 +173,12 @@ test('can create, close and delete a file using api', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('can open, close and delete a file using api', async () => {
|
test('can open, close and delete a file using api', async () => {
|
||||||
const conn =
|
const conn = await repertory.create_pool(
|
||||||
await repertory.create_pool(2, TEST_HOST, TEST_PORT, TEST_PASSWORD);
|
2,
|
||||||
|
TEST_HOST,
|
||||||
|
TEST_PORT,
|
||||||
|
TEST_PASSWORD
|
||||||
|
);
|
||||||
const api = repertory.create_api(conn);
|
const api = repertory.create_api(conn);
|
||||||
let f = await api.file.create_or_open('/repertory_file.dat');
|
let f = await api.file.create_or_open('/repertory_file.dat');
|
||||||
expect(await f.close()).toEqual(0);
|
expect(await f.close()).toEqual(0);
|
||||||
@@ -170,8 +198,12 @@ test('can open, close and delete a file using api', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('can write to and read from a file using api', async () => {
|
test('can write to and read from a file using api', async () => {
|
||||||
const conn =
|
const conn = await repertory.create_pool(
|
||||||
await repertory.create_pool(2, TEST_HOST, TEST_PORT, TEST_PASSWORD);
|
2,
|
||||||
|
TEST_HOST,
|
||||||
|
TEST_PORT,
|
||||||
|
TEST_PASSWORD
|
||||||
|
);
|
||||||
const api = repertory.create_api(conn);
|
const api = repertory.create_api(conn);
|
||||||
const f = await api.file.create_or_open('/repertory_file.dat');
|
const f = await api.file.create_or_open('/repertory_file.dat');
|
||||||
|
|
||||||
@@ -193,8 +225,12 @@ test('can write to and read from a file using api', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('can truncate a file using api', async () => {
|
test('can truncate a file using api', async () => {
|
||||||
const conn =
|
const conn = await repertory.create_pool(
|
||||||
await repertory.create_pool(2, TEST_HOST, TEST_PORT, TEST_PASSWORD);
|
2,
|
||||||
|
TEST_HOST,
|
||||||
|
TEST_PORT,
|
||||||
|
TEST_PASSWORD
|
||||||
|
);
|
||||||
const api = repertory.create_api(conn);
|
const api = repertory.create_api(conn);
|
||||||
const f = await api.file.create_or_open('/repertory_file.dat');
|
const f = await api.file.create_or_open('/repertory_file.dat');
|
||||||
|
|
||||||
@@ -213,22 +249,34 @@ test('can truncate a file using api', async () => {
|
|||||||
test('can upload and download a file using api', async () => {
|
test('can upload and download a file using api', async () => {
|
||||||
try {
|
try {
|
||||||
fs.unlinkSync('repertory_test.dat');
|
fs.unlinkSync('repertory_test.dat');
|
||||||
} catch {
|
} catch {}
|
||||||
}
|
|
||||||
|
|
||||||
const conn =
|
const conn = await repertory.create_pool(
|
||||||
await repertory.create_pool(2, TEST_HOST, TEST_PORT, TEST_PASSWORD);
|
2,
|
||||||
|
TEST_HOST,
|
||||||
|
TEST_PORT,
|
||||||
|
TEST_PASSWORD
|
||||||
|
);
|
||||||
const api = repertory.create_api(conn);
|
const api = repertory.create_api(conn);
|
||||||
expect(await api.file.upload('test.dat', '/repertory_test.dat',
|
expect(
|
||||||
(l, r, p, c) => { console.log(l, r, p, c); }))
|
await api.file.upload('test.dat', '/repertory_test.dat', (l, r, p, c) => {
|
||||||
.toBeTruthy();
|
console.log(l, r, p, c);
|
||||||
|
})
|
||||||
|
).toBeTruthy();
|
||||||
|
|
||||||
expect(await api.file.download('/repertory_test.dat', 'repertory_test.dat',
|
expect(
|
||||||
(l, r, p, c) => { console.log(l, r, p, c); }))
|
await api.file.download(
|
||||||
.toBeTruthy();
|
'/repertory_test.dat',
|
||||||
|
'repertory_test.dat',
|
||||||
|
(l, r, p, c) => {
|
||||||
|
console.log(l, r, p, c);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
).toBeTruthy();
|
||||||
|
|
||||||
expect(await calculate_sha256('test.dat'))
|
expect(await calculate_sha256('test.dat')).toEqual(
|
||||||
.toEqual(await calculate_sha256('repertory_test.dat'));
|
await calculate_sha256('repertory_test.dat')
|
||||||
|
);
|
||||||
|
|
||||||
expect(await api.file.delete('/repertory_test.dat')).toEqual(0);
|
expect(await api.file.delete('/repertory_test.dat')).toEqual(0);
|
||||||
fs.unlinkSync('repertory_test.dat');
|
fs.unlinkSync('repertory_test.dat');
|
||||||
@@ -237,21 +285,39 @@ test('can upload and download a file using api', async () => {
|
|||||||
}, 60000);
|
}, 60000);
|
||||||
|
|
||||||
test('can download and overwrite a file using api', async () => {
|
test('can download and overwrite a file using api', async () => {
|
||||||
const conn =
|
const conn = await repertory.create_pool(
|
||||||
await repertory.create_pool(2, TEST_HOST, TEST_PORT, TEST_PASSWORD);
|
2,
|
||||||
|
TEST_HOST,
|
||||||
|
TEST_PORT,
|
||||||
|
TEST_PASSWORD
|
||||||
|
);
|
||||||
const api = repertory.create_api(conn);
|
const api = repertory.create_api(conn);
|
||||||
expect(await api.file.upload('test.dat', '/repertory_test.dat',
|
expect(
|
||||||
(l, r, p, c) => { console.log(l, r, p, c); }))
|
await api.file.upload('test.dat', '/repertory_test.dat', (l, r, p, c) => {
|
||||||
.toBeTruthy();
|
console.log(l, r, p, c);
|
||||||
|
})
|
||||||
|
).toBeTruthy();
|
||||||
|
|
||||||
expect(await api.file.download('/repertory_test.dat', 'repertory_test.dat',
|
expect(
|
||||||
(l, r, p, c) => { console.log(l, r, p, c); }))
|
await api.file.download(
|
||||||
.toBeTruthy();
|
'/repertory_test.dat',
|
||||||
|
'repertory_test.dat',
|
||||||
|
(l, r, p, c) => {
|
||||||
|
console.log(l, r, p, c);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
).toBeTruthy();
|
||||||
|
|
||||||
expect(await api.file.download('/repertory_test.dat', 'repertory_test.dat',
|
expect(
|
||||||
(l, r, p, c) => { console.log(l, r, p, c); },
|
await api.file.download(
|
||||||
true))
|
'/repertory_test.dat',
|
||||||
.toBeTruthy();
|
'repertory_test.dat',
|
||||||
|
(l, r, p, c) => {
|
||||||
|
console.log(l, r, p, c);
|
||||||
|
},
|
||||||
|
true
|
||||||
|
)
|
||||||
|
).toBeTruthy();
|
||||||
|
|
||||||
expect(await api.file.delete('/repertory_test.dat')).toEqual(0);
|
expect(await api.file.delete('/repertory_test.dat')).toEqual(0);
|
||||||
fs.unlinkSync('repertory_test.dat');
|
fs.unlinkSync('repertory_test.dat');
|
||||||
@@ -260,21 +326,39 @@ test('can download and overwrite a file using api', async () => {
|
|||||||
}, 60000);
|
}, 60000);
|
||||||
|
|
||||||
test('download fails if overwrite is false using api', async () => {
|
test('download fails if overwrite is false using api', async () => {
|
||||||
const conn =
|
const conn = await repertory.create_pool(
|
||||||
await repertory.create_pool(2, TEST_HOST, TEST_PORT, TEST_PASSWORD);
|
2,
|
||||||
|
TEST_HOST,
|
||||||
|
TEST_PORT,
|
||||||
|
TEST_PASSWORD
|
||||||
|
);
|
||||||
const api = repertory.create_api(conn);
|
const api = repertory.create_api(conn);
|
||||||
expect(await api.file.upload('test.dat', '/repertory_test.dat',
|
expect(
|
||||||
(l, r, p, c) => { console.log(l, r, p, c); }))
|
await api.file.upload('test.dat', '/repertory_test.dat', (l, r, p, c) => {
|
||||||
.toBeTruthy();
|
console.log(l, r, p, c);
|
||||||
|
})
|
||||||
|
).toBeTruthy();
|
||||||
|
|
||||||
expect(await api.file.download('/repertory_test.dat', 'repertory_test.dat',
|
expect(
|
||||||
(l, r, p, c) => { console.log(l, r, p, c); }))
|
await api.file.download(
|
||||||
.toBeTruthy();
|
'/repertory_test.dat',
|
||||||
|
'repertory_test.dat',
|
||||||
|
(l, r, p, c) => {
|
||||||
|
console.log(l, r, p, c);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
).toBeTruthy();
|
||||||
|
|
||||||
await expect(api.file.download('/repertory_test.dat', 'repertory_test.dat',
|
await expect(
|
||||||
(l, r, p, c) => { console.log(l, r, p, c); },
|
api.file.download(
|
||||||
false))
|
'/repertory_test.dat',
|
||||||
.rejects.toThrow(Error);
|
'repertory_test.dat',
|
||||||
|
(l, r, p, c) => {
|
||||||
|
console.log(l, r, p, c);
|
||||||
|
},
|
||||||
|
false
|
||||||
|
)
|
||||||
|
).rejects.toThrow(Error);
|
||||||
|
|
||||||
expect(await api.file.delete('/repertory_test.dat')).toEqual(0);
|
expect(await api.file.delete('/repertory_test.dat')).toEqual(0);
|
||||||
fs.unlinkSync('repertory_test.dat');
|
fs.unlinkSync('repertory_test.dat');
|
||||||
@@ -283,17 +367,29 @@ test('download fails if overwrite is false using api', async () => {
|
|||||||
}, 60000);
|
}, 60000);
|
||||||
|
|
||||||
test('can upload and overwrite a file using api', async () => {
|
test('can upload and overwrite a file using api', async () => {
|
||||||
const conn =
|
const conn = await repertory.create_pool(
|
||||||
await repertory.create_pool(2, TEST_HOST, TEST_PORT, TEST_PASSWORD);
|
2,
|
||||||
|
TEST_HOST,
|
||||||
|
TEST_PORT,
|
||||||
|
TEST_PASSWORD
|
||||||
|
);
|
||||||
const api = repertory.create_api(conn);
|
const api = repertory.create_api(conn);
|
||||||
expect(await api.file.upload('test.dat', '/repertory_test.dat',
|
expect(
|
||||||
(l, r, p, c) => { console.log(l, r, p, c); }))
|
await api.file.upload('test.dat', '/repertory_test.dat', (l, r, p, c) => {
|
||||||
.toBeTruthy();
|
console.log(l, r, p, c);
|
||||||
|
})
|
||||||
|
).toBeTruthy();
|
||||||
|
|
||||||
expect(await api.file.upload('test.dat', '/repertory_test.dat',
|
expect(
|
||||||
(l, r, p, c) => { console.log(l, r, p, c); },
|
await api.file.upload(
|
||||||
true))
|
'test.dat',
|
||||||
.toBeTruthy();
|
'/repertory_test.dat',
|
||||||
|
(l, r, p, c) => {
|
||||||
|
console.log(l, r, p, c);
|
||||||
|
},
|
||||||
|
true
|
||||||
|
)
|
||||||
|
).toBeTruthy();
|
||||||
|
|
||||||
expect(await api.file.delete('/repertory_test.dat')).toEqual(0);
|
expect(await api.file.delete('/repertory_test.dat')).toEqual(0);
|
||||||
|
|
||||||
@@ -301,17 +397,29 @@ test('can upload and overwrite a file using api', async () => {
|
|||||||
}, 60000);
|
}, 60000);
|
||||||
|
|
||||||
test('upload fails if overwrite is false using api', async () => {
|
test('upload fails if overwrite is false using api', async () => {
|
||||||
const conn =
|
const conn = await repertory.create_pool(
|
||||||
await repertory.create_pool(2, TEST_HOST, TEST_PORT, TEST_PASSWORD);
|
2,
|
||||||
|
TEST_HOST,
|
||||||
|
TEST_PORT,
|
||||||
|
TEST_PASSWORD
|
||||||
|
);
|
||||||
const api = repertory.create_api(conn);
|
const api = repertory.create_api(conn);
|
||||||
expect(await api.file.upload('test.dat', '/repertory_test.dat',
|
expect(
|
||||||
(l, r, p, c) => { console.log(l, r, p, c); }))
|
await api.file.upload('test.dat', '/repertory_test.dat', (l, r, p, c) => {
|
||||||
.toBeTruthy();
|
console.log(l, r, p, c);
|
||||||
|
})
|
||||||
|
).toBeTruthy();
|
||||||
|
|
||||||
await expect(api.file.upload('test.dat', '/repertory_test.dat',
|
await expect(
|
||||||
(l, r, p, c) => { console.log(l, r, p, c); },
|
api.file.upload(
|
||||||
false))
|
'test.dat',
|
||||||
.rejects.toThrow(Error);
|
'/repertory_test.dat',
|
||||||
|
(l, r, p, c) => {
|
||||||
|
console.log(l, r, p, c);
|
||||||
|
},
|
||||||
|
false
|
||||||
|
)
|
||||||
|
).rejects.toThrow(Error);
|
||||||
|
|
||||||
expect(await api.file.delete('/repertory_test.dat')).toEqual(0);
|
expect(await api.file.delete('/repertory_test.dat')).toEqual(0);
|
||||||
|
|
||||||
@@ -319,12 +427,18 @@ test('upload fails if overwrite is false using api', async () => {
|
|||||||
}, 60000);
|
}, 60000);
|
||||||
|
|
||||||
test('can resume download using api', async () => {
|
test('can resume download using api', async () => {
|
||||||
const conn =
|
const conn = await repertory.create_pool(
|
||||||
await repertory.create_pool(2, TEST_HOST, TEST_PORT, TEST_PASSWORD);
|
2,
|
||||||
|
TEST_HOST,
|
||||||
|
TEST_PORT,
|
||||||
|
TEST_PASSWORD
|
||||||
|
);
|
||||||
const api = repertory.create_api(conn);
|
const api = repertory.create_api(conn);
|
||||||
expect(await api.file.upload('test.dat', '/repertory_test.dat',
|
expect(
|
||||||
(l, r, p, c) => { console.log(l, r, p, c); }))
|
await api.file.upload('test.dat', '/repertory_test.dat', (l, r, p, c) => {
|
||||||
.toBeTruthy();
|
console.log(l, r, p, c);
|
||||||
|
})
|
||||||
|
).toBeTruthy();
|
||||||
|
|
||||||
const fd = fs.openSync('test.dat', 'r');
|
const fd = fs.openSync('test.dat', 'r');
|
||||||
const buffer = Buffer.alloc(1024);
|
const buffer = Buffer.alloc(1024);
|
||||||
@@ -333,13 +447,21 @@ test('can resume download using api', async () => {
|
|||||||
|
|
||||||
fs.writeFileSync('repertory_test.dat', buffer);
|
fs.writeFileSync('repertory_test.dat', buffer);
|
||||||
|
|
||||||
expect(await api.file.download('/repertory_test.dat', 'repertory_test.dat',
|
expect(
|
||||||
(l, r, p, c) => { console.log(l, r, p, c); },
|
await api.file.download(
|
||||||
false, true))
|
'/repertory_test.dat',
|
||||||
.toBeTruthy();
|
'repertory_test.dat',
|
||||||
|
(l, r, p, c) => {
|
||||||
|
console.log(l, r, p, c);
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
).toBeTruthy();
|
||||||
|
|
||||||
expect(await calculate_sha256('test.dat'))
|
expect(await calculate_sha256('test.dat')).toEqual(
|
||||||
.toEqual(await calculate_sha256('repertory_test.dat'));
|
await calculate_sha256('repertory_test.dat')
|
||||||
|
);
|
||||||
|
|
||||||
expect(await api.file.delete('/repertory_test.dat')).toEqual(0);
|
expect(await api.file.delete('/repertory_test.dat')).toEqual(0);
|
||||||
fs.unlinkSync('repertory_test.dat');
|
fs.unlinkSync('repertory_test.dat');
|
||||||
@@ -348,8 +470,12 @@ test('can resume download using api', async () => {
|
|||||||
}, 60000);
|
}, 60000);
|
||||||
|
|
||||||
test('can resume upload using api', async () => {
|
test('can resume upload using api', async () => {
|
||||||
const conn =
|
const conn = await repertory.create_pool(
|
||||||
await repertory.create_pool(2, TEST_HOST, TEST_PORT, TEST_PASSWORD);
|
2,
|
||||||
|
TEST_HOST,
|
||||||
|
TEST_PORT,
|
||||||
|
TEST_PASSWORD
|
||||||
|
);
|
||||||
const api = repertory.create_api(conn);
|
const api = repertory.create_api(conn);
|
||||||
|
|
||||||
const fd = fs.openSync('test.dat', 'r');
|
const fd = fs.openSync('test.dat', 'r');
|
||||||
@@ -361,17 +487,31 @@ test('can resume upload using api', async () => {
|
|||||||
await f.write(0, buffer);
|
await f.write(0, buffer);
|
||||||
await f.close();
|
await f.close();
|
||||||
|
|
||||||
expect(await api.file.upload('test.dat', '/repertory_test.dat',
|
expect(
|
||||||
(l, r, p, c) => { console.log(l, r, p, c); },
|
await api.file.upload(
|
||||||
false, true))
|
'test.dat',
|
||||||
.toBeTruthy();
|
'/repertory_test.dat',
|
||||||
|
(l, r, p, c) => {
|
||||||
|
console.log(l, r, p, c);
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
).toBeTruthy();
|
||||||
|
|
||||||
expect(await api.file.download('/repertory_test.dat', 'repertory_test.dat',
|
expect(
|
||||||
(l, r, p, c) => { console.log(l, r, p, c); }))
|
await api.file.download(
|
||||||
.toBeTruthy();
|
'/repertory_test.dat',
|
||||||
|
'repertory_test.dat',
|
||||||
|
(l, r, p, c) => {
|
||||||
|
console.log(l, r, p, c);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
).toBeTruthy();
|
||||||
|
|
||||||
expect(await calculate_sha256('test.dat'))
|
expect(await calculate_sha256('test.dat')).toEqual(
|
||||||
.toEqual(await calculate_sha256('repertory_test.dat'));
|
await calculate_sha256('repertory_test.dat')
|
||||||
|
);
|
||||||
|
|
||||||
expect(await api.file.delete('/repertory_test.dat')).toEqual(0);
|
expect(await api.file.delete('/repertory_test.dat')).toEqual(0);
|
||||||
fs.unlinkSync('repertory_test.dat');
|
fs.unlinkSync('repertory_test.dat');
|
||||||
|
|||||||
64
src/index.js
64
src/index.js
@@ -1,7 +1,7 @@
|
|||||||
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 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);
|
||||||
@@ -9,33 +9,53 @@ export const connect = async (host_or_ip, port, password) => {
|
|||||||
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),
|
||||||
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 => new file(
|
create_or_open: async (remote_path) =>
|
||||||
conn, await ops.create_or_open_file(conn, remote_path), remote_path),
|
new file(
|
||||||
delete : async (remote_path) => ops.delete_file(conn, remote_path),
|
conn,
|
||||||
download :
|
await ops.create_or_open_file(conn, remote_path),
|
||||||
async (remote_path, local_path, progress_cb, overwrite, resume) =>
|
remote_path
|
||||||
ops.download_file(conn, remote_path, local_path, progress_cb,
|
),
|
||||||
overwrite, resume),
|
delete: async (remote_path) => ops.delete_file(conn, remote_path),
|
||||||
open : async remote_path =>
|
download: async (
|
||||||
new file(conn, await ops.open_file(conn, remote_path), remote_path),
|
remote_path,
|
||||||
upload :
|
local_path,
|
||||||
async (local_path, remote_path, progress_cb, overwrite, resume) =>
|
progress_cb,
|
||||||
ops.upload_file(conn, local_path, remote_path, progress_cb,
|
overwrite,
|
||||||
overwrite, resume),
|
resume
|
||||||
|
) =>
|
||||||
|
ops.download_file(
|
||||||
|
conn,
|
||||||
|
remote_path,
|
||||||
|
local_path,
|
||||||
|
progress_cb,
|
||||||
|
overwrite,
|
||||||
|
resume
|
||||||
|
),
|
||||||
|
open: async (remote_path) =>
|
||||||
|
new file(conn, await ops.open_file(conn, remote_path), remote_path),
|
||||||
|
upload: async (local_path, remote_path, progress_cb, overwrite, resume) =>
|
||||||
|
ops.upload_file(
|
||||||
|
conn,
|
||||||
|
local_path,
|
||||||
|
remote_path,
|
||||||
|
progress_cb,
|
||||||
|
overwrite,
|
||||||
|
resume
|
||||||
|
),
|
||||||
},
|
},
|
||||||
get_drive_information : async () => ops.get_drive_information(conn),
|
get_drive_information: async () => ops.get_drive_information(conn),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,12 @@ export default class file {
|
|||||||
|
|
||||||
async close() {
|
async close() {
|
||||||
if (this.handle !== null) {
|
if (this.handle !== null) {
|
||||||
const result = await ops.close_file(this.conn, this.remote_path,
|
const result = await ops.close_file(
|
||||||
this.handle, this.thread_id);
|
this.conn,
|
||||||
|
this.remote_path,
|
||||||
|
this.handle,
|
||||||
|
this.thread_id
|
||||||
|
);
|
||||||
if (result === 0) {
|
if (result === 0) {
|
||||||
this.handle = null;
|
this.handle = null;
|
||||||
}
|
}
|
||||||
@@ -30,38 +34,59 @@ export default class file {
|
|||||||
|
|
||||||
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.handle, this.remote_path, this.thread_id);
|
this.conn,
|
||||||
|
this.handle,
|
||||||
|
this.remote_path,
|
||||||
|
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(this.conn, this.handle, this.remote_path, offset,
|
return ops.read_file(
|
||||||
length, this.thread_id);
|
this.conn,
|
||||||
|
this.handle,
|
||||||
|
this.remote_path,
|
||||||
|
offset,
|
||||||
|
length,
|
||||||
|
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(this.conn, this.handle, this.remote_path, length,
|
return ops.truncate_file(
|
||||||
this.thread_id);
|
this.conn,
|
||||||
|
this.handle,
|
||||||
|
this.remote_path,
|
||||||
|
length,
|
||||||
|
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(this.conn, this.handle, this.remote_path, offset,
|
return ops.write_file(
|
||||||
buffer, this.thread_id);
|
this.conn,
|
||||||
|
this.handle,
|
||||||
|
this.remote_path,
|
||||||
|
offset,
|
||||||
|
buffer,
|
||||||
|
this.thread_id
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
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';
|
||||||
|
|
||||||
@@ -33,13 +33,16 @@ export default class connection {
|
|||||||
if (!this.socket) {
|
if (!this.socket) {
|
||||||
try {
|
try {
|
||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
this.socket =
|
this.socket = Socket.createConnection(
|
||||||
Socket.createConnection(this.port, this.host_or_ip, err => {
|
this.port,
|
||||||
|
this.host_or_ip,
|
||||||
|
(err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return reject(err)
|
return reject(err);
|
||||||
}
|
}
|
||||||
return resolve()
|
return resolve();
|
||||||
});
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return Promise.reject(new Error(`'connect()' failed: ${err}`));
|
return Promise.reject(new Error(`'connect()' failed: ${err}`));
|
||||||
@@ -57,7 +60,7 @@ export default class connection {
|
|||||||
buffer = null;
|
buffer = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.socket.on('data', chunk => {
|
this.socket.on('data', (chunk) => {
|
||||||
buffer = buffer ? Buffer.concat([buffer, chunk]) : chunk;
|
buffer = buffer ? Buffer.concat([buffer, chunk]) : chunk;
|
||||||
if (buffer.length > 4) {
|
if (buffer.length > 4) {
|
||||||
const size = buffer.readUInt32BE(0);
|
const size = buffer.readUInt32BE(0);
|
||||||
@@ -71,19 +74,20 @@ export default class connection {
|
|||||||
|
|
||||||
const response = new packet(this.password);
|
const response = new packet(this.password);
|
||||||
response.buffer = new Uint8Array(packet_data);
|
response.buffer = new Uint8Array(packet_data);
|
||||||
response.decrypt()
|
response
|
||||||
.then(() => {
|
.decrypt()
|
||||||
resolve(response)
|
.then(() => {
|
||||||
})
|
resolve(response);
|
||||||
.catch(e => {
|
})
|
||||||
reject(e)
|
.catch((e) => {
|
||||||
})
|
reject(e);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.socket.on('error', e => {
|
this.socket.on('error', (e) => {
|
||||||
if (this.reject) {
|
if (this.reject) {
|
||||||
const reject = this.reject;
|
const reject = this.reject;
|
||||||
|
|
||||||
@@ -115,7 +119,7 @@ export default class connection {
|
|||||||
this.connected = false;
|
this.connected = false;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e)
|
console.log(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +135,7 @@ export default class connection {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.reject = reject;
|
this.reject = reject;
|
||||||
this.resolve = resolve;
|
this.resolve = resolve;
|
||||||
this.socket.write(Buffer.from(packet.buffer), null, err => {
|
this.socket.write(Buffer.from(packet.buffer), null, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
this.cleanup_handlers();
|
this.cleanup_handlers();
|
||||||
reject(err);
|
reject(err);
|
||||||
|
|||||||
@@ -9,18 +9,18 @@ export default class connection_pool {
|
|||||||
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;
|
||||||
@@ -48,16 +48,19 @@ export default class connection_pool {
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await new connection(this.host_or_ip, this.port,
|
const result = await new connection(
|
||||||
this.password, socket)
|
this.host_or_ip,
|
||||||
.send(method_name, packet,
|
this.port,
|
||||||
optional_thread_id || socket.thread_id);
|
this.password,
|
||||||
|
socket
|
||||||
|
).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,7 +1,7 @@
|
|||||||
import {randomBytes} from 'crypto';
|
import { randomBytes } from 'crypto';
|
||||||
import {Int64BE, Uint64BE} from 'int64-buffer';
|
import { Int64BE, Uint64BE } from 'int64-buffer';
|
||||||
import {sha256} from 'js-sha256';
|
import { sha256 } from 'js-sha256';
|
||||||
import {TextEncoder} from 'text-encoding';
|
import { TextEncoder } from 'text-encoding';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
be_ui8_array_to_i16,
|
be_ui8_array_to_i16,
|
||||||
@@ -20,7 +20,9 @@ import {
|
|||||||
import JSChaCha20 from '../utils/jschacha20';
|
import JSChaCha20 from '../utils/jschacha20';
|
||||||
|
|
||||||
export default class packet {
|
export default class packet {
|
||||||
constructor(token) { this.token = token; }
|
constructor(token) {
|
||||||
|
this.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
static HEADER = new TextEncoder().encode('repertory');
|
static HEADER = new TextEncoder().encode('repertory');
|
||||||
|
|
||||||
@@ -28,13 +30,14 @@ export default class packet {
|
|||||||
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 ]) : buffer;
|
? new Uint8Array([...this.buffer, ...buffer])
|
||||||
|
: buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
clear = () => {
|
clear = () => {
|
||||||
@@ -42,13 +45,15 @@ export default class packet {
|
|||||||
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 =
|
const ret = this.buffer.slice(
|
||||||
this.buffer.slice(this.decode_offset, this.decode_offset + length);
|
this.decode_offset,
|
||||||
|
this.decode_offset + length
|
||||||
|
);
|
||||||
this.decode_offset += length;
|
this.decode_offset += length;
|
||||||
return Buffer.from(ret);
|
return Buffer.from(ret);
|
||||||
};
|
};
|
||||||
@@ -68,9 +73,20 @@ export default class packet {
|
|||||||
const flags = this.decode_ui32();
|
const flags = this.decode_ui32();
|
||||||
const directory = !!this.decode_ui8();
|
const directory = !!this.decode_ui8();
|
||||||
return {
|
return {
|
||||||
mode, nlink, uid, gid, atime, mtime, ctime, birth_time, size, blocks,
|
mode,
|
||||||
blksize, flags, directory,
|
nlink,
|
||||||
}
|
uid,
|
||||||
|
gid,
|
||||||
|
atime,
|
||||||
|
mtime,
|
||||||
|
ctime,
|
||||||
|
birth_time,
|
||||||
|
size,
|
||||||
|
blocks,
|
||||||
|
blksize,
|
||||||
|
flags,
|
||||||
|
directory,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
decode_utf8 = () => {
|
decode_utf8 = () => {
|
||||||
@@ -92,11 +108,13 @@ export default class packet {
|
|||||||
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);
|
||||||
@@ -124,7 +142,7 @@ export default class packet {
|
|||||||
|
|
||||||
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);
|
||||||
@@ -132,7 +150,7 @@ export default class packet {
|
|||||||
|
|
||||||
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);
|
||||||
@@ -146,10 +164,9 @@ export default class packet {
|
|||||||
const key = Uint8Array.from(hash.array());
|
const key = Uint8Array.from(hash.array());
|
||||||
const nonce = this.buffer.slice(0, 12);
|
const nonce = this.buffer.slice(0, 12);
|
||||||
|
|
||||||
this.buffer = new JSChaCha20(key, nonce, 0)
|
this.buffer = new JSChaCha20(key, nonce, 0).decrypt(
|
||||||
.decrypt(
|
this.buffer.slice(12)
|
||||||
this.buffer.slice(12),
|
);
|
||||||
);
|
|
||||||
|
|
||||||
this.decode_offset = packet.HEADER.length;
|
this.decode_offset = packet.HEADER.length;
|
||||||
|
|
||||||
@@ -164,65 +181,93 @@ export default class packet {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
encode_buffer = buffer => { this.append_buffer(new Uint8Array(buffer)); };
|
encode_buffer = (buffer) => {
|
||||||
|
this.append_buffer(new Uint8Array(buffer));
|
||||||
|
};
|
||||||
|
|
||||||
encode_i8 = num => { this.append_buffer(i8_to_ui8_array(num)); };
|
encode_i8 = (num) => {
|
||||||
|
this.append_buffer(i8_to_ui8_array(num));
|
||||||
|
};
|
||||||
|
|
||||||
encode_top_i8 = num => { this.push_buffer(i8_to_ui8_array(num)); };
|
encode_top_i8 = (num) => {
|
||||||
|
this.push_buffer(i8_to_ui8_array(num));
|
||||||
|
};
|
||||||
|
|
||||||
encode_u8 = num => { this.append_buffer(ui8_to_ui8_array(num)); };
|
encode_u8 = (num) => {
|
||||||
|
this.append_buffer(ui8_to_ui8_array(num));
|
||||||
|
};
|
||||||
|
|
||||||
encode_top_u8 = num => { this.push_buffer(ui8_to_ui8_array(num)); };
|
encode_top_u8 = (num) => {
|
||||||
|
this.push_buffer(ui8_to_ui8_array(num));
|
||||||
|
};
|
||||||
|
|
||||||
encode_i16 = num => { this.append_buffer(i16_to_be_ui8_array(num)); };
|
encode_i16 = (num) => {
|
||||||
|
this.append_buffer(i16_to_be_ui8_array(num));
|
||||||
|
};
|
||||||
|
|
||||||
encode_top_i16 = num => { this.push_buffer(i16_to_be_ui8_array(num)); };
|
encode_top_i16 = (num) => {
|
||||||
|
this.push_buffer(i16_to_be_ui8_array(num));
|
||||||
|
};
|
||||||
|
|
||||||
encode_ui16 = num => { this.append_buffer(ui16_to_be_ui8_array(num)); };
|
encode_ui16 = (num) => {
|
||||||
|
this.append_buffer(ui16_to_be_ui8_array(num));
|
||||||
|
};
|
||||||
|
|
||||||
encode_top_ui16 = num => { this.push_buffer(ui16_to_be_ui8_array(num)); };
|
encode_top_ui16 = (num) => {
|
||||||
|
this.push_buffer(ui16_to_be_ui8_array(num));
|
||||||
|
};
|
||||||
|
|
||||||
encode_i32 = num => { this.append_buffer(i32_to_be_ui8_array(num)); };
|
encode_i32 = (num) => {
|
||||||
|
this.append_buffer(i32_to_be_ui8_array(num));
|
||||||
|
};
|
||||||
|
|
||||||
encode_top_i32 = num => { this.push_buffer(i32_to_be_ui8_array(num)); };
|
encode_top_i32 = (num) => {
|
||||||
|
this.push_buffer(i32_to_be_ui8_array(num));
|
||||||
|
};
|
||||||
|
|
||||||
encode_ui32 = num => { this.append_buffer(ui32_to_be_ui8_array(num)); };
|
encode_ui32 = (num) => {
|
||||||
|
this.append_buffer(ui32_to_be_ui8_array(num));
|
||||||
|
};
|
||||||
|
|
||||||
encode_top_ui32 = num => { this.push_buffer(ui32_to_be_ui8_array(num)); };
|
encode_top_ui32 = (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 =
|
encode_top_i64 = (num) => {
|
||||||
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 =
|
encode_top_ui64 = (num) => {
|
||||||
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 {
|
||||||
this.push_buffer(packet.HEADER);
|
this.push_buffer(packet.HEADER);
|
||||||
const hash = sha256.create();
|
const hash = sha256.create();
|
||||||
@@ -242,12 +287,13 @@ export default class packet {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
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 ]) : buffer;
|
? new Uint8Array([...buffer, ...this.buffer])
|
||||||
|
: buffer;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
676
src/ops/index.js
676
src/ops/index.js
@@ -1,5 +1,5 @@
|
|||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import {Uint64BE} from 'int64-buffer';
|
import { Uint64BE } from 'int64-buffer';
|
||||||
|
|
||||||
import file from '../io/file';
|
import file from '../io/file';
|
||||||
import packet from '../networking/packet';
|
import packet from '../networking/packet';
|
||||||
@@ -9,8 +9,10 @@ const _snapshot_directory = async (conn, remote_path) => {
|
|||||||
const request = new packet();
|
const request = new packet();
|
||||||
request.encode_utf8(remote_path);
|
request.encode_utf8(remote_path);
|
||||||
|
|
||||||
const response =
|
const response = await conn.send(
|
||||||
await conn.send('::RemoteJSONCreateDirectorySnapshot', request);
|
'::RemoteJSONCreateDirectorySnapshot',
|
||||||
|
request
|
||||||
|
);
|
||||||
response.decode_ui32(); // Service flags
|
response.decode_ui32(); // Service flags
|
||||||
|
|
||||||
const result = response.decode_i32();
|
const result = response.decode_i32();
|
||||||
@@ -28,15 +30,17 @@ const _snapshot_directory = async (conn, remote_path) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const get_page = async page => {
|
const get_page = async (page) => {
|
||||||
try {
|
try {
|
||||||
const request = new packet();
|
const request = new packet();
|
||||||
request.encode_utf8(remote_path);
|
request.encode_utf8(remote_path);
|
||||||
request.encode_ui64(data.handle);
|
request.encode_ui64(data.handle);
|
||||||
request.encode_ui32(page);
|
request.encode_ui32(page);
|
||||||
|
|
||||||
const response =
|
const response = await conn.send(
|
||||||
await conn.send('::RemoteJSONReadDirectorySnapshot', request);
|
'::RemoteJSONReadDirectorySnapshot',
|
||||||
|
request
|
||||||
|
);
|
||||||
response.decode_ui32(); // Service flags
|
response.decode_ui32(); // Service flags
|
||||||
|
|
||||||
const result = response.decode_i32();
|
const result = response.decode_i32();
|
||||||
@@ -67,22 +71,29 @@ const _snapshot_directory = async (conn, remote_path) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const close_file =
|
export const close_file = async (
|
||||||
async (conn, remote_path, handle, optional_thread_id) => {
|
conn,
|
||||||
try {
|
remote_path,
|
||||||
const request = new packet();
|
handle,
|
||||||
request.encode_utf8(remote_path);
|
optional_thread_id
|
||||||
request.encode_ui64(handle);
|
) => {
|
||||||
|
try {
|
||||||
|
const request = new packet();
|
||||||
|
request.encode_utf8(remote_path);
|
||||||
|
request.encode_ui64(handle);
|
||||||
|
|
||||||
const response =
|
const response = await conn.send(
|
||||||
await conn.send('::RemoteFUSERelease', request, optional_thread_id);
|
'::RemoteFUSERelease',
|
||||||
response.decode_ui32(); // Service flags
|
request,
|
||||||
|
optional_thread_id
|
||||||
|
);
|
||||||
|
response.decode_ui32(); // Service flags
|
||||||
|
|
||||||
return response.decode_i32();
|
return response.decode_i32();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return Promise.reject(new Error(`'close_file' failed: ${err}`));
|
return Promise.reject(new Error(`'close_file' failed: ${err}`));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const create_directory = async (conn, remote_path) => {
|
export const create_directory = async (conn, remote_path) => {
|
||||||
try {
|
try {
|
||||||
@@ -99,28 +110,34 @@ export const create_directory = async (conn, remote_path) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const create_or_open_file =
|
export const create_or_open_file = async (
|
||||||
async (conn, remote_path, optional_thread_id) => {
|
conn,
|
||||||
try {
|
remote_path,
|
||||||
const request = new packet();
|
optional_thread_id
|
||||||
request.encode_utf8(remote_path);
|
) => {
|
||||||
request.encode_ui16((7 << 6) | (5 << 3));
|
try {
|
||||||
request.encode_ui32(2 | 4); // Read-Write, Create
|
const request = new packet();
|
||||||
|
request.encode_utf8(remote_path);
|
||||||
|
request.encode_ui16((7 << 6) | (5 << 3));
|
||||||
|
request.encode_ui32(2 | 4); // Read-Write, Create
|
||||||
|
|
||||||
const response =
|
const response = await conn.send(
|
||||||
await conn.send('::RemoteFUSECreate', request, optional_thread_id);
|
'::RemoteFUSECreate',
|
||||||
response.decode_ui32(); // Service flags
|
request,
|
||||||
|
optional_thread_id
|
||||||
|
);
|
||||||
|
response.decode_ui32(); // Service flags
|
||||||
|
|
||||||
const result = response.decode_i32();
|
const result = response.decode_i32();
|
||||||
if (result === 0) {
|
if (result === 0) {
|
||||||
return response.decode_ui64();
|
return response.decode_ui64();
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.reject(new Error(`'create_or_open_file' error: ${result}`));
|
|
||||||
} catch (err) {
|
|
||||||
return Promise.reject(new Error(`'create_or_open_file' failed: ${err}`));
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
return Promise.reject(new Error(`'create_or_open_file' error: ${result}`));
|
||||||
|
} catch (err) {
|
||||||
|
return Promise.reject(new Error(`'create_or_open_file' failed: ${err}`));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const delete_file = async (conn, remote_path) => {
|
export const delete_file = async (conn, remote_path) => {
|
||||||
try {
|
try {
|
||||||
@@ -136,97 +153,113 @@ export const delete_file = async (conn, remote_path) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const download_file =
|
export const download_file = async (
|
||||||
async (conn, remote_path, local_path, progress_cb, overwrite, resume) => {
|
conn,
|
||||||
try {
|
remote_path,
|
||||||
const src = new file(conn, await open_file(conn, remote_path), remote_path);
|
local_path,
|
||||||
const cleanup = async fd => {
|
progress_cb,
|
||||||
try {
|
overwrite,
|
||||||
await src.close();
|
resume
|
||||||
} catch (err) {
|
) => {
|
||||||
console.log(err);
|
try {
|
||||||
}
|
const src = new file(conn, await open_file(conn, remote_path), remote_path);
|
||||||
try {
|
const cleanup = async (fd) => {
|
||||||
if (fd !== undefined) {
|
|
||||||
fs.closeSync(fd);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const src_size = await src.get_size();
|
await src.close();
|
||||||
let dst_fd;
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
try {
|
}
|
||||||
let offset = 0;
|
try {
|
||||||
if (overwrite) {
|
if (fd !== undefined) {
|
||||||
dst_fd = fs.openSync(local_path, 'w+');
|
fs.closeSync(fd);
|
||||||
} else if (resume) {
|
|
||||||
dst_fd = fs.openSync(local_path, 'r+');
|
|
||||||
|
|
||||||
const dst_size = fs.fstatSync(dst_fd).size;
|
|
||||||
if (dst_size === src_size) {
|
|
||||||
await cleanup(dst_fd);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dst_size > src_size) {
|
|
||||||
await cleanup(dst_fd);
|
|
||||||
return Promise.reject(new Error(
|
|
||||||
`'download_file' failed: destination is larger than source`));
|
|
||||||
}
|
|
||||||
|
|
||||||
offset = dst_size;
|
|
||||||
} else {
|
|
||||||
if (fs.existsSync(local_path)) {
|
|
||||||
await cleanup(dst_fd);
|
|
||||||
return Promise.reject(
|
|
||||||
new Error(`'download_file' failed: file exists`));
|
|
||||||
}
|
|
||||||
|
|
||||||
dst_fd = fs.openSync(local_path, 'wx+');
|
|
||||||
}
|
|
||||||
|
|
||||||
let remain = src_size - offset;
|
|
||||||
while (remain > 0) {
|
|
||||||
const to_write = remain >= 65536 ? 65536 : remain;
|
|
||||||
const buffer = await src.read(offset, to_write);
|
|
||||||
const written = fs.writeSync(dst_fd, buffer, 0, to_write, offset);
|
|
||||||
if (written > 0) {
|
|
||||||
remain -= written;
|
|
||||||
offset += written;
|
|
||||||
if (progress_cb) {
|
|
||||||
progress_cb(local_path, remote_path,
|
|
||||||
((src_size - remain) / src_size) * 100.0, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (progress_cb) {
|
|
||||||
progress_cb(local_path, remote_path, 100, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
await cleanup(dst_fd);
|
|
||||||
return true;
|
|
||||||
} catch (err) {
|
|
||||||
await cleanup(dst_fd);
|
|
||||||
return Promise.reject(new Error(`'download_file' failed: ${err}`));
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await cleanup();
|
console.log(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const src_size = await src.get_size();
|
||||||
|
let dst_fd;
|
||||||
|
|
||||||
|
try {
|
||||||
|
let offset = 0;
|
||||||
|
if (overwrite) {
|
||||||
|
dst_fd = fs.openSync(local_path, 'w+');
|
||||||
|
} else if (resume) {
|
||||||
|
dst_fd = fs.openSync(local_path, 'r+');
|
||||||
|
|
||||||
|
const dst_size = fs.fstatSync(dst_fd).size;
|
||||||
|
if (dst_size === src_size) {
|
||||||
|
await cleanup(dst_fd);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dst_size > src_size) {
|
||||||
|
await cleanup(dst_fd);
|
||||||
|
return Promise.reject(
|
||||||
|
new Error(
|
||||||
|
`'download_file' failed: destination is larger than source`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = dst_size;
|
||||||
|
} else {
|
||||||
|
if (fs.existsSync(local_path)) {
|
||||||
|
await cleanup(dst_fd);
|
||||||
|
return Promise.reject(
|
||||||
|
new Error(`'download_file' failed: file exists`)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
dst_fd = fs.openSync(local_path, 'wx+');
|
||||||
|
}
|
||||||
|
|
||||||
|
let remain = src_size - offset;
|
||||||
|
while (remain > 0) {
|
||||||
|
const to_write = remain >= 65536 ? 65536 : remain;
|
||||||
|
const buffer = await src.read(offset, to_write);
|
||||||
|
const written = fs.writeSync(dst_fd, buffer, 0, to_write, offset);
|
||||||
|
if (written > 0) {
|
||||||
|
remain -= written;
|
||||||
|
offset += written;
|
||||||
|
if (progress_cb) {
|
||||||
|
progress_cb(
|
||||||
|
local_path,
|
||||||
|
remote_path,
|
||||||
|
((src_size - remain) / src_size) * 100.0,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (progress_cb) {
|
||||||
|
progress_cb(local_path, remote_path, 100, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
await cleanup(dst_fd);
|
||||||
|
return true;
|
||||||
|
} catch (err) {
|
||||||
|
await cleanup(dst_fd);
|
||||||
return Promise.reject(new Error(`'download_file' failed: ${err}`));
|
return Promise.reject(new Error(`'download_file' failed: ${err}`));
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
await cleanup();
|
||||||
return Promise.reject(new Error(`'download_file' failed: ${err}`));
|
return Promise.reject(new Error(`'download_file' failed: ${err}`));
|
||||||
}
|
}
|
||||||
};
|
} catch (err) {
|
||||||
|
return Promise.reject(new Error(`'download_file' failed: ${err}`));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const get_drive_information = async conn => {
|
export const get_drive_information = async (conn) => {
|
||||||
try {
|
try {
|
||||||
const response =
|
const response = await conn.send(
|
||||||
await conn.send('::RemoteWinFSPGetVolumeInfo', new packet());
|
'::RemoteWinFSPGetVolumeInfo',
|
||||||
|
new packet()
|
||||||
|
);
|
||||||
response.decode_ui32(); // Service flags
|
response.decode_ui32(); // Service flags
|
||||||
|
|
||||||
const result = response.decode_i32();
|
const result = response.decode_i32();
|
||||||
@@ -241,40 +274,52 @@ export const get_drive_information = async conn => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Promise.reject(
|
return Promise.reject(
|
||||||
new Error(`'get_drive_information' failed: ${result}`));
|
new Error(`'get_drive_information' failed: ${result}`)
|
||||||
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return Promise.reject(new Error(`'get_drive_information' failed: ${err}`));
|
return Promise.reject(new Error(`'get_drive_information' failed: ${err}`));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const get_file_attributes =
|
export const get_file_attributes = async (
|
||||||
async (conn, handle, remote_path, optional_thread_id) => {
|
conn,
|
||||||
try {
|
handle,
|
||||||
const request = new packet();
|
remote_path,
|
||||||
request.encode_utf8(remote_path);
|
optional_thread_id
|
||||||
request.encode_ui64(handle);
|
) => {
|
||||||
request.encode_ui32(0);
|
try {
|
||||||
request.encode_ui32(0);
|
const request = new packet();
|
||||||
|
request.encode_utf8(remote_path);
|
||||||
|
request.encode_ui64(handle);
|
||||||
|
request.encode_ui32(0);
|
||||||
|
request.encode_ui32(0);
|
||||||
|
|
||||||
const response =
|
const response = await conn.send(
|
||||||
await conn.send('::RemoteFUSEFgetattr', request, optional_thread_id);
|
'::RemoteFUSEFgetattr',
|
||||||
response.decode_ui32(); // Service flags
|
request,
|
||||||
|
optional_thread_id
|
||||||
|
);
|
||||||
|
response.decode_ui32(); // Service flags
|
||||||
|
|
||||||
const result = response.decode_i32();
|
const result = response.decode_i32();
|
||||||
if (result === 0) {
|
if (result === 0) {
|
||||||
return response.decode_stat();
|
return response.decode_stat();
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.reject(new Error(`'get_file_attributes' failed: ${result}`));
|
|
||||||
} catch (err) {
|
|
||||||
return Promise.reject(new Error(`'get_file_attributes' failed: ${err}`));
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
return Promise.reject(new Error(`'get_file_attributes' failed: ${result}`));
|
||||||
|
} catch (err) {
|
||||||
|
return Promise.reject(new Error(`'get_file_attributes' failed: ${err}`));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const list_directory = async (conn, remote_path, page_reader_cb) => {
|
export const list_directory = async (conn, remote_path, page_reader_cb) => {
|
||||||
const dir_snapshot = await _snapshot_directory(conn, remote_path);
|
const dir_snapshot = await _snapshot_directory(conn, remote_path);
|
||||||
try {
|
try {
|
||||||
await page_reader_cb(dir_snapshot.remote_path, dir_snapshot.page_count, dir_snapshot.get_page);
|
await page_reader_cb(
|
||||||
|
dir_snapshot.remote_path,
|
||||||
|
dir_snapshot.page_count,
|
||||||
|
dir_snapshot.get_page
|
||||||
|
);
|
||||||
await dir_snapshot.release();
|
await dir_snapshot.release();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await dir_snapshot.release();
|
await dir_snapshot.release();
|
||||||
@@ -288,8 +333,11 @@ export const open_file = async (conn, remote_path, optional_thread_id) => {
|
|||||||
request.encode_utf8(remote_path);
|
request.encode_utf8(remote_path);
|
||||||
request.encode_ui32(2); // Read-Write
|
request.encode_ui32(2); // Read-Write
|
||||||
|
|
||||||
const response =
|
const response = await conn.send(
|
||||||
await conn.send('::RemoteFUSEOpen', request, optional_thread_id);
|
'::RemoteFUSEOpen',
|
||||||
|
request,
|
||||||
|
optional_thread_id
|
||||||
|
);
|
||||||
response.decode_ui32(); // Service flags
|
response.decode_ui32(); // Service flags
|
||||||
|
|
||||||
const result = response.decode_i32();
|
const result = response.decode_i32();
|
||||||
@@ -302,28 +350,37 @@ export const open_file = async (conn, remote_path, optional_thread_id) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const read_file =
|
export const read_file = async (
|
||||||
async (conn, handle, remote_path, offset, length, optional_thread_id) => {
|
conn,
|
||||||
try {
|
handle,
|
||||||
const request = new packet();
|
remote_path,
|
||||||
request.encode_utf8(remote_path);
|
offset,
|
||||||
request.encode_ui64(length);
|
length,
|
||||||
request.encode_ui64(offset);
|
optional_thread_id
|
||||||
request.encode_ui64(handle);
|
) => {
|
||||||
|
try {
|
||||||
|
const request = new packet();
|
||||||
|
request.encode_utf8(remote_path);
|
||||||
|
request.encode_ui64(length);
|
||||||
|
request.encode_ui64(offset);
|
||||||
|
request.encode_ui64(handle);
|
||||||
|
|
||||||
const response =
|
const response = await conn.send(
|
||||||
await conn.send('::RemoteFUSERead', request, optional_thread_id);
|
'::RemoteFUSERead',
|
||||||
response.decode_ui32(); // Service flags
|
request,
|
||||||
|
optional_thread_id
|
||||||
|
);
|
||||||
|
response.decode_ui32(); // Service flags
|
||||||
|
|
||||||
const result = response.decode_i32();
|
const result = response.decode_i32();
|
||||||
if (result === length) {
|
if (result === length) {
|
||||||
return response.decode_buffer(result);
|
return response.decode_buffer(result);
|
||||||
}
|
|
||||||
return Promise.reject(new Error(`'read_file' error: ${result}`));
|
|
||||||
} catch (err) {
|
|
||||||
return Promise.reject(new Error(`'read_file' failed: ${err}`));
|
|
||||||
}
|
}
|
||||||
};
|
return Promise.reject(new Error(`'read_file' error: ${result}`));
|
||||||
|
} catch (err) {
|
||||||
|
return Promise.reject(new Error(`'read_file' failed: ${err}`));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const remove_directory = async (conn, remote_path) => {
|
export const remove_directory = async (conn, remote_path) => {
|
||||||
try {
|
try {
|
||||||
@@ -341,146 +398,183 @@ export const remove_directory = async (conn, remote_path) => {
|
|||||||
|
|
||||||
export const snapshot_directory = _snapshot_directory;
|
export const snapshot_directory = _snapshot_directory;
|
||||||
|
|
||||||
export const truncate_file =
|
export const truncate_file = async (
|
||||||
async (conn, handle, remote_path, length, optional_thread_id) => {
|
conn,
|
||||||
try {
|
handle,
|
||||||
const request = new packet();
|
remote_path,
|
||||||
request.encode_utf8(remote_path);
|
length,
|
||||||
request.encode_ui64(length);
|
optional_thread_id
|
||||||
request.encode_ui64(handle);
|
) => {
|
||||||
|
try {
|
||||||
|
const request = new packet();
|
||||||
|
request.encode_utf8(remote_path);
|
||||||
|
request.encode_ui64(length);
|
||||||
|
request.encode_ui64(handle);
|
||||||
|
|
||||||
const response =
|
const response = await conn.send(
|
||||||
await conn.send('::RemoteFUSEFtruncate', request, optional_thread_id);
|
'::RemoteFUSEFtruncate',
|
||||||
response.decode_ui32(); // Service flags
|
request,
|
||||||
|
optional_thread_id
|
||||||
|
);
|
||||||
|
response.decode_ui32(); // Service flags
|
||||||
|
|
||||||
return response.decode_i32();
|
return response.decode_i32();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return Promise.reject(new Error(`'truncate_file' failed: ${err}`));
|
return Promise.reject(new Error(`'truncate_file' failed: ${err}`));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const upload_file =
|
export const upload_file = async (
|
||||||
async (conn, local_path, remote_path, progress_cb, overwrite, resume) => {
|
conn,
|
||||||
try {
|
local_path,
|
||||||
const src_fd = fs.openSync(local_path, 'r');
|
remote_path,
|
||||||
const cleanup = async f => {
|
progress_cb,
|
||||||
try {
|
overwrite,
|
||||||
fs.closeSync(src_fd);
|
resume
|
||||||
} catch (err) {
|
) => {
|
||||||
console.log(err);
|
try {
|
||||||
}
|
const src_fd = fs.openSync(local_path, 'r');
|
||||||
try {
|
const cleanup = async (f) => {
|
||||||
if (f) {
|
|
||||||
await f.close();
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
try {
|
try {
|
||||||
const src_st = fs.fstatSync(src_fd);
|
fs.closeSync(src_fd);
|
||||||
let dst;
|
} catch (err) {
|
||||||
const create_dest = async () => {
|
console.log(err);
|
||||||
dst = new file(conn, await create_or_open_file(conn, remote_path),
|
}
|
||||||
remote_path);
|
try {
|
||||||
};
|
if (f) {
|
||||||
|
await f.close();
|
||||||
try {
|
|
||||||
let offset = 0;
|
|
||||||
if (overwrite) {
|
|
||||||
await create_dest();
|
|
||||||
const result = await dst.truncate(0);
|
|
||||||
if (result !== 0) {
|
|
||||||
await cleanup(dst);
|
|
||||||
return Promise.reject(new Error(`'upload_file' failed: ${result}`));
|
|
||||||
}
|
|
||||||
} else if (resume) {
|
|
||||||
await create_dest();
|
|
||||||
const dst_size = new Uint64BE(await dst.get_size()).toNumber();
|
|
||||||
if (dst_size === src_st.size) {
|
|
||||||
await cleanup(dst);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dst_size > src_st.size) {
|
|
||||||
await cleanup(dst);
|
|
||||||
return Promise.reject(new Error(
|
|
||||||
`'upload_file' failed: destination is larger than source`));
|
|
||||||
}
|
|
||||||
|
|
||||||
offset = dst_size;
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
const f =
|
|
||||||
new file(conn, await open_file(conn, remote_path), remote_path);
|
|
||||||
await cleanup(f);
|
|
||||||
return Promise.reject(
|
|
||||||
new Error('\'upload_file\' failed: file exists'));
|
|
||||||
} catch (err) {
|
|
||||||
await create_dest();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let remain = src_st.size - offset;
|
|
||||||
const default_buffer = Buffer.alloc(65536 * 2);
|
|
||||||
while (remain > 0) {
|
|
||||||
const to_write =
|
|
||||||
remain >= default_buffer.length ? default_buffer.length : remain;
|
|
||||||
const buffer = to_write === default_buffer.length
|
|
||||||
? default_buffer
|
|
||||||
: Buffer.alloc(to_write);
|
|
||||||
fs.readSync(src_fd, buffer, 0, to_write, offset);
|
|
||||||
const written = await dst.write(offset, buffer);
|
|
||||||
if (written > 0) {
|
|
||||||
remain -= written;
|
|
||||||
offset += written;
|
|
||||||
if (progress_cb) {
|
|
||||||
progress_cb(local_path, remote_path,
|
|
||||||
((src_st.size - remain) / src_st.size) * 100.0,
|
|
||||||
false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (progress_cb) {
|
|
||||||
progress_cb(local_path, remote_path, 100, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
await cleanup(dst);
|
|
||||||
return true;
|
|
||||||
} catch (err) {
|
|
||||||
await cleanup(dst);
|
|
||||||
return Promise.reject(new Error(`'upload_file' failed: ${err}`));
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await cleanup();
|
console.log(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
const src_st = fs.fstatSync(src_fd);
|
||||||
|
let dst;
|
||||||
|
const create_dest = async () => {
|
||||||
|
dst = new file(
|
||||||
|
conn,
|
||||||
|
await create_or_open_file(conn, remote_path),
|
||||||
|
remote_path
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
let offset = 0;
|
||||||
|
if (overwrite) {
|
||||||
|
await create_dest();
|
||||||
|
const result = await dst.truncate(0);
|
||||||
|
if (result !== 0) {
|
||||||
|
await cleanup(dst);
|
||||||
|
return Promise.reject(new Error(`'upload_file' failed: ${result}`));
|
||||||
|
}
|
||||||
|
} else if (resume) {
|
||||||
|
await create_dest();
|
||||||
|
const dst_size = new Uint64BE(await dst.get_size()).toNumber();
|
||||||
|
if (dst_size === src_st.size) {
|
||||||
|
await cleanup(dst);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dst_size > src_st.size) {
|
||||||
|
await cleanup(dst);
|
||||||
|
return Promise.reject(
|
||||||
|
new Error(
|
||||||
|
`'upload_file' failed: destination is larger than source`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = dst_size;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
const f = new file(
|
||||||
|
conn,
|
||||||
|
await open_file(conn, remote_path),
|
||||||
|
remote_path
|
||||||
|
);
|
||||||
|
await cleanup(f);
|
||||||
|
return Promise.reject(
|
||||||
|
new Error("'upload_file' failed: file exists")
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
await create_dest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let remain = src_st.size - offset;
|
||||||
|
const default_buffer = Buffer.alloc(65536 * 2);
|
||||||
|
while (remain > 0) {
|
||||||
|
const to_write =
|
||||||
|
remain >= default_buffer.length ? default_buffer.length : remain;
|
||||||
|
const buffer =
|
||||||
|
to_write === default_buffer.length
|
||||||
|
? default_buffer
|
||||||
|
: Buffer.alloc(to_write);
|
||||||
|
fs.readSync(src_fd, buffer, 0, to_write, offset);
|
||||||
|
const written = await dst.write(offset, buffer);
|
||||||
|
if (written > 0) {
|
||||||
|
remain -= written;
|
||||||
|
offset += written;
|
||||||
|
if (progress_cb) {
|
||||||
|
progress_cb(
|
||||||
|
local_path,
|
||||||
|
remote_path,
|
||||||
|
((src_st.size - remain) / src_st.size) * 100.0,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (progress_cb) {
|
||||||
|
progress_cb(local_path, remote_path, 100, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
await cleanup(dst);
|
||||||
|
return true;
|
||||||
|
} catch (err) {
|
||||||
|
await cleanup(dst);
|
||||||
return Promise.reject(new Error(`'upload_file' failed: ${err}`));
|
return Promise.reject(new Error(`'upload_file' failed: ${err}`));
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
await cleanup();
|
||||||
return Promise.reject(new Error(`'upload_file' failed: ${err}`));
|
return Promise.reject(new Error(`'upload_file' failed: ${err}`));
|
||||||
}
|
}
|
||||||
};
|
} catch (err) {
|
||||||
|
return Promise.reject(new Error(`'upload_file' failed: ${err}`));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const write_file =
|
export const write_file = async (
|
||||||
async (conn, handle, remote_path, offset, buffer, optional_thread_id) => {
|
conn,
|
||||||
try {
|
handle,
|
||||||
const request = new packet();
|
remote_path,
|
||||||
request.encode_utf8(remote_path);
|
offset,
|
||||||
request.encode_ui64(buffer.length);
|
buffer,
|
||||||
request.encode_buffer(buffer);
|
optional_thread_id
|
||||||
request.encode_ui64(offset);
|
) => {
|
||||||
request.encode_ui64(handle);
|
try {
|
||||||
|
const request = new packet();
|
||||||
|
request.encode_utf8(remote_path);
|
||||||
|
request.encode_ui64(buffer.length);
|
||||||
|
request.encode_buffer(buffer);
|
||||||
|
request.encode_ui64(offset);
|
||||||
|
request.encode_ui64(handle);
|
||||||
|
|
||||||
const response =
|
const response = await conn.send(
|
||||||
await conn.send('::RemoteFUSEWrite', request, optional_thread_id);
|
'::RemoteFUSEWrite',
|
||||||
response.decode_ui32(); // Service flags
|
request,
|
||||||
|
optional_thread_id
|
||||||
|
);
|
||||||
|
response.decode_ui32(); // Service flags
|
||||||
|
|
||||||
const result = response.decode_i32();
|
const result = response.decode_i32();
|
||||||
if (result === buffer.length) {
|
if (result === buffer.length) {
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
return Promise.reject(new Error(`'write_file' error: ${result}`));
|
|
||||||
} catch (err) {
|
|
||||||
return Promise.reject(new Error(`'write_file' failed: ${err}`));
|
|
||||||
}
|
}
|
||||||
};
|
return Promise.reject(new Error(`'write_file' error: ${result}`));
|
||||||
|
} catch (err) {
|
||||||
|
return Promise.reject(new Error(`'write_file' failed: ${err}`));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
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);
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@ export const ui8_array_to_i8 = (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);
|
||||||
}
|
}
|
||||||
@@ -38,7 +38,7 @@ export const ui8_array_to_ui8 = (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);
|
||||||
}
|
}
|
||||||
@@ -56,7 +56,7 @@ export const be_ui8_array_to_i16 = (ar, offset) => {
|
|||||||
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);
|
||||||
}
|
}
|
||||||
@@ -74,7 +74,7 @@ export const be_ui8_array_to_ui16 = (ar, offset) => {
|
|||||||
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);
|
||||||
}
|
}
|
||||||
@@ -92,7 +92,7 @@ export const be_ui8_array_to_i32 = (ar, offset) => {
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
const {v4: uuidv4} = require('uuid');
|
const { v4: uuidv4 } = require('uuid');
|
||||||
import _package_json from '../../package.json'
|
import _package_json from '../../package.json';
|
||||||
|
|
||||||
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 = () => process.env.REPERTORY_JS_FORCE_VERSION || _package_json.version;
|
export const get_version = () =>
|
||||||
|
process.env.REPERTORY_JS_FORCE_VERSION || _package_json.version;
|
||||||
|
|||||||
@@ -63,7 +63,7 @@
|
|||||||
*
|
*
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
var JSChaCha20 = function(key, nonce, counter) {
|
var JSChaCha20 = function (key, nonce, counter) {
|
||||||
if (typeof counter === 'undefined') {
|
if (typeof counter === 'undefined') {
|
||||||
counter = 0;
|
counter = 0;
|
||||||
}
|
}
|
||||||
@@ -175,7 +175,7 @@ var JSChaCha20 = function(key, nonce, counter) {
|
|||||||
this._byteCounter = 0;
|
this._byteCounter = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
JSChaCha20.prototype._chacha = function() {
|
JSChaCha20.prototype._chacha = function () {
|
||||||
var mix = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
var mix = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
var i = 0;
|
var i = 0;
|
||||||
var b = 0;
|
var b = 0;
|
||||||
@@ -221,7 +221,7 @@ JSChaCha20.prototype._chacha = function() {
|
|||||||
* @param {number} d
|
* @param {number} d
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
JSChaCha20.prototype._quarterround = function(output, a, b, c, d) {
|
JSChaCha20.prototype._quarterround = function (output, a, b, c, d) {
|
||||||
output[d] = this._rotl(output[d] ^ (output[a] += output[b]), 16);
|
output[d] = this._rotl(output[d] ^ (output[a] += output[b]), 16);
|
||||||
output[b] = this._rotl(output[b] ^ (output[c] += output[d]), 12);
|
output[b] = this._rotl(output[b] ^ (output[c] += output[d]), 12);
|
||||||
output[d] = this._rotl(output[d] ^ (output[a] += output[b]), 8);
|
output[d] = this._rotl(output[d] ^ (output[a] += output[b]), 8);
|
||||||
@@ -242,7 +242,7 @@ JSChaCha20.prototype._quarterround = function(output, a, b, c, d) {
|
|||||||
* @return {number}
|
* @return {number}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
JSChaCha20.prototype._get32 = function(data, index) {
|
JSChaCha20.prototype._get32 = function (data, index) {
|
||||||
return (
|
return (
|
||||||
data[index++] ^
|
data[index++] ^
|
||||||
(data[index++] << 8) ^
|
(data[index++] << 8) ^
|
||||||
@@ -259,7 +259,7 @@ JSChaCha20.prototype._get32 = function(data, index) {
|
|||||||
* @return {number}
|
* @return {number}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
JSChaCha20.prototype._rotl = function(data, shift) {
|
JSChaCha20.prototype._rotl = function (data, shift) {
|
||||||
return (data << shift) | (data >>> (32 - shift));
|
return (data << shift) | (data >>> (32 - shift));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -269,7 +269,7 @@ JSChaCha20.prototype._rotl = function(data, shift) {
|
|||||||
* @param {Uint8Array} data
|
* @param {Uint8Array} data
|
||||||
* @return {Uint8Array}
|
* @return {Uint8Array}
|
||||||
*/
|
*/
|
||||||
JSChaCha20.prototype.encrypt = function(data) {
|
JSChaCha20.prototype.encrypt = function (data) {
|
||||||
return this._update(data);
|
return this._update(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -279,7 +279,7 @@ JSChaCha20.prototype.encrypt = function(data) {
|
|||||||
* @param {Uint8Array} data
|
* @param {Uint8Array} data
|
||||||
* @return {Uint8Array}
|
* @return {Uint8Array}
|
||||||
*/
|
*/
|
||||||
JSChaCha20.prototype.decrypt = function(data) {
|
JSChaCha20.prototype.decrypt = function (data) {
|
||||||
return this._update(data);
|
return this._update(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -290,7 +290,7 @@ JSChaCha20.prototype.decrypt = function(data) {
|
|||||||
* @return {Uint8Array}
|
* @return {Uint8Array}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
JSChaCha20.prototype._update = function(data) {
|
JSChaCha20.prototype._update = function (data) {
|
||||||
if (!(data instanceof Uint8Array) || data.length === 0) {
|
if (!(data instanceof Uint8Array) || data.length === 0) {
|
||||||
throw new Error('Data should be type of bytes (Uint8Array) and not empty!');
|
throw new Error('Data should be type of bytes (Uint8Array) and not empty!');
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user