feat: implement Rtty server core (PTY + alacritty engine + WebSocket)

This commit is contained in:
2026-08-01 16:35:46 +08:00
parent 01b3bea1c6
commit f25506ec5b
9 changed files with 714 additions and 25 deletions

View File

@@ -1,27 +1,77 @@
//! WebSocket 通信协议。
//!
//! 服务端与客户端之间通过 WebSocket 交换消息:
//! - 客户端发送 [`ClientMessage`](输入、调整尺寸、声明控制权);
//! - 服务端发送 [`ServerMessage`](就绪、移动端快照、控制权授予、错误、会话结束)。
//!
//! 另外,为 PC 端提供**二进制**通道PTY 输出的原始 ANSI 字节流直接以 WebSocket
//! 二进制帧下发,供 `flutter_alacritty` 等渲染引擎消费,保证 100% 工业级兼容。
use serde::{Deserialize, Serialize};
/// 客户端发送给 Rtty 服务端的控制指令
/// 客户端发送给 Rtty 服务端的控制指令
#[derive(Debug, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ClientMessage {
/// 键盘/文本输入
/// 键盘/文本输入,原样写入 PTY。
Input { data: String },
/// 客户端请求 Resize
/// 客户端请求调整终端尺寸。
Resize { cols: u16, rows: u16 },
/// 客户端申明控制权 (用来解决多端控制冲突)
/// 客户端申明控制权用来解决多端控制冲突)。
ClaimControl,
/// 客户端心跳,保持连接活跃。
Ping,
}
/// 服务端推送给客户端的消息 (分别适配 PC 和 移动端)
/// 移动端语义化屏显数据(已解耦、去除 ANSI 序列)。
#[derive(Debug, Clone, Serialize)]
pub struct MobileSnapshot {
/// 光标列(相对视口)。
pub cursor_x: usize,
/// 光标行(相对视口)。
pub cursor_y: usize,
/// 网格列数。
pub cols: usize,
/// 网格行数。
pub rows: usize,
/// 当前回滚显示偏移。
pub display_offset: usize,
/// 滚动历史中的总行数。
pub scrollback_lines: usize,
/// 视口内的逐行文本(已按词、去尾空白)。
pub lines: Vec<String>,
}
/// 服务端推送给客户端的消息JSON 文本帧)。
#[derive(Debug, Serialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ServerMessage {
/// 原生 ANSI 字节流 (供 PC 端 xterm/flutter_alacritty 渲染)
RawData { data: String },
/// 移动端专属:解耦后的语义化 JSON 屏显数据
MobileSnapshot {
cursor_x: usize,
cursor_y: usize,
lines: Vec<String>,
/// 会话已就绪:携带会话 ID 与初始尺寸。
Ready {
id: String,
cols: u16,
rows: u16,
},
}
/// 移动端专属:解耦后的语义化屏显快照。
MobileSnapshot {
data: MobileSnapshot,
},
/// 控制权授予结果。
ControlResponse {
granted: bool,
holder: Option<String>,
},
/// 服务端错误。
Error {
message: String,
},
/// 会话已结束PTY 关闭)。
SessionClosed,
}
impl ServerMessage {
/// 序列化为 JSON 文本。
pub fn to_json(&self) -> String {
serde_json::to_string(self).unwrap_or_else(|_| "{}".to_string())
}
}