This commit is contained in:
crusader 2018-09-22 02:52:45 +09:00
parent d6825fdd2e
commit b126c5502d
7 changed files with 286 additions and 485 deletions

View File

@ -1,109 +0,0 @@
package connection
import (
"crypto/tls"
"net"
"strings"
"time"
omd "git.loafle.net/overflow/model/discovery"
omm "git.loafle.net/overflow/model/meta"
ounp "git.loafle.net/overflow/util-go/net/ping"
)
func Ping(service *omd.Service, pingOption ounp.Option) (ounp.Result, error) {
responses := make(map[int]ounp.Response, 0)
summary := &ounp.PingSummary{}
pingResult := &ounp.PingResult{
Responses: responses,
Summary: summary,
}
var _sum float64
var _res *ounp.PingResponse
for indexR := 0; indexR < pingOption.GetCount(); indexR++ {
summary.SendCount = summary.SendCount + 1
_res = &ounp.PingResponse{}
if 0 < indexR {
select {
case <-time.After(time.Duration(pingOption.GetDeadline()) * time.Second):
}
}
ttl, elapsedTime, err := sendPing(service, pingOption)
if 0 == indexR {
summary.MinTime = elapsedTime
summary.MaxTime = elapsedTime
}
if nil == err {
_sum = _sum + elapsedTime
summary.ReceiveCount = summary.ReceiveCount + 1
if summary.MinTime > elapsedTime {
summary.MinTime = elapsedTime
}
if summary.MaxTime < elapsedTime {
summary.MaxTime = elapsedTime
}
_res.Time = elapsedTime
_res.TTL = ttl
} else {
_res.Error = err.Error()
}
pingResult.Responses[indexR] = _res
}
if 0 == summary.ReceiveCount {
summary.AvgTime = 0
summary.LossPercent = 100
} else {
summary.AvgTime = _sum / float64(summary.ReceiveCount)
summary.LossPercent = (float32(summary.SendCount) - float32(summary.ReceiveCount)) / float32(summary.SendCount) * float32(100)
}
return pingResult, nil
}
func sendPing(service *omd.Service, pingOption ounp.Option) (ttl int, elapsedTime float64, err error) {
startTime := time.Now()
var conn net.Conn
conn, err = getConnection(service, pingOption)
if nil != err {
return
}
defer conn.Close()
elapsed := time.Since(startTime)
elapsedTime = elapsed.Seconds() * 1E3
return
}
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)
}
}

View File

@ -1,95 +0,0 @@
package connection
import (
"encoding/json"
"log"
"net"
"reflect"
"testing"
omd "git.loafle.net/overflow/model/discovery"
omm "git.loafle.net/overflow/model/meta"
ounp "git.loafle.net/overflow/util-go/net/ping"
"git.loafle.net/overflow_scanner/probe/__test"
)
func TestPing(t *testing.T) {
targetHost := __test.Host(
"",
"234",
"d0:7e:35:da:26:68",
)
targetPort := __test.Port(
targetHost,
139,
)
type args struct {
service *omd.Service
pingOption ounp.Option
}
tests := []struct {
name string
args args
want ounp.Result
wantErr bool
}{
{
name: "192.168.1.99",
args: args{
service: __test.Service(
targetPort,
omm.MetaCryptoTypeEnumNONE,
"",
),
pingOption: &ounp.PingOption{
Count: 3,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Ping(tt.args.service, tt.args.pingOption)
if (err != nil) != tt.wantErr {
t.Errorf("Ping() error = %v, wantErr %v", err, tt.wantErr)
return
}
_buf, _ := json.Marshal(got)
log.Print(string(_buf))
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("Ping() = %v, want %v", got, tt.want)
}
})
}
}
func Test_getConnection(t *testing.T) {
type args struct {
service *omd.Service
pingOption ounp.Option
}
tests := []struct {
name string
args args
want net.Conn
wantErr bool
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := getConnection(tt.args.service, tt.args.pingOption)
if (err != nil) != tt.wantErr {
t.Errorf("getConnection() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("getConnection() = %v, want %v", got, tt.want)
}
})
}
}

View File

@ -1,254 +0,0 @@
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)
}
}

View File

@ -0,0 +1,19 @@
package service
import (
"net"
omd "git.loafle.net/overflow/model/discovery"
ounp "git.loafle.net/overflow/util-go/net/ping"
)
func connectionPingFunc(service *omd.Service, pingOption ounp.Option) (ttl int, err error) {
var conn net.Conn
conn, err = getConnection(service, pingOption)
if nil != err {
return
}
defer conn.Close()
return
}

View File

