fea: config: add tests

This commit is contained in:
Daniel Ding
2022-10-28 20:52:02 +08:00
parent a69383c919
commit 72d8316aaa
15 changed files with 209 additions and 228 deletions

View File

@@ -1,4 +1,4 @@
# --- point.cfg --- # --- point.cfg ---
# This file define the configuration for OpenLAN Proxy. # This file define the configuration for OpenLAN Proxy.
OPTIONS='-log:file /dev/null -conf /etc/openlan/proxy.json' OPTIONS='-terminal off -log:file /dev/null'

View File

@@ -17,7 +17,7 @@ func (c *Crypt) IsZero() bool {
return c.Algo == "" && c.Secret == "" return c.Algo == "" && c.Secret == ""
} }
func (c *Crypt) Default() { func (c *Crypt) Correct() {
if c.Secret != "" && c.Algo == "" { if c.Secret != "" && c.Algo == "" {
c.Algo = "xor" c.Algo = "xor"
} }

View File

@@ -5,7 +5,7 @@ type manager struct {
} }
var Manager = manager{ var Manager = manager{
Switch: DefaultSwitch(), Switch: &Switch{},
} }
func Reload() { func Reload() {

View File

@@ -20,7 +20,7 @@ var (
QdVWr = 32 * 4 QdVWr = 32 * 4
) )
func (q *Queue) Default() { func (q *Queue) Correct() {
if q.SockWr == 0 { if q.SockWr == 0 {
q.SockWr = QdSwr q.SockWr = QdSwr
} }
@@ -39,5 +39,5 @@ func (q *Queue) Default() {
if q.VirWrt == 0 { if q.VirWrt == 0 {
q.VirWrt = QdVWr q.VirWrt = QdVWr
} }
libol.Debug("Queue.Default %v", q) libol.Debug("Queue.Correct %v", q)
} }

View File

@@ -41,42 +41,26 @@ type Point struct {
PidFile string `json:"pid,omitempty"` PidFile string `json:"pid,omitempty"`
} }
func DefaultPoint() *Point { func (i *Interface) Correct() {
obj := &Point{ if i.Provider == "" {
Alias: "", i.Provider = "kernel"
Connection: "xx.openlan.net", }
Network: "default", if i.Cost == 0 {
Protocol: "tcp", // udp, kcp, tcp, tls, ws and wss etc. i.Cost = 666
Timeout: 60, }
Log: Log{ if i.IPMtu == 0 {
File: "./point.log", i.IPMtu = 1500
Verbose: libol.INFO, }
}, }
Interface: Interface{
IPMtu: 1500, func (l *Log) Correct() {
Provider: "kernel", if l.Verbose == 0 {
Name: "", l.Verbose = libol.INFO
Cost: 1000,
},
SaveFile: "./point.json",
RequestAddr: true,
Crypt: &Crypt{},
Cert: &Cert{},
Terminal: "on",
} }
obj.Correct(nil)
return obj
} }
func NewPoint() *Point { func NewPoint() *Point {
obj := DefaultPoint() p := &Point{RequestAddr: true}
p := &Point{
RequestAddr: true,
Crypt: obj.Crypt,
Cert: obj.Cert,
Interface: obj.Interface,
}
p.Flags()
p.Parse() p.Parse()
if p.Terminal == "off" { if p.Terminal == "off" {
log.SetFlags(0) log.SetFlags(0)
@@ -85,20 +69,11 @@ func NewPoint() *Point {
return p return p
} }
func (ap *Point) Flags() {
obj := DefaultPoint()
flag.StringVar(&ap.Alias, "alias", obj.Alias, "Alias for this point")
flag.StringVar(&ap.Terminal, "terminal", obj.Terminal, "Run interactive terminal")
flag.StringVar(&ap.Connection, "conn", obj.Connection, "Connection access to")
flag.StringVar(&ap.Log.File, "log:file", obj.Log.File, "File log saved to")
flag.IntVar(&ap.Log.Verbose, "log:level", obj.Log.Verbose, "Log level value")
flag.StringVar(&ap.SaveFile, "conf", obj.SaveFile, "The configuration file")
flag.StringVar(&ap.PProf, "pprof", obj.PProf, "Http listen for pprof debug")
flag.StringVar(&ap.Cert.CaFile, "cacert", obj.Cert.CaFile, "CA certificate file")
flag.StringVar(&ap.PidFile, "pid", obj.PidFile, "Write pid to file")
}
func (ap *Point) Parse() { func (ap *Point) Parse() {
flag.StringVar(&ap.Alias, "alias", "", "Alias for this point")
flag.StringVar(&ap.Log.File, "log:file", "", "File log saved to")
flag.StringVar(&ap.Terminal, "terminal", "", "Run interactive terminal")
flag.StringVar(&ap.SaveFile, "conf", "", "The configuration file")
flag.Parse() flag.Parse()
} }
@@ -110,58 +85,50 @@ func (ap *Point) Initialize() {
if err := ap.Load(); err != nil { if err := ap.Load(); err != nil {
libol.Warn("NewPoint.Initialize %s", err) libol.Warn("NewPoint.Initialize %s", err)
} }
ap.Default() ap.Correct()
libol.SetLogger(ap.Log.File, ap.Log.Verbose) libol.SetLogger(ap.Log.File, ap.Log.Verbose)
} }
func (ap *Point) Correct(obj *Point) { func (ap *Point) Correct() {
if ap.Alias == "" { if ap.Alias == "" {
ap.Alias = GetAlias() ap.Alias = GetAlias()
} }
if ap.Network == "" { if ap.Network == "" {
if strings.Contains(ap.Username, "@") { if strings.Contains(ap.Username, "@") {
ap.Network = strings.SplitN(ap.Username, "@", 2)[1] ap.Network = strings.SplitN(ap.Username, "@", 2)[1]
} else if obj != nil {
ap.Network = obj.Network
} }
} }
CorrectAddr(&ap.Connection, 10002) CorrectAddr(&ap.Connection, 10002)
if runtime.GOOS == "darwin" { if runtime.GOOS == "darwin" {
ap.Interface.Provider = "tun" ap.Interface.Provider = "tun"
} }
if ap.Terminal == "" {
ap.Terminal = "on"
}
if ap.Protocol == "tls" || ap.Protocol == "wss" { if ap.Protocol == "tls" || ap.Protocol == "wss" {
if ap.Cert == nil && obj != nil { if ap.Cert == nil {
ap.Cert = obj.Cert ap.Cert = &Cert{}
} }
} }
if ap.Protocol == "" && obj != nil { if ap.Protocol == "" {
ap.Protocol = obj.Protocol ap.Protocol = "tcp"
} }
if ap.Cert != nil { if ap.Cert != nil {
ap.Cert.Correct() ap.Cert.Correct()
} }
if ap.Timeout == 0 && obj != nil { if ap.Crypt == nil {
ap.Timeout = obj.Timeout ap.Crypt = &Crypt{}
} }
if ap.Interface.Cost == 0 && obj != nil { ap.Crypt.Correct()
ap.Interface.Cost = obj.Interface.Cost if ap.Timeout == 0 {
ap.Timeout = 60
} }
if ap.Interface.IPMtu == 0 && obj != nil { ap.Interface.Correct()
ap.Interface.IPMtu = obj.Interface.IPMtu ap.Log.Correct()
}
}
func (ap *Point) Default() {
obj := DefaultPoint()
ap.Correct(obj)
if ap.Queue == nil { if ap.Queue == nil {
ap.Queue = &Queue{} ap.Queue = &Queue{}
} }
ap.Queue.Default() ap.Queue.Correct()
//reset zero value to default
if ap.Crypt != nil {
ap.Crypt.Default()
}
} }
func (ap *Point) Load() error { func (ap *Point) Load() error {

40
pkg/config/point_test.go Normal file
View File

@@ -0,0 +1,40 @@
package config
import (
"fmt"
"github.com/luscis/openlan/pkg/libol"
"github.com/stretchr/testify/assert"
"os"
"testing"
)
func TestPointFlags(t *testing.T) {
ap := Point{}
os.Args = []string{
"app",
"-conf", "/etc/openlan/fake.json",
"-terminal", "off",
"-alias", "fake",
}
ap.Parse()
fmt.Println(ap)
assert.Equal(t, "fake", ap.Alias, "be the same.")
assert.Equal(t, "/etc/openlan/fake.json", ap.SaveFile, "be the same.")
assert.Equal(t, "off", ap.Terminal, "be the same.")
}
func TestPoint(t *testing.T) {
ap := Point{
Username: "user0@fake",
}
ap.Correct()
assert.Equal(t, libol.INFO, ap.Log.Verbose, "be the same.")
assert.Equal(t, "tcp", ap.Protocol, "be the same.")
assert.Equal(t, "", ap.Crypt.Algo, "be the same.")
assert.Equal(t, "fake", ap.Network, "be the same.")
assert.Equal(t, "on", ap.Terminal, "be the same.")
ap.Crypt.Secret = "fake-pass"
ap.Correct()
assert.Equal(t, "xor", ap.Crypt.Algo, "be the same.")
}

View File

@@ -41,34 +41,18 @@ type Proxy struct {
PProf string `json:"pprof"` PProf string `json:"pprof"`
} }
func DefaultProxy() *Proxy {
obj := &Proxy{
Log: Log{
File: LogFile("openlan-proxy.log"),
Verbose: libol.INFO,
},
}
obj.Correct(nil)
return obj
}
func NewProxy() *Proxy { func NewProxy() *Proxy {
p := &Proxy{} p := &Proxy{}
p.Flags()
p.Parse() p.Parse()
p.Initialize() p.Initialize()
return p return p
} }
func (p *Proxy) Flags() {
obj := DefaultProxy()
flag.StringVar(&p.Log.File, "log:file", obj.Log.File, "Configure log file")
flag.StringVar(&p.Conf, "conf", obj.Conf, "The configure file")
flag.StringVar(&p.PProf, "prof", obj.PProf, "Http listen for CPU prof")
flag.IntVar(&p.Log.Verbose, "log:level", obj.Log.Verbose, "Configure log level")
}
func (p *Proxy) Parse() { func (p *Proxy) Parse() {
flag.StringVar(&p.Log.File, "log:file", "", "Configure log file")
flag.StringVar(&p.Conf, "conf", "", "The configure file")
flag.StringVar(&p.PProf, "prof", "", "Http listen for CPU prof")
flag.IntVar(&p.Log.Verbose, "log:level", 20, "Configure log level")
flag.Parse() flag.Parse()
} }
@@ -80,16 +64,17 @@ func (p *Proxy) Initialize() {
libol.Debug("Proxy.Initialize %v", p) libol.Debug("Proxy.Initialize %v", p)
} }
func (p *Proxy) Correct(obj *Proxy) { func (p *Proxy) Correct() {
for _, h := range p.Http { for _, h := range p.Http {
if h.Cert != nil { if h.Cert != nil {
h.Cert.Correct() h.Cert.Correct()
} }
} }
p.Log.Correct()
} }
func (p *Proxy) Default() { func (p *Proxy) Default() {
p.Correct(nil) p.Correct()
} }
func (p *Proxy) Load() error { func (p *Proxy) Load() error {

View File

@@ -6,20 +6,6 @@ import (
"path/filepath" "path/filepath"
) )
func DefaultPerf() *Perf {
return &Perf{
Point: 64,
Neighbor: 64,
OnLine: 64,
Link: 64,
User: 1024,
Esp: 64,
State: 64 * 4,
Policy: 64 * 8,
VxLAN: 64,
}
}
type Perf struct { type Perf struct {
Point int `json:"point"` Point int `json:"point"`
Neighbor int `json:"neighbor"` Neighbor int `json:"neighbor"`
@@ -32,33 +18,33 @@ type Perf struct {
VxLAN int `json:"vxlan"` VxLAN int `json:"vxlan"`
} }
func (p *Perf) Correct(obj *Perf) { func (p *Perf) Correct() {
if p.Point == 0 && obj != nil { if p.Point == 0 {
p.Point = obj.Point p.Point = 64
} }
if p.Neighbor == 0 && obj != nil { if p.Neighbor == 0 {
p.Neighbor = obj.Neighbor p.Neighbor = 64
} }
if p.OnLine == 0 && obj != nil { if p.OnLine == 0 {
p.OnLine = obj.OnLine p.OnLine = 64
} }
if p.Link == 0 && obj != nil { if p.Link == 0 {
p.Link = obj.Link p.Link = 64
} }
if p.User == 0 && obj != nil { if p.User == 0 {
p.User = obj.User p.User = 1024
} }
if p.Esp == 0 && obj != nil { if p.Esp == 0 {
p.Esp = obj.Esp p.Esp = 64
} }
if p.State == 0 && obj != nil { if p.State == 0 {
p.State = obj.State p.State = 64 * 4
} }
if p.Policy == 0 && obj != nil { if p.Policy == 0 {
p.Policy = obj.Policy p.Policy = 64 * 8
} }
if p.VxLAN == 0 && obj != nil { if p.VxLAN == 0 {
p.VxLAN = obj.VxLAN p.VxLAN = 64
} }
} }
@@ -85,40 +71,17 @@ type Switch struct {
TokenFile string `json:"-"` TokenFile string `json:"-"`
} }
func DefaultSwitch() *Switch {
obj := &Switch{
Timeout: 120,
Log: Log{
File: LogFile("openlan-switch.log"),
Verbose: libol.INFO,
},
Http: &Http{
Listen: "0.0.0.0:10000",
},
Listen: "0.0.0.0:10002",
Cert: &Cert{},
Crypt: &Crypt{},
}
obj.Correct(nil)
return obj
}
func NewSwitch() *Switch { func NewSwitch() *Switch {
s := Manager.Switch s := Manager.Switch
s.Flags()
s.Parse() s.Parse()
s.Initialize() s.Initialize()
return s return s
} }
func (s *Switch) Flags() {
obj := DefaultSwitch()
flag.StringVar(&s.Log.File, "log:file", obj.Log.File, "Configure log file")
flag.StringVar(&s.ConfDir, "conf:dir", obj.ConfDir, "Configure switch's directory")
flag.IntVar(&s.Log.Verbose, "log:level", obj.Log.Verbose, "Configure log level")
}
func (s *Switch) Parse() { func (s *Switch) Parse() {
flag.StringVar(&s.Log.File, "log:file", "", "Configure log file")
flag.StringVar(&s.ConfDir, "conf:dir", "", "Configure switch's directory")
flag.IntVar(&s.Log.Verbose, "log:level", 20, "Configure log level")
flag.Parse() flag.Parse()
} }
@@ -127,31 +90,48 @@ func (s *Switch) Initialize() {
if err := s.Load(); err != nil { if err := s.Load(); err != nil {
libol.Error("Switch.Initialize %s", err) libol.Error("Switch.Initialize %s", err)
} }
s.Default() s.Correct()
s.LoadExt()
libol.Debug("Switch.Initialize %v", s) libol.Debug("Switch.Initialize %v", s)
} }
func (s *Switch) Correct(obj *Switch) { func (s *Switch) LoadExt() {
s.LoadAcl()
s.LoadNetwork()
}
func (s *Switch) Correct() {
if s.Alias == "" { if s.Alias == "" {
s.Alias = GetAlias() s.Alias = GetAlias()
} }
if s.Listen == "" {
s.Listen = "0.0.0.0:10002"
}
CorrectAddr(&s.Listen, 10002) CorrectAddr(&s.Listen, 10002)
if s.Http == nil {
s.Http = &Http{
Listen: "0.0.0.0:10000",
}
}
if s.Http != nil { if s.Http != nil {
CorrectAddr(&s.Http.Listen, 10000) CorrectAddr(&s.Http.Listen, 10000)
} }
if s.Timeout == 0 {
s.Timeout = 120
}
libol.Debug("Proxy.Correct Http %v", s.Http) libol.Debug("Proxy.Correct Http %v", s.Http)
s.TokenFile = filepath.Join(s.ConfDir, "token") s.TokenFile = filepath.Join(s.ConfDir, "token")
s.File = filepath.Join(s.ConfDir, "switch.json") s.File = filepath.Join(s.ConfDir, "switch.json")
if s.Cert == nil { if s.Cert == nil {
s.Cert = obj.Cert s.Cert = &Cert{}
} else {
s.Cert.Correct()
} }
s.Cert.Correct()
if s.Crypt == nil { if s.Crypt == nil {
s.Crypt = obj.Crypt s.Crypt = &Crypt{}
} }
perf := &s.Perf s.Log.Correct()
perf.Correct(DefaultPerf()) s.Crypt.Correct()
s.Perf.Correct()
s.PassFile = filepath.Join(s.ConfDir, "password") s.PassFile = filepath.Join(s.ConfDir, "password")
if s.Protocol == "" { if s.Protocol == "" {
s.Protocol = "tcp" s.Protocol = "tcp"
@@ -159,6 +139,7 @@ func (s *Switch) Correct(obj *Switch) {
if s.AddrPool == "" { if s.AddrPool == "" {
s.AddrPool = "100.44" s.AddrPool = "100.44"
} }
s.Queue.Correct()
} }
func (s *Switch) Dir(elem ...string) string { func (s *Switch) Dir(elem ...string) string {
@@ -211,7 +192,7 @@ func (s *Switch) LoadNetwork() {
s.Format() s.Format()
for _, obj := range s.Network { for _, obj := range s.Network {
for _, link := range obj.Links { for _, link := range obj.Links {
link.Default() link.Correct()
} }
obj.Correct() obj.Correct()
obj.Alias = s.Alias obj.Alias = s.Alias
@@ -246,21 +227,6 @@ func (s *Switch) LoadAcl() {
} }
} }
func (s *Switch) Default() {
obj := DefaultSwitch()
s.Correct(obj)
if s.Timeout == 0 {
s.Timeout = obj.Timeout
}
if s.Crypt != nil {
s.Crypt.Default()
}
queue := &s.Queue
queue.Default()
s.LoadAcl()
s.LoadNetwork()
}
func (s *Switch) Load() error { func (s *Switch) Load() error {
return libol.UnmarshalLoad(s, s.File) return libol.UnmarshalLoad(s, s.File)
} }

18
pkg/config/switch_test.go Normal file
View File

@@ -0,0 +1,18 @@
package config
import (
"github.com/luscis/openlan/pkg/libol"
"github.com/stretchr/testify/assert"
"testing"
)
func TestSwitch(t *testing.T) {
sw := Switch{}
sw.Correct()
assert.Equal(t, libol.INFO, sw.Log.Verbose, "be the same.")
assert.Equal(t, "0.0.0.0:10002", sw.Listen, "be the same.")
assert.Equal(t, "0.0.0.0:10000", sw.Http.Listen, "be the same.")
sw.Listen = "192.168.1.0"
sw.Correct()
assert.Equal(t, "192.168.1.0:10002", sw.Listen, "be the same.")
}

View File

@@ -10,7 +10,7 @@ import (
) )
const ( const (
PRINT = 00 PRINT = 01
LOG = 05 LOG = 05
STACK = 06 STACK = 06
DEBUG = 10 DEBUG = 10

View File

@@ -2,6 +2,7 @@ package libol
import ( import (
"bytes" "bytes"
"crypto/md5"
"net" "net"
"sync" "sync"
"time" "time"
@@ -214,27 +215,28 @@ func (s *SocketClientImpl) negotiate() error {
return err return err
} }
s.status = ClNegotiating s.status = ClNegotiating
if reply, err := s.ReadMsg(); err == nil { reply, err := s.ReadMsg()
if reply.IsControl() { if err != nil {
action, params := reply.CmdAndParams()
if action != NegoResp {
return NewErr("wrong message type: %s", action)
}
if bytes.Compare(key, params) != 0 {
return NewErr("negotiate key failed: %s != %s", key, params)
}
if block := s.message.Crypt(); block != nil {
block.Update(string(key))
}
s.status = ClNegotiated
return nil
} else {
Info("SocketClientImpl.negotiate %s", reply.String())
}
return NewErr("wrong message type")
} else {
return err return err
} }
if !reply.IsControl() {
Info("SocketClientImpl.negotiate %s", reply.String())
return NewErr("wrong message type")
}
action, params := reply.CmdAndParams()
if action != NegoResp {
return NewErr("wrong message type: %s", action)
}
Cmd("SocketClientImpl.negotiate %s %x", action, params)
sum := md5.Sum(key)
if bytes.Compare(sum[:md5.Size], params) != 0 {
return NewErr("negotiate key failed: %x != %x", key, params)
}
if block := s.message.Crypt(); block != nil {
block.Update(string(key))
}
s.status = ClNegotiated
return nil
} }
// MUST IMPLEMENT // MUST IMPLEMENT
@@ -454,27 +456,28 @@ func (t *SocketServerImpl) negotiate(client SocketClient) error {
if client.Key() == "" { if client.Key() == "" {
return nil return nil
} }
if request, err := client.ReadMsg(); err == nil { request, err := client.ReadMsg()
if request.IsControl() { if err != nil {
client.SetStatus(ClNegotiated)
action, params := request.CmdAndParams()
if action == NegoReq {
Info("SocketServerImpl.negotiate %s", params)
reply := NewControlFrame(NegoResp, params)
if err := client.WriteMsg(reply); err != nil {
return err
}
client.SetKey(string(params))
return nil
}
return NewErr("wrong message type: %s", action)
} else {
Info("SocketServerImpl.negotiate %s", request.String())
}
return NewErr("wrong message type")
} else {
return err return err
} }
if !request.IsControl() {
Info("SocketServerImpl.negotiate %s", request.String())
return NewErr("wrong message type")
}
client.SetStatus(ClNegotiated)
action, params := request.CmdAndParams()
if action == NegoReq {
Cmd("SocketServerImpl.negotiate %s", params)
sum := md5.Sum(params)
reply := NewControlFrame(NegoResp, sum[:md5.Size])
if err := client.WriteMsg(reply); err != nil {
return err
}
client.SetKey(string(params))
return nil
}
return NewErr("wrong message type: %s", action)
} }
func (t *SocketServerImpl) doOnClient(call ServerListener, client SocketClient) { func (t *SocketServerImpl) doOnClient(call ServerListener, client SocketClient) {

View File

@@ -83,6 +83,7 @@ func (f *FireWall) jumpOLC() {
} }
func (f *FireWall) Initialize() { func (f *FireWall) Initialize() {
IpInit()
// Init chains // Init chains
f.addOLC() f.addOLC()
f.jumpOLC() f.jumpOLC()
@@ -174,7 +175,3 @@ func (f *FireWall) Refresh() {
f.cancel() f.cancel()
f.install() f.install()
} }
func init() {
IpInit()
}

View File

@@ -238,7 +238,13 @@ func (chains IpChains) Pop(obj IpChain) IpChains {
return news[:index] return news[:index]
} }
var __iptablesInit__ = false
func IpInit() { func IpInit() {
if __iptablesInit__ {
return
}
__iptablesInit__ = true
if err := iptables.FirewalldInit(); err != nil { if err := iptables.FirewalldInit(); err != nil {
libol.Error("IpInit %s", err) libol.Error("IpInit %s", err)
} }

View File

@@ -87,8 +87,7 @@ func (l *Link) Start() {
} }
libol.Go(func() { libol.Go(func() {
args := []string{ args := []string{
"-alias", l.cfg.Network, "-alias", l.cfg.Connection + "@" + l.cfg.Network,
"-conn", l.cfg.Connection,
"-conf", file, "-conf", file,
"-terminal", "ww", "-terminal", "ww",
} }

View File

@@ -79,9 +79,9 @@ func (w *OpenLANWorker) Initialize() {
func (w *OpenLANWorker) LoadLinks() { func (w *OpenLANWorker) LoadLinks() {
if w.cfg.Links != nil { if w.cfg.Links != nil {
for _, lin := range w.cfg.Links { for _, link := range w.cfg.Links {
lin.Default() link.Correct()
w.AddLink(&lin) w.AddLink(&link)
} }
} }
} }