1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.websocket;
16
17 import java.io.IOException;
18 import java.net.URI;
19 import java.nio.ByteBuffer;
20 import java.util.concurrent.Future;
21
22 import org.htmlunit.WebClient;
23 import org.htmlunit.WebClientOptions;
24 import org.htmlunit.jetty.util.ssl.SslContextFactory;
25 import org.htmlunit.jetty.websocket.api.Session;
26 import org.htmlunit.jetty.websocket.api.WebSocketPolicy;
27 import org.htmlunit.jetty.websocket.client.WebSocketClient;
28
29
30
31
32
33
34 public abstract class JettyWebSocketAdapter implements WebSocketAdapter {
35 private final Object clientLock_ = new Object();
36 private WebSocketClient client_;
37
38 private volatile Session incomingSession_;
39 private Session outgoingSession_;
40
41
42
43
44
45 public JettyWebSocketAdapter(final WebClient webClient) {
46 super();
47 final WebClientOptions options = webClient.getOptions();
48
49 if (webClient.getOptions().isUseInsecureSSL()) {
50 client_ = new WebSocketClient(new SslContextFactory(true), null, null);
51
52
53
54 }
55 else {
56 client_ = new WebSocketClient();
57 }
58
59
60 client_.setExecutor(webClient.getExecutor());
61
62 client_.getHttpClient().setCookieStore(new WebSocketCookieStore(webClient));
63
64 final WebSocketPolicy policy = client_.getPolicy();
65 int size = options.getWebSocketMaxBinaryMessageSize();
66 if (size > 0) {
67 policy.setMaxBinaryMessageSize(size);
68 }
69 size = options.getWebSocketMaxBinaryMessageBufferSize();
70 if (size > 0) {
71 policy.setMaxBinaryMessageBufferSize(size);
72 }
73 size = options.getWebSocketMaxTextMessageSize();
74 if (size > 0) {
75 policy.setMaxTextMessageSize(size);
76 }
77 size = options.getWebSocketMaxTextMessageBufferSize();
78 if (size > 0) {
79 policy.setMaxTextMessageBufferSize(size);
80 }
81 }
82
83
84
85
86 @Override
87 public void start() throws Exception {
88 synchronized (clientLock_) {
89 client_.start();
90 }
91 }
92
93
94
95
96 @Override
97 public void connect(final URI url) throws Exception {
98 synchronized (clientLock_) {
99 final Future<Session> connectFuture = client_.connect(new JettyWebSocketAdapterImpl(), url);
100 client_.getExecutor().execute(() -> {
101 try {
102 onWebSocketConnecting();
103 incomingSession_ = connectFuture.get();
104 }
105 catch (final Exception e) {
106 onWebSocketConnectError(e);
107 }
108 });
109 }
110 }
111
112
113
114
115 @Override
116 public void send(final Object content) throws IOException {
117 if (content instanceof String) {
118 outgoingSession_.getRemote().sendString((String) content);
119 }
120 else if (content instanceof ByteBuffer) {
121 outgoingSession_.getRemote().sendBytes((ByteBuffer) content);
122 }
123 else {
124 throw new IllegalStateException(
125 "Not Yet Implemented: WebSocket.send() was used to send non-string value");
126 }
127 }
128
129
130
131
132 @Override
133 public void closeIncommingSession() {
134 if (incomingSession_ != null) {
135 incomingSession_.close();
136 }
137 }
138
139
140
141
142 @Override
143 public void closeOutgoingSession() {
144 if (outgoingSession_ != null) {
145 outgoingSession_.close();
146 }
147 }
148
149
150
151
152 @Override
153 public void closeClient() throws Exception {
154 synchronized (clientLock_) {
155 if (client_ != null) {
156 client_.stop();
157 client_.destroy();
158
159
160 client_ = null;
161 }
162 }
163 }
164
165 private class JettyWebSocketAdapterImpl extends org.htmlunit.jetty.websocket.api.WebSocketAdapter {
166
167
168
169
170 JettyWebSocketAdapterImpl() {
171 super();
172 }
173
174
175
176
177 @Override
178 public void onWebSocketConnect(final Session session) {
179 super.onWebSocketConnect(session);
180 outgoingSession_ = session;
181
182 JettyWebSocketAdapter.this.onWebSocketConnect();
183 }
184
185
186
187
188 @Override
189 public void onWebSocketClose(final int statusCode, final String reason) {
190 super.onWebSocketClose(statusCode, reason);
191 outgoingSession_ = null;
192
193 JettyWebSocketAdapter.this.onWebSocketClose(statusCode, reason);
194 }
195
196
197
198
199 @Override
200 public void onWebSocketText(final String message) {
201 super.onWebSocketText(message);
202
203 JettyWebSocketAdapter.this.onWebSocketText(message);
204 }
205
206
207
208
209 @Override
210 public void onWebSocketBinary(final byte[] data, final int offset, final int length) {
211 super.onWebSocketBinary(data, offset, length);
212
213 JettyWebSocketAdapter.this.onWebSocketBinary(data, offset, length);
214 }
215
216
217
218
219 @Override
220 public void onWebSocketError(final Throwable cause) {
221 super.onWebSocketError(cause);
222 outgoingSession_ = null;
223
224 JettyWebSocketAdapter.this.onWebSocketError(cause);
225 }
226 }
227 }