github.com/zignig/go-ipfs@v0.0.0-20141111235910-c9e5fdf55a52/net/conn/handshake.go (about) 1 package conn 2 3 import ( 4 "errors" 5 "fmt" 6 7 handshake "github.com/jbenet/go-ipfs/net/handshake" 8 hspb "github.com/jbenet/go-ipfs/net/handshake/pb" 9 10 context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" 11 proto "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/goprotobuf/proto" 12 ) 13 14 // Handshake1 exchanges local and remote versions and compares them 15 // closes remote and returns an error in case of major difference 16 func Handshake1(ctx context.Context, c Conn) error { 17 rpeer := c.RemotePeer() 18 lpeer := c.LocalPeer() 19 20 var remoteH, localH *hspb.Handshake1 21 localH = handshake.Handshake1Msg() 22 23 myVerBytes, err := proto.Marshal(localH) 24 if err != nil { 25 return err 26 } 27 28 c.Out() <- myVerBytes 29 log.Debugf("Sent my version (%s) to %s", localH, rpeer) 30 31 select { 32 case <-ctx.Done(): 33 return ctx.Err() 34 35 case <-c.Closing(): 36 return errors.New("remote closed connection during version exchange") 37 38 case data, ok := <-c.In(): 39 if !ok { 40 return fmt.Errorf("error retrieving from conn: %v", rpeer) 41 } 42 43 remoteH = new(hspb.Handshake1) 44 err = proto.Unmarshal(data, remoteH) 45 if err != nil { 46 return fmt.Errorf("could not decode remote version: %q", err) 47 } 48 49 log.Debugf("Received remote version (%s) from %s", remoteH, rpeer) 50 } 51 52 if err := handshake.Handshake1Compatible(localH, remoteH); err != nil { 53 log.Infof("%s (%s) incompatible version with %s (%s)", lpeer, localH, rpeer, remoteH) 54 return err 55 } 56 57 log.Debugf("%s version handshake compatible %s", lpeer, rpeer) 58 return nil 59 } 60 61 // Handshake3 exchanges local and remote service information 62 func Handshake3(ctx context.Context, c Conn) (*handshake.Handshake3Result, error) { 63 rpeer := c.RemotePeer() 64 lpeer := c.LocalPeer() 65 66 // setup + send the message to remote 67 var remoteH, localH *hspb.Handshake3 68 localH = handshake.Handshake3Msg(lpeer, c.RemoteMultiaddr()) 69 localB, err := proto.Marshal(localH) 70 if err != nil { 71 return nil, err 72 } 73 74 c.Out() <- localB 75 log.Debugf("Handshake1: sent to %s", rpeer) 76 77 // wait + listen for response 78 select { 79 case <-ctx.Done(): 80 return nil, ctx.Err() 81 82 case <-c.Closing(): 83 return nil, errors.New("Handshake3: error remote connection closed") 84 85 case remoteB, ok := <-c.In(): 86 if !ok { 87 return nil, fmt.Errorf("Handshake3 error receiving from conn: %v", rpeer) 88 } 89 90 remoteH = new(hspb.Handshake3) 91 err = proto.Unmarshal(remoteB, remoteH) 92 if err != nil { 93 return nil, fmt.Errorf("Handshake3 could not decode remote msg: %q", err) 94 } 95 96 log.Debugf("Handshake3 received from %s", rpeer) 97 } 98 99 // actually update our state based on the new knowledge 100 res, err := handshake.Handshake3Update(lpeer, rpeer, remoteH) 101 if err != nil { 102 log.Errorf("Handshake3 failed to update %s", rpeer) 103 } 104 res.RemoteObservedAddress = c.RemoteMultiaddr() 105 return res, nil 106 }