Skip to content

fix: address code review bugs across client and server - #28

Merged
cursor[bot] merged 2 commits into
mainfrom
cursor/fix-all-code-review-bugs-e96c
Jul 1, 2026
Merged

cursor[bot] merged 2 commits into
mainfrom
cursor/fix-all-code-review-bugs-e96c

Conversation

@Gouryella

@Gouryella Gouryella commented Jun 30, 2026 •

Copy link
Copy Markdown
Owner

Summary

This PR fixes all issues identified in the comprehensive code review across client CLI, connection pool, and server tunnel infrastructure.

Client fixes

  • drip start hang: Separate startup and run phases so partial tunnel failures no longer block forever
  • Pool client lifecycle: Re-check stopCh during data session handshake; enforce maxSessions with pending slot tracking
  • c.primary data race: Guard primary session assignment with mutex
  • WebSocket upgrade: Close resp.Body after http.ReadResponse
  • SSE: Enable client-disconnect watcher for all SSE responses, not only zero Content-Length
  • Config: Validate before config init / config set save
  • Daemon: Wait for process exit on Unix after SIGTERM; pass token via DRIP_TOKEN env instead of argv
  • Tunnel runner: Return errors instead of os.Exit; extend shutdown wait after force-close timeout
  • Close errors: Use errors.Is for EOF / net.ErrClosed detection

Server fixes

  • Per-IP limits: Extract and pass RemoteIP on TCP/TLS listener path (previously only WebSocket)
  • Heartbeat: Never remove the primary session; skip overlapping pings per session
  • Heap pool: Return unused session heaps to sessionHeapPool on all paths
  • Rate limiting: Roll back registration rate-limit counter on failed registrations
  • Data connection auth: Reject connections when no token is configured
  • Stale group cleanup: Close PrimaryConn, then always call group.Close() so heartbeat/data sessions are torn down even when the map entry was already removed; defer map deletion until cleanup completes
  • HTTP handoff: Call UnregisterConnection() when connection is handed off
  • Port allocator: Hold listeners until proxy binds via TakeListener (fixes TOCTOU)
  • Tunnel activity: Update LastActive on send, stream open, and byte counters

Test plan

  • go test ./...
  • go vet ./...
  • go test -race ./internal/client/... ./internal/server/...
  • Added TestCleanupStaleGroupsStopsHeartbeat and TestCleanupStaleGroupsStopsHeartbeatWithPrimaryConn
Open in Web Open in Cursor 

- Fix drip start hanging when some tunnels fail to connect
- Pass RemoteIP on TCP/TLS listener path for per-IP limits
- Protect primary session from heartbeat removal; fix heap pool leaks
- Roll back registration rate limits on failed registrations
- Require authentication for data connections; improve stale group cleanup
- Fix HTTP handoff connection metric leak and port allocator TOCTOU
- Track tunnel activity for CleanupStale correctness
- Fix pool client Close race, maxSessions enforcement, and primary data race
- Close WebSocket response bodies; widen SSE disconnect handling
- Validate config before save; wait for daemon exit on Unix
- Pass daemon token via DRIP_TOKEN env instead of argv
- Return errors instead of os.Exit in tunnel runner

Co-authored-by: Gouryella <Gouryella@users.noreply.github.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 262f5113f5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +124 to +126
if group.PrimaryConn != nil {
group.PrimaryConn.Close()
continue

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Close stale groups after closing the primary

When cleanupStaleGroups deletes the stale group from m.groups before this branch, group.PrimaryConn.Close() can no longer rely on the lifecycle manager's RemoveGroup call to close the group, because RemoveGroup will find no map entry and return without calling group.Close(). For stale pooled tunnels that have a primary connection, this leaves the group's stopCh open and can leak the heartbeat goroutine and any data sessions after the tunnel has been removed; close the group explicitly as well, or defer deleting it until the lifecycle cleanup runs.

Useful? React with 👍 / 👎.

When cleanupStaleGroups removed groups from the map before calling
PrimaryConn.Close(), lifecycle RemoveGroup could not find the entry and
skipped group.Close(), leaking heartbeat and data sessions.

Keep groups in the map until cleanup completes, explicitly close the
group after PrimaryConn.Close(), and add regression tests.

Co-authored-by: Gouryella <Gouryella@users.noreply.github.com>
@cursor
cursor Bot merged commit 4df2b0b into main Jul 1, 2026
1 check passed
@cursor
cursor Bot deleted the cursor/fix-all-code-review-bugs-e96c branch July 1, 2026 07:04
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.

2 participants