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.buffer.api.BufferAllocator;
20 import io.netty5.util.CharsetUtil;
21 import io.netty5.util.internal.StringUtil;
22
23 import java.nio.charset.StandardCharsets;
24
25
26
27
28 public class CloseWebSocketFrame extends WebSocketFrame {
29
30
31
32
33
34
35
36 public CloseWebSocketFrame(BufferAllocator allocator, WebSocketCloseStatus status) {
37 this(allocator, requireValidStatusCode(status.code()), status.reasonText());
38 }
39
40
41
42
43
44
45
46
47
48
49 public CloseWebSocketFrame(BufferAllocator allocator, WebSocketCloseStatus status, String reasonText) {
50 this(allocator, requireValidStatusCode(status.code()), reasonText);
51 }
52
53
54
55
56
57
58
59
60
61
62 public CloseWebSocketFrame(BufferAllocator allocator, int statusCode, String reasonText) {
63 this(allocator, true, 0, requireValidStatusCode(statusCode), reasonText);
64 }
65
66
67
68
69
70
71
72
73 public CloseWebSocketFrame(BufferAllocator allocator, boolean finalFragment, int rsv) {
74 this(finalFragment, rsv, allocator.allocate(0));
75 }
76
77
78
79
80
81
82
83
84
85
86
87 public CloseWebSocketFrame(BufferAllocator allocator, boolean finalFragment, int rsv, int statusCode,
88 String reasonText) {
89 super(finalFragment, rsv, newBinaryData(allocator, requireValidStatusCode(statusCode), reasonText));
90 }
91
92 private static Buffer newBinaryData(BufferAllocator allocator, short statusCode, String reasonText) {
93 if (reasonText == null) {
94 reasonText = StringUtil.EMPTY_STRING;
95 }
96
97 final Buffer binaryData;
98 if (!reasonText.isEmpty()) {
99 byte[] reasonTextBytes = reasonText.getBytes(StandardCharsets.UTF_8);
100 binaryData = allocator.allocate(2 + reasonTextBytes.length);
101 binaryData.writeShort(statusCode);
102 binaryData.writeBytes(reasonTextBytes);
103 } else {
104 binaryData = allocator.allocate(2).writeShort(statusCode);
105 }
106
107 return binaryData;
108 }
109
110
111
112
113
114
115
116
117 public CloseWebSocketFrame(boolean finalFragment, int rsv, Buffer binaryData) {
118 super(finalFragment, rsv, binaryData);
119 }
120
121 private CloseWebSocketFrame(CloseWebSocketFrame copyFrom, Buffer data) {
122 super(copyFrom, data);
123 }
124
125
126
127
128
129 public int statusCode() {
130 Buffer binaryData = binaryData();
131 if (binaryData == null || binaryData.readableBytes() < 2) {
132 return -1;
133 }
134
135 return binaryData.getShort(binaryData.readerOffset());
136 }
137
138
139
140
141
142 public String reasonText() {
143 Buffer binaryData = binaryData();
144 if (binaryData == null || binaryData.readableBytes() <= 2) {
145 return "";
146 }
147
148 int base = binaryData.readerOffset();
149 try {
150 binaryData.skipReadableBytes(2);
151 return binaryData.toString(CharsetUtil.UTF_8);
152 } finally {
153 binaryData.readerOffset(base);
154 }
155 }
156
157 @Override
158 protected WebSocketFrame receive(Buffer buf) {
159 return new CloseWebSocketFrame(this, buf);
160 }
161
162 static short requireValidStatusCode(int statusCode) {
163 if (WebSocketCloseStatus.isValidStatusCode(statusCode)) {
164 return (short) statusCode;
165 } else {
166 throw new IllegalArgumentException(
167 "WebSocket close status code does NOT comply with RFC-6455: " + statusCode);
168 }
169 }
170 }