Fix WebSocket masking issue in VNC connections

- Added retry logic with partial write handling to ws_send_binary_frame()
- Prevents WebSocket frame corruption during large VNC data transmission
- Fixes 'server must not mask frames' error in noVNC browser connections
- ws_send_binary_frame now handles SSL write interruptions properly
parent f141f3ab
...@@ -538,8 +538,8 @@ bool ws_send_binary_frame(ws_connection_t *conn, const void *data, size_t len) { ...@@ -538,8 +538,8 @@ bool ws_send_binary_frame(ws_connection_t *conn, const void *data, size_t len) {
return false; return false;
} }
// Simple WebSocket binary frame construction for VNC // WebSocket binary frame construction for VNC
// No masking (server-to-client), no complex retry logic // No masking (server-to-client), with retry logic for partial writes
size_t header_len = 2; size_t header_len = 2;
if (len >= 126) { if (len >= 126) {
if (len < 65536) { if (len < 65536) {
...@@ -578,12 +578,38 @@ bool ws_send_binary_frame(ws_connection_t *conn, const void *data, size_t len) { ...@@ -578,12 +578,38 @@ bool ws_send_binary_frame(ws_connection_t *conn, const void *data, size_t len) {
memcpy(frame + header_len, data, len); memcpy(frame + header_len, data, len);
} }
// Send frame // Send frame with partial write handling and retry logic
int total_written = 0; int total_written = 0;
int retry_count = 0;
const int max_retries = 5;
while (total_written < (int)frame_len && retry_count < max_retries) {
int to_write = frame_len - total_written;
int written;
if (conn->ssl) { if (conn->ssl) {
total_written = SSL_write(conn->ssl, frame, frame_len); written = SSL_write(conn->ssl, frame + total_written, to_write);
if (written <= 0) {
int ssl_error = SSL_get_error(conn->ssl, written);
// Check for recoverable SSL errors
if ((ssl_error == SSL_ERROR_WANT_READ || ssl_error == SSL_ERROR_WANT_WRITE ||
ssl_error == SSL_ERROR_SSL || ssl_error == SSL_ERROR_SYSCALL) && retry_count < max_retries - 1) {
retry_count++;
usleep(10000 * (1 << retry_count)); // Exponential backoff
continue;
} else { } else {
total_written = write(conn->sock_fd, frame, frame_len); free(frame);
return false;
}
}
} else {
written = write(conn->sock_fd, frame + total_written, to_write);
if (written <= 0) {
free(frame);
return false;
}
}
total_written += written;
retry_count = 0; // Reset retry count on successful write
} }
free(frame); free(frame);
......
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