1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.handler.codec.http.websocketx;
17
18 import org.jboss.netty.buffer.ChannelBuffer;
19 import org.jboss.netty.buffer.ChannelBuffers;
20 import org.jboss.netty.channel.Channel;
21 import org.jboss.netty.channel.ChannelFuture;
22 import org.jboss.netty.channel.ChannelFutureListener;
23 import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
24 import org.jboss.netty.handler.codec.http.HttpHeaders.Names;
25 import org.jboss.netty.handler.codec.http.HttpRequest;
26 import org.jboss.netty.handler.codec.http.HttpResponse;
27 import org.jboss.netty.handler.codec.http.HttpResponseStatus;
28 import org.jboss.netty.logging.InternalLogger;
29 import org.jboss.netty.logging.InternalLoggerFactory;
30 import org.jboss.netty.util.CharsetUtil;
31
32 import static org.jboss.netty.handler.codec.http.HttpHeaders.Values.*;
33 import static org.jboss.netty.handler.codec.http.HttpVersion.*;
34
35
36
37
38
39
40
41
42
43
44 public class WebSocketServerHandshaker13 extends WebSocketServerHandshaker {
45
46 private static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketServerHandshaker13.class);
47
48 public static final String WEBSOCKET_13_ACCEPT_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
49
50 private final boolean allowExtensions;
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 public WebSocketServerHandshaker13(String webSocketURL, String subprotocols, boolean allowExtensions) {
66 this(webSocketURL, subprotocols, allowExtensions, Long.MAX_VALUE);
67 }
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86 public WebSocketServerHandshaker13(String webSocketURL, String subprotocols, boolean allowExtensions,
87 long maxFramePayloadLength) {
88 super(WebSocketVersion.V13, webSocketURL, subprotocols, maxFramePayloadLength);
89 this.allowExtensions = allowExtensions;
90 }
91
92
93
94
95
96
97
98
99
100
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 @Override
132 public ChannelFuture handshake(Channel channel, HttpRequest req) {
133
134 if (logger.isDebugEnabled()) {
135 logger.debug(String.format("Channel %s WS Version 13 server handshake", channel.getId()));
136 }
137
138 HttpResponse res = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.SWITCHING_PROTOCOLS);
139
140 String key = req.headers().get(Names.SEC_WEBSOCKET_KEY);
141 if (key == null) {
142 throw new WebSocketHandshakeException("not a WebSocket request: missing key");
143 }
144 String acceptSeed = key + WEBSOCKET_13_ACCEPT_GUID;
145 ChannelBuffer sha1 = WebSocketUtil.sha1(ChannelBuffers.copiedBuffer(acceptSeed, CharsetUtil.US_ASCII));
146 String accept = WebSocketUtil.base64(sha1);
147
148 if (logger.isDebugEnabled()) {
149 logger.debug(String.format("WS Version 13 Server Handshake key: %s. Response: %s.", key, accept));
150 }
151
152 res.setStatus(HttpResponseStatus.SWITCHING_PROTOCOLS);
153 res.headers().add(Names.UPGRADE, WEBSOCKET.toLowerCase());
154 res.headers().add(Names.CONNECTION, Names.UPGRADE);
155 res.headers().add(Names.SEC_WEBSOCKET_ACCEPT, accept);
156 String subprotocols = req.headers().get(Names.SEC_WEBSOCKET_PROTOCOL);
157 if (subprotocols != null) {
158 String selectedSubprotocol = selectSubprotocol(subprotocols);
159 if (selectedSubprotocol == null) {
160 throw new WebSocketHandshakeException("Requested subprotocol(s) not supported: " + subprotocols);
161 } else {
162 res.headers().add(Names.SEC_WEBSOCKET_PROTOCOL, selectedSubprotocol);
163 setSelectedSubprotocol(selectedSubprotocol);
164 }
165 }
166
167 return writeHandshakeResponse(
168 channel, res, new WebSocket13FrameEncoder(false),
169 new WebSocket13FrameDecoder(true, allowExtensions, getMaxFramePayloadLength()));
170 }
171
172
173
174
175
176
177
178
179
180 @Override
181 public ChannelFuture close(Channel channel, CloseWebSocketFrame frame) {
182 ChannelFuture f = channel.write(frame);
183 f.addListener(ChannelFutureListener.CLOSE);
184 return f;
185 }
186
187 }