Proper logged version of VncGatewayWebSocketHandler
This commit is contained in:
@@ -45,7 +45,7 @@ All traffic goes through the gateway.
|
|||||||
|
|
||||||
# Technology Stack
|
# Technology Stack
|
||||||
|
|
||||||
* Java 17
|
* Java 21
|
||||||
* Spring Boot 3
|
* Spring Boot 3
|
||||||
* Spring Security
|
* Spring Security
|
||||||
* JWT (JJWT)
|
* JWT (JJWT)
|
||||||
|
|||||||
+200
-171
@@ -5,12 +5,22 @@ import com.litoralregas.backend_gateway.client.ClientRepository;
|
|||||||
import com.litoralregas.backend_gateway.security.JwtService;
|
import com.litoralregas.backend_gateway.security.JwtService;
|
||||||
import jakarta.websocket.ContainerProvider;
|
import jakarta.websocket.ContainerProvider;
|
||||||
import jakarta.websocket.WebSocketContainer;
|
import jakarta.websocket.WebSocketContainer;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.socket.*;
|
import org.springframework.web.socket.BinaryMessage;
|
||||||
|
import org.springframework.web.socket.CloseStatus;
|
||||||
|
import org.springframework.web.socket.PingMessage;
|
||||||
|
import org.springframework.web.socket.PongMessage;
|
||||||
|
import org.springframework.web.socket.TextMessage;
|
||||||
|
import org.springframework.web.socket.WebSocketMessage;
|
||||||
|
import org.springframework.web.socket.WebSocketSession;
|
||||||
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
|
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
|
||||||
import org.springframework.web.socket.handler.BinaryWebSocketHandler;
|
import org.springframework.web.socket.handler.BinaryWebSocketHandler;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.net.URLDecoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
@@ -19,6 +29,11 @@ import java.util.concurrent.ConcurrentLinkedQueue;
|
|||||||
@Component
|
@Component
|
||||||
public class VncGatewayWebSocketHandler extends BinaryWebSocketHandler {
|
public class VncGatewayWebSocketHandler extends BinaryWebSocketHandler {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(VncGatewayWebSocketHandler.class);
|
||||||
|
|
||||||
|
private static final int MAX_BINARY_MESSAGE_BUFFER_SIZE = 4 * 1024 * 1024;
|
||||||
|
private static final int MAX_TEXT_MESSAGE_BUFFER_SIZE = 1024 * 1024;
|
||||||
|
|
||||||
private final JwtService jwtService;
|
private final JwtService jwtService;
|
||||||
private final ClientRepository clientRepository;
|
private final ClientRepository clientRepository;
|
||||||
private final StandardWebSocketClient webSocketClient;
|
private final StandardWebSocketClient webSocketClient;
|
||||||
@@ -34,106 +49,94 @@ public class VncGatewayWebSocketHandler extends BinaryWebSocketHandler {
|
|||||||
this.clientRepository = clientRepository;
|
this.clientRepository = clientRepository;
|
||||||
|
|
||||||
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
|
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
|
||||||
container.setDefaultMaxBinaryMessageBufferSize(4 * 1024 * 1024);
|
container.setDefaultMaxBinaryMessageBufferSize(MAX_BINARY_MESSAGE_BUFFER_SIZE);
|
||||||
container.setDefaultMaxTextMessageBufferSize(1024 * 1024);
|
container.setDefaultMaxTextMessageBufferSize(MAX_TEXT_MESSAGE_BUFFER_SIZE);
|
||||||
|
|
||||||
this.webSocketClient = new StandardWebSocketClient(container);
|
this.webSocketClient = new StandardWebSocketClient(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterConnectionEstablished(WebSocketSession frontendSession) {
|
public void afterConnectionEstablished(WebSocketSession frontendSession) {
|
||||||
log("FRONTEND CONNECTED", frontendSession);
|
log.info(
|
||||||
System.out.println("[VNC-GATEWAY] Frontend URI: " + frontendSession.getUri());
|
"VNC frontend websocket connected. frontendSession={}, uri={}",
|
||||||
|
frontendSession.getId(),
|
||||||
|
frontendSession.getUri()
|
||||||
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String token = extractAccessToken(frontendSession);
|
String token = extractAccessToken(frontendSession);
|
||||||
|
|
||||||
if (token == null || token.isBlank()) {
|
if (token == null || token.isBlank()) {
|
||||||
System.out.println("[VNC-GATEWAY] Missing access_token");
|
log.warn("VNC frontend websocket rejected. reason=missing_token frontendSession={}", frontendSession.getId());
|
||||||
sendError(frontendSession, "Invalid or missing access token");
|
sendError(frontendSession, "Invalid or missing access token");
|
||||||
closeSafe(frontendSession, "missing token");
|
closeSafe(frontendSession, "missing token");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println("[VNC-GATEWAY] Token received. length=" + token.length());
|
|
||||||
|
|
||||||
if (!jwtService.isValid(token)) {
|
if (!jwtService.isValid(token)) {
|
||||||
System.out.println("[VNC-GATEWAY] Token invalid");
|
log.warn("VNC frontend websocket rejected. reason=invalid_token frontendSession={}", frontendSession.getId());
|
||||||
sendError(frontendSession, "Invalid or missing access token");
|
sendError(frontendSession, "Invalid or missing access token");
|
||||||
closeSafe(frontendSession, "invalid token");
|
closeSafe(frontendSession, "invalid token");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String username = jwtService.extractUsername(token);
|
|
||||||
Long userId = jwtService.extractUserId(token);
|
Long userId = jwtService.extractUserId(token);
|
||||||
Long clientId = jwtService.extractClientId(token);
|
Long clientId = jwtService.extractClientId(token);
|
||||||
|
String username = jwtService.extractUsername(token);
|
||||||
String role = jwtService.extractRole(token);
|
String role = jwtService.extractRole(token);
|
||||||
|
|
||||||
System.out.println("[VNC-GATEWAY] Token valid:");
|
|
||||||
System.out.println("[VNC-GATEWAY] username=" + username);
|
|
||||||
System.out.println("[VNC-GATEWAY] userId=" + userId);
|
|
||||||
System.out.println("[VNC-GATEWAY] clientId=" + clientId);
|
|
||||||
System.out.println("[VNC-GATEWAY] role=" + role);
|
|
||||||
|
|
||||||
ClientEntity client = clientRepository.findByIdAndEnabledTrue(clientId)
|
ClientEntity client = clientRepository.findByIdAndEnabledTrue(clientId)
|
||||||
.orElseThrow(() -> new RuntimeException("Client not found or disabled"));
|
.orElseThrow(() -> new RuntimeException("Client not found or disabled"));
|
||||||
|
|
||||||
System.out.println("[VNC-GATEWAY] Client resolved:");
|
|
||||||
System.out.println("[VNC-GATEWAY] id=" + client.getId());
|
|
||||||
System.out.println("[VNC-GATEWAY] name=" + client.getName());
|
|
||||||
System.out.println("[VNC-GATEWAY] backendBaseUrl=" + client.getBackendBaseUrl());
|
|
||||||
|
|
||||||
String backendWebSocketUrl = toBackendVncWebSocketUrl(client.getBackendBaseUrl());
|
String backendWebSocketUrl = toBackendVncWebSocketUrl(client.getBackendBaseUrl());
|
||||||
|
|
||||||
System.out.println("[VNC-GATEWAY] Backend WS target: " + backendWebSocketUrl);
|
log.info(
|
||||||
|
"Opening VNC backend websocket. frontendSession={}, userId={}, username={}, role={}, clientId={}, clientName={}, backendUrl={}",
|
||||||
|
frontendSession.getId(),
|
||||||
|
userId,
|
||||||
|
username,
|
||||||
|
role,
|
||||||
|
client.getId(),
|
||||||
|
client.getName(),
|
||||||
|
backendWebSocketUrl
|
||||||
|
);
|
||||||
|
|
||||||
webSocketClient.execute(
|
webSocketClient.execute(
|
||||||
new BackendVncBridgeHandler(frontendSession),
|
new BackendVncBridgeHandler(frontendSession),
|
||||||
backendWebSocketUrl
|
backendWebSocketUrl
|
||||||
).whenComplete((backendSession, error) -> {
|
).whenComplete((backendSession, error) -> {
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
System.out.println("[VNC-GATEWAY] Backend WS connection failed");
|
log.error(
|
||||||
System.out.println("[VNC-GATEWAY] Error type: " + error.getClass().getName());
|
"VNC backend websocket connection failed. frontendSession={}, clientId={}, backendUrl={}",
|
||||||
System.out.println("[VNC-GATEWAY] Error message: " + error.getMessage());
|
frontendSession.getId(),
|
||||||
error.printStackTrace();
|
client.getId(),
|
||||||
|
backendWebSocketUrl,
|
||||||
|
error
|
||||||
|
);
|
||||||
|
|
||||||
sendError(frontendSession, "Could not connect to backend VNC websocket");
|
sendError(frontendSession, "Could not connect to backend VNC websocket");
|
||||||
closeSafe(frontendSession, "backend ws connection failed");
|
closeSafe(frontendSession, "backend websocket connection failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println("[VNC-GATEWAY] Backend WS connected");
|
|
||||||
System.out.println("[VNC-GATEWAY] Backend session id=" + backendSession.getId());
|
|
||||||
System.out.println("[VNC-GATEWAY] Backend URI=" + backendSession.getUri());
|
|
||||||
|
|
||||||
backendSessions.put(frontendSession.getId(), backendSession);
|
backendSessions.put(frontendSession.getId(), backendSession);
|
||||||
|
|
||||||
Queue<WebSocketMessage<?>> queue =
|
log.info(
|
||||||
pendingMessages.remove(frontendSession.getId());
|
"VNC backend websocket connected. frontendSession={}, backendSession={}, backendUri={}",
|
||||||
|
frontendSession.getId(),
|
||||||
|
backendSession.getId(),
|
||||||
|
backendSession.getUri()
|
||||||
|
);
|
||||||
|
|
||||||
if (queue == null || queue.isEmpty()) {
|
flushPendingMessages(frontendSession, backendSession);
|
||||||
System.out.println("[VNC-GATEWAY] No queued frontend messages to flush");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
System.out.println("[VNC-GATEWAY] Flushing queued messages: " + queue.size());
|
|
||||||
|
|
||||||
int index = 0;
|
|
||||||
for (WebSocketMessage<?> pendingMessage : queue) {
|
|
||||||
index++;
|
|
||||||
System.out.println("[VNC-GATEWAY] Flushing queued message #" + index
|
|
||||||
+ " type=" + messageType(pendingMessage)
|
|
||||||
+ " size=" + payloadLength(pendingMessage));
|
|
||||||
|
|
||||||
sendSafe(backendSession, pendingMessage, "flush queued frontend -> backend");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (Exception error) {
|
} catch (Exception error) {
|
||||||
System.out.println("[VNC-GATEWAY] Frontend connection setup failed");
|
log.error(
|
||||||
System.out.println("[VNC-GATEWAY] Error type: " + error.getClass().getName());
|
"VNC frontend websocket setup failed. frontendSession={}",
|
||||||
System.out.println("[VNC-GATEWAY] Error message: " + error.getMessage());
|
frontendSession.getId(),
|
||||||
error.printStackTrace();
|
error
|
||||||
|
);
|
||||||
|
|
||||||
sendError(frontendSession, error.getMessage());
|
sendError(frontendSession, error.getMessage());
|
||||||
closeSafe(frontendSession, "setup exception");
|
closeSafe(frontendSession, "setup exception");
|
||||||
@@ -145,10 +148,11 @@ public class VncGatewayWebSocketHandler extends BinaryWebSocketHandler {
|
|||||||
WebSocketSession frontendSession,
|
WebSocketSession frontendSession,
|
||||||
TextMessage message
|
TextMessage message
|
||||||
) {
|
) {
|
||||||
System.out.println("[VNC-GATEWAY] Frontend TEXT message:"
|
log.debug(
|
||||||
+ " session=" + frontendSession.getId()
|
"VNC frontend text message received. frontendSession={}, size={}",
|
||||||
+ " size=" + message.getPayloadLength()
|
frontendSession.getId(),
|
||||||
+ " payload=" + truncate(message.getPayload()));
|
message.getPayloadLength()
|
||||||
|
);
|
||||||
|
|
||||||
forwardOrQueue(frontendSession, message);
|
forwardOrQueue(frontendSession, message);
|
||||||
}
|
}
|
||||||
@@ -158,48 +162,25 @@ public class VncGatewayWebSocketHandler extends BinaryWebSocketHandler {
|
|||||||
WebSocketSession frontendSession,
|
WebSocketSession frontendSession,
|
||||||
BinaryMessage message
|
BinaryMessage message
|
||||||
) {
|
) {
|
||||||
System.out.println("[VNC-GATEWAY] Frontend BINARY message:"
|
log.debug(
|
||||||
+ " session=" + frontendSession.getId()
|
"VNC frontend binary message received. frontendSession={}, size={}",
|
||||||
+ " size=" + message.getPayloadLength());
|
frontendSession.getId(),
|
||||||
|
message.getPayloadLength()
|
||||||
|
);
|
||||||
|
|
||||||
forwardOrQueue(frontendSession, message);
|
forwardOrQueue(frontendSession, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void forwardOrQueue(
|
|
||||||
WebSocketSession frontendSession,
|
|
||||||
WebSocketMessage<?> message
|
|
||||||
) {
|
|
||||||
WebSocketSession backendSession = backendSessions.get(frontendSession.getId());
|
|
||||||
|
|
||||||
if (backendSession != null && backendSession.isOpen()) {
|
|
||||||
System.out.println("[VNC-GATEWAY] Forwarding frontend -> backend:"
|
|
||||||
+ " type=" + messageType(message)
|
|
||||||
+ " size=" + payloadLength(message));
|
|
||||||
|
|
||||||
sendSafe(backendSession, message, "frontend -> backend");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Queue<WebSocketMessage<?>> queue = pendingMessages
|
|
||||||
.computeIfAbsent(frontendSession.getId(), id -> new ConcurrentLinkedQueue<>());
|
|
||||||
|
|
||||||
queue.add(message);
|
|
||||||
|
|
||||||
System.out.println("[VNC-GATEWAY] Backend not ready. Queued frontend message:"
|
|
||||||
+ " session=" + frontendSession.getId()
|
|
||||||
+ " queueSize=" + queue.size()
|
|
||||||
+ " type=" + messageType(message)
|
|
||||||
+ " size=" + payloadLength(message));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterConnectionClosed(
|
public void afterConnectionClosed(
|
||||||
WebSocketSession frontendSession,
|
WebSocketSession frontendSession,
|
||||||
CloseStatus status
|
CloseStatus status
|
||||||
) {
|
) {
|
||||||
System.out.println("[VNC-GATEWAY] Frontend WS closed:"
|
log.info(
|
||||||
+ " session=" + frontendSession.getId()
|
"VNC frontend websocket closed. frontendSession={}, status={}",
|
||||||
+ " status=" + status);
|
frontendSession.getId(),
|
||||||
|
status
|
||||||
|
);
|
||||||
|
|
||||||
pendingMessages.remove(frontendSession.getId());
|
pendingMessages.remove(frontendSession.getId());
|
||||||
|
|
||||||
@@ -215,32 +196,85 @@ public class VncGatewayWebSocketHandler extends BinaryWebSocketHandler {
|
|||||||
WebSocketSession frontendSession,
|
WebSocketSession frontendSession,
|
||||||
Throwable exception
|
Throwable exception
|
||||||
) {
|
) {
|
||||||
System.out.println("[VNC-GATEWAY] Frontend transport error:"
|
log.error(
|
||||||
+ " session=" + frontendSession.getId()
|
"VNC frontend websocket transport error. frontendSession={}",
|
||||||
+ " error=" + exception.getClass().getName()
|
frontendSession.getId(),
|
||||||
+ ": " + exception.getMessage());
|
exception
|
||||||
|
);
|
||||||
exception.printStackTrace();
|
|
||||||
|
|
||||||
pendingMessages.remove(frontendSession.getId());
|
pendingMessages.remove(frontendSession.getId());
|
||||||
|
|
||||||
WebSocketSession backendSession = backendSessions.remove(frontendSession.getId());
|
WebSocketSession backendSession = backendSessions.remove(frontendSession.getId());
|
||||||
|
|
||||||
closeSafe(backendSession, "frontend transport error");
|
closeSafe(backendSession, "frontend transport error");
|
||||||
closeSafe(frontendSession, "frontend transport error");
|
closeSafe(frontendSession, "frontend transport error");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void forwardOrQueue(
|
||||||
|
WebSocketSession frontendSession,
|
||||||
|
WebSocketMessage<?> message
|
||||||
|
) {
|
||||||
|
WebSocketSession backendSession = backendSessions.get(frontendSession.getId());
|
||||||
|
|
||||||
|
if (backendSession != null && backendSession.isOpen()) {
|
||||||
|
log.debug(
|
||||||
|
"Forwarding VNC message frontend -> backend. frontendSession={}, backendSession={}, type={}, size={}",
|
||||||
|
frontendSession.getId(),
|
||||||
|
backendSession.getId(),
|
||||||
|
messageType(message),
|
||||||
|
payloadLength(message)
|
||||||
|
);
|
||||||
|
|
||||||
|
sendSafe(backendSession, message, "frontend -> backend");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Queue<WebSocketMessage<?>> queue = pendingMessages
|
||||||
|
.computeIfAbsent(frontendSession.getId(), id -> new ConcurrentLinkedQueue<>());
|
||||||
|
|
||||||
|
queue.add(message);
|
||||||
|
|
||||||
|
log.debug(
|
||||||
|
"Queued VNC frontend message because backend is not ready. frontendSession={}, queueSize={}, type={}, size={}",
|
||||||
|
frontendSession.getId(),
|
||||||
|
queue.size(),
|
||||||
|
messageType(message),
|
||||||
|
payloadLength(message)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void flushPendingMessages(
|
||||||
|
WebSocketSession frontendSession,
|
||||||
|
WebSocketSession backendSession
|
||||||
|
) {
|
||||||
|
Queue<WebSocketMessage<?>> queue = pendingMessages.remove(frontendSession.getId());
|
||||||
|
|
||||||
|
if (queue == null || queue.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info(
|
||||||
|
"Flushing queued VNC frontend messages. frontendSession={}, backendSession={}, count={}",
|
||||||
|
frontendSession.getId(),
|
||||||
|
backendSession.getId(),
|
||||||
|
queue.size()
|
||||||
|
);
|
||||||
|
|
||||||
|
for (WebSocketMessage<?> pendingMessage : queue) {
|
||||||
|
sendSafe(backendSession, pendingMessage, "flush queued frontend -> backend");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private String extractAccessToken(WebSocketSession session) {
|
private String extractAccessToken(WebSocketSession session) {
|
||||||
URI uri = session.getUri();
|
URI uri = session.getUri();
|
||||||
|
|
||||||
if (uri == null) {
|
if (uri == null) {
|
||||||
System.out.println("[VNC-GATEWAY] Session URI is null");
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String query = uri.getQuery();
|
String query = uri.getQuery();
|
||||||
|
|
||||||
if (query == null || query.isBlank()) {
|
if (query == null || query.isBlank()) {
|
||||||
System.out.println("[VNC-GATEWAY] Session query is empty");
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,10 +284,7 @@ public class VncGatewayWebSocketHandler extends BinaryWebSocketHandler {
|
|||||||
String[] parts = param.split("=", 2);
|
String[] parts = param.split("=", 2);
|
||||||
|
|
||||||
if (parts.length == 2 && parts[0].equals("access_token")) {
|
if (parts.length == 2 && parts[0].equals("access_token")) {
|
||||||
return java.net.URLDecoder.decode(
|
return URLDecoder.decode(parts[1], StandardCharsets.UTF_8);
|
||||||
parts[1],
|
|
||||||
java.nio.charset.StandardCharsets.UTF_8
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,7 +292,11 @@ public class VncGatewayWebSocketHandler extends BinaryWebSocketHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String toBackendVncWebSocketUrl(String backendBaseUrl) {
|
private String toBackendVncWebSocketUrl(String backendBaseUrl) {
|
||||||
String wsBaseUrl = backendBaseUrl
|
String normalizedBaseUrl = backendBaseUrl.endsWith("/")
|
||||||
|
? backendBaseUrl.substring(0, backendBaseUrl.length() - 1)
|
||||||
|
: backendBaseUrl;
|
||||||
|
|
||||||
|
String wsBaseUrl = normalizedBaseUrl
|
||||||
.replaceFirst("^http://", "ws://")
|
.replaceFirst("^http://", "ws://")
|
||||||
.replaceFirst("^https://", "wss://");
|
.replaceFirst("^https://", "wss://");
|
||||||
|
|
||||||
@@ -270,7 +305,6 @@ public class VncGatewayWebSocketHandler extends BinaryWebSocketHandler {
|
|||||||
|
|
||||||
private void sendError(WebSocketSession session, String message) {
|
private void sendError(WebSocketSession session, String message) {
|
||||||
if (session == null || !session.isOpen()) {
|
if (session == null || !session.isOpen()) {
|
||||||
System.out.println("[VNC-GATEWAY] Cannot send error, session closed/null: " + message);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,8 +313,6 @@ public class VncGatewayWebSocketHandler extends BinaryWebSocketHandler {
|
|||||||
safeJson(message == null ? "Unknown websocket error" : message) +
|
safeJson(message == null ? "Unknown websocket error" : message) +
|
||||||
"\"}";
|
"\"}";
|
||||||
|
|
||||||
System.out.println("[VNC-GATEWAY] Sending error to frontend: " + payload);
|
|
||||||
|
|
||||||
sendSafe(session, new TextMessage(payload), "send error");
|
sendSafe(session, new TextMessage(payload), "send error");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,14 +329,16 @@ public class VncGatewayWebSocketHandler extends BinaryWebSocketHandler {
|
|||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
if (session == null) {
|
if (session == null) {
|
||||||
System.out.println("[VNC-GATEWAY] sendSafe skipped, session null. direction=" + direction);
|
log.debug("VNC websocket send skipped because session is null. direction={}", direction);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!session.isOpen()) {
|
if (!session.isOpen()) {
|
||||||
System.out.println("[VNC-GATEWAY] sendSafe skipped, session closed."
|
log.debug(
|
||||||
+ " direction=" + direction
|
"VNC websocket send skipped because session is closed. direction={}, session={}",
|
||||||
+ " session=" + session.getId());
|
direction,
|
||||||
|
session.getId()
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,49 +346,50 @@ public class VncGatewayWebSocketHandler extends BinaryWebSocketHandler {
|
|||||||
session.sendMessage(message);
|
session.sendMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println("[VNC-GATEWAY] Sent message:"
|
log.debug(
|
||||||
+ " direction=" + direction
|
"VNC websocket message sent. direction={}, session={}, type={}, size={}",
|
||||||
+ " session=" + session.getId()
|
direction,
|
||||||
+ " type=" + messageType(message)
|
session.getId(),
|
||||||
+ " size=" + payloadLength(message));
|
messageType(message),
|
||||||
|
payloadLength(message)
|
||||||
|
);
|
||||||
|
|
||||||
} catch (IllegalStateException closed) {
|
} catch (IllegalStateException closed) {
|
||||||
System.out.println("[VNC-GATEWAY] send skipped, session already closed. direction=" + direction);
|
log.debug("VNC websocket send skipped because session was already closed. direction={}", direction);
|
||||||
} catch (Exception error) {
|
} catch (Exception error) {
|
||||||
System.out.println("[VNC-GATEWAY] send failed: " + direction + " " + error.getMessage());
|
log.warn(
|
||||||
|
"VNC websocket send failed. direction={}, session={}",
|
||||||
|
direction,
|
||||||
|
session == null ? "null" : session.getId(),
|
||||||
|
error
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void closeSafe(WebSocketSession session, String reason) {
|
private void closeSafe(WebSocketSession session, String reason) {
|
||||||
try {
|
try {
|
||||||
if (session == null) {
|
if (session == null || !session.isOpen()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!session.isOpen()) {
|
log.debug(
|
||||||
return;
|
"Closing VNC websocket session. session={}, reason={}",
|
||||||
}
|
session.getId(),
|
||||||
|
reason
|
||||||
System.out.println("[VNC-GATEWAY] Closing session:"
|
);
|
||||||
+ " session=" + session.getId()
|
|
||||||
+ " reason=" + reason);
|
|
||||||
|
|
||||||
session.close();
|
session.close();
|
||||||
|
|
||||||
} catch (Exception error) {
|
} catch (Exception error) {
|
||||||
System.out.println("[VNC-GATEWAY] closeSafe failed:"
|
log.warn(
|
||||||
+ " reason=" + reason
|
"Failed to close VNC websocket session. reason={}, session={}",
|
||||||
+ " error=" + error.getClass().getName()
|
reason,
|
||||||
+ ": " + error.getMessage());
|
session == null ? "null" : session.getId(),
|
||||||
|
error
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void log(String event, WebSocketSession session) {
|
|
||||||
System.out.println("[VNC-GATEWAY] " + event
|
|
||||||
+ " session=" + (session == null ? "null" : session.getId())
|
|
||||||
+ " open=" + (session != null && session.isOpen()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private String messageType(WebSocketMessage<?> message) {
|
private String messageType(WebSocketMessage<?> message) {
|
||||||
if (message instanceof TextMessage) {
|
if (message instanceof TextMessage) {
|
||||||
return "TEXT";
|
return "TEXT";
|
||||||
@@ -383,20 +418,6 @@ public class VncGatewayWebSocketHandler extends BinaryWebSocketHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String truncate(String value) {
|
|
||||||
if (value == null) {
|
|
||||||
return "null";
|
|
||||||
}
|
|
||||||
|
|
||||||
int max = 300;
|
|
||||||
|
|
||||||
if (value.length() <= max) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return value.substring(0, max) + "...";
|
|
||||||
}
|
|
||||||
|
|
||||||
private class BackendVncBridgeHandler extends BinaryWebSocketHandler {
|
private class BackendVncBridgeHandler extends BinaryWebSocketHandler {
|
||||||
|
|
||||||
private final WebSocketSession frontendSession;
|
private final WebSocketSession frontendSession;
|
||||||
@@ -407,10 +428,12 @@ public class VncGatewayWebSocketHandler extends BinaryWebSocketHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterConnectionEstablished(WebSocketSession backendSession) {
|
public void afterConnectionEstablished(WebSocketSession backendSession) {
|
||||||
System.out.println("[VNC-GATEWAY] Backend handler established:"
|
log.debug(
|
||||||
+ " backendSession=" + backendSession.getId()
|
"VNC backend bridge handler established. frontendSession={}, backendSession={}, backendUri={}",
|
||||||
+ " frontendSession=" + frontendSession.getId()
|
frontendSession.getId(),
|
||||||
+ " backendUri=" + backendSession.getUri());
|
backendSession.getId(),
|
||||||
|
backendSession.getUri()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -418,10 +441,12 @@ public class VncGatewayWebSocketHandler extends BinaryWebSocketHandler {
|
|||||||
WebSocketSession backendSession,
|
WebSocketSession backendSession,
|
||||||
TextMessage message
|
TextMessage message
|
||||||
) {
|
) {
|
||||||
System.out.println("[VNC-GATEWAY] Backend TEXT message:"
|
log.debug(
|
||||||
+ " backendSession=" + backendSession.getId()
|
"VNC backend text message received. backendSession={}, frontendSession={}, size={}",
|
||||||
+ " size=" + message.getPayloadLength()
|
backendSession.getId(),
|
||||||
+ " payload=" + truncate(message.getPayload()));
|
frontendSession.getId(),
|
||||||
|
message.getPayloadLength()
|
||||||
|
);
|
||||||
|
|
||||||
sendSafe(frontendSession, message, "backend -> frontend");
|
sendSafe(frontendSession, message, "backend -> frontend");
|
||||||
}
|
}
|
||||||
@@ -431,9 +456,12 @@ public class VncGatewayWebSocketHandler extends BinaryWebSocketHandler {
|
|||||||
WebSocketSession backendSession,
|
WebSocketSession backendSession,
|
||||||
BinaryMessage message
|
BinaryMessage message
|
||||||
) {
|
) {
|
||||||
System.out.println("[VNC-GATEWAY] Backend BINARY message:"
|
log.debug(
|
||||||
+ " backendSession=" + backendSession.getId()
|
"VNC backend binary message received. backendSession={}, frontendSession={}, size={}",
|
||||||
+ " size=" + message.getPayloadLength());
|
backendSession.getId(),
|
||||||
|
frontendSession.getId(),
|
||||||
|
message.getPayloadLength()
|
||||||
|
);
|
||||||
|
|
||||||
sendSafe(frontendSession, message, "backend -> frontend");
|
sendSafe(frontendSession, message, "backend -> frontend");
|
||||||
}
|
}
|
||||||
@@ -443,10 +471,12 @@ public class VncGatewayWebSocketHandler extends BinaryWebSocketHandler {
|
|||||||
WebSocketSession backendSession,
|
WebSocketSession backendSession,
|
||||||
CloseStatus status
|
CloseStatus status
|
||||||
) {
|
) {
|
||||||
System.out.println("[VNC-GATEWAY] Backend WS closed:"
|
log.info(
|
||||||
+ " backendSession=" + backendSession.getId()
|
"VNC backend websocket closed. backendSession={}, frontendSession={}, status={}",
|
||||||
+ " frontendSession=" + frontendSession.getId()
|
backendSession.getId(),
|
||||||
+ " status=" + status);
|
frontendSession.getId(),
|
||||||
|
status
|
||||||
|
);
|
||||||
|
|
||||||
backendSessions.remove(frontendSession.getId());
|
backendSessions.remove(frontendSession.getId());
|
||||||
pendingMessages.remove(frontendSession.getId());
|
pendingMessages.remove(frontendSession.getId());
|
||||||
@@ -459,13 +489,12 @@ public class VncGatewayWebSocketHandler extends BinaryWebSocketHandler {
|
|||||||
WebSocketSession backendSession,
|
WebSocketSession backendSession,
|
||||||
Throwable exception
|
Throwable exception
|
||||||
) {
|
) {
|
||||||
System.out.println("[VNC-GATEWAY] Backend transport error:"
|
log.error(
|
||||||
+ " backendSession=" + backendSession.getId()
|
"VNC backend websocket transport error. backendSession={}, frontendSession={}",
|
||||||
+ " frontendSession=" + frontendSession.getId()
|
backendSession.getId(),
|
||||||
+ " error=" + exception.getClass().getName()
|
frontendSession.getId(),
|
||||||
+ ": " + exception.getMessage());
|
exception
|
||||||
|
);
|
||||||
exception.printStackTrace();
|
|
||||||
|
|
||||||
sendError(frontendSession, "Backend websocket transport error");
|
sendError(frontendSession, "Backend websocket transport error");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user