All checks were successful
Build Tilde Friends / Build-All (push) Successful in 9m2s
189 lines
4.2 KiB
JavaScript
189 lines
4.2 KiB
JavaScript
/**
|
|
* \file
|
|
* \defgroup tfapp Tilde Friends App JS
|
|
* Tilde Friends server-side app wrapper.
|
|
* @{
|
|
*/
|
|
|
|
/** \cond */
|
|
import * as core from './core.js';
|
|
/** \endcond */
|
|
|
|
/** A sequence number of apps. */
|
|
let g_session_index = 0;
|
|
|
|
/**
|
|
** App socket handler.
|
|
** @param request The HTTP request of the WebSocket connection.
|
|
** @param response The HTTP response.
|
|
*/
|
|
exports.app_socket = async function socket(request, response) {
|
|
let process;
|
|
let credentials = await httpd.auth_query(request.headers);
|
|
|
|
response.onClose = async function () {
|
|
if (process && process.task) {
|
|
process.task.kill();
|
|
}
|
|
if (process) {
|
|
process.timeout = 0;
|
|
}
|
|
};
|
|
|
|
response.onMessage = async function (event) {
|
|
if (event.opCode == 0x1 || event.opCode == 0x2) {
|
|
let message;
|
|
try {
|
|
message = JSON.parse(event.data);
|
|
} catch (error) {
|
|
print(
|
|
'WebSocket error:',
|
|
error,
|
|
event.data,
|
|
event.data.length,
|
|
event.opCode
|
|
);
|
|
return;
|
|
}
|
|
if (!process && message.action == 'hello') {
|
|
let packageOwner;
|
|
let packageName;
|
|
let blobId;
|
|
let match;
|
|
if (
|
|
(match = /^\/([&%][^\.]{44}(?:\.\w+)?)(\/?.*)/.exec(message.path))
|
|
) {
|
|
blobId = match[1];
|
|
} else if ((match = /^\/\~([^\/]+)\/([^\/]+)\/$/.exec(message.path))) {
|
|
packageOwner = match[1];
|
|
packageName = match[2];
|
|
blobId = await new Database(packageOwner).get('path:' + packageName);
|
|
if (!blobId) {
|
|
response.send(
|
|
JSON.stringify({
|
|
action: 'tfrpc',
|
|
method: 'error',
|
|
params: [message.path + ' not found'],
|
|
id: -1,
|
|
}),
|
|
0x1
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
response.send(
|
|
JSON.stringify(
|
|
Object.assign(
|
|
{
|
|
action: 'session',
|
|
credentials: credentials,
|
|
id: blobId,
|
|
},
|
|
await ssb_internal.getIdentityInfo(
|
|
credentials?.session?.name,
|
|
packageOwner,
|
|
packageName
|
|
)
|
|
)
|
|
),
|
|
0x1
|
|
);
|
|
|
|
if (blobId) {
|
|
if (message.edit_only) {
|
|
response.send(
|
|
JSON.stringify({
|
|
action: 'ready',
|
|
version: version(),
|
|
edit_only: true,
|
|
}),
|
|
0x1
|
|
);
|
|
} else {
|
|
let sessionId = 'session_' + (g_session_index++).toString();
|
|
let options = {
|
|
api: message.api || [],
|
|
credentials: credentials,
|
|
packageOwner: packageOwner,
|
|
packageName: packageName,
|
|
url: message.url,
|
|
};
|
|
process = await core.getProcessBlob(blobId, sessionId, options);
|
|
}
|
|
}
|
|
if (process) {
|
|
process.client_api.tfrpc = function (message) {
|
|
if (message.id) {
|
|
let calls = process?.app?.calls;
|
|
if (calls) {
|
|
let call = calls[message.id];
|
|
if (call) {
|
|
if (message.error !== undefined) {
|
|
call.reject(message.error);
|
|
} else {
|
|
call.resolve(message.result);
|
|
}
|
|
delete calls[message.id];
|
|
}
|
|
}
|
|
}
|
|
};
|
|
process.app._on_output = (message) =>
|
|
response.send(JSON.stringify(message), 0x1);
|
|
process.app.send();
|
|
}
|
|
|
|
let ping = function () {
|
|
let now = Date.now();
|
|
let again = true;
|
|
if (now - process.lastActive < process.timeout) {
|
|
// Active.
|
|
} else if (process.lastPing > process.lastActive) {
|
|
// We lost them.
|
|
if (process.task) {
|
|
process.task.kill();
|
|
}
|
|
again = false;
|
|
} else {
|
|
// Idle. Ping them.
|
|
response.send('', 0x9);
|
|
process.lastPing = now;
|
|
}
|
|
|
|
if (again && process.timeout) {
|
|
setTimeout(ping, process.timeout);
|
|
}
|
|
};
|
|
|
|
if (process && process.timeout > 0) {
|
|
setTimeout(ping, process.timeout);
|
|
}
|
|
} else {
|
|
if (process) {
|
|
if (process.client_api[message.action]) {
|
|
process.client_api[message.action](message);
|
|
} else if (process.eventHandlers['message']) {
|
|
await core.invoke(process.eventHandlers['message'], [message]);
|
|
}
|
|
}
|
|
}
|
|
} else if (event.opCode == 0x8) {
|
|
// Close.
|
|
if (process && process.task) {
|
|
process.task.kill();
|
|
}
|
|
response.send(event.data, 0x8);
|
|
} else if (event.opCode == 0xa) {
|
|
// PONG
|
|
}
|
|
|
|
if (process) {
|
|
process.lastActive = Date.now();
|
|
}
|
|
};
|
|
|
|
response.upgrade(100, {});
|
|
};
|
|
|
|
/** @} */
|