feat: Waku v2 bridge

Issue #12610
This commit is contained in:
Michal Iskierko
2023-11-12 13:29:38 +01:00
parent 56e7bd01ca
commit 6d31343205
6716 changed files with 1982502 additions and 5891 deletions
+67
View File
@@ -0,0 +1,67 @@
# Description
This module is used by the Status app to select mailservers based on their RTT(Round Trip Time).
It is exposed via the JSON RPC endpoint in the [`services/mailservers/tcp_ping.go`](../services/mailservers/tcp_ping.go) file.
# Usage
The simplest way to use the `mailserver_Ping` RPC command is using `curl`.
The call takes one struct argument which contains two attributes:
* `addresses` - A list of `enode` addresses to ping.
* `timeoutMs` - Call timeout given in milliseconds.
The return value consists of a list of objects representing a result for each mailserver, each containing following attributes:
* `address` - The `enode` address of given mailserver.
* `rttMs` - Round Trip Time given in milliseconds. Set to `null` in case of an error.`
* `error` - A text of error that caused the ping failure.
# Example
```bash
$ cat >payload.json <<EOL
{
"jsonrpc": "2.0",
"method": "mailservers_ping",
"params": [
{
"addresses": [
"enode://c42f368a23fa98ee546fd247220759062323249ef657d26d357a777443aec04db1b29a3a22ef3e7c548e18493ddaf51a31b0aed6079bd6ebe5ae838fcfaf3a49@206.189.243.162:443",
"enode://c42f368a23fa98ee546fd247220759062323249ef657d26d357a777443aec04db1b29a3a22ef3e7c548e18493ddaf51a31b0aed6079bd6ebe5ae838fcfaf3a49@206.189.243.162:999"
],
"timeoutMs": 500
}
],
"id": 1
}
EOL
$ curl -s localhost:8545 -H 'content-type: application/json' -d @payload.json
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"address": "enode://c42f368a23fa98ee546fd247220759062323249ef657d26d357a777443aec04db1b29a3a22ef3e7c548e18493ddaf51a31b0aed6079bd6ebe5ae838fcfaf3a49@206.189.243.162:443",
"rttMs": 31,
"error": null
},
{
"address": "enode://c42f368a23fa98ee546fd247220759062323249ef657d26d357a777443aec04db1b29a3a22ef3e7c548e18493ddaf51a31b0aed6079bd6ebe5ae838fcfaf3a49@206.189.243.162:999",
"rttMs": null,
"error": "tcp check timeout: I/O timeout"
}
]
}
```
# Links
* https://github.com/status-im/status-mobile/issues/9394
* https://github.com/status-im/status-go/pull/1672
* https://github.com/status-im/tcp-shaker
+98
View File
@@ -0,0 +1,98 @@
package rtt
import (
"context"
"sync"
"time"
errors "github.com/pkg/errors"
tcp "github.com/status-im/tcp-shaker"
)
type Result struct {
Addr string
RTTMs int
Err error
}
// timeoutError indicates an error due to TCP connection timeout.
// tcp-shaker returns an error implementing this interface in such a case.
type timeoutError interface {
Timeout() bool
}
func runCheck(c *tcp.Checker, address string, timeout time.Duration) Result {
// mesaure RTT
start := time.Now()
// TCP Ping
err := c.CheckAddr(address, timeout)
// measure RTT
elapsed := time.Since(start)
latency := int(elapsed.Nanoseconds() / 1e6)
if err != nil { // don't confuse users with valid latency values on error
latency = -1
switch err.(type) {
case timeoutError:
err = errors.Wrap(err, "tcp check timeout")
case tcp.ErrConnect:
err = errors.Wrap(err, "unable to connect")
}
}
return Result{
Addr: address,
RTTMs: latency,
Err: err,
}
}
func waitForResults(errCh <-chan error, resCh <-chan Result) (results []Result, err error) {
for {
select {
case err = <-errCh:
return nil, err
case res, ok := <-resCh:
if !ok {
return
}
results = append(results, res)
}
}
}
func CheckHosts(addresses []string, timeout time.Duration) ([]Result, error) {
c := tcp.NewChecker()
// channel for receiving possible checking loop failure
errCh := make(chan error, 1)
// stop the checking loop when function exists
ctx, stopChecker := context.WithCancel(context.Background())
defer stopChecker()
// loop that queries Epoll and pipes events to CheckAddr() calls
go func() {
errCh <- c.CheckingLoop(ctx)
}()
// wait for CheckingLoop to prepare the epoll/kqueue
<-c.WaitReady()
// channel for returning results from concurrent checks
resCh := make(chan Result, len(addresses))
var wg sync.WaitGroup
for i := 0; i < len(addresses); i++ {
wg.Add(1)
go func(address string, resCh chan<- Result) {
defer wg.Done()
resCh <- runCheck(c, address, timeout)
}(addresses[i], resCh)
}
// wait for all the routines to finish before closing results channel
wg.Wait()
close(resCh)
// wait for the results for all addresses or a checking loop error
return waitForResults(errCh, resCh)
}