// Hixie 75 does not contain these headers while Hixie 76 does
boolean isHixie76 = req.headers().contains(SEC_WEBSOCKET_KEY1) && req.headers().contains(SEC_WEBSOCKET_KEY2);
// Create the WebSocket handshake response.
FullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, new HttpResponseStatus(101,
isHixie76 ? "WebSocket Protocol Handshake" : "Web Socket Protocol Handshake"));
if (headers != null) {
res.headers().add(headers);
}
res.headers().add(Names.UPGRADE, WEBSOCKET);
res.headers().add(CONNECTION, Values.UPGRADE);
// Fill in the headers and contents depending on handshake getMethod.
if (isHixie76) {
// New handshake getMethod with a challenge:
res.headers().add(SEC_WEBSOCKET_ORIGIN, req.headers().get(ORIGIN));
res.headers().add(SEC_WEBSOCKET_LOCATION, uri());
String subprotocols = req.headers().get(SEC_WEBSOCKET_PROTOCOL);
if (subprotocols != null) {
String selectedSubprotocol = selectSubprotocol(subprotocols);
if (selectedSubprotocol == null) {
if (logger.isDebugEnabled()) {
logger.debug("Requested subprotocol(s) not supported: {}", subprotocols);
}
} else {
res.headers().add(SEC_WEBSOCKET_PROTOCOL, selectedSubprotocol);
}
}
// Calculate the answer of the challenge.
String key1 = req.headers().get(SEC_WEBSOCKET_KEY1);
String key2 = req.headers().get(SEC_WEBSOCKET_KEY2);
int a = (int) (Long.parseLong(BEGINNING_DIGIT.matcher(key1).replaceAll("")) /
BEGINNING_SPACE.matcher(key1).replaceAll("").length());
int b = (int) (Long.parseLong(BEGINNING_DIGIT.matcher(key2).replaceAll("")) /
BEGINNING_SPACE.matcher(key2).replaceAll("").length());
long c = req.content().readLong();
ByteBuf input = Unpooled.buffer(16);
input.writeInt(a);
input.writeInt(b);
input.writeLong(c);
res.content().writeBytes(WebSocketUtil.md5(input.array()));
} else {
// Old Hixie 75 handshake getMethod with no challenge:
res.headers().add(WEBSOCKET_ORIGIN, req.headers().get(ORIGIN));
res.headers().add(WEBSOCKET_LOCATION, uri());
String protocol = req.headers().get(WEBSOCKET_PROTOCOL);
if (protocol != null) {
res.headers().add(WEBSOCKET_PROTOCOL, selectSubprotocol(protocol));
}
}
return res;
}