1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
//! 传输层:启动 Camoufox 子进程,并建立 Juggler 的 fd3/fd4 异步管道。
//!
//! Juggler 通过 `-juggler-pipe` 在子进程的 **fd3(读命令)/ fd4(写响应)** 上通信:
//! - 父进程把命令写入一个管道,其读端是子进程的 **fd3**;
//! - 子进程把响应写入另一个管道,其写端是子进程的 **fd4**,父进程读其读端。
//!
//! 帧格式由 [`crate::codec`] 负责(UTF-8 JSON + 单个 `\0`)。本层只负责字节进出 +
//! 子进程生命周期 + stderr 捕获(就绪检测与日志由 [`crate::launcher::process`] 使用)。
//!
//! 跨平台:
//! - **unix(macOS / Linux)**:`os_pipe` 匿名管道 + `command-fds` 映射子进程 fd3/fd4,
//! 父端用 tokio `unix::pipe` 异步读写。
//! - **windows**:命名管道(父端 tokio `NamedPipeServer` 异步,子端同步可继承句柄),
//! 句柄经 **CRT `lpReserved2` 块**注入子进程 fd3/fd4(等价 libuv/Node 的做法,
//! Camoufox/Firefox 的 `wmain`/`LauncherProcessWin` 用 `_get_osfhandle(3/4)` 取用)。
//!
//! 上层([`crate::protocol::Connection::from_pipe`] / Camoufox 后端的 `BrowserServer`)
//! 对 `writer`/`reader` 只要求 `AsyncWrite`/`AsyncRead`,故两平台的具体类型经下方别名统一。
pub use ;
pub use ;
// ── 跨平台传输类型别名 ────────────────────────────────────────────────────────
// 子进程句柄:unix 直接用 tokio 的 `Child`;windows 用自管理的 `WinChild`(同名方法
// `wait().await` / `kill().await` / `start_kill()`,故消费侧代码两平台一致)。
pub use Child;
pub use WinChild as Child;
// Juggler 命令写端(父→子 fd3):unix 管道 `Sender` / windows 命名管道 `NamedPipeServer`。
pub use Sender as PipeWriter;
pub use NamedPipeServer as PipeWriter;
// Juggler 响应读端(子 fd4→父):unix 管道 `Receiver` / windows 命名管道 `NamedPipeServer`。
pub use Receiver as PipeReader;
pub use NamedPipeServer as PipeReader;
use TcpStream;
use ;
use crate::;
/// 连接到一个 **Juggler WebSocket 端点**(`ws://host:port/token`),返回已就绪的 ws 流。
///
/// 端点必须讲**原始 Juggler 协议**(由 Camoufox 后端的 `BrowserServer` 暴露),
/// 而不是 Camoufox `python -m camoufox server` 那种 Playwright RPC 协议(二者不兼容)。
pub async