Skip to content

Commit

Permalink
fix IP error logs on startup
Browse files Browse the repository at this point in the history
  • Loading branch information
jimjbrettj committed Feb 8, 2024
1 parent fd779bf commit ead02ab
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 5 deletions.
2 changes: 1 addition & 1 deletion dot/network/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
"time"

"github.com/ChainSafe/gossamer/dot/peerset"
"github.com/chyeh/pubip"
"github.com/ChainSafe/gossamer/internal/pubip"
"github.com/dgraph-io/ristretto"
badger "github.com/ipfs/go-ds-badger2"
"github.com/libp2p/go-libp2p"
Expand Down
3 changes: 1 addition & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ require (
github.com/btcsuite/btcd/btcutil v1.1.5
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce
github.com/centrifuge/go-substrate-rpc-client/v4 v4.1.0
github.com/chyeh/pubip v0.0.0-20170203095919-b7e679cf541c
github.com/cockroachdb/pebble v1.0.0
github.com/cosmos/go-bip39 v1.0.0
github.com/dgraph-io/badger/v2 v2.2007.4
Expand All @@ -23,6 +22,7 @@ require (
github.com/gorilla/websocket v1.5.1
github.com/gtank/merlin v0.1.1
github.com/ipfs/go-ds-badger2 v0.1.3
github.com/jpillora/backoff v1.0.0
github.com/jpillora/ipfilter v1.2.9
github.com/klauspost/compress v1.17.5
github.com/libp2p/go-libp2p v0.31.0
Expand Down Expand Up @@ -106,7 +106,6 @@ require (
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/jbenet/goprocess v0.1.4 // indirect
github.com/jcelliott/lumber v0.0.0-20160324203708-dd349441af25 // indirect
github.com/jpillora/backoff v1.0.0 // indirect
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
github.com/koron/go-ssdp v0.0.4 // indirect
github.com/kr/pretty v0.3.1 // indirect
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,6 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chyeh/pubip v0.0.0-20170203095919-b7e679cf541c h1:++BhWlmSX+n8m3O4gPfy3S4PTZ0TMzH6nelerBLPUng=
github.com/chyeh/pubip v0.0.0-20170203095919-b7e679cf541c/go.mod h1:C7ma6h458jTWT65mXC58L1Q6hnEtr0unur8cMc0UEXM=
github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
Expand Down
137 changes: 137 additions & 0 deletions internal/pubip/pubip.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// Copyright 2024 ChainSafe Systems (ON)
// SPDX-License-Identifier: LGPL-3.0-only

package pubip

import (
"errors"
"fmt"
"io"
"net"
"net/http"
"reflect"
"strconv"
"strings"
"time"

"github.com/jpillora/backoff"
)

// MaxTries is the maximum amount of tries to attempt to one service.
const MaxTries = 3

// APIURIs is the URIs of the services.
var APIURIs = []string{
"https://api.ipify.org",
"http://ipinfo.io/ip",
"http://checkip.amazonaws.com",
"http://whatismyip.akamai.com",
"http://ipv4.text.wtfismyip.com",
}

// Timeout sets the time limit of collecting results from different services.
var Timeout = 2 * time.Second

// GetIPBy queries an API to retrieve a `net.IP` of this machine's public IP
// address.
func GetIPBy(dest string) (net.IP, error) {
b := &backoff.Backoff{
Jitter: true,
}
client := &http.Client{}

req, err := http.NewRequest(http.MethodGet, dest, nil)
if err != nil {
return nil, err
}

for tries := 0; tries < MaxTries; tries++ {
resp, err := client.Do(req)
if err != nil {
d := b.Duration()
time.Sleep(d)
continue
}

defer resp.Body.Close() //nolint

body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

if resp.StatusCode != http.StatusOK {
return nil, errors.New(dest + " status code " + strconv.Itoa(resp.StatusCode) + ", body: " + string(body))
}

tb := strings.TrimSpace(string(body))
ip := net.ParseIP(tb)
if ip == nil {
return nil, errors.New("IP address not valid: " + tb)
}
return ip, nil
}

return nil, errors.New("Failed to reach " + dest)
}

func detailErr(err error, errs []error) error {
errStrs := []string{err.Error()}
for _, e := range errs {
errStrs = append(errStrs, e.Error())
}
j := strings.Join(errStrs, "\n")
return errors.New(j)
}

func validate(rs []net.IP) (net.IP, error) {
if rs == nil {
return nil, fmt.Errorf("failed to get any result from %d APIs", len(APIURIs))
}
if len(rs) < 3 {
return nil, fmt.Errorf("less than %d results from %d APIs", 3, len(APIURIs))
}
first := rs[0]
for i := 1; i < len(rs); i++ {
if !reflect.DeepEqual(first, rs[i]) {
return nil, fmt.Errorf("results are not identical: %s", rs)
}
}
return first, nil
}

func worker(d string, r chan<- net.IP, e chan<- error) {
ip, err := GetIPBy(d)
if err != nil {
e <- err
return
}
r <- ip
}

// Get queries several APIs to retrieve a `net.IP` of this machine's public IP
// address.
func Get() (net.IP, error) {
var results []net.IP
resultCh := make(chan net.IP, len(APIURIs))
var errs []error
errCh := make(chan error, len(APIURIs))

for _, d := range APIURIs {
go worker(d, resultCh, errCh)
}
for {
select {
case err := <-errCh:
errs = append(errs, err)
case r := <-resultCh:
results = append(results, r)
case <-time.After(Timeout):
r, err := validate(results)
if err != nil {
return nil, detailErr(err, errs)
}
return r, nil
}
}
}
35 changes: 35 additions & 0 deletions internal/pubip/pubip_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2024 ChainSafe Systems (ON)
// SPDX-License-Identifier: LGPL-3.0-only

package pubip

import (
"net"
"reflect"
"testing"
)

func TestIsValidate(t *testing.T) {
tests := []struct {
input []net.IP
expected net.IP
}{
{nil, nil},
{[]net.IP{}, nil},
{[]net.IP{net.ParseIP("192.168.1.1")}, nil},
{[]net.IP{net.ParseIP("192.168.1.1"), net.ParseIP("192.168.1.1")}, nil},
{[]net.IP{net.ParseIP("192.168.1.1"), net.ParseIP("192.168.1.1"), net.ParseIP("192.168.1.1")},
net.ParseIP("192.168.1.1")},
{[]net.IP{net.ParseIP("192.168.1.1"), net.ParseIP("192.168.1.2")}, nil},
{[]net.IP{net.ParseIP("192.168.1.1"), net.ParseIP("192.168.1.1"), net.ParseIP("192.168.1.2")},
nil},
}
for i, v := range tests {
actual, _ := validate(v.input)
expected := v.expected
t.Logf("Check case %d: %s(actual) == %s(expected)", i, actual, expected)
if !reflect.DeepEqual(actual, expected) {
t.Errorf("Error on case %d: %s(actual) != %s(expected)", i, actual, expected)
}
}
}

0 comments on commit ead02ab

Please sign in to comment.