refactor: 重构 starssh 核心运行时并补强 ssh/exec/terminal/sftp 能力
- 拆分原有单体 ssh.go,按职责重组为 types、utils、transport、login、keepalive、session、exec、pool、shell、terminal、forward、hostkey、state 等模块,并补充平台相关实现 - 重做登录与连接运行时,补齐基于 context 的建连、jump/proxy 链路、可配置认证顺序,以及 Unix/Windows 下的 ssh-agent 支持 - 新增正式非交互执行模型 ExecRequest/ExecResult,支持流式输出、溢出统计、超时控制,以及 posix/powershell/cmd/raw 多方言执行 - 保留旧 shell 风格兼容接口,同时让路径/用户探测等 helper 具备跨 shell fallback,避免 Windows 目标继续硬依赖 POSIX 命令 - 新增 TerminalSession 作为原始交互终端基座,提供 IO attach、resize、signal/control、退出状态与关闭原因管理 - 重构端口转发语义,默认复用当前 SSH 连接,并显式提供 detached 的本地/动态转发模式承载隔离场景 - 梳理 keepalive 与取消语义,区分仅取消本次操作和关闭整条连接,并统一连接状态与传输关闭路径 - 围绕新的 session/连接生命周期重做执行池与运行时支撑 - 大幅增强 SFTP 传输链路,补齐更安全的原子替换、校验、进度回调、重试隔离、可复用 client 生命周期与失败语义 - 新增取消语义、keepalive、SFTP、forward、terminal input 等关键回归测试,提升核心链路稳定性
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
package starssh
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/sftp"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultSSHPort = 22
|
||||
defaultLoginTimeout = 5 * time.Second
|
||||
defaultKeepAliveTimeout = 3 * time.Second
|
||||
defaultShellPollInterval = 120 * time.Millisecond
|
||||
defaultShellSetupDelay = 200 * time.Millisecond
|
||||
defaultShellSetupTimeout = 3 * time.Second
|
||||
defaultShellWaitTimeout = 30 * time.Second
|
||||
defaultShellPromptToken = "__STARSSH_PROMPT__>"
|
||||
defaultPTYTerm = "xterm"
|
||||
defaultPTYRows = 500
|
||||
defaultPTYColumns = 250
|
||||
|
||||
defaultTransferBufferSize = 1024 * 1024
|
||||
|
||||
defaultExecStreamMaxPendingChunks = 256
|
||||
defaultExecStreamMaxPendingBytes = 4 * 1024 * 1024
|
||||
)
|
||||
|
||||
type DialContextFunc func(ctx context.Context, network, address string) (net.Conn, error)
|
||||
|
||||
type ProxyType string
|
||||
|
||||
const (
|
||||
ProxyTypeSOCKS5 ProxyType = "socks5"
|
||||
ProxyTypeHTTPConnect ProxyType = "http_connect"
|
||||
)
|
||||
|
||||
type ProxyConfig struct {
|
||||
Type ProxyType
|
||||
Addr string
|
||||
Username string
|
||||
Password string
|
||||
Timeout time.Duration
|
||||
}
|
||||
|
||||
type AuthMethodKind string
|
||||
|
||||
const (
|
||||
AuthMethodPrivateKey AuthMethodKind = "private_key"
|
||||
AuthMethodPassword AuthMethodKind = "password"
|
||||
AuthMethodKeyboardInteractive AuthMethodKind = "keyboard_interactive"
|
||||
AuthMethodSSHAgent AuthMethodKind = "ssh_agent"
|
||||
)
|
||||
|
||||
type StarSSH struct {
|
||||
stateMu sync.RWMutex
|
||||
Client *ssh.Client
|
||||
PublicKey ssh.PublicKey
|
||||
PubkeyBase64 string
|
||||
Hostname string
|
||||
RemoteAddr net.Addr
|
||||
Banner string
|
||||
LoginInfo LoginInput
|
||||
online bool
|
||||
upstream *StarSSH
|
||||
sftpClient *sftp.Client
|
||||
sftpMu sync.Mutex
|
||||
keepaliveMu sync.Mutex
|
||||
keepaliveStop chan struct{}
|
||||
keepaliveDone chan struct{}
|
||||
}
|
||||
|
||||
type LoginInput struct {
|
||||
KeyExchanges []string
|
||||
Ciphers []string
|
||||
MACs []string
|
||||
User string
|
||||
Password string
|
||||
PasswordCallback func() (string, error)
|
||||
KeyboardInteractiveCallback ssh.KeyboardInteractiveChallenge
|
||||
Prikey string
|
||||
PrikeyPwd string
|
||||
DisableSSHAgent bool
|
||||
AuthOrder []AuthMethodKind
|
||||
Addr string
|
||||
Port int
|
||||
Timeout time.Duration
|
||||
DialContext DialContextFunc
|
||||
Proxy *ProxyConfig
|
||||
Jump *LoginInput
|
||||
KeepAliveInterval time.Duration
|
||||
KeepAliveTimeout time.Duration
|
||||
HostKeyCallback func(string, net.Addr, ssh.PublicKey) error
|
||||
BannerCallback func(string) error
|
||||
}
|
||||
|
||||
// StarShell keeps the legacy prompt-driven helper for POSIX-style scripted shell interactions.
|
||||
// It is not a generic cross-shell abstraction; for product-grade interactive terminals, prefer TerminalSession.
|
||||
type StarShell struct {
|
||||
Keyword string
|
||||
UseWaitDefault bool
|
||||
WaitTimeout time.Duration
|
||||
Session *ssh.Session
|
||||
in io.Writer
|
||||
out *bufio.Reader
|
||||
er *bufio.Reader
|
||||
outbyte []byte
|
||||
errbyte []byte
|
||||
lastout int64
|
||||
errors error
|
||||
isprint bool
|
||||
isfuncs bool
|
||||
iscolor bool
|
||||
isecho bool
|
||||
rw sync.RWMutex
|
||||
funcs func(string)
|
||||
writeMu sync.Mutex
|
||||
commandMu sync.Mutex
|
||||
closeOnce sync.Once
|
||||
promptToken string
|
||||
}
|
||||
|
||||
type TerminalConfig struct {
|
||||
Term string
|
||||
Rows int
|
||||
Columns int
|
||||
Modes ssh.TerminalModes
|
||||
}
|
||||
|
||||
type TerminalControl byte
|
||||
|
||||
const (
|
||||
TerminalControlInterrupt TerminalControl = 0x03
|
||||
TerminalControlEOF TerminalControl = 0x04
|
||||
TerminalControlBell TerminalControl = 0x07
|
||||
TerminalControlBackspace TerminalControl = 0x08
|
||||
TerminalControlLineKill TerminalControl = 0x15
|
||||
TerminalControlQuit TerminalControl = 0x1c
|
||||
TerminalControlSuspend TerminalControl = 0x1a
|
||||
TerminalControlPauseOutput TerminalControl = 0x13
|
||||
TerminalControlResumeOutput TerminalControl = 0x11
|
||||
)
|
||||
|
||||
type TerminalCloseReason string
|
||||
|
||||
const (
|
||||
TerminalCloseReasonUnknown TerminalCloseReason = ""
|
||||
TerminalCloseReasonExit TerminalCloseReason = "exit"
|
||||
TerminalCloseReasonSignal TerminalCloseReason = "signal"
|
||||
TerminalCloseReasonClosed TerminalCloseReason = "closed"
|
||||
TerminalCloseReasonContextCanceled TerminalCloseReason = "context_canceled"
|
||||
TerminalCloseReasonDeadlineExceeded TerminalCloseReason = "deadline_exceeded"
|
||||
TerminalCloseReasonTransportError TerminalCloseReason = "transport_error"
|
||||
)
|
||||
|
||||
type TerminalExitInfo struct {
|
||||
ExitCode int
|
||||
ExitSignal string
|
||||
ExitMessage string
|
||||
Reason TerminalCloseReason
|
||||
}
|
||||
|
||||
type TerminalSession struct {
|
||||
Session *ssh.Session
|
||||
ID string
|
||||
Label string
|
||||
Metadata map[string]string
|
||||
stdin io.WriteCloser
|
||||
stdout io.Reader
|
||||
stderr io.Reader
|
||||
|
||||
attachMu sync.RWMutex
|
||||
in io.Reader
|
||||
out io.Writer
|
||||
errOut io.Writer
|
||||
|
||||
runOnce sync.Once
|
||||
runDone chan struct{}
|
||||
runErr error
|
||||
|
||||
waitOnce sync.Once
|
||||
waitDone chan struct{}
|
||||
|
||||
stateMu sync.RWMutex
|
||||
waitErr error
|
||||
exitInfo TerminalExitInfo
|
||||
closeReason TerminalCloseReason
|
||||
closeErr error
|
||||
|
||||
closeOnce sync.Once
|
||||
}
|
||||
Reference in New Issue
Block a user