1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.codec.http.websocketx;
17
18 import io.netty.buffer.ByteBuf;
19 import io.netty.buffer.Unpooled;
20 import io.netty.util.CharsetUtil;
21 import io.netty.util.internal.StringUtil;
22
23
24
25
26 public class CloseWebSocketFrame extends WebSocketFrame {
27
28
29
30
31 public CloseWebSocketFrame() {
32 super(Unpooled.buffer(0));
33 }
34
35
36
37
38
39
40
41
42 public CloseWebSocketFrame(WebSocketCloseStatus status) {
43 this(requireValidStatusCode(status.code()), status.reasonText());
44 }
45
46
47
48
49
50
51
52
53
54
55 public CloseWebSocketFrame(WebSocketCloseStatus status, String reasonText) {
56 this(requireValidStatusCode(status.code()), reasonText);
57 }
58
59
60
61
62
63
64
65
66
67
68 public CloseWebSocketFrame(int statusCode, String reasonText) {
69 this(true, 0, requireValidStatusCode(statusCode), reasonText);
70 }
71
72
73
74
75
76
77
78
79
80 public CloseWebSocketFrame(boolean finalFragment, int rsv) {
81 this(finalFragment, rsv, Unpooled.buffer(0));
82 }
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97 public CloseWebSocketFrame(boolean finalFragment, int rsv, int statusCode, String reasonText) {
98 super(finalFragment, rsv, newBinaryData(requireValidStatusCode(statusCode), reasonText));
99 }
100
101 private static ByteBuf newBinaryData(int statusCode, String reasonText) {
102 if (reasonText == null) {
103 reasonText = StringUtil.EMPTY_STRING;
104 }
105
106 ByteBuf binaryData = Unpooled.buffer(2 + reasonText.length());
107 binaryData.writeShort(statusCode);
108 if (!reasonText.isEmpty()) {
109 binaryData.writeCharSequence(reasonText, CharsetUtil.UTF_8);
110 }
111 return binaryData;
112 }
113
114
115
116
117
118
119
120
121
122
123
124 public CloseWebSocketFrame(boolean finalFragment, int rsv, ByteBuf binaryData) {
125 super(finalFragment, rsv, binaryData);
126 }
127
128
129
130
131
132 public int statusCode() {
133 ByteBuf binaryData = content();
134 if (binaryData == null || binaryData.readableBytes() < 2) {
135 return -1;
136 }
137
138 return binaryData.getUnsignedShort(binaryData.readerIndex());
139 }
140
141
142
143
144
145 public String reasonText() {
146 ByteBuf binaryData = content();
147 if (binaryData == null || binaryData.readableBytes() <= 2) {
148 return "";
149 }
150
151 return binaryData.toString(binaryData.readerIndex() + 2, binaryData.readableBytes() - 2, CharsetUtil.UTF_8);
152 }
153
154 @Override
155 public CloseWebSocketFrame copy() {
156 return (CloseWebSocketFrame) super.copy();
157 }
158
159 @Override
160 public CloseWebSocketFrame duplicate() {
161 return (CloseWebSocketFrame) super.duplicate();
162 }
163
164 @Override
165 public CloseWebSocketFrame retainedDuplicate() {
166 return (CloseWebSocketFrame) super.retainedDuplicate();
167 }
168
169 @Override
170 public CloseWebSocketFrame replace(ByteBuf content) {
171 return new CloseWebSocketFrame(isFinalFragment(), rsv(), content);
172 }
173
174 @Override
175 public CloseWebSocketFrame retain() {
176 super.retain();
177 return this;
178 }
179
180 @Override
181 public CloseWebSocketFrame retain(int increment) {
182 super.retain(increment);
183 return this;
184 }
185
186 @Override
187 public CloseWebSocketFrame touch() {
188 super.touch();
189 return this;
190 }
191
192 @Override
193 public CloseWebSocketFrame touch(Object hint) {
194 super.touch(hint);
195 return this;
196 }
197
198 static int requireValidStatusCode(int statusCode) {
199 if (WebSocketCloseStatus.isValidStatusCode(statusCode)) {
200 return statusCode;
201 } else {
202 throw new IllegalArgumentException("WebSocket close status code does NOT comply with RFC-6455: " +
203 statusCode);
204 }
205 }
206 }