ssh+stdinserver: dump sshbytestream for github.com/problame/go-netssh
Cleaner abstractions + underlying go-rwccmd package does proper handling of asynchronous exits, etc.
This commit is contained in:
@@ -1,18 +1,16 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/ftrvxmtrx/fd"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/problame/go-netssh"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
type StdinserverListenerFactory struct {
|
||||
ClientIdentity string `mapstructure:"client_identity"`
|
||||
sockaddr *net.UnixAddr
|
||||
sockpath string
|
||||
}
|
||||
|
||||
func parseStdinserverListenerFactory(c JobParsingContext, i map[string]interface{}) (f *StdinserverListenerFactory, err error) {
|
||||
@@ -27,78 +25,28 @@ func parseStdinserverListenerFactory(c JobParsingContext, i map[string]interface
|
||||
return
|
||||
}
|
||||
|
||||
f.sockaddr, err = stdinserverListenerSocket(c.Global.Serve.Stdinserver.SockDir, f.ClientIdentity)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
f.sockpath = path.Join(c.Global.Serve.Stdinserver.SockDir, f.ClientIdentity)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func stdinserverListenerSocket(sockdir, clientIdentity string) (addr *net.UnixAddr, err error) {
|
||||
sockpath := path.Join(sockdir, clientIdentity)
|
||||
addr, err = net.ResolveUnixAddr("unix", sockpath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot resolve unix address")
|
||||
}
|
||||
return addr, nil
|
||||
}
|
||||
|
||||
func (f *StdinserverListenerFactory) Listen() (al AuthenticatedChannelListener, err error) {
|
||||
|
||||
ul, err := ListenUnixPrivate(f.sockaddr)
|
||||
l, err := netssh.Listen(f.sockpath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "cannot listen on unix socket %s", f.sockaddr)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
l := &StdinserverListener{ul}
|
||||
|
||||
return l, nil
|
||||
return StdinserverListener{l}, nil
|
||||
}
|
||||
|
||||
type StdinserverListener struct {
|
||||
l *net.UnixListener
|
||||
l *netssh.Listener
|
||||
}
|
||||
|
||||
type fdRWC struct {
|
||||
stdin, stdout *os.File
|
||||
control *net.UnixConn
|
||||
func (l StdinserverListener) Accept() (ch io.ReadWriteCloser, err error) {
|
||||
return l.l.Accept()
|
||||
}
|
||||
|
||||
func (f fdRWC) Read(p []byte) (n int, err error) {
|
||||
return f.stdin.Read(p)
|
||||
}
|
||||
|
||||
func (f fdRWC) Write(p []byte) (n int, err error) {
|
||||
return f.stdout.Write(p)
|
||||
}
|
||||
|
||||
func (f fdRWC) Close() (err error) {
|
||||
f.stdin.Close()
|
||||
f.stdout.Close()
|
||||
return f.control.Close()
|
||||
}
|
||||
|
||||
func (l *StdinserverListener) Accept() (ch io.ReadWriteCloser, err error) {
|
||||
c, err := l.l.Accept()
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "error accepting on unix listener")
|
||||
return
|
||||
}
|
||||
|
||||
// Read the stdin and stdout of the stdinserver command
|
||||
files, err := fd.Get(c.(*net.UnixConn), 2, []string{"stdin", "stdout"})
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "error receiving fds from stdinserver command")
|
||||
c.Close()
|
||||
}
|
||||
|
||||
rwc := fdRWC{files[0], files[1], c.(*net.UnixConn)}
|
||||
|
||||
return rwc, nil
|
||||
|
||||
}
|
||||
|
||||
func (l *StdinserverListener) Close() (err error) {
|
||||
return l.l.Close() // removes socket file automatically
|
||||
func (l StdinserverListener) Close() (err error) {
|
||||
return l.l.Close()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user