mirror of
https://github.com/luscis/openlan.git
synced 2025-09-26 20:41:29 +08:00
157 lines
3.7 KiB
Go
Executable File
157 lines
3.7 KiB
Go
Executable File
package app
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strings"
|
|
|
|
"github.com/luscis/openlan/pkg/cache"
|
|
"github.com/luscis/openlan/pkg/libol"
|
|
"github.com/luscis/openlan/pkg/models"
|
|
"github.com/luscis/openlan/pkg/schema"
|
|
)
|
|
|
|
type Request struct {
|
|
master Master
|
|
}
|
|
|
|
func NewRequest(m Master) *Request {
|
|
return &Request{
|
|
master: m,
|
|
}
|
|
}
|
|
|
|
func (r *Request) OnFrame(client libol.SocketClient, frame *libol.FrameMessage) error {
|
|
out := client.Out()
|
|
if frame.IsEthernet() {
|
|
return nil
|
|
}
|
|
if out.Has(libol.DEBUG) {
|
|
out.Log("Request.OnFrame %s.", frame)
|
|
}
|
|
action, body := frame.CmdAndParams()
|
|
if out.Has(libol.CMD) {
|
|
out.Cmd("Request.OnFrame: %s %s", action, body)
|
|
}
|
|
switch action {
|
|
case libol.NeighborReq:
|
|
r.onNeighbor(client, body)
|
|
case libol.IpAddrReq:
|
|
r.onIpAddr(client, body)
|
|
case libol.LeftReq:
|
|
r.onLeave(client, body)
|
|
case libol.LoginReq:
|
|
out.Debug("Request.OnFrame %s: %s", action, body)
|
|
default:
|
|
r.onDefault(client, body)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *Request) onDefault(client libol.SocketClient, data []byte) {
|
|
m := libol.NewControlFrame(libol.PongResp, data)
|
|
_ = client.WriteMsg(m)
|
|
}
|
|
|
|
func (r *Request) onNeighbor(client libol.SocketClient, data []byte) {
|
|
resp := make([]schema.Neighbor, 0, 32)
|
|
for obj := range cache.Neighbor.List() {
|
|
if obj == nil {
|
|
break
|
|
}
|
|
resp = append(resp, models.NewNeighborSchema(obj))
|
|
}
|
|
if respStr, err := json.Marshal(resp); err == nil {
|
|
m := libol.NewControlFrame(libol.NeighborResp, respStr)
|
|
_ = client.WriteMsg(m)
|
|
}
|
|
}
|
|
|
|
func findLease(ifAddr string, p *models.Access) *schema.Lease {
|
|
alias := p.Alias
|
|
network := p.Network
|
|
lease := cache.Network.GetLease(alias, network) // try by alias firstly
|
|
if ifAddr == "" {
|
|
if lease == nil { // now to alloc it.
|
|
lease = cache.Network.NewLease(alias, network)
|
|
}
|
|
if lease == nil {
|
|
return nil
|
|
}
|
|
// has static address.
|
|
lease.Client = p.Client.String()
|
|
return lease
|
|
}
|
|
ipAddr := strings.SplitN(ifAddr, "/", 2)[0]
|
|
if lease == nil { //renew it.
|
|
has := cache.Network.GetLeaseByAddr(ipAddr, network)
|
|
if has == nil {
|
|
lease = cache.Network.AddLease(alias, ipAddr, network)
|
|
} else {
|
|
lease = cache.Network.NewLease(alias, network)
|
|
}
|
|
} else if lease.Address != ipAddr { // update
|
|
lease = cache.Network.AddLease(alias, ipAddr, network)
|
|
}
|
|
lease.Client = p.Client.String()
|
|
return lease
|
|
}
|
|
|
|
func (r *Request) onIpAddr(client libol.SocketClient, data []byte) {
|
|
out := client.Out()
|
|
out.Info("Request.onIpAddr: %s", data)
|
|
recv := models.NewNetwork("", "")
|
|
if err := json.Unmarshal(data, recv); err != nil {
|
|
out.Error("Request.onIpAddr: invalid json data.")
|
|
return
|
|
}
|
|
if recv.Name == "" {
|
|
recv.Name = recv.Tenant
|
|
}
|
|
if recv.Name == "" {
|
|
recv.Name = "default"
|
|
}
|
|
n := cache.Network.Get(recv.Name)
|
|
if n == nil {
|
|
out.Error("Request.onIpAddr: invalid network %s.", recv.Name)
|
|
return
|
|
}
|
|
out.Cmd("Request.onIpAddr: find %s", n)
|
|
p := cache.Access.Get(client.String())
|
|
if p == nil {
|
|
out.Error("Request.onIpAddr: point notFound")
|
|
return
|
|
}
|
|
resp := &models.Network{
|
|
Name: n.Name,
|
|
Address: recv.Address,
|
|
Netmask: recv.Netmask,
|
|
Gateway: libol.ParseAddr(n.Address).String(),
|
|
Routes: n.Routes,
|
|
}
|
|
lease := findLease(recv.Address, p)
|
|
if lease != nil {
|
|
resp.Address = lease.Address
|
|
resp.Netmask = n.Netmask
|
|
resp.Routes = n.Routes
|
|
} else {
|
|
resp.Address = "169.254.0.0"
|
|
resp.Netmask = n.Netmask
|
|
if resp.Netmask == "" {
|
|
resp.Netmask = "255.255.0.0"
|
|
}
|
|
resp.Routes = n.Routes
|
|
}
|
|
out.Cmd("Request.onIpAddr: resp %s", resp)
|
|
if respStr, err := json.Marshal(resp); err == nil {
|
|
m := libol.NewControlFrame(libol.IpAddrResp, respStr)
|
|
_ = client.WriteMsg(m)
|
|
}
|
|
out.Info("Request.onIpAddr: %s", resp.Address)
|
|
}
|
|
|
|
func (r *Request) onLeave(client libol.SocketClient, data []byte) {
|
|
out := client.Out()
|
|
out.Info("Request.onLeave")
|
|
r.master.OffClient(client)
|
|
}
|