add micro controller for clients
This commit is contained in:
parent
c28a14010d
commit
c704b08d5c
|
@ -16,6 +16,7 @@ import (
|
||||||
"github.com/genofire/golang-lib/worker"
|
"github.com/genofire/golang-lib/worker"
|
||||||
|
|
||||||
configPackage "github.com/FreifunkBremen/freifunkmanager/config"
|
configPackage "github.com/FreifunkBremen/freifunkmanager/config"
|
||||||
|
wifiController "github.com/FreifunkBremen/freifunkmanager/controller"
|
||||||
"github.com/FreifunkBremen/freifunkmanager/runtime"
|
"github.com/FreifunkBremen/freifunkmanager/runtime"
|
||||||
"github.com/FreifunkBremen/freifunkmanager/ssh"
|
"github.com/FreifunkBremen/freifunkmanager/ssh"
|
||||||
"github.com/FreifunkBremen/freifunkmanager/websocket"
|
"github.com/FreifunkBremen/freifunkmanager/websocket"
|
||||||
|
@ -43,14 +44,16 @@ func main() {
|
||||||
commands = runtime.NewCommands(sshmanager)
|
commands = runtime.NewCommands(sshmanager)
|
||||||
// nodesUpdateWorker := worker.NewWorker(time.Duration(3)*time.Minute, nodes.Updater)
|
// nodesUpdateWorker := worker.NewWorker(time.Duration(3)*time.Minute, nodes.Updater)
|
||||||
nodesSaveWorker := worker.NewWorker(time.Duration(3)*time.Second, nodes.Saver)
|
nodesSaveWorker := worker.NewWorker(time.Duration(3)*time.Second, nodes.Saver)
|
||||||
|
controller := wifiController.NewController(sshmanager)
|
||||||
|
|
||||||
// go nodesUpdateWorker.Start()
|
// go nodesUpdateWorker.Start()
|
||||||
go nodesSaveWorker.Start()
|
go nodesSaveWorker.Start()
|
||||||
|
go controller.Start()
|
||||||
|
|
||||||
websocket.Start(nodes, commands)
|
websocket.Start(nodes, commands)
|
||||||
|
|
||||||
if config.Yanic.Enable {
|
if config.Yanic.Enable {
|
||||||
yanicDialer := yanic.Dial(config.Yanic.Type, config.Yanic.Address)
|
yanicDialer = yanic.Dial(config.Yanic.Type, config.Yanic.Address)
|
||||||
yanicDialer.NodeHandler = nodes.LearnNode
|
yanicDialer.NodeHandler = nodes.LearnNode
|
||||||
yanicDialer.GlobalsHandler = func(data *runtimeYanic.GlobalStats) {
|
yanicDialer.GlobalsHandler = func(data *runtimeYanic.GlobalStats) {
|
||||||
stats = data
|
stats = data
|
||||||
|
@ -90,6 +93,7 @@ func main() {
|
||||||
// Stop services
|
// Stop services
|
||||||
websocket.Close()
|
websocket.Close()
|
||||||
srv.Close()
|
srv.Close()
|
||||||
|
controller.Close()
|
||||||
if config.Yanic.Enable {
|
if config.Yanic.Enable {
|
||||||
yanicDialer.Close()
|
yanicDialer.Close()
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,139 @@
|
||||||
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/genofire/golang-lib/log"
|
||||||
|
|
||||||
|
"github.com/FreifunkBremen/freifunkmanager/ssh"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
maxDB = 80
|
||||||
|
)
|
||||||
|
|
||||||
|
type Controller struct {
|
||||||
|
sshMgmt *ssh.Manager
|
||||||
|
no24Ghz map[string]bool
|
||||||
|
node map[string]map[string]time.Time
|
||||||
|
quit chan struct{}
|
||||||
|
sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewController(ssh *ssh.Manager) *Controller {
|
||||||
|
return &Controller{
|
||||||
|
sshMgmt: ssh,
|
||||||
|
quit: make(chan struct{}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (c *Controller) Start() {
|
||||||
|
ticker := time.NewTicker(time.Second)
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ticker.C:
|
||||||
|
c.tick()
|
||||||
|
case <-c.quit:
|
||||||
|
ticker.Stop()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) Close() {
|
||||||
|
close(c.quit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) tick() {
|
||||||
|
c.sshMgmt.RunEverywhere("if [ \"$(uci get wireless.radio0.hwmode | grep -c a)\" -ne 0 ]; then echo \"radio0\"; elif [ \"$(uci get wireless.radio1.hwmode | grep -c a)\" -ne 0 ]; then echo \"radio1\"; fi", ssh.SSHResultToStringHandler(func(ip string, iface string, err error) {
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
addr := net.TCPAddr{IP: net.ParseIP(ip), Port: 22}
|
||||||
|
result, err := c.sshMgmt.RunOn(addr, fmt.Sprintf("iwinfo %s assoclist | grep SNR", iface))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, line := range strings.Split(result, "\n") {
|
||||||
|
parts := strings.Fields(line)
|
||||||
|
mac := parts[0]
|
||||||
|
db, err := strconv.Atoi(parts[1])
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.no24Ghz[mac] = true
|
||||||
|
|
||||||
|
if db > maxDB {
|
||||||
|
|
||||||
|
node, ok := c.node[ip]
|
||||||
|
if !ok {
|
||||||
|
node = make(map[string]time.Time)
|
||||||
|
c.node[ip] = node
|
||||||
|
}
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
if last, ok := node[mac]; ok && last.After(now.Add(-3*time.Second)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
log.Log.Info("force roamed %s from %s", mac, addr)
|
||||||
|
cmd := fmt.Sprintf("ubus call hostapd.%s del_client '{\"addr\":\"%s\", \"reason\":1, \"deauth\":true, \"ban_time\":1000}'", iface, mac)
|
||||||
|
c.sshMgmt.ExecuteOn(addr, cmd)
|
||||||
|
node[mac] = now
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}))
|
||||||
|
|
||||||
|
c.sshMgmt.RunEverywhere("if [ \"$(uci get wireless.radio0.hwmode | grep -c g)\" -ne 0 ]; then echo \"radio0\"; elif [ \"$(uci get wireless.radio1.hwmode | grep -c g)\" -ne 0 ]; then echo \"radio1\"; fi", ssh.SSHResultToStringHandler(func(ip string, iface string, err error) {
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
addr := net.TCPAddr{IP: net.ParseIP(ip), Port: 22}
|
||||||
|
result, err := c.sshMgmt.RunOn(addr, fmt.Sprintf("iwinfo %s assoclist | grep SNR", iface))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, line := range strings.Split(result, "\n") {
|
||||||
|
parts := strings.Fields(line)
|
||||||
|
mac := parts[0]
|
||||||
|
db, err := strconv.Atoi(parts[1])
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := fmt.Sprintf("ubus call hostapd.%s del_client '{\"addr\":\"%s\", \"reason\":1, \"deauth\":true, \"ban_time\":1000}'", iface, mac)
|
||||||
|
|
||||||
|
if c.no24Ghz[mac] {
|
||||||
|
log.Log.Info("kicked becouse it use 2.4 Ghz %s from %s", mac, addr)
|
||||||
|
c.sshMgmt.ExecuteOn(addr, cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
if db > maxDB {
|
||||||
|
|
||||||
|
node, ok := c.node[ip]
|
||||||
|
if !ok {
|
||||||
|
node = make(map[string]time.Time)
|
||||||
|
c.node[ip] = node
|
||||||
|
}
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
if last, ok := node[mac]; ok && last.After(now.Add(-3*time.Second)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
log.Log.Info("force roamed %s from %s", mac, addr)
|
||||||
|
c.sshMgmt.ExecuteOn(addr, cmd)
|
||||||
|
node[mac] = now
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}))
|
||||||
|
}
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SSHResultHandler func(string, error)
|
type SSHResultHandler func(string, string, error)
|
||||||
|
|
||||||
func SSHResultToString(result string) string {
|
func SSHResultToString(result string) string {
|
||||||
if len(result) > 0 {
|
if len(result) > 0 {
|
||||||
|
@ -18,15 +18,15 @@ func SSHResultToString(result string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func SSHResultToStringHandler(handler SSHResultHandler) SSHResultHandler {
|
func SSHResultToStringHandler(handler SSHResultHandler) SSHResultHandler {
|
||||||
return func(result string, err error) {
|
return func(addr string, result string, err error) {
|
||||||
handler(SSHResultToString(result), err)
|
handler(addr, SSHResultToString(result), err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) RunEverywhere(cmd string, handler SSHResultHandler) {
|
func (m *Manager) RunEverywhere(cmd string, handler SSHResultHandler) {
|
||||||
for host, client := range m.clients {
|
for host, client := range m.clients {
|
||||||
result, err := m.run(host, client, cmd)
|
result, err := m.run(host, client, cmd)
|
||||||
handler(result, err)
|
handler(host, result, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue