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" ) func Ping(service *omd.Service, pingOption ounp.Option) (ounp.Result, error) { if isDiscoveredByMatcher(service) { return processPing(service, pingOption, matcherPingFunc) } return processPing(service, pingOption, connectionPingFunc) } func isDiscoveredByMatcher(service *omd.Service) bool { for _, discoveredBy := range service.DiscoveredBy { switch omm.ToMetaDiscovererTypeEnum(discoveredBy) { case omm.MetaDiscovererTypeEnumUDPMatcher, omm.MetaDiscovererTypeEnumTCPMatcher: return true } } 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 := float64(time.Since(startTime).Nanoseconds()) / float64(1E6) 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) } }