diff --git a/x/examples/smart-proxy/main.go b/x/examples/smart-proxy/main.go index a229e5c06..257bfce36 100644 --- a/x/examples/smart-proxy/main.go +++ b/x/examples/smart-proxy/main.go @@ -112,7 +112,7 @@ func main() { } finder := smart.StrategyFinder{ LogWriter: debugLog.Writer(), - TestTimeout: 5 * time.Second, + TestTimeout: 60 * time.Second, StreamDialer: streamDialer, PacketDialer: packetDialer, } diff --git a/x/smart/stream_dialer.go b/x/smart/stream_dialer.go index 84b28e388..5ebbaad36 100644 --- a/x/smart/stream_dialer.go +++ b/x/smart/stream_dialer.go @@ -248,21 +248,65 @@ func (f *StrategyFinder) testDialer(ctx context.Context, dialer transport.Stream testAddr := net.JoinHostPort(testDomain, "443") f.logCtx(ctx, "🏃 running test: '%v' (domain: %v)\n", transportCfg, testDomain) - ctx, cancel := context.WithTimeout(ctx, f.TestTimeout) + testCtx, cancel := context.WithTimeout(ctx, f.TestTimeout) defer cancel() - testConn, err := dialer.DialStream(ctx, testAddr) - if err != nil { - f.logCtx(ctx, "🏁 failed to dial: '%v' (domain: %v), duration=%v, dial_error=%v ❌\n", transportCfg, testDomain, time.Since(startTime), err) - return err - } - tlsConn := tls.Client(testConn, &tls.Config{ServerName: testDomain}) - err = tlsConn.HandshakeContext(ctx) - tlsConn.Close() - if err != nil { - f.logCtx(ctx, "🏁 failed TLS handshake: '%v' (domain: %v), duration=%v, handshake=%v ❌\n", transportCfg, testDomain, time.Since(startTime), err) - return err + + timeoutChan := make(chan struct{}) + go func() { + <-testCtx.Done() + if errors.Is(testCtx.Err(), context.DeadlineExceeded) { + f.logCtx(ctx, "⏱️ dialer failure, test timed out: '%v' (domain: %v), duration=%v ❌\n", transportCfg, testDomain, time.Since(startTime)) + close(timeoutChan) + } + }() + + for i := 0; i < 10; i++ { + + testConn, err := dialer.DialStream(testCtx, testAddr) + if err != nil { + f.logCtx(testCtx, "🏁 failed to dial: '%v' (domain: %v), duration=%v, dial_error=%v ❌\n", transportCfg, testDomain, time.Since(startTime), err) + return err + } + + tlsConn := tls.Client(testConn, &tls.Config{ServerName: testDomain}) + err = tlsConn.HandshakeContext(testCtx) + if err != nil { + f.logCtx(testCtx, "🏁 failed TLS handshake: '%v' (domain: %v), duration=%v, handshake=%v ❌\n", transportCfg, testDomain, time.Since(startTime), err) + return err + } + f.logCtx(testCtx, "🏁 success: '%v' (domain: %v), duration=%v, status=ok ✅\n", transportCfg, testDomain, time.Since(startTime)) + + f.logCtx(testCtx, "🏃 running response test: (resource: HEAD %v/)\n", testDomain) + + f.logCtx(testCtx, "looping %v\n", i) + + request := "GET /image/69105246_605.webp HTTP/1.1\r\n" + + "Host: " + testDomain[:len(testDomain)-1] + "\r\n" + + "Connection: close\r\n" + + "\r\n" + _, err = tlsConn.Write([]byte(request)) + if err != nil { + f.logCtx(testCtx, "🏁 failed to write request error=%v ❌ \n", err) + return err + } + + response, err := io.ReadAll(tlsConn) + if err != nil { + f.logCtx(testCtx, "🏁 reading response error=%v ❌ \n", err) + return err + } + + tlsConn.Close() + + sizeKB := float64(len(response)) / 1024.0 + if sizeKB == 0 { + f.logCtx(testCtx, "🏁 response had no content ❌ \n") + } + + f.logCtx(testCtx, "🏁 success: '%v' (resource: HEAD %v/, response: %.2f KB), duration=%v, status=ok ✅\n", transportCfg, testDomain, sizeKB, time.Since(startTime)) + } - f.logCtx(ctx, "🏁 success: '%v' (domain: %v), duration=%v, status=ok ✅\n", transportCfg, testDomain, time.Since(startTime)) + } return nil }