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  }