You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
150 lines
3.1 KiB
Go
150 lines
3.1 KiB
Go
package ping
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"html/template"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// Protocol ...
|
|
type Protocol int
|
|
|
|
func (protocol Protocol) String() string {
|
|
switch protocol {
|
|
case TCP:
|
|
return "tcp"
|
|
case HTTP:
|
|
return "http"
|
|
case HTTPS:
|
|
return "https"
|
|
}
|
|
return "unkown"
|
|
}
|
|
|
|
const (
|
|
// TCP is tcp protocol
|
|
TCP Protocol = iota
|
|
// HTTP is http protocol
|
|
HTTP
|
|
// HTTPS is https protocol
|
|
HTTPS
|
|
)
|
|
|
|
// NewProtocol convert protocol stirng to Protocol
|
|
func NewProtocol(protocol string) (Protocol, error) {
|
|
switch strings.ToLower(protocol) {
|
|
case TCP.String():
|
|
return TCP, nil
|
|
case HTTP.String():
|
|
return HTTP, nil
|
|
case HTTPS.String():
|
|
return HTTPS, nil
|
|
}
|
|
return 0, fmt.Errorf("protocol %s not support", protocol)
|
|
}
|
|
|
|
// Target is a ping
|
|
type Target struct {
|
|
Protocol Protocol
|
|
Host string
|
|
Port int
|
|
|
|
Counter int
|
|
Interval time.Duration
|
|
Timeout time.Duration
|
|
}
|
|
|
|
func (target Target) String() string {
|
|
return fmt.Sprintf("%s://%s:%d", target.Protocol, target.Host, target.Port)
|
|
}
|
|
|
|
// Pinger is a ping interface
|
|
type Pinger interface {
|
|
Start() <-chan struct{}
|
|
Stop()
|
|
Result() *Result
|
|
SetTarget(target *Target)
|
|
}
|
|
|
|
// Ping is a ping interface
|
|
type Ping interface {
|
|
Start() <-chan struct{}
|
|
|
|
Host() string
|
|
Port() int
|
|
Protocol() Protocol
|
|
Counter() int
|
|
|
|
Stop()
|
|
|
|
Result() Result
|
|
}
|
|
|
|
// Result ...
|
|
type Result struct {
|
|
Counter int
|
|
SuccessCounter int
|
|
Target *Target
|
|
|
|
MinDuration time.Duration
|
|
MaxDuration time.Duration
|
|
TotalDuration time.Duration
|
|
}
|
|
|
|
// Avg return the average time of ping
|
|
func (result Result) Avg() time.Duration {
|
|
if result.SuccessCounter == 0 {
|
|
return 0
|
|
}
|
|
return result.TotalDuration / time.Duration(result.SuccessCounter)
|
|
}
|
|
|
|
// Failed return failed counter
|
|
func (result Result) Failed() int {
|
|
return result.Counter - result.SuccessCounter
|
|
}
|
|
|
|
func (result Result) String() string {
|
|
const resultTpl = `
|
|
Ping statistics {{.Target}}
|
|
{{.Counter}} probes sent.
|
|
{{.SuccessCounter}} successful, {{.Failed}} failed.
|
|
Approximate trip times:
|
|
Minimum = {{.MinDuration}}, Maximum = {{.MaxDuration}}, Average = {{.Avg}}`
|
|
t := template.Must(template.New("result").Parse(resultTpl))
|
|
res := bytes.NewBufferString("")
|
|
t.Execute(res, result)
|
|
return res.String()
|
|
}
|
|
|
|
// CheckURI check uri
|
|
func CheckURI(uri string) (schema, host string, port int, matched bool) {
|
|
const reExp = `^((?P<schema>((ht|f)tp(s?))|tcp)\://)?((([a-zA-Z0-9_\-]+\.)+[a-zA-Z]{2,})|((?:(?:25[0-5]|2[0-4]\d|[01]\d\d|\d?\d)((\.?\d)\.)){4})|(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9]))(:([0-9]+))?(/[a-zA-Z0-9\-\._\?\,\'/\\\+&%\$#\=~]*)?$`
|
|
pattern := regexp.MustCompile(reExp)
|
|
res := pattern.FindStringSubmatch(uri)
|
|
if len(res) == 0 {
|
|
return
|
|
}
|
|
matched = true
|
|
schema = res[2]
|
|
if schema == "" {
|
|
schema = "tcp"
|
|
}
|
|
host = res[6]
|
|
if res[17] == "" {
|
|
if schema == HTTPS.String() {
|
|
port = 443
|
|
} else {
|
|
port = 80
|
|
}
|
|
} else {
|
|
port, _ = strconv.Atoi(res[17])
|
|
}
|
|
|
|
return
|
|
}
|