001/*
002 * Copyright (C) 2015-2017 Neo Visionaries Inc.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package NeoVisionaries.WebSockets;
017
018
019import static NeoVisionaries.WebSockets.WebSocketState.CLOSED;
020import static NeoVisionaries.WebSockets.WebSocketState.CLOSING;
021import static NeoVisionaries.WebSockets.WebSocketState.CONNECTING;
022import static NeoVisionaries.WebSockets.WebSocketState.CREATED;
023import static NeoVisionaries.WebSockets.WebSocketState.OPEN;
024
025import java.io.BufferedInputStream;
026import java.io.BufferedOutputStream;
027import java.io.IOException;
028import java.net.Socket;
029import java.net.URI;
030import java.util.List;
031import java.util.Map;
032import java.util.concurrent.Callable;
033import java.util.concurrent.ExecutorService;
034import java.util.concurrent.Future;
035import java.util.concurrent.RejectedExecutionException;
036
037import NeoVisionaries.WebSockets.StateManager.CloseInitiator;
038
039
040/**
041 * WebSocket.
042 * 
043 * <EMBED CLASS='external-html' DATA-FILE-ID=LICENSE><BR />
044 *
045 * <h3>Create WebSocketFactory</h3>
046 *
047 * <p>
048 * {@link WebSocketFactory} is a factory class that creates
049 * {@link WebSocket} instances. The first step is to create a
050 * {@code WebSocketFactory} instance.
051 * </p>
052 *
053 * <blockquote>
054 * <pre style="border-left: solid 5px lightgray;"> <span style="color: green;">// Create a WebSocketFactory instance.</span>
055 * WebSocketFactory factory = new {@link WebSocketFactory#WebSocketFactory()
056 * WebSocketFactory()};</pre>
057 * </blockquote>
058 *
059 * <p>
060 * By default, {@code WebSocketFactory} uses {@link
061 * javax.net.SocketFactory SocketFactory}{@code .}{@link
062 * javax.net.SocketFactory#getDefault() getDefault()} for
063 * non-secure WebSocket connections ({@code ws:}) and {@link
064 * javax.net.ssl.SSLSocketFactory SSLSocketFactory}{@code
065 * .}{@link javax.net.ssl.SSLSocketFactory#getDefault()
066 * getDefault()} for secure WebSocket connections ({@code
067 * wss:}). You can change this default behavior by using
068 * {@code WebSocketFactory.}{@link
069 * WebSocketFactory#setSocketFactory(javax.net.SocketFactory)
070 * setSocketFactory} method, {@code WebSocketFactory.}{@link
071 * WebSocketFactory#setSSLSocketFactory(javax.net.ssl.SSLSocketFactory)
072 * setSSLSocketFactory} method and {@code WebSocketFactory.}{@link
073 * WebSocketFactory#setSSLContext(javax.net.ssl.SSLContext)
074 * setSSLContext} method. Note that you don't have to call a {@code
075 * setSSL*} method at all if you use the default SSL configuration.
076 * Also note that calling {@code setSSLSocketFactory} method has no
077 * meaning if you have called {@code setSSLContext} method. See the
078 * description of {@code WebSocketFactory.}{@link
079 * WebSocketFactory#createSocket(URI) createSocket(URI)} method for
080 * details.
081 * </p>
082 *
083 * <p>
084 * The following is an example to set a custom SSL context to a
085 * {@code WebSocketFactory} instance. (Again, you don't have to call a
086 * {@code setSSL*} method if you use the default SSL configuration.)
087 * </p>
088 *
089 * <blockquote>
090 * <pre style="border-left: solid 5px lightgray;"> <span style="color: green;">// Create a custom SSL context.</span>
091 * SSLContext context = <a href="https://gist.github.com/TakahikoKawasaki/d07de2218b4b81bf65ac"
092 * >NaiveSSLContext</a>.getInstance(<span style="color:darkred;">"TLS"</span>);
093 *
094 * <span style="color: green;">// Set the custom SSL context.</span>
095 * factory.{@link WebSocketFactory#setSSLContext(javax.net.ssl.SSLContext)
096 * setSSLContext}(context);
097 *
098 * <span style="color: green;">// Disable manual hostname verification for NaiveSSLContext.
099 * //
100 * // Manual hostname verification has been enabled since the
101 * // version 2.1. Because the verification is executed manually
102 * // after Socket.connect(SocketAddress, int) succeeds, the
103 * // hostname verification is always executed even if you has
104 * // passed an SSLContext which naively accepts any server
105 * // certificate. However, this behavior is not desirable in
106 * // some cases and you may want to disable the hostname
107 * // verification. You can disable the hostname verification
108 * // by calling WebSocketFactory.setVerifyHostname(false).</span>
109 * factory.{@link WebSocketFactory#setVerifyHostname(boolean) setVerifyHostname}(false);</pre>
110 * </blockquote>
111 *
112 * <p>
113 * <a href="https://gist.github.com/TakahikoKawasaki/d07de2218b4b81bf65ac"
114 * >NaiveSSLContext</a> used in the above example is a factory class to
115 * create an {@link javax.net.ssl.SSLContext SSLContext} which naively
116 * accepts all certificates without verification. It's enough for testing
117 * purposes. When you see an error message
118 * "unable to find valid certificate path to requested target" while
119 * testing, try {@code NaiveSSLContext}.
120 * </p>
121 *
122 * <h3>HTTP Proxy</h3>
123 *
124 * <p>
125 * If a WebSocket endpoint needs to be accessed via an HTTP proxy,
126 * information about the proxy server has to be set to a {@code
127 * WebSocketFactory} instance before creating a {@code WebSocket}
128 * instance. Proxy settings are represented by {@link ProxySettings}
129 * class. A {@code WebSocketFactory} instance has an associated
130 * {@code ProxySettings} instance and it can be obtained by calling
131 * {@code WebSocketFactory.}{@link WebSocketFactory#getProxySettings()
132 * getProxySettings()} method.
133 * </p>
134 *
135 * <blockquote>
136 * <pre style="border-left: solid 5px lightgray;"> <span style="color: green;">// Get the associated ProxySettings instance.</span>
137 * {@link ProxySettings} settings = factory.{@link
138 * WebSocketFactory#getProxySettings() getProxySettings()};</pre>
139 * </blockquote>
140 *
141 * <p>
142 * {@code ProxySettings} class has methods to set information about
143 * a proxy server such as {@link ProxySettings#setHost(String) setHost}
144 * method and {@link ProxySettings#setPort(int) setPort} method. The
145 * following is an example to set a secure (<code>https</code>) proxy
146 * server.
147 * </p>
148 *
149 * <blockquote>
150 * <pre style="border-left: solid 5px lightgray;"> <span style="color: green;">// Set a proxy server.</span>
151 * settings.{@link ProxySettings#setServer(String)
152 * setServer}(<span style="color:darkred;">"https://proxy.example.com"</span>);</pre>
153 * </blockquote>
154 *
155 * <p>
156 * If credentials are required for authentication at a proxy server,
157 * {@link ProxySettings#setId(String) setId} method and {@link
158 * ProxySettings#setPassword(String) setPassword} method, or
159 * {@link ProxySettings#setCredentials(String, String) setCredentials}
160 * method can be used to set the credentials. Note that, however,
161 * the current implementation supports only Basic Authentication.
162 * </p>
163 *
164 * <blockquote>
165 * <pre style="border-left: solid 5px lightgray;"> <span style="color: green;">// Set credentials for authentication at a proxy server.</span>
166 * settings.{@link ProxySettings#setCredentials(String, String)
167 * setCredentials}(id, password);
168 * </pre>
169 * </blockquote>
170 *
171 * <h3>Create WebSocket</h3>
172 *
173 * <p>
174 * {@link WebSocket} class represents a WebSocket. Its instances are
175 * created by calling one of {@code createSocket} methods of a {@link
176 * WebSocketFactory} instance. Below is the simplest example to create
177 * a {@code WebSocket} instance.
178 * </p>
179 *
180 * <blockquote>
181 * <pre style="border-left: solid 5px lightgray;"> <span style="color: green;">// Create a WebSocket. The scheme part can be one of the following:
182 * // 'ws', 'wss', 'http' and 'https' (case-insensitive). The user info
183 * // part, if any, is interpreted as expected. If a raw socket failed
184 * // to be created, an IOException is thrown.</span>
185 * WebSocket ws = new {@link WebSocketFactory#WebSocketFactory()
186 * WebSocketFactory()}
187 *     .{@link WebSocketFactory#createSocket(String)
188 * createWebSocket}(<span style="color: darkred;">"ws://localhost/endpoint"</span>);</pre>
189 * </blockquote>
190 *
191 * <p>
192 * There are two ways to set a timeout value for socket connection. The
193 * first way is to call {@link WebSocketFactory#setConnectionTimeout(int)
194 * setConnectionTimeout(int timeout)} method of {@code WebSocketFactory}.
195 * </p>
196 *
197 * <blockquote>
198 * <pre style="border-left: solid 5px lightgray;"> <span style="color: green;">// Create a WebSocket factory and set 5000 milliseconds as a timeout
199 * // value for socket connection.</span>
200 * WebSocketFactory factory = new WebSocketFactory().{@link
201 * WebSocketFactory#setConnectionTimeout(int) setConnectionTimeout}(5000);
202 *
203 * <span style="color: green;">// Create a WebSocket. The timeout value set above is used.</span>
204 * WebSocket ws = factory.{@link WebSocketFactory#createSocket(String)
205 * createWebSocket}(<span style="color: darkred;">"ws://localhost/endpoint"</span>);</pre>
206 * </blockquote>
207 *
208 * <p>
209 * The other way is to give a timeout value to a {@code createSocket} method.
210 * </p>
211 *
212 * <blockquote>
213 * <pre style="border-left: solid 5px lightgray;"> <span style="color: green;">// Create a WebSocket factory. The timeout value remains 0.</span>
214 * WebSocketFactory factory = new WebSocketFactory();
215 *
216 * <span style="color: green;">// Create a WebSocket with a socket connection timeout value.</span>
217 * WebSocket ws = factory.{@link WebSocketFactory#createSocket(String, int)
218 * createWebSocket}(<span style="color: darkred;">"ws://localhost/endpoint"</span>, 5000);</pre>
219 * </blockquote>
220 *
221 * <p>
222 * The timeout value is passed to {@link Socket#connect(java.net.SocketAddress, int)
223 * connect}{@code (}{@link java.net.SocketAddress SocketAddress}{@code , int)}
224 * method of {@link java.net.Socket}.
225 * </p>
226 *
227 * <h3>Register Listener</h3>
228 *
229 * <p>
230 * After creating a {@code WebSocket} instance, you should call {@link
231 * #addListener(WebSocketListener)} method to register a {@link
232 * WebSocketListener} that receives WebSocket events. {@link
233 * WebSocketAdapter} is an empty implementation of {@link
234 * WebSocketListener} interface.
235 * </p>
236 *
237 * <blockquote>
238 * <pre style="border-left: solid 5px lightgray;"> <span style="color: green;">// Register a listener to receive WebSocket events.</span>
239 * ws.{@link #addListener(WebSocketListener) addListener}(new {@link
240 * WebSocketAdapter#WebSocketAdapter() WebSocketAdapter()} {
241 *     <span style="color: gray;">{@code @}Override</span>
242 *     public void {@link WebSocketListener#onTextMessage(WebSocket, String)
243 *     onTextMessage}(WebSocket websocket, String message) throws Exception {
244 *         <span style="color: green;">// Received a text message.</span>
245 *         ......
246 *     }
247 * });</pre>
248 * </blockquote>
249 *
250 * <p>
251 * The table below is the list of callback methods defined in {@code WebSocketListener}
252 * interface.
253 * </p>
254 *
255 * <blockquote>
256 * <table border="1" cellpadding="5" style="border-collapse: collapse;">
257 *   <caption>{@code WebSocketListener} methods</caption>
258 *   <thead>
259 *     <tr>
260 *       <th>Method</th>
261 *       <th>Description</th>
262 *     </tr>
263 *   </thead>
264 *   <tbody>
265 *     <tr>
266 *       <td>{@link WebSocketListener#handleCallbackError(WebSocket, Throwable) handleCallbackError}</td>
267 *       <td>Called when an <code>on<i>Xxx</i>()</code> method threw a {@code Throwable}.</td>
268 *     </tr>
269 *     <tr>
270 *       <td>{@link WebSocketListener#onBinaryFrame(WebSocket, WebSocketFrame) onBinaryFrame}</td>
271 *       <td>Called when a binary frame was received.</td>
272 *     </tr>
273 *     <tr>
274 *       <td>{@link WebSocketListener#onBinaryMessage(WebSocket, byte[]) onBinaryMessage}</td>
275 *       <td>Called when a binary message was received.</td>
276 *     </tr>
277 *     <tr>
278 *       <td>{@link WebSocketListener#onCloseFrame(WebSocket, WebSocketFrame) onCloseFrame}</td>
279 *       <td>Called when a close frame was received.</td>
280 *     </tr>
281 *     <tr>
282 *       <td>{@link WebSocketListener#onConnected(WebSocket, Map) onConnected}</td>
283 *       <td>Called after the opening handshake succeeded.</td>
284 *     </tr>
285 *     <tr>
286 *       <td>{@link WebSocketListener#onConnectError(WebSocket, WebSocketException) onConnectError}</td>
287 *       <td>Called when {@link #connectAsynchronously()} failed.</td>
288 *     </tr>
289 *     <tr>
290 *       <td>{@link WebSocketListener#onContinuationFrame(WebSocket, WebSocketFrame) onContinuationFrame}</td>
291 *       <td>Called when a continuation frame was received.</td>
292 *     </tr>
293 *     <tr>
294 *       <td>{@link WebSocketListener#onDisconnected(WebSocket, WebSocketFrame, WebSocketFrame, boolean) onDisconnected}</td>
295 *       <td>Called after a WebSocket connection was closed.</td>
296 *     </tr>
297 *     <tr>
298 *       <td>{@link WebSocketListener#onError(WebSocket, WebSocketException) onError}</td>
299 *       <td>Called when an error occurred.</td>
300 *     </tr>
301 *     <tr>
302 *       <td>{@link WebSocketListener#onFrame(WebSocket, WebSocketFrame) onFrame}</td>
303 *       <td>Called when a frame was received.</td>
304 *     </tr>
305 *     <tr>
306 *       <td>{@link WebSocketListener#onFrameError(WebSocket, WebSocketException, WebSocketFrame) onFrameError}</td>
307 *       <td>Called when a frame failed to be read.</td>
308 *     </tr>
309 *     <tr>
310 *       <td>{@link WebSocketListener#onFrameSent(WebSocket, WebSocketFrame) onFrameSent}</td>
311 *       <td>Called when a frame was sent.</td>
312 *     </tr>
313 *     <tr>
314 *       <td>{@link WebSocketListener#onFrameUnsent(WebSocket, WebSocketFrame) onFrameUnsent}</td>
315 *       <td>Called when a frame was not sent.</td>
316 *     </tr>
317 *     <tr>
318 *       <td>{@link WebSocketListener#onMessageDecompressionError(WebSocket, WebSocketException, byte[]) onMessageDecompressionError}</td>
319 *       <td>Called when a message failed to be decompressed.</td>
320 *     </tr>
321 *     <tr>
322 *       <td>{@link WebSocketListener#onMessageError(WebSocket, WebSocketException, List) onMessageError}</td>
323 *       <td>Called when a message failed to be constructed.</td>
324 *     </tr>
325 *     <tr>
326 *       <td>{@link WebSocketListener#onPingFrame(WebSocket, WebSocketFrame) onPingFrame}</td>
327 *       <td>Called when a ping frame was received.</td>
328 *     </tr>
329 *     <tr>
330 *       <td>{@link WebSocketListener#onPongFrame(WebSocket, WebSocketFrame) onPongFrame}</td>
331 *       <td>Called when a pong frame was received.</td>
332 *     </tr>
333 *     <tr>
334 *       <td>{@link WebSocketListener#onSendError(WebSocket, WebSocketException, WebSocketFrame) onSendError}</td>
335 *       <td>Called when an error occurred on sending a frame.</td>
336 *     </tr>
337 *     <tr>
338 *       <td>{@link WebSocketListener#onSendingFrame(WebSocket, WebSocketFrame) onSendingFrame}</td>
339 *       <td>Called before a frame is sent.</td>
340 *     </tr>
341 *     <tr>
342 *       <td>{@link WebSocketListener#onSendingHandshake(WebSocket, String, List) onSendingHandshake}</td>
343 *       <td>Called before an opening handshake is sent.</td>
344 *     </tr>
345 *     <tr>
346 *       <td>{@link WebSocketListener#onStateChanged(WebSocket, WebSocketState) onStateChanged}</td>
347 *       <td>Called when the state of WebSocket changed.</td>
348 *     </tr>
349 *     <tr>
350 *       <td>{@link WebSocketListener#onTextFrame(WebSocket, WebSocketFrame) onTextFrame}</td>
351 *       <td>Called when a text frame was received.</td>
352 *     </tr>
353 *     <tr>
354 *       <td>{@link WebSocketListener#onTextMessage(WebSocket, String) onTextMessage}</td>
355 *       <td>Called when a text message was received.</td>
356 *     </tr>
357 *     <tr>
358 *       <td>{@link WebSocketListener#onTextMessageError(WebSocket, WebSocketException, byte[]) onTextMessageError}</td>
359 *       <td>Called when a text message failed to be constructed.</td>
360 *     </tr>
361 *     <tr>
362 *       <td>{@link WebSocketListener#onThreadCreated(WebSocket, ThreadType, Thread) onThreadCreated}</td>
363 *       <td>Called after a thread was created.</td>
364 *     </tr>
365 *     <tr>
366 *       <td>{@link WebSocketListener#onThreadStarted(WebSocket, ThreadType, Thread) onThreadStarted}</td>
367 *       <td>Called at the beginning of a thread's {@code run()} method.</td>
368 *     </tr>
369 *     <tr>
370 *       <td>{@link WebSocketListener#onThreadStopping(WebSocket, ThreadType, Thread) onThreadStopping}</td>
371 *       <td>Called at the end of a thread's {@code run()} method.</td>
372 *     </tr>
373 *     <tr>
374 *       <td>{@link WebSocketListener#onUnexpectedError(WebSocket, WebSocketException) onUnexpectedError}</td>
375 *       <td>Called when an uncaught throwable was detected.</td>
376 *     </tr>
377 *   </tbody>
378 * </table>
379 * </blockquote>
380 *
381 * <h3>Configure WebSocket</h3>
382 *
383 * <p>
384 * Before starting a WebSocket <a href="https://tools.ietf.org/html/rfc6455#section-4"
385 * >opening handshake</a> with the server, you can configure the
386 * {@code WebSocket} instance by using the following methods.
387 * </p>
388 *
389 * <blockquote>
390 * <table border="1" cellpadding="5" style="border-collapse: collapse;">
391 *   <caption>Methods for Configuration</caption>
392 *   <thead>
393 *     <tr>
394 *       <th>METHOD</th>
395 *       <th>DESCRIPTION</th>
396 *     </tr>
397 *   </thead>
398 *   <tbody>
399 *     <tr>
400 *       <td>{@link #addProtocol(String) addProtocol}</td>
401 *       <td>Adds an element to {@code Sec-WebSocket-Protocol}</td>
402 *     </tr>
403 *     <tr>
404 *       <td>{@link #addExtension(WebSocketExtension) addExtension}</td>
405 *       <td>Adds an element to {@code Sec-WebSocket-Extensions}</td>
406 *     </tr>
407 *     <tr>
408 *       <td>{@link #addHeader(String, String) addHeader}</td>
409 *       <td>Adds an arbitrary HTTP header.</td>
410 *     </tr>
411 *     <tr>
412 *       <td>{@link #setUserInfo(String, String) setUserInfo}</td>
413 *       <td>Adds {@code Authorization} header for Basic Authentication.</td>
414 *     </tr>
415 *     <tr>
416 *       <td>{@link #getSocket() getSocket}</td>
417 *       <td>
418 *         Gets the underlying {@link Socket} instance to configure it.
419 *         Note that this may return {@code null} since version 2.9.
420 *         Consider using {@link #getConnectedSocket()} as necessary.
421 *       </td>
422 *     </tr>
423 *     <tr>
424 *       <td>{@link #getConnectedSocket() getConnectedSocket}</td>
425 *       <td>
426 *         Establishes and gets the underlying Socket instance to configure it.
427 *         Available since version 2.9.
428 *       </td>
429 *     </tr>
430 *     <tr>
431 *       <td>{@link #setExtended(boolean) setExtended}</td>
432 *       <td>Disables validity checks on RSV1/RSV2/RSV3 and opcode.</td>
433 *     </tr>
434 *     <tr>
435 *       <td>{@link #setFrameQueueSize(int) setFrameQueueSize}</td>
436 *       <td>Set the size of the frame queue for <a href="#congestion_control">congestion control</a>.</td>
437 *     </tr>
438 *     <tr>
439 *       <td>{@link #setMaxPayloadSize(int) setMaxPayloadSize}</td>
440 *       <td>Set the <a href="#maximum_payload_size">maximum payload size</a>.</td>
441 *     </tr>
442 *     <tr>
443 *       <td>{@link #setMissingCloseFrameAllowed(boolean) setMissingCloseFrameAllowed}</td>
444 *       <td>Set whether to allow the server to close the connection without sending a close frame.</td>
445 *     </tr>
446 *   </tbody>
447 * </table>
448 * </blockquote>
449 *
450 * <h3>Connect To Server</h3>
451 *
452 * <p>
453 * By calling {@link #connect()} method, connection to the server is
454 * established and a WebSocket opening handshake is performed
455 * synchronously. If an error occurred during the handshake,
456 * a {@link WebSocketException} would be thrown. Instead, when the
457 * handshake succeeds, the {@code connect()} implementation creates
458 * threads and starts them to read and write WebSocket frames
459 * asynchronously.
460 * </p>
461 *
462 * <blockquote>
463 * <pre style="border-left: solid 5px lightgray;"> try
464 * {
465 *     <span style="color: green;">// Connect to the server and perform an opening handshake.</span>
466 *     <span style="color: green;">// This method blocks until the opening handshake is finished.</span>
467 *     ws.{@link #connect()};
468 * }
469 * catch ({@link OpeningHandshakeException} e)
470 * {
471 *     <span style="color: green;">// A violation against the WebSocket protocol was detected</span>
472 *     <span style="color: green;">// during the opening handshake.</span>
473 * }
474 * catch ({@link HostnameUnverifiedException} e)
475 * {
476 *     <span style="color: green;">// The certificate of the peer does not match the expected hostname.</span>
477 * }
478 * catch ({@link WebSocketException} e)
479 * {
480 *     <span style="color: green;">// Failed to establish a WebSocket connection.</span>
481 * }</pre>
482 * </blockquote>
483 *
484 * <p>
485 * In some cases, {@code connect()} method throws {@link OpeningHandshakeException}
486 * which is a subclass of {@code WebSocketException} (since version 1.19).
487 * {@code OpeningHandshakeException} provides additional methods such as
488 * {@link OpeningHandshakeException#getStatusLine() getStatusLine()},
489 * {@link OpeningHandshakeException#getHeaders() getHeaders()} and
490 * {@link OpeningHandshakeException#getBody() getBody()} to access the
491 * response from a server. The following snippet is an example to print
492 * information that the exception holds.
493 * </p>
494 *
495 * <blockquote>
496 * <pre style="border-left: solid 5px lightgray;"> catch ({@link OpeningHandshakeException} e)
497 * {
498 *     <span style="color: green;">// Status line.</span>
499 *     {@link StatusLine} sl = e.{@link OpeningHandshakeException#getStatusLine() getStatusLine()};
500 *     System.out.println(<span style="color:darkred;">"=== Status Line ==="</span>);
501 *     System.out.format(<span style="color:darkred;">"HTTP Version  = %s\n"</span>, sl.{@link StatusLine#getHttpVersion() getHttpVersion()});
502 *     System.out.format(<span style="color:darkred;">"Status Code   = %d\n"</span>, sl.{@link StatusLine#getStatusCode() getStatusCode()});
503 *     System.out.format(<span style="color:darkred;">"Reason Phrase = %s\n"</span>, sl.{@link StatusLine#getReasonPhrase() getReasonPhrase()});
504 *
505 *     <span style="color: green;">// HTTP headers.</span>
506 *     Map&lt;String, List&lt;String&gt;&gt; headers = e.{@link OpeningHandshakeException#getHeaders() getHeaders()};
507 *     System.out.println(<span style="color:darkred;">"=== HTTP Headers ==="</span>);
508 *     for (Map.Entry&lt;String, List&lt;String&gt;&gt; entry : headers.entrySet())
509 *     {
510 *         <span style="color: green;">// Header name.</span>
511 *         String name = entry.getKey();
512 *
513 *         <span style="color: green;">// Values of the header.</span>
514 *         List&lt;String&gt; values = entry.getValue();
515 *
516 *         if (values == null || values.size() == 0)
517 *         {
518 *             <span style="color: green;">// Print the name only.</span>
519 *             System.out.println(name);
520 *             continue;
521 *         }
522 *
523 *         for (String value : values)
524 *         {
525 *             <span style="color: green;">// Print the name and the value.</span>
526 *             System.out.format(<span style="color:darkred;">"%s: %s\n"</span>, name, value);
527 *         }
528 *     }
529 * }</pre>
530 * </blockquote>
531 *
532 * <p>
533 * Also, {@code connect()} method throws {@link HostnameUnverifiedException}
534 * which is a subclass of {@code WebSocketException} (since version 2.1) when
535 * the certificate of the peer does not match the expected hostname.
536 * </p>
537 *
538 * <h3>Connect To Server Asynchronously</h3>
539 *
540 * <p>
541 * The simplest way to call {@code connect()} method asynchronously is to
542 * use {@link #connectAsynchronously()} method. The implementation of the
543 * method creates a thread and calls {@code connect()} method in the thread.
544 * When the {@code connect()} call failed, {@link
545 * WebSocketListener#onConnectError(WebSocket, WebSocketException)
546 * onConnectError()} of {@code WebSocketListener} would be called. Note that
547 * {@code onConnectError()} is called only when {@code connectAsynchronously()}
548 * was used and the {@code connect()} call executed in the background thread
549 * failed. Neither direct synchronous {@code connect()} nor
550 * {@link WebSocket#connect(java.util.concurrent.ExecutorService)
551 * connect(ExecutorService)} (described below) will trigger the callback method.
552 * </p>
553 *
554 * <blockquote>
555 * <pre style="border-left: solid 5px lightgray;"> <span style="color: green;">// Connect to the server asynchronously.</span>
556 * ws.{@link #connectAsynchronously()};
557 * </pre>
558 * </blockquote>
559 *
560 * <p>
561 * Another way to call {@code connect()} method asynchronously is to use
562 * {@link #connect(ExecutorService)} method. The method performs a WebSocket
563 * opening handshake asynchronously using the given {@link ExecutorService}.
564 * </p>
565 *
566 * <blockquote>
567 * <pre style="border-left: solid 5px lightgray;"> <span style="color: green;">// Prepare an ExecutorService.</span>
568 * {@link ExecutorService} es = {@link java.util.concurrent.Executors Executors}.{@link
569 * java.util.concurrent.Executors#newSingleThreadExecutor() newSingleThreadExecutor()};
570 *
571 * <span style="color: green;">// Connect to the server asynchronously.</span>
572 * {@link Future}{@code <WebSocket>} future = ws.{@link #connect(ExecutorService) connect}(es);
573 *
574 * try
575 * {
576 *     <span style="color: green;">// Wait for the opening handshake to complete.</span>
577 *     future.get();
578 * }
579 * catch ({@link java.util.concurrent.ExecutionException ExecutionException} e)
580 * {
581 *     if (e.getCause() instanceof {@link WebSocketException})
582 *     {
583 *         ......
584 *     }
585 * }</pre>
586 * </blockquote>
587 *
588 * <p>
589 * The implementation of {@code connect(ExecutorService)} method creates
590 * a {@link java.util.concurrent.Callable Callable}{@code <WebSocket>}
591 * instance by calling {@link #connectable()} method and passes the
592 * instance to {@link ExecutorService#submit(Callable) submit(Callable)}
593 * method of the given {@code ExecutorService}. What the implementation
594 * of {@link Callable#call() call()} method of the {@code Callable}
595 * instance does is just to call the synchronous {@code connect()}.
596 * </p>
597 *
598 * <h3>Send Frames</h3>
599 *
600 * <p>
601 * WebSocket frames can be sent by {@link #sendFrame(WebSocketFrame)}
602 * method. Other <code>send<i>Xxx</i></code> methods such as {@link
603 * #sendText(String)} are aliases of {@code sendFrame} method. All of
604 * the <code>send<i>Xxx</i></code> methods work asynchronously.
605 * However, under some conditions, <code>send<i>Xxx</i></code> methods
606 * may block. See <a href="#congestion_control">Congestion Control</a>
607 * for details.
608 * </p>
609 *
610 * <p>
611 * Below
612 * are some examples of <code>send<i>Xxx</i></code> methods. Note that
613 * in normal cases, you don't have to call {@link #sendClose()} method
614 * and {@link #sendPong()} (or their variants) explicitly because they
615 * are called automatically when appropriate.
616 * </p>
617 *
618 * <blockquote>
619 * <pre style="border-left: solid 5px lightgray;"> <span style="color: green;">// Send a text frame.</span>
620 * ws.{@link #sendText(String) sendText}(<span style="color: darkred;">"Hello."</span>);
621 *
622 * <span style="color: green;">// Send a binary frame.</span>
623 * byte[] binary = ......;
624 * ws.{@link #sendBinary(byte[]) sendBinary}(binary);
625 *
626 * <span style="color: green;">// Send a ping frame.</span>
627 * ws.{@link #sendPing(String) sendPing}(<span style="color: darkred;">"Are you there?"</span>);</pre>
628 * </blockquote>
629 *
630 * <p>
631 * If you want to send fragmented frames, you have to know the details
632 * of the specification (<a href="https://tools.ietf.org/html/rfc6455#section-5.4"
633 * >5.4. Fragmentation</a>). Below is an example to send a text message
634 * ({@code "How are you?"}) which consists of 3 fragmented frames.
635 * </p>
636 *
637 * <blockquote>
638 * <pre style="border-left: solid 5px lightgray;"> <span style="color: green;">// The first frame must be either a text frame or a binary frame.
639 * // And its FIN bit must be cleared.</span>
640 * WebSocketFrame firstFrame = WebSocketFrame
641 *     .{@link WebSocketFrame#createTextFrame(String)
642 *     createTextFrame}(<span style="color: darkred;">"How "</span>)
643 *     .{@link WebSocketFrame#setFin(boolean) setFin}(false);
644 *
645 * <span style="color: green;">// Subsequent frames must be continuation frames. The FIN bit of
646 * // all continuation frames except the last one must be cleared.
647 * // Note that the FIN bit of frames returned from
648 * // WebSocketFrame.createContinuationFrame methods is cleared, so
649 * // the example below does not clear the FIN bit explicitly.</span>
650 * WebSocketFrame secondFrame = WebSocketFrame
651 *     .{@link WebSocketFrame#createContinuationFrame(String)
652 *     createContinuationFrame}(<span style="color: darkred;">"are "</span>);
653 *
654 * <span style="color: green;">// The last frame must be a continuation frame with the FIN bit set.
655 * // Note that the FIN bit of frames returned from
656 * // WebSocketFrame.createContinuationFrame methods is cleared, so
657 * // the FIN bit of the last frame must be set explicitly.</span>
658 * WebSocketFrame lastFrame = WebSocketFrame
659 *     .{@link WebSocketFrame#createContinuationFrame(String)
660 *     createContinuationFrame}(<span style="color: darkred;">"you?"</span>)
661 *     .{@link WebSocketFrame#setFin(boolean) setFin}(true);
662 *
663 * <span style="color: green;">// Send a text message which consists of 3 frames.</span>
664 * ws.{@link #sendFrame(WebSocketFrame) sendFrame}(firstFrame)
665 *   .{@link #sendFrame(WebSocketFrame) sendFrame}(secondFrame)
666 *   .{@link #sendFrame(WebSocketFrame) sendFrame}(lastFrame);</pre>
667 * </blockquote>
668 *
669 * <p>
670 * Alternatively, the same as above can be done like this.
671 * </p>
672 *
673 * <blockquote>
674 * <pre style="border-left: solid 5px lightgray;"> <span style="color: green;">// Send a text message which consists of 3 frames.</span>
675 * ws.{@link #sendText(String, boolean) sendText}(<span style="color: darkred;">"How "</span>, false)
676 *   .{@link #sendContinuation(String) sendContinuation}(<span style="color: darkred;">"are "</span>)
677 *   .{@link #sendContinuation(String, boolean) sendContinuation}(<span style="color: darkred;">"you?"</span>, true);</pre>
678 * </blockquote>
679 *
680 * <h3>Send Ping/Pong Frames Periodically</h3>
681 *
682 * <p>
683 * You can send ping frames periodically by calling {@link #setPingInterval(long)
684 * setPingInterval} method with an interval in milliseconds between ping frames.
685 * This method can be called both before and after {@link #connect()} method.
686 * Passing zero stops the periodical sending.
687 * </p>
688 *
689 * <blockquote>
690 * <pre style="border-left: solid 5px lightgray;"> <span style="color: green;">// Send a ping per 60 seconds.</span>
691 * ws.{@link #setPingInterval(long) setPingInterval}(60 * 1000);
692 *
693 * <span style="color: green;">// Stop the periodical sending.</span>
694 * ws.{@link #setPingInterval(long) setPingInterval}(0);</pre>
695 * </blockquote>
696 *
697 * <p>
698 * Likewise, you can send pong frames periodically by calling {@link
699 * #setPongInterval(long) setPongInterval} method. "<i>A Pong frame MAY be sent
700 * <b>unsolicited</b>."</i> (<a href="https://tools.ietf.org/html/rfc6455#section-5.5.3"
701 * >RFC 6455, 5.5.3. Pong</a>)
702 * </p>
703 *
704 * <p>
705 * You can customize payload of ping/pong frames that are sent automatically by using
706 * {@link #setPingPayloadGenerator(PayloadGenerator)} and
707 * {@link #setPongPayloadGenerator(PayloadGenerator)} methods. Both methods take an
708 * instance of {@link PayloadGenerator} interface. The following is an example to
709 * use the string representation of the current date as payload of ping frames.
710 * </p>
711 *
712 * <blockquote>
713 * <pre style="border-left: solid 5px lightgray;"> ws.{@link #setPingPayloadGenerator(PayloadGenerator)
714 * setPingPayloadGenerator}(new {@link PayloadGenerator} () {
715 *     <span style="color: gray;">{@code @}Override</span>
716 *     public byte[] generate() {
717 *         <span style="color: green;">// The string representation of the current date.</span>
718 *         return new Date().toString().getBytes();
719 *     }
720 * });</pre>
721 * </blockquote>
722 *
723 * <p>
724 * Note that the maximum payload length of control frames (e.g. ping frames) is 125.
725 * Therefore, the length of a byte array returned from {@link PayloadGenerator#generate()
726 * generate()} method must not exceed 125.
727 * </p>
728 *
729 * <p>
730 * You can change the names of the {@link java.util.Timer Timer}s that send ping/pong
731 * frames periodically by using {@link #setPingSenderName(String)} and
732 * {@link #setPongSenderName(String)} methods.
733 * </p>
734 *
735 * <blockquote>
736 * <pre style="border-left: solid 5px lightgray;"> <span style="color: green;">// Change the Timers' names.</span>
737 * ws.{@link #setPingSenderName(String)
738 * setPingSenderName}(<span style="color: darkred;">"PING_SENDER"</span>);
739 * ws.{@link #setPongSenderName(String)
740 * setPongSenderName}(<span style="color: darkred;">"PONG_SENDER"</span>);
741 * </pre>
742 * </blockquote>
743 *
744 * <h3>Auto Flush</h3>
745 *
746 * <p>
747 * By default, a frame is automatically flushed to the server immediately after
748 * {@link #sendFrame(WebSocketFrame) sendFrame} method is executed. This automatic
749 * flush can be disabled by calling {@link #setAutoFlush(boolean) setAutoFlush}{@code
750 * (false)}.
751 * </p>
752 *
753 * <blockquote>
754 * <pre style="border-left: solid 5px lightgray;"> <span style="color: green;">// Disable auto-flush.</span>
755 * ws.{@link #setAutoFlush(boolean) setAutoFlush}(false);</pre>
756 * </blockquote>
757 *
758 * <p>
759 * To flush frames manually, call {@link #flush()} method. Note that this method
760 * works asynchronously.
761 * </p>
762 *
763 * <blockquote>
764 * <pre style="border-left: solid 5px lightgray;"> <span style="color: green;">// Flush frames to the server manually.</span>
765 * ws.{@link #flush()};</pre>
766 * </blockquote>
767 *
768 * <h3 id="congestion_control">Congestion Control</h3>
769 *
770 * <p>
771 * <code>send<i>Xxx</i></code> methods queue a {@link WebSocketFrame} instance to the
772 * internal queue. By default, no upper limit is imposed on the queue size, so
773 * <code>send<i>Xxx</i></code> methods do not block. However, this behavior may cause
774 * a problem if your WebSocket client application sends too many WebSocket frames in
775 * a short time for the WebSocket server to process. In such a case, you may want
776 * <code>send<i>Xxx</i></code> methods to block when many frames are queued.
777 * </p>
778 *
779 * <p>
780 * You can set an upper limit on the internal queue by calling {@link #setFrameQueueSize(int)}
781 * method. As a result, if the number of frames in the queue has reached the upper limit
782 * when a <code>send<i>Xxx</i></code> method is called, the method blocks until the
783 * queue gets spaces. The code snippet below is an example to set 5 as the upper limit
784 * of the internal frame queue.
785 * </p>
786 *
787 * <blockquote>
788 * <pre style="border-left: solid 5px lightgray;"> <span style="color: green;">// Set 5 as the frame queue size.</span>
789 * ws.{@link #setFrameQueueSize(int) setFrameQueueSize}(5);</pre>
790 * </blockquote>
791 *
792 * <p>
793 * Note that under some conditions, even if the queue is full, <code>send<i>Xxx</i></code>
794 * methods do not block. For example, in the case where the thread to send frames
795 * ({@code WritingThread}) is going to stop or has already stopped. In addition,
796 * method calls to send a <a href="https://tools.ietf.org/html/rfc6455#section-5.5"
797 * >control frame</a> (e.g. {@link #sendClose()} and {@link #sendPing()}) do not block.
798 * </p>
799 *
800 * <h3 id="maximum_payload_size">Maximum Payload Size</h3>
801 *
802 * <p>
803 * You can set an upper limit on the payload size of WebSocket frames by calling
804 * {@link #setMaxPayloadSize(int)} method with a positive value. Text, binary and
805 * continuation frames whose payload size is bigger than the maximum payload size
806 * you have set will be split into multiple frames.
807 * </p>
808 *
809 * <blockquote>
810 * <pre style="border-left: solid 5px lightgray;"> <span style="color: green;">// Set 1024 as the maximum payload size.</span>
811 * ws.{@link #setMaxPayloadSize(int) setMaxPayloadSize}(1024);</pre>
812 * </blockquote>
813 *
814 * <p>
815 * Control frames (close, ping and pong frames) are never split as per the specification.
816 * </p>
817 *
818 * <p>
819 * If permessage-deflate extension is enabled and if the payload size of a WebSocket
820 * frame after compression does not exceed the maximum payload size, the WebSocket
821 * frame is not split even if the payload size before compression execeeds the
822 * maximum payload size.
823 * </p>
824 *
825 * <h3 id="compression">Compression</h3>
826 *
827 * <p>
828 * The <strong>permessage-deflate</strong> extension (<a href=
829 * "http://tools.ietf.org/html/rfc7692">RFC 7692</a>) has been supported
830 * since the version 1.17. To enable the extension, call {@link #addExtension(String)
831 * addExtension} method with {@code "permessage-deflate"}.
832 * </p>
833 *
834 * <blockquote>
835 * <pre style="border-left: solid 5px lightgray;"><span style="color: green;"> // Enable "permessage-deflate" extension (RFC 7692).</span>
836 * ws.{@link #addExtension(String) addExtension}({@link WebSocketExtension#PERMESSAGE_DEFLATE});</pre>
837 * </blockquote>
838 *
839 * <h3>Missing Close Frame</h3>
840 *
841 * <p>
842 * Some server implementations close a WebSocket connection without sending a
843 * <a href="https://tools.ietf.org/html/rfc6455#section-5.5.1">close frame</a> to
844 * a client in some cases. Strictly speaking, this is a violation against the
845 * specification (<a href=
846 * "https://tools.ietf.org/html/rfc6455#section-5.5.1">RFC 6455</a>). However, this
847 * library has allowed the behavior by default since the version 1.29. Even if the
848 * end of the input stream of a WebSocket connection were reached without a close
849 * frame being received, it would trigger neither {@link
850 * WebSocketListener#onError(WebSocket, WebSocketException) onError()} method nor
851 * {@link WebSocketListener#onFrameError(WebSocket, WebSocketException, WebSocketFrame)
852 * onFrameError()} method of {@link WebSocketListener}. If you want to make a
853 * {@code WebSocket} instance report an error in the case, pass {@code false} to
854 * {@link #setMissingCloseFrameAllowed(boolean)} method.
855 * </p>
856 *
857 * <blockquote>
858 * <pre style="border-left: solid 5px lightgray;"><span style="color: green;"
859 * > // Make this library report an error when the end of the input stream
860 * // of the WebSocket connection is reached before a close frame is read.</span>
861 * ws.{@link #setMissingCloseFrameAllowed(boolean) setMissingCloseFrameAllowed}(false);</pre>
862 * </blockquote>
863 *
864 * <h3>Direct Text Message</h3>
865 *
866 * <p>
867 * When a text message was received, {@link WebSocketListener#onTextMessage(WebSocket, String)
868 * onTextMessage(WebSocket, String)} is called. The implementation internally converts
869 * the byte array of the text message into a {@code String} object before calling the
870 * listener method. If you want to receive the byte array directly without the string
871 * conversion, call {@link #setDirectTextMessage(boolean)} with {@code true}, and
872 * {@link WebSocketListener#onTextMessage(WebSocket, byte[]) onTextMessage(WebSocket, byte[])}
873 * will be called instead.
874 * </p>
875 *
876 * <blockquote>
877 * <pre style="border-left: solid 5px lightgray;"><span style="color: green;"
878 * > // Receive text messages without string conversion.</span>
879 * ws.{@link #setDirectTextMessage(boolean) setDirectTextMessage}(true);</pre>
880 * </blockquote>
881 *
882 * <h3>Disconnect WebSocket</h3>
883 *
884 * <p>
885 * Before a WebSocket is closed, a closing handshake is performed. A closing handshake
886 * is started (1) when the server sends a close frame to the client or (2) when the
887 * client sends a close frame to the server. You can start a closing handshake by calling
888 * {@link #disconnect()} method (or by sending a close frame manually).
889 * </p>
890 *
891 * <blockquote>
892 * <pre style="border-left: solid 5px lightgray;"> <span style="color: green;">// Close the WebSocket connection.</span>
893 * ws.{@link #disconnect()};</pre>
894 * </blockquote>
895 *
896 * <p>
897 * {@code disconnect()} method has some variants. If you want to change the close code
898 * and the reason phrase of the close frame that this client will send to the server,
899 * use a variant method such as {@link #disconnect(int, String)}. {@code disconnect()}
900 * method itself is an alias of {@code disconnect(}{@link WebSocketCloseCode}{@code
901 * .NORMAL, null)}.
902 * </p>
903 *
904 * <h3>Reconnection</h3>
905 *
906 * <p>
907 * {@code connect()} method can be called at most only once regardless of whether the
908 * method succeeded or failed. If you want to re-connect to the WebSocket endpoint,
909 * you have to create a new {@code WebSocket} instance again by calling one of {@code
910 * createSocket} methods of a {@code WebSocketFactory}. You may find {@link #recreate()}
911 * method useful if you want to create a new {@code WebSocket} instance that has the
912 * same settings as the original instance. Note that, however, settings you made on
913 * the raw socket of the original {@code WebSocket} instance are not copied.
914 * </p>
915 *
916 * <blockquote>
917 * <pre style="border-left: solid 5px lightgray;"> <span style="color: green;">// Create a new WebSocket instance and connect to the same endpoint.</span>
918 * ws = ws.{@link #recreate()}.{@link #connect()};</pre>
919 * </blockquote>
920 *
921 * <p>
922 * There is a variant of {@code recreate()} method that takes a timeout value for
923 * socket connection. If you want to use a timeout value that is different from the
924 * one used when the existing {@code WebSocket} instance was created, use {@link
925 * #recreate(int) recreate(int timeout)} method.
926 * </p>
927 *
928 * <p>
929 * Note that you should not trigger reconnection in {@link
930 * WebSocketListener#onError(WebSocket, WebSocketException) onError()} method
931 * because {@code onError()} may be called multiple times due to one error. Instead,
932 * {@link WebSocketListener#onDisconnected(WebSocket, WebSocketFrame, WebSocketFrame,
933 * boolean) onDisconnected()} is the right place to trigger reconnection.
934 * </p>
935 *
936 * <p>
937 * Also note that the reason I use an expression of <i>"to trigger reconnection"</i>
938 * instead of <i>"to call <code>recreate().connect()</code>"</i> is that I myself
939 * won't do it <i>synchronously</i> in <code>WebSocketListener</code> callback
940 * methods but will just schedule reconnection or will just go to the top of a kind
941 * of <i>application loop</i> that repeats to establish a WebSocket connection until
942 * it succeeds.
943 * </p>
944 *
945 * <h3>Error Handling</h3>
946 *
947 * <p>
948 * {@code WebSocketListener} has some {@code onXxxError()} methods such as {@link
949 * WebSocketListener#onFrameError(WebSocket, WebSocketException, WebSocketFrame)
950 * onFrameError()} and {@link
951 * WebSocketListener#onSendError(WebSocket, WebSocketException, WebSocketFrame)
952 * onSendError()}. Among such methods, {@link
953 * WebSocketListener#onError(WebSocket, WebSocketException) onError()} is a special
954 * one. It is always called before any other {@code onXxxError()} is called. For
955 * example, in the implementation of {@code run()} method of {@code ReadingThread},
956 * {@code Throwable} is caught and {@code onError()} and {@link
957 * WebSocketListener#onUnexpectedError(WebSocket, WebSocketException)
958 * onUnexpectedError()} are called in this order. The following is the implementation.
959 * </p>
960 *
961 * <blockquote>
962 * <pre style="border-left: solid 5px lightgray;"> <span style="color: gray;">{@code @}Override</span>
963 * public void run()
964 * {
965 *     try
966 *     {
967 *         main();
968 *     }
969 *     catch (Throwable t)
970 *     {
971 *         <span style="color: green;">// An uncaught throwable was detected in the reading thread.</span>
972 *         {@link WebSocketException} cause = new WebSocketException(
973 *             {@link WebSocketError}.{@link WebSocketError#UNEXPECTED_ERROR_IN_READING_THREAD UNEXPECTED_ERROR_IN_READING_THREAD},
974 *             <span style="color: darkred;">"An uncaught throwable was detected in the reading thread"</span>, t);
975 *
976 *         <span style="color: green;">// Notify the listeners.</span>
977 *         ListenerManager manager = mWebSocket.getListenerManager();
978 *         manager.callOnError(cause);
979 *         manager.callOnUnexpectedError(cause);
980 *     }
981 * }</pre>
982 * </blockquote>
983 *
984 * <p>
985 * So, you can handle all error cases in {@code onError()} method. However, note
986 * that {@code onError()} may be called multiple times for one error cause, so don't
987 * try to trigger reconnection in {@code onError()}. Instead, {@link
988 * WebSocketListener#onDisconnected(WebSocket, WebSocketFrame, WebSocketFrame, boolean)
989 * onDiconnected()} is the right place to trigger reconnection.
990 * </p>
991 *
992 * <p>
993 * All {@code onXxxError()} methods receive a {@link WebSocketException} instance
994 * as the second argument (the first argument is a {@code WebSocket} instance). The
995 * exception class provides {@link WebSocketException#getError() getError()} method
996 * which returns a {@link WebSocketError} enum entry. Entries in {@code WebSocketError}
997 * enum are possible causes of errors that may occur in the implementation of this
998 * library. The error causes are so granular that they can make it easy for you to
999 * find the root cause when an error occurs.
1000 * </p>
1001 *
1002 * <p>
1003 * {@code Throwable}s thrown by implementations of {@code onXXX()} callback methods
1004 * are passed to {@link WebSocketListener#handleCallbackError(WebSocket, Throwable)
1005 * handleCallbackError()} of {@code WebSocketListener}.
1006 * </p>
1007 *
1008 * <blockquote>
1009 * <pre style="border-left: solid 5px lightgray;"> <span style="color: gray;">{@code @}Override</span>
1010 * public void {@link WebSocketListener#handleCallbackError(WebSocket, Throwable)
1011 * handleCallbackError}(WebSocket websocket, Throwable cause) throws Exception {
1012 *     <span style="color: green;">// Throwables thrown by onXxx() callback methods come here.</span>
1013 * }</pre>
1014 * </blockquote>
1015 *
1016 * <h3>Thread Callbacks</h3>
1017 *
1018 * <p>
1019 * Some threads are created internally in the implementation of {@code WebSocket}.
1020 * Known threads are as follows.
1021 * </p>
1022 *
1023 * <blockquote>
1024 * <table border="1" cellpadding="5" style="border-collapse: collapse;">
1025 *   <caption>Internal Threads</caption>
1026 *   <thead>
1027 *     <tr>
1028 *       <th>THREAD TYPE</th>
1029 *       <th>DESCRIPTION</th>
1030 *     </tr>
1031 *   </thead>
1032 *   <tbody>
1033 *     <tr>
1034 *       <td>{@link ThreadType#READING_THREAD READING_THREAD}</td>
1035 *       <td>A thread which reads WebSocket frames from the server.</td>
1036 *     </tr>
1037 *     <tr>
1038 *       <td>{@link ThreadType#WRITING_THREAD WRITING_THREAD}</td>
1039 *       <td>A thread which sends WebSocket frames to the server.</td>
1040 *     </tr>
1041 *     <tr>
1042 *       <td>{@link ThreadType#CONNECT_THREAD CONNECT_THREAD}</td>
1043 *       <td>A thread which calls {@link WebSocket#connect()} asynchronously.</td>
1044 *     </tr>
1045 *     <tr>
1046 *       <td>{@link ThreadType#FINISH_THREAD FINISH_THREAD}</td>
1047 *       <td>A thread which does finalization of a {@code WebSocket} instance.</td>
1048 *     </tr>
1049 *   </tbody>
1050 * </table>
1051 * </blockquote>
1052 *
1053 * <p>
1054 * The following callback methods of {@link WebSocketListener} are called according
1055 * to the life cycle of the threads.
1056 * </p>
1057 *
1058 * <blockquote>
1059 * <table border="1" cellpadding="5" style="border-collapse: collapse;">
1060 *   <caption>Thread Callbacks</caption>
1061 *   <thead>
1062 *     <tr>
1063 *       <th>METHOD</th>
1064 *       <th>DESCRIPTION</th>
1065 *     </tr>
1066 *   </thead>
1067 *   <tbody>
1068 *     <tr>
1069 *       <td>{@link WebSocketListener#onThreadCreated(WebSocket, ThreadType, Thread) onThreadCreated()}</td>
1070 *       <td>Called after a thread was created.</td>
1071 *     </tr>
1072 *     <tr>
1073 *       <td>{@link WebSocketListener#onThreadStarted(WebSocket, ThreadType, Thread) onThreadStarted()}</td>
1074 *       <td>Called at the beginning of the thread's {@code run()} method.</td>
1075 *     </tr>
1076 *     <tr>
1077 *       <td>{@link WebSocketListener#onThreadStopping(WebSocket, ThreadType, Thread) onThreadStopping()}</td>
1078 *       <td>Called at the end of the thread's {@code run()} method.</td>
1079 *     </tr>
1080 *   </tbody>
1081 * </table>
1082 * </blockquote>
1083 *
1084 * <p>
1085 * For example, if you want to change the name of the reading thread,
1086 * implement {@link WebSocketListener#onThreadCreated(WebSocket, ThreadType, Thread)
1087 * onThreadCreated()} method like below.
1088 * </p>
1089 *
1090 * <blockquote>
1091 * <pre style="border-left: solid 5px lightgray;"> <span style="color: gray;">{@code @}Override</span>
1092 * public void {@link WebSocketListener#onThreadCreated(WebSocket, ThreadType, Thread)
1093 * onThreadCreated}(WebSocket websocket, {@link ThreadType} type, Thread thread)
1094 * {
1095 *     if (type == ThreadType.READING_THREAD)
1096 *     {
1097 *         thread.setName(<span style="color: darkred;">"READING_THREAD"</span>);
1098 *     }
1099 * }</pre>
1100 * </blockquote>
1101 *
1102 * @see <a href="https://tools.ietf.org/html/rfc6455">RFC 6455 (The WebSocket Protocol)</a>
1103 * @see <a href="https://tools.ietf.org/html/rfc7692">RFC 7692 (Compression Extensions for WebSocket)</a>
1104 * @see <a href="https://github.com/TakahikoKawasaki/nv-websocket-client">[GitHub] nv-websocket-client</a>
1105 *
1106 * @author Takahiko Kawasaki
1107 */
1108public class WebSocket
1109{
1110    private static final long DEFAULT_CLOSE_DELAY = 10 * 1000L;
1111    private final WebSocketFactory mWebSocketFactory;
1112    private final SocketConnector mSocketConnector;
1113    private final StateManager mStateManager;
1114    private HandshakeBuilder mHandshakeBuilder;
1115    private final ListenerManager mListenerManager;
1116    private final PingSender mPingSender;
1117    private final PongSender mPongSender;
1118    private final Object mThreadsLock = new Object();
1119    private WebSocketInputStream mInput;
1120    private WebSocketOutputStream mOutput;
1121    private ReadingThread mReadingThread;
1122    private WritingThread mWritingThread;
1123    private Map<String, List<String>> mServerHeaders;
1124    private List<WebSocketExtension> mAgreedExtensions;
1125    private String mAgreedProtocol;
1126    private boolean mExtended;
1127    private boolean mAutoFlush = true;
1128    private boolean mMissingCloseFrameAllowed = true;
1129    private boolean mDirectTextMessage;
1130    private int mFrameQueueSize;
1131    private int mMaxPayloadSize;
1132    private boolean mOnConnectedCalled;
1133    private Object mOnConnectedCalledLock = new Object();
1134    private boolean mReadingThreadStarted;
1135    private boolean mWritingThreadStarted;
1136    private boolean mReadingThreadFinished;
1137    private boolean mWritingThreadFinished;
1138    private WebSocketFrame mServerCloseFrame;
1139    private WebSocketFrame mClientCloseFrame;
1140    private PerMessageCompressionExtension mPerMessageCompressionExtension;
1141
1142
1143    WebSocket(WebSocketFactory factory, boolean secure, String userInfo,
1144            String host, String path, SocketConnector connector)
1145    {
1146        mWebSocketFactory  = factory;
1147        mSocketConnector   = connector;
1148        mStateManager      = new StateManager();
1149        mHandshakeBuilder  = new HandshakeBuilder(secure, userInfo, host, path);
1150        mListenerManager   = new ListenerManager(this);
1151        mPingSender        = new PingSender(this, new CounterPayloadGenerator());
1152        mPongSender        = new PongSender(this, new CounterPayloadGenerator());
1153    }
1154
1155
1156    /**
1157     * Create a new {@code WebSocket} instance that has the same settings
1158     * as this instance. Note that, however, settings you made on the raw
1159     * socket are not copied.
1160     *
1161     * <p>
1162     * The {@link WebSocketFactory} instance that you used to create this
1163     * {@code WebSocket} instance is used again.
1164     * </p>
1165     *
1166     * <p>
1167     * This method calls {@link #recreate(int)} with the timeout value that
1168     * was used when this instance was created. If you want to create a
1169     * socket connection with a different timeout value, use {@link
1170     * #recreate(int)} method instead.
1171     * </p>
1172     *
1173     * @return
1174     *         A new {@code WebSocket} instance.
1175     *
1176     * @throws IOException
1177     *         {@link WebSocketFactory#createSocket(URI)} threw an exception.
1178     *
1179     * @since 1.6
1180     */
1181    public WebSocket recreate() throws IOException
1182    {
1183        return recreate(mSocketConnector.getConnectionTimeout());
1184    }
1185
1186
1187    /**
1188     * Create a new {@code WebSocket} instance that has the same settings
1189     * as this instance. Note that, however, settings you made on the raw
1190     * socket are not copied.
1191     *
1192     * <p>
1193     * The {@link WebSocketFactory} instance that you used to create this
1194     * {@code WebSocket} instance is used again.
1195     * </p>
1196     *
1197     * @return
1198     *         A new {@code WebSocket} instance.
1199     *
1200     * @param timeout
1201     *         The timeout value in milliseconds for socket timeout.
1202     *         A timeout of zero is interpreted as an infinite timeout.
1203     *
1204     * @throws IllegalArgumentException
1205     *         The given timeout value is negative.
1206     *
1207     * @throws IOException
1208     *         {@link WebSocketFactory#createSocket(URI)} threw an exception.
1209     *
1210     * @since 1.10
1211     */
1212    public WebSocket recreate(int timeout) throws IOException
1213    {
1214        if (timeout < 0)
1215        {
1216            throw new IllegalArgumentException("The given timeout value is negative.");
1217        }
1218
1219        WebSocket instance = mWebSocketFactory.createSocket(getURI(), timeout);
1220
1221        // Copy the settings.
1222        instance.mHandshakeBuilder = new HandshakeBuilder(mHandshakeBuilder);
1223        instance.setPingInterval(getPingInterval());
1224        instance.setPongInterval(getPongInterval());
1225        instance.setPingPayloadGenerator(getPingPayloadGenerator());
1226        instance.setPongPayloadGenerator(getPongPayloadGenerator());
1227        instance.mExtended = mExtended;
1228        instance.mAutoFlush = mAutoFlush;
1229        instance.mMissingCloseFrameAllowed = mMissingCloseFrameAllowed;
1230        instance.mDirectTextMessage = mDirectTextMessage;
1231        instance.mFrameQueueSize = mFrameQueueSize;
1232
1233        // Copy listeners.
1234        List<WebSocketListener> listeners = mListenerManager.getListeners();
1235        synchronized (listeners)
1236        {
1237            instance.addListeners(listeners);
1238        }
1239
1240        return instance;
1241    }
1242
1243
1244    @Override
1245    protected void finalize() throws Throwable
1246    {
1247        if (isInState(CREATED))
1248        {
1249            // The raw socket needs to be closed.
1250            finish();
1251        }
1252
1253        super.finalize();
1254    }
1255
1256
1257    /**
1258     * Get the current state of this WebSocket.
1259     *
1260     * <p>
1261     * The initial state is {@link WebSocketState#CREATED CREATED}.
1262     * When {@link #connect()} is called, the state is changed to
1263     * {@link WebSocketState#CONNECTING CONNECTING}, and then to
1264     * {@link WebSocketState#OPEN OPEN} after a successful opening
1265     * handshake. The state is changed to {@link
1266     * WebSocketState#CLOSING CLOSING} when a closing handshake
1267     * is started, and then to {@link WebSocketState#CLOSED CLOSED}
1268     * when the closing handshake finished.
1269     * </p>
1270     *
1271     * <p>
1272     * See the description of {@link WebSocketState} for details.
1273     * </p>
1274     *
1275     * @return
1276     *         The current state.
1277     *
1278     * @see WebSocketState
1279     */
1280    public WebSocketState getState()
1281    {
1282        synchronized (mStateManager)
1283        {
1284            return mStateManager.getState();
1285        }
1286    }
1287
1288
1289    /**
1290     * Check if the current state of this WebSocket is {@link
1291     * WebSocketState#OPEN OPEN}.
1292     *
1293     * @return
1294     *         {@code true} if the current state is OPEN.
1295     *
1296     * @since 1.1
1297     */
1298    public boolean isOpen()
1299    {
1300        return isInState(OPEN);
1301    }
1302
1303
1304    /**
1305     * Check if the current state is equal to the specified state.
1306     */
1307    private boolean isInState(WebSocketState state)
1308    {
1309        synchronized (mStateManager)
1310        {
1311            return (mStateManager.getState() == state);
1312        }
1313    }
1314
1315
1316    /**
1317     * Add a value for {@code Sec-WebSocket-Protocol}.
1318     *
1319     * @param protocol
1320     *         A protocol name.
1321     *
1322     * @return
1323     *         {@code this} object.
1324     *
1325     * @throws IllegalArgumentException
1326     *         The protocol name is invalid. A protocol name must be
1327     *         a non-empty string with characters in the range U+0021
1328     *         to U+007E not including separator characters.
1329     */
1330    public WebSocket addProtocol(String protocol)
1331    {
1332        mHandshakeBuilder.addProtocol(protocol);
1333
1334        return this;
1335    }
1336
1337
1338    /**
1339     * Remove a protocol from {@code Sec-WebSocket-Protocol}.
1340     *
1341     * @param protocol
1342     *         A protocol name. {@code null} is silently ignored.
1343     *
1344     * @return
1345     *         {@code this} object.
1346     *
1347     * @since 1.14
1348     */
1349    public WebSocket removeProtocol(String protocol)
1350    {
1351        mHandshakeBuilder.removeProtocol(protocol);
1352
1353        return this;
1354    }
1355
1356
1357    /**
1358     * Remove all protocols from {@code Sec-WebSocket-Protocol}.
1359     *
1360     * @return
1361     *         {@code this} object.
1362     *
1363     * @since 1.14
1364     */
1365    public WebSocket clearProtocols()
1366    {
1367        mHandshakeBuilder.clearProtocols();
1368
1369        return this;
1370    }
1371
1372
1373    /**
1374     * Add a value for {@code Sec-WebSocket-Extension}.
1375     *
1376     * @param extension
1377     *         An extension. {@code null} is silently ignored.
1378     *
1379     * @return
1380     *         {@code this} object.
1381     */
1382    public WebSocket addExtension(WebSocketExtension extension)
1383    {
1384        mHandshakeBuilder.addExtension(extension);
1385
1386        return this;
1387    }
1388
1389
1390    /**
1391     * Add a value for {@code Sec-WebSocket-Extension}. The input string
1392     * should comply with the format described in <a href=
1393     * "https://tools.ietf.org/html/rfc6455#section-9.1">9.1. Negotiating
1394     * Extensions</a> in <a href="https://tools.ietf.org/html/rfc6455"
1395     * >RFC 6455</a>.
1396     *
1397     * @param extension
1398     *         A string that represents a WebSocket extension. If it does
1399     *         not comply with RFC 6455, no value is added to {@code
1400     *         Sec-WebSocket-Extension}.
1401     *
1402     * @return
1403     *         {@code this} object.
1404     *
1405     * @since 1.14
1406     */
1407    public WebSocket addExtension(String extension)
1408    {
1409        mHandshakeBuilder.addExtension(extension);
1410
1411        return this;
1412    }
1413
1414
1415    /**
1416     * Remove an extension from {@code Sec-WebSocket-Extension}.
1417     *
1418     * @param extension
1419     *         An extension to remove. {@code null} is silently ignored.
1420     *
1421     * @return
1422     *         {@code this} object.
1423     *
1424     * @since 1.14
1425     */
1426    public WebSocket removeExtension(WebSocketExtension extension)
1427    {
1428        mHandshakeBuilder.removeExtension(extension);
1429
1430        return this;
1431    }
1432
1433
1434    /**
1435     * Remove extensions from {@code Sec-WebSocket-Extension} by
1436     * an extension name.
1437     *
1438     * @param name
1439     *         An extension name. {@code null} is silently ignored.
1440     *
1441     * @return
1442     *         {@code this} object.
1443     *
1444     * @since 1.14
1445     */
1446    public WebSocket removeExtensions(String name)
1447    {
1448        mHandshakeBuilder.removeExtensions(name);
1449
1450        return this;
1451    }
1452
1453
1454    /**
1455     * Remove all extensions from {@code Sec-WebSocket-Extension}.
1456     *
1457     * @return
1458     *         {@code this} object.
1459     *
1460     * @since 1.14
1461     */
1462    public WebSocket clearExtensions()
1463    {
1464        mHandshakeBuilder.clearExtensions();
1465
1466        return this;
1467    }
1468
1469
1470    /**
1471     * Add a pair of extra HTTP header.
1472     *
1473     * @param name
1474     *         An HTTP header name. When {@code null} or an empty
1475     *         string is given, no header is added.
1476     *
1477     * @param value
1478     *         The value of the HTTP header.
1479     *
1480     * @return
1481     *         {@code this} object.
1482     */
1483    public WebSocket addHeader(String name, String value)
1484    {
1485        mHandshakeBuilder.addHeader(name, value);
1486
1487        return this;
1488    }
1489
1490
1491    /**
1492     * Remove pairs of extra HTTP headers.
1493     *
1494     * @param name
1495     *         An HTTP header name. {@code null} is silently ignored.
1496     *
1497     * @return
1498     *         {@code this} object.
1499     *
1500     * @since 1.14
1501     */
1502    public WebSocket removeHeaders(String name)
1503    {
1504        mHandshakeBuilder.removeHeaders(name);
1505
1506        return this;
1507    }
1508
1509
1510    /**
1511     * Clear all extra HTTP headers.
1512     *
1513     * @return
1514     *         {@code this} object.
1515     *
1516     * @since 1.14
1517     */
1518    public WebSocket clearHeaders()
1519    {
1520        mHandshakeBuilder.clearHeaders();
1521
1522        return this;
1523    }
1524
1525
1526    /**
1527     * Set the credentials to connect to the WebSocket endpoint.
1528     *
1529     * @param userInfo
1530     *         The credentials for Basic Authentication. The format
1531     *         should be <code><i>id</i>:<i>password</i></code>.
1532     *
1533     * @return
1534     *         {@code this} object.
1535     */
1536    public WebSocket setUserInfo(String userInfo)
1537    {
1538        mHandshakeBuilder.setUserInfo(userInfo);
1539
1540        return this;
1541    }
1542
1543
1544    /**
1545     * Set the credentials to connect to the WebSocket endpoint.
1546     *
1547     * @param id
1548     *         The ID.
1549     *
1550     * @param password
1551     *         The password.
1552     *
1553     * @return
1554     *         {@code this} object.
1555     */
1556    public WebSocket setUserInfo(String id, String password)
1557    {
1558        mHandshakeBuilder.setUserInfo(id, password);
1559
1560        return this;
1561    }
1562
1563
1564    /**
1565     * Clear the credentials to connect to the WebSocket endpoint.
1566     *
1567     * @return
1568     *         {@code this} object.
1569     *
1570     * @since 1.14
1571     */
1572    public WebSocket clearUserInfo()
1573    {
1574        mHandshakeBuilder.clearUserInfo();
1575
1576        return this;
1577    }
1578
1579
1580    /**
1581     * Check if extended use of WebSocket frames are allowed.
1582     *
1583     * <p>
1584     * When extended use is allowed, values of RSV1/RSV2/RSV3 bits
1585     * and opcode of frames are not checked. On the other hand,
1586     * if not allowed (default), non-zero values for RSV1/RSV2/RSV3
1587     * bits and unknown opcodes cause an error. In such a case,
1588     * {@link WebSocketListener#onFrameError(WebSocket,
1589     * WebSocketException, WebSocketFrame) onFrameError} method of
1590     * listeners are called and the WebSocket is eventually closed.
1591     * </p>
1592     *
1593     * @return
1594     *         {@code true} if extended use of WebSocket frames
1595     *         are allowed.
1596     */
1597    public boolean isExtended()
1598    {
1599        return mExtended;
1600    }
1601
1602
1603    /**
1604     * Allow or disallow extended use of WebSocket frames.
1605     *
1606     * @param extended
1607     *         {@code true} to allow extended use of WebSocket frames.
1608     *
1609     * @return
1610     *         {@code this} object.
1611     */
1612    public WebSocket setExtended(boolean extended)
1613    {
1614        mExtended = extended;
1615
1616        return this;
1617    }
1618
1619
1620    /**
1621     * Check if flush is performed automatically after {@link
1622     * #sendFrame(WebSocketFrame)} is done. The default value is
1623     * {@code true}.
1624     *
1625     * @return
1626     *         {@code true} if flush is performed automatically.
1627     *
1628     * @since 1.5
1629     */
1630    public boolean isAutoFlush()
1631    {
1632        return mAutoFlush;
1633    }
1634
1635
1636    /**
1637     * Enable or disable auto-flush of sent frames.
1638     *
1639     * @param auto
1640     *         {@code true} to enable auto-flush. {@code false} to
1641     *         disable it.
1642     *
1643     * @return
1644     *         {@code this} object.
1645     *
1646     * @since 1.5
1647     */
1648    public WebSocket setAutoFlush(boolean auto)
1649    {
1650        mAutoFlush = auto;
1651
1652        return this;
1653    }
1654
1655
1656    /**
1657     * Check if this instance allows the server to close the WebSocket
1658     * connection without sending a <a href=
1659     * "https://tools.ietf.org/html/rfc6455#section-5.5.1">close frame</a>
1660     * to this client. The default value is {@code true}.
1661     *
1662     * @return
1663     *         {@code true} if the configuration allows for the server to
1664     *         close the WebSocket connection without sending a close frame
1665     *         to this client. {@code false} if the configuration requires
1666     *         that an error be reported via
1667     *         {@link WebSocketListener#onError(WebSocket, WebSocketException)
1668     *         onError()} method and {@link WebSocketListener#onFrameError(WebSocket,
1669     *         WebSocketException, WebSocketFrame) onFrameError()} method of
1670     *         {@link WebSocketListener}.
1671     *
1672     * @since 1.29
1673     */
1674    public boolean isMissingCloseFrameAllowed()
1675    {
1676        return mMissingCloseFrameAllowed;
1677    }
1678
1679
1680    /**
1681     * Set whether to allow the server to close the WebSocket connection
1682     * without sending a <a href=
1683     * "https://tools.ietf.org/html/rfc6455#section-5.5.1">close frame</a>
1684     * to this client.
1685     *
1686     * @param allowed
1687     *         {@code true} to allow the server to close the WebSocket
1688     *         connection without sending a close frame to this client.
1689     *         {@code false} to make this instance report an error when the
1690     *         end of the input stream of the WebSocket connection is reached
1691     *         before a close frame is read.
1692     *
1693     * @return
1694     *         {@code this} object.
1695     *
1696     * @since 1.29
1697     */
1698    public WebSocket setMissingCloseFrameAllowed(boolean allowed)
1699    {
1700        mMissingCloseFrameAllowed = allowed;
1701
1702        return this;
1703    }
1704
1705
1706    /**
1707     * Check if text messages are passed to listeners without string conversion.
1708     *
1709     * <p>
1710     * If this method returns {@code true}, when a text message is received,
1711     * {@link WebSocketListener#onTextMessage(WebSocket, byte[])
1712     * onTextMessage(WebSocket, byte[])} will be called instead of
1713     * {@link WebSocketListener#onTextMessage(WebSocket, String)
1714     * onTextMessage(WebSocket, String)}. The purpose of this behavior
1715     * is to skip internal string conversion which is performed in the
1716     * implementation of {@code ReadingThread}.
1717     * </p>
1718     *
1719     * @return
1720     *         {@code true} if text messages are passed to listeners without
1721     *         string conversion.
1722     *
1723     * @since 2.6
1724     */
1725    public boolean isDirectTextMessage()
1726    {
1727        return mDirectTextMessage;
1728    }
1729
1730
1731    /**
1732     * Set whether to receive text messages directly as byte arrays without
1733     * string conversion.
1734     *
1735     * <p>
1736     * If {@code true} is set to this property, when a text message is received,
1737     * {@link WebSocketListener#onTextMessage(WebSocket, byte[])
1738     * onTextMessage(WebSocket, byte[])} will be called instead of
1739     * {@link WebSocketListener#onTextMessage(WebSocket, String)
1740     * onTextMessage(WebSocket, String)}. The purpose of this behavior
1741     * is to skip internal string conversion which is performed in the
1742     * implementation of {@code ReadingThread}.
1743     * </p>
1744     *
1745     * @param direct
1746     *         {@code true} to receive text messages as byte arrays.
1747     *
1748     * @return
1749     *         {@code this} object.
1750     *
1751     * @since 2.6
1752     */
1753    public WebSocket setDirectTextMessage(boolean direct)
1754    {
1755        mDirectTextMessage = direct;
1756
1757        return this;
1758    }
1759
1760
1761    /**
1762     * Flush frames to the server. Flush is performed asynchronously.
1763     *
1764     * @return
1765     *         {@code this} object.
1766     *
1767     * @since 1.5
1768     */
1769    public WebSocket flush()
1770    {
1771        synchronized (mStateManager)
1772        {
1773            WebSocketState state = mStateManager.getState();
1774
1775            if (state != OPEN && state != CLOSING)
1776            {
1777                return this;
1778            }
1779        }
1780
1781        // Get the reference to the instance of WritingThread.
1782        WritingThread wt = mWritingThread;
1783
1784        // If and only if an instance of WritingThread is available.
1785        if (wt != null)
1786        {
1787            // Request flush.
1788            wt.queueFlush();
1789        }
1790
1791        return this;
1792    }
1793
1794
1795    /**
1796     * Get the size of the frame queue. The default value is 0 and it means
1797     * there is no limit on the queue size.
1798     *
1799     * @return
1800     *         The size of the frame queue.
1801     *
1802     * @since 1.15
1803     */
1804    public int getFrameQueueSize()
1805    {
1806        return mFrameQueueSize;
1807    }
1808
1809
1810    /**
1811     * Set the size of the frame queue. The default value is 0 and it means
1812     * there is no limit on the queue size.
1813     *
1814     * <p>
1815     * <code>send<i>Xxx</i></code> methods queue a {@link WebSocketFrame}
1816     * instance to the internal queue. If the number of frames in the queue
1817     * has reached the upper limit (which has been set by this method) when
1818     * a <code>send<i>Xxx</i></code> method is called, the method blocks
1819     * until the queue gets spaces.
1820     * </p>
1821     *
1822     * <p>
1823     * Under some conditions, even if the queue is full, <code>send<i>Xxx</i></code>
1824     * methods do not block. For example, in the case where the thread to send
1825     * frames ({@code WritingThread}) is going to stop or has already stopped.
1826     * In addition, method calls to send a <a href=
1827     * "https://tools.ietf.org/html/rfc6455#section-5.5">control frame</a> (e.g.
1828     * {@link #sendClose()} and {@link #sendPing()}) do not block.
1829     * </p>
1830     *
1831     * @param size
1832     *         The queue size. 0 means no limit. Negative numbers are not allowed.
1833     *
1834     * @return
1835     *         {@code this} object.
1836     *
1837     * @throws IllegalArgumentException
1838     *         {@code size} is negative.
1839     *
1840     * @since 1.15
1841     */
1842    public WebSocket setFrameQueueSize(int size) throws IllegalArgumentException
1843    {
1844        if (size < 0)
1845        {
1846            throw new IllegalArgumentException("size must not be negative.");
1847        }
1848
1849        mFrameQueueSize = size;
1850
1851        return this;
1852    }
1853
1854
1855    /**
1856     * Get the maximum payload size. The default value is 0 which means that
1857     * the maximum payload size is not set and as a result frames are not split.
1858     *
1859     * @return
1860     *         The maximum payload size. 0 means that the maximum payload size
1861     *         is not set.
1862     *
1863     * @since 1.27
1864     */
1865    public int getMaxPayloadSize()
1866    {
1867        return mMaxPayloadSize;
1868    }
1869
1870
1871    /**
1872     * Set the maximum payload size.
1873     *
1874     * <p>
1875     * Text, binary and continuation frames whose payload size is bigger than
1876     * the maximum payload size will be split into multiple frames. Note that
1877     * control frames (close, ping and pong frames) are not split as per the
1878     * specification even if their payload size exceeds the maximum payload size.
1879     * </p>
1880     *
1881     * @param size
1882     *         The maximum payload size. 0 to unset the maximum payload size.
1883     *
1884     * @return
1885     *         {@code this} object.
1886     *
1887     * @throws IllegalArgumentException
1888     *         {@code size} is negative.
1889     *
1890     * @since 1.27
1891     */
1892    public WebSocket setMaxPayloadSize(int size) throws IllegalArgumentException
1893    {
1894        if (size < 0)
1895        {
1896            throw new IllegalArgumentException("size must not be negative.");
1897        }
1898
1899        mMaxPayloadSize = size;
1900
1901        return this;
1902    }
1903
1904
1905    /**
1906     * Get the interval of periodical
1907     * <a href="https://tools.ietf.org/html/rfc6455#section-5.5.2">ping</a>
1908     * frames.
1909     *
1910     * @return
1911     *         The interval in milliseconds.
1912     *
1913     * @since 1.2
1914     */
1915    public long getPingInterval()
1916    {
1917        return mPingSender.getInterval();
1918    }
1919
1920
1921    /**
1922     * Set the interval of periodical
1923     * <a href="https://tools.ietf.org/html/rfc6455#section-5.5.2">ping</a>
1924     * frames.
1925     *
1926     * <p>
1927     * Setting a positive number starts sending ping frames periodically.
1928     * Setting zero stops the periodical sending. This method can be called
1929     * both before and after {@link #connect()} method.
1930     * </p>
1931     *
1932     * @param interval
1933     *         The interval in milliseconds. A negative value is
1934     *         regarded as zero.
1935     *
1936     * @return
1937     *         {@code this} object.
1938     *
1939     * @since 1.2
1940     */
1941    public WebSocket setPingInterval(long interval)
1942    {
1943        mPingSender.setInterval(interval);
1944
1945        return this;
1946    }
1947
1948
1949    /**
1950     * Get the interval of periodical
1951     * <a href="https://tools.ietf.org/html/rfc6455#section-5.5.3">pong</a>
1952     * frames.
1953     *
1954     * @return
1955     *         The interval in milliseconds.
1956     *
1957     * @since 1.2
1958     */
1959    public long getPongInterval()
1960    {
1961        return mPongSender.getInterval();
1962    }
1963
1964
1965    /**
1966     * Set the interval of periodical
1967     * <a href="https://tools.ietf.org/html/rfc6455#section-5.5.3">pong</a>
1968     * frames.
1969     *
1970     * <p>
1971     * Setting a positive number starts sending pong frames periodically.
1972     * Setting zero stops the periodical sending. This method can be called
1973     * both before and after {@link #connect()} method.
1974     * </p>
1975     *
1976     * <blockquote>
1977     * <dl>
1978     * <dt>
1979     * <span style="font-weight: normal;">An excerpt from <a href=
1980     * "https://tools.ietf.org/html/rfc6455#section-5.5.3"
1981     * >RFC 6455, 5.5.3. Pong</a></span>
1982     * </dt>
1983     * <dd>
1984     * <p><i>
1985     * A Pong frame MAY be sent <b>unsolicited</b>. This serves as a
1986     * unidirectional heartbeat.  A response to an unsolicited Pong
1987     * frame is not expected.
1988     * </i></p>
1989     * </dd>
1990     * </dl>
1991     * </blockquote>
1992     *
1993     * @param interval
1994     *         The interval in milliseconds. A negative value is
1995     *         regarded as zero.
1996     *
1997     * @return
1998     *         {@code this} object.
1999     *
2000     * @since 1.2
2001     */
2002    public WebSocket setPongInterval(long interval)
2003    {
2004        mPongSender.setInterval(interval);
2005
2006        return this;
2007    }
2008
2009
2010    /**
2011     * Get the generator of payload of ping frames that are sent automatically.
2012     *
2013     * @return
2014     *         The generator of payload ping frames that are sent automatically.
2015     *
2016     * @since 1.20
2017     */
2018    public PayloadGenerator getPingPayloadGenerator()
2019    {
2020        return mPingSender.getPayloadGenerator();
2021    }
2022
2023
2024    /**
2025     * Set the generator of payload of ping frames that are sent automatically.
2026     *
2027     * @param generator
2028     *         The generator of payload ping frames that are sent automatically.
2029     *
2030     * @since 1.20
2031     */
2032    public WebSocket setPingPayloadGenerator(PayloadGenerator generator)
2033    {
2034        mPingSender.setPayloadGenerator(generator);
2035
2036        return this;
2037    }
2038
2039
2040    /**
2041     * Get the generator of payload of pong frames that are sent automatically.
2042     *
2043     * @return
2044     *         The generator of payload pong frames that are sent automatically.
2045     *
2046     * @since 1.20
2047     */
2048    public PayloadGenerator getPongPayloadGenerator()
2049    {
2050        return mPongSender.getPayloadGenerator();
2051    }
2052
2053
2054    /**
2055     * Set the generator of payload of pong frames that are sent automatically.
2056     *
2057     * @param generator
2058     *         The generator of payload ppng frames that are sent automatically.
2059     *
2060     * @since 1.20
2061     */
2062    public WebSocket setPongPayloadGenerator(PayloadGenerator generator)
2063    {
2064        mPongSender.setPayloadGenerator(generator);
2065
2066        return this;
2067    }
2068
2069
2070    /**
2071     * Get the name of the {@code Timer} that sends ping frames periodically.
2072     *
2073     * @return
2074     *         The {@code Timer}'s name.
2075     *
2076     * @since 2.5
2077     */
2078    public String getPingSenderName()
2079    {
2080        return mPingSender.getTimerName();
2081    }
2082
2083
2084    /**
2085     * Set the name of the {@code Timer} that sends ping frames periodically.
2086     *
2087     * @param name
2088     *         A name for the {@code Timer}.
2089     *
2090     * @return
2091     *         {@code this} object.
2092     *
2093     * @since 2.5
2094     */
2095    public WebSocket setPingSenderName(String name)
2096    {
2097        mPingSender.setTimerName(name);
2098
2099        return this;
2100    }
2101
2102
2103    /**
2104     * Get the name of the {@code Timer} that sends pong frames periodically.
2105     *
2106     * @return
2107     *         The {@code Timer}'s name.
2108     *
2109     * @since 2.5
2110     */
2111    public String getPongSenderName()
2112    {
2113        return mPongSender.getTimerName();
2114    }
2115
2116
2117    /**
2118     * Set the name of the {@code Timer} that sends pong frames periodically.
2119     *
2120     * @param name
2121     *         A name for the {@code Timer}.
2122     *
2123     * @return
2124     *         {@code this} object.
2125     *
2126     * @since 2.5
2127     */
2128    public WebSocket setPongSenderName(String name)
2129    {
2130        mPongSender.setTimerName(name);
2131
2132        return this;
2133    }
2134
2135
2136    /**
2137     * Add a listener to receive events on this WebSocket.
2138     *
2139     * @param listener
2140     *         A listener to add.
2141     *
2142     * @return
2143     *         {@code this} object.
2144     */
2145    public WebSocket addListener(WebSocketListener listener)
2146    {
2147        mListenerManager.addListener(listener);
2148
2149        return this;
2150    }
2151
2152
2153    /**
2154     * Add listeners.
2155     *
2156     * @param listeners
2157     *         Listeners to add. {@code null} is silently ignored.
2158     *         {@code null} elements in the list are ignored, too.
2159     *
2160     * @return
2161     *         {@code this} object.
2162     *
2163     * @since 1.14
2164     */
2165    public WebSocket addListeners(List<WebSocketListener> listeners)
2166    {
2167        mListenerManager.addListeners(listeners);
2168
2169        return this;
2170    }
2171
2172
2173    /**
2174     * Remove a listener from this WebSocket.
2175     *
2176     * @param listener
2177     *         A listener to remove. {@code null} won't cause an error.
2178     *
2179     * @return
2180     *         {@code this} object.
2181     *
2182     * @since 1.13
2183     */
2184    public WebSocket removeListener(WebSocketListener listener)
2185    {
2186        mListenerManager.removeListener(listener);
2187
2188        return this;
2189    }
2190
2191
2192    /**
2193     * Remove listeners.
2194     *
2195     * @param listeners
2196     *         Listeners to remove. {@code null} is silently ignored.
2197     *         {@code null} elements in the list are ignored, too.
2198     *
2199     * @return
2200     *         {@code this} object.
2201     *
2202     * @since 1.14
2203     */
2204    public WebSocket removeListeners(List<WebSocketListener> listeners)
2205    {
2206        mListenerManager.removeListeners(listeners);
2207
2208        return this;
2209    }
2210
2211
2212    /**
2213     * Remove all the listeners from this WebSocket.
2214     *
2215     * @return
2216     *         {@code this} object.
2217     *
2218     * @since 1.13
2219     */
2220    public WebSocket clearListeners()
2221    {
2222        mListenerManager.clearListeners();
2223
2224        return this;
2225    }
2226
2227
2228    /**
2229     * Get the raw socket which this WebSocket uses internally if it has been
2230     * established, yet.
2231     *
2232     * <p>
2233     * Version 2.9 has changed the behavior of this method, and this method may
2234     * return {@code null} if the underlying socket has not been established yet.
2235     * Consider using {@link #getConnectedSocket()} method as necessary.
2236     * </p>
2237     *
2238     * @return
2239     *         The underlying {@link Socket} instance.
2240     *         This may be {@code null} in case the underlying socket has not
2241     *         been established, yet.
2242     *
2243     * @see #getConnectedSocket()
2244     */
2245    public Socket getSocket()
2246    {
2247        return mSocketConnector.getSocket();
2248    }
2249
2250
2251    /**
2252     * Get the raw socket which this WebSocket uses internally. This will
2253     * establish a connection to the server if not already done.
2254     *
2255     * @return
2256     *         The underlying {@link Socket} instance.
2257     *
2258     * @since 2.9
2259     */
2260    public Socket getConnectedSocket() throws WebSocketException
2261    {
2262        return mSocketConnector.getConnectedSocket();
2263    }
2264
2265
2266    /**
2267     * Get the URI of the WebSocket endpoint. The scheme part is either
2268     * {@code "ws"} or {@code "wss"}. The authority part is always empty.
2269     *
2270     * @return
2271     *         The URI of the WebSocket endpoint.
2272     *
2273     * @since 1.1
2274     */
2275    public URI getURI()
2276    {
2277        return mHandshakeBuilder.getURI();
2278    }
2279
2280
2281    /**
2282     * Connect to the server, send an opening handshake to the server,
2283     * receive the response and then start threads to communicate with
2284     * the server.
2285     *
2286     * <p>
2287     * As necessary, {@link #addProtocol(String)}, {@link #addExtension(WebSocketExtension)}
2288     * {@link #addHeader(String, String)} should be called before you call this
2289     * method. It is because the parameters set by these methods are used in the
2290     * opening handshake.
2291     * </p>
2292     *
2293     * <p>
2294     * Also, as necessary, {@link #getSocket()} should be used to set up socket
2295     * parameters before you call this method. For example, you can set the
2296     * socket timeout like the following. Note that, however, because the version
2297     * 2.9 changed the behavior of {@link #getSocket()} and the method may return
2298     * {@code null} if the underlying socket has not been established yet, you may
2299     * need to use {@link #getConnectedSocket()} method instead.
2300     * </p>
2301     *
2302     * <pre>
2303     * WebSocket websocket = ......;
2304     * websocket.{@link #getSocket() getSocket()}.{@link Socket#setSoTimeout(int)
2305     * setSoTimeout}(5000);
2306     *
2307     * <span style="color: green;">// getConnectedSocket() instead of getSocket(), since version 2.9.</span>
2308     * websocket.{@link #getConnectedSocket() getConnectedSocket()}.{@link
2309     * Socket#setSoTimeout(int) setSoTimeout}(5000);
2310     * </pre>
2311     *
2312     * <p>
2313     * If the WebSocket endpoint requires Basic Authentication, you can set
2314     * credentials by {@link #setUserInfo(String) setUserInfo(userInfo)} or
2315     * {@link #setUserInfo(String, String) setUserInfo(id, password)} before
2316     * you call this method.
2317     * Note that if the URI passed to {@link WebSocketFactory}{@code
2318     * .createSocket} method contains the user-info part, you don't have to
2319     * call {@code setUserInfo} method.
2320     * </p>
2321     *
2322     * <p>
2323     * Note that this method can be called at most only once regardless of
2324     * whether this method succeeded or failed. If you want to re-connect to
2325     * the WebSocket endpoint, you have to create a new {@code WebSocket}
2326     * instance again by calling one of {@code createSocket} methods of a
2327     * {@link WebSocketFactory}. You may find {@link #recreate()} method
2328     * useful if you want to create a new {@code WebSocket} instance that
2329     * has the same settings as this instance. (But settings you made on
2330     * the raw socket are not copied.)
2331     * </p>
2332     *
2333     * @return
2334     *         {@code this} object.
2335     *
2336     * @throws WebSocketException
2337     *         <ul>
2338     *           <li>The current state of the WebSocket is not {@link
2339     *               WebSocketState#CREATED CREATED}
2340     *           </li>
2341     *           <li>Connecting the server failed.</li>
2342     *           <li>The opening handshake failed.</li>
2343     *         </ul>
2344     */
2345    public WebSocket connect() throws WebSocketException
2346    {
2347        // Change the state to CONNECTING. If the state before
2348        // the change is not CREATED, an exception is thrown.
2349        changeStateOnConnect();
2350
2351        // HTTP headers from the server.
2352        Map<String, List<String>> headers;
2353
2354        try
2355        {
2356            // Connect to the server.
2357            Socket socket = mSocketConnector.connect();
2358
2359            // Perform WebSocket handshake.
2360            headers = shakeHands(socket);
2361        }
2362        catch (WebSocketException e)
2363        {
2364            // Close the socket.
2365            mSocketConnector.closeSilently();
2366
2367            // Change the state to CLOSED.
2368            mStateManager.setState(CLOSED);
2369
2370            // Notify the listener of the state change.
2371            mListenerManager.callOnStateChanged(CLOSED);
2372
2373            // The handshake failed.
2374            throw e;
2375        }
2376
2377        // HTTP headers in the response from the server.
2378        mServerHeaders = headers;
2379
2380        // Extensions.
2381        mPerMessageCompressionExtension = findAgreedPerMessageCompressionExtension();
2382
2383        // Change the state to OPEN.
2384        mStateManager.setState(OPEN);
2385
2386        // Notify the listener of the state change.
2387        mListenerManager.callOnStateChanged(OPEN);
2388
2389        // Start threads that communicate with the server.
2390        startThreads();
2391
2392        return this;
2393    }
2394
2395
2396    /**
2397     * Execute {@link #connect()} asynchronously using the given {@link
2398     * ExecutorService}. This method is just an alias of the following.
2399     *
2400     * <blockquote>
2401     * <code>executorService.{@link ExecutorService#submit(Callable) submit}({@link #connectable()})</code>
2402     * </blockquote>
2403     *
2404     * @param executorService
2405     *         An {@link ExecutorService} to execute a task created by
2406     *         {@link #connectable()}.
2407     *
2408     * @return
2409     *         The value returned from {@link ExecutorService#submit(Callable)}.
2410     *
2411     * @throws NullPointerException
2412     *         If the given {@link ExecutorService} is {@code null}.
2413     *
2414     * @throws RejectedExecutionException
2415     *         If the given {@link ExecutorService} rejected the task
2416     *         created by {@link #connectable()}.
2417     *
2418     * @see #connectAsynchronously()
2419     *
2420     * @since 1.7
2421     */
2422    public Future<WebSocket> connect(ExecutorService executorService)
2423    {
2424        return executorService.submit(connectable());
2425    }
2426
2427
2428    /**
2429     * Get a new {@link Callable}{@code <}{@link WebSocket}{@code >} instance
2430     * whose {@link Callable#call() call()} method calls {@link #connect()}
2431     * method of this {@code WebSocket} instance.
2432     *
2433     * @return
2434     *         A new {@link Callable}{@code <}{@link WebSocket}{@code >} instance
2435     *         for asynchronous {@link #connect()}.
2436     *
2437     * @see #connect(ExecutorService)
2438     *
2439     * @since 1.7
2440     */
2441    public Callable<WebSocket> connectable()
2442    {
2443        return new Connectable(this);
2444    }
2445
2446
2447    /**
2448     * Execute {@link #connect()} asynchronously by creating a new thread and
2449     * calling {@code connect()} in the thread. If {@code connect()} failed,
2450     * {@link WebSocketListener#onConnectError(WebSocket, WebSocketException)
2451     * onConnectError()} method of {@link WebSocketListener} is called.
2452     *
2453     * @return
2454     *         {@code this} object.
2455     *
2456     * @since 1.8
2457     */
2458    public WebSocket connectAsynchronously()
2459    {
2460        Thread thread = new ConnectThread(this);
2461
2462        // Get the reference (just in case)
2463        ListenerManager lm = mListenerManager;
2464
2465        if (lm != null)
2466        {
2467            lm.callOnThreadCreated(ThreadType.CONNECT_THREAD, thread);
2468        }
2469
2470        thread.start();
2471
2472        return this;
2473    }
2474
2475
2476    /**
2477     * Disconnect the WebSocket.
2478     *
2479     * <p>
2480     * This method is an alias of {@link #disconnect(int, String)
2481     * disconnect}{@code (}{@link WebSocketCloseCode#NORMAL}{@code , null)}.
2482     * </p>
2483     *
2484     * @return
2485     *         {@code this} object.
2486     */
2487    public WebSocket disconnect()
2488    {
2489        return disconnect(WebSocketCloseCode.NORMAL, null);
2490    }
2491
2492
2493    /**
2494     * Disconnect the WebSocket.
2495     *
2496     * <p>
2497     * This method is an alias of {@link #disconnect(int, String)
2498     * disconnect}{@code (closeCode, null)}.
2499     * </p>
2500     *
2501     * @param closeCode
2502     *         The close code embedded in a <a href=
2503     *         "https://tools.ietf.org/html/rfc6455#section-5.5.1">close frame</a>
2504     *         which this WebSocket client will send to the server.
2505     *
2506     * @return
2507     *         {@code this} object.
2508     *
2509     * @since 1.5
2510     */
2511    public WebSocket disconnect(int closeCode)
2512    {
2513        return disconnect(closeCode, null);
2514    }
2515
2516
2517    /**
2518     * Disconnect the WebSocket.
2519     *
2520     * <p>
2521     * This method is an alias of {@link #disconnect(int, String)
2522     * disconnect}{@code (}{@link WebSocketCloseCode#NORMAL}{@code , reason)}.
2523     * </p>
2524     *
2525     * @param reason
2526     *         The reason embedded in a <a href=
2527     *         "https://tools.ietf.org/html/rfc6455#section-5.5.1">close frame</a>
2528     *         which this WebSocket client will send to the server. Note that
2529     *         the length of the bytes which represents the given reason must
2530     *         not exceed 125. In other words, {@code (reason.}{@link
2531     *         String#getBytes(String) getBytes}{@code ("UTF-8").length <= 125)}
2532     *         must be true.
2533     *
2534     * @return
2535     *         {@code this} object.
2536     *
2537     * @since 1.5
2538     */
2539    public WebSocket disconnect(String reason)
2540    {
2541        return disconnect(WebSocketCloseCode.NORMAL, reason);
2542    }
2543
2544
2545    /**
2546     * Disconnect the WebSocket.
2547     *
2548     * <p>
2549     * This method is an alias of {@link #disconnect(int, String, long)
2550     * disconnect}{@code (closeCode, reason, 10000L)}.
2551     * </p>
2552     *
2553     * @param closeCode
2554     *         The close code embedded in a <a href=
2555     *         "https://tools.ietf.org/html/rfc6455#section-5.5.1">close frame</a>
2556     *         which this WebSocket client will send to the server.
2557     *
2558     * @param reason
2559     *         The reason embedded in a <a href=
2560     *         "https://tools.ietf.org/html/rfc6455#section-5.5.1">close frame</a>
2561     *         which this WebSocket client will send to the server. Note that
2562     *         the length of the bytes which represents the given reason must
2563     *         not exceed 125. In other words, {@code (reason.}{@link
2564     *         String#getBytes(String) getBytes}{@code ("UTF-8").length <= 125)}
2565     *         must be true.
2566     *
2567     * @return
2568     *         {@code this} object.
2569     *
2570     * @see WebSocketCloseCode
2571     *
2572     * @see <a href="https://tools.ietf.org/html/rfc6455#section-5.5.1">RFC 6455, 5.5.1. Close</a>
2573     *
2574     * @since 1.5
2575     */
2576    public WebSocket disconnect(int closeCode, String reason)
2577    {
2578        return disconnect(closeCode, reason, DEFAULT_CLOSE_DELAY);
2579    }
2580
2581
2582    /**
2583     * Disconnect the WebSocket.
2584     *
2585     * @param closeCode
2586     *         The close code embedded in a <a href=
2587     *         "https://tools.ietf.org/html/rfc6455#section-5.5.1">close frame</a>
2588     *         which this WebSocket client will send to the server.
2589     *
2590     * @param reason
2591     *         The reason embedded in a <a href=
2592     *         "https://tools.ietf.org/html/rfc6455#section-5.5.1">close frame</a>
2593     *         which this WebSocket client will send to the server. Note that
2594     *         the length of the bytes which represents the given reason must
2595     *         not exceed 125. In other words, {@code (reason.}{@link
2596     *         String#getBytes(String) getBytes}{@code ("UTF-8").length <= 125)}
2597     *         must be true.
2598     *
2599     * @param closeDelay
2600     *         Delay in milliseconds before calling {@link Socket#close()} forcibly.
2601     *         This safeguard is needed for the case where the server fails to send
2602     *         back a close frame. The default value is 10000 (= 10 seconds). When
2603     *         a negative value is given, the default value is used.
2604     *
2605     *         If a very short time (e.g. 0) is given, it is likely to happen either
2606     *         (1) that this client will fail to send a close frame to the server
2607     *         (in this case, you will probably see an error message "Flushing frames
2608     *         to the server failed: Socket closed") or (2) that the WebSocket
2609     *         connection will be closed before this client receives a close frame
2610     *         from the server (in this case, the second argument of {@link
2611     *         WebSocketListener#onDisconnected(WebSocket, WebSocketFrame,
2612     *         WebSocketFrame, boolean) WebSocketListener.onDisconnected} will be
2613     *         {@code null}).
2614     *
2615     * @return
2616     *         {@code this} object.
2617     *
2618     * @see WebSocketCloseCode
2619     *
2620     * @see <a href="https://tools.ietf.org/html/rfc6455#section-5.5.1">RFC 6455, 5.5.1. Close</a>
2621     *
2622     * @since 1.26
2623     */
2624    public WebSocket disconnect(int closeCode, String reason, long closeDelay)
2625    {
2626        synchronized (mStateManager)
2627        {
2628            switch (mStateManager.getState())
2629            {
2630                case CREATED:
2631                    finishAsynchronously();
2632                    return this;
2633
2634                case OPEN:
2635                    break;
2636
2637                default:
2638                    // - CONNECTING
2639                    //     It won't happen unless the programmer dare call
2640                    //     open() and disconnect() in parallel.
2641                    //
2642                    // - CLOSING
2643                    //     A closing handshake has already been started.
2644                    //
2645                    // - CLOSED
2646                    //     The connection has already been closed.
2647                    return this;
2648            }
2649
2650            // Change the state to CLOSING.
2651            mStateManager.changeToClosing(CloseInitiator.CLIENT);
2652
2653            // Create a close frame.
2654            WebSocketFrame frame = WebSocketFrame.createCloseFrame(closeCode, reason);
2655
2656            // Send the close frame to the server.
2657            sendFrame(frame);
2658        }
2659
2660        // Notify the listeners of the state change.
2661        mListenerManager.callOnStateChanged(CLOSING);
2662
2663        // If a negative value is given.
2664        if (closeDelay < 0)
2665        {
2666            // Use the default value.
2667            closeDelay = DEFAULT_CLOSE_DELAY;
2668        }
2669
2670        // Request the threads to stop.
2671        stopThreads(closeDelay);
2672
2673        return this;
2674    }
2675
2676
2677    /**
2678     * Get the agreed extensions.
2679     *
2680     * <p>
2681     * This method works correctly only after {@link #connect()} succeeds
2682     * (= after the opening handshake succeeds).
2683     * </p>
2684     *
2685     * @return
2686     *         The agreed extensions.
2687     */
2688    public List<WebSocketExtension> getAgreedExtensions()
2689    {
2690        return mAgreedExtensions;
2691    }
2692
2693
2694    /**
2695     * Get the agreed protocol.
2696     *
2697     * <p>
2698     * This method works correctly only after {@link #connect()} succeeds
2699     * (= after the opening handshake succeeds).
2700     * </p>
2701     *
2702     * @return
2703     *         The agreed protocol.
2704     */
2705    public String getAgreedProtocol()
2706    {
2707        return mAgreedProtocol;
2708    }
2709
2710
2711    /**
2712     * Send a WebSocket frame to the server.
2713     *
2714     * <p>
2715     * This method just queues the given frame. Actual transmission
2716     * is performed asynchronously.
2717     * </p>
2718     *
2719     * <p>
2720     * When the current state of this WebSocket is not {@link
2721     * WebSocketState#OPEN OPEN}, this method does not accept
2722     * the frame.
2723     * </p>
2724     *
2725     * <p>
2726     * Sending a <a href="https://tools.ietf.org/html/rfc6455#section-5.5.1"
2727     * >close frame</a> changes the state to {@link WebSocketState#CLOSING
2728     * CLOSING} (if the current state is neither {@link WebSocketState#CLOSING
2729     * CLOSING} nor {@link WebSocketState#CLOSED CLOSED}).
2730     * </p>
2731     *
2732     * <p>
2733     * Note that the validity of the give frame is not checked.
2734     * For example, even if the payload length of a given frame
2735     * is greater than 125 and the opcode indicates that the
2736     * frame is a control frame, this method accepts the given
2737     * frame.
2738     * </p>
2739     *
2740     * @param frame
2741     *         A WebSocket frame to be sent to the server.
2742     *         If {@code null} is given, nothing is done.
2743     *
2744     * @return
2745     *         {@code this} object.
2746     */
2747    public WebSocket sendFrame(WebSocketFrame frame)
2748    {
2749        if (frame == null)
2750        {
2751            return this;
2752        }
2753
2754        synchronized (mStateManager)
2755        {
2756            WebSocketState state = mStateManager.getState();
2757
2758            if (state != OPEN && state != CLOSING)
2759            {
2760                return this;
2761            }
2762        }
2763
2764        // The current state is either OPEN or CLOSING. Or, CLOSED.
2765
2766        // Get the reference to the writing thread.
2767        WritingThread wt = mWritingThread;
2768
2769        // Some applications call sendFrame() without waiting for the
2770        // notification of WebSocketListener.onConnected() (Issue #23),
2771        // and/or even after the connection is closed. That is, there
2772        // are chances that sendFrame() is called when mWritingThread
2773        // is null. So, it should be checked whether an instance of
2774        // WritingThread is available or not before calling queueFrame().
2775        if (wt == null)
2776        {
2777            // An instance of WritingThread is not available.
2778            return this;
2779        }
2780
2781        // Split the frame into multiple frames if necessary.
2782        List<WebSocketFrame> frames = splitIfNecessary(frame);
2783
2784        // Queue the frame or the frames. Even if the current state is
2785        // CLOSED, queueing won't be a big issue.
2786
2787        // If the frame was not split.
2788        if (frames == null)
2789        {
2790            // Queue the frame.
2791            wt.queueFrame(frame);
2792        }
2793        else
2794        {
2795            for (WebSocketFrame f : frames)
2796            {
2797                // Queue the frame.
2798                wt.queueFrame(f);
2799            }
2800        }
2801
2802        return this;
2803    }
2804
2805
2806    private List<WebSocketFrame> splitIfNecessary(WebSocketFrame frame)
2807    {
2808        return WebSocketFrame.splitIfNecessary(frame, mMaxPayloadSize, mPerMessageCompressionExtension);
2809    }
2810
2811
2812    /**
2813     * Send a continuation frame to the server.
2814     *
2815     * <p>
2816     * This method is an alias of {@link #sendFrame(WebSocketFrame)
2817     * sendFrame}{@code (WebSocketFrame.}{@link
2818     * WebSocketFrame#createContinuationFrame()
2819     * createContinuationFrame()}{@code )}.
2820     * </p>
2821     *
2822     * <p>
2823     * Note that the FIN bit of a frame sent by this method is {@code false}.
2824     * If you want to set the FIN bit, use {@link #sendContinuation(boolean)
2825     * sendContinuation(boolean fin)} with {@code fin=true}.
2826     * </p>
2827     *
2828     * @return
2829     *         {@code this} object.
2830     */
2831    public WebSocket sendContinuation()
2832    {
2833        return sendFrame(WebSocketFrame.createContinuationFrame());
2834    }
2835
2836
2837    /**
2838     * Send a continuation frame to the server.
2839     *
2840     * <p>
2841     * This method is an alias of {@link #sendFrame(WebSocketFrame)
2842     * sendFrame}{@code (WebSocketFrame.}{@link
2843     * WebSocketFrame#createContinuationFrame()
2844     * createContinuationFrame()}{@code .}{@link
2845     * WebSocketFrame#setFin(boolean) setFin}{@code (fin))}.
2846     * </p>
2847     *
2848     * @param fin
2849     *         The FIN bit value.
2850     *
2851     * @return
2852     *         {@code this} object.
2853     */
2854    public WebSocket sendContinuation(boolean fin)
2855    {
2856        return sendFrame(WebSocketFrame.createContinuationFrame().setFin(fin));
2857    }
2858
2859
2860    /**
2861     * Send a continuation frame to the server.
2862     *
2863     * <p>
2864     * This method is an alias of {@link #sendFrame(WebSocketFrame)
2865     * sendFrame}{@code (WebSocketFrame.}{@link
2866     * WebSocketFrame#createContinuationFrame(String)
2867     * createContinuationFrame}{@code (payload))}.
2868     * </p>
2869     *
2870     * <p>
2871     * Note that the FIN bit of a frame sent by this method is {@code false}.
2872     * If you want to set the FIN bit, use {@link #sendContinuation(String,
2873     * boolean) sendContinuation(String payload, boolean fin)} with {@code
2874     * fin=true}.
2875     * </p>
2876     *
2877     * @param payload
2878     *         The payload of a continuation frame.
2879     *
2880     * @return
2881     *         {@code this} object.
2882     */
2883    public WebSocket sendContinuation(String payload)
2884    {
2885        return sendFrame(WebSocketFrame.createContinuationFrame(payload));
2886    }
2887
2888
2889    /**
2890     * Send a continuation frame to the server.
2891     *
2892     * <p>
2893     * This method is an alias of {@link #sendFrame(WebSocketFrame)
2894     * sendFrame}{@code (WebSocketFrame.}{@link
2895     * WebSocketFrame#createContinuationFrame(String)
2896     * createContinuationFrame}{@code (payload).}{@link
2897     * WebSocketFrame#setFin(boolean) setFin}{@code (fin))}.
2898     * </p>
2899     *
2900     * @param payload
2901     *         The payload of a continuation frame.
2902     *
2903     * @param fin
2904     *         The FIN bit value.
2905     *
2906     * @return
2907     *         {@code this} object.
2908     */
2909    public WebSocket sendContinuation(String payload, boolean fin)
2910    {
2911        return sendFrame(WebSocketFrame.createContinuationFrame(payload).setFin(fin));
2912    }
2913
2914
2915    /**
2916     * Send a continuation frame to the server.
2917     *
2918     * <p>
2919     * This method is an alias of {@link #sendFrame(WebSocketFrame)
2920     * sendFrame}{@code (WebSocketFrame.}{@link
2921     * WebSocketFrame#createContinuationFrame(byte[])
2922     * createContinuationFrame}{@code (payload))}.
2923     * </p>
2924     *
2925     * <p>
2926     * Note that the FIN bit of a frame sent by this method is {@code false}.
2927     * If you want to set the FIN bit, use {@link #sendContinuation(byte[],
2928     * boolean) sendContinuation(byte[] payload, boolean fin)} with {@code
2929     * fin=true}.
2930     * </p>
2931     *
2932     * @param payload
2933     *         The payload of a continuation frame.
2934     *
2935     * @return
2936     *         {@code this} object.
2937     */
2938    public WebSocket sendContinuation(byte[] payload)
2939    {
2940        return sendFrame(WebSocketFrame.createContinuationFrame(payload));
2941    }
2942
2943
2944    /**
2945     * Send a continuation frame to the server.
2946     *
2947     * <p>
2948     * This method is an alias of {@link #sendFrame(WebSocketFrame)
2949     * sendFrame}{@code (WebSocketFrame.}{@link
2950     * WebSocketFrame#createContinuationFrame(byte[])
2951     * createContinuationFrame}{@code (payload).}{@link
2952     * WebSocketFrame#setFin(boolean) setFin}{@code (fin))}.
2953     * </p>
2954     *
2955     * @param payload
2956     *         The payload of a continuation frame.
2957     *
2958     * @param fin
2959     *         The FIN bit value.
2960     *
2961     * @return
2962     *         {@code this} object.
2963     */
2964    public WebSocket sendContinuation(byte[] payload, boolean fin)
2965    {
2966        return sendFrame(WebSocketFrame.createContinuationFrame(payload).setFin(fin));
2967    }
2968
2969
2970    /**
2971     * Send a text message to the server.
2972     *
2973     * <p>
2974     * This method is an alias of {@link #sendFrame(WebSocketFrame)
2975     * sendFrame}{@code (WebSocketFrame.}{@link
2976     * WebSocketFrame#createTextFrame(String)
2977     * createTextFrame}{@code (message))}.
2978     * </p>
2979     *
2980     * <p>
2981     * If you want to send a text frame that is to be followed by
2982     * continuation frames, use {@link #sendText(String, boolean)
2983     * setText(String payload, boolean fin)} with {@code fin=false}.
2984     * </p>
2985     *
2986     * @param message
2987     *         A text message to be sent to the server.
2988     *
2989     * @return
2990     *         {@code this} object.
2991     */
2992    public WebSocket sendText(String message)
2993    {
2994        return sendFrame(WebSocketFrame.createTextFrame(message));
2995    }
2996
2997
2998    /**
2999     * Send a text frame to the server.
3000     *
3001     * <p>
3002     * This method is an alias of {@link #sendFrame(WebSocketFrame)
3003     * sendFrame}{@code (WebSocketFrame.}{@link
3004     * WebSocketFrame#createTextFrame(String)
3005     * createTextFrame}{@code (payload).}{@link
3006     * WebSocketFrame#setFin(boolean) setFin}{@code (fin))}.
3007     * </p>
3008     *
3009     * @param payload
3010     *         The payload of a text frame.
3011     *
3012     * @param fin
3013     *         The FIN bit value.
3014     *
3015     * @return
3016     *         {@code this} object.
3017     */
3018    public WebSocket sendText(String payload, boolean fin)
3019    {
3020        return sendFrame(WebSocketFrame.createTextFrame(payload).setFin(fin));
3021    }
3022
3023
3024    /**
3025     * Send a binary message to the server.
3026     *
3027     * <p>
3028     * This method is an alias of {@link #sendFrame(WebSocketFrame)
3029     * sendFrame}{@code (WebSocketFrame.}{@link
3030     * WebSocketFrame#createBinaryFrame(byte[])
3031     * createBinaryFrame}{@code (message))}.
3032     * </p>
3033     *
3034     * <p>
3035     * If you want to send a binary frame that is to be followed by
3036     * continuation frames, use {@link #sendBinary(byte[], boolean)
3037     * setBinary(byte[] payload, boolean fin)} with {@code fin=false}.
3038     * </p>
3039     *
3040     * @param message
3041     *         A binary message to be sent to the server.
3042     *
3043     * @return
3044     *         {@code this} object.
3045     */
3046    public WebSocket sendBinary(byte[] message)
3047    {
3048        return sendFrame(WebSocketFrame.createBinaryFrame(message));
3049    }
3050
3051
3052    /**
3053     * Send a binary frame to the server.
3054     *
3055     * <p>
3056     * This method is an alias of {@link #sendFrame(WebSocketFrame)
3057     * sendFrame}{@code (WebSocketFrame.}{@link
3058     * WebSocketFrame#createBinaryFrame(byte[])
3059     * createBinaryFrame}{@code (payload).}{@link
3060     * WebSocketFrame#setFin(boolean) setFin}{@code (fin))}.
3061     * </p>
3062     *
3063     * @param payload
3064     *         The payload of a binary frame.
3065     *
3066     * @param fin
3067     *         The FIN bit value.
3068     *
3069     * @return
3070     *         {@code this} object.
3071     */
3072    public WebSocket sendBinary(byte[] payload, boolean fin)
3073    {
3074        return sendFrame(WebSocketFrame.createBinaryFrame(payload).setFin(fin));
3075    }
3076
3077
3078    /**
3079     * Send a close frame to the server.
3080     *
3081     * <p>
3082     * This method is an alias of {@link #sendFrame(WebSocketFrame)
3083     * sendFrame}{@code (WebSocketFrame.}{@link
3084     * WebSocketFrame#createCloseFrame() createCloseFrame()}).
3085     * </p>
3086     *
3087     * @return
3088     *         {@code this} object.
3089     */
3090    public WebSocket sendClose()
3091    {
3092        return sendFrame(WebSocketFrame.createCloseFrame());
3093    }
3094
3095
3096    /**
3097     * Send a close frame to the server.
3098     *
3099     * <p>
3100     * This method is an alias of {@link #sendFrame(WebSocketFrame)
3101     * sendFrame}{@code (WebSocketFrame.}{@link
3102     * WebSocketFrame#createCloseFrame(int)
3103     * createCloseFrame}{@code (closeCode))}.
3104     * </p>
3105     *
3106     * @param closeCode
3107     *         The close code.
3108     *
3109     * @return
3110     *         {@code this} object.
3111     *
3112     * @see WebSocketCloseCode
3113     */
3114    public WebSocket sendClose(int closeCode)
3115    {
3116        return sendFrame(WebSocketFrame.createCloseFrame(closeCode));
3117    }
3118
3119
3120    /**
3121     * Send a close frame to the server.
3122     *
3123     * <p>
3124     * This method is an alias of {@link #sendFrame(WebSocketFrame)
3125     * sendFrame}{@code (WebSocketFrame.}{@link
3126     * WebSocketFrame#createCloseFrame(int, String)
3127     * createCloseFrame}{@code (closeCode, reason))}.
3128     * </p>
3129     *
3130     * @param closeCode
3131     *         The close code.
3132     *
3133     * @param reason
3134     *         The close reason.
3135     *         Note that a control frame's payload length must be 125 bytes or less
3136     *         (RFC 6455, <a href="https://tools.ietf.org/html/rfc6455#section-5.5"
3137     *         >5.5. Control Frames</a>).
3138     *
3139     * @return
3140     *         {@code this} object.
3141     *
3142     * @see WebSocketCloseCode
3143     */
3144    public WebSocket sendClose(int closeCode, String reason)
3145    {
3146        return sendFrame(WebSocketFrame.createCloseFrame(closeCode, reason));
3147    }
3148
3149
3150    /**
3151     * Send a ping frame to the server.
3152     *
3153     * <p>
3154     * This method is an alias of {@link #sendFrame(WebSocketFrame)
3155     * sendFrame}{@code (WebSocketFrame.}{@link
3156     * WebSocketFrame#createPingFrame() createPingFrame()}).
3157     * </p>
3158     *
3159     * @return
3160     *         {@code this} object.
3161     */
3162    public WebSocket sendPing()
3163    {
3164        return sendFrame(WebSocketFrame.createPingFrame());
3165    }
3166
3167
3168    /**
3169     * Send a ping frame to the server.
3170     *
3171     * <p>
3172     * This method is an alias of {@link #sendFrame(WebSocketFrame)
3173     * sendFrame}{@code (WebSocketFrame.}{@link
3174     * WebSocketFrame#createPingFrame(byte[])
3175     * createPingFrame}{@code (payload))}.
3176     * </p>
3177     *
3178     * @param payload
3179     *         The payload for a ping frame.
3180     *         Note that a control frame's payload length must be 125 bytes or less
3181     *         (RFC 6455, <a href="https://tools.ietf.org/html/rfc6455#section-5.5"
3182     *         >5.5. Control Frames</a>).
3183     *
3184     * @return
3185     *         {@code this} object.
3186     */
3187    public WebSocket sendPing(byte[] payload)
3188    {
3189        return sendFrame(WebSocketFrame.createPingFrame(payload));
3190    }
3191
3192
3193    /**
3194     * Send a ping frame to the server.
3195     *
3196     * <p>
3197     * This method is an alias of {@link #sendFrame(WebSocketFrame)
3198     * sendFrame}{@code (WebSocketFrame.}{@link
3199     * WebSocketFrame#createPingFrame(String)
3200     * createPingFrame}{@code (payload))}.
3201     * </p>
3202     *
3203     * @param payload
3204     *         The payload for a ping frame.
3205     *         Note that a control frame's payload length must be 125 bytes or less
3206     *         (RFC 6455, <a href="https://tools.ietf.org/html/rfc6455#section-5.5"
3207     *         >5.5. Control Frames</a>).
3208     *
3209     * @return
3210     *         {@code this} object.
3211     */
3212    public WebSocket sendPing(String payload)
3213    {
3214        return sendFrame(WebSocketFrame.createPingFrame(payload));
3215    }
3216
3217
3218    /**
3219     * Send a pong frame to the server.
3220     *
3221     * <p>
3222     * This method is an alias of {@link #sendFrame(WebSocketFrame)
3223     * sendFrame}{@code (WebSocketFrame.}{@link
3224     * WebSocketFrame#createPongFrame() createPongFrame()}).
3225     * </p>
3226     *
3227     * @return
3228     *         {@code this} object.
3229     */
3230    public WebSocket sendPong()
3231    {
3232        return sendFrame(WebSocketFrame.createPongFrame());
3233    }
3234
3235
3236    /**
3237     * Send a pong frame to the server.
3238     *
3239     * <p>
3240     * This method is an alias of {@link #sendFrame(WebSocketFrame)
3241     * sendFrame}{@code (WebSocketFrame.}{@link
3242     * WebSocketFrame#createPongFrame(byte[])
3243     * createPongFrame}{@code (payload))}.
3244     * </p>
3245     *
3246     * @param payload
3247     *         The payload for a pong frame.
3248     *         Note that a control frame's payload length must be 125 bytes or less
3249     *         (RFC 6455, <a href="https://tools.ietf.org/html/rfc6455#section-5.5"
3250     *         >5.5. Control Frames</a>).
3251     *
3252     * @return
3253     *         {@code this} object.
3254     */
3255    public WebSocket sendPong(byte[] payload)
3256    {
3257        return sendFrame(WebSocketFrame.createPongFrame(payload));
3258    }
3259
3260
3261    /**
3262     * Send a pong frame to the server.
3263     *
3264     * <p>
3265     * This method is an alias of {@link #sendFrame(WebSocketFrame)
3266     * sendFrame}{@code (WebSocketFrame.}{@link
3267     * WebSocketFrame#createPongFrame(String)
3268     * createPongFrame}{@code (payload))}.
3269     * </p>
3270     *
3271     * @param payload
3272     *         The payload for a pong frame.
3273     *         Note that a control frame's payload length must be 125 bytes or less
3274     *         (RFC 6455, <a href="https://tools.ietf.org/html/rfc6455#section-5.5"
3275     *         >5.5. Control Frames</a>).
3276     *
3277     * @return
3278     *         {@code this} object.
3279     */
3280    public WebSocket sendPong(String payload)
3281    {
3282        return sendFrame(WebSocketFrame.createPongFrame(payload));
3283    }
3284
3285
3286    private void changeStateOnConnect() throws WebSocketException
3287    {
3288        synchronized (mStateManager)
3289        {
3290            // If the current state is not CREATED.
3291            if (mStateManager.getState() != CREATED)
3292            {
3293                throw new WebSocketException(
3294                    WebSocketError.NOT_IN_CREATED_STATE,
3295                    "The current state of the WebSocket is not CREATED.");
3296            }
3297
3298            // Change the state to CONNECTING.
3299            mStateManager.setState(CONNECTING);
3300        }
3301
3302        // Notify the listeners of the state change.
3303        mListenerManager.callOnStateChanged(CONNECTING);
3304    }
3305
3306
3307    /**
3308     * Perform the opening handshake.
3309     */
3310    private Map<String, List<String>> shakeHands(Socket socket) throws WebSocketException
3311    {
3312        // Get the input stream of the socket.
3313        WebSocketInputStream input = openInputStream(socket);
3314
3315        // Get the output stream of the socket.
3316        WebSocketOutputStream output = openOutputStream(socket);
3317
3318        // Generate a value for Sec-WebSocket-Key.
3319        String key = generateWebSocketKey();
3320
3321        // Send an opening handshake to the server.
3322        writeHandshake(output, key);
3323
3324        // Read the response from the server.
3325        Map<String, List<String>> headers = readHandshake(input, key);
3326
3327        // Keep the input stream and the output stream to pass them
3328        // to the reading thread and the writing thread later.
3329        mInput  = input;
3330        mOutput = output;
3331
3332        // The handshake succeeded.
3333        return headers;
3334    }
3335
3336
3337    /**
3338     * Open the input stream of the WebSocket connection.
3339     * The stream is used by the reading thread.
3340     */
3341    private WebSocketInputStream openInputStream(Socket socket) throws WebSocketException
3342    {
3343        try
3344        {
3345            // Get the input stream of the raw socket through which
3346            // this client receives data from the server.
3347            return new WebSocketInputStream(
3348                new BufferedInputStream(socket.getInputStream()));
3349        }
3350        catch (IOException e)
3351        {
3352            // Failed to get the input stream of the raw socket.
3353            throw new WebSocketException(
3354                WebSocketError.SOCKET_INPUT_STREAM_FAILURE,
3355                "Failed to get the input stream of the raw socket: " + e.getMessage(), e);
3356        }
3357    }
3358
3359
3360    /**
3361     * Open the output stream of the WebSocket connection.
3362     * The stream is used by the writing thread.
3363     */
3364    private WebSocketOutputStream openOutputStream(Socket socket) throws WebSocketException
3365    {
3366        try
3367        {
3368            // Get the output stream of the socket through which
3369            // this client sends data to the server.
3370            return new WebSocketOutputStream(
3371                new BufferedOutputStream(socket.getOutputStream()));
3372        }
3373        catch (IOException e)
3374        {
3375            // Failed to get the output stream from the raw socket.
3376            throw new WebSocketException(
3377                WebSocketError.SOCKET_OUTPUT_STREAM_FAILURE,
3378                "Failed to get the output stream from the raw socket: " + e.getMessage(), e);
3379        }
3380    }
3381
3382
3383    /**
3384     * Generate a value for Sec-WebSocket-Key.
3385     *
3386     * <blockquote>
3387     * <p><i>
3388     * The request MUST include a header field with the name Sec-WebSocket-Key.
3389     * The value of this header field MUST be a nonce consisting of a randomly
3390     * selected 16-byte value that has been base64-encoded (see Section 4 of
3391     * RFC 4648). The nonce MUST be selected randomly for each connection.
3392     * </i></p>
3393     * </blockquote>
3394     *
3395     * @return
3396     *         A randomly generated WebSocket key.
3397     */
3398    private static String generateWebSocketKey()
3399    {
3400        // "16-byte value"
3401        byte[] data = new byte[16];
3402
3403        // "randomly selected"
3404        Misc.nextBytes(data);
3405
3406        // "base64-encoded"
3407        return Base64.encode(data);
3408    }
3409
3410
3411    /**
3412     * Send an opening handshake request to the WebSocket server.
3413     */
3414    private void writeHandshake(WebSocketOutputStream output, String key) throws WebSocketException
3415    {
3416        // Generate an opening handshake sent to the server from this client.
3417        mHandshakeBuilder.setKey(key);
3418        String requestLine     = mHandshakeBuilder.buildRequestLine();
3419        List<String[]> headers = mHandshakeBuilder.buildHeaders();
3420        String handshake       = HandshakeBuilder.build(requestLine, headers);
3421
3422        // Call onSendingHandshake() method of listeners.
3423        mListenerManager.callOnSendingHandshake(requestLine, headers);
3424
3425        try
3426        {
3427            // Send the opening handshake to the server.
3428            output.write(handshake);
3429            output.flush();
3430        }
3431        catch (IOException e)
3432        {
3433            // Failed to send an opening handshake request to the server.
3434            throw new WebSocketException(
3435                WebSocketError.OPENING_HAHDSHAKE_REQUEST_FAILURE,
3436                "Failed to send an opening handshake request to the server: " + e.getMessage(), e);
3437        }
3438    }
3439
3440
3441    /**
3442     * Receive an opening handshake response from the WebSocket server.
3443     */
3444    private Map<String, List<String>> readHandshake(WebSocketInputStream input, String key) throws WebSocketException
3445    {
3446        return new HandshakeReader(this).readHandshake(input, key);
3447    }
3448
3449
3450    /**
3451     * Start both the reading thread and the writing thread.
3452     *
3453     * <p>
3454     * The reading thread will call {@link #onReadingThreadStarted()}
3455     * as its first step. Likewise, the writing thread will call
3456     * {@link #onWritingThreadStarted()} as its first step. After
3457     * both the threads have started, {@link #onThreadsStarted()} is
3458     * called.
3459     * </p>
3460     */
3461    private void startThreads()
3462    {
3463        ReadingThread readingThread = new ReadingThread(this);
3464        WritingThread writingThread = new WritingThread(this);
3465
3466        synchronized (mThreadsLock)
3467        {
3468            mReadingThread = readingThread;
3469            mWritingThread = writingThread;
3470        }
3471
3472        // Execute onThreadCreated of the listeners.
3473        readingThread.callOnThreadCreated();
3474        writingThread.callOnThreadCreated();
3475
3476        readingThread.start();
3477        writingThread.start();
3478    }
3479
3480
3481    /**
3482     * Stop both the reading thread and the writing thread.
3483     *
3484     * <p>
3485     * The reading thread will call {@link #onReadingThreadFinished(WebSocketFrame)}
3486     * as its last step. Likewise, the writing thread will call {@link
3487     * #onWritingThreadFinished(WebSocketFrame)} as its last step.
3488     * After both the threads have stopped, {@link #onThreadsFinished()}
3489     * is called.
3490     * </p>
3491     */
3492    private void stopThreads(long closeDelay)
3493    {
3494        ReadingThread readingThread;
3495        WritingThread writingThread;
3496
3497        synchronized (mThreadsLock)
3498        {
3499            readingThread = mReadingThread;
3500            writingThread = mWritingThread;
3501
3502            mReadingThread = null;
3503            mWritingThread = null;
3504        }
3505
3506        if (readingThread != null)
3507        {
3508            readingThread.requestStop(closeDelay);
3509        }
3510
3511        if (writingThread != null)
3512        {
3513            writingThread.requestStop();
3514        }
3515    }
3516
3517
3518    /**
3519     * Get the input stream of the WebSocket connection.
3520     */
3521    WebSocketInputStream getInput()
3522    {
3523        return mInput;
3524    }
3525
3526
3527    /**
3528     * Get the output stream of the WebSocket connection.
3529     */
3530    WebSocketOutputStream getOutput()
3531    {
3532        return mOutput;
3533    }
3534
3535
3536    /**
3537     * Get the manager that manages the state of this {@code WebSocket} instance.
3538     */
3539    StateManager getStateManager()
3540    {
3541        return mStateManager;
3542    }
3543
3544
3545    /**
3546     * Get the manager that manages registered listeners.
3547     */
3548    ListenerManager getListenerManager()
3549    {
3550        return mListenerManager;
3551    }
3552
3553
3554    /**
3555     * Get the handshake builder. {@link HandshakeReader} uses this method.
3556     */
3557    HandshakeBuilder getHandshakeBuilder()
3558    {
3559        return mHandshakeBuilder;
3560    }
3561
3562
3563    /**
3564     * Set the agreed extensions. {@link HandshakeReader} uses this method.
3565     */
3566    void setAgreedExtensions(List<WebSocketExtension> extensions)
3567    {
3568        mAgreedExtensions = extensions;
3569    }
3570
3571
3572    /**
3573     * Set the agreed protocol. {@link HandshakeReader} uses this method.
3574     */
3575    void setAgreedProtocol(String protocol)
3576    {
3577        mAgreedProtocol = protocol;
3578    }
3579
3580
3581    /**
3582     * Called by the reading thread as its first step.
3583     */
3584    void onReadingThreadStarted()
3585    {
3586        boolean bothStarted = false;
3587
3588        synchronized (mThreadsLock)
3589        {
3590            mReadingThreadStarted = true;
3591
3592            if (mWritingThreadStarted)
3593            {
3594                // Both the reading thread and the writing thread have started.
3595                bothStarted = true;
3596            }
3597        }
3598
3599        // Call onConnected() method of listeners if not called yet.
3600        callOnConnectedIfNotYet();
3601
3602        // If both the reading thread and the writing thread have started.
3603        if (bothStarted)
3604        {
3605            onThreadsStarted();
3606        }
3607    }
3608
3609
3610    /**
3611     * Called by the writing thread as its first step.
3612     */
3613    void onWritingThreadStarted()
3614    {
3615        boolean bothStarted = false;
3616
3617        synchronized (mThreadsLock)
3618        {
3619            mWritingThreadStarted = true;
3620
3621            if (mReadingThreadStarted)
3622            {
3623                // Both the reading thread and the writing thread have started.
3624                bothStarted = true;
3625            }
3626        }
3627
3628        // Call onConnected() method of listeners if not called yet.
3629        callOnConnectedIfNotYet();
3630
3631        // If both the reading thread and the writing thread have started.
3632        if (bothStarted)
3633        {
3634            onThreadsStarted();
3635        }
3636    }
3637
3638
3639    /**
3640     * Call {@link WebSocketListener#onConnected(WebSocket, Map)} method
3641     * of the registered listeners if it has not been called yet. Either
3642     * the reading thread or the writing thread calls this method.
3643     */
3644    private void callOnConnectedIfNotYet()
3645    {
3646        synchronized (mOnConnectedCalledLock)
3647        {
3648            // If onConnected() has already been called.
3649            if (mOnConnectedCalled)
3650            {
3651                // Do not call onConnected() twice.
3652                return;
3653            }
3654
3655            mOnConnectedCalled = true;
3656        }
3657
3658        // Notify the listeners that the handshake succeeded.
3659        mListenerManager.callOnConnected(mServerHeaders);
3660    }
3661
3662
3663    /**
3664     * Called when both the reading thread and the writing thread have started.
3665     * This method is called in the context of either the reading thread or
3666     * the writing thread.
3667     */
3668    private void onThreadsStarted()
3669    {
3670        // Start sending ping frames periodically.
3671        // If the interval is zero, this call does nothing.
3672        mPingSender.start();
3673
3674        // Likewise, start the pong sender.
3675        mPongSender.start();
3676    }
3677
3678
3679    /**
3680     * Called by the reading thread as its last step.
3681     */
3682    void onReadingThreadFinished(WebSocketFrame closeFrame)
3683    {
3684        synchronized (mThreadsLock)
3685        {
3686            mReadingThreadFinished = true;
3687            mServerCloseFrame = closeFrame;
3688
3689            if (mWritingThreadFinished == false)
3690            {
3691                // Wait for the writing thread to finish.
3692                return;
3693            }
3694        }
3695
3696        // Both the reading thread and the writing thread have finished.
3697        onThreadsFinished();
3698    }
3699
3700
3701    /**
3702     * Called by the writing thread as its last step.
3703     */
3704    void onWritingThreadFinished(WebSocketFrame closeFrame)
3705    {
3706        synchronized (mThreadsLock)
3707        {
3708            mWritingThreadFinished = true;
3709            mClientCloseFrame = closeFrame;
3710
3711            if (mReadingThreadFinished == false)
3712            {
3713                // Wait for the reading thread to finish.
3714                return;
3715            }
3716        }
3717
3718        // Both the reading thread and the writing thread have finished.
3719        onThreadsFinished();
3720    }
3721
3722
3723    /**
3724     * Called when both the reading thread and the writing thread have finished.
3725     * This method is called in the context of either the reading thread or
3726     * the writing thread.
3727     */
3728    private void onThreadsFinished()
3729    {
3730        finish();
3731    }
3732
3733
3734    void finish()
3735    {
3736        // Stop the ping sender and the pong sender.
3737        mPingSender.stop();
3738        mPongSender.stop();
3739
3740        // Close the raw socket.
3741        Socket socket = mSocketConnector.getSocket();
3742        if (socket != null)
3743        {
3744            try
3745            {
3746                socket.close();
3747            }
3748            catch (Throwable t)
3749            {
3750                // Ignore any error raised by close().
3751            }
3752        }
3753
3754        synchronized (mStateManager)
3755        {
3756            // Change the state to CLOSED.
3757            mStateManager.setState(CLOSED);
3758        }
3759
3760        // Notify the listeners of the state change.
3761        mListenerManager.callOnStateChanged(CLOSED);
3762
3763        // Notify the listeners that the WebSocket was disconnected.
3764        mListenerManager.callOnDisconnected(
3765            mServerCloseFrame, mClientCloseFrame, mStateManager.getClosedByServer());
3766    }
3767
3768
3769    /**
3770     * Call {@link #finish()} from within a separate thread.
3771     */
3772    private void finishAsynchronously()
3773    {
3774        WebSocketThread thread = new FinishThread(this);
3775
3776        // Execute onThreadCreated() of the listeners.
3777        thread.callOnThreadCreated();
3778
3779        thread.start();
3780    }
3781
3782
3783    /**
3784     * Find a per-message compression extension from among the agreed extensions.
3785     */
3786    private PerMessageCompressionExtension findAgreedPerMessageCompressionExtension()
3787    {
3788        if (mAgreedExtensions == null)
3789        {
3790            return null;
3791        }
3792
3793        for (WebSocketExtension extension : mAgreedExtensions)
3794        {
3795            if (extension instanceof PerMessageCompressionExtension)
3796            {
3797                return (PerMessageCompressionExtension)extension;
3798            }
3799        }
3800
3801        return null;
3802    }
3803
3804
3805    /**
3806     * Get the PerMessageCompressionExtension in the agreed extensions.
3807     * This method returns null if a per-message compression extension
3808     * is not found in the agreed extensions.
3809     */
3810    PerMessageCompressionExtension getPerMessageCompressionExtension()
3811    {
3812        return mPerMessageCompressionExtension;
3813    }
3814}