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:
Christian Schwarz
2018-02-17 01:08:15 +01:00
parent fc1c46ffd7
commit ccd062e238
6 changed files with 54 additions and 249 deletions
+11 -63
View File
@@ -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()
}