2023-09-29 16:00:20 +02:00
|
|
|
package robin
|
2023-09-18 18:00:43 +02:00
|
|
|
|
|
|
|
import (
|
2023-09-19 19:29:35 +02:00
|
|
|
"context"
|
2023-09-18 18:00:43 +02:00
|
|
|
"errors"
|
2023-10-24 17:00:46 +02:00
|
|
|
"fmt"
|
2024-01-05 17:59:02 +01:00
|
|
|
"slices"
|
2023-09-19 19:29:35 +02:00
|
|
|
"time"
|
2023-09-18 18:00:43 +02:00
|
|
|
|
2024-01-02 00:55:50 +01:00
|
|
|
"github.com/tim-beatham/smegmesh/pkg/conf"
|
|
|
|
"github.com/tim-beatham/smegmesh/pkg/ctrlserver"
|
|
|
|
"github.com/tim-beatham/smegmesh/pkg/ipc"
|
|
|
|
"github.com/tim-beatham/smegmesh/pkg/mesh"
|
|
|
|
"github.com/tim-beatham/smegmesh/pkg/rpc"
|
2023-09-18 18:00:43 +02:00
|
|
|
)
|
|
|
|
|
2024-01-04 14:12:07 +01:00
|
|
|
// IpcHandler: represents a handler for ipc calls
|
2023-10-26 17:53:12 +02:00
|
|
|
type IpcHandler struct {
|
2023-11-05 19:03:58 +01:00
|
|
|
Server ctrlserver.CtrlServer
|
2023-09-18 18:00:43 +02:00
|
|
|
}
|
|
|
|
|
2024-01-04 14:12:07 +01:00
|
|
|
// getOverrideConfiguration: override any specific WireGuard configuration
|
2023-12-12 12:58:47 +01:00
|
|
|
func getOverrideConfiguration(args *ipc.WireGuardArgs) conf.WgConfiguration {
|
|
|
|
overrideConf := conf.WgConfiguration{}
|
2023-12-10 20:21:54 +01:00
|
|
|
|
|
|
|
if args.Role != "" {
|
|
|
|
role := conf.NodeType(args.Role)
|
|
|
|
overrideConf.Role = &role
|
|
|
|
}
|
|
|
|
|
|
|
|
if args.Endpoint != "" {
|
|
|
|
overrideConf.Endpoint = &args.Endpoint
|
|
|
|
}
|
|
|
|
|
2023-12-12 12:58:47 +01:00
|
|
|
if args.KeepAliveWg != 0 {
|
|
|
|
keepAliveWg := args.KeepAliveWg
|
|
|
|
overrideConf.KeepAliveWg = &keepAliveWg
|
|
|
|
}
|
|
|
|
|
|
|
|
overrideConf.AdvertiseRoutes = &args.AdvertiseRoutes
|
|
|
|
overrideConf.AdvertiseDefaultRoute = &args.AdvertiseDefaultRoute
|
|
|
|
return overrideConf
|
|
|
|
}
|
|
|
|
|
2024-01-04 14:12:07 +01:00
|
|
|
// CreateMesh: create a new mesh network
|
2023-12-12 12:58:47 +01:00
|
|
|
func (n *IpcHandler) CreateMesh(args *ipc.NewMeshArgs, reply *string) error {
|
|
|
|
overrideConf := getOverrideConfiguration(&args.WgArgs)
|
|
|
|
|
2023-12-10 20:21:54 +01:00
|
|
|
meshId, err := n.Server.GetMeshManager().CreateMesh(&mesh.CreateMeshParams{
|
2023-12-12 12:58:47 +01:00
|
|
|
Port: args.WgArgs.WgPort,
|
|
|
|
Conf: &overrideConf,
|
2023-12-10 20:21:54 +01:00
|
|
|
})
|
2023-10-21 19:08:45 +02:00
|
|
|
|
|
|
|
if err != nil {
|
2024-01-05 17:59:02 +01:00
|
|
|
return errors.New("could not create mesh")
|
2023-10-21 19:08:45 +02:00
|
|
|
}
|
2023-10-05 18:48:54 +02:00
|
|
|
|
2023-11-05 19:03:58 +01:00
|
|
|
err = n.Server.GetMeshManager().AddSelf(&mesh.AddSelfParams{
|
2023-10-28 17:38:25 +02:00
|
|
|
MeshId: meshId,
|
2023-12-12 12:58:47 +01:00
|
|
|
WgPort: args.WgArgs.WgPort,
|
|
|
|
Endpoint: args.WgArgs.Endpoint,
|
2023-10-28 17:38:25 +02:00
|
|
|
})
|
2023-10-30 17:49:02 +01:00
|
|
|
|
2023-11-07 20:48:53 +01:00
|
|
|
if err != nil {
|
2024-08-11 13:24:15 +02:00
|
|
|
return errors.New("could not create mesh: " + err.Error())
|
2023-11-07 20:48:53 +01:00
|
|
|
}
|
|
|
|
|
2023-10-06 11:12:46 +02:00
|
|
|
*reply = meshId
|
2023-10-30 17:49:02 +01:00
|
|
|
return err
|
2023-09-18 18:00:43 +02:00
|
|
|
}
|
|
|
|
|
2024-01-04 14:12:07 +01:00
|
|
|
// ListMeshes: list mesh networks
|
2023-10-26 17:53:12 +02:00
|
|
|
func (n *IpcHandler) ListMeshes(_ string, reply *ipc.ListMeshReply) error {
|
2023-11-05 19:03:58 +01:00
|
|
|
meshNames := make([]string, len(n.Server.GetMeshManager().GetMeshes()))
|
2023-10-06 19:25:38 +02:00
|
|
|
|
|
|
|
i := 0
|
2023-12-10 20:21:54 +01:00
|
|
|
for meshId := range n.Server.GetMeshManager().GetMeshes() {
|
2023-10-26 17:53:12 +02:00
|
|
|
meshNames[i] = meshId
|
2023-10-06 19:25:38 +02:00
|
|
|
i++
|
|
|
|
}
|
2023-09-20 15:34:34 +02:00
|
|
|
|
2024-01-05 17:59:02 +01:00
|
|
|
slices.Sort(meshNames)
|
2023-10-06 19:25:38 +02:00
|
|
|
*reply = ipc.ListMeshReply{Meshes: meshNames}
|
2023-09-20 15:34:34 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-01-04 14:12:07 +01:00
|
|
|
// JoinMesh: join a mesh network
|
2023-12-31 15:25:06 +01:00
|
|
|
func (n *IpcHandler) JoinMesh(args *ipc.JoinMeshArgs, reply *string) error {
|
2023-12-12 12:58:47 +01:00
|
|
|
overrideConf := getOverrideConfiguration(&args.WgArgs)
|
2023-12-10 20:21:54 +01:00
|
|
|
|
2023-12-31 13:44:50 +01:00
|
|
|
if n.Server.GetMeshManager().GetMesh(args.MeshId) != nil {
|
2024-08-11 13:24:15 +02:00
|
|
|
return fmt.Errorf("user is already a part of the mesh")
|
2023-12-31 13:44:50 +01:00
|
|
|
}
|
|
|
|
|
2023-12-31 15:25:06 +01:00
|
|
|
peerConnection, err := n.Server.GetConnectionManager().GetConnection(args.IpAddress)
|
2023-10-01 21:14:09 +02:00
|
|
|
|
2023-10-30 17:49:02 +01:00
|
|
|
if err != nil {
|
2024-01-05 17:59:02 +01:00
|
|
|
return fmt.Errorf("could not join mesh %s", args.MeshId)
|
2023-10-30 17:49:02 +01:00
|
|
|
}
|
|
|
|
|
2023-10-02 17:03:41 +02:00
|
|
|
client, err := peerConnection.GetClient()
|
2023-09-19 19:29:35 +02:00
|
|
|
|
|
|
|
if err != nil {
|
2024-01-05 17:59:02 +01:00
|
|
|
return fmt.Errorf("could not join mesh %s", args.MeshId)
|
2023-09-19 19:29:35 +02:00
|
|
|
}
|
|
|
|
|
2023-10-02 17:03:41 +02:00
|
|
|
c := rpc.NewMeshCtrlServerClient(client)
|
2023-09-19 19:29:35 +02:00
|
|
|
|
2023-10-01 21:14:09 +02:00
|
|
|
if err != nil {
|
2024-01-05 17:59:02 +01:00
|
|
|
return fmt.Errorf("could not join mesh %s", args.MeshId)
|
2023-10-01 21:14:09 +02:00
|
|
|
}
|
|
|
|
|
2023-11-24 13:07:03 +01:00
|
|
|
configuration := n.Server.GetConfiguration()
|
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(configuration.Timeout))
|
2023-09-19 19:29:35 +02:00
|
|
|
defer cancel()
|
|
|
|
|
2023-10-06 12:52:51 +02:00
|
|
|
meshReply, err := c.GetMesh(ctx, &rpc.GetMeshRequest{MeshId: args.MeshId})
|
|
|
|
|
|
|
|
if err != nil {
|
2024-01-05 17:59:02 +01:00
|
|
|
return fmt.Errorf("could not join mesh %s", args.MeshId)
|
2023-10-06 12:52:51 +02:00
|
|
|
}
|
|
|
|
|
2023-11-05 19:03:58 +01:00
|
|
|
err = n.Server.GetMeshManager().AddMesh(&mesh.AddMeshParams{
|
2023-10-28 17:38:25 +02:00
|
|
|
MeshId: args.MeshId,
|
2023-12-12 12:58:47 +01:00
|
|
|
WgPort: args.WgArgs.WgPort,
|
2023-10-28 17:38:25 +02:00
|
|
|
MeshBytes: meshReply.Mesh,
|
2023-12-12 12:58:47 +01:00
|
|
|
Conf: &overrideConf,
|
2023-10-28 17:38:25 +02:00
|
|
|
})
|
2023-10-06 12:52:51 +02:00
|
|
|
|
|
|
|
if err != nil {
|
2024-01-05 17:59:02 +01:00
|
|
|
return fmt.Errorf("could not join mesh %s", args.MeshId)
|
2023-10-06 12:52:51 +02:00
|
|
|
}
|
|
|
|
|
2023-11-05 19:03:58 +01:00
|
|
|
err = n.Server.GetMeshManager().AddSelf(&mesh.AddSelfParams{
|
2023-10-28 17:38:25 +02:00
|
|
|
MeshId: args.MeshId,
|
2023-12-12 12:58:47 +01:00
|
|
|
WgPort: args.WgArgs.WgPort,
|
|
|
|
Endpoint: args.WgArgs.Endpoint,
|
2023-10-28 17:38:25 +02:00
|
|
|
})
|
2023-09-20 00:50:44 +02:00
|
|
|
|
2023-10-06 12:52:51 +02:00
|
|
|
if err != nil {
|
2024-01-05 17:59:02 +01:00
|
|
|
return fmt.Errorf("could not join mesh %s", args.MeshId)
|
2023-10-06 12:52:51 +02:00
|
|
|
}
|
|
|
|
|
2024-01-05 13:59:13 +01:00
|
|
|
*reply = fmt.Sprintf("Successfully Joined: %s", args.MeshId)
|
2023-10-28 17:38:25 +02:00
|
|
|
return nil
|
|
|
|
}
|
2023-09-21 14:50:59 +02:00
|
|
|
|
2024-01-04 14:12:07 +01:00
|
|
|
// LeaveMesh: leaves a mesh network
|
2023-10-28 17:38:25 +02:00
|
|
|
func (n *IpcHandler) LeaveMesh(meshId string, reply *string) error {
|
2023-11-05 19:03:58 +01:00
|
|
|
err := n.Server.GetMeshManager().LeaveMesh(meshId)
|
2023-10-06 12:52:51 +02:00
|
|
|
|
2023-10-28 17:38:25 +02:00
|
|
|
if err == nil {
|
|
|
|
*reply = fmt.Sprintf("Left Mesh %s", meshId)
|
2023-10-27 18:49:18 +02:00
|
|
|
}
|
2023-10-28 17:38:25 +02:00
|
|
|
return err
|
2023-09-20 00:50:44 +02:00
|
|
|
}
|
|
|
|
|
2024-01-04 14:12:07 +01:00
|
|
|
// GetMesh: get a mesh network at the given meshid
|
2023-10-26 17:53:12 +02:00
|
|
|
func (n *IpcHandler) GetMesh(meshId string, reply *ipc.GetMeshReply) error {
|
2023-11-25 04:15:58 +01:00
|
|
|
theMesh := n.Server.GetMeshManager().GetMesh(meshId)
|
2023-11-17 23:13:51 +01:00
|
|
|
|
2023-11-25 04:15:58 +01:00
|
|
|
if theMesh == nil {
|
2023-11-17 23:13:51 +01:00
|
|
|
return fmt.Errorf("mesh %s does not exist", meshId)
|
|
|
|
}
|
|
|
|
|
2023-11-25 04:15:58 +01:00
|
|
|
meshSnapshot, err := theMesh.GetMesh()
|
2023-10-06 12:52:51 +02:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2023-09-20 00:50:44 +02:00
|
|
|
|
2023-11-25 04:15:58 +01:00
|
|
|
if theMesh == nil {
|
2023-10-26 17:53:12 +02:00
|
|
|
return errors.New("mesh does not exist")
|
|
|
|
}
|
2023-11-07 20:48:53 +01:00
|
|
|
|
2023-10-26 17:53:12 +02:00
|
|
|
nodes := make([]ctrlserver.MeshNode, len(meshSnapshot.GetNodes()))
|
2023-09-20 00:50:44 +02:00
|
|
|
|
2023-10-26 17:53:12 +02:00
|
|
|
i := 0
|
|
|
|
for _, node := range meshSnapshot.GetNodes() {
|
2023-12-11 10:55:25 +01:00
|
|
|
node := ctrlserver.NewCtrlNode(theMesh, node)
|
|
|
|
|
|
|
|
nodes[i] = *node
|
2023-10-26 17:53:12 +02:00
|
|
|
i += 1
|
2023-09-20 00:50:44 +02:00
|
|
|
}
|
2023-10-26 17:53:12 +02:00
|
|
|
|
|
|
|
*reply = ipc.GetMeshReply{Nodes: nodes}
|
2023-09-19 19:29:35 +02:00
|
|
|
return nil
|
2023-09-19 14:45:49 +02:00
|
|
|
}
|
|
|
|
|
2024-01-04 14:12:07 +01:00
|
|
|
// Query: perform a jmespath query
|
2023-10-30 20:02:28 +01:00
|
|
|
func (n *IpcHandler) Query(params ipc.QueryMesh, reply *string) error {
|
2023-11-05 19:03:58 +01:00
|
|
|
queryResponse, err := n.Server.GetQuerier().Query(params.MeshId, params.Query)
|
2023-10-30 20:02:28 +01:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
*reply = string(queryResponse)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-01-04 14:12:07 +01:00
|
|
|
// PutDescription: change your description in the mesh
|
2023-12-31 15:25:06 +01:00
|
|
|
func (n *IpcHandler) PutDescription(args ipc.PutDescriptionArgs, reply *string) error {
|
2024-01-18 17:13:41 +01:00
|
|
|
err := n.Server.GetMeshManager().SetDescription(args.MeshId, args.Description)
|
2023-11-01 12:58:10 +01:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2023-12-31 15:25:06 +01:00
|
|
|
*reply = fmt.Sprintf("set description to %s for %s", args.Description, args.MeshId)
|
2023-11-01 12:58:10 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-01-04 14:12:07 +01:00
|
|
|
// PutAlias: put your aliasin the mesh
|
2023-12-31 15:25:06 +01:00
|
|
|
func (n *IpcHandler) PutAlias(args ipc.PutAliasArgs, reply *string) error {
|
|
|
|
if args.Alias == "" {
|
|
|
|
return fmt.Errorf("alias not provided")
|
|
|
|
}
|
|
|
|
|
|
|
|
err := n.Server.GetMeshManager().SetAlias(args.MeshId, args.Alias)
|
2023-11-17 20:05:21 +01:00
|
|
|
|
|
|
|
if err != nil {
|
2024-01-05 17:59:02 +01:00
|
|
|
return fmt.Errorf("could not set alias: %s", args.Alias)
|
2023-11-17 20:05:21 +01:00
|
|
|
}
|
|
|
|
|
2023-12-31 15:25:06 +01:00
|
|
|
*reply = fmt.Sprintf("Set alias to %s", args.Alias)
|
2023-11-17 20:05:21 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-01-04 14:12:07 +01:00
|
|
|
// PutService: place a service in the mesh
|
2023-11-17 23:13:51 +01:00
|
|
|
func (n *IpcHandler) PutService(service ipc.PutServiceArgs, reply *string) error {
|
2023-12-31 15:25:06 +01:00
|
|
|
err := n.Server.GetMeshManager().SetService(service.MeshId, service.Service, service.Value)
|
2023-11-17 23:13:51 +01:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-01-05 13:59:13 +01:00
|
|
|
*reply = fmt.Sprintf("Set service %s in %s to %s", service.Service, service.MeshId, service.Value)
|
2023-11-17 23:13:51 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-01-04 14:12:07 +01:00
|
|
|
// DeleteService: withtract a service in the mesh
|
2023-12-31 15:25:06 +01:00
|
|
|
func (n *IpcHandler) DeleteService(service ipc.DeleteServiceArgs, reply *string) error {
|
|
|
|
err := n.Server.GetMeshManager().RemoveService(service.MeshId, service.Service)
|
2023-11-17 23:13:51 +01:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-01-05 13:59:13 +01:00
|
|
|
*reply = fmt.Sprintf("Removed service %s from %s", service.Service, service.MeshId)
|
2023-11-17 23:13:51 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-01-04 14:12:07 +01:00
|
|
|
// RobinIpcParams: parameters required to construct a new mesh network
|
2023-10-05 18:48:54 +02:00
|
|
|
type RobinIpcParams struct {
|
2023-11-05 19:03:58 +01:00
|
|
|
CtrlServer ctrlserver.CtrlServer
|
2023-10-05 18:48:54 +02:00
|
|
|
}
|
|
|
|
|
2023-10-26 17:53:12 +02:00
|
|
|
func NewRobinIpc(ipcParams RobinIpcParams) IpcHandler {
|
|
|
|
return IpcHandler{
|
2023-10-28 17:38:25 +02:00
|
|
|
Server: ipcParams.CtrlServer,
|
2023-10-05 18:48:54 +02:00
|
|
|
}
|
2023-09-18 18:00:43 +02:00
|
|
|
}
|