1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.websocket.client.io;
20
21 import java.net.InetSocketAddress;
22 import java.net.SocketAddress;
23 import java.net.URI;
24 import java.nio.channels.SocketChannel;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.Locale;
28 import java.util.Queue;
29 import java.util.concurrent.ConcurrentLinkedQueue;
30
31 import org.eclipse.jetty.util.component.ContainerLifeCycle;
32 import org.eclipse.jetty.util.log.Log;
33 import org.eclipse.jetty.util.log.Logger;
34 import org.eclipse.jetty.websocket.api.WebSocketException;
35 import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
36 import org.eclipse.jetty.websocket.client.WebSocketClient;
37 import org.eclipse.jetty.websocket.common.WebSocketSession;
38 import org.eclipse.jetty.websocket.common.events.EventDriver;
39
40
41
42
43
44 public class ConnectionManager extends ContainerLifeCycle
45 {
46 private class PhysicalConnect extends ConnectPromise
47 {
48 private SocketAddress bindAddress;
49
50 public PhysicalConnect(WebSocketClient client, EventDriver driver, ClientUpgradeRequest request)
51 {
52 super(client,driver,request);
53 this.bindAddress = client.getBindAddress();
54 }
55
56 @Override
57 public void run()
58 {
59 try
60 {
61 SocketChannel channel = SocketChannel.open();
62 if (bindAddress != null)
63 {
64 channel.bind(bindAddress);
65 }
66
67 URI wsUri = getRequest().getRequestURI();
68
69 channel.socket().setTcpNoDelay(true);
70 channel.configureBlocking(false);
71
72 InetSocketAddress address = toSocketAddress(wsUri);
73
74 channel.connect(address);
75 getSelector().connect(channel,this);
76 }
77 catch (Throwable t)
78 {
79 failed(t);
80 }
81 }
82 }
83
84 private class VirtualConnect extends ConnectPromise
85 {
86 public VirtualConnect(WebSocketClient client, EventDriver driver, ClientUpgradeRequest request)
87 {
88 super(client,driver,request);
89 }
90
91 @Override
92 public void run()
93 {
94 failed(new WebSocketException("MUX Not yet supported"));
95 }
96 }
97
98 private static final Logger LOG = Log.getLogger(ConnectionManager.class);
99
100 public static InetSocketAddress toSocketAddress(URI uri)
101 {
102 if (!uri.isAbsolute())
103 {
104 throw new IllegalArgumentException("Cannot get InetSocketAddress of non-absolute URIs");
105 }
106
107 int port = uri.getPort();
108 String scheme = uri.getScheme().toLowerCase(Locale.ENGLISH);
109 if ("ws".equals(scheme))
110 {
111 if (port == (-1))
112 {
113 port = 80;
114 }
115 }
116 else if ("wss".equals(scheme))
117 {
118 if (port == (-1))
119 {
120 port = 443;
121 }
122 }
123 else
124 {
125 throw new IllegalArgumentException("Only support ws:// and wss:// URIs");
126 }
127
128 return new InetSocketAddress(uri.getHost(),port);
129 }
130
131 private final Queue<WebSocketSession> sessions = new ConcurrentLinkedQueue<>();
132 private final WebSocketClient client;
133 private WebSocketClientSelectorManager selector;
134
135 public ConnectionManager(WebSocketClient client)
136 {
137 this.client = client;
138 }
139
140 public void addSession(WebSocketSession session)
141 {
142 sessions.add(session);
143 }
144
145 private void closeAllConnections()
146 {
147 for (WebSocketSession session : sessions)
148 {
149 if (session.getConnection() != null)
150 {
151 try
152 {
153 session.getConnection().close();
154 }
155 catch (Throwable t)
156 {
157 LOG.debug("During Close All Connections",t);
158 }
159 }
160 }
161 }
162
163 public ConnectPromise connect(WebSocketClient client, EventDriver driver, ClientUpgradeRequest request)
164 {
165 URI toUri = request.getRequestURI();
166 String hostname = toUri.getHost();
167
168 if (isVirtualConnectionPossibleTo(hostname))
169 {
170 return new VirtualConnect(client,driver,request);
171 }
172
173 return new PhysicalConnect(client,driver,request);
174 }
175
176 @Override
177 protected void doStart() throws Exception
178 {
179 selector = newWebSocketClientSelectorManager(client);
180 selector.setSslContextFactory(client.getSslContextFactory());
181 selector.setConnectTimeout(client.getConnectTimeout());
182 addBean(selector);
183
184 super.doStart();
185 }
186
187 @Override
188 protected void doStop() throws Exception
189 {
190 closeAllConnections();
191 sessions.clear();
192 super.doStop();
193 removeBean(selector);
194 }
195
196 public WebSocketClientSelectorManager getSelector()
197 {
198 return selector;
199 }
200
201 public Collection<WebSocketSession> getSessions()
202 {
203 return Collections.unmodifiableCollection(sessions);
204 }
205
206 public boolean isVirtualConnectionPossibleTo(String hostname)
207 {
208
209 return false;
210 }
211
212
213
214
215
216
217
218
219 protected WebSocketClientSelectorManager newWebSocketClientSelectorManager(WebSocketClient client)
220 {
221 return new WebSocketClientSelectorManager(client);
222 }
223
224 public void removeSession(WebSocketSession session)
225 {
226 sessions.remove(session);
227 }
228 }