Fix critical wsssh process hanging issue after SSH client disconnection

- Add 'broken' flag to tunnel_t struct to distinguish between normal closure and broken connections
- Set broken=1 when detecting EBADF/EPIPE/ECONNRESET errors in tunnel operations
- Modify main loop to immediately kill SSH child process and exit when tunnel breaks
- Exit with code 1 for error conditions, code 0 for normal termination
- Update CHANGELOG.md, README.md, and TODO.md for version 1.4.7
- Prevent indefinite hanging of wsssh process after tunnel failures
parent d6ee31e9
...@@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file. ...@@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.4.7] - 2025-09-16
### Fixed
- **Critical Process Exit Bug**: Fixed wsssh process hanging after SSH client disconnection
- Added `broken` flag to tunnel structure to distinguish between normal closure and broken connections
- Implemented proper tunnel state tracking for EBADF, EPIPE, and ECONNRESET errors
- Enhanced error handling in `handle_tunnel_data()` for SSH client disconnections
- Fixed main loop to immediately kill SSH child process and exit when tunnel breaks
- Added proper exit code handling: 0 for normal termination, 1 for error conditions
- Prevented indefinite hanging of wsssh process after tunnel failures
### Technical Details
- **Tunnel State Management**: Added `int broken` field to `tunnel_t` structure for connection state tracking
- **Error Detection**: Enhanced detection of broken SSH connections with proper error classification
- **Process Management**: Improved SSH child process termination logic with immediate cleanup
- **Exit Code Standards**: Implemented standard exit codes (0=success, 1=error) for better automation support
- **Memory Management**: Maintained proper cleanup of tunnel resources in all exit paths
## [1.4.6] - 2025-09-16 ## [1.4.6] - 2025-09-16
### Added ### Added
......
...@@ -597,7 +597,25 @@ Your support helps us continue developing and maintaining this open-source proje ...@@ -597,7 +597,25 @@ Your support helps us continue developing and maintaining this open-source proje
## Changelog ## Changelog
### Version 1.4.6 (Latest) ### Version 1.4.7 (Latest)
**Critical Bug Fix:**
- **Process Exit Issue Resolution**: Fixed wsssh process hanging after SSH client disconnection
- Added `broken` flag to tunnel structure to distinguish between normal closure and broken connections
- Implemented proper tunnel state tracking for EBADF, EPIPE, and ECONNRESET errors
- Enhanced error handling in `handle_tunnel_data()` for SSH client disconnections
- Fixed main loop to immediately kill SSH child process and exit when tunnel breaks
- Added proper exit code handling: 0 for normal termination, 1 for error conditions
- Prevented indefinite hanging of wsssh process after tunnel failures
**Technical Improvements:**
- **Tunnel State Management**: Added `int broken` field to `tunnel_t` structure for connection state tracking
- **Error Detection**: Enhanced detection of broken SSH connections with proper error classification
- **Process Management**: Improved SSH child process termination logic with immediate cleanup
- **Exit Code Standards**: Implemented standard exit codes (0=success, 1=error) for better automation support
- **Memory Management**: Maintained proper cleanup of tunnel resources in all exit paths
### Version 1.4.6
**Major Refactoring:** **Major Refactoring:**
- **Code Architecture Overhaul**: Major refactoring to eliminate code duplication - **Code Architecture Overhaul**: Major refactoring to eliminate code duplication
......
# WebSocket SSH - Future Enhancements Roadmap # WebSocket SSH - Future Enhancements Roadmap
## Recently Completed (v1.4.7)
- [x] **Critical Process Exit Bug Fix**: Fixed wsssh process hanging after SSH client disconnection
- Added `broken` flag to tunnel structure to distinguish between normal closure and broken connections
- Implemented proper tunnel state tracking for EBADF, EPIPE, and ECONNRESET errors
- Enhanced error handling in `handle_tunnel_data()` for SSH client disconnections
- Fixed main loop to immediately kill SSH child process and exit when tunnel breaks
- Added proper exit code handling: 0 for normal termination, 1 for error conditions
- Prevented indefinite hanging of wsssh process after tunnel failures
- [x] **Documentation Updates**: Updated CHANGELOG.md, README.md, DOCUMENTATION.md, and TODO.md for version 1.4.7
## Recently Completed (v1.4.6) ## Recently Completed (v1.4.6)
- [x] **Code Refactoring and Library Architecture**: Major refactoring to eliminate code duplication - [x] **Code Refactoring and Library Architecture**: Major refactoring to eliminate code duplication
- Created shared libraries: `wssshlib.h/.c`, `websocket.h/.c`, `wssh_ssl.h/.c`, `tunnel.h/.c` - Created shared libraries: `wssshlib.h/.c`, `websocket.h/.c`, `wssh_ssl.h/.c`, `tunnel.h/.c`
......
...@@ -139,13 +139,15 @@ void handle_tunnel_request(SSL *ssl, const char *request_id, int debug) { ...@@ -139,13 +139,15 @@ void handle_tunnel_request(SSL *ssl, const char *request_id, int debug) {
active_tunnel->local_sock = -1; // Not used in wssshc active_tunnel->local_sock = -1; // Not used in wssshc
strcpy(active_tunnel->request_id, request_id); strcpy(active_tunnel->request_id, request_id);
active_tunnel->active = 1; active_tunnel->active = 1;
active_tunnel->broken = 0;
active_tunnel->ssl = ssl; active_tunnel->ssl = ssl;
active_tunnel->outgoing_buffer = NULL; // wssshc doesn't use buffer active_tunnel->outgoing_buffer = NULL; // wssshc doesn't use buffer
active_tunnel->incoming_buffer = NULL; // wssshc doesn't need incoming buffer active_tunnel->incoming_buffer = NULL; // wssshc doesn't need incoming buffer
pthread_mutex_unlock(&tunnel_mutex); pthread_mutex_unlock(&tunnel_mutex);
if (debug) { if (debug) {
printf("[DEBUG] wssshc connected to target SSH server\n"); printf("[DEBUG - Tunnel] wssshc connected to target SSH server\n");
fflush(stdout);
} }
// Send tunnel_ack back to server // Send tunnel_ack back to server
...@@ -153,7 +155,8 @@ void handle_tunnel_request(SSL *ssl, const char *request_id, int debug) { ...@@ -153,7 +155,8 @@ void handle_tunnel_request(SSL *ssl, const char *request_id, int debug) {
snprintf(ack_msg, sizeof(ack_msg), "{\"type\":\"tunnel_ack\",\"request_id\":\"%s\"}", request_id); snprintf(ack_msg, sizeof(ack_msg), "{\"type\":\"tunnel_ack\",\"request_id\":\"%s\"}", request_id);
if (debug) { if (debug) {
printf("[DEBUG] Sending tunnel_ack: %s\n", ack_msg); printf("[DEBUG - WebSockets] Sending tunnel_ack: %s\n", ack_msg);
fflush(stdout);
} }
if (!send_websocket_frame(ssl, ack_msg)) { if (!send_websocket_frame(ssl, ack_msg)) {
...@@ -223,7 +226,7 @@ void *forward_tcp_to_ws(void *arg) { ...@@ -223,7 +226,7 @@ void *forward_tcp_to_ws(void *arg) {
// Check if socket is valid // Check if socket is valid
if (sock < 0) { if (sock < 0) {
if (debug) { if (debug) {
printf("[DEBUG] Socket not ready yet, waiting...\n"); printf("[DEBUG - Tunnel] Socket not ready yet, waiting...\n");
fflush(stdout); fflush(stdout);
} }
pthread_mutex_unlock(&tunnel_mutex); pthread_mutex_unlock(&tunnel_mutex);
...@@ -256,7 +259,7 @@ void *forward_tcp_to_ws(void *arg) { ...@@ -256,7 +259,7 @@ void *forward_tcp_to_ws(void *arg) {
// Send any buffered data to the SSH client // Send any buffered data to the SSH client
if (active_tunnel->incoming_buffer && active_tunnel->incoming_buffer->used > 0) { if (active_tunnel->incoming_buffer && active_tunnel->incoming_buffer->used > 0) {
if (debug) { if (debug) {
printf("[DEBUG] Sending %zu bytes of buffered data to SSH client\n", active_tunnel->incoming_buffer->used); printf("[DEBUG - TCPConnection] Sending %zu bytes of buffered data to SSH client\n", active_tunnel->incoming_buffer->used);
fflush(stdout); fflush(stdout);
} }
ssize_t sent = send(client_sock, active_tunnel->incoming_buffer->buffer, active_tunnel->incoming_buffer->used, 0); ssize_t sent = send(client_sock, active_tunnel->incoming_buffer->buffer, active_tunnel->incoming_buffer->used, 0);
...@@ -270,7 +273,7 @@ void *forward_tcp_to_ws(void *arg) { ...@@ -270,7 +273,7 @@ void *forward_tcp_to_ws(void *arg) {
} }
if (debug) { if (debug) {
printf("[DEBUG] SSH client connected, starting data forwarding\n"); printf("[DEBUG - Tunnel] SSH client connected, starting data forwarding\n");
fflush(stdout); fflush(stdout);
} }
} }
...@@ -281,7 +284,7 @@ void *forward_tcp_to_ws(void *arg) { ...@@ -281,7 +284,7 @@ void *forward_tcp_to_ws(void *arg) {
if (sent > 0) { if (sent > 0) {
frame_buffer_consume(active_tunnel->outgoing_buffer, sent); frame_buffer_consume(active_tunnel->outgoing_buffer, sent);
if (debug) { if (debug) {
printf("[DEBUG] Sent %zd bytes from buffer to local socket\n", sent); printf("[DEBUG - TCPConnection] Sent %zd bytes from buffer to local socket\n", sent);
fflush(stdout); fflush(stdout);
} }
} else if (sent == -1 && errno != EAGAIN && errno != EWOULDBLOCK) { } else if (sent == -1 && errno != EAGAIN && errno != EWOULDBLOCK) {
...@@ -319,9 +322,9 @@ void *forward_tcp_to_ws(void *arg) { ...@@ -319,9 +322,9 @@ void *forward_tcp_to_ws(void *arg) {
if (bytes_read <= 0) { if (bytes_read <= 0) {
if (debug) { if (debug) {
if (bytes_read == 0) { if (bytes_read == 0) {
printf("[DEBUG] TCP connection closed by peer (SSH client disconnected)\n"); printf("[DEBUG - TCPConnection] TCP connection closed by peer (SSH client disconnected)\n");
} else { } else {
printf("[DEBUG] TCP connection error: %s\n", strerror(errno)); printf("[DEBUG - TCPConnection] TCP connection error: %s\n", strerror(errno));
} }
fflush(stdout); fflush(stdout);
} }
...@@ -329,13 +332,20 @@ void *forward_tcp_to_ws(void *arg) { ...@@ -329,13 +332,20 @@ void *forward_tcp_to_ws(void *arg) {
pthread_mutex_lock(&tunnel_mutex); pthread_mutex_lock(&tunnel_mutex);
if (active_tunnel) { if (active_tunnel) {
active_tunnel->active = 0; active_tunnel->active = 0;
active_tunnel->broken = 1;
// Send tunnel_close notification immediately when local connection breaks
if (debug) {
printf("[DEBUG - Tunnel] Sending tunnel_close notification from forwarding thread...\n");
fflush(stdout);
}
send_tunnel_close(active_tunnel->ssl, active_tunnel->request_id, debug);
} }
pthread_mutex_unlock(&tunnel_mutex); pthread_mutex_unlock(&tunnel_mutex);
break; break;
} }
if (debug) { if (debug) {
printf("[DEBUG] Forwarding %d bytes from TCP to WebSocket\n", bytes_read); printf("[DEBUG - TCPConnection] Forwarding %d bytes from TCP to WebSocket\n", bytes_read);
fflush(stdout); fflush(stdout);
} }
...@@ -371,10 +381,25 @@ void *forward_tcp_to_ws(void *arg) { ...@@ -371,10 +381,25 @@ void *forward_tcp_to_ws(void *arg) {
} }
if (debug) { if (debug) {
printf("[DEBUG] TCP to WebSocket forwarding thread exiting\n"); printf("[DEBUG - TCPConnection] TCP to WebSocket forwarding thread exiting\n");
fflush(stdout); fflush(stdout);
} }
// Mark tunnel as inactive when forwarding thread exits due to broken connection
if (active_tunnel) {
pthread_mutex_lock(&tunnel_mutex);
if (active_tunnel->active) {
active_tunnel->active = 0;
if (debug) {
printf("[DEBUG - TCPConnection] Marked tunnel as inactive due to forwarding thread exit\n");
fflush(stdout);
}
// Send tunnel_close notification
send_tunnel_close(active_tunnel->ssl, active_tunnel->request_id, debug);
}
pthread_mutex_unlock(&tunnel_mutex);
}
free(args); free(args);
return NULL; return NULL;
} }
...@@ -422,14 +447,14 @@ void *forward_ws_to_ssh_server(void *arg) { ...@@ -422,14 +447,14 @@ void *forward_ws_to_ssh_server(void *arg) {
bytes_read = recv(ssh_sock, buffer, sizeof(buffer), 0); bytes_read = recv(ssh_sock, buffer, sizeof(buffer), 0);
if (bytes_read <= 0) { if (bytes_read <= 0) {
if (debug) { if (debug) {
printf("[DEBUG] SSH server connection closed or error\n"); printf("[DEBUG - TCPConnection] SSH server connection closed or error\n");
fflush(stdout); fflush(stdout);
} }
break; break;
} }
if (debug) { if (debug) {
printf("[DEBUG] Forwarding %d bytes from SSH server to WebSocket\n", bytes_read); printf("[DEBUG - TCPConnection] Forwarding %d bytes from SSH server to WebSocket\n", bytes_read);
fflush(stdout); fflush(stdout);
} }
...@@ -465,7 +490,7 @@ void *forward_ws_to_ssh_server(void *arg) { ...@@ -465,7 +490,7 @@ void *forward_ws_to_ssh_server(void *arg) {
} }
if (debug) { if (debug) {
printf("[DEBUG] SSH server to WebSocket forwarding thread exiting\n"); printf("[DEBUG - TCPConnection] SSH server to WebSocket forwarding thread exiting\n");
fflush(stdout); fflush(stdout);
} }
...@@ -595,6 +620,9 @@ void handle_tunnel_data(SSL *ssl __attribute__((unused)), const char *request_id ...@@ -595,6 +620,9 @@ void handle_tunnel_data(SSL *ssl __attribute__((unused)), const char *request_id
pthread_mutex_lock(&tunnel_mutex); pthread_mutex_lock(&tunnel_mutex);
if (active_tunnel) { if (active_tunnel) {
active_tunnel->active = 0; active_tunnel->active = 0;
active_tunnel->broken = 1;
// Send tunnel_close notification immediately
send_tunnel_close(active_tunnel->ssl, active_tunnel->request_id, debug);
} }
pthread_mutex_unlock(&tunnel_mutex); pthread_mutex_unlock(&tunnel_mutex);
} else if (errno == EAGAIN || errno == EWOULDBLOCK) { } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
...@@ -613,6 +641,9 @@ void handle_tunnel_data(SSL *ssl __attribute__((unused)), const char *request_id ...@@ -613,6 +641,9 @@ void handle_tunnel_data(SSL *ssl __attribute__((unused)), const char *request_id
pthread_mutex_lock(&tunnel_mutex); pthread_mutex_lock(&tunnel_mutex);
if (active_tunnel) { if (active_tunnel) {
active_tunnel->active = 0; active_tunnel->active = 0;
active_tunnel->broken = 1;
// Send tunnel_close notification immediately
send_tunnel_close(active_tunnel->ssl, active_tunnel->request_id, debug);
} }
pthread_mutex_unlock(&tunnel_mutex); pthread_mutex_unlock(&tunnel_mutex);
} else { } else {
...@@ -639,6 +670,23 @@ void handle_tunnel_data(SSL *ssl __attribute__((unused)), const char *request_id ...@@ -639,6 +670,23 @@ void handle_tunnel_data(SSL *ssl __attribute__((unused)), const char *request_id
free(data); free(data);
} }
void send_tunnel_close(SSL *ssl, const char *request_id, int debug) {
char close_msg[256];
snprintf(close_msg, sizeof(close_msg), "{\"type\":\"tunnel_close\",\"request_id\":\"%s\"}", request_id);
if (debug) {
printf("[DEBUG - Tunnel] Sending tunnel_close: %s\n", close_msg);
fflush(stdout);
}
if (!send_websocket_frame(ssl, close_msg)) {
if (debug) {
printf("[DEBUG - Tunnel] Failed to send tunnel_close message\n");
fflush(stdout);
}
}
}
void handle_tunnel_close(SSL *ssl __attribute__((unused)), const char *request_id, int debug) { void handle_tunnel_close(SSL *ssl __attribute__((unused)), const char *request_id, int debug) {
pthread_mutex_lock(&tunnel_mutex); pthread_mutex_lock(&tunnel_mutex);
if (active_tunnel && strcmp(active_tunnel->request_id, request_id) == 0) { if (active_tunnel && strcmp(active_tunnel->request_id, request_id) == 0) {
...@@ -658,7 +706,8 @@ void handle_tunnel_close(SSL *ssl __attribute__((unused)), const char *request_i ...@@ -658,7 +706,8 @@ void handle_tunnel_close(SSL *ssl __attribute__((unused)), const char *request_i
free(active_tunnel); free(active_tunnel);
active_tunnel = NULL; active_tunnel = NULL;
if (debug) { if (debug) {
printf("[DEBUG] Tunnel %s closed\n", request_id); printf("[DEBUG - Tunnel] Tunnel %s closed\n", request_id);
fflush(stdout);
} }
} }
pthread_mutex_unlock(&tunnel_mutex); pthread_mutex_unlock(&tunnel_mutex);
...@@ -1008,6 +1057,7 @@ int setup_tunnel(const char *wssshd_host, int wssshd_port, const char *client_id ...@@ -1008,6 +1057,7 @@ int setup_tunnel(const char *wssshd_host, int wssshd_port, const char *client_id
strcpy(active_tunnel->request_id, request_id); strcpy(active_tunnel->request_id, request_id);
active_tunnel->local_sock = -1; active_tunnel->local_sock = -1;
active_tunnel->active = 1; active_tunnel->active = 1;
active_tunnel->broken = 0;
active_tunnel->ssl = ssl; active_tunnel->ssl = ssl;
// Start listening on local port // Start listening on local port
......
...@@ -36,6 +36,7 @@ typedef struct { ...@@ -36,6 +36,7 @@ typedef struct {
int sock; // SSH client connection socket (for wsssh) or SSH server connection socket (for wssshc) int sock; // SSH client connection socket (for wsssh) or SSH server connection socket (for wssshc)
char request_id[37]; // UUID string char request_id[37]; // UUID string
int active; int active;
int broken; // Flag to indicate if the tunnel is broken (not normal closure)
SSL *ssl; // WebSocket SSL connection SSL *ssl; // WebSocket SSL connection
frame_buffer_t *outgoing_buffer; // Buffer for data to send to local socket (wsscp only) frame_buffer_t *outgoing_buffer; // Buffer for data to send to local socket (wsscp only)
frame_buffer_t *incoming_buffer; // Buffer for incoming data before connection is established frame_buffer_t *incoming_buffer; // Buffer for incoming data before connection is established
...@@ -59,6 +60,7 @@ void *tunnel_thread(void *arg); ...@@ -59,6 +60,7 @@ void *tunnel_thread(void *arg);
void handle_tunnel_request(SSL *ssl, const char *request_id, int debug); void handle_tunnel_request(SSL *ssl, const char *request_id, int debug);
void handle_tunnel_data(SSL *ssl, const char *request_id, const char *data_hex, int debug); void handle_tunnel_data(SSL *ssl, const char *request_id, const char *data_hex, int debug);
void handle_tunnel_close(SSL *ssl, const char *request_id, int debug); void handle_tunnel_close(SSL *ssl, const char *request_id, int debug);
void send_tunnel_close(SSL *ssl, const char *request_id, int debug);
void cleanup_tunnel(int debug); void cleanup_tunnel(int debug);
int reconnect_websocket(tunnel_t *tunnel, const char *wssshd_host, int wssshd_port, const char *client_id, const char *request_id, int debug); int reconnect_websocket(tunnel_t *tunnel, const char *wssshd_host, int wssshd_port, const char *client_id, const char *request_id, int debug);
int setup_tunnel(const char *wssshd_host, int wssshd_port, const char *client_id, int local_port, int debug, int use_buffer); int setup_tunnel(const char *wssshd_host, int wssshd_port, const char *client_id, int local_port, int debug, int use_buffer);
......
...@@ -544,6 +544,15 @@ int main(int argc, char *argv[]) { ...@@ -544,6 +544,15 @@ int main(int argc, char *argv[]) {
break; break;
} }
// Check if tunnel became inactive during processing
if (!active_tunnel || !active_tunnel->active) {
if (config.debug) {
printf("[DEBUG] Tunnel became inactive, exiting main loop\n");
fflush(stdout);
}
break;
}
// Use select to wait for data on SSL socket with timeout // Use select to wait for data on SSL socket with timeout
FD_ZERO(&readfds); FD_ZERO(&readfds);
FD_SET(ssl_fd, &readfds); FD_SET(ssl_fd, &readfds);
...@@ -558,6 +567,14 @@ int main(int argc, char *argv[]) { ...@@ -558,6 +567,14 @@ int main(int argc, char *argv[]) {
} }
break; break;
} else if (retval == 0) { } else if (retval == 0) {
// Timeout, check if tunnel became inactive during timeout
if (!active_tunnel || !active_tunnel->active) {
if (config.debug) {
printf("[DEBUG] Tunnel became inactive during timeout, exiting\n");
fflush(stdout);
}
break;
}
// Timeout, continue loop // Timeout, continue loop
continue; continue;
} }
...@@ -886,5 +903,6 @@ cleanup: ...@@ -886,5 +903,6 @@ cleanup:
free(config_domain); free(config_domain);
pthread_mutex_destroy(&tunnel_mutex); pthread_mutex_destroy(&tunnel_mutex);
return 0; // Ensure we exit the process
exit(0);
} }
\ No newline at end of file
...@@ -146,7 +146,8 @@ int parse_ssh_args(int argc, char *argv[], char **host, int debug) { ...@@ -146,7 +146,8 @@ int parse_ssh_args(int argc, char *argv[], char **host, int debug) {
// First non-option argument should be the host // First non-option argument should be the host
*host = argv[i]; *host = argv[i];
if (debug) { if (debug) {
printf("[DEBUG] Found SSH host: %s\n", *host); printf("[DEBUG - Tunnel] Found SSH host: %s\n", *host);
fflush(stdout);
} }
break; break;
} }
...@@ -305,10 +306,11 @@ int main(int argc, char *argv[]) { ...@@ -305,10 +306,11 @@ int main(int argc, char *argv[]) {
} }
if (config.debug) { if (config.debug) {
printf("[DEBUG] SSH Host: %s\n", ssh_host); printf("[DEBUG - Tunnel] SSH Host: %s\n", ssh_host);
printf("[DEBUG] Client ID: %s\n", client_id); printf("[DEBUG - Tunnel] Client ID: %s\n", client_id);
printf("[DEBUG] WSSSHD Host: %s\n", wssshd_host); printf("[DEBUG - Tunnel] WSSSHD Host: %s\n", wssshd_host);
printf("[DEBUG] WSSSHD Port: %d\n", wssshd_port); printf("[DEBUG - Tunnel] WSSSHD Port: %d\n", wssshd_port);
fflush(stdout);
} }
// Find available local port // Find available local port
...@@ -323,7 +325,8 @@ int main(int argc, char *argv[]) { ...@@ -323,7 +325,8 @@ int main(int argc, char *argv[]) {
} }
if (config.debug) { if (config.debug) {
printf("[DEBUG] Using local port: %d\n", local_port); printf("[DEBUG - Tunnel] Using local port: %d\n", local_port);
fflush(stdout);
} }
// Modify SSH arguments // Modify SSH arguments
...@@ -339,7 +342,7 @@ int main(int argc, char *argv[]) { ...@@ -339,7 +342,7 @@ int main(int argc, char *argv[]) {
} }
if (config.debug) { if (config.debug) {
printf("[DEBUG] Modified SSH command:"); printf("[DEBUG - Tunnel] Modified SSH command:");
for (int i = 0; new_ssh_args[i]; i++) { for (int i = 0; new_ssh_args[i]; i++) {
printf(" %s", new_ssh_args[i]); printf(" %s", new_ssh_args[i]);
} }
...@@ -349,7 +352,7 @@ int main(int argc, char *argv[]) { ...@@ -349,7 +352,7 @@ int main(int argc, char *argv[]) {
// Parent process: setup tunnel FIRST // Parent process: setup tunnel FIRST
if (config.debug) { if (config.debug) {
printf("[DEBUG] Parent process setting up tunnel...\n"); printf("[DEBUG - Tunnel] Parent process setting up tunnel...\n");
fflush(stdout); fflush(stdout);
} }
...@@ -360,7 +363,7 @@ int main(int argc, char *argv[]) { ...@@ -360,7 +363,7 @@ int main(int argc, char *argv[]) {
while (setup_attempts < max_setup_attempts && listen_sock < 0) { while (setup_attempts < max_setup_attempts && listen_sock < 0) {
if (config.debug && setup_attempts > 0) { if (config.debug && setup_attempts > 0) {
printf("[DEBUG] Initial tunnel setup attempt %d/%d\n", setup_attempts + 1, max_setup_attempts); printf("[DEBUG - Tunnel] Initial tunnel setup attempt %d/%d\n", setup_attempts + 1, max_setup_attempts);
fflush(stdout); fflush(stdout);
} }
...@@ -370,7 +373,7 @@ int main(int argc, char *argv[]) { ...@@ -370,7 +373,7 @@ int main(int argc, char *argv[]) {
setup_attempts++; setup_attempts++;
if (setup_attempts < max_setup_attempts) { if (setup_attempts < max_setup_attempts) {
if (config.debug) { if (config.debug) {
printf("[DEBUG] Initial tunnel setup failed, waiting %d seconds...\n", config.interval); printf("[DEBUG - Tunnel] Initial tunnel setup failed, waiting %d seconds...\n", config.interval);
fflush(stdout); fflush(stdout);
} }
sleep(config.interval); sleep(config.interval);
...@@ -395,7 +398,7 @@ int main(int argc, char *argv[]) { ...@@ -395,7 +398,7 @@ int main(int argc, char *argv[]) {
// NOW fork to run SSH in background (after tunnel is ready) // NOW fork to run SSH in background (after tunnel is ready)
if (config.debug) { if (config.debug) {
printf("[DEBUG] About to fork SSH process...\n"); printf("[DEBUG - Tunnel] About to fork SSH process...\n");
fflush(stdout); fflush(stdout);
} }
pid_t pid = fork(); pid_t pid = fork();
...@@ -417,7 +420,7 @@ int main(int argc, char *argv[]) { ...@@ -417,7 +420,7 @@ int main(int argc, char *argv[]) {
if (pid == 0) { if (pid == 0) {
// Child process: run SSH // Child process: run SSH
if (config.debug) { if (config.debug) {
printf("[DEBUG] Child process starting SSH...\n"); printf("[DEBUG - Tunnel] Child process starting SSH...\n");
fflush(stdout); fflush(stdout);
} }
execvp("ssh", new_ssh_args); execvp("ssh", new_ssh_args);
...@@ -437,7 +440,7 @@ int main(int argc, char *argv[]) { ...@@ -437,7 +440,7 @@ int main(int argc, char *argv[]) {
// Parent process: accept SSH connection and start forwarding // Parent process: accept SSH connection and start forwarding
if (config.debug) { if (config.debug) {
printf("[DEBUG] Waiting for SSH connection on localhost:%d...\n", local_port); printf("[DEBUG - Tunnel] Waiting for SSH connection on localhost:%d...\n", local_port);
fflush(stdout); fflush(stdout);
} }
...@@ -472,7 +475,7 @@ int main(int argc, char *argv[]) { ...@@ -472,7 +475,7 @@ int main(int argc, char *argv[]) {
pthread_mutex_unlock(&tunnel_mutex); pthread_mutex_unlock(&tunnel_mutex);
if (config.debug) { if (config.debug) {
printf("[DEBUG] Local SSH connection accepted! Starting data forwarding...\n"); printf("[DEBUG - Tunnel] Local SSH connection accepted! Starting data forwarding...\n");
fflush(stdout); fflush(stdout);
} }
...@@ -519,16 +522,76 @@ int main(int argc, char *argv[]) { ...@@ -519,16 +522,76 @@ int main(int argc, char *argv[]) {
int bytes_read; int bytes_read;
fd_set readfds; fd_set readfds;
struct timeval tv; struct timeval tv;
int tunnel_broken = 0;
while (1) { while (1) {
// Get SSL fd with mutex protection // Get SSL fd with mutex protection
pthread_mutex_lock(&tunnel_mutex); pthread_mutex_lock(&tunnel_mutex);
if (!active_tunnel || !active_tunnel->active) { if (!active_tunnel || !active_tunnel->active) {
pthread_mutex_unlock(&tunnel_mutex); if (active_tunnel && active_tunnel->broken) {
break; tunnel_broken = 1;
kill(pid, SIGTERM);
pthread_mutex_unlock(&tunnel_mutex);
goto cleanup_and_exit;
} else {
// normal closure
pthread_mutex_unlock(&tunnel_mutex);
if (config.debug) {
printf("[DEBUG - Tunnel] Tunnel is no longer active, exiting main loop\n");
fflush(stdout);
}
break;
}
} }
int ssl_fd = SSL_get_fd(active_tunnel->ssl); int ssl_fd = SSL_get_fd(active_tunnel->ssl);
current_ssl = active_tunnel->ssl; current_ssl = active_tunnel->ssl;
// Check if local socket is still valid
if (active_tunnel->local_sock < 0) {
if (config.debug) {
printf("[DEBUG - Tunnel] Local socket is invalid, tunnel broken\n");
fflush(stdout);
}
tunnel_broken = 1;
active_tunnel->broken = 1;
// Send tunnel_close notification immediately when local connection breaks
if (config.debug) {
printf("[DEBUG - Tunnel] Sending tunnel_close notification due to invalid local socket...\n");
fflush(stdout);
}
send_tunnel_close(current_ssl, active_tunnel->request_id, config.debug);
pthread_mutex_unlock(&tunnel_mutex);
// Kill SSH process and exit immediately
if (config.debug) {
printf("[DEBUG - Tunnel] Killing SSH process and exiting due to broken tunnel\n");
fflush(stdout);
}
kill(pid, SIGTERM);
goto cleanup_and_exit;
}
// Also check if the local socket connection is broken by trying to peek at it
char test_buf[1];
int result = recv(active_tunnel->local_sock, test_buf, 1, MSG_PEEK | MSG_DONTWAIT);
if (result == 0 || (result < 0 && (errno == ECONNRESET || errno == EPIPE || errno == EBADF))) {
if (config.debug) {
printf("[DEBUG - Tunnel] Local socket connection is broken (errno=%d), sending tunnel_close\n", errno);
fflush(stdout);
}
tunnel_broken = 1;
active_tunnel->broken = 1;
// Send tunnel_close notification immediately when local connection breaks
send_tunnel_close(current_ssl, active_tunnel->request_id, config.debug);
pthread_mutex_unlock(&tunnel_mutex);
// Kill SSH process and exit immediately
if (config.debug) {
printf("[DEBUG - Tunnel] Killing SSH process and exiting due to broken tunnel\n");
fflush(stdout);
}
kill(pid, SIGTERM);
goto cleanup_and_exit;
}
pthread_mutex_unlock(&tunnel_mutex); pthread_mutex_unlock(&tunnel_mutex);
// Use select to wait for data on SSL socket with timeout // Use select to wait for data on SSL socket with timeout
FD_ZERO(&readfds); FD_ZERO(&readfds);
...@@ -539,11 +602,42 @@ int main(int argc, char *argv[]) { ...@@ -539,11 +602,42 @@ int main(int argc, char *argv[]) {
int retval = select(ssl_fd + 1, &readfds, NULL, NULL, &tv); int retval = select(ssl_fd + 1, &readfds, NULL, NULL, &tv);
if (retval == -1) { if (retval == -1) {
if (config.debug) { if (config.debug) {
perror("[DEBUG] select on SSL fd failed"); perror("[DEBUG - WebSockets] select on SSL fd failed");
fflush(stdout); fflush(stdout);
} }
break; tunnel_broken = 1;
// Send tunnel_close notification before breaking
if (config.debug) {
printf("[DEBUG - Tunnel] Sending tunnel_close notification due to select failure...\n");
fflush(stdout);
}
send_tunnel_close(current_ssl, active_tunnel->request_id, config.debug);
// Kill SSH process and exit immediately
if (config.debug) {
printf("[DEBUG - Tunnel] Killing SSH process and exiting due to broken tunnel\n");
fflush(stdout);
}
kill(pid, SIGTERM);
goto cleanup_and_exit;
} else if (retval == 0) { } else if (retval == 0) {
// Timeout, check if tunnel became inactive during timeout
pthread_mutex_lock(&tunnel_mutex);
if (!active_tunnel || !active_tunnel->active) {
pthread_mutex_unlock(&tunnel_mutex);
if (config.debug) {
printf("[DEBUG - Tunnel] Tunnel became inactive during timeout, exiting\n");
fflush(stdout);
}
tunnel_broken = 1;
// Kill SSH process and exit immediately
if (config.debug) {
printf("[DEBUG - Tunnel] Killing SSH process and exiting due to broken tunnel\n");
fflush(stdout);
}
kill(pid, SIGTERM);
goto cleanup_and_exit;
}
pthread_mutex_unlock(&tunnel_mutex);
// Timeout, continue loop // Timeout, continue loop
continue; continue;
} }
...@@ -552,7 +646,7 @@ int main(int argc, char *argv[]) { ...@@ -552,7 +646,7 @@ int main(int argc, char *argv[]) {
bytes_read = SSL_read(current_ssl, buffer, sizeof(buffer)); bytes_read = SSL_read(current_ssl, buffer, sizeof(buffer));
if (bytes_read <= 0) { if (bytes_read <= 0) {
if (config.debug) { if (config.debug) {
printf("[DEBUG] WebSocket connection lost, attempting reconnection...\n"); printf("[DEBUG - WebSockets] WebSocket connection lost, attempting reconnection...\n");
fflush(stdout); fflush(stdout);
} }
...@@ -563,7 +657,7 @@ int main(int argc, char *argv[]) { ...@@ -563,7 +657,7 @@ int main(int argc, char *argv[]) {
while (reconnect_attempts < max_reconnect_attempts && !reconnected) { while (reconnect_attempts < max_reconnect_attempts && !reconnected) {
if (config.debug) { if (config.debug) {
printf("[DEBUG] WebSocket reconnection attempt %d/%d\n", reconnect_attempts + 1, max_reconnect_attempts); printf("[DEBUG - WebSockets] WebSocket reconnection attempt %d/%d\n", reconnect_attempts + 1, max_reconnect_attempts);
fflush(stdout); fflush(stdout);
} }
...@@ -575,7 +669,7 @@ int main(int argc, char *argv[]) { ...@@ -575,7 +669,7 @@ int main(int argc, char *argv[]) {
if (reconnect_websocket(active_tunnel, wssshd_host, wssshd_port, client_id, active_tunnel->request_id, config.debug) == 0) { if (reconnect_websocket(active_tunnel, wssshd_host, wssshd_port, client_id, active_tunnel->request_id, config.debug) == 0) {
reconnected = 1; reconnected = 1;
if (config.debug) { if (config.debug) {
printf("[DEBUG] WebSocket reconnection successful, continuing tunnel\n"); printf("[DEBUG - WebSockets] WebSocket reconnection successful, continuing tunnel\n");
fflush(stdout); fflush(stdout);
} }
// Update ssl_fd for select // Update ssl_fd for select
...@@ -588,7 +682,7 @@ int main(int argc, char *argv[]) { ...@@ -588,7 +682,7 @@ int main(int argc, char *argv[]) {
reconnect_attempts++; reconnect_attempts++;
if (reconnect_attempts < max_reconnect_attempts) { if (reconnect_attempts < max_reconnect_attempts) {
if (config.debug) { if (config.debug) {
printf("[DEBUG] WebSocket reconnection failed, waiting 1 second...\n"); printf("[DEBUG - WebSockets] WebSocket reconnection failed, waiting 1 second...\n");
fflush(stdout); fflush(stdout);
} }
sleep(1); // Use 1 second for WebSocket reconnections sleep(1); // Use 1 second for WebSocket reconnections
...@@ -598,32 +692,77 @@ int main(int argc, char *argv[]) { ...@@ -598,32 +692,77 @@ int main(int argc, char *argv[]) {
if (!reconnected) { if (!reconnected) {
if (config.debug) { if (config.debug) {
printf("[DEBUG] All reconnection attempts failed, exiting\n"); printf("[DEBUG - WebSockets] All reconnection attempts failed, exiting\n");
fflush(stdout);
}
tunnel_broken = 1;
// Send tunnel_close notification before breaking
if (config.debug) {
printf("[DEBUG - Tunnel] Sending tunnel_close notification due to connection failure...\n");
fflush(stdout); fflush(stdout);
} }
break; send_tunnel_close(current_ssl, active_tunnel->request_id, config.debug);
// Kill SSH process and exit immediately
if (config.debug) {
printf("[DEBUG - Tunnel] Killing SSH process and exiting due to broken tunnel\n");
fflush(stdout);
}
kill(pid, SIGTERM);
goto cleanup_and_exit;
} }
// Skip processing this iteration since we just reconnected // Skip processing this iteration since we just reconnected
continue; continue;
} }
// Check if tunnel became inactive during WebSocket processing
pthread_mutex_lock(&tunnel_mutex);
if (!active_tunnel || !active_tunnel->active) {
pthread_mutex_unlock(&tunnel_mutex);
if (config.debug) {
printf("[DEBUG - Tunnel] Tunnel became inactive during WebSocket processing, exiting\n");
fflush(stdout);
}
tunnel_broken = 1;
// Kill SSH process and exit immediately
if (config.debug) {
printf("[DEBUG - Tunnel] Killing SSH process and exiting due to broken tunnel\n");
fflush(stdout);
}
kill(pid, SIGTERM);
goto cleanup_and_exit;
}
pthread_mutex_unlock(&tunnel_mutex);
// Check frame type // Check frame type
unsigned char frame_type = buffer[0] & 0x8F; unsigned char frame_type = buffer[0] & 0x8F;
// Handle close frame // Handle close frame
if (frame_type == 0x88) { if (frame_type == 0x88) {
if (config.debug) { if (config.debug) {
printf("[DEBUG] Received close frame from server\n"); printf("[DEBUG - WebSockets] Received close frame from server\n");
fflush(stdout); fflush(stdout);
} }
break; tunnel_broken = 1;
// Send tunnel_close notification before breaking
if (config.debug) {
printf("[DEBUG - Tunnel] Sending tunnel_close notification due to server close frame...\n");
fflush(stdout);
}
send_tunnel_close(current_ssl, active_tunnel->request_id, config.debug);
// Kill SSH process and exit immediately
if (config.debug) {
printf("[DEBUG - Tunnel] Killing SSH process and exiting due to broken tunnel\n");
fflush(stdout);
}
kill(pid, SIGTERM);
goto cleanup_and_exit;
} }
// Handle ping frame // Handle ping frame
if (frame_type == 0x89) { if (frame_type == 0x89) {
if (config.debug) { if (config.debug) {
printf("[DEBUG] Received ping frame, sending pong\n"); printf("[DEBUG - WebSockets] Received ping frame, sending pong\n");
fflush(stdout); fflush(stdout);
} }
// Parse the ping frame to get payload // Parse the ping frame to get payload
...@@ -633,7 +772,7 @@ int main(int argc, char *argv[]) { ...@@ -633,7 +772,7 @@ int main(int argc, char *argv[]) {
// Send pong with same payload // Send pong with same payload
if (!send_pong_frame(current_ssl, ping_payload, ping_payload_len)) { if (!send_pong_frame(current_ssl, ping_payload, ping_payload_len)) {
if (config.debug) { if (config.debug) {
printf("[DEBUG] Failed to send pong frame\n"); printf("[DEBUG - WebSockets] Failed to send pong frame\n");
fflush(stdout); fflush(stdout);
} }
} }
...@@ -661,7 +800,7 @@ int main(int argc, char *argv[]) { ...@@ -661,7 +800,7 @@ int main(int argc, char *argv[]) {
int payload_len; int payload_len;
if (!parse_websocket_frame(buffer, bytes_read, &payload, &payload_len)) { if (!parse_websocket_frame(buffer, bytes_read, &payload, &payload_len)) {
if (config.debug) { if (config.debug) {
printf("[DEBUG] Failed to parse WebSocket frame\n"); printf("[DEBUG - WebSockets] Failed to parse WebSocket frame\n");
fflush(stdout); fflush(stdout);
} }
continue; continue;
...@@ -670,7 +809,7 @@ int main(int argc, char *argv[]) { ...@@ -670,7 +809,7 @@ int main(int argc, char *argv[]) {
payload[payload_len] = '\0'; payload[payload_len] = '\0';
if (config.debug) { if (config.debug) {
printf("[DEBUG] Received: %s\n", payload); printf("[DEBUG - WebSockets] Received: %s\n", payload);
fflush(stdout); fflush(stdout);
} }
...@@ -678,9 +817,9 @@ int main(int argc, char *argv[]) { ...@@ -678,9 +817,9 @@ int main(int argc, char *argv[]) {
if (strstr(payload, "tunnel_data") || strstr(payload, "tunnel_response")) { if (strstr(payload, "tunnel_data") || strstr(payload, "tunnel_response")) {
if (config.debug) { if (config.debug) {
if (strstr(payload, "tunnel_data")) { if (strstr(payload, "tunnel_data")) {
printf("[DEBUG] Received tunnel_data message\n"); printf("[DEBUG - Tunnel] Received tunnel_data message\n");
} else { } else {
printf("[DEBUG] Received tunnel_response message\n"); printf("[DEBUG - Tunnel] Received tunnel_response message\n");
} }
fflush(stdout); fflush(stdout);
} }
...@@ -714,7 +853,7 @@ int main(int argc, char *argv[]) { ...@@ -714,7 +853,7 @@ int main(int argc, char *argv[]) {
} }
} else if (strstr(payload, "tunnel_close")) { } else if (strstr(payload, "tunnel_close")) {
if (config.debug) { if (config.debug) {
printf("[DEBUG] Received tunnel_close message\n"); printf("[DEBUG - Tunnel] Received tunnel_close message\n");
fflush(stdout); fflush(stdout);
} }
char *id_start = strstr(payload, "\"request_id\""); char *id_start = strstr(payload, "\"request_id\"");
...@@ -734,38 +873,100 @@ int main(int argc, char *argv[]) { ...@@ -734,38 +873,100 @@ int main(int argc, char *argv[]) {
} }
} else { } else {
if (config.debug) { if (config.debug) {
printf("[DEBUG] Received unknown message type: %s\n", payload); printf("[DEBUG - WebSockets] Received unknown message type: %s\n", payload);
fflush(stdout); fflush(stdout);
} }
} }
} }
} }
if (config.debug) { // If we reach here normally (not via goto), handle normal tunnel closure
printf("[DEBUG] Tunnel loop ended, waiting for SSH to finish...\n"); if (!tunnel_broken) {
fflush(stdout); if (config.debug) {
printf("[DEBUG - Tunnel] Tunnel loop ended normally, sending tunnel_close notification...\n");
fflush(stdout);
}
// Send tunnel_close notification to server
pthread_mutex_lock(&tunnel_mutex);
if (active_tunnel && active_tunnel->ssl) {
send_tunnel_close(active_tunnel->ssl, active_tunnel->request_id, config.debug);
}
pthread_mutex_unlock(&tunnel_mutex);
} else {
if (config.debug) {
printf("[DEBUG - Tunnel] Tunnel was already broken, skipping duplicate tunnel_close notification\n");
fflush(stdout);
}
} }
// Wait for SSH to finish // Wait for SSH to finish (only if we didn't kill it already)
int status; if (!tunnel_broken) {
waitpid(pid, &status, 0); if (config.debug) {
printf("[DEBUG - Tunnel] Waiting for SSH process to finish normally\n");
fflush(stdout);
}
if (config.debug) { int status;
printf("[DEBUG] SSH process finished with status: %d\n", status); waitpid(pid, &status, 0);
fflush(stdout);
if (config.debug) {
printf("[DEBUG - Tunnel] SSH process finished with status: %d\n", status);
fflush(stdout);
}
// Wait a few seconds before exiting cleanly
if (config.debug) {
printf("[DEBUG - Tunnel] Waiting 3 seconds before exit...\n");
fflush(stdout);
}
sleep(3);
} }
// Wait a few seconds before exiting cleanly cleanup_and_exit:
// Cleanup section - reached either normally or via goto
if (config.debug) { if (config.debug) {
printf("[DEBUG] Waiting 3 seconds before exit...\n"); printf("[DEBUG - Tunnel] Performing cleanup and exiting\n");
fflush(stdout); fflush(stdout);
} }
sleep(3);
// If tunnel was broken, wait a moment for SSH process to terminate
if (tunnel_broken) {
if (config.debug) {
printf("[DEBUG - Tunnel] Waiting briefly for SSH process to terminate\n");
fflush(stdout);
}
// Give SSH process a moment to terminate gracefully
usleep(100000); // 100ms
// Check if SSH process is still running
int status;
pid_t result = waitpid(pid, &status, WNOHANG);
if (result == 0) {
if (config.debug) {
printf("[DEBUG - Tunnel] SSH process still running, sending SIGKILL\n");
fflush(stdout);
}
// SSH process is still running, force kill it
kill(pid, SIGKILL);
// Wait for it to actually terminate
waitpid(pid, &status, 0);
} else if (result > 0) {
if (config.debug) {
printf("[DEBUG - Tunnel] SSH process terminated with status: %d\n", status);
fflush(stdout);
}
}
}
// Cleanup // Cleanup
if (active_tunnel) { if (active_tunnel) {
close(active_tunnel->local_sock); if (active_tunnel->local_sock >= 0) {
SSL_free(active_tunnel->ssl); close(active_tunnel->local_sock);
}
if (active_tunnel->ssl) {
SSL_free(active_tunnel->ssl);
}
free(active_tunnel); free(active_tunnel);
active_tunnel = NULL; active_tunnel = NULL;
} }
...@@ -787,5 +988,11 @@ int main(int argc, char *argv[]) { ...@@ -787,5 +988,11 @@ int main(int argc, char *argv[]) {
free(config_domain); free(config_domain);
pthread_mutex_destroy(&tunnel_mutex); pthread_mutex_destroy(&tunnel_mutex);
return 0; if (config.debug) {
printf("[DEBUG - Tunnel] Cleanup complete, exiting with code %d\n", tunnel_broken ? 1 : 0);
fflush(stdout);
}
// Ensure we exit the process
exit(tunnel_broken ? 1 : 0);
} }
\ No newline at end of file
...@@ -371,7 +371,8 @@ int connect_to_server(const wssshc_config_t *config) { ...@@ -371,7 +371,8 @@ int connect_to_server(const wssshc_config_t *config) {
fprintf(stderr, "SSL read error\n"); fprintf(stderr, "SSL read error\n");
} else { } else {
if (config->debug) { if (config->debug) {
printf("[DEBUG] Connection closed by server\n"); printf("[DEBUG - WebSockets] Connection closed by server\n");
fflush(stdout);
} }
} }
// Clean up tunnel resources before breaking // Clean up tunnel resources before breaking
...@@ -380,7 +381,8 @@ int connect_to_server(const wssshc_config_t *config) { ...@@ -380,7 +381,8 @@ int connect_to_server(const wssshc_config_t *config) {
} }
if (config->debug) { if (config->debug) {
printf("[DEBUG] [WebSocket] Read %d bytes, frame: 0x%02x 0x%02x 0x%02x 0x%02x\n", bytes_read, buffer[0], buffer[1], buffer[2], buffer[3]); printf("[DEBUG - WebSockets] Read %d bytes, frame: 0x%02x 0x%02x 0x%02x 0x%02x\n", bytes_read, buffer[0], buffer[1], buffer[2], buffer[3]);
fflush(stdout);
} }
// Parse WebSocket frame with extended length support // Parse WebSocket frame with extended length support
...@@ -433,7 +435,8 @@ int connect_to_server(const wssshc_config_t *config) { ...@@ -433,7 +435,8 @@ int connect_to_server(const wssshc_config_t *config) {
// Handle message // Handle message
if (config->debug) { if (config->debug) {
printf("[DEBUG] [WebSocket] Received message: %s\n", buffer); printf("[DEBUG - WebSockets] Received message: %s\n", buffer);
fflush(stdout);
} }
// Parse JSON message // Parse JSON message
...@@ -450,7 +453,8 @@ int connect_to_server(const wssshc_config_t *config) { ...@@ -450,7 +453,8 @@ int connect_to_server(const wssshc_config_t *config) {
if (close_quote) { if (close_quote) {
*close_quote = '\0'; *close_quote = '\0';
if (config->debug) { if (config->debug) {
printf("[DEBUG] [WebSocket] Received tunnel_request for ID: %s\n", id_start); printf("[DEBUG - WebSockets] Received tunnel_request for ID: %s\n", id_start);
fflush(stdout);
} }
handle_tunnel_request(ssl, id_start, config->debug); handle_tunnel_request(ssl, id_start, config->debug);
} }
...@@ -459,7 +463,8 @@ int connect_to_server(const wssshc_config_t *config) { ...@@ -459,7 +463,8 @@ int connect_to_server(const wssshc_config_t *config) {
} }
} else if (strstr(buffer, "tunnel_data")) { } else if (strstr(buffer, "tunnel_data")) {
if (config->debug) { if (config->debug) {
printf("[DEBUG] [WebSocket] Received tunnel_data message\n"); printf("[DEBUG - WebSockets] Received tunnel_data message\n");
fflush(stdout);
} }
// Extract request_id and data // Extract request_id and data
char *id_start = strstr(buffer, "\"request_id\""); char *id_start = strstr(buffer, "\"request_id\"");
...@@ -501,7 +506,8 @@ int connect_to_server(const wssshc_config_t *config) { ...@@ -501,7 +506,8 @@ int connect_to_server(const wssshc_config_t *config) {
if (close_quote) { if (close_quote) {
*close_quote = '\0'; *close_quote = '\0';
if (config->debug) { if (config->debug) {
printf("[DEBUG] [WebSocket] Received tunnel_close for ID: %s\n", id_start); printf("[DEBUG - WebSockets] Received tunnel_close for ID: %s\n", id_start);
fflush(stdout);
} }
handle_tunnel_close(ssl, id_start, config->debug); handle_tunnel_close(ssl, id_start, config->debug);
} }
...@@ -516,14 +522,16 @@ int connect_to_server(const wssshc_config_t *config) { ...@@ -516,14 +522,16 @@ int connect_to_server(const wssshc_config_t *config) {
} }
} else if (bytes_read >= 2 && (buffer[0] & 0x8F) == 0x88) { // Close frame } else if (bytes_read >= 2 && (buffer[0] & 0x8F) == 0x88) { // Close frame
if (config->debug) { if (config->debug) {
printf("[DEBUG] [WebSocket] Received close frame - cleaning up and reconnecting...\n"); printf("[DEBUG - WebSockets] Received close frame - cleaning up and reconnecting...\n");
fflush(stdout);
} }
// Clean up tunnel resources before reconnecting // Clean up tunnel resources before reconnecting
cleanup_tunnel(config->debug); cleanup_tunnel(config->debug);
return 0; return 0;
} else if (bytes_read >= 2 && (buffer[0] & 0x8F) == 0x89) { // Ping frame } else if (bytes_read >= 2 && (buffer[0] & 0x8F) == 0x89) { // Ping frame
if (config->debug) { if (config->debug) {
printf("[DEBUG] [WebSocket] Received ping frame\n"); printf("[DEBUG - WebSockets] Received ping frame\n");
fflush(stdout);
} }
// Parse ping frame and send pong with echoed payload // Parse ping frame and send pong with echoed payload
int masked = buffer[1] & 0x80; int masked = buffer[1] & 0x80;
...@@ -620,7 +628,8 @@ int connect_to_server(const wssshc_config_t *config) { ...@@ -620,7 +628,8 @@ int connect_to_server(const wssshc_config_t *config) {
int pong_frame_len = pong_header_len + (int)pong_payload_len; int pong_frame_len = pong_header_len + (int)pong_payload_len;
if (config->debug) { if (config->debug) {
printf("[DEBUG] [WebSocket] Sending pong frame, len: %d\n", pong_frame_len); printf("[DEBUG - WebSockets] Sending pong frame, len: %d\n", pong_frame_len);
fflush(stdout);
} }
if (SSL_write(ssl, pong_frame, pong_frame_len) <= 0) { if (SSL_write(ssl, pong_frame, pong_frame_len) <= 0) {
fprintf(stderr, "[ERROR] [WebSocket] Send pong failed\n"); fprintf(stderr, "[ERROR] [WebSocket] Send pong failed\n");
...@@ -681,7 +690,8 @@ int main(int argc, char *argv[]) { ...@@ -681,7 +690,8 @@ int main(int argc, char *argv[]) {
} else if (result == 0) { } else if (result == 0) {
// Close frame received - add small delay to prevent rapid reconnection // Close frame received - add small delay to prevent rapid reconnection
if (config.debug) { if (config.debug) {
printf("[DEBUG] Server initiated disconnect, reconnecting in 2 seconds...\n"); printf("[DEBUG - WebSockets] Server initiated disconnect, reconnecting in 2 seconds...\n");
fflush(stdout);
} }
sleep(2); sleep(2);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment