diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index a198643..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: Release -permissions: - contents: write - -on: - release: - types: [ created ] - -jobs: - compile: - strategy: - fail-fast: false - matrix: - os: [ linux, darwin, windows ] - arch: [ amd64, 386 ] - exclude: - - os: darwin - arch: 386 - name: Release - ${{matrix.os}}-${{matrix.arch}} - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@v4 - - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version: "1.20" - - - name: compile - run: | - GOOS=${{matrix.os}} GOARCH=${{matrix.arch}} make - - - name: Upload release assets - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ github.event.release.upload_url }} - asset_name: pinger-${{github.event.release.tag_name}}-${{matrix.os}}-${{matrix.arch}} - asset_path: pinger - asset_content_type: application/octal-stream diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 055d997..0000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Test - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -jobs: - - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version: '1.20' - - - name: Fmt - run: go fmt $(go list ./... | grep -v /vendor/) - - name: Vet - run: go vet $(go list ./... | grep -v /vendor/) - - name: Test - run: go test -race $(go list ./... | grep -v /vendor/) - diff --git a/.gitignore b/.gitignore index f8b2950..adb36c8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ -pinger -*.exe +*.exe \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..69fb79a --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,46 @@ +# This file is a template, and might need editing before it works on your project. +# You can copy and paste this template into a new `.gitlab-ci.yml` file. +# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword. +# +# To contribute improvements to CI/CD templates, please follow the Development guide at: +# https://docs.gitlab.com/ee/development/cicd/templates.html +# This specific template is located at: +# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Go.gitlab-ci.yml + +stages: + - test + - build + - release + +format: + image: golang:latest + stage: test + script: + - go fmt $(go list ./... | grep -v /vendor/) + - go vet $(go list ./... | grep -v /vendor/) + - go test -race $(go list ./... | grep -v /vendor/) + +compile: + image: golang:latest + stage: build + script: + - mkdir -p bin + - GOOS=windows GOARCH=386 go build -o bin/pinger-32.exe ./... + - GOOS=windows GOARCH=amd64 go build -o bin/pinger-x64.exe ./... + - GOOS=linux GOARCH=386 go build -o bin/pinger-linux-x86 ./... + - GOOS=linux GOARCH=amd64 go build -o bin/pinger-linux-x64 ./... + artifacts: + paths: + - bin + expire_in: 1 week + +upload: + stage: release + image: curlimages/curl:latest + rules: + - if: $CI_COMMIT_TAG + script: + - 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file bin/pinger-32.exe "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/release/${CI_COMMIT_TAG}/pinger-32.exe"' + - 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file bin/pinger-x64.exe "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/release/${CI_COMMIT_TAG}/pinger-x64.exe"' + - 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file bin/pinger-linux-x86 "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/release/${CI_COMMIT_TAG}/pinger-linux-x86"' + - 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file bin/pinger-linux-x64 "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/release/${CI_COMMIT_TAG}/pinger-linux-x64"' \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 965f691..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2023-2026 Henrik Hautakoski - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/Makefile b/Makefile deleted file mode 100644 index c01b168..0000000 --- a/Makefile +++ /dev/null @@ -1,5 +0,0 @@ - -GO=go - -pinger : main.go - $(GO) build -o $@ $^ diff --git a/README.md b/README.md deleted file mode 100644 index 71dd48d..0000000 --- a/README.md +++ /dev/null @@ -1,58 +0,0 @@ -# Pinger - -**Pinger** is a lightweight, high-performance network utility written in Go. -It enables users to send ICMP echo requests (pings) to specified hosts, facilitating network diagnostics and monitoring. - -## Features - -* Send ICMP echo requests to specified hosts. -* Measure round-trip time (RTT) for each ping. -* Support for both IPv4 and IPv6 addresses. -* Configurable number of ping attempts and intervals. -* Lightweight and efficient, suitable for scripting and automation. - -## Installation - -### Prerequisites - -* Go (version 1.20 or later) installed on your system. -* make - -### Steps - -1. Clone the repository: - -```bash -git clone https://github.com/pnx/pinger.git -cd pinger -``` - -2. Build the application: - -```bash -make -``` - -## Usage - -See `./pinger -h` - -### Example - -```bash -./pinger --udp -t 30s example.com -``` - -This command sends UDP echo requests to example.com, stopping after 30 seconds - -```bash -./pinger -c 8 -i 1s example.com -``` - -This command sends 8 ICMP echo requests to example.com, with a 1-second interval between pings. - -NOTE: this requires root privileges - -## License - -This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. diff --git a/go.mod b/go.mod index d240580..2479bd0 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module pinger -go 1.20 +go 1.19 require ( github.com/pborman/getopt/v2 v2.1.0 @@ -9,7 +9,7 @@ require ( require ( github.com/google/uuid v1.3.0 // indirect - golang.org/x/net v0.8.0 // indirect - golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.6.0 // indirect + golang.org/x/net v0.5.0 // indirect + golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect + golang.org/x/sys v0.4.0 // indirect ) diff --git a/go.sum b/go.sum index 8b4cd58..d532404 100644 --- a/go.sum +++ b/go.sum @@ -4,9 +4,9 @@ github.com/pborman/getopt/v2 v2.1.0 h1:eNfR+r+dWLdWmV8g5OlpyrTYHkhVNxHBdN2cCrJmO github.com/pborman/getopt/v2 v2.1.0/go.mod h1:4NtW75ny4eBw9fO1bhtNdYTlZKYX5/tBLtsOpwKIKd0= github.com/prometheus-community/pro-bing v0.1.0 h1:zjzLGhfNPP0bP1OlzGB+SJcguOViw7df12LPg2vUJh8= github.com/prometheus-community/pro-bing v0.1.0/go.mod h1:BpWlHurD9flHtzq8wrh8QGWYz9ka9z9ZJAyOel8ej58= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f h1:Ax0t5p6N38Ga0dThY21weqDEyz2oklo4IvDkpigvkD8= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/main.go b/main.go index d3f7f20..e347c43 100644 --- a/main.go +++ b/main.go @@ -8,11 +8,13 @@ import ( "time" "github.com/pborman/getopt/v2" - probing "github.com/prometheus-community/pro-bing" + "github.com/prometheus-community/pro-bing" ) // printStats prints statistics from a ping. -func printStats(stats *probing.Statistics) { +func printStats(pinger *probing.Pinger) { + stats := pinger.Statistics() + fmt.Printf("%d packets transmitted, %d packets received, %.2f%% packet loss\n", stats.PacketsSent, stats.PacketsRecv, stats.PacketLoss) @@ -20,9 +22,8 @@ func printStats(stats *probing.Statistics) { stats.MinRtt, stats.AvgRtt, stats.MaxRtt, stats.StdDevRtt) } -func eventLoop(pinger *probing.Pinger, ticker *time.Ticker) { - defer ticker.Stop() - defer pinger.Stop() +func eventLoop(pinger *probing.Pinger) { + ticker := time.NewTicker(time.Second * 4) // Setup signals on term and interrupt. sig := make(chan os.Signal, 1) @@ -31,12 +32,13 @@ func eventLoop(pinger *probing.Pinger, ticker *time.Ticker) { for { select { // Got signal. stop pinger and exit goroutine - case s := <-sig: - fmt.Printf("Recived signal: %s, exiting.\n", s) + case <-sig: + ticker.Stop() + pinger.Stop() return // Ticker ticks. print stats. case <-ticker.C: - printStats(pinger.Statistics()) + printStats(pinger) } } } @@ -49,7 +51,6 @@ func main() { count := getopt.IntLong("count", 'c', 0, "Stop after this many packages has been sent (and received). If this option is not specified, pinger will operate until interrupted.") timeout := getopt.DurationLong("timeout", 't', 0, "Exit the program after this time is reached, regardless of how many packets have been received.") interval := getopt.DurationLong("interval", 'i', time.Second*2, "Wait time between each packet send") - statsInterval := getopt.DurationLong("stats-interval", 0, time.Second*4, "How often stats should be printed to the console.") proto_udp := getopt.BoolLong("udp", 0, "Send UDP ping instead of a raw IMCP ping, IMCP required super-user privileges") record_rtt := getopt.BoolLong("rtt", 0, "Keep a record of rtts of all received packets.") @@ -57,7 +58,7 @@ func main() { getopt.Parse() if *version { - fmt.Println("Version 0.0.4") + fmt.Println("Version 0.0.2") os.Exit(0) } @@ -78,17 +79,17 @@ func main() { pinger.Source = *source pinger.Count = *count pinger.RecordRtts = *record_rtt - pinger.OnFinish = printStats if timeout != nil && *timeout > 0 { pinger.Timeout = *timeout } // Enter event loop in another goroutine. - go eventLoop(pinger, time.NewTicker(*statsInterval)) + go eventLoop(pinger) // Run pinger in main thread. fmt.Println("PING", pinger.Addr()) if err = pinger.Run(); err != nil { fmt.Println("Error:", err) + return } }