139
// unixConnection creates two halves of a connected net.UnixConn. It
140
// is used for connecting the Go SSH client with sshd without opening
142
func unixConnection() (*net.UnixConn, *net.UnixConn, error) {
143
dir, err := ioutil.TempDir("", "unixConnection")
149
addr := filepath.Join(dir, "ssh")
150
listener, err := net.Listen("unix", addr)
154
defer listener.Close()
155
c1, err := net.Dial("unix", addr)
160
c2, err := listener.Accept()
166
return c1.(*net.UnixConn), c2.(*net.UnixConn), nil
138
169
func (s *server) TryDial(config *ssh.ClientConfig) (*ssh.ClientConn, error) {
139
170
sshd, err := exec.LookPath("sshd")
141
172
s.t.Skipf("skipping test: %v", err)
175
c1, c2, err := unixConnection()
177
s.t.Fatalf("unixConnection: %v", err)
143
180
s.cmd = exec.Command(sshd, "-f", s.configfile, "-i", "-e")
144
r1, w1, err := os.Pipe()
149
r2, w2, err := os.Pipe()
183
s.t.Fatalf("UnixConn.File: %v", err)
154
187
s.cmd.Stderr = os.Stderr
155
188
if err := s.cmd.Start(); err != nil {
158
191
s.t.Fatalf("s.cmd.Start: %v", err)
161
return ssh.Client(&client{wc: w2, r: r1}, config)
194
return ssh.Client(c1, config)
164
197
func (s *server) Dial(config *ssh.ClientConfig) *ssh.ClientConn {
188
// client wraps a pair of Reader/WriteClosers to implement the
189
// net.Conn interface. Importantly, client also mocks the
190
// ability of net.Conn to support concurrent calls to Read/Write
191
// and Close. See golang.org/issue/5138 for more details.
195
sync.Mutex // protects refcount and closing
200
var errClosing = errors.New("use of closed network connection")
202
func (c *client) LocalAddr() net.Addr { return nil }
203
func (c *client) RemoteAddr() net.Addr { return nil }
204
func (c *client) SetDeadline(time.Time) error { return nil }
205
func (c *client) SetReadDeadline(time.Time) error { return nil }
206
func (c *client) SetWriteDeadline(time.Time) error { return nil }
208
// incref, decref are copied from the net package (see net/fd_unix.go) to
209
// implement the concurrent Close contract that net.Conn implementations
210
// from that that package provide.
212
func (c *client) incRef(closing bool) error {
225
func (c *client) decRef() {
229
if c.closing && c.refcount == 0 {
234
func (c *client) Close() error {
235
if err := c.incRef(true); err != nil {
242
func (c *client) Read(b []byte) (int, error) {
243
if err := c.incRef(false); err != nil {
250
func (c *client) Write(b []byte) (int, error) {
251
if err := c.incRef(false); err != nil {
258
221
// newServer returns a new mock ssh server.
259
222
func newServer(t *testing.T) *server {
260
223
dir, err := ioutil.TempDir("", "sshtest")