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 java.util.List;
020import java.util.Map;
021
022
023/**
024 * Listener interface to receive WebSocket events.
025 * 
026 * <EMBED CLASS='external-html' DATA-FILE-ID=LICENSE><BR />
027 *
028 * <p>
029 * An implementation of this interface should be added by {@link
030 * WebSocket#addListener(WebSocketListener)} to a {@link WebSocket}
031 * instance before calling {@link WebSocket#connect()}.
032 * </p>
033 *
034 * <p>
035 * {@link WebSocketAdapter} is an empty implementation of this interface.
036 * </p>
037 *
038 * @see WebSocket#addListener(WebSocketListener)
039 * @see WebSocketAdapter
040 */
041public interface WebSocketListener
042{
043    /**
044     * Called after the state of the WebSocket changed.
045     *
046     * @param websocket
047     *         The WebSocket.
048     *
049     * @param newState
050     *         The new state of the WebSocket.
051     *
052     * @throws Exception
053     *         An exception thrown by an implementation of this method.
054     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
055     *
056     * @since 1.1
057     */
058    void onStateChanged(WebSocket websocket, WebSocketState newState) throws Exception;
059
060
061    /**
062     * Called after the opening handshake of the WebSocket connection succeeded.
063     *
064     * @param websocket
065     *         The WebSsocket.
066     *
067     * @param headers
068     *         HTTP headers received from the server. Keys of the map are
069     *         HTTP header names such as {@code "Sec-WebSocket-Accept"}.
070     *         Note that the comparator used by the map is {@link
071     *         String#CASE_INSENSITIVE_ORDER}.
072     *
073     * @throws Exception
074     *         An exception thrown by an implementation of this method.
075     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
076     */
077    void onConnected(WebSocket websocket, Map<String, List<String>> headers) throws Exception;
078
079
080    /**
081     * Called when {@link WebSocket#connectAsynchronously()} failed.
082     *
083     * <p>
084     * Note that this method is called only when {@code connectAsynchronously()}
085     * was used and the {@link WebSocket#connect() connect()} executed in the
086     * background thread failed. Neither direct synchronous {@code connect()}
087     * nor {@link WebSocket#connect(java.util.concurrent.ExecutorService)
088     * connect(ExecutorService)} will trigger this callback method.
089     * </p>
090     *
091     * @param websocket
092     *         The WebSocket.
093     *
094     * @param cause
095     *         The exception thrown by {@link WebSocket#connect() connect()}
096     *         method.
097     *
098     * @throws Exception
099     *         An exception thrown by an implementation of this method.
100     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
101     *
102     * @since 1.8
103     */
104    void onConnectError(WebSocket websocket, WebSocketException cause) throws Exception;
105
106
107    /**
108     * Called after the WebSocket connection was closed.
109     *
110     * @param websocket
111     *         The WebSocket.
112     *
113     * @param serverCloseFrame
114     *         The <a href="https://tools.ietf.org/html/rfc6455#section-5.5.1"
115     *         >close frame</a> which the server sent to this client.
116     *         This may be {@code null}.
117     *
118     * @param clientCloseFrame
119     *         The <a href="https://tools.ietf.org/html/rfc6455#section-5.5.1"
120     *         >close frame</a> which this client sent to the server.
121     *         This may be {@code null}.
122     *
123     * @param closedByServer
124     *         {@code true} if the closing handshake was started by the server.
125     *         {@code false} if the closing handshake was started by the client.
126     *
127     * @throws Exception
128     *         An exception thrown by an implementation of this method.
129     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
130     */
131    void onDisconnected(WebSocket websocket,
132        WebSocketFrame serverCloseFrame, WebSocketFrame clientCloseFrame,
133        boolean closedByServer) throws Exception;
134
135
136    /**
137     * Called when a frame was received. This method is called before
138     * an <code>on<i>Xxx</i>Frame</code> method is called.
139     *
140     * @param websocket
141     *         The WebSocket.
142     *
143     * @param frame
144     *         The frame.
145     *
146     * @throws Exception
147     *         An exception thrown by an implementation of this method.
148     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
149     */
150    void onFrame(WebSocket websocket, WebSocketFrame frame) throws Exception;
151
152
153    /**
154     * Called when a continuation frame (opcode = 0x0) was received.
155     *
156     * @param websocket
157     *         The WebSocket.
158     *
159     * @param frame
160     *         The continuation frame.
161     *
162     * @throws Exception
163     *         An exception thrown by an implementation of this method.
164     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
165     */
166    void onContinuationFrame(WebSocket websocket, WebSocketFrame frame) throws Exception;
167
168
169    /**
170     * Called when a text frame (opcode = 0x1) was received.
171     *
172     * @param websocket
173     *         The WebSocket.
174     *
175     * @param frame
176     *         The text frame.
177     *
178     * @throws Exception
179     *         An exception thrown by an implementation of this method.
180     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
181     */
182    void onTextFrame(WebSocket websocket, WebSocketFrame frame) throws Exception;
183
184
185    /**
186     * Called when a binary frame (opcode = 0x2) was received.
187     *
188     * @param websocket
189     *         The WebSocket.
190     *
191     * @param frame
192     *         The binary frame.
193     *
194     * @throws Exception
195     *         An exception thrown by an implementation of this method.
196     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
197     */
198    void onBinaryFrame(WebSocket websocket, WebSocketFrame frame) throws Exception;
199
200
201    /**
202     * Called when a <a href="https://tools.ietf.org/html/rfc6455#section-5.5.1"
203     * >close frame</a> (opcode = 0x8) was received.
204     *
205     * @param websocket
206     *         The WebSocket.
207     *
208     * @param frame
209     *         The <a href="https://tools.ietf.org/html/rfc6455#section-5.5.1">close frame</a>.
210     *
211     * @throws Exception
212     *         An exception thrown by an implementation of this method.
213     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
214     */
215    void onCloseFrame(WebSocket websocket, WebSocketFrame frame) throws Exception;
216
217
218    /**
219     * Called when a <a href="https://tools.ietf.org/html/rfc6455#section-5.5.2"
220     * >ping frame</a> (opcode = 0x9) was received.
221     *
222     * @param websocket
223     *         The WebSocket.
224     *
225     * @param frame
226     *         The <a href="https://tools.ietf.org/html/rfc6455#section-5.5.2">ping frame</a>.
227     *
228     * @throws Exception
229     *         An exception thrown by an implementation of this method.
230     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
231     */
232    void onPingFrame(WebSocket websocket, WebSocketFrame frame) throws Exception;
233
234
235    /**
236     * Called when a <a href="https://tools.ietf.org/html/rfc6455#section-5.5.3"
237     * >pong frame</a> (opcode = 0xA) was received.
238     *
239     * @param websocket
240     *         The WebSocket.
241     *
242     * @param frame
243     *         The <a href="https://tools.ietf.org/html/rfc6455#section-5.5.3">pong frame</a>.
244     *
245     * @throws Exception
246     *         An exception thrown by an implementation of this method.
247     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
248     */
249    void onPongFrame(WebSocket websocket, WebSocketFrame frame) throws Exception;
250
251
252    /**
253     * Called when a text message was received.
254     *
255     * <p>
256     * When {@link WebSocket#isDirectTextMessage()} returns {@code true},
257     * {@link #onTextMessage(WebSocket, byte[])} will be called instead of
258     * this method (since version 2.6).
259     * </p>
260     *
261     * @param websocket
262     *         The WebSocket.
263     *
264     * @param text
265     *         The text message.
266     *
267     * @throws Exception
268     *         An exception thrown by an implementation of this method.
269     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
270     */
271    void onTextMessage(WebSocket websocket, String text) throws Exception;
272
273
274    /**
275     * Called when a text message was received instead of
276     * {@link #onTextMessage(WebSocket, String)} when {@link WebSocket#isDirectTextMessage()}
277     * returns {@code true}.
278     *
279     * @param websocket
280     *         The WebSocket.
281     *
282     * @param data
283     *         The UTF-8 byte sequence of the text message.
284     *
285     * @throws Exception
286     *         An exception thrown by an implementation of this method.
287     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
288     *
289     * @since 2.6
290     */
291    void onTextMessage(WebSocket websocket, byte[] data) throws Exception;
292
293
294    /**
295     * Called when a binary message was received.
296     *
297     * @param websocket
298     *         The WebSocket.
299     *
300     * @param binary
301     *         The binary message.
302     *
303     * @throws Exception
304     *         An exception thrown by an implementation of this method.
305     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
306     */
307    void onBinaryMessage(WebSocket websocket, byte[] binary) throws Exception;
308
309
310    /**
311     * Called before a WebSocket frame is sent.
312     *
313     * @param websocket
314     *         The WebSocket.
315     *
316     * @param frame
317     *         The WebSocket frame to be sent.
318     *
319     * @throws Exception
320     *         An exception thrown by an implementation of this method.
321     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
322     *
323     * @since 1.15
324     */
325    void onSendingFrame(WebSocket websocket, WebSocketFrame frame) throws Exception;
326
327
328    /**
329     * Called when a WebSocket frame was sent to the server
330     * (but not flushed yet).
331     *
332     * @param websocket
333     *         The WebSocket.
334     *
335     * @param frame
336     *         The sent frame.
337     *
338     * @throws Exception
339     *         An exception thrown by an implementation of this method.
340     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
341     */
342    void onFrameSent(WebSocket websocket, WebSocketFrame frame) throws Exception;
343
344
345    /**
346     * Called when a WebSocket frame was not sent to the server
347     * because a <a href="https://tools.ietf.org/html/rfc6455#section-5.5.1"
348     * >close frame</a> has already been sent.
349     *
350     * <p>
351     * Note that {@code onFrameUnsent} is not called when {@link
352     * #onSendError(WebSocket, WebSocketException, WebSocketFrame)
353     * onSendError} is called.
354     * </p>
355     *
356     * @param websocket
357     *         The WebSocket.
358     *
359     * @param frame
360     *         The unsent frame.
361     *
362     * @throws Exception
363     *         An exception thrown by an implementation of this method.
364     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
365     */
366    void onFrameUnsent(WebSocket websocket, WebSocketFrame frame) throws Exception;
367
368
369    /**
370     * Called between after a thread is created and before the thread's
371     * {@code start()} method is called.
372     *
373     * @param websocket
374     *         The WebSocket.
375     *
376     * @param threadType
377     *         The thread type.
378     *
379     * @param thread
380     *         The newly created thread instance.
381     *
382     * @throws Exception
383     *         An exception thrown by an implementation of this method.
384     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
385     *
386     * @since 2.0
387     */
388    void onThreadCreated(WebSocket websocket, ThreadType threadType, Thread thread) throws Exception;
389
390
391    /**
392     * Called at the very beginning of the thread's {@code run()} method implementation.
393     *
394     * @param websocket
395     *         The WebSocket.
396     *
397     * @param threadType
398     *         The thread type.
399     *
400     * @param thread
401     *         The thread instance.
402     *
403     * @throws Exception
404     *         An exception thrown by an implementation of this method.
405     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
406     *
407     * @since 2.0
408     */
409    void onThreadStarted(WebSocket websocket, ThreadType threadType, Thread thread) throws Exception;
410
411
412    /**
413     * Called at the very end of the thread's {@code run()} method implementation.
414     *
415     * @param websocket
416     *         The WebSocket.
417     *
418     * @param threadType
419     *         The thread type.
420     *
421     * @param thread
422     *         The thread instance.
423     *
424     * @throws Exception
425     *         An exception thrown by an implementation of this method.
426     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
427     *
428     * @since 2.0
429     */
430    void onThreadStopping(WebSocket websocket, ThreadType threadType, Thread thread) throws Exception;
431
432
433    /**
434     * Call when an error occurred. This method is called before
435     * an <code>on<i>Xxx</i>Error</code> method is called.
436     *
437     * @param websocket
438     *         The WebSocket.
439     *
440     * @param cause
441     *         An exception that represents the error.
442     *
443     * @throws Exception
444     *         An exception thrown by an implementation of this method.
445     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
446     */
447    void onError(WebSocket websocket, WebSocketException cause) throws Exception;
448
449
450    /**
451     * Called when a WebSocket frame failed to be read from the WebSocket.
452     *
453     * <p>
454     * Some WebSocket server implementations close a WebSocket connection without sending
455     * a <a href="https://tools.ietf.org/html/rfc6455#section-5.5.1">close frame</a> to a
456     * client in some cases. Strictly speaking, this behavior is a violation against the
457     * specification (<a href="https://tools.ietf.org/html/rfc6455">RFC 6455</a>). However,
458     * this library has allowed the behavior by default since the version 1.29. Even if
459     * the end of the input stream of a WebSocket connection were reached without a
460     * close frame being received, it would trigger neither {@link #onError(WebSocket,
461     * WebSocketException) onError()} method nor {@link #onFrameError(WebSocket,
462     * WebSocketException, WebSocketFrame) onFrameError()} method. If you want to make
463     * this library report an error in the case, pass {@code false} to {@link
464     * WebSocket#setMissingCloseFrameAllowed(boolean)} method.
465     * </p>
466     *
467     * @param websocket
468     *         The WebSocket.
469     *
470     * @param cause
471     *         An exception that represents the error. When the error occurred
472     *         because of {@link java.io.InterruptedIOException InterruptedIOException},
473     *         {@code exception.getError()} returns {@link WebSocketError#INTERRUPTED_IN_READING}.
474     *         For other IO errors, {@code exception.getError()} returns {@link
475     *         WebSocketError#IO_ERROR_IN_READING}. Other error codes denote
476     *         protocol errors, which imply that some bugs may exist in either
477     *         or both of the client-side and the server-side implementations.
478     *
479     * @param frame
480     *         The WebSocket frame. If this is not {@code null}, it means that
481     *         verification of the frame failed.
482     *
483     * @throws Exception
484     *         An exception thrown by an implementation of this method.
485     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
486     */
487    void onFrameError(WebSocket websocket, WebSocketException cause, WebSocketFrame frame) throws Exception;
488
489
490    /**
491     * Called when it failed to concatenate payloads of multiple frames
492     * to construct a message. The reason of the failure is probably
493     * out-of-memory.
494     *
495     * @param websocket
496     *         The WebSocket.
497     *
498     * @param cause
499     *         An exception that represents the error.
500     *
501     * @param frames
502     *         The list of frames that form a message. The first element
503     *         is either a text frame and a binary frame, and the other
504     *         frames are continuation frames.
505     *
506     * @throws Exception
507     *         An exception thrown by an implementation of this method.
508     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
509     */
510    void onMessageError(WebSocket websocket, WebSocketException cause, List<WebSocketFrame> frames) throws Exception;
511
512
513    /**
514     * Called when a message failed to be decompressed.
515     *
516     * @param websocket
517     *         The WebSocket.
518     *
519     * @param cause
520     *         An exception that represents the error.
521     *
522     * @param compressed
523     *         The compressed message that failed to be decompressed.
524     *
525     * @throws Exception
526     *         An exception thrown by an implementation of this method.
527     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
528     *
529     * @since 1.16
530     */
531    void onMessageDecompressionError(WebSocket websocket, WebSocketException cause, byte[] compressed) throws Exception;
532
533
534    /**
535     * Called when it failed to convert payload data into a string.
536     * The reason of the failure is probably out-of-memory.
537     *
538     * @param websocket
539     *         The WebSocket.
540     *
541     * @param cause
542     *         An exception that represents the error.
543     *
544     * @param data
545     *         The payload data that failed to be converted to a string.
546     *
547     * @throws Exception
548     *         An exception thrown by an implementation of this method.
549     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
550     */
551    void onTextMessageError(WebSocket websocket, WebSocketException cause, byte[] data) throws Exception;
552
553
554    /**
555     * Called when an error occurred when a frame was tried to be sent
556     * to the server.
557     *
558     * @param websocket
559     *         The WebSocket.
560     *
561     * @param cause
562     *         An exception that represents the error.
563     *
564     * @param frame
565     *         The frame which was tried to be sent. This is {@code null}
566     *         when the error code of the exception is {@link
567     *         WebSocketError#FLUSH_ERROR FLUSH_ERROR}.
568     *
569     * @throws Exception
570     *         An exception thrown by an implementation of this method.
571     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
572     */
573    void onSendError(WebSocket websocket, WebSocketException cause, WebSocketFrame frame) throws Exception;
574
575
576    /**
577     * Called when an uncaught throwable was detected in either the
578     * reading thread (which reads frames from the server) or the
579     * writing thread (which sends frames to the server).
580     *
581     * @param websocket
582     *         The WebSocket.
583     *
584     * @param cause
585     *         The cause of the error.
586     *
587     * @throws Exception
588     *         An exception thrown by an implementation of this method.
589     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
590     */
591    void onUnexpectedError(WebSocket websocket, WebSocketException cause) throws Exception;
592
593
594    /**
595     * Called when an <code>on<i>Xxx</i>()</code> method threw a {@code Throwable}.
596     *
597     * @param websocket
598     *         The WebSocket.
599     *
600     * @param cause
601     *         The {@code Throwable} an <code>on<i>Xxx</i></code> method threw.
602     *
603     * @throws Exception
604     *         An exception thrown by an implementation of this method.
605     *         The exception is just ignored.
606     *
607     * @since 1.9
608     */
609    void handleCallbackError(WebSocket websocket, Throwable cause) throws Exception;
610
611
612    /**
613     * Called before an opening handshake is sent to the server.
614     *
615     * @param websocket
616     *         The WebSocket.
617     *
618     * @param requestLine
619     *         The request line. For example, {@code "GET /chat HTTP/1.1"}.
620     *
621     * @param headers
622     *         The HTTP headers.
623     *
624     * @throws Exception
625     *         An exception thrown by an implementation of this method.
626     *         The exception is passed to {@link #handleCallbackError(WebSocket, Throwable)}.
627     *
628     * @since 1.21
629     */
630    void onSendingHandshake(WebSocket websocket, String requestLine, List<String[]> headers) throws Exception;
631}