MCPcopy Create free account
hub / github.com/Hidden-Node/GooseRelayVPN-AndroidClient / newFrontedClient

Function newFrontedClient

internal/carrier/fronting.go:349–407  ·  view source on GitHub ↗

newFrontedClient builds a single *http.Client that dials googleIP and presents sniHost in the TLS handshake.

(googleIP, sniHost string, pollTimeout time.Duration, sessionCache tls.ClientSessionCache)

Source from the content-addressed store, hash-verified

347// newFrontedClient builds a single *http.Client that dials googleIP and
348// presents sniHost in the TLS handshake.
349func newFrontedClient(googleIP, sniHost string, pollTimeout time.Duration, sessionCache tls.ClientSessionCache) *http.Client {
350 dialer := &net.Dialer{Timeout: 30 * time.Second, KeepAlive: 30 * time.Second}
351
352 transport := &http.Transport{
353 DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
354 if googleIP != "" {
355 return dialer.DialContext(ctx, "tcp", googleIP)
356 }
357 return dialer.DialContext(ctx, network, addr)
358 },
359 TLSClientConfig: &tls.Config{
360 ServerName: sniHost,
361 // Pin TLS 1.3 floor to prevent downgrade; Go's default minimum is 1.2.
362 MinVersion: tls.VersionTLS13,
363 // Enable TLS session resumption tickets so reconnects after
364 // idle timeout (and the prewarm dial in NewFrontedClients) can
365 // skip a full handshake round-trip.
366 ClientSessionCache: sessionCache,
367 // Pin ALPN so the resumed session matches the prewarm dial.
368 // (The TLS 1.3 resumption ticket is bound to ALPN; mismatched
369 // NextProtos causes the server to fall back to a full handshake.)
370 NextProtos: []string{"h2", "http/1.1"},
371 },
372 ForceAttemptHTTP2: true,
373 MaxIdleConns: 16,
374 // Default MaxIdleConnsPerHost is 2, which forces idle h1 conns to be
375 // recycled between poll workers when ALPN downgrades or the server
376 // closes h2 streams. Pin it to roughly the worker count per endpoint
377 // so each worker can keep its own warm conn.
378 MaxIdleConnsPerHost: workersPerEndpoint * 2,
379 // Larger HTTP read/write buffers cut syscall count on bulk batch
380 // bodies (server can return up to ~12 MB per poll under busy
381 // fan-out: 144 frames × 256 KB max payload, base64-expanded).
382 WriteBufferSize: 64 * 1024,
383 ReadBufferSize: 64 * 1024,
384 IdleConnTimeout: 90 * time.Second,
385 TLSHandshakeTimeout: 15 * time.Second,
386 ExpectContinueTimeout: 1 * time.Second,
387 }
388
389 // Configure HTTP/2 so the long-lived h2 connection sends pings and detects
390 // black-holed peers quickly. Without ReadIdleTimeout, a dead h2 conn can
391 // linger until the kernel's TCP keepalive fires (~2 hours by default),
392 // leaking poll worker time as in-flight requests stall.
393 if h2t, err := http2.ConfigureTransports(transport); err == nil && h2t != nil {
394 h2t.ReadIdleTimeout = 30 * time.Second
395 h2t.PingTimeout = 15 * time.Second
396 // Raise the max DATA frame size we are willing to receive from 16 KiB
397 // (spec default) to 1 MiB. Each DATA frame carries a 9-byte header,
398 // so on a long bulk download (Apps Script gateway streaming a video
399 // chunk back) the framing overhead drops by ~64× and the receiver
400 // makes ~64× fewer Read syscalls per MiB. Stream/conn flow control
401 // windows in golang.org/x/net/http2 already default to 4 MiB / 1 GiB,
402 // so the actual throughput cap is RTT-bound, not window-bound.
403 h2t.MaxReadFrameSize = 1 << 20
404 }
405
406 return &http.Client{Transport: transport, Timeout: pollTimeout}

Callers 1

NewFrontedClientsFunction · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected