Merge remote-tracking branch 'eclipse/jetty-10.0.x' into jetty-10.0.x-websocketmapping-refactor

Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
Lachlan Roberts 2019-01-23 18:45:59 +11:00
commit d37dfd4357
32 changed files with 591 additions and 332 deletions

View File

@ -30,7 +30,7 @@ public class JAASPrincipal implements Principal, Serializable
{
private static final long serialVersionUID = -5538962177019315479L;
private String _name = null;
private final String _name;
public JAASPrincipal(String userName)
{

View File

@ -1,5 +0,0 @@
source.. = src/main/java/
output.. = target/classes/
bin.includes = META-INF/,\
.
src.includes = META-INF/

View File

@ -1,5 +0,0 @@
source.. = src/main/java/
output.. = target/classes/
bin.includes = META-INF/,\
.
src.includes = META-INF/

View File

@ -1,8 +0,0 @@
source.. = src/main/java/
output.. = target/classes/
bin.includes = META-INF/,\
.,\
jettyhome/
bin.excludes = jettyhome/logs/*.log,\
jettyhome/lib/*
src.includes = jettyhome/

View File

@ -1,4 +0,0 @@
source.. = src/main/java/
output.. = target/classes/
bin.includes = META-INF/,\
.

View File

@ -11,8 +11,9 @@
<properties>
<assembly-directory>target/distribution</assembly-directory>
<bundle-symbolic-name>${project.groupId}.runner</bundle-symbolic-name>
<it.debug>false</it.debug>
</properties>
<url>http://www.eclipse.org/jetty</url>
<build>
<plugins>
<plugin>
@ -35,21 +36,38 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<!-- jetty-runner is not an OSGi component -->
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<artifactId>maven-invoker-plugin</artifactId>
<executions>
<execution>
<id>integration-test</id>
<phase>integration-test</phase>
<goals>
<goal>install</goal>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
</archive>
<javaHome>${java.home}</javaHome>
<environmentVariables>
<JAVA_HOME>${java.home}</JAVA_HOME>
</environmentVariables>
<debug>${it.debug}</debug>
<projectsDirectory>src/it</projectsDirectory>
<timeoutInSeconds>600</timeoutInSeconds>
<cloneProjectsTo>${project.build.directory}/it</cloneProjectsTo>
<localRepositoryPath>${project.build.directory}/local-repo</localRepositoryPath>
<settingsFile>src/it/settings.xml</settingsFile>
<skipInvocation>${skipTests}</skipInvocation>
<scriptVariables>
<maven.dependency.plugin.version>${maven.dependency.plugin.version}</maven.dependency.plugin.version>
</scriptVariables>
<goals>
<goal>clean</goal>
</goals>
</configuration>
</plugin>
</plugins>
@ -63,6 +81,28 @@
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<!-- jetty-runner is not an OSGi component -->
<skip>true</skip>
<!-- there is no way to skip MANIFEST creation by the plugin so just configure dummy location -->
<manifestLocation>${project.build.directory}/NON_USED_MANIFEST</manifestLocation>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestFile>src/main/resources/MANIFEST.MF</manifestFile>
<manifest>
<mainClass>org.eclipse.jetty.runner.Runner</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<settings>
<profiles>
<profile>
<id>it-repo</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<repositories>
<repository>
<id>local.central</id>
<url>@localRepositoryUrl@</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>local.central</id>
<url>@localRepositoryUrl@</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
</settings>

View File

@ -0,0 +1 @@
invoker.goals = generate-resources

View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.its</groupId>
<artifactId>jetty-runner-it-test</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-runner</artifactId>
<version>@project.version@</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>@maven.dependency.plugin.version@</version>
<executions>
<execution>
<id>copy-jetty-runner</id>
<phase>generate-resources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-runner</artifactId>
<version>@project.version@</version>
<type>jar</type>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/</outputDirectory>
<destFileName>jetty-runner.jar</destFileName>
</artifactItem>
</artifactItems>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,10 @@
import java.util.jar.*
File artifact = new File( basedir, "target/jetty-runner.jar" )
assert artifact.exists()
JarFile jar = new JarFile( artifact );
Attributes manifest = jar.getManifest().getMainAttributes();
assert manifest.getValue( new Attributes.Name( "Main-Class" ) ).equals( "org.eclipse.jetty.runner.Runner" )

View File

@ -0,0 +1 @@
Comment: Jetty Runner

View File

@ -128,7 +128,18 @@ public interface Callback extends Invocable
}
};
}
static Callback from(Runnable completed)
{
return new Completing()
{
public void completed()
{
completed.run();
}
};
}
class Completing implements Callback
{
@Override

View File

@ -18,24 +18,6 @@
package org.eclipse.jetty.websocket.javax.common;
import org.eclipse.jetty.util.SharedBlockingCallback;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.core.ExtensionConfig;
import org.eclipse.jetty.websocket.core.FrameHandler;
import org.eclipse.jetty.websocket.javax.common.decoders.AvailableDecoders;
import org.eclipse.jetty.websocket.javax.common.encoders.AvailableEncoders;
import org.eclipse.jetty.websocket.javax.common.util.ReflectUtils;
import javax.websocket.CloseReason;
import javax.websocket.EndpointConfig;
import javax.websocket.Extension;
import javax.websocket.MessageHandler;
import javax.websocket.RemoteEndpoint.Async;
import javax.websocket.RemoteEndpoint.Basic;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;
import java.io.IOException;
import java.net.URI;
import java.security.Principal;
@ -48,6 +30,25 @@ import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import javax.websocket.CloseReason;
import javax.websocket.EndpointConfig;
import javax.websocket.Extension;
import javax.websocket.MessageHandler;
import javax.websocket.RemoteEndpoint.Async;
import javax.websocket.RemoteEndpoint.Basic;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;
import org.eclipse.jetty.util.SharedBlockingCallback;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.core.ExtensionConfig;
import org.eclipse.jetty.websocket.core.FrameHandler;
import org.eclipse.jetty.websocket.javax.common.decoders.AvailableDecoders;
import org.eclipse.jetty.websocket.javax.common.encoders.AvailableEncoders;
import org.eclipse.jetty.websocket.javax.common.util.ReflectUtils;
/**
* Client Session for the JSR.
*/
@ -535,7 +536,7 @@ public class JavaxWebSocketSession extends AbstractLifeCycle implements javax.we
@Override
public boolean isOpen()
{
return coreSession.isOpen();
return coreSession.isOutputOpen();
}
/**

View File

@ -32,7 +32,14 @@ import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.pathmap.PathSpec;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.server.*;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;

View File

@ -18,6 +18,13 @@
package org.eclipse.jetty.websocket.javax.tests.client.misbehaving;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import javax.websocket.ContainerProvider;
import javax.websocket.WebSocketContainer;
import org.eclipse.jetty.util.log.StacklessLogging;
import org.eclipse.jetty.websocket.core.internal.WebSocketChannel;
import org.eclipse.jetty.websocket.javax.tests.CoreServer;
@ -25,12 +32,6 @@ import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import javax.websocket.ContainerProvider;
import javax.websocket.WebSocketContainer;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;

View File

@ -38,7 +38,9 @@ import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
/**
* Tests a {@link javax.websocket.Decoder.TextStream} automatic decoding to a Socket onMessage parameter

View File

@ -25,7 +25,12 @@ import java.net.URI;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.websocket.*;
import javax.websocket.ContainerProvider;
import javax.websocket.Endpoint;
import javax.websocket.EndpointConfig;
import javax.websocket.MessageHandler;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;
import javax.websocket.server.ServerContainer;
import javax.websocket.server.ServerEndpointConfig;

View File

@ -31,7 +31,13 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.websocket.*;
import javax.websocket.ContainerProvider;
import javax.websocket.Endpoint;
import javax.websocket.EndpointConfig;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.client.HttpClient;

View File

@ -18,6 +18,11 @@
package org.eclipse.jetty.websocket.common;
import java.io.IOException;
import java.net.SocketAddress;
import java.time.Duration;
import java.util.Objects;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.websocket.api.CloseStatus;
import org.eclipse.jetty.websocket.api.Session;
@ -27,11 +32,6 @@ import org.eclipse.jetty.websocket.api.UpgradeResponse;
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.core.FrameHandler;
import java.io.IOException;
import java.net.SocketAddress;
import java.time.Duration;
import java.util.Objects;
public class WebSocketSessionImpl implements Session, Dumpable
{
private final FrameHandler.CoreSession coreSession;
@ -160,7 +160,7 @@ public class WebSocketSessionImpl implements Session, Dumpable
@Override
public boolean isOpen()
{
return remoteEndpoint.getCoreSession().isOpen();
return remoteEndpoint.getCoreSession().isOutputOpen();
}
@Override

View File

@ -18,14 +18,13 @@
package org.eclipse.jetty.websocket.core;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Utf8Appendable;
import org.eclipse.jetty.util.Utf8StringBuilder;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.function.Supplier;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Utf8Appendable;
import org.eclipse.jetty.util.Utf8StringBuilder;
/**
* Representation of a WebSocket Close (status code &amp; reason)
@ -194,7 +193,7 @@ public class CloseStatus
int len = 2; // status code
byte reasonBytes[] = null;
byte[] reasonBytes = null;
if (reason != null)
{
@ -208,7 +207,7 @@ public class CloseStatus
ByteBuffer buf = BufferUtil.allocate(len);
BufferUtil.flipToFill(buf);
buf.put((byte)((statusCode >>> 8) & 0xFF));
buf.put((byte)((statusCode >>> 0) & 0xFF));
buf.put((byte)(statusCode & 0xFF));
if ((reasonBytes != null) && (reasonBytes.length > 0))
{

View File

@ -270,7 +270,7 @@ public interface FrameHandler extends IncomingFrames
/**
* @return True if the websocket is open outbound
*/
boolean isOpen();
boolean isOutputOpen();
/**
* If using BatchMode.ON or BatchMode.AUTO, trigger a flush of enqueued / batched frames.
@ -374,7 +374,7 @@ public interface FrameHandler extends IncomingFrames
}
@Override
public boolean isOpen()
public boolean isOutputOpen()
{
return false;
}

View File

@ -19,18 +19,15 @@
package org.eclipse.jetty.websocket.core.internal;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import java.util.Queue;
import java.util.stream.Collectors;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.util.IteratingCallback;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.Dumpable;
@ -201,7 +198,7 @@ public class ExtensionStack implements IncomingFrames, OutgoingFrames, Dumpable
outgoing.sendFrame(frame, callback, batch);
}
public void connect(IncomingFrames incoming, OutgoingFrames outgoing, WebSocketChannel webSocketChannel)
public void initialize(IncomingFrames incoming, OutgoingFrames outgoing, WebSocketChannel webSocketChannel)
{
if (extensions == null)
throw new IllegalStateException();

View File

@ -18,6 +18,7 @@
package org.eclipse.jetty.websocket.core.internal;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayDeque;
import java.util.ArrayList;
@ -74,6 +75,18 @@ public class FrameFlusher extends IteratingCallback
}
}
public void onClose()
{
Throwable cause = null;
synchronized (this)
{
if (!queue.isEmpty())
cause = new IOException("Closed");
}
if (cause!=null)
onCompleteFailure(cause);
}
@Override
protected Action process() throws Throwable
{

View File

@ -20,16 +20,19 @@ package org.eclipse.jetty.websocket.core.internal;
import java.io.IOException;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.URI;
import java.time.Duration;
import java.util.ArrayDeque;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeoutException;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.IteratingCallback;
import org.eclipse.jetty.util.Utf8Appendable;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log;
@ -62,6 +65,7 @@ public class WebSocketChannel implements IncomingFrames, FrameHandler.CoreSessio
private final FrameHandler handler;
private final Negotiated negotiated;
private final boolean demanding;
private final Flusher flusher = new Flusher();
private WebSocketConnection connection;
private boolean autoFragment = WebSocketConstants.DEFAULT_AUTO_FRAGMENT;
@ -79,7 +83,7 @@ public class WebSocketChannel implements IncomingFrames, FrameHandler.CoreSessio
this.behavior = behavior;
this.negotiated = negotiated;
this.demanding = handler.isDemanding();
negotiated.getExtensions().connect(new IncomingAdaptor(), new OutgoingAdaptor(), this);
negotiated.getExtensions().initialize(new IncomingAdaptor(), new OutgoingAdaptor(), this);
}
/**
@ -153,7 +157,7 @@ public class WebSocketChannel implements IncomingFrames, FrameHandler.CoreSessio
if (frame.getOpCode() == OpCode.CLOSE)
{
if (!(frame instanceof ParsedFrame)) // already check in parser
CloseStatus.getCloseStatus(frame);
CloseStatus.getCloseStatus(frame); // return ignored as get used to validate there is a closeStatus
}
}
else
@ -235,9 +239,14 @@ public class WebSocketChannel implements IncomingFrames, FrameHandler.CoreSessio
}
@Override
public boolean isOpen()
public boolean isOutputOpen()
{
return channelState.isOutOpen();
return channelState.isOutputOpen();
}
public boolean isClosed()
{
return channelState.isClosed();
}
public void setWebSocketConnection(WebSocketConnection connection)
@ -282,99 +291,94 @@ public class WebSocketChannel implements IncomingFrames, FrameHandler.CoreSessio
public void onClosed(Throwable cause)
{
onClosed(cause, new CloseStatus(CloseStatus.NO_CLOSE, cause == null?null:cause.toString()));
CloseStatus closeStatus = new CloseStatus(CloseStatus.NO_CLOSE, cause == null?null:cause.toString());
if (channelState.onClosed(closeStatus))
closeConnection(cause, closeStatus);
}
public void onClosed(Throwable cause, CloseStatus closeStatus)
public void closeConnection(Throwable cause, CloseStatus closeStatus)
{
if (channelState.onClosed(closeStatus))
{
connection.cancelDemand();
connection.cancelDemand();
// Forward Errors to Local WebSocket EndPoint
// Forward Errors to Local WebSocket EndPoint
if (cause!=null)
{
try
{
handler.onError(cause);
}
catch (Throwable e)
{
cause.addSuppressed(e);
if (e != cause)
cause.addSuppressed(e);
LOG.warn(cause);
}
try
{
handler.onClosed(closeStatus);
}
catch (Exception e)
{
LOG.warn(e);
}
}
}
/**
* Process an Error event seen by the Session and/or Connection
*
* @param cause the cause
*/
public void processError(Throwable cause)
{
CloseStatus closeStatus;
if (cause instanceof Utf8Appendable.NotUtf8Exception)
{
closeStatus = new CloseStatus(CloseStatus.BAD_PAYLOAD, cause.getMessage());
}
else if (cause instanceof SocketTimeoutException)
{
// A path often seen in Windows
closeStatus = new CloseStatus(CloseStatus.SHUTDOWN, cause.getMessage());
}
else if (cause instanceof IOException)
{
closeStatus = new CloseStatus(CloseStatus.PROTOCOL, cause.getMessage());
}
else if (cause instanceof SocketException)
{
// A path unique to Unix
closeStatus = new CloseStatus(CloseStatus.SHUTDOWN, cause.getMessage());
}
else if (cause instanceof CloseException)
{
CloseException ce = (CloseException)cause;
closeStatus = new CloseStatus(ce.getStatusCode(), ce.getMessage());
}
else if (cause instanceof WebSocketTimeoutException)
{
closeStatus = new CloseStatus(CloseStatus.SHUTDOWN, cause.getMessage());
}
else
{
LOG.warn("Unhandled Error (closing connection)", cause);
// Exception on end-user WS-Endpoint.
// Fast-fail & close connection with reason.
int statusCode = CloseStatus.SERVER_ERROR;
if (behavior == Behavior.CLIENT)
statusCode = CloseStatus.POLICY_VIOLATION;
closeStatus = new CloseStatus(statusCode, cause.getMessage());
}
try
{
// TODO can we avoid the illegal state exception in outClosed
close(closeStatus, Callback.NOOP, false);
handler.onClosed(closeStatus);
}
catch (IllegalStateException e)
catch (Throwable e)
{
if (cause == null)
cause = e;
else
cause.addSuppressed(e);
LOG.warn(e);
}
onClosed(cause, closeStatus);
if (connection.getEndPoint().isOpen())
connection.close();
}
AbnormalCloseStatus abnormalCloseStatusFor(Throwable cause)
{
int code;
if (cause instanceof ProtocolException)
code = CloseStatus.PROTOCOL;
else if (cause instanceof CloseException)
code = ((CloseException)cause).getStatusCode();
else if (cause instanceof Utf8Appendable.NotUtf8Exception)
code = CloseStatus.BAD_PAYLOAD;
else if (cause instanceof WebSocketTimeoutException || cause instanceof TimeoutException || cause instanceof SocketTimeoutException)
code = CloseStatus.SHUTDOWN;
else if (behavior == Behavior.CLIENT)
code = CloseStatus.POLICY_VIOLATION;
else
code = CloseStatus.SERVER_ERROR;
return new AbnormalCloseStatus(code, cause.getMessage());
}
/**
* Process an Error that originated from the connection.
* For protocol causes, send and abnormal close frame
* otherwise just close the connection.
*
* @param cause the cause
*/
public void processConnectionError(Throwable cause)
{
if (LOG.isDebugEnabled())
LOG.debug("processConnectionError {} {}", this, cause);
CloseStatus closeStatus = abnormalCloseStatusFor(cause);
if (closeStatus.getCode() == CloseStatus.PROTOCOL)
close(closeStatus, Callback.NOOP, false);
else if (channelState.onClosed(closeStatus))
closeConnection(cause, closeStatus);
}
/**
* Process an Error that originated from the handler.
* Send an abnormal close frame to ensure connection is closed.
*
* @param cause the cause
*/
public void processHandlerError(Throwable cause)
{
if (LOG.isDebugEnabled())
LOG.debug("processHandlerError {} {}", this, cause);
close(abnormalCloseStatusFor(cause), Callback.NOOP, false);
}
/**
@ -393,27 +397,27 @@ public class WebSocketChannel implements IncomingFrames, FrameHandler.CoreSessio
if (LOG.isDebugEnabled())
LOG.debug("ConnectionState: Transition to CONNECTED");
try
{
// Open connection and handler
channelState.onOpen();
handler.onOpen(this);
if (!demanding)
connection.demand(1);
// Open connection and handler
channelState.onOpen();
handler.onOpen(this);
if (!demanding)
connection.demand(1);
if (LOG.isDebugEnabled())
LOG.debug("ConnectionState: Transition to OPEN");
}
catch (Throwable t)
{
LOG.warn("Error during OPEN", t);
// TODO: this must trigger onError AND onClose
processError(new CloseException(CloseStatus.SERVER_ERROR, t));
}
if (LOG.isDebugEnabled())
LOG.debug("ConnectionState: Transition to OPEN");
}
catch (Throwable t)
{
processError(t); // Handle error
LOG.warn("Error during OPEN", t);
try
{
handler.onError(t);
}
catch (Exception e)
{
t.addSuppressed(e);
}
processHandlerError(new CloseException(CloseStatus.SERVER_ERROR, t));
}
}
@ -454,73 +458,73 @@ public class WebSocketChannel implements IncomingFrames, FrameHandler.CoreSessio
@Override
public void sendFrame(Frame frame, Callback callback, boolean batch)
{
synchronized(this)
{
if (LOG.isDebugEnabled())
LOG.debug("sendFrame({}, {}, {})", frame, callback, batch);
if (LOG.isDebugEnabled())
LOG.debug("sendFrame({}, {}, {})", frame, callback, batch);
boolean closed;
try
{
assertValidOutgoing(frame);
}
catch (Throwable ex)
{
callback.failed(ex);
return;
}
try
{
synchronized(flusher)
{
boolean closeConnection = channelState.onOutgoingFrame(frame);
if (frame.getOpCode() == OpCode.CLOSE)
{
if (LOG.isDebugEnabled())
LOG.debug("close({}, {}, {})", CloseStatus.getCloseStatus(frame), callback, batch);
if (closeConnection)
{
callback = new Callback.Nested(callback)
{
@Override
public void completed()
{
closeConnection(null, channelState.getCloseStatus());
}
};
}
}
flusher.queue.offer(new FrameEntry(frame, callback, batch));
}
flusher.iterate();
}
catch (Throwable ex)
{
try
{
assertValidOutgoing(frame);
closed = channelState.checkOutgoing(frame);
}
catch (Throwable ex)
{
callback.failed(ex);
return;
}
if (frame.getOpCode() == OpCode.CLOSE)
finally
{
if (LOG.isDebugEnabled())
LOG.debug("close({}, {}, {})", CloseStatus.getCloseStatus(frame), callback, batch);
if (closed)
if (frame.getOpCode() == OpCode.CLOSE)
{
callback = new Callback.Nested(callback)
{
@Override
public void completed()
{
try
{
handler.onClosed(channelState.getCloseStatus());
}
catch (Throwable e)
{
try
{
handler.onError(e);
}
catch (Throwable e2)
{
e.addSuppressed(e2);
LOG.warn(e);
}
}
finally
{
connection.close();
}
}
};
CloseStatus closeStatus = CloseStatus.getCloseStatus(frame);
if (closeStatus instanceof AbnormalCloseStatus)
closeConnection(null, closeStatus);
}
}
negotiated.getExtensions().sendFrame(frame, callback, batch);
}
connection.sendFrameQueue();
}
@Override
public void flush(Callback callback)
{
synchronized(this)
synchronized(flusher)
{
negotiated.getExtensions().sendFrame(FrameFlusher.FLUSH_FRAME, callback, false);
flusher.queue.offer(new FrameEntry(FrameFlusher.FLUSH_FRAME, callback, false));
}
connection.sendFrameQueue();
flusher.iterate();
}
@Override
@ -613,14 +617,13 @@ public class WebSocketChannel implements IncomingFrames, FrameHandler.CoreSessio
LOG.debug("receiveFrame({}, {}) - connectionState={}, handler={}",
frame, callback, channelState, handler);
boolean closed = channelState.checkIncoming(frame);
boolean closeConnection = channelState.onIncomingFrame(frame);
// Handle inbound close
if (frame.getOpCode() == OpCode.CLOSE)
{
connection.cancelDemand();
if (closed)
if (closeConnection)
{
callback = new Callback.Nested(callback)
{
@ -640,7 +643,7 @@ public class WebSocketChannel implements IncomingFrames, FrameHandler.CoreSessio
@Override
public void completed()
{
if (channelState.isOutOpen())
if (channelState.isOutputOpen())
{
CloseStatus closeStatus = CloseStatus.getCloseStatus(frame);
@ -648,8 +651,9 @@ public class WebSocketChannel implements IncomingFrames, FrameHandler.CoreSessio
LOG.debug("ConnectionState: sending close response {}", closeStatus);
// this may race with a rare application close but errors are ignored
if (closeStatus==null)
closeStatus = CloseStatus.NO_CODE_STATUS;
close(closeStatus.getCode(), closeStatus.getReason(), Callback.NOOP);
return;
}
}
};
@ -735,8 +739,9 @@ public class WebSocketChannel implements IncomingFrames, FrameHandler.CoreSessio
@Override
public String toString()
{
return String.format("WSChannel@%x{%s,%s,af=%b,i/o=%d/%d,fs=%d}->%s",
return String.format("WSChannel@%x{%s,%s,%s,af=%b,i/o=%d/%d,fs=%d}->%s",
hashCode(),
behavior,
channelState,
negotiated,
autoFragment,
@ -745,4 +750,67 @@ public class WebSocketChannel implements IncomingFrames, FrameHandler.CoreSessio
maxFrameSize,
handler);
}
static class AbnormalCloseStatus extends CloseStatus
{
public AbnormalCloseStatus(int statusCode, String reasonPhrase)
{
super(statusCode, reasonPhrase);
}
}
private class Flusher extends IteratingCallback
{
private final Queue<FrameEntry> queue = new ArrayDeque<>();
FrameEntry entry;
@Override
protected Action process() throws Throwable
{
synchronized (this)
{
entry = queue.poll();
}
if (entry==null)
return Action.IDLE;
negotiated.getExtensions().sendFrame(entry.frame, this, entry.batch);
return Action.SCHEDULED;
}
@Override
public void succeeded()
{
entry.callback.succeeded();
super.succeeded();
}
@Override
protected void onCompleteFailure(Throwable cause)
{
entry.callback.failed(cause);
Queue<FrameEntry> entries;
synchronized (this)
{
entries = new ArrayDeque<>(queue);
queue.clear();
}
entries.forEach(e-> failEntry(cause, e));
}
private void failEntry(Throwable cause, FrameEntry e)
{
try
{
e.callback.failed(cause);
}
catch(Throwable x)
{
if (cause != x)
cause.addSuppressed(x);
LOG.warn(cause);
}
}
}
}

View File

@ -33,8 +33,8 @@ public class WebSocketChannelState
CONNECTING,
CONNECTED,
OPEN,
ICLOSED,
OCLOSED,
ISHUT,
OSHUT,
CLOSED
}
@ -68,7 +68,11 @@ public class WebSocketChannelState
@Override
public String toString()
{
return _channelState.toString();
return String.format("%s@%x{%s,i=%s,o=%s,c=%s}",getClass().getSimpleName(),hashCode(),
_channelState,
OpCode.name(_incomingContinuation),
OpCode.name(_outgoingContinuation),
_closeStatus);
}
@ -85,16 +89,16 @@ public class WebSocketChannelState
return getState()==State.CLOSED;
}
public boolean isInOpen()
public boolean isInputOpen()
{
State state = getState();
return (state==State.OPEN || state==State.OCLOSED);
return (state==State.OPEN || state==State.OSHUT);
}
public boolean isOutOpen()
public boolean isOutputOpen()
{
State state = getState();
return (state==State.OPEN || state==State.ICLOSED);
return (state==State.OPEN || state==State.ISHUT);
}
public CloseStatus getCloseStatus()
@ -118,28 +122,39 @@ public class WebSocketChannelState
}
}
public boolean checkOutgoing(Frame frame) throws ProtocolException
public boolean onOutgoingFrame(Frame frame) throws ProtocolException
{
byte opcode = frame.getOpCode();
boolean fin = frame.isFin();
synchronized (this)
{
if (!isOutOpen())
if (!isOutputOpen())
{
if (opcode == OpCode.CLOSE && CloseStatus.getCloseStatus(frame) instanceof WebSocketChannel.AbnormalCloseStatus)
_channelState = State.CLOSED;
throw new IllegalStateException(_channelState.toString());
}
if (opcode == OpCode.CLOSE)
{
_closeStatus = CloseStatus.getCloseStatus(frame);
if (_closeStatus instanceof WebSocketChannel.AbnormalCloseStatus)
{
_channelState = State.CLOSED;
return true;
}
switch (_channelState)
{
case OPEN:
_channelState = State.OCLOSED;
_channelState = State.OSHUT;
return false;
case ICLOSED:
case ISHUT:
_channelState = State.CLOSED;
return true;
default:
throw new IllegalStateException(_channelState.toString());
}
@ -153,14 +168,14 @@ public class WebSocketChannelState
return false;
}
public boolean checkIncoming(Frame frame) throws ProtocolException
public boolean onIncomingFrame(Frame frame) throws ProtocolException
{
byte opcode = frame.getOpCode();
boolean fin = frame.isFin();
synchronized (this)
{
if (!isInOpen())
if (!isInputOpen())
throw new IllegalStateException(_channelState.toString());
if (opcode == OpCode.CLOSE)
@ -170,9 +185,9 @@ public class WebSocketChannelState
switch (_channelState)
{
case OPEN:
_channelState = State.ICLOSED;
_channelState = State.ISHUT;
return false;
case OCLOSED:
case OSHUT:
_channelState = State.CLOSED;
return true;
default:

View File

@ -18,6 +18,13 @@
package org.eclipse.jetty.websocket.core.internal;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.Executor;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.Connection;
@ -34,13 +41,6 @@ import org.eclipse.jetty.websocket.core.MessageTooLargeException;
import org.eclipse.jetty.websocket.core.ProtocolException;
import org.eclipse.jetty.websocket.core.WebSocketTimeoutException;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.Executor;
/**
* Provides the implementation of {@link org.eclipse.jetty.io.Connection} that is suitable for WebSocket
*/
@ -167,22 +167,44 @@ public class WebSocketConnection extends AbstractConnection implements Connectio
if (LOG.isDebugEnabled())
LOG.debug("onClose() of physical connection");
// TODO review all close paths
IOException e = new IOException("Closed");
channel.onClosed(e);
if (!channel.isClosed())
{
IOException e = new IOException("Closed");
channel.onClosed(e);
}
flusher.onClose();
super.onClose();
}
@Override
public boolean onIdleExpired()
{
if (LOG.isDebugEnabled())
LOG.debug("onIdleExpired()");
channel.processError(new WebSocketTimeoutException("Connection Idle Timeout"));
// treat as a handler error because socket is still open
channel.processHandlerError(new WebSocketTimeoutException("Connection Idle Timeout"));
return true;
}
/**
* Event for no activity on connection (read or write)
*
* @return true to signal that the endpoint must be closed, false to keep the endpoint open
*/
@Override
protected boolean onReadTimeout(Throwable timeout)
{
if (LOG.isDebugEnabled())
LOG.debug("onReadTimeout()");
// treat as a handler error because socket is still open
channel.processHandlerError(new WebSocketTimeoutException("Timeout on Read", timeout));
return false;
}
protected void onFrame(Parser.ParsedFrame frame)
{
if (LOG.isDebugEnabled())
@ -219,7 +241,7 @@ public class WebSocketConnection extends AbstractConnection implements Connectio
referenced.release();
// notify session & endpoint
channel.processError(cause);
channel.processHandlerError(cause);
}
});
}
@ -431,7 +453,7 @@ public class WebSocketConnection extends AbstractConnection implements Connectio
LOG.warn(t.toString());
BufferUtil.clear(networkBuffer.getBuffer());
releaseNetworkBuffer();
channel.processError(t);
channel.processConnectionError(t);
}
}
@ -476,18 +498,6 @@ public class WebSocketConnection extends AbstractConnection implements Connectio
super.onOpen();
}
/**
* Event for no activity on connection (read or write)
*
* @return true to signal that the endpoint must be closed, false to keep the endpoint open
*/
@Override
protected boolean onReadTimeout(Throwable timeout)
{
channel.processError(new WebSocketTimeoutException("Timeout on Read", timeout));
return false;
}
@Override
public void setInputBufferSize(int inputBufferSize)
{
@ -577,7 +587,6 @@ public class WebSocketConnection extends AbstractConnection implements Connectio
/**
* Enqueue a Frame to be sent.
* @see #sendFrameQueue()
* @param frame The frame to queue
* @param callback The callback to call once the frame is sent
* @param batch True if batch mode is to be used
@ -592,10 +601,6 @@ public class WebSocketConnection extends AbstractConnection implements Connectio
wsf.setMask(mask);
}
flusher.enqueue(frame, callback, batch);
}
void sendFrameQueue()
{
flusher.iterate();
}
@ -610,7 +615,7 @@ public class WebSocketConnection extends AbstractConnection implements Connectio
public void onCompleteFailure(Throwable x)
{
super.onCompleteFailure(x);
channel.processError(x);
channel.processConnectionError(x);
}
}
}

View File

@ -18,6 +18,11 @@
package org.eclipse.jetty.websocket.core;
import java.net.Socket;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.NetworkConnector;
import org.eclipse.jetty.server.Server;
@ -39,11 +44,6 @@ import org.eclipse.jetty.websocket.core.server.internal.RFC6455Handshaker;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import java.net.Socket;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import static org.eclipse.jetty.util.Callback.NOOP;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
@ -65,7 +65,7 @@ public class WebSocketCloseTest extends WebSocketTester
enum State
{
OPEN, ICLOSED, OCLOSED
OPEN, ISHUT, OSHUT
}
@AfterEach
@ -93,7 +93,7 @@ public class WebSocketCloseTest extends WebSocketTester
break;
}
case ICLOSED:
case ISHUT:
{
TestFrameHandler serverHandler = new TestFrameHandler();
@ -109,12 +109,12 @@ public class WebSocketCloseTest extends WebSocketTester
assertNotNull(frame);
assertThat(new CloseStatus(frame.getPayload()).getCode(), is(CloseStatus.NORMAL));
assertThat(server.handler.getCoreSession().toString(), containsString("ICLOSED"));
LOG.info("Server: ICLOSED");
assertThat(server.handler.getCoreSession().toString(), containsString("ISHUT"));
LOG.info("Server: ISHUT");
break;
}
case OCLOSED:
case OSHUT:
{
TestFrameHandler serverHandler = new TestFrameHandler();
@ -129,8 +129,8 @@ public class WebSocketCloseTest extends WebSocketTester
assertNotNull(frame);
assertThat(new CloseStatus(frame.getPayload()).getCode(), is(CloseStatus.NORMAL));
assertThat(server.handler.getCoreSession().toString(), containsString("OCLOSED"));
LOG.info("Server: OCLOSED");
assertThat(server.handler.getCoreSession().toString(), containsString("OSHUT"));
LOG.info("Server: OSHUT");
break;
}
@ -140,7 +140,7 @@ public class WebSocketCloseTest extends WebSocketTester
@Test
public void serverClose_ICLOSED() throws Exception
{
setup(State.ICLOSED);
setup(State.ISHUT);
server.handler.receivedCallback.poll().succeeded();
Frame frame = receiveFrame(client.getInputStream());
@ -154,7 +154,7 @@ public class WebSocketCloseTest extends WebSocketTester
@Test
public void serverDifferentClose_ICLOSED() throws Exception
{
setup(State.ICLOSED);
setup(State.ISHUT);
server.sendFrame(CloseStatus.toFrame(CloseStatus.SHUTDOWN));
server.handler.receivedCallback.poll().succeeded();
@ -171,7 +171,7 @@ public class WebSocketCloseTest extends WebSocketTester
{
try (StacklessLogging stackless = new StacklessLogging(WebSocketChannel.class))
{
setup(State.ICLOSED);
setup(State.ISHUT);
server.handler.receivedCallback.poll().failed(new Exception("test failure"));
Frame frame = receiveFrame(client.getInputStream());
@ -186,7 +186,7 @@ public class WebSocketCloseTest extends WebSocketTester
@Test
public void clientClose_OCLOSED() throws Exception
{
setup(State.OCLOSED);
setup(State.OSHUT);
server.handler.getCoreSession().demand(1);
client.getOutputStream().write(RawFrameBuilder.buildClose(new CloseStatus(CloseStatus.NORMAL), true));
assertNotNull(server.handler.receivedFrames.poll(10, TimeUnit.SECONDS));
@ -201,7 +201,7 @@ public class WebSocketCloseTest extends WebSocketTester
@Test
public void clientDifferentClose_OCLOSED() throws Exception
{
setup(State.OCLOSED);
setup(State.OSHUT);
server.handler.getCoreSession().demand(1);
client.getOutputStream().write(RawFrameBuilder.buildClose(new CloseStatus(CloseStatus.BAD_PAYLOAD), true));
assertNotNull(server.handler.receivedFrames.poll(10, TimeUnit.SECONDS));
@ -218,7 +218,7 @@ public class WebSocketCloseTest extends WebSocketTester
{
try (StacklessLogging stackless = new StacklessLogging(WebSocketChannel.class))
{
setup(State.OCLOSED);
setup(State.OSHUT);
server.handler.getCoreSession().demand(1);
client.getOutputStream().write(RawFrameBuilder.buildClose(new CloseStatus(CloseStatus.NORMAL), true));
assertNotNull(server.handler.receivedFrames.poll(10, TimeUnit.SECONDS));
@ -246,7 +246,7 @@ public class WebSocketCloseTest extends WebSocketTester
@Test
public void clientSendsBadFrame_OCLOSED() throws Exception
{
setup(State.OCLOSED);
setup(State.OSHUT);
client.getOutputStream().write(RawFrameBuilder.buildFrame(OpCode.PONG, "pong frame not masked", false));
server.handler.getCoreSession().demand(1);
@ -258,7 +258,7 @@ public class WebSocketCloseTest extends WebSocketTester
@Test
public void clientSendsBadFrame_ICLOSED() throws Exception
{
setup(State.ICLOSED);
setup(State.ISHUT);
client.getOutputStream().write(RawFrameBuilder.buildFrame(OpCode.PONG, "pong frame not masked", false));
assertFalse(server.handler.closed.await(250, TimeUnit.MILLISECONDS));
@ -286,7 +286,7 @@ public class WebSocketCloseTest extends WebSocketTester
@Test
public void clientAborts_OCLOSED() throws Exception
{
setup(State.OCLOSED);
setup(State.OSHUT);
client.close();
assertFalse(server.handler.closed.await(250, TimeUnit.MILLISECONDS));
@ -299,7 +299,7 @@ public class WebSocketCloseTest extends WebSocketTester
@Test
public void clientAborts_ICLOSED() throws Exception
{
setup(State.ICLOSED);
setup(State.ISHUT);
client.close();
assertFalse(server.handler.closed.await(250, TimeUnit.MILLISECONDS));
@ -330,7 +330,7 @@ public class WebSocketCloseTest extends WebSocketTester
@Test
public void onFrameThrows_OCLOSED() throws Exception
{
setup(State.OCLOSED);
setup(State.OSHUT);
client.getOutputStream().write(RawFrameBuilder.buildFrame(OpCode.BINARY, "binary", true));
@ -478,7 +478,7 @@ public class WebSocketCloseTest extends WebSocketTester
public boolean isOpen()
{
return handler.getCoreSession().isOpen();
return handler.getCoreSession().isOutputOpen();
}
}
}

View File

@ -18,6 +18,11 @@
package org.eclipse.jetty.websocket.core.client;
import java.net.URI;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.NetworkConnector;
import org.eclipse.jetty.server.Server;
@ -45,11 +50,6 @@ import org.hamcrest.Matchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.net.URI;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ -208,7 +208,7 @@ public class WebSocketClientServerTest
public boolean isOpen()
{
return handler.getCoreSession().isOpen();
return handler.getCoreSession().isOutputOpen();
}
}
@ -272,7 +272,7 @@ public class WebSocketClientServerTest
public boolean isOpen()
{
return handler.getCoreSession().isOpen();
return handler.getCoreSession().isOutputOpen();
}
}

View File

@ -18,6 +18,9 @@
package org.eclipse.jetty.websocket.core.extensions;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.util.DecoratedObjectFactory;
@ -35,9 +38,6 @@ import org.eclipse.jetty.websocket.core.internal.IdentityExtension;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -80,7 +80,7 @@ public class ExtensionStackTest
// Setup Listeners
IncomingFrames session = new IncomingFramesCapture();
OutgoingFrames connection = new OutgoingFramesCapture();
stack.connect(session, connection, null);
stack.initialize(session, connection, null);
// Dump
LOG.debug("{}", stack.dump());
@ -104,7 +104,7 @@ public class ExtensionStackTest
// Setup Listeners
IncomingFrames session = new IncomingFramesCapture();
OutgoingFrames connection = new OutgoingFramesCapture();
stack.connect(session, connection, null);
stack.initialize(session, connection, null);
// Dump
LOG.debug("{}", stack.dump());

View File

@ -18,6 +18,10 @@
package org.eclipse.jetty.websocket.core.extensions;
import java.net.Socket;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.NetworkConnector;
import org.eclipse.jetty.server.Server;
@ -44,10 +48,6 @@ import org.eclipse.jetty.websocket.core.server.WebSocketUpgradeHandler;
import org.eclipse.jetty.websocket.core.server.internal.RFC6455Handshaker;
import org.junit.jupiter.api.Test;
import java.net.Socket;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import static org.eclipse.jetty.util.Callback.NOOP;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
@ -218,7 +218,7 @@ public class ValidationExtensionTest extends WebSocketTester
public boolean isOpen()
{
return handler.getCoreSession().isOpen();
return handler.getCoreSession().isOutputOpen();
}
}
}

View File

@ -18,6 +18,12 @@
package org.eclipse.jetty.websocket.core.server;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.NetworkConnector;
@ -46,12 +52,6 @@ import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
@ -547,7 +547,7 @@ public class WebSocketServerTest extends WebSocketTester
public boolean isOpen()
{
return handler.getCoreSession().isOpen();
return handler.getCoreSession().isOutputOpen();
}
}
}

View File

@ -436,7 +436,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<version>3.1.1</version>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty.toolchain</groupId>