Fixed GUI login redirect and web-socket idle issues.
Change-Id: Ie8b0f6fd9952e3ed8bd65c58f21032fc2d2f132f
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/MainIndexResource.java b/web/gui/src/main/java/org/onosproject/ui/impl/MainIndexResource.java
index 1e72b94..218e259 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/MainIndexResource.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/MainIndexResource.java
@@ -36,6 +36,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;
+import java.net.URI;
import static com.google.common.collect.ImmutableList.of;
import static com.google.common.io.ByteStreams.toByteArray;
@@ -46,6 +47,8 @@
@Path("/")
public class MainIndexResource extends AbstractInjectionResource {
+ private static final String INDEX_REDIRECT = "/onos/ui/index.html";
+
private static final String INDEX = "index.html";
private static final String NOT_READY = "not-ready.html";
@@ -66,6 +69,16 @@
@GET
@Produces(MediaType.TEXT_HTML)
+ public Response getMainIndexRedirect() throws IOException {
+ if (ctx == null || ctx.getUserPrincipal() == null) {
+ return Response.temporaryRedirect(URI.create(INDEX_REDIRECT)).build();
+ }
+ return getMainIndex();
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ @Path("/index.html")
public Response getMainIndex() throws IOException {
ClassLoader classLoader = getClass().getClassLoader();
UiExtensionService service;
@@ -94,8 +107,7 @@
// FIXME: use global opaque auth token to allow secure failover
// for now, just use the user principal name...
- String userName = ctx != null && ctx.getUserPrincipal() != null ?
- ctx.getUserPrincipal().getName() : "unknown";
+ String userName = ctx.getUserPrincipal().getName();
// get a session token to use for UI-web-socket authentication
UiSessionToken token = tokens.issueToken(userName);
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocket.java b/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocket.java
index 25c2f03..44acba2 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocket.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocket.java
@@ -19,10 +19,7 @@
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
-import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
-import org.eclipse.jetty.websocket.api.annotations.WebSocket;
+import org.eclipse.jetty.websocket.api.WebSocketAdapter;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.ServiceNotFoundException;
import org.onosproject.cluster.ClusterService;
@@ -51,16 +48,18 @@
import org.slf4j.LoggerFactory;
import java.io.IOException;
+import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
+import static org.onosproject.ui.impl.UiWebSocketServlet.PING_DELAY_MS;
+
/**
* Web socket capable of interacting with the Web UI.
*/
-@WebSocket
-public class UiWebSocket implements UiConnection {
+public class UiWebSocket extends WebSocketAdapter implements UiConnection {
private static final Logger log = LoggerFactory.getLogger(UiWebSocket.class);
@@ -87,12 +86,13 @@
private static final long MAX_AGE_MS = 30_000;
+ private static final byte[] PING_DATA = new byte[]{(byte) 0xde, (byte) 0xad};
+ private static final ByteBuffer PING = ByteBuffer.wrap(PING_DATA);
+
private final ObjectMapper mapper = new ObjectMapper();
private final ServiceDirectory directory;
private final UiTopoSession topoSession;
- private Session session;
- //private FrameConnection control;
private String userName;
private String currentView;
@@ -172,10 +172,10 @@
/**
* Issues a close on the connection.
*/
- synchronized void close() {
+ void close() {
destroyHandlersAndOverlays();
- if (session.isOpen()) {
- session.close();
+ if (isConnected()) {
+ getSession().close();
}
}
@@ -184,43 +184,43 @@
*
* @return true if idle or closed
*/
- synchronized boolean isIdle() {
+ boolean isIdle() {
long quietFor = System.currentTimeMillis() - lastActive;
boolean idle = quietFor > MAX_AGE_MS;
- if (idle || (session != null && !session.isOpen())) {
+ if (idle || isNotConnected()) {
log.debug("IDLE (or closed) websocket [{} ms]", quietFor);
return true;
- //} else if (session != null) {
- // try {
- // control.sendControl(PING, PING_DATA, 0, PING_DATA.length);
- // } catch (IOException e) {
- // log.warn("Unable to send ping message due to: ", e);
- // }
+
+ } else if (isConnected() && quietFor > PING_DELAY_MS) {
+ try {
+ getRemote().sendPing(PING);
+ lastActive = System.currentTimeMillis();
+ } catch (IOException e) {
+ log.warn("Unable to send ping message due to: ", e);
+ }
}
return false;
}
- @OnWebSocketConnect
- public synchronized void onOpen(Session session) {
- this.session = session;
- //this.control = (FrameConnection) connection;
+ @Override
+ public void onWebSocketConnect(Session session) {
+ super.onWebSocketConnect(session);
try {
topoSession.init();
createHandlersAndOverlays();
sendBootstrapData();
sendUberLionBundle();
+ lastActive = System.currentTimeMillis();
log.info("GUI client connected -- user <{}>", userName);
} catch (ServiceNotFoundException e) {
log.warn("Unable to open GUI connection; services have been shut-down", e);
- this.session.close();
- this.session = null;
- //this.control = null;
+ getSession().close();
}
}
- @OnWebSocketClose
- public synchronized void onClose(int closeCode, String message) {
+ @Override
+ public void onWebSocketClose(int closeCode, String reason) {
try {
try {
tokenService().revokeToken(sessionToken);
@@ -235,12 +235,13 @@
} catch (Exception e) {
log.warn("Unexpected error", e);
}
+ super.onWebSocketClose(closeCode, reason);
log.info("GUI client disconnected [close-code={}, message={}]",
- closeCode, message);
+ closeCode, reason);
}
- @OnWebSocketMessage
- public void onText(Session session, String data) {
+ @Override
+ public void onWebSocketText(String data) {
lastActive = System.currentTimeMillis();
try {
ObjectNode message = (ObjectNode) mapper.reader().readTree(data);
@@ -265,10 +266,16 @@
}
@Override
+ public void onWebSocketBinary(byte[] payload, int offset, int length) {
+ lastActive = System.currentTimeMillis();
+ log.warn("Binary messages are currently not supported");
+ }
+
+ @Override
public synchronized void sendMessage(ObjectNode message) {
try {
- if (session.isOpen()) {
- session.getRemote().sendString(message.toString());
+ if (isConnected()) {
+ getRemote().sendString(message.toString());
log.debug("TX message: {}", message);
}
} catch (IOException e) {
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocketServlet.java b/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocketServlet.java
index 8d5d1c9..e9a4cbd 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocketServlet.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocketServlet.java
@@ -37,8 +37,7 @@
*/
public class UiWebSocketServlet extends WebSocketServlet {
- private static final long PING_DELAY_MS = 5000;
- private static final long IDLE_TIMEOUT_MS = 10000;
+ static final long PING_DELAY_MS = 5000;
private static UiWebSocketServlet instance;
private static final Object INSTANCE_LOCK = new Object();
@@ -53,7 +52,7 @@
@Override
public void configure(WebSocketServletFactory webSocketServletFactory) {
- webSocketServletFactory.getPolicy().setIdleTimeout(IDLE_TIMEOUT_MS);
+ webSocketServletFactory.getPolicy().setIdleTimeout(Long.MAX_VALUE);
webSocketServletFactory.setCreator(new UiWebSocketCreator());
}
diff --git a/web/gui/src/main/webapp/WEB-INF/web.xml b/web/gui/src/main/webapp/WEB-INF/web.xml
index 6b65ba4..bb7d7fb 100644
--- a/web/gui/src/main/webapp/WEB-INF/web.xml
+++ b/web/gui/src/main/webapp/WEB-INF/web.xml
@@ -22,7 +22,7 @@
<display-name>ONOS GUI</display-name>
<welcome-file-list>
- <welcome-file>index.html</welcome-file>
+ <welcome-file>/index.html</welcome-file>
</welcome-file-list>
<!--