Search in sources :

Example 11 with CloseReason

use of javax.websocket.CloseReason 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)

Example 12 with CloseReason

use of javax.websocket.CloseReason in project undertow by undertow-io.

the class UndertowSession method closeInternal.

public void closeInternal(CloseReason closeReason) throws IOException {
    if (closed.compareAndSet(false, true)) {
        try {
            try {
                if (!webSocketChannel.isCloseFrameReceived() && !webSocketChannel.isCloseFrameSent()) {
                    //will deal with sending back the reason message
                    if (closeReason == null || closeReason.getCloseCode().getCode() == CloseReason.CloseCodes.NO_STATUS_CODE.getCode()) {
                        webSocketChannel.sendClose();
                    } else {
                        WebSockets.sendClose(new CloseMessage(closeReason.getCloseCode().getCode(), closeReason.getReasonPhrase()).toByteBuffer(), webSocketChannel, null);
                    }
                }
            } finally {
                try {
                    String reason = null;
                    CloseReason.CloseCode code = CloseReason.CloseCodes.NO_STATUS_CODE;
                    if (webSocketChannel.getCloseCode() != -1) {
                        reason = webSocketChannel.getCloseReason();
                        code = CloseReason.CloseCodes.getCloseCode(webSocketChannel.getCloseCode());
                    } else if (closeReason != null) {
                        reason = closeReason.getReasonPhrase();
                        code = closeReason.getCloseCode();
                    }
                    //we need to really clean up the close behaviour in the next spec
                    if (!webSocketChannel.isCloseInitiatedByRemotePeer() && !localClose && code.getCode() != CloseReason.CloseCodes.TOO_BIG.getCode()) {
                        //2.1.5: we must use 1006 if the close was initiated locally
                        //however we only do this for normal closure
                        //if the close was due to another reason such as a message being too long we need to report the real reason
                        code = CloseReason.CloseCodes.CLOSED_ABNORMALLY;
                    }
                    endpoint.getInstance().onClose(this, new CloseReason(code, reason));
                } catch (Exception e) {
                    endpoint.getInstance().onError(this, e);
                }
            }
        } finally {
            close0();
            if (clientConnectionBuilder != null && !localClose) {
                WebSocketReconnectHandler webSocketReconnectHandler = container.getWebSocketReconnectHandler();
                if (webSocketReconnectHandler != null) {
                    JsrWebSocketLogger.REQUEST_LOGGER.debugf("Calling reconnect handler for %s", this);
                    long reconnect = webSocketReconnectHandler.disconnected(closeReason, requestUri, this, ++disconnectCount);
                    if (reconnect >= 0) {
                        handleReconnect(reconnect);
                    }
                }
            }
        }
    }
}
Also used : CloseReason(javax.websocket.CloseReason) CloseMessage(io.undertow.websockets.core.CloseMessage) IOException(java.io.IOException)

Example 13 with CloseReason

use of javax.websocket.CloseReason in project undertow by undertow-io.

the class UndertowSession method setupWebSocketChannel.

private void setupWebSocketChannel(WebSocketChannel webSocketChannel) {
    this.frameHandler = new FrameHandler(this, this.endpoint.getInstance());
    webSocketChannel.getReceiveSetter().set(frameHandler);
    webSocketChannel.addCloseTask(new ChannelListener<WebSocketChannel>() {

        @Override
        public void handleEvent(WebSocketChannel channel) {
            //so this puts us in an interesting position. We know the underlying
            //TCP connection has been torn down, however this may have involved reading
            //a close frame, which will be delivered shortly
            //to get around this we schedule the code in the IO thread, so if there is a close
            //frame awaiting delivery it will be delivered before the close
            channel.getIoThread().execute(new Runnable() {

                @Override
                public void run() {
                    //we delegate this execution to the IO thread
                    try {
                        closeInternal(new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE, null));
                    } catch (IOException e) {
                    //ignore
                    }
                }
            });
        }
    });
}
Also used : CloseReason(javax.websocket.CloseReason) WebSocketChannel(io.undertow.websockets.core.WebSocketChannel) IOException(java.io.IOException)

Example 14 with CloseReason

use of javax.websocket.CloseReason in project undertow by undertow-io.

the class ClientEndpointReconnectTestCase method setup.

