forked from extern/smegmesh
81-seperate-synchronisation-into-independent
- Separated synchronisation calls into independent processes - Commented code for submission
This commit is contained in:
parent
9818645299
commit
02dfd73e08
@ -10,10 +10,8 @@ import (
|
|||||||
ctrlserver "github.com/tim-beatham/smegmesh/pkg/ctrlserver"
|
ctrlserver "github.com/tim-beatham/smegmesh/pkg/ctrlserver"
|
||||||
"github.com/tim-beatham/smegmesh/pkg/ipc"
|
"github.com/tim-beatham/smegmesh/pkg/ipc"
|
||||||
logging "github.com/tim-beatham/smegmesh/pkg/log"
|
logging "github.com/tim-beatham/smegmesh/pkg/log"
|
||||||
"github.com/tim-beatham/smegmesh/pkg/mesh"
|
|
||||||
"github.com/tim-beatham/smegmesh/pkg/robin"
|
"github.com/tim-beatham/smegmesh/pkg/robin"
|
||||||
"github.com/tim-beatham/smegmesh/pkg/sync"
|
"github.com/tim-beatham/smegmesh/pkg/sync"
|
||||||
timer "github.com/tim-beatham/smegmesh/pkg/timers"
|
|
||||||
"golang.zx2c4.com/wireguard/wgctrl"
|
"golang.zx2c4.com/wireguard/wgctrl"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -45,17 +43,12 @@ func main() {
|
|||||||
var robinRpc robin.WgRpc
|
var robinRpc robin.WgRpc
|
||||||
var robinIpc robin.IpcHandler
|
var robinIpc robin.IpcHandler
|
||||||
var syncProvider sync.SyncServiceImpl
|
var syncProvider sync.SyncServiceImpl
|
||||||
var syncRequester sync.SyncRequester
|
|
||||||
var syncer sync.Syncer
|
|
||||||
|
|
||||||
ctrlServerParams := ctrlserver.NewCtrlServerParams{
|
ctrlServerParams := ctrlserver.NewCtrlServerParams{
|
||||||
Conf: conf,
|
Conf: conf,
|
||||||
CtrlProvider: &robinRpc,
|
CtrlProvider: &robinRpc,
|
||||||
SyncProvider: &syncProvider,
|
SyncProvider: &syncProvider,
|
||||||
Client: client,
|
Client: client,
|
||||||
OnDelete: func(mp mesh.MeshProvider) {
|
|
||||||
syncer.SyncMeshes()
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctrlServer, err := ctrlserver.NewCtrlServer(&ctrlServerParams)
|
ctrlServer, err := ctrlserver.NewCtrlServer(&ctrlServerParams)
|
||||||
@ -64,11 +57,7 @@ func main() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
syncProvider.Server = ctrlServer
|
syncProvider.MeshManager = ctrlServer.MeshManager
|
||||||
syncRequester = sync.NewSyncRequester(ctrlServer)
|
|
||||||
syncer = sync.NewSyncer(ctrlServer.MeshManager, conf, syncRequester)
|
|
||||||
syncScheduler := sync.NewSyncScheduler(ctrlServer, syncRequester, syncer)
|
|
||||||
keepAlive := timer.NewTimestampScheduler(ctrlServer)
|
|
||||||
|
|
||||||
robinIpcParams := robin.RobinIpcParams{
|
robinIpcParams := robin.RobinIpcParams{
|
||||||
CtrlServer: ctrlServer,
|
CtrlServer: ctrlServer,
|
||||||
@ -82,16 +71,11 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
logging.Log.WriteInfof("Running IPC Handler")
|
logging.Log.WriteInfof("running ipc handler")
|
||||||
|
|
||||||
go ipc.RunIpcHandler(&robinIpc)
|
go ipc.RunIpcHandler(&robinIpc)
|
||||||
go syncScheduler.Run()
|
|
||||||
go keepAlive.Run()
|
|
||||||
|
|
||||||
closeResources := func() {
|
closeResources := func() {
|
||||||
logging.Log.WriteInfof("Closing resources")
|
logging.Log.WriteInfof("closing resources")
|
||||||
syncScheduler.Stop()
|
|
||||||
keepAlive.Stop()
|
|
||||||
ctrlServer.Close()
|
ctrlServer.Close()
|
||||||
client.Close()
|
client.Close()
|
||||||
}
|
}
|
||||||
|
@ -11,17 +11,7 @@ import (
|
|||||||
"github.com/tim-beatham/smegmesh/pkg/what8words"
|
"github.com/tim-beatham/smegmesh/pkg/what8words"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ApiServer interface {
|
// routesToApiRoute: convert the returned type to a JSON object
|
||||||
GetMeshes(c *gin.Context)
|
|
||||||
Run(addr string) error
|
|
||||||
}
|
|
||||||
|
|
||||||
type SmegServer struct {
|
|
||||||
router *gin.Engine
|
|
||||||
client *ipc.SmegmeshIpc
|
|
||||||
words *what8words.What8Words
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SmegServer) routeToApiRoute(meshNode ctrlserver.MeshNode) []Route {
|
func (s *SmegServer) routeToApiRoute(meshNode ctrlserver.MeshNode) []Route {
|
||||||
routes := make([]Route, len(meshNode.Routes))
|
routes := make([]Route, len(meshNode.Routes))
|
||||||
|
|
||||||
@ -40,6 +30,7 @@ func (s *SmegServer) routeToApiRoute(meshNode ctrlserver.MeshNode) []Route {
|
|||||||
return routes
|
return routes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// meshNodeToAPImeshNode: convert daemon node to a JSON node
|
||||||
func (s *SmegServer) meshNodeToAPIMeshNode(meshNode ctrlserver.MeshNode) *SmegNode {
|
func (s *SmegServer) meshNodeToAPIMeshNode(meshNode ctrlserver.MeshNode) *SmegNode {
|
||||||
if meshNode.Routes == nil {
|
if meshNode.Routes == nil {
|
||||||
meshNode.Routes = make([]ctrlserver.MeshRoute, 0)
|
meshNode.Routes = make([]ctrlserver.MeshRoute, 0)
|
||||||
@ -70,6 +61,7 @@ func (s *SmegServer) meshNodeToAPIMeshNode(meshNode ctrlserver.MeshNode) *SmegNo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// meshToAPIMesh: Convert daemon mesh network to a JSON mesh network
|
||||||
func (s *SmegServer) meshToAPIMesh(meshId string, nodes []ctrlserver.MeshNode) SmegMesh {
|
func (s *SmegServer) meshToAPIMesh(meshId string, nodes []ctrlserver.MeshNode) SmegMesh {
|
||||||
var smegMesh SmegMesh
|
var smegMesh SmegMesh
|
||||||
smegMesh.MeshId = meshId
|
smegMesh.MeshId = meshId
|
||||||
@ -175,6 +167,8 @@ func (s *SmegServer) GetMesh(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, mesh)
|
c.JSON(http.StatusOK, mesh)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetMeshes: return all the mesh networks that the
|
||||||
|
// user is a part of
|
||||||
func (s *SmegServer) GetMeshes(c *gin.Context) {
|
func (s *SmegServer) GetMeshes(c *gin.Context) {
|
||||||
listMeshesReply := new(ipc.ListMeshReply)
|
listMeshesReply := new(ipc.ListMeshReply)
|
||||||
|
|
||||||
@ -205,11 +199,14 @@ func (s *SmegServer) GetMeshes(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, meshes)
|
c.JSON(http.StatusOK, meshes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Run: run the API server
|
||||||
func (s *SmegServer) Run(addr string) error {
|
func (s *SmegServer) Run(addr string) error {
|
||||||
logging.Log.WriteInfof("Running API server")
|
logging.Log.WriteInfof("Running API server")
|
||||||
return s.router.Run(addr)
|
return s.router.Run(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewSmegServer: creates an instance of a new API server
|
||||||
|
// returns an error if something went wrong
|
||||||
func NewSmegServer(conf ApiServerConf) (ApiServer, error) {
|
func NewSmegServer(conf ApiServerConf) (ApiServer, error) {
|
||||||
client, err := ipc.NewClientIpc()
|
client, err := ipc.NewClientIpc()
|
||||||
|
|
||||||
|
@ -1,47 +1,105 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import "time"
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/tim-beatham/smegmesh/pkg/ipc"
|
||||||
|
"github.com/tim-beatham/smegmesh/pkg/what8words"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Route is an advertised route in the data store
|
||||||
type Route struct {
|
type Route struct {
|
||||||
|
// Prefix is the advertised route prefix
|
||||||
Prefix string `json:"prefix"`
|
Prefix string `json:"prefix"`
|
||||||
|
// Path is the hops the destination
|
||||||
Path []string `json:"path"`
|
Path []string `json:"path"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SmegStats is the WireGuard stats that the underlying host
|
||||||
|
// has sent to the peer
|
||||||
type SmegStats struct {
|
type SmegStats struct {
|
||||||
|
// TotalTransmit number of bytes sent to the peer
|
||||||
TotalTransmit int64 `json:"totalTransmit"`
|
TotalTransmit int64 `json:"totalTransmit"`
|
||||||
|
// TotalReceived number of bytes received from the peer
|
||||||
TotalReceived int64 `json:"totalReceived"`
|
TotalReceived int64 `json:"totalReceived"`
|
||||||
|
// KeepAliveInterval WireGuard keepalive interval that is sent to the host
|
||||||
KeepAliveInterval time.Duration `json:"keepaliveInterval"`
|
KeepAliveInterval time.Duration `json:"keepaliveInterval"`
|
||||||
|
// AllowsIps is the allowed path to the destination
|
||||||
AllowedIps []string `json:"allowedIps"`
|
AllowedIps []string `json:"allowedIps"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SmegNode is a node in the mesh network
|
||||||
type SmegNode struct {
|
type SmegNode struct {
|
||||||
|
// Alias is the human readable name that the node is assocaited with
|
||||||
Alias string `json:"alias"`
|
Alias string `json:"alias"`
|
||||||
|
// WgHost is the WireGuard IP address of the node. This is an IPv6
|
||||||
|
// address
|
||||||
WgHost string `json:"wgHost"`
|
WgHost string `json:"wgHost"`
|
||||||
|
// WgEndpoint is the physical endpoint of the host that packets
|
||||||
|
// are forwarded to
|
||||||
WgEndpoint string `json:"wgEndpoint"`
|
WgEndpoint string `json:"wgEndpoint"`
|
||||||
|
// Endpoint is the control plane endpoint of the host which
|
||||||
|
// grpc connections are to be sent along
|
||||||
Endpoint string `json:"endpoint"`
|
Endpoint string `json:"endpoint"`
|
||||||
|
// Timestamp is the last time the signified it was alive.
|
||||||
|
// if the node is the leader this is evert heartBeatInterval
|
||||||
|
// otherwise this is the time the node joined the network
|
||||||
Timestamp int `json:"timestamp"`
|
Timestamp int `json:"timestamp"`
|
||||||
|
// Description is the human readable description of the node
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
|
// PublicKey is the WireGuard public key of the node
|
||||||
PublicKey string `json:"publicKey"`
|
PublicKey string `json:"publicKey"`
|
||||||
|
// Routes is the routes that the node is advertising
|
||||||
Routes []Route `json:"routes"`
|
Routes []Route `json:"routes"`
|
||||||
|
// Services is information about services that the node offers
|
||||||
Services map[string]string `json:"services"`
|
Services map[string]string `json:"services"`
|
||||||
|
// Stats is the WireGuard stats of the node (if any)
|
||||||
Stats SmegStats `json:"stats"`
|
Stats SmegStats `json:"stats"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SmegMesh encapsulates a single mesh in the API
|
||||||
type SmegMesh struct {
|
type SmegMesh struct {
|
||||||
|
// MeshId is the mesh id of the network
|
||||||
MeshId string `json:"meshid"`
|
MeshId string `json:"meshid"`
|
||||||
|
// Nodes is the nodes in the network keyed by their public
|
||||||
|
// key
|
||||||
Nodes map[string]SmegNode `json:"nodes"`
|
Nodes map[string]SmegNode `json:"nodes"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateMeshRequest encapsulates a request to create a mesh network
|
||||||
type CreateMeshRequest struct {
|
type CreateMeshRequest struct {
|
||||||
|
// WgPort is the WireGuard to create the mesh in
|
||||||
WgPort int `json:"port" binding:"omitempty,gte=1024,lt=65535"`
|
WgPort int `json:"port" binding:"omitempty,gte=1024,lt=65535"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// JoinMeshRequests encapsulates a request to create a mesh network
|
||||||
type JoinMeshRequest struct {
|
type JoinMeshRequest struct {
|
||||||
|
// WgPort is the WireGuard port to run the service on
|
||||||
WgPort int `json:"port" binding:"omitempty,gte=1024,lt=65535"`
|
WgPort int `json:"port" binding:"omitempty,gte=1024,lt=65535"`
|
||||||
|
// Bootstrap is a bootstrap node to use to join the network
|
||||||
Bootstrap string `json:"bootstrap" binding:"required"`
|
Bootstrap string `json:"bootstrap" binding:"required"`
|
||||||
|
// MeshId is the ID of the mesh to join
|
||||||
MeshId string `json:"meshid" binding:"required"`
|
MeshId string `json:"meshid" binding:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ApiServerConf configuration to instantiate the API server
|
||||||
type ApiServerConf struct {
|
type ApiServerConf struct {
|
||||||
|
// WordsFile to use to map IP to words
|
||||||
WordsFile string
|
WordsFile string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SmegSever is the GIN api server that runs the service
|
||||||
|
type SmegServer struct {
|
||||||
|
// gin router to use
|
||||||
|
router *gin.Engine
|
||||||
|
// client to invoke operations
|
||||||
|
client *ipc.SmegmeshIpc
|
||||||
|
// what8words to use to convert IP to an alias
|
||||||
|
words *what8words.What8Words
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApiSever absrtacts the API server
|
||||||
|
type ApiServer interface {
|
||||||
|
Run(addr string) error
|
||||||
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
// automerge: package is depracated and unused. Please refer to crdt
|
||||||
|
// for crdt operations in the mesh
|
||||||
package automerge
|
package automerge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -17,18 +19,28 @@ import (
|
|||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CrdtMeshManager manages nodes in the crdt mesh
|
// CrdtMeshManager manage the CRDT datastore
|
||||||
type CrdtMeshManager struct {
|
type CrdtMeshManager struct {
|
||||||
|
// MeshID of the mesh the datastore represents
|
||||||
MeshId string
|
MeshId string
|
||||||
|
// IfName: corresponding ifName
|
||||||
IfName string
|
IfName string
|
||||||
|
// Client: corresponding wireguard control client
|
||||||
Client *wgctrl.Client
|
Client *wgctrl.Client
|
||||||
|
// doc: autommerge document
|
||||||
doc *automerge.Doc
|
doc *automerge.Doc
|
||||||
|
// LastHash: last hash that the changes were made to
|
||||||
LastHash automerge.ChangeHash
|
LastHash automerge.ChangeHash
|
||||||
|
// conf: WireGuard configuration
|
||||||
conf *conf.WgConfiguration
|
conf *conf.WgConfiguration
|
||||||
|
// cache: stored cache of the list automerge document
|
||||||
|
// so that the store does not have to be repopulated each time
|
||||||
cache *MeshCrdt
|
cache *MeshCrdt
|
||||||
|
// lastCachehash: hash of when the document was last changed
|
||||||
lastCacheHash automerge.ChangeHash
|
lastCacheHash automerge.ChangeHash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddNode as a node to the datastore
|
||||||
func (c *CrdtMeshManager) AddNode(node mesh.MeshNode) {
|
func (c *CrdtMeshManager) AddNode(node mesh.MeshNode) {
|
||||||
crdt, ok := node.(*MeshNodeCrdt)
|
crdt, ok := node.(*MeshNodeCrdt)
|
||||||
|
|
||||||
@ -47,6 +59,7 @@ func (c *CrdtMeshManager) AddNode(node mesh.MeshNode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isPeer: returns true if the given node has type peer
|
||||||
func (c *CrdtMeshManager) isPeer(nodeId string) bool {
|
func (c *CrdtMeshManager) isPeer(nodeId string) bool {
|
||||||
node, err := c.doc.Path("nodes").Map().Get(nodeId)
|
node, err := c.doc.Path("nodes").Map().Get(nodeId)
|
||||||
|
|
||||||
@ -64,7 +77,8 @@ func (c *CrdtMeshManager) isPeer(nodeId string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// isAlive: checks that the node's configuration has been updated
|
// isAlive: checks that the node's configuration has been updated
|
||||||
// since the rquired keep alive time
|
// since the rquired keep alive time. Depracated no longer works
|
||||||
|
// due to changes in approach
|
||||||
func (c *CrdtMeshManager) isAlive(nodeId string) bool {
|
func (c *CrdtMeshManager) isAlive(nodeId string) bool {
|
||||||
node, err := c.doc.Path("nodes").Map().Get(nodeId)
|
node, err := c.doc.Path("nodes").Map().Get(nodeId)
|
||||||
|
|
||||||
@ -78,10 +92,11 @@ func (c *CrdtMeshManager) isAlive(nodeId string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
|
||||||
// return (time.Now().Unix() - keepAliveTime) < int64(c.conf.DeadTime)
|
// return (time.Now().Unix() - keepAliveTime) < int64(c.conf.DeadTime)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPeers: get all the peers in the mesh
|
||||||
func (c *CrdtMeshManager) GetPeers() []string {
|
func (c *CrdtMeshManager) GetPeers() []string {
|
||||||
keys, _ := c.doc.Path("nodes").Map().Keys()
|
keys, _ := c.doc.Path("nodes").Map().Keys()
|
||||||
|
|
||||||
@ -92,7 +107,7 @@ func (c *CrdtMeshManager) GetPeers() []string {
|
|||||||
return keys
|
return keys
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMesh(): Converts the document into a struct
|
// GetMesh: Converts the document into a mesh network
|
||||||
func (c *CrdtMeshManager) GetMesh() (mesh.MeshSnapshot, error) {
|
func (c *CrdtMeshManager) GetMesh() (mesh.MeshSnapshot, error) {
|
||||||
changes, err := c.doc.Changes(c.lastCacheHash)
|
changes, err := c.doc.Changes(c.lastCacheHash)
|
||||||
|
|
||||||
@ -114,7 +129,7 @@ func (c *CrdtMeshManager) GetMesh() (mesh.MeshSnapshot, error) {
|
|||||||
return c.cache, nil
|
return c.cache, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMeshId returns the meshid of the mesh
|
// GetMeshId: returns the meshid of the mesh
|
||||||
func (c *CrdtMeshManager) GetMeshId() string {
|
func (c *CrdtMeshManager) GetMeshId() string {
|
||||||
return c.MeshId
|
return c.MeshId
|
||||||
}
|
}
|
||||||
@ -135,6 +150,8 @@ func (c *CrdtMeshManager) Load(bytes []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewCrdtNodeManagerParams: params to instantiate a new automerge
|
||||||
|
// datastore
|
||||||
type NewCrdtNodeMangerParams struct {
|
type NewCrdtNodeMangerParams struct {
|
||||||
MeshId string
|
MeshId string
|
||||||
DevName string
|
DevName string
|
||||||
@ -143,7 +160,7 @@ type NewCrdtNodeMangerParams struct {
|
|||||||
Client *wgctrl.Client
|
Client *wgctrl.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCrdtNodeManager: Create a new crdt node manager
|
// NewCrdtNodeManager: Create a new automerge crdt data store
|
||||||
func NewCrdtNodeManager(params *NewCrdtNodeMangerParams) (*CrdtMeshManager, error) {
|
func NewCrdtNodeManager(params *NewCrdtNodeMangerParams) (*CrdtMeshManager, error) {
|
||||||
var manager CrdtMeshManager
|
var manager CrdtMeshManager
|
||||||
manager.MeshId = params.MeshId
|
manager.MeshId = params.MeshId
|
||||||
@ -155,12 +172,13 @@ func NewCrdtNodeManager(params *NewCrdtNodeMangerParams) (*CrdtMeshManager, erro
|
|||||||
return &manager, nil
|
return &manager, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NodeExists: returns true if the node exists. Returns false
|
// NodeExists: returns true if the node exists other returns false
|
||||||
func (m *CrdtMeshManager) NodeExists(key string) bool {
|
func (m *CrdtMeshManager) NodeExists(key string) bool {
|
||||||
node, err := m.doc.Path("nodes").Map().Get(key)
|
node, err := m.doc.Path("nodes").Map().Get(key)
|
||||||
return node.Kind() == automerge.KindMap && err == nil
|
return node.Kind() == automerge.KindMap && err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetNode: gets a node from the mesh network.
|
||||||
func (m *CrdtMeshManager) GetNode(endpoint string) (mesh.MeshNode, error) {
|
func (m *CrdtMeshManager) GetNode(endpoint string) (mesh.MeshNode, error) {
|
||||||
node, err := m.doc.Path("nodes").Map().Get(endpoint)
|
node, err := m.doc.Path("nodes").Map().Get(endpoint)
|
||||||
|
|
||||||
@ -181,10 +199,12 @@ func (m *CrdtMeshManager) GetNode(endpoint string) (mesh.MeshNode, error) {
|
|||||||
return meshNode, nil
|
return meshNode, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Length: returns the number of nodes in the store
|
||||||
func (m *CrdtMeshManager) Length() int {
|
func (m *CrdtMeshManager) Length() int {
|
||||||
return m.doc.Path("nodes").Map().Len()
|
return m.doc.Path("nodes").Map().Len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDevice: get the underlying WireGuard device
|
||||||
func (m *CrdtMeshManager) GetDevice() (*wgtypes.Device, error) {
|
func (m *CrdtMeshManager) GetDevice() (*wgtypes.Device, error) {
|
||||||
dev, err := m.Client.Device(m.IfName)
|
dev, err := m.Client.Device(m.IfName)
|
||||||
|
|
||||||
@ -195,7 +215,7 @@ func (m *CrdtMeshManager) GetDevice() (*wgtypes.Device, error) {
|
|||||||
return dev, nil
|
return dev, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasChanges returns true if we have changes since the last time we synced
|
// HasChanges: returns true if there are changes since last time synchronised
|
||||||
func (m *CrdtMeshManager) HasChanges() bool {
|
func (m *CrdtMeshManager) HasChanges() bool {
|
||||||
changes, err := m.doc.Changes(m.LastHash)
|
changes, err := m.doc.Changes(m.LastHash)
|
||||||
|
|
||||||
@ -209,6 +229,7 @@ func (m *CrdtMeshManager) HasChanges() bool {
|
|||||||
return len(changes) > 0
|
return len(changes) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SaveChanges: save changes to the datastore
|
||||||
func (m *CrdtMeshManager) SaveChanges() {
|
func (m *CrdtMeshManager) SaveChanges() {
|
||||||
hashes := m.doc.Heads()
|
hashes := m.doc.Heads()
|
||||||
hash := hashes[len(hashes)-1]
|
hash := hashes[len(hashes)-1]
|
||||||
@ -217,6 +238,7 @@ func (m *CrdtMeshManager) SaveChanges() {
|
|||||||
m.LastHash = hash
|
m.LastHash = hash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateTimeStamp: updates the timestamp of the document
|
||||||
func (m *CrdtMeshManager) UpdateTimeStamp(nodeId string) error {
|
func (m *CrdtMeshManager) UpdateTimeStamp(nodeId string) error {
|
||||||
node, err := m.doc.Path("nodes").Map().Get(nodeId)
|
node, err := m.doc.Path("nodes").Map().Get(nodeId)
|
||||||
|
|
||||||
@ -237,6 +259,7 @@ func (m *CrdtMeshManager) UpdateTimeStamp(nodeId string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetDescription: set the description of the given node
|
||||||
func (m *CrdtMeshManager) SetDescription(nodeId string, description string) error {
|
func (m *CrdtMeshManager) SetDescription(nodeId string, description string) error {
|
||||||
node, err := m.doc.Path("nodes").Map().Get(nodeId)
|
node, err := m.doc.Path("nodes").Map().Get(nodeId)
|
||||||
|
|
||||||
@ -257,6 +280,7 @@ func (m *CrdtMeshManager) SetDescription(nodeId string, description string) erro
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetAlias: set the alias of the given node
|
||||||
func (m *CrdtMeshManager) SetAlias(nodeId string, alias string) error {
|
func (m *CrdtMeshManager) SetAlias(nodeId string, alias string) error {
|
||||||
node, err := m.doc.Path("nodes").Map().Get(nodeId)
|
node, err := m.doc.Path("nodes").Map().Get(nodeId)
|
||||||
|
|
||||||
@ -277,6 +301,7 @@ func (m *CrdtMeshManager) SetAlias(nodeId string, alias string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddService: add a service to the given node
|
||||||
func (m *CrdtMeshManager) AddService(nodeId, key, value string) error {
|
func (m *CrdtMeshManager) AddService(nodeId, key, value string) error {
|
||||||
node, err := m.doc.Path("nodes").Map().Get(nodeId)
|
node, err := m.doc.Path("nodes").Map().Get(nodeId)
|
||||||
|
|
||||||
@ -298,6 +323,7 @@ func (m *CrdtMeshManager) AddService(nodeId, key, value string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemoveService: remove a service from a node
|
||||||
func (m *CrdtMeshManager) RemoveService(nodeId, key string) error {
|
func (m *CrdtMeshManager) RemoveService(nodeId, key string) error {
|
||||||
node, err := m.doc.Path("nodes").Map().Get(nodeId)
|
node, err := m.doc.Path("nodes").Map().Get(nodeId)
|
||||||
|
|
||||||
@ -378,6 +404,7 @@ func (m *CrdtMeshManager) AddRoutes(nodeId string, routes ...mesh.Route) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getRoutes: get the routes that the given node is directly advertising
|
||||||
func (m *CrdtMeshManager) getRoutes(nodeId string) ([]Route, error) {
|
func (m *CrdtMeshManager) getRoutes(nodeId string) ([]Route, error) {
|
||||||
nodeVal, err := m.doc.Path("nodes").Map().Get(nodeId)
|
nodeVal, err := m.doc.Path("nodes").Map().Get(nodeId)
|
||||||
|
|
||||||
@ -404,6 +431,8 @@ func (m *CrdtMeshManager) getRoutes(nodeId string) ([]Route, error) {
|
|||||||
return lib.MapValues(routes), err
|
return lib.MapValues(routes), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetRoutes: get all the routes that the node can see. The routes that the node
|
||||||
|
// can say may not be direct but cann also be indirect
|
||||||
func (m *CrdtMeshManager) GetRoutes(targetNode string) (map[string]mesh.Route, error) {
|
func (m *CrdtMeshManager) GetRoutes(targetNode string) (map[string]mesh.Route, error) {
|
||||||
node, err := m.GetNode(targetNode)
|
node, err := m.GetNode(targetNode)
|
||||||
|
|
||||||
@ -447,12 +476,13 @@ func (m *CrdtMeshManager) GetRoutes(targetNode string) (map[string]mesh.Route, e
|
|||||||
return routes, nil
|
return routes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemoveNode: removes a node from the datastore
|
||||||
func (m *CrdtMeshManager) RemoveNode(nodeId string) error {
|
func (m *CrdtMeshManager) RemoveNode(nodeId string) error {
|
||||||
err := m.doc.Path("nodes").Map().Delete(nodeId)
|
err := m.doc.Path("nodes").Map().Delete(nodeId)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteRoutes deletes the specified routes
|
// RemoveRoutes: withdraw all the routes the nodeID is advertising
|
||||||
func (m *CrdtMeshManager) RemoveRoutes(nodeId string, routes ...mesh.Route) error {
|
func (m *CrdtMeshManager) RemoveRoutes(nodeId string, routes ...mesh.Route) error {
|
||||||
nodeVal, err := m.doc.Path("nodes").Map().Get(nodeId)
|
nodeVal, err := m.doc.Path("nodes").Map().Get(nodeId)
|
||||||
|
|
||||||
@ -486,30 +516,37 @@ func (m *CrdtMeshManager) GetConfiguration() *conf.WgConfiguration {
|
|||||||
func (m *CrdtMeshManager) Mark(nodeId string) {
|
func (m *CrdtMeshManager) Mark(nodeId string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetSyncer: get the bi-directionally syncer to synchronise the document
|
||||||
func (m *CrdtMeshManager) GetSyncer() mesh.MeshSyncer {
|
func (m *CrdtMeshManager) GetSyncer() mesh.MeshSyncer {
|
||||||
return NewAutomergeSync(m)
|
return NewAutomergeSync(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prune: prune all dead nodes
|
||||||
func (m *CrdtMeshManager) Prune() error {
|
func (m *CrdtMeshManager) Prune() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compare: compare two mesh node for equality
|
||||||
func (m1 *MeshNodeCrdt) Compare(m2 *MeshNodeCrdt) int {
|
func (m1 *MeshNodeCrdt) Compare(m2 *MeshNodeCrdt) int {
|
||||||
return strings.Compare(m1.PublicKey, m2.PublicKey)
|
return strings.Compare(m1.PublicKey, m2.PublicKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetHostEndpoint: get the ctrl endpoint of the host
|
||||||
func (m *MeshNodeCrdt) GetHostEndpoint() string {
|
func (m *MeshNodeCrdt) GetHostEndpoint() string {
|
||||||
return m.HostEndpoint
|
return m.HostEndpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPublicKey: get the public key of the node
|
||||||
func (m *MeshNodeCrdt) GetPublicKey() (wgtypes.Key, error) {
|
func (m *MeshNodeCrdt) GetPublicKey() (wgtypes.Key, error) {
|
||||||
return wgtypes.ParseKey(m.PublicKey)
|
return wgtypes.ParseKey(m.PublicKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetWgEndpoint: get the outer WireGuard endpoint
|
||||||
func (m *MeshNodeCrdt) GetWgEndpoint() string {
|
func (m *MeshNodeCrdt) GetWgEndpoint() string {
|
||||||
return m.WgEndpoint
|
return m.WgEndpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetWgHost: get the WireGuard IP address of the host
|
||||||
func (m *MeshNodeCrdt) GetWgHost() *net.IPNet {
|
func (m *MeshNodeCrdt) GetWgHost() *net.IPNet {
|
||||||
_, ipnet, err := net.ParseCIDR(m.WgHost)
|
_, ipnet, err := net.ParseCIDR(m.WgHost)
|
||||||
|
|
||||||
@ -520,10 +557,12 @@ func (m *MeshNodeCrdt) GetWgHost() *net.IPNet {
|
|||||||
return ipnet
|
return ipnet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTimeStamp: get timestamp if when the node was last updated
|
||||||
func (m *MeshNodeCrdt) GetTimeStamp() int64 {
|
func (m *MeshNodeCrdt) GetTimeStamp() int64 {
|
||||||
return m.Timestamp
|
return m.Timestamp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetRoutes: get all the routes advertised by the node
|
||||||
func (m *MeshNodeCrdt) GetRoutes() []mesh.Route {
|
func (m *MeshNodeCrdt) GetRoutes() []mesh.Route {
|
||||||
return lib.Map(lib.MapValues(m.Routes), func(r Route) mesh.Route {
|
return lib.Map(lib.MapValues(m.Routes), func(r Route) mesh.Route {
|
||||||
return &Route{
|
return &Route{
|
||||||
@ -533,10 +572,12 @@ func (m *MeshNodeCrdt) GetRoutes() []mesh.Route {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDescription: get the description of the node
|
||||||
func (m *MeshNodeCrdt) GetDescription() string {
|
func (m *MeshNodeCrdt) GetDescription() string {
|
||||||
return m.Description
|
return m.Description
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetIdentifier: get the iderntifier section of the ipv6 address
|
||||||
func (m *MeshNodeCrdt) GetIdentifier() string {
|
func (m *MeshNodeCrdt) GetIdentifier() string {
|
||||||
ipv6 := m.WgHost[:len(m.WgHost)-4]
|
ipv6 := m.WgHost[:len(m.WgHost)-4]
|
||||||
|
|
||||||
@ -545,10 +586,12 @@ func (m *MeshNodeCrdt) GetIdentifier() string {
|
|||||||
return strings.Join(constituents, ":")
|
return strings.Join(constituents, ":")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAlias: get the alias of the node
|
||||||
func (m *MeshNodeCrdt) GetAlias() string {
|
func (m *MeshNodeCrdt) GetAlias() string {
|
||||||
return m.Alias
|
return m.Alias
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetServices: get all the services the node is advertising
|
||||||
func (m *MeshNodeCrdt) GetServices() map[string]string {
|
func (m *MeshNodeCrdt) GetServices() map[string]string {
|
||||||
services := make(map[string]string)
|
services := make(map[string]string)
|
||||||
|
|
||||||
@ -565,6 +608,7 @@ func (n *MeshNodeCrdt) GetType() conf.NodeType {
|
|||||||
return conf.NodeType(n.Type)
|
return conf.NodeType(n.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetNodes: get all the nodes in the network
|
||||||
func (m *MeshCrdt) GetNodes() map[string]mesh.MeshNode {
|
func (m *MeshCrdt) GetNodes() map[string]mesh.MeshNode {
|
||||||
nodes := make(map[string]mesh.MeshNode)
|
nodes := make(map[string]mesh.MeshNode)
|
||||||
|
|
||||||
@ -586,15 +630,18 @@ func (m *MeshCrdt) GetNodes() map[string]mesh.MeshNode {
|
|||||||
return nodes
|
return nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDestination: get destination of the route
|
||||||
func (r *Route) GetDestination() *net.IPNet {
|
func (r *Route) GetDestination() *net.IPNet {
|
||||||
_, ipnet, _ := net.ParseCIDR(r.Destination)
|
_, ipnet, _ := net.ParseCIDR(r.Destination)
|
||||||
return ipnet
|
return ipnet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetHopCount: get the number of hops to the destination
|
||||||
func (r *Route) GetHopCount() int {
|
func (r *Route) GetHopCount() int {
|
||||||
return len(r.Path)
|
return len(r.Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPath: get the total path which includes the number of hops
|
||||||
func (r *Route) GetPath() []string {
|
func (r *Route) GetPath() []string {
|
||||||
return r.Path
|
return r.Path
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
// automerge: automerge is a CRDT library. Defines a CRDT
|
||||||
|
// datastore and methods to resolve conflicts
|
||||||
package automerge
|
package automerge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -5,11 +7,18 @@ import (
|
|||||||
logging "github.com/tim-beatham/smegmesh/pkg/log"
|
logging "github.com/tim-beatham/smegmesh/pkg/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// AutomergeSync: defines a synchroniser to bi-directionally synchronise the
|
||||||
|
// two states
|
||||||
type AutomergeSync struct {
|
type AutomergeSync struct {
|
||||||
|
// state: the automerge sync state to use
|
||||||
state *automerge.SyncState
|
state *automerge.SyncState
|
||||||
|
// manager: the corresponding data store that we are merging
|
||||||
manager *CrdtMeshManager
|
manager *CrdtMeshManager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenerateMessage: geenrate a new automerge message to synchronise
|
||||||
|
// returns a byte of the message and a boolean of whether or not there
|
||||||
|
// are more messages in the sequence
|
||||||
func (a *AutomergeSync) GenerateMessage() ([]byte, bool) {
|
func (a *AutomergeSync) GenerateMessage() ([]byte, bool) {
|
||||||
msg, valid := a.state.GenerateMessage()
|
msg, valid := a.state.GenerateMessage()
|
||||||
|
|
||||||
@ -20,6 +29,8 @@ func (a *AutomergeSync) GenerateMessage() ([]byte, bool) {
|
|||||||
return msg.Bytes(), true
|
return msg.Bytes(), true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RecvMessage: receive an automerge message to merge in the datastore
|
||||||
|
// returns an error if unsuccessful
|
||||||
func (a *AutomergeSync) RecvMessage(msg []byte) error {
|
func (a *AutomergeSync) RecvMessage(msg []byte) error {
|
||||||
_, err := a.state.ReceiveMessage(msg)
|
_, err := a.state.ReceiveMessage(msg)
|
||||||
|
|
||||||
@ -30,11 +41,13 @@ func (a *AutomergeSync) RecvMessage(msg []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Complete: complete the synchronisation process
|
||||||
func (a *AutomergeSync) Complete() {
|
func (a *AutomergeSync) Complete() {
|
||||||
logging.Log.WriteInfof("Sync Completed")
|
logging.Log.WriteInfof("sync completed")
|
||||||
a.manager.SaveChanges()
|
a.manager.SaveChanges()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewAutomergeSync: instantiates a new automerge syncer
|
||||||
func NewAutomergeSync(manager *CrdtMeshManager) *AutomergeSync {
|
func NewAutomergeSync(manager *CrdtMeshManager) *AutomergeSync {
|
||||||
return &AutomergeSync{
|
return &AutomergeSync{
|
||||||
state: automerge.NewSyncState(manager.doc),
|
state: automerge.NewSyncState(manager.doc),
|
||||||
|
@ -8,8 +8,11 @@ import (
|
|||||||
"github.com/tim-beatham/smegmesh/pkg/mesh"
|
"github.com/tim-beatham/smegmesh/pkg/mesh"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// CrdtProviderFactory: abstracts the instantiation of an automerge
|
||||||
|
// datastore
|
||||||
type CrdtProviderFactory struct{}
|
type CrdtProviderFactory struct{}
|
||||||
|
|
||||||
|
// CreateMesh: create a new mesh datastore
|
||||||
func (f *CrdtProviderFactory) CreateMesh(params *mesh.MeshProviderFactoryParams) (mesh.MeshProvider, error) {
|
func (f *CrdtProviderFactory) CreateMesh(params *mesh.MeshProviderFactoryParams) (mesh.MeshProvider, error) {
|
||||||
return NewCrdtNodeManager(&NewCrdtNodeMangerParams{
|
return NewCrdtNodeManager(&NewCrdtNodeMangerParams{
|
||||||
MeshId: params.MeshId,
|
MeshId: params.MeshId,
|
||||||
@ -19,11 +22,12 @@ func (f *CrdtProviderFactory) CreateMesh(params *mesh.MeshProviderFactoryParams)
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MeshNodeFactory: abstracts the instnatiation of a node
|
||||||
type MeshNodeFactory struct {
|
type MeshNodeFactory struct {
|
||||||
Config conf.DaemonConfiguration
|
Config conf.DaemonConfiguration
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build builds the mesh node that represents the host machine to add
|
// Build: builds the mesh node that represents the host machine to add
|
||||||
// to the mesh
|
// to the mesh
|
||||||
func (f *MeshNodeFactory) Build(params *mesh.MeshNodeFactoryParams) mesh.MeshNode {
|
func (f *MeshNodeFactory) Build(params *mesh.MeshNodeFactoryParams) mesh.MeshNode {
|
||||||
hostName := f.getAddress(params)
|
hostName := f.getAddress(params)
|
||||||
@ -48,7 +52,7 @@ func (f *MeshNodeFactory) Build(params *mesh.MeshNodeFactoryParams) mesh.MeshNod
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// getAddress returns the routable address of the machine.
|
// getAddress: returns the routable address of the machine.
|
||||||
func (f *MeshNodeFactory) getAddress(params *mesh.MeshNodeFactoryParams) string {
|
func (f *MeshNodeFactory) getAddress(params *mesh.MeshNodeFactoryParams) string {
|
||||||
var hostName string = ""
|
var hostName string = ""
|
||||||
|
|
||||||
|
@ -6,10 +6,12 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// CmdRunner: run cmd commands when instantiating a network
|
||||||
type CmdRunner interface {
|
type CmdRunner interface {
|
||||||
RunCommands(commands ...string) error
|
RunCommands(commands ...string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnixCmdRunner: Run UNIX commands
|
||||||
type UnixCmdRunner struct{}
|
type UnixCmdRunner struct{}
|
||||||
|
|
||||||
// RunCommand: runs the unix command. It splits the command into fields
|
// RunCommand: runs the unix command. It splits the command into fields
|
||||||
@ -20,6 +22,7 @@ func RunCommand(cmd string) error {
|
|||||||
return c.Run()
|
return c.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RunCommands: run a series of commands
|
||||||
func (l *UnixCmdRunner) RunCommands(commands ...string) error {
|
func (l *UnixCmdRunner) RunCommands(commands ...string) error {
|
||||||
for _, cmd := range commands {
|
for _, cmd := range commands {
|
||||||
err := RunCommand(cmd)
|
err := RunCommand(cmd)
|
||||||
|
@ -7,17 +7,21 @@ import (
|
|||||||
"slices"
|
"slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ConnCluster splits nodes into clusters where nodes in a cluster communicate
|
// ConnCluster: splits nodes into clusters where nodes in a cluster communicate
|
||||||
// frequently and nodes outside of a cluster communicate infrequently
|
// frequently and nodes outside of a cluster communicate infrequently
|
||||||
type ConnCluster interface {
|
type ConnCluster interface {
|
||||||
|
// Getneighbours: get neighbours of the cluster the node is in
|
||||||
GetNeighbours(global []string, selfId string) []string
|
GetNeighbours(global []string, selfId string) []string
|
||||||
|
// GetInterCluster: get the cluster to communicate with
|
||||||
GetInterCluster(global []string, selfId string) string
|
GetInterCluster(global []string, selfId string) string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConnnClusterImpl: implementation of the connection cluster
|
||||||
type ConnClusterImpl struct {
|
type ConnClusterImpl struct {
|
||||||
clusterSize int
|
clusterSize int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// perform binary search to attain a size of a group
|
||||||
func binarySearch(global []string, selfId string, groupSize int) (int, int) {
|
func binarySearch(global []string, selfId string, groupSize int) (int, int) {
|
||||||
slices.Sort(global)
|
slices.Sort(global)
|
||||||
|
|
||||||
@ -39,7 +43,7 @@ func binarySearch(global []string, selfId string, groupSize int) (int, int) {
|
|||||||
return lower, int(math.Min(float64(lower+groupSize), float64(len(global))))
|
return lower, int(math.Min(float64(lower+groupSize), float64(len(global))))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNeighbours return the neighbours 'nearest' to you. In this implementation the
|
// GetNeighbours: return the neighbours 'nearest' to you. In this implementation the
|
||||||
// neighbours aren't actually the ones nearest to you but just the ones nearest
|
// neighbours aren't actually the ones nearest to you but just the ones nearest
|
||||||
// to you alphabetically. Perform binary search to get the total group
|
// to you alphabetically. Perform binary search to get the total group
|
||||||
func (i *ConnClusterImpl) GetNeighbours(global []string, selfId string) []string {
|
func (i *ConnClusterImpl) GetNeighbours(global []string, selfId string) []string {
|
||||||
@ -50,7 +54,7 @@ func (i *ConnClusterImpl) GetNeighbours(global []string, selfId string) []string
|
|||||||
return global[lower:higher]
|
return global[lower:higher]
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetInterCluster get nodes not in your cluster. Every round there is a given chance
|
// GetInterCluster: get nodes not in your cluster. Every round there is a given chance
|
||||||
// you will communicate with a random node that is not in your cluster.
|
// you will communicate with a random node that is not in your cluster.
|
||||||
func (i *ConnClusterImpl) GetInterCluster(global []string, selfId string) string {
|
func (i *ConnClusterImpl) GetInterCluster(global []string, selfId string) string {
|
||||||
// Doesn't matter if not in it. Get index of where the node 'should' be
|
// Doesn't matter if not in it. Get index of where the node 'should' be
|
||||||
@ -65,6 +69,7 @@ func (i *ConnClusterImpl) GetInterCluster(global []string, selfId string) string
|
|||||||
return global[neighbourIndex]
|
return global[neighbourIndex]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewConnCluster: instantiate a new connection cluster of a given group size.
|
||||||
func NewConnCluster(clusterSize int) (ConnCluster, error) {
|
func NewConnCluster(clusterSize int) (ConnCluster, error) {
|
||||||
log2Cluster := math.Log2(float64(clusterSize))
|
log2Cluster := math.Log2(float64(clusterSize))
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ type PeerConnection interface {
|
|||||||
GetClient() (*grpc.ClientConn, error)
|
GetClient() (*grpc.ClientConn, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PeerConenctionFactory: create a new connection to a peer
|
||||||
type PeerConnectionFactory = func(clientConfig *tls.Config, server string) (PeerConnection, error)
|
type PeerConnectionFactory = func(clientConfig *tls.Config, server string) (PeerConnection, error)
|
||||||
|
|
||||||
// WgCtrlConnection implements PeerConnection.
|
// WgCtrlConnection implements PeerConnection.
|
||||||
|
@ -17,8 +17,11 @@ import (
|
|||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Route: represents a route within the data store
|
||||||
type Route struct {
|
type Route struct {
|
||||||
|
// Destination the route is advertising
|
||||||
Destination string
|
Destination string
|
||||||
|
// Path to the destination
|
||||||
Path []string
|
Path []string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,7 +251,8 @@ func (m *TwoPhaseStoreMeshManager) SaveChanges() {
|
|||||||
m.LastClock = clockValue
|
m.LastClock = clockValue
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateTimeStamp: update the timestamp of the given node
|
// UpdateTimeStamp: update the timestamp of the given node, causes a configuration refresh if the node
|
||||||
|
// is the leader causing all nodes to update their vector clocks
|
||||||
func (m *TwoPhaseStoreMeshManager) UpdateTimeStamp(nodeId string) error {
|
func (m *TwoPhaseStoreMeshManager) UpdateTimeStamp(nodeId string) error {
|
||||||
if !m.store.Contains(nodeId) {
|
if !m.store.Contains(nodeId) {
|
||||||
return fmt.Errorf("datastore: %s does not exist in the mesh", nodeId)
|
return fmt.Errorf("datastore: %s does not exist in the mesh", nodeId)
|
||||||
@ -312,6 +316,8 @@ func (m *TwoPhaseStoreMeshManager) AddRoutes(nodeId string, routes ...mesh.Route
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only add nodes on changes. Otherwise the node will advertise new
|
||||||
|
// information whenever they get new routes
|
||||||
if changes {
|
if changes {
|
||||||
m.store.Put(nodeId, node)
|
m.store.Put(nodeId, node)
|
||||||
}
|
}
|
||||||
@ -319,7 +325,7 @@ func (m *TwoPhaseStoreMeshManager) AddRoutes(nodeId string, routes ...mesh.Route
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteRoutes: deletes the routes from the node
|
// RemoveRoute: deletes the routes from the given node
|
||||||
func (m *TwoPhaseStoreMeshManager) RemoveRoutes(nodeId string, routes ...mesh.Route) error {
|
func (m *TwoPhaseStoreMeshManager) RemoveRoutes(nodeId string, routes ...mesh.Route) error {
|
||||||
if !m.store.Contains(nodeId) {
|
if !m.store.Contains(nodeId) {
|
||||||
return fmt.Errorf("datastore: %s does not exist in the mesh", nodeId)
|
return fmt.Errorf("datastore: %s does not exist in the mesh", nodeId)
|
||||||
@ -345,12 +351,12 @@ func (m *TwoPhaseStoreMeshManager) RemoveRoutes(nodeId string, routes ...mesh.Ro
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSyncer: returns the automerge syncer for sync
|
// GetSyncer: returns the bi-directionally synchroniser to merge documents
|
||||||
func (m *TwoPhaseStoreMeshManager) GetSyncer() mesh.MeshSyncer {
|
func (m *TwoPhaseStoreMeshManager) GetSyncer() mesh.MeshSyncer {
|
||||||
return NewTwoPhaseSyncer(m)
|
return NewTwoPhaseSyncer(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNode get a particular not within the mesh
|
// GetNode: get a particular not within the mesh network
|
||||||
func (m *TwoPhaseStoreMeshManager) GetNode(nodeId string) (mesh.MeshNode, error) {
|
func (m *TwoPhaseStoreMeshManager) GetNode(nodeId string) (mesh.MeshNode, error) {
|
||||||
if !m.store.Contains(nodeId) {
|
if !m.store.Contains(nodeId) {
|
||||||
return nil, fmt.Errorf("datastore: %s does not exist in the mesh", nodeId)
|
return nil, fmt.Errorf("datastore: %s does not exist in the mesh", nodeId)
|
||||||
@ -378,7 +384,7 @@ func (m *TwoPhaseStoreMeshManager) SetDescription(nodeId string, description str
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetAlias: set the alias of the nodeId
|
// SetAlias: set the alias of the given node
|
||||||
func (m *TwoPhaseStoreMeshManager) SetAlias(nodeId string, alias string) error {
|
func (m *TwoPhaseStoreMeshManager) SetAlias(nodeId string, alias string) error {
|
||||||
if !m.store.Contains(nodeId) {
|
if !m.store.Contains(nodeId) {
|
||||||
return fmt.Errorf("datastore: %s does not exist in the mesh", nodeId)
|
return fmt.Errorf("datastore: %s does not exist in the mesh", nodeId)
|
||||||
@ -391,7 +397,7 @@ func (m *TwoPhaseStoreMeshManager) SetAlias(nodeId string, alias string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddService: adds the service to the given node
|
// AddService: adds a service to the given node
|
||||||
func (m *TwoPhaseStoreMeshManager) AddService(nodeId string, key string, value string) error {
|
func (m *TwoPhaseStoreMeshManager) AddService(nodeId string, key string, value string) error {
|
||||||
if !m.store.Contains(nodeId) {
|
if !m.store.Contains(nodeId) {
|
||||||
return fmt.Errorf("datastore: %s does not exist in the mesh", nodeId)
|
return fmt.Errorf("datastore: %s does not exist in the mesh", nodeId)
|
||||||
@ -403,7 +409,7 @@ func (m *TwoPhaseStoreMeshManager) AddService(nodeId string, key string, value s
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveService: removes the service form the node. throws an error if the service does not exist
|
// RemoveService: removes the service form a node, throws an error if the service does not exist
|
||||||
func (m *TwoPhaseStoreMeshManager) RemoveService(nodeId string, key string) error {
|
func (m *TwoPhaseStoreMeshManager) RemoveService(nodeId string, key string) error {
|
||||||
if !m.store.Contains(nodeId) {
|
if !m.store.Contains(nodeId) {
|
||||||
return fmt.Errorf("datastore: %s does not exist in the mesh", nodeId)
|
return fmt.Errorf("datastore: %s does not exist in the mesh", nodeId)
|
||||||
@ -420,7 +426,8 @@ func (m *TwoPhaseStoreMeshManager) RemoveService(nodeId string, key string) erro
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prune: prunes all nodes that have not updated their timestamp in
|
// Prune: prunes all nodes that have not updated their vector clock in a given amount
|
||||||
|
// of time
|
||||||
func (m *TwoPhaseStoreMeshManager) Prune() error {
|
func (m *TwoPhaseStoreMeshManager) Prune() error {
|
||||||
m.store.Prune()
|
m.store.Prune()
|
||||||
return nil
|
return nil
|
||||||
@ -449,6 +456,7 @@ func (m *TwoPhaseStoreMeshManager) GetPeers() []string {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getRoutes: get all routes the target node is advertising
|
||||||
func (m *TwoPhaseStoreMeshManager) getRoutes(targetNode string) (map[string]Route, error) {
|
func (m *TwoPhaseStoreMeshManager) getRoutes(targetNode string) (map[string]Route, error) {
|
||||||
if !m.store.Contains(targetNode) {
|
if !m.store.Contains(targetNode) {
|
||||||
return nil, fmt.Errorf("getRoute: cannot get route %s does not exist", targetNode)
|
return nil, fmt.Errorf("getRoute: cannot get route %s does not exist", targetNode)
|
||||||
@ -458,7 +466,8 @@ func (m *TwoPhaseStoreMeshManager) getRoutes(targetNode string) (map[string]Rout
|
|||||||
return node.Routes, nil
|
return node.Routes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRoutes(): Get all unique routes. Where the route with the least hop count is chosen
|
// GetRoutes: Get all unique routes the target node is advertising.
|
||||||
|
// on conflicts the route with the least hop count is chosen
|
||||||
func (m *TwoPhaseStoreMeshManager) GetRoutes(targetNode string) (map[string]mesh.Route, error) {
|
func (m *TwoPhaseStoreMeshManager) GetRoutes(targetNode string) (map[string]mesh.Route, error) {
|
||||||
node, err := m.GetNode(targetNode)
|
node, err := m.GetNode(targetNode)
|
||||||
|
|
||||||
@ -502,7 +511,7 @@ func (m *TwoPhaseStoreMeshManager) GetRoutes(targetNode string) (map[string]mesh
|
|||||||
return routes, nil
|
return routes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveNode(): remove the node from the mesh
|
// RemoveNode: remove the node from the mesh
|
||||||
func (m *TwoPhaseStoreMeshManager) RemoveNode(nodeId string) error {
|
func (m *TwoPhaseStoreMeshManager) RemoveNode(nodeId string) error {
|
||||||
if !m.store.Contains(nodeId) {
|
if !m.store.Contains(nodeId) {
|
||||||
return fmt.Errorf("datastore: %s does not exist in the mesh", nodeId)
|
return fmt.Errorf("datastore: %s does not exist in the mesh", nodeId)
|
||||||
@ -512,7 +521,8 @@ func (m *TwoPhaseStoreMeshManager) RemoveNode(nodeId string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetConfiguration implements mesh.MeshProvider.
|
// GetConfiguration gets the WireGuard configuration to use for this
|
||||||
|
// network
|
||||||
func (m *TwoPhaseStoreMeshManager) GetConfiguration() *conf.WgConfiguration {
|
func (m *TwoPhaseStoreMeshManager) GetConfiguration() *conf.WgConfiguration {
|
||||||
return m.Conf
|
return m.Conf
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,13 @@ import (
|
|||||||
"github.com/tim-beatham/smegmesh/pkg/mesh"
|
"github.com/tim-beatham/smegmesh/pkg/mesh"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TwoPhaseMapFactory: instantiate a new twophasemap
|
||||||
|
// datastore
|
||||||
type TwoPhaseMapFactory struct {
|
type TwoPhaseMapFactory struct {
|
||||||
Config *conf.DaemonConfiguration
|
Config *conf.DaemonConfiguration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateMesh: create a new mesh network
|
||||||
func (f *TwoPhaseMapFactory) CreateMesh(params *mesh.MeshProviderFactoryParams) (mesh.MeshProvider, error) {
|
func (f *TwoPhaseMapFactory) CreateMesh(params *mesh.MeshProviderFactoryParams) (mesh.MeshProvider, error) {
|
||||||
return &TwoPhaseStoreMeshManager{
|
return &TwoPhaseStoreMeshManager{
|
||||||
MeshId: params.MeshId,
|
MeshId: params.MeshId,
|
||||||
@ -28,10 +31,12 @@ func (f *TwoPhaseMapFactory) CreateMesh(params *mesh.MeshProviderFactoryParams)
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MeshNodeFactory: create a new node in the mesh network
|
||||||
type MeshNodeFactory struct {
|
type MeshNodeFactory struct {
|
||||||
Config conf.DaemonConfiguration
|
Config conf.DaemonConfiguration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Build: build a new mesh network
|
||||||
func (f *MeshNodeFactory) Build(params *mesh.MeshNodeFactoryParams) mesh.MeshNode {
|
func (f *MeshNodeFactory) Build(params *mesh.MeshNodeFactoryParams) mesh.MeshNode {
|
||||||
hostName := f.getAddress(params)
|
hostName := f.getAddress(params)
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Bucket: bucket represents a value in the grow only map
|
||||||
type Bucket[D any] struct {
|
type Bucket[D any] struct {
|
||||||
Vector uint64
|
Vector uint64
|
||||||
Contents D
|
Contents D
|
||||||
@ -19,6 +20,7 @@ type GMap[K cmp.Ordered, D any] struct {
|
|||||||
clock *VectorClock[K]
|
clock *VectorClock[K]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Put: put a new entry in the grow-only-map
|
||||||
func (g *GMap[K, D]) Put(key K, value D) {
|
func (g *GMap[K, D]) Put(key K, value D) {
|
||||||
g.lock.Lock()
|
g.lock.Lock()
|
||||||
|
|
||||||
@ -32,6 +34,8 @@ func (g *GMap[K, D]) Put(key K, value D) {
|
|||||||
g.lock.Unlock()
|
g.lock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Contains: returns whether or not the key is contained
|
||||||
|
// in the g-map
|
||||||
func (g *GMap[K, D]) Contains(key K) bool {
|
func (g *GMap[K, D]) Contains(key K) bool {
|
||||||
return g.contains(g.clock.hashFunc(key))
|
return g.contains(g.clock.hashFunc(key))
|
||||||
}
|
}
|
||||||
@ -64,6 +68,7 @@ func (g *GMap[K, D]) get(key uint64) Bucket[D] {
|
|||||||
return bucket
|
return bucket
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get: get the value associated with the given key
|
||||||
func (g *GMap[K, D]) Get(key K) D {
|
func (g *GMap[K, D]) Get(key K) D {
|
||||||
if !g.Contains(key) {
|
if !g.Contains(key) {
|
||||||
var def D
|
var def D
|
||||||
@ -73,6 +78,8 @@ func (g *GMap[K, D]) Get(key K) D {
|
|||||||
return g.get(g.clock.hashFunc(key)).Contents
|
return g.get(g.clock.hashFunc(key)).Contents
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mark: marks the node, this means the status of the node
|
||||||
|
// is an undefined state
|
||||||
func (g *GMap[K, D]) Mark(key K) {
|
func (g *GMap[K, D]) Mark(key K) {
|
||||||
if !g.Contains(key) {
|
if !g.Contains(key) {
|
||||||
return
|
return
|
||||||
@ -85,7 +92,7 @@ func (g *GMap[K, D]) Mark(key K) {
|
|||||||
g.lock.Unlock()
|
g.lock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsMarked: returns true if the node is marked
|
// IsMarked: returns true if the node is marked (in an undefined state)
|
||||||
func (g *GMap[K, D]) IsMarked(key K) bool {
|
func (g *GMap[K, D]) IsMarked(key K) bool {
|
||||||
marked := false
|
marked := false
|
||||||
|
|
||||||
@ -101,6 +108,7 @@ func (g *GMap[K, D]) IsMarked(key K) bool {
|
|||||||
return marked
|
return marked
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keys: return all the keys in the grow-only map
|
||||||
func (g *GMap[K, D]) Keys() []uint64 {
|
func (g *GMap[K, D]) Keys() []uint64 {
|
||||||
g.lock.RLock()
|
g.lock.RLock()
|
||||||
|
|
||||||
@ -116,6 +124,7 @@ func (g *GMap[K, D]) Keys() []uint64 {
|
|||||||
return contents
|
return contents
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Save: saves the grow only map
|
||||||
func (g *GMap[K, D]) Save() map[uint64]Bucket[D] {
|
func (g *GMap[K, D]) Save() map[uint64]Bucket[D] {
|
||||||
buckets := make(map[uint64]Bucket[D])
|
buckets := make(map[uint64]Bucket[D])
|
||||||
g.lock.RLock()
|
g.lock.RLock()
|
||||||
@ -128,6 +137,7 @@ func (g *GMap[K, D]) Save() map[uint64]Bucket[D] {
|
|||||||
return buckets
|
return buckets
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SaveWithKeys: get all the values corresponding with the provided keys
|
||||||
func (g *GMap[K, D]) SaveWithKeys(keys []uint64) map[uint64]Bucket[D] {
|
func (g *GMap[K, D]) SaveWithKeys(keys []uint64) map[uint64]Bucket[D] {
|
||||||
buckets := make(map[uint64]Bucket[D])
|
buckets := make(map[uint64]Bucket[D])
|
||||||
g.lock.RLock()
|
g.lock.RLock()
|
||||||
@ -140,6 +150,7 @@ func (g *GMap[K, D]) SaveWithKeys(keys []uint64) map[uint64]Bucket[D] {
|
|||||||
return buckets
|
return buckets
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetClock: get all the vector clocks in the g_map
|
||||||
func (g *GMap[K, D]) GetClock() map[uint64]uint64 {
|
func (g *GMap[K, D]) GetClock() map[uint64]uint64 {
|
||||||
clock := make(map[uint64]uint64)
|
clock := make(map[uint64]uint64)
|
||||||
g.lock.RLock()
|
g.lock.RLock()
|
||||||
@ -152,6 +163,7 @@ func (g *GMap[K, D]) GetClock() map[uint64]uint64 {
|
|||||||
return clock
|
return clock
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetHash: get the hash of the g_map representing its state
|
||||||
func (g *GMap[K, D]) GetHash() uint64 {
|
func (g *GMap[K, D]) GetHash() uint64 {
|
||||||
hash := uint64(0)
|
hash := uint64(0)
|
||||||
|
|
||||||
@ -165,6 +177,7 @@ func (g *GMap[K, D]) GetHash() uint64 {
|
|||||||
return hash
|
return hash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prune: prune all stale entries
|
||||||
func (g *GMap[K, D]) Prune() {
|
func (g *GMap[K, D]) Prune() {
|
||||||
stale := g.clock.getStale()
|
stale := g.clock.getStale()
|
||||||
g.lock.Lock()
|
g.lock.Lock()
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/tim-beatham/smegmesh/pkg/lib"
|
"github.com/tim-beatham/smegmesh/pkg/lib"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TwoPhaseMap: comprises of two grow-only maps
|
||||||
type TwoPhaseMap[K cmp.Ordered, D any] struct {
|
type TwoPhaseMap[K cmp.Ordered, D any] struct {
|
||||||
addMap *GMap[K, D]
|
addMap *GMap[K, D]
|
||||||
removeMap *GMap[K, bool]
|
removeMap *GMap[K, bool]
|
||||||
@ -23,7 +24,7 @@ func (m *TwoPhaseMap[K, D]) Contains(key K) bool {
|
|||||||
return m.contains(m.Clock.hashFunc(key))
|
return m.contains(m.Clock.hashFunc(key))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Contains checks whether the value exists in the map
|
// contains: checks whether the key exists in the map
|
||||||
func (m *TwoPhaseMap[K, D]) contains(key uint64) bool {
|
func (m *TwoPhaseMap[K, D]) contains(key uint64) bool {
|
||||||
if !m.addMap.contains(key) {
|
if !m.addMap.contains(key) {
|
||||||
return false
|
return false
|
||||||
@ -40,6 +41,7 @@ func (m *TwoPhaseMap[K, D]) contains(key uint64) bool {
|
|||||||
return addValue.Vector >= removeValue.Vector
|
return addValue.Vector >= removeValue.Vector
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get: get the value corresponding with the given key
|
||||||
func (m *TwoPhaseMap[K, D]) Get(key K) D {
|
func (m *TwoPhaseMap[K, D]) Get(key K) D {
|
||||||
var result D
|
var result D
|
||||||
|
|
||||||
@ -60,18 +62,19 @@ func (m *TwoPhaseMap[K, D]) get(key uint64) D {
|
|||||||
return m.addMap.get(key).Contents
|
return m.addMap.get(key).Contents
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put places the key K in the map
|
// Put: places the key K in the map with the associated data D
|
||||||
func (m *TwoPhaseMap[K, D]) Put(key K, data D) {
|
func (m *TwoPhaseMap[K, D]) Put(key K, data D) {
|
||||||
msgSequence := m.Clock.IncrementClock()
|
msgSequence := m.Clock.IncrementClock()
|
||||||
m.Clock.Put(key, msgSequence)
|
m.Clock.Put(key, msgSequence)
|
||||||
m.addMap.Put(key, data)
|
m.addMap.Put(key, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mark: marks the status of the node as undetermiend
|
||||||
func (m *TwoPhaseMap[K, D]) Mark(key K) {
|
func (m *TwoPhaseMap[K, D]) Mark(key K) {
|
||||||
m.addMap.Mark(key)
|
m.addMap.Mark(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove removes the value from the map
|
// Remove: removes the value from the map
|
||||||
func (m *TwoPhaseMap[K, D]) Remove(key K) {
|
func (m *TwoPhaseMap[K, D]) Remove(key K) {
|
||||||
m.removeMap.Put(key, true)
|
m.removeMap.Put(key, true)
|
||||||
}
|
}
|
||||||
@ -92,6 +95,7 @@ func (m *TwoPhaseMap[K, D]) keys() []uint64 {
|
|||||||
return keys
|
return keys
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AsList: convert the map to a list
|
||||||
func (m *TwoPhaseMap[K, D]) AsList() []D {
|
func (m *TwoPhaseMap[K, D]) AsList() []D {
|
||||||
theList := make([]D, 0)
|
theList := make([]D, 0)
|
||||||
|
|
||||||
@ -104,6 +108,8 @@ func (m *TwoPhaseMap[K, D]) AsList() []D {
|
|||||||
return theList
|
return theList
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Snapshot: convert the map into an immutable snapshot.
|
||||||
|
// contains the contents of the add and remove map
|
||||||
func (m *TwoPhaseMap[K, D]) Snapshot() *TwoPhaseMapSnapshot[K, D] {
|
func (m *TwoPhaseMap[K, D]) Snapshot() *TwoPhaseMapSnapshot[K, D] {
|
||||||
return &TwoPhaseMapSnapshot[K, D]{
|
return &TwoPhaseMapSnapshot[K, D]{
|
||||||
Add: m.addMap.Save(),
|
Add: m.addMap.Save(),
|
||||||
@ -111,6 +117,8 @@ func (m *TwoPhaseMap[K, D]) Snapshot() *TwoPhaseMapSnapshot[K, D] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SnapshotFromState: create a snapshot of the intersection of values provided
|
||||||
|
// in the given state
|
||||||
func (m *TwoPhaseMap[K, D]) SnapShotFromState(state *TwoPhaseMapState[K]) *TwoPhaseMapSnapshot[K, D] {
|
func (m *TwoPhaseMap[K, D]) SnapShotFromState(state *TwoPhaseMapState[K]) *TwoPhaseMapSnapshot[K, D] {
|
||||||
addKeys := lib.MapKeys(state.AddContents)
|
addKeys := lib.MapKeys(state.AddContents)
|
||||||
removeKeys := lib.MapKeys(state.RemoveContents)
|
removeKeys := lib.MapKeys(state.RemoveContents)
|
||||||
@ -121,12 +129,18 @@ func (m *TwoPhaseMap[K, D]) SnapShotFromState(state *TwoPhaseMapState[K]) *TwoPh
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TwoPhaseMapState: encapsulates the state of the map
|
||||||
|
// without specifying the data that is stored
|
||||||
type TwoPhaseMapState[K cmp.Ordered] struct {
|
type TwoPhaseMapState[K cmp.Ordered] struct {
|
||||||
|
// Vectors: the vector ID of each process
|
||||||
Vectors map[uint64]uint64
|
Vectors map[uint64]uint64
|
||||||
|
// AddContents: the contents of the add map
|
||||||
AddContents map[uint64]uint64
|
AddContents map[uint64]uint64
|
||||||
|
// RemoveContents: the contents of the remove map
|
||||||
RemoveContents map[uint64]uint64
|
RemoveContents map[uint64]uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsMarked: returns true if the given value is marked in an undetermined state
|
||||||
func (m *TwoPhaseMap[K, D]) IsMarked(key K) bool {
|
func (m *TwoPhaseMap[K, D]) IsMarked(key K) bool {
|
||||||
return m.addMap.IsMarked(key)
|
return m.addMap.IsMarked(key)
|
||||||
}
|
}
|
||||||
@ -151,6 +165,8 @@ func (m *TwoPhaseMap[K, D]) GenerateMessage() *TwoPhaseMapState[K] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Difference: compute the set difference between the two states.
|
||||||
|
// highestStale represents the highest vector clock that has been marked as stale
|
||||||
func (m *TwoPhaseMapState[K]) Difference(highestStale uint64, state *TwoPhaseMapState[K]) *TwoPhaseMapState[K] {
|
func (m *TwoPhaseMapState[K]) Difference(highestStale uint64, state *TwoPhaseMapState[K]) *TwoPhaseMapState[K] {
|
||||||
mapState := &TwoPhaseMapState[K]{
|
mapState := &TwoPhaseMapState[K]{
|
||||||
AddContents: make(map[uint64]uint64),
|
AddContents: make(map[uint64]uint64),
|
||||||
@ -176,6 +192,7 @@ func (m *TwoPhaseMapState[K]) Difference(highestStale uint64, state *TwoPhaseMap
|
|||||||
return mapState
|
return mapState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Merge: merge a snapshot into the map
|
||||||
func (m *TwoPhaseMap[K, D]) Merge(snapshot TwoPhaseMapSnapshot[K, D]) {
|
func (m *TwoPhaseMap[K, D]) Merge(snapshot TwoPhaseMapSnapshot[K, D]) {
|
||||||
for key, value := range snapshot.Add {
|
for key, value := range snapshot.Add {
|
||||||
// Gravestone is local only to that node.
|
// Gravestone is local only to that node.
|
||||||
@ -190,6 +207,7 @@ func (m *TwoPhaseMap[K, D]) Merge(snapshot TwoPhaseMapSnapshot[K, D]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prune: garbage collect all stale entries in the map
|
||||||
func (m *TwoPhaseMap[K, D]) Prune() {
|
func (m *TwoPhaseMap[K, D]) Prune() {
|
||||||
m.addMap.Prune()
|
m.addMap.Prune()
|
||||||
m.removeMap.Prune()
|
m.removeMap.Prune()
|
||||||
|
@ -8,6 +8,9 @@ import (
|
|||||||
"github.com/tim-beatham/smegmesh/pkg/lib"
|
"github.com/tim-beatham/smegmesh/pkg/lib"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// VectorBucket: represents a vector clock in the bucket
|
||||||
|
// recording both the time changes were last seen
|
||||||
|
// and when the lastUpdate epoch was recorded
|
||||||
type VectorBucket struct {
|
type VectorBucket struct {
|
||||||
// clock current value of the node's clock
|
// clock current value of the node's clock
|
||||||
clock uint64
|
clock uint64
|
||||||
@ -15,8 +18,9 @@ type VectorBucket struct {
|
|||||||
lastUpdate uint64
|
lastUpdate uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vector clock defines an abstract data type
|
// VectorClock: defines an abstract data type
|
||||||
// for a vector clock implementation
|
// for a vector clock implementation. Including a mechanism to
|
||||||
|
// garbage collect stale entries
|
||||||
type VectorClock[K cmp.Ordered] struct {
|
type VectorClock[K cmp.Ordered] struct {
|
||||||
vectors map[uint64]*VectorBucket
|
vectors map[uint64]*VectorBucket
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
@ -62,6 +66,7 @@ func (m *VectorClock[K]) GetHash() uint64 {
|
|||||||
return hash
|
return hash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Merge: merge two clocks together
|
||||||
func (m *VectorClock[K]) Merge(vectors map[uint64]uint64) {
|
func (m *VectorClock[K]) Merge(vectors map[uint64]uint64) {
|
||||||
for key, value := range vectors {
|
for key, value := range vectors {
|
||||||
m.put(key, value)
|
m.put(key, value)
|
||||||
@ -97,6 +102,7 @@ func (m *VectorClock[K]) GetStaleCount() uint64 {
|
|||||||
return staleCount
|
return staleCount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prune: prunes all stale entries in the vector clock
|
||||||
func (m *VectorClock[K]) Prune() {
|
func (m *VectorClock[K]) Prune() {
|
||||||
stale := m.getStale()
|
stale := m.getStale()
|
||||||
|
|
||||||
@ -109,6 +115,8 @@ func (m *VectorClock[K]) Prune() {
|
|||||||
m.lock.Unlock()
|
m.lock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTimeStamp: get the last time the node was updated in UNIX
|
||||||
|
// epoch time
|
||||||
func (m *VectorClock[K]) GetTimestamp(processId K) uint64 {
|
func (m *VectorClock[K]) GetTimestamp(processId K) uint64 {
|
||||||
m.lock.RLock()
|
m.lock.RLock()
|
||||||
|
|
||||||
@ -118,6 +126,8 @@ func (m *VectorClock[K]) GetTimestamp(processId K) uint64 {
|
|||||||
return lastUpdate
|
return lastUpdate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Put: places the key with vector clock in the clock of the given
|
||||||
|
// process
|
||||||
func (m *VectorClock[K]) Put(key K, value uint64) {
|
func (m *VectorClock[K]) Put(key K, value uint64) {
|
||||||
m.put(m.hashFunc(key), value)
|
m.put(m.hashFunc(key), value)
|
||||||
}
|
}
|
||||||
@ -133,7 +143,8 @@ func (m *VectorClock[K]) put(key uint64, value uint64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make sure that entries that were garbage collected don't get
|
// Make sure that entries that were garbage collected don't get
|
||||||
// addded back
|
// highestStale represents the highest vector clock that has been
|
||||||
|
// invalidated
|
||||||
if value > clockValue && value > m.highestStale {
|
if value > clockValue && value > m.highestStale {
|
||||||
newBucket := VectorBucket{
|
newBucket := VectorBucket{
|
||||||
clock: value,
|
clock: value,
|
||||||
@ -145,6 +156,7 @@ func (m *VectorClock[K]) put(key uint64, value uint64) {
|
|||||||
m.lock.Unlock()
|
m.lock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetClock: serialize the vector clock into an immutable map
|
||||||
func (m *VectorClock[K]) GetClock() map[uint64]uint64 {
|
func (m *VectorClock[K]) GetClock() map[uint64]uint64 {
|
||||||
clock := make(map[uint64]uint64)
|
clock := make(map[uint64]uint64)
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/tim-beatham/smegmesh/pkg/mesh"
|
"github.com/tim-beatham/smegmesh/pkg/mesh"
|
||||||
"github.com/tim-beatham/smegmesh/pkg/query"
|
"github.com/tim-beatham/smegmesh/pkg/query"
|
||||||
"github.com/tim-beatham/smegmesh/pkg/rpc"
|
"github.com/tim-beatham/smegmesh/pkg/rpc"
|
||||||
|
"github.com/tim-beatham/smegmesh/pkg/sync"
|
||||||
"github.com/tim-beatham/smegmesh/pkg/wg"
|
"github.com/tim-beatham/smegmesh/pkg/wg"
|
||||||
"golang.zx2c4.com/wireguard/wgctrl"
|
"golang.zx2c4.com/wireguard/wgctrl"
|
||||||
)
|
)
|
||||||
@ -21,7 +22,6 @@ type NewCtrlServerParams struct {
|
|||||||
CtrlProvider rpc.MeshCtrlServerServer
|
CtrlProvider rpc.MeshCtrlServerServer
|
||||||
SyncProvider rpc.SyncServiceServer
|
SyncProvider rpc.SyncServiceServer
|
||||||
Querier query.Querier
|
Querier query.Querier
|
||||||
OnDelete func(mesh.MeshProvider)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new instance of the MeshCtrlServer or error if the
|
// Create a new instance of the MeshCtrlServer or error if the
|
||||||
@ -38,8 +38,12 @@ func NewCtrlServer(params *NewCtrlServerParams) (*MeshCtrlServer, error) {
|
|||||||
ipAllocator := &ip.ULABuilder{}
|
ipAllocator := &ip.ULABuilder{}
|
||||||
interfaceManipulator := wg.NewWgInterfaceManipulator(params.Client)
|
interfaceManipulator := wg.NewWgInterfaceManipulator(params.Client)
|
||||||
|
|
||||||
|
ctrlServer.timers = make([]*lib.Timer, 0)
|
||||||
|
|
||||||
configApplyer := mesh.NewWgMeshConfigApplyer()
|
configApplyer := mesh.NewWgMeshConfigApplyer()
|
||||||
|
|
||||||
|
var syncer sync.Syncer
|
||||||
|
|
||||||
meshManagerParams := &mesh.NewMeshManagerParams{
|
meshManagerParams := &mesh.NewMeshManagerParams{
|
||||||
Conf: *params.Conf,
|
Conf: *params.Conf,
|
||||||
Client: params.Client,
|
Client: params.Client,
|
||||||
@ -49,7 +53,13 @@ func NewCtrlServer(params *NewCtrlServerParams) (*MeshCtrlServer, error) {
|
|||||||
IPAllocator: ipAllocator,
|
IPAllocator: ipAllocator,
|
||||||
InterfaceManipulator: interfaceManipulator,
|
InterfaceManipulator: interfaceManipulator,
|
||||||
ConfigApplyer: configApplyer,
|
ConfigApplyer: configApplyer,
|
||||||
OnDelete: params.OnDelete,
|
OnDelete: func(mesh mesh.MeshProvider) {
|
||||||
|
_, err := syncer.Sync(mesh)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
logging.Log.WriteErrorf(err.Error())
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
ctrlServer.MeshManager = mesh.NewMeshManager(meshManagerParams)
|
ctrlServer.MeshManager = mesh.NewMeshManager(meshManagerParams)
|
||||||
@ -83,9 +93,37 @@ func NewCtrlServer(params *NewCtrlServerParams) (*MeshCtrlServer, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
syncer = sync.NewSyncer(&sync.NewSyncerParams{
|
||||||
|
MeshManager: ctrlServer.MeshManager,
|
||||||
|
ConnectionManager: ctrlServer.ConnectionManager,
|
||||||
|
Configuration: params.Conf,
|
||||||
|
})
|
||||||
|
|
||||||
|
// Check any syncs every 1 second
|
||||||
|
syncTimer := lib.NewTimer(func() error {
|
||||||
|
err = syncer.SyncMeshes()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
logging.Log.WriteErrorf(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}, 1)
|
||||||
|
|
||||||
|
heartbeatTimer := lib.NewTimer(func() error {
|
||||||
|
logging.Log.WriteInfof("checking heartbeat")
|
||||||
|
return ctrlServer.MeshManager.UpdateTimeStamp()
|
||||||
|
}, params.Conf.HeartBeat)
|
||||||
|
|
||||||
|
ctrlServer.timers = append(ctrlServer.timers, syncTimer, heartbeatTimer)
|
||||||
|
|
||||||
ctrlServer.Querier = query.NewJmesQuerier(ctrlServer.MeshManager)
|
ctrlServer.Querier = query.NewJmesQuerier(ctrlServer.MeshManager)
|
||||||
ctrlServer.ConnectionServer = connServer
|
ctrlServer.ConnectionServer = connServer
|
||||||
|
|
||||||
|
for _, timer := range ctrlServer.timers {
|
||||||
|
go timer.Run()
|
||||||
|
}
|
||||||
|
|
||||||
return ctrlServer, nil
|
return ctrlServer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,5 +161,13 @@ func (s *MeshCtrlServer) Close() error {
|
|||||||
logging.Log.WriteErrorf(err.Error())
|
logging.Log.WriteErrorf(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, timer := range s.timers {
|
||||||
|
err := timer.Stop()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
logging.Log.WriteErrorf(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -13,12 +13,14 @@ import (
|
|||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// MeshRoute: represents a route in the mesh that is
|
||||||
|
// available to client applications
|
||||||
type MeshRoute struct {
|
type MeshRoute struct {
|
||||||
Destination string
|
Destination string
|
||||||
Path []string
|
Path []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Represents the WireGuard configuration attached to the node
|
// WireGuardStats: Represents the WireGuard configuration attached to the node
|
||||||
type WireGuardStats struct {
|
type WireGuardStats struct {
|
||||||
AllowedIPs []string
|
AllowedIPs []string
|
||||||
TransmitBytes int64
|
TransmitBytes int64
|
||||||
@ -26,7 +28,8 @@ type WireGuardStats struct {
|
|||||||
PersistentKeepAliveInterval time.Duration
|
PersistentKeepAliveInterval time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
// Represents a WireGuard MeshNode
|
// MeshNode: represents a node in the WireGuard mesh that can be
|
||||||
|
// sent to ip chandlers
|
||||||
type MeshNode struct {
|
type MeshNode struct {
|
||||||
HostEndpoint string
|
HostEndpoint string
|
||||||
WgEndpoint string
|
WgEndpoint string
|
||||||
@ -40,12 +43,13 @@ type MeshNode struct {
|
|||||||
Stats WireGuardStats
|
Stats WireGuardStats
|
||||||
}
|
}
|
||||||
|
|
||||||
// Represents a WireGuard Mesh
|
// Mesh: Represents a WireGuard Mesh network that can be sent
|
||||||
|
// along ipc to client frameworks
|
||||||
type Mesh struct {
|
type Mesh struct {
|
||||||
SharedKey *wgtypes.Key
|
|
||||||
Nodes map[string]MeshNode
|
Nodes map[string]MeshNode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CtrlServer: Encapsulates th ctrlserver
|
||||||
type CtrlServer interface {
|
type CtrlServer interface {
|
||||||
GetConfiguration() *conf.DaemonConfiguration
|
GetConfiguration() *conf.DaemonConfiguration
|
||||||
GetClient() *wgctrl.Client
|
GetClient() *wgctrl.Client
|
||||||
@ -55,7 +59,7 @@ type CtrlServer interface {
|
|||||||
GetConnectionManager() conn.ConnectionManager
|
GetConnectionManager() conn.ConnectionManager
|
||||||
}
|
}
|
||||||
|
|
||||||
// Represents a ctrlserver to be used in WireGuard
|
// MeshCtrlServer: Represents a ctrlserver to be used in WireGuard
|
||||||
type MeshCtrlServer struct {
|
type MeshCtrlServer struct {
|
||||||
Client *wgctrl.Client
|
Client *wgctrl.Client
|
||||||
MeshManager mesh.MeshManager
|
MeshManager mesh.MeshManager
|
||||||
@ -63,6 +67,7 @@ type MeshCtrlServer struct {
|
|||||||
ConnectionServer *conn.ConnectionServer
|
ConnectionServer *conn.ConnectionServer
|
||||||
Conf *conf.DaemonConfiguration
|
Conf *conf.DaemonConfiguration
|
||||||
Querier query.Querier
|
Querier query.Querier
|
||||||
|
timers []*lib.Timer
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCtrlNode create an instance of a ctrl node to send over an
|
// NewCtrlNode create an instance of a ctrl node to send over an
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// smegdns: example of how to implement dns in the mesh
|
||||||
package smegdns
|
package smegdns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -45,6 +46,7 @@ func (d *DNSHandler) queryMesh(meshId, alias string) net.IP {
|
|||||||
return ip
|
return ip
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handleQuery: handles a DNS query
|
||||||
func (d *DNSHandler) handleQuery(m *dns.Msg) {
|
func (d *DNSHandler) handleQuery(m *dns.Msg) {
|
||||||
for _, q := range m.Question {
|
for _, q := range m.Question {
|
||||||
switch q.Qtype {
|
switch q.Qtype {
|
||||||
@ -72,6 +74,7 @@ func (d *DNSHandler) handleQuery(m *dns.Msg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handleDNS query: handle a DNS request
|
||||||
func (h *DNSHandler) handleDnsRequest(w dns.ResponseWriter, r *dns.Msg) {
|
func (h *DNSHandler) handleDnsRequest(w dns.ResponseWriter, r *dns.Msg) {
|
||||||
msg := new(dns.Msg)
|
msg := new(dns.Msg)
|
||||||
msg.SetReply(r)
|
msg.SetReply(r)
|
||||||
|
@ -29,6 +29,7 @@ type Graph interface {
|
|||||||
GetType() GraphType
|
GetType() GraphType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cluster: represents a subgraph in the graphs
|
||||||
type Cluster struct {
|
type Cluster struct {
|
||||||
Type GraphType
|
Type GraphType
|
||||||
Name string
|
Name string
|
||||||
@ -37,6 +38,7 @@ type Cluster struct {
|
|||||||
edges map[string]Edge
|
edges map[string]Edge
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RootGraph: Represents the top level graph
|
||||||
type RootGraph struct {
|
type RootGraph struct {
|
||||||
Type GraphType
|
Type GraphType
|
||||||
Label string
|
Label string
|
||||||
@ -45,6 +47,7 @@ type RootGraph struct {
|
|||||||
edges map[string]Edge
|
edges map[string]Edge
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Node: represents a graphviz not
|
||||||
type Node struct {
|
type Node struct {
|
||||||
Name string
|
Name string
|
||||||
Label string
|
Label string
|
||||||
@ -52,10 +55,12 @@ type Node struct {
|
|||||||
Size int
|
Size int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Edge: represents an edge between adjacent nodes
|
||||||
type Edge interface {
|
type Edge interface {
|
||||||
Dottable
|
Dottable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DirectEdge: contains a directed edge between any two nodes
|
||||||
type DirectedEdge struct {
|
type DirectedEdge struct {
|
||||||
Name string
|
Name string
|
||||||
Label string
|
Label string
|
||||||
@ -63,6 +68,8 @@ type DirectedEdge struct {
|
|||||||
To string
|
To string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UndirectedEdge: contains an undirected edge between any two
|
||||||
|
// nodes
|
||||||
type UndirectedEdge struct {
|
type UndirectedEdge struct {
|
||||||
Name string
|
Name string
|
||||||
Label string
|
Label string
|
||||||
@ -75,11 +82,7 @@ type Dottable interface {
|
|||||||
GetDOT() (string, error)
|
GetDOT() (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGraph(label string, graphType GraphType) *RootGraph {
|
// PutNode: puts a node in the root graph
|
||||||
return &RootGraph{Type: graphType, Label: label, clusters: map[string]*Cluster{}, nodes: make(map[string]*Node), edges: make(map[string]Edge)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PutNode: puts a node in the graph
|
|
||||||
func (g *RootGraph) PutNode(name, label string, size int, shape Shape) error {
|
func (g *RootGraph) PutNode(name, label string, size int, shape Shape) error {
|
||||||
_, exists := g.nodes[name]
|
_, exists := g.nodes[name]
|
||||||
|
|
||||||
@ -92,6 +95,7 @@ func (g *RootGraph) PutNode(name, label string, size int, shape Shape) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PutCluster: puts a cluster in the root graph
|
||||||
func (g *RootGraph) PutCluster(graph *Cluster) {
|
func (g *RootGraph) PutCluster(graph *Cluster) {
|
||||||
g.clusters[graph.Label] = graph
|
g.clusters[graph.Label] = graph
|
||||||
}
|
}
|
||||||
@ -113,6 +117,7 @@ func writeContituents[D Dottable](result *strings.Builder, elements ...D) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDOT: convert the root graph into dot format
|
||||||
func (g *RootGraph) GetDOT() (string, error) {
|
func (g *RootGraph) GetDOT() (string, error) {
|
||||||
var result strings.Builder
|
var result strings.Builder
|
||||||
|
|
||||||
@ -138,7 +143,7 @@ func (g *RootGraph) GetDOT() (string, error) {
|
|||||||
return result.String(), nil
|
return result.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetType implements Graph.
|
// GetType: get the graph type. DIRECTED|UNDIRECTED
|
||||||
func (r *RootGraph) GetType() GraphType {
|
func (r *RootGraph) GetType() GraphType {
|
||||||
return r.Type
|
return r.Type
|
||||||
}
|
}
|
||||||
@ -152,7 +157,7 @@ func constructEdge(graph Graph, name, label, from, to string) Edge {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddEdge: adds an edge between two nodes in the graph
|
// AddEdge: adds an edge between two nodes in the root graph
|
||||||
func (g *RootGraph) AddEdge(name string, label string, from string, to string) error {
|
func (g *RootGraph) AddEdge(name string, label string, from string, to string) error {
|
||||||
g.edges[name] = constructEdge(g, name, label, from, to)
|
g.edges[name] = constructEdge(g, name, label, from, to)
|
||||||
return nil
|
return nil
|
||||||
@ -166,15 +171,18 @@ func (n *Node) hash() int {
|
|||||||
return (int(h.Sum32()) % numColours) + 1
|
return (int(h.Sum32()) % numColours) + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDOT: convert the node into DOT format
|
||||||
func (n *Node) GetDOT() (string, error) {
|
func (n *Node) GetDOT() (string, error) {
|
||||||
return fmt.Sprintf("node[label=\"%s\",shape=%s, style=\"filled\", fillcolor=%d, width=%d, height=%d, fixedsize=true] \"%s\";\n",
|
return fmt.Sprintf("node[label=\"%s\",shape=%s, style=\"filled\", fillcolor=%d, width=%d, height=%d, fixedsize=true] \"%s\";\n",
|
||||||
n.Label, n.Shape, n.hash(), n.Size, n.Size, n.Name), nil
|
n.Label, n.Shape, n.hash(), n.Size, n.Size, n.Name), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDOT: Convert a directed edge into dot format
|
||||||
func (e *DirectedEdge) GetDOT() (string, error) {
|
func (e *DirectedEdge) GetDOT() (string, error) {
|
||||||
return fmt.Sprintf("\"%s\" -> \"%s\" [label=\"%s\"];\n", e.From, e.To, e.Label), nil
|
return fmt.Sprintf("\"%s\" -> \"%s\" [label=\"%s\"];\n", e.From, e.To, e.Label), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDOT: convert an undirected edge into dot format
|
||||||
func (e *UndirectedEdge) GetDOT() (string, error) {
|
func (e *UndirectedEdge) GetDOT() (string, error) {
|
||||||
return fmt.Sprintf("\"%s\" -- \"%s\" [label=\"%s\"];\n", e.From, e.To, e.Label), nil
|
return fmt.Sprintf("\"%s\" -- \"%s\" [label=\"%s\"];\n", e.From, e.To, e.Label), nil
|
||||||
}
|
}
|
||||||
@ -198,6 +206,7 @@ func (g *Cluster) PutNode(name, label string, size int, shape Shape) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDOT: convert the cluster into dot format
|
||||||
func (g *Cluster) GetDOT() (string, error) {
|
func (g *Cluster) GetDOT() (string, error) {
|
||||||
var builder strings.Builder
|
var builder strings.Builder
|
||||||
|
|
||||||
@ -212,10 +221,12 @@ func (g *Cluster) GetDOT() (string, error) {
|
|||||||
return builder.String(), nil
|
return builder.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetType: get the type of the subgraph (directed|undirected)
|
||||||
func (g *Cluster) GetType() GraphType {
|
func (g *Cluster) GetType() GraphType {
|
||||||
return g.Type
|
return g.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewSubGraph: instantiate a new subgraph
|
||||||
func NewSubGraph(name string, label string, graphType GraphType) *Cluster {
|
func NewSubGraph(name string, label string, graphType GraphType) *Cluster {
|
||||||
return &Cluster{
|
return &Cluster{
|
||||||
Label: name,
|
Label: name,
|
||||||
@ -225,3 +236,14 @@ func NewSubGraph(name string, label string, graphType GraphType) *Cluster {
|
|||||||
edges: make(map[string]Edge),
|
edges: make(map[string]Edge),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewGraph: create a new root graph
|
||||||
|
func NewGraph(label string, graphType GraphType) *RootGraph {
|
||||||
|
return &RootGraph{
|
||||||
|
Type: graphType,
|
||||||
|
Label: label,
|
||||||
|
clusters: map[string]*Cluster{},
|
||||||
|
nodes: make(map[string]*Node),
|
||||||
|
edges: make(map[string]Edge)
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,7 @@
|
|||||||
package ip
|
package ip
|
||||||
|
|
||||||
/*
|
// Generates a CGA see RFC 3972
|
||||||
* Use a WireGuard public key to generate a unique interface ID
|
// https://datatracker.ietf.org/doc/html/rfc3972
|
||||||
*/
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
@ -22,15 +21,19 @@ const (
|
|||||||
InterfaceIdLen = 8
|
InterfaceIdLen = 8
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
// CGAParameters: parameters used to create a new cryotpgraphically generated
|
||||||
* Cga parameters used to generate an IPV6 interface ID
|
// address
|
||||||
*/
|
|
||||||
type CgaParameters struct {
|
type CgaParameters struct {
|
||||||
Modifier [ModifierLength]byte
|
Modifier [ModifierLength]byte
|
||||||
|
// SubnetPrefix: prefix of the subnetwork
|
||||||
SubnetPrefix [2 * InterfaceIdLen]byte
|
SubnetPrefix [2 * InterfaceIdLen]byte
|
||||||
|
// CollisionCount: total number of times we have atempted to generate a porefix
|
||||||
CollisionCount uint8
|
CollisionCount uint8
|
||||||
|
// PublicKey: WireGuard public key of our interface
|
||||||
PublicKey wgtypes.Key
|
PublicKey wgtypes.Key
|
||||||
|
// interfaceId: the generated interfaceId
|
||||||
interfaceId [2 * InterfaceIdLen]byte
|
interfaceId [2 * InterfaceIdLen]byte
|
||||||
|
// flag: represents whether or not an IP address has been generated
|
||||||
flag byte
|
flag byte
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,22 +52,6 @@ func NewCga(key wgtypes.Key, collisionCount uint8, subnetPrefix [2 * InterfaceId
|
|||||||
return ¶ms, nil
|
return ¶ms, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CgaParameters) generateHash2() []byte {
|
|
||||||
var byteVal [hash2Length]byte
|
|
||||||
|
|
||||||
for i := 0; i < ModifierLength; i++ {
|
|
||||||
byteVal[i] = c.Modifier[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < wgtypes.KeyLen; i++ {
|
|
||||||
byteVal[ModifierLength+ZeroLength+i] = c.PublicKey[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
hash := sha1.Sum(byteVal[:])
|
|
||||||
|
|
||||||
return hash[:Hash2Prefix]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *CgaParameters) generateHash1() []byte {
|
func (c *CgaParameters) generateHash1() []byte {
|
||||||
var byteVal [hash1Length]byte
|
var byteVal [hash1Length]byte
|
||||||
|
|
||||||
@ -98,7 +85,6 @@ func (c *CgaParameters) generateInterface() []byte {
|
|||||||
|
|
||||||
interfaceId[0] = clearBit(int(interfaceId[0]), 6)
|
interfaceId[0] = clearBit(int(interfaceId[0]), 6)
|
||||||
interfaceId[0] = clearBit(int(interfaceId[1]), 7)
|
interfaceId[0] = clearBit(int(interfaceId[1]), 7)
|
||||||
|
|
||||||
return interfaceId
|
return interfaceId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// IPAllocator: abstracts the process of creating an IP address
|
||||||
type IPAllocator interface {
|
type IPAllocator interface {
|
||||||
GetIP(key wgtypes.Key, meshId string, collisionCount uint8) (net.IP, error)
|
GetIP(key wgtypes.Key, meshId string, collisionCount uint8) (net.IP, error)
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ULABuilder: Create a new ULA in WireGuard
|
||||||
type ULABuilder struct{}
|
type ULABuilder struct{}
|
||||||
|
|
||||||
func getMeshPrefix(meshId string) [16]byte {
|
func getMeshPrefix(meshId string) [16]byte {
|
||||||
|
@ -5,13 +5,12 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/rpc"
|
"net/rpc"
|
||||||
ipcRpc "net/rpc"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/tim-beatham/smegmesh/pkg/ctrlserver"
|
"github.com/tim-beatham/smegmesh/pkg/ctrlserver"
|
||||||
)
|
)
|
||||||
|
|
||||||
const SockAddr = "/tmp/wgmesh_sock"
|
const SockAddr = "/tmp/smeg.sock"
|
||||||
|
|
||||||
type MeshIpc interface {
|
type MeshIpc interface {
|
||||||
CreateMesh(args *NewMeshArgs, reply *string) error
|
CreateMesh(args *NewMeshArgs, reply *string) error
|
||||||
@ -60,55 +59,80 @@ type JoinMeshArgs struct {
|
|||||||
WgArgs WireGuardArgs
|
WgArgs WireGuardArgs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PutServiceArgs: args to place a service into the data store
|
||||||
type PutServiceArgs struct {
|
type PutServiceArgs struct {
|
||||||
Service string
|
Service string
|
||||||
Value string
|
Value string
|
||||||
MeshId string
|
MeshId string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteServiceArgs: args to remove a service from the data store
|
||||||
type DeleteServiceArgs struct {
|
type DeleteServiceArgs struct {
|
||||||
Service string
|
Service string
|
||||||
MeshId string
|
MeshId string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PutAliasArgs: args to assign an alias to a node
|
||||||
type PutAliasArgs struct {
|
type PutAliasArgs struct {
|
||||||
|
// Alias: represents the alias of the node
|
||||||
Alias string
|
Alias string
|
||||||
|
// MeshId: represents the meshID of the node
|
||||||
MeshId string
|
MeshId string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PutDescriptionArgs: args to assign a description to a node
|
||||||
type PutDescriptionArgs struct {
|
type PutDescriptionArgs struct {
|
||||||
|
// Description: descriptio to add to the network
|
||||||
Description string
|
Description string
|
||||||
|
// MeshID to add to the mesh network
|
||||||
MeshId string
|
MeshId string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// GetMeshReply: ipc reply to get the mesh network
|
||||||
type GetMeshReply struct {
|
type GetMeshReply struct {
|
||||||
Nodes []ctrlserver.MeshNode
|
Nodes []ctrlserver.MeshNode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListMeshReply: ipc reply of the networks the node is part of
|
||||||
type ListMeshReply struct {
|
type ListMeshReply struct {
|
||||||
Meshes []string
|
Meshes []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Querymesh: ipc args to query a mesh network
|
||||||
type QueryMesh struct {
|
type QueryMesh struct {
|
||||||
|
// MeshId: id of the mesh to query
|
||||||
MeshId string
|
MeshId string
|
||||||
|
// JMESPath: query string to query
|
||||||
Query string
|
Query string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ClientIpc: Framework to invoke ipc calls to the daemon
|
||||||
type ClientIpc interface {
|
type ClientIpc interface {
|
||||||
|
// CreateMesh: create a mesh network, return an error if the operation failed
|
||||||
CreateMesh(args *NewMeshArgs, reply *string) error
|
CreateMesh(args *NewMeshArgs, reply *string) error
|
||||||
|
// ListMesh: list mesh network the node is a part of, return an error if the operation failed
|
||||||
ListMeshes(args *ListMeshReply, reply *string) error
|
ListMeshes(args *ListMeshReply, reply *string) error
|
||||||
|
// JoinMesh: join a mesh network return an error if the operation failed
|
||||||
JoinMesh(args JoinMeshArgs, reply *string) error
|
JoinMesh(args JoinMeshArgs, reply *string) error
|
||||||
|
// LeaveMesh: leave a mesh network, return an error if the operation failed
|
||||||
LeaveMesh(meshId string, reply *string) error
|
LeaveMesh(meshId string, reply *string) error
|
||||||
|
// GetMesh: get the given mesh network, return an error if the operation failed
|
||||||
GetMesh(meshId string, reply *GetMeshReply) error
|
GetMesh(meshId string, reply *GetMeshReply) error
|
||||||
|
// Query: query the given mesh network
|
||||||
Query(query QueryMesh, reply *string) error
|
Query(query QueryMesh, reply *string) error
|
||||||
|
// PutDescription: assign a description to yourself
|
||||||
PutDescription(args PutDescriptionArgs, reply *string) error
|
PutDescription(args PutDescriptionArgs, reply *string) error
|
||||||
|
// PutAlias: assign an alias to yourself
|
||||||
PutAlias(args PutAliasArgs, reply *string) error
|
PutAlias(args PutAliasArgs, reply *string) error
|
||||||
|
// PutService: assign a service to yourself
|
||||||
PutService(args PutServiceArgs, reply *string) error
|
PutService(args PutServiceArgs, reply *string) error
|
||||||
|
// DeleteService: retract a service
|
||||||
DeleteService(args DeleteServiceArgs, reply *string) error
|
DeleteService(args DeleteServiceArgs, reply *string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type SmegmeshIpc struct {
|
type SmegmeshIpc struct {
|
||||||
client *ipcRpc.Client
|
client *ipc.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClientIpc() (*SmegmeshIpc, error) {
|
func NewClientIpc() (*SmegmeshIpc, error) {
|
||||||
@ -164,7 +188,7 @@ func (c *SmegmeshIpc) DeleteService(args DeleteServiceArgs, reply *string) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *SmegmeshIpc) Close() error {
|
func (c *SmegmeshIpc) Close() error {
|
||||||
return c.Close()
|
return c.client.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunIpcHandler(server MeshIpc) error {
|
func RunIpcHandler(server MeshIpc) error {
|
||||||
|
@ -36,11 +36,13 @@ func ConsistentHash[V any, K any](values []V, client K, bucketFunc func(V) int,
|
|||||||
|
|
||||||
ourKey := keyFunc(client)
|
ourKey := keyFunc(client)
|
||||||
|
|
||||||
for _, record := range vs {
|
idx := sort.Search(len(vs), func(i int) bool {
|
||||||
if ourKey < record.value {
|
return vs[i].value >= ourKey
|
||||||
return record.record
|
})
|
||||||
}
|
|
||||||
|
if idx == len(vs) {
|
||||||
|
return vs[0].record
|
||||||
}
|
}
|
||||||
|
|
||||||
return vs[0].record
|
return vs[idx].record
|
||||||
}
|
}
|
||||||
|
@ -10,23 +10,17 @@ import (
|
|||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Maximum MTU to assin to WireGuard
|
||||||
|
// This isn't configurable
|
||||||
|
const WIREGUARD_MTU = 1420
|
||||||
|
|
||||||
|
// RtNetlinkConfig: represents an rtnetlkink configuration instance
|
||||||
type RtNetlinkConfig struct {
|
type RtNetlinkConfig struct {
|
||||||
|
// conn: connection to the rtnetlink API
|
||||||
conn *rtnetlink.Conn
|
conn *rtnetlink.Conn
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRtNetlinkConfig() (*RtNetlinkConfig, error) {
|
// CreateLink: Create a netlink interface if it does not exist. ifName is the name of the netlink interface
|
||||||
conn, err := rtnetlink.Dial(nil)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &RtNetlinkConfig{conn: conn}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
const WIREGUARD_MTU = 1420
|
|
||||||
|
|
||||||
// Create a netlink interface if it does not exist. ifName is the name of the netlink interface
|
|
||||||
func (c *RtNetlinkConfig) CreateLink(ifName string) error {
|
func (c *RtNetlinkConfig) CreateLink(ifName string) error {
|
||||||
_, err := net.InterfaceByName(ifName)
|
_, err := net.InterfaceByName(ifName)
|
||||||
|
|
||||||
@ -51,7 +45,7 @@ func (c *RtNetlinkConfig) CreateLink(ifName string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete link delete the specified interface
|
// DeleteLink: delete the specified interface
|
||||||
func (c *RtNetlinkConfig) DeleteLink(ifName string) error {
|
func (c *RtNetlinkConfig) DeleteLink(ifName string) error {
|
||||||
iface, err := net.InterfaceByName(ifName)
|
iface, err := net.InterfaceByName(ifName)
|
||||||
|
|
||||||
@ -68,7 +62,7 @@ func (c *RtNetlinkConfig) DeleteLink(ifName string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddAddress adds an address to the given interface.
|
// AddAddress: adds an address to the given interface.
|
||||||
func (c *RtNetlinkConfig) AddAddress(ifName string, address string) error {
|
func (c *RtNetlinkConfig) AddAddress(ifName string, address string) error {
|
||||||
iface, err := net.InterfaceByName(ifName)
|
iface, err := net.InterfaceByName(ifName)
|
||||||
|
|
||||||
@ -177,7 +171,7 @@ func (c *RtNetlinkConfig) AddRoute(ifName string, route Route) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteRoute deletes routes with the gateway and destination
|
// DeleteRoute: deletes routes with the gateway and destination
|
||||||
func (c *RtNetlinkConfig) DeleteRoute(ifName string, route Route) error {
|
func (c *RtNetlinkConfig) DeleteRoute(ifName string, route Route) error {
|
||||||
iface, err := net.InterfaceByName(ifName)
|
iface, err := net.InterfaceByName(ifName)
|
||||||
|
|
||||||
@ -219,6 +213,7 @@ func (c *RtNetlinkConfig) DeleteRoute(ifName string, route Route) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// route: represents a rout to add to the RIB
|
||||||
type Route struct {
|
type Route struct {
|
||||||
Gateway net.IP
|
Gateway net.IP
|
||||||
Destination net.IPNet
|
Destination net.IPNet
|
||||||
@ -232,7 +227,7 @@ func (r1 Route) equal(r2 Route) bool {
|
|||||||
(mask1Ones == 0 && mask2Ones == 0 || r1.Destination.IP.Equal(r2.Destination.IP))
|
(mask1Ones == 0 && mask2Ones == 0 || r1.Destination.IP.Equal(r2.Destination.IP))
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteRoutes deletes all routes not in exclude
|
// DeleteRoutes: deletes all routes not in exclude on the given interface
|
||||||
func (c *RtNetlinkConfig) DeleteRoutes(ifName string, family uint8, exclude ...Route) error {
|
func (c *RtNetlinkConfig) DeleteRoutes(ifName string, family uint8, exclude ...Route) error {
|
||||||
routes, err := c.listRoutes(ifName, family)
|
routes, err := c.listRoutes(ifName, family)
|
||||||
|
|
||||||
@ -282,7 +277,7 @@ func (c *RtNetlinkConfig) DeleteRoutes(ifName string, family uint8, exclude ...R
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// listRoutes lists all routes on the interface
|
// listRoutes: lists all routes on the interface
|
||||||
func (c *RtNetlinkConfig) listRoutes(ifName string, family uint8) ([]rtnetlink.RouteMessage, error) {
|
func (c *RtNetlinkConfig) listRoutes(ifName string, family uint8) ([]rtnetlink.RouteMessage, error) {
|
||||||
iface, err := net.InterfaceByName(ifName)
|
iface, err := net.InterfaceByName(ifName)
|
||||||
|
|
||||||
@ -304,6 +299,18 @@ func (c *RtNetlinkConfig) listRoutes(ifName string, family uint8) ([]rtnetlink.R
|
|||||||
return routes, nil
|
return routes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close: close the Rtnetlink API
|
||||||
func (c *RtNetlinkConfig) Close() error {
|
func (c *RtNetlinkConfig) Close() error {
|
||||||
return c.conn.Close()
|
return c.conn.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newRtNetlinkConfig: connect to the RtnetlinkAPI
|
||||||
|
func NewRtNetlinkConfig() (*RtNetlinkConfig, error) {
|
||||||
|
conn, err := rtnetlink.Dial(nil)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &RtNetlinkConfig{conn: conn}, nil
|
||||||
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package mesh
|
package mesh
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"net"
|
"net"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
@ -16,12 +15,13 @@ import (
|
|||||||
|
|
||||||
// MeshConfigApplyer abstracts applying the mesh configuration
|
// MeshConfigApplyer abstracts applying the mesh configuration
|
||||||
type MeshConfigApplyer interface {
|
type MeshConfigApplyer interface {
|
||||||
|
// ApplyConfig: apply the configurtation
|
||||||
ApplyConfig() error
|
ApplyConfig() error
|
||||||
RemovePeers(meshId string) error
|
// SetMeshManager: sets the associated manager
|
||||||
SetMeshManager(manager MeshManager)
|
SetMeshManager(manager MeshManager)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WgMeshConfigApplyer applies WireGuard configuration
|
// WgMeshConfigApplyer: applies WireGuard configuration
|
||||||
type WgMeshConfigApplyer struct {
|
type WgMeshConfigApplyer struct {
|
||||||
meshManager MeshManager
|
meshManager MeshManager
|
||||||
routeInstaller route.RouteInstaller
|
routeInstaller route.RouteInstaller
|
||||||
@ -196,6 +196,7 @@ func (m *WgMeshConfigApplyer) getCorrespondingPeer(peers []MeshNode, client Mesh
|
|||||||
return peer
|
return peer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getPeerCfgsToRemove: remove peer configurations that are no longer in the mesh
|
||||||
func (m *WgMeshConfigApplyer) getPeerCfgsToRemove(dev *wgtypes.Device, newPeers []wgtypes.PeerConfig) []wgtypes.PeerConfig {
|
func (m *WgMeshConfigApplyer) getPeerCfgsToRemove(dev *wgtypes.Device, newPeers []wgtypes.PeerConfig) []wgtypes.PeerConfig {
|
||||||
peers := dev.Peers
|
peers := dev.Peers
|
||||||
peers = lib.Filter(peers, func(p1 wgtypes.Peer) bool {
|
peers = lib.Filter(peers, func(p1 wgtypes.Peer) bool {
|
||||||
@ -220,6 +221,7 @@ type GetConfigParams struct {
|
|||||||
routes map[string][]routeNode
|
routes map[string][]routeNode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getClientConfig: if the node is a client get their configuration
|
||||||
func (m *WgMeshConfigApplyer) getClientConfig(params *GetConfigParams) (*wgtypes.Config, error) {
|
func (m *WgMeshConfigApplyer) getClientConfig(params *GetConfigParams) (*wgtypes.Config, error) {
|
||||||
ula := &ip.ULABuilder{}
|
ula := &ip.ULABuilder{}
|
||||||
meshNet, _ := ula.GetIPNet(params.mesh.GetMeshId())
|
meshNet, _ := ula.GetIPNet(params.mesh.GetMeshId())
|
||||||
@ -281,6 +283,8 @@ func (m *WgMeshConfigApplyer) getClientConfig(params *GetConfigParams) (*wgtypes
|
|||||||
return &cfg, err
|
return &cfg, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getRoutesToInstall: work out if the given node is advertising routes that should be installed into the
|
||||||
|
// RIB
|
||||||
func (m *WgMeshConfigApplyer) getRoutesToInstall(wgNode *wgtypes.PeerConfig, mesh MeshProvider, node MeshNode) []lib.Route {
|
func (m *WgMeshConfigApplyer) getRoutesToInstall(wgNode *wgtypes.PeerConfig, mesh MeshProvider, node MeshNode) []lib.Route {
|
||||||
routes := make([]lib.Route, 0)
|
routes := make([]lib.Route, 0)
|
||||||
|
|
||||||
@ -301,6 +305,7 @@ func (m *WgMeshConfigApplyer) getRoutesToInstall(wgNode *wgtypes.PeerConfig, mes
|
|||||||
return routes
|
return routes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getPeerConfig: creates the WireGuard configuration for a peer
|
||||||
func (m *WgMeshConfigApplyer) getPeerConfig(params *GetConfigParams) (*wgtypes.Config, error) {
|
func (m *WgMeshConfigApplyer) getPeerConfig(params *GetConfigParams) (*wgtypes.Config, error) {
|
||||||
peerToClients := make(map[string][]net.IPNet)
|
peerToClients := make(map[string][]net.IPNet)
|
||||||
installedRoutes := make([]lib.Route, 0)
|
installedRoutes := make([]lib.Route, 0)
|
||||||
@ -374,6 +379,7 @@ func (m *WgMeshConfigApplyer) getPeerConfig(params *GetConfigParams) (*wgtypes.C
|
|||||||
return &cfg, err
|
return &cfg, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// updateWgConf: update the WireGuard configuration
|
||||||
func (m *WgMeshConfigApplyer) updateWgConf(mesh MeshProvider, routes map[string][]routeNode) error {
|
func (m *WgMeshConfigApplyer) updateWgConf(mesh MeshProvider, routes map[string][]routeNode) error {
|
||||||
snap, err := mesh.GetMesh()
|
snap, err := mesh.GetMesh()
|
||||||
|
|
||||||
@ -435,6 +441,8 @@ func (m *WgMeshConfigApplyer) updateWgConf(mesh MeshProvider, routes map[string]
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getAllRoutes: works out all the routes to install out of all the routes in the
|
||||||
|
// set of networks the node is a part of
|
||||||
func (m *WgMeshConfigApplyer) getAllRoutes() (map[string][]routeNode, error) {
|
func (m *WgMeshConfigApplyer) getAllRoutes() (map[string][]routeNode, error) {
|
||||||
allRoutes := make(map[string][]routeNode)
|
allRoutes := make(map[string][]routeNode)
|
||||||
|
|
||||||
@ -464,6 +472,7 @@ func (m *WgMeshConfigApplyer) getAllRoutes() (map[string][]routeNode, error) {
|
|||||||
return allRoutes, nil
|
return allRoutes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ApplyConfig: apply the WireGuard configuration
|
||||||
func (m *WgMeshConfigApplyer) ApplyConfig() error {
|
func (m *WgMeshConfigApplyer) ApplyConfig() error {
|
||||||
allRoutes, err := m.getAllRoutes()
|
allRoutes, err := m.getAllRoutes()
|
||||||
|
|
||||||
@ -482,27 +491,6 @@ func (m *WgMeshConfigApplyer) ApplyConfig() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *WgMeshConfigApplyer) RemovePeers(meshId string) error {
|
|
||||||
mesh := m.meshManager.GetMesh(meshId)
|
|
||||||
|
|
||||||
if mesh == nil {
|
|
||||||
return fmt.Errorf("mesh %s does not exist", meshId)
|
|
||||||
}
|
|
||||||
|
|
||||||
dev, err := mesh.GetDevice()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
m.meshManager.GetClient().ConfigureDevice(dev.Name, wgtypes.Config{
|
|
||||||
Peers: make([]wgtypes.PeerConfig, 0),
|
|
||||||
ReplacePeers: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *WgMeshConfigApplyer) SetMeshManager(manager MeshManager) {
|
func (m *WgMeshConfigApplyer) SetMeshManager(manager MeshManager) {
|
||||||
m.meshManager = manager
|
m.meshManager = manager
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,8 @@ import (
|
|||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// MeshManager: abstracts maanging meshes, including installing the WireGuard configuration
|
||||||
|
// to the device, and adding and removing nodes
|
||||||
type MeshManager interface {
|
type MeshManager interface {
|
||||||
CreateMesh(params *CreateMeshParams) (string, error)
|
CreateMesh(params *CreateMeshParams) (string, error)
|
||||||
AddMesh(params *AddMeshParams) error
|
AddMesh(params *AddMeshParams) error
|
||||||
@ -39,12 +41,10 @@ type MeshManager interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type MeshManagerImpl struct {
|
type MeshManagerImpl struct {
|
||||||
lock sync.RWMutex
|
meshLock sync.RWMutex
|
||||||
Meshes map[string]MeshProvider
|
meshes map[string]MeshProvider
|
||||||
RouteManager RouteManager
|
RouteManager RouteManager
|
||||||
Client *wgctrl.Client
|
Client *wgctrl.Client
|
||||||
// HostParameters contains information that uniquely locates
|
|
||||||
// the node in the mesh network.
|
|
||||||
HostParameters *HostParameters
|
HostParameters *HostParameters
|
||||||
conf *conf.DaemonConfiguration
|
conf *conf.DaemonConfiguration
|
||||||
meshProviderFactory MeshProviderFactory
|
meshProviderFactory MeshProviderFactory
|
||||||
@ -57,12 +57,11 @@ type MeshManagerImpl struct {
|
|||||||
OnDelete func(MeshProvider)
|
OnDelete func(MeshProvider)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRouteManager implements MeshManager.
|
|
||||||
func (m *MeshManagerImpl) GetRouteManager() RouteManager {
|
func (m *MeshManagerImpl) GetRouteManager() RouteManager {
|
||||||
return m.RouteManager
|
return m.RouteManager
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveService implements MeshManager.
|
// RemoveService: remove a service from the given mesh.
|
||||||
func (m *MeshManagerImpl) RemoveService(meshId, service string) error {
|
func (m *MeshManagerImpl) RemoveService(meshId, service string) error {
|
||||||
mesh := m.GetMesh(meshId)
|
mesh := m.GetMesh(meshId)
|
||||||
|
|
||||||
@ -77,7 +76,7 @@ func (m *MeshManagerImpl) RemoveService(meshId, service string) error {
|
|||||||
return mesh.RemoveService(m.HostParameters.GetPublicKey(), service)
|
return mesh.RemoveService(m.HostParameters.GetPublicKey(), service)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetService implements MeshManager.
|
// SetService: add a service to the given mesh
|
||||||
func (m *MeshManagerImpl) SetService(meshId, service, value string) error {
|
func (m *MeshManagerImpl) SetService(meshId, service, value string) error {
|
||||||
mesh := m.GetMesh(meshId)
|
mesh := m.GetMesh(meshId)
|
||||||
|
|
||||||
@ -92,8 +91,9 @@ func (m *MeshManagerImpl) SetService(meshId, service, value string) error {
|
|||||||
return mesh.AddService(m.HostParameters.GetPublicKey(), service, value)
|
return mesh.AddService(m.HostParameters.GetPublicKey(), service, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetNode: gets the node with given id in the mesh network
|
||||||
func (m *MeshManagerImpl) GetNode(meshid, nodeId string) MeshNode {
|
func (m *MeshManagerImpl) GetNode(meshid, nodeId string) MeshNode {
|
||||||
mesh, ok := m.Meshes[meshid]
|
mesh, ok := m.meshes[meshid]
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
@ -176,9 +176,9 @@ func (m *MeshManagerImpl) CreateMesh(args *CreateMeshParams) (string, error) {
|
|||||||
return "", fmt.Errorf("error creating mesh: %w", err)
|
return "", fmt.Errorf("error creating mesh: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
m.lock.Lock()
|
m.meshLock.Lock()
|
||||||
m.Meshes[meshId] = nodeManager
|
m.meshes[meshId] = nodeManager
|
||||||
m.lock.Unlock()
|
m.meshLock.Unlock()
|
||||||
|
|
||||||
m.cmdRunner.RunCommands(m.conf.BaseConfiguration.PostUp...)
|
m.cmdRunner.RunCommands(m.conf.BaseConfiguration.PostUp...)
|
||||||
|
|
||||||
@ -192,7 +192,7 @@ type AddMeshParams struct {
|
|||||||
Conf *conf.WgConfiguration
|
Conf *conf.WgConfiguration
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddMesh: Add the mesh to the list of meshes
|
// AddMesh: Add a new mesh network to the list of addresses
|
||||||
func (m *MeshManagerImpl) AddMesh(params *AddMeshParams) error {
|
func (m *MeshManagerImpl) AddMesh(params *AddMeshParams) error {
|
||||||
var ifName string
|
var ifName string
|
||||||
var err error
|
var err error
|
||||||
@ -235,20 +235,20 @@ func (m *MeshManagerImpl) AddMesh(params *AddMeshParams) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
m.lock.Lock()
|
m.meshLock.Lock()
|
||||||
m.Meshes[params.MeshId] = meshProvider
|
m.meshes[params.MeshId] = meshProvider
|
||||||
m.lock.Unlock()
|
m.meshLock.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasChanges returns true if the mesh has changes
|
// HasChanges: returns true if the mesh has changes
|
||||||
func (m *MeshManagerImpl) HasChanges(meshId string) bool {
|
func (m *MeshManagerImpl) HasChanges(meshId string) bool {
|
||||||
return m.Meshes[meshId].HasChanges()
|
return m.meshes[meshId].HasChanges()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMesh returns the mesh with the given meshid
|
// GetMesh: returns the mesh with the given meshid
|
||||||
func (m *MeshManagerImpl) GetMesh(meshId string) MeshProvider {
|
func (m *MeshManagerImpl) GetMesh(meshId string) MeshProvider {
|
||||||
theMesh := m.Meshes[meshId]
|
theMesh := m.meshes[meshId]
|
||||||
return theMesh
|
return theMesh
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,6 +258,8 @@ func (s *MeshManagerImpl) GetPublicKey() *wgtypes.Key {
|
|||||||
return &key
|
return &key
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddSelfParams: parameters required to add yourself to a mesh
|
||||||
|
// network
|
||||||
type AddSelfParams struct {
|
type AddSelfParams struct {
|
||||||
// MeshId is the ID of the mesh to add this instance to
|
// MeshId is the ID of the mesh to add this instance to
|
||||||
MeshId string
|
MeshId string
|
||||||
@ -267,7 +269,7 @@ type AddSelfParams struct {
|
|||||||
Endpoint string
|
Endpoint string
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddSelf adds this host to the mesh
|
// AddSelf: adds this host to the mesh
|
||||||
func (s *MeshManagerImpl) AddSelf(params *AddSelfParams) error {
|
func (s *MeshManagerImpl) AddSelf(params *AddSelfParams) error {
|
||||||
mesh := s.GetMesh(params.MeshId)
|
mesh := s.GetMesh(params.MeshId)
|
||||||
|
|
||||||
@ -341,11 +343,11 @@ func (s *MeshManagerImpl) AddSelf(params *AddSelfParams) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Meshes[params.MeshId].AddNode(node)
|
s.meshes[params.MeshId].AddNode(node)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LeaveMesh leaves the mesh network
|
// LeaveMesh: leaves the mesh network
|
||||||
func (s *MeshManagerImpl) LeaveMesh(meshId string) error {
|
func (s *MeshManagerImpl) LeaveMesh(meshId string) error {
|
||||||
mesh := s.GetMesh(meshId)
|
mesh := s.GetMesh(meshId)
|
||||||
|
|
||||||
@ -363,9 +365,9 @@ func (s *MeshManagerImpl) LeaveMesh(meshId string) error {
|
|||||||
s.OnDelete(mesh)
|
s.OnDelete(mesh)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.lock.Lock()
|
s.meshLock.Lock()
|
||||||
delete(s.Meshes, meshId)
|
delete(s.meshes, meshId)
|
||||||
s.lock.Unlock()
|
s.meshLock.Unlock()
|
||||||
|
|
||||||
s.cmdRunner.RunCommands(s.conf.BaseConfiguration.PreDown...)
|
s.cmdRunner.RunCommands(s.conf.BaseConfiguration.PreDown...)
|
||||||
|
|
||||||
@ -388,7 +390,7 @@ func (s *MeshManagerImpl) LeaveMesh(meshId string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *MeshManagerImpl) GetSelf(meshId string) (MeshNode, error) {
|
func (s *MeshManagerImpl) GetSelf(meshId string) (MeshNode, error) {
|
||||||
meshInstance, ok := s.Meshes[meshId]
|
meshInstance, ok := s.meshes[meshId]
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("mesh %s does not exist", meshId)
|
return nil, fmt.Errorf("mesh %s does not exist", meshId)
|
||||||
@ -403,11 +405,12 @@ func (s *MeshManagerImpl) GetSelf(meshId string) (MeshNode, error) {
|
|||||||
return node, nil
|
return node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ApplyConfig: applies the WireGuard configuration
|
||||||
|
// adds routes to the RIB and so forth.
|
||||||
func (s *MeshManagerImpl) ApplyConfig() error {
|
func (s *MeshManagerImpl) ApplyConfig() error {
|
||||||
if s.conf.StubWg {
|
if s.conf.StubWg {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.configApplyer.ApplyConfig()
|
return s.configApplyer.ApplyConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,7 +428,7 @@ func (s *MeshManagerImpl) SetDescription(meshId, description string) error {
|
|||||||
return mesh.SetDescription(s.HostParameters.GetPublicKey(), description)
|
return mesh.SetDescription(s.HostParameters.GetPublicKey(), description)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetAlias implements MeshManager.
|
// SetAlias sets the alias of the node for the given meshid
|
||||||
func (s *MeshManagerImpl) SetAlias(meshId, alias string) error {
|
func (s *MeshManagerImpl) SetAlias(meshId, alias string) error {
|
||||||
mesh := s.GetMesh(meshId)
|
mesh := s.GetMesh(meshId)
|
||||||
|
|
||||||
@ -440,7 +443,8 @@ func (s *MeshManagerImpl) SetAlias(meshId, alias string) error {
|
|||||||
return mesh.SetAlias(s.HostParameters.GetPublicKey(), alias)
|
return mesh.SetAlias(s.HostParameters.GetPublicKey(), alias)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateTimeStamp updates the timestamp of this node in all meshes
|
// UpdateTimeStamp: updates the timestamp of this node in all meshes
|
||||||
|
// essentially performs heartbeat if the node is the leader
|
||||||
func (s *MeshManagerImpl) UpdateTimeStamp() error {
|
func (s *MeshManagerImpl) UpdateTimeStamp() error {
|
||||||
meshes := s.GetMeshes()
|
meshes := s.GetMeshes()
|
||||||
for _, mesh := range meshes {
|
for _, mesh := range meshes {
|
||||||
@ -460,26 +464,27 @@ func (s *MeshManagerImpl) GetClient() *wgctrl.Client {
|
|||||||
return s.Client
|
return s.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetMeshes: get all meshes the node is part of
|
||||||
func (s *MeshManagerImpl) GetMeshes() map[string]MeshProvider {
|
func (s *MeshManagerImpl) GetMeshes() map[string]MeshProvider {
|
||||||
meshes := make(map[string]MeshProvider)
|
meshes := make(map[string]MeshProvider)
|
||||||
|
|
||||||
s.lock.RLock()
|
s.meshLock.RLock()
|
||||||
|
|
||||||
for id, mesh := range s.Meshes {
|
for id, mesh := range s.meshes {
|
||||||
meshes[id] = mesh
|
meshes[id] = mesh
|
||||||
}
|
}
|
||||||
|
|
||||||
s.lock.RUnlock()
|
s.meshLock.RUnlock()
|
||||||
return meshes
|
return meshes
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the mesh manager
|
// Close: close the mesh manager
|
||||||
func (s *MeshManagerImpl) Close() error {
|
func (s *MeshManagerImpl) Close() error {
|
||||||
if s.conf.StubWg {
|
if s.conf.StubWg {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, mesh := range s.Meshes {
|
for _, mesh := range s.meshes {
|
||||||
dev, err := mesh.GetDevice()
|
dev, err := mesh.GetDevice()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -496,7 +501,7 @@ func (s *MeshManagerImpl) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMeshManagerParams params required to create an instance of a mesh manager
|
// NewMeshManagerParams: params required to create an instance of a mesh manager
|
||||||
type NewMeshManagerParams struct {
|
type NewMeshManagerParams struct {
|
||||||
Conf conf.DaemonConfiguration
|
Conf conf.DaemonConfiguration
|
||||||
Client *wgctrl.Client
|
Client *wgctrl.Client
|
||||||
@ -511,7 +516,7 @@ type NewMeshManagerParams struct {
|
|||||||
OnDelete func(MeshProvider)
|
OnDelete func(MeshProvider)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a new instance of a mesh manager with the given parameters
|
// NewMeshManager: Creates a new instance of a mesh manager with the given parameters
|
||||||
func NewMeshManager(params *NewMeshManagerParams) MeshManager {
|
func NewMeshManager(params *NewMeshManagerParams) MeshManager {
|
||||||
privateKey, _ := wgtypes.GeneratePrivateKey()
|
privateKey, _ := wgtypes.GeneratePrivateKey()
|
||||||
hostParams := HostParameters{
|
hostParams := HostParameters{
|
||||||
@ -519,7 +524,7 @@ func NewMeshManager(params *NewMeshManagerParams) MeshManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
m := &MeshManagerImpl{
|
m := &MeshManagerImpl{
|
||||||
Meshes: make(map[string]MeshProvider),
|
meshes: make(map[string]MeshProvider),
|
||||||
HostParameters: &hostParams,
|
HostParameters: &hostParams,
|
||||||
meshProviderFactory: params.MeshProvider,
|
meshProviderFactory: params.MeshProvider,
|
||||||
nodeFactory: params.NodeFactory,
|
nodeFactory: params.NodeFactory,
|
||||||
|
@ -1,235 +0,0 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
|
||||||
// versions:
|
|
||||||
// protoc-gen-go v1.28.1
|
|
||||||
// protoc v3.21.12
|
|
||||||
// source: pkg/grpc/ctrlserver/authentication.proto
|
|
||||||
|
|
||||||
package rpc
|
|
||||||
|
|
||||||
import (
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
|
||||||
reflect "reflect"
|
|
||||||
sync "sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Verify that this generated code is sufficiently up-to-date.
|
|
||||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
|
||||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
|
||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
|
||||||
)
|
|
||||||
|
|
||||||
type JoinAuthMeshRequest struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
MeshId string `protobuf:"bytes,1,opt,name=meshId,proto3" json:"meshId,omitempty"`
|
|
||||||
Alias string `protobuf:"bytes,2,opt,name=alias,proto3" json:"alias,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *JoinAuthMeshRequest) Reset() {
|
|
||||||
*x = JoinAuthMeshRequest{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_pkg_grpc_ctrlserver_authentication_proto_msgTypes[0]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *JoinAuthMeshRequest) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*JoinAuthMeshRequest) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *JoinAuthMeshRequest) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_pkg_grpc_ctrlserver_authentication_proto_msgTypes[0]
|
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use JoinAuthMeshRequest.ProtoReflect.Descriptor instead.
|
|
||||||
func (*JoinAuthMeshRequest) Descriptor() ([]byte, []int) {
|
|
||||||
return file_pkg_grpc_ctrlserver_authentication_proto_rawDescGZIP(), []int{0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *JoinAuthMeshRequest) GetMeshId() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.MeshId
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *JoinAuthMeshRequest) GetAlias() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.Alias
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
type JoinAuthMeshReply struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
|
|
||||||
Token *string `protobuf:"bytes,2,opt,name=token,proto3,oneof" json:"token,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *JoinAuthMeshReply) Reset() {
|
|
||||||
*x = JoinAuthMeshReply{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_pkg_grpc_ctrlserver_authentication_proto_msgTypes[1]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *JoinAuthMeshReply) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*JoinAuthMeshReply) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *JoinAuthMeshReply) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_pkg_grpc_ctrlserver_authentication_proto_msgTypes[1]
|
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use JoinAuthMeshReply.ProtoReflect.Descriptor instead.
|
|
||||||
func (*JoinAuthMeshReply) Descriptor() ([]byte, []int) {
|
|
||||||
return file_pkg_grpc_ctrlserver_authentication_proto_rawDescGZIP(), []int{1}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *JoinAuthMeshReply) GetSuccess() bool {
|
|
||||||
if x != nil {
|
|
||||||
return x.Success
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *JoinAuthMeshReply) GetToken() string {
|
|
||||||
if x != nil && x.Token != nil {
|
|
||||||
return *x.Token
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
var File_pkg_grpc_ctrlserver_authentication_proto protoreflect.FileDescriptor
|
|
||||||
|
|
||||||
var file_pkg_grpc_ctrlserver_authentication_proto_rawDesc = []byte{
|
|
||||||
0x0a, 0x28, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x74, 0x72, 0x6c, 0x73,
|
|
||||||
0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61,
|
|
||||||
0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x72, 0x70, 0x63, 0x74,
|
|
||||||
0x79, 0x70, 0x65, 0x73, 0x22, 0x43, 0x0a, 0x13, 0x4a, 0x6f, 0x69, 0x6e, 0x41, 0x75, 0x74, 0x68,
|
|
||||||
0x4d, 0x65, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6d,
|
|
||||||
0x65, 0x73, 0x68, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x73,
|
|
||||||
0x68, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x02, 0x20, 0x01,
|
|
||||||
0x28, 0x09, 0x52, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x22, 0x52, 0x0a, 0x11, 0x4a, 0x6f, 0x69,
|
|
||||||
0x6e, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x73, 0x68, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18,
|
|
||||||
0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52,
|
|
||||||
0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x19, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65,
|
|
||||||
0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e,
|
|
||||||
0x88, 0x01, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x32, 0x5a, 0x0a,
|
|
||||||
0x0e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12,
|
|
||||||
0x48, 0x0a, 0x08, 0x4a, 0x6f, 0x69, 0x6e, 0x4d, 0x65, 0x73, 0x68, 0x12, 0x1d, 0x2e, 0x72, 0x70,
|
|
||||||
0x63, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4a, 0x6f, 0x69, 0x6e, 0x41, 0x75, 0x74, 0x68, 0x4d,
|
|
||||||
0x65, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x72, 0x70, 0x63,
|
|
||||||
0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4a, 0x6f, 0x69, 0x6e, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65,
|
|
||||||
0x73, 0x68, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, 0x09, 0x5a, 0x07, 0x70, 0x6b, 0x67,
|
|
||||||
0x2f, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
file_pkg_grpc_ctrlserver_authentication_proto_rawDescOnce sync.Once
|
|
||||||
file_pkg_grpc_ctrlserver_authentication_proto_rawDescData = file_pkg_grpc_ctrlserver_authentication_proto_rawDesc
|
|
||||||
)
|
|
||||||
|
|
||||||
func file_pkg_grpc_ctrlserver_authentication_proto_rawDescGZIP() []byte {
|
|
||||||
file_pkg_grpc_ctrlserver_authentication_proto_rawDescOnce.Do(func() {
|
|
||||||
file_pkg_grpc_ctrlserver_authentication_proto_rawDescData = protoimpl.X.CompressGZIP(file_pkg_grpc_ctrlserver_authentication_proto_rawDescData)
|
|
||||||
})
|
|
||||||
return file_pkg_grpc_ctrlserver_authentication_proto_rawDescData
|
|
||||||
}
|
|
||||||
|
|
||||||
var file_pkg_grpc_ctrlserver_authentication_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
|
||||||
var file_pkg_grpc_ctrlserver_authentication_proto_goTypes = []interface{}{
|
|
||||||
(*JoinAuthMeshRequest)(nil), // 0: rpctypes.JoinAuthMeshRequest
|
|
||||||
(*JoinAuthMeshReply)(nil), // 1: rpctypes.JoinAuthMeshReply
|
|
||||||
}
|
|
||||||
var file_pkg_grpc_ctrlserver_authentication_proto_depIdxs = []int32{
|
|
||||||
0, // 0: rpctypes.Authentication.JoinMesh:input_type -> rpctypes.JoinAuthMeshRequest
|
|
||||||
1, // 1: rpctypes.Authentication.JoinMesh:output_type -> rpctypes.JoinAuthMeshReply
|
|
||||||
1, // [1:2] is the sub-list for method output_type
|
|
||||||
0, // [0:1] is the sub-list for method input_type
|
|
||||||
0, // [0:0] is the sub-list for extension type_name
|
|
||||||
0, // [0:0] is the sub-list for extension extendee
|
|
||||||
0, // [0:0] is the sub-list for field type_name
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() { file_pkg_grpc_ctrlserver_authentication_proto_init() }
|
|
||||||
func file_pkg_grpc_ctrlserver_authentication_proto_init() {
|
|
||||||
if File_pkg_grpc_ctrlserver_authentication_proto != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !protoimpl.UnsafeEnabled {
|
|
||||||
file_pkg_grpc_ctrlserver_authentication_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*JoinAuthMeshRequest); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_pkg_grpc_ctrlserver_authentication_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*JoinAuthMeshReply); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_pkg_grpc_ctrlserver_authentication_proto_msgTypes[1].OneofWrappers = []interface{}{}
|
|
||||||
type x struct{}
|
|
||||||
out := protoimpl.TypeBuilder{
|
|
||||||
File: protoimpl.DescBuilder{
|
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
|
||||||
RawDescriptor: file_pkg_grpc_ctrlserver_authentication_proto_rawDesc,
|
|
||||||
NumEnums: 0,
|
|
||||||
NumMessages: 2,
|
|
||||||
NumExtensions: 0,
|
|
||||||
NumServices: 1,
|
|
||||||
},
|
|
||||||
GoTypes: file_pkg_grpc_ctrlserver_authentication_proto_goTypes,
|
|
||||||
DependencyIndexes: file_pkg_grpc_ctrlserver_authentication_proto_depIdxs,
|
|
||||||
MessageInfos: file_pkg_grpc_ctrlserver_authentication_proto_msgTypes,
|
|
||||||
}.Build()
|
|
||||||
File_pkg_grpc_ctrlserver_authentication_proto = out.File
|
|
||||||
file_pkg_grpc_ctrlserver_authentication_proto_rawDesc = nil
|
|
||||||
file_pkg_grpc_ctrlserver_authentication_proto_goTypes = nil
|
|
||||||
file_pkg_grpc_ctrlserver_authentication_proto_depIdxs = nil
|
|
||||||
}
|
|
@ -1,105 +0,0 @@
|
|||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
|
||||||
// versions:
|
|
||||||
// - protoc-gen-go-grpc v1.2.0
|
|
||||||
// - protoc v3.21.12
|
|
||||||
// source: pkg/grpc/ctrlserver/authentication.proto
|
|
||||||
|
|
||||||
package rpc
|
|
||||||
|
|
||||||
import (
|
|
||||||
context "context"
|
|
||||||
grpc "google.golang.org/grpc"
|
|
||||||
codes "google.golang.org/grpc/codes"
|
|
||||||
status "google.golang.org/grpc/status"
|
|
||||||
)
|
|
||||||
|
|
||||||
// This is a compile-time assertion to ensure that this generated file
|
|
||||||
// is compatible with the grpc package it is being compiled against.
|
|
||||||
// Requires gRPC-Go v1.32.0 or later.
|
|
||||||
const _ = grpc.SupportPackageIsVersion7
|
|
||||||
|
|
||||||
// AuthenticationClient is the client API for Authentication service.
|
|
||||||
//
|
|
||||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
|
||||||
type AuthenticationClient interface {
|
|
||||||
JoinMesh(ctx context.Context, in *JoinAuthMeshRequest, opts ...grpc.CallOption) (*JoinAuthMeshReply, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type authenticationClient struct {
|
|
||||||
cc grpc.ClientConnInterface
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewAuthenticationClient(cc grpc.ClientConnInterface) AuthenticationClient {
|
|
||||||
return &authenticationClient{cc}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *authenticationClient) JoinMesh(ctx context.Context, in *JoinAuthMeshRequest, opts ...grpc.CallOption) (*JoinAuthMeshReply, error) {
|
|
||||||
out := new(JoinAuthMeshReply)
|
|
||||||
err := c.cc.Invoke(ctx, "/rpctypes.Authentication/JoinMesh", in, out, opts...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AuthenticationServer is the server API for Authentication service.
|
|
||||||
// All implementations must embed UnimplementedAuthenticationServer
|
|
||||||
// for forward compatibility
|
|
||||||
type AuthenticationServer interface {
|
|
||||||
JoinMesh(context.Context, *JoinAuthMeshRequest) (*JoinAuthMeshReply, error)
|
|
||||||
mustEmbedUnimplementedAuthenticationServer()
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnimplementedAuthenticationServer must be embedded to have forward compatible implementations.
|
|
||||||
type UnimplementedAuthenticationServer struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (UnimplementedAuthenticationServer) JoinMesh(context.Context, *JoinAuthMeshRequest) (*JoinAuthMeshReply, error) {
|
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method JoinMesh not implemented")
|
|
||||||
}
|
|
||||||
func (UnimplementedAuthenticationServer) mustEmbedUnimplementedAuthenticationServer() {}
|
|
||||||
|
|
||||||
// UnsafeAuthenticationServer may be embedded to opt out of forward compatibility for this service.
|
|
||||||
// Use of this interface is not recommended, as added methods to AuthenticationServer will
|
|
||||||
// result in compilation errors.
|
|
||||||
type UnsafeAuthenticationServer interface {
|
|
||||||
mustEmbedUnimplementedAuthenticationServer()
|
|
||||||
}
|
|
||||||
|
|
||||||
func RegisterAuthenticationServer(s grpc.ServiceRegistrar, srv AuthenticationServer) {
|
|
||||||
s.RegisterService(&Authentication_ServiceDesc, srv)
|
|
||||||
}
|
|
||||||
|
|
||||||
func _Authentication_JoinMesh_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
|
||||||
in := new(JoinAuthMeshRequest)
|
|
||||||
if err := dec(in); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if interceptor == nil {
|
|
||||||
return srv.(AuthenticationServer).JoinMesh(ctx, in)
|
|
||||||
}
|
|
||||||
info := &grpc.UnaryServerInfo{
|
|
||||||
Server: srv,
|
|
||||||
FullMethod: "/rpctypes.Authentication/JoinMesh",
|
|
||||||
}
|
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
|
||||||
return srv.(AuthenticationServer).JoinMesh(ctx, req.(*JoinAuthMeshRequest))
|
|
||||||
}
|
|
||||||
return interceptor(ctx, in, info, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Authentication_ServiceDesc is the grpc.ServiceDesc for Authentication service.
|
|
||||||
// It's only intended for direct use with grpc.RegisterService,
|
|
||||||
// and not to be introspected or modified (even as a copy)
|
|
||||||
var Authentication_ServiceDesc = grpc.ServiceDesc{
|
|
||||||
ServiceName: "rpctypes.Authentication",
|
|
||||||
HandlerType: (*AuthenticationServer)(nil),
|
|
||||||
Methods: []grpc.MethodDesc{
|
|
||||||
{
|
|
||||||
MethodName: "JoinMesh",
|
|
||||||
Handler: _Authentication_JoinMesh_Handler,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Streams: []grpc.StreamDesc{},
|
|
||||||
Metadata: "pkg/grpc/ctrlserver/authentication.proto",
|
|
||||||
}
|
|
@ -16,34 +16,33 @@ import (
|
|||||||
|
|
||||||
// Syncer: picks random nodes from the meshs
|
// Syncer: picks random nodes from the meshs
|
||||||
type Syncer interface {
|
type Syncer interface {
|
||||||
Sync(theMesh mesh.MeshProvider) error
|
Sync(theMesh mesh.MeshProvider) (bool, error)
|
||||||
SyncMeshes() error
|
SyncMeshes() error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SyncerImpl: implementation of a syncer to sync meshes
|
||||||
type SyncerImpl struct {
|
type SyncerImpl struct {
|
||||||
manager mesh.MeshManager
|
meshManager mesh.MeshManager
|
||||||
requester SyncRequester
|
requester SyncRequester
|
||||||
infectionCount int
|
infectionCount int
|
||||||
syncCount int
|
syncCount int
|
||||||
cluster conn.ConnCluster
|
cluster conn.ConnCluster
|
||||||
conf *conf.DaemonConfiguration
|
configuration *conf.DaemonConfiguration
|
||||||
lastSync map[string]int64
|
lastSync map[string]int64
|
||||||
lock sync.RWMutex
|
lastPoll map[string]int64
|
||||||
|
lastSyncLock sync.RWMutex
|
||||||
|
lastPollLock sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync: Sync with random nodes
|
// Sync: Sync with random nodes. Returns true if there was changes false otherwise
|
||||||
func (s *SyncerImpl) Sync(correspondingMesh mesh.MeshProvider) error {
|
func (s *SyncerImpl) Sync(correspondingMesh mesh.MeshProvider) (bool, error) {
|
||||||
if correspondingMesh == nil {
|
if correspondingMesh == nil {
|
||||||
return fmt.Errorf("mesh provided was nil cannot sync nil mesh")
|
return false, fmt.Errorf("mesh provided was nil cannot sync nil mesh")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Self can be nil if the node is removed
|
// Self can be nil if the node is removed
|
||||||
selfID := s.manager.GetPublicKey()
|
selfID := s.meshManager.GetPublicKey()
|
||||||
self, err := correspondingMesh.GetNode(selfID.String())
|
self, _ := correspondingMesh.GetNode(selfID.String())
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
logging.Log.WriteErrorf(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
correspondingMesh.Prune()
|
correspondingMesh.Prune()
|
||||||
|
|
||||||
@ -56,21 +55,21 @@ func (s *SyncerImpl) Sync(correspondingMesh mesh.MeshProvider) error {
|
|||||||
logging.Log.WriteInfof("no changes for %s", correspondingMesh.GetMeshId())
|
logging.Log.WriteInfof("no changes for %s", correspondingMesh.GetMeshId())
|
||||||
|
|
||||||
// If not synchronised in certain time pull from random neighbour
|
// If not synchronised in certain time pull from random neighbour
|
||||||
if s.conf.PullTime != 0 && time.Now().Unix()-s.lastSync[correspondingMesh.GetMeshId()] > int64(s.conf.PullTime) {
|
if s.configuration.PullTime != 0 && time.Now().Unix()-s.lastSync[correspondingMesh.GetMeshId()] > int64(s.configuration.PullTime) {
|
||||||
return s.Pull(self, correspondingMesh)
|
return s.Pull(self, correspondingMesh)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
before := time.Now()
|
before := time.Now()
|
||||||
err = s.manager.GetRouteManager().UpdateRoutes()
|
err := s.meshManager.GetRouteManager().UpdateRoutes()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logging.Log.WriteErrorf(err.Error())
|
logging.Log.WriteErrorf(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
publicKey := s.manager.GetPublicKey()
|
publicKey := s.meshManager.GetPublicKey()
|
||||||
nodeNames := correspondingMesh.GetPeers()
|
nodeNames := correspondingMesh.GetPeers()
|
||||||
|
|
||||||
nodeNames = lib.Filter(nodeNames, func(s string) bool {
|
nodeNames = lib.Filter(nodeNames, func(s string) bool {
|
||||||
@ -85,7 +84,7 @@ func (s *SyncerImpl) Sync(correspondingMesh mesh.MeshProvider) error {
|
|||||||
neighbours := s.cluster.GetNeighbours(nodeNames, publicKey.String())
|
neighbours := s.cluster.GetNeighbours(nodeNames, publicKey.String())
|
||||||
|
|
||||||
if len(neighbours) == 0 {
|
if len(neighbours) == 0 {
|
||||||
return nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Peer with 2 nodes so that there is redundnacy in
|
// Peer with 2 nodes so that there is redundnacy in
|
||||||
@ -94,9 +93,9 @@ func (s *SyncerImpl) Sync(correspondingMesh mesh.MeshProvider) error {
|
|||||||
gossipNodes = neighbours[:redundancyLength]
|
gossipNodes = neighbours[:redundancyLength]
|
||||||
} else {
|
} else {
|
||||||
neighbours := s.cluster.GetNeighbours(nodeNames, publicKey.String())
|
neighbours := s.cluster.GetNeighbours(nodeNames, publicKey.String())
|
||||||
gossipNodes = lib.RandomSubsetOfLength(neighbours, s.conf.BranchRate)
|
gossipNodes = lib.RandomSubsetOfLength(neighbours, s.configuration.BranchRate)
|
||||||
|
|
||||||
if len(nodeNames) > s.conf.ClusterSize && rand.Float64() < s.conf.InterClusterChance {
|
if len(nodeNames) > s.configuration.ClusterSize && rand.Float64() < s.configuration.InterClusterChance {
|
||||||
gossipNodes[len(gossipNodes)-1] = s.cluster.GetInterCluster(nodeNames, publicKey.String())
|
gossipNodes[len(gossipNodes)-1] = s.cluster.GetInterCluster(nodeNames, publicKey.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,23 +126,24 @@ func (s *SyncerImpl) Sync(correspondingMesh mesh.MeshProvider) error {
|
|||||||
logging.Log.WriteInfof("sync time: %v", time.Since(before))
|
logging.Log.WriteInfof("sync time: %v", time.Since(before))
|
||||||
logging.Log.WriteInfof("number of syncs: %d", s.syncCount)
|
logging.Log.WriteInfof("number of syncs: %d", s.syncCount)
|
||||||
|
|
||||||
s.infectionCount = ((s.conf.InfectionCount + s.infectionCount - 1) % s.conf.InfectionCount)
|
s.infectionCount = ((s.configuration.InfectionCount + s.infectionCount - 1) % s.configuration.InfectionCount)
|
||||||
|
|
||||||
if !succeeded {
|
if !succeeded {
|
||||||
s.infectionCount++
|
s.infectionCount++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changes := correspondingMesh.HasChanges()
|
||||||
correspondingMesh.SaveChanges()
|
correspondingMesh.SaveChanges()
|
||||||
|
|
||||||
s.lock.Lock()
|
s.lastSyncLock.Lock()
|
||||||
s.lastSync[correspondingMesh.GetMeshId()] = time.Now().Unix()
|
s.lastSync[correspondingMesh.GetMeshId()] = time.Now().Unix()
|
||||||
s.lock.Unlock()
|
s.lastSyncLock.Unlock()
|
||||||
return nil
|
return changes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pull one node in the cluster, if there has not been message dissemination
|
// Pull one node in the cluster, if there has not been message dissemination
|
||||||
// in a certain period of time pull a random node within the cluster
|
// in a certain period of time pull a random node within the cluster
|
||||||
func (s *SyncerImpl) Pull(self mesh.MeshNode, mesh mesh.MeshProvider) error {
|
func (s *SyncerImpl) Pull(self mesh.MeshNode, mesh mesh.MeshProvider) (bool, error) {
|
||||||
peers := mesh.GetPeers()
|
peers := mesh.GetPeers()
|
||||||
pubKey, _ := self.GetPublicKey()
|
pubKey, _ := self.GetPublicKey()
|
||||||
|
|
||||||
@ -152,7 +152,7 @@ func (s *SyncerImpl) Pull(self mesh.MeshNode, mesh mesh.MeshProvider) error {
|
|||||||
|
|
||||||
if len(neighbour) == 0 {
|
if len(neighbour) == 0 {
|
||||||
logging.Log.WriteInfof("no neighbours")
|
logging.Log.WriteInfof("no neighbours")
|
||||||
return nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
logging.Log.WriteInfof("pulling from node %s", neighbour[0])
|
logging.Log.WriteInfof("pulling from node %s", neighbour[0])
|
||||||
@ -160,7 +160,7 @@ func (s *SyncerImpl) Pull(self mesh.MeshNode, mesh mesh.MeshProvider) error {
|
|||||||
pullNode, err := mesh.GetNode(neighbour[0])
|
pullNode, err := mesh.GetNode(neighbour[0])
|
||||||
|
|
||||||
if err != nil || pullNode == nil {
|
if err != nil || pullNode == nil {
|
||||||
return fmt.Errorf("node %s does not exist in the mesh", neighbour[0])
|
return false, fmt.Errorf("node %s does not exist in the mesh", neighbour[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s.requester.SyncMesh(mesh.GetMeshId(), pullNode)
|
err = s.requester.SyncMesh(mesh.GetMeshId(), pullNode)
|
||||||
@ -168,36 +168,70 @@ func (s *SyncerImpl) Pull(self mesh.MeshNode, mesh mesh.MeshProvider) error {
|
|||||||
if err == nil || err == io.EOF {
|
if err == nil || err == io.EOF {
|
||||||
s.lastSync[mesh.GetMeshId()] = time.Now().Unix()
|
s.lastSync[mesh.GetMeshId()] = time.Now().Unix()
|
||||||
} else {
|
} else {
|
||||||
return err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.syncCount++
|
s.syncCount++
|
||||||
return nil
|
|
||||||
|
changes := mesh.HasChanges()
|
||||||
|
return changes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SyncMeshes: Sync all meshes
|
// SyncMeshes: Sync all meshes
|
||||||
func (s *SyncerImpl) SyncMeshes() error {
|
func (s *SyncerImpl) SyncMeshes() error {
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
for _, mesh := range s.manager.GetMeshes() {
|
meshes := s.meshManager.GetMeshes()
|
||||||
|
|
||||||
|
s.lastPollLock.Lock()
|
||||||
|
meshesToSync := lib.Filter(lib.MapValues(meshes), func(mesh mesh.MeshProvider) bool {
|
||||||
|
return time.Now().Unix()-s.lastPoll[mesh.GetMeshId()] >= int64(s.configuration.SyncTime)
|
||||||
|
})
|
||||||
|
s.lastPollLock.Unlock()
|
||||||
|
|
||||||
|
changes := make(chan bool, len(meshesToSync))
|
||||||
|
|
||||||
|
for i := 0; i < len(meshesToSync); {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
|
|
||||||
sync := func() {
|
sync := func(index int) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
err := s.Sync(mesh)
|
var hasChanges bool = false
|
||||||
|
|
||||||
|
mesh := meshesToSync[index]
|
||||||
|
|
||||||
|
hasChanges, err := s.Sync(mesh)
|
||||||
|
changes <- hasChanges
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logging.Log.WriteErrorf(err.Error())
|
logging.Log.WriteErrorf(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.lastPollLock.Lock()
|
||||||
|
s.lastPoll[mesh.GetMeshId()] = time.Now().Unix()
|
||||||
|
s.lastPollLock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
go sync()
|
go sync(i)
|
||||||
|
i++
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
|
hasChanges := false
|
||||||
|
|
||||||
|
for i := 0; i < len(changes); i++ {
|
||||||
|
if <-changes {
|
||||||
|
hasChanges = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if hasChanges {
|
||||||
logging.Log.WriteInfof("updating the WireGuard configuration")
|
logging.Log.WriteInfof("updating the WireGuard configuration")
|
||||||
err := s.manager.ApplyConfig()
|
err = s.meshManager.ApplyConfig()
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logging.Log.WriteInfof("failed to update config %w", err)
|
logging.Log.WriteInfof("failed to update config %w", err)
|
||||||
@ -205,14 +239,28 @@ func (s *SyncerImpl) SyncMeshes() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSyncer(m mesh.MeshManager, conf *conf.DaemonConfiguration, r SyncRequester) Syncer {
|
type NewSyncerParams struct {
|
||||||
cluster, _ := conn.NewConnCluster(conf.ClusterSize)
|
MeshManager mesh.MeshManager
|
||||||
|
ConnectionManager conn.ConnectionManager
|
||||||
|
Configuration *conf.DaemonConfiguration
|
||||||
|
Requester SyncRequester
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSyncer(params *NewSyncerParams) Syncer {
|
||||||
|
cluster, _ := conn.NewConnCluster(params.Configuration.ClusterSize)
|
||||||
|
syncRequester := NewSyncRequester(NewSyncRequesterParams{
|
||||||
|
MeshManager: params.MeshManager,
|
||||||
|
ConnectionManager: params.ConnectionManager,
|
||||||
|
Configuration: params.Configuration,
|
||||||
|
})
|
||||||
|
|
||||||
return &SyncerImpl{
|
return &SyncerImpl{
|
||||||
manager: m,
|
meshManager: params.MeshManager,
|
||||||
conf: conf,
|
configuration: params.Configuration,
|
||||||
requester: r,
|
requester: syncRequester,
|
||||||
infectionCount: 0,
|
infectionCount: 0,
|
||||||
syncCount: 0,
|
syncCount: 0,
|
||||||
cluster: cluster,
|
cluster: cluster,
|
||||||
lastSync: make(map[string]int64)}
|
lastSync: make(map[string]int64),
|
||||||
|
lastPoll: make(map[string]int64)}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,8 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/tim-beatham/smegmesh/pkg/ctrlserver"
|
"github.com/tim-beatham/smegmesh/pkg/conf"
|
||||||
|
"github.com/tim-beatham/smegmesh/pkg/conn"
|
||||||
logging "github.com/tim-beatham/smegmesh/pkg/log"
|
logging "github.com/tim-beatham/smegmesh/pkg/log"
|
||||||
"github.com/tim-beatham/smegmesh/pkg/mesh"
|
"github.com/tim-beatham/smegmesh/pkg/mesh"
|
||||||
"github.com/tim-beatham/smegmesh/pkg/rpc"
|
"github.com/tim-beatham/smegmesh/pkg/rpc"
|
||||||
@ -19,13 +20,15 @@ type SyncRequester interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SyncRequesterImpl struct {
|
type SyncRequesterImpl struct {
|
||||||
server *ctrlserver.MeshCtrlServer
|
manager mesh.MeshManager
|
||||||
|
connectionManager conn.ConnectionManager
|
||||||
|
configuration *conf.DaemonConfiguration
|
||||||
errorHdlr SyncErrorHandler
|
errorHdlr SyncErrorHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMesh: Retrieves the local state of the mesh at the endpoint
|
// GetMesh: Retrieves the local state of the mesh at the endpoint
|
||||||
func (s *SyncRequesterImpl) GetMesh(meshId string, ifName string, port int, endPoint string) error {
|
func (s *SyncRequesterImpl) GetMesh(meshId string, ifName string, port int, endPoint string) error {
|
||||||
peerConnection, err := s.server.ConnectionManager.GetConnection(endPoint)
|
peerConnection, err := s.connectionManager.GetConnection(endPoint)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -48,7 +51,7 @@ func (s *SyncRequesterImpl) GetMesh(meshId string, ifName string, port int, endP
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s.server.MeshManager.AddMesh(&mesh.AddMeshParams{
|
err = s.manager.AddMesh(&mesh.AddMeshParams{
|
||||||
MeshId: meshId,
|
MeshId: meshId,
|
||||||
WgPort: port,
|
WgPort: port,
|
||||||
MeshBytes: reply.Mesh,
|
MeshBytes: reply.Mesh,
|
||||||
@ -56,13 +59,13 @@ func (s *SyncRequesterImpl) GetMesh(meshId string, ifName string, port int, endP
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handleErr: handleGrpc errors
|
||||||
func (s *SyncRequesterImpl) handleErr(meshId, pubKey string, err error) error {
|
func (s *SyncRequesterImpl) handleErr(meshId, pubKey string, err error) error {
|
||||||
ok := s.errorHdlr.Handle(meshId, pubKey, err)
|
ok := s.errorHdlr.Handle(meshId, pubKey, err)
|
||||||
|
|
||||||
if ok {
|
if ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +74,7 @@ func (s *SyncRequesterImpl) SyncMesh(meshId string, meshNode mesh.MeshNode) erro
|
|||||||
endpoint := meshNode.GetHostEndpoint()
|
endpoint := meshNode.GetHostEndpoint()
|
||||||
pubKey, _ := meshNode.GetPublicKey()
|
pubKey, _ := meshNode.GetPublicKey()
|
||||||
|
|
||||||
peerConnection, err := s.server.ConnectionManager.GetConnection(endpoint)
|
peerConnection, err := s.connectionManager.GetConnection(endpoint)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -83,7 +86,7 @@ func (s *SyncRequesterImpl) SyncMesh(meshId string, meshNode mesh.MeshNode) erro
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
mesh := s.server.MeshManager.GetMesh(meshId)
|
mesh := s.manager.GetMesh(meshId)
|
||||||
|
|
||||||
if mesh == nil {
|
if mesh == nil {
|
||||||
return errors.New("mesh does not exist")
|
return errors.New("mesh does not exist")
|
||||||
@ -91,7 +94,7 @@ func (s *SyncRequesterImpl) SyncMesh(meshId string, meshNode mesh.MeshNode) erro
|
|||||||
|
|
||||||
c := rpc.NewSyncServiceClient(client)
|
c := rpc.NewSyncServiceClient(client)
|
||||||
|
|
||||||
syncTimeOut := float64(s.server.Conf.SyncTime) * float64(time.Second)
|
syncTimeOut := float64(s.configuration.SyncTime) * float64(time.Second)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(syncTimeOut))
|
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(syncTimeOut))
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@ -102,7 +105,7 @@ func (s *SyncRequesterImpl) SyncMesh(meshId string, meshNode mesh.MeshNode) erro
|
|||||||
s.handleErr(meshId, pubKey.String(), err)
|
s.handleErr(meshId, pubKey.String(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
logging.Log.WriteInfof("Synced with node: %s meshId: %s\n", endpoint, meshId)
|
logging.Log.WriteInfof("synced with node: %s meshId: %s\n", endpoint, meshId)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +130,7 @@ func (s *SyncRequesterImpl) syncMesh(mesh mesh.MeshProvider, ctx context.Context
|
|||||||
in, err := stream.Recv()
|
in, err := stream.Recv()
|
||||||
|
|
||||||
if err != nil && err != io.EOF {
|
if err != nil && err != io.EOF {
|
||||||
logging.Log.WriteInfof("Stream recv error: %s\n", err.Error())
|
logging.Log.WriteInfof("stream recv error: %s\n", err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +139,7 @@ func (s *SyncRequesterImpl) syncMesh(mesh mesh.MeshProvider, ctx context.Context
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logging.Log.WriteInfof("Syncer recv error: %s\n", err.Error())
|
logging.Log.WriteInfof("syncer recv error: %s\n", err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +153,17 @@ func (s *SyncRequesterImpl) syncMesh(mesh mesh.MeshProvider, ctx context.Context
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSyncRequester(s *ctrlserver.MeshCtrlServer) SyncRequester {
|
type NewSyncRequesterParams struct {
|
||||||
errorHdlr := NewSyncErrorHandler(s.MeshManager, s.ConnectionManager)
|
MeshManager mesh.MeshManager
|
||||||
return &SyncRequesterImpl{server: s, errorHdlr: errorHdlr}
|
ConnectionManager conn.ConnectionManager
|
||||||
|
Configuration *conf.DaemonConfiguration
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSyncRequester(params NewSyncRequesterParams) SyncRequester {
|
||||||
|
errorHdlr := NewSyncErrorHandler(params.MeshManager, params.ConnectionManager)
|
||||||
|
return &SyncRequesterImpl{manager: params.MeshManager,
|
||||||
|
connectionManager: params.ConnectionManager,
|
||||||
|
configuration: params.Configuration,
|
||||||
|
errorHdlr: errorHdlr,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
package sync
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/tim-beatham/smegmesh/pkg/ctrlserver"
|
|
||||||
"github.com/tim-beatham/smegmesh/pkg/lib"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Run implements SyncScheduler.
|
|
||||||
func syncFunction(syncer Syncer) lib.TimerFunc {
|
|
||||||
return func() error {
|
|
||||||
syncer.SyncMeshes()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewSyncScheduler(s *ctrlserver.MeshCtrlServer, syncRequester SyncRequester, syncer Syncer) *lib.Timer {
|
|
||||||
return lib.NewTimer(syncFunction(syncer), s.Conf.SyncTime)
|
|
||||||
}
|
|
@ -6,19 +6,18 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/tim-beatham/smegmesh/pkg/ctrlserver"
|
|
||||||
"github.com/tim-beatham/smegmesh/pkg/mesh"
|
"github.com/tim-beatham/smegmesh/pkg/mesh"
|
||||||
"github.com/tim-beatham/smegmesh/pkg/rpc"
|
"github.com/tim-beatham/smegmesh/pkg/rpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SyncServiceImpl struct {
|
type SyncServiceImpl struct {
|
||||||
rpc.UnimplementedSyncServiceServer
|
rpc.UnimplementedSyncServiceServer
|
||||||
Server *ctrlserver.MeshCtrlServer
|
MeshManager mesh.MeshManager
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMesh: Gets a nodes local mesh configuration as a CRDT
|
// GetMesh: Gets a nodes local mesh configuration as a CRDT
|
||||||
func (s *SyncServiceImpl) GetConf(context context.Context, request *rpc.GetConfRequest) (*rpc.GetConfReply, error) {
|
func (s *SyncServiceImpl) GetConf(context context.Context, request *rpc.GetConfRequest) (*rpc.GetConfReply, error) {
|
||||||
mesh := s.Server.MeshManager.GetMesh(request.MeshId)
|
mesh := s.MeshManager.GetMesh(request.MeshId)
|
||||||
|
|
||||||
if mesh == nil {
|
if mesh == nil {
|
||||||
return nil, errors.New("mesh does not exist")
|
return nil, errors.New("mesh does not exist")
|
||||||
@ -56,7 +55,7 @@ func (s *SyncServiceImpl) SyncMesh(stream rpc.SyncService_SyncMeshServer) error
|
|||||||
if len(meshId) == 0 {
|
if len(meshId) == 0 {
|
||||||
meshId = in.MeshId
|
meshId = in.MeshId
|
||||||
|
|
||||||
mesh := s.Server.MeshManager.GetMesh(meshId)
|
mesh := s.MeshManager.GetMesh(meshId)
|
||||||
|
|
||||||
if mesh == nil {
|
if mesh == nil {
|
||||||
return errors.New("mesh does not exist")
|
return errors.New("mesh does not exist")
|
||||||
@ -92,7 +91,3 @@ func (s *SyncServiceImpl) SyncMesh(stream rpc.SyncService_SyncMeshServer) error
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSyncService(server *ctrlserver.MeshCtrlServer) *SyncServiceImpl {
|
|
||||||
return &SyncServiceImpl{Server: server}
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user