1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty5.handler.codec.http.websocketx;
17
18 import io.netty5.buffer.api.Buffer;
19 import io.netty5.channel.ChannelFutureListeners;
20 import io.netty5.channel.ChannelHandler;
21 import io.netty5.channel.ChannelHandlerContext;
22
23
24
25
26 public class Utf8FrameValidator implements ChannelHandler {
27
28 private final boolean closeOnProtocolViolation;
29
30 private int fragmentedFramesCount;
31 private Utf8Validator utf8Validator;
32
33 public Utf8FrameValidator() {
34 this(true);
35 }
36
37 public Utf8FrameValidator(boolean closeOnProtocolViolation) {
38 this.closeOnProtocolViolation = closeOnProtocolViolation;
39 }
40
41 @Override
42 public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
43 if (msg instanceof WebSocketFrame) {
44 WebSocketFrame frame = (WebSocketFrame) msg;
45
46 try {
47
48
49 if (((WebSocketFrame) msg).isFinalFragment()) {
50
51
52 if (!(frame instanceof PingWebSocketFrame)) {
53 fragmentedFramesCount = 0;
54
55
56 if ((frame instanceof TextWebSocketFrame) ||
57 (utf8Validator != null && utf8Validator.isChecking())) {
58
59 checkUTF8String(frame.binaryData());
60
61
62
63 utf8Validator.finish();
64 }
65 }
66 } else {
67
68
69 if (fragmentedFramesCount == 0) {
70
71 if (frame instanceof TextWebSocketFrame) {
72 checkUTF8String(frame.binaryData());
73 }
74 } else {
75
76 if (utf8Validator != null && utf8Validator.isChecking()) {
77 checkUTF8String(frame.binaryData());
78 }
79 }
80
81
82 fragmentedFramesCount++;
83 }
84 } catch (CorruptedWebSocketFrameException e) {
85 protocolViolation(ctx, frame, e);
86 }
87 }
88
89 ctx.fireChannelRead(msg);
90 }
91
92 private void checkUTF8String(Buffer buffer) {
93 if (utf8Validator == null) {
94 utf8Validator = new Utf8Validator();
95 }
96 utf8Validator.check(buffer);
97 }
98
99 private void protocolViolation(ChannelHandlerContext ctx, WebSocketFrame frame,
100 CorruptedWebSocketFrameException ex) {
101 frame.close();
102 if (closeOnProtocolViolation && ctx.channel().isOpen()) {
103 WebSocketCloseStatus closeStatus = ex.closeStatus();
104 String reasonText = ex.getMessage();
105 if (reasonText == null) {
106 reasonText = closeStatus.reasonText();
107 }
108
109 CloseWebSocketFrame closeFrame = new CloseWebSocketFrame(
110 ctx.bufferAllocator(), closeStatus.code(), reasonText);
111 ctx.writeAndFlush(closeFrame).addListener(ctx, ChannelFutureListeners.CLOSE);
112 }
113
114 throw ex;
115 }
116 }