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");
}
}
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);
}
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());
}
}
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();
}
}
}
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;
}
Aggregations