diff --git a/.claude/memory/MEMORY.md b/.claude/memory/MEMORY.md new file mode 100644 index 000000000..b1891785a --- /dev/null +++ b/.claude/memory/MEMORY.md @@ -0,0 +1,20 @@ +# GNS3 Server Project Memory + +> **Note**: This directory stores important project-related memories and case studies, managed with the code repository. +> +> **How to record**: Use the `/memory` skill to record important information to the project memory directory. + +## Quick Reference +- **Memory directory**: `.claude/memory/` +- **Skill file**: `.claude/skills/memory/SKILL.md` +- **Main index**: `MEMORY.md` (this file) + +## Topics + +### Web Wireshark Integration +- **[JWT Token Flow](./web-wireshark-jwt-token-flow.md)** - JWT token transmission path in Web Wireshark + - Key point: UDPLink only passes through jwt_token, ultimately used by curl command inside Web Wireshark container to authenticate with GNS3 capture stream API +- **[Xpra HTML5 Client](./xpra-html5-client.md)** - Xpra HTML5 client menu control parameters for customizing the web interface + +### uBridge Permission +- **[uBridge Permission Issue](./gns3-ubridge-permission.md)** - Docker containers fail to start due to missing CAP_NET_ADMIN/CAP_NET_RAW capabilities on uBridge diff --git a/.claude/memory/gns3-ubridge-permission.md b/.claude/memory/gns3-ubridge-permission.md new file mode 100644 index 000000000..2cdb01549 --- /dev/null +++ b/.claude/memory/gns3-ubridge-permission.md @@ -0,0 +1,25 @@ +# GNS3 uBridge Permission Issue + +## Problem +Docker container node fails to start with error: `uBridge requires root access or the capability to interact with network adapters` + +## Root Cause +- uBridge needs to create TAP network interfaces to connect Docker containers to GNS3 virtual network +- This requires `CAP_NET_ADMIN` and `CAP_NET_RAW` capabilities +- Other node types (like QEMU) may have their own network implementation and don't need uBridge + +## Solution +```bash +sudo setcap cap_net_admin,cap_net_raw=eip /usr/bin/ubridge +``` + +## Code Locations +- uBridge path check: `gns3server/compute/base_manager.py:298` (`has_privileged_access`) +- Permission check call: `gns3server/compute/base_node.py:851` +- Error message definition: `gns3server/compute/base_node.py:852` + +## Error Propagation Flow +Error is propagated via `NodeError` exception: +1. `NodeError` is caught at `gns3server/api/routes/compute/__init__.py:131-137` +2. Returns HTTP 409 with JSON: `{"message": "...", "exception": "NodeError"}` +3. Frontend should read error info from `message` field diff --git a/.claude/memory/web-wireshark-jwt-token-flow.md b/.claude/memory/web-wireshark-jwt-token-flow.md new file mode 100644 index 000000000..8ed59f472 --- /dev/null +++ b/.claude/memory/web-wireshark-jwt-token-flow.md @@ -0,0 +1,53 @@ +# Web Wireshark JWT Token Flow + +## Background + +Question: What is the purpose of `jwt_token` parameter in UDPLink and how is it transmitted? + +## JWT Token Complete Flow + +1. **User initiates request** → HTTP request with `Authorization: Bearer ` + +2. **API layer extracts token** → `gns3server/api/routes/controller/links.py`: + ```python + auth_header = http_request.headers.get("Authorization", "") + jwt_token = auth_header.replace("Bearer ", "") if auth_header else None + ``` + +3. **Pass to Link layer** → `Link.start_capture(wireshark=True, jwt_token=xxx)` + +4. **UDPLink forwards** → `UDPLink.start_capture()` calls `super().start_capture(jwt_token=jwt_token)` + +5. **Start Web Wireshark container** → `Link._start_web_wireshark(jwt_token)` calls management script + +6. **Container uses token** → `manage_wireshark.py` executes inside container: + ```bash + curl -N -H 'Authorization: Bearer {jwt_token}' \ + 'http://controller:3080/v3/projects/{project_id}/links/{link_id}/capture/stream' | \ + wireshark -i - -k -display :{display} + ``` + +## Why More Verbose Than gns3-copilot? + +**gns3-copilot approach**: +- All code within the same process +- Uses `contextvars` to store and retrieve token +- Downstream code directly calls `get_current_jwt_token()`, no need to pass through layers + +**Web Wireshark approach**: +- Token needs to be passed across processes (management script is separate process) +- Token needs to be passed across containers (Docker container isolation) +- Cannot use `contextvars`, must pass through command line arguments + +## Conclusion + +UDPLink does not use this token, it only forwards it to the parent class. Ultimately used by the curl command inside the Web Wireshark container to authenticate with the GNS3 controller's capture stream API. + +Token flow: **Client → GNS3 API → Link → UDPLink → Web Wireshark container → GNS3 capture stream API** + +## Related Files + +- `gns3server/api/routes/controller/links.py:114-115` - JWT token extraction +- `gns3server/controller/link.py:321-360` - Web Wireshark startup logic +- `gns3server/controller/udp_link.py:178` - UDPLink start_capture signature +- `gns3server/agent/web_wireshark/manage_wireshark.py:527-529` - Container curl command with JWT diff --git a/.claude/memory/xpra-html5-client.md b/.claude/memory/xpra-html5-client.md new file mode 100644 index 000000000..6d529ff34 --- /dev/null +++ b/.claude/memory/xpra-html5-client.md @@ -0,0 +1,148 @@ +# Xpra HTML5 Client Configuration + +## Overview + +Web Wireshark integration uses xpra's built-in HTML5 client to provide browser-based packet capture viewing. The xpra HTML5 client is located at `/usr/share/xpra/www` in the container. + +## Configuration Methods + +### 1. URL Parameters (Per-Session) + +Control toolbar menu items via URL query parameters (default: true): + +| Parameter | Menu Item | Description | +|-----------|-----------|-------------| +| xpramenu | Xpra Menu | Main menu (Server, Information submenus) | +| open_windows | Open Windows | List of open windows | +| fullscreen_button | Fullscreen | Fullscreen toggle button | +| keyboard_button | Keyboard | Keyboard layout/shortcuts | +| clipboard_button | Clipboard Copy | Clipboard copy functionality | +| sound_button | Audio | Audio toggle | +| cursor_lock_button | Lock Cursor | Game cursor lock mode | + +```bash +# Examples +?fullscreen_button=false&sound_button=false +?xpramenu=false&keyboard_button=false&clipboard_button=false&sound_button=false&cursor_lock_button=false +``` + +### 2. default-settings.txt (Recommended - Global/Persistent) + +Modify `html5/default-settings.txt` (INI format) for all users. + +**Features:** + +| Parameter | Default | Description | +|-----------|---------|-------------| +| keyboard | auto-detect | Enable keyboard input | +| keyboard_layout | us | Keyboard layout | +| clipboard | yes | Clipboard sharing | +| printing | yes | Printer forwarding | +| file_transfer | yes | File transfer | +| swap_keys | MacOS yes | Swap Command/Control keys | +| scroll_reverse_x | no | Reverse mouse X-axis | +| floating_menu | yes | Show floating menu | +| toolbar_position | top-left | Toolbar position | +| autohide | no | Auto-hide toolbar | +| sound | yes | Audio forwarding | +| video | 64-bit yes | Video decoding | + +**Connection Options:** + +| Parameter | Description | +|-----------|-------------| +| server | Server address | +| port | Port number | +| username | Username | +| password | Password | +| ssl | Enable SSL | +| encryption | Encryption type (AES-CBC/CTR/CFB) | +| key | AES encryption key | +| sharing | Allow session sharing | +| steal | Steal session | +| reconnect | Auto-reconnect | +| bandwidth_limit | Bandwidth limit (bits/s) | +| override_width | Client desktop width | + +**Advanced Options:** + +| Parameter | Default | Description | +|-----------|---------|-------------| +| audio_codec | auto-detect | Audio codec | +| encoding | auto | Image encoding (png/jpeg/webp/etc) | +| remote_logging | yes | Send logs to server | +| action | connect | Connection mode (start/shadow) | +| submit | yes | Show diagnostics on disconnect | + +### 3. default_settings in Code + +Set directly in `