@ -0,0 +1,144 @@
package service
import (
"fmt"
"net"
"time"
omd "git.loafle.net/overflow/model/discovery"
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 matcherPingFunc(service *omd.Service, pingOption ounp.Option) (ttl int, err error) {
var portNumber int
portNumber, err = ouej.NumberToInt(service.Port.PortNumber)
if nil != err {
return
}
matchCtx := osm.NewMatchCtx(service.Port.Host.Address, portNumber)
_matcher := matcher.GetMatcherByKey(service.Key)
if _matcher.IsPrePacket() {
return processPrepacket(service, pingOption, matchCtx, _matcher)
}
return processPostpacket(service, pingOption, matchCtx, _matcher)
}
func processPrepacket(service *omd.Service, pingOption ounp.Option, matchCtx *osm.MatchCtx, _matcher osm.Matcher) (ttl int, err error) {
var conn net.Conn
var bufLen int
buf := make([]byte, 1024)
conn, err = getConnection(service, pingOption)
if nil != err {
return
}
defer conn.Close()
err = conn.SetReadDeadline(time.Now().Add(time.Duration(pingOption.GetDeadline()) * time.Second))
if nil != err {
return
}
bufLen, err = conn.Read(buf)
if nil != err {
return
}
err = _matcher.Match(matchCtx, 0, osm.NewPacket(buf, bufLen))
if nil != err {
return
}
packetCount := _matcher.PacketCount(matchCtx)
if 0 == packetCount {
return
}
for indexM := 0; indexM < packetCount; indexM++ {
_packet := _matcher.Packet(matchCtx, indexM)
err = conn.SetWriteDeadline(time.Now().Add(time.Duration(pingOption.GetDeadline()) * time.Second))
if nil != err {
return
}
_, err = conn.Write(_packet.Buffer)
if nil != err {
return
}
err = conn.SetReadDeadline(time.Now().Add(time.Duration(pingOption.GetDeadline()) * time.Second))
if nil != err {
return
}
bufLen, err = conn.Read(buf)
if nil != err {
return
}
err = _matcher.Match(matchCtx, indexM+1, osm.NewPacket(buf, bufLen))
if nil != err {
err = fmt.Errorf("Protocol not match")
return
}
}
return
}
func processPostpacket(service *omd.Service, pingOption ounp.Option, matchCtx *osm.MatchCtx, _matcher osm.Matcher) (ttl int, err error) {
var conn net.Conn
var bufLen int
buf := make([]byte, 1024)
packetCount := _matcher.PacketCount(matchCtx)
if 0 == packetCount {
err = fmt.Errorf("Protocol not match")
return
}
conn, err = getConnection(service, pingOption)
if nil != err {
return
}
defer conn.Close()
for indexM := 0; indexM < packetCount; indexM++ {
_packet := _matcher.Packet(matchCtx, indexM)
err = conn.SetWriteDeadline(time.Now().Add(time.Duration(pingOption.GetDeadline()) * time.Second))
if nil != err {
return
}
_, err = conn.Write(_packet.Buffer)
if nil != err {
return
}
err = conn.SetReadDeadline(time.Now().Add(time.Duration(pingOption.GetDeadline()) * time.Second))
if nil != err {
return
}
bufLen, err = conn.Read(buf)
if nil != err {
return
}
err = _matcher.Match(matchCtx, indexM+1, osm.NewPacket(buf, bufLen))
if nil != err {
return
}
if packetCount-1 == indexM {
return
}
}
return
}

View File

@ -1,19 +1,22 @@
package service
import (
"crypto/tls"
"net"
"strings"
"time"
omd "git.loafle.net/overflow/model/discovery"
omm "git.loafle.net/overflow/model/meta"
ounp "git.loafle.net/overflow/util-go/net/ping"
"git.loafle.net/overflow_scanner/probe/ping/service/connection"
"git.loafle.net/overflow_scanner/probe/ping/service/matcher"
)
func Ping(service *omd.Service, pingOption ounp.Option) (ounp.Result, error) {
if isDiscoveredByMatcher(service) {
return matcher.Ping(service, pingOption)
return processPing(service, pingOption, matcherPingFunc)
}
return connection.Ping(service, pingOption)
return processPing(service, pingOption, connectionPingFunc)
}
func isDiscoveredByMatcher(service *omd.Service) bool {
@ -26,3 +29,89 @@ func isDiscoveredByMatcher(service *omd.Service) bool {
return false
}
type pingFunc func(service *omd.Service, pingOption ounp.Option) (ttl int, err error)
func processPing(service *omd.Service, pingOption ounp.Option, _pingFunc pingFunc) (ounp.Result, error) {
responses := make(map[int]ounp.Response, 0)
summary := &ounp.PingSummary{}
pingResult := &ounp.PingResult{
Responses: responses,
Summary: summary,
}
var _sum float64
var _res *ounp.PingResponse
for indexR := 0; indexR < pingOption.GetCount(); indexR++ {
summary.SendCount = summary.SendCount + 1
startTime := time.Now()
_res = &ounp.PingResponse{}
if 0 < indexR {
select {
case <-time.After(time.Duration(pingOption.GetDeadline()) * time.Second):
}
}
ttl, err := _pingFunc(service, pingOption)
elapsedTime := time.Since(startTime).Seconds() * 1E3
if 0 == indexR {
summary.MinTime = elapsedTime
summary.MaxTime = elapsedTime
}
if nil == err {
_sum = _sum + elapsedTime
summary.ReceiveCount = summary.ReceiveCount + 1
if summary.MinTime > elapsedTime {
summary.MinTime = elapsedTime
}
if summary.MaxTime < elapsedTime {
summary.MaxTime = elapsedTime
}
_res.Time = elapsedTime
_res.TTL = ttl
} else {
_res.Error = err.Error()
}
pingResult.Responses[indexR] = _res
}
if 0 == summary.ReceiveCount {
summary.AvgTime = 0
summary.LossPercent = 100
} else {
summary.AvgTime = _sum / float64(summary.ReceiveCount)
summary.LossPercent = (float32(summary.SendCount) - float32(summary.ReceiveCount)) / float32(summary.SendCount) * float32(100)
}
return pingResult, nil
}
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)
}
}

