mirror of
https://github.com/luscis/openlan.git
synced 2025-09-26 20:41:29 +08:00
178 lines
3.2 KiB
Go
Executable File
178 lines
3.2 KiB
Go
Executable File
package cswitch
|
|
|
|
import (
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
"sync"
|
|
|
|
co "github.com/luscis/openlan/pkg/config"
|
|
"github.com/luscis/openlan/pkg/libol"
|
|
"github.com/luscis/openlan/pkg/models"
|
|
nl "github.com/vishvananda/netlink"
|
|
)
|
|
|
|
const (
|
|
AccessBin = "openlan-access"
|
|
AccessDir = "/var/openlan/access"
|
|
)
|
|
|
|
type Link struct {
|
|
cfg *co.Access
|
|
out *libol.SubLogger
|
|
uuid string
|
|
}
|
|
|
|
func NewLink(cfg *co.Access) *Link {
|
|
uuid := libol.GenString(13)
|
|
return &Link{
|
|
uuid: uuid,
|
|
cfg: cfg,
|
|
out: libol.NewSubLogger(cfg.Network),
|
|
}
|
|
}
|
|
|
|
func (l *Link) Model() *models.Link {
|
|
cfg := l.Conf()
|
|
return &models.Link{
|
|
User: cfg.Username,
|
|
Network: cfg.Network,
|
|
Protocol: cfg.Protocol,
|
|
StatusFile: l.StatusFile(),
|
|
}
|
|
}
|
|
|
|
func (l *Link) Initialize() {
|
|
file := l.ConfFile()
|
|
l.cfg.StatusFile = l.StatusFile()
|
|
l.cfg.PidFile = l.PidFile()
|
|
_ = libol.MarshalSave(l.cfg, file, true)
|
|
}
|
|
|
|
func (l *Link) Conf() *co.Access {
|
|
return l.cfg
|
|
}
|
|
|
|
func (l *Link) UUID() string {
|
|
return l.uuid
|
|
}
|
|
|
|
func (l *Link) Path() string {
|
|
return AccessBin
|
|
}
|
|
|
|
func (l *Link) ConfFile() string {
|
|
return filepath.Join(AccessDir, l.uuid+".json")
|
|
}
|
|
|
|
func (l *Link) StatusFile() string {
|
|
return filepath.Join(AccessDir, l.uuid+".status")
|
|
}
|
|
|
|
func (l *Link) PidFile() string {
|
|
return filepath.Join(AccessDir, l.uuid+".pid")
|
|
}
|
|
|
|
func (l *Link) LogFile() string {
|
|
return filepath.Join(AccessDir, l.uuid+".log")
|
|
}
|
|
|
|
func (l *Link) Start() error {
|
|
file := l.ConfFile()
|
|
log, err := libol.CreateFile(l.LogFile())
|
|
if err != nil {
|
|
l.out.Warn("Link.Start %s", err)
|
|
return nil
|
|
}
|
|
libol.Go(func() {
|
|
args := []string{
|
|
"-alias", l.cfg.Connection + "@" + l.cfg.Network,
|
|
"-conf", file,
|
|
"-terminal", "ww",
|
|
}
|
|
l.out.Debug("Link.Start %s %v", l.Path(), args)
|
|
cmd := exec.Command(l.Path(), args...)
|
|
cmd.Stdout = log
|
|
cmd.Stderr = log
|
|
if err := cmd.Run(); err != nil {
|
|
l.out.Error("Link.Start %s: %s", l.uuid, err)
|
|
}
|
|
})
|
|
return nil
|
|
}
|
|
|
|
func (l *Link) Clean() {
|
|
files := []string{
|
|
l.LogFile(), l.StatusFile(), l.PidFile(), l.ConfFile(),
|
|
}
|
|
for _, file := range files {
|
|
if err := libol.FileExist(file); err == nil {
|
|
if err := os.Remove(file); err != nil {
|
|
l.out.Warn("Link.Clean %s", err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (l *Link) Stop() error {
|
|
if data, err := os.ReadFile(l.PidFile()); err != nil {
|
|
l.out.Debug("Link.Stop %s", err)
|
|
} else {
|
|
pid := strings.TrimSpace(string(data))
|
|
cmd := exec.Command("kill", pid)
|
|
if err := cmd.Run(); err != nil {
|
|
l.out.Warn("Link.Stop %s: %s", pid, err)
|
|
return err
|
|
}
|
|
}
|
|
l.Clean()
|
|
return nil
|
|
}
|
|
|
|
type Links struct {
|
|
lock sync.RWMutex
|
|
links map[string]*Link
|
|
}
|
|
|
|
func NewLinks() *Links {
|
|
return &Links{
|
|
links: make(map[string]*Link),
|
|
}
|
|
}
|
|
|
|
func (ls *Links) Add(l *Link) {
|
|
ls.lock.Lock()
|
|
defer ls.lock.Unlock()
|
|
ls.links[l.cfg.Connection] = l
|
|
}
|
|
|
|
func (ls *Links) Remove(addr string) *Link {
|
|
ls.lock.Lock()
|
|
defer ls.lock.Unlock()
|
|
if p, ok := ls.links[addr]; ok {
|
|
p.Stop()
|
|
delete(ls.links, addr)
|
|
return p
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type LinuxLink struct {
|
|
link nl.Link
|
|
}
|
|
|
|
func (ll *LinuxLink) Start() error {
|
|
if err := nl.LinkAdd(ll.link); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (ll *LinuxLink) Stop() error {
|
|
if err := nl.LinkDel(ll.link); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|