@@ -52,6 +52,7 @@ public class NettyWebSocket implements WebSocket {
52
52
// no need for volatile because only mutated in IO thread
53
53
private boolean ready ;
54
54
private List <WebSocketFrame > bufferedFrames ;
55
+ protected FragmentedFrameType expectedFragmentedFrameType ;
55
56
56
57
public NettyWebSocket (Channel channel , HttpHeaders upgradeHeaders ) {
57
58
this (channel , upgradeHeaders , new ConcurrentLinkedQueue <>());
@@ -238,6 +239,9 @@ public void handleFrame(WebSocketFrame frame) {
238
239
239
240
} else if (frame instanceof PongWebSocketFrame ) {
240
241
onPongFrame ((PongWebSocketFrame ) frame );
242
+
243
+ } else if (frame instanceof ContinuationWebSocketFrame ) {
244
+ onContinuationFrame ((ContinuationWebSocketFrame ) frame );
241
245
}
242
246
}
243
247
@@ -276,13 +280,27 @@ public String toString() {
276
280
}
277
281
278
282
public void onBinaryFrame (BinaryWebSocketFrame frame ) {
283
+ if (expectedFragmentedFrameType == null && !frame .isFinalFragment ()) {
284
+ expectedFragmentedFrameType = FragmentedFrameType .BINARY ;
285
+ }
286
+ onBinaryFrame0 (frame );
287
+ }
288
+
289
+ private void onBinaryFrame0 (WebSocketFrame frame ) {
279
290
byte [] bytes = byteBuf2Bytes (frame .content ());
280
291
for (WebSocketListener listener : listeners ) {
281
292
listener .onBinaryFrame (bytes , frame .isFinalFragment (), frame .rsv ());
282
293
}
283
294
}
284
295
285
296
public void onTextFrame (TextWebSocketFrame frame ) {
297
+ if (expectedFragmentedFrameType == null && !frame .isFinalFragment ()) {
298
+ expectedFragmentedFrameType = FragmentedFrameType .TEXT ;
299
+ }
300
+ onTextFrame0 (frame );
301
+ }
302
+
303
+ private void onTextFrame0 (WebSocketFrame frame ) {
286
304
try {
287
305
// faster than frame.text();
288
306
String text = Utf8ByteBufCharsetDecoder .decodeUtf8 (frame .content ());
@@ -296,6 +314,29 @@ public void onTextFrame(TextWebSocketFrame frame) {
296
314
}
297
315
}
298
316
317
+ public void onContinuationFrame (ContinuationWebSocketFrame frame ) {
318
+ if (expectedFragmentedFrameType == null ) {
319
+ LOGGER .warn ("Received continuation frame without an original text or binary frame, ignoring" );
320
+ return ;
321
+ }
322
+ try {
323
+ switch (expectedFragmentedFrameType ) {
324
+ case BINARY :
325
+ onBinaryFrame0 (frame );
326
+ break ;
327
+ case TEXT :
328
+ onTextFrame0 (frame );
329
+ break ;
330
+ default :
331
+ throw new IllegalArgumentException ("Unknown FragmentedFrameType " + expectedFragmentedFrameType );
332
+ }
333
+ } finally {
334
+ if (frame .isFinalFragment ()) {
335
+ expectedFragmentedFrameType = null ;
336
+ }
337
+ }
338
+ }
339
+
299
340
public void onPingFrame (PingWebSocketFrame frame ) {
300
341
byte [] bytes = byteBuf2Bytes (frame .content ());
301
342
for (WebSocketListener listener : listeners ) {
@@ -309,4 +350,8 @@ public void onPongFrame(PongWebSocketFrame frame) {
309
350
listener .onPongFrame (bytes );
310
351
}
311
352
}
353
+
354
+ private enum FragmentedFrameType {
355
+ TEXT , BINARY ;
356
+ }
312
357
}
0 commit comments