Search in sources :

Example 1 with JSR356WebSocket

use of org.atmosphere.container.version.JSR356WebSocket in project atmosphere by Atmosphere.

the class JSR356Endpoint method onOpen.

@Override
public void onOpen(Session session, final EndpointConfig endpointConfig) {
    if (framework.isDestroyed())
        return;
    if (!session.isOpen()) {
        logger.trace("Session Closed {}", session);
        return;
    }
    if (maxBinaryBufferSize != -1)
        session.setMaxBinaryMessageBufferSize(maxBinaryBufferSize);
    if (webSocketWriteTimeout != -1)
        session.setMaxIdleTimeout(webSocketWriteTimeout);
    if (maxTextBufferSize != -1)
        session.setMaxTextMessageBufferSize(maxTextBufferSize);
    webSocket = new JSR356WebSocket(session, framework.getAtmosphereConfig());
    Map<String, String> headers = new HashMap<String, String>();
    // TODO: We don't support multi map header, which cause => https://github.com/Atmosphere/atmosphere/issues/1945
    for (Map.Entry<String, List<String>> e : handshakeRequest.getHeaders().entrySet()) {
        headers.put(e.getKey(), !e.getValue().isEmpty() ? e.getValue().get(0) : "");
    }
    // Force WebSocket. Hack for https://github.com/Atmosphere/atmosphere/issues/1944
    headers.put("Connection", "Upgrade");
    String servletPath = framework.getAtmosphereConfig().getInitParameter(ApplicationConfig.JSR356_MAPPING_PATH);
    if (servletPath == null) {
        servletPath = IOUtils.guestServletPath(framework.getAtmosphereConfig());
    }
    boolean recomputeForBackwardCompat = false;
    URI uri = session.getRequestURI();
    String rawPath = uri.getPath();
    String contextPath = framework.getAtmosphereConfig().getServletContext().getContextPath();
    int pathInfoStartAt = rawPath.indexOf(servletPath) + servletPath.length();
    String pathInfo = null;
    if (rawPath.length() >= pathInfoStartAt) {
        pathInfo = rawPath.substring(pathInfoStartAt);
    } else {
        recomputeForBackwardCompat = true;
    }
    if (recomputeForBackwardCompat) {
        // DON"T SCREAM this code is for broken/backward compatible
        String[] paths = uri.getPath() != null ? uri.getPath().split("/") : new String[] {};
        int pathInfoStartIndex = 3;
        if ("".equals(contextPath) || "".equals(servletPath)) {
            pathInfoStartIndex = 2;
        }
        ///contextPath / servletPath / pathInfo or / servletPath / pathInfo
        StringBuilder b = new StringBuilder("/");
        for (int i = 0; i < paths.length; i++) {
            if (i >= pathInfoStartIndex) {
                b.append(paths[i]).append("/");
            }
        }
        if (b.length() > 1) {
            b.deleteCharAt(b.length() - 1);
        }
        pathInfo = b.toString();
    }
    if (pathInfo.equals("/")) {
        pathInfo = null;
    }
    try {
        String requestURL = uri.toASCIIString();
        if (requestURL.contains("?")) {
            requestURL = requestURL.substring(0, requestURL.indexOf("?"));
        }
        // https://java.net/jira/browse/WEBSOCKET_SPEC-228
        if ((!requestURL.startsWith("http://")) || (!requestURL.startsWith("https://"))) {
            if (requestURL.startsWith("/")) {
                List<String> l = handshakeRequest.getHeaders().get("origin");
                if (l == null) {
                    // https://issues.jboss.org/browse/UNDERTOW-252
                    l = handshakeRequest.getHeaders().get("Origin");
                }
                String origin;
                if (l != null && !l.isEmpty()) {
                    origin = l.get(0);
                } else {
                    // Broken WebSocket Spec
                    logger.trace("Unable to retrieve the `origin` header for websocket {}", session);
                    origin = "http" + (session.isSecure() ? "s" : "") + "://0.0.0.0:80";
                }
                requestURL = origin + requestURL;
            } else if (requestURL.startsWith("ws://")) {
                requestURL = requestURL.replace("ws://", "http://");
            } else if (requestURL.startsWith("wss://")) {
                requestURL = requestURL.replace("wss://", "https://");
            }
        }
        List<String> cookieHeaders = handshakeRequest.getHeaders().get("Cookie");
        Set<Cookie> cookies = null;
        if (cookieHeaders != null) {
            cookies = new HashSet<Cookie>();
            for (String cookieHeader : cookieHeaders) cookies.addAll(CookieUtil.ServerCookieDecoder.STRICT.decode(cookieHeader));
        }
        request = new AtmosphereRequestImpl.Builder().requestURI(uri.getPath()).requestURL(requestURL).headers(headers).cookies(cookies).session((HttpSession) handshakeRequest.getHttpSession()).servletPath(servletPath).contextPath(framework.getServletContext().getContextPath()).pathInfo(pathInfo).destroyable(false).userPrincipal(session.getUserPrincipal()).remoteInetSocketAddress(new Callable<InetSocketAddress>() {

            @Override
            public InetSocketAddress call() throws Exception {
                return (InetSocketAddress) endpointConfig.getUserProperties().get(JAVAX_WEBSOCKET_ENDPOINT_REMOTE_ADDRESS);
            }
        }).localInetSocketAddress(new Callable<InetSocketAddress>() {

            @Override
            public InetSocketAddress call() throws Exception {
                return (InetSocketAddress) endpointConfig.getUserProperties().get(JAVAX_WEBSOCKET_ENDPOINT_LOCAL_ADDRESS);
            }
        }).build().queryString(session.getQueryString());
        if (!webSocketProcessor.handshake(request)) {
            try {
                session.close(new CloseReason(CloseReason.CloseCodes.CANNOT_ACCEPT, "Handshake not accepted."));
            } catch (IOException e) {
                logger.trace("", e);
            }
            return;
        }
        // TODO: Fix this crazy code.
        framework.addInitParameter(ALLOW_QUERYSTRING_AS_REQUEST, "false");
        webSocketProcessor.open(webSocket, request, AtmosphereResponseImpl.newInstance(framework.getAtmosphereConfig(), request, webSocket));
        framework.addInitParameter(ALLOW_QUERYSTRING_AS_REQUEST, "true");
        if (session.isOpen()) {
            session.addMessageHandler(new MessageHandler.Whole<String>() {

                @Override
                public void onMessage(String s) {
                    webSocketProcessor.invokeWebSocketProtocol(webSocket, s);
                }
            });
            session.addMessageHandler(new MessageHandler.Whole<ByteBuffer>() {

                @Override
                public void onMessage(ByteBuffer bb) {
                    byte[] b = bb.hasArray() ? bb.array() : new byte[bb.limit()];
                    bb.get(b);
                    webSocketProcessor.invokeWebSocketProtocol(webSocket, b, 0, b.length);
                }
            });
        } else {
            logger.trace("Session closed during onOpen {}", session);
            onClose(session, new CloseReason(CloseReason.CloseCodes.GOING_AWAY, "Session closed already"));
        }
    } catch (Throwable e) {
        if (session.isOpen()) {
            logger.error("", e);
        } else {
            logger.trace("Session closed during onOpen", e);
        }
        try {
            session.close(new CloseReason(CloseReason.CloseCodes.UNEXPECTED_CONDITION, e.getMessage()));
        } catch (IOException e1) {
            logger.trace("", e);
        }
        return;
    }
}
Also used : MessageHandler(javax.websocket.MessageHandler) HashMap(java.util.HashMap) InetSocketAddress(java.net.InetSocketAddress) URI(java.net.URI) Callable(java.util.concurrent.Callable) CloseReason(javax.websocket.CloseReason) List(java.util.List) Cookie(javax.servlet.http.Cookie) IOException(java.io.IOException) JSR356WebSocket(org.atmosphere.container.version.JSR356WebSocket) ByteBuffer(java.nio.ByteBuffer) Endpoint(javax.websocket.Endpoint) IOException(java.io.IOException) AtmosphereRequestImpl(org.atmosphere.runtime.AtmosphereRequestImpl) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

IOException (java.io.IOException)1 InetSocketAddress (java.net.InetSocketAddress)1 URI (java.net.URI)1 ByteBuffer (java.nio.ByteBuffer)1 HashMap (java.util.HashMap)1 List (java.util.List)1 Map (java.util.Map)1 Callable (java.util.concurrent.Callable)1 Cookie (javax.servlet.http.Cookie)1 CloseReason (javax.websocket.CloseReason)1 Endpoint (javax.websocket.Endpoint)1 MessageHandler (javax.websocket.MessageHandler)1 JSR356WebSocket (org.atmosphere.container.version.JSR356WebSocket)1 AtmosphereRequestImpl (org.atmosphere.runtime.AtmosphereRequestImpl)1