mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUAC-906: Implement GuacamoleConnectionClosedException. Throw when read/write fails due to closure.
This commit is contained in:
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Glyptodon LLC
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.glyptodon.guacamole;
|
||||||
|
|
||||||
|
import org.glyptodon.guacamole.protocol.GuacamoleStatus;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An exception which is thrown when an operation cannot be performed because
|
||||||
|
* its corresponding connection is closed.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
public class GuacamoleConnectionClosedException extends GuacamoleServerException {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new GuacamoleConnectionClosedException with the given message
|
||||||
|
* and cause.
|
||||||
|
*
|
||||||
|
* @param message A human readable description of the exception that
|
||||||
|
* occurred.
|
||||||
|
* @param cause The cause of this exception.
|
||||||
|
*/
|
||||||
|
public GuacamoleConnectionClosedException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new GuacamoleConnectionClosedException with the given message.
|
||||||
|
*
|
||||||
|
* @param message A human readable description of the exception that
|
||||||
|
* occurred.
|
||||||
|
*/
|
||||||
|
public GuacamoleConnectionClosedException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new GuacamoleConnectionClosedException with the given cause.
|
||||||
|
*
|
||||||
|
* @param cause The cause of this exception.
|
||||||
|
*/
|
||||||
|
public GuacamoleConnectionClosedException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GuacamoleStatus getStatus() {
|
||||||
|
return GuacamoleStatus.SERVER_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -25,9 +25,11 @@ package org.glyptodon.guacamole.io;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
|
import java.net.SocketException;
|
||||||
import java.net.SocketTimeoutException;
|
import java.net.SocketTimeoutException;
|
||||||
import java.util.Deque;
|
import java.util.Deque;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
import org.glyptodon.guacamole.GuacamoleConnectionClosedException;
|
||||||
import org.glyptodon.guacamole.GuacamoleException;
|
import org.glyptodon.guacamole.GuacamoleException;
|
||||||
import org.glyptodon.guacamole.GuacamoleServerException;
|
import org.glyptodon.guacamole.GuacamoleServerException;
|
||||||
import org.glyptodon.guacamole.GuacamoleUpstreamTimeoutException;
|
import org.glyptodon.guacamole.GuacamoleUpstreamTimeoutException;
|
||||||
@@ -182,6 +184,9 @@ public class ReaderGuacamoleReader implements GuacamoleReader {
|
|||||||
catch (SocketTimeoutException e) {
|
catch (SocketTimeoutException e) {
|
||||||
throw new GuacamoleUpstreamTimeoutException("Connection to guacd timed out.", e);
|
throw new GuacamoleUpstreamTimeoutException("Connection to guacd timed out.", e);
|
||||||
}
|
}
|
||||||
|
catch (SocketException e) {
|
||||||
|
throw new GuacamoleConnectionClosedException("Connection to guacd is closed.", e);
|
||||||
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
throw new GuacamoleServerException(e);
|
throw new GuacamoleServerException(e);
|
||||||
}
|
}
|
||||||
|
@@ -25,8 +25,12 @@ package org.glyptodon.guacamole.io;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
|
import java.net.SocketException;
|
||||||
|
import java.net.SocketTimeoutException;
|
||||||
|
import org.glyptodon.guacamole.GuacamoleConnectionClosedException;
|
||||||
import org.glyptodon.guacamole.GuacamoleException;
|
import org.glyptodon.guacamole.GuacamoleException;
|
||||||
import org.glyptodon.guacamole.GuacamoleServerException;
|
import org.glyptodon.guacamole.GuacamoleServerException;
|
||||||
|
import org.glyptodon.guacamole.GuacamoleUpstreamTimeoutException;
|
||||||
import org.glyptodon.guacamole.protocol.GuacamoleInstruction;
|
import org.glyptodon.guacamole.protocol.GuacamoleInstruction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -58,6 +62,12 @@ public class WriterGuacamoleWriter implements GuacamoleWriter {
|
|||||||
output.write(chunk, off, len);
|
output.write(chunk, off, len);
|
||||||
output.flush();
|
output.flush();
|
||||||
}
|
}
|
||||||
|
catch (SocketTimeoutException e) {
|
||||||
|
throw new GuacamoleUpstreamTimeoutException("Connection to guacd timed out.", e);
|
||||||
|
}
|
||||||
|
catch (SocketException e) {
|
||||||
|
throw new GuacamoleConnectionClosedException("Connection to guacd is closed.", e);
|
||||||
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
throw new GuacamoleServerException(e);
|
throw new GuacamoleServerException(e);
|
||||||
}
|
}
|
||||||
|
@@ -35,9 +35,9 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import javax.servlet.http.HttpSession;
|
import javax.servlet.http.HttpSession;
|
||||||
import org.glyptodon.guacamole.GuacamoleClientException;
|
import org.glyptodon.guacamole.GuacamoleClientException;
|
||||||
|
import org.glyptodon.guacamole.GuacamoleConnectionClosedException;
|
||||||
import org.glyptodon.guacamole.GuacamoleException;
|
import org.glyptodon.guacamole.GuacamoleException;
|
||||||
import org.glyptodon.guacamole.GuacamoleResourceNotFoundException;
|
import org.glyptodon.guacamole.GuacamoleResourceNotFoundException;
|
||||||
import org.glyptodon.guacamole.GuacamoleSecurityException;
|
|
||||||
import org.glyptodon.guacamole.GuacamoleServerException;
|
import org.glyptodon.guacamole.GuacamoleServerException;
|
||||||
import org.glyptodon.guacamole.io.GuacamoleReader;
|
import org.glyptodon.guacamole.io.GuacamoleReader;
|
||||||
import org.glyptodon.guacamole.io.GuacamoleWriter;
|
import org.glyptodon.guacamole.io.GuacamoleWriter;
|
||||||
@@ -287,7 +287,7 @@ public abstract class GuacamoleHTTPTunnelServlet extends HttpServlet {
|
|||||||
// data yet.
|
// data yet.
|
||||||
char[] message = reader.read();
|
char[] message = reader.read();
|
||||||
if (message == null)
|
if (message == null)
|
||||||
throw new GuacamoleResourceNotFoundException("Tunnel reached end of stream.");
|
throw new GuacamoleConnectionClosedException("Tunnel reached end of stream.");
|
||||||
|
|
||||||
// For all messages, until another stream is ready (we send at least one message)
|
// For all messages, until another stream is ready (we send at least one message)
|
||||||
do {
|
do {
|
||||||
@@ -317,20 +317,28 @@ public abstract class GuacamoleHTTPTunnelServlet extends HttpServlet {
|
|||||||
response.flushBuffer();
|
response.flushBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send end-of-stream marker if connection is closed
|
||||||
|
catch (GuacamoleConnectionClosedException e) {
|
||||||
|
out.write("0.;");
|
||||||
|
out.flush();
|
||||||
|
response.flushBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (GuacamoleException e) {
|
||||||
|
|
||||||
|
// Detach and close
|
||||||
|
session.detachTunnel(tunnel);
|
||||||
|
tunnel.close();
|
||||||
|
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
// Always close output stream
|
// Always close output stream
|
||||||
finally {
|
finally {
|
||||||
out.close();
|
out.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (GuacamoleException e) {
|
|
||||||
|
|
||||||
// Detach and close
|
|
||||||
session.detachTunnel(tunnel);
|
|
||||||
tunnel.close();
|
|
||||||
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
|
|
||||||
// Log typically frequent I/O error if desired
|
// Log typically frequent I/O error if desired
|
||||||
@@ -411,6 +419,9 @@ public abstract class GuacamoleHTTPTunnelServlet extends HttpServlet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
catch (GuacamoleConnectionClosedException e) {
|
||||||
|
logger.debug("Connection closed.", e);
|
||||||
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
|
|
||||||
// Detach and close
|
// Detach and close
|
||||||
|
@@ -38,6 +38,7 @@ import org.glyptodon.guacamole.io.GuacamoleReader;
|
|||||||
import org.glyptodon.guacamole.io.GuacamoleWriter;
|
import org.glyptodon.guacamole.io.GuacamoleWriter;
|
||||||
import org.glyptodon.guacamole.net.GuacamoleTunnel;
|
import org.glyptodon.guacamole.net.GuacamoleTunnel;
|
||||||
import org.glyptodon.guacamole.GuacamoleClientException;
|
import org.glyptodon.guacamole.GuacamoleClientException;
|
||||||
|
import org.glyptodon.guacamole.GuacamoleConnectionClosedException;
|
||||||
import org.glyptodon.guacamole.protocol.GuacamoleStatus;
|
import org.glyptodon.guacamole.protocol.GuacamoleStatus;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -178,6 +179,10 @@ public abstract class GuacamoleWebSocketTunnelEndpoint extends Endpoint {
|
|||||||
logger.warn("Client request rejected: {}", e.getMessage());
|
logger.warn("Client request rejected: {}", e.getMessage());
|
||||||
closeConnection(session, e.getStatus());
|
closeConnection(session, e.getStatus());
|
||||||
}
|
}
|
||||||
|
catch (GuacamoleConnectionClosedException e) {
|
||||||
|
logger.debug("Connection closed.", e);
|
||||||
|
closeConnection(session, GuacamoleStatus.SUCCESS);
|
||||||
|
}
|
||||||
catch (GuacamoleException e) {
|
catch (GuacamoleException e) {
|
||||||
logger.error("Internal server error.", e);
|
logger.error("Internal server error.", e);
|
||||||
closeConnection(session, e.getStatus());
|
closeConnection(session, e.getStatus());
|
||||||
@@ -205,6 +210,9 @@ public abstract class GuacamoleWebSocketTunnelEndpoint extends Endpoint {
|
|||||||
// Write received message
|
// Write received message
|
||||||
writer.write(message.toCharArray());
|
writer.write(message.toCharArray());
|
||||||
}
|
}
|
||||||
|
catch (GuacamoleConnectionClosedException e) {
|
||||||
|
logger.debug("Connection closed.", e);
|
||||||
|
}
|
||||||
catch (GuacamoleException e) {
|
catch (GuacamoleException e) {
|
||||||
logger.debug("Tunnel write failed.", e);
|
logger.debug("Tunnel write failed.", e);
|
||||||
}
|
}
|
||||||
|
@@ -32,6 +32,7 @@ import org.eclipse.jetty.websocket.WebSocket;
|
|||||||
import org.eclipse.jetty.websocket.WebSocket.Connection;
|
import org.eclipse.jetty.websocket.WebSocket.Connection;
|
||||||
import org.eclipse.jetty.websocket.WebSocketServlet;
|
import org.eclipse.jetty.websocket.WebSocketServlet;
|
||||||
import org.glyptodon.guacamole.GuacamoleClientException;
|
import org.glyptodon.guacamole.GuacamoleClientException;
|
||||||
|
import org.glyptodon.guacamole.GuacamoleConnectionClosedException;
|
||||||
import org.glyptodon.guacamole.protocol.GuacamoleStatus;
|
import org.glyptodon.guacamole.protocol.GuacamoleStatus;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -93,6 +94,9 @@ public abstract class GuacamoleWebSocketTunnelServlet extends WebSocketServlet {
|
|||||||
try {
|
try {
|
||||||
writer.write(string.toCharArray());
|
writer.write(string.toCharArray());
|
||||||
}
|
}
|
||||||
|
catch (GuacamoleConnectionClosedException e) {
|
||||||
|
logger.debug("Connection closed.", e);
|
||||||
|
}
|
||||||
catch (GuacamoleException e) {
|
catch (GuacamoleException e) {
|
||||||
logger.debug("Tunnel write failed.", e);
|
logger.debug("Tunnel write failed.", e);
|
||||||
}
|
}
|
||||||
@@ -148,6 +152,10 @@ public abstract class GuacamoleWebSocketTunnelServlet extends WebSocketServlet {
|
|||||||
logger.warn("Client request rejected: {}", e.getMessage());
|
logger.warn("Client request rejected: {}", e.getMessage());
|
||||||
closeConnection(connection, e.getStatus());
|
closeConnection(connection, e.getStatus());
|
||||||
}
|
}
|
||||||
|
catch (GuacamoleConnectionClosedException e) {
|
||||||
|
logger.debug("Connection closed.", e);
|
||||||
|
closeConnection(connection, GuacamoleStatus.SUCCESS);
|
||||||
|
}
|
||||||
catch (GuacamoleException e) {
|
catch (GuacamoleException e) {
|
||||||
logger.error("Internal server error.", e);
|
logger.error("Internal server error.", e);
|
||||||
closeConnection(connection, e.getStatus());
|
closeConnection(connection, e.getStatus());
|
||||||
|
@@ -28,6 +28,7 @@ import org.eclipse.jetty.websocket.api.RemoteEndpoint;
|
|||||||
import org.eclipse.jetty.websocket.api.Session;
|
import org.eclipse.jetty.websocket.api.Session;
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketListener;
|
import org.eclipse.jetty.websocket.api.WebSocketListener;
|
||||||
import org.glyptodon.guacamole.GuacamoleClientException;
|
import org.glyptodon.guacamole.GuacamoleClientException;
|
||||||
|
import org.glyptodon.guacamole.GuacamoleConnectionClosedException;
|
||||||
import org.glyptodon.guacamole.GuacamoleException;
|
import org.glyptodon.guacamole.GuacamoleException;
|
||||||
import org.glyptodon.guacamole.io.GuacamoleReader;
|
import org.glyptodon.guacamole.io.GuacamoleReader;
|
||||||
import org.glyptodon.guacamole.io.GuacamoleWriter;
|
import org.glyptodon.guacamole.io.GuacamoleWriter;
|
||||||
@@ -164,6 +165,10 @@ public abstract class GuacamoleWebSocketTunnelListener implements WebSocketListe
|
|||||||
logger.warn("Client request rejected: {}", e.getMessage());
|
logger.warn("Client request rejected: {}", e.getMessage());
|
||||||
closeConnection(session, e.getStatus());
|
closeConnection(session, e.getStatus());
|
||||||
}
|
}
|
||||||
|
catch (GuacamoleConnectionClosedException e) {
|
||||||
|
logger.debug("Connection closed.", e);
|
||||||
|
closeConnection(session, GuacamoleStatus.SUCCESS);
|
||||||
|
}
|
||||||
catch (GuacamoleException e) {
|
catch (GuacamoleException e) {
|
||||||
logger.error("Internal server error.", e);
|
logger.error("Internal server error.", e);
|
||||||
closeConnection(session, e.getStatus());
|
closeConnection(session, e.getStatus());
|
||||||
@@ -191,6 +196,9 @@ public abstract class GuacamoleWebSocketTunnelListener implements WebSocketListe
|
|||||||
// Write received message
|
// Write received message
|
||||||
writer.write(message.toCharArray());
|
writer.write(message.toCharArray());
|
||||||
}
|
}
|
||||||
|
catch (GuacamoleConnectionClosedException e) {
|
||||||
|
logger.debug("Connection closed.", e);
|
||||||
|
}
|
||||||
catch (GuacamoleException e) {
|
catch (GuacamoleException e) {
|
||||||
logger.debug("Tunnel write failed.", e);
|
logger.debug("Tunnel write failed.", e);
|
||||||
}
|
}
|
||||||
|
@@ -37,6 +37,7 @@ import org.apache.catalina.websocket.StreamInbound;
|
|||||||
import org.apache.catalina.websocket.WebSocketServlet;
|
import org.apache.catalina.websocket.WebSocketServlet;
|
||||||
import org.apache.catalina.websocket.WsOutbound;
|
import org.apache.catalina.websocket.WsOutbound;
|
||||||
import org.glyptodon.guacamole.GuacamoleClientException;
|
import org.glyptodon.guacamole.GuacamoleClientException;
|
||||||
|
import org.glyptodon.guacamole.GuacamoleConnectionClosedException;
|
||||||
import org.glyptodon.guacamole.protocol.GuacamoleStatus;
|
import org.glyptodon.guacamole.protocol.GuacamoleStatus;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -120,6 +121,9 @@ public abstract class GuacamoleWebSocketTunnelServlet extends WebSocketServlet {
|
|||||||
writer.write(buffer, 0, num_read);
|
writer.write(buffer, 0, num_read);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
catch (GuacamoleConnectionClosedException e) {
|
||||||
|
logger.debug("Connection closed.", e);
|
||||||
|
}
|
||||||
catch (GuacamoleException e) {
|
catch (GuacamoleException e) {
|
||||||
logger.debug("Tunnel write failed.", e);
|
logger.debug("Tunnel write failed.", e);
|
||||||
}
|
}
|
||||||
@@ -180,6 +184,10 @@ public abstract class GuacamoleWebSocketTunnelServlet extends WebSocketServlet {
|
|||||||
logger.warn("Client request rejected: {}", e.getMessage());
|
logger.warn("Client request rejected: {}", e.getMessage());
|
||||||
closeConnection(outbound, e.getStatus());
|
closeConnection(outbound, e.getStatus());
|
||||||
}
|
}
|
||||||
|
catch (GuacamoleConnectionClosedException e) {
|
||||||
|
logger.debug("Connection closed.", e);
|
||||||
|
closeConnection(outbound, GuacamoleStatus.SUCCESS);
|
||||||
|
}
|
||||||
catch (GuacamoleException e) {
|
catch (GuacamoleException e) {
|
||||||
logger.error("Internal server error.", e);
|
logger.error("Internal server error.", e);
|
||||||
closeConnection(outbound, e.getStatus());
|
closeConnection(outbound, e.getStatus());
|
||||||
|
Reference in New Issue
Block a user