ing
This commit is contained in:
parent
12395bf397
commit
ffd94e2c8e
223
discovery/discoverer.go
Normal file
223
discovery/discoverer.go
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
package discovery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
omd "git.loafle.net/overflow/model/discovery"
|
||||||
|
omu "git.loafle.net/overflow/model/util"
|
||||||
|
"git.loafle.net/overflow_scanner/probe/discovery/session"
|
||||||
|
"git.loafle.net/overflow_scanner/probe/discovery/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Discoverer interface {
|
||||||
|
DiscoverHost(requesterID string, zone *omd.Zone, dh *omd.DiscoverHost)
|
||||||
|
DiscoverPort(requesterID string, host *omd.Host, dp *omd.DiscoverPort)
|
||||||
|
DiscoverService(requesterID string, port *omd.Port, ds *omd.DiscoverService)
|
||||||
|
Message() <-chan types.DiscoveryMessage
|
||||||
|
|
||||||
|
Shutdown()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Instance() Discoverer {
|
||||||
|
_once.Do(func() {
|
||||||
|
_instance = newDiscoverer()
|
||||||
|
})
|
||||||
|
return _instance
|
||||||
|
}
|
||||||
|
|
||||||
|
var _instance Discoverer
|
||||||
|
var _once sync.Once
|
||||||
|
|
||||||
|
func newDiscoverer() Discoverer {
|
||||||
|
i := &ofDiscoverer{}
|
||||||
|
i.start()
|
||||||
|
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
type ofDiscoverer struct {
|
||||||
|
stopChan chan struct{}
|
||||||
|
stopWg sync.WaitGroup
|
||||||
|
|
||||||
|
requestQueue chan types.DiscoveryRequest
|
||||||
|
messageChan chan types.DiscoveryMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *ofDiscoverer) DiscoverHost(requesterID string, zone *omd.Zone, dh *omd.DiscoverHost) {
|
||||||
|
d.enqueue(retainDiscoveryRequest(d.messageChan, requesterID, types.DiscoveryRequestTypeHost, zone, dh))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *ofDiscoverer) DiscoverPort(requesterID string, host *omd.Host, dp *omd.DiscoverPort) {
|
||||||
|
d.enqueue(retainDiscoveryRequest(d.messageChan, requesterID, types.DiscoveryRequestTypePort, host, dp))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *ofDiscoverer) DiscoverService(requesterID string, port *omd.Port, ds *omd.DiscoverService) {
|
||||||
|
d.enqueue(retainDiscoveryRequest(d.messageChan, requesterID, types.DiscoveryRequestTypeService, port, ds))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *ofDiscoverer) Message() <-chan types.DiscoveryMessage {
|
||||||
|
return d.messageChan
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *ofDiscoverer) Shutdown() {
|
||||||
|
if d.stopChan == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
close(d.requestQueue)
|
||||||
|
close(d.messageChan)
|
||||||
|
|
||||||
|
close(d.stopChan)
|
||||||
|
d.stopWg.Wait()
|
||||||
|
|
||||||
|
d.stopChan = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *ofDiscoverer) start() {
|
||||||
|
d.stopChan = make(chan struct{})
|
||||||
|
|
||||||
|
d.requestQueue = make(chan types.DiscoveryRequest, 10)
|
||||||
|
d.messageChan = make(chan types.DiscoveryMessage, 256)
|
||||||
|
|
||||||
|
d.stopWg.Add(1)
|
||||||
|
go d.handleRequest()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *ofDiscoverer) enqueue(req *ofDiscoveryRequest) {
|
||||||
|
select {
|
||||||
|
case d.requestQueue <- req:
|
||||||
|
req.SendMessage(types.DiscoveryMessageTypeQueueing, omu.Now(), nil)
|
||||||
|
go func() {
|
||||||
|
select {
|
||||||
|
case <-req.dequeue:
|
||||||
|
case <-time.After(10 * time.Second):
|
||||||
|
req.timeout = true
|
||||||
|
req.SendMessage(types.DiscoveryMessageTypeTimeout, omu.Now(), nil)
|
||||||
|
req.release()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
default:
|
||||||
|
req.SendMessage(types.DiscoveryMessageTypeFailedQueueing, omu.Now(), nil)
|
||||||
|
req.release()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *ofDiscoverer) handleRequest() {
|
||||||
|
defer func() {
|
||||||
|
d.stopWg.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
|
LOOP:
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case req, ok := <-d.requestQueue:
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if req.(*ofDiscoveryRequest).timeout {
|
||||||
|
continue LOOP
|
||||||
|
}
|
||||||
|
req.(*ofDiscoveryRequest).dequeue <- true
|
||||||
|
|
||||||
|
req.SendMessage(types.DiscoveryMessageTypeStart, omu.Now(), nil)
|
||||||
|
d.discover(req)
|
||||||
|
req.SendMessage(types.DiscoveryMessageTypeStop, omu.Now(), nil)
|
||||||
|
|
||||||
|
req.(*ofDiscoveryRequest).release()
|
||||||
|
case <-d.stopChan:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *ofDiscoverer) discover(req types.DiscoveryRequest) {
|
||||||
|
if types.DiscoveryRequestTypeNone == req.RequestType() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
s := session.RetainDiscoverySession()
|
||||||
|
defer func() {
|
||||||
|
session.ReleaseDiscoverySession(s)
|
||||||
|
}()
|
||||||
|
|
||||||
|
params := req.Params()
|
||||||
|
|
||||||
|
switch req.RequestType() {
|
||||||
|
case types.DiscoveryRequestTypeHost:
|
||||||
|
if nil == params || 2 != len(params) {
|
||||||
|
req.SendMessage(types.DiscoveryMessageTypeError, nil, fmt.Errorf("Parameter is not valid"))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
zone, ok := params[0].(*omd.Zone)
|
||||||
|
if !ok {
|
||||||
|
req.SendMessage(types.DiscoveryMessageTypeError, nil, fmt.Errorf("Zone of parameter is not valid"))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
dh, ok := params[1].(*omd.DiscoverHost)
|
||||||
|
if !ok {
|
||||||
|
req.SendMessage(types.DiscoveryMessageTypeError, nil, fmt.Errorf("DiscoverHost of parameter is not valid"))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
s.InitWithDiscoverHost(req, zone, dh)
|
||||||
|
case types.DiscoveryRequestTypePort:
|
||||||
|
if nil == params || 2 != len(params) {
|
||||||
|
req.SendMessage(types.DiscoveryMessageTypeError, nil, fmt.Errorf("Parameter is not valid"))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
host, ok := params[0].(*omd.Host)
|
||||||
|
if !ok {
|
||||||
|
req.SendMessage(types.DiscoveryMessageTypeError, nil, fmt.Errorf("Host of parameter is not valid"))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
dp, ok := params[1].(*omd.DiscoverPort)
|
||||||
|
if !ok {
|
||||||
|
req.SendMessage(types.DiscoveryMessageTypeError, nil, fmt.Errorf("DiscoverPort of parameter is not valid"))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
s.InitWithDiscoverPort(req, host, dp)
|
||||||
|
case types.DiscoveryRequestTypeService:
|
||||||
|
if nil == params || 2 != len(params) {
|
||||||
|
req.SendMessage(types.DiscoveryMessageTypeError, nil, fmt.Errorf("Parameter is not valid"))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
port, ok := params[0].(*omd.Port)
|
||||||
|
if !ok {
|
||||||
|
req.SendMessage(types.DiscoveryMessageTypeError, nil, fmt.Errorf("Port of parameter is not valid"))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
ds, ok := params[1].(*omd.DiscoverService)
|
||||||
|
if !ok {
|
||||||
|
req.SendMessage(types.DiscoveryMessageTypeError, nil, fmt.Errorf("DiscoverService of parameter is not valid"))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
s.InitWithDiscoverService(req, port, ds)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.preDiscovery(s)
|
||||||
|
|
||||||
|
d.layerDiscovery(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *ofDiscoverer) preDiscovery(s session.DiscoverySession) {
|
||||||
|
|
||||||
|
// SNMP
|
||||||
|
// mDNS
|
||||||
|
// UPnP
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *ofDiscoverer) layerDiscovery(s session.DiscoverySession) {
|
||||||
|
// SNMP
|
||||||
|
// mDNS
|
||||||
|
// UPnP
|
||||||
|
}
|
70
discovery/discovery-message.go
Normal file
70
discovery/discovery-message.go
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
package discovery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"git.loafle.net/overflow_scanner/probe/discovery/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ofDiscoveryMessage struct {
|
||||||
|
request types.DiscoveryRequest
|
||||||
|
messageType types.DiscoveryMessageType
|
||||||
|
data interface{}
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dm *ofDiscoveryMessage) Request() types.DiscoveryRequest {
|
||||||
|
return dm.request
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dm *ofDiscoveryMessage) Type() types.DiscoveryMessageType {
|
||||||
|
return dm.messageType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dm *ofDiscoveryMessage) Result() interface{} {
|
||||||
|
return dm.data
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dm *ofDiscoveryMessage) Error() error {
|
||||||
|
return dm.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dm *ofDiscoveryMessage) Release() {
|
||||||
|
releaseDiscoveryMessage(dm)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RetainDiscoveryMessage(request types.DiscoveryRequest, messageType types.DiscoveryMessageType, data interface{}, err error) *ofDiscoveryMessage {
|
||||||
|
return retainDiscoveryMessage(request, messageType, data, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReleaseDiscoveryMessage(dm *ofDiscoveryMessage) {
|
||||||
|
releaseDiscoveryMessage(dm)
|
||||||
|
}
|
||||||
|
|
||||||
|
var discoveryMessagePool sync.Pool
|
||||||
|
|
||||||
|
func retainDiscoveryMessage(request types.DiscoveryRequest, messageType types.DiscoveryMessageType, data interface{}, err error) *ofDiscoveryMessage {
|
||||||
|
v := discoveryMessagePool.Get()
|
||||||
|
var dm *ofDiscoveryMessage
|
||||||
|
if v == nil {
|
||||||
|
dm = &ofDiscoveryMessage{}
|
||||||
|
} else {
|
||||||
|
dm = v.(*ofDiscoveryMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
dm.request = request
|
||||||
|
dm.messageType = messageType
|
||||||
|
dm.data = data
|
||||||
|
dm.err = err
|
||||||
|
|
||||||
|
return dm
|
||||||
|
}
|
||||||
|
|
||||||
|
func releaseDiscoveryMessage(dm *ofDiscoveryMessage) {
|
||||||
|
dm.request = nil
|
||||||
|
dm.messageType = types.DiscoveryMessageTypeNone
|
||||||
|
dm.data = nil
|
||||||
|
dm.err = nil
|
||||||
|
|
||||||
|
discoveryMessagePool.Put(dm)
|
||||||
|
}
|
70
discovery/discovery-request.go
Normal file
70
discovery/discovery-request.go
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
package discovery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"git.loafle.net/overflow_scanner/probe/discovery/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ofDiscoveryRequest struct {
|
||||||
|
requesterID string
|
||||||
|
requestType types.DiscoveryRequestType
|
||||||
|
params []interface{}
|
||||||
|
|
||||||
|
messageChan chan<- types.DiscoveryMessage
|
||||||
|
dequeue chan bool
|
||||||
|
timeout bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dr *ofDiscoveryRequest) RequesterID() string {
|
||||||
|
return dr.requesterID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dr *ofDiscoveryRequest) RequestType() types.DiscoveryRequestType {
|
||||||
|
return dr.requestType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dr *ofDiscoveryRequest) Params() []interface{} {
|
||||||
|
return dr.params
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dr *ofDiscoveryRequest) SendMessage(messageType types.DiscoveryMessageType, data interface{}, err error) {
|
||||||
|
dr.messageChan <- retainDiscoveryMessage(dr, messageType, data, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dr *ofDiscoveryRequest) release() {
|
||||||
|
releaseDiscoveryRequest(dr)
|
||||||
|
}
|
||||||
|
|
||||||
|
var discoveryRequestPool sync.Pool
|
||||||
|
|
||||||
|
func retainDiscoveryRequest(messageChan chan<- types.DiscoveryMessage, requesterID string, requestType types.DiscoveryRequestType, params ...interface{}) *ofDiscoveryRequest {
|
||||||
|
v := discoveryRequestPool.Get()
|
||||||
|
var dr *ofDiscoveryRequest
|
||||||
|
if v == nil {
|
||||||
|
dr = &ofDiscoveryRequest{}
|
||||||
|
} else {
|
||||||
|
dr = v.(*ofDiscoveryRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
dr.requesterID = requesterID
|
||||||
|
dr.requestType = requestType
|
||||||
|
dr.params = params
|
||||||
|
dr.messageChan = messageChan
|
||||||
|
dr.dequeue = make(chan bool, 1)
|
||||||
|
dr.timeout = false
|
||||||
|
|
||||||
|
return dr
|
||||||
|
}
|
||||||
|
|
||||||
|
func releaseDiscoveryRequest(dr *ofDiscoveryRequest) {
|
||||||
|
dr.requesterID = ""
|
||||||
|
dr.requestType = types.DiscoveryRequestTypeNone
|
||||||
|
dr.params = nil
|
||||||
|
dr.messageChan = nil
|
||||||
|
close(dr.dequeue)
|
||||||
|
dr.dequeue = nil
|
||||||
|
dr.timeout = false
|
||||||
|
|
||||||
|
discoveryRequestPool.Put(dr)
|
||||||
|
}
|
215
discovery/protocol/mdns/mdns.go
Normal file
215
discovery/protocol/mdns/mdns.go
Normal file
|
@ -0,0 +1,215 @@
|
||||||
|
package mdns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
omd "git.loafle.net/overflow/model/discovery"
|
||||||
|
omm "git.loafle.net/overflow/model/meta"
|
||||||
|
omu "git.loafle.net/overflow/model/util"
|
||||||
|
"git.loafle.net/overflow_scanner/probe/discovery/session"
|
||||||
|
"github.com/grandcat/zeroconf"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Scan(discoverySession session.DiscoverySession) {
|
||||||
|
serviceEntries, err := browse("_services._dns-sd._udp", "local")
|
||||||
|
if nil != err {
|
||||||
|
log.Print("Cannot find service ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
metaIPTypeEnum := omm.ToMetaIPTypeEnum(discoverySession.Zone().MetaIPType)
|
||||||
|
|
||||||
|
for _, serviceEntry := range serviceEntries {
|
||||||
|
name := removeDomainName(serviceEntry.Instance, serviceEntry.Domain)
|
||||||
|
entries, _err := browse(name, serviceEntry.Domain)
|
||||||
|
if nil != _err {
|
||||||
|
log.Print("Cannot find entry ", _err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
LOOP:
|
||||||
|
for _, entry := range entries {
|
||||||
|
log.Print("serviceEntry ", entry)
|
||||||
|
|
||||||
|
name := entry.Instance // HP\ LaserJet\ P1505n
|
||||||
|
service := entry.Service // _pdl-datastream._tcp
|
||||||
|
port := entry.Port // 9100
|
||||||
|
meta := toMeta(entry.Text)
|
||||||
|
hostName := removeDomainName(entry.HostName, entry.Domain) // NPIFACA9B
|
||||||
|
serviceName, portType, cryptoType := parseService(service)
|
||||||
|
|
||||||
|
var metaPortType *omm.MetaPortType
|
||||||
|
switch portType {
|
||||||
|
case "tcp":
|
||||||
|
metaPortType = omm.ToMetaPortType(omm.MetaPortTypeEnumTCP)
|
||||||
|
case "udp":
|
||||||
|
metaPortType = omm.ToMetaPortType(omm.MetaPortTypeEnumUDP)
|
||||||
|
}
|
||||||
|
|
||||||
|
metaCryptoType := omm.ToMetaCryptoType(omm.MetaCryptoTypeEnumUNKNOWN)
|
||||||
|
switch cryptoType {
|
||||||
|
case "NONE":
|
||||||
|
metaCryptoType = omm.ToMetaCryptoType(omm.MetaCryptoTypeEnumNONE)
|
||||||
|
case "TLS":
|
||||||
|
metaCryptoType = omm.ToMetaCryptoType(omm.MetaCryptoTypeEnumTLS)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch metaIPTypeEnum {
|
||||||
|
case omm.MetaIPTypeEnumV4:
|
||||||
|
for _, ipv4 := range entry.AddrIPv4 {
|
||||||
|
h := discoverySession.AddHost(&omd.Host{
|
||||||
|
MetaIPType: omm.ToMetaIPType(metaIPTypeEnum),
|
||||||
|
Name: hostName,
|
||||||
|
Address: ipv4.String(),
|
||||||
|
Meta: meta,
|
||||||
|
Zone: discoverySession.Zone(),
|
||||||
|
DiscoveredDate: omu.NowPtr(),
|
||||||
|
})
|
||||||
|
|
||||||
|
if 1 > port {
|
||||||
|
continue LOOP
|
||||||
|
}
|
||||||
|
|
||||||
|
p := discoverySession.AddPort(&omd.Port{
|
||||||
|
MetaPortType: metaPortType,
|
||||||
|
PortNumber: json.Number(strconv.Itoa(port)),
|
||||||
|
Meta: meta,
|
||||||
|
Host: h,
|
||||||
|
})
|
||||||
|
|
||||||
|
discoverySession.AddService(&omd.Service{
|
||||||
|
MetaCryptoType: metaCryptoType,
|
||||||
|
Key: serviceName,
|
||||||
|
Name: name,
|
||||||
|
Port: p,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
case omm.MetaIPTypeEnumV6:
|
||||||
|
for _, ipv6 := range entry.AddrIPv6 {
|
||||||
|
h := discoverySession.AddHost(&omd.Host{
|
||||||
|
MetaIPType: omm.ToMetaIPType(metaIPTypeEnum),
|
||||||
|
Name: hostName,
|
||||||
|
Address: ipv6.String(),
|
||||||
|
Meta: meta,
|
||||||
|
Zone: discoverySession.Zone(),
|
||||||
|
DiscoveredDate: omu.NowPtr(),
|
||||||
|
})
|
||||||
|
|
||||||
|
if 1 > port {
|
||||||
|
continue LOOP
|
||||||
|
}
|
||||||
|
|
||||||
|
p := discoverySession.AddPort(&omd.Port{
|
||||||
|
MetaPortType: metaPortType,
|
||||||
|
PortNumber: json.Number(strconv.Itoa(port)),
|
||||||
|
Meta: meta,
|
||||||
|
Host: h,
|
||||||
|
})
|
||||||
|
|
||||||
|
discoverySession.AddService(&omd.Service{
|
||||||
|
MetaCryptoType: metaCryptoType,
|
||||||
|
Key: serviceName,
|
||||||
|
Name: name,
|
||||||
|
Port: p,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeDomainName(instance string, domain string) (service string) {
|
||||||
|
_instance := strings.TrimRight(instance, ".")
|
||||||
|
return strings.TrimRight(_instance, fmt.Sprintf(".%s", domain))
|
||||||
|
}
|
||||||
|
|
||||||
|
func toMeta(text []string) map[string]string {
|
||||||
|
if nil == text || 0 == len(text) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
meta := make(map[string]string)
|
||||||
|
for _, v := range text {
|
||||||
|
ss := strings.SplitN(v, "=", 2)
|
||||||
|
if 2 != len(ss) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if nil != ss {
|
||||||
|
meta[ss[0]] = ss[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return meta
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseService(service string) (name string, portType string, cryptoType string) {
|
||||||
|
ss := strings.SplitN(service, ".", 2)
|
||||||
|
if nil == ss {
|
||||||
|
return "UNKNOWN", "UNKNOWN", "UNKNOWN"
|
||||||
|
}
|
||||||
|
|
||||||
|
_name := strings.TrimLeft(ss[0], "_")
|
||||||
|
_portType := strings.TrimLeft(ss[1], "_")
|
||||||
|
|
||||||
|
name = _name
|
||||||
|
portType = _portType
|
||||||
|
cryptoType = "NONE"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func browse(service string, domain string) ([]*zeroconf.ServiceEntry, error) {
|
||||||
|
resolver, err := zeroconf.NewResolver(nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to initialize resolver %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
entryChan := make(chan *zeroconf.ServiceEntry)
|
||||||
|
timerStopped := make(chan struct{})
|
||||||
|
|
||||||
|
serviceEntries := make([]*zeroconf.ServiceEntry, 0)
|
||||||
|
|
||||||
|
go func(_entryChan <-chan *zeroconf.ServiceEntry) {
|
||||||
|
var delay atomic.Value
|
||||||
|
delay.Store(false)
|
||||||
|
ticker := time.NewTicker(time.Second * 1)
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case entry, ok := <-_entryChan:
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
delay.Store(true)
|
||||||
|
serviceEntries = append(serviceEntries, entry)
|
||||||
|
case <-ticker.C:
|
||||||
|
if false == delay.Load().(bool) {
|
||||||
|
ticker.Stop()
|
||||||
|
timerStopped <- struct{}{}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
delay.Store(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}(entryChan)
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(30))
|
||||||
|
defer cancel()
|
||||||
|
err = resolver.Browse(ctx, service, domain, entryChan)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to browse %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
case <-timerStopped:
|
||||||
|
}
|
||||||
|
|
||||||
|
return serviceEntries, nil
|
||||||
|
}
|
139
discovery/protocol/mdns/mdns_test.go
Normal file
139
discovery/protocol/mdns/mdns_test.go
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
package mdns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
omd "git.loafle.net/overflow/model/discovery"
|
||||||
|
omm "git.loafle.net/overflow/model/meta"
|
||||||
|
"git.loafle.net/overflow_scanner/probe/model"
|
||||||
|
"github.com/grandcat/zeroconf"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestScan(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
discovered model.Discovered
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
}{
|
||||||
|
// TODO: Add test cases.
|
||||||
|
{
|
||||||
|
name: "1",
|
||||||
|
args: args{
|
||||||
|
discovered: model.New(
|
||||||
|
&omd.Zone{
|
||||||
|
Network: "192.168.1.0/24",
|
||||||
|
Iface: "enp3s0",
|
||||||
|
MetaIPType: omm.ToMetaIPType(omm.MetaIPTypeEnumV4),
|
||||||
|
Address: "192.168.1.101",
|
||||||
|
Mac: "44:8a:5b:f1:f1:f3",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
Scan(tt.args.discovered)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_removeDomainName(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
instance string
|
||||||
|
domain string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
wantService string
|
||||||
|
}{
|
||||||
|
// TODO: Add test cases.
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if gotService := removeDomainName(tt.args.instance, tt.args.domain); gotService != tt.wantService {
|
||||||
|
t.Errorf("removeDomainName() = %v, want %v", gotService, tt.wantService)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_toMeta(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
text []string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want map[string]string
|
||||||
|
}{
|
||||||
|
// TODO: Add test cases.
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := toMeta(tt.args.text); !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("toMeta() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_parseService(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
service string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
wantName string
|
||||||
|
wantPortType string
|
||||||
|
wantCryptoType string
|
||||||
|
}{
|
||||||
|
// TODO: Add test cases.
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
gotName, gotPortType, gotCryptoType := parseService(tt.args.service)
|
||||||
|
if gotName != tt.wantName {
|
||||||
|
t.Errorf("parseService() gotName = %v, want %v", gotName, tt.wantName)
|
||||||
|
}
|
||||||
|
if gotPortType != tt.wantPortType {
|
||||||
|
t.Errorf("parseService() gotPortType = %v, want %v", gotPortType, tt.wantPortType)
|
||||||
|
}
|
||||||
|
if gotCryptoType != tt.wantCryptoType {
|
||||||
|
t.Errorf("parseService() gotCryptoType = %v, want %v", gotCryptoType, tt.wantCryptoType)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_browse(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
service string
|
||||||
|
domain string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want []*zeroconf.ServiceEntry
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
// TODO: Add test cases.
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := browse(tt.args.service, tt.args.domain)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("browse() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("browse() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
69
discovery/protocol/snmp/snmp.go
Normal file
69
discovery/protocol/snmp/snmp.go
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
package snmp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
omd "git.loafle.net/overflow/model/discovery"
|
||||||
|
"github.com/k-sone/snmpgo"
|
||||||
|
)
|
||||||
|
|
||||||
|
var defaultPort = 161
|
||||||
|
var defaultOIDs = []string{
|
||||||
|
"1.3.6.1.2.1.1.5.0", //sysName
|
||||||
|
}
|
||||||
|
|
||||||
|
type SNMPResponse struct {
|
||||||
|
Host *omd.Host
|
||||||
|
Value map[string]string
|
||||||
|
Error error
|
||||||
|
}
|
||||||
|
|
||||||
|
func ScanSNMP(host *omd.Host, community string, ch chan *SNMPResponse) {
|
||||||
|
go func() {
|
||||||
|
getV2(host, defaultPort, community, defaultOIDs, ch)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func getV2(host *omd.Host, port int, community string, _oids []string, ch chan *SNMPResponse) {
|
||||||
|
address := fmt.Sprintf("%s:%d", host.Address, port)
|
||||||
|
snmp, err := snmpgo.NewSNMP(snmpgo.SNMPArguments{
|
||||||
|
Version: snmpgo.V2c,
|
||||||
|
Address: address,
|
||||||
|
Retries: 1,
|
||||||
|
Community: community,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ch <- &SNMPResponse{host, nil, err}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer snmp.Close()
|
||||||
|
|
||||||
|
oids, err := snmpgo.NewOids(_oids)
|
||||||
|
if err != nil {
|
||||||
|
ch <- &SNMPResponse{host, nil, err}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pdu, err := snmp.GetRequest(oids)
|
||||||
|
if err != nil {
|
||||||
|
ch <- &SNMPResponse{host, nil, err}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if pdu.ErrorStatus() != snmpgo.NoError {
|
||||||
|
ch <- &SNMPResponse{host, nil, fmt.Errorf("%s", pdu.ErrorStatus().String())}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if pdu == nil {
|
||||||
|
ch <- &SNMPResponse{host, nil, fmt.Errorf("%s", "Empty PDU")}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resMap := make(map[string]string)
|
||||||
|
for _, val := range pdu.VarBinds() {
|
||||||
|
resMap[val.Oid.String()] = val.Variable.String()
|
||||||
|
}
|
||||||
|
ch <- &SNMPResponse{host, resMap, nil}
|
||||||
|
return
|
||||||
|
}
|
23
discovery/protocol/snmp/snmp_test.go
Normal file
23
discovery/protocol/snmp/snmp_test.go
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
package snmp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
omd "git.loafle.net/overflow/model/discovery"
|
||||||
|
omm "git.loafle.net/overflow/model/meta"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSNMPScan(t *testing.T) {
|
||||||
|
host := &omd.Host{
|
||||||
|
MetaIPType: omm.ToMetaIPType(omm.MetaIPTypeEnumV4),
|
||||||
|
Address: "192.168.1.229",
|
||||||
|
}
|
||||||
|
|
||||||
|
ch := make(chan *SNMPResponse)
|
||||||
|
defer close(ch)
|
||||||
|
ScanSNMP(host, "test1252serc", ch)
|
||||||
|
|
||||||
|
msg := <-ch
|
||||||
|
t.Log(msg)
|
||||||
|
|
||||||
|
}
|
49
discovery/protocol/upnp/upnp.go
Normal file
49
discovery/protocol/upnp/upnp.go
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
package upnp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
omd "git.loafle.net/overflow/model/discovery"
|
||||||
|
omu "git.loafle.net/overflow/model/util"
|
||||||
|
"git.loafle.net/overflow_scanner/probe/discovery/session"
|
||||||
|
"github.com/huin/goupnp"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
TargetRootDevice = "upnp:rootdevice"
|
||||||
|
TargetSSDPAll = "ssdp:all"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Scan(discoverySession session.DiscoverySession) {
|
||||||
|
devs, err := goupnp.DiscoverDevices(TargetRootDevice)
|
||||||
|
if nil != err {
|
||||||
|
fmt.Println("DeletePortMapping: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
LOOP:
|
||||||
|
for _, dev := range devs {
|
||||||
|
rd := dev.Root.Device
|
||||||
|
if !rd.PresentationURL.Ok {
|
||||||
|
continue LOOP
|
||||||
|
}
|
||||||
|
|
||||||
|
discoverySession.AddHost(&omd.Host{
|
||||||
|
MetaIPType: discoverySession.Zone().MetaIPType,
|
||||||
|
Name: rd.FriendlyName,
|
||||||
|
Address: rd.PresentationURL.URL.Host,
|
||||||
|
Meta: map[string]string{
|
||||||
|
"DeviceType": rd.DeviceType,
|
||||||
|
"Manufacturer": rd.Manufacturer,
|
||||||
|
"ManufacturerURL": rd.ManufacturerURL.Str,
|
||||||
|
"ModelName": rd.ModelName,
|
||||||
|
"ModelDescription": rd.ModelDescription,
|
||||||
|
"ModelNumber": rd.ModelNumber,
|
||||||
|
"SerialNumber": rd.SerialNumber,
|
||||||
|
"UDN": rd.UDN,
|
||||||
|
"UPC": rd.UPC,
|
||||||
|
},
|
||||||
|
Zone: discoverySession.Zone(),
|
||||||
|
DiscoveredDate: omu.NowPtr(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
48
discovery/protocol/upnp/upnp_test.go
Normal file
48
discovery/protocol/upnp/upnp_test.go
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
package upnp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
omd "git.loafle.net/overflow/model/discovery"
|
||||||
|
omm "git.loafle.net/overflow/model/meta"
|
||||||
|
"git.loafle.net/overflow_scanner/probe/discovery/session"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestScan(t *testing.T) {
|
||||||
|
s := session.MockDiscoverySession()
|
||||||
|
s.InitWithDiscoverHost(
|
||||||
|
nil,
|
||||||
|
&omd.Zone{
|
||||||
|
Network: "192.168.1.0/24",
|
||||||
|
Iface: "enp3s0",
|
||||||
|
MetaIPType: omm.ToMetaIPType(omm.MetaIPTypeEnumV4),
|
||||||
|
Address: "192.168.1.101",
|
||||||
|
Mac: "44:8a:5b:f1:f1:f3",
|
||||||
|
},
|
||||||
|
&omd.DiscoverHost{
|
||||||
|
MetaIPType: omm.ToMetaIPType(omm.MetaIPTypeEnumV4),
|
||||||
|
FirstScanRange: "192.168.1.1",
|
||||||
|
LastScanRange: "192.168.1.254",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
type args struct {
|
||||||
|
discoverySession session.DiscoverySession
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "1",
|
||||||
|
args: args{
|
||||||
|
discoverySession: s,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
Scan(tt.args.discoverySession)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
328
discovery/session/discovery-session.go
Normal file
328
discovery/session/discovery-session.go
Normal file
|
@ -0,0 +1,328 @@
|
||||||
|
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
|
||||||
|
|
||||||
|
InitWithDiscoverHost(request types.DiscoveryRequest, zone *omd.Zone, discoverHost *omd.DiscoverHost)
|
||||||
|
InitWithDiscoverPort(request types.DiscoveryRequest, host *omd.Host, discoverPort *omd.DiscoverPort)
|
||||||
|
InitWithDiscoverService(request types.DiscoveryRequest, port *omd.Port, discoverService *omd.DiscoverService)
|
||||||
|
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() {
|
||||||
|
ds.discoveryRequest = nil
|
||||||
|
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) {
|
||||||
|
ds.init()
|
||||||
|
|
||||||
|
ds.discoveryRequest = request
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *ofDiscoverySession) InitWithDiscoverHost(request types.DiscoveryRequest, zone *omd.Zone, discoverHost *omd.DiscoverHost) {
|
||||||
|
ds.initWithRequest(request)
|
||||||
|
|
||||||
|
ds.setZone(zone)
|
||||||
|
ds.setDiscoverHost(discoverHost)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *ofDiscoverySession) InitWithDiscoverPort(request types.DiscoveryRequest, host *omd.Host, discoverPort *omd.DiscoverPort) {
|
||||||
|
ds.initWithRequest(request)
|
||||||
|
|
||||||
|
ds.setHost(host)
|
||||||
|
ds.setDiscoverPort(discoverPort)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *ofDiscoverySession) InitWithDiscoverService(request types.DiscoveryRequest, port *omd.Port, discoverService *omd.DiscoverService) {
|
||||||
|
ds.initWithRequest(request)
|
||||||
|
|
||||||
|
ds.setPort(port)
|
||||||
|
ds.setDiscoverService(discoverService)
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
41
discovery/session/mock-discovery-session.go
Normal file
41
discovery/session/mock-discovery-session.go
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
package session
|
||||||
|
|
||||||
|
import (
|
||||||
|
omd "git.loafle.net/overflow/model/discovery"
|
||||||
|
"git.loafle.net/overflow_scanner/probe/discovery/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func MockDiscoverySession() *mockDiscoverySession {
|
||||||
|
return &mockDiscoverySession{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockDiscoverySession struct {
|
||||||
|
ofDiscoverySession
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *mockDiscoverySession) InitWithDiscoverHost(request types.DiscoveryRequest, zone *omd.Zone, discoverHost *omd.DiscoverHost) {
|
||||||
|
ds.setZone(zone)
|
||||||
|
ds.setDiscoverHost(discoverHost)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *mockDiscoverySession) InitWithDiscoverPort(request types.DiscoveryRequest, host *omd.Host, discoverPort *omd.DiscoverPort) {
|
||||||
|
ds.setHost(host)
|
||||||
|
ds.setDiscoverPort(discoverPort)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *mockDiscoverySession) InitWithDiscoverService(request types.DiscoveryRequest, port *omd.Port, discoverService *omd.DiscoverService) {
|
||||||
|
ds.setPort(port)
|
||||||
|
ds.setDiscoverService(discoverService)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *mockDiscoverySession) AddHost(host *omd.Host) *omd.Host {
|
||||||
|
return host
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *mockDiscoverySession) AddPort(port *omd.Port) *omd.Port {
|
||||||
|
return port
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *mockDiscoverySession) AddService(service *omd.Service) *omd.Service {
|
||||||
|
return service
|
||||||
|
}
|
41
discovery/types/types.go
Normal file
41
discovery/types/types.go
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
type DiscoveryMessageType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
DiscoveryMessageTypeNone DiscoveryMessageType = iota
|
||||||
|
DiscoveryMessageTypeQueueing
|
||||||
|
DiscoveryMessageTypeFailedQueueing
|
||||||
|
DiscoveryMessageTypeTimeout
|
||||||
|
DiscoveryMessageTypeStart
|
||||||
|
DiscoveryMessageTypeStop
|
||||||
|
DiscoveryMessageTypeError
|
||||||
|
DiscoveryMessageTypeHost
|
||||||
|
DiscoveryMessageTypePort
|
||||||
|
DiscoveryMessageTypeService
|
||||||
|
)
|
||||||
|
|
||||||
|
type DiscoveryMessage interface {
|
||||||
|
Request() DiscoveryRequest
|
||||||
|
Type() DiscoveryMessageType
|
||||||
|
Result() interface{}
|
||||||
|
Error() error
|
||||||
|
Release()
|
||||||
|
}
|
||||||
|
|
||||||
|
type DiscoveryRequestType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
DiscoveryRequestTypeNone DiscoveryRequestType = iota
|
||||||
|
DiscoveryRequestTypeHost
|
||||||
|
DiscoveryRequestTypePort
|
||||||
|
DiscoveryRequestTypeService
|
||||||
|
)
|
||||||
|
|
||||||
|
type DiscoveryRequest interface {
|
||||||
|
RequesterID() string
|
||||||
|
RequestType() DiscoveryRequestType
|
||||||
|
Params() []interface{}
|
||||||
|
|
||||||
|
SendMessage(messageType DiscoveryMessageType, data interface{}, err error)
|
||||||
|
}
|
0
internal/discovery/host/host.go
Normal file
0
internal/discovery/host/host.go
Normal file
|
@ -5,7 +5,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDHCP(t *testing.T) {
|
func TestDHCP(t *testing.T) {
|
||||||
offer, err := doDiscoverV4("192.168.1.203")
|
offer, err := doDiscoverV4("192.168.1.101")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("ERROR : %s", err.Error())
|
t.Errorf("ERROR : %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
oa "git.loafle.net/overflow/annotation-go"
|
oa "git.loafle.net/overflow/annotation-go"
|
||||||
od "git.loafle.net/overflow/di-go"
|
od "git.loafle.net/overflow/di-go"
|
||||||
omd "git.loafle.net/overflow/model/discovery"
|
omd "git.loafle.net/overflow/model/discovery"
|
||||||
"git.loafle.net/overflow_scanner/probe/model"
|
"git.loafle.net/overflow_scanner/probe/discovery"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -18,11 +18,51 @@ var DiscoveryServiceType = reflect.TypeOf((*DiscoveryService)(nil))
|
||||||
|
|
||||||
type DiscoveryService struct {
|
type DiscoveryService struct {
|
||||||
oa.TypeAnnotation `annotation:"@Injectable('name': 'DiscoveryService') @Service()"`
|
oa.TypeAnnotation `annotation:"@Injectable('name': 'DiscoveryService') @Service()"`
|
||||||
|
|
||||||
|
Discoverer discovery.Discoverer `annotation:"@Resource('name': 'Discoverer')"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DiscoveryService) StartDiscover(zone *omd.Zone) error {
|
func (s *DiscoveryService) InitService() error {
|
||||||
d := model.New(zone)
|
|
||||||
log.Print(d)
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DiscoveryService) StartService() error {
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case msg, ok := <-s.Discoverer.Message():
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Print(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DiscoveryService) StopService() {
|
||||||
|
s.Discoverer.Shutdown()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DiscoveryService) DestroyService() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DiscoveryService) DiscoverHost(requesterID string, zone *omd.Zone, dh *omd.DiscoverHost) error {
|
||||||
|
s.Discoverer.DiscoverHost(requesterID, zone, dh)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DiscoveryService) DiscoverPort(requesterID string, host *omd.Host, dp *omd.DiscoverPort) error {
|
||||||
|
s.Discoverer.DiscoverPort(requesterID, host, dp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DiscoveryService) DiscoverService(requesterID string, port *omd.Port, ds *omd.DiscoverService) error {
|
||||||
|
s.Discoverer.DiscoverService(requesterID, port, ds)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user