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.handler.codec.http.DefaultFullHttpResponse;
19 import io.netty.handler.codec.http.FullHttpRequest;
20 import io.netty.handler.codec.http.FullHttpResponse;
21 import io.netty.handler.codec.http.HttpHeaderNames;
22 import io.netty.handler.codec.http.HttpHeaderValues;
23 import io.netty.handler.codec.http.HttpHeaders;
24 import io.netty.handler.codec.http.HttpMethod;
25 import io.netty.handler.codec.http.HttpResponseStatus;
26 import io.netty.util.CharsetUtil;
27
28 import static io.netty.handler.codec.http.HttpMethod.GET;
29 import static io.netty.handler.codec.http.HttpVersion.*;
30
31
32
33
34
35
36
37 public class WebSocketServerHandshaker13 extends WebSocketServerHandshaker {
38
39 public static final String WEBSOCKET_13_ACCEPT_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 public WebSocketServerHandshaker13(
56 String webSocketURL, String subprotocols, boolean allowExtensions, int maxFramePayloadLength) {
57 this(webSocketURL, subprotocols, allowExtensions, maxFramePayloadLength, false);
58 }
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77 public WebSocketServerHandshaker13(
78 String webSocketURL, String subprotocols, boolean allowExtensions, int maxFramePayloadLength,
79 boolean allowMaskMismatch) {
80 this(webSocketURL, subprotocols, WebSocketDecoderConfig.newBuilder()
81 .allowExtensions(allowExtensions)
82 .maxFramePayloadLength(maxFramePayloadLength)
83 .allowMaskMismatch(allowMaskMismatch)
84 .build());
85 }
86
87
88
89
90
91
92
93
94
95
96
97
98 public WebSocketServerHandshaker13(
99 String webSocketURL, String subprotocols, WebSocketDecoderConfig decoderConfig) {
100 super(WebSocketVersion.V13, webSocketURL, subprotocols, decoderConfig);
101 }
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137 @Override
138 protected FullHttpResponse newHandshakeResponse(FullHttpRequest req, HttpHeaders headers) {
139 HttpMethod method = req.method();
140 if (!GET.equals(method)) {
141 throw new WebSocketServerHandshakeException("Invalid WebSocket handshake method: " + method, req);
142 }
143
144 HttpHeaders reqHeaders = req.headers();
145 if (!reqHeaders.contains(HttpHeaderNames.CONNECTION) ||
146 !reqHeaders.containsValue(HttpHeaderNames.CONNECTION, HttpHeaderValues.UPGRADE, true)) {
147 throw new WebSocketServerHandshakeException(
148 "not a WebSocket request: a |Connection| header must includes a token 'Upgrade'", req);
149 }
150
151 if (!reqHeaders.contains(HttpHeaderNames.UPGRADE, HttpHeaderValues.WEBSOCKET, true)) {
152 throw new WebSocketServerHandshakeException(
153 "not a WebSocket request: a |Upgrade| header must containing the value 'websocket'", req);
154 }
155
156 CharSequence key = reqHeaders.get(HttpHeaderNames.SEC_WEBSOCKET_KEY);
157 if (key == null) {
158 throw new WebSocketServerHandshakeException("not a WebSocket request: missing key", req);
159 }
160
161 FullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.SWITCHING_PROTOCOLS,
162 req.content().alloc().buffer(0));
163 if (headers != null) {
164 res.headers().add(headers);
165 }
166
167 String acceptSeed = key + WEBSOCKET_13_ACCEPT_GUID;
168 byte[] sha1 = WebSocketUtil.sha1(acceptSeed.getBytes(CharsetUtil.US_ASCII));
169 String accept = WebSocketUtil.base64(sha1);
170
171 if (logger.isDebugEnabled()) {
172 logger.debug("WebSocket version 13 server handshake key: {}, response: {}", key, accept);
173 }
174
175 res.headers().set(HttpHeaderNames.UPGRADE, HttpHeaderValues.WEBSOCKET)
176 .set(HttpHeaderNames.CONNECTION, HttpHeaderValues.UPGRADE)
177 .set(HttpHeaderNames.SEC_WEBSOCKET_ACCEPT, accept);
178
179 String subprotocols = reqHeaders.get(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL);
180 if (subprotocols != null) {
181 String selectedSubprotocol = selectSubprotocol(subprotocols);
182 if (selectedSubprotocol == null) {
183 if (logger.isDebugEnabled()) {
184 logger.debug("Requested subprotocol(s) not supported: {}", subprotocols);
185 }
186 } else {
187 res.headers().set(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL, selectedSubprotocol);
188 }
189 }
190 return res;
191 }
192
193 @Override
194 protected WebSocketFrameDecoder newWebsocketDecoder() {
195 return new WebSocket13FrameDecoder(decoderConfig());
196 }
197
198 @Override
199 protected WebSocketFrameEncoder newWebSocketEncoder() {
200 return new WebSocket13FrameEncoder(false);
201 }
202 }