feat(transport): 完成安全架构拆分并收口 stream/bulk 传输优化
- 新增 managed/external/nested 三种传输保护模式 - 新增 peer attach 显式认证、抗重放、channel binding 和可选前向保密协商 - 明确单连接注入与可重拨连接源的语义边界 - 禁止 ConnectByConn 场景下 dedicated bulk 走 sidecar,auto 模式自动回退 shared - 修正 dedicated attach 在 bootstrap/steady profile 切换下的处理逻辑 - 优化 shared bulk super-batch 与批量 framed write 路径 - 降低 stream/bulk fast path 的复制和分发损耗 - 补齐 benchmark、回归测试、运行时快照和 README 文档
This commit is contained in:
@@ -3,8 +3,10 @@ package notify
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"b612.me/starcrypto"
|
||||
)
|
||||
@@ -207,6 +209,17 @@ func TestUseModernPSKRejectsEmptySecret(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUsePSKOverExternalTransportRejectsForwardSecrecyRequirement(t *testing.T) {
|
||||
opts := testModernPSKOptions()
|
||||
opts.RequireForwardSecrecy = true
|
||||
if err := UsePSKOverExternalTransportClient(NewClient(), []byte("secret"), opts); !errors.Is(err, errModernPSKForwardSecrecyUnsupported) {
|
||||
t.Fatalf("UsePSKOverExternalTransportClient error = %v, want %v", err, errModernPSKForwardSecrecyUnsupported)
|
||||
}
|
||||
if err := UsePSKOverExternalTransportServer(NewServer(), []byte("secret"), opts); !errors.Is(err, errModernPSKForwardSecrecyUnsupported) {
|
||||
t.Fatalf("UsePSKOverExternalTransportServer error = %v, want %v", err, errModernPSKForwardSecrecyUnsupported)
|
||||
}
|
||||
}
|
||||
|
||||
func TestModernPSKCodecRejectsLegacyPayload(t *testing.T) {
|
||||
key, aad, err := deriveModernPSKKey([]byte("notify-legacy-reject"), testModernPSKOptions())
|
||||
if err != nil {
|
||||
@@ -315,6 +328,166 @@ func TestModernPSKFastBulkEncodeRoundTrip(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestExternalTransportFastStreamEncodeRoundTrip(t *testing.T) {
|
||||
transport := buildExternalTransportBundle()
|
||||
wire, err := transport.fastStreamEncode(nil, 23, 7, []byte("payload"))
|
||||
if err != nil {
|
||||
t.Fatalf("fastStreamEncode failed: %v", err)
|
||||
}
|
||||
plain := transport.msgDe(nil, wire)
|
||||
frame, matched, err := decodeStreamFastDataFrame(plain)
|
||||
if err != nil {
|
||||
t.Fatalf("decodeStreamFastDataFrame failed: %v", err)
|
||||
}
|
||||
if !matched {
|
||||
t.Fatal("decodeStreamFastDataFrame should match fast payload")
|
||||
}
|
||||
if frame.DataID != 23 || frame.Seq != 7 || !bytes.Equal(frame.Payload, []byte("payload")) {
|
||||
t.Fatalf("frame mismatch: %+v", frame)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExternalTransportFastBulkEncodeRoundTrip(t *testing.T) {
|
||||
transport := buildExternalTransportBundle()
|
||||
wire, err := transport.fastBulkEncode(nil, 41, 9, []byte("payload"))
|
||||
if err != nil {
|
||||
t.Fatalf("fastBulkEncode failed: %v", err)
|
||||
}
|
||||
plain := transport.msgDe(nil, wire)
|
||||
frame, matched, err := decodeBulkFastDataFrame(plain)
|
||||
if err != nil {
|
||||
t.Fatalf("decodeBulkFastDataFrame failed: %v", err)
|
||||
}
|
||||
if !matched {
|
||||
t.Fatal("decodeBulkFastDataFrame should match fast payload")
|
||||
}
|
||||
if frame.DataID != 41 || frame.Seq != 9 || !bytes.Equal(frame.Payload, []byte("payload")) {
|
||||
t.Fatalf("frame mismatch: %+v", frame)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecryptTransportPayloadCodecPooledExternalDefersRelease(t *testing.T) {
|
||||
payload := []byte("payload")
|
||||
released := false
|
||||
plain, release, err := decryptTransportPayloadCodecPooled(ProtectionExternal, nil, passthroughTransportCodec, nil, payload, func() {
|
||||
released = true
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("decryptTransportPayloadCodecPooled failed: %v", err)
|
||||
}
|
||||
if released {
|
||||
t.Fatal("release should not run before caller is done")
|
||||
}
|
||||
if !bytes.Equal(plain, payload) {
|
||||
t.Fatalf("plain mismatch: got %q want %q", plain, payload)
|
||||
}
|
||||
if release == nil {
|
||||
t.Fatal("release callback should be preserved for external mode")
|
||||
}
|
||||
release()
|
||||
if !released {
|
||||
t.Fatal("release callback should run when caller finishes")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUsePSKOverExternalTransportConnectByConnSwitchesToExternal(t *testing.T) {
|
||||
client := NewClient().(*ClientCommon)
|
||||
server := newRunningPeerAttachServerForTest(t, func(server *ServerCommon) {
|
||||
if err := UsePSKOverExternalTransportServer(server, []byte("correct horse battery staple"), testModernPSKOptions()); err != nil {
|
||||
t.Fatalf("UsePSKOverExternalTransportServer failed: %v", err)
|
||||
}
|
||||
server.SetLink("external-roundtrip", func(msg *Message) {
|
||||
_ = msg.Reply([]byte("ack:" + string(msg.Value)))
|
||||
})
|
||||
})
|
||||
if err := UsePSKOverExternalTransportClient(client, []byte("correct horse battery staple"), testModernPSKOptions()); err != nil {
|
||||
t.Fatalf("UsePSKOverExternalTransportClient failed: %v", err)
|
||||
}
|
||||
if got := client.clientTransportProtectionSnapshot().mode; got != ProtectionManaged {
|
||||
t.Fatalf("client bootstrap mode = %v, want %v", got, ProtectionManaged)
|
||||
}
|
||||
|
||||
left, right := net.Pipe()
|
||||
defer right.Close()
|
||||
bootstrapPeerAttachConnForTest(t, server, right)
|
||||
if err := client.ConnectByConn(left); err != nil {
|
||||
t.Fatalf("ConnectByConn failed: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
client.setByeFromServer(true)
|
||||
_ = client.Stop()
|
||||
}()
|
||||
|
||||
if got := client.clientTransportProtectionSnapshot().mode; got != ProtectionExternal {
|
||||
t.Fatalf("client steady mode = %v, want %v", got, ProtectionExternal)
|
||||
}
|
||||
|
||||
reply, err := client.SendWait("external-roundtrip", []byte("ping"), time.Second)
|
||||
if err != nil {
|
||||
t.Fatalf("SendWait failed: %v", err)
|
||||
}
|
||||
if got, want := string(reply.Value), "ack:ping"; got != want {
|
||||
t.Fatalf("reply mismatch: got %q want %q", got, want)
|
||||
}
|
||||
|
||||
list := server.GetLogicalConnList()
|
||||
if len(list) != 1 {
|
||||
t.Fatalf("logical conn count = %d, want 1", len(list))
|
||||
}
|
||||
if got := list[0].protectionModeSnapshot(); got != ProtectionExternal {
|
||||
t.Fatalf("server steady mode = %v, want %v", got, ProtectionExternal)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUseNestedSecurityConnectByConnKeepsNestedMode(t *testing.T) {
|
||||
client := NewClient().(*ClientCommon)
|
||||
server := newRunningPeerAttachServerForTest(t, func(server *ServerCommon) {
|
||||
if err := UseNestedSecurityServer(server, []byte("correct horse battery staple"), testModernPSKOptions()); err != nil {
|
||||
t.Fatalf("UseNestedSecurityServer failed: %v", err)
|
||||
}
|
||||
server.SetLink("nested-roundtrip", func(msg *Message) {
|
||||
_ = msg.Reply([]byte("ack:" + string(msg.Value)))
|
||||
})
|
||||
})
|
||||
if err := UseNestedSecurityClient(client, []byte("correct horse battery staple"), testModernPSKOptions()); err != nil {
|
||||
t.Fatalf("UseNestedSecurityClient failed: %v", err)
|
||||
}
|
||||
if got := client.clientTransportProtectionSnapshot().mode; got != ProtectionNested {
|
||||
t.Fatalf("client bootstrap mode = %v, want %v", got, ProtectionNested)
|
||||
}
|
||||
|
||||
left, right := net.Pipe()
|
||||
defer right.Close()
|
||||
bootstrapPeerAttachConnForTest(t, server, right)
|
||||
if err := client.ConnectByConn(left); err != nil {
|
||||
t.Fatalf("ConnectByConn failed: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
client.setByeFromServer(true)
|
||||
_ = client.Stop()
|
||||
}()
|
||||
|
||||
if got := client.clientTransportProtectionSnapshot().mode; got != ProtectionNested {
|
||||
t.Fatalf("client steady mode = %v, want %v", got, ProtectionNested)
|
||||
}
|
||||
|
||||
reply, err := client.SendWait("nested-roundtrip", []byte("ping"), time.Second)
|
||||
if err != nil {
|
||||
t.Fatalf("SendWait failed: %v", err)
|
||||
}
|
||||
if got, want := string(reply.Value), "ack:ping"; got != want {
|
||||
t.Fatalf("reply mismatch: got %q want %q", got, want)
|
||||
}
|
||||
|
||||
list := server.GetLogicalConnList()
|
||||
if len(list) != 1 {
|
||||
t.Fatalf("logical conn count = %d, want 1", len(list))
|
||||
}
|
||||
if got := list[0].protectionModeSnapshot(); got != ProtectionNested {
|
||||
t.Fatalf("server steady mode = %v, want %v", got, ProtectionNested)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUseLegacySecurityRoundTrip(t *testing.T) {
|
||||
client := NewClient()
|
||||
server := NewServer()
|
||||
|
||||
Reference in New Issue
Block a user