mirror of
https://github.com/ipfs/kubo.git
synced 2025-09-10 22:49:13 +08:00
add in message type routing to the swarm object. tired, needs cleanup.
This commit is contained in:
@ -100,10 +100,11 @@ func (dht *IpfsDHT) Connect(addr *ma.Multiaddr) (*peer.Peer, error) {
|
||||
func (dht *IpfsDHT) handleMessages() {
|
||||
u.DOut("Begin message handling routine\n")
|
||||
|
||||
ch := dht.network.GetChan()
|
||||
errs := dht.network.GetErrChan()
|
||||
dhtmes := dht.network.GetChannel(swarm.PBWrapper_DHT_MESSAGE)
|
||||
for {
|
||||
select {
|
||||
case mes, ok := <-ch.Incoming:
|
||||
case mes, ok := <-dhtmes:
|
||||
if !ok {
|
||||
u.DOut("handleMessages closing, bad recv on incoming\n")
|
||||
return
|
||||
@ -147,7 +148,7 @@ func (dht *IpfsDHT) handleMessages() {
|
||||
u.PErr("Recieved invalid message type")
|
||||
}
|
||||
|
||||
case err := <-ch.Errors:
|
||||
case err := <-errs:
|
||||
u.PErr("dht err: %s\n", err)
|
||||
case <-dht.shutdown:
|
||||
return
|
||||
|
@ -132,8 +132,8 @@ func TestValueGetSet(t *testing.T) {
|
||||
dhtA.Start()
|
||||
dhtB.Start()
|
||||
|
||||
errsa := dhtA.network.GetChan().Errors
|
||||
errsb := dhtB.network.GetChan().Errors
|
||||
errsa := dhtA.network.GetErrChan()
|
||||
errsb := dhtB.network.GetErrChan()
|
||||
go func() {
|
||||
select {
|
||||
case err := <-errsa:
|
||||
|
@ -66,8 +66,12 @@ func (f *fauxNet) Send(mes *swarm.Message) {
|
||||
f.Chan.Outgoing <- mes
|
||||
}
|
||||
|
||||
func (f *fauxNet) GetChan() *swarm.Chan {
|
||||
return f.Chan
|
||||
func (f *fauxNet) GetErrChan() chan error {
|
||||
return f.Chan.Errors
|
||||
}
|
||||
|
||||
func (f *fauxNet) GetChannel(t swarm.PBWrapper_MessageType) chan *swarm.Message {
|
||||
return f.Chan.Incoming
|
||||
}
|
||||
|
||||
func (f *fauxNet) Connect(addr *ma.Multiaddr) (*peer.Peer, error) {
|
||||
@ -167,7 +171,6 @@ func _randPeer() *peer.Peer {
|
||||
}
|
||||
|
||||
func TestNotFound(t *testing.T) {
|
||||
u.Debug = true
|
||||
fn := newFauxNet()
|
||||
fn.Listen()
|
||||
|
||||
@ -225,3 +228,64 @@ func TestNotFound(t *testing.T) {
|
||||
}
|
||||
t.Fatal("Expected to recieve an error.")
|
||||
}
|
||||
|
||||
// If less than K nodes are in the entire network, it should fail when we make
|
||||
// a GET rpc and nobody has the value
|
||||
func TestLessThanKResponses(t *testing.T) {
|
||||
u.Debug = false
|
||||
fn := newFauxNet()
|
||||
fn.Listen()
|
||||
|
||||
local := new(peer.Peer)
|
||||
local.ID = peer.ID("test_peer")
|
||||
|
||||
d := NewDHT(local, fn)
|
||||
d.Start()
|
||||
|
||||
var ps []*peer.Peer
|
||||
for i := 0; i < 5; i++ {
|
||||
ps = append(ps, _randPeer())
|
||||
d.Update(ps[i])
|
||||
}
|
||||
other := _randPeer()
|
||||
|
||||
// Reply with random peers to every message
|
||||
fn.AddHandler(func(mes *swarm.Message) *swarm.Message {
|
||||
t.Log("Handling message...")
|
||||
pmes := new(PBDHTMessage)
|
||||
err := proto.Unmarshal(mes.Data, pmes)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
switch pmes.GetType() {
|
||||
case PBDHTMessage_GET_VALUE:
|
||||
resp := Message{
|
||||
Type: pmes.GetType(),
|
||||
ID: pmes.GetId(),
|
||||
Response: true,
|
||||
Success: false,
|
||||
Peers: []*peer.Peer{other},
|
||||
}
|
||||
|
||||
return swarm.NewMessage(mes.Peer, resp.ToProtobuf())
|
||||
default:
|
||||
panic("Shouldnt recieve this.")
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
_, err := d.GetValue(u.Key("hello"), time.Second*30)
|
||||
if err != nil {
|
||||
switch err {
|
||||
case u.ErrNotFound:
|
||||
//Success!
|
||||
return
|
||||
case u.ErrTimeout:
|
||||
t.Fatal("Should not have gotten timeout!")
|
||||
default:
|
||||
t.Fatalf("Got unexpected error: %s", err)
|
||||
}
|
||||
}
|
||||
t.Fatal("Expected to recieve an error.")
|
||||
}
|
||||
|
@ -3,8 +3,8 @@ package dht
|
||||
import (
|
||||
"time"
|
||||
|
||||
u "github.com/jbenet/go-ipfs/util"
|
||||
peer "github.com/jbenet/go-ipfs/peer"
|
||||
u "github.com/jbenet/go-ipfs/util"
|
||||
)
|
||||
|
||||
type ProviderManager struct {
|
||||
|
@ -164,7 +164,8 @@ func (dht *IpfsDHT) GetValue(key u.Key, timeout time.Duration) ([]byte, error) {
|
||||
case p := <-npeerChan:
|
||||
count++
|
||||
if count >= KValue {
|
||||
break
|
||||
errChan <- u.ErrNotFound
|
||||
return
|
||||
}
|
||||
c.Increment()
|
||||
|
||||
@ -172,16 +173,15 @@ func (dht *IpfsDHT) GetValue(key u.Key, timeout time.Duration) ([]byte, error) {
|
||||
default:
|
||||
if c.Size() == 0 {
|
||||
errChan <- u.ErrNotFound
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
process := func() {
|
||||
for {
|
||||
select {
|
||||
case p, ok := <-procPeer:
|
||||
if !ok || p == nil {
|
||||
for p := range procPeer {
|
||||
if p == nil {
|
||||
c.Decrement()
|
||||
return
|
||||
}
|
||||
@ -207,7 +207,6 @@ func (dht *IpfsDHT) GetValue(key u.Key, timeout time.Duration) ([]byte, error) {
|
||||
c.Decrement()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < AlphaValue; i++ {
|
||||
go process()
|
||||
|
@ -40,8 +40,6 @@ func Dial(network string, peer *peer.Peer) (*Conn, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Printf("Making connection to: %s\n", host)
|
||||
|
||||
nconn, err := net.Dial(network, host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -14,7 +14,8 @@ type Network interface {
|
||||
Listen() error
|
||||
ConnectNew(*ma.Multiaddr) (*peer.Peer, error)
|
||||
GetConnection(id peer.ID, addr *ma.Multiaddr) (*peer.Peer, error)
|
||||
GetChan() *Chan
|
||||
GetErrChan() chan error
|
||||
GetChannel(PBWrapper_MessageType) chan *Message
|
||||
Close()
|
||||
Drop(*peer.Peer) error
|
||||
}
|
||||
|
@ -84,6 +84,10 @@ type Swarm struct {
|
||||
conns ConnMap
|
||||
connsLock sync.RWMutex
|
||||
|
||||
filterChans map[PBWrapper_MessageType]chan *Message
|
||||
toFilter chan *Message
|
||||
newFilters chan *newFilterInfo
|
||||
|
||||
local *peer.Peer
|
||||
listeners []net.Listener
|
||||
}
|
||||
@ -94,7 +98,11 @@ func NewSwarm(local *peer.Peer) *Swarm {
|
||||
Chan: NewChan(10),
|
||||
conns: ConnMap{},
|
||||
local: local,
|
||||
filterChans: make(map[PBWrapper_MessageType]chan *Message),
|
||||
toFilter: make(chan *Message, 32),
|
||||
newFilters: make(chan *newFilterInfo),
|
||||
}
|
||||
go s.routeMessages()
|
||||
go s.fanOut()
|
||||
return s
|
||||
}
|
||||
@ -299,15 +307,8 @@ func (s *Swarm) fanIn(conn *Conn) {
|
||||
goto out
|
||||
}
|
||||
|
||||
wrapper, err := Unwrap(data)
|
||||
if err != nil {
|
||||
s.Error(err)
|
||||
continue
|
||||
}
|
||||
|
||||
// wrap it for consumers.
|
||||
msg := &Message{Peer: conn.Peer, Data: wrapper.GetMessage()}
|
||||
s.Chan.Incoming <- msg
|
||||
msg := &Message{Peer: conn.Peer, Data: data}
|
||||
s.toFilter <- msg
|
||||
}
|
||||
}
|
||||
out:
|
||||
@ -317,6 +318,39 @@ out:
|
||||
s.connsLock.Unlock()
|
||||
}
|
||||
|
||||
type newFilterInfo struct {
|
||||
Type PBWrapper_MessageType
|
||||
resp chan chan *Message
|
||||
}
|
||||
|
||||
func (s *Swarm) routeMessages() {
|
||||
for {
|
||||
select {
|
||||
case mes, ok := <-s.toFilter:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
wrapper, err := Unwrap(mes.Data)
|
||||
if err != nil {
|
||||
u.PErr("error in route messages: %s\n", err)
|
||||
}
|
||||
|
||||
ch, ok := s.filterChans[PBWrapper_MessageType(wrapper.GetType())]
|
||||
if !ok {
|
||||
u.PErr("Received message with invalid type: %d\n", wrapper.GetType())
|
||||
continue
|
||||
}
|
||||
|
||||
mes.Data = wrapper.GetMessage()
|
||||
ch <- mes
|
||||
case gchan := <-s.newFilters:
|
||||
nch := make(chan *Message)
|
||||
s.filterChans[gchan.Type] = nch
|
||||
gchan.resp <- nch
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Swarm) Find(key u.Key) *peer.Peer {
|
||||
s.connsLock.RLock()
|
||||
defer s.connsLock.RUnlock()
|
||||
@ -414,8 +448,8 @@ func (s *Swarm) Error(e error) {
|
||||
s.Chan.Errors <- e
|
||||
}
|
||||
|
||||
func (s *Swarm) GetChan() *Chan {
|
||||
return s.Chan
|
||||
func (s *Swarm) GetErrChan() chan error {
|
||||
return s.Chan.Errors
|
||||
}
|
||||
|
||||
func Wrap(data []byte, typ PBWrapper_MessageType) ([]byte, error) {
|
||||
@ -439,5 +473,15 @@ func Unwrap(data []byte) (*PBWrapper, error) {
|
||||
return mes, nil
|
||||
}
|
||||
|
||||
func (s *Swarm) GetChannel(typ PBWrapper_MessageType) chan *Message {
|
||||
nfi := &newFilterInfo{
|
||||
Type: typ,
|
||||
resp: make(chan chan *Message),
|
||||
}
|
||||
s.newFilters <- nfi
|
||||
|
||||
return <-nfi.resp
|
||||
}
|
||||
|
||||
// Temporary to ensure that the Swarm always matches the Network interface as we are changing it
|
||||
var _ Network = &Swarm{}
|
||||
|
Reference in New Issue
Block a user