Skip to content

Improve LAN IP Detection and User Selection for WebSocket Server#35

Open
DeveloperAmrit wants to merge 3 commits intoAOSSIE-Org:mainfrom
DeveloperAmrit:fix-27-multiip
Open

Improve LAN IP Detection and User Selection for WebSocket Server#35
DeveloperAmrit wants to merge 3 commits intoAOSSIE-Org:mainfrom
DeveloperAmrit:fix-27-multiip

Conversation

@DeveloperAmrit
Copy link
Contributor

@DeveloperAmrit DeveloperAmrit commented Feb 8, 2026

Fixes #27

Summary
This PR addresses a bug in the getLocalIp() function that caused the application to select incorrect IP addresses (e.g., Docker or VPN interfaces) on developer machines. The changes improve the LAN IP detection logic and enhance the frontend UI to allow users to select the correct IP address if the auto-detection is inaccurate.

Changes Made

  1. Backend: Enhanced LAN IP Detection
  • Replaced the getLocalIp() function with getLocalIps() to collect all valid non-internal IPv4 addresses.
  • Implemented a heuristic to prioritize common LAN subnets (192.168., then 10.) for selecting the BEST_IP.
  • Updated WebSocket messages to include both the BEST_IP and a list of all valid IPs (LAN_IPS).
  1. Frontend: Improved IP Selection UI
  • Added availableIps state to store the list of detected IPs.
  • Updated the WebSocket message handler to populate the availableIps list and cautiously auto-detect the IP.
  • Enhanced the Settings page UI:
    • Added a "Detected LAN IPs" section with clickable buttons for all detected IPs.
    • Allowed users to quickly select an alternative IP if the auto-detection is incorrect.

Testing

  • Verified that the server correctly detects and prioritizes LAN IPs.
  • Tested the frontend to ensure the "Detected LAN IPs" section displays all valid IPs and updates the selected IP when a button is clicked.
  • Confirmed that the QR code updates dynamically based on the selected IP.

Video

Screen.Recording.2026-02-08.at.9.05.36.AM.mov

Summary by CodeRabbit

  • New Features
    • Detect and display multiple available LAN IP addresses in Settings.
    • Show a "Detected LAN IPs" section beneath the IP input when addresses are found.
    • Add clickable buttons to quickly populate the IP field from detected addresses.
    • Avoid overwriting manually configured IP values unless they are defaults/localhost.
    • Include detected network IPs in connection status information.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 8, 2026

📝 Walkthrough

Walkthrough

Server IP detection now returns multiple LAN IPs and selects a preferred one; WebSocket onboarding and get-ip messages include the ips array and chosen serverIp. Client settings stores detected IPs and displays clickable LAN IP buttons beneath the IP input for quick selection.

Changes

Cohort / File(s) Summary
Server IP Detection & WebSocket
src/server/websocket.ts
Replaced single-IP detection with multi-IP detection (getLocalIps); added BEST_IP heuristic (prefer 192.168., then 10.); onboarding and get-ip payloads now include ips (array) and serverIp (chosen IP). Logs updated accordingly.
Client Settings UI
src/routes/settings.tsx
Added availableIps state and logic to populate it from server payloads; conditionally update stored IP only when user hasn't set one or it's a default/localhost; render "Detected LAN IPs" with clickable buttons under the IP input to insert chosen IP.

Sequence Diagram(s)

sequenceDiagram
    participant Server as Server
    participant WS as WebSocket
    participant Client as Client UI
    participant User as User

    Server->>Server: getLocalIps() -> [ips]
    Server->>Server: select BEST_IP (192.168 > 10 > first)
    Server->>WS: onboarding msg { ips: [...], serverIp: BEST_IP }
    WS->>Client: deliver onboarding payload
    Client->>Client: set availableIps state
    Client->>Client: show "Detected LAN IPs" buttons
    User->>Client: click IP button
    Client->>Client: populate IP input with chosen IP
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped through nets both near and far,
I found many addresses — a bright LAN star,
I picked the best, then gave a clue,
Click a button — I'll fill it for you,
Hooray for fewer QR-code scars! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the primary changes: improving LAN IP detection and adding user selection capability via the Settings interface.
Linked Issues check ✅ Passed The PR fulfills issue #27 requirements: filters for likely LAN interfaces (192.168., 10.) via BEST_IP heuristic and sends all candidates to frontend for user selection.
Out of Scope Changes check ✅ Passed All changes directly address the linked issue: server-side IP collection/prioritization and frontend UI for user selection, with no unrelated modifications present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

