Search in sources :

Example 6 with Endpoint

use of javax.websocket.Endpoint in project tomcat70 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<Extension>();
    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<Extension>();
        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<Extension>(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(PojoEndpointServer.POJO_PATH_PARAM_KEY, pathParams);
        }
    } catch (InstantiationException e) {
        throw new ServletException(e);
    }
    // Small hack until the Servlet API provides a way to do this.
    ServletRequest inner = req;
    // Unwrap the request
    while (inner instanceof ServletRequestWrapper) {
        inner = ((ServletRequestWrapper) inner).getRequest();
    }
    if (inner instanceof RequestFacade) {
        WsHttpUpgradeHandler wsHandler = ((RequestFacade) inner).upgrade(WsHttpUpgradeHandler.class);
        wsHandler.preInit(ep, perSessionServerEndpointConfig, sc, wsRequest, negotiatedExtensionsPhase2, subProtocol, transformation, pathParams, req.isSecure());
    } else {
        throw new ServletException("Upgrade failed");
    }
}
Also used : HttpServletRequest(javax.servlet.http.HttpServletRequest) ServletRequest(javax.servlet.ServletRequest) Transformation(org.apache.tomcat.websocket.Transformation) ArrayList(java.util.ArrayList) PojoEndpointServer(org.apache.tomcat.websocket.pojo.PojoEndpointServer) ServletException(javax.servlet.ServletException) Endpoint(javax.websocket.Endpoint) ArrayList(java.util.ArrayList) List(java.util.List) WsHandshakeResponse(org.apache.tomcat.websocket.WsHandshakeResponse) ServletRequestWrapper(javax.servlet.ServletRequestWrapper) RequestFacade(org.apache.catalina.connector.RequestFacade) Extension(javax.websocket.Extension)

Example 7 with Endpoint

use of javax.websocket.Endpoint in project tomcat70 by apache.

the class WsWebSocketContainer method connectToServer.

@Override
public Session connectToServer(Object pojo, URI path) throws DeploymentException {
    ClientEndpoint annotation = pojo.getClass().getAnnotation(ClientEndpoint.class);
    if (annotation == null) {
        throw new DeploymentException(sm.getString("wsWebSocketContainer.missingAnnotation", pojo.getClass().getName()));
    }
    Endpoint ep = new PojoEndpointClient(pojo, Arrays.asList(annotation.decoders()));
    Class<? extends ClientEndpointConfig.Configurator> configuratorClazz = annotation.configurator();
    ClientEndpointConfig.Configurator configurator = null;
    if (!ClientEndpointConfig.Configurator.class.equals(configuratorClazz)) {
        try {
            configurator = configuratorClazz.newInstance();
        } catch (InstantiationException e) {
            throw new DeploymentException(sm.getString("wsWebSocketContainer.defaultConfiguratorFail"), e);
        } catch (IllegalAccessException e) {
            throw new DeploymentException(sm.getString("wsWebSocketContainer.defaultConfiguratorFail"), e);
        }
    }
    ClientEndpointConfig.Builder builder = ClientEndpointConfig.Builder.create();
    // Avoid NPE when using RI API JAR - see BZ 56343
    if (configurator != null) {
        builder.configurator(configurator);
    }
    ClientEndpointConfig config = builder.decoders(Arrays.asList(annotation.decoders())).encoders(Arrays.asList(annotation.encoders())).preferredSubprotocols(Arrays.asList(annotation.subprotocols())).build();
    return connectToServer(ep, config, path);
}
Also used : Endpoint(javax.websocket.Endpoint) ClientEndpoint(javax.websocket.ClientEndpoint) PojoEndpointClient(org.apache.tomcat.websocket.pojo.PojoEndpointClient) DeploymentException(javax.websocket.DeploymentException) ClientEndpointConfig(javax.websocket.ClientEndpointConfig) ClientEndpoint(javax.websocket.ClientEndpoint)

Example 8 with Endpoint

