Commit 197d609b authored by lash's avatar lash Committed by Anton Evangelatov

swarm/pss: Message handler refactor (#18169)

parent ca228569
...@@ -81,14 +81,15 @@ func NewKadParams() *KadParams { ...@@ -81,14 +81,15 @@ func NewKadParams() *KadParams {
// Kademlia is a table of live peers and a db of known peers (node records) // Kademlia is a table of live peers and a db of known peers (node records)
type Kademlia struct { type Kademlia struct {
lock sync.RWMutex lock sync.RWMutex
*KadParams // Kademlia configuration parameters *KadParams // Kademlia configuration parameters
base []byte // immutable baseaddress of the table base []byte // immutable baseaddress of the table
addrs *pot.Pot // pots container for known peer addresses addrs *pot.Pot // pots container for known peer addresses
conns *pot.Pot // pots container for live peer connections conns *pot.Pot // pots container for live peer connections
depth uint8 // stores the last current depth of saturation depth uint8 // stores the last current depth of saturation
nDepth int // stores the last neighbourhood depth nDepth int // stores the last neighbourhood depth
nDepthC chan int // returned by DepthC function to signal neighbourhood depth change nDepthC chan int // returned by DepthC function to signal neighbourhood depth change
addrCountC chan int // returned by AddrCountC function to signal peer count change addrCountC chan int // returned by AddrCountC function to signal peer count change
Pof func(pot.Val, pot.Val, int) (int, bool) // function for calculating kademlia routing distance between two addresses
} }
// NewKademlia creates a Kademlia table for base address addr // NewKademlia creates a Kademlia table for base address addr
...@@ -103,6 +104,7 @@ func NewKademlia(addr []byte, params *KadParams) *Kademlia { ...@@ -103,6 +104,7 @@ func NewKademlia(addr []byte, params *KadParams) *Kademlia {
KadParams: params, KadParams: params,
addrs: pot.NewPot(nil, 0), addrs: pot.NewPot(nil, 0),
conns: pot.NewPot(nil, 0), conns: pot.NewPot(nil, 0),
Pof: pof,
} }
} }
...@@ -289,6 +291,7 @@ func (k *Kademlia) On(p *Peer) (uint8, bool) { ...@@ -289,6 +291,7 @@ func (k *Kademlia) On(p *Peer) (uint8, bool) {
// neighbourhood depth on each change. // neighbourhood depth on each change.
// Not receiving from the returned channel will block On function // Not receiving from the returned channel will block On function
// when the neighbourhood depth is changed. // when the neighbourhood depth is changed.
// TODO: Why is this exported, and if it should be; why can't we have more subscribers than one?
func (k *Kademlia) NeighbourhoodDepthC() <-chan int { func (k *Kademlia) NeighbourhoodDepthC() <-chan int {
k.lock.Lock() k.lock.Lock()
defer k.lock.Unlock() defer k.lock.Unlock()
...@@ -429,7 +432,12 @@ func (k *Kademlia) eachAddr(base []byte, o int, f func(*BzzAddr, int, bool) bool ...@@ -429,7 +432,12 @@ func (k *Kademlia) eachAddr(base []byte, o int, f func(*BzzAddr, int, bool) bool
// neighbourhoodDepth returns the proximity order that defines the distance of // neighbourhoodDepth returns the proximity order that defines the distance of
// the nearest neighbour set with cardinality >= MinProxBinSize // the nearest neighbour set with cardinality >= MinProxBinSize
// if there is altogether less than MinProxBinSize peers it returns 0 // if there is altogether less than MinProxBinSize peers it returns 0
// caller must hold the lock func (k *Kademlia) NeighbourhoodDepth() (depth int) {
k.lock.RLock()
defer k.lock.RUnlock()
return k.neighbourhoodDepth()
}
func (k *Kademlia) neighbourhoodDepth() (depth int) { func (k *Kademlia) neighbourhoodDepth() (depth int) {
if k.conns.Size() < k.MinProxBinSize { if k.conns.Size() < k.MinProxBinSize {
return 0 return 0
......
...@@ -51,7 +51,7 @@ func NewAPI(ps *Pss) *API { ...@@ -51,7 +51,7 @@ func NewAPI(ps *Pss) *API {
// //
// All incoming messages to the node matching this topic will be encapsulated in the APIMsg // All incoming messages to the node matching this topic will be encapsulated in the APIMsg
// struct and sent to the subscriber // struct and sent to the subscriber
func (pssapi *API) Receive(ctx context.Context, topic Topic) (*rpc.Subscription, error) { func (pssapi *API) Receive(ctx context.Context, topic Topic, raw bool, prox bool) (*rpc.Subscription, error) {
notifier, supported := rpc.NotifierFromContext(ctx) notifier, supported := rpc.NotifierFromContext(ctx)
if !supported { if !supported {
return nil, fmt.Errorf("Subscribe not supported") return nil, fmt.Errorf("Subscribe not supported")
...@@ -59,7 +59,7 @@ func (pssapi *API) Receive(ctx context.Context, topic Topic) (*rpc.Subscription, ...@@ -59,7 +59,7 @@ func (pssapi *API) Receive(ctx context.Context, topic Topic) (*rpc.Subscription,
psssub := notifier.CreateSubscription() psssub := notifier.CreateSubscription()
handler := func(msg []byte, p *p2p.Peer, asymmetric bool, keyid string) error { hndlr := NewHandler(func(msg []byte, p *p2p.Peer, asymmetric bool, keyid string) error {
apimsg := &APIMsg{ apimsg := &APIMsg{
Msg: hexutil.Bytes(msg), Msg: hexutil.Bytes(msg),
Asymmetric: asymmetric, Asymmetric: asymmetric,
...@@ -69,9 +69,15 @@ func (pssapi *API) Receive(ctx context.Context, topic Topic) (*rpc.Subscription, ...@@ -69,9 +69,15 @@ func (pssapi *API) Receive(ctx context.Context, topic Topic) (*rpc.Subscription,
log.Warn(fmt.Sprintf("notification on pss sub topic rpc (sub %v) msg %v failed!", psssub.ID, msg)) log.Warn(fmt.Sprintf("notification on pss sub topic rpc (sub %v) msg %v failed!", psssub.ID, msg))
} }
return nil return nil
})
if raw {
hndlr.caps.raw = true
}
if prox {
hndlr.caps.prox = true
} }
deregf := pssapi.Register(&topic, handler) deregf := pssapi.Register(&topic, hndlr)
go func() { go func() {
defer deregf() defer deregf()
select { select {
......
...@@ -236,7 +236,7 @@ func (c *Client) RunProtocol(ctx context.Context, proto *p2p.Protocol) error { ...@@ -236,7 +236,7 @@ func (c *Client) RunProtocol(ctx context.Context, proto *p2p.Protocol) error {
topichex := topicobj.String() topichex := topicobj.String()
msgC := make(chan pss.APIMsg) msgC := make(chan pss.APIMsg)
c.peerPool[topicobj] = make(map[string]*pssRPCRW) c.peerPool[topicobj] = make(map[string]*pssRPCRW)
sub, err := c.rpc.Subscribe(ctx, "pss", msgC, "receive", topichex) sub, err := c.rpc.Subscribe(ctx, "pss", msgC, "receive", topichex, false, false)
if err != nil { if err != nil {
return fmt.Errorf("pss event subscription failed: %v", err) return fmt.Errorf("pss event subscription failed: %v", err)
} }
......
...@@ -486,7 +486,7 @@ func (api *HandshakeAPI) Handshake(pubkeyid string, topic Topic, sync bool, flus ...@@ -486,7 +486,7 @@ func (api *HandshakeAPI) Handshake(pubkeyid string, topic Topic, sync bool, flus
// Activate handshake functionality on a topic // Activate handshake functionality on a topic
func (api *HandshakeAPI) AddHandshake(topic Topic) error { func (api *HandshakeAPI) AddHandshake(topic Topic) error {
api.ctrl.deregisterFuncs[topic] = api.ctrl.pss.Register(&topic, api.ctrl.handler) api.ctrl.deregisterFuncs[topic] = api.ctrl.pss.Register(&topic, NewHandler(api.ctrl.handler))
return nil return nil
} }
......
...@@ -113,7 +113,7 @@ func NewController(ps *pss.Pss) *Controller { ...@@ -113,7 +113,7 @@ func NewController(ps *pss.Pss) *Controller {
notifiers: make(map[string]*notifier), notifiers: make(map[string]*notifier),
subscriptions: make(map[string]*subscription), subscriptions: make(map[string]*subscription),
} }
ctrl.pss.Register(&controlTopic, ctrl.Handler) ctrl.pss.Register(&controlTopic, pss.NewHandler(ctrl.Handler))
return ctrl return ctrl
} }
...@@ -336,7 +336,7 @@ func (c *Controller) handleNotifyWithKeyMsg(msg *Msg) error { ...@@ -336,7 +336,7 @@ func (c *Controller) handleNotifyWithKeyMsg(msg *Msg) error {
// \TODO keep track of and add actual address // \TODO keep track of and add actual address
updaterAddr := pss.PssAddress([]byte{}) updaterAddr := pss.PssAddress([]byte{})
c.pss.SetSymmetricKey(symkey, topic, &updaterAddr, true) c.pss.SetSymmetricKey(symkey, topic, &updaterAddr, true)
c.pss.Register(&topic, c.Handler) c.pss.Register(&topic, pss.NewHandler(c.Handler))
return c.subscriptions[msg.namestring].handler(msg.namestring, msg.Payload[:len(msg.Payload)-symKeyLength]) return c.subscriptions[msg.namestring].handler(msg.namestring, msg.Payload[:len(msg.Payload)-symKeyLength])
} }
......
...@@ -121,7 +121,7 @@ func TestStart(t *testing.T) { ...@@ -121,7 +121,7 @@ func TestStart(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
defer cancel() defer cancel()
rmsgC := make(chan *pss.APIMsg) rmsgC := make(chan *pss.APIMsg)
rightSub, err := rightRpc.Subscribe(ctx, "pss", rmsgC, "receive", controlTopic) rightSub, err := rightRpc.Subscribe(ctx, "pss", rmsgC, "receive", controlTopic, false, false)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -174,7 +174,7 @@ func TestStart(t *testing.T) { ...@@ -174,7 +174,7 @@ func TestStart(t *testing.T) {
t.Fatalf("expected payload length %d, have %d", len(updateMsg)+symKeyLength, len(dMsg.Payload)) t.Fatalf("expected payload length %d, have %d", len(updateMsg)+symKeyLength, len(dMsg.Payload))
} }
rightSubUpdate, err := rightRpc.Subscribe(ctx, "pss", rmsgC, "receive", rsrcTopic) rightSubUpdate, err := rightRpc.Subscribe(ctx, "pss", rmsgC, "receive", rsrcTopic, false, false)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
......
...@@ -92,7 +92,7 @@ func testProtocol(t *testing.T) { ...@@ -92,7 +92,7 @@ func testProtocol(t *testing.T) {
lmsgC := make(chan APIMsg) lmsgC := make(chan APIMsg)
lctx, cancel := context.WithTimeout(context.Background(), time.Second*10) lctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel() defer cancel()
lsub, err := clients[0].Subscribe(lctx, "pss", lmsgC, "receive", topic) lsub, err := clients[0].Subscribe(lctx, "pss", lmsgC, "receive", topic, false, false)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -100,7 +100,7 @@ func testProtocol(t *testing.T) { ...@@ -100,7 +100,7 @@ func testProtocol(t *testing.T) {
rmsgC := make(chan APIMsg) rmsgC := make(chan APIMsg)
rctx, cancel := context.WithTimeout(context.Background(), time.Second*10) rctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel() defer cancel()
rsub, err := clients[1].Subscribe(rctx, "pss", rmsgC, "receive", topic) rsub, err := clients[1].Subscribe(rctx, "pss", rmsgC, "receive", topic, false, false)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -130,6 +130,7 @@ func testProtocol(t *testing.T) { ...@@ -130,6 +130,7 @@ func testProtocol(t *testing.T) {
log.Debug("lnode ok") log.Debug("lnode ok")
case cerr := <-lctx.Done(): case cerr := <-lctx.Done():
t.Fatalf("test message timed out: %v", cerr) t.Fatalf("test message timed out: %v", cerr)
return
} }
select { select {
case <-rmsgC: case <-rmsgC:
......
This diff is collapsed.
This diff is collapsed.
...@@ -159,9 +159,39 @@ func (msg *PssMsg) String() string { ...@@ -159,9 +159,39 @@ func (msg *PssMsg) String() string {
} }
// Signature for a message handler function for a PssMsg // Signature for a message handler function for a PssMsg
//
// Implementations of this type are passed to Pss.Register together with a topic, // Implementations of this type are passed to Pss.Register together with a topic,
type Handler func(msg []byte, p *p2p.Peer, asymmetric bool, keyid string) error type HandlerFunc func(msg []byte, p *p2p.Peer, asymmetric bool, keyid string) error
type handlerCaps struct {
raw bool
prox bool
}
// Handler defines code to be executed upon reception of content.
type handler struct {
f HandlerFunc
caps *handlerCaps
}
// NewHandler returns a new message handler
func NewHandler(f HandlerFunc) *handler {
return &handler{
f: f,
caps: &handlerCaps{},
}
}
// WithRaw is a chainable method that allows raw messages to be handled.
func (h *handler) WithRaw() *handler {
h.caps.raw = true
return h
}
// WithProxBin is a chainable method that allows sending messages with full addresses to neighbourhoods using the kademlia depth as reference
func (h *handler) WithProxBin() *handler {
h.caps.prox = true
return h
}
// the stateStore handles saving and loading PSS peers and their corresponding keys // the stateStore handles saving and loading PSS peers and their corresponding keys
// it is currently unimplemented // it is currently unimplemented
......
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