View File

@ -1,13 +1,14 @@
package matcher
package service
import (
"encoding/json"
"log"
"net"
"reflect"
"testing"
omd "git.loafle.net/overflow/model/discovery"
omm "git.loafle.net/overflow/model/meta"
osm "git.loafle.net/overflow/service_matcher-go"
ounp "git.loafle.net/overflow/util-go/net/ping"
"git.loafle.net/overflow_scanner/probe/__test"
)
@ -15,13 +16,13 @@ import (
func TestPing(t *testing.T) {
targetHost := __test.Host(
"",
"99",
"00:25:b3:fa:ca:9b",
"234",
"d0:7e:35:da:26:68",
)
targetPort := __test.Port(
targetHost,
80,
139,
)
type args struct {
@ -35,12 +36,12 @@ func TestPing(t *testing.T) {
wantErr bool
}{
{
name: "192.168.1.99",
name: "UNKNOWN",
args: args{
service: __test.Service(
targetPort,
omm.MetaCryptoTypeEnumNONE,
"HTTP",
"",
),
pingOption: &ounp.PingOption{
Count: 3,
@ -55,6 +56,10 @@ func TestPing(t *testing.T) {
t.Errorf("Ping() error = %v, wantErr %v", err, tt.wantErr)
return
}
_buf, _ := json.Marshal(got)
log.Print(string(_buf))
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("Ping() = %v, want %v", got, tt.want)
}
@ -62,47 +67,49 @@ func TestPing(t *testing.T) {
}
}
func Test_processPrepacket(t *testing.T) {
func Test_isDiscoveredByMatcher(t *testing.T) {
type args struct {
service *omd.Service
pingOption ounp.Option
matchCtx *osm.MatchCtx
_matcher osm.Matcher
service *omd.Service
}
tests := []struct {
name string
args args
want ounp.Result
want bool
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := processPrepacket(tt.args.service, tt.args.pingOption, tt.args.matchCtx, tt.args._matcher); !reflect.DeepEqual(got, tt.want) {
t.Errorf("processPrepacket() = %v, want %v", got, tt.want)
if got := isDiscoveredByMatcher(tt.args.service); got != tt.want {
t.Errorf("isDiscoveredByMatcher() = %v, want %v", got, tt.want)
}
})
}
}
func Test_processPostpacket(t *testing.T) {
func Test_processPing(t *testing.T) {
type args struct {
service *omd.Service
pingOption ounp.Option
matchCtx *osm.MatchCtx
_matcher osm.Matcher
_pingFunc pingFunc
}
tests := []struct {
name string
args args
want ounp.Result
name string
args args
want ounp.Result
wantErr bool
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := processPostpacket(tt.args.service, tt.args.pingOption, tt.args.matchCtx, tt.args._matcher); !reflect.DeepEqual(got, tt.want) {
t.Errorf("processPostpacket() = %v, want %v", got, tt.want)
got, err := processPing(tt.args.service, tt.args.pingOption, tt.args._pingFunc)
if (err != nil) != tt.wantErr {
t.Errorf("processPing() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("processPing() = %v, want %v", got, tt.want)
}
})
}