use of javax.websocket.Endpoint in project tomcat70 by apache.

the class TestWsWebSocketContainer method doBufferTest.

private void doBufferTest(boolean isTextBuffer, boolean isServerBuffer, boolean isTextMessage, boolean pass) throws Exception {
    Tomcat tomcat = getTomcatInstance();
    // No file system docBase required
    Context ctx = tomcat.addContext("", null);
    ctx.addApplicationListener(TesterEchoServer.Config.class.getName());
    Tomcat.addServlet(ctx, "default", new DefaultServlet());
    ctx.addServletMapping("/", "default");
    WebSocketContainer wsContainer = ContainerProvider.getWebSocketContainer();
    if (isServerBuffer) {
        if (isTextBuffer) {
            ctx.addParameter(org.apache.tomcat.websocket.server.Constants.TEXT_BUFFER_SIZE_SERVLET_CONTEXT_INIT_PARAM, "1024");
        } else {
            ctx.addParameter(org.apache.tomcat.websocket.server.Constants.BINARY_BUFFER_SIZE_SERVLET_CONTEXT_INIT_PARAM, "1024");
        }
    } else {
        if (isTextBuffer) {
            wsContainer.setDefaultMaxTextMessageBufferSize(1024);
        } else {
            wsContainer.setDefaultMaxBinaryMessageBufferSize(1024);
        }
    }
    tomcat.start();
    Session wsSession = wsContainer.connectToServer(TesterProgrammaticEndpoint.class, ClientEndpointConfig.Builder.create().build(), new URI("ws://" + getHostName() + ":" + getPort() + TesterEchoServer.Config.PATH_BASIC));
    BasicHandler<?> handler;
    CountDownLatch latch = new CountDownLatch(1);
    TesterEndpoint tep = (TesterEndpoint) wsSession.getUserProperties().get("endpoint");
    tep.setLatch(latch);
    if (isTextMessage) {
        handler = new BasicText(latch);
    } else {
        handler = new BasicBinary(latch);
    }
    wsSession.addMessageHandler(handler);
    try {
        if (isTextMessage) {
            wsSession.getBasicRemote().sendText(MESSAGE_TEXT_4K);
        } else {
            wsSession.getBasicRemote().sendBinary(ByteBuffer.wrap(MESSAGE_BINARY_4K));
        }
    } catch (IOException ioe) {
    // Some messages sends are expected to fail. Assertions further on
    // in this method will check for the correct behaviour so ignore any
    // exception here.
    }
    boolean latchResult = handler.getLatch().await(10, TimeUnit.SECONDS);
    Assert.assertTrue(latchResult);
    Queue<?> messages = handler.getMessages();
    if (pass) {
        Assert.assertEquals(1, messages.size());
        if (isTextMessage) {
            Assert.assertEquals(MESSAGE_TEXT_4K, messages.peek());
        } else {
            Assert.assertEquals(ByteBuffer.wrap(MESSAGE_BINARY_4K), messages.peek());
        }
    } else {
        // give the session a chance to complete the close process.
        for (int i = 0; i < 500; i++) {
            if (!wsSession.isOpen()) {
                break;
            }
            Thread.sleep(10);
        }
        Assert.assertFalse(wsSession.isOpen());
    }
}
Also used : Context(org.apache.catalina.Context) Tomcat(org.apache.catalina.startup.Tomcat) WebSocketContainer(javax.websocket.WebSocketContainer) ClientEndpointConfig(javax.websocket.ClientEndpointConfig) ServerEndpointConfig(javax.websocket.server.ServerEndpointConfig) EndpointConfig(javax.websocket.EndpointConfig) BasicBinary(org.apache.tomcat.websocket.TesterMessageCountClient.BasicBinary) IOException(java.io.IOException) CountDownLatch(java.util.concurrent.CountDownLatch) URI(java.net.URI) TesterEndpoint(org.apache.tomcat.websocket.TesterMessageCountClient.TesterEndpoint) TesterProgrammaticEndpoint(org.apache.tomcat.websocket.TesterMessageCountClient.TesterProgrammaticEndpoint) Endpoint(javax.websocket.Endpoint) ServerEndpoint(javax.websocket.server.ServerEndpoint) TesterEndpoint(org.apache.tomcat.websocket.TesterMessageCountClient.TesterEndpoint) BasicText(org.apache.tomcat.websocket.TesterMessageCountClient.BasicText) DefaultServlet(org.apache.catalina.servlets.DefaultServlet) Session(javax.websocket.Session)

