From 4e70d11c0432d098b635dbaaae0ae396cf10eb1e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 06:41:38 +0000 Subject: [PATCH] build(deps): bump github.com/go-ping/ping Bumps [github.com/go-ping/ping](https://github.com/go-ping/ping) from 0.0.0-20201022122018-3977ed72668a to 1.2.0. - [Release notes](https://github.com/go-ping/ping/releases) - [Changelog](https://github.com/go-ping/ping/blob/master/.goreleaser.yml) - [Commits](https://github.com/go-ping/ping/commits/v1.2.0) --- updated-dependencies: - dependency-name: github.com/go-ping/ping dependency-version: 1.2.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- go.mod | 3 +- go.sum | 10 +- vendor/github.com/go-ping/ping/.golangci.yml | 4 + .../github.com/go-ping/ping/CONTRIBUTING.md | 44 ++ vendor/github.com/go-ping/ping/README.md | 57 +- vendor/github.com/go-ping/ping/logger.go | 53 ++ vendor/github.com/go-ping/ping/packetconn.go | 103 ++++ vendor/github.com/go-ping/ping/ping.go | 490 ++++++++++++------ vendor/github.com/go-ping/ping/utils_linux.go | 20 + vendor/github.com/go-ping/ping/utils_other.go | 17 + .../github.com/go-ping/ping/utils_windows.go | 25 + vendor/golang.org/x/sync/LICENSE | 27 + vendor/golang.org/x/sync/PATENTS | 22 + vendor/golang.org/x/sync/errgroup/errgroup.go | 135 +++++ vendor/golang.org/x/sync/errgroup/go120.go | 13 + .../golang.org/x/sync/errgroup/pre_go120.go | 14 + vendor/modules.txt | 5 +- 17 files changed, 856 insertions(+), 186 deletions(-) create mode 100644 vendor/github.com/go-ping/ping/CONTRIBUTING.md create mode 100644 vendor/github.com/go-ping/ping/logger.go create mode 100644 vendor/github.com/go-ping/ping/packetconn.go create mode 100644 vendor/github.com/go-ping/ping/utils_linux.go create mode 100644 vendor/github.com/go-ping/ping/utils_other.go create mode 100644 vendor/github.com/go-ping/ping/utils_windows.go create mode 100644 vendor/golang.org/x/sync/LICENSE create mode 100644 vendor/golang.org/x/sync/PATENTS create mode 100644 vendor/golang.org/x/sync/errgroup/errgroup.go create mode 100644 vendor/golang.org/x/sync/errgroup/go120.go create mode 100644 vendor/golang.org/x/sync/errgroup/pre_go120.go diff --git a/go.mod b/go.mod index 2a630ff38..641401a3c 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/container-storage-interface/spec v1.10.0 github.com/containerd/ttrpc v1.2.3 github.com/go-logr/logr v1.4.2 - github.com/go-ping/ping v0.0.0-20201022122018-3977ed72668a + github.com/go-ping/ping v1.2.0 github.com/golang/mock v1.6.0 github.com/google/go-cmp v0.6.0 github.com/jarcoal/httpmock v1.3.1 @@ -87,6 +87,7 @@ require ( go.uber.org/zap v1.27.0 // indirect golang.org/x/net v0.33.0 // indirect golang.org/x/oauth2 v0.27.0 // indirect + golang.org/x/sync v0.10.0 // indirect golang.org/x/term v0.27.0 // indirect golang.org/x/text v0.21.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7 // indirect diff --git a/go.sum b/go.sum index c4f4045af..e59468c6d 100644 --- a/go.sum +++ b/go.sum @@ -142,8 +142,8 @@ github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dp github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= -github.com/go-ping/ping v0.0.0-20201022122018-3977ed72668a h1:O9xspHB2yrvKfMQ1m6OQhqe37i5yvg0dXAYMuAjugmM= -github.com/go-ping/ping v0.0.0-20201022122018-3977ed72668a/go.mod h1:35JbSyV/BYqHwwRA6Zr1uVDm1637YlNOU61wI797NPI= +github.com/go-ping/ping v1.2.0 h1:vsJ8slZBZAXNCK4dPcI2PEE9eM9n9RbXbGouVQ/Y4yQ= +github.com/go-ping/ping v1.2.0/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= @@ -194,6 +194,7 @@ github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OI github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo= github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -423,10 +424,10 @@ golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= @@ -460,6 +461,8 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -475,6 +478,7 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/vendor/github.com/go-ping/ping/.golangci.yml b/vendor/github.com/go-ping/ping/.golangci.yml index eb311f814..904d008ce 100644 --- a/vendor/github.com/go-ping/ping/.golangci.yml +++ b/vendor/github.com/go-ping/ping/.golangci.yml @@ -4,3 +4,7 @@ issues: - path: _test.go linters: - errcheck +linters-settings: + staticcheck: + checks: + - "-SA1019" diff --git a/vendor/github.com/go-ping/ping/CONTRIBUTING.md b/vendor/github.com/go-ping/ping/CONTRIBUTING.md new file mode 100644 index 000000000..001998de1 --- /dev/null +++ b/vendor/github.com/go-ping/ping/CONTRIBUTING.md @@ -0,0 +1,44 @@ +# Contributing + +First off, thanks for taking the time to contribute! + +Remember that this is open source software so please consider the other people who will read your code. +Make it look nice for them, document your logic in comments and add or update the unit test cases. + +This library is used by various other projects, companies and individuals in live production environments so please discuss any breaking changes with us before making them. +Feel free to join us in the #go-ping channel of the [Gophers Slack](https://invite.slack.golangbridge.org/). + +## Pull Requests + +[Fork the repo on GitHub](https://github.com/go-ping/ping/fork) and clone it to your local machine. + +```bash +git clone https://github.com/YOUR_USERNAME/ping.git && cd ping +``` + +Here is a guide on [how to configure a remote repository](https://docs.github.com/en/free-pro-team@latest/github/collaborating-with-issues-and-pull-requests/configuring-a-remote-for-a-fork). + +Check out a new branch, make changes, run tests, commit & sign-off, then push branch to your fork. + +```bash +$ git checkout -b +# edit files +$ make style vet test +$ git add +$ git commit -s +$ git push +``` + +Open a [new pull request](https://github.com/go-ping/ping/compare) in the main `go-ping/ping` repository. +Please describe the purpose of your PR and remember link it to any related issues. + +*We may ask you to rebase your feature branch or squash the commits in order to keep the history clean.* + +## Development Guides + +- Run `make style vet test` before committing your changes. +- Document your logic in code comments. +- Add tests for bug fixes and new features. +- Use UNIX-style (LF) line endings. +- End every file with a single blank line. +- Use the UTF-8 character set. diff --git a/vendor/github.com/go-ping/ping/README.md b/vendor/github.com/go-ping/ping/README.md index 939b994eb..fd97e7fa4 100644 --- a/vendor/github.com/go-ping/ping/README.md +++ b/vendor/github.com/go-ping/ping/README.md @@ -1,20 +1,28 @@ +# Deprecated + +Due to lack of maintainers and access, this library is no longer maintained. +There is a new actively maintained fork: https://github.com/prometheus-community/pro-bing + # go-ping [![PkgGoDev](https://pkg.go.dev/badge/github.com/go-ping/ping)](https://pkg.go.dev/github.com/go-ping/ping) [![Circle CI](https://circleci.com/gh/go-ping/ping.svg?style=svg)](https://circleci.com/gh/go-ping/ping) A simple but powerful ICMP echo (ping) library for Go, inspired by -[go-fastping](https://github.com/tatsushid/go-fastping) +[go-fastping](https://github.com/tatsushid/go-fastping). Here is a very simple example that sends and receives three packets: ```go pinger, err := ping.NewPinger("www.google.com") if err != nil { - panic(err) + panic(err) } pinger.Count = 3 -pinger.Run() // blocks until finished -stats := pinger.Statistics() // get send/receive/rtt stats +err = pinger.Run() // Blocks until finished. +if err != nil { + panic(err) +} +stats := pinger.Statistics() // get send/receive/duplicate/rtt stats ``` Here is an example that emulates the traditional UNIX ping command: @@ -22,10 +30,10 @@ Here is an example that emulates the traditional UNIX ping command: ```go pinger, err := ping.NewPinger("www.google.com") if err != nil { - panic(err) + panic(err) } -// listen for ctrl-C signal +// Listen for Ctrl-C. c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt) go func() { @@ -35,27 +43,38 @@ go func() { }() pinger.OnRecv = func(pkt *ping.Packet) { - fmt.Printf("%d bytes from %s: icmp_seq=%d time=%v\n", - pkt.Nbytes, pkt.IPAddr, pkt.Seq, pkt.Rtt) + fmt.Printf("%d bytes from %s: icmp_seq=%d time=%v\n", + pkt.Nbytes, pkt.IPAddr, pkt.Seq, pkt.Rtt) +} + +pinger.OnDuplicateRecv = func(pkt *ping.Packet) { + fmt.Printf("%d bytes from %s: icmp_seq=%d time=%v ttl=%v (DUP!)\n", + pkt.Nbytes, pkt.IPAddr, pkt.Seq, pkt.Rtt, pkt.Ttl) } + pinger.OnFinish = func(stats *ping.Statistics) { - fmt.Printf("\n--- %s ping statistics ---\n", stats.Addr) - fmt.Printf("%d packets transmitted, %d packets received, %v%% packet loss\n", - stats.PacketsSent, stats.PacketsRecv, stats.PacketLoss) - fmt.Printf("round-trip min/avg/max/stddev = %v/%v/%v/%v\n", - stats.MinRtt, stats.AvgRtt, stats.MaxRtt, stats.StdDevRtt) + fmt.Printf("\n--- %s ping statistics ---\n", stats.Addr) + fmt.Printf("%d packets transmitted, %d packets received, %v%% packet loss\n", + stats.PacketsSent, stats.PacketsRecv, stats.PacketLoss) + fmt.Printf("round-trip min/avg/max/stddev = %v/%v/%v/%v\n", + stats.MinRtt, stats.AvgRtt, stats.MaxRtt, stats.StdDevRtt) } fmt.Printf("PING %s (%s):\n", pinger.Addr(), pinger.IPAddr()) -pinger.Run() +err = pinger.Run() +if err != nil { + panic(err) +} ``` It sends ICMP Echo Request packet(s) and waits for an Echo Reply in -response. If it receives a response, it calls the `OnRecv` callback. -When it's finished, it calls the `OnFinish` callback. +response. If it receives a response, it calls the `OnRecv` callback +unless a packet with that sequence number has already been received, +in which case it calls the `OnDuplicateRecv` callback. When it's +finished, it calls the `OnFinish` callback. For a full ping example, see -[cmd/ping/ping.go](https://github.com/go-ping/ping/blob/master/cmd/ping/ping.go) +[cmd/ping/ping.go](https://github.com/go-ping/ping/blob/master/cmd/ping/ping.go). ## Installation @@ -121,3 +140,7 @@ This repo was originally in the personal account of For support and help, you usually find us in the #go-ping channel of Gophers Slack. See https://invite.slack.golangbridge.org/ for an invite to the Gophers Slack org. + +## Contributing + +Refer to [CONTRIBUTING.md](https://github.com/go-ping/ping/blob/master/CONTRIBUTING.md) diff --git a/vendor/github.com/go-ping/ping/logger.go b/vendor/github.com/go-ping/ping/logger.go new file mode 100644 index 000000000..be3d4fa2a --- /dev/null +++ b/vendor/github.com/go-ping/ping/logger.go @@ -0,0 +1,53 @@ +package ping + +import "log" + +type Logger interface { + Fatalf(format string, v ...interface{}) + Errorf(format string, v ...interface{}) + Warnf(format string, v ...interface{}) + Infof(format string, v ...interface{}) + Debugf(format string, v ...interface{}) +} + +type StdLogger struct { + Logger *log.Logger +} + +func (l StdLogger) Fatalf(format string, v ...interface{}) { + l.Logger.Printf("FATAL: "+format, v...) +} + +func (l StdLogger) Errorf(format string, v ...interface{}) { + l.Logger.Printf("ERROR: "+format, v...) +} + +func (l StdLogger) Warnf(format string, v ...interface{}) { + l.Logger.Printf("WARN: "+format, v...) +} + +func (l StdLogger) Infof(format string, v ...interface{}) { + l.Logger.Printf("INFO: "+format, v...) +} + +func (l StdLogger) Debugf(format string, v ...interface{}) { + l.Logger.Printf("DEBUG: "+format, v...) +} + +type NoopLogger struct { +} + +func (l NoopLogger) Fatalf(format string, v ...interface{}) { +} + +func (l NoopLogger) Errorf(format string, v ...interface{}) { +} + +func (l NoopLogger) Warnf(format string, v ...interface{}) { +} + +func (l NoopLogger) Infof(format string, v ...interface{}) { +} + +func (l NoopLogger) Debugf(format string, v ...interface{}) { +} diff --git a/vendor/github.com/go-ping/ping/packetconn.go b/vendor/github.com/go-ping/ping/packetconn.go new file mode 100644 index 000000000..6a972f5af --- /dev/null +++ b/vendor/github.com/go-ping/ping/packetconn.go @@ -0,0 +1,103 @@ +package ping + +import ( + "net" + "runtime" + "time" + + "golang.org/x/net/icmp" + "golang.org/x/net/ipv4" + "golang.org/x/net/ipv6" +) + +type packetConn interface { + Close() error + ICMPRequestType() icmp.Type + ReadFrom(b []byte) (n int, ttl int, src net.Addr, err error) + SetFlagTTL() error + SetReadDeadline(t time.Time) error + WriteTo(b []byte, dst net.Addr) (int, error) + SetTTL(ttl int) +} + +type icmpConn struct { + c *icmp.PacketConn + ttl int +} + +func (c *icmpConn) Close() error { + return c.c.Close() +} + +func (c *icmpConn) SetTTL(ttl int) { + c.ttl = ttl +} + +func (c *icmpConn) SetReadDeadline(t time.Time) error { + return c.c.SetReadDeadline(t) +} + +func (c *icmpConn) WriteTo(b []byte, dst net.Addr) (int, error) { + if c.c.IPv6PacketConn() != nil { + if err := c.c.IPv6PacketConn().SetHopLimit(c.ttl); err != nil { + return 0, err + } + } + if c.c.IPv4PacketConn() != nil { + if err := c.c.IPv4PacketConn().SetTTL(c.ttl); err != nil { + return 0, err + } + } + + return c.c.WriteTo(b, dst) +} + +type icmpv4Conn struct { + icmpConn +} + +func (c *icmpv4Conn) SetFlagTTL() error { + err := c.c.IPv4PacketConn().SetControlMessage(ipv4.FlagTTL, true) + if runtime.GOOS == "windows" { + return nil + } + return err +} + +func (c *icmpv4Conn) ReadFrom(b []byte) (int, int, net.Addr, error) { + ttl := -1 + n, cm, src, err := c.c.IPv4PacketConn().ReadFrom(b) + if cm != nil { + ttl = cm.TTL + } + return n, ttl, src, err +} + +func (c icmpv4Conn) ICMPRequestType() icmp.Type { + return ipv4.ICMPTypeEcho +} + +type icmpV6Conn struct { + icmpConn +} + +func (c *icmpV6Conn) SetFlagTTL() error { + err := c.c.IPv6PacketConn().SetControlMessage(ipv6.FlagHopLimit, true) + if runtime.GOOS == "windows" { + return nil + } + return err +} + +func (c *icmpV6Conn) ReadFrom(b []byte) (int, int, net.Addr, error) { + ttl := -1 + n, cm, src, err := c.c.IPv6PacketConn().ReadFrom(b) + if cm != nil { + ttl = cm.HopLimit + } + return n, ttl, src, err +} + +func (c icmpV6Conn) ICMPRequestType() icmp.Type { + return ipv6.ICMPTypeEchoRequest +} diff --git a/vendor/github.com/go-ping/ping/ping.go b/vendor/github.com/go-ping/ping/ping.go index 3eab173aa..94f4244ea 100644 --- a/vendor/github.com/go-ping/ping/ping.go +++ b/vendor/github.com/go-ping/ping/ping.go @@ -1,25 +1,34 @@ -// Package ping is an ICMP ping library seeking to emulate the unix "ping" -// command. +// Package ping is a simple but powerful ICMP echo (ping) library. // -// Here is a very simple example that sends & receives 3 packets: +// Deprecated: This package is no longer maintained. +// +// Here is a very simple example that sends and receives three packets: // // pinger, err := ping.NewPinger("www.google.com") // if err != nil { // panic(err) // } -// // pinger.Count = 3 -// pinger.Run() // blocks until finished +// err = pinger.Run() // blocks until finished +// if err != nil { +// panic(err) +// } // stats := pinger.Statistics() // get send/receive/rtt stats // -// Here is an example that emulates the unix ping command: +// Here is an example that emulates the traditional UNIX ping command: // // pinger, err := ping.NewPinger("www.google.com") // if err != nil { -// fmt.Printf("ERROR: %s\n", err.Error()) -// return +// panic(err) // } -// +// // Listen for Ctrl-C. +// c := make(chan os.Signal, 1) +// signal.Notify(c, os.Interrupt) +// go func() { +// for _ = range c { +// pinger.Stop() +// } +// }() // pinger.OnRecv = func(pkt *ping.Packet) { // fmt.Printf("%d bytes from %s: icmp_seq=%d time=%v\n", // pkt.Nbytes, pkt.IPAddr, pkt.Seq, pkt.Rtt) @@ -31,13 +40,15 @@ // fmt.Printf("round-trip min/avg/max/stddev = %v/%v/%v/%v\n", // stats.MinRtt, stats.AvgRtt, stats.MaxRtt, stats.StdDevRtt) // } -// // fmt.Printf("PING %s (%s):\n", pinger.Addr(), pinger.IPAddr()) -// pinger.Run() +// err = pinger.Run() +// if err != nil { +// panic(err) +// } // -// It sends ICMP packet(s) and waits for a response. If it receives a response, -// it calls the "receive" callback. When it's finished, it calls the "finish" -// callback. +// It sends ICMP Echo Request packet(s) and waits for an Echo Reply in response. +// If it receives a response, it calls the OnRecv callback. When it's finished, +// it calls the OnFinish callback. // // For a full ping example, see "cmd/ping/ping.go". // @@ -45,25 +56,27 @@ package ping import ( "bytes" - "encoding/binary" "errors" "fmt" + "log" "math" "math/rand" "net" - "runtime" "sync" + "sync/atomic" "syscall" "time" + "github.com/google/uuid" "golang.org/x/net/icmp" "golang.org/x/net/ipv4" "golang.org/x/net/ipv6" + "golang.org/x/sync/errgroup" ) const ( timeSliceLength = 8 - trackerLength = 8 + trackerLength = len(uuid.UUID{}) protocolICMP = 1 protocolIPv6ICMP = 58 ) @@ -75,22 +88,28 @@ var ( // New returns a new Pinger struct pointer. func New(addr string) *Pinger { - r := rand.New(rand.NewSource(time.Now().UnixNano())) + r := rand.New(rand.NewSource(getSeed())) + firstUUID := uuid.New() + var firstSequence = map[uuid.UUID]map[int]struct{}{} + firstSequence[firstUUID] = make(map[int]struct{}) return &Pinger{ Count: -1, Interval: time.Second, RecordRtts: true, - Size: timeSliceLength, - Timeout: time.Second * 100000, - Tracker: r.Int63n(math.MaxInt64), - - addr: addr, - done: make(chan bool), - id: r.Intn(math.MaxInt16), - ipaddr: nil, - ipv4: false, - network: "ip", - protocol: "udp", + Size: timeSliceLength + trackerLength, + Timeout: time.Duration(math.MaxInt64), + + addr: addr, + done: make(chan interface{}), + id: r.Intn(math.MaxUint16), + trackerUUIDs: []uuid.UUID{firstUUID}, + ipaddr: nil, + ipv4: false, + network: "ip", + protocol: "udp", + awaitingSequences: firstSequence, + TTL: 64, + logger: StdLogger{Logger: log.New(log.Writer(), log.Prefix(), log.Flags())}, } } @@ -123,6 +142,17 @@ type Pinger struct { // Number of packets received PacketsRecv int + // Number of duplicate packets received + PacketsRecvDuplicates int + + // Round trip time statistics + minRtt time.Duration + maxRtt time.Duration + avgRtt time.Duration + stdDevRtt time.Duration + stddevm2 time.Duration + statsMu sync.RWMutex + // If true, keep a record of rtts of all received packets. // Set to false to avoid memory bloat for long running pings. RecordRtts bool @@ -130,6 +160,9 @@ type Pinger struct { // rtts is all of the Rtts rtts []time.Duration + // OnSetup is called when Pinger has finished setting up the listening socket + OnSetup func() + // OnSend is called when Pinger sends a packet OnSend func(*Packet) @@ -139,28 +172,41 @@ type Pinger struct { // OnFinish is called when Pinger exits OnFinish func(*Statistics) + // OnDuplicateRecv is called when a packet is received that has already been received. + OnDuplicateRecv func(*Packet) + // Size of packet being sent Size int - // Tracker: Used to uniquely identify packet when non-priviledged - Tracker int64 + // Tracker: Used to uniquely identify packets - Deprecated + Tracker uint64 // Source is the source IP address Source string - // stop chan bool - done chan bool + // Channel and mutex used to communicate when the Pinger should stop between goroutines. + done chan interface{} + lock sync.Mutex ipaddr *net.IPAddr addr string + // trackerUUIDs is the list of UUIDs being used for sending packets. + trackerUUIDs []uuid.UUID + ipv4 bool id int sequence int + // awaitingSequences are in-flight sequence numbers we keep track of to help remove duplicate receipts + awaitingSequences map[uuid.UUID]map[int]struct{} // network is one of "ip", "ip4", or "ip6". network string // protocol is "icmp" or "udp". protocol string + + logger Logger + + TTL int } type packet struct { @@ -188,6 +234,9 @@ type Packet struct { // TTL is the Time To Live on the packet. Ttl int + + // ID is the ICMP identifier. + ID int } // Statistics represent the stats of a currently running or finished @@ -199,6 +248,9 @@ type Statistics struct { // PacketsSent is the number of packets sent. PacketsSent int + // PacketsRecvDuplicates is the number of duplicate responses there were to a sent packet. + PacketsRecvDuplicates int + // PacketLoss is the percentage of packets lost. PacketLoss float64 @@ -225,6 +277,34 @@ type Statistics struct { StdDevRtt time.Duration } +func (p *Pinger) updateStatistics(pkt *Packet) { + p.statsMu.Lock() + defer p.statsMu.Unlock() + + p.PacketsRecv++ + if p.RecordRtts { + p.rtts = append(p.rtts, pkt.Rtt) + } + + if p.PacketsRecv == 1 || pkt.Rtt < p.minRtt { + p.minRtt = pkt.Rtt + } + + if pkt.Rtt > p.maxRtt { + p.maxRtt = pkt.Rtt + } + + pktCount := time.Duration(p.PacketsRecv) + // welford's online method for stddev + // https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Welford's_online_algorithm + delta := pkt.Rtt - p.avgRtt + p.avgRtt += delta / pktCount + delta2 := pkt.Rtt - p.avgRtt + p.stddevm2 += delta * delta2 + + p.stdDevRtt = time.Duration(math.Sqrt(float64(p.stddevm2 / pktCount))) +} + // SetIPAddr sets the ip address of the target host. func (p *Pinger) SetIPAddr(ipaddr *net.IPAddr) { p.ipv4 = isIPv4(ipaddr.IP) @@ -305,88 +385,138 @@ func (p *Pinger) Privileged() bool { return p.protocol == "icmp" } +// SetLogger sets the logger to be used to log events from the pinger. +func (p *Pinger) SetLogger(logger Logger) { + p.logger = logger +} + +// SetID sets the ICMP identifier. +func (p *Pinger) SetID(id int) { + p.id = id +} + +// ID returns the ICMP identifier. +func (p *Pinger) ID() int { + return p.id +} + // Run runs the pinger. This is a blocking function that will exit when it's // done. If Count or Interval are not specified, it will run continuously until // it is interrupted. func (p *Pinger) Run() error { - var conn *icmp.PacketConn + var conn packetConn var err error + if p.Size < timeSliceLength+trackerLength { + return fmt.Errorf("size %d is less than minimum required size %d", p.Size, timeSliceLength+trackerLength) + } if p.ipaddr == nil { err = p.Resolve() } if err != nil { return err } - if p.ipv4 { - if conn, err = p.listen(ipv4Proto[p.protocol]); err != nil { - return err - } - if err = conn.IPv4PacketConn().SetControlMessage(ipv4.FlagTTL, true); runtime.GOOS != "windows" && err != nil { - return err - } - } else { - if conn, err = p.listen(ipv6Proto[p.protocol]); err != nil { - return err - } - if err = conn.IPv6PacketConn().SetControlMessage(ipv6.FlagHopLimit, true); runtime.GOOS != "windows" && err != nil { - return err - } + if conn, err = p.listen(); err != nil { + return err } defer conn.Close() + + conn.SetTTL(p.TTL) + return p.run(conn) +} + +func (p *Pinger) run(conn packetConn) error { + if err := conn.SetFlagTTL(); err != nil { + return err + } defer p.finish() - var wg sync.WaitGroup recv := make(chan *packet, 5) defer close(recv) - wg.Add(1) - //nolint:errcheck - go p.recvICMP(conn, recv, &wg) - err = p.sendICMP(conn) - if err != nil { - return err + if handler := p.OnSetup; handler != nil { + handler() + } + + var g errgroup.Group + + g.Go(func() error { + defer p.Stop() + return p.recvICMP(conn, recv) + }) + + g.Go(func() error { + defer p.Stop() + return p.runLoop(conn, recv) + }) + + return g.Wait() +} + +func (p *Pinger) runLoop( + conn packetConn, + recvCh <-chan *packet, +) error { + logger := p.logger + if logger == nil { + logger = NoopLogger{} } timeout := time.NewTicker(p.Timeout) - defer timeout.Stop() interval := time.NewTicker(p.Interval) - defer interval.Stop() + defer func() { + interval.Stop() + timeout.Stop() + }() + + if err := p.sendICMP(conn); err != nil { + return err + } for { select { case <-p.done: - wg.Wait() return nil + case <-timeout.C: - close(p.done) - wg.Wait() return nil + + case r := <-recvCh: + err := p.processPacket(r) + if err != nil { + // FIXME: this logs as FATAL but continues + logger.Fatalf("processing received packet: %s", err) + } + case <-interval.C: if p.Count > 0 && p.PacketsSent >= p.Count { + interval.Stop() continue } - err = p.sendICMP(conn) - if err != nil { - // FIXME: this logs as FATAL but continues - fmt.Println("FATAL: ", err.Error()) - } - case r := <-recv: - err := p.processPacket(r) + err := p.sendICMP(conn) if err != nil { // FIXME: this logs as FATAL but continues - fmt.Println("FATAL: ", err.Error()) + logger.Fatalf("sending packet: %s", err) } } if p.Count > 0 && p.PacketsRecv >= p.Count { - close(p.done) - wg.Wait() return nil } } } func (p *Pinger) Stop() { - close(p.done) + p.lock.Lock() + defer p.lock.Unlock() + + open := true + select { + case _, open = <-p.done: + default: + } + + if open { + close(p.done) + } } func (p *Pinger) finish() { @@ -401,83 +531,73 @@ func (p *Pinger) finish() { // pinger is running or after it is finished. OnFinish calls this function to // get it's finished statistics. func (p *Pinger) Statistics() *Statistics { - loss := float64(p.PacketsSent-p.PacketsRecv) / float64(p.PacketsSent) * 100 - var min, max, total time.Duration - if len(p.rtts) > 0 { - min = p.rtts[0] - max = p.rtts[0] - } - for _, rtt := range p.rtts { - if rtt < min { - min = rtt - } - if rtt > max { - max = rtt - } - total += rtt - } + p.statsMu.RLock() + defer p.statsMu.RUnlock() + sent := p.PacketsSent + loss := float64(sent-p.PacketsRecv) / float64(sent) * 100 s := Statistics{ - PacketsSent: p.PacketsSent, - PacketsRecv: p.PacketsRecv, - PacketLoss: loss, - Rtts: p.rtts, - Addr: p.addr, - IPAddr: p.ipaddr, - MaxRtt: max, - MinRtt: min, - } - if len(p.rtts) > 0 { - s.AvgRtt = total / time.Duration(len(p.rtts)) - var sumsquares time.Duration - for _, rtt := range p.rtts { - sumsquares += (rtt - s.AvgRtt) * (rtt - s.AvgRtt) - } - s.StdDevRtt = time.Duration(math.Sqrt( - float64(sumsquares / time.Duration(len(p.rtts))))) + PacketsSent: sent, + PacketsRecv: p.PacketsRecv, + PacketsRecvDuplicates: p.PacketsRecvDuplicates, + PacketLoss: loss, + Rtts: p.rtts, + Addr: p.addr, + IPAddr: p.ipaddr, + MaxRtt: p.maxRtt, + MinRtt: p.minRtt, + AvgRtt: p.avgRtt, + StdDevRtt: p.stdDevRtt, } return &s } +type expBackoff struct { + baseDelay time.Duration + maxExp int64 + c int64 +} + +func (b *expBackoff) Get() time.Duration { + if b.c < b.maxExp { + b.c++ + } + + return b.baseDelay * time.Duration(rand.Int63n(1< 0 { t = append(t, bytes.Repeat([]byte{1}, remainSize)...) } @@ -582,7 +724,7 @@ func (p *Pinger) sendICMP(conn *icmp.PacketConn) error { } msg := &icmp.Message{ - Type: typ, + Type: conn.ICMPRequestType(), Code: 0, Body: body, } @@ -599,6 +741,7 @@ func (p *Pinger) sendICMP(conn *icmp.PacketConn) error { continue } } + return err } handler := p.OnSend if handler != nil { @@ -607,22 +750,44 @@ func (p *Pinger) sendICMP(conn *icmp.PacketConn) error { IPAddr: p.ipaddr, Addr: p.addr, Seq: p.sequence, + ID: p.id, } handler(outPkt) } - + // mark this sequence as in-flight + p.awaitingSequences[currentUUID][p.sequence] = struct{}{} p.PacketsSent++ p.sequence++ + if p.sequence > 65535 { + newUUID := uuid.New() + p.trackerUUIDs = append(p.trackerUUIDs, newUUID) + p.awaitingSequences[newUUID] = make(map[int]struct{}) + p.sequence = 0 + } break } return nil } -func (p *Pinger) listen(netProto string) (*icmp.PacketConn, error) { - conn, err := icmp.ListenPacket(netProto, p.Source) +func (p *Pinger) listen() (packetConn, error) { + var ( + conn packetConn + err error + ) + + if p.ipv4 { + var c icmpv4Conn + c.c, err = icmp.ListenPacket(ipv4Proto[p.protocol], p.Source) + conn = &c + } else { + var c icmpV6Conn + c.c, err = icmp.ListenPacket(ipv6Proto[p.protocol], p.Source) + conn = &c + } + if err != nil { - close(p.done) + p.Stop() return nil, err } return conn, nil @@ -649,12 +814,9 @@ func timeToBytes(t time.Time) []byte { return b } -func bytesToInt(b []byte) int64 { - return int64(binary.BigEndian.Uint64(b)) -} +var seed int64 = time.Now().UnixNano() -func intToBytes(tracker int64) []byte { - b := make([]byte, 8) - binary.BigEndian.PutUint64(b, uint64(tracker)) - return b +// getSeed returns a goroutine-safe unique seed +func getSeed() int64 { + return atomic.AddInt64(&seed, 1) } diff --git a/vendor/github.com/go-ping/ping/utils_linux.go b/vendor/github.com/go-ping/ping/utils_linux.go new file mode 100644 index 000000000..a3e4e8c87 --- /dev/null +++ b/vendor/github.com/go-ping/ping/utils_linux.go @@ -0,0 +1,20 @@ +//go:build linux +// +build linux + +package ping + +// Returns the length of an ICMP message. +func (p *Pinger) getMessageLength() int { + return p.Size + 8 +} + +// Attempts to match the ID of an ICMP packet. +func (p *Pinger) matchID(ID int) bool { + // On Linux we can only match ID if we are privileged. + if p.protocol == "icmp" { + if ID != p.id { + return false + } + } + return true +} diff --git a/vendor/github.com/go-ping/ping/utils_other.go b/vendor/github.com/go-ping/ping/utils_other.go new file mode 100644 index 000000000..d229c41a9 --- /dev/null +++ b/vendor/github.com/go-ping/ping/utils_other.go @@ -0,0 +1,17 @@ +//go:build !linux && !windows +// +build !linux,!windows + +package ping + +// Returns the length of an ICMP message. +func (p *Pinger) getMessageLength() int { + return p.Size + 8 +} + +// Attempts to match the ID of an ICMP packet. +func (p *Pinger) matchID(ID int) bool { + if ID != p.id { + return false + } + return true +} diff --git a/vendor/github.com/go-ping/ping/utils_windows.go b/vendor/github.com/go-ping/ping/utils_windows.go new file mode 100644 index 000000000..37ab8b525 --- /dev/null +++ b/vendor/github.com/go-ping/ping/utils_windows.go @@ -0,0 +1,25 @@ +//go:build windows +// +build windows + +package ping + +import ( + "golang.org/x/net/ipv4" + "golang.org/x/net/ipv6" +) + +// Returns the length of an ICMP message, plus the IP packet header. +func (p *Pinger) getMessageLength() int { + if p.ipv4 { + return p.Size + 8 + ipv4.HeaderLen + } + return p.Size + 8 + ipv6.HeaderLen +} + +// Attempts to match the ID of an ICMP packet. +func (p *Pinger) matchID(ID int) bool { + if ID != p.id { + return false + } + return true +} diff --git a/vendor/golang.org/x/sync/LICENSE b/vendor/golang.org/x/sync/LICENSE new file mode 100644 index 000000000..2a7cf70da --- /dev/null +++ b/vendor/golang.org/x/sync/LICENSE @@ -0,0 +1,27 @@ +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/sync/PATENTS b/vendor/golang.org/x/sync/PATENTS new file mode 100644 index 000000000..733099041 --- /dev/null +++ b/vendor/golang.org/x/sync/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) +patent license to make, have made, use, offer to sell, sell, import, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/sync/errgroup/errgroup.go b/vendor/golang.org/x/sync/errgroup/errgroup.go new file mode 100644 index 000000000..948a3ee63 --- /dev/null +++ b/vendor/golang.org/x/sync/errgroup/errgroup.go @@ -0,0 +1,135 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package errgroup provides synchronization, error propagation, and Context +// cancelation for groups of goroutines working on subtasks of a common task. +// +// [errgroup.Group] is related to [sync.WaitGroup] but adds handling of tasks +// returning errors. +package errgroup + +import ( + "context" + "fmt" + "sync" +) + +type token struct{} + +// A Group is a collection of goroutines working on subtasks that are part of +// the same overall task. +// +// A zero Group is valid, has no limit on the number of active goroutines, +// and does not cancel on error. +type Group struct { + cancel func(error) + + wg sync.WaitGroup + + sem chan token + + errOnce sync.Once + err error +} + +func (g *Group) done() { + if g.sem != nil { + <-g.sem + } + g.wg.Done() +} + +// WithContext returns a new Group and an associated Context derived from ctx. +// +// The derived Context is canceled the first time a function passed to Go +// returns a non-nil error or the first time Wait returns, whichever occurs +// first. +func WithContext(ctx context.Context) (*Group, context.Context) { + ctx, cancel := withCancelCause(ctx) + return &Group{cancel: cancel}, ctx +} + +// Wait blocks until all function calls from the Go method have returned, then +// returns the first non-nil error (if any) from them. +func (g *Group) Wait() error { + g.wg.Wait() + if g.cancel != nil { + g.cancel(g.err) + } + return g.err +} + +// Go calls the given function in a new goroutine. +// It blocks until the new goroutine can be added without the number of +// active goroutines in the group exceeding the configured limit. +// +// The first call to return a non-nil error cancels the group's context, if the +// group was created by calling WithContext. The error will be returned by Wait. +func (g *Group) Go(f func() error) { + if g.sem != nil { + g.sem <- token{} + } + + g.wg.Add(1) + go func() { + defer g.done() + + if err := f(); err != nil { + g.errOnce.Do(func() { + g.err = err + if g.cancel != nil { + g.cancel(g.err) + } + }) + } + }() +} + +// TryGo calls the given function in a new goroutine only if the number of +// active goroutines in the group is currently below the configured limit. +// +// The return value reports whether the goroutine was started. +func (g *Group) TryGo(f func() error) bool { + if g.sem != nil { + select { + case g.sem <- token{}: + // Note: this allows barging iff channels in general allow barging. + default: + return false + } + } + + g.wg.Add(1) + go func() { + defer g.done() + + if err := f(); err != nil { + g.errOnce.Do(func() { + g.err = err + if g.cancel != nil { + g.cancel(g.err) + } + }) + } + }() + return true +} + +// SetLimit limits the number of active goroutines in this group to at most n. +// A negative value indicates no limit. +// +// Any subsequent call to the Go method will block until it can add an active +// goroutine without exceeding the configured limit. +// +// The limit must not be modified while any goroutines in the group are active. +func (g *Group) SetLimit(n int) { + if n < 0 { + g.sem = nil + return + } + if len(g.sem) != 0 { + panic(fmt.Errorf("errgroup: modify limit while %v goroutines in the group are still active", len(g.sem))) + } + g.sem = make(chan token, n) +} diff --git a/vendor/golang.org/x/sync/errgroup/go120.go b/vendor/golang.org/x/sync/errgroup/go120.go new file mode 100644 index 000000000..f93c740b6 --- /dev/null +++ b/vendor/golang.org/x/sync/errgroup/go120.go @@ -0,0 +1,13 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.20 + +package errgroup + +import "context" + +func withCancelCause(parent context.Context) (context.Context, func(error)) { + return context.WithCancelCause(parent) +} diff --git a/vendor/golang.org/x/sync/errgroup/pre_go120.go b/vendor/golang.org/x/sync/errgroup/pre_go120.go new file mode 100644 index 000000000..88ce33434 --- /dev/null +++ b/vendor/golang.org/x/sync/errgroup/pre_go120.go @@ -0,0 +1,14 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !go1.20 + +package errgroup + +import "context" + +func withCancelCause(parent context.Context) (context.Context, func(error)) { + ctx, cancel := context.WithCancel(parent) + return ctx, func(error) { cancel() } +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 13a16303e..033da3c45 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -109,7 +109,7 @@ github.com/go-openapi/jsonreference/internal # github.com/go-openapi/swag v0.23.0 ## explicit; go 1.20 github.com/go-openapi/swag -# github.com/go-ping/ping v0.0.0-20201022122018-3977ed72668a +# github.com/go-ping/ping v1.2.0 ## explicit; go 1.14 github.com/go-ping/ping # github.com/gogo/protobuf v1.3.2 @@ -299,6 +299,9 @@ golang.org/x/net/trace ## explicit; go 1.23.0 golang.org/x/oauth2 golang.org/x/oauth2/internal +# golang.org/x/sync v0.10.0 +## explicit; go 1.18 +golang.org/x/sync/errgroup # golang.org/x/sys v0.30.0 ## explicit; go 1.18 golang.org/x/sys/plan9