Source:
private boolean upgrade(final ChannelHandlerContext ctx, final FullHttpRequest request) { final List<CharSequence> requestedProtocols = splitHeader(request.headers().get(HttpHeaderNames.UPGRADE)); final int numRequestedProtocols = requestedProtocols.size(); UpgradeCodec upgradeCodec = null; CharSequence upgradeProtocol = null; for (int i = 0; i < numRequestedProtocols; i ++) { final CharSequence p = requestedProtocols.get(i); final UpgradeCodec c = upgradeCodecFactory.newUpgradeCodec(p); if (c != null) { upgradeProtocol = p; upgradeCodec = c; break; } } if (upgradeCodec == null) { return false; } List<String> connectionHeaderValues = request.headers().getAll(HttpHeaderNames.CONNECTION); if (connectionHeaderValues == null) { return false; } CharSequence connectionHeader = null; for (CharSequence connectionHeaderValue : connectionHeaderValues) { if (containsIgnoreCase(connectionHeaderValue, HttpHeaderNames.UPGRADE)) { connectionHeader = connectionHeaderValue; break; } } if (connectionHeader == null) { return false; } Collection<CharSequence> requiredHeaders = upgradeCodec.requiredUpgradeHeaders(); List<CharSequence> values = splitHeader(connectionHeader); if (!containsContentEqualsIgnoreCase(values, HttpHeaderNames.UPGRADE) || !containsAllContentEqualsIgnoreCase(values, requiredHeaders)) { return false; } for (CharSequence requiredHeader : requiredHeaders) { if (!request.headers().contains(requiredHeader)) { return false; } } final FullHttpResponse upgradeResponse = createUpgradeResponse(upgradeProtocol); if (!upgradeCodec.prepareUpgradeResponse(ctx, request, upgradeResponse.headers())) { return false; } final UpgradeEvent event = new UpgradeEvent(upgradeProtocol, request); try { final ChannelFuture writeComplete = ctx.writeAndFlush(upgradeResponse); sourceCodec.upgradeFrom(ctx); upgradeCodec.upgradeTo(ctx, request); ctx.pipeline().remove(HttpServerUpgradeHandler.this); ctx.fireUserEventTriggered(event.retain()); writeComplete.addListener(ChannelFutureListener.CLOSE_ON_FAILURE); } finally { event.release(); } return true; }

Target:
private boolean upgrade(final ChannelHandlerContext ctx, final FullHttpRequest request) { final List<CharSequence> requestedProtocols = splitHeader(request.headers().get(HttpHeaderNames.UPGRADE)); final int numRequestedProtocols = requestedProtocols.size(); UpgradeCodec upgradeCodec = null; CharSequence upgradeProtocol = null; for (int i = 0; i < numRequestedProtocols; i ++) { final CharSequence p = requestedProtocols.get(i); final UpgradeCodec c = upgradeCodecFactory.newUpgradeCodec(p); if (c != null) { upgradeProtocol = p; upgradeCodec = c; break; } } if (upgradeCodec == null) { return false; } List<String> connectionHeaderValues = request.headers().getAll(HttpHeaderNames.CONNECTION); if (connectionHeaderValues == null) { return false; } final StringBuilder concatenatedConnectionValue = new StringBuilder(connectionHeaderValues.size() * 10); for (CharSequence connectionHeaderValue : connectionHeaderValues) { concatenatedConnectionValue.append(connectionHeaderValue).append(COMMA); } concatenatedConnectionValue.setLength(concatenatedConnectionValue.length() - 1); Collection<CharSequence> requiredHeaders = upgradeCodec.requiredUpgradeHeaders(); List<CharSequence> values = splitHeader(concatenatedConnectionValue); if (!containsContentEqualsIgnoreCase(values, HttpHeaderNames.UPGRADE) || !containsAllContentEqualsIgnoreCase(values, requiredHeaders)) { return false; } for (CharSequence requiredHeader : requiredHeaders) { if (!request.headers().contains(requiredHeader)) { return false; } } final FullHttpResponse upgradeResponse = createUpgradeResponse(upgradeProtocol); if (!upgradeCodec.prepareUpgradeResponse(ctx, request, upgradeResponse.headers())) { return false; } final UpgradeEvent event = new UpgradeEvent(upgradeProtocol, request); try { final ChannelFuture writeComplete = ctx.writeAndFlush(upgradeResponse); sourceCodec.upgradeFrom(ctx); upgradeCodec.upgradeTo(ctx, request); ctx.pipeline().remove(HttpServerUpgradeHandler.this); ctx.fireUserEventTriggered(event.retain()); writeComplete.addListener(ChannelFutureListener.CLOSE_ON_FAILURE); } finally { event.release(); } return true; }