@heyputer/puter.js 2.1.4 → 2.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/puter.cjs +2 -2
- package/index.d.ts +41 -15
- package/package.json +1 -1
- package/src/index.js +116 -79
- package/src/lib/APICallLogger.js +20 -21
- package/src/lib/EventListener.js +10 -10
- package/src/lib/filesystem/APIFS.js +11 -19
- package/src/lib/filesystem/CacheFS.js +25 -25
- package/src/lib/filesystem/PostMessageFS.js +11 -11
- package/src/lib/filesystem/definitions.js +11 -10
- package/src/lib/path.js +505 -446
- package/src/lib/polyfills/fileReaderPoly.js +40 -0
- package/src/lib/polyfills/localStorage.js +30 -33
- package/src/lib/polyfills/xhrshim.js +206 -207
- package/src/lib/utils.js +160 -151
- package/src/lib/xdrpc.js +9 -9
- package/src/modules/AI.js +473 -292
- package/src/modules/Apps.js +56 -56
- package/src/modules/Auth.js +17 -17
- package/src/modules/Debug.js +1 -1
- package/src/modules/Drivers.js +41 -41
- package/src/modules/FSItem.js +64 -62
- package/src/modules/FileSystem/index.js +22 -23
- package/src/modules/FileSystem/operations/copy.js +7 -7
- package/src/modules/FileSystem/operations/deleteFSEntry.js +14 -12
- package/src/modules/FileSystem/operations/getReadUrl.js +16 -14
- package/src/modules/FileSystem/operations/mkdir.js +11 -11
- package/src/modules/FileSystem/operations/move.js +12 -12
- package/src/modules/FileSystem/operations/read.js +10 -10
- package/src/modules/FileSystem/operations/readdir.js +28 -28
- package/src/modules/FileSystem/operations/rename.js +11 -11
- package/src/modules/FileSystem/operations/sign.js +33 -30
- package/src/modules/FileSystem/operations/space.js +7 -7
- package/src/modules/FileSystem/operations/stat.js +25 -25
- package/src/modules/FileSystem/operations/symlink.js +15 -17
- package/src/modules/FileSystem/operations/upload.js +151 -122
- package/src/modules/FileSystem/operations/write.js +16 -12
- package/src/modules/FileSystem/utils/getAbsolutePathForApp.js +10 -6
- package/src/modules/Hosting.js +29 -29
- package/src/modules/KV.js +23 -23
- package/src/modules/OS.js +15 -15
- package/src/modules/Perms.js +19 -21
- package/src/modules/PuterDialog.js +46 -48
- package/src/modules/Threads.js +17 -20
- package/src/modules/UI.js +156 -156
- package/src/modules/Util.js +3 -3
- package/src/modules/Workers.js +52 -49
- package/src/modules/networking/PSocket.js +38 -38
- package/src/modules/networking/PTLS.js +54 -47
- package/src/modules/networking/PWispHandler.js +49 -47
- package/src/modules/networking/parsers.js +110 -108
- package/src/modules/networking/requests.js +67 -78
- package/src/services/APIAccess.js +9 -9
- package/src/services/FSRelay.js +6 -6
- package/src/services/Filesystem.js +8 -8
- package/src/services/NoPuterYet.js +2 -2
- package/src/services/XDIncoming.js +1 -1
package/src/modules/Util.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $SCOPE, CallbackManager, Dehydrator, Hydrator } from
|
|
1
|
+
import { $SCOPE, CallbackManager, Dehydrator, Hydrator } from '../lib/xdrpc.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* The Util module exposes utilities within puter.js itself.
|
|
@@ -27,11 +27,11 @@ class UtilRPC {
|
|
|
27
27
|
getHydrator ({ target }) {
|
|
28
28
|
return new Hydrator({ target });
|
|
29
29
|
}
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
registerCallback (resolve) {
|
|
32
32
|
return this.callbackManager.register_callback(resolve);
|
|
33
33
|
}
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
send (target, id, ...args) {
|
|
36
36
|
target.postMessage({ $SCOPE, id, args }, '*');
|
|
37
37
|
}
|
package/src/modules/Workers.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import getAbsolutePathForApp from
|
|
1
|
+
import getAbsolutePathForApp from './FileSystem/utils/getAbsolutePathForApp.js';
|
|
2
2
|
import * as utils from '../lib/utils.js';
|
|
3
3
|
|
|
4
4
|
export class WorkersHandler {
|
|
5
5
|
|
|
6
|
-
constructor(authToken) {
|
|
6
|
+
constructor (authToken) {
|
|
7
7
|
this.authToken = authToken;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
async create(workerName, filePath, appName) {
|
|
11
|
-
if (!puter.authToken && puter.env === 'web') {
|
|
10
|
+
async create (workerName, filePath, appName) {
|
|
11
|
+
if ( !puter.authToken && puter.env === 'web' ) {
|
|
12
12
|
try {
|
|
13
13
|
await puter.ui.authenticateWithPuter();
|
|
14
14
|
} catch (e) {
|
|
@@ -18,30 +18,30 @@ export class WorkersHandler {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
let appId;
|
|
21
|
-
if (typeof (appName)===
|
|
21
|
+
if ( typeof (appName) === 'string' ) {
|
|
22
22
|
appId = ((await puter.apps.list()).find(el => el.name === appName)).uid;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
workerName = workerName.toLocaleLowerCase(); // just incase
|
|
26
|
-
let currentWorkers = await puter.kv.get(
|
|
27
|
-
if (!currentWorkers) {
|
|
26
|
+
let currentWorkers = await puter.kv.get('user-workers');
|
|
27
|
+
if ( ! currentWorkers ) {
|
|
28
28
|
currentWorkers = {};
|
|
29
29
|
}
|
|
30
30
|
filePath = getAbsolutePathForApp(filePath);
|
|
31
31
|
|
|
32
|
-
const driverResult = await utils.make_driver_method(['authorization', 'filePath', 'workerName', 'appId'], 'workers',
|
|
32
|
+
const driverResult = await utils.make_driver_method(['authorization', 'filePath', 'workerName', 'appId'], 'workers', 'worker-service', 'create')(puter.authToken, filePath, workerName, appId);;
|
|
33
33
|
|
|
34
|
-
if (!driverResult.success) {
|
|
35
|
-
throw new Error(driverResult?.errors ||
|
|
34
|
+
if ( ! driverResult.success ) {
|
|
35
|
+
throw new Error(driverResult?.errors || 'Driver failed to execute, do you have the necessary permissions?');
|
|
36
36
|
}
|
|
37
|
-
currentWorkers[workerName] = { filePath, url: driverResult[
|
|
38
|
-
await puter.kv.set(
|
|
37
|
+
currentWorkers[workerName] = { filePath, url: driverResult['url'], deployTime: Date.now(), createTime: Date.now() };
|
|
38
|
+
await puter.kv.set('user-workers', currentWorkers);
|
|
39
39
|
|
|
40
40
|
return driverResult;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
async exec(...args) {
|
|
44
|
-
if (!puter.authToken && puter.env === 'web') {
|
|
43
|
+
async exec (...args) {
|
|
44
|
+
if ( !puter.authToken && puter.env === 'web' ) {
|
|
45
45
|
try {
|
|
46
46
|
await puter.ui.authenticateWithPuter();
|
|
47
47
|
} catch (e) {
|
|
@@ -51,14 +51,14 @@ export class WorkersHandler {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
const req = new Request(...args);
|
|
54
|
-
if (!req.headers.get(
|
|
55
|
-
req.headers.set(
|
|
54
|
+
if ( ! req.headers.get('puter-auth') ) {
|
|
55
|
+
req.headers.set('puter-auth', puter.authToken);
|
|
56
56
|
}
|
|
57
57
|
return fetch(req);
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
async list() {
|
|
61
|
-
if (!puter.authToken && puter.env === 'web') {
|
|
60
|
+
async list () {
|
|
61
|
+
if ( !puter.authToken && puter.env === 'web' ) {
|
|
62
62
|
try {
|
|
63
63
|
await puter.ui.authenticateWithPuter();
|
|
64
64
|
} catch (e) {
|
|
@@ -66,12 +66,12 @@ export class WorkersHandler {
|
|
|
66
66
|
throw 'Authentication failed.';
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
-
const driverCall = await utils.make_driver_method([], 'workers',
|
|
69
|
+
const driverCall = await utils.make_driver_method([], 'workers', 'worker-service', 'getFilePaths')();
|
|
70
70
|
return driverCall;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
async get(workerName) {
|
|
74
|
-
if (!puter.authToken && puter.env === 'web') {
|
|
73
|
+
async get (workerName) {
|
|
74
|
+
if ( !puter.authToken && puter.env === 'web' ) {
|
|
75
75
|
try {
|
|
76
76
|
await puter.ui.authenticateWithPuter();
|
|
77
77
|
} catch (e) {
|
|
@@ -81,12 +81,12 @@ export class WorkersHandler {
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
workerName = workerName.toLocaleLowerCase(); // just incase
|
|
84
|
-
const driverCall = await utils.make_driver_method(['workerName'], 'workers',
|
|
84
|
+
const driverCall = await utils.make_driver_method(['workerName'], 'workers', 'worker-service', 'getFilePaths')(workerName);
|
|
85
85
|
return driverCall[0];
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
async delete(workerName) {
|
|
89
|
-
if (!puter.authToken && puter.env === 'web') {
|
|
88
|
+
async delete (workerName) {
|
|
89
|
+
if ( !puter.authToken && puter.env === 'web' ) {
|
|
90
90
|
try {
|
|
91
91
|
await puter.ui.authenticateWithPuter();
|
|
92
92
|
} catch (e) {
|
|
@@ -97,74 +97,77 @@ export class WorkersHandler {
|
|
|
97
97
|
|
|
98
98
|
workerName = workerName.toLocaleLowerCase(); // just incase
|
|
99
99
|
// const driverCall = await puter.drivers.call("workers", "worker-service", "destroy", { authorization: puter.authToken, workerName });
|
|
100
|
-
const driverResult = await utils.make_driver_method(['authorization', 'workerName'], 'workers',
|
|
100
|
+
const driverResult = await utils.make_driver_method(['authorization', 'workerName'], 'workers', 'worker-service', 'destroy')(puter.authToken, workerName);
|
|
101
101
|
|
|
102
|
-
if (!driverResult.result) {
|
|
103
|
-
if (!driverResult.result) {
|
|
102
|
+
if ( ! driverResult.result ) {
|
|
103
|
+
if ( ! driverResult.result ) {
|
|
104
104
|
new Error("Worker doesn't exist");
|
|
105
105
|
}
|
|
106
|
-
throw new Error(driverResult?.errors ||
|
|
106
|
+
throw new Error(driverResult?.errors || 'Driver failed to execute, do you have the necessary permissions?');
|
|
107
107
|
} else {
|
|
108
|
-
let currentWorkers = await puter.kv.get(
|
|
108
|
+
let currentWorkers = await puter.kv.get('user-workers');
|
|
109
109
|
|
|
110
|
-
if (!currentWorkers) {
|
|
110
|
+
if ( ! currentWorkers ) {
|
|
111
111
|
currentWorkers = {};
|
|
112
112
|
}
|
|
113
113
|
delete currentWorkers[workerName];
|
|
114
114
|
|
|
115
|
-
await puter.kv.set(
|
|
115
|
+
await puter.kv.set('user-workers', currentWorkers);
|
|
116
116
|
return true;
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
|
-
|
|
119
|
+
|
|
120
120
|
async getLoggingHandle (workerName) {
|
|
121
|
-
const loggingEndpoint = await utils.make_driver_method([], 'workers',
|
|
121
|
+
const loggingEndpoint = await utils.make_driver_method([], 'workers', 'worker-service', 'getLoggingUrl')(puter.authToken, workerName);
|
|
122
122
|
const socket = new WebSocket(`${loggingEndpoint}/${puter.authToken}/${workerName}`);
|
|
123
123
|
const logStreamObject = new EventTarget();
|
|
124
|
-
logStreamObject.onLog = (data) => {
|
|
124
|
+
logStreamObject.onLog = (data) => {
|
|
125
|
+
|
|
126
|
+
};
|
|
125
127
|
|
|
126
128
|
// Coercibility to ReadableStream
|
|
127
129
|
Object.defineProperty(logStreamObject, 'start', {
|
|
128
130
|
enumerable: false,
|
|
129
131
|
value: async (controller) => {
|
|
130
|
-
socket.addEventListener(
|
|
132
|
+
socket.addEventListener('message', (event) => {
|
|
131
133
|
controller.enqueue(JSON.parse(event.data));
|
|
132
134
|
});
|
|
133
|
-
socket.addEventListener(
|
|
135
|
+
socket.addEventListener('close', (event) => {
|
|
134
136
|
try {
|
|
135
137
|
controller.close();
|
|
136
|
-
} catch (e) {
|
|
138
|
+
} catch (e) {
|
|
139
|
+
|
|
140
|
+
}
|
|
137
141
|
});
|
|
138
|
-
}
|
|
142
|
+
},
|
|
139
143
|
});
|
|
140
144
|
Object.defineProperty(logStreamObject, 'cancel', {
|
|
141
145
|
enumerable: false,
|
|
142
146
|
value: async () => {
|
|
143
147
|
socket.close();
|
|
144
|
-
}
|
|
148
|
+
},
|
|
145
149
|
});
|
|
146
150
|
|
|
151
|
+
socket.addEventListener('message', (event) => {
|
|
152
|
+
const logEvent = new MessageEvent('log', { data: JSON.parse(event.data) });
|
|
147
153
|
|
|
148
|
-
|
|
149
|
-
const logEvent = new MessageEvent("log", { data: JSON.parse(event.data) });
|
|
150
|
-
|
|
151
|
-
logStreamObject.dispatchEvent(logEvent)
|
|
154
|
+
logStreamObject.dispatchEvent(logEvent);
|
|
152
155
|
logStreamObject.onLog(logEvent);
|
|
153
156
|
});
|
|
154
157
|
logStreamObject.close = socket.close;
|
|
155
158
|
return new Promise((res, rej) => {
|
|
156
159
|
let done = false;
|
|
157
|
-
socket.onopen = ()=>{
|
|
160
|
+
socket.onopen = () => {
|
|
158
161
|
done = true;
|
|
159
162
|
res(logStreamObject);
|
|
160
|
-
}
|
|
163
|
+
};
|
|
161
164
|
|
|
162
165
|
socket.onerror = () => {
|
|
163
|
-
if (!done) {
|
|
164
|
-
rej(
|
|
166
|
+
if ( ! done ) {
|
|
167
|
+
rej('Failed to open logging connection');
|
|
165
168
|
}
|
|
166
|
-
}
|
|
167
|
-
})
|
|
169
|
+
};
|
|
170
|
+
});
|
|
168
171
|
}
|
|
169
172
|
|
|
170
173
|
}
|
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
import EventListener from
|
|
2
|
-
import { errors } from
|
|
3
|
-
import { PWispHandler } from
|
|
1
|
+
import EventListener from '../../lib/EventListener.js';
|
|
2
|
+
import { errors } from './parsers.js';
|
|
3
|
+
import { PWispHandler } from './PWispHandler.js';
|
|
4
4
|
const texten = new TextEncoder();
|
|
5
5
|
const requireAuth = false; // for initial launch
|
|
6
6
|
|
|
7
7
|
export let wispInfo = {
|
|
8
|
-
server:
|
|
9
|
-
handler: undefined
|
|
8
|
+
server: 'wss://puter.cafe/', // Unused currently
|
|
9
|
+
handler: undefined,
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
export class PSocket extends EventListener {
|
|
13
13
|
_events = new Map();
|
|
14
14
|
_streamID;
|
|
15
|
-
constructor(host, port) {
|
|
16
|
-
super([
|
|
15
|
+
constructor (host, port) {
|
|
16
|
+
super(['data', 'drain', 'open', 'error', 'close', 'tlsdata', 'tlsopen', 'tlsclose']);
|
|
17
17
|
|
|
18
18
|
(async () => {
|
|
19
|
-
if(!puter.authToken && puter.env === 'web' && requireAuth){
|
|
20
|
-
try{
|
|
19
|
+
if ( !puter.authToken && puter.env === 'web' && requireAuth ) {
|
|
20
|
+
try {
|
|
21
21
|
await puter.ui.authenticateWithPuter();
|
|
22
|
-
|
|
23
|
-
}catch(e){
|
|
22
|
+
|
|
23
|
+
} catch (e) {
|
|
24
24
|
// if authentication fails, throw an error
|
|
25
25
|
throw (e);
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
|
-
if (!wispInfo.handler) {
|
|
28
|
+
if ( ! wispInfo.handler ) {
|
|
29
29
|
// first launch -- lets init the socket
|
|
30
|
-
const { token: wispToken, server: wispServer } = (await (await fetch(puter.APIOrigin
|
|
30
|
+
const { token: wispToken, server: wispServer } = (await (await fetch(`${puter.APIOrigin }/wisp/relay-token/create`, {
|
|
31
31
|
method: 'POST',
|
|
32
32
|
headers: {
|
|
33
|
-
Authorization: puter.authToken ? `Bearer ${puter.authToken}
|
|
33
|
+
Authorization: puter.authToken ? `Bearer ${puter.authToken}` : '',
|
|
34
34
|
'Content-Type': 'application/json',
|
|
35
35
|
},
|
|
36
36
|
body: JSON.stringify({}),
|
|
37
37
|
})).json());
|
|
38
|
-
|
|
38
|
+
|
|
39
39
|
wispInfo.handler = new PWispHandler(wispServer, wispToken);
|
|
40
40
|
// Wait for websocket to fully open
|
|
41
41
|
await new Promise((res, req) => {
|
|
@@ -43,45 +43,45 @@ export class PSocket extends EventListener {
|
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
46
|
const callbacks = {
|
|
49
47
|
dataCallBack: (data) => {
|
|
50
|
-
this.emit(
|
|
48
|
+
this.emit('data', data);
|
|
51
49
|
},
|
|
52
50
|
closeCallBack: (reason) => {
|
|
53
|
-
if (reason !== 0x02) {
|
|
54
|
-
this.emit(
|
|
55
|
-
this.emit(
|
|
56
|
-
return;
|
|
51
|
+
if ( reason !== 0x02 ) {
|
|
52
|
+
this.emit('error', new Error(errors[reason]));
|
|
53
|
+
this.emit('close', true);
|
|
54
|
+
return;
|
|
57
55
|
}
|
|
58
|
-
this.emit(
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
56
|
+
this.emit('close', false);
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
|
|
62
60
|
this._streamID = wispInfo.handler.register(host, port, callbacks);
|
|
63
|
-
setTimeout(() => {
|
|
61
|
+
setTimeout(() => {
|
|
62
|
+
this.emit('open', undefined);
|
|
63
|
+
}, 0);
|
|
64
64
|
|
|
65
65
|
})();
|
|
66
66
|
}
|
|
67
|
-
addListener(...args) {
|
|
67
|
+
addListener (...args) {
|
|
68
68
|
this.on(...args);
|
|
69
69
|
}
|
|
70
|
-
write(data, callback) {
|
|
71
|
-
if (data.buffer) { // TypedArray
|
|
70
|
+
write (data, callback) {
|
|
71
|
+
if ( data.buffer ) { // TypedArray
|
|
72
72
|
wispInfo.handler.write(this._streamID, data);
|
|
73
|
-
if (callback) callback();
|
|
74
|
-
} else if (data.resize) { // ArrayBuffer
|
|
73
|
+
if ( callback ) callback();
|
|
74
|
+
} else if ( data.resize ) { // ArrayBuffer
|
|
75
75
|
data.write(this._streamID, new Uint8Array(data));
|
|
76
|
-
if (callback) callback();
|
|
77
|
-
} else if (typeof(data) ===
|
|
78
|
-
wispInfo.handler.write(this._streamID, texten.encode(data))
|
|
79
|
-
if (callback) callback();
|
|
76
|
+
if ( callback ) callback();
|
|
77
|
+
} else if ( typeof (data) === 'string' ) {
|
|
78
|
+
wispInfo.handler.write(this._streamID, texten.encode(data));
|
|
79
|
+
if ( callback ) callback();
|
|
80
80
|
} else {
|
|
81
|
-
throw new Error(
|
|
81
|
+
throw new Error('Invalid data type (not TypedArray, ArrayBuffer or String!!)');
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
|
-
close() {
|
|
84
|
+
close () {
|
|
85
85
|
wispInfo.handler.close(this._streamID);
|
|
86
86
|
}
|
|
87
87
|
}
|
|
@@ -2,102 +2,109 @@
|
|
|
2
2
|
* This file uses https://github.com/MercuryWorkshop/rustls-wasm authored by GitHub:@r58Playz under the MIT License
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { PSocket } from
|
|
5
|
+
import { PSocket } from './PSocket.js';
|
|
6
6
|
|
|
7
7
|
let rustls = undefined;
|
|
8
8
|
|
|
9
9
|
export class PTLSSocket extends PSocket {
|
|
10
|
-
constructor(...args) {
|
|
10
|
+
constructor (...args) {
|
|
11
11
|
super(...args);
|
|
12
|
-
super.on(
|
|
13
|
-
if (!rustls) {
|
|
12
|
+
super.on('open', (async () => {
|
|
13
|
+
if ( ! rustls ) {
|
|
14
14
|
// Safari exists unfortunately without good ReadableStream support. Until that is fixed we need this.
|
|
15
|
-
if (!globalThis.ReadableByteStreamController) {
|
|
16
|
-
await import( /* webpackIgnore: true */
|
|
15
|
+
if ( ! globalThis.ReadableByteStreamController ) {
|
|
16
|
+
await import( /* webpackIgnore: true */ 'https://unpkg.com/web-streams-polyfill@3.0.2/dist/polyfill.js');
|
|
17
17
|
}
|
|
18
|
-
rustls = (await import( /* webpackIgnore: true */
|
|
19
|
-
await rustls.default(
|
|
18
|
+
rustls = (await import( /* webpackIgnore: true */ 'https://puter-net.b-cdn.net/rustls.js'));
|
|
19
|
+
await rustls.default('https://puter-net.b-cdn.net/rustls.wasm');
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
let cancelled = false;
|
|
23
23
|
const readable = new ReadableStream({
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
26
|
-
* @param {ReadableStreamDefaultController} controller
|
|
25
|
+
*
|
|
26
|
+
* @param {ReadableStreamDefaultController} controller
|
|
27
27
|
*/
|
|
28
28
|
start: (controller) => {
|
|
29
|
-
super.on(
|
|
30
|
-
controller.enqueue(data.buffer)
|
|
31
|
-
})
|
|
32
|
-
super.on(
|
|
33
|
-
if (!cancelled)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
29
|
+
super.on('data', (data) => {
|
|
30
|
+
controller.enqueue(data.buffer);
|
|
31
|
+
});
|
|
32
|
+
super.on('close', () => {
|
|
33
|
+
if ( ! cancelled )
|
|
34
|
+
{
|
|
35
|
+
controller.close();
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
37
39
|
},
|
|
38
40
|
pull: (controller) => {
|
|
39
41
|
|
|
40
42
|
},
|
|
41
43
|
cancel: () => {
|
|
42
44
|
cancelled = true;
|
|
43
|
-
}
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
});
|
|
44
48
|
|
|
45
|
-
})
|
|
46
|
-
|
|
47
49
|
const writable = new WritableStream({
|
|
48
|
-
write: (chunk) => {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
write: (chunk) => {
|
|
51
|
+
super.write(chunk);
|
|
52
|
+
},
|
|
53
|
+
abort: () => {
|
|
54
|
+
super.close();
|
|
55
|
+
},
|
|
56
|
+
close: () => {
|
|
57
|
+
super.close();
|
|
58
|
+
},
|
|
59
|
+
});
|
|
52
60
|
|
|
53
61
|
let read, write;
|
|
54
62
|
try {
|
|
55
|
-
const TLSConnnection = await rustls.connect_tls(readable, writable, args[0])
|
|
63
|
+
const TLSConnnection = await rustls.connect_tls(readable, writable, args[0]);
|
|
56
64
|
read = TLSConnnection.read;
|
|
57
65
|
write = TLSConnnection.write;
|
|
58
66
|
} catch (e) {
|
|
59
|
-
this.emit(
|
|
67
|
+
this.emit('error', new Error(`TLS Handshake failed: ${ e}`));
|
|
60
68
|
return;
|
|
61
69
|
}
|
|
62
|
-
|
|
63
|
-
|
|
70
|
+
|
|
64
71
|
this.writer = write.getWriter();
|
|
65
72
|
// writer.write("GET / HTTP/1.1\r\nHost: google.com\r\n\r\n");
|
|
66
73
|
let reader = read.getReader();
|
|
67
74
|
let done = false;
|
|
68
|
-
this.emit(
|
|
69
|
-
try {
|
|
70
|
-
while (!done) {
|
|
71
|
-
const {done: readerDone, value} = await reader.read();
|
|
75
|
+
this.emit('tlsopen', undefined);
|
|
76
|
+
try {
|
|
77
|
+
while ( !done ) {
|
|
78
|
+
const { done: readerDone, value } = await reader.read();
|
|
72
79
|
done = readerDone;
|
|
73
|
-
if (!done) {
|
|
74
|
-
this.emit(
|
|
80
|
+
if ( ! done ) {
|
|
81
|
+
this.emit('tlsdata', value);
|
|
75
82
|
}
|
|
76
83
|
}
|
|
77
|
-
this.emit(
|
|
84
|
+
this.emit('tlsclose', false);
|
|
78
85
|
} catch (e) {
|
|
79
|
-
this.emit(
|
|
80
|
-
this.emit(
|
|
86
|
+
this.emit('error', e);
|
|
87
|
+
this.emit('tlsclose', true);
|
|
81
88
|
}
|
|
82
|
-
|
|
89
|
+
|
|
83
90
|
}));
|
|
84
91
|
}
|
|
85
|
-
on(event, callback) {
|
|
86
|
-
if (event ===
|
|
87
|
-
return super.on(
|
|
92
|
+
on (event, callback) {
|
|
93
|
+
if ( event === 'data' || event === 'open' || event === 'close' ) {
|
|
94
|
+
return super.on(`tls${ event}`, callback);
|
|
88
95
|
} else {
|
|
89
96
|
return super.on(event, callback);
|
|
90
97
|
}
|
|
91
98
|
}
|
|
92
|
-
write(data, callback) {
|
|
93
|
-
if (data.buffer) { // TypedArray
|
|
99
|
+
write (data, callback) {
|
|
100
|
+
if ( data.buffer ) { // TypedArray
|
|
94
101
|
this.writer.write(data.slice(0).buffer).then(callback);
|
|
95
|
-
} else if (data.resize) { // ArrayBuffer
|
|
102
|
+
} else if ( data.resize ) { // ArrayBuffer
|
|
96
103
|
this.writer.write(data).then(callback);
|
|
97
|
-
} else if (typeof(data) ===
|
|
104
|
+
} else if ( typeof (data) === 'string' ) {
|
|
98
105
|
this.writer.write(data).then(callback);
|
|
99
106
|
} else {
|
|
100
|
-
throw new Error(
|
|
107
|
+
throw new Error('Invalid data type (not TypedArray, ArrayBuffer or String!!)');
|
|
101
108
|
}
|
|
102
109
|
}
|
|
103
110
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {CLOSE, CONNECT, DATA, CONTINUE, INFO, TCP, UDP, createWispPacket, parseIncomingPacket, textde} from
|
|
1
|
+
import { CLOSE, CONNECT, DATA, CONTINUE, INFO, TCP, UDP, createWispPacket, parseIncomingPacket, textde } from './parsers.js';
|
|
2
2
|
|
|
3
3
|
export class PWispHandler {
|
|
4
4
|
_ws;
|
|
@@ -6,84 +6,86 @@ export class PWispHandler {
|
|
|
6
6
|
_bufferMax;
|
|
7
7
|
onReady = undefined;
|
|
8
8
|
streamMap = new Map();
|
|
9
|
-
constructor(wispURL, puterAuth) {
|
|
9
|
+
constructor (wispURL, puterAuth) {
|
|
10
10
|
const setup = () => {
|
|
11
11
|
this._ws = new WebSocket(wispURL);
|
|
12
|
-
this._ws.binaryType =
|
|
12
|
+
this._ws.binaryType = 'arraybuffer';
|
|
13
13
|
this._ws.onmessage = (event) => {
|
|
14
14
|
const parsed = parseIncomingPacket(new Uint8Array(event.data));
|
|
15
|
-
switch (parsed.packetType) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
return;
|
|
15
|
+
switch ( parsed.packetType ) {
|
|
16
|
+
case DATA:
|
|
17
|
+
this.streamMap.get(parsed.streamID).dataCallBack(parsed.payload.slice(0)); // return a copy for the user to do as they please
|
|
18
|
+
break;
|
|
19
|
+
case CONTINUE:
|
|
20
|
+
if ( parsed.streamID === 0 ) {
|
|
21
|
+
this._bufferMax = parsed.remainingBuffer;
|
|
22
|
+
this._ws.onclose = () => {
|
|
23
|
+
setTimeout(setup(), 1000);
|
|
24
|
+
};
|
|
25
|
+
if ( this.onReady ) {
|
|
26
|
+
this.onReady();
|
|
29
27
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
this.streamMap.get(parsed.streamID).buffer = parsed.remainingBuffer;
|
|
31
|
+
this._continue();
|
|
32
|
+
break;
|
|
33
|
+
case CLOSE:
|
|
34
|
+
if ( parsed.streamID !== 0 )
|
|
35
|
+
{
|
|
36
|
+
this.streamMap.get(parsed.streamID).closeCallBack(parsed.reason);
|
|
37
|
+
}
|
|
38
|
+
break;
|
|
39
|
+
case INFO:
|
|
40
|
+
puterAuth && this._ws.send(createWispPacket({
|
|
41
|
+
packetType: INFO,
|
|
42
|
+
streamID: 0,
|
|
43
|
+
puterAuth,
|
|
44
|
+
}));
|
|
45
|
+
break;
|
|
44
46
|
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
+
};
|
|
48
|
+
};
|
|
47
49
|
setup();
|
|
48
50
|
}
|
|
49
|
-
_continue(streamID) {
|
|
51
|
+
_continue (streamID) {
|
|
50
52
|
const queue = this.streamMap.get(streamID).queue;
|
|
51
|
-
for (let i = 0; i < queue.length; i++) {
|
|
53
|
+
for ( let i = 0; i < queue.length; i++ ) {
|
|
52
54
|
this.write(streamID, queue.shift());
|
|
53
55
|
}
|
|
54
56
|
}
|
|
55
|
-
register(host, port, callbacks) {
|
|
57
|
+
register (host, port, callbacks) {
|
|
56
58
|
const streamID = this._nextStreamID++;
|
|
57
|
-
this.streamMap.set(streamID, {queue: [], streamID, buffer: this._bufferMax, dataCallBack: callbacks.dataCallBack, closeCallBack: callbacks.closeCallBack});
|
|
59
|
+
this.streamMap.set(streamID, { queue: [], streamID, buffer: this._bufferMax, dataCallBack: callbacks.dataCallBack, closeCallBack: callbacks.closeCallBack });
|
|
58
60
|
this._ws.send(createWispPacket({
|
|
59
61
|
packetType: CONNECT,
|
|
60
62
|
streamType: TCP,
|
|
61
63
|
streamID: streamID,
|
|
62
64
|
hostname: host,
|
|
63
|
-
port: port
|
|
64
|
-
}))
|
|
65
|
+
port: port,
|
|
66
|
+
}));
|
|
65
67
|
return streamID;
|
|
66
68
|
}
|
|
67
69
|
|
|
68
|
-
write(streamID, data) {
|
|
70
|
+
write (streamID, data) {
|
|
69
71
|
const streamData = this.streamMap.get(streamID);
|
|
70
|
-
if (streamData.buffer > 0) {
|
|
72
|
+
if ( streamData.buffer > 0 ) {
|
|
71
73
|
streamData.buffer--;
|
|
72
74
|
|
|
73
75
|
this._ws.send(createWispPacket({
|
|
74
76
|
packetType: DATA,
|
|
75
77
|
streamID: streamID,
|
|
76
|
-
payload: data
|
|
77
|
-
}))
|
|
78
|
+
payload: data,
|
|
79
|
+
}));
|
|
78
80
|
} else {
|
|
79
|
-
streamData.queue.push(data)
|
|
81
|
+
streamData.queue.push(data);
|
|
80
82
|
}
|
|
81
83
|
}
|
|
82
|
-
close(streamID) {
|
|
84
|
+
close (streamID) {
|
|
83
85
|
this._ws.send(createWispPacket({
|
|
84
86
|
packetType: CLOSE,
|
|
85
87
|
streamID: streamID,
|
|
86
|
-
reason: 0x02
|
|
87
|
-
}))
|
|
88
|
+
reason: 0x02,
|
|
89
|
+
}));
|
|
88
90
|
}
|
|
89
91
|
}
|