github.com/zignig/go-ipfs@v0.0.0-20141111235910-c9e5fdf55a52/net/conn/secure_conn.go (about)

     1  package conn
     2  
     3  import (
     4  	"errors"
     5  
     6  	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
     7  	ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
     8  
     9  	spipe "github.com/jbenet/go-ipfs/crypto/spipe"
    10  	peer "github.com/jbenet/go-ipfs/peer"
    11  	ctxc "github.com/jbenet/go-ipfs/util/ctxcloser"
    12  	"github.com/jbenet/go-ipfs/util/pipes"
    13  )
    14  
    15  // secureConn wraps another Conn object with an encrypted channel.
    16  type secureConn struct {
    17  
    18  	// the wrapped conn
    19  	insecure Conn
    20  
    21  	// secure pipe, wrapping insecure
    22  	secure *spipe.SecurePipe
    23  
    24  	ctxc.ContextCloser
    25  }
    26  
    27  // newConn constructs a new connection
    28  func newSecureConn(ctx context.Context, insecure Conn, peers peer.Peerstore) (Conn, error) {
    29  
    30  	conn := &secureConn{
    31  		insecure: insecure,
    32  	}
    33  	conn.ContextCloser = ctxc.NewContextCloser(ctx, conn.close)
    34  
    35  	log.Debugf("newSecureConn: %v to %v", insecure.LocalPeer(), insecure.RemotePeer())
    36  	// perform secure handshake before returning this connection.
    37  	if err := conn.secureHandshake(peers); err != nil {
    38  		conn.Close()
    39  		return nil, err
    40  	}
    41  	log.Debugf("newSecureConn: %v to %v handshake success!", insecure.LocalPeer(), insecure.RemotePeer())
    42  
    43  	return conn, nil
    44  }
    45  
    46  // secureHandshake performs the spipe secure handshake.
    47  func (c *secureConn) secureHandshake(peers peer.Peerstore) error {
    48  	if c.secure != nil {
    49  		return errors.New("Conn is already secured or being secured.")
    50  	}
    51  
    52  	// ok to panic here if this type assertion fails. Interface hack.
    53  	// when we support wrapping other Conns, we'll need to change
    54  	// spipe to do something else.
    55  	insecureSC := c.insecure.(*singleConn)
    56  
    57  	// setup a Duplex pipe for spipe
    58  	insecureD := pipes.Duplex{
    59  		In:  insecureSC.msgio.incoming.MsgChan,
    60  		Out: insecureSC.msgio.outgoing.MsgChan,
    61  	}
    62  
    63  	// spipe performs the secure handshake, which takes multiple RTT
    64  	sp, err := spipe.NewSecurePipe(c.Context(), 10, c.LocalPeer(), peers, insecureD)
    65  	if err != nil {
    66  		return err
    67  	}
    68  
    69  	// assign it into the conn object
    70  	c.secure = sp
    71  
    72  	// if we do not know RemotePeer, get it from secure chan (who identifies it)
    73  	if insecureSC.remote == nil {
    74  		insecureSC.remote = c.secure.RemotePeer()
    75  
    76  	} else if insecureSC.remote != c.secure.RemotePeer() {
    77  		// this panic is here because this would be an insidious programmer error
    78  		// that we need to ensure we catch.
    79  		// update: this actually might happen under normal operation-- should
    80  		// perhaps return an error. TBD.
    81  
    82  		log.Errorf("secureConn peer mismatch. %v != %v", insecureSC.remote, c.secure.RemotePeer())
    83  		log.Errorf("insecureSC.remote: %s %#v", insecureSC.remote, insecureSC.remote)
    84  		log.Errorf("c.secure.LocalPeer: %s %#v", c.secure.RemotePeer(), c.secure.RemotePeer())
    85  		panic("secureConn peer mismatch. consructed incorrectly?")
    86  	}
    87  
    88  	return nil
    89  }
    90  
    91  // close is called by ContextCloser
    92  func (c *secureConn) close() error {
    93  	err := c.insecure.Close()
    94  	if c.secure != nil { // may never have gotten here.
    95  		err = c.secure.Close()
    96  	}
    97  	return err
    98  }
    99  
   100  // ID is an identifier unique to this connection.
   101  func (c *secureConn) ID() string {
   102  	return ID(c)
   103  }
   104  
   105  func (c *secureConn) String() string {
   106  	return String(c, "secureConn")
   107  }
   108  
   109  // LocalMultiaddr is the Multiaddr on this side
   110  func (c *secureConn) LocalMultiaddr() ma.Multiaddr {
   111  	return c.insecure.LocalMultiaddr()
   112  }
   113  
   114  // RemoteMultiaddr is the Multiaddr on the remote side
   115  func (c *secureConn) RemoteMultiaddr() ma.Multiaddr {
   116  	return c.insecure.RemoteMultiaddr()
   117  }
   118  
   119  // LocalPeer is the Peer on this side
   120  func (c *secureConn) LocalPeer() peer.Peer {
   121  	return c.insecure.LocalPeer()
   122  }
   123  
   124  // RemotePeer is the Peer on the remote side
   125  func (c *secureConn) RemotePeer() peer.Peer {
   126  	return c.insecure.RemotePeer()
   127  }
   128  
   129  // In returns a readable message channel
   130  func (c *secureConn) In() <-chan []byte {
   131  	return c.secure.In
   132  }
   133  
   134  // Out returns a writable message channel
   135  func (c *secureConn) Out() chan<- []byte {
   136  	return c.secure.Out
   137  }
   138  
   139  func (c *secureConn) GetError() error {
   140  	return c.insecure.GetError()
   141  }