OSDN Git Service

libgo: Update to weekly.2011-12-06.
[pf3gnuchains/gcc-fork.git] / libgo / go / exp / ssh / tcpip.go
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 )
13 // Dial initiates a connection to the addr from the remote host.
14 // addr is resolved using net.ResolveTCPAddr before connection. 
15 // This could allow an observer to observe the DNS name of the 
16 // remote host. Consider using ssh.DialTCP to avoid this.
17 func (c *ClientConn) Dial(n, addr string) (net.Conn, error) {
18         raddr, err := net.ResolveTCPAddr(n, addr)
19         if err != nil {
20                 return nil, err
21         }
22         return c.DialTCP(n, nil, raddr)
23 }
24
25 // DialTCP connects to the remote address raddr on the network net,
26 // which must be "tcp", "tcp4", or "tcp6".  If laddr is not nil, it is used
27 // as the local address for the connection.
28 func (c *ClientConn) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, error) {
29         if laddr == nil {
30                 laddr = &net.TCPAddr{
31                         IP:   net.IPv4zero,
32                         Port: 0,
33                 }
34         }
35         ch, err := c.dial(laddr.IP.String(), laddr.Port, raddr.IP.String(), raddr.Port)
36         if err != nil {
37                 return nil, err
38         }
39         return &tcpchanconn{
40                 tcpchan: ch,
41                 laddr:   laddr,
42                 raddr:   raddr,
43         }, nil
44 }
45
46 // RFC 4254 7.2
47 type channelOpenDirectMsg struct {
48         ChanType      string
49         PeersId       uint32
50         PeersWindow   uint32
51         MaxPacketSize uint32
52         raddr         string
53         rport         uint32
54         laddr         string
55         lport         uint32
56 }
57
58 // dial opens a direct-tcpip connection to the remote server. laddr and raddr are passed as
59 // strings and are expected to be resolveable at the remote end.
60 func (c *ClientConn) dial(laddr string, lport int, raddr string, rport int) (*tcpchan, error) {
61         ch := c.newChan(c.transport)
62         if err := c.writePacket(marshal(msgChannelOpen, channelOpenDirectMsg{
63                 ChanType:      "direct-tcpip",
64                 PeersId:       ch.id,
65                 PeersWindow:   1 << 14,
66                 MaxPacketSize: 1 << 15, // RFC 4253 6.1
67                 raddr:         raddr,
68                 rport:         uint32(rport),
69                 laddr:         laddr,
70                 lport:         uint32(lport),
71         })); err != nil {
72                 c.chanlist.remove(ch.id)
73                 return nil, err
74         }
75         if err := ch.waitForChannelOpenResponse(); err != nil {
76                 c.chanlist.remove(ch.id)
77                 return nil, fmt.Errorf("ssh: unable to open direct tcpip connection: %v", err)
78         }
79         return &tcpchan{
80                 clientChan: ch,
81                 Reader:     ch.stdout,
82                 Writer:     ch.stdin,
83         }, nil
84 }
85
86 type tcpchan struct {
87         *clientChan // the backing channel
88         io.Reader
89         io.Writer
90 }
91
92 // tcpchanconn fulfills the net.Conn interface without 
93 // the tcpchan having to hold laddr or raddr directly.
94 type tcpchanconn struct {
95         *tcpchan
96         laddr, raddr net.Addr
97 }
98
99 // LocalAddr returns the local network address.
100 func (t *tcpchanconn) LocalAddr() net.Addr {
101         return t.laddr
102 }
103
104 // RemoteAddr returns the remote network address.
105 func (t *tcpchanconn) RemoteAddr() net.Addr {
106         return t.raddr
107 }
108
109 // SetTimeout sets the read and write deadlines associated
110 // with the connection.
111 func (t *tcpchanconn) SetTimeout(nsec int64) error {
112         if err := t.SetReadTimeout(nsec); err != nil {
113                 return err
114         }
115         return t.SetWriteTimeout(nsec)
116 }
117
118 // SetReadTimeout sets the time (in nanoseconds) that
119 // Read will wait for data before returning an error with Timeout() == true.
120 // Setting nsec == 0 (the default) disables the deadline.
121 func (t *tcpchanconn) SetReadTimeout(nsec int64) error {
122         return errors.New("ssh: tcpchan: timeout not supported")
123 }
124
125 // SetWriteTimeout sets the time (in nanoseconds) that
126 // Write will wait to send its data before returning an error with Timeout() == true.
127 // Setting nsec == 0 (the default) disables the deadline.
128 // Even if write times out, it may return n > 0, indicating that
129 // some of the data was successfully written.
130 func (t *tcpchanconn) SetWriteTimeout(nsec int64) error {
131         return errors.New("ssh: tcpchan: timeout not supported")
132 }