mirror of
https://github.com/luscis/openlan.git
synced 2025-09-26 20:41:29 +08:00
123 lines
2.9 KiB
Go
Executable File
123 lines
2.9 KiB
Go
Executable File
package app
|
|
|
|
import (
|
|
"encoding/json"
|
|
|
|
"github.com/luscis/openlan/pkg/cache"
|
|
"github.com/luscis/openlan/pkg/libol"
|
|
"github.com/luscis/openlan/pkg/models"
|
|
)
|
|
|
|
type Access struct {
|
|
success int
|
|
failed int
|
|
master Master
|
|
}
|
|
|
|
func NewAccess(m Master) *Access {
|
|
return &Access{
|
|
master: m,
|
|
}
|
|
}
|
|
|
|
func (p *Access) OnFrame(client libol.SocketClient, frame *libol.FrameMessage) error {
|
|
out := client.Out()
|
|
if out.Has(libol.LOG) {
|
|
out.Log("Access.OnFrame %s.", frame)
|
|
}
|
|
if frame.IsControl() {
|
|
action, params := frame.CmdAndParams()
|
|
out.Debug("Access.OnFrame: %s", action)
|
|
switch action {
|
|
case libol.LoginReq:
|
|
if err := p.handleLogin(client, params); err != nil {
|
|
out.Error("Access.OnFrame: %s", err)
|
|
m := libol.NewControlFrame(libol.LoginResp, []byte(err.Error()))
|
|
_ = client.WriteMsg(m)
|
|
//client.Close()
|
|
return err
|
|
}
|
|
m := libol.NewControlFrame(libol.LoginResp, []byte("okay"))
|
|
_ = client.WriteMsg(m)
|
|
}
|
|
//If instruct is not login and already auth, continue to process.
|
|
if client.Have(libol.ClAuth) {
|
|
return nil
|
|
}
|
|
}
|
|
//Dropped all frames if not auth.
|
|
if !client.Have(libol.ClAuth) {
|
|
out.Debug("Access.OnFrame: unAuth")
|
|
return libol.NewErr("unAuth client.")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (p *Access) handleLogin(client libol.SocketClient, data []byte) error {
|
|
out := client.Out()
|
|
out.Debug("Access.handleLogin: %s", data)
|
|
if client.Have(libol.ClAuth) {
|
|
out.Warn("Access.handleLogin: already auth")
|
|
return nil
|
|
}
|
|
user := &models.User{}
|
|
if err := json.Unmarshal(data, user); err != nil {
|
|
return libol.NewErr("Invalid json data.")
|
|
}
|
|
user.Update()
|
|
out.Info("Access.handleLogin: %s on %s", user.Id(), user.Alias)
|
|
if now, err := cache.User.Check(user); now != nil {
|
|
if now.Role != "admin" && now.Last != nil {
|
|
// To offline lastly client if guest.
|
|
p.master.OffClient(now.Last)
|
|
}
|
|
p.success++
|
|
now.Last = client
|
|
client.SetStatus(libol.ClAuth)
|
|
out.Info("Access.handleLogin: success")
|
|
_ = p.onAuth(client, user)
|
|
return nil
|
|
} else {
|
|
p.failed++
|
|
client.SetStatus(libol.ClUnAuth)
|
|
return err
|
|
}
|
|
}
|
|
|
|
func (p *Access) onAuth(client libol.SocketClient, user *models.User) error {
|
|
out := client.Out()
|
|
if !client.Have(libol.ClAuth) {
|
|
return libol.NewErr("not auth.")
|
|
}
|
|
out.Info("Access.onAuth")
|
|
dev, err := p.master.NewTap(user.Network)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
out.Info("Access.onAuth: on >>> %s <<<", dev.Name())
|
|
proto := p.master.Protocol()
|
|
m := models.NewAccess(client, dev, proto)
|
|
m.SetUser(user)
|
|
// free point has same uuid.
|
|
if om := cache.Access.GetByUUID(m.UUID); om != nil {
|
|
out.Info("Access.onAuth: OffClient %s", om.Client)
|
|
p.master.OffClient(om.Client)
|
|
}
|
|
client.SetPrivate(m)
|
|
cache.Access.Add(m)
|
|
libol.Go(func() {
|
|
p.master.ReadTap(dev, func(f *libol.FrameMessage) error {
|
|
if err := client.WriteMsg(f); err != nil {
|
|
p.master.OffClient(client)
|
|
return err
|
|
}
|
|
return nil
|
|
})
|
|
})
|
|
return nil
|
|
}
|
|
|
|
func (p *Access) Stats() (success, failed int) {
|
|
return p.success, p.failed
|
|
}
|