Example 9 with Endpoint

use of javax.websocket.Endpoint in project tomcat70 by apache.

the class TestWsRemoteEndpoint method doTestWriter.

private void doTestWriter(Class<?> clazz, boolean useWriter) throws Exception {
    Tomcat tomcat = getTomcatInstance();
    // No file system docBase required
    Context ctx = tomcat.addContext("", null);
    ctx.addApplicationListener(TesterEchoServer.Config.class.getName());
    Tomcat.addServlet(ctx, "default", new DefaultServlet());
    ctx.addServletMapping("/", "default");
    WebSocketContainer wsContainer = ContainerProvider.getWebSocketContainer();
    tomcat.start();
    Session wsSession;
    URI uri = new URI("ws://localhost:" + getPort() + TesterEchoServer.Config.PATH_ASYNC);
    if (Endpoint.class.isAssignableFrom(clazz)) {
        @SuppressWarnings("unchecked") Class<? extends Endpoint> endpointClazz = (Class<? extends Endpoint>) clazz;
        wsSession = wsContainer.connectToServer(endpointClazz, Builder.create().build(), uri);
    } else {
        wsSession = wsContainer.connectToServer(clazz, uri);
    }
    CountDownLatch latch = new CountDownLatch(1);
    TesterEndpoint tep = (TesterEndpoint) wsSession.getUserProperties().get("endpoint");
    tep.setLatch(latch);
    AsyncHandler<?> handler;
    if (useWriter) {
        handler = new AsyncText(latch);
    } else {
        handler = new AsyncBinary(latch);
    }
    wsSession.addMessageHandler(handler);
    if (useWriter) {
        Writer w = wsSession.getBasicRemote().getSendWriter();
        for (int i = 0; i < 8; i++) {
            w.write(TEST_MESSAGE_5K);
        }
        w.close();
    } else {
        OutputStream s = wsSession.getBasicRemote().getSendStream();
        for (int i = 0; i < 8; i++) {
            s.write(TEST_MESSAGE_5K.getBytes(B2CConverter.UTF_8));
        }
        s.close();
    }
    boolean latchResult = handler.getLatch().await(10, TimeUnit.SECONDS);
    Assert.assertTrue(latchResult);
    List<String> results = new ArrayList<String>();
    if (useWriter) {
        @SuppressWarnings("unchecked") List<String> messages = (List<String>) handler.getMessages();
        results.addAll(messages);
    } else {
        // Take advantage of the fact that the message uses characters that
        // are represented as a single UTF-8 byte so won't be split across
        // binary messages
        @SuppressWarnings("unchecked") List<ByteBuffer> messages = (List<ByteBuffer>) handler.getMessages();
        for (ByteBuffer message : messages) {
            byte[] bytes = new byte[message.limit()];
            message.get(bytes);
            results.add(new String(bytes, B2CConverter.UTF_8));
        }
    }
    int offset = 0;
    int i = 0;
    for (String result : results) {
        // First may be a fragment
        Assert.assertEquals(SEQUENCE.substring(offset, S_LEN), result.substring(0, S_LEN - offset));
        i = S_LEN - offset;
        while (i + S_LEN < result.length()) {
            if (!SEQUENCE.equals(result.substring(i, i + S_LEN))) {
                Assert.fail();
            }
            i += S_LEN;
        }
        offset = result.length() - i;
        if (!SEQUENCE.substring(0, offset).equals(result.substring(i))) {
            Assert.fail();
        }
    }
}
Also used : AsyncText(org.apache.tomcat.websocket.TesterMessageCountClient.AsyncText) Tomcat(org.apache.catalina.startup.Tomcat) OutputStream(java.io.OutputStream) ArrayList(java.util.ArrayList) URI(java.net.URI) TesterProgrammaticEndpoint(org.apache.tomcat.websocket.TesterMessageCountClient.TesterProgrammaticEndpoint) TesterAnnotatedEndpoint(org.apache.tomcat.websocket.TesterMessageCountClient.TesterAnnotatedEndpoint) Endpoint(javax.websocket.Endpoint) TesterEndpoint(org.apache.tomcat.websocket.TesterMessageCountClient.TesterEndpoint) ArrayList(java.util.ArrayList) List(java.util.List) DefaultServlet(org.apache.catalina.servlets.DefaultServlet) Context(org.apache.catalina.Context) WebSocketContainer(javax.websocket.WebSocketContainer) CountDownLatch(java.util.concurrent.CountDownLatch) ByteBuffer(java.nio.ByteBuffer) TesterEndpoint(org.apache.tomcat.websocket.TesterMessageCountClient.TesterEndpoint) TesterProgrammaticEndpoint(org.apache.tomcat.websocket.TesterMessageCountClient.TesterProgrammaticEndpoint) TesterAnnotatedEndpoint(org.apache.tomcat.websocket.TesterMessageCountClient.TesterAnnotatedEndpoint) Endpoint(javax.websocket.Endpoint) TesterEndpoint(org.apache.tomcat.websocket.TesterMessageCountClient.TesterEndpoint) AsyncBinary(org.apache.tomcat.websocket.TesterMessageCountClient.AsyncBinary) Writer(java.io.Writer) Session(javax.websocket.Session)