We've launched Issue Planner and it is currently in beta. Please try it out and share your feedback on Discord!


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@src/routes/settings.tsx`:
- Around line 111-115: The button element that calls setIp(addr) should include
an explicit type to avoid accidental form submissions; update the JSX button
(the one with key={addr} and onClick={() => setIp(addr)}) to add type="button"
so it doesn't default to type="submit".
- Around line 64-68: The guard prevents applying the auto-detected IP because it
only sets IP when localStorage.getItem('rein_ip') is falsy; instead, read the
stored value into a variable and only skip overwriting when the user has
explicitly chosen a non-default LAN IP. Update the condition around
setIp(data.ip) to something like: const stored =
localStorage.getItem('rein_ip'); if (!stored || stored === '' || stored ===
'localhost' || stored === '127.0.0.1') { setIp(data.ip); } — reference the use
of localStorage.getItem('rein_ip') and the setIp(data.ip) call when making the
change.

In `@src/server/websocket.ts`:
- Around line 26-29: Update the IP selection heuristic used to compute BEST_IP
so it also prefers RFC1918 172.16.0.0/12 addresses before falling back to
10.x.x.x; specifically, change the LAN_IPS checks (the expression that sets
BEST_IP) to test for 192.168.* first, then detect 172.16.0.0/12 addresses (e.g.,
by checking the first octet is "172" and the second octet is between 16 and 31),
then 10.*, and finally LAN_IPS[0]; keep the order of preference and existing
symbol names (BEST_IP, LAN_IPS).
🧹 Nitpick comments (2)
src/server/websocket.ts (1)

48-48: Inconsistent property naming between message types.

The connected message uses serverIp while the server-ip response uses ip for the same BEST_IP value. This forces the client to handle two different property names for the same data.

Consider aligning on a single name (e.g., ip in both, or serverIp in both) to reduce client-side confusion.

Also applies to: 56-56

src/routes/settings.tsx (1)

80-82: WebSocket cleanup doesn't handle CONNECTING state.

If the component unmounts while the socket is still connecting, it won't be closed (readyState is CONNECTING, not OPEN). This can cause the onmessage handler to fire after unmount, triggering state updates on an unmounted component.

Proposed fix
         return () => {
-            if (socket.readyState === WebSocket.OPEN) socket.close();
+            if (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING) {
+                socket.close();
+            }
         }

Comment on lines +111 to +115
<button
key={addr}
className="btn btn-xs btn-outline"
onClick={() => setIp(addr)}
>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add explicit type="button" to prevent unintended form submission.

Per the Biome lint finding (useButtonType): buttons default to type="submit". While there's no enclosing <form> currently, adding the explicit type is a defensive best practice.

Proposed fix
                                   <button 
                                       key={addr} 
+                                      type="button"
                                       className="btn btn-xs btn-outline"
                                       onClick={() => setIp(addr)}
                                   >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<button
key={addr}
className="btn btn-xs btn-outline"
onClick={() => setIp(addr)}
>
<button
key={addr}
type="button"
className="btn btn-xs btn-outline"
onClick={() => setIp(addr)}
>
🧰 Tools
🪛 Biome (2.3.13)

[error] 111-115: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)

🤖 Prompt for AI Agents
In `@src/routes/settings.tsx` around lines 111 - 115, The button element that
calls setIp(addr) should include an explicit type to avoid accidental form
submissions; update the JSX button (the one with key={addr} and onClick={() =>
setIp(addr)}) to add type="button" so it doesn't default to type="submit".

Comment on lines +26 to +29
// Heuristic: Prefer 192.168.x.x, then 10.x.x.x, then first available
const BEST_IP = LAN_IPS.find(ip => ip.startsWith('192.168.'))
|| LAN_IPS.find(ip => ip.startsWith('10.'))
|| LAN_IPS[0];
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Missing 172.16.0.0/12 private subnet in heuristic.

The RFC 1918 private range 172.16.0.0 – 172.31.255.255 is not considered. This is common in corporate/VPN environments and Docker default bridges.

Proposed fix
     const BEST_IP = LAN_IPS.find(ip => ip.startsWith('192.168.'))
         || LAN_IPS.find(ip => ip.startsWith('10.'))
+        || LAN_IPS.find(ip => {
+            const second = parseInt(ip.split('.')[1], 10);
+            return ip.startsWith('172.') && second >= 16 && second <= 31;
+        })
         || LAN_IPS[0];
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Heuristic: Prefer 192.168.x.x, then 10.x.x.x, then first available
const BEST_IP = LAN_IPS.find(ip => ip.startsWith('192.168.'))
|| LAN_IPS.find(ip => ip.startsWith('10.'))
|| LAN_IPS[0];
// Heuristic: Prefer 192.168.x.x, then 10.x.x.x, then first available
const BEST_IP = LAN_IPS.find(ip => ip.startsWith('192.168.'))
|| LAN_IPS.find(ip => ip.startsWith('10.'))
|| LAN_IPS.find(ip => {
const second = parseInt(ip.split('.')[1], 10);
return ip.startsWith('172.') && second >= 16 && second <= 31;
})
|| LAN_IPS[0];
🤖 Prompt for AI Agents
In `@src/server/websocket.ts` around lines 26 - 29, Update the IP selection
heuristic used to compute BEST_IP so it also prefers RFC1918 172.16.0.0/12
addresses before falling back to 10.x.x.x; specifically, change the LAN_IPS
checks (the expression that sets BEST_IP) to test for 192.168.* first, then
detect 172.16.0.0/12 addresses (e.g., by checking the first octet is "172" and
the second octet is between 16 and 31), then 10.*, and finally LAN_IPS[0]; keep
the order of preference and existing symbol names (BEST_IP, LAN_IPS).

@imxade
Copy link
Contributor

imxade commented Feb 9, 2026

@DeveloperAmrit
Docker support would be good to have
but first check and make sure if input injection works via docker on other platforms as well

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/routes/settings.tsx (1)

82-84: ⚠️ Potential issue | 🟡 Minor

WebSocket cleanup doesn't handle CONNECTING state.

If the component unmounts while the socket is still connecting (state 0), socket.close() is never called and the connection may complete after unmount, potentially firing onmessage on a stale component.

Proposed fix
         return () => {
-            if (socket.readyState === WebSocket.OPEN) socket.close();
+            if (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING) {
+                socket.close();
+            }
         }

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.

[Bug]: Incorrect LAN IP Detection for QR Code

2 participants