Search in sources :

Example 1 with Transformation

use of org.apache.tomcat.websocket.Transformation in project tomcat by apache.

the class UpgradeUtil method doUpgrade.

public static void doUpgrade(WsServerContainer sc, HttpServletRequest req, HttpServletResponse resp, ServerEndpointConfig sec, Map<String, String> pathParams) throws ServletException, IOException {
    // Validate the rest of the headers and reject the request if that
    // validation fails
    String key;
    String subProtocol = null;
    if (!headerContainsToken(req, Constants.CONNECTION_HEADER_NAME, Constants.CONNECTION_HEADER_VALUE)) {
        resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
        return;
    }
    if (!headerContainsToken(req, Constants.WS_VERSION_HEADER_NAME, Constants.WS_VERSION_HEADER_VALUE)) {
        resp.setStatus(426);
        resp.setHeader(Constants.WS_VERSION_HEADER_NAME, Constants.WS_VERSION_HEADER_VALUE);
        return;
    }
    key = req.getHeader(Constants.WS_KEY_HEADER_NAME);
    if (key == null) {
        resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
        return;
    }
    // Origin check
    String origin = req.getHeader(Constants.ORIGIN_HEADER_NAME);
    if (!sec.getConfigurator().checkOrigin(origin)) {
        resp.sendError(HttpServletResponse.SC_FORBIDDEN);
        return;
    }
    // Sub-protocols
    List<String> subProtocols = getTokensFromHeader(req, Constants.WS_PROTOCOL_HEADER_NAME);
    subProtocol = sec.getConfigurator().getNegotiatedSubprotocol(sec.getSubprotocols(), subProtocols);
    // Extensions
    // Should normally only be one header but handle the case of multiple
    // headers
    List<Extension> extensionsRequested = new ArrayList<>();
    Enumeration<String> extHeaders = req.getHeaders(Constants.WS_EXTENSIONS_HEADER_NAME);
    while (extHeaders.hasMoreElements()) {
        Util.parseExtensionHeader(extensionsRequested, extHeaders.nextElement());
    }
    // Negotiation phase 1. By default this simply filters out the
    // extensions that the server does not support but applications could
    // use a custom configurator to do more than this.
    List<Extension> installedExtensions = null;
    if (sec.getExtensions().size() == 0) {
        installedExtensions = Constants.INSTALLED_EXTENSIONS;
    } else {
        installedExtensions = new ArrayList<>();
        installedExtensions.addAll(sec.getExtensions());
        installedExtensions.addAll(Constants.INSTALLED_EXTENSIONS);
    }
    List<Extension> negotiatedExtensionsPhase1 = sec.getConfigurator().getNegotiatedExtensions(installedExtensions, extensionsRequested);
    // Negotiation phase 2. Create the Transformations that will be applied
    // to this connection. Note than an extension may be dropped at this
    // point if the client has requested a configuration that the server is
    // unable to support.
    List<Transformation> transformations = createTransformations(negotiatedExtensionsPhase1);
    List<Extension> negotiatedExtensionsPhase2;
    if (transformations.isEmpty()) {
        negotiatedExtensionsPhase2 = Collections.emptyList();
    } else {
        negotiatedExtensionsPhase2 = new ArrayList<>(transformations.size());
        for (Transformation t : transformations) {
            negotiatedExtensionsPhase2.add(t.getExtensionResponse());
        }
    }
    // Build the transformation pipeline
    Transformation transformation = null;
    StringBuilder responseHeaderExtensions = new StringBuilder();
    boolean first = true;
    for (Transformation t : transformations) {
        if (first) {
            first = false;
        } else {
            responseHeaderExtensions.append(',');
        }
        append(responseHeaderExtensions, t.getExtensionResponse());
        if (transformation == null) {
            transformation = t;
        } else {
            transformation.setNext(t);
        }
    }
    // Now we have the full pipeline, validate the use of the RSV bits.
    if (transformation != null && !transformation.validateRsvBits(0)) {
        throw new ServletException(sm.getString("upgradeUtil.incompatibleRsv"));
    }
    // If we got this far, all is good. Accept the connection.
    resp.setHeader(Constants.UPGRADE_HEADER_NAME, Constants.UPGRADE_HEADER_VALUE);
    resp.setHeader(Constants.CONNECTION_HEADER_NAME, Constants.CONNECTION_HEADER_VALUE);
    resp.setHeader(HandshakeResponse.SEC_WEBSOCKET_ACCEPT, getWebSocketAccept(key));
    if (subProtocol != null && subProtocol.length() > 0) {
        // RFC6455 4.2.2 explicitly states "" is not valid here
        resp.setHeader(Constants.WS_PROTOCOL_HEADER_NAME, subProtocol);
    }
    if (!transformations.isEmpty()) {
        resp.setHeader(Constants.WS_EXTENSIONS_HEADER_NAME, responseHeaderExtensions.toString());
    }
    WsHandshakeRequest wsRequest = new WsHandshakeRequest(req, pathParams);
    WsHandshakeResponse wsResponse = new WsHandshakeResponse();
    WsPerSessionServerEndpointConfig perSessionServerEndpointConfig = new WsPerSessionServerEndpointConfig(sec);
    sec.getConfigurator().modifyHandshake(perSessionServerEndpointConfig, wsRequest, wsResponse);
    wsRequest.finished();
    // Add any additional headers
    for (Entry<String, List<String>> entry : wsResponse.getHeaders().entrySet()) {
        for (String headerValue : entry.getValue()) {
            resp.addHeader(entry.getKey(), headerValue);
        }
    }
    Endpoint ep;
    try {
        Class<?> clazz = sec.getEndpointClass();
        if (Endpoint.class.isAssignableFrom(clazz)) {
            ep = (Endpoint) sec.getConfigurator().getEndpointInstance(clazz);
        } else {
            ep = new PojoEndpointServer();
            // Need to make path params available to POJO
            perSessionServerEndpointConfig.getUserProperties().put(org.apache.tomcat.websocket.pojo.Constants.POJO_PATH_PARAM_KEY, pathParams);
        }
    } catch (InstantiationException e) {
        throw new ServletException(e);
    }
    WsHttpUpgradeHandler wsHandler = req.upgrade(WsHttpUpgradeHandler.class);
    wsHandler.preInit(ep, perSessionServerEndpointConfig, sc, wsRequest, negotiatedExtensionsPhase2, subProtocol, transformation, pathParams, req.isSecure());
}
Also used : Transformation(org.apache.tomcat.websocket.Transformation) WsHandshakeResponse(org.apache.tomcat.websocket.WsHandshakeResponse) ArrayList(java.util.ArrayList) PojoEndpointServer(org.apache.tomcat.websocket.pojo.PojoEndpointServer) Extension(javax.websocket.Extension) ServletException(javax.servlet.ServletException) Endpoint(javax.websocket.Endpoint) ArrayList(java.util.ArrayList) List(java.util.List)

