aboutsummaryrefslogtreecommitdiff
path: root/scream/ipecho.go
diff options
context:
space:
mode:
Diffstat (limited to 'scream/ipecho.go')
-rw-r--r--scream/ipecho.go69
1 files changed, 69 insertions, 0 deletions
diff --git a/scream/ipecho.go b/scream/ipecho.go
new file mode 100644
index 0000000..9b0c117
--- /dev/null
+++ b/scream/ipecho.go
@@ -0,0 +1,69 @@
+package scream
+
+import (
+ "fmt"
+ "net"
+ "os"
+ "time"
+
+ "golang.org/x/net/icmp"
+ "golang.org/x/net/ipv4"
+)
+
+// PingHost Send a icmp packet and wait for reply, and return icmp reply time
+func PingHost(addr string, blackout int) (*net.IPAddr, time.Duration, error) {
+ c, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0")
+ if err != nil {
+ return nil, 0, err
+ }
+ defer c.Close()
+
+ dst, err := net.ResolveIPAddr("ip4", addr)
+ if err != nil {
+ return nil, 0, err
+ }
+
+ // Make a new hello message
+ m := icmp.Message{
+ Type: ipv4.ICMPTypeEcho, Code: 0,
+ Body: &icmp.Echo{
+ ID: os.Getpid() & 0xffff, Seq: 1,
+ Data: []byte(""),
+ },
+ }
+ b, err := m.Marshal(nil)
+ if err != nil {
+ return dst, 0, err
+ }
+
+ // send hi to destination
+ start := time.Now()
+ n, err := c.WriteTo(b, dst)
+ if err != nil {
+ return dst, 0, err
+ } else if n != len(b) {
+ return dst, 0, fmt.Errorf("can not write all data, wrote: %v, data: %v", n, len(b))
+ }
+
+ // catch the reply
+ reply := make([]byte, 1500)
+ err = c.SetReadDeadline(time.Now().Add(time.Duration(blackout) * time.Second))
+ if err != nil {
+ return dst, 0, err
+ }
+ n, peer, err := c.ReadFrom(reply)
+ if err != nil {
+ return dst, 0, err
+ }
+ duration := time.Since(start)
+ rm, err := icmp.ParseMessage(1, reply[:n])
+ if err != nil {
+ return dst, 0, err
+ }
+ switch rm.Type {
+ case ipv4.ICMPTypeEchoReply:
+ return dst, duration, nil
+ default:
+ return dst, 0, fmt.Errorf("mismatch data, %v and %v", rm, peer)
+ }
+}

Snix LLC Git Repository Holder Copyright(C) 2022 All Rights Reserved Email To Snix.IR