io.undertow.websockets.jsr.handshake.Handshake Maven / Gradle / Ivy
/*
* JBoss, Home of Professional Open Source.
* Copyright 2018 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.undertow.websockets.jsr.handshake;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.regex.Pattern;
import javax.websocket.Extension;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.http.HttpContentCompressor;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.websocketx.WebSocket13FrameDecoder;
import io.netty.handler.codec.http.websocketx.WebSocket13FrameEncoder;
import io.netty.handler.codec.http.websocketx.extensions.WebSocketExtensionData;
import io.netty.handler.codec.http.websocketx.extensions.WebSocketExtensionDecoder;
import io.netty.handler.codec.http.websocketx.extensions.WebSocketExtensionEncoder;
import io.netty.handler.codec.http.websocketx.extensions.WebSocketExtensionUtil;
import io.netty.handler.codec.http.websocketx.extensions.WebSocketServerExtension;
import io.netty.handler.codec.http.websocketx.extensions.WebSocketServerExtensionHandshaker;
import io.undertow.httpcore.HttpHeaderNames;
import io.undertow.websockets.jsr.ConfiguredServerEndpoint;
import io.undertow.websockets.jsr.ExtensionImpl;
/**
* Abstract base class for doing a WebSocket Handshake.
*
* @author Mike Brock
*/
public class Handshake {
private static final String EXTENSION_SEPARATOR = ",";
private static final String PARAMETER_SEPARATOR = ";";
private static final char PARAMETER_EQUAL = '=';
public static final String MAGIC_NUMBER = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
public static final String SHA1 = "SHA1";
private static final String WEB_SOCKET_VERSION = "13";
protected final Set subprotocols;
private static final byte[] EMPTY = new byte[0];
private static final Pattern PATTERN = Pattern.compile("\\s*,\\s*");
protected Set availableExtensions = new HashSet<>();
protected boolean allowExtensions;
private final ConfiguredServerEndpoint config;
private final int maxFrameSize;
public Handshake(ConfiguredServerEndpoint config, final Set subprotocols, int maxFrameSize) {
this.subprotocols = subprotocols;
this.config = config;
this.maxFrameSize = maxFrameSize;
}
public ConfiguredServerEndpoint getConfig() {
return config;
}
/**
* Return the full url of the websocket location of the given {@link WebSocketHttpExchange}
*/
protected static String getWebSocketLocation(WebSocketHttpExchange exchange) {
String scheme;
if ("https".equals(exchange.getRequestScheme())) {
scheme = "wss";
} else {
scheme = "ws";
}
return scheme + "://" + exchange.getRequestHeader(HttpHeaderNames.HOST) + exchange.getRequestURI();
}
/**
* Issue the WebSocket upgrade
*
* @param exchange The {@link WebSocketHttpExchange} for which the handshake and upgrade should occur.
*/
public final void handshake(final WebSocketHttpExchange exchange, Consumer completeListener) {
String origin = exchange.getRequestHeader(HttpHeaderNames.ORIGIN);
if (origin != null) {
exchange.setResponseHeader(HttpHeaderNames.ORIGIN, origin);
}
selectSubprotocol(exchange);
List extensions = selectExtensions(exchange);
exchange.setResponseHeader(HttpHeaderNames.SEC_WEB_SOCKET_LOCATION, getWebSocketLocation(exchange));
final String key = exchange.getRequestHeader(HttpHeaderNames.SEC_WEB_SOCKET_KEY);
try {
final String solution = solve(key);
exchange.setResponseHeader(HttpHeaderNames.SEC_WEB_SOCKET_ACCEPT, solution);
performUpgrade(exchange);
} catch (NoSuchAlgorithmException e) {
exchange.endExchange();
return;
}
handshakeInternal(exchange);
exchange.upgradeChannel(new Consumer
© 2015 - 2025 Weber Informatics LLC | Privacy Policy