Skip to content

Commit aed9e15

Browse files
committed
add tcp-pinger
Signed-off-by: Jakub Sokołowski <[email protected]>
1 parent 89659f8 commit aed9e15

File tree

4 files changed

+159
-0
lines changed

4 files changed

+159
-0
lines changed

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,17 @@ require (
2727
github.com/mutecomm/go-sqlcipher v0.0.0-20190227152316-55dbde17881f
2828
github.com/okzk/sdnotify v0.0.0-20180710141335-d9becc38acbd
2929
github.com/pborman/uuid v1.2.0
30+
github.com/pkg/errors v0.8.1
3031
github.com/prometheus/client_golang v1.2.1
3132
github.com/russolsen/transit v0.0.0-20180705123435-0794b4c4505a
3233
github.com/status-im/migrate/v4 v4.6.2-status.2
3334
github.com/status-im/rendezvous v1.3.0
3435
github.com/status-im/status-protocol-go v0.4.5-0.20191107122821-775d17008edf
36+
github.com/status-im/tcp-shaker v0.0.0-20191112133506-73fe1d0a9410 // indirect
3537
github.com/status-im/whisper v1.5.2
3638
github.com/stretchr/testify v1.4.0
3739
github.com/syndtr/goleveldb v1.0.0
40+
github.com/tevino/tcp-shaker v0.0.0-20191112104505-00eab0aefc80
3841
go.uber.org/zap v1.10.0
3942
golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf
4043
golang.org/x/text v0.3.2

go.sum

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,8 @@ github.com/status-im/rendezvous v1.3.0 h1:7RK/MXXW+tlm0asKm1u7Qp7Yni6AO29a7j8+E4
578578
github.com/status-im/rendezvous v1.3.0/go.mod h1:+hzjuP+j/XzLPeF6E50b88pWOTLdTcwjvNYt+Gh1W1s=
579579
github.com/status-im/status-protocol-go v0.4.5-0.20191107122821-775d17008edf h1:1boOd5yMePhXxYei97Rm/hFF45alUpMl87ZAWvlSKtg=
580580
github.com/status-im/status-protocol-go v0.4.5-0.20191107122821-775d17008edf/go.mod h1:r8TgqNOpY+fGKkBfR9PldxSSaBN0EsEEY4a3WsIh9LY=
581+
github.com/status-im/tcp-shaker v0.0.0-20191112133506-73fe1d0a9410 h1:prSlfowPLBIx5IBKgJVlzg4b/Gd1PpRGCdRC/H9f4NA=
582+
github.com/status-im/tcp-shaker v0.0.0-20191112133506-73fe1d0a9410/go.mod h1:5bLqb2K4TvKZrrAY/c/d8Znmz11HnBRv2b03vkWGzzQ=
581583
github.com/status-im/whisper v1.5.2 h1:26NgiKusmPic38eQdtXnaY+iaQ/LuQ3Dh0kCGYT/Uxs=
582584
github.com/status-im/whisper v1.5.2/go.mod h1:emrOxzJme0k66QtbbQ2bdd3P8RCdLZ8sTD7SkwH1s2s=
583585
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE=
@@ -596,6 +598,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
596598
github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
597599
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
598600
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
601+
github.com/tevino/tcp-shaker v0.0.0-20191112104505-00eab0aefc80 h1:sb31WKdNlj2prwQwgjHHkayI3cKUlS+V4mmImc1GGpw=
602+
github.com/tevino/tcp-shaker v0.0.0-20191112104505-00eab0aefc80/go.mod h1:2F2ToSBehSmJcaQPE0lNhfH3xv+9Z2vH1a/d9fFw1nE=
599603
github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
600604
github.com/tyler-smith/go-bip39 v1.0.2 h1:+t3w+KwLXO6154GNJY+qUtIxLTmFjfUmpguQT1OlOT8=
601605
github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
@@ -716,6 +720,8 @@ golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7w
716720
golang.org/x/sys v0.0.0-20190927073244-c990c680b611/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
717721
golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/ntt0swNk5oYBziWeTCvY=
718722
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
723+
golang.org/x/sys v0.0.0-20191110163157-d32e6e3b99c4 h1:Hynbrlo6LbYI3H1IqXpkVDOcX/3HiPdhVEuyj5a59RM=
724+
golang.org/x/sys v0.0.0-20191110163157-d32e6e3b99c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
719725
golang.org/x/text v0.0.0-20171227012246-e19ae1496984/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
720726
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
721727
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

rtt/rtt.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package rtt
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"sync"
7+
"time"
8+
9+
errors "github.com/pkg/errors"
10+
tcp "github.com/tevino/tcp-shaker"
11+
)
12+
13+
type Result struct {
14+
Address string
15+
Latency int
16+
PingErr error
17+
}
18+
19+
func (cr *Result) String() string {
20+
return fmt.Sprintf(
21+
"Result{address: %s, latency: %d, error: %s}\n",
22+
cr.Address, cr.Latency, cr.PingErr)
23+
}
24+
25+
func runCheck(c *tcp.Checker, address string, ch chan<- Result, timeout time.Duration) {
26+
// mesaure RTT
27+
start := time.Now()
28+
// TCP Ping
29+
err := c.CheckAddr(address, timeout)
30+
// measure RTT
31+
elapsed := time.Since(start)
32+
latency := int(elapsed.Milliseconds())
33+
34+
if err != nil { // don't confuse users with valid latency values on error
35+
latency = -1
36+
if err == tcp.ErrTimeout {
37+
err = errors.Wrap(err, "tcp check timeout")
38+
} else {
39+
switch err.(type) {
40+
case tcp.ErrConnect:
41+
err = errors.Wrap(err, "unable to connect")
42+
default:
43+
err = errors.Wrap(err, "unknown error")
44+
}
45+
}
46+
}
47+
48+
// return results
49+
ch <- Result{
50+
Address: address,
51+
Latency: latency,
52+
PingErr: err,
53+
}
54+
}
55+
56+
func waitForResults(errCh <-chan error, resCh <-chan Result) (results []Result, err error) {
57+
for {
58+
select {
59+
case err = <-errCh:
60+
return nil, err
61+
case res, ok := <-resCh:
62+
if !ok {
63+
return
64+
}
65+
results = append(results, res)
66+
}
67+
}
68+
}
69+
70+
func CheckHosts(addresses []string, timeout time.Duration) ([]Result, error) {
71+
c := tcp.NewChecker()
72+
73+
// channel for receiving possible checking loop failure
74+
errCh := make(chan error, 1)
75+
// channel for returning results from concurrent checks
76+
resCh := make(chan Result, len(addresses))
77+
78+
// stop the checking loop when function exists
79+
ctx, stopChecker := context.WithCancel(context.Background())
80+
defer stopChecker()
81+
82+
// loop that queries Epoll and pipes events
83+
go func() {
84+
// TODO handle error from this?
85+
errCh <- c.CheckingLoop(ctx)
86+
}()
87+
88+
var wg sync.WaitGroup
89+
for i := 0; i < len(addresses); i++ {
90+
wg.Add(1)
91+
go func(address string) {
92+
defer wg.Done()
93+
runCheck(c, address, resCh, timeout)
94+
}(addresses[i])
95+
}
96+
// wait for all the routines to finish
97+
wg.Wait()
98+
// close the pipe
99+
close(resCh)
100+
101+
// wait for the results for all addresses
102+
return waitForResults(errCh, resCh)
103+
}