Example 10 with Endpoint

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

the class ServerWebSocketContainer method connectToServer.

public Session connectToServer(final Endpoint endpointInstance, final ClientEndpointConfig config, WebSocketClient.ConnectionBuilder connectionBuilder) throws DeploymentException, IOException {
    if (closed) {
        throw new ClosedChannelException();
    }
    ClientEndpointConfig cec = config != null ? config : ClientEndpointConfig.Builder.create().build();
    WebSocketClientNegotiation clientNegotiation = connectionBuilder.getClientNegotiation();
    IoFuture<WebSocketChannel> session = connectionBuilder.connect();
    Number timeout = (Number) cec.getUserProperties().get(TIMEOUT);
    if (session.await(timeout == null ? DEFAULT_WEB_SOCKET_TIMEOUT_SECONDS : timeout.intValue(), TimeUnit.SECONDS) == IoFuture.Status.WAITING) {
        // add a notifier to close the channel if the connection actually completes
        session.cancel();
        session.addNotifier(new IoFuture.HandlingNotifier<WebSocketChannel, Object>() {

            @Override
            public void handleDone(WebSocketChannel data, Object attachment) {
                IoUtils.safeClose(data);
            }
        }, null);
        throw JsrWebSocketMessages.MESSAGES.connectionTimedOut();
    }
    WebSocketChannel channel;
    try {
        channel = session.get();
    } catch (UpgradeFailedException e) {
        throw new DeploymentException(e.getMessage(), e);
    }
    EndpointSessionHandler sessionHandler = new EndpointSessionHandler(this);
    final List<Extension> extensions = new ArrayList<>();
    final Map<String, Extension> extMap = new HashMap<>();
    for (Extension ext : cec.getExtensions()) {
        extMap.put(ext.getName(), ext);
    }
    for (WebSocketExtension e : clientNegotiation.getSelectedExtensions()) {
        Extension ext = extMap.get(e.getName());
        if (ext == null) {
            throw JsrWebSocketMessages.MESSAGES.extensionWasNotPresentInClientHandshake(e.getName(), clientNegotiation.getSupportedExtensions());
        }
        extensions.add(ExtensionImpl.create(e));
    }
    ConfiguredClientEndpoint configured = clientEndpoints.get(endpointInstance.getClass());
    Endpoint instance = endpointInstance;
    if (configured == null) {
        synchronized (clientEndpoints) {
            // make sure to create an instance of AnnotatedEndpoint if we have the annotation
            configured = getClientEndpoint(endpointInstance.getClass(), false);
            if (configured == null) {
                // if we don't, add an endpoint anyway to the list of clientEndpoints
                clientEndpoints.put(endpointInstance.getClass(), configured = new ConfiguredClientEndpoint());
            } else {
                // use the  factory in configured to reach the endpoint
                instance = configured.getFactory().createInstance(new ImmediateInstanceHandle<>(endpointInstance));
            }
        }
    }
    EncodingFactory encodingFactory = EncodingFactory.createFactory(classIntrospecter, cec.getDecoders(), cec.getEncoders());
    UndertowSession undertowSession = new UndertowSession(channel, connectionBuilder.getUri(), Collections.<String, String>emptyMap(), Collections.<String, List<String>>emptyMap(), sessionHandler, null, new ImmediateInstanceHandle<>(endpointInstance), cec, connectionBuilder.getUri().getQuery(), encodingFactory.createEncoding(cec), configured, clientNegotiation.getSelectedSubProtocol(), extensions, connectionBuilder);
    instance.onOpen(undertowSession, cec);
    channel.resumeReceives();
    return undertowSession;
}
Also used : HashMap(java.util.HashMap) WebSocketChannel(io.undertow.websockets.core.WebSocketChannel) ArrayList(java.util.ArrayList) IoFuture(org.xnio.IoFuture) WebSocketClientNegotiation(io.undertow.websockets.client.WebSocketClientNegotiation) Endpoint(javax.websocket.Endpoint) ServerEndpoint(javax.websocket.server.ServerEndpoint) ClientEndpoint(javax.websocket.ClientEndpoint) UpgradeFailedException(org.xnio.http.UpgradeFailedException) ClientEndpointConfig(javax.websocket.ClientEndpointConfig) ClosedChannelException(java.nio.channels.ClosedChannelException) WebSocketExtension(io.undertow.websockets.WebSocketExtension) WebSocketExtension(io.undertow.websockets.WebSocketExtension) Extension(javax.websocket.Extension) ImmediateInstanceHandle(io.undertow.servlet.util.ImmediateInstanceHandle) DeploymentException(javax.websocket.DeploymentException)

