Fix critical VNC pipe bug and add debug logging

- Fix pipe handling in vnc.c: was writing to read end instead of write end
- Add separate read_fd/write_fd fields to vnc_session_t struct
- Add debug logging for VNC data exchange in websocket handler
- Add hex dump logging for VNC pipe communication

This resolves the 'Wrote -1 bytes to pipe' error that was preventing
VNC connections from working properly.
parent 79fa8426
...@@ -40,19 +40,29 @@ static void *read_pipe_output(void *arg) { ...@@ -40,19 +40,29 @@ static void *read_pipe_output(void *arg) {
while (1) { while (1) {
FD_ZERO(&readfds); FD_ZERO(&readfds);
FD_SET(session->master_fd, &readfds); FD_SET(session->read_fd, &readfds);
tv.tv_sec = 0; tv.tv_sec = 0;
tv.tv_usec = 100000; // 100ms timeout tv.tv_usec = 100000; // 100ms timeout
int ret = select(session->master_fd + 1, &readfds, NULL, NULL, &tv); int ret = select(session->read_fd + 1, &readfds, NULL, NULL, &tv);
if (ret < 0) break; if (ret < 0) break;
if (ret == 0) continue; // timeout if (ret == 0) continue; // timeout
if (FD_ISSET(session->master_fd, &readfds)) { if (FD_ISSET(session->read_fd, &readfds)) {
ssize_t bytes_read = read(session->master_fd, buffer, sizeof(buffer)); ssize_t bytes_read = read(session->read_fd, buffer, sizeof(buffer));
if (bytes_read <= 0) break; if (bytes_read <= 0) break;
if (session->debug_vnc) {
printf("VNC: Received %zd bytes from pipe\n", bytes_read);
// Debug: print first 20 bytes in hex
printf("VNC received data (first 20 bytes): ");
for (ssize_t i = 0; i < bytes_read && i < 20; i++) {
printf("%02x ", (unsigned char)buffer[i]);
}
printf("\n");
}
// Append to session output buffer // Append to session output buffer
pthread_mutex_lock(&session->output_mutex); pthread_mutex_lock(&session->output_mutex);
if (session->output_used + bytes_read > session->output_size) { if (session->output_used + bytes_read > session->output_size) {
...@@ -79,7 +89,7 @@ static void *read_pipe_output(void *arg) { ...@@ -79,7 +89,7 @@ static void *read_pipe_output(void *arg) {
return NULL; return NULL;
} }
vnc_session_t *vnc_create_session(const wssshd_config_t *config, const char *client_id, const char *username) { vnc_session_t *vnc_create_session(const wssshd_config_t *config, const char *client_id, const char *username, bool debug_vnc) {
vnc_session_t *session = calloc(1, sizeof(vnc_session_t)); vnc_session_t *session = calloc(1, sizeof(vnc_session_t));
if (!session) return NULL; if (!session) return NULL;
...@@ -104,6 +114,7 @@ vnc_session_t *vnc_create_session(const wssshd_config_t *config, const char *cli ...@@ -104,6 +114,7 @@ vnc_session_t *vnc_create_session(const wssshd_config_t *config, const char *cli
} }
session->output_size = 4096; session->output_size = 4096;
session->output_used = 0; session->output_used = 0;
session->debug_vnc = debug_vnc;
pthread_mutex_init(&session->output_mutex, NULL); pthread_mutex_init(&session->output_mutex, NULL);
// Create pipe for communication // Create pipe for communication
...@@ -114,7 +125,8 @@ vnc_session_t *vnc_create_session(const wssshd_config_t *config, const char *cli ...@@ -114,7 +125,8 @@ vnc_session_t *vnc_create_session(const wssshd_config_t *config, const char *cli
return NULL; return NULL;
} }
session->master_fd = pipefd[0]; // read end session->read_fd = pipefd[0]; // read end
session->write_fd = pipefd[1]; // write end
// Build command: wsssht --pipe --wssshd-port 9898 vnc://{client_id}@mbetter.nexlab.net // Build command: wsssht --pipe --wssshd-port 9898 vnc://{client_id}@mbetter.nexlab.net
char command[1024]; char command[1024];
...@@ -143,8 +155,7 @@ vnc_session_t *vnc_create_session(const wssshd_config_t *config, const char *cli ...@@ -143,8 +155,7 @@ vnc_session_t *vnc_create_session(const wssshd_config_t *config, const char *cli
_exit(1); // Should not reach here _exit(1); // Should not reach here
} }
// Parent process // Parent process keeps both ends: read_fd for reading from child, write_fd for writing to child
close(pipefd[1]); // close write end
session->proc_pid = pid; session->proc_pid = pid;
// Start output reading thread // Start output reading thread
...@@ -158,8 +169,11 @@ vnc_session_t *vnc_create_session(const wssshd_config_t *config, const char *cli ...@@ -158,8 +169,11 @@ vnc_session_t *vnc_create_session(const wssshd_config_t *config, const char *cli
void vnc_free_session(vnc_session_t *session) { void vnc_free_session(vnc_session_t *session) {
if (!session) return; if (!session) return;
if (session->master_fd >= 0) { if (session->read_fd >= 0) {
close(session->master_fd); close(session->read_fd);
}
if (session->write_fd >= 0) {
close(session->write_fd);
} }
if (session->output_buffer) { if (session->output_buffer) {
...@@ -171,14 +185,27 @@ void vnc_free_session(vnc_session_t *session) { ...@@ -171,14 +185,27 @@ void vnc_free_session(vnc_session_t *session) {
} }
bool vnc_send_data(vnc_session_t *session, const char *data, size_t len) { bool vnc_send_data(vnc_session_t *session, const char *data, size_t len) {
if (!session || session->master_fd < 0) return false; if (!session || session->write_fd < 0) return false;
// Check if process is still running // Check if process is still running
if (waitpid(session->proc_pid, NULL, WNOHANG) > 0) { if (waitpid(session->proc_pid, NULL, WNOHANG) > 0) {
return false; return false;
} }
ssize_t written = write(session->master_fd, data, len); if (session->debug_vnc) {
printf("VNC: Sending %zu bytes to pipe\n", len);
// Debug: print first 20 bytes in hex
printf("VNC send data (first 20 bytes): ");
for (size_t i = 0; i < len && i < 20; i++) {
printf("%02x ", (unsigned char)data[i]);
}
printf("\n");
}
ssize_t written = write(session->write_fd, data, len);
if (session->debug_vnc) {
printf("VNC: Wrote %zd bytes to pipe\n", written);
}
return written > 0; return written > 0;
} }
......
...@@ -29,15 +29,17 @@ typedef struct { ...@@ -29,15 +29,17 @@ typedef struct {
char client_id[256]; char client_id[256];
char username[50]; char username[50];
int proc_pid; int proc_pid;
int master_fd; // pipe fd int read_fd; // pipe read end
int write_fd; // pipe write end
bool active; bool active;
bool debug_vnc;
char *output_buffer; char *output_buffer;
size_t output_size; size_t output_size;
size_t output_used; size_t output_used;
pthread_mutex_t output_mutex; pthread_mutex_t output_mutex;
} vnc_session_t; } vnc_session_t;
vnc_session_t *vnc_create_session(const wssshd_config_t *config, const char *client_id, const char *username); vnc_session_t *vnc_create_session(const wssshd_config_t *config, const char *client_id, const char *username, bool debug_vnc);
void vnc_free_session(vnc_session_t *session); void vnc_free_session(vnc_session_t *session);
bool vnc_send_data(vnc_session_t *session, const char *data, size_t len); bool vnc_send_data(vnc_session_t *session, const char *data, size_t len);
char *vnc_get_output(vnc_session_t *session, size_t *len); char *vnc_get_output(vnc_session_t *session, size_t *len);
......
...@@ -321,7 +321,7 @@ static void *websocket_vnc_handler(void *arg) { ...@@ -321,7 +321,7 @@ static void *websocket_vnc_handler(void *arg) {
printf("[DEBUG] Launching wsssht for VNC client %s\n", ws_conn->client_id); printf("[DEBUG] Launching wsssht for VNC client %s\n", ws_conn->client_id);
} }
vnc_session_t *session = vnc_create_session(global_config, ws_conn->client_id, ws_conn->username); vnc_session_t *session = vnc_create_session(global_config, ws_conn->client_id, ws_conn->username, global_config->debug_vnc);
if (!session) { if (!session) {
printf("Failed to create VNC session for client: %s\n", ws_conn->client_id); printf("Failed to create VNC session for client: %s\n", ws_conn->client_id);
ws_send_frame(ws_conn->ws_conn, WS_OPCODE_TEXT, "{\"error\":\"Failed to launch VNC session\"}", 40); ws_send_frame(ws_conn->ws_conn, WS_OPCODE_TEXT, "{\"error\":\"Failed to launch VNC session\"}", 40);
...@@ -366,6 +366,13 @@ static void *websocket_vnc_handler(void *arg) { ...@@ -366,6 +366,13 @@ static void *websocket_vnc_handler(void *arg) {
char *output = vnc_get_output(session, &output_len); char *output = vnc_get_output(session, &output_len);
if (output && output_len > 0) { if (output && output_len > 0) {
printf("WebSocket sending %zu bytes of VNC output for request_id: %s\n", output_len, ws_conn->request_id); printf("WebSocket sending %zu bytes of VNC output for request_id: %s\n", output_len, ws_conn->request_id);
if (global_config->debug_vnc) {
printf("VNC output data (first 20 bytes): ");
for (size_t i = 0; i < output_len && i < 20; i++) {
printf("%02x ", (unsigned char)output[i]);
}
printf("\n");
}
ws_send_frame(ws_conn->ws_conn, WS_OPCODE_BINARY, output, output_len); ws_send_frame(ws_conn->ws_conn, WS_OPCODE_BINARY, output, output_len);
free(output); free(output);
} }
...@@ -379,6 +386,13 @@ static void *websocket_vnc_handler(void *arg) { ...@@ -379,6 +386,13 @@ static void *websocket_vnc_handler(void *arg) {
if (opcode == WS_OPCODE_BINARY && len > 0) { if (opcode == WS_OPCODE_BINARY && len > 0) {
// VNC input data // VNC input data
printf("WebSocket received %zu bytes of VNC input for request_id: %s\n", len, ws_conn->request_id); printf("WebSocket received %zu bytes of VNC input for request_id: %s\n", len, ws_conn->request_id);
if (global_config->debug_vnc) {
printf("VNC input data (first 20 bytes): ");
for (size_t i = 0; i < len && i < 20; i++) {
printf("%02x ", (unsigned char)((const char *)data)[i]);
}
printf("\n");
}
vnc_send_data(session, (const char *)data, len); vnc_send_data(session, (const char *)data, len);
} else if (opcode == WS_OPCODE_CLOSE) { } else if (opcode == WS_OPCODE_CLOSE) {
// Connection closed // Connection closed
......
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