2017-05-07 03:37:30 +02:00
|
|
|
package runtime
|
|
|
|
|
|
|
|
import (
|
2018-07-27 13:40:04 +02:00
|
|
|
"fmt"
|
2017-05-07 03:37:30 +02:00
|
|
|
"net"
|
2018-07-24 15:07:11 +02:00
|
|
|
"strings"
|
2018-08-10 17:17:00 +02:00
|
|
|
"time"
|
2017-05-07 03:37:30 +02:00
|
|
|
|
2018-06-30 01:45:51 +02:00
|
|
|
yanicData "github.com/FreifunkBremen/yanic/data"
|
|
|
|
"github.com/FreifunkBremen/yanic/lib/jsontime"
|
2017-05-07 03:37:30 +02:00
|
|
|
yanicRuntime "github.com/FreifunkBremen/yanic/runtime"
|
|
|
|
)
|
|
|
|
|
2018-08-11 12:34:19 +02:00
|
|
|
type WirelessSettings struct {
|
|
|
|
TxPower24 uint32 `json:"txpower24,omitempty"`
|
|
|
|
Channel24 uint32 `json:"channel24,omitempty"`
|
|
|
|
TxPower5 uint32 `json:"txpower5,omitempty"`
|
|
|
|
Channel5 uint32 `json:"channel5,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func GetWirelessSettings(node *yanicRuntime.Node) *WirelessSettings {
|
|
|
|
if stats := node.Statistics; stats != nil {
|
|
|
|
|
|
|
|
settings := &WirelessSettings{}
|
|
|
|
for _, wifi := range stats.Wireless {
|
|
|
|
ch, channel := GetChannelByFrequency(wifi.Frequency)
|
|
|
|
if channel == nil || ChannelEU && !channel.AllowedInEU {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if channel.Frequency > FREQ_THREASHOLD {
|
|
|
|
settings.Channel5 = ch
|
|
|
|
} else {
|
|
|
|
settings.Channel24 = ch
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if nodeinfo := node.Nodeinfo; nodeinfo != nil {
|
|
|
|
if wifi := nodeinfo.Wireless; wifi != nil {
|
|
|
|
/* skip to only use airtime frequency (current really used - not configurated)
|
|
|
|
if settings.Channel24 == 0 {
|
|
|
|
settings.Channel24 = wifi.Channel24
|
|
|
|
}
|
|
|
|
if settings.Channel5 == 0 {
|
|
|
|
settings.Channel5 = wifi.Channel5
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
if settings.TxPower24 == 0 {
|
|
|
|
settings.TxPower24 = wifi.TxPower24
|
|
|
|
}
|
|
|
|
if settings.TxPower5 == 0 {
|
|
|
|
settings.TxPower5 = wifi.TxPower5
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return settings
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-05-07 03:37:30 +02:00
|
|
|
type Node struct {
|
2018-08-10 19:48:34 +02:00
|
|
|
Lastseen jsontime.Time `json:"lastseen" mapstructure:"-" gorm:"-"`
|
2018-08-10 13:46:18 +02:00
|
|
|
NodeID string `json:"node_id" gorm:"primary_key" mapstructure:"node_id"`
|
2018-08-10 17:17:00 +02:00
|
|
|
Blacklist *time.Time `json:"-"`
|
2018-08-10 13:46:18 +02:00
|
|
|
Address string `json:"ip"`
|
|
|
|
|
|
|
|
Hostname string `json:"hostname"`
|
2018-08-10 17:17:00 +02:00
|
|
|
HostnameRespondd string `json:"hostname_respondd" gorm:"-"`
|
2018-08-10 13:46:18 +02:00
|
|
|
Owner string `json:"owner"`
|
2018-08-10 17:17:00 +02:00
|
|
|
OwnerRespondd string `json:"owner_respondd" gorm:"-"`
|
2018-08-10 13:46:18 +02:00
|
|
|
Location yanicData.Location `json:"location" gorm:"embedded;embedded_prefix:location_"`
|
2018-08-10 17:17:00 +02:00
|
|
|
LocationRespondd yanicData.Location `json:"location_respondd" gorm:"-"`
|
2018-08-11 12:34:19 +02:00
|
|
|
Wireless WirelessSettings `json:"wireless" gorm:"embedded;embedded_prefix:wireless_"`
|
|
|
|
WirelessRespondd WirelessSettings `json:"wireless_respondd" gorm:"-"`
|
2018-08-10 13:46:18 +02:00
|
|
|
|
|
|
|
StatisticsRespondd struct {
|
2018-06-30 01:45:51 +02:00
|
|
|
Wireless yanicData.WirelessStatistics `json:"wireless"`
|
|
|
|
Clients yanicData.Clients `json:"clients"`
|
2018-08-10 13:46:18 +02:00
|
|
|
} `json:"statistics_respondd" mapstructure:"-"`
|
2017-05-07 03:37:30 +02:00
|
|
|
}
|
|
|
|
|
2018-07-24 15:07:11 +02:00
|
|
|
func NewNode(nodeOrigin *yanicRuntime.Node, ipPrefix string) *Node {
|
2017-05-08 19:49:18 +02:00
|
|
|
if nodeinfo := nodeOrigin.Nodeinfo; nodeinfo != nil {
|
2017-05-07 03:37:30 +02:00
|
|
|
node := &Node{
|
|
|
|
Hostname: nodeinfo.Hostname,
|
|
|
|
NodeID: nodeinfo.NodeID,
|
2018-06-30 01:45:51 +02:00
|
|
|
}
|
2017-05-07 03:37:30 +02:00
|
|
|
if owner := nodeinfo.Owner; owner != nil {
|
|
|
|
node.Owner = owner.Contact
|
|
|
|
}
|
|
|
|
if location := nodeinfo.Location; location != nil {
|
|
|
|
node.Location = *location
|
|
|
|
}
|
2018-08-11 12:34:19 +02:00
|
|
|
if wireless := GetWirelessSettings(nodeOrigin); wireless != nil {
|
2017-05-07 03:37:30 +02:00
|
|
|
node.Wireless = *wireless
|
|
|
|
}
|
2018-08-10 13:46:18 +02:00
|
|
|
node.Update(nodeOrigin, ipPrefix)
|
2017-05-07 03:37:30 +02:00
|
|
|
return node
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2018-07-26 14:14:23 +02:00
|
|
|
func (n *Node) GetAddress() net.TCPAddr {
|
|
|
|
return net.TCPAddr{IP: net.ParseIP(n.Address), Port: 22}
|
2017-05-07 03:37:30 +02:00
|
|
|
}
|
2018-08-10 13:46:18 +02:00
|
|
|
func (n *Node) Update(node *yanicRuntime.Node, ipPrefix string) {
|
|
|
|
if node == nil {
|
|
|
|
return
|
|
|
|
}
|
2018-08-10 17:17:00 +02:00
|
|
|
n.Lastseen = jsontime.Now()
|
2017-05-07 03:37:30 +02:00
|
|
|
if nodeinfo := node.Nodeinfo; nodeinfo != nil {
|
2018-08-10 13:46:18 +02:00
|
|
|
n.HostnameRespondd = nodeinfo.Hostname
|
|
|
|
|
|
|
|
for _, ip := range nodeinfo.Network.Addresses {
|
|
|
|
if !strings.HasPrefix(ip, ipPrefix) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
ipAddr := net.ParseIP(ip)
|
|
|
|
if n.Address == "" || ipAddr.IsGlobalUnicast() || !ipAddr.IsLinkLocalUnicast() {
|
|
|
|
n.Address = ip
|
|
|
|
}
|
|
|
|
}
|
2017-05-07 03:37:30 +02:00
|
|
|
|
|
|
|
if owner := nodeinfo.Owner; owner != nil {
|
2018-08-10 13:46:18 +02:00
|
|
|
n.OwnerRespondd = owner.Contact
|
2017-05-07 03:37:30 +02:00
|
|
|
}
|
|
|
|
if location := nodeinfo.Location; location != nil {
|
2018-08-10 13:46:18 +02:00
|
|
|
n.LocationRespondd = *location
|
2017-05-07 03:37:30 +02:00
|
|
|
}
|
2018-08-11 12:34:19 +02:00
|
|
|
if wireless := GetWirelessSettings(node); wireless != nil {
|
2018-08-10 13:46:18 +02:00
|
|
|
n.WirelessRespondd = *wireless
|
2017-05-07 03:37:30 +02:00
|
|
|
}
|
|
|
|
}
|
2018-08-10 13:46:18 +02:00
|
|
|
if stats := node.Statistics; stats != nil {
|
|
|
|
n.StatisticsRespondd.Clients = stats.Clients
|
|
|
|
n.StatisticsRespondd.Wireless = stats.Wireless
|
2017-05-07 03:37:30 +02:00
|
|
|
}
|
2018-08-10 13:46:18 +02:00
|
|
|
}
|
|
|
|
func (n *Node) CheckRespondd() bool {
|
|
|
|
if n.Hostname != n.HostnameRespondd {
|
2017-05-07 03:37:30 +02:00
|
|
|
return false
|
|
|
|
}
|
2018-08-10 13:46:18 +02:00
|
|
|
if n.Owner != n.OwnerRespondd {
|
2017-05-07 03:37:30 +02:00
|
|
|
return false
|
|
|
|
}
|
2018-08-10 13:46:18 +02:00
|
|
|
if !locationEqual(n.Location, n.LocationRespondd) {
|
2017-05-07 03:37:30 +02:00
|
|
|
return false
|
|
|
|
}
|
2018-08-10 13:46:18 +02:00
|
|
|
if !wirelessEqual(n.Wireless, n.WirelessRespondd) {
|
2017-05-07 03:37:30 +02:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2018-07-27 13:40:04 +02:00
|
|
|
const LOCATION_EQUAL_FORMAT_STRING = "%.6f"
|
|
|
|
|
2018-06-30 01:45:51 +02:00
|
|
|
func locationEqual(a, b yanicData.Location) bool {
|
2018-07-27 13:40:04 +02:00
|
|
|
if fmt.Sprintf(LOCATION_EQUAL_FORMAT_STRING, a.Latitude) != fmt.Sprintf(LOCATION_EQUAL_FORMAT_STRING, b.Latitude) {
|
2017-05-07 03:37:30 +02:00
|
|
|
return false
|
|
|
|
}
|
2018-07-27 13:40:04 +02:00
|
|
|
if fmt.Sprintf(LOCATION_EQUAL_FORMAT_STRING, a.Longitude) != fmt.Sprintf(LOCATION_EQUAL_FORMAT_STRING, b.Longitude) {
|
2017-05-07 03:37:30 +02:00
|
|
|
return false
|
|
|
|
}
|
2018-07-27 13:40:04 +02:00
|
|
|
|
2017-05-07 03:37:30 +02:00
|
|
|
if a.Altitude != b.Altitude {
|
|
|
|
return false
|
|
|
|
}
|
2018-07-27 13:40:04 +02:00
|
|
|
|
2017-05-07 03:37:30 +02:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2018-08-11 12:34:19 +02:00
|
|
|
func wirelessEqual(a, b WirelessSettings) bool {
|
2017-05-07 03:37:30 +02:00
|
|
|
if a.Channel24 != b.Channel24 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if a.Channel5 != b.Channel5 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if a.TxPower24 != b.TxPower24 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if a.TxPower5 != b.TxPower5 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|