Initial sketch of the GUI web-socket mechanics.
Change-Id: I5f481886fd45ce058be4aaf07fba466e702ae7ad
Showing
8 changed files
with
273 additions
and
0 deletions
... | @@ -119,6 +119,7 @@ | ... | @@ -119,6 +119,7 @@ |
119 | description="ONOS GUI console components"> | 119 | description="ONOS GUI console components"> |
120 | <feature>onos-api</feature> | 120 | <feature>onos-api</feature> |
121 | <feature>onos-thirdparty-web</feature> | 121 | <feature>onos-thirdparty-web</feature> |
122 | + <bundle>mvn:org.eclipse.jetty/jetty-websocket/8.1.15.v20140411</bundle> | ||
122 | <bundle>mvn:org.onlab.onos/onos-gui/1.0.0-SNAPSHOT</bundle> | 123 | <bundle>mvn:org.onlab.onos/onos-gui/1.0.0-SNAPSHOT</bundle> |
123 | </feature> | 124 | </feature> |
124 | 125 | ... | ... |
... | @@ -35,4 +35,16 @@ | ... | @@ -35,4 +35,16 @@ |
35 | <web.context>/onos/ui</web.context> | 35 | <web.context>/onos/ui</web.context> |
36 | </properties> | 36 | </properties> |
37 | 37 | ||
38 | + <dependencies> | ||
39 | + <dependency> | ||
40 | + <groupId>org.eclipse.jetty</groupId> | ||
41 | + <artifactId>jetty-websocket</artifactId> | ||
42 | + <version>8.1.15.v20140411</version> | ||
43 | + </dependency> | ||
44 | + <dependency> | ||
45 | + <groupId>javax.servlet</groupId> | ||
46 | + <artifactId>servlet-api</artifactId> | ||
47 | + <version>2.5</version> | ||
48 | + </dependency> | ||
49 | + </dependencies> | ||
38 | </project> | 50 | </project> | ... | ... |
1 | +/* | ||
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 | + */ | ||
16 | +package org.onlab.onos.gui; | ||
17 | + | ||
18 | +import org.eclipse.jetty.websocket.WebSocket; | ||
19 | +import org.eclipse.jetty.websocket.WebSocketServlet; | ||
20 | +import org.onlab.osgi.DefaultServiceDirectory; | ||
21 | +import org.onlab.osgi.ServiceDirectory; | ||
22 | + | ||
23 | +import javax.servlet.http.HttpServletRequest; | ||
24 | + | ||
25 | +/** | ||
26 | + * Web socket servlet capable of creating various sockets for the user interface. | ||
27 | + */ | ||
28 | +public class GuiWebSocketServlet extends WebSocketServlet { | ||
29 | + | ||
30 | + private ServiceDirectory directory = new DefaultServiceDirectory(); | ||
31 | + | ||
32 | + @Override | ||
33 | + public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) { | ||
34 | + | ||
35 | + return new TopologyWebSocket(directory); | ||
36 | + } | ||
37 | + | ||
38 | +} |
1 | +/* | ||
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 | + */ | ||
16 | +package org.onlab.onos.gui; | ||
17 | + | ||
18 | +import org.eclipse.jetty.websocket.WebSocket; | ||
19 | +import org.onlab.onos.net.device.DeviceService; | ||
20 | +import org.onlab.onos.net.topology.Topology; | ||
21 | +import org.onlab.onos.net.topology.TopologyEdge; | ||
22 | +import org.onlab.onos.net.topology.TopologyEvent; | ||
23 | +import org.onlab.onos.net.topology.TopologyGraph; | ||
24 | +import org.onlab.onos.net.topology.TopologyListener; | ||
25 | +import org.onlab.onos.net.topology.TopologyService; | ||
26 | +import org.onlab.onos.net.topology.TopologyVertex; | ||
27 | +import org.onlab.osgi.ServiceDirectory; | ||
28 | + | ||
29 | +import java.io.IOException; | ||
30 | + | ||
31 | +/** | ||
32 | + * Web socket capable of interacting with the GUI topology view. | ||
33 | + */ | ||
34 | +public class TopologyWebSocket implements WebSocket.OnTextMessage, TopologyListener { | ||
35 | + | ||
36 | + private final ServiceDirectory directory; | ||
37 | + private final TopologyService topologyService; | ||
38 | + private final DeviceService deviceService; | ||
39 | + | ||
40 | + private Connection connection; | ||
41 | + | ||
42 | + /** | ||
43 | + * Creates a new web-socket for serving data to GUI topology view. | ||
44 | + * | ||
45 | + * @param directory service directory | ||
46 | + */ | ||
47 | + public TopologyWebSocket(ServiceDirectory directory) { | ||
48 | + this.directory = directory; | ||
49 | + topologyService = directory.get(TopologyService.class); | ||
50 | + deviceService = directory.get(DeviceService.class); | ||
51 | + } | ||
52 | + | ||
53 | + @Override | ||
54 | + public void onOpen(Connection connection) { | ||
55 | + this.connection = connection; | ||
56 | + | ||
57 | + // Register for topology events... | ||
58 | + if (topologyService != null && deviceService != null) { | ||
59 | + topologyService.addListener(this); | ||
60 | + | ||
61 | + sendMessage("Yo!!!"); | ||
62 | + | ||
63 | + Topology topology = topologyService.currentTopology(); | ||
64 | + TopologyGraph graph = topologyService.getGraph(topology); | ||
65 | + for (TopologyVertex vertex : graph.getVertexes()) { | ||
66 | + sendMessage(deviceService.getDevice(vertex.deviceId()).toString()); | ||
67 | + } | ||
68 | + | ||
69 | + for (TopologyEdge edge : graph.getEdges()) { | ||
70 | + sendMessage(edge.link().toString()); | ||
71 | + } | ||
72 | + | ||
73 | + sendMessage("That's what we're starting with..."); | ||
74 | + | ||
75 | + } else { | ||
76 | + sendMessage("No topology service!!!"); | ||
77 | + } | ||
78 | + } | ||
79 | + | ||
80 | + @Override | ||
81 | + public void onClose(int closeCode, String message) { | ||
82 | + TopologyService topologyService = directory.get(TopologyService.class); | ||
83 | + if (topologyService != null) { | ||
84 | + topologyService.removeListener(this); | ||
85 | + } | ||
86 | + } | ||
87 | + | ||
88 | + @Override | ||
89 | + public void onMessage(String data) { | ||
90 | + System.out.println("Received: " + data); | ||
91 | + } | ||
92 | + | ||
93 | + public void sendMessage(String data) { | ||
94 | + try { | ||
95 | + connection.sendMessage(data); | ||
96 | + } catch (IOException e) { | ||
97 | + e.printStackTrace(); | ||
98 | + } | ||
99 | + } | ||
100 | + | ||
101 | + @Override | ||
102 | + public void event(TopologyEvent event) { | ||
103 | + sendMessage(event.toString()); | ||
104 | + } | ||
105 | +} | ||
106 | + |
... | @@ -39,4 +39,16 @@ | ... | @@ -39,4 +39,16 @@ |
39 | <url-pattern>/rs/*</url-pattern> | 39 | <url-pattern>/rs/*</url-pattern> |
40 | </servlet-mapping> | 40 | </servlet-mapping> |
41 | 41 | ||
42 | + <servlet> | ||
43 | + <servlet-name>Web Socket Service</servlet-name> | ||
44 | + <servlet-class>org.onlab.onos.gui.GuiWebSocketServlet</servlet-class> | ||
45 | + <load-on-startup>2</load-on-startup> | ||
46 | + </servlet> | ||
47 | + | ||
48 | + <servlet-mapping> | ||
49 | + <servlet-name>Web Socket Service</servlet-name> | ||
50 | + <url-pattern>/ws/*</url-pattern> | ||
51 | + </servlet-mapping> | ||
52 | + | ||
53 | + | ||
42 | </web-app> | 54 | </web-app> |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -40,6 +40,7 @@ | ... | @@ -40,6 +40,7 @@ |
40 | showBackground: true | 40 | showBackground: true |
41 | }, | 41 | }, |
42 | backgroundUrl: 'img/us-map.png', | 42 | backgroundUrl: 'img/us-map.png', |
43 | + webSockUrl: 'ws/topology', | ||
43 | data: { | 44 | data: { |
44 | live: { | 45 | live: { |
45 | jsonUrl: 'rs/topology/graph', | 46 | jsonUrl: 'rs/topology/graph', |
... | @@ -130,6 +131,7 @@ | ... | @@ -130,6 +131,7 @@ |
130 | links: [], | 131 | links: [], |
131 | lookup: {} | 132 | lookup: {} |
132 | }, | 133 | }, |
134 | + webSock, | ||
133 | labelIdx = 0, | 135 | labelIdx = 0, |
134 | selected = {}, | 136 | selected = {}, |
135 | highlighted = null, | 137 | highlighted = null, |
... | @@ -579,6 +581,52 @@ | ... | @@ -579,6 +581,52 @@ |
579 | } | 581 | } |
580 | 582 | ||
581 | // ============================== | 583 | // ============================== |
584 | + // Web-Socket for live data | ||
585 | + | ||
586 | + function webSockUrl() { | ||
587 | + return document.location.toString() | ||
588 | + .replace(/\#.*/, '') | ||
589 | + .replace('http://', 'ws://') | ||
590 | + .replace('https://', 'wss://') | ||
591 | + .replace('index2.html', config.webSockUrl); | ||
592 | + } | ||
593 | + | ||
594 | + webSock = { | ||
595 | + ws : null, | ||
596 | + | ||
597 | + connect : function() { | ||
598 | + webSock.ws = new WebSocket(webSockUrl()); | ||
599 | + | ||
600 | + webSock.ws.onopen = function() { | ||
601 | + webSock._send("Hi there!"); | ||
602 | + }; | ||
603 | + | ||
604 | + webSock.ws.onmessage = function(m) { | ||
605 | + if (m.data) { | ||
606 | + console.log(m.data); | ||
607 | + } | ||
608 | + }; | ||
609 | + | ||
610 | + webSock.ws.onclose = function(m) { | ||
611 | + webSock.ws = null; | ||
612 | + }; | ||
613 | + }, | ||
614 | + | ||
615 | + send : function(text) { | ||
616 | + if (text != null && text.length > 0) { | ||
617 | + webSock._send(text); | ||
618 | + } | ||
619 | + }, | ||
620 | + | ||
621 | + _send : function(message) { | ||
622 | + if (webSock.ws) { | ||
623 | + webSock.ws.send(message); | ||
624 | + } | ||
625 | + } | ||
626 | + | ||
627 | + }; | ||
628 | + | ||
629 | + // ============================== | ||
582 | // View life-cycle callbacks | 630 | // View life-cycle callbacks |
583 | 631 | ||
584 | function preload(view, ctx) { | 632 | function preload(view, ctx) { |
... | @@ -656,6 +704,7 @@ | ... | @@ -656,6 +704,7 @@ |
656 | .on('tick', tick); | 704 | .on('tick', tick); |
657 | 705 | ||
658 | network.drag = d3u.createDragBehavior(network.force, selectCb, atDragEnd); | 706 | network.drag = d3u.createDragBehavior(network.force, selectCb, atDragEnd); |
707 | + webSock.connect(); | ||
659 | } | 708 | } |
660 | 709 | ||
661 | function load(view, ctx) { | 710 | function load(view, ctx) { | ... | ... |
web/gui/src/main/webapp/ws.html
0 → 100644
1 | +<html> | ||
2 | +<head> | ||
3 | + <title>Web Sockets Demo</title> | ||
4 | + | ||
5 | + <script src="libs/jquery-2.1.1.min.js"></script> | ||
6 | + | ||
7 | + <script type='text/javascript'> | ||
8 | + if (!window.WebSocket) | ||
9 | + alert("WebSocket not supported by this browser"); | ||
10 | + | ||
11 | + var server = { | ||
12 | + connect : function() { | ||
13 | + var location = document.location.toString().replace('http://', | ||
14 | + 'ws://').replace('https://', 'wss://').replace('ws.html','ws/topology'); | ||
15 | + this.ws = new WebSocket(location); | ||
16 | + | ||
17 | + this.ws.onopen = function() { | ||
18 | + server._send("Hi there!"); | ||
19 | + }; | ||
20 | + | ||
21 | + this.ws.onmessage = function(m) { | ||
22 | + if (m.data) { | ||
23 | + $('#log').append(m.data).append($('<br/>')); | ||
24 | + } | ||
25 | + }; | ||
26 | + | ||
27 | + this.ws.onclose = function(m) { | ||
28 | + this.ws = null; | ||
29 | + }; | ||
30 | + }, | ||
31 | + | ||
32 | + _send : function(message) { | ||
33 | + if (this.ws) { | ||
34 | + this.ws.send(message); | ||
35 | + } | ||
36 | + }, | ||
37 | + | ||
38 | + send : function(text) { | ||
39 | + if (text != null && text.length > 0) { | ||
40 | + server._send(text); | ||
41 | + } | ||
42 | + } | ||
43 | + }; | ||
44 | + </script> | ||
45 | +</head> | ||
46 | +<body> | ||
47 | +<pre id='log'></pre> | ||
48 | + | ||
49 | +<script type='text/javascript'> | ||
50 | + server.connect(); | ||
51 | +</script> | ||
52 | + | ||
53 | +</body> | ||
54 | +</html> |
... | @@ -131,6 +131,7 @@ | ... | @@ -131,6 +131,7 @@ |
131 | com.fasterxml.jackson.databind, | 131 | com.fasterxml.jackson.databind, |
132 | com.fasterxml.jackson.databind.node, | 132 | com.fasterxml.jackson.databind.node, |
133 | com.google.common.base.*, | 133 | com.google.common.base.*, |
134 | + org.eclipse.jetty.websocket.*, | ||
134 | org.onlab.api.*, | 135 | org.onlab.api.*, |
135 | org.onlab.osgi.*, | 136 | org.onlab.osgi.*, |
136 | org.onlab.packet.*, | 137 | org.onlab.packet.*, | ... | ... |
-
Please register or login to post a comment