diff --git a/config_example.conf b/config_example.conf index a94a032..218b4b7 100644 --- a/config_example.conf +++ b/config_example.conf @@ -49,3 +49,12 @@ ifname = "wlp4s0" # Local UDP port where Yanic will listen for response packets. Default: a dynamically selected port # (note: request packets to nodes will always be sent to port 1001, regardless of this setting) # port = 1001 + + +# nodes will pinged periodically +[pinger] +# if true, nodes will pinged periodically. default: false +enable = true +every = "1s" +timeout = "1s" +count = 1 \ No newline at end of file diff --git a/data/ping_result.go b/data/ping_result.go index b6225d2..502341f 100644 --- a/data/ping_result.go +++ b/data/ping_result.go @@ -1,6 +1,6 @@ package data type PingResult struct { - True []string `json:"true"` - False []string `json:"false"` -} \ No newline at end of file + True []string `json:"true"` + False []string `json:"false"` +} diff --git a/main.go b/main.go index 0d9b30d..75bc45b 100644 --- a/main.go +++ b/main.go @@ -56,12 +56,13 @@ func main() { ws := websocket.NewWebsocketServer(config.Secret, config.SSHIPAddressPrefix, db, config.BlacklistFor.Duration, nodesYanic) yanic := runtime.NewYanicDB(db, sshmanager, config.BlacklistFor.Duration, ws.SendNode, ws.SendStats, config.SSHIPAddressPrefix) - - pinger, err := runtime.NewPinger(db, config.BlacklistFor.Duration, ws.SendPing) - if err != nil { - log.Panic(err) + if config.Pinger.Enable { + pinger, err := runtime.NewPinger(db, &config.Pinger, config.BlacklistFor.Duration, ws.SendPing) + if err != nil { + log.Panic(err) + } + go pinger.Start() } - go pinger.Start() if config.YanicEnable { if duration := config.YanicSynchronize.Duration; duration > 0 { diff --git a/runtime/channel.go b/runtime/channel.go index 483d05c..7c69720 100644 --- a/runtime/channel.go +++ b/runtime/channel.go @@ -16,71 +16,71 @@ var ( ChannelEU = true ChannelList = map[uint32]*Channel{ - 1: &Channel{Frequency: 2412, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, - 2: &Channel{Frequency: 2417, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, - 3: &Channel{Frequency: 2422, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, - 4: &Channel{Frequency: 2427, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, - 5: &Channel{Frequency: 2432, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, - 6: &Channel{Frequency: 2437, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, - 7: &Channel{Frequency: 2442, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, - 8: &Channel{Frequency: 2447, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, - 9: &Channel{Frequency: 2452, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, - 10: &Channel{Frequency: 2457, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, - 11: &Channel{Frequency: 2462, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, - 12: &Channel{Frequency: 2467, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, - 13: &Channel{Frequency: 2472, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, - 14: &Channel{Frequency: 2484, AllowedInEU: false, DFS: false, Indoor: false, SDR: false}, - 32: &Channel{Frequency: 5160, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, - 34: &Channel{Frequency: 5170, AllowedInEU: false, DFS: false, Indoor: true, SDR: false}, - 36: &Channel{Frequency: 5180, AllowedInEU: true, DFS: false, Indoor: true, SDR: false}, - 38: &Channel{Frequency: 5190, AllowedInEU: false, DFS: false, Indoor: true, SDR: false}, - 40: &Channel{Frequency: 5200, AllowedInEU: true, DFS: false, Indoor: true, SDR: false}, - 42: &Channel{Frequency: 5210, AllowedInEU: false, DFS: false, Indoor: true, SDR: false}, - 44: &Channel{Frequency: 5220, AllowedInEU: true, DFS: false, Indoor: true, SDR: false}, - 46: &Channel{Frequency: 5230, AllowedInEU: false, DFS: false, Indoor: true, SDR: false}, - 48: &Channel{Frequency: 5240, AllowedInEU: true, DFS: false, Indoor: true, SDR: false}, - 50: &Channel{Frequency: 5250, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, - 52: &Channel{Frequency: 5260, AllowedInEU: true, DFS: true, Indoor: true, SDR: false}, - 54: &Channel{Frequency: 5270, AllowedInEU: false, DFS: true, Indoor: true, SDR: false}, - 56: &Channel{Frequency: 5280, AllowedInEU: true, DFS: true, Indoor: true, SDR: false}, - 58: &Channel{Frequency: 5290, AllowedInEU: false, DFS: true, Indoor: true, SDR: false}, - 60: &Channel{Frequency: 5300, AllowedInEU: true, DFS: true, Indoor: true, SDR: false}, - 62: &Channel{Frequency: 5310, AllowedInEU: false, DFS: true, Indoor: true, SDR: false}, - 64: &Channel{Frequency: 5320, AllowedInEU: true, DFS: true, Indoor: true, SDR: false}, - 68: &Channel{Frequency: 5340, AllowedInEU: true, DFS: true, Indoor: true, SDR: false}, - 96: &Channel{Frequency: 5480, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, - 100: &Channel{Frequency: 5500, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, - 102: &Channel{Frequency: 5510, AllowedInEU: false, DFS: true, Indoor: false, SDR: false}, - 104: &Channel{Frequency: 5520, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, - 106: &Channel{Frequency: 5530, AllowedInEU: false, DFS: true, Indoor: false, SDR: false}, - 108: &Channel{Frequency: 5540, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, - 110: &Channel{Frequency: 5550, AllowedInEU: false, DFS: true, Indoor: false, SDR: false}, - 112: &Channel{Frequency: 5560, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, - 114: &Channel{Frequency: 5570, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, - 116: &Channel{Frequency: 5580, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, - 118: &Channel{Frequency: 5590, AllowedInEU: false, DFS: true, Indoor: false, SDR: false}, - 120: &Channel{Frequency: 5600, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, - 122: &Channel{Frequency: 5610, AllowedInEU: false, DFS: true, Indoor: false, SDR: false}, - 124: &Channel{Frequency: 5620, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, - 126: &Channel{Frequency: 5630, AllowedInEU: false, DFS: true, Indoor: false, SDR: false}, - 128: &Channel{Frequency: 5640, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, - 132: &Channel{Frequency: 5660, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, - 134: &Channel{Frequency: 5670, AllowedInEU: false, DFS: true, Indoor: false, SDR: false}, - 136: &Channel{Frequency: 5680, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, - 138: &Channel{Frequency: 5690, AllowedInEU: false, DFS: true, Indoor: false, SDR: false}, - 140: &Channel{Frequency: 5700, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, - 142: &Channel{Frequency: 5710, AllowedInEU: false, DFS: true, Indoor: false, SDR: false}, - 144: &Channel{Frequency: 5720, AllowedInEU: true, DFS: true, Indoor: false, SDR: true}, - 149: &Channel{Frequency: 5745, AllowedInEU: true, DFS: false, Indoor: false, SDR: true}, - 151: &Channel{Frequency: 5755, AllowedInEU: true, DFS: false, Indoor: false, SDR: true}, - 153: &Channel{Frequency: 5765, AllowedInEU: true, DFS: false, Indoor: false, SDR: true}, - 155: &Channel{Frequency: 5775, AllowedInEU: true, DFS: false, Indoor: false, SDR: true}, - 157: &Channel{Frequency: 5785, AllowedInEU: true, DFS: false, Indoor: false, SDR: true}, - 159: &Channel{Frequency: 5795, AllowedInEU: true, DFS: false, Indoor: false, SDR: true}, - 161: &Channel{Frequency: 5805, AllowedInEU: true, DFS: false, Indoor: false, SDR: true}, - 165: &Channel{Frequency: 5825, AllowedInEU: true, DFS: false, Indoor: false, SDR: true}, - 169: &Channel{Frequency: 5845, AllowedInEU: true, DFS: false, Indoor: false, SDR: true}, - 173: &Channel{Frequency: 5865, AllowedInEU: true, DFS: false, Indoor: false, SDR: true}, + 1: {Frequency: 2412, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, + 2: {Frequency: 2417, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, + 3: {Frequency: 2422, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, + 4: {Frequency: 2427, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, + 5: {Frequency: 2432, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, + 6: {Frequency: 2437, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, + 7: {Frequency: 2442, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, + 8: {Frequency: 2447, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, + 9: {Frequency: 2452, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, + 10: {Frequency: 2457, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, + 11: {Frequency: 2462, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, + 12: {Frequency: 2467, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, + 13: {Frequency: 2472, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, + 14: {Frequency: 2484, AllowedInEU: false, DFS: false, Indoor: false, SDR: false}, + 32: {Frequency: 5160, AllowedInEU: true, DFS: false, Indoor: false, SDR: false}, + 34: {Frequency: 5170, AllowedInEU: false, DFS: false, Indoor: true, SDR: false}, + 36: {Frequency: 5180, AllowedInEU: true, DFS: false, Indoor: true, SDR: false}, + 38: {Frequency: 5190, AllowedInEU: false, DFS: false, Indoor: true, SDR: false}, + 40: {Frequency: 5200, AllowedInEU: true, DFS: false, Indoor: true, SDR: false}, + 42: {Frequency: 5210, AllowedInEU: false, DFS: false, Indoor: true, SDR: false}, + 44: {Frequency: 5220, AllowedInEU: true, DFS: false, Indoor: true, SDR: false}, + 46: {Frequency: 5230, AllowedInEU: false, DFS: false, Indoor: true, SDR: false}, + 48: {Frequency: 5240, AllowedInEU: true, DFS: false, Indoor: true, SDR: false}, + 50: {Frequency: 5250, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, + 52: {Frequency: 5260, AllowedInEU: true, DFS: true, Indoor: true, SDR: false}, + 54: {Frequency: 5270, AllowedInEU: false, DFS: true, Indoor: true, SDR: false}, + 56: {Frequency: 5280, AllowedInEU: true, DFS: true, Indoor: true, SDR: false}, + 58: {Frequency: 5290, AllowedInEU: false, DFS: true, Indoor: true, SDR: false}, + 60: {Frequency: 5300, AllowedInEU: true, DFS: true, Indoor: true, SDR: false}, + 62: {Frequency: 5310, AllowedInEU: false, DFS: true, Indoor: true, SDR: false}, + 64: {Frequency: 5320, AllowedInEU: true, DFS: true, Indoor: true, SDR: false}, + 68: {Frequency: 5340, AllowedInEU: true, DFS: true, Indoor: true, SDR: false}, + 96: {Frequency: 5480, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, + 100: {Frequency: 5500, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, + 102: {Frequency: 5510, AllowedInEU: false, DFS: true, Indoor: false, SDR: false}, + 104: {Frequency: 5520, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, + 106: {Frequency: 5530, AllowedInEU: false, DFS: true, Indoor: false, SDR: false}, + 108: {Frequency: 5540, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, + 110: {Frequency: 5550, AllowedInEU: false, DFS: true, Indoor: false, SDR: false}, + 112: {Frequency: 5560, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, + 114: {Frequency: 5570, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, + 116: {Frequency: 5580, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, + 118: {Frequency: 5590, AllowedInEU: false, DFS: true, Indoor: false, SDR: false}, + 120: {Frequency: 5600, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, + 122: {Frequency: 5610, AllowedInEU: false, DFS: true, Indoor: false, SDR: false}, + 124: {Frequency: 5620, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, + 126: {Frequency: 5630, AllowedInEU: false, DFS: true, Indoor: false, SDR: false}, + 128: {Frequency: 5640, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, + 132: {Frequency: 5660, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, + 134: {Frequency: 5670, AllowedInEU: false, DFS: true, Indoor: false, SDR: false}, + 136: {Frequency: 5680, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, + 138: {Frequency: 5690, AllowedInEU: false, DFS: true, Indoor: false, SDR: false}, + 140: {Frequency: 5700, AllowedInEU: true, DFS: true, Indoor: false, SDR: false}, + 142: {Frequency: 5710, AllowedInEU: false, DFS: true, Indoor: false, SDR: false}, + 144: {Frequency: 5720, AllowedInEU: true, DFS: true, Indoor: false, SDR: true}, + 149: {Frequency: 5745, AllowedInEU: true, DFS: false, Indoor: false, SDR: true}, + 151: {Frequency: 5755, AllowedInEU: true, DFS: false, Indoor: false, SDR: true}, + 153: {Frequency: 5765, AllowedInEU: true, DFS: false, Indoor: false, SDR: true}, + 155: {Frequency: 5775, AllowedInEU: true, DFS: false, Indoor: false, SDR: true}, + 157: {Frequency: 5785, AllowedInEU: true, DFS: false, Indoor: false, SDR: true}, + 159: {Frequency: 5795, AllowedInEU: true, DFS: false, Indoor: false, SDR: true}, + 161: {Frequency: 5805, AllowedInEU: true, DFS: false, Indoor: false, SDR: true}, + 165: {Frequency: 5825, AllowedInEU: true, DFS: false, Indoor: false, SDR: true}, + 169: {Frequency: 5845, AllowedInEU: true, DFS: false, Indoor: false, SDR: true}, + 173: {Frequency: 5865, AllowedInEU: true, DFS: false, Indoor: false, SDR: true}, } ) diff --git a/runtime/config.go b/runtime/config.go index 0f31de4..5f28c51 100644 --- a/runtime/config.go +++ b/runtime/config.go @@ -27,6 +27,9 @@ type Config struct { SSHIPAddressPrefix string `toml:"ssh_ipaddress_prefix"` SSHTimeout duration.Duration `toml:"ssh_timeout"` + // Pinger + Pinger PingerConfig `toml:"pinger"` + // yanic socket YanicEnable bool `toml:"yanic_enable"` YanicSynchronize duration.Duration `toml:"yanic_synchronize"` diff --git a/runtime/ping.go b/runtime/ping.go index 16dd48c..8c31d31 100644 --- a/runtime/ping.go +++ b/runtime/ping.go @@ -1,104 +1,112 @@ package runtime import ( - "net" - "time" - "sync" + "net" + "sync" + "time" - log "github.com/sirupsen/logrus" - "github.com/digineo/go-ping" - "github.com/jinzhu/gorm" + "github.com/FreifunkBremen/yanic/lib/duration" + "github.com/digineo/go-ping" + "github.com/jinzhu/gorm" + log "github.com/sirupsen/logrus" - "github.com/FreifunkBremen/freifunkmanager/data" + "github.com/FreifunkBremen/freifunkmanager/data" ) +type PingerConfig struct { + Enable bool `toml:"enable"` + Every duration.Duration `toml:"every"` + Timeout duration.Duration `toml:"timeout"` + Count int `toml:"count"` +} + type Pinger struct { db *gorm.DB - blacklistFor time.Duration + config *PingerConfig + blacklistFor time.Duration sendResult func(*data.PingResult) - - stop bool - wg sync.WaitGroup - - p *ping.Pinger - pingTimeout time.Duration - pingCount int + stop bool + wg sync.WaitGroup + p *ping.Pinger } -func NewPinger(db *gorm.DB, blacklistFor time.Duration, sendResult func(*data.PingResult)) (*Pinger, error) { - ping, err := ping.New("", "::") - if err != nil { - return nil, err - } - +func NewPinger(db *gorm.DB, config *PingerConfig, blacklistFor time.Duration, sendResult func(*data.PingResult)) (*Pinger, error) { + ping, err := ping.New("", "::") + if err != nil { + return nil, err + } + return &Pinger{ db: db, - blacklistFor: blacklistFor, + config: config, + blacklistFor: blacklistFor, sendResult: sendResult, - - stop: false, - - p: ping, - pingTimeout: time.Duration(time.Second), - pingCount: 2, + stop: false, + p: ping, }, nil } func (pinger *Pinger) Start() { - pinger.wg.Add(1) - for !pinger.stop { - pinger.run() - } - pinger.wg.Done() + pinger.wg.Add(1) + timer := time.NewTimer(pinger.config.Every.Duration) + for !pinger.stop { + select { + case <-timer.C: + pinger.run() + timer.Reset(pinger.config.Every.Duration) + } + } + timer.Stop() + pinger.wg.Done() } func (pinger *Pinger) Stop() { - pinger.stop = true - pinger.wg.Wait() + pinger.stop = true + pinger.wg.Wait() } func (pinger *Pinger) run() { - result := &data.PingResult{} - now := time.Now() + result := &data.PingResult{} + now := time.Now() - count := 0 - var nodes []*Node + count := 0 + var nodes []*Node - pinger.db.Find(&nodes).Count(&count) + pinger.db.Find(&nodes).Count(&count) - wg := sync.WaitGroup{} - wg.Add(count) + wg := sync.WaitGroup{} + wg.Add(count) - for _, node := range nodes { + for _, node := range nodes { go func(n *Node) { - defer wg.Done() - if n.Blacklist.After(now.Add(-pinger.blacklistFor)) { - return - } + defer wg.Done() + if n.Blacklist.After(now.Add(-pinger.blacklistFor)) { + return + } - addr, err := net.ResolveIPAddr("ip6", n.Address) - if err != nil { - return - } + addr, err := net.ResolveIPAddr("ip6", n.Address) + if err != nil { + return + } - _, err = pinger.p.PingAttempts(addr, pinger.pingTimeout, pinger.pingCount) + _, err = pinger.p.PingAttempts(addr, pinger.config.Timeout.Duration, pinger.config.Count) - if err == nil { - result.True = append(result.True, n.NodeID) - } else { - result.False = append(result.False, n.NodeID) - } + if err == nil { + result.True = append(result.True, n.NodeID) + } else { + result.False = append(result.False, n.NodeID) + } - }(node) - } - wg.Wait() + }(node) + } + wg.Wait() - log.WithFields(map[string]interface{}{ - "count": count, - "count_skipped": count - (len(result.True) + len(result.False)), - "count_false": len(result.False), - "count_true": len(result.True), - }).Debug("pinger complete") + log.WithFields(map[string]interface{}{ + "count": count, + "count_skipped": count - (len(result.True) + len(result.False)), + "count_false": len(result.False), + "count_true": len(result.True), + }).Debug("pinger complete") - pinger.sendResult(result) -} \ No newline at end of file + pinger.sendResult(result) +} diff --git a/websocket/send.go b/websocket/send.go index bf36245..73125fe 100644 --- a/websocket/send.go +++ b/websocket/send.go @@ -5,8 +5,8 @@ import ( yanicRuntime "github.com/FreifunkBremen/yanic/runtime" - "github.com/FreifunkBremen/freifunkmanager/runtime" "github.com/FreifunkBremen/freifunkmanager/data" + "github.com/FreifunkBremen/freifunkmanager/runtime" ) func (ws *WebsocketServer) SendNode(node *runtime.Node) {