-
Notifications
You must be signed in to change notification settings - Fork 50
/
proxycommand.go
93 lines (77 loc) · 1.86 KB
/
proxycommand.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package main
import (
"io"
"net"
"os/exec"
"strings"
"time"
shlex "github.com/flynn/go-shlex"
log "github.com/sirupsen/logrus"
)
// ProxyCmdConn is a Conn for talking to the underlying ProxyCommand.
type ProxyCmdConn struct {
io.ReadCloser
io.WriteCloser
}
// NewProxyCmdConn creates a new ProxyCmdConn
// and starts the underlying ProxyCommand.
func NewProxyCmdConn(s *sshClientConfig, cmd string) (*ProxyCmdConn, error) {
host, port, err := net.SplitHostPort(s.host)
if err != nil {
return nil, err
}
cmd = strings.Replace(cmd, "%h", host, -1)
cmd = strings.Replace(cmd, "%p", port, -1)
args, err := shlex.Split(cmd)
if err != nil {
return nil, err
}
c := exec.Command(args[0], args[1:]...)
stdin, err := c.StdinPipe()
if err != nil {
return nil, err
}
stdout, err := c.StdoutPipe()
if err != nil {
return nil, err
}
// FIXME: Report errors from StderrPipe
if err := c.Start(); err != nil {
return nil, err
}
log.Debugf("ProxyCommand started: '%s %s'.", args[0], strings.Join(args[1:], " "))
return &ProxyCmdConn{
ReadCloser: stdout,
WriteCloser: stdin,
}, nil
}
func (c *ProxyCmdConn) Close() error {
// Stdin pipe must be closed before stdout pipe
// so that the underlying command knows it's time to end.
// Otherwise, closing the stdout pipe first will be blocked forever.
if err := c.WriteCloser.Close(); err != nil {
return err
}
if err := c.ReadCloser.Close(); err != nil {
return err
}
return nil
}
func (c *ProxyCmdConn) LocalAddr() net.Addr {
return nil
}
func (c *ProxyCmdConn) RemoteAddr() net.Addr {
return nil
}
func (c *ProxyCmdConn) SetDeadline(t time.Time) error {
// FIXME: Implement timeout
return nil
}
func (c *ProxyCmdConn) SetReadDeadline(t time.Time) error {
// FIXME: Implement timeout
return nil
}
func (c *ProxyCmdConn) SetWriteDeadline(t time.Time) error {
// FIXME: Implement timeout
return nil
}