Commit 0817ffa3 authored by Juan Batiz-Benet's avatar Juan Batiz-Benet

spipe + handshake with peerstore

parent a93a31f2
......@@ -90,23 +90,18 @@ func (s *SecurePipe) handshake() error {
return err
}
s.remote.PubKey, err = ci.UnmarshalPublicKey(proposeResp.GetPubkey())
// get remote identity
remotePubKey, err := ci.UnmarshalPublicKey(proposeResp.GetPubkey())
if err != nil {
return err
}
remoteID, err := IDFromPubKey(s.remote.PubKey)
// get or construct peer
s.remote, err = getOrConstructPeer(s.peers, remotePubKey)
if err != nil {
return err
}
if s.remote.ID != nil && !remoteID.Equal(s.remote.ID) {
e := "Expected pubkey does not match sent pubkey: %v - %v"
return fmt.Errorf(e, s.remote.ID.Pretty(), remoteID.Pretty())
} else if s.remote.ID == nil {
s.remote.ID = remoteID
}
// u.POut("Remote Peer Identified as %s\n", s.remote.ID.Pretty())
u.DOut("[%s] Remote Peer Identified as %s\n", s.local.ID.Pretty(), s.remote.ID.Pretty())
exchange, err := selectBest(SupportedExchanges, proposeResp.GetExchanges())
if err != nil {
......@@ -340,3 +335,62 @@ func selectBest(myPrefs, theirPrefs string) (string, error) {
return "", errors.New("No algorithms in common!")
}
// getOrConstructPeer attempts to fetch a peer from a peerstore.
// if succeeds, verify ID and PubKey match.
// else, construct it.
func getOrConstructPeer(peers peer.Peerstore, rpk ci.PubKey) (*peer.Peer, error) {
rid, err := IDFromPubKey(rpk)
if err != nil {
return nil, err
}
npeer, err := peers.Get(rid)
if err != nil {
if err != peer.ErrNotFound {
return nil, err // unexpected error happened.
}
// dont have peer, so construct it + add it to peerstore.
npeer = &peer.Peer{ID: rid, PubKey: rpk}
if err := peers.Put(npeer); err != nil {
return nil, err
}
// done, return the newly constructed peer.
return npeer, nil
}
// did have it locally.
// let's verify ID
if !npeer.ID.Equal(rid) {
e := "Expected peer.ID does not match sent pubkey's hash: %v - %v"
return nil, fmt.Errorf(e, npeer.ID.Pretty(), rid.Pretty())
}
if npeer.PubKey == nil {
// didn't have a pubkey, just set it.
npeer.PubKey = rpk
return npeer, nil
}
// did have pubkey, let's verify it's really the same.
// this shouldn't ever happen, given we hashed, etc, but it could mean
// expected code (or protocol) invariants violated.
lb, err1 := npeer.PubKey.Bytes()
if err1 != nil {
return nil, err1
}
rb, err2 := rpk.Bytes()
if err2 != nil {
return nil, err2
}
if !bytes.Equal(lb, rb) {
return nil, fmt.Errorf("WARNING: PubKey mismatch: %v", npeer.ID.Pretty())
}
return npeer, nil
}
......@@ -20,6 +20,7 @@ type SecurePipe struct {
local *peer.Peer
remote *peer.Peer
peers peer.Peerstore
params params
......@@ -32,16 +33,16 @@ type params struct {
}
// NewSecurePipe constructs a pipe with channels of a given buffer size.
func NewSecurePipe(ctx context.Context, bufsize int, local,
remote *peer.Peer) (*SecurePipe, error) {
func NewSecurePipe(ctx context.Context, bufsize int, local *peer.Peer,
peers peer.Peerstore) (*SecurePipe, error) {
sp := &SecurePipe{
Duplex: Duplex{
In: make(chan []byte, bufsize),
Out: make(chan []byte, bufsize),
},
local: local,
remote: remote,
local: local,
peers: peers,
}
return sp, nil
}
......@@ -63,6 +64,16 @@ func (s *SecurePipe) Wrap(ctx context.Context, insecure Duplex) error {
return nil
}
// LocalPeer retrieves the local peer.
func (s *SecurePipe) LocalPeer() *peer.Peer {
return s.local
}
// RemotePeer retrieves the local peer.
func (s *SecurePipe) RemotePeer() *peer.Peer {
return s.remote
}
// Close closes the secure pipe
func (s *SecurePipe) Close() error {
if s.cancel == nil {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment