core: Remove app.js.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 9m3s
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 9m3s
This commit is contained in:
188
core/app.js
188
core/app.js
@@ -1,188 +0,0 @@
|
|||||||
/**
|
|
||||||
* \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, {});
|
|
||||||
};
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
@@ -5,12 +5,6 @@
|
|||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** \cond */
|
|
||||||
import * as app_module from './app.js';
|
|
||||||
|
|
||||||
export {invoke, getProcessBlob};
|
|
||||||
/** \endcond */
|
|
||||||
|
|
||||||
/** All running processes. */
|
/** All running processes. */
|
||||||
let gProcesses = {};
|
let gProcesses = {};
|
||||||
/** Whether stats are currently being sent. */
|
/** Whether stats are currently being sent. */
|
||||||
|
|||||||
@@ -741,7 +741,6 @@ static void _httpd_auth_query_after_work(tf_ssb_t* ssb, int status, void* user_d
|
|||||||
|
|
||||||
uv_timer_start(&work->timer, _httpd_app_on_timer, 6 * 1000, 6 * 1000);
|
uv_timer_start(&work->timer, _httpd_app_on_timer, 6 * 1000, 6 * 1000);
|
||||||
|
|
||||||
/* What now? */
|
|
||||||
tf_free((void*)cookie);
|
tf_free((void*)cookie);
|
||||||
JS_FreeCString(context, name_string);
|
JS_FreeCString(context, name_string);
|
||||||
|
|
||||||
@@ -752,7 +751,7 @@ static void _httpd_auth_query_after_work(tf_ssb_t* ssb, int status, void* user_d
|
|||||||
request->user_data = work;
|
request->user_data = work;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _tf_httpd_endpoint_app_socket_c(tf_http_request_t* request)
|
void tf_httpd_endpoint_app_socket(tf_http_request_t* request)
|
||||||
{
|
{
|
||||||
const char* header_connection = tf_http_request_get_header(request, "connection");
|
const char* header_connection = tf_http_request_get_header(request, "connection");
|
||||||
const char* header_upgrade = tf_http_request_get_header(request, "upgrade");
|
const char* header_upgrade = tf_http_request_get_header(request, "upgrade");
|
||||||
@@ -786,65 +785,3 @@ static void _tf_httpd_endpoint_app_socket_c(tf_http_request_t* request)
|
|||||||
tf_ssb_run_work(ssb, _httpd_auth_query_work, _httpd_auth_query_after_work, work);
|
tf_ssb_run_work(ssb, _httpd_auth_query_work, _httpd_auth_query_after_work, work);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _tf_httpd_endpoint_app_socket_js(tf_http_request_t* request)
|
|
||||||
{
|
|
||||||
tf_task_t* task = request->user_data;
|
|
||||||
tf_ssb_t* ssb = tf_task_get_ssb(task);
|
|
||||||
|
|
||||||
JSContext* context = tf_ssb_get_context(ssb);
|
|
||||||
JSValue global = JS_GetGlobalObject(context);
|
|
||||||
JSValue exports = JS_GetPropertyStr(context, global, "exports");
|
|
||||||
JSValue app_socket = JS_GetPropertyStr(context, exports, "app_socket");
|
|
||||||
|
|
||||||
JSValue request_object = JS_NewObject(context);
|
|
||||||
JSValue headers = JS_NewObject(context);
|
|
||||||
for (int i = 0; i < request->headers_count; i++)
|
|
||||||
{
|
|
||||||
JS_SetPropertyStr(context, headers, request->headers[i].name, JS_NewString(context, request->headers[i].value));
|
|
||||||
}
|
|
||||||
JS_SetPropertyStr(context, request_object, "headers", headers);
|
|
||||||
|
|
||||||
JSValue response = tf_httpd_make_response_object(context, request);
|
|
||||||
tf_http_request_ref(request);
|
|
||||||
|
|
||||||
JSValue args[] = {
|
|
||||||
request_object,
|
|
||||||
response,
|
|
||||||
};
|
|
||||||
|
|
||||||
JSValue result = JS_Call(context, app_socket, JS_NULL, tf_countof(args), args);
|
|
||||||
tf_util_report_error(context, result);
|
|
||||||
JS_FreeValue(context, result);
|
|
||||||
|
|
||||||
for (int i = 0; i < tf_countof(args); i++)
|
|
||||||
{
|
|
||||||
JS_FreeValue(context, args[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_FreeValue(context, app_socket);
|
|
||||||
JS_FreeValue(context, exports);
|
|
||||||
JS_FreeValue(context, global);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tf_httpd_endpoint_app_socket(tf_http_request_t* request)
|
|
||||||
{
|
|
||||||
static bool checked_env;
|
|
||||||
static bool use_c;
|
|
||||||
if (!checked_env)
|
|
||||||
{
|
|
||||||
char buffer[8] = { 0 };
|
|
||||||
size_t buffer_size = sizeof(buffer);
|
|
||||||
use_c = uv_os_getenv("TF_APP_C", buffer, &buffer_size) == 0 && strcmp(buffer, "1") == 0;
|
|
||||||
checked_env = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (use_c)
|
|
||||||
{
|
|
||||||
_tf_httpd_endpoint_app_socket_c(request);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_tf_httpd_endpoint_app_socket_js(request);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user