Skip to content

Optimize DialStream with route caching, latency sorting, and entry ca…#361

Merged
0pcom merged 8 commits intoskycoin:developfrom
0pcom:feature/optimize-dial-latency
Mar 31, 2026
Merged

Optimize DialStream with route caching, latency sorting, and entry ca…#361
0pcom merged 8 commits intoskycoin:developfrom
0pcom:feature/optimize-dial-latency

Conversation

@0pcom
Copy link
Copy Markdown
Collaborator

@0pcom 0pcom commented Mar 31, 2026

…ching

  • Add route cache: remember which server successfully reached a destination, try it first on subsequent dials, evict on failure
  • Sort sessions by measured ping latency so lowest-latency server is tried first instead of random map iteration order
  • Cache discovery entry lookups with 30s TTL to avoid re-querying HTTP discovery on every request
  • Background ping loop measures all session RTTs every 30s

0pcom added 8 commits March 30, 2026 20:39
…ching

- Add route cache: remember which server successfully reached a destination,
  try it first on subsequent dials, evict on failure
- Sort sessions by measured ping latency so lowest-latency server is tried
  first instead of random map iteration order
- Cache discovery entry lookups with 30s TTL to avoid re-querying HTTP
  discovery on every request
- Background ping loop measures all session RTTs every 30s
- Use http.NewRequestWithContext to propagate browser request context
  to dmsg dial, so cancellations stop the stream dial immediately
  instead of waiting for the full 20s HandshakeTimeout
- Remove impossible c.String(500) after c.Status() was already written,
  which caused "Headers were already written" warnings in gin
Replace manual stream-per-request dial/write/read pattern with Go's
http.Transport using a custom DialContext. Keep-alives are disabled
because dmsg streams use noise-encrypted per-stream handshakes that
make connection reuse unreliable (server ReadTimeout can expire between
requests, and POST requests cannot be retried on stale connections).

Benefits:
- Proper request context propagation through the transport
- Standard error handling and timeout support
- Removes manual wrappedBody response draining hack
- Normalizes dmsg:// URLs to http:// for Go's transport
- Cleans up idle connections on context cancellation
…timeouts

- Fix TCP proxy io.Copy race: close both connections after first copy
  returns to unblock the second, preventing goroutine leak
- Replace dlog.Fatal with error return on port overflow (was killing process)
- Replace gin r.Run() with http.Server and graceful Shutdown on context
  cancel, preventing goroutine leak on shutdown
- Pass context to proxyTCPConn/proxyHTTPConn for proper cancellation
- Fix silent ReverseProxy Director failure: parse URL before creating
  proxy, return 500 on parse error instead of forwarding to wrong URL
- Add 30s timeout to HTTP clients in dmsghttp/util.go to prevent hanging
- Add connection semaphore (max 256) to server-side TCP proxy to prevent
  unbounded goroutine growth from many simultaneous connections
- Fix server-side TCP proxy io.Copy race: close both connections after
  first copy returns, wait for goroutine with done channel
- Add 10MB request body limit via http.MaxBytesReader in HTTP proxy
- Log close errors at debug level instead of silently ignoring them
- Fix G104 (gosec): handle Close() errors with debug logging instead
  of ignoring them in TCP proxy
- Fix G112 (gosec): add ReadHeaderTimeout to HTTP server to prevent
  Slowloris attacks
- Fix G118 (gosec): use parent context for DialStream instead of
  context.Background(); add nolint for intentional Background in
  graceful shutdown
- Fix misspell: cancelled -> canceled in comment
The http.Transport wrapper with DisableKeepAlives caused timeouts on
Windows CI and hangs on Linux CI due to Go's transport adding overhead
(Connection: close headers, persistConn goroutines) that interacts
poorly with noise-encrypted streams under concurrent load.

Revert to the proven direct approach: dial stream, write request, read
response, wrap body to close stream. Keep the dmsg:// URL normalization.
@0pcom 0pcom merged commit c2b7a54 into skycoin:develop Mar 31, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant