152
vendor/github.com/status-im/status-go/services/mailservers/tcp_ping.go
generated
vendored
Normal file
152
vendor/github.com/status-im/status-go/services/mailservers/tcp_ping.go
generated
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
package mailservers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
multiaddr "github.com/multiformats/go-multiaddr"
|
||||
|
||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||
"github.com/ethereum/go-ethereum/p2p/enr"
|
||||
"github.com/status-im/status-go/rtt"
|
||||
)
|
||||
|
||||
type PingQuery struct {
|
||||
Addresses []string `json:"addresses"`
|
||||
TimeoutMs int `json:"timeoutMs"`
|
||||
}
|
||||
|
||||
type PingResult struct {
|
||||
Address string `json:"address"`
|
||||
RTTMs *int `json:"rttMs"`
|
||||
Err *string `json:"error"`
|
||||
}
|
||||
|
||||
type parseFn func(string) (string, error)
|
||||
|
||||
func (pr *PingResult) Update(rttMs int, err error) {
|
||||
if err != nil {
|
||||
errStr := err.Error()
|
||||
pr.Err = &errStr
|
||||
}
|
||||
if rttMs >= 0 {
|
||||
pr.RTTMs = &rttMs
|
||||
} else {
|
||||
pr.RTTMs = nil
|
||||
}
|
||||
}
|
||||
|
||||
func EnodeToAddr(node *enode.Node) (string, error) {
|
||||
var ip4 enr.IPv4
|
||||
err := node.Load(&ip4)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var tcp enr.TCP
|
||||
err = node.Load(&tcp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("%s:%d", net.IP(ip4).String(), tcp), nil
|
||||
}
|
||||
|
||||
func EnodeStringToAddr(enodeAddr string) (string, error) {
|
||||
node, err := enode.ParseV4(enodeAddr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return EnodeToAddr(node)
|
||||
}
|
||||
|
||||
func parse(addresses []string, fn parseFn) (map[string]*PingResult, []string) {
|
||||
results := make(map[string]*PingResult, len(addresses))
|
||||
var toPing []string
|
||||
|
||||
for i := range addresses {
|
||||
addr, err := fn(addresses[i])
|
||||
if err != nil {
|
||||
errStr := err.Error()
|
||||
results[addresses[i]] = &PingResult{Address: addresses[i], Err: &errStr}
|
||||
continue
|
||||
}
|
||||
results[addr] = &PingResult{Address: addresses[i]}
|
||||
toPing = append(toPing, addr)
|
||||
}
|
||||
return results, toPing
|
||||
}
|
||||
|
||||
func mapValues(m map[string]*PingResult) []*PingResult {
|
||||
rval := make([]*PingResult, 0, len(m))
|
||||
for _, value := range m {
|
||||
rval = append(rval, value)
|
||||
}
|
||||
return rval
|
||||
}
|
||||
|
||||
func DoPing(ctx context.Context, addresses []string, timeoutMs int, p parseFn) ([]*PingResult, error) {
|
||||
timeout := time.Duration(timeoutMs) * time.Millisecond
|
||||
|
||||
resultsMap, toPing := parse(addresses, p)
|
||||
|
||||
// run the checks concurrently
|
||||
results, err := rtt.CheckHosts(toPing, timeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// set ping results
|
||||
for i := range results {
|
||||
r := results[i]
|
||||
pr := resultsMap[r.Addr]
|
||||
if pr == nil {
|
||||
continue
|
||||
}
|
||||
pr.Update(r.RTTMs, r.Err)
|
||||
}
|
||||
|
||||
return mapValues(resultsMap), nil
|
||||
}
|
||||
|
||||
func (a *API) Ping(ctx context.Context, pq PingQuery) ([]*PingResult, error) {
|
||||
return DoPing(ctx, pq.Addresses, pq.TimeoutMs, EnodeStringToAddr)
|
||||
}
|
||||
|
||||
func MultiAddressToAddress(multiAddr string) (string, error) {
|
||||
|
||||
ma, err := multiaddr.NewMultiaddr(multiAddr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
dns4, err := ma.ValueForProtocol(multiaddr.P_DNS4)
|
||||
if err != nil && err != multiaddr.ErrProtocolNotFound {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ip4 := ""
|
||||
if dns4 != "" {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||
defer cancel()
|
||||
ip4, err = net.DefaultResolver.LookupCNAME(ctx, dns4)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
} else {
|
||||
ip4, err = ma.ValueForProtocol(multiaddr.P_IP4)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
tcp, err := ma.ValueForProtocol(multiaddr.P_TCP)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("%s:%s", ip4, tcp), nil
|
||||
}
|
||||
|
||||
func (a *API) MultiAddressPing(ctx context.Context, pq PingQuery) ([]*PingResult, error) {
|
||||
return DoPing(ctx, pq.Addresses, pq.TimeoutMs, MultiAddressToAddress)
|
||||
}
|
||||
Reference in New Issue
Block a user