Merge remote-tracking branch 'origin/jetty-10.0.x' into jetty-10.0.x-3012-Compliance
This commit is contained in:
commit
0ecbdec9d0
|
@ -179,7 +179,6 @@ To allow the greatest degree of flexibility in using JAAS with web applications,
|
|||
Note that you don't ordinarily need to set these explicitly, as Jetty has defaults which will work in 99% of cases.
|
||||
However, should you need to, you can configure:
|
||||
|
||||
* a policy for role-based authorization (Default: `org.eclipse.jetty.jaas.StrictRoleCheckPolicy`)
|
||||
* a CallbackHandler (Default: `org.eclipse.jetty.jaas.callback.DefaultCallbackHandler`)
|
||||
* a list of classnames for the Principal implementation that equate to a user role (Default: `org.eclipse.jetty.jaas.JAASRole`)
|
||||
|
||||
|
@ -190,9 +189,6 @@ Here's an example of setting each of these (to their default values):
|
|||
<New class="org.eclipse.jetty.jaas.JAASLoginService">
|
||||
<Set name="Name">Test JAAS Realm</Set>
|
||||
<Set name="LoginModuleName">xyz</Set>
|
||||
<Set name="RoleCheckPolicy">
|
||||
<New class="org.eclipse.jetty.jaas.StrictRoleCheckPolicy"/>
|
||||
</Set>
|
||||
<Set name="CallbackHandlerClass">
|
||||
org.eclipse.jetty.jaas.callback.DefaultCallbackHandler
|
||||
</Set>
|
||||
|
@ -204,16 +200,6 @@ Here's an example of setting each of these (to their default values):
|
|||
</New>
|
||||
----
|
||||
|
||||
===== RoleCheckPolicy
|
||||
|
||||
The `RoleCheckPolicy` must be an implementation of the `org.eclipse.jetty.jaas.RoleCheckPolicy` interface and its purpose is to help answer the question "is User X in Role Y" for role-based authorization requests.
|
||||
The default implementation distributed with Jetty is the `org.eclipse.jetty.jaas.StrictRoleCheckPolicy`, which will assess a user as having a particular role if that role is at the top of the stack of roles that have been temporarily pushed onto the user.
|
||||
If the user has no temporarily assigned roles, the role is amongst those configured for the user.
|
||||
|
||||
Roles can be temporarily assigned to a user programmatically by using the `pushRole(String rolename)` method of the `org.eclipse.jetty.jaas.JAASUserPrincipal` class.
|
||||
|
||||
For the majority of webapps, the default `StrictRoleCheckPolicy` will be quite adequate, however you may provide your own implementation and set it on your `JAASLoginService` instance.
|
||||
|
||||
===== CallbackHandler
|
||||
|
||||
A CallbackHandler is responsible for interfacing with the user to obtain usernames and credentials to be authenticated.
|
||||
|
|
|
@ -33,6 +33,20 @@ import static java.lang.Long.MAX_VALUE;
|
|||
* <p>Subclasses should implement {@link #onTimeoutExpired()}.</p>
|
||||
* <p>This implementation is optimised assuming that the timeout
|
||||
* will mostly be cancelled and then reused with a similar value.</p>
|
||||
* <p>This implementation has a {@link Timeout} holding the time
|
||||
* at which the scheduled task should fire, and a linked list of
|
||||
* {@link Wakeup}, each holding the actual scheduled task.</p>
|
||||
* <p>Calling {@link #schedule(long, TimeUnit)} the first time will
|
||||
* create a Timeout with an associated Wakeup and submit a task to
|
||||
* the scheduler.
|
||||
* Calling {@link #schedule(long, TimeUnit)} again with the same or
|
||||
* a larger delay will cancel the previous Timeout, but keep the
|
||||
* previous Wakeup without submitting a new task to the scheduler,
|
||||
* therefore reducing the pressure on the scheduler and avoid it
|
||||
* becomes a bottleneck.
|
||||
* When the Wakeup task fires, it will see that the Timeout is now
|
||||
* in the future and will attach a new Wakeup with the future time
|
||||
* to the Timeout, and submit a scheduler task for the new Wakeup.</p>
|
||||
*/
|
||||
public abstract class CyclicTimeout implements Destroyable
|
||||
{
|
||||
|
@ -59,24 +73,24 @@ public abstract class CyclicTimeout implements Destroyable
|
|||
}
|
||||
|
||||
/**
|
||||
* Schedules a timeout, even if already set, cancelled or expired.
|
||||
* <p>Schedules a timeout, even if already set, cancelled or expired.</p>
|
||||
* <p>If a timeout is already set, it will be cancelled and replaced
|
||||
* by the new one.</p>
|
||||
*
|
||||
* @param delay The period of time before the timeout expires.
|
||||
* @param units The unit of time of the period.
|
||||
* @return true if the timer was already set.
|
||||
* @return true if the timeout was already set.
|
||||
*/
|
||||
public boolean schedule(long delay, TimeUnit units)
|
||||
{
|
||||
long now = System.nanoTime();
|
||||
long new_timeout_at = now + units.toNanos(delay);
|
||||
|
||||
Wakeup new_wakeup = null;
|
||||
boolean result;
|
||||
Wakeup new_wakeup;
|
||||
while (true)
|
||||
{
|
||||
Timeout timeout = _timeout.get();
|
||||
|
||||
new_wakeup = null;
|
||||
result = timeout._at != MAX_VALUE;
|
||||
|
||||
// Is the current wakeup good to use? ie before our timeout time?
|
||||
|
@ -114,14 +128,12 @@ public abstract class CyclicTimeout implements Destroyable
|
|||
public boolean cancel()
|
||||
{
|
||||
boolean result;
|
||||
Timeout timeout;
|
||||
Timeout new_timeout;
|
||||
while (true)
|
||||
{
|
||||
timeout = _timeout.get();
|
||||
Timeout timeout = _timeout.get();
|
||||
result = timeout._at != MAX_VALUE;
|
||||
Wakeup wakeup = timeout._wakeup;
|
||||
new_timeout = wakeup == null ? NOT_SET : new Timeout(MAX_VALUE, wakeup);
|
||||
Timeout new_timeout = wakeup == null ? NOT_SET : new Timeout(MAX_VALUE, wakeup);
|
||||
if (_timeout.compareAndSet(timeout, new_timeout))
|
||||
break;
|
||||
}
|
||||
|
@ -166,7 +178,11 @@ public abstract class CyclicTimeout implements Destroyable
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s@%x:%d,%s", getClass().getSimpleName(), hashCode(), _at, _wakeup);
|
||||
return String.format("%s@%x:%dms,%s",
|
||||
getClass().getSimpleName(),
|
||||
hashCode(),
|
||||
TimeUnit.NANOSECONDS.toMillis(_at - System.nanoTime()),
|
||||
_wakeup);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -200,10 +216,9 @@ public abstract class CyclicTimeout implements Destroyable
|
|||
@Override
|
||||
public void run()
|
||||
{
|
||||
long now;
|
||||
Wakeup new_wakeup;
|
||||
boolean has_expired;
|
||||
|
||||
long now = System.nanoTime();
|
||||
Wakeup new_wakeup = null;
|
||||
boolean has_expired = false;
|
||||
while (true)
|
||||
{
|
||||
Timeout timeout = _timeout.get();
|
||||
|
@ -226,16 +241,12 @@ public abstract class CyclicTimeout implements Destroyable
|
|||
// Not found, we become a noop.
|
||||
return;
|
||||
|
||||
now = System.nanoTime();
|
||||
new_wakeup = null;
|
||||
has_expired = false;
|
||||
Timeout new_timeout;
|
||||
|
||||
// We are in the wakeup list! So we have to act and we know our
|
||||
// tail has not expired (else it would have removed us from the list).
|
||||
// Remove ourselves (and any prior Wakeup) from the wakeup list.
|
||||
wakeup = wakeup._next;
|
||||
|
||||
Timeout new_timeout;
|
||||
if (timeout._at <= now)
|
||||
{
|
||||
// We have timed out!
|
||||
|
@ -274,7 +285,11 @@ public abstract class CyclicTimeout implements Destroyable
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s@%x:%d->%s", getClass().getSimpleName(), hashCode(), _at, _next);
|
||||
return String.format("%s@%x:%dms->%s",
|
||||
getClass().getSimpleName(),
|
||||
hashCode(),
|
||||
_at == MAX_VALUE ? _at : TimeUnit.NANOSECONDS.toMillis(_at - System.nanoTime()),
|
||||
_next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,117 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 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.jaas;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.security.acl.Group;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
||||
public class JAASGroup implements Group
|
||||
{
|
||||
public static final String ROLES = "__roles__";
|
||||
|
||||
private String _name = null;
|
||||
private HashSet<Principal> _members = null;
|
||||
|
||||
public JAASGroup(String n)
|
||||
{
|
||||
this._name = n;
|
||||
this._members = new HashSet<Principal>();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public synchronized boolean addMember(Principal principal)
|
||||
{
|
||||
return _members.add(principal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean removeMember(Principal principal)
|
||||
{
|
||||
return _members.remove(principal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMember(Principal principal)
|
||||
{
|
||||
return _members.contains(principal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<? extends Principal> members()
|
||||
{
|
||||
|
||||
class MembersEnumeration implements Enumeration<Principal>
|
||||
{
|
||||
private Iterator<? extends Principal> itor;
|
||||
|
||||
public MembersEnumeration (Iterator<? extends Principal> itor)
|
||||
{
|
||||
this.itor = itor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMoreElements ()
|
||||
{
|
||||
return this.itor.hasNext();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Principal nextElement ()
|
||||
{
|
||||
return this.itor.next();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return new MembersEnumeration (_members.iterator());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return getName().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object)
|
||||
{
|
||||
if (! (object instanceof JAASGroup))
|
||||
return false;
|
||||
|
||||
return ((JAASGroup)object).getName().equals(getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
|
||||
return _name;
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 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.jaas;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.security.acl.Group;
|
||||
|
||||
public interface RoleCheckPolicy
|
||||
{
|
||||
/* ------------------------------------------------ */
|
||||
/** Check if a role is either a runAsRole or in a set of roles
|
||||
* @param roleName the role to check
|
||||
* @param runAsRole a pushed role (can be null)
|
||||
* @param roles a Group whose Principals are role names
|
||||
* @return <code>true</code> if <code>role</code> equals <code>runAsRole</code> or is a member of <code>roles</code>.
|
||||
*/
|
||||
public boolean checkRole (String roleName, Principal runAsRole, Group roles);
|
||||
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 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.jaas;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.security.acl.Group;
|
||||
import java.util.Enumeration;
|
||||
|
||||
|
||||
/* ---------------------------------------------------- */
|
||||
/** StrictRoleCheckPolicy
|
||||
* <p>Enforces that if a runAsRole is present, then the
|
||||
* role to check must be the same as that runAsRole and
|
||||
* the set of static roles is ignored.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class StrictRoleCheckPolicy implements RoleCheckPolicy
|
||||
{
|
||||
|
||||
@Override
|
||||
public boolean checkRole (String roleName, Principal runAsRole, Group roles)
|
||||
{
|
||||
//check if this user has had any temporary role pushed onto
|
||||
//them. If so, then only check if the user has that role.
|
||||
if (runAsRole != null)
|
||||
{
|
||||
return (roleName.equals(runAsRole.getName()));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (roles == null)
|
||||
return false;
|
||||
Enumeration<? extends Principal> rolesEnum = roles.members();
|
||||
boolean found = false;
|
||||
while (rolesEnum.hasMoreElements() && !found)
|
||||
{
|
||||
Principal p = (Principal)rolesEnum.nextElement();
|
||||
found = roleName.equals(p.getName());
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -29,6 +29,7 @@ import java.util.Optional;
|
|||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.websocket.CloseReason;
|
||||
import javax.websocket.Decoder;
|
||||
import javax.websocket.EndpointConfig;
|
||||
|
@ -234,7 +235,7 @@ public class JavaxWebSocketFrameHandler implements FrameHandler
|
|||
}
|
||||
catch (Throwable cause)
|
||||
{
|
||||
Exception wse = new WebSocketException(endpointInstance.getClass().getName() + " OPEN method error: " + cause.getMessage(), cause);
|
||||
Exception wse = new WebSocketException(endpointInstance.getClass().getSimpleName() + " OPEN method error: " + cause.getMessage(), cause);
|
||||
callback.failed(wse);
|
||||
futureSession.completeExceptionally(wse);
|
||||
}
|
||||
|
@ -283,12 +284,13 @@ public class JavaxWebSocketFrameHandler implements FrameHandler
|
|||
closeHandle.invoke(closeReason);
|
||||
}
|
||||
callback.succeeded();
|
||||
container.notifySessionListeners((listener) -> listener.onJavaxWebSocketSessionClosed(session));
|
||||
}
|
||||
catch (Throwable cause)
|
||||
{
|
||||
callback.failed(new WebSocketException(endpointInstance.getClass().getName() + " CLOSE method error: " + cause.getMessage(), cause));
|
||||
callback.failed(new WebSocketException(endpointInstance.getClass().getSimpleName() + " CLOSE method error: " + cause.getMessage(), cause));
|
||||
}
|
||||
|
||||
container.notifySessionListeners((listener) -> listener.onJavaxWebSocketSessionClosed(session));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -306,7 +308,7 @@ public class JavaxWebSocketFrameHandler implements FrameHandler
|
|||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
WebSocketException wsError = new WebSocketException(endpointInstance.getClass().getName() + " ERROR method error: " + cause.getMessage(), t);
|
||||
WebSocketException wsError = new WebSocketException(endpointInstance.getClass().getSimpleName() + " ERROR method error: " + cause.getMessage(), t);
|
||||
wsError.addSuppressed(cause);
|
||||
callback.failed(wsError);
|
||||
// TODO should futureSession be failed here?
|
||||
|
@ -609,7 +611,7 @@ public class JavaxWebSocketFrameHandler implements FrameHandler
|
|||
}
|
||||
catch (Throwable cause)
|
||||
{
|
||||
throw new WebSocketException(endpointInstance.getClass().getName() + " PONG method error: " + cause.getMessage(), cause);
|
||||
throw new WebSocketException(endpointInstance.getClass().getSimpleName() + " PONG method error: " + cause.getMessage(), cause);
|
||||
}
|
||||
}
|
||||
callback.succeeded();
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.eclipse.jetty.websocket.javax.common;
|
|||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import javax.websocket.Session;
|
||||
|
||||
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
||||
|
@ -44,7 +45,7 @@ public class SessionTracker extends AbstractLifeCycle implements JavaxWebSocketS
|
|||
@Override
|
||||
public void onJavaxWebSocketSessionClosed(JavaxWebSocketSession session)
|
||||
{
|
||||
sessions.remove(sessions);
|
||||
sessions.remove(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -18,20 +18,6 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.javax.tests.server;
|
||||
|
||||
import org.eclipse.jetty.util.BlockingArrayQueue;
|
||||
import org.eclipse.jetty.websocket.core.Frame;
|
||||
import org.eclipse.jetty.websocket.core.OpCode;
|
||||
import org.eclipse.jetty.websocket.javax.tests.Fuzzer;
|
||||
import org.eclipse.jetty.websocket.javax.tests.LocalServer;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import javax.websocket.OnMessage;
|
||||
import javax.websocket.OnOpen;
|
||||
import javax.websocket.Session;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -39,9 +25,22 @@ import java.util.Collection;
|
|||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.websocket.OnMessage;
|
||||
import javax.websocket.OnOpen;
|
||||
import javax.websocket.Session;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
|
||||
import org.eclipse.jetty.util.BlockingArrayQueue;
|
||||
import org.eclipse.jetty.websocket.core.Frame;
|
||||
import org.eclipse.jetty.websocket.core.OpCode;
|
||||
import org.eclipse.jetty.websocket.javax.tests.Fuzzer;
|
||||
import org.eclipse.jetty.websocket.javax.tests.LocalServer;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
@Disabled("Replaced with ServerCloseTest.testOpenSessionCleanup()") // TODO: Remove once ServerCloseTest is fixed
|
||||
public class SessionTrackingTest
|
||||
{
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ import java.util.function.Consumer;
|
|||
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.util.DecoratedObjectFactory;
|
||||
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
@ -49,6 +50,7 @@ import org.eclipse.jetty.websocket.common.JettyWebSocketFrameHandlerFactory;
|
|||
import org.eclipse.jetty.websocket.common.SessionTracker;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketContainer;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketSessionListener;
|
||||
import org.eclipse.jetty.websocket.core.FrameHandler;
|
||||
import org.eclipse.jetty.websocket.core.WebSocketExtensionRegistry;
|
||||
import org.eclipse.jetty.websocket.core.client.UpgradeListener;
|
||||
import org.eclipse.jetty.websocket.core.client.WebSocketCoreClient;
|
||||
|
@ -61,23 +63,16 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketPoli
|
|||
private final JettyWebSocketFrameHandlerFactory frameHandlerFactory;
|
||||
private final List<WebSocketSessionListener> sessionListeners = new CopyOnWriteArrayList<>();
|
||||
private final SessionTracker sessionTracker = new SessionTracker();
|
||||
private ClassLoader contextClassLoader;
|
||||
private final FrameHandler.ConfigurationCustomizer configurationCustomizer = new FrameHandler.ConfigurationCustomizer();
|
||||
private DecoratedObjectFactory objectFactory;
|
||||
private WebSocketExtensionRegistry extensionRegistry;
|
||||
private int inputBufferSize = 4 * 1024;
|
||||
private int outputBufferSize = 4 * 1024;
|
||||
private long maxBinaryMessageSize = 64 * 1024;
|
||||
private long maxTextMessageSize = 64 * 1024;
|
||||
|
||||
/**
|
||||
* Instantiate a WebSocketClient with defaults
|
||||
*/
|
||||
public WebSocketClient()
|
||||
{
|
||||
this(new WebSocketCoreClient());
|
||||
this.coreClient.getHttpClient().setName("Jetty-WebSocketClient@" + hashCode());
|
||||
// We created WebSocketCoreClient, let lifecycle be managed by us
|
||||
addManaged(coreClient);
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -87,19 +82,16 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketPoli
|
|||
*/
|
||||
public WebSocketClient(HttpClient httpClient)
|
||||
{
|
||||
this(new WebSocketCoreClient(httpClient));
|
||||
// We created WebSocketCoreClient, let lifecycle be managed by us
|
||||
coreClient = new WebSocketCoreClient(httpClient, configurationCustomizer);
|
||||
addManaged(coreClient);
|
||||
}
|
||||
|
||||
private WebSocketClient(WebSocketCoreClient coreClient)
|
||||
{
|
||||
this.coreClient = coreClient;
|
||||
this.contextClassLoader = this.getClass().getClassLoader();
|
||||
this.objectFactory = new DecoratedObjectFactory();
|
||||
this.extensionRegistry = new WebSocketExtensionRegistry();
|
||||
this.frameHandlerFactory = new JettyWebSocketFrameHandlerFactory(this);
|
||||
this.sessionListeners.add(sessionTracker);
|
||||
if (httpClient == null)
|
||||
coreClient.getHttpClient().setName("Jetty-WebSocketClient@" + hashCode());
|
||||
|
||||
objectFactory = new DecoratedObjectFactory();
|
||||
extensionRegistry = new WebSocketExtensionRegistry();
|
||||
frameHandlerFactory = new JettyWebSocketFrameHandlerFactory(this);
|
||||
sessionListeners.add(sessionTracker);
|
||||
addBean(sessionTracker);
|
||||
}
|
||||
|
||||
|
@ -128,15 +120,19 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketPoli
|
|||
* @param websocket the websocket object
|
||||
* @param toUri the websocket uri to connect to
|
||||
* @param request the upgrade request information
|
||||
* @param listener the upgrade listener
|
||||
* @param upgradeListener the upgrade listener
|
||||
* @return the future for the session, available on success of connect
|
||||
* @throws IOException if unable to connect
|
||||
*/
|
||||
public CompletableFuture<Session> connect(Object websocket, URI toUri, UpgradeRequest request, UpgradeListener listener) throws IOException
|
||||
public CompletableFuture<Session> connect(Object websocket, URI toUri, UpgradeRequest request, UpgradeListener upgradeListener) throws IOException
|
||||
{
|
||||
for (Connection.Listener listener : getBeans(Connection.Listener.class))
|
||||
coreClient.addBean(listener);
|
||||
|
||||
JettyClientUpgradeRequest upgradeRequest = new JettyClientUpgradeRequest(this, coreClient, request, toUri, websocket);
|
||||
if (listener != null)
|
||||
upgradeRequest.addListener(listener);
|
||||
if (upgradeListener != null)
|
||||
upgradeRequest.addListener(upgradeListener);
|
||||
|
||||
coreClient.connect(upgradeRequest);
|
||||
return upgradeRequest.getFutureSession();
|
||||
}
|
||||
|
@ -184,61 +180,61 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketPoli
|
|||
@Override
|
||||
public Duration getIdleTimeout()
|
||||
{
|
||||
return Duration.ofMillis(getHttpClient().getIdleTimeout());
|
||||
return configurationCustomizer.getIdleTimeout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInputBufferSize()
|
||||
{
|
||||
return this.inputBufferSize;
|
||||
return configurationCustomizer.getInputBufferSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOutputBufferSize()
|
||||
{
|
||||
return this.outputBufferSize;
|
||||
return configurationCustomizer.getOutputBufferSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMaxBinaryMessageSize()
|
||||
{
|
||||
return this.maxBinaryMessageSize;
|
||||
return configurationCustomizer.getMaxBinaryMessageSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMaxTextMessageSize()
|
||||
{
|
||||
return this.maxTextMessageSize;
|
||||
return configurationCustomizer.getMaxTextMessageSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdleTimeout(Duration duration)
|
||||
{
|
||||
getHttpClient().setIdleTimeout(duration.toMillis());
|
||||
configurationCustomizer.setIdleTimeout(duration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInputBufferSize(int size)
|
||||
{
|
||||
this.inputBufferSize = size;
|
||||
configurationCustomizer.setInputBufferSize(size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOutputBufferSize(int size)
|
||||
{
|
||||
this.outputBufferSize = size;
|
||||
configurationCustomizer.setOutputBufferSize(size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxBinaryMessageSize(long size)
|
||||
{
|
||||
this.maxBinaryMessageSize = size;
|
||||
configurationCustomizer.setMaxBinaryMessageSize(size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxTextMessageSize(long size)
|
||||
{
|
||||
this.maxTextMessageSize = size;
|
||||
configurationCustomizer.setMaxTextMessageSize(size);
|
||||
}
|
||||
|
||||
public SocketAddress getBindAddress()
|
||||
|
|
|
@ -150,7 +150,7 @@ public class JettyWebSocketFrameHandler implements FrameHandler
|
|||
}
|
||||
catch (Throwable cause)
|
||||
{
|
||||
callback.failed(new WebSocketException(endpointInstance.getClass().getName() + " OPEN method error: " + cause.getMessage(), cause));
|
||||
callback.failed(new WebSocketException(endpointInstance.getClass().getSimpleName() + " OPEN method error: " + cause.getMessage(), cause));
|
||||
futureSession.completeExceptionally(cause);
|
||||
}
|
||||
}
|
||||
|
@ -172,7 +172,7 @@ public class JettyWebSocketFrameHandler implements FrameHandler
|
|||
}
|
||||
catch (Throwable cause)
|
||||
{
|
||||
throw new WebSocketException(endpointInstance.getClass().getName() + " FRAME method error: " + cause.getMessage(), cause);
|
||||
throw new WebSocketException(endpointInstance.getClass().getSimpleName() + " FRAME method error: " + cause.getMessage(), cause);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -219,7 +219,7 @@ public class JettyWebSocketFrameHandler implements FrameHandler
|
|||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
WebSocketException wsError = new WebSocketException(endpointInstance.getClass().getName() + " ERROR method error: " + cause.getMessage(), t);
|
||||
WebSocketException wsError = new WebSocketException(endpointInstance.getClass().getSimpleName() + " ERROR method error: " + cause.getMessage(), t);
|
||||
wsError.addSuppressed(cause);
|
||||
callback.failed(wsError);
|
||||
}
|
||||
|
@ -228,7 +228,18 @@ public class JettyWebSocketFrameHandler implements FrameHandler
|
|||
@Override
|
||||
public void onClosed(CloseStatus closeStatus, Callback callback)
|
||||
{
|
||||
callback.succeeded();
|
||||
try
|
||||
{
|
||||
if (closeHandle != null)
|
||||
closeHandle.invoke(closeStatus.getCode(), closeStatus.getReason());
|
||||
|
||||
callback.succeeded();
|
||||
}
|
||||
catch (Throwable cause)
|
||||
{
|
||||
callback.failed(new WebSocketException(endpointInstance.getClass().getSimpleName() + " CLOSE method error: " + cause.getMessage(), cause));
|
||||
}
|
||||
|
||||
container.notifySessionListeners((listener) -> listener.onWebSocketSessionClosed(session));
|
||||
}
|
||||
|
||||
|
@ -262,18 +273,6 @@ public class JettyWebSocketFrameHandler implements FrameHandler
|
|||
|
||||
private void onCloseFrame(Frame frame, Callback callback)
|
||||
{
|
||||
if (closeHandle != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
CloseStatus close = new CloseStatus(frame.getPayload());
|
||||
closeHandle.invoke(close.getCode(), close.getReason());
|
||||
}
|
||||
catch (Throwable cause)
|
||||
{
|
||||
throw new WebSocketException(endpointInstance.getClass().getName() + " CLOSE method error: " + cause.getMessage(), cause);
|
||||
}
|
||||
}
|
||||
callback.succeeded();
|
||||
}
|
||||
|
||||
|
@ -296,7 +295,7 @@ public class JettyWebSocketFrameHandler implements FrameHandler
|
|||
}
|
||||
catch (Throwable cause)
|
||||
{
|
||||
throw new WebSocketException(endpointInstance.getClass().getName() + " PING method error: " + cause.getMessage(), cause);
|
||||
throw new WebSocketException(endpointInstance.getClass().getSimpleName() + " PING method error: " + cause.getMessage(), cause);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -324,7 +323,7 @@ public class JettyWebSocketFrameHandler implements FrameHandler
|
|||
}
|
||||
catch (Throwable cause)
|
||||
{
|
||||
throw new WebSocketException(endpointInstance.getClass().getName() + " PONG method error: " + cause.getMessage(), cause);
|
||||
throw new WebSocketException(endpointInstance.getClass().getSimpleName() + " PONG method error: " + cause.getMessage(), cause);
|
||||
}
|
||||
}
|
||||
callback.succeeded();
|
||||
|
|
|
@ -19,10 +19,12 @@
|
|||
package org.eclipse.jetty.websocket.common;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
|
||||
import static org.eclipse.jetty.toolchain.test.matchers.RegexMatcher.matchesPattern;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
public class EventQueue extends LinkedBlockingDeque<String>
|
||||
{
|
||||
|
@ -33,10 +35,18 @@ public class EventQueue extends LinkedBlockingDeque<String>
|
|||
|
||||
public void assertEvents(String... regexEvents)
|
||||
{
|
||||
Iterator<String> capturedIterator = iterator();
|
||||
for (int i = 0; i < regexEvents.length; i++)
|
||||
int i = 0;
|
||||
try
|
||||
{
|
||||
assertThat("Event [" + i + "]", capturedIterator.next(), matchesPattern(regexEvents[i]));
|
||||
Iterator<String> capturedIterator = iterator();
|
||||
for (i = 0; i < regexEvents.length; i++)
|
||||
{
|
||||
assertThat("Event [" + i + "]", capturedIterator.next(), matchesPattern(regexEvents[i]));
|
||||
}
|
||||
}
|
||||
catch (NoSuchElementException e)
|
||||
{
|
||||
fail("Event [" + (i) + "] not found: " + regexEvents[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,7 +121,7 @@ public class JettyWebSocketFrameHandlerTest
|
|||
// Trigger Events
|
||||
localEndpoint.onOpen(channel, Callback.NOOP);
|
||||
localEndpoint.onFrame(new Frame(OpCode.TEXT).setPayload("Hello?").setFin(true), Callback.NOOP);
|
||||
localEndpoint.onFrame(CloseStatus.toFrame(StatusCode.NORMAL, "Normal"), Callback.NOOP);
|
||||
localEndpoint.onClosed(new CloseStatus(StatusCode.NORMAL, "Normal"), Callback.NOOP);
|
||||
|
||||
// Validate Events
|
||||
socket.events.assertEvents(
|
||||
|
@ -216,6 +216,7 @@ public class JettyWebSocketFrameHandlerTest
|
|||
localEndpoint.onFrame(new Frame(OpCode.CONTINUATION).setPayload(" the ").setFin(false), Callback.NOOP);
|
||||
localEndpoint.onFrame(new Frame(OpCode.CONTINUATION).setPayload("Pig").setFin(true), Callback.NOOP);
|
||||
localEndpoint.onFrame(CloseStatus.toFrame(StatusCode.NORMAL), Callback.NOOP);
|
||||
localEndpoint.onClosed(CloseStatus.NORMAL_STATUS, Callback.NOOP);
|
||||
|
||||
// Validate Events
|
||||
socket.events.assertEvents(
|
||||
|
@ -245,7 +246,7 @@ public class JettyWebSocketFrameHandlerTest
|
|||
localEndpoint.onFrame(new Frame(OpCode.BINARY).setPayload("Save").setFin(false), Callback.NOOP);
|
||||
localEndpoint.onFrame(new Frame(OpCode.CONTINUATION).setPayload(" the ").setFin(false), Callback.NOOP);
|
||||
localEndpoint.onFrame(new Frame(OpCode.CONTINUATION).setPayload("Pig").setFin(true), Callback.NOOP);
|
||||
localEndpoint.onFrame(CloseStatus.toFrame(StatusCode.NORMAL, "Normal"), Callback.NOOP);
|
||||
localEndpoint.onClosed(new CloseStatus(StatusCode.NORMAL, "Normal"), Callback.NOOP);
|
||||
|
||||
// Validate Events
|
||||
socket.events.assertEvents(
|
||||
|
@ -323,7 +324,7 @@ public class JettyWebSocketFrameHandlerTest
|
|||
localEndpoint.onFrame(new Frame(OpCode.CONTINUATION).setPayload(" the ").setFin(false), Callback.NOOP);
|
||||
localEndpoint.onFrame(new Frame(OpCode.PONG).setPayload("You there?"), Callback.NOOP);
|
||||
localEndpoint.onFrame(new Frame(OpCode.CONTINUATION).setPayload("Pig").setFin(true), Callback.NOOP);
|
||||
localEndpoint.onFrame(CloseStatus.toFrame(StatusCode.NORMAL, "Normal"), Callback.NOOP);
|
||||
localEndpoint.onClosed(new CloseStatus(StatusCode.NORMAL, "Normal"), Callback.NOOP);
|
||||
|
||||
// Validate Events
|
||||
socket.events.assertEvents(
|
||||
|
|
|
@ -43,7 +43,6 @@ import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
|
|||
import org.eclipse.jetty.websocket.tests.CloseTrackingEndpoint;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
@ -52,7 +51,6 @@ import static org.hamcrest.Matchers.is;
|
|||
/**
|
||||
* Tests for conditions due to bad networking.
|
||||
*/
|
||||
@Disabled("Needs triage")
|
||||
public class BadNetworkTest
|
||||
{
|
||||
private Server server;
|
||||
|
|
|
@ -28,7 +28,6 @@ import java.util.Arrays;
|
|||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
|
@ -39,12 +38,12 @@ import org.eclipse.jetty.servlet.ServletContextHandler;
|
|||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.CloseException;
|
||||
import org.eclipse.jetty.websocket.api.MessageTooLargeException;
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.StatusCode;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketFrameListener;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketListener;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketTimeoutException;
|
||||
import org.eclipse.jetty.websocket.api.util.WSURI;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.eclipse.jetty.websocket.core.CloseStatus;
|
||||
|
@ -55,7 +54,6 @@ import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
|
|||
import org.eclipse.jetty.websocket.tests.CloseTrackingEndpoint;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
@ -68,7 +66,6 @@ import static org.hamcrest.Matchers.is;
|
|||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
|
||||
|
||||
@Disabled("Needs triage")
|
||||
public class ClientCloseTest
|
||||
{
|
||||
private Server server;
|
||||
|
@ -252,8 +249,8 @@ public class ClientCloseTest
|
|||
// client reads -1 (EOF)
|
||||
// client triggers close event on client ws-endpoint
|
||||
clientSocket.assertReceivedCloseEvent(clientTimeout * 2,
|
||||
is(StatusCode.SHUTDOWN),
|
||||
containsString("timeout"));
|
||||
is(StatusCode.ABNORMAL),
|
||||
containsString("Channel Closed"));
|
||||
}
|
||||
|
||||
clientSessionTracker.assertClosedProperly(client);
|
||||
|
@ -285,12 +282,11 @@ public class ClientCloseTest
|
|||
// client close should occur
|
||||
clientSocket.assertReceivedCloseEvent(clientTimeout * 2,
|
||||
is(StatusCode.SHUTDOWN),
|
||||
containsString("timeout"));
|
||||
containsString("Timeout"));
|
||||
|
||||
// client idle timeout triggers close event on client ws-endpoint
|
||||
assertThat("OnError Latch", clientSocket.errorLatch.await(2, SECONDS), is(true));
|
||||
assertThat("OnError", clientSocket.error.get(), instanceOf(CloseException.class));
|
||||
assertThat("OnError.cause", clientSocket.error.get().getCause(), instanceOf(TimeoutException.class));
|
||||
assertThat("OnError", clientSocket.error.get(), instanceOf(WebSocketTimeoutException.class));
|
||||
}
|
||||
|
||||
clientSessionTracker.assertClosedProperly(client);
|
||||
|
@ -330,7 +326,7 @@ public class ClientCloseTest
|
|||
// clients disconnect
|
||||
for (int i = 0; i < sessionCount; i++)
|
||||
{
|
||||
clientSockets.get(i).assertReceivedCloseEvent(timeout, is(StatusCode.ABNORMAL), containsString("Disconnected"));
|
||||
clientSockets.get(i).assertReceivedCloseEvent(timeout, is(StatusCode.ABNORMAL), containsString("Channel Closed"));
|
||||
}
|
||||
|
||||
// ensure all Sessions are gone. connections are gone. etc. (client and server)
|
||||
|
@ -370,7 +366,7 @@ public class ClientCloseTest
|
|||
|
||||
// client triggers close event on client ws-endpoint
|
||||
// assert - close code==1006 (abnormal)
|
||||
clientSocket.assertReceivedCloseEvent(timeout, is(StatusCode.ABNORMAL), containsString("Eof"));
|
||||
clientSocket.assertReceivedCloseEvent(timeout, is(StatusCode.ABNORMAL), containsString("Channel Closed"));
|
||||
|
||||
clientSessionTracker.assertClosedProperly(client);
|
||||
}
|
||||
|
|
|
@ -46,7 +46,6 @@ import org.eclipse.jetty.websocket.tests.CloseTrackingEndpoint;
|
|||
import org.eclipse.jetty.websocket.tests.EchoCreator;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
@ -55,7 +54,6 @@ import static org.hamcrest.Matchers.is;
|
|||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@Disabled("Needs triage")
|
||||
public class ClientSessionsTest
|
||||
{
|
||||
private Server server;
|
||||
|
@ -147,6 +145,8 @@ public class ClientSessionsTest
|
|||
|
||||
String received = cliSock.messageQueue.poll(5, TimeUnit.SECONDS);
|
||||
assertThat("Message", received, containsString("Hello World!"));
|
||||
|
||||
sess.close(StatusCode.NORMAL, null);
|
||||
}
|
||||
|
||||
cliSock.assertReceivedCloseEvent(30000, is(StatusCode.NORMAL));
|
||||
|
|
|
@ -36,13 +36,13 @@ 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.common.WebSocketSessionImpl;
|
||||
import org.eclipse.jetty.websocket.core.internal.WebSocketChannel;
|
||||
import org.eclipse.jetty.websocket.server.JettyWebSocketServletContainerInitializer;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
|
||||
import org.eclipse.jetty.websocket.tests.CloseTrackingEndpoint;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
@ -55,7 +55,6 @@ import static org.hamcrest.Matchers.is;
|
|||
/**
|
||||
* Tests various close scenarios
|
||||
*/
|
||||
@Disabled("Needs triage")
|
||||
public class ServerCloseTest
|
||||
{
|
||||
private WebSocketClient client;
|
||||
|
@ -150,7 +149,7 @@ public class ServerCloseTest
|
|||
// Verify that server socket got close event
|
||||
AbstractCloseEndpoint serverEndpoint = serverEndpointCreator.pollLastCreated();
|
||||
assertThat("Fast Close Latch", serverEndpoint.closeLatch.await(5, SECONDS), is(true));
|
||||
assertThat("Fast Close.statusCode", serverEndpoint.closeStatusCode, is(StatusCode.ABNORMAL));
|
||||
assertThat("Fast Close.statusCode", serverEndpoint.closeStatusCode, is(StatusCode.NORMAL));
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -174,7 +173,7 @@ public class ServerCloseTest
|
|||
Future<Session> futSession = client.connect(clientEndpoint, wsUri, request);
|
||||
|
||||
Session session = null;
|
||||
try(StacklessLogging ignore = new StacklessLogging(FastFailEndpoint.class, WebSocketSessionImpl.class))
|
||||
try(StacklessLogging ignore = new StacklessLogging(WebSocketChannel.class))
|
||||
{
|
||||
session = futSession.get(5, SECONDS);
|
||||
|
||||
|
@ -221,12 +220,13 @@ public class ServerCloseTest
|
|||
clientEndpoint.getEndPoint().close();
|
||||
|
||||
// Verify that client got close
|
||||
clientEndpoint.assertReceivedCloseEvent(5000, is(StatusCode.ABNORMAL), containsString("Disconnected"));
|
||||
clientEndpoint.assertReceivedCloseEvent(5000, is(StatusCode.ABNORMAL), containsString("Channel Closed"));
|
||||
|
||||
// Verify that server socket got close event
|
||||
AbstractCloseEndpoint serverEndpoint = serverEndpointCreator.pollLastCreated();
|
||||
serverEndpoint.assertReceivedCloseEvent(5000, is(StatusCode.ABNORMAL), containsString("Disconnected"));
|
||||
} finally
|
||||
serverEndpoint.assertReceivedCloseEvent(5000, is(StatusCode.ABNORMAL), containsString("Channel Closed"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
close(session);
|
||||
}
|
||||
|
|
|
@ -134,7 +134,7 @@ public class WebSocketChannelState
|
|||
|
||||
default:
|
||||
if (_closeStatus == null || CloseStatus.isOrdinary(_closeStatus))
|
||||
_closeStatus = CloseStatus.NO_CLOSE_STATUS;
|
||||
_closeStatus = new CloseStatus(CloseStatus.NO_CLOSE, "Channel Closed");
|
||||
_channelState = State.CLOSED;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<!-- =============================================================== -->
|
||||
<!-- Configure the test-jndi webapp -->
|
||||
<!-- Configure the test-jaas webapp -->
|
||||
<!-- =============================================================== -->
|
||||
<Configure id='wac' class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
|
||||
|
|
Loading…
Reference in New Issue