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 static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*;
19 import static org.jboss.netty.handler.codec.http.HttpHeaders.Values.*;
20 import static org.jboss.netty.handler.codec.http.HttpVersion.*;
21
22 import org.jboss.netty.buffer.ChannelBuffer;
23 import org.jboss.netty.buffer.ChannelBuffers;
24 import org.jboss.netty.channel.Channel;
25 import org.jboss.netty.channel.ChannelFuture;
26 import org.jboss.netty.channel.ChannelPipeline;
27 import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
28 import org.jboss.netty.handler.codec.http.HttpChunkAggregator;
29 import org.jboss.netty.handler.codec.http.HttpHeaders.Names;
30 import org.jboss.netty.handler.codec.http.HttpHeaders.Values;
31 import org.jboss.netty.handler.codec.http.HttpRequest;
32 import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
33 import org.jboss.netty.handler.codec.http.HttpResponse;
34 import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
35 import org.jboss.netty.handler.codec.http.HttpResponseStatus;
36 import org.jboss.netty.logging.InternalLogger;
37 import org.jboss.netty.logging.InternalLoggerFactory;
38
39
40
41
42
43
44
45
46
47
48
49 public class WebSocketServerHandshaker00 extends WebSocketServerHandshaker {
50
51 private static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketServerHandshaker00.class);
52
53
54
55
56
57
58
59
60
61
62 public WebSocketServerHandshaker00(String webSocketURL, String subprotocols) {
63 this(webSocketURL, subprotocols, Long.MAX_VALUE);
64 }
65
66
67
68
69
70
71
72
73
74
75
76
77
78 public WebSocketServerHandshaker00(String webSocketURL, String subprotocols, long maxFramePayloadLength) {
79 super(WebSocketVersion.V00, webSocketURL, subprotocols, maxFramePayloadLength);
80 }
81
82
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
125
126
127 @Override
128 public ChannelFuture handshake(Channel channel, HttpRequest req) {
129
130 if (logger.isDebugEnabled()) {
131 logger.debug(String.format("Channel %s WS Version 00 server handshake", channel.getId()));
132 }
133
134
135 if (!Values.UPGRADE.equalsIgnoreCase(req.getHeader(CONNECTION))
136 || !WEBSOCKET.equalsIgnoreCase(req.getHeader(Names.UPGRADE))) {
137 throw new WebSocketHandshakeException("not a WebSocket handshake request: missing upgrade");
138 }
139
140
141 boolean isHixie76 = req.containsHeader(SEC_WEBSOCKET_KEY1) && req.containsHeader(SEC_WEBSOCKET_KEY2);
142
143
144 HttpResponse res = new DefaultHttpResponse(HTTP_1_1, new HttpResponseStatus(101,
145 isHixie76 ? "WebSocket Protocol Handshake" : "Web Socket Protocol Handshake"));
146 res.addHeader(Names.UPGRADE, WEBSOCKET);
147 res.addHeader(CONNECTION, Values.UPGRADE);
148
149
150 if (isHixie76) {
151
152 res.addHeader(SEC_WEBSOCKET_ORIGIN, req.getHeader(ORIGIN));
153 res.addHeader(SEC_WEBSOCKET_LOCATION, getWebSocketUrl());
154 String subprotocols = req.getHeader(Names.SEC_WEBSOCKET_PROTOCOL);
155 if (subprotocols != null) {
156 String selectedSubprotocol = selectSubprotocol(subprotocols);
157 if (selectedSubprotocol == null) {
158 throw new WebSocketHandshakeException("Requested subprotocol(s) not supported: " + subprotocols);
159 } else {
160 res.addHeader(Names.SEC_WEBSOCKET_PROTOCOL, selectedSubprotocol);
161 setSelectedSubprotocol(selectedSubprotocol);
162 }
163 }
164
165
166 String key1 = req.getHeader(SEC_WEBSOCKET_KEY1);
167 String key2 = req.getHeader(SEC_WEBSOCKET_KEY2);
168 int a = (int) (Long.parseLong(key1.replaceAll("[^0-9]", "")) / key1.replaceAll("[^ ]", "").length());
169 int b = (int) (Long.parseLong(key2.replaceAll("[^0-9]", "")) / key2.replaceAll("[^ ]", "").length());
170 long c = req.getContent().readLong();
171 ChannelBuffer input = ChannelBuffers.buffer(16);
172 input.writeInt(a);
173 input.writeInt(b);
174 input.writeLong(c);
175 ChannelBuffer output = ChannelBuffers.wrappedBuffer(WebSocketUtil.md5(input.array()));
176 res.setContent(output);
177 } else {
178
179 res.addHeader(WEBSOCKET_ORIGIN, req.getHeader(ORIGIN));
180 res.addHeader(WEBSOCKET_LOCATION, getWebSocketUrl());
181 String protocol = req.getHeader(WEBSOCKET_PROTOCOL);
182 if (protocol != null) {
183 res.addHeader(WEBSOCKET_PROTOCOL, selectSubprotocol(protocol));
184 }
185 }
186
187
188 ChannelPipeline p = channel.getPipeline();
189 if (p.get(HttpChunkAggregator.class) != null) {
190 p.remove(HttpChunkAggregator.class);
191 }
192 p.replace(HttpRequestDecoder.class, "wsdecoder",
193 new WebSocket00FrameDecoder(getMaxFramePayloadLength()));
194
195 ChannelFuture future = channel.write(res);
196
197 p.replace(HttpResponseEncoder.class, "wsencoder", new WebSocket00FrameEncoder());
198
199 return future;
200 }
201
202
203
204
205
206
207
208
209
210 @Override
211 public ChannelFuture close(Channel channel, CloseWebSocketFrame frame) {
212 return channel.write(frame);
213 }
214 }