@BeforeClass
public static void setup() throws Exception {
    final ServletContainer container = ServletContainer.Factory.newInstance();
    DeploymentInfo builder = new DeploymentInfo().setClassLoader(ClientEndpointReconnectTestCase.class.getClassLoader()).setContextPath("/ws").setResourceManager(new TestResourceLoader(ClientEndpointReconnectTestCase.class)).setClassIntrospecter(TestClassIntrospector.INSTANCE).addServletContextAttribute(WebSocketDeploymentInfo.ATTRIBUTE_NAME, new WebSocketDeploymentInfo().setBuffers(new DefaultByteBufferPool(true, 8192)).setWorker(DefaultServer.getWorker()).addEndpoint(DisconnectServerEndpoint.class).addEndpoint(AnnotatedClientReconnectEndpoint.class).addListener(new WebSocketDeploymentInfo.ContainerReadyListener() {

        @Override
        public void ready(ServerWebSocketContainer container) {
            deployment = container;
        }
    }).setReconnectHandler(new WebSocketReconnectHandler() {

        @Override
        public long disconnected(CloseReason closeReason, URI connectionUri, Session session, int disconnectCount) {
            if (disconnectCount < 3) {
                return 1;
            } else {
                return -1;
            }
        }

        @Override
        public long reconnectFailed(IOException exception, URI connectionUri, Session session, int failedCount) {
            failed = true;
            return -1;
        }
    })).setDeploymentName("servletContext.war");
    DeploymentManager manager = container.addDeployment(builder);
    manager.deploy();
    DefaultServer.setRootHandler(Handlers.path().addPrefixPath("/ws", manager.start()));
}
Also used : WebSocketReconnectHandler(io.undertow.websockets.jsr.WebSocketReconnectHandler) DefaultByteBufferPool(io.undertow.server.DefaultByteBufferPool) TestResourceLoader(io.undertow.servlet.test.util.TestResourceLoader) ServerWebSocketContainer(io.undertow.websockets.jsr.ServerWebSocketContainer) DeploymentManager(io.undertow.servlet.api.DeploymentManager) IOException(java.io.IOException) WebSocketDeploymentInfo(io.undertow.websockets.jsr.WebSocketDeploymentInfo) URI(java.net.URI) CloseReason(javax.websocket.CloseReason) ServletContainer(io.undertow.servlet.api.ServletContainer) WebSocketDeploymentInfo(io.undertow.websockets.jsr.WebSocketDeploymentInfo) DeploymentInfo(io.undertow.servlet.api.DeploymentInfo) Session(javax.websocket.Session) BeforeClass(org.junit.BeforeClass)

Example 15 with CloseReason

use of javax.websocket.CloseReason in project undertow by undertow-io.

the class AnnotatedEndpointTest method testCloseReason.

@Test
public void testCloseReason() throws Exception {
    MessageEndpoint.reset();
    Session session = deployment.connectToServer(AnnotatedClientEndpoint.class, new URI("ws://" + DefaultServer.getHostAddress("default") + ":" + DefaultServer.getHostPort("default") + "/ws/chat/Bob"));
    Assert.assertEquals("hi Bob (protocol=foo)", AnnotatedClientEndpoint.message());
    session.close(new CloseReason(CloseReason.CloseCodes.VIOLATED_POLICY, "Foo!"));
    Assert.assertEquals("CLOSED", AnnotatedClientEndpoint.message());
    CloseReason cr = MessageEndpoint.getReason();
    Assert.assertEquals(CloseReason.CloseCodes.VIOLATED_POLICY.getCode(), cr.getCloseCode().getCode());
    Assert.assertEquals("Foo!", cr.getReasonPhrase());
}
Also used : CloseReason(javax.websocket.CloseReason) URI(java.net.URI) Session(javax.websocket.Session) UndertowSession(io.undertow.websockets.jsr.UndertowSession) Test(org.junit.Test)

Aggregations

CloseReason (javax.websocket.CloseReason)29 IOException (java.io.IOException)16 Session (javax.websocket.Session)8 URI (java.net.URI)7 Test (org.junit.Test)6 ByteBuffer (java.nio.ByteBuffer)5 Endpoint (javax.websocket.Endpoint)5 CountDownLatch (java.util.concurrent.CountDownLatch)4 EndpointConfig (javax.websocket.EndpointConfig)4 ServerWebSocketContainer (io.undertow.websockets.jsr.ServerWebSocketContainer)3 UndertowSession (io.undertow.websockets.jsr.UndertowSession)3 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)3 CloseWebSocketFrame (io.netty.handler.codec.http.websocketx.CloseWebSocketFrame)2 AnnotatedClientEndpoint (io.undertow.websockets.jsr.test.annotated.AnnotatedClientEndpoint)2 FrameChecker (io.undertow.websockets.utils.FrameChecker)2 WebSocketTestClient (io.undertow.websockets.utils.WebSocketTestClient)2 CoderResult (java.nio.charset.CoderResult)2 ArrayList (java.util.ArrayList)2 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)2 AtomicReference (java.util.concurrent.atomic.AtomicReference)2