# notify `b612.me/notify` 是一个面向点对点直连场景的 Go 通信基础包,覆盖消息信令、流式传输、批量数据通道和文件传输内核能力。 ## 模块定位 - 消息面:`Send`、`SendWait`、`Reply`、`SetLink` - 流式数据面:`OpenStream` - 记录流数据面:`OpenRecordStream` - 批量数据面:`OpenBulk`(`shared` / `dedicated`) - 文件传输内核:transfer control / progress / resume - 观测面:runtime snapshot / diagnostics summary - 会话模型:`LogicalConn`(逻辑会话)与 `TransportConn`(物理承载)分离 ## 版本要求 - Go `1.24+` ## 安全初始化要求 `Client` / `Server` 在 `Connect` / `Listen` 前必须完成安全配置。默认使用现代 PSK 方案。 - 客户端:`UseModernPSKClient` - 服务端:`UseModernPSKServer` 未配置时会返回 `errModernPSKRequired`。 ## 安全模式选择 - `UseModernPSKClient` / `UseModernPSKServer` - bootstrap 和稳态传输都由 `notify` 自己保护 - 适合默认场景 - 支持 peer attach 显式认证、抗重放,以及在需要时协商前向保密 - `UsePSKOverExternalTransportClient` / `UsePSKOverExternalTransportServer` - bootstrap 仍用 PSK 做认证 - 稳态阶段信任外部物理通道,不再做 `notify` 内层加密 - 适合 `tls.Conn` 或调用方自认可信的外部通道 - 不支持 `RequireForwardSecrecy` - `UseNestedSecurityClient` / `UseNestedSecurityServer` - 外层已有可信通道,但仍保留 `notify` 内层保护 - 适合需要“外层可信 + 内层独立保护”的场景 ## 快速开始 服务端: ```go package main import ( "log" "b612.me/notify" ) func main() { srv := notify.NewServer() if err := notify.UseModernPSKServer(srv, []byte("shared-secret"), nil); err != nil { log.Fatal(err) } srv.SetLink("ping", func(msg *notify.Message) { _ = msg.Reply([]byte("pong")) }) if err := srv.Listen("tcp", "127.0.0.1:28080"); err != nil { log.Fatal(err) } select {} } ``` 客户端: ```go package main import ( "log" "time" "b612.me/notify" ) func main() { cli := notify.NewClient() if err := notify.UseModernPSKClient(cli, []byte("shared-secret"), nil); err != nil { log.Fatal(err) } if err := cli.Connect("tcp", "127.0.0.1:28080"); err != nil { log.Fatal(err) } defer cli.Stop() reply, err := cli.SendWait("ping", []byte("hello"), 5*time.Second) if err != nil { log.Fatal(err) } log.Printf("reply=%s", string(reply.Value)) } ``` ## 连接入口与物理连接语义 - `Connect` / `ConnectTimeout` - 由 `notify` 自己拨号 - 支持重连,也支持 dedicated bulk 额外 sidecar 连接 - `ConnectByFactory` - 调用方提供 `dialFn` - `notify` 会在需要时再次调用 `dialFn`,因此仍支持重连和 dedicated bulk - `ConnectByConn` - 调用方注入一个已经建立好的 `net.Conn` - 该模式被视为“单物理连接模式” - `OpenDedicatedBulk` 会直接返回错误 - `OpenBulk` 使用 `auto` 模式时会自动回退到 `shared` - `ListenByListener` - 服务端复用调用方提供的 `net.Listener` - 适合需要和现有 listener 栈整合的场景 `dedicated bulk` 依赖额外物理连接,因此只适用于可再次拨号的 transport source。 ## Peer Attach 安全策略 可通过 `SetPeerAttachSecurityConfig` 配置逻辑会话 attach 阶段的额外保护。 - `RequireExplicitAuth` - 要求 peer attach 使用显式认证 - `RequireChannelBinding` - 要求 attach 绑定到底层可信通道 - 启用后会隐式要求显式认证 - `ChannelBinding` - 由调用方提供 channel binding 提取函数 - 适合外层 TLS 或其他可信通道整合 - `ReplayWindow` / `ReplayCapacity` - 控制 attach 抗重放窗口和缓存容量 如果你选择 `UsePSKOverExternalTransport*`,并且希望 attach 阶段显式绑定到外层可信信道,建议同时配置 channel binding。 ## RecordStream 说明 `RecordStream` 构建在 `Stream` 之上,适合“有边界的顺序记录”场景。 - 写入入口:`OpenRecordStream`、`WriteRecord` - 接收入口:`ReadRecord` - 确认入口:`AckRecord` - 检查点:`Barrier`、`BarrierTo` - 错误回包:`RecordFailure` 确认语义: - `AckRecord` 表示“该序号及其之前的连续记录已完成 apply”,不是“已收到” - `Barrier` / `BarrierTo` 等待的是对端 `apply-complete` 的最大连续序号 - `RecordFailure` 会返回 `FailedSeq`、`Code`、`Retryable`、`Message` 兼容与传输: - record stream 在打开阶段协商 batch ack 能力 - 双端都支持时,累计 `AckSeq` 会随 batch header piggyback 发送 - 对端不支持时,自动回退到独立 ack frame - mixed-version peer 可以互通,不要求双方同时升级 ## 诊断快照 顶层诊断入口: - `GetClientDiagnosticsSnapshot` - `GetServerDiagnosticsSnapshot` 快照内容: - 会话运行态:client / server runtime - 数据面快照:`StreamSnapshot`、`BulkSnapshot`、`RecordSnapshot` - 文件传输快照:`TransferSnapshot` - 汇总视图:`DiagnosticsSummary` `RecordSnapshot` / `DiagnosticsSummary.RecordTelemetry` 当前覆盖: - batch / ack / error frame 收发计数 - piggyback ack 命中计数 - barrier 等待时间拆分:`flush` / `apply` - `outstanding records/bytes` - `pending apply / pending ack / peak pending apply` ## 传输与 IPC - `tcp` - `udp` - `unix` - `npipe`(Windows) 示例目录: - [examples/signal](/mnt/c/coding/gocode/src/b612.me/notify/examples/signal) ## 现代 PSK 与兼容入口 现代方案特性: - 共享密钥派生(Argon2id) - 消息层加密(AES-GCM) - `stream` / `bulk` fast path 复用现代编码栈 - peer attach 显式认证 / 抗重放 - 可选 channel binding - 可选前向保密(`UseModernPSK*` / `UseNestedSecurity*`) 兼容入口仍保留,但属于历史路径: - `UseLegacySecurityClient` - `UseLegacySecurityServer` - `ExchangeKey` - `SetSecretKey` - `SetMsgEn` / `SetMsgDe` ## 发布前检查 ```bash export SENTRUX_SKIP_GRAMMAR_DOWNLOAD='1' sentrux check . env GOCACHE=/tmp/b612-gocache GOMODCACHE=/tmp/b612-gomodcache go test ./... env GOCACHE=/tmp/b612-gocache GOMODCACHE=/tmp/b612-gomodcache go test -race ./... env GOCACHE=/tmp/b612-gocache GOMODCACHE=/tmp/b612-gomodcache go vet ./... ``` 手工 soak 测试(可选): ```bash env GOCACHE=/tmp/b612-gocache GOMODCACHE=/tmp/b612-gomodcache \ go test -tags notify_manual_soak -run 'Test_ServerTuAndClientCommon|Test_normal|Test_normal_udp' ``` ## 兼容性说明 - 对外主入口保留:`NewClient`、`NewServer`、`Connect`、`Listen`、`SetLink`、`SetDefaultLink`、`Send`、`SendWait`、`SendObj`、`Reply`、`Stop` - 内部主对象已迁移为 `LogicalConn` / `TransportConn` - `ClientConn` 作为兼容适配层继续保留