blob: 564b07f8f78be448f0670a722741f23ffc09b795 [file] [log] [blame]
Thomas Vachuska3553b302015-03-07 14:49:43 -08001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.ui.impl;
17
Thomas Vachuskafa74dd72016-03-20 19:11:12 -070018import com.fasterxml.jackson.databind.node.ObjectNode;
Thomas Vachuska3553b302015-03-07 14:49:43 -080019import org.eclipse.jetty.websocket.WebSocket;
20import org.eclipse.jetty.websocket.WebSocketServlet;
21import org.onlab.osgi.DefaultServiceDirectory;
22import org.onlab.osgi.ServiceDirectory;
23
24import javax.servlet.ServletException;
25import javax.servlet.http.HttpServletRequest;
26import java.util.HashSet;
27import java.util.Iterator;
28import java.util.Set;
29import java.util.Timer;
30import java.util.TimerTask;
31
32/**
33 * Web socket servlet capable of creating web sockets for the user interface.
34 */
35public class UiWebSocketServlet extends WebSocketServlet {
36
37 private static final long PING_DELAY_MS = 5000;
38
Thomas Vachuska51f540f2015-05-27 17:26:57 -070039 private static UiWebSocketServlet instance;
40
Thomas Vachuska3553b302015-03-07 14:49:43 -080041 private ServiceDirectory directory = new DefaultServiceDirectory();
42
43 private final Set<UiWebSocket> sockets = new HashSet<>();
44 private final Timer timer = new Timer();
45 private final TimerTask pruner = new Pruner();
Thomas Vachuska4e0e0932015-07-24 10:14:34 -070046 private boolean isStopped = false;
Thomas Vachuska3553b302015-03-07 14:49:43 -080047
Thomas Vachuska51f540f2015-05-27 17:26:57 -070048 /**
49 * Closes all currently open UI web-sockets.
50 */
51 public static void closeAll() {
52 if (instance != null) {
Thomas Vachuska4e0e0932015-07-24 10:14:34 -070053 instance.isStopped = true;
Thomas Vachuska51f540f2015-05-27 17:26:57 -070054 instance.sockets.forEach(UiWebSocket::close);
55 instance.sockets.clear();
Thomas Vachuska4e0e0932015-07-24 10:14:34 -070056 instance.pruner.cancel();
57 instance.timer.cancel();
Thomas Vachuska51f540f2015-05-27 17:26:57 -070058 }
59 }
60
Thomas Vachuska3553b302015-03-07 14:49:43 -080061 @Override
62 public void init() throws ServletException {
63 super.init();
Thomas Vachuska51f540f2015-05-27 17:26:57 -070064 instance = this;
Thomas Vachuska3553b302015-03-07 14:49:43 -080065 timer.schedule(pruner, PING_DELAY_MS, PING_DELAY_MS);
66 }
67
68 @Override
69 public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) {
Thomas Vachuska4e0e0932015-07-24 10:14:34 -070070 if (isStopped) {
71 return null;
72 }
Thomas Vachuska3553b302015-03-07 14:49:43 -080073 UiWebSocket socket = new UiWebSocket(directory);
74 synchronized (sockets) {
75 sockets.add(socket);
76 }
77 return socket;
78 }
79
Thomas Vachuskafa74dd72016-03-20 19:11:12 -070080 /**
81 * Sends the specified message to all the GUI clients.
82 *
83 * @param type message type
84 * @param payload message payload
85 */
86 static void sendToAll(String type, ObjectNode payload) {
87 if (instance != null) {
88 instance.sockets.forEach(ws -> ws.sendMessage(type, 0, payload));
89 }
90 }
91
Thomas Vachuska3553b302015-03-07 14:49:43 -080092 // Task for pruning web-sockets that are idle.
93 private class Pruner extends TimerTask {
94 @Override
95 public void run() {
96 synchronized (sockets) {
97 Iterator<UiWebSocket> it = sockets.iterator();
98 while (it.hasNext()) {
99 UiWebSocket socket = it.next();
100 if (socket.isIdle()) {
101 it.remove();
102 socket.close();
103 }
104 }
105 }
106 }
107 }
108}