Addresses the "Key exchange failed: Socket error: disconnected"
errors that were causing service instability.
Changes:
- Add 10-second timeout for SSH network operations to prevent hung connections
- Enable TCP keepalive with aggressive parameters (60s idle, 10s interval, 3 probes)
- Disable SSH compression to reduce CPU overhead
- Set log verbosity to NOLOG to eliminate excessive logging that was
filling up systemd journal and potentially impacting performance
- Remove error logging for failed key exchanges to reduce log spam
(these are normal when clients disconnect during handshake)
The timeout and keepalive settings ensure dead connections are detected
and cleaned up quickly, while reduced logging minimizes I/O overhead
during high connection churn scenarios.
Tested: Server builds cleanly and starts successfully on macOS.
TCP keepalive is Linux-specific and properly guarded with #ifdef.
- README: BSD man page format (NAME/SYNOPSIS/OPTIONS/etc)
- README.md: Minimal markdown (82 lines vs 200+)
Philosophy: Dense information, no fluff, reference style.
Inspired by original Unix manuals and BSD docs.
Changes:
- Removed emojis and badges
- Condensed verbose sections
- Clear command examples
- Direct references to detailed docs
Previous implementation:
- Allocated MAX_MESSAGES * 10 (1000 messages) temporarily
- Wasted ~100KB per server startup
- Could fail if log file grows very large
New implementation:
- Track file positions of last 1000 lines
- Seek to appropriate position before reading
- Only allocate MAX_MESSAGES (100 messages)
- Memory usage reduced by 90%
Benefits:
- Faster startup with large log files
- Lower memory footprint
- No risk of allocation failure
- Same functionality maintained
Uses fseek/ftell for efficient log file handling.
Fixes three critical bugs that caused crashes after long-running:
1. Use-after-free race condition in room_broadcast()
- Added reference counting to client_t structure
- Increment ref_count before using client outside lock
- Decrement and free only when ref_count reaches 0
- Prevents accessing freed client memory during broadcast
2. strtok() data corruption in tui_render_command_output()
- strtok() modifies original string by replacing delimiters
- Now use a local copy before calling strtok()
- Prevents corruption of client->command_output
3. Improved handle_key() consistency
- Return bool to indicate if key was consumed
- Fixes issue where mode-switch keys were processed twice
Thread safety changes:
- Added client->ref_count and client->ref_lock
- Added client_release() for safe cleanup
- room_broadcast() now properly increments/decrements refs
This fixes the primary cause of crashes during extended operation.
When pressing ':' in NORMAL mode, the key was being processed twice:
1. handle_key() detected it and switched to COMMAND mode
2. The same ':' character was then added to command_input
This resulted in '::' appearing instead of ':'.
Solution:
- Changed handle_key() to return bool indicating if key was consumed
- Only add character to input if handle_key() returns false
- All mode-switching keys now return true to prevent reprocessing
Fixes the most annoying UX bug reported by users.
- Allow SSH_AUTH_METHOD_NONE for passwordless authentication
- Replace all \n with \r\n in TUI rendering for proper line breaks
- Fixes messages appearing misaligned on terminal
- Implement SSH server using libssh for secure connections
- Replace insecure telnet with encrypted SSH protocol
- Add automatic terminal size detection via PTY requests
- Support dynamic window resize (SIGWINCH handling)
- Fix UI display bug by using SSH channel instead of fd
- Update tui_clear_screen to work with SSH connections
- Add RSA host key auto-generation on first run
- Update README with SSH instructions and security notes
- Add libssh dependency to Makefile with auto-detection
- Remove all telnet-related code
Security improvements:
- All traffic now encrypted
- Host key authentication
- No more plaintext transmission