Skip to content

Commit

Permalink
GUACAMOLE-504: Merge changes adding support for overriding HTTP/WebSo…
Browse files Browse the repository at this point in the history
…cket status codes via custom exceptions.
  • Loading branch information
mike-jumper committed Feb 14, 2018
2 parents c8d825e + c2ae43d commit 2da179f
Show file tree
Hide file tree
Showing 7 changed files with 189 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,29 @@ public GuacamoleException(Throwable cause) {
public GuacamoleStatus getStatus() {
return GuacamoleStatus.SERVER_ERROR;
}

/**
* Returns the most applicable HTTP status code that can be associated
* with this exception.
*
* @return
* An integer representing the most applicable HTTP status code
* associated with this exception.
*/
public int getHttpStatusCode() {
return getStatus().getHttpStatusCode();
}

/**
* Returns the most applicable WebSocket status code that can be
* associated with this exception.
*
* @return
* An integer representing the most applicable WebSocket status
* code associated with this exception.
*/
public int getWebSocketCode() {
return getStatus().getWebSocketCode();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -149,26 +149,29 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response)
* @param response
* The HTTP response to use to send the error.
*
* @param guacStatus
* The status to send
* @param guacamoleStatusCode
* The GuacamoleStatus code to send.
*
* @param guacamoleHttpCode
* The numeric HTTP code to send.
*
* @param message
* A human-readable message that can be presented to the user.
* The human-readable error message to send.
*
* @throws ServletException
* If an error prevents sending of the error code.
*/
protected void sendError(HttpServletResponse response,
GuacamoleStatus guacStatus, String message)
protected void sendError(HttpServletResponse response, int guacamoleStatusCode,
int guacamoleHttpCode, String message)
throws ServletException {

try {

// If response not committed, send error code and message
if (!response.isCommitted()) {
response.addHeader("Guacamole-Status-Code", Integer.toString(guacStatus.getGuacamoleStatusCode()));
response.addHeader("Guacamole-Status-Code", Integer.toString(guacamoleStatusCode));
response.addHeader("Guacamole-Error-Message", message);
response.sendError(guacStatus.getHttpStatusCode());
response.sendError(guacamoleHttpCode);
}

}
Expand Down Expand Up @@ -237,14 +240,14 @@ protected void handleTunnelRequest(HttpServletRequest request,

// If read operation, call doRead() with tunnel UUID, ignoring any
// characters following the tunnel UUID.
else if(query.startsWith(READ_PREFIX))
else if (query.startsWith(READ_PREFIX))
doRead(request, response, query.substring(
READ_PREFIX_LENGTH,
READ_PREFIX_LENGTH + UUID_LENGTH));

// If write operation, call doWrite() with tunnel UUID, ignoring any
// characters following the tunnel UUID.
else if(query.startsWith(WRITE_PREFIX))
else if (query.startsWith(WRITE_PREFIX))
doWrite(request, response, query.substring(
WRITE_PREFIX_LENGTH,
WRITE_PREFIX_LENGTH + UUID_LENGTH));
Expand All @@ -258,12 +261,14 @@ else if(query.startsWith(WRITE_PREFIX))
// HTTP response, logging each error appropriately.
catch (GuacamoleClientException e) {
logger.warn("HTTP tunnel request rejected: {}", e.getMessage());
sendError(response, e.getStatus(), e.getMessage());
sendError(response, e.getStatus().getGuacamoleStatusCode(),
e.getStatus().getHttpStatusCode(), e.getMessage());
}
catch (GuacamoleException e) {
logger.error("HTTP tunnel request failed: {}", e.getMessage());
logger.debug("Internal error in HTTP tunnel.", e);
sendError(response, e.getStatus(), "Internal server error.");
sendError(response, e.getStatus().getGuacamoleStatusCode(),
e.getStatus().getHttpStatusCode(), "Internal server error.");
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,17 +66,24 @@ public abstract class GuacamoleWebSocketTunnelEndpoint extends Endpoint {
private GuacamoleTunnel tunnel;

/**
* Sends the given status on the given WebSocket connection and closes the
* connection.
* Sends the numeric Guacaomle Status Code and Web Socket
* code and closes the connection.
*
* @param session
* The outbound WebSocket connection to close.
*
* @param guacamoleStatusCode
* The numeric Guacamole status to send.
*
* @param session The outbound WebSocket connection to close.
* @param guac_status The status to send.
* @param webSocketCode
* The numeric WebSocket status to send.
*/
private void closeConnection(Session session, GuacamoleStatus guac_status) {
private void closeConnection(Session session, int guacamoleStatusCode,
int webSocketCode) {

try {
CloseCode code = CloseReason.CloseCodes.getCloseCode(guac_status.getWebSocketCode());
String message = Integer.toString(guac_status.getGuacamoleStatusCode());
CloseCode code = CloseReason.CloseCodes.getCloseCode(webSocketCode);
String message = Integer.toString(guacamoleStatusCode);
session.close(new CloseReason(code, message));
}
catch (IOException e) {
Expand All @@ -85,6 +92,21 @@ private void closeConnection(Session session, GuacamoleStatus guac_status) {

}

/**
* Sends the given Guacaomle Status and closes the given
* connection.
*
* @param session
* The outbound WebSocket connection to close.
*
* @param guacStatus
* The status to use for the connection.
*/
private void closeConnection(Session session, GuacamoleStatus guacStatus) {
closeConnection(session, guacStatus.getGuacamoleStatusCode(),
guacStatus.getWebSocketCode());
}

/**
* Returns a new tunnel for the given session. How this tunnel is created
* or retrieved is implementation-dependent.
Expand Down Expand Up @@ -117,7 +139,8 @@ public void onOpen(final Session session, EndpointConfig config) {
catch (GuacamoleException e) {
logger.error("Creation of WebSocket tunnel to guacd failed: {}", e.getMessage());
logger.debug("Error connecting WebSocket tunnel.", e);
closeConnection(session, e.getStatus());
closeConnection(session, e.getStatus().getGuacamoleStatusCode(),
e.getWebSocketCode());
return;
}

Expand Down Expand Up @@ -181,7 +204,8 @@ public void run() {
catch (GuacamoleClientException e) {
logger.info("WebSocket connection terminated: {}", e.getMessage());
logger.debug("WebSocket connection terminated due to client error.", e);
closeConnection(session, e.getStatus());
closeConnection(session, e.getStatus().getGuacamoleStatusCode(),
e.getWebSocketCode());
}
catch (GuacamoleConnectionClosedException e) {
logger.debug("Connection to guacd closed.", e);
Expand All @@ -190,7 +214,8 @@ public void run() {
catch (GuacamoleException e) {
logger.error("Connection to guacd terminated abnormally: {}", e.getMessage());
logger.debug("Internal error during connection to guacd.", e);
closeConnection(session, e.getStatus());
closeConnection(session, e.getStatus().getGuacamoleStatusCode(),
e.getWebSocketCode());
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ public Object invoke(MethodInvocation invocation) throws WebApplicationException
// Translate GuacamoleException subclasses to HTTP error codes
catch (GuacamoleException e) {
throw new APIException(
Response.Status.fromStatusCode(e.getStatus().getHttpStatusCode()),
Response.Status.fromStatusCode(e.getHttpStatusCode()),
e
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,42 @@ public abstract class GuacamoleWebSocketTunnelServlet extends WebSocketServlet {
private static final int BUFFER_SIZE = 8192;

/**
* Sends the given status on the given WebSocket connection and closes the
* Sends the given numeric Guacamole and WebSocket status
* on the given WebSocket connection and closes the
* connection.
*
* @param connection The WebSocket connection to close.
* @param guac_status The status to send.
* @param connection
* The WebSocket connection to close.
*
* @param guacamoleStatusCode
* The numeric Guacamole Status code to send.
*
* @param webSocketCode
* The numeric WebSocket status code to send.
*/
private static void closeConnection(Connection connection,
int guacamoleStatusCode, int webSocketCode) {

connection.close(webSocketCode,
Integer.toString(guacamoleStatusCode));

}

/**
* Sends the given status on the given WebSocket connection
* and closes the connection.
*
* @param connection
* The WebSocket connection to close.
*
* @param guacStatus
* The status to send.
*/
public static void closeConnection(Connection connection,
GuacamoleStatus guac_status) {
private static void closeConnection(Connection connection,
GuacamoleStatus guacStatus) {

connection.close(guac_status.getWebSocketCode(),
Integer.toString(guac_status.getGuacamoleStatusCode()));
closeConnection(connection, guacStatus.getGuacamoleStatusCode(),
guacStatus.getWebSocketCode());

}

Expand Down Expand Up @@ -114,7 +139,8 @@ public void onOpen(final Connection connection) {
catch (GuacamoleException e) {
logger.error("Creation of WebSocket tunnel to guacd failed: {}", e.getMessage());
logger.debug("Error connecting WebSocket tunnel.", e);
closeConnection(connection, e.getStatus());
closeConnection(connection, e.getStatus().getGuacamoleStatusCode(),
e.getWebSocketCode());
return;
}

Expand Down Expand Up @@ -168,7 +194,8 @@ public void run() {
catch (GuacamoleClientException e) {
logger.info("WebSocket connection terminated: {}", e.getMessage());
logger.debug("WebSocket connection terminated due to client error.", e);
closeConnection(connection, e.getStatus());
closeConnection(connection, e.getStatus().getGuacamoleStatusCode(),
e.getWebSocketCode());
}
catch (GuacamoleConnectionClosedException e) {
logger.debug("Connection to guacd closed.", e);
Expand All @@ -177,7 +204,8 @@ public void run() {
catch (GuacamoleException e) {
logger.error("Connection to guacd terminated abnormally: {}", e.getMessage());
logger.debug("Internal error during connection to guacd.", e);
closeConnection(connection, e.getStatus());
closeConnection(connection, e.getStatus().getGuacamoleStatusCode(),
e.getWebSocketCode());
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,25 +57,50 @@ public abstract class GuacamoleWebSocketTunnelListener implements WebSocketListe
private GuacamoleTunnel tunnel;

/**
* Sends the given status on the given WebSocket connection and closes the
* Sends the given numeric Guacamole and WebSocket status
* codes on the given WebSocket connection and closes the
* connection.
*
* @param session The outbound WebSocket connection to close.
* @param guac_status The status to send.
* @param session
* The outbound WebSocket connection to close.
*
* @param guacamoleStatusCode
* The numeric Guacamole status code to send.
*
* @param webSocketCode
* The numeric WebSocket status code to send.
*/
private void closeConnection(Session session, GuacamoleStatus guac_status) {
private void closeConnection(Session session, int guacamoleStatusCode,
int webSocketCode) {

try {
int code = guac_status.getWebSocketCode();
String message = Integer.toString(guac_status.getGuacamoleStatusCode());
session.close(new CloseStatus(code, message));
String message = Integer.toString(guacamoleStatusCode);
session.close(new CloseStatus(webSocketCode, message));
}
catch (IOException e) {
logger.debug("Unable to close WebSocket connection.", e);
}

}

/**
* Sends the given status on the given WebSocket connection
* and closes the connection.
*
* @param session
* The outbound WebSocket connection to close.
*
* @param guacStatus
* The status to send.
*/
private void closeConnection(Session session,
GuacamoleStatus guacStatus) {

closeConnection(session, guacStatus.getGuacamoleStatusCode(),
guacStatus.getWebSocketCode());

}

/**
* Returns a new tunnel for the given session. How this tunnel is created
* or retrieved is implementation-dependent.
Expand Down Expand Up @@ -105,7 +130,7 @@ public void onWebSocketConnect(final Session session) {
catch (GuacamoleException e) {
logger.error("Creation of WebSocket tunnel to guacd failed: {}", e.getMessage());
logger.debug("Error connecting WebSocket tunnel.", e);
closeConnection(session, e.getStatus());
closeConnection(session, e.getStatus().getGuacamoleStatusCode(), e.getWebSocketCode());
return;
}

Expand Down Expand Up @@ -159,7 +184,8 @@ public void run() {
catch (GuacamoleClientException e) {
logger.info("WebSocket connection terminated: {}", e.getMessage());
logger.debug("WebSocket connection terminated due to client error.", e);
closeConnection(session, e.getStatus());
closeConnection(session, e.getStatus().getGuacamoleStatusCode(),
e.getWebSocketCode());
}
catch (GuacamoleConnectionClosedException e) {
logger.debug("Connection to guacd closed.", e);
Expand All @@ -168,7 +194,8 @@ public void run() {
catch (GuacamoleException e) {
logger.error("Connection to guacd terminated abnormally: {}", e.getMessage());
logger.debug("Internal error during connection to guacd.", e);
closeConnection(session, e.getStatus());
closeConnection(session, e.getStatus().getGuacamoleStatusCode(),
e.getWebSocketCode());
}

}
Expand Down
Loading

0 comments on commit 2da179f

Please sign in to comment.