Example 2 with Transformation

use of org.apache.tomcat.websocket.Transformation in project tomcat by apache.

the class UpgradeUtil method createTransformations.

private static List<Transformation> createTransformations(List<Extension> negotiatedExtensions) {
    TransformationFactory factory = TransformationFactory.getInstance();
    LinkedHashMap<String, List<List<Extension.Parameter>>> extensionPreferences = new LinkedHashMap<>();
    // Result will likely be smaller than this
    List<Transformation> result = new ArrayList<>(negotiatedExtensions.size());
    for (Extension extension : negotiatedExtensions) {
        List<List<Extension.Parameter>> preferences = extensionPreferences.get(extension.getName());
        if (preferences == null) {
            preferences = new ArrayList<>();
            extensionPreferences.put(extension.getName(), preferences);
        }
        preferences.add(extension.getParameters());
    }
    for (Map.Entry<String, List<List<Extension.Parameter>>> entry : extensionPreferences.entrySet()) {
        Transformation transformation = factory.create(entry.getKey(), entry.getValue(), true);
        if (transformation != null) {
            result.add(transformation);
        }
    }
    return result;
}
Also used : Transformation(org.apache.tomcat.websocket.Transformation) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) Extension(javax.websocket.Extension) ArrayList(java.util.ArrayList) List(java.util.List) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) TransformationFactory(org.apache.tomcat.websocket.TransformationFactory)

Aggregations

ArrayList (java.util.ArrayList)2 List (java.util.List)2 Extension (javax.websocket.Extension)2 Transformation (org.apache.tomcat.websocket.Transformation)2 LinkedHashMap (java.util.LinkedHashMap)1 Map (java.util.Map)1 ServletException (javax.servlet.ServletException)1 Endpoint (javax.websocket.Endpoint)1 TransformationFactory (org.apache.tomcat.websocket.TransformationFactory)1 WsHandshakeResponse (org.apache.tomcat.websocket.WsHandshakeResponse)1 PojoEndpointServer (org.apache.tomcat.websocket.pojo.PojoEndpointServer)1