| 
									
										
										
										
											2014-12-12 11:39:29 +01:00
										 |  |  | package p2p | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 	"net" | 
					
						
							|  |  |  | 	"reflect" | 
					
						
							| 
									
										
										
										
											2015-01-06 12:15:51 +01:00
										 |  |  | 	"sync" | 
					
						
							| 
									
										
										
										
											2014-12-12 11:39:29 +01:00
										 |  |  | 	"testing" | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/crypto" | 
					
						
							| 
									
										
										
										
											2014-12-12 11:39:29 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | type peerId struct { | 
					
						
							|  |  |  | 	pubkey []byte | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *peerId) String() string { | 
					
						
							|  |  |  | 	return fmt.Sprintf("test peer %x", self.Pubkey()[:4]) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *peerId) Pubkey() (pubkey []byte) { | 
					
						
							|  |  |  | 	pubkey = self.pubkey | 
					
						
							|  |  |  | 	if len(pubkey) == 0 { | 
					
						
							|  |  |  | 		pubkey = crypto.GenerateNewKeyPair().PublicKey | 
					
						
							|  |  |  | 		self.pubkey = pubkey | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func newTestPeer() (peer *Peer) { | 
					
						
							|  |  |  | 	peer = NewPeer(&peerId{}, []Cap{}) | 
					
						
							|  |  |  | 	peer.pubkeyHook = func(*peerAddr) error { return nil } | 
					
						
							|  |  |  | 	peer.ourID = &peerId{} | 
					
						
							|  |  |  | 	peer.listenAddr = &peerAddr{} | 
					
						
							|  |  |  | 	peer.otherPeers = func() []*Peer { return nil } | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestBaseProtocolPeers(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2015-01-06 12:15:51 +01:00
										 |  |  | 	peerList := []*peerAddr{ | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 		{IP: net.ParseIP("1.2.3.4"), Port: 2222, Pubkey: []byte{}}, | 
					
						
							|  |  |  | 		{IP: net.ParseIP("5.6.7.8"), Port: 3333, Pubkey: []byte{}}, | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-01-06 12:15:51 +01:00
										 |  |  | 	listenAddr := &peerAddr{IP: net.ParseIP("1.3.5.7"), Port: 1111, Pubkey: []byte{}} | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 	rw1, rw2 := MsgPipe() | 
					
						
							| 
									
										
										
										
											2015-01-06 12:15:51 +01:00
										 |  |  | 	defer rw1.Close() | 
					
						
							|  |  |  | 	wg := new(sync.WaitGroup) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 	// run matcher, close pipe when addresses have arrived | 
					
						
							| 
									
										
										
										
											2015-01-06 12:15:51 +01:00
										 |  |  | 	numPeers := len(peerList) + 1 | 
					
						
							|  |  |  | 	addrChan := make(chan *peerAddr) | 
					
						
							|  |  |  | 	wg.Add(1) | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 	go func() { | 
					
						
							| 
									
										
										
										
											2015-01-06 12:15:51 +01:00
										 |  |  | 		i := 0 | 
					
						
							|  |  |  | 		for got := range addrChan { | 
					
						
							|  |  |  | 			var want *peerAddr | 
					
						
							|  |  |  | 			switch { | 
					
						
							|  |  |  | 			case i < len(peerList): | 
					
						
							|  |  |  | 				want = peerList[i] | 
					
						
							|  |  |  | 			case i == len(peerList): | 
					
						
							|  |  |  | 				want = listenAddr // listenAddr should be the last thing sent | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			t.Logf("got peer %d/%d: %v", i+1, numPeers, got) | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 			if !reflect.DeepEqual(want, got) { | 
					
						
							| 
									
										
										
										
											2015-01-06 12:15:51 +01:00
										 |  |  | 				t.Errorf("mismatch: got %+v, want %+v", got, want) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			i++ | 
					
						
							|  |  |  | 			if i == numPeers { | 
					
						
							|  |  |  | 				break | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-01-06 12:15:51 +01:00
										 |  |  | 		if i != numPeers { | 
					
						
							|  |  |  | 			t.Errorf("wrong number of peers received: got %d, want %d", i, numPeers) | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-01-06 12:15:51 +01:00
										 |  |  | 		rw1.Close() | 
					
						
							|  |  |  | 		wg.Done() | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 	}() | 
					
						
							| 
									
										
										
										
											2015-01-06 12:15:51 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// run first peer (in background) | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 	peer1 := newTestPeer() | 
					
						
							| 
									
										
										
										
											2015-01-06 12:15:51 +01:00
										 |  |  | 	peer1.ourListenAddr = listenAddr | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 	peer1.otherPeers = func() []*Peer { | 
					
						
							| 
									
										
										
										
											2015-01-06 12:15:51 +01:00
										 |  |  | 		pl := make([]*Peer, len(peerList)) | 
					
						
							|  |  |  | 		for i, addr := range peerList { | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 			pl[i] = &Peer{listenAddr: addr} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return pl | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-01-06 12:15:51 +01:00
										 |  |  | 	wg.Add(1) | 
					
						
							|  |  |  | 	go func() { | 
					
						
							|  |  |  | 		runBaseProtocol(peer1, rw1) | 
					
						
							|  |  |  | 		wg.Done() | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 	// run second peer | 
					
						
							|  |  |  | 	peer2 := newTestPeer() | 
					
						
							|  |  |  | 	peer2.newPeerAddr = addrChan // feed peer suggestions into matcher | 
					
						
							|  |  |  | 	if err := runBaseProtocol(peer2, rw2); err != ErrPipeClosed { | 
					
						
							|  |  |  | 		t.Errorf("peer2 terminated with unexpected error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-01-06 12:15:51 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// terminate matcher | 
					
						
							|  |  |  | 	close(addrChan) | 
					
						
							|  |  |  | 	wg.Wait() | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-12 11:39:29 +01:00
										 |  |  | func TestBaseProtocolDisconnect(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 	peer := NewPeer(&peerId{}, nil) | 
					
						
							|  |  |  | 	peer.ourID = &peerId{} | 
					
						
							| 
									
										
										
										
											2014-12-12 11:39:29 +01:00
										 |  |  | 	peer.pubkeyHook = func(*peerAddr) error { return nil } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rw1, rw2 := MsgPipe() | 
					
						
							|  |  |  | 	done := make(chan struct{}) | 
					
						
							|  |  |  | 	go func() { | 
					
						
							|  |  |  | 		if err := expectMsg(rw2, handshakeMsg); err != nil { | 
					
						
							|  |  |  | 			t.Error(err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-01-06 11:35:09 +01:00
										 |  |  | 		err := EncodeMsg(rw2, handshakeMsg, | 
					
						
							| 
									
										
										
										
											2014-12-12 11:39:29 +01:00
										 |  |  | 			baseProtocolVersion, | 
					
						
							|  |  |  | 			"", | 
					
						
							|  |  |  | 			[]interface{}{}, | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 			make([]byte, 64), | 
					
						
							|  |  |  | 		) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Error(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if err := expectMsg(rw2, getPeersMsg); err != nil { | 
					
						
							|  |  |  | 			t.Error(err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-01-06 11:35:09 +01:00
										 |  |  | 		if err := EncodeMsg(rw2, discMsg, DiscQuitting); err != nil { | 
					
						
							| 
									
										
										
										
											2014-12-12 11:39:29 +01:00
										 |  |  | 			t.Error(err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-12 11:39:29 +01:00
										 |  |  | 		close(done) | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err := runBaseProtocol(peer, rw1); err == nil { | 
					
						
							|  |  |  | 		t.Errorf("base protocol returned without error") | 
					
						
							|  |  |  | 	} else if reason, ok := err.(discRequestedError); !ok || reason != DiscQuitting { | 
					
						
							|  |  |  | 		t.Errorf("base protocol returned wrong error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	<-done | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func expectMsg(r MsgReader, code uint64) error { | 
					
						
							|  |  |  | 	msg, err := r.ReadMsg() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := msg.Discard(); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if msg.Code != code { | 
					
						
							|  |  |  | 		return fmt.Errorf("wrong message code: got %d, expected %d", msg.Code, code) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } |