Issue #207 - more test induced fixes
# Conflicts: # jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/IdleTimeoutTest.java
This commit is contained in:
parent
79f30041a1
commit
ad29d65229
|
@ -1,119 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.jsr356.server;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.StatusCode;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.eclipse.jetty.websocket.common.test.LeakTrackingBufferPoolRule;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.idletimeout.IdleTimeoutContextListener;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.idletimeout.OnOpenIdleTimeoutEndpoint;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.idletimeout.OnOpenIdleTimeoutSocket;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
public class IdleTimeoutTest
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(IdleTimeoutTest.class);
|
||||
|
||||
private static WSServer server;
|
||||
|
||||
@BeforeClass
|
||||
public static void setupServer() throws Exception
|
||||
{
|
||||
server = new WSServer(MavenTestingUtils.getTargetTestingPath(IdleTimeoutTest.class.getName()),"app");
|
||||
server.copyWebInf("idle-timeout-config-web.xml");
|
||||
// the endpoint (extends javax.websocket.Endpoint)
|
||||
server.copyClass(OnOpenIdleTimeoutEndpoint.class);
|
||||
// the configuration that adds the endpoint
|
||||
server.copyClass(IdleTimeoutContextListener.class);
|
||||
// the annotated socket
|
||||
server.copyClass(OnOpenIdleTimeoutSocket.class);
|
||||
|
||||
server.start();
|
||||
|
||||
WebAppContext webapp = server.createWebAppContext();
|
||||
server.deployWebapp(webapp);
|
||||
// wsb.dump();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void stopServer()
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
|
||||
private void assertConnectionTimeout(URI uri) throws Exception
|
||||
{
|
||||
WebSocketClient client = new WebSocketClient();
|
||||
try
|
||||
{
|
||||
client.start();
|
||||
JettyEchoSocket clientSocket = new JettyEchoSocket();
|
||||
|
||||
Future<Session> clientConnectFuture = client.connect(clientSocket,uri);
|
||||
// wait for connect
|
||||
clientConnectFuture.get(1,TimeUnit.SECONDS);
|
||||
// wait 1 second
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
|
||||
// Try to write
|
||||
clientSocket.sendMessage("You shouldn't be there");
|
||||
|
||||
// See if remote sent anything (it shouldn't have)
|
||||
String incomingMessage = clientSocket.messageQueue.poll(1, TimeUnit.SECONDS);
|
||||
assertThat("Should not have received messages echoed back",incomingMessage,nullValue());
|
||||
|
||||
// wait for local close
|
||||
clientSocket.awaitCloseEvent("Client");
|
||||
clientSocket.assertCloseInfo("Client", StatusCode.SHUTDOWN, containsString("Idle Timeout"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotated() throws Exception
|
||||
{
|
||||
URI uri = server.getServerBaseURI();
|
||||
assertConnectionTimeout(uri.resolve("idle-onopen-socket"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEndpoint() throws Exception
|
||||
{
|
||||
URI uri = server.getServerBaseURI();
|
||||
assertConnectionTimeout(uri.resolve("idle-onopen-endpoint"));
|
||||
}
|
||||
}
|
|
@ -1,183 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.jsr356.server;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.websocket.CloseReason;
|
||||
import javax.websocket.Endpoint;
|
||||
import javax.websocket.EndpointConfig;
|
||||
import javax.websocket.OnMessage;
|
||||
import javax.websocket.Session;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketSession;
|
||||
import org.eclipse.jetty.websocket.jsr356.ClientContainer;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
|
||||
import org.eclipse.jetty.websocket.server.WebSocketServerFactory;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SessionTrackingTest
|
||||
{
|
||||
public static class ClientSocket extends Endpoint
|
||||
{
|
||||
public Session session;
|
||||
public CountDownLatch openLatch = new CountDownLatch(1);
|
||||
public CountDownLatch closeLatch = new CountDownLatch(1);
|
||||
|
||||
@Override
|
||||
public void onOpen(Session session, EndpointConfig config)
|
||||
{
|
||||
this.session = session;
|
||||
openLatch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose(Session session, CloseReason closeReason)
|
||||
{
|
||||
closeLatch.countDown();
|
||||
}
|
||||
|
||||
public void waitForOpen(long timeout, TimeUnit unit) throws InterruptedException
|
||||
{
|
||||
assertThat("ClientSocket opened",openLatch.await(timeout,unit),is(true));
|
||||
}
|
||||
|
||||
public void waitForClose(long timeout, TimeUnit unit) throws InterruptedException
|
||||
{
|
||||
assertThat("ClientSocket opened",closeLatch.await(timeout,unit),is(true));
|
||||
}
|
||||
}
|
||||
|
||||
@ServerEndpoint("/test")
|
||||
public static class EchoSocket
|
||||
{
|
||||
@OnMessage
|
||||
public String echo(String msg)
|
||||
{
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
||||
private static Server server;
|
||||
private static WebSocketServerFactory wsServerFactory;
|
||||
private static URI serverURI;
|
||||
|
||||
@BeforeClass
|
||||
public static void startServer() throws Exception
|
||||
{
|
||||
Server server = new Server();
|
||||
ServerConnector serverConnector = new ServerConnector(server);
|
||||
serverConnector.setPort(0);
|
||||
server.addConnector(serverConnector);
|
||||
ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
|
||||
servletContextHandler.setContextPath("/");
|
||||
server.setHandler(servletContextHandler);
|
||||
|
||||
ServerContainer serverContainer = WebSocketServerContainerInitializer.configureContext(servletContextHandler);
|
||||
serverContainer.addEndpoint(EchoSocket.class);
|
||||
|
||||
wsServerFactory = serverContainer.getWebSocketServerFactory();
|
||||
|
||||
server.start();
|
||||
|
||||
String host = serverConnector.getHost();
|
||||
if (StringUtil.isBlank(host))
|
||||
{
|
||||
host = "localhost";
|
||||
}
|
||||
serverURI = new URI("ws://" + host + ":" + serverConnector.getLocalPort());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void stopServer() throws Exception
|
||||
{
|
||||
if (server == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddRemoveSessions() throws Exception
|
||||
{
|
||||
// Create Client
|
||||
ClientContainer clientContainer = new ClientContainer();
|
||||
try
|
||||
{
|
||||
clientContainer.start();
|
||||
|
||||
// Establish connections
|
||||
ClientSocket cli1 = new ClientSocket();
|
||||
clientContainer.connectToServer(cli1,serverURI.resolve("/test"));
|
||||
cli1.waitForOpen(1,TimeUnit.SECONDS);
|
||||
|
||||
// Assert open connections
|
||||
assertServerOpenConnectionCount(1);
|
||||
|
||||
// Establish new connection
|
||||
ClientSocket cli2 = new ClientSocket();
|
||||
clientContainer.connectToServer(cli2,serverURI.resolve("/test"));
|
||||
cli2.waitForOpen(1,TimeUnit.SECONDS);
|
||||
|
||||
// Assert open connections
|
||||
assertServerOpenConnectionCount(2);
|
||||
|
||||
// Establish close both connections
|
||||
cli1.session.close();
|
||||
cli2.session.close();
|
||||
|
||||
cli1.waitForClose(1,TimeUnit.SECONDS);
|
||||
cli2.waitForClose(1,TimeUnit.SECONDS);
|
||||
|
||||
// Assert open connections
|
||||
assertServerOpenConnectionCount(0);
|
||||
}
|
||||
finally
|
||||
{
|
||||
clientContainer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
private void assertServerOpenConnectionCount(int expectedCount)
|
||||
{
|
||||
Collection<javax.websocket.Session> sessions = wsServerFactory.getBeans(javax.websocket.Session.class);
|
||||
int openCount = 0;
|
||||
for (javax.websocket.Session session : sessions)
|
||||
{
|
||||
assertThat("Session.isopen: " + session,session.isOpen(),is(true));
|
||||
openCount++;
|
||||
}
|
||||
assertThat("Open Session Count",openCount,is(expectedCount));
|
||||
}
|
||||
}
|
|
@ -86,27 +86,29 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
private final Executor executor;
|
||||
private final AtomicConnectionState connectionState = new AtomicConnectionState();
|
||||
private final AtomicBoolean closeSent = new AtomicBoolean();
|
||||
|
||||
|
||||
// The websocket endpoint object itself
|
||||
private final Object endpoint;
|
||||
|
||||
// Callbacks
|
||||
private FrameCallback onDisconnectCallback = new CompletionCallback() {
|
||||
private FrameCallback onDisconnectCallback = new CompletionCallback()
|
||||
{
|
||||
@Override
|
||||
public void complete()
|
||||
{
|
||||
if (connectionState.onClosed())
|
||||
{
|
||||
LOG.debug("ConnectionState: Transition to CLOSED");
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("ConnectionState: Transition to CLOSED");
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Endpoint Functions and MessageSinks
|
||||
protected EndpointFunctions endpointFunctions;
|
||||
private MessageSink activeMessageSink;
|
||||
|
||||
|
||||
private ClassLoader classLoader;
|
||||
private ExtensionFactory extensionFactory;
|
||||
private BatchMode batchmode = BatchMode.AUTO;
|
||||
|
@ -124,9 +126,9 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
{
|
||||
Objects.requireNonNull(containerScope, "Container Scope cannot be null");
|
||||
Objects.requireNonNull(requestURI, "Request URI cannot be null");
|
||||
|
||||
|
||||
LOG = Log.getLogger(WebSocketSession.class.getName() + "." + connection.getPolicy().getBehavior().name());
|
||||
|
||||
|
||||
this.classLoader = Thread.currentThread().getContextClassLoader();
|
||||
this.containerScope = containerScope;
|
||||
this.requestURI = requestURI;
|
||||
|
@ -135,7 +137,7 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
this.executor = connection.getExecutor();
|
||||
this.outgoingHandler = connection;
|
||||
this.policy = connection.getPolicy();
|
||||
|
||||
|
||||
addBean(this.connection);
|
||||
}
|
||||
|
||||
|
@ -155,13 +157,13 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
/* This is assumed to always be a NORMAL closure, no reason phrase */
|
||||
close(StatusCode.NORMAL, null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void close(CloseStatus closeStatus)
|
||||
{
|
||||
close(closeStatus.getCode(),closeStatus.getPhrase());
|
||||
close(closeStatus.getCode(), closeStatus.getPhrase());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void close(int statusCode, String reason)
|
||||
{
|
||||
|
@ -177,19 +179,21 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
{
|
||||
connectionState.onClosing(); // move to CLOSING state (always)
|
||||
|
||||
if(closeSent.compareAndSet(false,true))
|
||||
if (closeSent.compareAndSet(false, true))
|
||||
{
|
||||
LOG.debug("Sending Close Frame");
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Sending Close Frame");
|
||||
CloseFrame closeFrame = closeInfo.asFrame();
|
||||
outgoingHandler.outgoingFrame(closeFrame, callback, BatchMode.OFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.debug("Close Frame Previously Sent: ignoring: {} [{}]", closeInfo, callback);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Close Frame Previously Sent: ignoring: {} [{}]", closeInfo, callback);
|
||||
callback.succeed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Harsh disconnect
|
||||
*/
|
||||
|
@ -198,31 +202,31 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
{
|
||||
connection.disconnect();
|
||||
}
|
||||
|
||||
|
||||
public void dispatch(Runnable runnable)
|
||||
{
|
||||
executor.execute(runnable);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void doStart() throws Exception
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("starting - {}", this);
|
||||
|
||||
|
||||
Iterator<RemoteEndpointFactory> iter = ServiceLoader.load(RemoteEndpointFactory.class).iterator();
|
||||
if (iter.hasNext())
|
||||
remoteEndpointFactory = iter.next();
|
||||
|
||||
|
||||
if (remoteEndpointFactory == null)
|
||||
remoteEndpointFactory = this;
|
||||
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Using RemoteEndpointFactory: {}", remoteEndpointFactory);
|
||||
|
||||
|
||||
this.endpointFunctions = newEndpointFunctions(this.endpoint);
|
||||
addManaged(this.endpointFunctions);
|
||||
|
||||
|
||||
super.doStart();
|
||||
|
||||
connection.setMaxIdleTimeout(this.policy.getIdleTimeout());
|
||||
|
@ -232,27 +236,27 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
{
|
||||
fastFail = pendingError.get();
|
||||
}
|
||||
if(fastFail != null)
|
||||
if (fastFail != null)
|
||||
onError(fastFail);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void doStop() throws Exception
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("stopping - {}", this);
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
close(StatusCode.SHUTDOWN,"Shutdown");
|
||||
close(StatusCode.SHUTDOWN, "Shutdown");
|
||||
}
|
||||
catch (Throwable t)
|
||||
catch (Throwable ignore)
|
||||
{
|
||||
LOG.debug("During Connection Shutdown",t);
|
||||
LOG.ignore(ignore);
|
||||
}
|
||||
super.doStop();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void dump(Appendable out, String indent) throws IOException
|
||||
{
|
||||
|
@ -268,7 +272,7 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
out.append(outgoingHandler.toString()).append(System.lineSeparator());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
|
@ -298,17 +302,17 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public ByteBufferPool getBufferPool()
|
||||
{
|
||||
return this.connection.getBufferPool();
|
||||
}
|
||||
|
||||
|
||||
public ClassLoader getClassLoader()
|
||||
{
|
||||
return this.getClass().getClassLoader();
|
||||
}
|
||||
|
||||
|
||||
public LogicalConnection getConnection()
|
||||
{
|
||||
return connection;
|
||||
|
@ -324,17 +328,17 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
{
|
||||
return this.containerScope;
|
||||
}
|
||||
|
||||
|
||||
public Executor getExecutor()
|
||||
{
|
||||
return executor;
|
||||
}
|
||||
|
||||
|
||||
public ExtensionFactory getExtensionFactory()
|
||||
{
|
||||
return extensionFactory;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The idle timeout in milliseconds
|
||||
*/
|
||||
|
@ -343,43 +347,43 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
{
|
||||
return connection.getMaxIdleTimeout();
|
||||
}
|
||||
|
||||
|
||||
private Throwable getInvokedCause(Throwable t)
|
||||
{
|
||||
if (t instanceof FunctionCallException)
|
||||
{
|
||||
Throwable cause = ((FunctionCallException) t).getInvokedCause();
|
||||
if(cause != null)
|
||||
if (cause != null)
|
||||
return cause;
|
||||
}
|
||||
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getLocalAddress()
|
||||
{
|
||||
return connection.getLocalAddress();
|
||||
}
|
||||
|
||||
|
||||
@ManagedAttribute(readonly = true)
|
||||
public OutgoingFrames getOutgoingHandler()
|
||||
{
|
||||
return outgoingHandler;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public WebSocketPolicy getPolicy()
|
||||
{
|
||||
return this.policy;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getProtocolVersion()
|
||||
{
|
||||
return protocolVersion;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public RemoteEndpoint getRemote()
|
||||
{
|
||||
|
@ -387,44 +391,47 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
LOG.debug("{}.getRemote()", this.getClass().getSimpleName());
|
||||
|
||||
AtomicConnectionState.State state = connectionState.get();
|
||||
|
||||
|
||||
if ((state == AtomicConnectionState.State.OPEN) || (state == AtomicConnectionState.State.CONNECTED))
|
||||
{
|
||||
return remote;
|
||||
}
|
||||
|
||||
throw new WebSocketException("RemoteEndpoint unavailable, current state [" + state + "], expecting [OPEN or CONNECTED]");
|
||||
|
||||
String err = String.format("RemoteEndpoint unavailable, current state [%s], expecting [%s or %s]",
|
||||
state.name(), AtomicConnectionState.State.OPEN.name(), AtomicConnectionState.State.CONNECTED.name());
|
||||
|
||||
throw new WebSocketException(err);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getRemoteAddress()
|
||||
{
|
||||
return connection.getRemoteAddress();
|
||||
}
|
||||
|
||||
|
||||
public URI getRequestURI()
|
||||
{
|
||||
return requestURI;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public UpgradeRequest getUpgradeRequest()
|
||||
{
|
||||
return this.upgradeRequest;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public UpgradeResponse getUpgradeResponse()
|
||||
{
|
||||
return this.upgradeResponse;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public WebSocketSession getWebSocketSession()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
|
@ -440,14 +447,14 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
@Override
|
||||
public void incomingFrame(Frame frame, FrameCallback callback)
|
||||
{
|
||||
try(ThreadClassLoaderScope scope = new ThreadClassLoaderScope(classLoader))
|
||||
try (ThreadClassLoaderScope scope = new ThreadClassLoaderScope(classLoader))
|
||||
{
|
||||
if (connectionState.get() == AtomicConnectionState.State.OPEN)
|
||||
if (connectionState.get() != AtomicConnectionState.State.CLOSED)
|
||||
{
|
||||
// For endpoints that want to see raw frames.
|
||||
// These are immutable.
|
||||
endpointFunctions.onFrame(frame);
|
||||
|
||||
|
||||
byte opcode = frame.getOpCode();
|
||||
switch (opcode)
|
||||
{
|
||||
|
@ -457,13 +464,21 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
|
||||
if (connectionState.onClosing())
|
||||
{
|
||||
LOG.debug("ConnectionState: Transition to CLOSING");
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("ConnectionState: Transition to CLOSING");
|
||||
CloseFrame closeframe = (CloseFrame) frame;
|
||||
closeInfo = new CloseInfo(closeframe, true);
|
||||
}
|
||||
else if (connectionState.onClosed())
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("ConnectionState: Transition to CLOSED");
|
||||
connection.disconnect();
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.debug("ConnectionState: {} - Close Frame Received", connectionState);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("ConnectionState: {} - Close Frame Received", connectionState);
|
||||
}
|
||||
|
||||
if (closeInfo != null)
|
||||
|
@ -474,14 +489,14 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
|
||||
// let fill/parse continue
|
||||
callback.succeed();
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
case OpCode.PING:
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("PING: {}", BufferUtil.toDetailString(frame.getPayload()));
|
||||
|
||||
|
||||
ByteBuffer pongBuf;
|
||||
if (frame.hasPayload())
|
||||
{
|
||||
|
@ -493,17 +508,18 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
{
|
||||
pongBuf = ByteBuffer.allocate(0);
|
||||
}
|
||||
|
||||
|
||||
endpointFunctions.onPing(frame.getPayload());
|
||||
callback.succeed();
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
getRemote().sendPong(pongBuf);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
LOG.debug("Unable to send pong", t);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Unable to send pong", t);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -511,7 +527,7 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("PONG: {}", BufferUtil.toDetailString(frame.getPayload()));
|
||||
|
||||
|
||||
endpointFunctions.onPong(frame.getPayload());
|
||||
callback.succeed();
|
||||
break;
|
||||
|
@ -531,7 +547,7 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
endpointFunctions.onContinuation(frame, callback);
|
||||
if (activeMessageSink != null)
|
||||
activeMessageSink.accept(frame, callback);
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
default:
|
||||
|
@ -562,7 +578,7 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
{
|
||||
return this.connectionState.get() == AtomicConnectionState.State.OPEN;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isSecure()
|
||||
{
|
||||
|
@ -570,19 +586,19 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
{
|
||||
throw new IllegalStateException("No valid UpgradeRequest yet");
|
||||
}
|
||||
|
||||
|
||||
URI requestURI = upgradeRequest.getRequestURI();
|
||||
|
||||
|
||||
return "wss".equalsIgnoreCase(requestURI.getScheme());
|
||||
}
|
||||
|
||||
|
||||
public void notifyClose(int statusCode, String reason)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("notifyClose({},{}) [{}]", statusCode, reason, getState());
|
||||
}
|
||||
|
||||
|
||||
CloseInfo closeInfo = new CloseInfo(statusCode, reason);
|
||||
endpointFunctions.onClose(closeInfo);
|
||||
}
|
||||
|
@ -590,7 +606,7 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
/**
|
||||
* Error Event.
|
||||
* <p>
|
||||
* Can be seen from Session and Connection.
|
||||
* Can be seen from Session and Connection.
|
||||
* </p>
|
||||
*
|
||||
* @param t the raw cause
|
||||
|
@ -612,10 +628,10 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
|
||||
if (openFuture != null && !openFuture.isDone())
|
||||
openFuture.completeExceptionally(cause);
|
||||
|
||||
|
||||
// Forward Errors to User WebSocket Object
|
||||
endpointFunctions.onError(cause);
|
||||
|
||||
|
||||
if (cause instanceof NotUtf8Exception)
|
||||
{
|
||||
close(StatusCode.BAD_PAYLOAD, cause.getMessage(), onDisconnectCallback);
|
||||
|
@ -636,7 +652,7 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
{
|
||||
CloseException ce = (CloseException) cause;
|
||||
FrameCallback callback = EMPTY;
|
||||
|
||||
|
||||
// Force disconnect for protocol breaking status codes
|
||||
switch (ce.getStatusCode())
|
||||
{
|
||||
|
@ -645,6 +661,7 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
case StatusCode.BAD_PAYLOAD:
|
||||
case StatusCode.MESSAGE_TOO_LARGE:
|
||||
case StatusCode.POLICY_VIOLATION:
|
||||
case StatusCode.SERVER_ERROR:
|
||||
{
|
||||
callback = onDisconnectCallback;
|
||||
}
|
||||
|
@ -655,7 +672,7 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
else
|
||||
{
|
||||
LOG.warn("Unhandled Error (closing connection)", cause);
|
||||
|
||||
|
||||
// Exception on end-user WS-Endpoint.
|
||||
// Fast-fail & close connection with reason.
|
||||
int statusCode = StatusCode.SERVER_ERROR;
|
||||
|
@ -669,6 +686,7 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
|
||||
/**
|
||||
* Connection Disconnect Event
|
||||
*
|
||||
* @param connection the connection
|
||||
*/
|
||||
@Override
|
||||
|
@ -688,6 +706,7 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
|
||||
/**
|
||||
* Connection Open Event
|
||||
*
|
||||
* @param connection the connection
|
||||
*/
|
||||
@Override
|
||||
|
@ -701,9 +720,9 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
|
||||
public WebSocketRemoteEndpoint newRemoteEndpoint(LogicalConnection connection, OutgoingFrames outgoingFrames, BatchMode batchMode)
|
||||
{
|
||||
return new WebSocketRemoteEndpoint(this,outgoingHandler,getBatchMode());
|
||||
return new WebSocketRemoteEndpoint(this, outgoingHandler, getBatchMode());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Open/Activate the session
|
||||
*/
|
||||
|
@ -711,53 +730,78 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{}.open()", this.getClass().getSimpleName());
|
||||
|
||||
|
||||
if (remote != null)
|
||||
{
|
||||
// already opened
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
try (ThreadClassLoaderScope scope = new ThreadClassLoaderScope(classLoader))
|
||||
{
|
||||
// Upgrade success
|
||||
if(connectionState.onConnected())
|
||||
if (connectionState.onConnected())
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("ConnectionState: Transition to CONNECTED");
|
||||
|
||||
// Connect remote
|
||||
remote = remoteEndpointFactory.newRemoteEndpoint(connection, outgoingHandler, getBatchMode());
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{}.open() remote={}", this.getClass().getSimpleName(), remote);
|
||||
|
||||
// Open WebSocket
|
||||
endpointFunctions.onOpen(this);
|
||||
|
||||
// Open connection
|
||||
if(connectionState.onOpen())
|
||||
|
||||
try
|
||||
{
|
||||
// notify session listeners
|
||||
try
|
||||
// Open WebSocket
|
||||
endpointFunctions.onOpen(this);
|
||||
|
||||
// Open connection
|
||||
if (connectionState.onOpen())
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{}.onSessionOpened()", containerScope.getClass().getSimpleName());
|
||||
containerScope.onSessionOpened(this);
|
||||
LOG.debug("ConnectionState: Transition to OPEN");
|
||||
|
||||
// notify session listeners
|
||||
try
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{}.onSessionOpened()", containerScope.getClass().getSimpleName());
|
||||
containerScope.onSessionOpened(this);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
LOG.ignore(t);
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("open -> {}", dump());
|
||||
}
|
||||
|
||||
if (openFuture != null)
|
||||
{
|
||||
openFuture.complete(this);
|
||||
}
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
LOG.ignore(t);
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("open -> {}", dump());
|
||||
}
|
||||
|
||||
if (openFuture != null)
|
||||
{
|
||||
openFuture.complete(this);
|
||||
}
|
||||
|
||||
connection.fillInterested();
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
endpointFunctions.getLog().warn("Error during OPEN", t);
|
||||
onError(new CloseException(StatusCode.SERVER_ERROR, t));
|
||||
}
|
||||
|
||||
/* Perform fillInterested outside of onConnected / onOpen.
|
||||
*
|
||||
* This is to allow for 2 specific scenarios.
|
||||
*
|
||||
* 1) Fast Close
|
||||
* When an end users WSEndpoint.onOpen() calls
|
||||
* the Session.close() method.
|
||||
* This is a state transition of CONNECTING -> CONNECTED -> CLOSING
|
||||
* 2) Fast Fail
|
||||
* When an end users WSEndpoint.onOpen() throws an Exception.
|
||||
*/
|
||||
connection.fillInterested();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -778,17 +822,17 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
onError(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setExtensionFactory(ExtensionFactory extensionFactory)
|
||||
{
|
||||
this.extensionFactory = extensionFactory;
|
||||
}
|
||||
|
||||
|
||||
public void setFuture(CompletableFuture<Session> fut)
|
||||
{
|
||||
this.openFuture = fut;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the timeout in milliseconds
|
||||
*/
|
||||
|
@ -797,12 +841,12 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
{
|
||||
connection.setMaxIdleTimeout(ms);
|
||||
}
|
||||
|
||||
|
||||
public void setOutgoingHandler(OutgoingFrames outgoing)
|
||||
{
|
||||
this.outgoingHandler = outgoing;
|
||||
}
|
||||
|
||||
|
||||
public void setUpgradeRequest(UpgradeRequest request)
|
||||
{
|
||||
this.upgradeRequest = request;
|
||||
|
@ -824,18 +868,18 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setUpgradeResponse(UpgradeResponse response)
|
||||
{
|
||||
this.upgradeResponse = response;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SuspendToken suspend()
|
||||
{
|
||||
return connection.suspend();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the default (initial) value for the batching mode.
|
||||
*/
|
||||
|
@ -843,7 +887,7 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
{
|
||||
return this.batchmode;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
|
@ -861,7 +905,7 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
sb.append(',').append(getConnection().getClass().getSimpleName());
|
||||
if (getConnection() instanceof AbstractWebSocketConnection)
|
||||
{
|
||||
if(isOpen() && remote != null)
|
||||
if (isOpen() && remote != null)
|
||||
{
|
||||
sb.append(',').append(getRemoteAddress());
|
||||
if (getPolicy().getBehavior() == WebSocketBehavior.SERVER)
|
||||
|
@ -874,11 +918,11 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
sb.append(']');
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
public interface Listener
|
||||
{
|
||||
void onOpened(WebSocketSession session);
|
||||
|
||||
|
||||
void onClosed(WebSocketSession session);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,6 +79,7 @@ public class CommonEndpointFunctions<T extends Session> extends AbstractLifeCycl
|
|||
protected final WebSocketPolicy policy;
|
||||
protected final Executor executor;
|
||||
|
||||
protected Logger endpointLog;
|
||||
private T session;
|
||||
private Function<T, Void> onOpenFunction;
|
||||
private Function<CloseInfo, Void> onCloseFunction;
|
||||
|
@ -513,6 +514,16 @@ public class CommonEndpointFunctions<T extends Session> extends AbstractLifeCycl
|
|||
return executor;
|
||||
}
|
||||
|
||||
public Logger getLog()
|
||||
{
|
||||
if(endpointLog == null)
|
||||
{
|
||||
endpointLog = Log.getLogger(endpoint.getClass());
|
||||
}
|
||||
|
||||
return endpointLog;
|
||||
}
|
||||
|
||||
public T getSession()
|
||||
{
|
||||
return session;
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.eclipse.jetty.websocket.common.function;
|
|||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.FrameCallback;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.common.CloseInfo;
|
||||
|
@ -32,6 +33,8 @@ import org.eclipse.jetty.websocket.common.CloseInfo;
|
|||
*/
|
||||
public interface EndpointFunctions<T> extends LifeCycle
|
||||
{
|
||||
Logger getLog();
|
||||
|
||||
void onOpen(T session);
|
||||
|
||||
void onClose(CloseInfo close);
|
||||
|
|
|
@ -435,8 +435,10 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp
|
|||
@Override
|
||||
public void resume()
|
||||
{
|
||||
suspendToken.set(false);
|
||||
fillAndParse();
|
||||
if (suspendToken.compareAndSet(true, false))
|
||||
{
|
||||
fillAndParse();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean addListener(LogicalConnection.Listener listener)
|
||||
|
|
|
@ -50,6 +50,7 @@ public class LocalFuzzer implements AutoCloseable
|
|||
public final LocalFuzzer.Provider provider;
|
||||
public final UnitGenerator generator;
|
||||
public final LocalConnector.LocalEndPoint endPoint;
|
||||
public final HttpTester.Response upgradeResponse;
|
||||
|
||||
public LocalFuzzer(LocalFuzzer.Provider provider) throws Exception
|
||||
{
|
||||
|
@ -68,7 +69,7 @@ public class LocalFuzzer implements AutoCloseable
|
|||
LOG.debug("Request: {}", upgradeRequest);
|
||||
ByteBuffer upgradeRequestBytes = BufferUtil.toBuffer(upgradeRequest.toString(), StandardCharsets.UTF_8);
|
||||
this.endPoint = this.provider.newLocalConnection();
|
||||
performUpgrade(endPoint, upgradeRequestBytes);
|
||||
this.upgradeResponse = performUpgrade(endPoint, upgradeRequestBytes);
|
||||
this.generator = new UnitGenerator(WebSocketPolicy.newClientPolicy());
|
||||
}
|
||||
|
||||
|
@ -291,6 +292,27 @@ public class LocalFuzzer implements AutoCloseable
|
|||
endPoint.addInputEOF();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a ByteBuffer for each frame, and submit each to
|
||||
* {@link org.eclipse.jetty.server.LocalConnector.LocalEndPoint#addInput(ByteBuffer)}
|
||||
*
|
||||
* @param frames the list of frames to send
|
||||
*/
|
||||
public void sendFrames(WebSocketFrame ... frames)
|
||||
{
|
||||
boolean eof = false;
|
||||
for (WebSocketFrame f : frames)
|
||||
{
|
||||
ByteBuffer buffer = generator.generate(f);
|
||||
endPoint.addInput(buffer);
|
||||
if (f.getOpCode() == OpCode.CLOSE)
|
||||
eof = true;
|
||||
}
|
||||
|
||||
if (eof)
|
||||
endPoint.addInputEOF();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a ByteBuffer for each frame, and submit each to
|
||||
* {@link org.eclipse.jetty.server.LocalConnector.LocalEndPoint#addInput(ByteBuffer)}
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.util.Map;
|
|||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||
import org.eclipse.jetty.server.LocalConnector;
|
||||
|
@ -115,6 +116,14 @@ public class LocalServer extends ContainerLifeCycle implements LocalFuzzer.Provi
|
|||
return new LocalFuzzer(this, requestPath, upgradeRequest);
|
||||
}
|
||||
|
||||
protected Handler createRootHandler(Server server) throws Exception
|
||||
{
|
||||
servletContextHandler = new ServletContextHandler(server, "/", true, false);
|
||||
servletContextHandler.setContextPath("/");
|
||||
configureServletContextHandler(servletContextHandler);
|
||||
return servletContextHandler;
|
||||
}
|
||||
|
||||
protected void configureServletContextHandler(ServletContextHandler context) throws Exception
|
||||
{
|
||||
/* override to change context handler */
|
||||
|
@ -166,10 +175,8 @@ public class LocalServer extends ContainerLifeCycle implements LocalFuzzer.Provi
|
|||
localConnector = new LocalConnector(server);
|
||||
server.addConnector(localConnector);
|
||||
|
||||
servletContextHandler = new ServletContextHandler(server, "/", true, false);
|
||||
servletContextHandler.setContextPath("/");
|
||||
configureServletContextHandler(servletContextHandler);
|
||||
server.setHandler(servletContextHandler);
|
||||
Handler rootHandler = createRootHandler(server);
|
||||
server.setHandler(rootHandler);
|
||||
|
||||
// Start Server
|
||||
addBean(server);
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.tests;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.security.DigestOutputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.jetty.toolchain.test.Hex;
|
||||
import org.eclipse.jetty.toolchain.test.IO;
|
||||
import org.junit.Assert;
|
||||
|
||||
/**
|
||||
* Calculate the sha1sum for various content
|
||||
*/
|
||||
public class Sha1Sum
|
||||
{
|
||||
private static class NoOpOutputStream extends OutputStream
|
||||
{
|
||||
@Override
|
||||
public void write(byte[] b) throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public static String calculate(File file) throws NoSuchAlgorithmException, IOException
|
||||
{
|
||||
return calculate(file.toPath());
|
||||
}
|
||||
|
||||
public static String calculate(Path path) throws NoSuchAlgorithmException, IOException
|
||||
{
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA1");
|
||||
try (InputStream in = Files.newInputStream(path,StandardOpenOption.READ);
|
||||
NoOpOutputStream noop = new NoOpOutputStream();
|
||||
DigestOutputStream digester = new DigestOutputStream(noop,digest))
|
||||
{
|
||||
IO.copy(in,digester);
|
||||
return Hex.asHex(digest.digest());
|
||||
}
|
||||
}
|
||||
|
||||
public static String calculate(byte[] buf) throws NoSuchAlgorithmException
|
||||
{
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA1");
|
||||
digest.update(buf);
|
||||
return Hex.asHex(digest.digest());
|
||||
}
|
||||
|
||||
public static String calculate(byte[] buf, int offset, int len) throws NoSuchAlgorithmException
|
||||
{
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA1");
|
||||
digest.update(buf,offset,len);
|
||||
return Hex.asHex(digest.digest());
|
||||
}
|
||||
|
||||
public static String loadSha1(File sha1File) throws IOException
|
||||
{
|
||||
String contents = IO.readToString(sha1File);
|
||||
Pattern pat = Pattern.compile("^[0-9A-Fa-f]*");
|
||||
Matcher mat = pat.matcher(contents);
|
||||
Assert.assertTrue("Should have found HEX code in SHA1 file: " + sha1File,mat.find());
|
||||
return mat.group();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.tests;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.BatchMode;
|
||||
import org.eclipse.jetty.websocket.api.FrameCallback;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.extensions.ExtensionStack;
|
||||
import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory;
|
||||
import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope;
|
||||
|
||||
public class UnitExtensionStack extends ExtensionStack
|
||||
{
|
||||
public static UnitExtensionStack clientBased()
|
||||
{
|
||||
return policyBased(new WebSocketPolicy(WebSocketBehavior.CLIENT));
|
||||
}
|
||||
|
||||
public static UnitExtensionStack serverBased()
|
||||
{
|
||||
return policyBased(new WebSocketPolicy(WebSocketBehavior.SERVER));
|
||||
}
|
||||
|
||||
private static UnitExtensionStack policyBased(WebSocketPolicy policy)
|
||||
{
|
||||
SimpleContainerScope containerScope = new SimpleContainerScope(policy);
|
||||
WebSocketExtensionFactory extensionFactory = new WebSocketExtensionFactory(containerScope);
|
||||
return new UnitExtensionStack(extensionFactory);
|
||||
}
|
||||
|
||||
private UnitExtensionStack(WebSocketExtensionFactory extensionFactory)
|
||||
{
|
||||
super(extensionFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process frames
|
||||
*/
|
||||
public BlockingQueue<WebSocketFrame> processIncoming(BlockingQueue<WebSocketFrame> framesQueue)
|
||||
{
|
||||
BlockingQueue<WebSocketFrame> processed = new LinkedBlockingDeque<>();
|
||||
setNextIncoming((frame, callback) ->
|
||||
{
|
||||
processed.offer(WebSocketFrame.copy(frame));
|
||||
callback.succeed();
|
||||
});
|
||||
|
||||
FrameCallback callback = new FrameCallback.Adapter();
|
||||
for (WebSocketFrame frame : framesQueue)
|
||||
{
|
||||
incomingFrame(frame, callback);
|
||||
}
|
||||
|
||||
setNextIncoming(null);
|
||||
return processed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process frames as if they are for an outgoing path
|
||||
*
|
||||
* @param frames the frames to process
|
||||
* @return the processed frames (post extension stack)
|
||||
*/
|
||||
public List<WebSocketFrame> processOutgoing(List<WebSocketFrame> frames)
|
||||
{
|
||||
List<WebSocketFrame> captured = new ArrayList<>();
|
||||
setNextOutgoing((frame, callback, batchMode) ->
|
||||
{
|
||||
captured.add(WebSocketFrame.copy(frame));
|
||||
callback.succeed();
|
||||
});
|
||||
|
||||
FrameCallback callback = new FrameCallback.Adapter();
|
||||
for (WebSocketFrame frame : frames)
|
||||
{
|
||||
outgoingFrame(frame, callback, BatchMode.OFF);
|
||||
}
|
||||
|
||||
setNextOutgoing(null);
|
||||
return captured;
|
||||
}
|
||||
}
|
|
@ -24,20 +24,15 @@ import static org.junit.Assert.assertThat;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationConfiguration;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.plus.webapp.EnvConfiguration;
|
||||
import org.eclipse.jetty.plus.webapp.PlusConfiguration;
|
||||
import org.eclipse.jetty.server.LocalConnector;
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
|
||||
import org.eclipse.jetty.server.handler.HandlerCollection;
|
||||
import org.eclipse.jetty.toolchain.test.FS;
|
||||
|
@ -54,24 +49,18 @@ import org.eclipse.jetty.webapp.MetaInfConfiguration;
|
|||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.eclipse.jetty.webapp.WebInfConfiguration;
|
||||
import org.eclipse.jetty.webapp.WebXmlConfiguration;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.common.Parser;
|
||||
|
||||
/**
|
||||
* Utility to build out exploded directory WebApps, in the /target/tests/ directory, for testing out servers that use javax.websocket endpoints.
|
||||
* <p>
|
||||
* This is particularly useful when the WebSocket endpoints are discovered via the javax.websocket annotation scanning.
|
||||
*/
|
||||
public class WSServer implements LocalFuzzer.Provider
|
||||
public class WSServer extends LocalServer implements LocalFuzzer.Provider
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(WSServer.class);
|
||||
private final Path contextDir;
|
||||
private final String contextPath;
|
||||
private final ByteBufferPool bufferPool = new MappedByteBufferPool();
|
||||
private Server server;
|
||||
private URI serverUri;
|
||||
private ContextHandlerCollection contexts;
|
||||
private LocalConnector localConnector;
|
||||
private Path webinf;
|
||||
private Path classesDir;
|
||||
|
||||
|
@ -182,103 +171,16 @@ public class WSServer implements LocalFuzzer.Provider
|
|||
}
|
||||
}
|
||||
|
||||
public void dump()
|
||||
{
|
||||
server.dumpStdErr();
|
||||
}
|
||||
|
||||
public LocalConnector getLocalConnector()
|
||||
{
|
||||
return localConnector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Parser newClientParser(Parser.Handler parserHandler)
|
||||
{
|
||||
return new Parser(WebSocketPolicy.newClientPolicy(), bufferPool, parserHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalConnector.LocalEndPoint newLocalConnection()
|
||||
{
|
||||
return getLocalConnector().connect();
|
||||
}
|
||||
|
||||
public LocalFuzzer newLocalFuzzer() throws Exception
|
||||
{
|
||||
return new LocalFuzzer(this);
|
||||
}
|
||||
|
||||
public LocalFuzzer newLocalFuzzer(CharSequence requestPath) throws Exception
|
||||
{
|
||||
return new LocalFuzzer(this, requestPath);
|
||||
}
|
||||
|
||||
public LocalFuzzer newLocalFuzzer(CharSequence requestPath, Map<String,String> upgradeRequest) throws Exception
|
||||
{
|
||||
return new LocalFuzzer(this, requestPath, upgradeRequest);
|
||||
}
|
||||
|
||||
public URI getServerBaseURI()
|
||||
{
|
||||
return serverUri;
|
||||
}
|
||||
|
||||
public Server getServer()
|
||||
{
|
||||
return server;
|
||||
}
|
||||
|
||||
public Path getWebAppDir()
|
||||
{
|
||||
return this.contextDir;
|
||||
}
|
||||
|
||||
public void start() throws Exception
|
||||
@Override
|
||||
protected Handler createRootHandler(Server server) throws Exception
|
||||
{
|
||||
server = new Server();
|
||||
|
||||
// Main network connector
|
||||
ServerConnector connector = new ServerConnector(server);
|
||||
connector.setPort(0);
|
||||
server.addConnector(connector);
|
||||
|
||||
// Add Local Connector
|
||||
localConnector = new LocalConnector(server);
|
||||
server.addConnector(localConnector);
|
||||
|
||||
HandlerCollection handlers = new HandlerCollection();
|
||||
contexts = new ContextHandlerCollection();
|
||||
handlers.addHandler(contexts);
|
||||
server.setHandler(handlers);
|
||||
|
||||
server.start();
|
||||
|
||||
String host = connector.getHost();
|
||||
if (host == null)
|
||||
{
|
||||
host = "localhost";
|
||||
}
|
||||
int port = connector.getLocalPort();
|
||||
serverUri = new URI(String.format("ws://%s:%d%s/", host, port, contextPath));
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Server started on {}", serverUri);
|
||||
}
|
||||
|
||||
public void stop()
|
||||
{
|
||||
if (server == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
return contexts;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,204 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.tests.server;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.util.DecoratedObjectFactory;
|
||||
import org.eclipse.jetty.util.Decorator;
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketAdapter;
|
||||
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
|
||||
import org.eclipse.jetty.websocket.tests.Defaults;
|
||||
import org.eclipse.jetty.websocket.tests.SimpleServletServer;
|
||||
import org.eclipse.jetty.websocket.tests.TrackingEndpoint;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TestName;
|
||||
|
||||
public class DecoratorsLegacyTest
|
||||
{
|
||||
private static class DecoratorsSocket extends WebSocketAdapter
|
||||
{
|
||||
private final DecoratedObjectFactory objFactory;
|
||||
|
||||
public DecoratorsSocket(DecoratedObjectFactory objFactory)
|
||||
{
|
||||
this.objFactory = objFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWebSocketText(String message)
|
||||
{
|
||||
StringWriter str = new StringWriter();
|
||||
PrintWriter out = new PrintWriter(str);
|
||||
|
||||
if (objFactory != null)
|
||||
{
|
||||
out.printf("Object is a DecoratedObjectFactory%n");
|
||||
List<Decorator> decorators = objFactory.getDecorators();
|
||||
out.printf("Decorators.size = [%d]%n", decorators.size());
|
||||
for (Decorator decorator : decorators)
|
||||
{
|
||||
out.printf(" decorator[] = %s%n", decorator.getClass().getName());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
out.printf("DecoratedObjectFactory is NULL%n");
|
||||
}
|
||||
|
||||
getRemote().sendStringByFuture(str.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private static class DecoratorsCreator implements WebSocketCreator
|
||||
{
|
||||
@Override
|
||||
public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp)
|
||||
{
|
||||
ServletContext servletContext = req.getHttpServletRequest().getServletContext();
|
||||
DecoratedObjectFactory objFactory = (DecoratedObjectFactory) servletContext.getAttribute(DecoratedObjectFactory.ATTR);
|
||||
return new DecoratorsSocket(objFactory);
|
||||
}
|
||||
}
|
||||
|
||||
public static class DecoratorsRequestServlet extends WebSocketServlet
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final WebSocketCreator creator;
|
||||
|
||||
public DecoratorsRequestServlet(WebSocketCreator creator)
|
||||
{
|
||||
this.creator = creator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(WebSocketServletFactory factory)
|
||||
{
|
||||
factory.setCreator(this.creator);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private static class DummyLegacyDecorator implements org.eclipse.jetty.servlet.ServletContextHandler.Decorator
|
||||
{
|
||||
@Override
|
||||
public <T> T decorate(T o)
|
||||
{
|
||||
return o;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy(Object o)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private static SimpleServletServer server;
|
||||
private static DecoratorsCreator decoratorsCreator;
|
||||
|
||||
@BeforeClass
|
||||
public static void startServer() throws Exception
|
||||
{
|
||||
decoratorsCreator = new DecoratorsCreator();
|
||||
server = new SimpleServletServer(new DecoratorsRequestServlet(decoratorsCreator))
|
||||
{
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected void configureServletContextHandler(ServletContextHandler context)
|
||||
{
|
||||
context.getObjectFactory().clear();
|
||||
// Add decorator in the legacy way
|
||||
context.addDecorator(new DummyLegacyDecorator());
|
||||
}
|
||||
};
|
||||
server.start();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void stopServer() throws Exception
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@Rule
|
||||
public TestName testname = new TestName();
|
||||
|
||||
private WebSocketClient client;
|
||||
|
||||
@Before
|
||||
public void startClient() throws Exception
|
||||
{
|
||||
client = new WebSocketClient();
|
||||
client.start();
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopClient() throws Exception
|
||||
{
|
||||
client.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccessRequestCookies() throws Exception
|
||||
{
|
||||
client.setMaxIdleTimeout(TimeUnit.SECONDS.toMillis(1));
|
||||
|
||||
URI wsUri = server.getServerUri();
|
||||
|
||||
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
|
||||
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
|
||||
Future<Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
|
||||
|
||||
Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
|
||||
// Request Info
|
||||
clientSession.getRemote().sendString("info");
|
||||
|
||||
// Read message
|
||||
String incomingMsg = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
|
||||
assertThat("DecoratedObjectFactory", incomingMsg, containsString("Object is a DecoratedObjectFactory"));
|
||||
assertThat("decorators.size", incomingMsg, containsString("Decorators.size = [1]"));
|
||||
assertThat("decorator type", incomingMsg, containsString("decorator[] = " + DummyLegacyDecorator.class.getName()));
|
||||
|
||||
clientSession.close();
|
||||
}
|
||||
}
|
|
@ -18,14 +18,16 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.tests.server;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
@ -33,29 +35,34 @@ import javax.servlet.ServletContext;
|
|||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.util.DecoratedObjectFactory;
|
||||
import org.eclipse.jetty.util.Decorator;
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.StatusCode;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketAdapter;
|
||||
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.eclipse.jetty.websocket.common.CloseInfo;
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.frames.TextFrame;
|
||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
|
||||
import org.eclipse.jetty.websocket.tests.Defaults;
|
||||
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
|
||||
import org.eclipse.jetty.websocket.tests.SimpleServletServer;
|
||||
import org.eclipse.jetty.websocket.tests.TrackingEndpoint;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TestName;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
@Ignore
|
||||
/**
|
||||
* Test the {@link Decorator} features of the WebSocketServer
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class DecoratorsTest
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(DecoratorsTest.class);
|
||||
|
||||
private static class DecoratorsSocket extends WebSocketAdapter
|
||||
{
|
||||
private final DecoratedObjectFactory objFactory;
|
||||
|
@ -85,6 +92,8 @@ public class DecoratorsTest
|
|||
{
|
||||
out.printf("DecoratedObjectFactory is NULL%n");
|
||||
}
|
||||
|
||||
LOG.debug(out.toString());
|
||||
|
||||
getRemote().sendStringByFuture(str.toString());
|
||||
}
|
||||
|
@ -131,73 +140,100 @@ public class DecoratorsTest
|
|||
{
|
||||
}
|
||||
}
|
||||
|
||||
private static SimpleServletServer server;
|
||||
private static DecoratorsCreator decoratorsCreator;
|
||||
|
||||
@BeforeClass
|
||||
public static void startServer() throws Exception
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private static class DummyLegacyDecorator implements org.eclipse.jetty.servlet.ServletContextHandler.Decorator
|
||||
{
|
||||
decoratorsCreator = new DecoratorsCreator();
|
||||
server = new SimpleServletServer(new DecoratorsRequestServlet(decoratorsCreator))
|
||||
@Override
|
||||
public <T> T decorate(T o)
|
||||
{
|
||||
return o;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy(Object o)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private interface Case
|
||||
{
|
||||
void customize(ServletContextHandler context);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
public static Collection<Object[]> data()
|
||||
{
|
||||
List<Object[]> cases = new ArrayList<>();
|
||||
|
||||
cases.add(new Object[] {
|
||||
"Legacy Usage",
|
||||
(Case) (context) -> {
|
||||
context.getObjectFactory().clear();
|
||||
// Add decorator in the legacy way
|
||||
context.addDecorator(new DummyLegacyDecorator());
|
||||
},
|
||||
DummyLegacyDecorator.class
|
||||
});
|
||||
|
||||
cases.add(new Object[] {
|
||||
"Recommended Usage",
|
||||
(Case) (context) -> {
|
||||
// Add decorator in the new util way
|
||||
context.getObjectFactory().clear();
|
||||
context.getObjectFactory().addDecorator(new DummyUtilDecorator());
|
||||
},
|
||||
DummyUtilDecorator.class
|
||||
});
|
||||
|
||||
return cases;
|
||||
}
|
||||
|
||||
private SimpleServletServer server;
|
||||
private Class<?> expectedDecoratorClass;
|
||||
|
||||
public DecoratorsTest(String testId, Case testcase, Class<?> expectedDecoratorClass) throws Exception
|
||||
{
|
||||
LOG.debug("Testing {}", testId);
|
||||
this.expectedDecoratorClass = expectedDecoratorClass;
|
||||
server = new SimpleServletServer(new DecoratorsRequestServlet(new DecoratorsCreator()))
|
||||
{
|
||||
@Override
|
||||
protected void configureServletContextHandler(ServletContextHandler context)
|
||||
{
|
||||
// Add decorator in the new util way
|
||||
context.getObjectFactory().clear();
|
||||
context.getObjectFactory().addDecorator(new DummyUtilDecorator());
|
||||
super.configureServletContextHandler(context);
|
||||
testcase.customize(context);
|
||||
}
|
||||
};
|
||||
server.start();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void stopServer() throws Exception
|
||||
@After
|
||||
public void stopServer() throws Exception
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@Rule
|
||||
public TestName testname = new TestName();
|
||||
|
||||
private WebSocketClient client;
|
||||
|
||||
@Before
|
||||
public void startClient() throws Exception
|
||||
{
|
||||
client = new WebSocketClient();
|
||||
client.start();
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopClient() throws Exception
|
||||
{
|
||||
client.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccessRequestCookies() throws Exception
|
||||
{
|
||||
client.setMaxIdleTimeout(TimeUnit.SECONDS.toMillis(1));
|
||||
|
||||
URI wsUri = server.getServerUri();
|
||||
|
||||
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
|
||||
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
|
||||
Future<Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
|
||||
|
||||
Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
|
||||
// Request Info
|
||||
clientSession.getRemote().sendString("info");
|
||||
|
||||
// Read message
|
||||
String incomingMsg = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
|
||||
assertThat("DecoratedObjectFactory", incomingMsg, containsString("Object is a DecoratedObjectFactory"));
|
||||
assertThat("decorators.size", incomingMsg, containsString("Decorators.size = [1]"));
|
||||
assertThat("decorator type", incomingMsg, containsString("decorator[] = " + DummyUtilDecorator.class.getName()));
|
||||
|
||||
clientSession.close();
|
||||
try (LocalFuzzer session = server.newLocalFuzzer("/"))
|
||||
{
|
||||
session.sendFrames(
|
||||
new TextFrame().setPayload("info"),
|
||||
new CloseInfo(StatusCode.NORMAL).asFrame()
|
||||
);
|
||||
|
||||
BlockingQueue<WebSocketFrame> framesQueue = session.getOutputFrames();
|
||||
|
||||
WebSocketFrame frame = framesQueue.poll(1, TimeUnit.SECONDS);
|
||||
assertThat("Frame.opCode", frame.getOpCode(), is(OpCode.TEXT));
|
||||
|
||||
String payload = frame.getPayloadAsUTF8();
|
||||
assertThat("Text - DecoratedObjectFactory", payload, containsString("Object is a DecoratedObjectFactory"));
|
||||
assertThat("Text - decorators.size", payload, containsString("Decorators.size = [1]"));
|
||||
assertThat("Text - decorator type", payload, containsString("decorator[] = " + this.expectedDecoratorClass.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,92 +18,41 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.tests.server;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.eclipse.jetty.websocket.tests.Defaults;
|
||||
import org.eclipse.jetty.websocket.tests.SimpleServletServer;
|
||||
import org.eclipse.jetty.websocket.tests.TrackingEndpoint;
|
||||
import org.eclipse.jetty.websocket.tests.servlets.EchoServlet;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.eclipse.jetty.websocket.api.StatusCode;
|
||||
import org.eclipse.jetty.websocket.common.CloseInfo;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.frames.TextFrame;
|
||||
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
|
||||
import org.eclipse.jetty.websocket.tests.UpgradeUtils;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TestName;
|
||||
|
||||
public class FirefoxTest
|
||||
public class FirefoxTest extends AbstractLocalServerCase
|
||||
{
|
||||
private static SimpleServletServer server;
|
||||
|
||||
@BeforeClass
|
||||
public static void startServer() throws Exception
|
||||
{
|
||||
server = new SimpleServletServer(new EchoServlet());
|
||||
server.start();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void stopServer() throws Exception
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@Rule
|
||||
public TestName testname = new TestName();
|
||||
|
||||
private WebSocketClient client;
|
||||
|
||||
@Before
|
||||
public void startClient() throws Exception
|
||||
{
|
||||
client = new WebSocketClient();
|
||||
client.start();
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopClient() throws Exception
|
||||
{
|
||||
client.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectionKeepAlive() throws Exception
|
||||
{
|
||||
URI wsUri = server.getServerUri();
|
||||
|
||||
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
|
||||
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
|
||||
// Odd Connection Header value seen in Firefox
|
||||
upgradeRequest.setHeader("Connection", "keep-alive, Upgrade");
|
||||
Future<Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
|
||||
|
||||
Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
List<ExtensionConfig> extensionConfigList = clientSession.getUpgradeResponse().getExtensions();
|
||||
assertThat("Client Upgrade Response.Extensions", extensionConfigList.size(), is(1));
|
||||
assertThat("Client Upgrade Response.Extensions[0]", extensionConfigList.get(0).toString(), containsString("x-webkit-deflate-frame"));
|
||||
|
||||
// Message
|
||||
String msg = "this is an echo ... cho ... ho ... o";
|
||||
clientSession.getRemote().sendString(msg);
|
||||
|
||||
List<WebSocketFrame> send = new ArrayList<>();
|
||||
send.add(new TextFrame().setPayload(msg));
|
||||
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
|
||||
|
||||
// Read message
|
||||
String incomingMsg = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
|
||||
Assert.assertThat("Incoming Message", incomingMsg, is(msg));
|
||||
List<WebSocketFrame> expect = new ArrayList<>();
|
||||
expect.add(new TextFrame().setPayload(msg));
|
||||
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
|
||||
|
||||
clientSession.close();
|
||||
Map<String,String> upgradeHeaders = UpgradeUtils.newDefaultUpgradeRequestHeaders();
|
||||
// Odd Connection Header value seen in Firefox
|
||||
upgradeHeaders.put("Connection", "keep-alive, Upgrade");
|
||||
|
||||
try (LocalFuzzer session = server.newLocalFuzzer("/", upgradeHeaders))
|
||||
{
|
||||
session.sendBulk(send);
|
||||
session.expect(expect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,31 +20,31 @@ package org.eclipse.jetty.websocket.tests.server;
|
|||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.StatusCode;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketConstants;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory;
|
||||
import org.eclipse.jetty.websocket.common.CloseInfo;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.tests.Defaults;
|
||||
import org.eclipse.jetty.websocket.common.frames.TextFrame;
|
||||
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
|
||||
import org.eclipse.jetty.websocket.tests.SimpleServletServer;
|
||||
import org.eclipse.jetty.websocket.tests.TrackingEndpoint;
|
||||
import org.eclipse.jetty.websocket.tests.UnitExtensionStack;
|
||||
import org.eclipse.jetty.websocket.tests.UpgradeUtils;
|
||||
import org.eclipse.jetty.websocket.tests.servlets.EchoServlet;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Assume;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TestName;
|
||||
|
||||
public class FragmentExtensionTest
|
||||
{
|
||||
|
@ -63,24 +63,6 @@ public class FragmentExtensionTest
|
|||
server.stop();
|
||||
}
|
||||
|
||||
@Rule
|
||||
public TestName testname = new TestName();
|
||||
|
||||
private WebSocketClient client;
|
||||
|
||||
@Before
|
||||
public void startClient() throws Exception
|
||||
{
|
||||
client = new WebSocketClient();
|
||||
client.start();
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopClient() throws Exception
|
||||
{
|
||||
client.stop();
|
||||
}
|
||||
|
||||
private String[] split(String str, int partSize)
|
||||
{
|
||||
int strLength = str.length();
|
||||
|
@ -98,36 +80,41 @@ public class FragmentExtensionTest
|
|||
@Test
|
||||
public void testFragmentExtension() throws Exception
|
||||
{
|
||||
Assume.assumeTrue("Server has fragment registered",
|
||||
server.getWebSocketServletFactory().getExtensionFactory().isAvailable("fragment"));
|
||||
ExtensionFactory extensionFactory = server.getWebSocketServletFactory().getExtensionFactory();
|
||||
assertThat("Extension Factory", extensionFactory, notNullValue());
|
||||
Assume.assumeTrue("Server has fragment registered", extensionFactory.isAvailable("fragment"));
|
||||
|
||||
int fragSize = 4;
|
||||
|
||||
URI wsUri = server.getServerUri();
|
||||
|
||||
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
|
||||
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
|
||||
upgradeRequest.addExtensions("fragment;maxLength=" + fragSize);
|
||||
upgradeRequest.setSubProtocols("onConnect");
|
||||
Future<Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
|
||||
|
||||
Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
List<ExtensionConfig> extensionConfigList = clientSession.getUpgradeResponse().getExtensions();
|
||||
assertThat("Client Upgrade Response.Extensions", extensionConfigList.size(), is(1));
|
||||
assertThat("Client Upgrade Response.Extensions[0]", extensionConfigList.get(0).toString(), containsString("fragment"));
|
||||
|
||||
// Message
|
||||
String msg = "Sent as a long message that should be split";
|
||||
clientSession.getRemote().sendString(msg);
|
||||
|
||||
// Read message
|
||||
String parts[] = split(msg, fragSize);
|
||||
for (int i = 0; i < parts.length; i++)
|
||||
List<WebSocketFrame> send = new ArrayList<>();
|
||||
send.add(new TextFrame().setPayload(msg));
|
||||
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
|
||||
|
||||
Map<String,String> upgradeHeaders = UpgradeUtils.newDefaultUpgradeRequestHeaders();
|
||||
upgradeHeaders.put(WebSocketConstants.SEC_WEBSOCKET_EXTENSIONS, "fragment;maxLength=" + fragSize);
|
||||
|
||||
try (LocalFuzzer session = server.newLocalFuzzer("/", upgradeHeaders))
|
||||
{
|
||||
WebSocketFrame frame = clientSocket.framesQueue.poll();
|
||||
Assert.assertThat("text[" + i + "].payload", frame.getPayloadAsUTF8(), is(parts[i]));
|
||||
String negotiatedExtensions = session.upgradeResponse.get(WebSocketConstants.SEC_WEBSOCKET_EXTENSIONS);
|
||||
|
||||
List<ExtensionConfig> extensionConfigList = ExtensionConfig.parseList(negotiatedExtensions);
|
||||
assertThat("Client Upgrade Response.Extensions", extensionConfigList.size(), is(1));
|
||||
assertThat("Client Upgrade Response.Extensions[0]", extensionConfigList.get(0).toString(), containsString("fragment"));
|
||||
|
||||
UnitExtensionStack extensionStack = UnitExtensionStack.clientBased();
|
||||
List<WebSocketFrame> outgoingFrames = extensionStack.processOutgoing(send);
|
||||
session.sendBulk(outgoingFrames);
|
||||
|
||||
BlockingQueue<WebSocketFrame> framesQueue = session.getOutputFrames();
|
||||
BlockingQueue<WebSocketFrame> incomingFrames = extensionStack.processIncoming(framesQueue);
|
||||
|
||||
String parts[] = split(msg, fragSize);
|
||||
for (int i = 0; i < parts.length; i++)
|
||||
{
|
||||
WebSocketFrame frame = incomingFrames.poll();
|
||||
Assert.assertThat("text[" + i + "].payload", frame.getPayloadAsUTF8(), is(parts[i]));
|
||||
}
|
||||
}
|
||||
|
||||
clientSession.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,94 +20,82 @@ package org.eclipse.jetty.websocket.tests.server;
|
|||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.StatusCode;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketConstants;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.eclipse.jetty.websocket.tests.Defaults;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory;
|
||||
import org.eclipse.jetty.websocket.common.CloseInfo;
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.frames.TextFrame;
|
||||
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
|
||||
import org.eclipse.jetty.websocket.tests.SimpleServletServer;
|
||||
import org.eclipse.jetty.websocket.tests.TrackingEndpoint;
|
||||
import org.eclipse.jetty.websocket.tests.UnitExtensionStack;
|
||||
import org.eclipse.jetty.websocket.tests.UpgradeUtils;
|
||||
import org.eclipse.jetty.websocket.tests.servlets.EchoServlet;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Assume;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TestName;
|
||||
|
||||
public class IdentityExtensionTest
|
||||
{
|
||||
private static SimpleServletServer server;
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void startServer() throws Exception
|
||||
{
|
||||
server = new SimpleServletServer(new EchoServlet());
|
||||
server.start();
|
||||
}
|
||||
|
||||
|
||||
@AfterClass
|
||||
public static void stopServer() throws Exception
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@Rule
|
||||
public TestName testname = new TestName();
|
||||
|
||||
private WebSocketClient client;
|
||||
|
||||
@Before
|
||||
public void startClient() throws Exception
|
||||
{
|
||||
client = new WebSocketClient();
|
||||
client.start();
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopClient() throws Exception
|
||||
{
|
||||
client.stop();
|
||||
}
|
||||
|
||||
@Test(timeout = 60000)
|
||||
public void testIdentityExtension() throws Exception
|
||||
{
|
||||
Assume.assumeTrue("Server has identity extension registered",
|
||||
server.getWebSocketServletFactory().getExtensionFactory().isAvailable("identity"));
|
||||
|
||||
URI wsUri = server.getServerUri();
|
||||
|
||||
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
|
||||
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
|
||||
upgradeRequest.addExtensions("identity;param=0");
|
||||
upgradeRequest.addExtensions("identity;param=1, identity ; param = '2' ; other = ' some = value '");
|
||||
upgradeRequest.setSubProtocols("onConnect");
|
||||
Future<Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
|
||||
|
||||
Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
List<ExtensionConfig> extensionConfigList = clientSession.getUpgradeResponse().getExtensions();
|
||||
assertThat("Client Upgrade Response.Extensions", extensionConfigList.size(), is(3));
|
||||
assertThat("Client Upgrade Response.Extensions[0]", extensionConfigList.get(0).toString(), containsString("identity"));
|
||||
|
||||
// Message
|
||||
String msg = "Hello Identity";
|
||||
clientSession.getRemote().sendString(msg);
|
||||
|
||||
// Read message
|
||||
String incomingMsg = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
|
||||
Assert.assertThat("Incoming Message", incomingMsg, is(msg));
|
||||
|
||||
clientSession.close();
|
||||
ExtensionFactory extensionFactory = server.getWebSocketServletFactory().getExtensionFactory();
|
||||
assertThat("Extension Factory", extensionFactory, notNullValue());
|
||||
Assume.assumeTrue("Server has identity registered", extensionFactory.isAvailable("identity"));
|
||||
|
||||
List<WebSocketFrame> send = new ArrayList<>();
|
||||
send.add(new TextFrame().setPayload("Hello Identity"));
|
||||
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
|
||||
|
||||
Map<String, String> upgradeHeaders = UpgradeUtils.newDefaultUpgradeRequestHeaders();
|
||||
upgradeHeaders.put(WebSocketConstants.SEC_WEBSOCKET_EXTENSIONS, "identity;param=0, identity;param=1, identity ; param = '2' ; other = ' some = value '");
|
||||
|
||||
try (LocalFuzzer session = server.newLocalFuzzer("/", upgradeHeaders))
|
||||
{
|
||||
String negotiatedExtensions = session.upgradeResponse.get(WebSocketConstants.SEC_WEBSOCKET_EXTENSIONS);
|
||||
|
||||
List<ExtensionConfig> extensionConfigList = ExtensionConfig.parseList(negotiatedExtensions);
|
||||
assertThat("Client Upgrade Response.Extensions", extensionConfigList.size(), is(3));
|
||||
assertThat("Client Upgrade Response.Extensions[0]", extensionConfigList.get(0).toString(), containsString("identity"));
|
||||
|
||||
UnitExtensionStack extensionStack = UnitExtensionStack.clientBased();
|
||||
List<WebSocketFrame> outgoingFrames = extensionStack.processOutgoing(send);
|
||||
session.sendBulk(outgoingFrames);
|
||||
|
||||
BlockingQueue<WebSocketFrame> framesQueue = session.getOutputFrames();
|
||||
BlockingQueue<WebSocketFrame> incomingFrames = extensionStack.processIncoming(framesQueue);
|
||||
|
||||
WebSocketFrame frame = incomingFrames.poll();
|
||||
Assert.assertThat("Frame.opCode", frame.getOpCode(), is(OpCode.TEXT));
|
||||
Assert.assertThat("Frame.text-payload", frame.getPayloadAsUTF8(), is("Hello Identity"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,25 +18,24 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.tests.server;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.StatusCode;
|
||||
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
||||
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.eclipse.jetty.websocket.common.CloseInfo;
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.frames.TextFrame;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
|
||||
import org.eclipse.jetty.websocket.tests.Defaults;
|
||||
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
|
||||
import org.eclipse.jetty.websocket.tests.SimpleServletServer;
|
||||
import org.eclipse.jetty.websocket.tests.TrackingEndpoint;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
@ -45,7 +44,7 @@ import org.junit.rules.TestName;
|
|||
public class IdleTimeoutTest
|
||||
{
|
||||
@WebSocket(maxIdleTime = 500)
|
||||
public static class FastTimeoutRFCSocket extends RFC6455Socket
|
||||
public static class FastTimeoutSocket
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -55,11 +54,14 @@ public class IdleTimeoutTest
|
|||
@Override
|
||||
public void configure(WebSocketServletFactory factory)
|
||||
{
|
||||
factory.register(FastTimeoutRFCSocket.class);
|
||||
factory.register(FastTimeoutSocket.class);
|
||||
}
|
||||
}
|
||||
|
||||
private static SimpleServletServer server;
|
||||
protected static SimpleServletServer server;
|
||||
|
||||
@Rule
|
||||
public TestName testname = new TestName();
|
||||
|
||||
@BeforeClass
|
||||
public static void startServer() throws Exception
|
||||
|
@ -74,24 +76,6 @@ public class IdleTimeoutTest
|
|||
server.stop();
|
||||
}
|
||||
|
||||
@Rule
|
||||
public TestName testname = new TestName();
|
||||
|
||||
private WebSocketClient client;
|
||||
|
||||
@Before
|
||||
public void startClient() throws Exception
|
||||
{
|
||||
client = new WebSocketClient();
|
||||
client.start();
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopClient() throws Exception
|
||||
{
|
||||
client.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IdleTimeout on server.
|
||||
*
|
||||
|
@ -100,32 +84,19 @@ public class IdleTimeoutTest
|
|||
@Test
|
||||
public void testIdleTimeout() throws Exception
|
||||
{
|
||||
client.setMaxIdleTimeout(2500);
|
||||
URI wsUri = server.getServerUri();
|
||||
|
||||
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
|
||||
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
|
||||
upgradeRequest.setSubProtocols("onConnect");
|
||||
Future<Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
|
||||
|
||||
Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
|
||||
// This wait should be shorter than client timeout above, but
|
||||
// longer than server timeout configured in FastTimeoutRFCSocket
|
||||
// eg: websocket server endpoint timeout < this timeout < websocket client idle timeout
|
||||
TimeUnit.MILLISECONDS.sleep(1000);
|
||||
|
||||
// Write to server
|
||||
// This action is possible, but does nothing.
|
||||
// Server could be in a half-closed state at this point.
|
||||
// Where the server read is closed (due to timeout), but the server write is still open.
|
||||
// The server could not read this frame, if it is in this half closed state
|
||||
clientSession.getRemote().sendString("Hello");
|
||||
|
||||
// Expect closure, as server should have timed out
|
||||
clientSocket.awaitCloseEvent("Client");
|
||||
clientSocket.assertCloseInfo("Client", StatusCode.SHUTDOWN, containsString("Timeout"));
|
||||
|
||||
clientSession.close();
|
||||
try (LocalFuzzer session = server.newLocalFuzzer())
|
||||
{
|
||||
// wait 1 second to allow timeout to fire off
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
|
||||
session.sendFrames(new TextFrame().setPayload("You shouldn't be there"));
|
||||
|
||||
BlockingQueue<WebSocketFrame> framesQueue = session.getOutputFrames();
|
||||
WebSocketFrame frame = framesQueue.poll(1, TimeUnit.SECONDS);
|
||||
assertThat("Frame.opCode", frame.getOpCode(), is(OpCode.CLOSE));
|
||||
CloseInfo closeInfo = new CloseInfo(frame);
|
||||
assertThat("Close.statusCode", closeInfo.getStatusCode(), is(StatusCode.SHUTDOWN));
|
||||
assertThat("Close.reason", closeInfo.getReason(), containsString("Timeout"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,105 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.tests.server;
|
||||
|
||||
import static org.hamcrest.Matchers.anyOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
|
||||
import java.net.HttpCookie;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.eclipse.jetty.websocket.tests.Defaults;
|
||||
import org.eclipse.jetty.websocket.tests.SimpleServletServer;
|
||||
import org.eclipse.jetty.websocket.tests.TrackingEndpoint;
|
||||
import org.eclipse.jetty.websocket.tests.servlets.EchoServlet;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TestName;
|
||||
|
||||
public class RequestHeadersTest
|
||||
{
|
||||
private static SimpleServletServer server;
|
||||
|
||||
@BeforeClass
|
||||
public static void startServer() throws Exception
|
||||
{
|
||||
server = new SimpleServletServer(new EchoServlet());
|
||||
server.start();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void stopServer() throws Exception
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@Rule
|
||||
public TestName testname = new TestName();
|
||||
|
||||
private WebSocketClient client;
|
||||
|
||||
@Before
|
||||
public void startClient() throws Exception
|
||||
{
|
||||
client = new WebSocketClient();
|
||||
client.start();
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopClient() throws Exception
|
||||
{
|
||||
client.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccessRequestCookies() throws Exception
|
||||
{
|
||||
URI wsUri = server.getServerUri();
|
||||
client.setMaxIdleTimeout(1000);
|
||||
|
||||
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
|
||||
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
|
||||
upgradeRequest.setHeader("Cookie", "fruit=Pear; type=Anjou");
|
||||
Future<Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
|
||||
|
||||
Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
|
||||
List<HttpCookie> cookies = clientSession.getUpgradeRequest().getCookies();
|
||||
Assert.assertThat("Request cookies", cookies, notNullValue());
|
||||
Assert.assertThat("Request cookies.size", cookies.size(), is(2));
|
||||
for (HttpCookie cookie : cookies)
|
||||
{
|
||||
Assert.assertThat("Cookie name", cookie.getName(), anyOf(is("fruit"), is("type")));
|
||||
Assert.assertThat("Cookie value", cookie.getValue(), anyOf(is("Pear"), is("Anjou")));
|
||||
}
|
||||
clientSession.close();
|
||||
}
|
||||
}
|
|
@ -18,11 +18,8 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.tests.server;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.SuspendToken;
|
||||
|
@ -30,24 +27,20 @@ import org.eclipse.jetty.websocket.api.WriteCallback;
|
|||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
|
||||
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
||||
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.frames.CloseFrame;
|
||||
import org.eclipse.jetty.websocket.common.frames.TextFrame;
|
||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
|
||||
import org.eclipse.jetty.websocket.tests.Defaults;
|
||||
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
|
||||
import org.eclipse.jetty.websocket.tests.SimpleServletServer;
|
||||
import org.eclipse.jetty.websocket.tests.TrackingEndpoint;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TestName;
|
||||
|
||||
public class SuspendResumeTest
|
||||
{
|
||||
|
@ -69,7 +62,6 @@ public class SuspendResumeTest
|
|||
this.session.getRemote().sendString(message,
|
||||
new WriteCallback()
|
||||
{
|
||||
|
||||
@Override
|
||||
public void writeSuccess()
|
||||
{
|
||||
|
@ -94,7 +86,7 @@ public class SuspendResumeTest
|
|||
}
|
||||
}
|
||||
|
||||
public static class EchoServlet extends WebSocketServlet
|
||||
public static class BackPressureServlet extends WebSocketServlet
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
@ -110,7 +102,7 @@ public class SuspendResumeTest
|
|||
@BeforeClass
|
||||
public static void startServer() throws Exception
|
||||
{
|
||||
server = new SimpleServletServer(new EchoServlet());
|
||||
server = new SimpleServletServer(new BackPressureServlet());
|
||||
server.start();
|
||||
}
|
||||
|
||||
|
@ -120,46 +112,43 @@ public class SuspendResumeTest
|
|||
server.stop();
|
||||
}
|
||||
|
||||
@Rule
|
||||
public TestName testname = new TestName();
|
||||
|
||||
private WebSocketClient client;
|
||||
|
||||
@Before
|
||||
public void startClient() throws Exception
|
||||
{
|
||||
client = new WebSocketClient();
|
||||
client.start();
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopClient() throws Exception
|
||||
{
|
||||
client.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuspendResume() throws Exception
|
||||
{
|
||||
URI wsUri = server.getServerUri();
|
||||
List<WebSocketFrame> send = new ArrayList<>();
|
||||
send.add(new TextFrame().setPayload("echo1"));
|
||||
send.add(new TextFrame().setPayload("echo2"));
|
||||
send.add(new CloseFrame());
|
||||
|
||||
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
|
||||
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
|
||||
Future<Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
|
||||
List<WebSocketFrame> expect = new ArrayList<>();
|
||||
expect.add(new TextFrame().setPayload("echo1"));
|
||||
expect.add(new TextFrame().setPayload("echo2"));
|
||||
expect.add(new CloseFrame());
|
||||
|
||||
Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
try (LocalFuzzer session = server.newLocalFuzzer())
|
||||
{
|
||||
session.sendBulk(send);
|
||||
session.expect(expect);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuspendResume_SmallBuffers() throws Exception
|
||||
{
|
||||
List<WebSocketFrame> send = new ArrayList<>();
|
||||
send.add(new TextFrame().setPayload("echo1"));
|
||||
send.add(new TextFrame().setPayload("echo2"));
|
||||
send.add(new CloseFrame());
|
||||
|
||||
// Message
|
||||
clientSession.getRemote().sendString("echo1");
|
||||
clientSession.getRemote().sendString("echo2");
|
||||
List<WebSocketFrame> expect = new ArrayList<>();
|
||||
expect.add(new TextFrame().setPayload("echo1"));
|
||||
expect.add(new TextFrame().setPayload("echo2"));
|
||||
expect.add(new CloseFrame());
|
||||
|
||||
// Read message
|
||||
String incomingMsg;
|
||||
incomingMsg = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
|
||||
Assert.assertThat("Incoming Message 1", incomingMsg, is("echo1"));
|
||||
incomingMsg = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
|
||||
Assert.assertThat("Incoming Message 2", incomingMsg, is("echo2"));
|
||||
|
||||
clientSession.close();
|
||||
try (LocalFuzzer session = server.newLocalFuzzer())
|
||||
{
|
||||
session.sendSegmented(send, 2);
|
||||
session.expect(expect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,42 +18,43 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.tests.server;
|
||||
|
||||
import static org.hamcrest.Matchers.anything;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.net.URI;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.log.StacklessLogging;
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.StatusCode;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketAdapter;
|
||||
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketConstants;
|
||||
import org.eclipse.jetty.websocket.common.CloseInfo;
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketSession;
|
||||
import org.eclipse.jetty.websocket.common.frames.TextFrame;
|
||||
import org.eclipse.jetty.websocket.server.WebSocketServerFactory;
|
||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
|
||||
import org.eclipse.jetty.websocket.tests.Defaults;
|
||||
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
|
||||
import org.eclipse.jetty.websocket.tests.SimpleServletServer;
|
||||
import org.eclipse.jetty.websocket.tests.TrackingEndpoint;
|
||||
import org.eclipse.jetty.websocket.tests.UpgradeUtils;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TestName;
|
||||
|
||||
/**
|
||||
* Tests various close scenarios
|
||||
|
@ -61,310 +62,254 @@ import org.junit.rules.TestName;
|
|||
@Ignore
|
||||
public class WebSocketCloseTest
|
||||
{
|
||||
static class AbstractCloseSocket extends WebSocketAdapter
|
||||
/**
|
||||
* On Message, return container information
|
||||
*/
|
||||
public static class ContainerSocket extends WebSocketAdapter
|
||||
{
|
||||
public CountDownLatch closeLatch = new CountDownLatch(1);
|
||||
public String closeReason = null;
|
||||
public int closeStatusCode = -1;
|
||||
public List<Throwable> errors = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void onWebSocketClose(int statusCode, String reason)
|
||||
private static final Logger LOG = Log.getLogger(WebSocketCloseTest.ContainerSocket.class);
|
||||
private final WebSocketServerFactory container;
|
||||
private Session session;
|
||||
|
||||
public ContainerSocket(WebSocketServerFactory container)
|
||||
{
|
||||
LOG.debug("onWebSocketClose({}, {})",statusCode,reason);
|
||||
this.closeStatusCode = statusCode;
|
||||
this.closeReason = reason;
|
||||
closeLatch.countDown();
|
||||
this.container = container;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onWebSocketError(Throwable cause)
|
||||
public void onWebSocketText(String message)
|
||||
{
|
||||
errors.add(cause);
|
||||
LOG.debug("onWebSocketText({})", message);
|
||||
if (message.equalsIgnoreCase("openSessions"))
|
||||
{
|
||||
try
|
||||
{
|
||||
Collection<WebSocketSession> sessions = container.getOpenSessions();
|
||||
|
||||
StringBuilder ret = new StringBuilder();
|
||||
ret.append("openSessions.size=").append(sessions.size()).append('\n');
|
||||
int idx = 0;
|
||||
for (WebSocketSession sess : sessions)
|
||||
{
|
||||
ret.append('[').append(idx++).append("] ").append(sess.toString()).append('\n');
|
||||
}
|
||||
session.getRemote().sendString(ret.toString());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
session.close(StatusCode.NORMAL, "ContainerSocket");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWebSocketConnect(Session sess)
|
||||
{
|
||||
LOG.debug("onWebSocketConnect({})", sess);
|
||||
this.session = sess;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
|
||||
/**
|
||||
* On Connect, close socket
|
||||
*/
|
||||
public static class FastCloseSocket extends WebSocketAdapter
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(WebSocketCloseTest.FastCloseSocket.class);
|
||||
|
||||
@Override
|
||||
public void onWebSocketConnect(Session sess)
|
||||
{
|
||||
LOG.debug("onWebSocketConnect({})", sess);
|
||||
sess.close(StatusCode.NORMAL, "FastCloseServer");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* On Connect, throw unhandled exception
|
||||
*/
|
||||
public static class FastFailSocket extends WebSocketAdapter
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(WebSocketCloseTest.FastFailSocket.class);
|
||||
|
||||
@Override
|
||||
public void onWebSocketConnect(Session sess)
|
||||
{
|
||||
LOG.debug("onWebSocketConnect({})", sess);
|
||||
// Test failure due to unhandled exception
|
||||
// this should trigger a fast-fail closure during open/connect
|
||||
throw new RuntimeException("Intentional FastFail");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* On Message, drop connection
|
||||
*/
|
||||
public static class DropServerConnectionSocket extends WebSocketAdapter
|
||||
{
|
||||
@Override
|
||||
public void onWebSocketText(String message)
|
||||
{
|
||||
try
|
||||
{
|
||||
getSession().disconnect();
|
||||
}
|
||||
catch (IOException ignore)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class CloseServlet extends WebSocketServlet implements WebSocketCreator
|
||||
{
|
||||
private WebSocketServerFactory serverFactory;
|
||||
|
||||
|
||||
@Override
|
||||
public void configure(WebSocketServletFactory factory)
|
||||
{
|
||||
factory.setCreator(this);
|
||||
if (factory instanceof WebSocketServerFactory)
|
||||
{
|
||||
this.serverFactory = (WebSocketServerFactory)factory;
|
||||
this.serverFactory = (WebSocketServerFactory) factory;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp)
|
||||
{
|
||||
if (req.hasSubProtocol("fastclose"))
|
||||
{
|
||||
closeSocket = new FastCloseSocket();
|
||||
return closeSocket;
|
||||
return new FastCloseSocket();
|
||||
}
|
||||
|
||||
|
||||
if (req.hasSubProtocol("fastfail"))
|
||||
{
|
||||
closeSocket = new FastFailSocket();
|
||||
return closeSocket;
|
||||
return new FastFailSocket();
|
||||
}
|
||||
|
||||
|
||||
if (req.hasSubProtocol("drop"))
|
||||
{
|
||||
return new DropServerConnectionSocket();
|
||||
}
|
||||
|
||||
if (req.hasSubProtocol("container"))
|
||||
{
|
||||
closeSocket = new ContainerSocket(serverFactory);
|
||||
return closeSocket;
|
||||
return new ContainerSocket(serverFactory);
|
||||
}
|
||||
|
||||
return new RFC6455Socket();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* On Message, return container information
|
||||
*/
|
||||
public static class ContainerSocket extends AbstractCloseSocket
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(WebSocketCloseTest.ContainerSocket.class);
|
||||
private final WebSocketServerFactory container;
|
||||
private Session session;
|
||||
|
||||
public ContainerSocket(WebSocketServerFactory container)
|
||||
{
|
||||
this.container = container;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWebSocketText(String message)
|
||||
{
|
||||
LOG.debug("onWebSocketText({})",message);
|
||||
if (message.equalsIgnoreCase("openSessions"))
|
||||
{
|
||||
Collection<WebSocketSession> sessions = container.getOpenSessions();
|
||||
|
||||
StringBuilder ret = new StringBuilder();
|
||||
ret.append("openSessions.size=").append(sessions.size()).append('\n');
|
||||
int idx = 0;
|
||||
for (WebSocketSession sess : sessions)
|
||||
{
|
||||
ret.append('[').append(idx++).append("] ").append(sess.toString()).append('\n');
|
||||
}
|
||||
session.getRemote().sendStringByFuture(ret.toString());
|
||||
}
|
||||
session.close(StatusCode.NORMAL,"ContainerSocket");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWebSocketConnect(Session sess)
|
||||
{
|
||||
LOG.debug("onWebSocketConnect({})",sess);
|
||||
this.session = sess;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* On Connect, close socket
|
||||
*/
|
||||
public static class FastCloseSocket extends AbstractCloseSocket
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(WebSocketCloseTest.FastCloseSocket.class);
|
||||
|
||||
@Override
|
||||
public void onWebSocketConnect(Session sess)
|
||||
{
|
||||
LOG.debug("onWebSocketConnect({})",sess);
|
||||
sess.close(StatusCode.NORMAL,"FastCloseServer");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* On Connect, throw unhandled exception
|
||||
*/
|
||||
public static class FastFailSocket extends AbstractCloseSocket
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(WebSocketCloseTest.FastFailSocket.class);
|
||||
|
||||
@Override
|
||||
public void onWebSocketConnect(Session sess)
|
||||
{
|
||||
LOG.debug("onWebSocketConnect({})",sess);
|
||||
// Test failure due to unhandled exception
|
||||
// this should trigger a fast-fail closure during open/connect
|
||||
throw new RuntimeException("Intentional FastFail");
|
||||
}
|
||||
}
|
||||
|
||||
private static final Logger LOG = Log.getLogger(WebSocketCloseTest.class);
|
||||
|
||||
private static SimpleServletServer server;
|
||||
private static AbstractCloseSocket closeSocket;
|
||||
|
||||
@BeforeClass
|
||||
public static void startServer() throws Exception
|
||||
|
||||
private SimpleServletServer server;
|
||||
|
||||
@Before
|
||||
public void startServer() throws Exception
|
||||
{
|
||||
server = new SimpleServletServer(new CloseServlet());
|
||||
server.start();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void stopServer() throws Exception
|
||||
|
||||
@After
|
||||
public void stopServer() throws Exception
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@Rule
|
||||
public TestName testname = new TestName();
|
||||
|
||||
private WebSocketClient client;
|
||||
|
||||
@Before
|
||||
public void startClient() throws Exception
|
||||
{
|
||||
client = new WebSocketClient();
|
||||
client.start();
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopClient() throws Exception
|
||||
{
|
||||
client.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test fast close (bug #403817)
|
||||
*
|
||||
* @throws Exception
|
||||
* on test failure
|
||||
*
|
||||
* @throws Exception on test failure
|
||||
*/
|
||||
@Test
|
||||
public void testFastClose() throws Exception
|
||||
public void fastClose() throws Exception
|
||||
{
|
||||
client.setMaxIdleTimeout(5000);
|
||||
URI wsUri = server.getServerUri();
|
||||
|
||||
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
|
||||
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
|
||||
upgradeRequest.setSubProtocols("fastclose");
|
||||
Future<Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
|
||||
|
||||
Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
|
||||
clientSocket.awaitCloseEvent("Client");
|
||||
clientSocket.assertCloseInfo("Client", StatusCode.NORMAL, anything());
|
||||
Map<String, String> upgradeHeaders = UpgradeUtils.newDefaultUpgradeRequestHeaders();
|
||||
upgradeHeaders.put(WebSocketConstants.SEC_WEBSOCKET_PROTOCOL, "fastclose");
|
||||
|
||||
clientSession.close();
|
||||
List<WebSocketFrame> expect = new ArrayList<>();
|
||||
expect.add(new CloseInfo(StatusCode.NORMAL, "FastCloseServer").asFrame());
|
||||
|
||||
try (LocalFuzzer session = server.newLocalFuzzer("/", upgradeHeaders))
|
||||
{
|
||||
session.sendFrames(new CloseInfo(StatusCode.NORMAL).asFrame());
|
||||
session.expect(expect);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test fast fail (bug #410537)
|
||||
*
|
||||
* @throws Exception
|
||||
* on test failure
|
||||
*
|
||||
* @throws Exception on test failure
|
||||
*/
|
||||
@Test
|
||||
public void testFastFail() throws Exception
|
||||
public void fastFail() throws Exception
|
||||
{
|
||||
client.setMaxIdleTimeout(1000);
|
||||
URI wsUri = server.getServerUri();
|
||||
|
||||
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
|
||||
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
|
||||
upgradeRequest.setSubProtocols("fastfail");
|
||||
Future<Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
|
||||
|
||||
Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
|
||||
clientSocket.awaitCloseEvent("Client");
|
||||
clientSocket.assertCloseInfo("Client", StatusCode.SERVER_ERROR, anything());
|
||||
|
||||
clientSession.close();
|
||||
Map<String, String> upgradeHeaders = UpgradeUtils.newDefaultUpgradeRequestHeaders();
|
||||
upgradeHeaders.put(WebSocketConstants.SEC_WEBSOCKET_PROTOCOL, "fastfail");
|
||||
|
||||
List<WebSocketFrame> expect = new ArrayList<>();
|
||||
expect.add(new CloseInfo(StatusCode.SERVER_ERROR).asFrame());
|
||||
|
||||
try (StacklessLogging ignore = new StacklessLogging(FastFailSocket.class);
|
||||
LocalFuzzer session = server.newLocalFuzzer("/", upgradeHeaders))
|
||||
{
|
||||
session.expect(expect);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void dropServerConnection() throws Exception
|
||||
{
|
||||
Map<String, String> upgradeHeaders = UpgradeUtils.newDefaultUpgradeRequestHeaders();
|
||||
upgradeHeaders.put(WebSocketConstants.SEC_WEBSOCKET_PROTOCOL, "drop");
|
||||
|
||||
try (LocalFuzzer session = server.newLocalFuzzer("/", upgradeHeaders))
|
||||
{
|
||||
session.sendFrames(new TextFrame().setPayload("drop"));
|
||||
BlockingQueue<WebSocketFrame> framesQueue = session.getOutputFrames();
|
||||
assertThat("No frames as output", framesQueue.size(), Matchers.is(0));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test session open session cleanup (bug #474936)
|
||||
*
|
||||
* @throws Exception
|
||||
* on test failure
|
||||
*
|
||||
* @throws Exception on test failure
|
||||
*/
|
||||
@Test
|
||||
public void testOpenSessionCleanup() throws Exception
|
||||
{
|
||||
fastFail();
|
||||
fastClose();
|
||||
dropConnection();
|
||||
|
||||
client.setMaxIdleTimeout(1000);
|
||||
URI wsUri = server.getServerUri();
|
||||
|
||||
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
|
||||
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
|
||||
upgradeRequest.setSubProtocols("container");
|
||||
Future<Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
|
||||
|
||||
Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
dropClientConnection();
|
||||
|
||||
clientSession.getRemote().sendString("openSessions");
|
||||
Map<String, String> upgradeHeaders = UpgradeUtils.newDefaultUpgradeRequestHeaders();
|
||||
upgradeHeaders.put(WebSocketConstants.SEC_WEBSOCKET_PROTOCOL, "container");
|
||||
|
||||
String incomingMessage = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
|
||||
assertThat("Incoming Message", incomingMessage, containsString("openSessions.size=1\n"));
|
||||
|
||||
clientSocket.awaitCloseEvent("Client");
|
||||
clientSocket.assertCloseInfo("Client", StatusCode.NORMAL, anything());
|
||||
}
|
||||
|
||||
@SuppressWarnings("Duplicates")
|
||||
private void fastClose() throws Exception
|
||||
{
|
||||
client.setMaxIdleTimeout(1000);
|
||||
URI wsUri = server.getServerUri();
|
||||
|
||||
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
|
||||
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
|
||||
upgradeRequest.setSubProtocols("fastclose");
|
||||
Future<Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
|
||||
|
||||
Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
|
||||
clientSocket.awaitCloseEvent("Client");
|
||||
clientSocket.assertCloseInfo("Client", StatusCode.NORMAL, anything());
|
||||
|
||||
clientSession.close();
|
||||
}
|
||||
|
||||
private void fastFail() throws Exception
|
||||
{
|
||||
client.setMaxIdleTimeout(1000);
|
||||
URI wsUri = server.getServerUri();
|
||||
|
||||
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
|
||||
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
|
||||
upgradeRequest.setSubProtocols("fastfail");
|
||||
Future<Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
|
||||
|
||||
Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
|
||||
clientSocket.awaitCloseEvent("Client");
|
||||
clientSocket.assertCloseInfo("Client", StatusCode.SERVER_ERROR, anything());
|
||||
|
||||
clientSession.close();
|
||||
try (LocalFuzzer session = server.newLocalFuzzer("/?openSessions", upgradeHeaders))
|
||||
{
|
||||
session.sendFrames(
|
||||
new TextFrame().setPayload("openSessions"),
|
||||
new CloseInfo(StatusCode.NORMAL).asFrame()
|
||||
);
|
||||
|
||||
BlockingQueue<WebSocketFrame> framesQueue = session.getOutputFrames();
|
||||
WebSocketFrame frame = framesQueue.poll(1, TimeUnit.SECONDS);
|
||||
assertThat("Frame.opCode", frame.getOpCode(), is(OpCode.TEXT));
|
||||
assertThat("Frame.text-payload", frame.getPayloadAsUTF8(), containsString("openSessions.size=1\n"));
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("Duplicates")
|
||||
private void dropConnection() throws Exception
|
||||
private void dropClientConnection() throws Exception
|
||||
{
|
||||
client.setMaxIdleTimeout(1000);
|
||||
URI wsUri = server.getServerUri();
|
||||
|
||||
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
|
||||
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
|
||||
upgradeRequest.setSubProtocols("container");
|
||||
Future<Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
|
||||
|
||||
Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
|
||||
clientSession.close();
|
||||
Map<String, String> upgradeHeaders = UpgradeUtils.newDefaultUpgradeRequestHeaders();
|
||||
upgradeHeaders.put(WebSocketConstants.SEC_WEBSOCKET_PROTOCOL, "container");
|
||||
|
||||
try (LocalFuzzer ignored = server.newLocalFuzzer("/", upgradeHeaders))
|
||||
{
|
||||
// do nothing, just let endpoint close
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,17 +18,11 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.tests.server;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.toolchain.test.AdvancedRunner;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.BatchMode;
|
||||
|
@ -37,26 +31,20 @@ import org.eclipse.jetty.websocket.api.Session;
|
|||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
|
||||
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
||||
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.frames.CloseFrame;
|
||||
import org.eclipse.jetty.websocket.common.frames.TextFrame;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
|
||||
import org.eclipse.jetty.websocket.tests.Defaults;
|
||||
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
|
||||
import org.eclipse.jetty.websocket.tests.SimpleServletServer;
|
||||
import org.eclipse.jetty.websocket.tests.TrackingEndpoint;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TestName;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
/**
|
||||
* Testing various aspects of the server side support for WebSocket {@link org.eclipse.jetty.websocket.api.Session}
|
||||
*/
|
||||
@RunWith(AdvancedRunner.class)
|
||||
public class WebSocketServerSessionTest
|
||||
{
|
||||
public static class SessionServlet extends WebSocketServlet
|
||||
|
@ -83,7 +71,7 @@ public class WebSocketServerSessionTest
|
|||
@OnWebSocketMessage
|
||||
public void onText(String message)
|
||||
{
|
||||
LOG.debug("onText({})",message);
|
||||
LOG.debug("onText({})", message);
|
||||
if (message == null)
|
||||
{
|
||||
return;
|
||||
|
@ -125,24 +113,18 @@ public class WebSocketServerSessionTest
|
|||
|
||||
if ("session.isSecure".equals(message))
|
||||
{
|
||||
String issecure = String.format("session.isSecure=%b",session.isSecure());
|
||||
String issecure = String.format("session.isSecure=%b", session.isSecure());
|
||||
sendString(issecure);
|
||||
return;
|
||||
}
|
||||
|
||||
if ("session.upgradeRequest.requestURI".equals(message))
|
||||
{
|
||||
String response = String.format("session.upgradeRequest.requestURI=%s",session.getUpgradeRequest().getRequestURI().toASCIIString());
|
||||
String response = String.format("session.upgradeRequest.requestURI=%s", session.getUpgradeRequest().getRequestURI().toASCIIString());
|
||||
sendString(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if ("harsh-disconnect".equals(message))
|
||||
{
|
||||
session.disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
// echo the message back.
|
||||
sendString(message);
|
||||
}
|
||||
|
@ -162,77 +144,43 @@ public class WebSocketServerSessionTest
|
|||
}
|
||||
|
||||
private static SimpleServletServer server;
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void startServer() throws Exception
|
||||
{
|
||||
server = new SimpleServletServer(new SessionServlet());
|
||||
server.start();
|
||||
}
|
||||
|
||||
|
||||
@AfterClass
|
||||
public static void stopServer() throws Exception
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@Rule
|
||||
public TestName testname = new TestName();
|
||||
|
||||
private WebSocketClient client;
|
||||
|
||||
@Before
|
||||
public void startClient() throws Exception
|
||||
{
|
||||
client = new WebSocketClient();
|
||||
client.start();
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopClient() throws Exception
|
||||
{
|
||||
client.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisconnect() throws Exception
|
||||
{
|
||||
URI wsUri = server.getServerUri().resolve("/test/disconnect");
|
||||
|
||||
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
|
||||
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
|
||||
Future<Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
|
||||
|
||||
Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
clientSession.getRemote().sendString("harsh-disconnect");
|
||||
|
||||
// TODO: or onError(EOF)
|
||||
clientSocket.awaitCloseEvent("Client");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpgradeRequestResponse() throws Exception
|
||||
{
|
||||
URI wsUri = server.getServerUri().resolve("/test?snack=cashews&amount=handful&brand=off");
|
||||
|
||||
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
|
||||
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
|
||||
Future<Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
|
||||
|
||||
Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
clientSession.getRemote().sendString("getParameterMap|snack");
|
||||
clientSession.getRemote().sendString("getParameterMap|amount");
|
||||
clientSession.getRemote().sendString("getParameterMap|brand");
|
||||
clientSession.getRemote().sendString("getParameterMap|cost");
|
||||
String requestPath = "/test?snack=cashews&amount=handful&brand=off";
|
||||
|
||||
String incomingMessage;
|
||||
incomingMessage = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
|
||||
assertThat("Parameter Map[snack]", incomingMessage, is("[cashews]"));
|
||||
incomingMessage = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
|
||||
assertThat("Parameter Map[amount]", incomingMessage, is("[handful]"));
|
||||
incomingMessage = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
|
||||
assertThat("Parameter Map[brand]", incomingMessage, is("[off]"));
|
||||
incomingMessage = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
|
||||
assertThat("Parameter Map[cost]", incomingMessage, is("<null>"));
|
||||
List<WebSocketFrame> send = new ArrayList<>();
|
||||
send.add(new TextFrame().setPayload("getParameterMap|snack"));
|
||||
send.add(new TextFrame().setPayload("getParameterMap|amount"));
|
||||
send.add(new TextFrame().setPayload("getParameterMap|brand"));
|
||||
send.add(new TextFrame().setPayload("getParameterMap|cost"));
|
||||
send.add(new CloseFrame());
|
||||
|
||||
List<WebSocketFrame> expect = new ArrayList<>();
|
||||
expect.add(new TextFrame().setPayload("[cashews]"));
|
||||
expect.add(new TextFrame().setPayload("[handful]"));
|
||||
expect.add(new TextFrame().setPayload("[off]"));
|
||||
expect.add(new TextFrame().setPayload("<null>"));
|
||||
send.add(new CloseFrame());
|
||||
|
||||
try (LocalFuzzer session = server.newLocalFuzzer(requestPath))
|
||||
{
|
||||
session.sendFrames(send);
|
||||
session.expect(expect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.tests.server;
|
||||
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.websocket.server.NativeWebSocketConfiguration;
|
||||
import org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
|
||||
import org.eclipse.jetty.websocket.tests.LocalServer;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class WebSocketUpgradeFilterEmbeddedTest extends WebSocketUpgradeFilterTest
|
||||
{
|
||||
private interface Case
|
||||
{
|
||||
void customize(ServletContextHandler context) throws Exception;
|
||||
}
|
||||
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
public static List<Object[]> data()
|
||||
{
|
||||
final WebSocketCreator infoCreator = (req, resp) -> new InfoSocket();
|
||||
|
||||
List<Object[]> cases = new ArrayList<>();
|
||||
|
||||
// Embedded WSUF.configureContext(), directly app-ws configuration
|
||||
|
||||
cases.add(new Object[]
|
||||
{"wsuf.configureContext/Direct configure", (Case) (context) ->
|
||||
{
|
||||
WebSocketUpgradeFilter wsuf = WebSocketUpgradeFilter.configureContext(context);
|
||||
// direct configuration via WSUF
|
||||
wsuf.getFactory().getPolicy().setMaxTextMessageSize(10 * 1024 * 1024);
|
||||
wsuf.addMapping("/info/*", infoCreator);
|
||||
}});
|
||||
|
||||
// Embedded WSUF.configureContext(), apply app-ws configuration via attribute
|
||||
|
||||
cases.add(new Object[]{
|
||||
"wsuf.configureContext/Attribute based configure", (Case) (context) ->
|
||||
{
|
||||
WebSocketUpgradeFilter.configureContext(context);
|
||||
|
||||
// configuration via attribute
|
||||
NativeWebSocketConfiguration configuration = (NativeWebSocketConfiguration) context.getServletContext().getAttribute(NativeWebSocketConfiguration.class.getName());
|
||||
assertThat("NativeWebSocketConfiguration", configuration, notNullValue());
|
||||
configuration.getFactory().getPolicy().setMaxTextMessageSize(10 * 1024 * 1024);
|
||||
configuration.addMapping("/info/*", infoCreator);
|
||||
}});
|
||||
|
||||
// Embedded WSUF, added as filter, apply app-ws configuration via attribute
|
||||
|
||||
cases.add(new Object[]{
|
||||
"wsuf/addFilter/Attribute based configure", (Case) (context) ->
|
||||
{
|
||||
context.addFilter(WebSocketUpgradeFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
|
||||
|
||||
NativeWebSocketConfiguration configuration = new NativeWebSocketConfiguration(context.getServletContext());
|
||||
configuration.getFactory().getPolicy().setMaxTextMessageSize(10 * 1024 * 1024);
|
||||
configuration.addMapping("/info/*", infoCreator);
|
||||
context.setAttribute(NativeWebSocketConfiguration.class.getName(), configuration);
|
||||
}});
|
||||
|
||||
// Embedded WSUF, added as filter, apply app-ws configuration via wsuf constructor
|
||||
|
||||
cases.add(new Object[]{
|
||||
"wsuf/addFilter/WSUF Constructor configure", (Case) (context) ->
|
||||
{
|
||||
NativeWebSocketConfiguration configuration = new NativeWebSocketConfiguration(context.getServletContext());
|
||||
configuration.getFactory().getPolicy().setMaxTextMessageSize(10 * 1024 * 1024);
|
||||
configuration.addMapping("/info/*", infoCreator);
|
||||
context.addBean(configuration, true);
|
||||
|
||||
FilterHolder wsufHolder = new FilterHolder(new WebSocketUpgradeFilter(configuration));
|
||||
context.addFilter(wsufHolder, "/*", EnumSet.of(DispatcherType.REQUEST));
|
||||
}});
|
||||
|
||||
// Embedded WSUF, added as filter, apply app-ws configuration via ServletContextListener
|
||||
|
||||
cases.add(new Object[]{
|
||||
"wsuf.configureContext/ServletContextListener configure", (Case) (context) ->
|
||||
{
|
||||
context.addFilter(WebSocketUpgradeFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
|
||||
context.addEventListener(new InfoContextListener());
|
||||
}});
|
||||
|
||||
return cases;
|
||||
}
|
||||
|
||||
public WebSocketUpgradeFilterEmbeddedTest(String testid, Case testcase) throws Exception
|
||||
{
|
||||
super(newServer(testcase));
|
||||
}
|
||||
|
||||
private static LocalServer newServer(Case testcase)
|
||||
{
|
||||
return new LocalServer()
|
||||
{
|
||||
@Override
|
||||
protected void configureServletContextHandler(ServletContextHandler context) throws Exception
|
||||
{
|
||||
testcase.customize(context);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -18,361 +18,118 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.tests.server;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.toolchain.test.FS;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.util.WSURI;
|
||||
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.eclipse.jetty.websocket.server.NativeWebSocketConfiguration;
|
||||
import org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
|
||||
import org.eclipse.jetty.websocket.tests.Defaults;
|
||||
import org.eclipse.jetty.websocket.tests.TrackingEndpoint;
|
||||
import org.eclipse.jetty.websocket.tests.WSServer;
|
||||
import org.eclipse.jetty.websocket.api.StatusCode;
|
||||
import org.eclipse.jetty.websocket.common.CloseInfo;
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.frames.TextFrame;
|
||||
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
|
||||
import org.eclipse.jetty.websocket.tests.LocalServer;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TestName;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class WebSocketUpgradeFilterTest
|
||||
public abstract class WebSocketUpgradeFilterTest
|
||||
{
|
||||
interface ServerProvider
|
||||
{
|
||||
Server newServer() throws Exception;
|
||||
}
|
||||
|
||||
private static AtomicInteger uniqTestDirId = new AtomicInteger(0);
|
||||
|
||||
private static File getNewTestDir()
|
||||
protected static File getNewTestDir()
|
||||
{
|
||||
return MavenTestingUtils.getTargetTestingDir("WSUF-webxml-" + uniqTestDirId.getAndIncrement());
|
||||
}
|
||||
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
public static List<Object[]> data()
|
||||
{
|
||||
final WebSocketCreator infoCreator = (req, resp) -> new InfoSocket();
|
||||
|
||||
List<Object[]> cases = new ArrayList<>();
|
||||
|
||||
// Embedded WSUF.configureContext(), directly app-ws configuration
|
||||
|
||||
cases.add(new Object[]{"wsuf.configureContext/Direct configure", (ServerProvider) () ->
|
||||
{
|
||||
Server server1 = new Server();
|
||||
ServerConnector connector = new ServerConnector(server1);
|
||||
connector.setPort(0);
|
||||
server1.addConnector(connector);
|
||||
|
||||
ServletContextHandler context = new ServletContextHandler();
|
||||
context.setContextPath("/");
|
||||
server1.setHandler(context);
|
||||
|
||||
WebSocketUpgradeFilter wsuf = WebSocketUpgradeFilter.configureContext(context);
|
||||
|
||||
// direct configuration via WSUF
|
||||
wsuf.getFactory().getPolicy().setMaxTextMessageSize(10 * 1024 * 1024);
|
||||
wsuf.addMapping("/info/*", infoCreator);
|
||||
|
||||
server1.start();
|
||||
return server1;
|
||||
}});
|
||||
|
||||
// Embedded WSUF.configureContext(), apply app-ws configuration via attribute
|
||||
|
||||
cases.add(new Object[]{"wsuf.configureContext/Attribute based configure", (ServerProvider) () ->
|
||||
{
|
||||
Server server12 = new Server();
|
||||
ServerConnector connector = new ServerConnector(server12);
|
||||
connector.setPort(0);
|
||||
server12.addConnector(connector);
|
||||
|
||||
ServletContextHandler context = new ServletContextHandler();
|
||||
context.setContextPath("/");
|
||||
server12.setHandler(context);
|
||||
|
||||
WebSocketUpgradeFilter.configureContext(context);
|
||||
|
||||
// configuration via attribute
|
||||
NativeWebSocketConfiguration configuration = (NativeWebSocketConfiguration) context.getServletContext().getAttribute(NativeWebSocketConfiguration.class.getName());
|
||||
assertThat("NativeWebSocketConfiguration", configuration, notNullValue());
|
||||
configuration.getFactory().getPolicy().setMaxTextMessageSize(10 * 1024 * 1024);
|
||||
configuration.addMapping("/info/*", infoCreator);
|
||||
|
||||
server12.start();
|
||||
|
||||
return server12;
|
||||
}});
|
||||
|
||||
// Embedded WSUF, added as filter, apply app-ws configuration via attribute
|
||||
|
||||
cases.add(new Object[]{"wsuf/addFilter/Attribute based configure", (ServerProvider) () ->
|
||||
{
|
||||
Server server13 = new Server();
|
||||
ServerConnector connector = new ServerConnector(server13);
|
||||
connector.setPort(0);
|
||||
server13.addConnector(connector);
|
||||
|
||||
ServletContextHandler context = new ServletContextHandler();
|
||||
context.setContextPath("/");
|
||||
server13.setHandler(context);
|
||||
context.addFilter(WebSocketUpgradeFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
|
||||
|
||||
NativeWebSocketConfiguration configuration = new NativeWebSocketConfiguration(context.getServletContext());
|
||||
configuration.getFactory().getPolicy().setMaxTextMessageSize(10 * 1024 * 1024);
|
||||
configuration.addMapping("/info/*", infoCreator);
|
||||
context.setAttribute(NativeWebSocketConfiguration.class.getName(), configuration);
|
||||
|
||||
server13.start();
|
||||
|
||||
return server13;
|
||||
}});
|
||||
|
||||
// Embedded WSUF, added as filter, apply app-ws configuration via wsuf constructor
|
||||
|
||||
cases.add(new Object[]{"wsuf/addFilter/WSUF Constructor configure", new ServerProvider()
|
||||
{
|
||||
@Override
|
||||
public Server newServer() throws Exception
|
||||
{
|
||||
Server server = new Server();
|
||||
ServerConnector connector = new ServerConnector(server);
|
||||
connector.setPort(0);
|
||||
server.addConnector(connector);
|
||||
|
||||
ServletContextHandler context = new ServletContextHandler();
|
||||
context.setContextPath("/");
|
||||
server.setHandler(context);
|
||||
|
||||
NativeWebSocketConfiguration configuration = new NativeWebSocketConfiguration(context.getServletContext());
|
||||
configuration.getFactory().getPolicy().setMaxTextMessageSize(10 * 1024 * 1024);
|
||||
configuration.addMapping("/info/*", infoCreator);
|
||||
context.addBean(configuration, true);
|
||||
|
||||
FilterHolder wsufHolder = new FilterHolder(new WebSocketUpgradeFilter(configuration));
|
||||
context.addFilter(wsufHolder, "/*", EnumSet.of(DispatcherType.REQUEST));
|
||||
|
||||
server.start();
|
||||
|
||||
return server;
|
||||
}
|
||||
}});
|
||||
|
||||
// Embedded WSUF, added as filter, apply app-ws configuration via ServletContextListener
|
||||
|
||||
cases.add(new Object[]{"wsuf.configureContext/ServletContextListener configure", (ServerProvider) () ->
|
||||
{
|
||||
Server server14 = new Server();
|
||||
ServerConnector connector = new ServerConnector(server14);
|
||||
connector.setPort(0);
|
||||
server14.addConnector(connector);
|
||||
|
||||
ServletContextHandler context = new ServletContextHandler();
|
||||
context.setContextPath("/");
|
||||
server14.setHandler(context);
|
||||
context.addFilter(WebSocketUpgradeFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
|
||||
context.addEventListener(new InfoContextListener());
|
||||
|
||||
server14.start();
|
||||
|
||||
return server14;
|
||||
}});
|
||||
|
||||
// WSUF from web.xml, SCI active, apply app-ws configuration via ServletContextListener
|
||||
|
||||
cases.add(new Object[]{"wsuf/WebAppContext/web.xml/ServletContextListener", (ServerProvider) () ->
|
||||
{
|
||||
File testDir = getNewTestDir();
|
||||
|
||||
WSServer server15 = new WSServer(testDir, "/");
|
||||
|
||||
server15.copyWebInf("wsuf-config-via-listener.xml");
|
||||
server15.copyClass(InfoSocket.class);
|
||||
server15.copyClass(InfoContextAttributeListener.class);
|
||||
server15.start();
|
||||
|
||||
WebAppContext webapp = server15.createWebAppContext();
|
||||
server15.deployWebapp(webapp);
|
||||
|
||||
return server15.getServer();
|
||||
}});
|
||||
|
||||
// WSUF from web.xml, SCI active, apply app-ws configuration via ServletContextListener with WEB-INF/lib/jetty-http.jar
|
||||
|
||||
cases.add(new Object[]{"wsuf/WebAppContext/web.xml/ServletContextListener/jetty-http.jar", new ServerProvider()
|
||||
{
|
||||
@Override
|
||||
public Server newServer() throws Exception
|
||||
{
|
||||
File testDir = getNewTestDir();
|
||||
|
||||
WSServer server = new WSServer(testDir, "/");
|
||||
|
||||
server.copyWebInf("wsuf-config-via-listener.xml");
|
||||
server.copyClass(InfoSocket.class);
|
||||
server.copyClass(InfoContextAttributeListener.class);
|
||||
// Add a jetty-http.jar to ensure that the classloader constraints
|
||||
// and the WebAppClassloader setup is sane and correct
|
||||
// The odd version string is present to capture bad regex behavior in Jetty
|
||||
server.copyLib(org.eclipse.jetty.http.pathmap.PathSpec.class, "jetty-http-9.99.999.jar");
|
||||
server.start();
|
||||
|
||||
WebAppContext webapp = server.createWebAppContext();
|
||||
server.deployWebapp(webapp);
|
||||
|
||||
return server.getServer();
|
||||
}
|
||||
}});
|
||||
|
||||
// WSUF from web.xml, SCI active, apply app-ws configuration via Servlet.init
|
||||
|
||||
cases.add(new Object[]{"wsuf/WebAppContext/web.xml/Servlet.init", (ServerProvider) () ->
|
||||
{
|
||||
File testDir = getNewTestDir();
|
||||
|
||||
WSServer server16 = new WSServer(testDir, "/");
|
||||
|
||||
server16.copyWebInf("wsuf-config-via-servlet-init.xml");
|
||||
server16.copyClass(InfoSocket.class);
|
||||
server16.copyClass(InfoServlet.class);
|
||||
server16.start();
|
||||
|
||||
WebAppContext webapp = server16.createWebAppContext();
|
||||
server16.deployWebapp(webapp);
|
||||
|
||||
return server16.getServer();
|
||||
}});
|
||||
|
||||
// xml based, wsuf, on alternate url-pattern and config attribute location
|
||||
|
||||
cases.add(new Object[]{"wsuf/WebAppContext/web.xml/ServletContextListener/alt-config", (ServerProvider) () ->
|
||||
{
|
||||
File testDir = getNewTestDir();
|
||||
|
||||
WSServer server17 = new WSServer(testDir, "/");
|
||||
|
||||
server17.copyWebInf("wsuf-alt-config-via-listener.xml");
|
||||
server17.copyClass(InfoSocket.class);
|
||||
server17.copyClass(InfoContextAltAttributeListener.class);
|
||||
server17.start();
|
||||
|
||||
WebAppContext webapp = server17.createWebAppContext();
|
||||
server17.deployWebapp(webapp);
|
||||
|
||||
return server17.getServer();
|
||||
}});
|
||||
|
||||
return cases;
|
||||
File testDir = MavenTestingUtils.getTargetTestingDir("WSUF-webxml-" + uniqTestDirId.getAndIncrement());
|
||||
FS.ensureDirExists(testDir);
|
||||
return testDir;
|
||||
}
|
||||
|
||||
@Rule
|
||||
public TestName testname = new TestName();
|
||||
|
||||
private WebSocketClient client;
|
||||
private LocalServer server;
|
||||
|
||||
@Before
|
||||
public void startClient() throws Exception
|
||||
public WebSocketUpgradeFilterTest(LocalServer server) throws Exception
|
||||
{
|
||||
client = new WebSocketClient();
|
||||
client.start();
|
||||
this.server = server;
|
||||
this.server.start();
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopClient() throws Exception
|
||||
public void stopServer() throws Exception
|
||||
{
|
||||
client.stop();
|
||||
}
|
||||
|
||||
private final Server server;
|
||||
private final URI serverUri;
|
||||
|
||||
public WebSocketUpgradeFilterTest(String testId, ServerProvider serverProvider) throws Exception
|
||||
{
|
||||
this.server = serverProvider.newServer();
|
||||
serverUri = WSURI.toWebsocket(server.getURI());
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalConfiguration() throws Exception
|
||||
{
|
||||
URI wsUri = serverUri.resolve("/info/");
|
||||
|
||||
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
|
||||
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
|
||||
Future<Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
|
||||
|
||||
Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
clientSession.getRemote().sendString("hello");
|
||||
|
||||
String incomingMessage = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
|
||||
|
||||
// If we can connect and send a text message, we know that the endpoint was
|
||||
// added properly, and the response will help us verify the policy configuration too
|
||||
assertThat("Client incoming message", incomingMessage, containsString("session.maxTextMessageSize=" + (10 * 1024 * 1024)));
|
||||
try (LocalFuzzer session = server.newLocalFuzzer("/info/"))
|
||||
{
|
||||
session.sendFrames(
|
||||
new TextFrame().setPayload("hello"),
|
||||
new CloseInfo(StatusCode.NORMAL).asFrame()
|
||||
);
|
||||
|
||||
BlockingQueue<WebSocketFrame> framesQueue = session.getOutputFrames();
|
||||
WebSocketFrame frame = framesQueue.poll(1, TimeUnit.SECONDS);
|
||||
|
||||
assertThat("Frame.opCode", frame.getOpCode(), is(OpCode.TEXT));
|
||||
|
||||
// If we can connect and send a text message, we know that the endpoint was
|
||||
// added properly, and the response will help us verify the policy configuration too
|
||||
assertThat("Frame.text-payload", frame.getPayloadAsUTF8(), containsString("session.maxTextMessageSize=" + (10 * 1024 * 1024)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStopStartOfHandler() throws Exception
|
||||
{
|
||||
URI wsUri = serverUri.resolve("/info/");
|
||||
|
||||
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
|
||||
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
|
||||
Future<Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
|
||||
|
||||
Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
clientSession.getRemote().sendString("hello 1");
|
||||
|
||||
String incomingMessage = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
|
||||
|
||||
// If we can connect and send a text message, we know that the endpoint was
|
||||
// added properly, and the response will help us verify the policy configuration too
|
||||
assertThat("Client incoming message", incomingMessage, containsString("session.maxTextMessageSize=" + (10 * 1024 * 1024)));
|
||||
|
||||
clientSession.close();
|
||||
try (LocalFuzzer session = server.newLocalFuzzer("/info/"))
|
||||
{
|
||||
session.sendFrames(
|
||||
new TextFrame().setPayload("hello 1"),
|
||||
new CloseInfo(StatusCode.NORMAL).asFrame()
|
||||
);
|
||||
|
||||
BlockingQueue<WebSocketFrame> framesQueue = session.getOutputFrames();
|
||||
WebSocketFrame frame = framesQueue.poll(1, TimeUnit.SECONDS);
|
||||
|
||||
assertThat("Frame.opCode", frame.getOpCode(), is(OpCode.TEXT));
|
||||
|
||||
// If we can connect and send a text message, we know that the endpoint was
|
||||
// added properly, and the response will help us verify the policy configuration too
|
||||
assertThat("Frame.text-payload", frame.getPayloadAsUTF8(), containsString("session.maxTextMessageSize=" + (10 * 1024 * 1024)));
|
||||
}
|
||||
|
||||
server.getHandler().stop();
|
||||
server.getHandler().start();
|
||||
server.getServletContextHandler().stop();
|
||||
server.getServletContextHandler().start();
|
||||
|
||||
// Make request again (server should have retained websocket configuration)
|
||||
|
||||
clientSocket = new TrackingEndpoint(testname.getMethodName());
|
||||
upgradeRequest = new ClientUpgradeRequest();
|
||||
clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
|
||||
|
||||
clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
clientSession.getRemote().sendString("hello 2");
|
||||
|
||||
incomingMessage = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
|
||||
|
||||
// If we can connect and send a text message, we know that the endpoint was
|
||||
// added properly, and the response will help us verify the policy configuration too
|
||||
assertThat("Client incoming message", incomingMessage, containsString("session.maxTextMessageSize=" + (10 * 1024 * 1024)));
|
||||
|
||||
clientSession.close();
|
||||
|
||||
try (LocalFuzzer session = server.newLocalFuzzer("/info/"))
|
||||
{
|
||||
session.sendFrames(
|
||||
new TextFrame().setPayload("hello 2"),
|
||||
new CloseInfo(StatusCode.NORMAL).asFrame()
|
||||
);
|
||||
|
||||
BlockingQueue<WebSocketFrame> framesQueue = session.getOutputFrames();
|
||||
WebSocketFrame frame = framesQueue.poll(1, TimeUnit.SECONDS);
|
||||
|
||||
assertThat("Frame.opCode", frame.getOpCode(), is(OpCode.TEXT));
|
||||
|
||||
// If we can connect and send a text message, we know that the endpoint was
|
||||
// added properly, and the response will help us verify the policy configuration too
|
||||
assertThat("Frame.text-payload", frame.getPayloadAsUTF8(), containsString("session.maxTextMessageSize=" + (10 * 1024 * 1024)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.tests.server;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.eclipse.jetty.websocket.tests.WSServer;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class WebSocketUpgradeFilterWebappTest extends WebSocketUpgradeFilterTest
|
||||
{
|
||||
private interface Case
|
||||
{
|
||||
void customize(WSServer server) throws Exception;
|
||||
}
|
||||
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
public static List<Object[]> data()
|
||||
{
|
||||
List<Object[]> cases = new ArrayList<>();
|
||||
|
||||
// WSUF from web.xml, SCI active, apply app-ws configuration via ServletContextListener
|
||||
|
||||
cases.add(new Object[]{
|
||||
"From ServletContextListener",
|
||||
(Case) (server) ->
|
||||
{
|
||||
server.copyWebInf("wsuf-config-via-listener.xml");
|
||||
server.copyClass(InfoSocket.class);
|
||||
server.copyClass(InfoContextAttributeListener.class);
|
||||
}
|
||||
});
|
||||
|
||||
// WSUF from web.xml, SCI active, apply app-ws configuration via ServletContextListener with WEB-INF/lib/jetty-http.jar
|
||||
|
||||
cases.add(new Object[]{
|
||||
"From ServletContextListener with jar scanning",
|
||||
(Case) (server) ->
|
||||
{
|
||||
server.copyWebInf("wsuf-config-via-listener.xml");
|
||||
server.copyClass(InfoSocket.class);
|
||||
server.copyClass(InfoContextAttributeListener.class);
|
||||
// Add a jetty-http.jar to ensure that the classloader constraints
|
||||
// and the WebAppClassloader setup is sane and correct
|
||||
// The odd version string is present to capture bad regex behavior in Jetty
|
||||
server.copyLib(org.eclipse.jetty.http.pathmap.PathSpec.class, "jetty-http-9.99.999.jar");
|
||||
}
|
||||
});
|
||||
|
||||
return cases;
|
||||
}
|
||||
|
||||
public WebSocketUpgradeFilterWebappTest(String testid, Case testcase) throws Exception
|
||||
{
|
||||
super(newServer(testcase));
|
||||
}
|
||||
|
||||
private static WSServer newServer(Case testcase)
|
||||
{
|
||||
return new WSServer(getNewTestDir(), "")
|
||||
{
|
||||
private WebAppContext webapp;
|
||||
|
||||
@Override
|
||||
protected Handler createRootHandler(Server server) throws Exception
|
||||
{
|
||||
Handler handler = super.createRootHandler(server);
|
||||
testcase.customize(this);
|
||||
return handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletContextHandler getServletContextHandler()
|
||||
{
|
||||
return this.webapp;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStart() throws Exception
|
||||
{
|
||||
super.doStart();
|
||||
|
||||
this.webapp = createWebAppContext();
|
||||
deployWebapp(webapp);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -71,7 +71,7 @@ public class AnnotatedServerEndpointTest
|
|||
}
|
||||
|
||||
@AfterClass
|
||||
public static void stopServer()
|
||||
public static void stopServer() throws Exception
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.tests.server.jsr356;
|
||||
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
import javax.websocket.DeploymentException;
|
||||
import javax.websocket.server.ServerContainer;
|
||||
import javax.websocket.server.ServerEndpointConfig;
|
||||
|
||||
import org.eclipse.jetty.websocket.tests.server.jsr356.sockets.IdleTimeoutOnOpenEndpoint;
|
||||
|
||||
/**
|
||||
* Example of adding a server WebSocket (extending {@link javax.websocket.Endpoint}) programmatically via config
|
||||
*/
|
||||
public class IdleTimeoutContextListener implements ServletContextListener
|
||||
{
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent sce)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce)
|
||||
{
|
||||
ServerContainer container = (ServerContainer)sce.getServletContext().getAttribute(ServerContainer.class.getName());
|
||||
// Build up a configuration with a specific path
|
||||
String path = "/idle-onopen-endpoint";
|
||||
ServerEndpointConfig.Builder builder = ServerEndpointConfig.Builder.create(IdleTimeoutOnOpenEndpoint.class,path);
|
||||
try
|
||||
{
|
||||
container.addEndpoint(builder.build());
|
||||
}
|
||||
catch (DeploymentException e)
|
||||
{
|
||||
throw new RuntimeException("Unable to add endpoint via config file",e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.tests.server.jsr356;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.eclipse.jetty.websocket.api.StatusCode;
|
||||
import org.eclipse.jetty.websocket.common.CloseInfo;
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.frames.TextFrame;
|
||||
import org.eclipse.jetty.websocket.tests.LeakTrackingBufferPoolRule;
|
||||
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
|
||||
import org.eclipse.jetty.websocket.tests.WSServer;
|
||||
import org.eclipse.jetty.websocket.tests.server.jsr356.sockets.IdleTimeoutOnOpenEndpoint;
|
||||
import org.eclipse.jetty.websocket.tests.server.jsr356.sockets.IdleTimeoutOnOpenSocket;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
public class IdleTimeoutTest
|
||||
{
|
||||
@Rule
|
||||
public LeakTrackingBufferPoolRule bufferPool = new LeakTrackingBufferPoolRule("Test");
|
||||
|
||||
private static WSServer server;
|
||||
|
||||
@BeforeClass
|
||||
public static void setupServer() throws Exception
|
||||
{
|
||||
server = new WSServer(MavenTestingUtils.getTargetTestingPath(IdleTimeoutTest.class.getName()), "app");
|
||||
server.copyWebInf("idle-timeout-config-web.xml");
|
||||
// the endpoint (extends javax.websocket.Endpoint)
|
||||
server.copyClass(IdleTimeoutOnOpenEndpoint.class);
|
||||
// the configuration that adds the endpoint
|
||||
server.copyClass(IdleTimeoutContextListener.class);
|
||||
// the annotated socket
|
||||
server.copyClass(IdleTimeoutOnOpenSocket.class);
|
||||
|
||||
server.start();
|
||||
|
||||
WebAppContext webapp = server.createWebAppContext();
|
||||
server.deployWebapp(webapp);
|
||||
// wsb.dump();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void stopServer() throws Exception
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
|
||||
private void assertConnectionTimeout(String requestPath) throws Exception
|
||||
{
|
||||
try (LocalFuzzer session = server.newLocalFuzzer(requestPath))
|
||||
{
|
||||
// wait 1 second to allow timeout to fire off
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
|
||||
session.sendFrames(new TextFrame().setPayload("You shouldn't be there"));
|
||||
|
||||
BlockingQueue<WebSocketFrame> framesQueue = session.getOutputFrames();
|
||||
WebSocketFrame frame = framesQueue.poll(1, TimeUnit.SECONDS);
|
||||
assertThat("Frame.opCode", frame.getOpCode(), is(OpCode.CLOSE));
|
||||
CloseInfo closeInfo = new CloseInfo(frame);
|
||||
assertThat("Close.statusCode", closeInfo.getStatusCode(), is(StatusCode.SHUTDOWN));
|
||||
assertThat("Close.reason", closeInfo.getReason(), containsString("Timeout"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotated() throws Exception
|
||||
{
|
||||
assertConnectionTimeout("/app/idle-onopen-socket");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEndpoint() throws Exception
|
||||
{
|
||||
assertConnectionTimeout("/app/idle-onopen-endpoint");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.tests.server.jsr356;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
|
||||
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketSession;
|
||||
import org.eclipse.jetty.websocket.common.frames.CloseFrame;
|
||||
import org.eclipse.jetty.websocket.common.frames.TextFrame;
|
||||
import org.eclipse.jetty.websocket.server.WebSocketServerFactory;
|
||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
|
||||
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
|
||||
import org.eclipse.jetty.websocket.tests.SimpleServletServer;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SessionTrackingTest
|
||||
{
|
||||
@WebSocket
|
||||
public static class SessionTrackingSocket
|
||||
{
|
||||
private final WebSocketServerFactory container;
|
||||
|
||||
public SessionTrackingSocket(WebSocketServerFactory container)
|
||||
{
|
||||
this.container = container;
|
||||
}
|
||||
|
||||
@OnWebSocketMessage
|
||||
public void onMessage(Session session, String msg) throws IOException
|
||||
{
|
||||
if (msg == null)
|
||||
{
|
||||
session.getRemote().sendString("Unknown command: <null>");
|
||||
return;
|
||||
}
|
||||
|
||||
String parts[] = msg.split("\\|");
|
||||
|
||||
if ("openSessions".equals(parts[0]))
|
||||
{
|
||||
Collection<WebSocketSession> sessions = container.getOpenSessions();
|
||||
String ret = String.format("openSessions(@%s).size=%d", parts[1], sessions.size());
|
||||
session.getRemote().sendString(ret);
|
||||
return;
|
||||
}
|
||||
|
||||
session.getRemote().sendString("Unknown command: " + msg);
|
||||
}
|
||||
}
|
||||
|
||||
public static class SessionTrackingServlet extends WebSocketServlet implements WebSocketCreator
|
||||
{
|
||||
private WebSocketServerFactory serverFactory;
|
||||
|
||||
@Override
|
||||
public void configure(WebSocketServletFactory factory)
|
||||
{
|
||||
// If this fails, then we have a lot of tests failing.
|
||||
this.serverFactory = (WebSocketServerFactory) factory;
|
||||
factory.setCreator(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp)
|
||||
{
|
||||
return new SessionTrackingSocket(serverFactory);
|
||||
}
|
||||
}
|
||||
|
||||
private static SimpleServletServer server;
|
||||
|
||||
@BeforeClass
|
||||
public static void startServer() throws Exception
|
||||
{
|
||||
server = new SimpleServletServer(new SessionTrackingServlet());
|
||||
server.start();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void stopServer() throws Exception
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddRemoveSessions() throws Exception
|
||||
{
|
||||
try (LocalFuzzer session1 = server.newLocalFuzzer("/1"))
|
||||
{
|
||||
sendTextFrameToAll("openSessions|in-1", session1);
|
||||
|
||||
try (LocalFuzzer session2 = server.newLocalFuzzer("/2"))
|
||||
{
|
||||
sendTextFrameToAll("openSessions|in-2", session1, session2);
|
||||
|
||||
try (LocalFuzzer session3 = server.newLocalFuzzer("/3"))
|
||||
{
|
||||
sendTextFrameToAll("openSessions|in-3", session1, session2, session3);
|
||||
sendTextFrameToAll("openSessions|lvl-3", session1, session2, session3);
|
||||
|
||||
session3.sendFrames(new CloseFrame());
|
||||
|
||||
List<WebSocketFrame> expect3 = new ArrayList<>();
|
||||
expect3.add(new TextFrame().setPayload("openSessions(@in-3).size=3"));
|
||||
expect3.add(new TextFrame().setPayload("openSessions(@lvl-3).size=3"));
|
||||
expect3.add(new CloseFrame());
|
||||
session3.expect(expect3);
|
||||
}
|
||||
|
||||
sendTextFrameToAll("openSessions|lvl-2", session1, session2);
|
||||
session2.sendFrames(new CloseFrame());
|
||||
|
||||
List<WebSocketFrame> expect2 = new ArrayList<>();
|
||||
expect2.add(new TextFrame().setPayload("openSessions(@in-2).size=2"));
|
||||
expect2.add(new TextFrame().setPayload("openSessions(@in-3).size=3"));
|
||||
expect2.add(new TextFrame().setPayload("openSessions(@lvl-3).size=3"));
|
||||
expect2.add(new TextFrame().setPayload("openSessions(@lvl-2).size=2"));
|
||||
expect2.add(new CloseFrame());
|
||||
session2.expect(expect2);
|
||||
}
|
||||
|
||||
sendTextFrameToAll("openSessions|lvl-1", session1);
|
||||
session1.sendFrames(new CloseFrame());
|
||||
|
||||
List<WebSocketFrame> expect1 = new ArrayList<>();
|
||||
expect1.add(new TextFrame().setPayload("openSessions(@in-1).size=1"));
|
||||
expect1.add(new TextFrame().setPayload("openSessions(@in-2).size=2"));
|
||||
expect1.add(new TextFrame().setPayload("openSessions(@in-3).size=3"));
|
||||
expect1.add(new TextFrame().setPayload("openSessions(@lvl-3).size=3"));
|
||||
expect1.add(new TextFrame().setPayload("openSessions(@lvl-2).size=2"));
|
||||
expect1.add(new TextFrame().setPayload("openSessions(@lvl-1).size=1"));
|
||||
expect1.add(new CloseFrame());
|
||||
session1.expect(expect1);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendTextFrameToAll(String msg, LocalFuzzer... sessions)
|
||||
{
|
||||
for (LocalFuzzer session : sessions)
|
||||
{
|
||||
session.sendFrames(new TextFrame().setPayload(msg));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,7 +16,7 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.jsr356.server;
|
||||
package org.eclipse.jetty.websocket.tests.server.jsr356;
|
||||
|
||||
import static org.hamcrest.Matchers.equalToIgnoringCase;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
@ -58,9 +58,10 @@ import org.eclipse.jetty.toolchain.test.IO;
|
|||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.common.test.LeakTrackingBufferPoolRule;
|
||||
import org.eclipse.jetty.websocket.common.util.Sha1Sum;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.ServerContainer;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
|
||||
import org.eclipse.jetty.websocket.tests.LeakTrackingBufferPoolRule;
|
||||
import org.eclipse.jetty.websocket.tests.Sha1Sum;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
|
@ -0,0 +1,44 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.tests.server.jsr356.sockets;
|
||||
|
||||
import javax.websocket.Endpoint;
|
||||
import javax.websocket.EndpointConfig;
|
||||
import javax.websocket.MessageHandler;
|
||||
import javax.websocket.Session;
|
||||
|
||||
public class IdleTimeoutOnOpenEndpoint extends Endpoint implements MessageHandler.Whole<String>
|
||||
{
|
||||
private Session session;
|
||||
|
||||
@Override
|
||||
public void onOpen(Session session, EndpointConfig config)
|
||||
{
|
||||
this.session = session;
|
||||
session.addMessageHandler(this);
|
||||
session.setMaxIdleTimeout(500);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(String message)
|
||||
{
|
||||
// echo message back (this is an indication of timeout failure)
|
||||
session.getAsyncRemote().sendText(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.tests.server.jsr356.sockets;
|
||||
|
||||
import javax.websocket.OnMessage;
|
||||
import javax.websocket.OnOpen;
|
||||
import javax.websocket.Session;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
|
||||
@ServerEndpoint(value = "/idle-onopen-socket")
|
||||
public class IdleTimeoutOnOpenSocket
|
||||
{
|
||||
@OnOpen
|
||||
public void onOpen(Session session)
|
||||
{
|
||||
session.setMaxIdleTimeout(500);
|
||||
}
|
||||
|
||||
@OnMessage
|
||||
public String onMessage(String msg)
|
||||
{
|
||||
return msg;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
metadata-complete="false"
|
||||
version="3.0">
|
||||
|
||||
<listener>
|
||||
<listener-class>org.eclipse.jetty.websocket.tests.server.jsr356.IdleTimeoutContextListener</listener-class>
|
||||
</listener>
|
||||
</web-app>
|
|
@ -22,14 +22,17 @@ org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
|||
org.eclipse.jetty.LEVEL=WARN
|
||||
# org.eclipse.jetty.util.log.stderr.LONG=true
|
||||
|
||||
# org.eclipse.jetty.server.AbstractConnector.LEVEL=DEBUG
|
||||
# org.eclipse.jetty.io.WriteFlusher.LEVEL=DEBUG
|
||||
org.eclipse.jetty.io.FillInterest.LEVEL=DEBUG
|
||||
# org.eclipse.jetty.websocket.LEVEL=DEBUG
|
||||
# org.eclipse.jetty.websocket.LEVEL=INFO
|
||||
# org.eclipse.jetty.websocket.tests.LEVEL=DEBUG
|
||||
org.eclipse.jetty.websocket.tests.LEVEL=DEBUG
|
||||
# org.eclipse.jetty.websocket.tests.client.LEVEL=DEBUG
|
||||
# org.eclipse.jetty.websocket.tests.client.jsr356.LEVEL=DEBUG
|
||||
# org.eclipse.jetty.websocket.tests.server.LEVEL=DEBUG
|
||||
# org.eclipse.jetty.websocket.tests.server.jsr356.LEVEL=DEBUG
|
||||
org.eclipse.jetty.websocket.common.LEVEL=DEBUG
|
||||
# org.eclipse.jetty.websocket.common.io.LEVEL=DEBUG
|
||||
# org.eclipse.jetty.websocket.common.io.FrameFlusher.LEVEL=DEBUG
|
||||
# org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.LEVEL=DEBUG
|
||||
|
@ -40,5 +43,6 @@ org.eclipse.jetty.LEVEL=WARN
|
|||
# org.eclipse.jetty.websocket.common.message.LEVEL=DEBUG
|
||||
org.eclipse.jetty.websocket.common.CompletionCallback.LEVEL=ALL
|
||||
|
||||
|
||||
### Disabling intentional error out of RFCSocket
|
||||
org.eclipse.jetty.websocket.tests.server.RFCSocket.LEVEL=OFF
|
||||
|
|
Loading…
Reference in New Issue