255 lines
6.3 KiB
Go
255 lines
6.3 KiB
Go
package matcher
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"net"
|
|
"strings"
|
|
"time"
|
|
|
|
omd "git.loafle.net/overflow/model/discovery"
|
|
omm "git.loafle.net/overflow/model/meta"
|
|
osm "git.loafle.net/overflow/service_matcher-go"
|
|
ouej "git.loafle.net/overflow/util-go/encoding/json"
|
|
ounp "git.loafle.net/overflow/util-go/net/ping"
|
|
"git.loafle.net/overflow_scanner/probe/internal/matcher"
|
|
)
|
|
|
|
func Ping(service *omd.Service, pingOption ounp.Option) (ounp.Result, error) {
|
|
portNumber, err := ouej.NumberToInt(service.Port.PortNumber)
|
|
if nil != err {
|
|
return nil, err
|
|
}
|
|
|
|
matchCtx := osm.NewMatchCtx(service.Port.Host.Address, portNumber)
|
|
_matcher := matcher.GetMatcherByKey(service.Key)
|
|
if _matcher.IsPrePacket() {
|
|
return processPrepacket(service, pingOption, matchCtx, _matcher), nil
|
|
}
|
|
return processPostpacket(service, pingOption, matchCtx, _matcher), nil
|
|
}
|
|
|
|
func processPrepacket(service *omd.Service, pingOption ounp.Option, matchCtx *osm.MatchCtx, _matcher osm.Matcher) ounp.Result {
|
|
pingResult := &ounp.PingResult{
|
|
Responses: make(map[int]ounp.Response, 0),
|
|
Summary: &ounp.PingSummary{},
|
|
}
|
|
|
|
buf := make([]byte, 1024)
|
|
|
|
LOOP:
|
|
for indexR := 0; indexR < pingOption.GetCount(); indexR++ {
|
|
startTime := time.Now()
|
|
matchCtx.InitAttribute()
|
|
conn, err := getConnection(service, pingOption)
|
|
if nil != err {
|
|
pingResult.Responses[indexR] = &ounp.PingResponse{
|
|
Error: err.Error(),
|
|
}
|
|
continue LOOP
|
|
}
|
|
|
|
if err := conn.SetReadDeadline(time.Now().Add(time.Duration(pingOption.GetDeadline()) * time.Second)); nil != err {
|
|
pingResult.Responses[indexR] = &ounp.PingResponse{
|
|
Error: err.Error(),
|
|
}
|
|
conn.Close()
|
|
continue LOOP
|
|
}
|
|
n, err := conn.Read(buf)
|
|
if nil != err {
|
|
pingResult.Responses[indexR] = &ounp.PingResponse{
|
|
Error: err.Error(),
|
|
}
|
|
conn.Close()
|
|
continue LOOP
|
|
}
|
|
|
|
if err := _matcher.Match(matchCtx, 0, osm.NewPacket(buf, n)); nil != err {
|
|
pingResult.Responses[indexR] = &ounp.PingResponse{
|
|
Error: err.Error(),
|
|
}
|
|
conn.Close()
|
|
continue LOOP
|
|
}
|
|
|
|
packetCount := _matcher.PacketCount(matchCtx)
|
|
|
|
if 0 == packetCount {
|
|
pingResult.Responses[indexR] = &ounp.PingResponse{
|
|
Time: 0,
|
|
}
|
|
conn.Close()
|
|
continue LOOP
|
|
}
|
|
|
|
isMatched := false
|
|
|
|
INNER_LOOP:
|
|
for indexM := 0; indexM < packetCount; indexM++ {
|
|
_packet := _matcher.Packet(matchCtx, indexM)
|
|
|
|
if err := conn.SetWriteDeadline(time.Now().Add(time.Duration(pingOption.GetDeadline()) * time.Second)); nil != err {
|
|
pingResult.Responses[indexR] = &ounp.PingResponse{
|
|
Error: err.Error(),
|
|
}
|
|
break INNER_LOOP
|
|
}
|
|
_, err := conn.Write(_packet.Buffer)
|
|
if nil != err {
|
|
pingResult.Responses[indexR] = &ounp.PingResponse{
|
|
Error: err.Error(),
|
|
}
|
|
break INNER_LOOP
|
|
}
|
|
|
|
if err := conn.SetReadDeadline(time.Now().Add(time.Duration(pingOption.GetDeadline()) * time.Second)); nil != err {
|
|
pingResult.Responses[indexR] = &ounp.PingResponse{
|
|
Error: err.Error(),
|
|
}
|
|
break INNER_LOOP
|
|
}
|
|
n, err := conn.Read(buf)
|
|
if nil != err {
|
|
pingResult.Responses[indexR] = &ounp.PingResponse{
|
|
Error: err.Error(),
|
|
}
|
|
break INNER_LOOP
|
|
}
|
|
|
|
if err := _matcher.Match(matchCtx, indexM+1, osm.NewPacket(buf, n)); nil == err {
|
|
isMatched = true
|
|
} else {
|
|
pingResult.Responses[indexR] = &ounp.PingResponse{
|
|
Error: "Protocol not match",
|
|
}
|
|
break INNER_LOOP
|
|
}
|
|
}
|
|
|
|
conn.Close()
|
|
|
|
if isMatched {
|
|
elapsed := time.Since(startTime)
|
|
pingResult.Responses[indexR] = &ounp.PingResponse{
|
|
Time: float32(elapsed),
|
|
}
|
|
}
|
|
}
|
|
|
|
return pingResult
|
|
}
|
|
|
|
func processPostpacket(service *omd.Service, pingOption ounp.Option, matchCtx *osm.MatchCtx, _matcher osm.Matcher) ounp.Result {
|
|
pingResult := &ounp.PingResult{
|
|
Responses: make(map[int]ounp.Response, 0),
|
|
Summary: &ounp.PingSummary{},
|
|
}
|
|
|
|
buf := make([]byte, 1024)
|
|
|
|
LOOP:
|
|
for indexR := 0; indexR < pingOption.GetCount(); indexR++ {
|
|
startTime := time.Now()
|
|
matchCtx.InitAttribute()
|
|
packetCount := _matcher.PacketCount(matchCtx)
|
|
|
|
if 0 == packetCount {
|
|
pingResult.Responses[indexR] = &ounp.PingResponse{
|
|
Error: "Protocol not match",
|
|
}
|
|
continue LOOP
|
|
}
|
|
|
|
conn, err := getConnection(service, pingOption)
|
|
if nil != err {
|
|
pingResult.Responses[indexR] = &ounp.PingResponse{
|
|
Error: err.Error(),
|
|
}
|
|
continue LOOP
|
|
}
|
|
|
|
isMatched := false
|
|
|
|
INNER_LOOP:
|
|
for indexM := 0; indexM < packetCount; indexM++ {
|
|
_packet := _matcher.Packet(matchCtx, indexM)
|
|
|
|
if err := conn.SetWriteDeadline(time.Now().Add(time.Duration(pingOption.GetDeadline()) * time.Second)); nil != err {
|
|
pingResult.Responses[indexR] = &ounp.PingResponse{
|
|
Error: err.Error(),
|
|
}
|
|
break INNER_LOOP
|
|
}
|
|
_, err := conn.Write(_packet.Buffer)
|
|
if nil != err {
|
|
pingResult.Responses[indexR] = &ounp.PingResponse{
|
|
Error: err.Error(),
|
|
}
|
|
break INNER_LOOP
|
|
}
|
|
|
|
if err := conn.SetReadDeadline(time.Now().Add(time.Duration(pingOption.GetDeadline()) * time.Second)); nil != err {
|
|
pingResult.Responses[indexR] = &ounp.PingResponse{
|
|
Error: err.Error(),
|
|
}
|
|
break INNER_LOOP
|
|
}
|
|
n, err := conn.Read(buf)
|
|
if nil != err {
|
|
pingResult.Responses[indexR] = &ounp.PingResponse{
|
|
Error: err.Error(),
|
|
}
|
|
break INNER_LOOP
|
|
}
|
|
|
|
if err := _matcher.Match(matchCtx, indexM+1, osm.NewPacket(buf, n)); nil == err {
|
|
if packetCount-1 == indexM {
|
|
isMatched = true
|
|
break INNER_LOOP
|
|
}
|
|
} else {
|
|
pingResult.Responses[indexR] = &ounp.PingResponse{
|
|
Error: "Protocol not match",
|
|
}
|
|
break INNER_LOOP
|
|
}
|
|
}
|
|
|
|
conn.Close()
|
|
|
|
if isMatched {
|
|
elapsed := time.Since(startTime)
|
|
pingResult.Responses[indexR] = &ounp.PingResponse{
|
|
Time: float32(elapsed),
|
|
}
|
|
}
|
|
}
|
|
|
|
return pingResult
|
|
}
|
|
|
|
func getConnection(service *omd.Service, pingOption ounp.Option) (net.Conn, error) {
|
|
addr := net.JoinHostPort(service.Port.Host.Address, service.Port.PortNumber.String())
|
|
portType := strings.ToLower(service.Port.MetaPortType.Key)
|
|
|
|
switch omm.ToMetaCryptoTypeEnum(service.MetaCryptoType) {
|
|
case omm.MetaCryptoTypeEnumTLS:
|
|
dialer := &net.Dialer{
|
|
Timeout: time.Duration(pingOption.GetDeadline()) * time.Second,
|
|
}
|
|
|
|
return tls.DialWithDialer(
|
|
dialer,
|
|
portType,
|
|
addr,
|
|
&tls.Config{
|
|
InsecureSkipVerify: true,
|
|
ServerName: service.Port.Host.Address,
|
|
},
|
|
)
|
|
default:
|
|
|
|
return net.DialTimeout(portType, addr, time.Duration(pingOption.GetDeadline())*time.Second)
|
|
}
|
|
}
|