feat: 增强 starssh 的 agent forwarding 与 tcp/unix 转发能力
- 为 LoginInput 增加 ForwardSSHAgent 配置,并在 Exec/PTTY 会话创建时按需自动请求 agent forwarding - 新增 agent_forward 运行时,封装本地 ssh-agent 建连、转发注册、显式请求与 unavailable/denied 语义 - 自动 agent forwarding 改为 best-effort:本地 agent 不可用、转发被拒绝或初始化失败时不再打断会话创建 - 为 StarSSH 增加 closing 状态与 agent forwarder 生命周期回收,避免 Close 与会话创建并发时泄漏资源 - 扩展 ForwardRequest 为带网络归一化的转发模型,支持 tcp/tcp4/tcp6/unix 端点组合 - 新增本地/远端 tcp<->unix、unix<->unix 及 detached helper,补齐 streamlocal 场景下的常用 API - 将显式网络地址编码收口为 tcp4://、tcp6://、unix://,消除 tcp:22 一类值的解析歧义 - 为本地 unix listener 增加 stale socket 探测、复用与关闭清理,避免遗留 socket 导致重启失败 - 补充 agent forwarding、关闭竞态、remote unix forward、local unix forward、stale socket 复用与端点解析等回归测试
This commit is contained in:
+534
@@ -2,8 +2,13 @@ package starssh
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -11,6 +16,59 @@ import (
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
type stubListener struct {
|
||||
addr net.Addr
|
||||
acceptCh chan net.Conn
|
||||
closeCh chan struct{}
|
||||
closeOnce sync.Once
|
||||
}
|
||||
|
||||
type dialRecord struct {
|
||||
network string
|
||||
addr string
|
||||
}
|
||||
|
||||
func newStubListener(addr net.Addr) *stubListener {
|
||||
return &stubListener{
|
||||
addr: addr,
|
||||
acceptCh: make(chan net.Conn, 1),
|
||||
closeCh: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
func (l *stubListener) Accept() (net.Conn, error) {
|
||||
select {
|
||||
case conn, ok := <-l.acceptCh:
|
||||
if !ok {
|
||||
return nil, io.EOF
|
||||
}
|
||||
return conn, nil
|
||||
case <-l.closeCh:
|
||||
return nil, net.ErrClosed
|
||||
}
|
||||
}
|
||||
|
||||
func (l *stubListener) Close() error {
|
||||
l.closeOnce.Do(func() {
|
||||
close(l.closeCh)
|
||||
close(l.acceptCh)
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *stubListener) Addr() net.Addr {
|
||||
return l.addr
|
||||
}
|
||||
|
||||
func (l *stubListener) Push(conn net.Conn) error {
|
||||
select {
|
||||
case <-l.closeCh:
|
||||
return net.ErrClosed
|
||||
case l.acceptCh <- conn:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func TestStartLocalForwardUsesExistingConnectionByDefault(t *testing.T) {
|
||||
oldDialSSHClient := dialSSHClient
|
||||
oldNewDetachedForwardClient := newDetachedForwardClient
|
||||
@@ -63,6 +121,64 @@ func TestStartLocalForwardUsesExistingConnectionByDefault(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestForwardRequestLegacyPositionalLiteralDefaultsToTCP(t *testing.T) {
|
||||
dialer := func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
req, err := normalizeForwardRequest(ForwardRequest{
|
||||
"127.0.0.1:10022",
|
||||
"example.internal:22",
|
||||
dialer,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("normalizeForwardRequest: %v", err)
|
||||
}
|
||||
if req.ListenNetwork != "tcp" {
|
||||
t.Fatalf("ListenNetwork=%q want tcp", req.ListenNetwork)
|
||||
}
|
||||
if req.TargetNetwork != "tcp" {
|
||||
t.Fatalf("TargetNetwork=%q want tcp", req.TargetNetwork)
|
||||
}
|
||||
if req.ListenAddr != "127.0.0.1:10022" || req.TargetAddr != "example.internal:22" {
|
||||
t.Fatalf("unexpected normalized request: %+v", req)
|
||||
}
|
||||
if req.DialContext == nil {
|
||||
t.Fatal("expected DialContext to be preserved")
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseForwardEndpointTreatsTCPPrefixLikePlainAddress(t *testing.T) {
|
||||
network, address, err := parseForwardEndpoint("tcp:22")
|
||||
if err != nil {
|
||||
t.Fatalf("parseForwardEndpoint: %v", err)
|
||||
}
|
||||
if network != "tcp" {
|
||||
t.Fatalf("network=%q want tcp", network)
|
||||
}
|
||||
if address != "tcp:22" {
|
||||
t.Fatalf("address=%q want tcp:22", address)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseForwardEndpointSupportsExplicitSchemes(t *testing.T) {
|
||||
network, address, err := parseForwardEndpoint("unix:///tmp/test-forward.sock")
|
||||
if err != nil {
|
||||
t.Fatalf("parseForwardEndpoint unix: %v", err)
|
||||
}
|
||||
if network != "unix" || address != "/tmp/test-forward.sock" {
|
||||
t.Fatalf("unexpected unix endpoint parse: network=%q address=%q", network, address)
|
||||
}
|
||||
|
||||
network, address, err = parseForwardEndpoint("tcp6://[::1]:2222")
|
||||
if err != nil {
|
||||
t.Fatalf("parseForwardEndpoint tcp6: %v", err)
|
||||
}
|
||||
if network != "tcp6" || address != "[::1]:2222" {
|
||||
t.Fatalf("unexpected tcp6 endpoint parse: network=%q address=%q", network, address)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStartLocalForwardDetachedUsesSeparateConnection(t *testing.T) {
|
||||
oldDialSSHClient := dialSSHClient
|
||||
oldNewDetachedForwardClient := newDetachedForwardClient
|
||||
@@ -132,6 +248,424 @@ func TestStartLocalForwardDetachedUsesSeparateConnection(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestStartRemoteForwardSupportsUnixListenAndTCPTarget(t *testing.T) {
|
||||
oldListenSSHClient := listenSSHClient
|
||||
t.Cleanup(func() {
|
||||
listenSSHClient = oldListenSSHClient
|
||||
})
|
||||
|
||||
baseClient := &ssh.Client{}
|
||||
star := &StarSSH{}
|
||||
star.setTransport(baseClient, nil)
|
||||
|
||||
listener := newStubListener(&net.UnixAddr{
|
||||
Name: "/run/user/0/gnupg/S.gpg-agent",
|
||||
Net: "unix",
|
||||
})
|
||||
|
||||
var listenedNetwork string
|
||||
var listenedAddr string
|
||||
listenSSHClient = func(client *ssh.Client, network, address string) (net.Listener, error) {
|
||||
if client != baseClient {
|
||||
t.Fatalf("unexpected ssh client %p", client)
|
||||
}
|
||||
listenedNetwork = network
|
||||
listenedAddr = address
|
||||
return listener, nil
|
||||
}
|
||||
|
||||
var targetNetwork string
|
||||
var targetAddr string
|
||||
forwarder, err := star.StartRemoteForward(ForwardRequest{
|
||||
ListenAddr: forwardEndpoint("unix", "/run/user/0/gnupg/S.gpg-agent"),
|
||||
TargetAddr: "127.0.0.1:4321",
|
||||
DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
targetNetwork = network
|
||||
targetAddr = address
|
||||
serverConn, clientConn := net.Pipe()
|
||||
go echoForwardPipe(serverConn)
|
||||
return clientConn, nil
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("start remote unix forward: %v", err)
|
||||
}
|
||||
defer forwarder.Close()
|
||||
|
||||
srcPeer, forwardedConn := net.Pipe()
|
||||
defer srcPeer.Close()
|
||||
if err := listener.Push(forwardedConn); err != nil {
|
||||
t.Fatalf("push forwarded connection: %v", err)
|
||||
}
|
||||
|
||||
payload := []byte("unix-forward")
|
||||
done := make(chan []byte, 1)
|
||||
go func() {
|
||||
reply := make([]byte, len(payload))
|
||||
_, _ = io.ReadFull(srcPeer, reply)
|
||||
done <- reply
|
||||
}()
|
||||
|
||||
if _, err := srcPeer.Write(payload); err != nil {
|
||||
t.Fatalf("write source payload: %v", err)
|
||||
}
|
||||
|
||||
select {
|
||||
case reply := <-done:
|
||||
if string(reply) != string(payload) {
|
||||
t.Fatalf("unexpected remote unix forward reply: %q", string(reply))
|
||||
}
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("remote unix forward did not relay payload")
|
||||
}
|
||||
|
||||
if listenedNetwork != "unix" || listenedAddr != "/run/user/0/gnupg/S.gpg-agent" {
|
||||
t.Fatalf("unexpected remote listen request: network=%q addr=%q", listenedNetwork, listenedAddr)
|
||||
}
|
||||
if targetNetwork != "tcp" || targetAddr != "127.0.0.1:4321" {
|
||||
t.Fatalf("unexpected local dial target: network=%q addr=%q", targetNetwork, targetAddr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStartLocalUnixForwardUsesUnixListenerAndTCPTarget(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("unix socket smoke test is exercised in WSL/Linux CI path")
|
||||
}
|
||||
|
||||
oldDialSSHClient := dialSSHClient
|
||||
t.Cleanup(func() {
|
||||
dialSSHClient = oldDialSSHClient
|
||||
})
|
||||
|
||||
baseClient := &ssh.Client{}
|
||||
star := &StarSSH{}
|
||||
star.setTransport(baseClient, nil)
|
||||
|
||||
var targetNetwork string
|
||||
var targetAddr string
|
||||
dialSSHClient = func(ctx context.Context, client *ssh.Client, network, address string) (net.Conn, error) {
|
||||
if client != baseClient {
|
||||
t.Fatalf("unexpected ssh client %p", client)
|
||||
}
|
||||
targetNetwork = network
|
||||
targetAddr = address
|
||||
serverConn, clientConn := net.Pipe()
|
||||
go echoForwardPipe(serverConn)
|
||||
return clientConn, nil
|
||||
}
|
||||
|
||||
socketPath := filepath.Join(t.TempDir(), "forward.sock")
|
||||
forwarder, err := star.StartLocalUnixForward(socketPath, "127.0.0.1:4321")
|
||||
if err != nil {
|
||||
t.Fatalf("start local unix forward: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
closeErr := forwarder.Close()
|
||||
if closeErr != nil && !errors.Is(closeErr, net.ErrClosed) {
|
||||
t.Fatalf("close local unix forward: %v", closeErr)
|
||||
}
|
||||
}()
|
||||
|
||||
conn, err := net.DialTimeout("unix", socketPath, time.Second)
|
||||
if err != nil {
|
||||
t.Fatalf("dial unix forward listener: %v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
_ = conn.SetDeadline(time.Now().Add(2 * time.Second))
|
||||
|
||||
payload := []byte("unix-local-forward")
|
||||
if _, err := conn.Write(payload); err != nil {
|
||||
t.Fatalf("write unix forward payload: %v", err)
|
||||
}
|
||||
reply := make([]byte, len(payload))
|
||||
if _, err := io.ReadFull(conn, reply); err != nil {
|
||||
t.Fatalf("read unix forward reply: %v", err)
|
||||
}
|
||||
if string(reply) != string(payload) {
|
||||
t.Fatalf("unexpected unix forward reply: %q", string(reply))
|
||||
}
|
||||
if targetNetwork != "tcp" || targetAddr != "127.0.0.1:4321" {
|
||||
t.Fatalf("unexpected remote dial target: network=%q addr=%q", targetNetwork, targetAddr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStartLocalUnixForwardRemovesSocketOnClose(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("unix socket smoke test is exercised in WSL/Linux CI path")
|
||||
}
|
||||
|
||||
oldDialSSHClient := dialSSHClient
|
||||
t.Cleanup(func() {
|
||||
dialSSHClient = oldDialSSHClient
|
||||
})
|
||||
|
||||
baseClient := &ssh.Client{}
|
||||
star := &StarSSH{}
|
||||
star.setTransport(baseClient, nil)
|
||||
|
||||
dialSSHClient = func(ctx context.Context, client *ssh.Client, network, address string) (net.Conn, error) {
|
||||
serverConn, clientConn := net.Pipe()
|
||||
go echoForwardPipe(serverConn)
|
||||
return clientConn, nil
|
||||
}
|
||||
|
||||
socketPath := filepath.Join(t.TempDir(), "cleanup.sock")
|
||||
forwarder, err := star.StartLocalUnixForward(socketPath, "127.0.0.1:4321")
|
||||
if err != nil {
|
||||
t.Fatalf("start local unix forward: %v", err)
|
||||
}
|
||||
|
||||
if _, err := os.Lstat(socketPath); err != nil {
|
||||
t.Fatalf("socket should exist while forward is running: %v", err)
|
||||
}
|
||||
if err := forwarder.Close(); err != nil && !errors.Is(err, net.ErrClosed) {
|
||||
t.Fatalf("close local unix forward: %v", err)
|
||||
}
|
||||
if _, err := os.Lstat(socketPath); !errors.Is(err, os.ErrNotExist) {
|
||||
t.Fatalf("socket path should be removed on close, got err=%v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStartLocalUnixForwardReusesStaleSocketPath(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("unix socket smoke test is exercised in WSL/Linux CI path")
|
||||
}
|
||||
|
||||
oldDialSSHClient := dialSSHClient
|
||||
t.Cleanup(func() {
|
||||
dialSSHClient = oldDialSSHClient
|
||||
})
|
||||
|
||||
baseClient := &ssh.Client{}
|
||||
star := &StarSSH{}
|
||||
star.setTransport(baseClient, nil)
|
||||
|
||||
dialSSHClient = func(ctx context.Context, client *ssh.Client, network, address string) (net.Conn, error) {
|
||||
serverConn, clientConn := net.Pipe()
|
||||
go echoForwardPipe(serverConn)
|
||||
return clientConn, nil
|
||||
}
|
||||
|
||||
socketPath := filepath.Join(t.TempDir(), "stale.sock")
|
||||
staleListener, err := net.ListenUnix("unix", &net.UnixAddr{
|
||||
Name: socketPath,
|
||||
Net: "unix",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("create stale unix socket: %v", err)
|
||||
}
|
||||
staleListener.SetUnlinkOnClose(false)
|
||||
if err := staleListener.Close(); err != nil {
|
||||
t.Fatalf("close stale unix socket listener: %v", err)
|
||||
}
|
||||
if _, err := os.Lstat(socketPath); err != nil {
|
||||
t.Fatalf("expected stale unix socket path to remain after close: %v", err)
|
||||
}
|
||||
|
||||
forwarder, err := star.StartLocalUnixForward(socketPath, "127.0.0.1:4321")
|
||||
if err != nil {
|
||||
t.Fatalf("start local unix forward on stale socket path: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
closeErr := forwarder.Close()
|
||||
if closeErr != nil && !errors.Is(closeErr, net.ErrClosed) {
|
||||
t.Fatalf("close local unix forward: %v", closeErr)
|
||||
}
|
||||
}()
|
||||
|
||||
reply := make([]byte, len("stale-reuse"))
|
||||
conn, err := net.DialTimeout("unix", socketPath, time.Second)
|
||||
if err != nil {
|
||||
t.Fatalf("dial reused unix forward listener: %v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
_ = conn.SetDeadline(time.Now().Add(2 * time.Second))
|
||||
if _, err := conn.Write([]byte("stale-reuse")); err != nil {
|
||||
t.Fatalf("write reused unix forward payload: %v", err)
|
||||
}
|
||||
if _, err := io.ReadFull(conn, reply); err != nil {
|
||||
t.Fatalf("read reused unix forward reply: %v", err)
|
||||
}
|
||||
if string(reply) != "stale-reuse" {
|
||||
t.Fatalf("unexpected reply on reused unix forward: %q", string(reply))
|
||||
}
|
||||
}
|
||||
|
||||
func TestStartLocalUnixToUnixForwardUsesUnixTarget(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("unix socket smoke test is exercised in WSL/Linux CI path")
|
||||
}
|
||||
|
||||
oldDialSSHClient := dialSSHClient
|
||||
t.Cleanup(func() {
|
||||
dialSSHClient = oldDialSSHClient
|
||||
})
|
||||
|
||||
baseClient := &ssh.Client{}
|
||||
star := &StarSSH{}
|
||||
star.setTransport(baseClient, nil)
|
||||
|
||||
targetSocketPath := filepath.Join(t.TempDir(), "target.sock")
|
||||
targetListener, err := net.Listen("unix", targetSocketPath)
|
||||
if err != nil {
|
||||
t.Fatalf("listen target unix socket: %v", err)
|
||||
}
|
||||
defer targetListener.Close()
|
||||
|
||||
done := make(chan []byte, 1)
|
||||
go func() {
|
||||
conn, acceptErr := targetListener.Accept()
|
||||
if acceptErr != nil {
|
||||
done <- nil
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
buf := make([]byte, 64)
|
||||
n, _ := conn.Read(buf)
|
||||
_, _ = conn.Write(buf[:n])
|
||||
done <- buf[:n]
|
||||
}()
|
||||
|
||||
dialRecordCh := make(chan dialRecord, 1)
|
||||
dialSSHClient = func(ctx context.Context, client *ssh.Client, network, address string) (net.Conn, error) {
|
||||
if client != baseClient {
|
||||
t.Fatalf("unexpected ssh client %p", client)
|
||||
}
|
||||
dialRecordCh <- dialRecord{network: network, addr: address}
|
||||
var dialer net.Dialer
|
||||
return dialer.DialContext(ctx, network, address)
|
||||
}
|
||||
|
||||
listenSocketPath := filepath.Join(t.TempDir(), "listen.sock")
|
||||
forwarder, err := star.StartLocalUnixToUnixForward(listenSocketPath, targetSocketPath)
|
||||
if err != nil {
|
||||
t.Fatalf("start local unix-to-unix forward: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
closeErr := forwarder.Close()
|
||||
if closeErr != nil && !errors.Is(closeErr, net.ErrClosed) {
|
||||
t.Fatalf("close local unix-to-unix forward: %v", closeErr)
|
||||
}
|
||||
}()
|
||||
|
||||
conn, err := net.DialTimeout("unix", listenSocketPath, time.Second)
|
||||
if err != nil {
|
||||
t.Fatalf("dial unix-to-unix listener: %v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
_ = conn.SetDeadline(time.Now().Add(2 * time.Second))
|
||||
|
||||
payload := []byte("unix-to-unix")
|
||||
if _, err := conn.Write(payload); err != nil {
|
||||
t.Fatalf("write unix-to-unix payload: %v", err)
|
||||
}
|
||||
reply := make([]byte, len(payload))
|
||||
if _, err := io.ReadFull(conn, reply); err != nil {
|
||||
t.Fatalf("read unix-to-unix reply: %v", err)
|
||||
}
|
||||
if string(reply) != string(payload) {
|
||||
t.Fatalf("unexpected unix-to-unix reply: %q", string(reply))
|
||||
}
|
||||
|
||||
select {
|
||||
case got := <-done:
|
||||
if string(got) != string(payload) {
|
||||
t.Fatalf("unexpected payload seen by target unix socket: %q", string(got))
|
||||
}
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("target unix socket did not receive forwarded payload")
|
||||
}
|
||||
|
||||
select {
|
||||
case got := <-dialRecordCh:
|
||||
if got.network != "unix" || got.addr != targetSocketPath {
|
||||
t.Fatalf("unexpected unix target dial: network=%q addr=%q", got.network, got.addr)
|
||||
}
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("did not observe unix target dial")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStartLocalTCPToUnixForwardUsesUnixTarget(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("unix socket smoke test is exercised in WSL/Linux CI path")
|
||||
}
|
||||
|
||||
oldDialSSHClient := dialSSHClient
|
||||
t.Cleanup(func() {
|
||||
dialSSHClient = oldDialSSHClient
|
||||
})
|
||||
|
||||
baseClient := &ssh.Client{}
|
||||
star := &StarSSH{}
|
||||
star.setTransport(baseClient, nil)
|
||||
|
||||
targetSocketPath := filepath.Join(t.TempDir(), "target-tcp-to-unix.sock")
|
||||
targetListener, err := net.Listen("unix", targetSocketPath)
|
||||
if err != nil {
|
||||
t.Fatalf("listen target unix socket: %v", err)
|
||||
}
|
||||
defer targetListener.Close()
|
||||
|
||||
done := make(chan []byte, 1)
|
||||
go func() {
|
||||
conn, acceptErr := targetListener.Accept()
|
||||
if acceptErr != nil {
|
||||
done <- nil
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
buf := make([]byte, 64)
|
||||
n, _ := conn.Read(buf)
|
||||
_, _ = conn.Write(buf[:n])
|
||||
done <- buf[:n]
|
||||
}()
|
||||
|
||||
dialRecordCh := make(chan dialRecord, 1)
|
||||
dialSSHClient = func(ctx context.Context, client *ssh.Client, network, address string) (net.Conn, error) {
|
||||
if client != baseClient {
|
||||
t.Fatalf("unexpected ssh client %p", client)
|
||||
}
|
||||
dialRecordCh <- dialRecord{network: network, addr: address}
|
||||
var dialer net.Dialer
|
||||
return dialer.DialContext(ctx, network, address)
|
||||
}
|
||||
|
||||
forwarder, err := star.StartLocalTCPToUnixForward("127.0.0.1:0", targetSocketPath)
|
||||
if err != nil {
|
||||
t.Fatalf("start local tcp-to-unix forward: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
closeErr := forwarder.Close()
|
||||
if closeErr != nil && !errors.Is(closeErr, net.ErrClosed) {
|
||||
t.Fatalf("close local tcp-to-unix forward: %v", closeErr)
|
||||
}
|
||||
}()
|
||||
|
||||
reply := exerciseForwarder(t, forwarder.Addr().String(), []byte("tcp-to-unix"))
|
||||
if string(reply) != "tcp-to-unix" {
|
||||
t.Fatalf("unexpected tcp-to-unix reply: %q", string(reply))
|
||||
}
|
||||
|
||||
select {
|
||||
case got := <-done:
|
||||
if string(got) != "tcp-to-unix" {
|
||||
t.Fatalf("unexpected payload seen by unix target: %q", string(got))
|
||||
}
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("unix target did not receive forwarded tcp payload")
|
||||
}
|
||||
|
||||
select {
|
||||
case got := <-dialRecordCh:
|
||||
if got.network != "unix" || got.addr != targetSocketPath {
|
||||
t.Fatalf("unexpected unix target dial: network=%q addr=%q", got.network, got.addr)
|
||||
}
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("did not observe unix target dial")
|
||||
}
|
||||
}
|
||||
|
||||
func echoForwardPipe(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
buf := make([]byte, 4096)
|
||||
|
||||
Reference in New Issue
Block a user