forked from extern/smegmesh
Merge pull request #22 from tim-beatham/21-phonetic-words-ipv6
21 phonetic words ipv6
This commit is contained in:
commit
f13319cfc1
@ -7,11 +7,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
apiServer, err := api.NewSmegServer()
|
apiServer, err := api.NewSmegServer(api.ApiServerConf{
|
||||||
|
WordsFile: "./cmd/api/words.txt",
|
||||||
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err.Error())
|
log.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
apiServer.Run(":40000")
|
apiServer.Run(":8080")
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/tim-beatham/wgmesh/pkg/ctrlserver"
|
"github.com/tim-beatham/wgmesh/pkg/ctrlserver"
|
||||||
"github.com/tim-beatham/wgmesh/pkg/ipc"
|
"github.com/tim-beatham/wgmesh/pkg/ipc"
|
||||||
logging "github.com/tim-beatham/wgmesh/pkg/log"
|
logging "github.com/tim-beatham/wgmesh/pkg/log"
|
||||||
|
"github.com/tim-beatham/wgmesh/pkg/what8words"
|
||||||
)
|
)
|
||||||
|
|
||||||
const SockAddr = "/tmp/wgmesh_ipc.sock"
|
const SockAddr = "/tmp/wgmesh_ipc.sock"
|
||||||
@ -22,33 +23,59 @@ type ApiServer interface {
|
|||||||
type SmegServer struct {
|
type SmegServer struct {
|
||||||
router *gin.Engine
|
router *gin.Engine
|
||||||
client *ipcRpc.Client
|
client *ipcRpc.Client
|
||||||
|
words *what8words.What8Words
|
||||||
}
|
}
|
||||||
|
|
||||||
func meshNodeToAPIMeshNode(meshNode ctrlserver.MeshNode) *SmegNode {
|
func (s *SmegServer) routeToApiRoute(meshNode ctrlserver.MeshNode) []Route {
|
||||||
|
routes := make([]Route, len(meshNode.Routes))
|
||||||
|
|
||||||
|
for index, route := range meshNode.Routes {
|
||||||
|
word, err := s.words.Convert(route)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
routes[index] = Route{
|
||||||
|
Prefix: route,
|
||||||
|
RouteId: word,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return routes
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SmegServer) meshNodeToAPIMeshNode(meshNode ctrlserver.MeshNode) *SmegNode {
|
||||||
if meshNode.Routes == nil {
|
if meshNode.Routes == nil {
|
||||||
meshNode.Routes = make([]string, 0)
|
meshNode.Routes = make([]string, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
alias := meshNode.Alias
|
||||||
|
|
||||||
|
if alias == "" {
|
||||||
|
alias, _ = s.words.ConvertIdentifier(meshNode.WgHost)
|
||||||
|
}
|
||||||
|
|
||||||
return &SmegNode{
|
return &SmegNode{
|
||||||
WgHost: meshNode.WgHost,
|
WgHost: meshNode.WgHost,
|
||||||
WgEndpoint: meshNode.WgEndpoint,
|
WgEndpoint: meshNode.WgEndpoint,
|
||||||
Endpoint: meshNode.HostEndpoint,
|
Endpoint: meshNode.HostEndpoint,
|
||||||
Timestamp: int(meshNode.Timestamp),
|
Timestamp: int(meshNode.Timestamp),
|
||||||
Description: meshNode.Description,
|
Description: meshNode.Description,
|
||||||
Routes: meshNode.Routes,
|
Routes: s.routeToApiRoute(meshNode),
|
||||||
PublicKey: meshNode.PublicKey,
|
PublicKey: meshNode.PublicKey,
|
||||||
Alias: meshNode.Alias,
|
Alias: alias,
|
||||||
Services: meshNode.Services,
|
Services: meshNode.Services,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func 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
|
||||||
smegMesh.Nodes = make(map[string]SmegNode)
|
smegMesh.Nodes = make(map[string]SmegNode)
|
||||||
|
|
||||||
for _, node := range nodes {
|
for _, node := range nodes {
|
||||||
smegMesh.Nodes[node.WgHost] = *meshNodeToAPIMeshNode(node)
|
smegMesh.Nodes[node.WgHost] = *s.meshNodeToAPIMeshNode(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
return smegMesh
|
return smegMesh
|
||||||
@ -138,7 +165,7 @@ func (s *SmegServer) GetMesh(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
mesh := meshToAPIMesh(meshidParam, getMeshReply.Nodes)
|
mesh := s.meshToAPIMesh(meshidParam, getMeshReply.Nodes)
|
||||||
|
|
||||||
c.JSON(http.StatusOK, mesh)
|
c.JSON(http.StatusOK, mesh)
|
||||||
}
|
}
|
||||||
@ -167,7 +194,7 @@ func (s *SmegServer) GetMeshes(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
meshes = append(meshes, meshToAPIMesh(mesh, getMeshReply.Nodes))
|
meshes = append(meshes, s.meshToAPIMesh(mesh, getMeshReply.Nodes))
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, meshes)
|
c.JSON(http.StatusOK, meshes)
|
||||||
@ -178,13 +205,19 @@ func (s *SmegServer) Run(addr string) error {
|
|||||||
return s.router.Run(addr)
|
return s.router.Run(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSmegServer() (ApiServer, error) {
|
func NewSmegServer(conf ApiServerConf) (ApiServer, error) {
|
||||||
client, err := ipcRpc.DialHTTP("unix", SockAddr)
|
client, err := ipcRpc.DialHTTP("unix", SockAddr)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
words, err := what8words.NewWhat8Words(conf.WordsFile)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
router := gin.Default()
|
router := gin.Default()
|
||||||
|
|
||||||
router.Use(gin.LoggerWithConfig(gin.LoggerConfig{
|
router.Use(gin.LoggerWithConfig(gin.LoggerConfig{
|
||||||
@ -194,6 +227,7 @@ func NewSmegServer() (ApiServer, error) {
|
|||||||
smegServer := &SmegServer{
|
smegServer := &SmegServer{
|
||||||
router: router,
|
router: router,
|
||||||
client: client,
|
client: client,
|
||||||
|
words: words,
|
||||||
}
|
}
|
||||||
|
|
||||||
router.GET("/meshes", smegServer.GetMeshes)
|
router.GET("/meshes", smegServer.GetMeshes)
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
|
type Route struct {
|
||||||
|
RouteId string `json:"routeId"`
|
||||||
|
Prefix string `json:"prefix"`
|
||||||
|
}
|
||||||
|
|
||||||
type SmegNode struct {
|
type SmegNode struct {
|
||||||
Alias string `json:"alias"`
|
Alias string `json:"alias"`
|
||||||
WgHost string `json:"wgHost"`
|
WgHost string `json:"wgHost"`
|
||||||
@ -8,7 +13,7 @@ type SmegNode struct {
|
|||||||
Timestamp int `json:"timestamp"`
|
Timestamp int `json:"timestamp"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
PublicKey string `json:"publicKey"`
|
PublicKey string `json:"publicKey"`
|
||||||
Routes []string `json:"routes"`
|
Routes []Route `json:"routes"`
|
||||||
Services map[string]string `json:"services"`
|
Services map[string]string `json:"services"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -18,11 +23,15 @@ type SmegMesh struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type CreateMeshRequest struct {
|
type CreateMeshRequest struct {
|
||||||
WgPort int `json:"port" binding:"gte=1024,lt=65535"`
|
WgPort int `json:"port" binding:"omitempty,gte=1024,lt=65535"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type JoinMeshRequest struct {
|
type JoinMeshRequest struct {
|
||||||
WgPort int `json:"port" binding:"gte=1024,lt=65535"`
|
WgPort int `json:"port" binding:"omitempty,gte=1024,lt=65535"`
|
||||||
Bootstrap string `json:"bootstrap" binding:"required"`
|
Bootstrap string `json:"bootstrap" binding:"required"`
|
||||||
MeshId string `json:"meshid" binding:"required"`
|
MeshId string `json:"meshid" binding:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ApiServerConf struct {
|
||||||
|
WordsFile string
|
||||||
|
}
|
||||||
|
@ -53,6 +53,8 @@ type WgMeshConfiguration struct {
|
|||||||
Profile bool `yaml:"profile"`
|
Profile bool `yaml:"profile"`
|
||||||
// StubWg whether or not to stub the WireGuard types
|
// StubWg whether or not to stub the WireGuard types
|
||||||
StubWg bool `yaml:"stubWg"`
|
StubWg bool `yaml:"stubWg"`
|
||||||
|
// What8Words file path for the what 8 words word list.
|
||||||
|
What8Words string `yaml:"what8Words"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func ValidateConfiguration(c *WgMeshConfiguration) error {
|
func ValidateConfiguration(c *WgMeshConfiguration) error {
|
||||||
|
92
pkg/what8words/what8words.go
Normal file
92
pkg/what8words/what8words.go
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
// Package to convert an IPV6 addres into 8 words
|
||||||
|
package what8words
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type What8Words struct {
|
||||||
|
words []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert implements What8Words.
|
||||||
|
func (w *What8Words) Convert(ipStr string) (string, error) {
|
||||||
|
ip, ipNet, err := net.ParseCIDR(ipStr)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
ip16 := ip.To16()
|
||||||
|
|
||||||
|
if ip16 == nil {
|
||||||
|
return "", fmt.Errorf("cannot convert ip to 16 representation")
|
||||||
|
}
|
||||||
|
|
||||||
|
representation := make([]string, 7)
|
||||||
|
|
||||||
|
for i := 2; i <= net.IPv6len-2; i += 2 {
|
||||||
|
word1 := w.words[ip16[i]]
|
||||||
|
word2 := w.words[ip16[i+1]]
|
||||||
|
|
||||||
|
representation[i/2-1] = fmt.Sprintf("%s-%s", word1, word2)
|
||||||
|
}
|
||||||
|
|
||||||
|
prefixSize, _ := ipNet.Mask.Size()
|
||||||
|
return strings.Join(representation[:prefixSize/16-1], "."), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert implements What8Words.
|
||||||
|
func (w *What8Words) ConvertIdentifier(ipStr string) (string, error) {
|
||||||
|
ip, err := w.Convert(ipStr)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
constituents := strings.Split(ip, ".")
|
||||||
|
|
||||||
|
return strings.Join(constituents[3:], "."), nil
|
||||||
|
}
|
||||||
|
func NewWhat8Words(pathToWords string) (*What8Words, error) {
|
||||||
|
words, err := ReadWords(pathToWords)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &What8Words{words: words}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadWords reads the what 8 words txt file
|
||||||
|
func ReadWords(wordFile string) ([]string, error) {
|
||||||
|
f, err := os.ReadFile(wordFile)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
words := make([]string, 257)
|
||||||
|
|
||||||
|
reader := bufio.NewScanner(bytes.NewReader(f))
|
||||||
|
|
||||||
|
counter := 0
|
||||||
|
|
||||||
|
for reader.Scan() && counter <= len(words) {
|
||||||
|
text := reader.Text()
|
||||||
|
|
||||||
|
words[counter] = text
|
||||||
|
counter++
|
||||||
|
|
||||||
|
if reader.Err() != nil {
|
||||||
|
return nil, reader.Err()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return words, nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user