Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/project/servers/hub/handle-message.ts
Views: 687
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45/*6Handle a general message from the hub. These are the generic message,7as opposed to the messages specific to "client" functionality such as8database queries.9*/1011import processKill from "@cocalc/backend/misc/process-kill";12import { CoCalcSocket } from "@cocalc/backend/tcp/enable-messaging-protocol";13import { handle_save_blob_message } from "@cocalc/project/blobs";14import { getClient } from "@cocalc/project/client";15import { project_id } from "@cocalc/project/data";16import { exec_shell_code } from "@cocalc/project/exec_shell_code";17import { get_kernel_data } from "@cocalc/jupyter/kernel/kernel-data";18import jupyterExecute from "@cocalc/jupyter/stateless-api/execute";19import { getLogger } from "@cocalc/project/logger";20import handleNamedServer from "@cocalc/project/named-servers";21import { print_to_pdf } from "@cocalc/project/print_to_pdf";22import {23read_file_from_project,24write_file_to_project,25} from "@cocalc/project/read_write_files";26import * as message from "@cocalc/util/message";27import { version } from "@cocalc/util/smc-version";28import { Message } from "./types";29import writeTextFileToProject from "./write-text-file-to-project";30import readTextFileFromProject from "./read-text-file-from-project";3132const logger = getLogger("handle-message-from-hub");3334export default async function handleMessage(35socket: CoCalcSocket,36mesg: Message,37) {38logger.debug("received a message", {39event: mesg.event,40id: mesg.id,41"...": "...",42});4344// We can't just log this in general, since it can be big.45// So only uncomment this for low level debugging, unfortunately.46// logger.debug("received ", mesg);4748if (getClient().handle_mesg(mesg, socket)) {49return;50}5152switch (mesg.event) {53case "heartbeat":54logger.debug(`received heartbeat on socket '${socket.id}'`);55// Update the last hearbeat timestamp, so we know socket is working.56socket.heartbeat = new Date();57return;5859case "ping":60// ping message is used only for debugging purposes.61socket.write_mesg("json", message.pong({ id: mesg.id }));62return;6364case "named_server_port":65handleNamedServer(socket, mesg);66return;6768case "project_exec":69// this is no longer used by web browser clients; however it *is* used by the HTTP api served70// by the hub to api key users, so do NOT remove it! E.g., the latex endpoint, the compute71// server, etc., use it. The web browser clients use the websocket api,72exec_shell_code(socket, mesg);73return;7475case "jupyter_execute":76try {77await jupyterExecute(socket, mesg);78} catch (err) {79socket.write_mesg(80"json",81message.error({82id: mesg.id,83error: `${err}`,84}),85);86}87return;8889case "jupyter_kernels":90try {91socket.write_mesg(92"json",93message.jupyter_kernels({94kernels: await get_kernel_data(),95id: mesg.id,96}),97);98} catch (err) {99socket.write_mesg(100"json",101message.error({102id: mesg.id,103error: `${err}`,104}),105);106}107return;108109// Reading and writing files to/from project and sending over socket110case "read_file_from_project":111read_file_from_project(socket, mesg);112return;113114case "write_file_to_project":115write_file_to_project(socket, mesg);116return;117118case "write_text_file_to_project":119writeTextFileToProject(socket, mesg);120return;121122case "read_text_file_from_project":123readTextFileFromProject(socket, mesg);124return;125126case "print_to_pdf":127print_to_pdf(socket, mesg);128return;129130case "send_signal":131if (132mesg.pid &&133(mesg.signal == 2 || mesg.signal == 3 || mesg.signal == 9)134) {135processKill(mesg.pid, mesg.signal);136} else {137if (mesg.id) {138socket.write_mesg(139"json",140message.error({141id: mesg.id,142error: "invalid pid or signal (must be 2,3,9)",143}),144);145}146return;147}148if (mesg.id != null) {149// send back confirmation that a signal was sent150socket.write_mesg("json", message.signal_sent({ id: mesg.id }));151}152return;153154case "save_blob":155handle_save_blob_message(mesg);156return;157158case "error":159logger.error(`ERROR from hub: ${mesg.error}`);160return;161162case "hello":163// No action -- this is used by the hub to send an initial control message that has no effect, so that164// we know this socket will be used for control messages.165logger.info(`hello from hub -- sending back our version = ${version}`);166socket.write_mesg("json", message.version({ version }));167return;168169default:170if (mesg.id != null) {171// only respond with error if there is an id -- otherwise response has no meaning to hub.172const err = message.error({173id: mesg.id,174error: `Project ${project_id} does not implement handling mesg with event='${mesg.event}'`,175});176socket.write_mesg("json", err);177} else {178logger.debug(`Dropping unknown message with event='${mesg.event}'`);179}180}181}182183184