ping.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896
  1. // Package probing is a simple but powerful ICMP echo (ping) library.
  2. //
  3. // Here is a very simple example that sends and receives three packets:
  4. //
  5. // pinger, err := probing.NewPinger("www.google.com")
  6. // if err != nil {
  7. // panic(err)
  8. // }
  9. // pinger.Count = 3
  10. // err = pinger.Run() // blocks until finished
  11. // if err != nil {
  12. // panic(err)
  13. // }
  14. // stats := pinger.Statistics() // get send/receive/rtt stats
  15. //
  16. // Here is an example that emulates the traditional UNIX ping command:
  17. //
  18. // pinger, err := probing.NewPinger("www.google.com")
  19. // if err != nil {
  20. // panic(err)
  21. // }
  22. // // Listen for Ctrl-C.
  23. // c := make(chan os.Signal, 1)
  24. // signal.Notify(c, os.Interrupt)
  25. // go func() {
  26. // for _ = range c {
  27. // pinger.Stop()
  28. // }
  29. // }()
  30. // pinger.OnRecv = func(pkt *probing.Packet) {
  31. // fmt.Printf("%d bytes from %s: icmp_seq=%d time=%v\n",
  32. // pkt.Nbytes, pkt.IPAddr, pkt.Seq, pkt.Rtt)
  33. // }
  34. // pinger.OnFinish = func(stats *probing.Statistics) {
  35. // fmt.Printf("\n--- %s ping statistics ---\n", stats.Addr)
  36. // fmt.Printf("%d packets transmitted, %d packets received, %v%% packet loss\n",
  37. // stats.PacketsSent, stats.PacketsRecv, stats.PacketLoss)
  38. // fmt.Printf("round-trip min/avg/max/stddev = %v/%v/%v/%v\n",
  39. // stats.MinRtt, stats.AvgRtt, stats.MaxRtt, stats.StdDevRtt)
  40. // }
  41. // fmt.Printf("PING %s (%s):\n", pinger.Addr(), pinger.IPAddr())
  42. // err = pinger.Run()
  43. // if err != nil {
  44. // panic(err)
  45. // }
  46. //
  47. // It sends ICMP Echo Request packet(s) and waits for an Echo Reply in response.
  48. // If it receives a response, it calls the OnRecv callback. When it's finished,
  49. // it calls the OnFinish callback.
  50. //
  51. // For a full ping example, see "cmd/ping/ping.go".
  52. package probing
  53. import (
  54. "bytes"
  55. "errors"
  56. "fmt"
  57. "log"
  58. "math"
  59. "math/rand"
  60. "net"
  61. "sync"
  62. "sync/atomic"
  63. "syscall"
  64. "time"
  65. "git.wecise.com/wecise/common/matrix/cfg"
  66. "github.com/google/uuid"
  67. "golang.org/x/net/icmp"
  68. "golang.org/x/net/ipv4"
  69. "golang.org/x/net/ipv6"
  70. "golang.org/x/sync/errgroup"
  71. )
  72. var mcfg = cfg.MConfig()
  73. var ping_interval_one_host = mcfg.GetDuration("ping.interval.one.host", 10000*time.Millisecond)
  74. var ping_interval_one_conn = mcfg.GetDuration("ping.interval.one.conn", 200*time.Millisecond)
  75. var concurlimit_ping = mcfg.GetInt("concurlimit.ping", 100)
  76. var concurlimit_send = mcfg.GetInt("concurlimit.send", 10)
  77. var concurchan_ping = make(chan struct{}, concurlimit_ping)
  78. var concurchan_send = make(chan struct{}, concurlimit_send)
  79. var lastpingtimemutex sync.Mutex
  80. var lastpingtime = map[string]time.Time{}
  81. var lastsendtimemutex sync.Mutex
  82. var lastsendtime = map[string]time.Time{}
  83. const (
  84. timeSliceLength = 8
  85. trackerLength = len(uuid.UUID{})
  86. protocolICMP = 1
  87. protocolIPv6ICMP = 58
  88. )
  89. var (
  90. ipv4Proto = map[string]string{"icmp": "ip4:icmp", "udp": "udp4"}
  91. ipv6Proto = map[string]string{"icmp": "ip6:ipv6-icmp", "udp": "udp6"}
  92. )
  93. // New returns a new Pinger struct pointer.
  94. func New(addr string) *Pinger {
  95. r := rand.New(rand.NewSource(getSeed()))
  96. firstUUID := uuid.New()
  97. var firstSequence = map[uuid.UUID]map[int]struct{}{}
  98. firstSequence[firstUUID] = make(map[int]struct{})
  99. return &Pinger{
  100. Count: -1,
  101. Interval: time.Second,
  102. RecordRtts: true,
  103. Size: timeSliceLength + trackerLength,
  104. Timeout: time.Duration(math.MaxInt64),
  105. addr: addr,
  106. done: make(chan interface{}),
  107. id: r.Intn(math.MaxUint16),
  108. trackerUUIDs: []uuid.UUID{firstUUID},
  109. ipaddr: nil,
  110. ipv4: false,
  111. network: "ip",
  112. protocol: "udp",
  113. awaitingSequences: firstSequence,
  114. TTL: 64,
  115. logger: StdLogger{Logger: log.New(log.Writer(), log.Prefix(), log.Flags())},
  116. }
  117. }
  118. // NewPinger returns a new Pinger and resolves the address.
  119. func NewPinger(addr string) (*Pinger, error) {
  120. p := New(addr)
  121. return p, p.Resolve()
  122. }
  123. // Pinger represents a packet sender/receiver.
  124. type Pinger struct {
  125. // Interval is the wait time between each packet send. Default is 1s.
  126. Interval time.Duration
  127. // Timeout specifies a timeout before ping exits, regardless of how many
  128. // packets have been received.
  129. Timeout time.Duration
  130. // Count tells pinger to stop after sending (and receiving) Count echo
  131. // packets. If this option is not specified, pinger will operate until
  132. // interrupted.
  133. Count int
  134. // Debug runs in debug mode
  135. Debug bool
  136. // Number of packets sent
  137. PacketsSent int
  138. // Number of packets received
  139. PacketsRecv int
  140. // Number of duplicate packets received
  141. PacketsRecvDuplicates int
  142. // Round trip time statistics
  143. minRtt time.Duration
  144. maxRtt time.Duration
  145. avgRtt time.Duration
  146. stdDevRtt time.Duration
  147. stddevm2 time.Duration
  148. statsMu sync.RWMutex
  149. // If true, keep a record of rtts of all received packets.
  150. // Set to false to avoid memory bloat for long running pings.
  151. RecordRtts bool
  152. // rtts is all of the Rtts
  153. rtts []time.Duration
  154. // OnSetup is called when Pinger has finished setting up the listening socket
  155. OnSetup func()
  156. // OnSend is called when Pinger sends a packet
  157. OnSend func(*Packet)
  158. // OnRecv is called when Pinger receives and processes a packet
  159. OnRecv func(*Packet)
  160. // OnFinish is called when Pinger exits
  161. OnFinish func(*Statistics)
  162. // OnDuplicateRecv is called when a packet is received that has already been received.
  163. OnDuplicateRecv func(*Packet)
  164. // Size of packet being sent
  165. Size int
  166. // Tracker: Used to uniquely identify packets - Deprecated
  167. Tracker uint64
  168. // Source is the source IP address
  169. Source string
  170. // Channel and mutex used to communicate when the Pinger should stop between goroutines.
  171. done chan interface{}
  172. lock sync.Mutex
  173. ipaddr *net.IPAddr
  174. addr string
  175. // trackerUUIDs is the list of UUIDs being used for sending packets.
  176. trackerUUIDs []uuid.UUID
  177. ipv4 bool
  178. id int
  179. sequence int
  180. // awaitingSequences are in-flight sequence numbers we keep track of to help remove duplicate receipts
  181. awaitingSequences map[uuid.UUID]map[int]struct{}
  182. // network is one of "ip", "ip4", or "ip6".
  183. network string
  184. // protocol is "icmp" or "udp".
  185. protocol string
  186. logger Logger
  187. TTL int
  188. }
  189. type packet struct {
  190. bytes []byte
  191. nbytes int
  192. ttl int
  193. }
  194. // Packet represents a received and processed ICMP echo packet.
  195. type Packet struct {
  196. // Rtt is the round-trip time it took to ping.
  197. Rtt time.Duration
  198. // IPAddr is the address of the host being pinged.
  199. IPAddr *net.IPAddr
  200. // Addr is the string address of the host being pinged.
  201. Addr string
  202. // NBytes is the number of bytes in the message.
  203. Nbytes int
  204. // Seq is the ICMP sequence number.
  205. Seq int
  206. // TTL is the Time To Live on the packet.
  207. TTL int
  208. // ID is the ICMP identifier.
  209. ID int
  210. }
  211. // Statistics represent the stats of a currently running or finished
  212. // pinger operation.
  213. type Statistics struct {
  214. // PacketsRecv is the number of packets received.
  215. PacketsRecv int
  216. // PacketsSent is the number of packets sent.
  217. PacketsSent int
  218. // PacketsRecvDuplicates is the number of duplicate responses there were to a sent packet.
  219. PacketsRecvDuplicates int
  220. // PacketLoss is the percentage of packets lost.
  221. PacketLoss float64
  222. // IPAddr is the address of the host being pinged.
  223. IPAddr *net.IPAddr
  224. // Addr is the string address of the host being pinged.
  225. Addr string
  226. // Rtts is all of the round-trip times sent via this pinger.
  227. Rtts []time.Duration
  228. // MinRtt is the minimum round-trip time sent via this pinger.
  229. MinRtt time.Duration
  230. // MaxRtt is the maximum round-trip time sent via this pinger.
  231. MaxRtt time.Duration
  232. // AvgRtt is the average round-trip time sent via this pinger.
  233. AvgRtt time.Duration
  234. // StdDevRtt is the standard deviation of the round-trip times sent via
  235. // this pinger.
  236. StdDevRtt time.Duration
  237. }
  238. func (p *Pinger) updateStatistics(pkt *Packet) {
  239. p.statsMu.Lock()
  240. defer p.statsMu.Unlock()
  241. p.PacketsRecv++
  242. if p.RecordRtts {
  243. p.rtts = append(p.rtts, pkt.Rtt)
  244. }
  245. if p.PacketsRecv == 1 || pkt.Rtt < p.minRtt {
  246. p.minRtt = pkt.Rtt
  247. }
  248. if pkt.Rtt > p.maxRtt {
  249. p.maxRtt = pkt.Rtt
  250. }
  251. pktCount := time.Duration(p.PacketsRecv)
  252. // welford's online method for stddev
  253. // https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Welford's_online_algorithm
  254. delta := pkt.Rtt - p.avgRtt
  255. p.avgRtt += delta / pktCount
  256. delta2 := pkt.Rtt - p.avgRtt
  257. p.stddevm2 += delta * delta2
  258. p.stdDevRtt = time.Duration(math.Sqrt(float64(p.stddevm2 / pktCount)))
  259. }
  260. // SetIPAddr sets the ip address of the target host.
  261. func (p *Pinger) SetIPAddr(ipaddr *net.IPAddr) {
  262. p.ipv4 = isIPv4(ipaddr.IP)
  263. p.ipaddr = ipaddr
  264. p.addr = ipaddr.String()
  265. }
  266. // IPAddr returns the ip address of the target host.
  267. func (p *Pinger) IPAddr() *net.IPAddr {
  268. return p.ipaddr
  269. }
  270. // Resolve does the DNS lookup for the Pinger address and sets IP protocol.
  271. func (p *Pinger) Resolve() error {
  272. if len(p.addr) == 0 {
  273. return errors.New("addr cannot be empty")
  274. }
  275. ipaddr, err := net.ResolveIPAddr(p.network, p.addr)
  276. if err != nil {
  277. return err
  278. }
  279. p.ipv4 = isIPv4(ipaddr.IP)
  280. p.ipaddr = ipaddr
  281. return nil
  282. }
  283. // SetAddr resolves and sets the ip address of the target host, addr can be a
  284. // DNS name like "www.google.com" or IP like "127.0.0.1".
  285. func (p *Pinger) SetAddr(addr string) error {
  286. oldAddr := p.addr
  287. p.addr = addr
  288. err := p.Resolve()
  289. if err != nil {
  290. p.addr = oldAddr
  291. return err
  292. }
  293. return nil
  294. }
  295. // Addr returns the string ip address of the target host.
  296. func (p *Pinger) Addr() string {
  297. return p.addr
  298. }
  299. // SetNetwork allows configuration of DNS resolution.
  300. // * "ip" will automatically select IPv4 or IPv6.
  301. // * "ip4" will select IPv4.
  302. // * "ip6" will select IPv6.
  303. func (p *Pinger) SetNetwork(n string) {
  304. switch n {
  305. case "ip4":
  306. p.network = "ip4"
  307. case "ip6":
  308. p.network = "ip6"
  309. default:
  310. p.network = "ip"
  311. }
  312. }
  313. // SetPrivileged sets the type of ping pinger will send.
  314. // false means pinger will send an "unprivileged" UDP ping.
  315. // true means pinger will send a "privileged" raw ICMP ping.
  316. // NOTE: setting to true requires that it be run with super-user privileges.
  317. func (p *Pinger) SetPrivileged(privileged bool) {
  318. if privileged {
  319. p.protocol = "icmp"
  320. } else {
  321. p.protocol = "udp"
  322. }
  323. }
  324. // Privileged returns whether pinger is running in privileged mode.
  325. func (p *Pinger) Privileged() bool {
  326. return p.protocol == "icmp"
  327. }
  328. // SetLogger sets the logger to be used to log events from the pinger.
  329. func (p *Pinger) SetLogger(logger Logger) {
  330. p.logger = logger
  331. }
  332. // SetID sets the ICMP identifier.
  333. func (p *Pinger) SetID(id int) {
  334. p.id = id
  335. }
  336. // ID returns the ICMP identifier.
  337. func (p *Pinger) ID() int {
  338. return p.id
  339. }
  340. // Run runs the pinger. This is a blocking function that will exit when it's
  341. // done. If Count or Interval are not specified, it will run continuously until
  342. // it is interrupted.
  343. func (p *Pinger) Run() error {
  344. sleeptime := time.Duration(0)
  345. for sleeptime >= 0 {
  346. time.Sleep(sleeptime)
  347. lastpingtimemutex.Lock()
  348. alastpingtime := lastpingtime[p.ipaddr.String()]
  349. sleeptime = ping_interval_one_host - time.Since(alastpingtime)
  350. if sleeptime <= 0 {
  351. lastpingtime[p.ipaddr.String()] = time.Now()
  352. } else {
  353. // logger.Error(fmt.Sprint("ping", p.addr, "[", p.ipaddr.String(), "]", "同一地址至少间隔一秒"))
  354. }
  355. lastpingtimemutex.Unlock()
  356. }
  357. lastpingtimemutex.Lock()
  358. for idping[p.id] != nil && idping[p.id] != p {
  359. p.id = (p.id + 1) % 65536
  360. }
  361. idping[p.id] = p
  362. lastpingtimemutex.Unlock()
  363. defer func() {
  364. lastpingtimemutex.Lock()
  365. lastpingtime[p.ipaddr.String()] = time.Now()
  366. delete(idping, p.id)
  367. lastpingtimemutex.Unlock()
  368. }()
  369. // concurchan_ping <- struct{}{}
  370. // defer func() {
  371. // <-concurchan_ping
  372. // }()
  373. var conn packetConn
  374. var err error
  375. if p.Size < timeSliceLength+trackerLength {
  376. return fmt.Errorf("size %d is less than minimum required size %d", p.Size, timeSliceLength+trackerLength)
  377. }
  378. if p.ipaddr == nil {
  379. err = p.Resolve()
  380. }
  381. if err != nil {
  382. return err
  383. }
  384. if conn, err = p.listen(); err != nil {
  385. return err
  386. }
  387. defer conn.Close()
  388. conn.SetTTL(p.TTL)
  389. return p.run(conn)
  390. }
  391. func (p *Pinger) run(conn packetConn) error {
  392. if err := conn.SetFlagTTL(); err != nil {
  393. return err
  394. }
  395. defer p.finish()
  396. recv := make(chan *packet, 5)
  397. defer close(recv)
  398. if handler := p.OnSetup; handler != nil {
  399. handler()
  400. }
  401. var g errgroup.Group
  402. g.Go(func() error {
  403. defer p.Stop()
  404. return p.recvICMP(conn, recv)
  405. })
  406. g.Go(func() error {
  407. defer p.Stop()
  408. return p.runLoop(conn, recv)
  409. })
  410. return g.Wait()
  411. }
  412. func (p *Pinger) runLoop(
  413. conn packetConn,
  414. recvCh <-chan *packet,
  415. ) error {
  416. logger := p.logger
  417. if logger == nil {
  418. logger = NoopLogger{}
  419. }
  420. timeout := time.NewTicker(p.Timeout)
  421. interval := time.NewTicker(p.Interval)
  422. defer func() {
  423. interval.Stop()
  424. timeout.Stop()
  425. }()
  426. if err := p.sendICMP(conn); err != nil {
  427. return err
  428. }
  429. for {
  430. select {
  431. case <-p.done:
  432. return nil
  433. case <-timeout.C:
  434. return nil
  435. case r := <-recvCh:
  436. err := p.processPacket(r)
  437. if err != nil {
  438. // FIXME: this logs as FATAL but continues
  439. logger.Errorf("processing received packet: %s", err)
  440. }
  441. case <-interval.C:
  442. if p.Count > 0 && p.PacketsSent >= p.Count {
  443. interval.Stop()
  444. continue
  445. }
  446. err := p.sendICMP(conn)
  447. if err != nil {
  448. // FIXME: this logs as FATAL but continues
  449. logger.Errorf("sending packet: %s", err)
  450. }
  451. }
  452. if p.Count > 0 && p.PacketsRecv >= p.Count {
  453. return nil
  454. }
  455. }
  456. }
  457. func (p *Pinger) Stop() {
  458. p.lock.Lock()
  459. defer p.lock.Unlock()
  460. open := true
  461. select {
  462. case _, open = <-p.done:
  463. default:
  464. }
  465. if open {
  466. close(p.done)
  467. }
  468. }
  469. func (p *Pinger) finish() {
  470. handler := p.OnFinish
  471. if handler != nil {
  472. s := p.Statistics()
  473. handler(s)
  474. }
  475. }
  476. // Statistics returns the statistics of the pinger. This can be run while the
  477. // pinger is running or after it is finished. OnFinish calls this function to
  478. // get it's finished statistics.
  479. func (p *Pinger) Statistics() *Statistics {
  480. p.statsMu.RLock()
  481. defer p.statsMu.RUnlock()
  482. sent := p.PacketsSent
  483. loss := float64(sent-p.PacketsRecv) / float64(sent) * 100
  484. s := Statistics{
  485. PacketsSent: sent,
  486. PacketsRecv: p.PacketsRecv,
  487. PacketsRecvDuplicates: p.PacketsRecvDuplicates,
  488. PacketLoss: loss,
  489. Rtts: p.rtts,
  490. Addr: p.addr,
  491. IPAddr: p.ipaddr,
  492. MaxRtt: p.maxRtt,
  493. MinRtt: p.minRtt,
  494. AvgRtt: p.avgRtt,
  495. StdDevRtt: p.stdDevRtt,
  496. }
  497. return &s
  498. }
  499. type expBackoff struct {
  500. baseDelay time.Duration
  501. maxExp int64
  502. c int64
  503. }
  504. func (b *expBackoff) Get() time.Duration {
  505. if b.c < b.maxExp {
  506. b.c++
  507. }
  508. return b.baseDelay * time.Duration(rand.Int63n(1<<b.c))
  509. }
  510. func newExpBackoff(baseDelay time.Duration, maxExp int64) expBackoff {
  511. return expBackoff{baseDelay: baseDelay, maxExp: maxExp}
  512. }
  513. func (p *Pinger) recvICMP(
  514. conn packetConn,
  515. recv chan<- *packet,
  516. ) error {
  517. // Start by waiting for 50 µs and increase to a possible maximum of ~ 100 ms.
  518. expBackoff := newExpBackoff(50*time.Microsecond, 100)
  519. delay := expBackoff.Get()
  520. for {
  521. select {
  522. case <-p.done:
  523. return nil
  524. default:
  525. bytes := make([]byte, p.getMessageLength())
  526. if err := conn.SetReadDeadline(time.Now().Add(delay)); err != nil {
  527. return err
  528. }
  529. var n, ttl int
  530. var err error
  531. n, ttl, _, err = conn.ReadFrom(bytes)
  532. if err != nil {
  533. if neterr, ok := err.(*net.OpError); ok {
  534. if neterr.Timeout() {
  535. // Read timeout
  536. delay = expBackoff.Get()
  537. continue
  538. }
  539. }
  540. return err
  541. }
  542. select {
  543. case <-p.done:
  544. return nil
  545. case recv <- &packet{bytes: bytes, nbytes: n, ttl: ttl}:
  546. }
  547. }
  548. }
  549. }
  550. // getPacketUUID scans the tracking slice for matches.
  551. func (p *Pinger) getPacketUUID(pkt []byte) (*uuid.UUID, error) {
  552. var packetUUID uuid.UUID
  553. err := packetUUID.UnmarshalBinary(pkt[timeSliceLength : timeSliceLength+trackerLength])
  554. if err != nil {
  555. return nil, fmt.Errorf("error decoding tracking UUID: %w", err)
  556. }
  557. for _, item := range p.trackerUUIDs {
  558. if item == packetUUID {
  559. return &packetUUID, nil
  560. }
  561. }
  562. return nil, nil
  563. }
  564. // getCurrentTrackerUUID grabs the latest tracker UUID.
  565. func (p *Pinger) getCurrentTrackerUUID() uuid.UUID {
  566. return p.trackerUUIDs[len(p.trackerUUIDs)-1]
  567. }
  568. func (p *Pinger) processPacket(recv *packet) error {
  569. receivedAt := time.Now()
  570. var proto int
  571. if p.ipv4 {
  572. proto = protocolICMP
  573. } else {
  574. proto = protocolIPv6ICMP
  575. }
  576. var m *icmp.Message
  577. var err error
  578. if m, err = icmp.ParseMessage(proto, recv.bytes); err != nil {
  579. return fmt.Errorf("error parsing icmp message: %w", err)
  580. }
  581. if m.Type != ipv4.ICMPTypeEchoReply && m.Type != ipv6.ICMPTypeEchoReply {
  582. // Not an echo reply, ignore it
  583. return nil
  584. }
  585. inPkt := &Packet{
  586. Nbytes: recv.nbytes,
  587. IPAddr: p.ipaddr,
  588. Addr: p.addr,
  589. TTL: recv.ttl,
  590. ID: p.id,
  591. }
  592. switch pkt := m.Body.(type) {
  593. case *icmp.Echo:
  594. return p.processEchoReply(pkt, receivedAt, inPkt)
  595. default:
  596. // Very bad, not sure how this can happen
  597. return fmt.Errorf("invalid ICMP echo reply; type: '%T', '%v'", pkt, pkt)
  598. }
  599. }
  600. var idping = map[int]*Pinger{}
  601. func (p *Pinger) processEchoReply(pkt *icmp.Echo, receivedAt time.Time, inPkt *Packet) error {
  602. if !p.matchID(pkt.ID) {
  603. // lastpingtimemutex.Lock()
  604. // ap := idping[pkt.ID]
  605. // lastpingtimemutex.Unlock()
  606. // println(fmt.Sprintf("%#v%s%#v", ap, "\n", p))
  607. return nil
  608. }
  609. if len(pkt.Data) < timeSliceLength+trackerLength {
  610. return fmt.Errorf("insufficient data received; got: %d %v",
  611. len(pkt.Data), pkt.Data)
  612. }
  613. pktUUID, err := p.getPacketUUID(pkt.Data)
  614. if err != nil || pktUUID == nil {
  615. return err
  616. }
  617. timestamp := bytesToTime(pkt.Data[:timeSliceLength])
  618. inPkt.Rtt = receivedAt.Sub(timestamp)
  619. inPkt.Seq = pkt.Seq
  620. // If we've already received this sequence, ignore it.
  621. if _, inflight := p.awaitingSequences[*pktUUID][pkt.Seq]; !inflight {
  622. p.PacketsRecvDuplicates++
  623. if p.OnDuplicateRecv != nil {
  624. p.OnDuplicateRecv(inPkt)
  625. }
  626. return nil
  627. }
  628. // remove it from the list of sequences we're waiting for so we don't get duplicates.
  629. delete(p.awaitingSequences[*pktUUID], pkt.Seq)
  630. p.updateStatistics(inPkt)
  631. handler := p.OnRecv
  632. if handler != nil {
  633. handler(inPkt)
  634. }
  635. return nil
  636. }
  637. func (p *Pinger) sendICMP(conn packetConn) error {
  638. concurchan_send <- struct{}{}
  639. defer func() {
  640. <-concurchan_send
  641. lastpingtimemutex.Lock()
  642. lastpingtime[p.ipaddr.String()] = time.Now()
  643. lastpingtimemutex.Unlock()
  644. }()
  645. // lastsendtimemutex.Lock()
  646. // alastsendtime := lastsendtime[p.addr]
  647. // sleeptime := 200*time.Millisecond - time.Since(alastsendtime)
  648. // lastsendtimemutex.Unlock()
  649. // if sleeptime > 0 {
  650. // time.Sleep(sleeptime)
  651. // }
  652. // lastsendtimemutex.Lock()
  653. // lastsendtime[p.addr] = time.Now()
  654. // lastsendtimemutex.Unlock()
  655. // defer func() {
  656. // lastsendtimemutex.Lock()
  657. // lastsendtime[p.addr] = time.Now()
  658. // lastsendtimemutex.Unlock()
  659. // }()
  660. return p.sendICMPx(conn)
  661. }
  662. func (p *Pinger) sendICMPx(conn packetConn) error {
  663. var dst net.Addr = p.ipaddr
  664. if p.protocol == "udp" {
  665. dst = &net.UDPAddr{IP: p.ipaddr.IP, Zone: p.ipaddr.Zone}
  666. }
  667. currentUUID := p.getCurrentTrackerUUID()
  668. uuidEncoded, err := currentUUID.MarshalBinary()
  669. if err != nil {
  670. return fmt.Errorf("unable to marshal UUID binary: %w", err)
  671. }
  672. t := append(timeToBytes(time.Now()), uuidEncoded...)
  673. t = append(t, []byte(p.addr)...)
  674. if remainSize := p.Size - len(t); remainSize > 0 {
  675. t = append(t, bytes.Repeat([]byte{1}, remainSize)...)
  676. }
  677. body := &icmp.Echo{
  678. ID: p.id,
  679. Seq: p.sequence,
  680. Data: t,
  681. }
  682. msg := &icmp.Message{
  683. Type: conn.ICMPRequestType(),
  684. Code: 0,
  685. Body: body,
  686. }
  687. msgBytes, err := msg.Marshal(nil)
  688. if err != nil {
  689. return err
  690. }
  691. // fmt.Println("len(body.Data)=", len(body.Data))
  692. // fmt.Println("len(msgBytes)=", len(msgBytes))
  693. for {
  694. if _, err := conn.WriteTo(msgBytes, dst); err != nil {
  695. if neterr, ok := err.(*net.OpError); ok {
  696. if neterr.Err == syscall.ENOBUFS {
  697. fmt.Println("发送失败,重发")
  698. continue
  699. }
  700. }
  701. return err
  702. }
  703. handler := p.OnSend
  704. if handler != nil {
  705. outPkt := &Packet{
  706. Nbytes: len(msgBytes),
  707. IPAddr: p.ipaddr,
  708. Addr: p.addr,
  709. Seq: p.sequence,
  710. ID: p.id,
  711. }
  712. handler(outPkt)
  713. }
  714. // mark this sequence as in-flight
  715. p.awaitingSequences[currentUUID][p.sequence] = struct{}{}
  716. p.PacketsSent++
  717. p.sequence++
  718. if p.sequence > 65535 {
  719. newUUID := uuid.New()
  720. p.trackerUUIDs = append(p.trackerUUIDs, newUUID)
  721. p.awaitingSequences[newUUID] = make(map[int]struct{})
  722. p.sequence = 0
  723. }
  724. break
  725. }
  726. return nil
  727. }
  728. func (p *Pinger) listen() (packetConn, error) {
  729. var (
  730. conn packetConn
  731. err error
  732. )
  733. conn, err = mpconn.listen()
  734. if err != nil {
  735. p.Stop()
  736. return nil, err
  737. }
  738. return conn, nil
  739. }
  740. func bytesToTime(b []byte) time.Time {
  741. var nsec int64
  742. for i := uint8(0); i < 8; i++ {
  743. nsec += int64(b[i]) << ((7 - i) * 8)
  744. }
  745. return time.Unix(nsec/1000000000, nsec%1000000000)
  746. }
  747. func isIPv4(ip net.IP) bool {
  748. return len(ip.To4()) == net.IPv4len
  749. }
  750. func timeToBytes(t time.Time) []byte {
  751. nsec := t.UnixNano()
  752. b := make([]byte, 8)
  753. for i := uint8(0); i < 8; i++ {
  754. b[i] = byte((nsec >> ((7 - i) * 8)) & 0xff)
  755. }
  756. return b
  757. }
  758. var seed = time.Now().UnixNano()
  759. // getSeed returns a goroutine-safe unique seed
  760. func getSeed() int64 {
  761. return atomic.AddInt64(&seed, 1)
  762. }