GUAC-867: Add periodic keep-alive ping to ensure the session does not perish while a connection is active.

This commit is contained in:
Michael Jumper
2014-10-13 03:25:31 -07:00
parent 115f647f7a
commit 04ba001f15
4 changed files with 111 additions and 7 deletions

View File

@@ -0,0 +1,54 @@
/*
* 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.net.basic;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.glyptodon.guacamole.net.auth.UserContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Dummy servlet which provides an endpoint for arbitrary requests intended to
* simply keep the HTTP session from expiring.
*
* @author Michael Jumper
*/
public class SessionKeepAlive extends RestrictedHttpServlet {
/**
* Logger for this class.
*/
private final Logger logger = LoggerFactory.getLogger(SessionKeepAlive.class);
@Override
protected void restrictedService(
UserContext context,
HttpServletRequest request, HttpServletResponse response) {
// Do nothing
logger.trace("Keep-alive signal received.");
}
}

View File

@@ -86,6 +86,17 @@
<url-pattern>/logout</url-pattern>
</servlet-mapping>
<!-- Session Keep-Alive Servlet -->
<servlet>
<description>Session keep-alive servlet.</description>
<servlet-name>SessionKeepAlive</servlet-name>
<servlet-class>org.glyptodon.guacamole.net.basic.SessionKeepAlive</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SessionKeepAlive</servlet-name>
<url-pattern>/keep-alive</url-pattern>
</servlet-mapping>
<!-- Clipboard State Servlet -->
<servlet>
<description>Clipboard state servlet.</description>

View File

@@ -196,6 +196,7 @@ GuacUI.Client = {
/* Constants */
"KEEP_ALIVE_INTERVAL" : 60000, /* milliseconds */
"KEYBOARD_AUTO_RESIZE_INTERVAL" : 30, /* milliseconds */
"RECONNECT_PERIOD" : 15, /* seconds */
"TEXT_INPUT_PADDING" : 128, /* characters */
@@ -1014,6 +1015,11 @@ GuacUI.Client.connect = function() {
connect_string += "&video=" + encodeURIComponent(mimetype);
});
// Ping server every 10 seconds
var session_keep_alive = window.setInterval(function _session_keep_alive() {
GuacamoleService.KeepAlive.ping();
}, GuacUI.Client.KEEP_ALIVE_INTERVAL);
// Show connection errors from tunnel
tunnel.onerror = function(status) {
var message = GuacUI.Client.tunnel_errors[status.code] || GuacUI.Client.tunnel_errors.DEFAULT;
@@ -1021,10 +1027,20 @@ GuacUI.Client.connect = function() {
GuacUI.Client.tunnel_auto_reconnect[status.code] && GuacUI.Client.RECONNECT_PERIOD);
};
// Notify of disconnections (if not already notified of something else)
tunnel.onstatechange = function(state) {
if (state === Guacamole.Tunnel.State.CLOSED && !GuacUI.Client.visibleStatus)
GuacUI.Client.showStatus("Disconnected", "You have been disconnected. Reload the page to reconnect.");
// Handle disconnect
if (state === Guacamole.Tunnel.State.CLOSED) {
// No need for a keep-alive ping if the tunnel is closed
window.clearInterval(session_keep_alive);
// Notify of disconnections (if not already notified of something else)
if (!GuacUI.Client.visibleStatus)
GuacUI.Client.showStatus("Disconnected",
"You have been disconnected. Reload the page to reconnect.");
}
};
// Connect

View File

@@ -1438,3 +1438,26 @@ GuacamoleService.Clipboard = {
}
};
/**
* Collection of service functions which deal with the session keep-alive. Each
* function makes an explicit HTTP query to the server. In the case of the
* keep-alive ping, no response is expected, and any received response is
* ignored.
*/
GuacamoleService.KeepAlive = {
"ping" : function(parameters) {
// Construct request URL
var ping_url = "keep-alive";
if (parameters) ping_url += "?" + parameters;
// Send keep-alive "ping"
var xhr = new XMLHttpRequest();
xhr.open("GET", ping_url, true);
xhr.send(null);
}
};