From a6db1787f96670ec06104f022df15b2fbcf94154 Mon Sep 17 00:00:00 2001 From: jbhusson <jonah@elixxir.io> Date: Fri, 2 Sep 2022 14:43:19 -0400 Subject: [PATCH] Add separate isonline func for webconn --- connect/connection.go | 2 ++ connect/grpcConn.go | 20 +++++++++++++++ connect/host.go | 18 +------------- connect/webConn.go | 57 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 17 deletions(-) diff --git a/connect/connection.go b/connect/connection.go index c035d55..31b7464 100644 --- a/connect/connection.go +++ b/connect/connection.go @@ -4,6 +4,7 @@ import ( "git.xx.network/elixxir/grpc-web-go-client/grpcweb" jww "github.com/spf13/jwalterweatherman" "google.golang.org/grpc" + "time" ) const ( @@ -49,6 +50,7 @@ type Connection interface { // Close closes the underlying connection Close() error + IsOnline() (time.Duration, bool) clientConnHelpers } diff --git a/connect/grpcConn.go b/connect/grpcConn.go index 2dc9e6e..e9b0aba 100644 --- a/connect/grpcConn.go +++ b/connect/grpcConn.go @@ -8,6 +8,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/connectivity" "math" + "net" "sync/atomic" "time" ) @@ -148,3 +149,22 @@ func (gc *grpcConn) isAlive() bool { return state == connectivity.Idle || state == connectivity.Connecting || state == connectivity.Ready } + +func (gc *grpcConn) IsOnline() (time.Duration, bool) { + addr := gc.h.GetAddress() + start := time.Now() + conn, err := net.DialTimeout("tcp", addr, gc.h.params.PingTimeout) + if err != nil { + // If we cannot connect, mark the connection as failed + jww.DEBUG.Printf("Failed to verify connectivity for address %s", addr) + return 0, false + } + // Attempt to close the connection + if conn != nil { + errClose := conn.Close() + if errClose != nil { + jww.DEBUG.Printf("Failed to close connection for address %s", addr) + } + } + return time.Since(start), true +} diff --git a/connect/host.go b/connect/host.go index 681f27e..3c5ee9b 100644 --- a/connect/host.go +++ b/connect/host.go @@ -22,7 +22,6 @@ import ( "gitlab.com/xx_network/primitives/rateLimiting" "google.golang.org/grpc/credentials" "math" - "net" "strings" "sync" "sync/atomic" @@ -251,22 +250,7 @@ func (h *Host) conditionalDisconnect(count uint64) { // before the timeout by attempting to dial a tcp connection // Returns how long the ping took, and whether it was successful func (h *Host) IsOnline() (time.Duration, bool) { - addr := h.GetAddress() - start := time.Now() - conn, err := net.DialTimeout("tcp", addr, h.params.PingTimeout) - if err != nil { - // If we cannot connect, mark the connection as failed - jww.DEBUG.Printf("Failed to verify connectivity for address %s", addr) - return 0, false - } - // Attempt to close the connection - if conn != nil { - errClose := conn.Close() - if errClose != nil { - jww.DEBUG.Printf("Failed to close connection for address %s", addr) - } - } - return time.Since(start), true + return h.connection.IsOnline() } // send checks that the host has a connection and sends if it does. diff --git a/connect/webConn.go b/connect/webConn.go index c19d435..82bf288 100644 --- a/connect/webConn.go +++ b/connect/webConn.go @@ -1,11 +1,15 @@ package connect import ( + "crypto/tls" "fmt" "git.xx.network/elixxir/grpc-web-go-client/grpcweb" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" "google.golang.org/grpc" + "net/http" + "net/http/httptrace" + "strings" "time" ) @@ -163,3 +167,56 @@ func (wc *webConn) isAlive() bool { } return wc.connection.IsAlive() } + +func (wc *webConn) IsOnline() (time.Duration, bool) { + addr := wc.h.GetAddress() + start := time.Now() + tr := &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, + }, + } + client := http.Client{ + Transport: tr, + Timeout: wc.h.params.PingTimeout, + } + req, err := http.NewRequest("GET", addr, nil) + if err != nil { + fmt.Print("Failed to initiate request ", err) + } + + trace := &httptrace.ClientTrace{ + DNSDone: func(dnsInfo httptrace.DNSDoneInfo) { + fmt.Println("DNS Info: %+v\n", dnsInfo) + }, + GotConn: func(connInfo httptrace.GotConnInfo) { + fmt.Println("Got Conn: %+v\n", connInfo) + }, + GotFirstResponseByte: func() { + fmt.Println("Got first byte!") + }, + } + + // IMPORTANT - enables better HTTP(S) discovery, because many browsers block CORS by default. + req.Header.Add("js.fetch:mode", "no-cors") + fmt.Println("(GO request): ", fmt.Sprintf("%+v", req)) + + req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace)) + if _, err := client.Do(req); err != nil { + fmt.Println(err) + fmt.Println("(GO error): ", err.Error()) + + // TODO: Get more exception strings for major browsers + errString := strings.ToLower(err.Error()) + if strings.Contains(errString, "exceeded while awaiting") || + strings.Contains(errString, "ssl") || + strings.Contains(errString, "cors") || + strings.Contains(errString, "invalid") || + strings.Contains(errString, "protocol") { + return time.Since(start), true + } else { + return time.Since(start), false + } + } + return time.Since(start), true +} -- GitLab