blob: 9562040256169e1fc0f44d6648a7f6d56dbd6096 [file] [log] [blame]
Thomas Vachuska7d638d32014-11-07 10:24:43 -08001/*
2 * Copyright 2014 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.onlab.onos.gui;
17
Thomas Vachuskadea45ff2014-11-12 18:35:46 -080018import com.fasterxml.jackson.databind.node.ArrayNode;
Thomas Vachuskad472c6e2014-11-07 19:11:05 -080019import com.fasterxml.jackson.databind.node.ObjectNode;
Thomas Vachuska7d638d32014-11-07 10:24:43 -080020import org.eclipse.jetty.websocket.WebSocket;
Thomas Vachuskaa7c3dd12014-11-11 09:10:19 -080021import org.onlab.onos.cluster.ClusterEvent;
22import org.onlab.onos.cluster.ClusterEventListener;
23import org.onlab.onos.cluster.ControllerNode;
Thomas Vachuska4830d392014-11-09 17:09:56 -080024import org.onlab.onos.core.ApplicationId;
25import org.onlab.onos.core.CoreService;
Thomas Vachuskad472c6e2014-11-07 19:11:05 -080026import org.onlab.onos.net.Device;
Thomas Vachuska690e5f62014-11-09 08:26:47 -080027import org.onlab.onos.net.Host;
28import org.onlab.onos.net.HostId;
Thomas Vachuskad472c6e2014-11-07 19:11:05 -080029import org.onlab.onos.net.Link;
30import org.onlab.onos.net.device.DeviceEvent;
Thomas Vachuska690e5f62014-11-09 08:26:47 -080031import org.onlab.onos.net.device.DeviceListener;
Thomas Vachuska4830d392014-11-09 17:09:56 -080032import org.onlab.onos.net.flow.DefaultTrafficSelector;
33import org.onlab.onos.net.flow.DefaultTrafficTreatment;
Thomas Vachuska690e5f62014-11-09 08:26:47 -080034import org.onlab.onos.net.host.HostEvent;
35import org.onlab.onos.net.host.HostListener;
Thomas Vachuska4830d392014-11-09 17:09:56 -080036import org.onlab.onos.net.intent.HostToHostIntent;
37import org.onlab.onos.net.intent.Intent;
38import org.onlab.onos.net.intent.IntentEvent;
Thomas Vachuska4830d392014-11-09 17:09:56 -080039import org.onlab.onos.net.intent.IntentListener;
Thomas Vachuskad472c6e2014-11-07 19:11:05 -080040import org.onlab.onos.net.link.LinkEvent;
Thomas Vachuska690e5f62014-11-09 08:26:47 -080041import org.onlab.onos.net.link.LinkListener;
Thomas Vachuska7d638d32014-11-07 10:24:43 -080042import org.onlab.osgi.ServiceDirectory;
43
44import java.io.IOException;
Thomas Vachuska47635c62014-11-22 01:21:36 -080045import java.util.ArrayList;
46import java.util.Collections;
47import java.util.Comparator;
Thomas Vachuska29617e52014-11-20 03:17:46 -080048import java.util.HashSet;
Thomas Vachuska47635c62014-11-22 01:21:36 -080049import java.util.List;
Thomas Vachuskadea45ff2014-11-12 18:35:46 -080050import java.util.Set;
Thomas Vachuska22e34922014-11-14 00:40:55 -080051import java.util.Timer;
52import java.util.TimerTask;
Thomas Vachuska7d638d32014-11-07 10:24:43 -080053
Thomas Vachuskae7591e52014-11-13 21:31:15 -080054import static com.google.common.base.Strings.isNullOrEmpty;
Thomas Vachuskaa7c3dd12014-11-11 09:10:19 -080055import static org.onlab.onos.cluster.ClusterEvent.Type.INSTANCE_ADDED;
Thomas Vachuskad1be50d2014-11-08 16:10:20 -080056import static org.onlab.onos.net.DeviceId.deviceId;
Thomas Vachuska690e5f62014-11-09 08:26:47 -080057import static org.onlab.onos.net.HostId.hostId;
Thomas Vachuskad472c6e2014-11-07 19:11:05 -080058import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_ADDED;
Thomas Vachuska4830d392014-11-09 17:09:56 -080059import static org.onlab.onos.net.host.HostEvent.Type.HOST_ADDED;
Thomas Vachuskad472c6e2014-11-07 19:11:05 -080060import static org.onlab.onos.net.link.LinkEvent.Type.LINK_ADDED;
Thomas Vachuskad472c6e2014-11-07 19:11:05 -080061
Thomas Vachuska7d638d32014-11-07 10:24:43 -080062/**
63 * Web socket capable of interacting with the GUI topology view.
64 */
Thomas Vachuska7c27ad72014-11-14 16:20:10 -080065public class TopologyViewWebSocket
66 extends TopologyViewMessages
Thomas Vachuskaba5621e2014-11-12 01:47:19 -080067 implements WebSocket.OnTextMessage, WebSocket.OnControl {
68
69 private static final long MAX_AGE_MS = 15000;
70
71 private static final byte PING = 0x9;
72 private static final byte PONG = 0xA;
73 private static final byte[] PING_DATA = new byte[]{(byte) 0xde, (byte) 0xad};
Thomas Vachuska7d638d32014-11-07 10:24:43 -080074
Thomas Vachuska4830d392014-11-09 17:09:56 -080075 private static final String APP_ID = "org.onlab.onos.gui";
Thomas Vachuska4830d392014-11-09 17:09:56 -080076
Thomas Vachuska47635c62014-11-22 01:21:36 -080077 private static final long SUMMARY_FREQUENCY_SEC = 2000;
Thomas Vachuska7c27ad72014-11-14 16:20:10 -080078 private static final long TRAFFIC_FREQUENCY_SEC = 1000;
Thomas Vachuska22e34922014-11-14 00:40:55 -080079
Thomas Vachuska47635c62014-11-22 01:21:36 -080080 private static final Comparator<? super ControllerNode> NODE_COMPARATOR =
81 new Comparator<ControllerNode>() {
82 @Override
83 public int compare(ControllerNode o1, ControllerNode o2) {
84 return o1.id().toString().compareTo(o2.id().toString());
85 }
86 };
87
Thomas Vachuska4830d392014-11-09 17:09:56 -080088 private final ApplicationId appId;
Thomas Vachuskad472c6e2014-11-07 19:11:05 -080089
Thomas Vachuska7d638d32014-11-07 10:24:43 -080090 private Connection connection;
Thomas Vachuskaba5621e2014-11-12 01:47:19 -080091 private FrameConnection control;
Thomas Vachuska7d638d32014-11-07 10:24:43 -080092
Thomas Vachuskaa7c3dd12014-11-11 09:10:19 -080093 private final ClusterEventListener clusterListener = new InternalClusterListener();
Thomas Vachuska690e5f62014-11-09 08:26:47 -080094 private final DeviceListener deviceListener = new InternalDeviceListener();
95 private final LinkListener linkListener = new InternalLinkListener();
96 private final HostListener hostListener = new InternalHostListener();
Thomas Vachuska4830d392014-11-09 17:09:56 -080097 private final IntentListener intentListener = new InternalIntentListener();
Thomas Vachuska690e5f62014-11-09 08:26:47 -080098
Thomas Vachuska47635c62014-11-22 01:21:36 -080099 // Timers and objects being monitored
100 private final Timer timer = new Timer("topology-view");
101
102 private TimerTask trafficTask;
103 private ObjectNode trafficEvent;
104
105 private TimerTask summaryTask;
106 private ObjectNode summaryEvent;
Thomas Vachuskad1be50d2014-11-08 16:10:20 -0800107
Thomas Vachuskaba5621e2014-11-12 01:47:19 -0800108 private long lastActive = System.currentTimeMillis();
Thomas Vachuskadea45ff2014-11-12 18:35:46 -0800109 private boolean listenersRemoved = false;
Thomas Vachuskaba5621e2014-11-12 01:47:19 -0800110
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800111 private TopologyViewIntentFilter intentFilter;
112
Thomas Vachuska7d638d32014-11-07 10:24:43 -0800113 /**
114 * Creates a new web-socket for serving data to GUI topology view.
115 *
116 * @param directory service directory
117 */
Thomas Vachuska7c27ad72014-11-14 16:20:10 -0800118 public TopologyViewWebSocket(ServiceDirectory directory) {
Thomas Vachuskaa7c3dd12014-11-11 09:10:19 -0800119 super(directory);
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800120
121 intentFilter = new TopologyViewIntentFilter(intentService, deviceService,
122 hostService, linkService);
Thomas Vachuska4830d392014-11-09 17:09:56 -0800123 appId = directory.get(CoreService.class).registerApplication(APP_ID);
Thomas Vachuska7d638d32014-11-07 10:24:43 -0800124 }
125
Thomas Vachuskaba5621e2014-11-12 01:47:19 -0800126 /**
127 * Issues a close on the connection.
128 */
129 synchronized void close() {
Thomas Vachuskadea45ff2014-11-12 18:35:46 -0800130 removeListeners();
Thomas Vachuskaba5621e2014-11-12 01:47:19 -0800131 if (connection.isOpen()) {
Thomas Vachuskaba5621e2014-11-12 01:47:19 -0800132 connection.close();
133 }
134 }
135
136 /**
137 * Indicates if this connection is idle.
Thomas Vachuska3266abf2014-11-13 09:28:46 -0800138 *
139 * @return true if idle or closed
Thomas Vachuskaba5621e2014-11-12 01:47:19 -0800140 */
141 synchronized boolean isIdle() {
142 boolean idle = (System.currentTimeMillis() - lastActive) > MAX_AGE_MS;
143 if (idle || !connection.isOpen()) {
144 return true;
145 }
146 try {
147 control.sendControl(PING, PING_DATA, 0, PING_DATA.length);
148 } catch (IOException e) {
149 log.warn("Unable to send ping message due to: ", e);
150 }
151 return false;
152 }
153
Thomas Vachuska7d638d32014-11-07 10:24:43 -0800154 @Override
155 public void onOpen(Connection connection) {
Thomas Vachuskaba5621e2014-11-12 01:47:19 -0800156 log.info("GUI client connected");
Thomas Vachuska7d638d32014-11-07 10:24:43 -0800157 this.connection = connection;
Thomas Vachuskaba5621e2014-11-12 01:47:19 -0800158 this.control = (FrameConnection) connection;
Thomas Vachuskaa7c3dd12014-11-11 09:10:19 -0800159 addListeners();
Thomas Vachuska7d638d32014-11-07 10:24:43 -0800160
Thomas Vachuskaa7c3dd12014-11-11 09:10:19 -0800161 sendAllInstances();
Thomas Vachuska690e5f62014-11-09 08:26:47 -0800162 sendAllDevices();
163 sendAllLinks();
Thomas Vachuska4830d392014-11-09 17:09:56 -0800164 sendAllHosts();
165 }
166
Thomas Vachuska7d638d32014-11-07 10:24:43 -0800167 @Override
Thomas Vachuskaba5621e2014-11-12 01:47:19 -0800168 public synchronized void onClose(int closeCode, String message) {
Thomas Vachuskadea45ff2014-11-12 18:35:46 -0800169 removeListeners();
Thomas Vachuska22e34922014-11-14 00:40:55 -0800170 timer.cancel();
Thomas Vachuskaba5621e2014-11-12 01:47:19 -0800171 log.info("GUI client disconnected");
172 }
173
174 @Override
175 public boolean onControl(byte controlCode, byte[] data, int offset, int length) {
176 lastActive = System.currentTimeMillis();
177 return true;
Thomas Vachuska7d638d32014-11-07 10:24:43 -0800178 }
179
180 @Override
181 public void onMessage(String data) {
Thomas Vachuskaba5621e2014-11-12 01:47:19 -0800182 lastActive = System.currentTimeMillis();
Thomas Vachuskad1be50d2014-11-08 16:10:20 -0800183 try {
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800184 processMessage((ObjectNode) mapper.reader().readTree(data));
Thomas Vachuska4830d392014-11-09 17:09:56 -0800185 } catch (Exception e) {
Thomas Vachuska0f6baee2014-11-11 15:02:32 -0800186 log.warn("Unable to parse GUI request {} due to {}", data, e);
Thomas Vachuska29617e52014-11-20 03:17:46 -0800187 log.warn("Boom!!!!", e);
Thomas Vachuskad1be50d2014-11-08 16:10:20 -0800188 }
Thomas Vachuska7d638d32014-11-07 10:24:43 -0800189 }
190
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800191 // Processes the specified event.
192 private void processMessage(ObjectNode event) {
193 String type = string(event, "event", "unknown");
194 if (type.equals("requestDetails")) {
195 requestDetails(event);
196 } else if (type.equals("updateMeta")) {
197 updateMetaUi(event);
198 } else if (type.equals("addHostIntent")) {
199 createHostIntent(event);
Thomas Vachuska47635c62014-11-22 01:21:36 -0800200
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800201 } else if (type.equals("requestTraffic")) {
202 requestTraffic(event);
203 } else if (type.equals("requestAllTraffic")) {
204 requestAllTraffic(event);
Thomas Vachuska29617e52014-11-20 03:17:46 -0800205 } else if (type.equals("requestDeviceLinkFlows")) {
206 requestDeviceLinkFlows(event);
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800207 } else if (type.equals("cancelTraffic")) {
208 cancelTraffic(event);
Thomas Vachuska47635c62014-11-22 01:21:36 -0800209
210 } else if (type.equals("requestSummary")) {
211 requestSummary(event);
212 } else if (type.equals("cancelSummary")) {
213 cancelSummary(event);
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800214 }
215 }
216
Thomas Vachuska690e5f62014-11-09 08:26:47 -0800217 // Sends the specified data to the client.
Thomas Vachuskaba5621e2014-11-12 01:47:19 -0800218 private synchronized void sendMessage(ObjectNode data) {
Thomas Vachuska690e5f62014-11-09 08:26:47 -0800219 try {
Thomas Vachuskaba5621e2014-11-12 01:47:19 -0800220 if (connection.isOpen()) {
221 connection.sendMessage(data.toString());
222 }
Thomas Vachuska690e5f62014-11-09 08:26:47 -0800223 } catch (IOException e) {
Thomas Vachuskaba5621e2014-11-12 01:47:19 -0800224 log.warn("Unable to send message {} to GUI due to {}", data, e);
Thomas Vachuskad1be50d2014-11-08 16:10:20 -0800225 }
Thomas Vachuska690e5f62014-11-09 08:26:47 -0800226 }
227
Thomas Vachuskaa7c3dd12014-11-11 09:10:19 -0800228 // Sends all controller nodes to the client as node-added messages.
229 private void sendAllInstances() {
Thomas Vachuska47635c62014-11-22 01:21:36 -0800230 List<ControllerNode> nodes = new ArrayList<>(clusterService.getNodes());
231 Collections.sort(nodes, NODE_COMPARATOR);
232 for (ControllerNode node : nodes) {
Thomas Vachuskaa7c3dd12014-11-11 09:10:19 -0800233 sendMessage(instanceMessage(new ClusterEvent(INSTANCE_ADDED, node)));
Thomas Vachuska690e5f62014-11-09 08:26:47 -0800234 }
Thomas Vachuska690e5f62014-11-09 08:26:47 -0800235 }
236
Thomas Vachuskaa7c3dd12014-11-11 09:10:19 -0800237 // Sends all devices to the client as device-added messages.
238 private void sendAllDevices() {
239 for (Device device : deviceService.getDevices()) {
240 sendMessage(deviceMessage(new DeviceEvent(DEVICE_ADDED, device)));
Thomas Vachuska690e5f62014-11-09 08:26:47 -0800241 }
Thomas Vachuska690e5f62014-11-09 08:26:47 -0800242 }
243
Thomas Vachuskaa7c3dd12014-11-11 09:10:19 -0800244 // Sends all links to the client as link-added messages.
245 private void sendAllLinks() {
246 for (Link link : linkService.getLinks()) {
247 sendMessage(linkMessage(new LinkEvent(LINK_ADDED, link)));
Thomas Vachuska690e5f62014-11-09 08:26:47 -0800248 }
Thomas Vachuskaa7c3dd12014-11-11 09:10:19 -0800249 }
250
251 // Sends all hosts to the client as host-added messages.
252 private void sendAllHosts() {
253 for (Host host : hostService.getHosts()) {
254 sendMessage(hostMessage(new HostEvent(HOST_ADDED, host)));
255 }
Thomas Vachuska690e5f62014-11-09 08:26:47 -0800256 }
257
258 // Sends back device or host details.
Thomas Vachuskaf1fae002014-11-11 18:22:02 -0800259 private void requestDetails(ObjectNode event) {
Thomas Vachuska690e5f62014-11-09 08:26:47 -0800260 ObjectNode payload = payload(event);
Thomas Vachuskaf1fae002014-11-11 18:22:02 -0800261 String type = string(payload, "class", "unknown");
Thomas Vachuskadea45ff2014-11-12 18:35:46 -0800262 long sid = number(event, "sid");
263
Thomas Vachuska690e5f62014-11-09 08:26:47 -0800264 if (type.equals("device")) {
Thomas Vachuskadea45ff2014-11-12 18:35:46 -0800265 sendMessage(deviceDetails(deviceId(string(payload, "id")), sid));
Thomas Vachuska690e5f62014-11-09 08:26:47 -0800266 } else if (type.equals("host")) {
Thomas Vachuskadea45ff2014-11-12 18:35:46 -0800267 sendMessage(hostDetails(hostId(string(payload, "id")), sid));
Thomas Vachuska690e5f62014-11-09 08:26:47 -0800268 }
269 }
270
Thomas Vachuska4830d392014-11-09 17:09:56 -0800271 // Creates host-to-host intent.
272 private void createHostIntent(ObjectNode event) {
Thomas Vachuska690e5f62014-11-09 08:26:47 -0800273 ObjectNode payload = payload(event);
274 long id = number(event, "sid");
Thomas Vachuska4830d392014-11-09 17:09:56 -0800275 // TODO: add protection against device ids and non-existent hosts.
276 HostId one = hostId(string(payload, "one"));
277 HostId two = hostId(string(payload, "two"));
Thomas Vachuska690e5f62014-11-09 08:26:47 -0800278
Thomas Vachuska4830d392014-11-09 17:09:56 -0800279 HostToHostIntent hostIntent = new HostToHostIntent(appId, one, two,
280 DefaultTrafficSelector.builder().build(),
281 DefaultTrafficTreatment.builder().build());
Thomas Vachuska47635c62014-11-22 01:21:36 -0800282 trafficEvent = event;
Thomas Vachuska4830d392014-11-09 17:09:56 -0800283 intentService.submit(hostIntent);
Thomas Vachuska690e5f62014-11-09 08:26:47 -0800284 }
285
Thomas Vachuska47635c62014-11-22 01:21:36 -0800286 private synchronized long startMonitoring(ObjectNode event) {
287 if (trafficTask == null) {
288 trafficEvent = event;
289 trafficTask = new TrafficMonitor();
290 timer.schedule(trafficTask, TRAFFIC_FREQUENCY_SEC, TRAFFIC_FREQUENCY_SEC);
291 }
292 return number(event, "sid");
293 }
294
295 private synchronized void stopMonitoring() {
296 if (trafficTask != null) {
297 trafficTask.cancel();
298 trafficTask = null;
299 trafficEvent = null;
300 }
301 }
302
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800303 // Subscribes for host traffic messages.
304 private synchronized void requestAllTraffic(ObjectNode event) {
305 ObjectNode payload = payload(event);
Thomas Vachuska47635c62014-11-22 01:21:36 -0800306 long sid = startMonitoring(event);
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800307 sendMessage(trafficSummaryMessage(sid));
308 }
309
Thomas Vachuska29617e52014-11-20 03:17:46 -0800310 private void requestDeviceLinkFlows(ObjectNode event) {
311 ObjectNode payload = payload(event);
Thomas Vachuska47635c62014-11-22 01:21:36 -0800312 long sid = startMonitoring(event);
Thomas Vachuska29617e52014-11-20 03:17:46 -0800313
314 // Get the set of selected hosts and their intents.
315 ArrayNode ids = (ArrayNode) payload.path("ids");
316 Set<Host> hosts = new HashSet<>();
317 Set<Device> devices = getDevices(ids);
318
319 // If there is a hover node, include it in the hosts and find intents.
320 String hover = string(payload, "hover");
321 Set<Intent> hoverIntents;
322 if (!isNullOrEmpty(hover)) {
323 addHover(hosts, devices, hover);
324 }
325 sendMessage(flowSummaryMessage(sid, devices));
326 }
327
328
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800329 // Subscribes for host traffic messages.
Thomas Vachuska22e34922014-11-14 00:40:55 -0800330 private synchronized void requestTraffic(ObjectNode event) {
Thomas Vachuska690e5f62014-11-09 08:26:47 -0800331 ObjectNode payload = payload(event);
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800332 if (!payload.has("ids")) {
333 return;
334 }
335
Thomas Vachuska47635c62014-11-22 01:21:36 -0800336 long sid = startMonitoring(event);
Thomas Vachuska690e5f62014-11-09 08:26:47 -0800337
Thomas Vachuskae7591e52014-11-13 21:31:15 -0800338 // Get the set of selected hosts and their intents.
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800339 ArrayNode ids = (ArrayNode) payload.path("ids");
340 Set<Host> hosts = getHosts(ids);
341 Set<Device> devices = getDevices(ids);
342 Set<Intent> intents = intentFilter.findPathIntents(hosts, devices);
Thomas Vachuskae7591e52014-11-13 21:31:15 -0800343
344 // If there is a hover node, include it in the hosts and find intents.
345 String hover = string(payload, "hover");
346 Set<Intent> hoverIntents;
347 if (!isNullOrEmpty(hover)) {
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800348 addHover(hosts, devices, hover);
349 hoverIntents = intentFilter.findPathIntents(hosts, devices);
Thomas Vachuskae7591e52014-11-13 21:31:15 -0800350 intents.removeAll(hoverIntents);
351
352 // Send an initial message to highlight all links of all monitored intents.
353 sendMessage(trafficMessage(sid,
354 new TrafficClass("primary", hoverIntents),
355 new TrafficClass("secondary", intents)));
356
357 } else {
358 // Send an initial message to highlight all links of all monitored intents.
359 sendMessage(trafficMessage(sid, new TrafficClass("primary", intents)));
Thomas Vachuska690e5f62014-11-09 08:26:47 -0800360 }
361 }
362
363 // Cancels sending traffic messages.
364 private void cancelTraffic(ObjectNode event) {
Thomas Vachuskae7591e52014-11-13 21:31:15 -0800365 sendMessage(trafficMessage(number(event, "sid")));
Thomas Vachuska47635c62014-11-22 01:21:36 -0800366 stopMonitoring();
Thomas Vachuskadea45ff2014-11-12 18:35:46 -0800367 }
368
Thomas Vachuska47635c62014-11-22 01:21:36 -0800369
370 // Subscribes for summary messages.
371 private synchronized void requestSummary(ObjectNode event) {
372 if (summaryTask == null) {
373 summaryEvent = event;
374 summaryTask = new SummaryMonitor();
375 timer.schedule(summaryTask, SUMMARY_FREQUENCY_SEC, SUMMARY_FREQUENCY_SEC);
376 }
377 sendMessage(summmaryMessage(number(event, "sid")));
378 }
379
380 // Cancels sending summary messages.
381 private synchronized void cancelSummary(ObjectNode event) {
382 if (summaryTask != null) {
383 summaryTask.cancel();
384 summaryTask = null;
385 summaryEvent = null;
386 }
387 }
388
389
Thomas Vachuskaa7c3dd12014-11-11 09:10:19 -0800390 // Adds all internal listeners.
391 private void addListeners() {
392 clusterService.addListener(clusterListener);
393 deviceService.addListener(deviceListener);
394 linkService.addListener(linkListener);
395 hostService.addListener(hostListener);
Thomas Vachuskaa7c3dd12014-11-11 09:10:19 -0800396 intentService.addListener(intentListener);
397 }
398
399 // Removes all internal listeners.
Thomas Vachuskadea45ff2014-11-12 18:35:46 -0800400 private synchronized void removeListeners() {
401 if (!listenersRemoved) {
402 listenersRemoved = true;
403 clusterService.removeListener(clusterListener);
404 deviceService.removeListener(deviceListener);
405 linkService.removeListener(linkListener);
406 hostService.removeListener(hostListener);
Thomas Vachuskadea45ff2014-11-12 18:35:46 -0800407 intentService.removeListener(intentListener);
408 }
Thomas Vachuskaa7c3dd12014-11-11 09:10:19 -0800409 }
410
411 // Cluster event listener.
412 private class InternalClusterListener implements ClusterEventListener {
413 @Override
414 public void event(ClusterEvent event) {
415 sendMessage(instanceMessage(event));
Thomas Vachuska690e5f62014-11-09 08:26:47 -0800416 }
417 }
418
Thomas Vachuskaa7c3dd12014-11-11 09:10:19 -0800419 // Device event listener.
Thomas Vachuska690e5f62014-11-09 08:26:47 -0800420 private class InternalDeviceListener implements DeviceListener {
421 @Override
422 public void event(DeviceEvent event) {
423 sendMessage(deviceMessage(event));
424 }
425 }
426
Thomas Vachuskaa7c3dd12014-11-11 09:10:19 -0800427 // Link event listener.
Thomas Vachuska690e5f62014-11-09 08:26:47 -0800428 private class InternalLinkListener implements LinkListener {
429 @Override
430 public void event(LinkEvent event) {
431 sendMessage(linkMessage(event));
432 }
433 }
434
Thomas Vachuskaa7c3dd12014-11-11 09:10:19 -0800435 // Host event listener.
Thomas Vachuska690e5f62014-11-09 08:26:47 -0800436 private class InternalHostListener implements HostListener {
437 @Override
438 public void event(HostEvent event) {
439 sendMessage(hostMessage(event));
440 }
441 }
442
Thomas Vachuskaa7c3dd12014-11-11 09:10:19 -0800443 // Intent event listener.
Thomas Vachuska4830d392014-11-09 17:09:56 -0800444 private class InternalIntentListener implements IntentListener {
445 @Override
446 public void event(IntentEvent event) {
Thomas Vachuska47635c62014-11-22 01:21:36 -0800447 if (trafficEvent != null) {
448 requestTraffic(trafficEvent);
Thomas Vachuska4830d392014-11-09 17:09:56 -0800449 }
450 }
451 }
Thomas Vachuskaa7c3dd12014-11-11 09:10:19 -0800452
Thomas Vachuska47635c62014-11-22 01:21:36 -0800453 private class TrafficMonitor extends TimerTask {
Thomas Vachuska22e34922014-11-14 00:40:55 -0800454 @Override
455 public void run() {
Thomas Vachuska47635c62014-11-22 01:21:36 -0800456 if (trafficEvent != null) {
457 String type = string(trafficEvent, "event", "unknown");
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800458 if (type.equals("requestAllTraffic")) {
Thomas Vachuska47635c62014-11-22 01:21:36 -0800459 requestAllTraffic(trafficEvent);
Thomas Vachuska29617e52014-11-20 03:17:46 -0800460 } else if (type.equals("requestDeviceLinkFlows")) {
Thomas Vachuska47635c62014-11-22 01:21:36 -0800461 requestDeviceLinkFlows(trafficEvent);
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800462 } else {
Thomas Vachuska47635c62014-11-22 01:21:36 -0800463 requestTraffic(trafficEvent);
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800464 }
Thomas Vachuska22e34922014-11-14 00:40:55 -0800465 }
466 }
467 }
Thomas Vachuska47635c62014-11-22 01:21:36 -0800468
469 private class SummaryMonitor extends TimerTask {
470 @Override
471 public void run() {
472 if (summaryEvent != null) {
473 requestSummary(summaryEvent);
474 }
475 }
476 }
477
Thomas Vachuska7d638d32014-11-07 10:24:43 -0800478}
479