sing-box/protocol/tailscale/tailssh/session_platform.go

78 lines
1.7 KiB
Go

//go:build with_gvisor && !windows
package tailssh
import (
"os"
"syscall"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing/common"
)
type platformShellBackend struct {
platform adapter.PlatformInterface
}
func (b *platformShellBackend) OpenSession(request shellRequest) (shellSession, error) {
session, err := b.platform.OpenShellSession(request.User, request.Command, request.Env, request.Term, int32(request.Rows), int32(request.Cols))
if err != nil {
return nil, err
}
dupFd, err := syscall.Dup(int(session.MasterFD()))
if err != nil {
session.Close()
return nil, err
}
master := os.NewFile(uintptr(dupFd), "pty-master")
return &platformShellSession{
session: session,
master: master,
isPty: request.Term != "",
}, nil
}
func (b *platformShellBackend) Close() error {
return nil
}
type platformShellSession struct {
session adapter.ShellSession
master *os.File
isPty bool
}
func (s *platformShellSession) Read(p []byte) (int, error) {
return s.master.Read(p)
}
func (s *platformShellSession) Write(p []byte) (int, error) {
return s.master.Write(p)
}
func (s *platformShellSession) Close() error {
return common.Close(s.master, s.session)
}
func (s *platformShellSession) CloseWrite() error {
if s.isPty {
return nil
}
return syscall.Shutdown(int(s.master.Fd()), syscall.SHUT_WR)
}
func (s *platformShellSession) Resize(rows, cols uint16) error {
return s.session.Resize(int32(rows), int32(cols))
}
func (s *platformShellSession) Signal(sig int) error {
return s.session.Signal(int32(sig))
}
func (s *platformShellSession) Wait() (uint32, error) {
exitStatus, err := s.session.WaitExit()
if err != nil {
return 0, err
}
return uint32(exitStatus), nil
}