forked from extern/smegmesh
85 lines
2.2 KiB
Go
85 lines
2.2 KiB
Go
package conn
|
|
|
|
import (
|
|
"errors"
|
|
"slices"
|
|
|
|
"github.com/tim-beatham/wgmesh/pkg/lib"
|
|
)
|
|
|
|
// ConnectionWindow maintains a sliding window of connections between users
|
|
type ConnectionWindow interface {
|
|
// GetWindow is a list of connections to choose from
|
|
GetWindow() []string
|
|
// SlideConnection removes a node from the window and adds a random node
|
|
// not already in the window. connList represents the list of possible
|
|
// connections to choose from
|
|
SlideConnection(connList []string) error
|
|
// PushConneciton is used when connection list less than window size.
|
|
PutConnection(conn []string) error
|
|
// IsFull returns true if the window is full. In which case we must slide the window
|
|
IsFull() bool
|
|
}
|
|
|
|
type ConnectionWindowImpl struct {
|
|
window []string
|
|
windowSize int
|
|
}
|
|
|
|
// GetWindow gets the current list of active connections in
|
|
// the window
|
|
func (c *ConnectionWindowImpl) GetWindow() []string {
|
|
return c.window
|
|
}
|
|
|
|
// SlideConnection slides the connection window by one shuffling items
|
|
// in the windows
|
|
func (c *ConnectionWindowImpl) SlideConnection(connList []string) error {
|
|
// If the number of peer connections is less than the length of the window
|
|
// then exit early. Can't slide the window it should contain all nodes!
|
|
if len(c.window) < c.windowSize {
|
|
return nil
|
|
}
|
|
|
|
filter := func(node string) bool {
|
|
return !slices.Contains(c.window, node)
|
|
}
|
|
|
|
pool := lib.Filter(connList, filter)
|
|
newNode := lib.RandomSubsetOfLength(pool, 1)
|
|
|
|
if len(newNode) == 0 {
|
|
return errors.New("could not slide window")
|
|
}
|
|
|
|
for i := len(c.window) - 1; i >= 1; i-- {
|
|
c.window[i] = c.window[i-1]
|
|
}
|
|
|
|
c.window[0] = newNode[0]
|
|
return nil
|
|
}
|
|
|
|
// PutConnection put random connections in the connection
|
|
func (c *ConnectionWindowImpl) PutConnection(connList []string) error {
|
|
if len(c.window) >= c.windowSize {
|
|
return errors.New("cannot place connection. Window full need to slide")
|
|
}
|
|
|
|
c.window = lib.RandomSubsetOfLength(connList, c.windowSize)
|
|
return nil
|
|
}
|
|
|
|
func (c *ConnectionWindowImpl) IsFull() bool {
|
|
return len(c.window) >= c.windowSize
|
|
}
|
|
|
|
func NewConnectionWindow(windowLength int) ConnectionWindow {
|
|
window := &ConnectionWindowImpl{
|
|
window: make([]string, 0),
|
|
windowSize: windowLength,
|
|
}
|
|
|
|
return window
|
|
}
|