spipe + handshake with peerstore
Juan Batiz-Benet committed
Sep 26, 2014 at 02:09 UTC
0817ffa366ea592a604430b7416173bc3fc1d9c4
2 files changed
+79
-14
crypto/spipe/handshake.go
+64
-10
@@ -90,23 +90,18 @@ func (s *SecurePipe) handshake() error {
90
return err
91
}
92
93
- s.remote.PubKey, err = ci.UnmarshalPublicKey(proposeResp.GetPubkey())
93
+ // get remote identity
94
+ remotePubKey, err := ci.UnmarshalPublicKey(proposeResp.GetPubkey())
95
if err != nil {
96
return err
97
}
98
98
- remoteID, err := IDFromPubKey(s.remote.PubKey)
99
+ // get or construct peer
100
+ s.remote, err = getOrConstructPeer(s.peers, remotePubKey)
101
if err != nil {
102
return err
103
}
102
-
103
- if s.remote.ID != nil && !remoteID.Equal(s.remote.ID) {
104
- e := "Expected pubkey does not match sent pubkey: %v - %v"
105
- return fmt.Errorf(e, s.remote.ID.Pretty(), remoteID.Pretty())
106
- } else if s.remote.ID == nil {
107
- s.remote.ID = remoteID
108
- }
109
- // u.POut("Remote Peer Identified as %s\n", s.remote.ID.Pretty())
104
+ u.DOut("[%s] Remote Peer Identified as %s\n", s.local.ID.Pretty(), s.remote.ID.Pretty())
105
106
exchange, err := selectBest(SupportedExchanges, proposeResp.GetExchanges())
107
if err != nil {
@@ -340,3 +335,62 @@ func selectBest(myPrefs, theirPrefs string) (string, error) {
335
336
return "", errors.New("No algorithms in common!")
337
}
338
+
339
+// getOrConstructPeer attempts to fetch a peer from a peerstore.
340
+// if succeeds, verify ID and PubKey match.
341
+// else, construct it.
342
+func getOrConstructPeer(peers peer.Peerstore, rpk ci.PubKey) (*peer.Peer, error) {
343
+
344
+ rid, err := IDFromPubKey(rpk)
345
+ if err != nil {
346
+ return nil, err
347
+ }
348
+
349
+ npeer, err := peers.Get(rid)
350
+ if err != nil {
351
+ if err != peer.ErrNotFound {
352
+ return nil, err // unexpected error happened.
353
+ }
354
+
355
+ // dont have peer, so construct it + add it to peerstore.
356
+ npeer = &peer.Peer{ID: rid, PubKey: rpk}
357
+ if err := peers.Put(npeer); err != nil {
358
+ return nil, err
359
+ }
360
+
361
+ // done, return the newly constructed peer.
362
+ return npeer, nil
363
+ }
364
+
365
+ // did have it locally.
366
+
367
+ // let's verify ID
368
+ if !npeer.ID.Equal(rid) {
369
+ e := "Expected peer.ID does not match sent pubkey's hash: %v - %v"
370
+ return nil, fmt.Errorf(e, npeer.ID.Pretty(), rid.Pretty())
371
+ }
372
+
373
+ if npeer.PubKey == nil {
374
+ // didn't have a pubkey, just set it.
375
+ npeer.PubKey = rpk
376
+ return npeer, nil
377
+ }
378
+
379
+ // did have pubkey, let's verify it's really the same.
380
+ // this shouldn't ever happen, given we hashed, etc, but it could mean
381
+ // expected code (or protocol) invariants violated.
382
+
383
+ lb, err1 := npeer.PubKey.Bytes()
384
+ if err1 != nil {
385
+ return nil, err1
386
+ }
387
+ rb, err2 := rpk.Bytes()
388
+ if err2 != nil {
389
+ return nil, err2
390
+ }
391
+
392
+ if !bytes.Equal(lb, rb) {
393
+ return nil, fmt.Errorf("WARNING: PubKey mismatch: %v", npeer.ID.Pretty())
394
+ }
395
+ return npeer, nil
396
+}
crypto/spipe/pipe.go
+15
-4
@@ -20,6 +20,7 @@ type SecurePipe struct {
20
21
local *peer.Peer
22
remote *peer.Peer
23
+ peers peer.Peerstore
24
25
params params
26
@@ -32,16 +33,16 @@ type params struct {
33
}
34
35
// NewSecurePipe constructs a pipe with channels of a given buffer size.
35
-func NewSecurePipe(ctx context.Context, bufsize int, local,
36
- remote *peer.Peer) (*SecurePipe, error) {
36
+func NewSecurePipe(ctx context.Context, bufsize int, local *peer.Peer,
37
+ peers peer.Peerstore) (*SecurePipe, error) {
38
39
sp := &SecurePipe{
40
Duplex: Duplex{
41
In: make(chan []byte, bufsize),
42
Out: make(chan []byte, bufsize),
43
},
43
- local: local,
44
- remote: remote,
44
+ local: local,
45
+ peers: peers,
46
}
47
return sp, nil
48
}
@@ -63,6 +64,16 @@ func (s *SecurePipe) Wrap(ctx context.Context, insecure Duplex) error {
64
return nil
65
}
66
67
+// LocalPeer retrieves the local peer.
68
+func (s *SecurePipe) LocalPeer() *peer.Peer {
69
+ return s.local
70
+}
71
+
72
+// RemotePeer retrieves the local peer.
73
+func (s *SecurePipe) RemotePeer() *peer.Peer {
74
+ return s.remote
75
+}
76
+
77
// Close closes the secure pipe
78
func (s *SecurePipe) Close() error {
79
if s.cancel == nil {