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 public class WebSocketServerHandshaker08 extends WebSocketServerHandshaker {
43
44 private static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketServerHandshaker08.class);
45
46 public static final String WEBSOCKET_08_ACCEPT_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
47
48 private final boolean allowExtensions;
49
50
51
52
53
54
55
56
57
58
59
60
61 public WebSocketServerHandshaker08(String webSocketURL, String subprotocols, boolean allowExtensions) {
62 this(webSocketURL, subprotocols, allowExtensions, Long.MAX_VALUE);
63 }
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79 public WebSocketServerHandshaker08(String webSocketURL, String subprotocols, boolean allowExtensions,
80 long maxFramePayloadLength) {
81 super(WebSocketVersion.V08, webSocketURL, subprotocols, maxFramePayloadLength);
82 this.allowExtensions = allowExtensions;
83 }
84
85
86
87
88
89
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 @Override
125 public ChannelFuture handshake(Channel channel, HttpRequest req) {
126
127 if (logger.isDebugEnabled()) {
128 logger.debug(String.format("Channel %s WS Version 8 server handshake", channel.getId()));
129 }
130
131 HttpResponse res = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.SWITCHING_PROTOCOLS);
132
133 String key = req.headers().get(Names.SEC_WEBSOCKET_KEY);
134 if (key == null) {
135 throw new WebSocketHandshakeException("not a WebSocket request: missing key");
136 }
137 String acceptSeed = key + WEBSOCKET_08_ACCEPT_GUID;
138 ChannelBuffer sha1 = WebSocketUtil.sha1(ChannelBuffers.copiedBuffer(acceptSeed, CharsetUtil.US_ASCII));
139
140 String accept = WebSocketUtil.base64(sha1);
141
142 if (logger.isDebugEnabled()) {
143 logger.debug(String.format("WS Version 8 Server Handshake key: %s. Response: %s.", key, accept));
144 }
145
146 res.setStatus(HttpResponseStatus.SWITCHING_PROTOCOLS);
147 res.headers().add(Names.UPGRADE, WEBSOCKET.toLowerCase());
148 res.headers().add(Names.CONNECTION, Names.UPGRADE);
149 res.headers().add(Names.SEC_WEBSOCKET_ACCEPT, accept);
150 String subprotocols = req.headers().get(Names.SEC_WEBSOCKET_PROTOCOL);
151 if (subprotocols != null) {
152 String selectedSubprotocol = selectSubprotocol(subprotocols);
153 if (selectedSubprotocol == null) {
154 throw new WebSocketHandshakeException("Requested subprotocol(s) not supported: " + subprotocols);
155 } else {
156 res.headers().add(Names.SEC_WEBSOCKET_PROTOCOL, selectedSubprotocol);
157 setSelectedSubprotocol(selectedSubprotocol);
158 }
159 }
160
161 return writeHandshakeResponse(
162 channel, res, new WebSocket08FrameEncoder(false),
163 new WebSocket08FrameDecoder(true, allowExtensions, getMaxFramePayloadLength()));
164 }
165
166
167
168
169
170
171
172
173
174 @Override
175 public ChannelFuture close(Channel channel, CloseWebSocketFrame frame) {
176 ChannelFuture f = channel.write(frame);
177 f.addListener(ChannelFutureListener.CLOSE);
178 return f;
179 }
180
181 }