services/mailservers/tcp_ping.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package mailservers
2+
3+
import (
4+
"context"
5+
"time"
6+
7+
"github.com/status-im/status-go/rtt"
8+
)
9+
10+
type PingQuery struct {
11+
Addresses []string `json:"addresses"`
12+
TimeoutMs int `json:"timeoutMs"`
13+
}
14+
15+
type PingResult struct {
16+
Address string `json:"address"`
17+
Latency *int `json:"latency"`
18+
PingErr *string `json:"error"`
19+
}
20+
21+
func toPingResult(r rtt.Result) PingResult {
22+
var err *string = nil
23+
if r.PingErr != nil {
24+
tmpErr := r.PingErr.Error()
25+
err = &tmpErr
26+
}
27+
return PingResult{
28+
Address: r.Address,
29+
Latency: &r.Latency,
30+
PingErr: err,
31+
}
32+
}
33+
34+
func (a *API) Ping(ctx context.Context, pq PingQuery) ([]PingResult, error) {
35+
timeout := time.Duration(pq.TimeoutMs) * time.Millisecond
36+
// run the checks concurrently
37+
results, err := rtt.CheckHosts(pq.Addresses, timeout)
38+
if err != nil {
39+
return nil, err
40+
}
41+
// conver to json format
42+
jsonResults := make([]PingResult, len(results))
43+
for i := range results {
44+
jsonResults[i] = toPingResult(results[i])
45+
}
46+
return jsonResults, err
47+
}

0 commit comments

Comments
 (0)