Search in sources :

Example 1 with AbstractWebSocketConnection

use of org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection in project jetty.project by eclipse.

the class WebSocketServerFactory method upgrade.

/**
     * Upgrade the request/response to a WebSocket Connection.
     * <p/>
     * This method will not normally return, but will instead throw a UpgradeConnectionException, to exit HTTP handling and initiate WebSocket handling of the
     * connection.
     *
     * @param http the raw http connection
     * @param request The request to upgrade
     * @param response The response to upgrade
     * @param driver The websocket handler implementation to use
     */
private boolean upgrade(HttpConnection http, ServletUpgradeRequest request, ServletUpgradeResponse response, EventDriver driver) throws IOException {
    if (!"websocket".equalsIgnoreCase(request.getHeader("Upgrade"))) {
        throw new IllegalStateException("Not a 'WebSocket: Upgrade' request");
    }
    if (!"HTTP/1.1".equals(request.getHttpVersion())) {
        throw new IllegalStateException("Not a 'HTTP/1.1' request");
    }
    int version = request.getHeaderInt("Sec-WebSocket-Version");
    if (version < 0) {
        // Old pre-RFC version specifications (header not present in RFC-6455)
        version = request.getHeaderInt("Sec-WebSocket-Draft");
    }
    WebSocketHandshake handshaker = handshakes.get(version);
    if (handshaker == null) {
        StringBuilder warn = new StringBuilder();
        warn.append("Client ").append(request.getRemoteAddress());
        warn.append(" (:").append(request.getRemotePort());
        warn.append(") User Agent: ");
        String ua = request.getHeader("User-Agent");
        if (ua == null) {
            warn.append("[unset] ");
        } else {
            warn.append('"').append(StringUtil.sanitizeXmlString(ua)).append("\" ");
        }
        warn.append("requested WebSocket version [").append(version);
        warn.append("], Jetty supports version");
        if (handshakes.size() > 1) {
            warn.append('s');
        }
        warn.append(": [").append(supportedVersions).append("]");
        LOG.warn(warn.toString());
        // Per RFC 6455 - 4.4 - Supporting Multiple Versions of WebSocket Protocol
        // Using the examples as outlined
        response.setHeader("Sec-WebSocket-Version", supportedVersions);
        response.sendError(HttpStatus.BAD_REQUEST_400, "Unsupported websocket version specification");
        return false;
    }
    // Initialize / Negotiate Extensions
    ExtensionStack extensionStack = new ExtensionStack(getExtensionFactory());
    // Usually from a Configurator.
    if (response.isExtensionsNegotiated()) {
        // Use pre-negotiated extension list from response
        extensionStack.negotiate(response.getExtensions());
    } else {
        // Use raw extension list from request
        extensionStack.negotiate(request.getExtensions());
    }
    // Get original HTTP connection
    EndPoint endp = http.getEndPoint();
    Connector connector = http.getConnector();
    Executor executor = connector.getExecutor();
    ByteBufferPool bufferPool = connector.getByteBufferPool();
    // Setup websocket connection
    AbstractWebSocketConnection wsConnection = new WebSocketServerConnection(endp, executor, scheduler, driver.getPolicy(), bufferPool);
    extensionStack.setPolicy(driver.getPolicy());
    extensionStack.configure(wsConnection.getParser());
    extensionStack.configure(wsConnection.getGenerator());
    if (LOG.isDebugEnabled()) {
        LOG.debug("HttpConnection: {}", http);
        LOG.debug("WebSocketConnection: {}", wsConnection);
    }
    // Setup Session
    WebSocketSession session = createSession(request.getRequestURI(), driver, wsConnection);
    session.setUpgradeRequest(request);
    // set true negotiated extension list back to response
    response.setExtensions(extensionStack.getNegotiatedExtensions());
    session.setUpgradeResponse(response);
    wsConnection.addListener(session);
    // Setup Incoming Routing
    wsConnection.setNextIncomingFrames(extensionStack);
    extensionStack.setNextIncoming(session);
    // Setup Outgoing Routing
    session.setOutgoingHandler(extensionStack);
    extensionStack.setNextOutgoing(wsConnection);
    // Start Components
    session.addManaged(extensionStack);
    this.addManaged(session);
    if (session.isFailed()) {
        throw new IOException("Session failed to start");
    }
    // Tell jetty about the new upgraded connection
    request.setServletAttribute(HttpConnection.UPGRADE_CONNECTION_ATTRIBUTE, wsConnection);
    if (LOG.isDebugEnabled())
        LOG.debug("Handshake Response: {}", handshaker);
    if (getSendServerVersion(connector))
        response.setHeader("Server", HttpConfiguration.SERVER_VERSION);
    // Process (version specific) handshake response
    handshaker.doHandshakeResponse(request, response);
    if (LOG.isDebugEnabled())
        LOG.debug("Websocket upgrade {} {} {} {}", request.getRequestURI(), version, response.getAcceptedSubProtocol(), wsConnection);
    return true;
}
Also used : ByteBufferPool(org.eclipse.jetty.io.ByteBufferPool) MappedByteBufferPool(org.eclipse.jetty.io.MappedByteBufferPool) Connector(org.eclipse.jetty.server.Connector) EndPoint(org.eclipse.jetty.io.EndPoint) IOException(java.io.IOException) ExtensionStack(org.eclipse.jetty.websocket.common.extensions.ExtensionStack) EndPoint(org.eclipse.jetty.io.EndPoint) AbstractWebSocketConnection(org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection) WebSocketSession(org.eclipse.jetty.websocket.common.WebSocketSession) Executor(java.util.concurrent.Executor)

Aggregations

IOException (java.io.IOException)1 Executor (java.util.concurrent.Executor)1 ByteBufferPool (org.eclipse.jetty.io.ByteBufferPool)1 EndPoint (org.eclipse.jetty.io.EndPoint)1 MappedByteBufferPool (org.eclipse.jetty.io.MappedByteBufferPool)1 Connector (org.eclipse.jetty.server.Connector)1 WebSocketSession (org.eclipse.jetty.websocket.common.WebSocketSession)1 ExtensionStack (org.eclipse.jetty.websocket.common.extensions.ExtensionStack)1 AbstractWebSocketConnection (org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection)1