363 lines
7.2 KiB
Go
363 lines
7.2 KiB
Go
package session
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"sync"
|
|
|
|
omd "git.loafle.net/overflow/model/discovery"
|
|
"git.loafle.net/overflow_scanner/probe/discovery/types"
|
|
)
|
|
|
|
type DiscoverySession interface {
|
|
Zone() *omd.Zone
|
|
Host() *omd.Host
|
|
Port() *omd.Port
|
|
|
|
DiscoverHost() *omd.DiscoverHost
|
|
DiscoverPort() *omd.DiscoverPort
|
|
DiscoverService() *omd.DiscoverService
|
|
|
|
InitWithRequest(request types.DiscoveryRequest) error
|
|
|
|
AddHost(host *omd.Host) *omd.Host
|
|
AddPort(port *omd.Port) *omd.Port
|
|
AddService(service *omd.Service) *omd.Service
|
|
}
|
|
|
|
type ofDiscoverySession struct {
|
|
discoveryRequest types.DiscoveryRequest
|
|
|
|
zone *omd.Zone
|
|
host *omd.Host
|
|
port *omd.Port
|
|
|
|
discoverHost *omd.DiscoverHost
|
|
discoverPort *omd.DiscoverPort
|
|
discoverService *omd.DiscoverService
|
|
|
|
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 (ds *ofDiscoverySession) init(request types.DiscoveryRequest) {
|
|
ds.discoveryRequest = request
|
|
ds.zone = nil
|
|
ds.host = nil
|
|
ds.port = nil
|
|
ds.discoverHost = nil
|
|
ds.discoverPort = nil
|
|
ds.discoverService = nil
|
|
|
|
ds.hosts = make(map[string]*omd.Host)
|
|
ds.ports = make(map[*omd.Host]map[json.Number]map[string]*omd.Port)
|
|
ds.services = make(map[*omd.Port]map[string]map[string]*omd.Service)
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) InitWithRequest(request types.DiscoveryRequest) error {
|
|
ds.init(request)
|
|
|
|
params := request.Params()
|
|
|
|
switch request.RequestType() {
|
|
case types.DiscoveryRequestTypeHost:
|
|
if nil == params || 2 != len(params) {
|
|
return fmt.Errorf("Parameter is not valid")
|
|
}
|
|
|
|
zone, ok := params[0].(*omd.Zone)
|
|
if !ok {
|
|
return fmt.Errorf("Zone of parameter is not valid")
|
|
}
|
|
|
|
discoverHost, ok := params[1].(*omd.DiscoverHost)
|
|
if !ok {
|
|
return fmt.Errorf("DiscoverHost of parameter is not valid")
|
|
}
|
|
|
|
ds.setZone(zone)
|
|
ds.setDiscoverHost(discoverHost)
|
|
case types.DiscoveryRequestTypePort:
|
|
if nil == params || 2 != len(params) {
|
|
return fmt.Errorf("Parameter is not valid")
|
|
}
|
|
|
|
host, ok := params[0].(*omd.Host)
|
|
if !ok {
|
|
return fmt.Errorf("Host of parameter is not valid")
|
|
}
|
|
|
|
discoverPort, ok := params[1].(*omd.DiscoverPort)
|
|
if !ok {
|
|
return fmt.Errorf("DiscoverPort of parameter is not valid")
|
|
}
|
|
|
|
ds.setHost(host)
|
|
ds.setDiscoverPort(discoverPort)
|
|
case types.DiscoveryRequestTypeService:
|
|
if nil == params || 2 != len(params) {
|
|
return fmt.Errorf("Parameter is not valid")
|
|
}
|
|
|
|
port, ok := params[0].(*omd.Port)
|
|
if !ok {
|
|
return fmt.Errorf("Port of parameter is not valid")
|
|
}
|
|
|
|
discoverService, ok := params[1].(*omd.DiscoverService)
|
|
if !ok {
|
|
return fmt.Errorf("DiscoverService of parameter is not valid")
|
|
}
|
|
|
|
ds.setPort(port)
|
|
ds.setDiscoverService(discoverService)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) Zone() *omd.Zone {
|
|
return ds.zone
|
|
}
|
|
func (ds *ofDiscoverySession) Host() *omd.Host {
|
|
return ds.host
|
|
}
|
|
func (ds *ofDiscoverySession) Port() *omd.Port {
|
|
return ds.port
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) DiscoverHost() *omd.DiscoverHost {
|
|
return ds.discoverHost
|
|
}
|
|
func (ds *ofDiscoverySession) DiscoverPort() *omd.DiscoverPort {
|
|
return ds.discoverPort
|
|
}
|
|
func (ds *ofDiscoverySession) DiscoverService() *omd.DiscoverService {
|
|
return ds.discoverService
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) AddHost(host *omd.Host) *omd.Host {
|
|
h := ds.findHost(host, true)
|
|
|
|
if "" == h.Mac && "" != host.Mac {
|
|
h.Mac = host.Mac
|
|
}
|
|
|
|
h.Meta = ds.appendMeta(h.Meta, host.Meta)
|
|
|
|
ds.discoveryRequest.SendMessage(types.DiscoveryMessageTypeHost, h, nil)
|
|
|
|
return h
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) AddPort(port *omd.Port) *omd.Port {
|
|
p := ds.findPort(port, true)
|
|
|
|
p.Meta = ds.appendMeta(p.Meta, port.Meta)
|
|
|
|
return p
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) AddService(service *omd.Service) *omd.Service {
|
|
s := ds.findService(service, true)
|
|
|
|
s.Meta = ds.appendMeta(s.Meta, service.Meta)
|
|
|
|
return s
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) findHost(host *omd.Host, add bool) *omd.Host {
|
|
h, ok := ds.hosts[host.Address]
|
|
if !ok {
|
|
if !add {
|
|
return nil
|
|
}
|
|
ds.hosts[host.Address] = host
|
|
h = host
|
|
}
|
|
|
|
return h
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) findPort(port *omd.Port, add bool) *omd.Port {
|
|
h := ds.findHost(port.Host, false)
|
|
if nil == h {
|
|
return nil
|
|
}
|
|
|
|
hostPorts, ok := ds.ports[h]
|
|
if !ok {
|
|
if !add {
|
|
return nil
|
|
}
|
|
|
|
ds.ports[h] = make(map[json.Number]map[string]*omd.Port)
|
|
hostPorts = ds.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 (ds *ofDiscoverySession) findService(service *omd.Service, add bool) *omd.Service {
|
|
p := ds.findPort(service.Port, false)
|
|
if nil == p {
|
|
return nil
|
|
}
|
|
|
|
portServices, ok := ds.services[p]
|
|
if !ok {
|
|
if !add {
|
|
return nil
|
|
}
|
|
|
|
ds.services[p] = make(map[string]map[string]*omd.Service)
|
|
portServices = ds.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 (ds *ofDiscoverySession) 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
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) setZone(zone *omd.Zone) {
|
|
if nil == zone {
|
|
return
|
|
}
|
|
ds.zone = zone
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) setHost(host *omd.Host) {
|
|
if nil == host {
|
|
return
|
|
}
|
|
ds.setZone(host.Zone)
|
|
ds.host = host
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) setPort(port *omd.Port) {
|
|
if nil == port {
|
|
return
|
|
}
|
|
ds.setHost(port.Host)
|
|
ds.port = port
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) setDiscoverHost(discoverHost *omd.DiscoverHost) {
|
|
if nil == discoverHost {
|
|
return
|
|
}
|
|
|
|
ds.discoverHost = discoverHost
|
|
ds.setDiscoverPort(discoverHost.DiscoverPort)
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) setDiscoverPort(discoverPort *omd.DiscoverPort) {
|
|
if nil == discoverPort {
|
|
return
|
|
}
|
|
|
|
ds.discoverPort = discoverPort
|
|
ds.setDiscoverService(discoverPort.DiscoverService)
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) setDiscoverService(discoverService *omd.DiscoverService) {
|
|
if nil == discoverService {
|
|
return
|
|
}
|
|
|
|
ds.discoverService = discoverService
|
|
}
|
|
|
|
var discoverySessionPool sync.Pool
|
|
|
|
func RetainDiscoverySession() *ofDiscoverySession {
|
|
v := discoverySessionPool.Get()
|
|
var ds *ofDiscoverySession
|
|
if v == nil {
|
|
ds = &ofDiscoverySession{}
|
|
} else {
|
|
ds = v.(*ofDiscoverySession)
|
|
}
|
|
|
|
return ds
|
|
}
|
|
|
|
func ReleaseDiscoverySession(ds *ofDiscoverySession) {
|
|
ds.discoveryRequest = nil
|
|
ds.zone = nil
|
|
ds.host = nil
|
|
ds.port = nil
|
|
ds.discoverHost = nil
|
|
ds.discoverPort = nil
|
|
ds.discoverService = nil
|
|
|
|
ds.hosts = nil
|
|
ds.ports = nil
|
|
ds.services = nil
|
|
|
|
discoverySessionPool.Put(ds)
|
|
}
|