probe/model/Discovered.go
crusader b88509516a ing
2018-08-29 00:32:03 +09:00

179 lines
3.2 KiB
Go

package model
import (
"encoding/json"
"fmt"
omd "git.loafle.net/overflow/model/discovery"
)
type Discovered interface {
Zone() *omd.Zone
AddHost(host *omd.Host) *omd.Host
AddPort(port *omd.Port) *omd.Port
AddService(service *omd.Service) *omd.Service
}
func New(zone *omd.Zone) Discovered {
return &discovered{
zone: zone,
hosts: make(map[string]*omd.Host),
ports: make(map[*omd.Host]map[json.Number]map[string]*omd.Port),
services: make(map[*omd.Port]map[string]map[string]*omd.Service),
}
}
type discovered struct {
zone *omd.Zone
hosts map[string]*omd.Host
ports map[*omd.Host]map[json.Number]map[string]*omd.Port
services map[*omd.Port]map[string]map[string]*omd.Service
}
func (d *discovered) Zone() *omd.Zone {
return d.zone
}
func (d *discovered) AddHost(host *omd.Host) *omd.Host {
h := d.findHost(host, true)
if "" == h.Mac && "" != host.Mac {
h.Mac = host.Mac
}
h.Meta = d.appendMeta(h.Meta, host.Meta)
return h
}
func (d *discovered) AddPort(port *omd.Port) *omd.Port {
p := d.findPort(port, true)
p.Meta = d.appendMeta(p.Meta, port.Meta)
return p
}
func (d *discovered) AddService(service *omd.Service) *omd.Service {
s := d.findService(service, true)
s.Meta = d.appendMeta(s.Meta, service.Meta)
return s
}
func (d *discovered) findHost(host *omd.Host, add bool) *omd.Host {
h, ok := d.hosts[host.Address]
if !ok {
if !add {
return nil
}
d.hosts[host.Address] = host
h = host
}
return h
}
func (d *discovered) findPort(port *omd.Port, add bool) *omd.Port {
h := d.findHost(port.Host, false)
if nil == h {
return nil
}
hostPorts, ok := d.ports[h]
if !ok {
if !add {
return nil
}
d.ports[h] = make(map[json.Number]map[string]*omd.Port)
hostPorts = d.ports[h]
}
ports, ok := hostPorts[port.PortNumber]
if !ok {
if !add {
return nil
}
hostPorts[port.PortNumber] = make(map[string]*omd.Port)
ports = hostPorts[port.PortNumber]
}
p, ok := ports[port.MetaPortType.Key]
if !ok {
if !add {
return nil
}
ports[port.MetaPortType.Key] = port
p = ports[port.MetaPortType.Key]
}
return p
}
func (d *discovered) findService(service *omd.Service, add bool) *omd.Service {
p := d.findPort(service.Port, false)
if nil == p {
return nil
}
portServices, ok := d.services[p]
if !ok {
if !add {
return nil
}
d.services[p] = make(map[string]map[string]*omd.Service)
portServices = d.services[p]
}
services, ok := portServices[service.Key]
if !ok {
if !add {
return nil
}
portServices[service.Key] = make(map[string]*omd.Service)
services = portServices[service.Key]
}
s, ok := services[service.MetaCryptoType.Key]
if !ok {
if !add {
return nil
}
services[service.MetaCryptoType.Key] = service
s = services[service.MetaCryptoType.Key]
}
return s
}
func (d *discovered) appendMeta(oriMeta map[string]string, newMeta map[string]string) map[string]string {
if nil == newMeta {
return oriMeta
}
if nil == oriMeta {
return newMeta
}
LOOP:
for k, v := range oriMeta {
_v, _ok := oriMeta[k]
if !_ok {
oriMeta[k] = v
continue LOOP
}
if v == _v {
continue LOOP
}
oriMeta[k] = fmt.Sprintf("%s|||%s", _v, v)
}
return oriMeta
}