mirror of https://github.com/status-im/go-waku.git
73 lines
1.9 KiB
Go
73 lines
1.9 KiB
Go
package rendezvous
|
|
|
|
import (
|
|
"context"
|
|
"math/rand"
|
|
"sort"
|
|
"time"
|
|
|
|
"github.com/multiformats/go-multiaddr"
|
|
"github.com/waku-org/go-waku/waku/v2/utils"
|
|
)
|
|
|
|
type RendezvousPointIterator struct {
|
|
rendezvousPoints []*RendezvousPoint
|
|
}
|
|
|
|
// NewRendezvousPointIterator creates an iterator with a backoff mechanism to use random rendezvous points taking into account successful/unsuccesful connection attempts
|
|
func NewRendezvousPointIterator(rendezvousPoints []multiaddr.Multiaddr) *RendezvousPointIterator {
|
|
var rendevousPoints []*RendezvousPoint
|
|
for _, rp := range rendezvousPoints {
|
|
peerID, err := utils.GetPeerID(rp)
|
|
if err == nil {
|
|
rendevousPoints = append(rendevousPoints, NewRendezvousPoint(peerID))
|
|
}
|
|
}
|
|
|
|
return &RendezvousPointIterator{
|
|
rendezvousPoints: rendevousPoints,
|
|
}
|
|
}
|
|
|
|
// RendezvousPoints returns the list of rendezvous points registered in this iterator
|
|
func (r *RendezvousPointIterator) RendezvousPoints() []*RendezvousPoint {
|
|
return r.rendezvousPoints
|
|
}
|
|
|
|
// Next will return a channel that will be triggered as soon as the next rendevous point is available to be used (depending on backoff time)
|
|
func (r *RendezvousPointIterator) Next(ctx context.Context) <-chan *RendezvousPoint {
|
|
var dialableRP []*RendezvousPoint
|
|
now := time.Now()
|
|
for _, rp := range r.rendezvousPoints {
|
|
if now.After(rp.NextTry()) {
|
|
dialableRP = append(dialableRP, rp)
|
|
}
|
|
}
|
|
|
|
result := make(chan *RendezvousPoint, 1)
|
|
|
|
if len(dialableRP) > 0 {
|
|
result <- r.rendezvousPoints[rand.Intn(len(r.rendezvousPoints))] // nolint: gosec
|
|
} else {
|
|
if len(r.rendezvousPoints) > 0 {
|
|
sort.Slice(r.rendezvousPoints, func(i, j int) bool {
|
|
return r.rendezvousPoints[i].nextTry.Before(r.rendezvousPoints[j].nextTry)
|
|
})
|
|
|
|
tryIn := r.rendezvousPoints[0].NextTry().Sub(now)
|
|
timer := time.NewTimer(tryIn)
|
|
defer timer.Stop()
|
|
|
|
select {
|
|
case <-ctx.Done():
|
|
break
|
|
case <-timer.C:
|
|
result <- r.rendezvousPoints[0]
|
|
}
|
|
}
|
|
}
|
|
|
|
close(result)
|
|
return result
|
|
}
|