Aggregations

Endpoint (javax.websocket.Endpoint)46 Session (javax.websocket.Session)29 URI (java.net.URI)24 EndpointConfig (javax.websocket.EndpointConfig)24 ServerEndpointConfig (javax.websocket.server.ServerEndpointConfig)20 AtomicReference (java.util.concurrent.atomic.AtomicReference)18 ServerWebSocketContainer (io.undertow.websockets.jsr.ServerWebSocketContainer)14 UndertowSession (io.undertow.websockets.jsr.UndertowSession)14 AnnotatedClientEndpoint (io.undertow.websockets.jsr.test.annotated.AnnotatedClientEndpoint)14 FrameChecker (io.undertow.websockets.utils.FrameChecker)14 WebSocketTestClient (io.undertow.websockets.utils.WebSocketTestClient)14 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)14 FutureResult (org.xnio.FutureResult)14 IOException (java.io.IOException)13 ClientEndpointConfig (javax.websocket.ClientEndpointConfig)12 MessageHandler (javax.websocket.MessageHandler)12 ByteBuffer (java.nio.ByteBuffer)11 ServerEndpoint (javax.websocket.server.ServerEndpoint)11 CountDownLatch (java.util.concurrent.CountDownLatch)10 ClientEndpoint (javax.websocket.ClientEndpoint)10