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 }