github.com/olivere/camlistore@v0.0.0-20140121221811-1b7ac2da0199/third_party/code.google.com/p/go.crypto/ssh/tcpip.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package ssh 6 7 import ( 8 "errors" 9 "fmt" 10 "io" 11 "net" 12 "time" 13 ) 14 15 // Dial initiates a connection to the addr from the remote host. 16 // addr is resolved using net.ResolveTCPAddr before connection. 17 // This could allow an observer to observe the DNS name of the 18 // remote host. Consider using ssh.DialTCP to avoid this. 19 func (c *ClientConn) Dial(n, addr string) (net.Conn, error) { 20 raddr, err := net.ResolveTCPAddr(n, addr) 21 if err != nil { 22 return nil, err 23 } 24 return c.DialTCP(n, nil, raddr) 25 } 26 27 // DialTCP connects to the remote address raddr on the network net, 28 // which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used 29 // as the local address for the connection. 30 func (c *ClientConn) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, error) { 31 if laddr == nil { 32 laddr = &net.TCPAddr{ 33 IP: net.IPv4zero, 34 Port: 0, 35 } 36 } 37 ch, err := c.dial(laddr.IP.String(), laddr.Port, raddr.IP.String(), raddr.Port) 38 if err != nil { 39 return nil, err 40 } 41 return &tcpchanconn{ 42 tcpchan: ch, 43 laddr: laddr, 44 raddr: raddr, 45 }, nil 46 } 47 48 // RFC 4254 7.2 49 type channelOpenDirectMsg struct { 50 ChanType string 51 PeersId uint32 52 PeersWindow uint32 53 MaxPacketSize uint32 54 raddr string 55 rport uint32 56 laddr string 57 lport uint32 58 } 59 60 // dial opens a direct-tcpip connection to the remote server. laddr and raddr are passed as 61 // strings and are expected to be resolveable at the remote end. 62 func (c *ClientConn) dial(laddr string, lport int, raddr string, rport int) (*tcpchan, error) { 63 ch := c.newChan(c.transport) 64 if err := c.writePacket(marshal(msgChannelOpen, channelOpenDirectMsg{ 65 ChanType: "direct-tcpip", 66 PeersId: ch.id, 67 PeersWindow: 1 << 14, 68 MaxPacketSize: 1 << 15, // RFC 4253 6.1 69 raddr: raddr, 70 rport: uint32(rport), 71 laddr: laddr, 72 lport: uint32(lport), 73 })); err != nil { 74 c.chanlist.remove(ch.id) 75 return nil, err 76 } 77 if err := ch.waitForChannelOpenResponse(); err != nil { 78 c.chanlist.remove(ch.id) 79 return nil, fmt.Errorf("ssh: unable to open direct tcpip connection: %v", err) 80 } 81 return &tcpchan{ 82 clientChan: ch, 83 Reader: ch.stdout, 84 Writer: ch.stdin, 85 }, nil 86 } 87 88 type tcpchan struct { 89 *clientChan // the backing channel 90 io.Reader 91 io.Writer 92 } 93 94 // tcpchanconn fulfills the net.Conn interface without 95 // the tcpchan having to hold laddr or raddr directly. 96 type tcpchanconn struct { 97 *tcpchan 98 laddr, raddr net.Addr 99 } 100 101 // LocalAddr returns the local network address. 102 func (t *tcpchanconn) LocalAddr() net.Addr { 103 return t.laddr 104 } 105 106 // RemoteAddr returns the remote network address. 107 func (t *tcpchanconn) RemoteAddr() net.Addr { 108 return t.raddr 109 } 110 111 // SetDeadline sets the read and write deadlines associated 112 // with the connection. 113 func (t *tcpchanconn) SetDeadline(deadline time.Time) error { 114 if err := t.SetReadDeadline(deadline); err != nil { 115 return err 116 } 117 return t.SetWriteDeadline(deadline) 118 } 119 120 // SetReadDeadline sets the read deadline. 121 // A zero value for t means Read will not time out. 122 // After the deadline, the error from Read will implement net.Error 123 // with Timeout() == true. 124 func (t *tcpchanconn) SetReadDeadline(deadline time.Time) error { 125 return errors.New("ssh: tcpchan: deadline not supported") 126 } 127 128 // SetWriteDeadline exists to satisfy the net.Conn interface 129 // but is not implemented by this type. It always returns an error. 130 func (t *tcpchanconn) SetWriteDeadline(deadline time.Time) error { 131 return errors.New("ssh: tcpchan: deadline not supported") 132 }