Fix VNC WebSocket connection hanging after initial RFB handshake

- Implement bidirectional pipe communication for VNC sessions
- Replace single pipe with separate stdin/stdout pipes
- Fix child process redirection to properly handle both input and output
- Add enhanced debug logging for VNC data flow
- Update resource cleanup in vnc_free_session()

This resolves the issue where VNC connections would hang after exchanging
the first 12 bytes (RFB protocol version strings) because input from
noVNC WebSocket wasn't reaching the wsssht process.
parent 8545d971
......@@ -117,16 +117,22 @@ vnc_session_t *vnc_create_session(const wssshd_config_t *config, const char *cli
session->debug_vnc = debug_vnc;
pthread_mutex_init(&session->output_mutex, NULL);
// Create pipe for communication
int pipefd[2];
if (pipe(pipefd) < 0) {
// Create pipes for bidirectional communication
int stdout_pipe[2]; // parent reads from child stdout
int stdin_pipe[2]; // parent writes to child stdin
if (pipe(stdout_pipe) < 0 || pipe(stdin_pipe) < 0) {
if (stdout_pipe[0] >= 0) close(stdout_pipe[0]);
if (stdout_pipe[1] >= 0) close(stdout_pipe[1]);
if (stdin_pipe[0] >= 0) close(stdin_pipe[0]);
if (stdin_pipe[1] >= 0) close(stdin_pipe[1]);
free(session->output_buffer);
free(session);
return NULL;
}
session->read_fd = pipefd[0]; // read end
session->write_fd = pipefd[1]; // write end
session->read_fd = stdout_pipe[0]; // parent reads from child stdout
session->write_fd = stdin_pipe[1]; // parent writes to child stdin
// Build command: wsssht --pipe --wssshd-port 9898 vnc://{client_id}@mbetter.nexlab.net
char command[1024];
......@@ -137,25 +143,33 @@ vnc_session_t *vnc_create_session(const wssshd_config_t *config, const char *cli
// Fork and execute
pid_t pid = fork();
if (pid < 0) {
close(pipefd[0]);
close(pipefd[1]);
close(stdout_pipe[0]);
close(stdout_pipe[1]);
close(stdin_pipe[0]);
close(stdin_pipe[1]);
free(session->output_buffer);
free(session);
return NULL;
}
if (pid == 0) { // Child process
// Redirect stdout to pipe
dup2(pipefd[1], 1);
close(pipefd[0]);
close(pipefd[1]);
// Redirect stdout to stdout_pipe
dup2(stdout_pipe[1], 1);
// Redirect stdin from stdin_pipe
dup2(stdin_pipe[0], 0);
close(stdout_pipe[0]);
close(stdout_pipe[1]);
close(stdin_pipe[0]);
close(stdin_pipe[1]);
// Execute command
execl("/bin/sh", "sh", "-c", command, NULL);
_exit(1); // Should not reach here
}
// Parent process keeps both ends: read_fd for reading from child, write_fd for writing to child
// Parent process
close(stdout_pipe[1]); // close write end of stdout pipe
close(stdin_pipe[0]); // close read end of stdin pipe
session->proc_pid = pid;
// Start output reading thread
......@@ -171,13 +185,16 @@ void vnc_free_session(vnc_session_t *session) {
if (session->read_fd >= 0) {
close(session->read_fd);
session->read_fd = -1;
}
if (session->write_fd >= 0) {
close(session->write_fd);
session->write_fd = -1;
}
if (session->output_buffer) {
free(session->output_buffer);
session->output_buffer = NULL;
}
pthread_mutex_destroy(&session->output_mutex);
......
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