Merge remote-tracking branch 'origin/master' into session-refactor

This commit is contained in:
Jan Bartel 2015-09-09 16:13:10 +10:00
commit bf2a1fa29e
134 changed files with 859 additions and 293 deletions

View File

@ -1,4 +1,35 @@
jetty-9.3.3-SNAPSHOT
jetty-9.3.4-SNAPSHOT
jetty-9.3.3.v20150827 - 27 August 2015
+ 470311 Introduce a proxy-protocol module.
+ 471055 Restore legacy/experimental WebSocket extensions (deflate-frame)
+ 472411 PathResource.checkAliasPath() typo
+ 473321 Overriding SSL context KeyStoreType requires explicit override of
TrustStoreType
+ 474025 SslContextFactory does not work with JCEKS Keystore
+ 474068 Update WebSocket Extension for permessage-deflate draft-22
+ 474319 Reintroduce blocking connect().
+ 474321 Allow synchronous address resolution.
+ 474344 apache-jstl includes test dependencies
+ 474358 DefaultServlet bad Content-Type on compressed content
+ 474361 Handle JVM version extensions like -internal
+ 474453 Tiny buffers (under 7 bytes) fail to compress in permessage-deflate
+ 474454 Backport permessage-deflate from Jetty 9.3.x to 9.2.x
+ 474455 Enable permessage-deflate WebSocket extension
+ 474558 Debug log ServletContainerInitializer @HandlesTypes contents
+ 474617 AsyncListener.onError not called for errors
+ 474618 AsyncListener.onComplete not called when error occurs
+ 474634 AsyncListener.onError() handling.
+ 474685 GzipHandler configuration supports csv paths and mimetypes.
+ 474888 HttpClient JMX support.
+ 474936 WebSocketSessions are not always cleaned out from openSessions
+ 474961 Close input stream for classes in AnnotationParser after scanning
+ 475195 SNI matching fails when keystore does not contain wild certificates.
+ 475483 Starting Jetty with [exec] should use properties file.
+ 475546 ClosedChannelException when connecting to HTTPS over HTTP proxy with
CONNECT.
+ 475605 Add support for multi-homed destinations.
+ 475927 SecureRequestCustomizer fails to match host.
jetty-9.3.2.v20150730 - 30 July 2015
+ 470351 Fixed SNI matching of wildcard certificates

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>apache-jsp</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>apache-jstl</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>example-async-rest</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.example-async-rest</groupId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>example-async-rest</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.example-async-rest</groupId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.examples</groupId>
<artifactId>examples-parent</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.examples</groupId>
<artifactId>examples-parent</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -21,7 +21,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>org.eclipse.jetty.examples</groupId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-parent</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-alpn-client</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-parent</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-alpn-server</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-alpn-parent</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-annotations</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-ant</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.cdi</groupId>
<artifactId>jetty-cdi-parent</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cdi-core</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.cdi</groupId>
<artifactId>jetty-cdi-parent</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cdi-full-servlet</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.cdi</groupId>
<artifactId>jetty-cdi-parent</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cdi-servlet</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.cdi</groupId>
<artifactId>jetty-cdi-parent</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cdi-websocket</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.cdi</groupId>

View File

@ -20,7 +20,7 @@
<parent>
<groupId>org.eclipse.jetty.cdi</groupId>
<artifactId>jetty-cdi-parent</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>test-cdi-webapp</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -21,9 +21,9 @@ package org.eclipse.jetty.client;
import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.BlockingQueue;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
@ -44,15 +44,15 @@ import org.eclipse.jetty.util.thread.Sweeper;
@ManagedObject("The connection pool")
public class ConnectionPool implements Closeable, Dumpable, Sweeper.Sweepable
{
protected static final Logger LOG = Log.getLogger(ConnectionPool.class);
private static final Logger LOG = Log.getLogger(ConnectionPool.class);
private final AtomicInteger connectionCount = new AtomicInteger();
private final ReentrantLock lock = new ReentrantLock();
private final Destination destination;
private final int maxConnections;
private final Callback requester;
private final BlockingDeque<Connection> idleConnections;
private final BlockingQueue<Connection> activeConnections;
private final Deque<Connection> idleConnections;
private final Queue<Connection> activeConnections;
public ConnectionPool(Destination destination, int maxConnections, Callback requester)
{
@ -81,12 +81,12 @@ public class ConnectionPool implements Closeable, Dumpable, Sweeper.Sweepable
return activeConnections.size();
}
public BlockingQueue<Connection> getIdleConnections()
public Queue<Connection> getIdleConnections()
{
return idleConnections;
}
public BlockingQueue<Connection> getActiveConnections()
public Queue<Connection> getActiveConnections()
{
return activeConnections;
}
@ -129,7 +129,7 @@ public class ConnectionPool implements Closeable, Dumpable, Sweeper.Sweepable
idleCreated(connection);
requester.succeeded();
proceed();
}
@Override
@ -150,11 +150,15 @@ public class ConnectionPool implements Closeable, Dumpable, Sweeper.Sweepable
}
}
protected void proceed()
{
requester.succeeded();
}
protected void idleCreated(Connection connection)
{
boolean idle;
final ReentrantLock lock = this.lock;
lock.lock();
lock();
try
{
// Use "cold" new connections as last.
@ -162,7 +166,7 @@ public class ConnectionPool implements Closeable, Dumpable, Sweeper.Sweepable
}
finally
{
lock.unlock();
unlock();
}
idle(connection, idle);
@ -172,8 +176,7 @@ public class ConnectionPool implements Closeable, Dumpable, Sweeper.Sweepable
{
boolean acquired;
Connection connection;
final ReentrantLock lock = this.lock;
lock.lock();
lock();
try
{
connection = idleConnections.pollFirst();
@ -183,7 +186,7 @@ public class ConnectionPool implements Closeable, Dumpable, Sweeper.Sweepable
}
finally
{
lock.unlock();
unlock();
}
if (acquired)
@ -209,24 +212,28 @@ public class ConnectionPool implements Closeable, Dumpable, Sweeper.Sweepable
public boolean release(Connection connection)
{
boolean idle;
final ReentrantLock lock = this.lock;
lock.lock();
lock();
try
{
if (!activeConnections.remove(connection))
return false;
// Make sure we use "hot" connections first.
idle = idleConnections.offerFirst(connection);
idle = offerIdle(connection);
}
finally
{
lock.unlock();
unlock();
}
released(connection);
return idle(connection, idle);
}
protected boolean offerIdle(Connection connection)
{
return idleConnections.offerFirst(connection);
}
protected boolean idle(Connection connection, boolean idle)
{
if (idle)
@ -249,11 +256,15 @@ public class ConnectionPool implements Closeable, Dumpable, Sweeper.Sweepable
}
public boolean remove(Connection connection)
{
return remove(connection, false);
}
protected boolean remove(Connection connection, boolean force)
{
boolean activeRemoved;
boolean idleRemoved;
final ReentrantLock lock = this.lock;
lock.lock();
lock();
try
{
activeRemoved = activeConnections.remove(connection);
@ -261,12 +272,12 @@ public class ConnectionPool implements Closeable, Dumpable, Sweeper.Sweepable
}
finally
{
lock.unlock();
unlock();
}
if (activeRemoved)
released(connection);
boolean removed = activeRemoved || idleRemoved;
boolean removed = activeRemoved || idleRemoved || force;
if (removed)
{
int pooled = connectionCount.decrementAndGet();
@ -278,29 +289,27 @@ public class ConnectionPool implements Closeable, Dumpable, Sweeper.Sweepable
public boolean isActive(Connection connection)
{
final ReentrantLock lock = this.lock;
lock.lock();
lock();
try
{
return activeConnections.contains(connection);
}
finally
{
lock.unlock();
unlock();
}
}
public boolean isIdle(Connection connection)
{
final ReentrantLock lock = this.lock;
lock.lock();
lock();
try
{
return idleConnections.contains(connection);
}
finally
{
lock.unlock();
unlock();
}
}
@ -313,8 +322,7 @@ public class ConnectionPool implements Closeable, Dumpable, Sweeper.Sweepable
{
List<Connection> idles = new ArrayList<>();
List<Connection> actives = new ArrayList<>();
final ReentrantLock lock = this.lock;
lock.lock();
lock();
try
{
idles.addAll(idleConnections);
@ -324,7 +332,7 @@ public class ConnectionPool implements Closeable, Dumpable, Sweeper.Sweepable
}
finally
{
lock.unlock();
unlock();
}
connectionCount.set(0);
@ -348,8 +356,7 @@ public class ConnectionPool implements Closeable, Dumpable, Sweeper.Sweepable
{
List<Connection> actives = new ArrayList<>();
List<Connection> idles = new ArrayList<>();
final ReentrantLock lock = this.lock;
lock.lock();
lock();
try
{
actives.addAll(activeConnections);
@ -357,7 +364,7 @@ public class ConnectionPool implements Closeable, Dumpable, Sweeper.Sweepable
}
finally
{
lock.unlock();
unlock();
}
ContainerLifeCycle.dumpObject(out, this);
@ -368,8 +375,7 @@ public class ConnectionPool implements Closeable, Dumpable, Sweeper.Sweepable
public boolean sweep()
{
List<Sweeper.Sweepable> toSweep = new ArrayList<>();
final ReentrantLock lock = this.lock;
lock.lock();
lock();
try
{
for (Connection connection : getActiveConnections())
@ -380,7 +386,7 @@ public class ConnectionPool implements Closeable, Dumpable, Sweeper.Sweepable
}
finally
{
lock.unlock();
unlock();
}
for (Sweeper.Sweepable candidate : toSweep)
@ -400,13 +406,22 @@ public class ConnectionPool implements Closeable, Dumpable, Sweeper.Sweepable
return false;
}
protected void lock()
{
lock.lock();
}
protected void unlock()
{
lock.unlock();
}
@Override
public String toString()
{
int activeSize;
int idleSize;
final ReentrantLock lock = this.lock;
lock.lock();
lock();
try
{
activeSize = activeConnections.size();
@ -414,7 +429,7 @@ public class ConnectionPool implements Closeable, Dumpable, Sweeper.Sweepable
}
finally
{
lock.unlock();
unlock();
}
return String.format("%s[c=%d/%d,a=%d,i=%d]",

View File

@ -22,9 +22,13 @@ import org.eclipse.jetty.client.api.Connection;
import org.eclipse.jetty.client.api.Destination;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.LeakDetector;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class LeakTrackingConnectionPool extends ConnectionPool
{
private static final Logger LOG = Log.getLogger(LeakTrackingConnectionPool.class);
private final LeakDetector<Connection> leakDetector = new LeakDetector<Connection>()
{
@Override

View File

@ -71,9 +71,7 @@ public abstract class PoolingHttpDestination<C extends Connection> extends HttpD
{
if (getHttpExchanges().isEmpty())
return;
C connection = acquire();
if (connection != null)
process(connection);
process();
}
@SuppressWarnings("unchecked")
@ -82,6 +80,13 @@ public abstract class PoolingHttpDestination<C extends Connection> extends HttpD
return (C)connectionPool.acquire();
}
private void process()
{
C connection = acquire();
if (connection != null)
process(connection);
}
/**
* <p>Processes a new connection making it idle or active depending on whether requests are waiting to be sent.</p>
* <p>A new connection is created when a request needs to be executed; it is possible that the request that
@ -137,18 +142,21 @@ public abstract class PoolingHttpDestination<C extends Connection> extends HttpD
@SuppressWarnings("unchecked")
C connection = (C)c;
if (LOG.isDebugEnabled())
LOG.debug("{} released", connection);
LOG.debug("Released {}", connection);
HttpClient client = getHttpClient();
if (client.isRunning())
{
if (connectionPool.isActive(connection))
{
process(connection);
if (connectionPool.release(connection))
send();
else
connection.close();
}
else
{
if (LOG.isDebugEnabled())
LOG.debug("{} explicit", connection);
LOG.debug("Released explicit {}", connection);
}
}
else
@ -184,9 +192,7 @@ public abstract class PoolingHttpDestination<C extends Connection> extends HttpD
// We need to execute queued requests even if this connection failed.
// We may create a connection that is not needed, but it will eventually
// idle timeout, so no worries.
C newConnection = acquire();
if (newConnection != null)
process(newConnection);
process();
}
}

View File

@ -0,0 +1,209 @@
//
// ========================================================================
// Copyright (c) 1995-2015 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.client;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jetty.client.api.Connection;
import org.eclipse.jetty.client.api.Destination;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.Scheduler;
/**
* <p>A {@link ConnectionPool} that validates connections before
* making them available for use.</p>
* <p>Connections that have just been opened are not validated.
* Connections that are {@link #release(Connection) released} will
* be validated.</p>
* <p>Validation by reading from the EndPoint is not reliable,
* since the TCP FIN may arrive just after the validation read.</p>
* <p>This class validates connections by putting them in a
* "quarantine" for a configurable timeout, where they cannot
* be used to send requests. When the timeout expires, the
* quarantined connection is made idle and therefore available
* to send requests.</p>
* <p>The existing HttpClient mechanism to detect server closes
* will trigger and close quarantined connections, before they
* are made idle (and reusable) again.</p>
* <p>There still is a small chance that the timeout expires,
* the connection is made idle and available again, it is used
* to send a request exactly when the server decides to close.
* This case is however unavoidable and may be mitigated by
* tuning the idle timeout of the servers to be larger than
* that of the client.</p>
*/
public class ValidatingConnectionPool extends ConnectionPool
{
private static final Logger LOG = Log.getLogger(ValidatingConnectionPool.class);
private final Scheduler scheduler;
private final long timeout;
private final Map<Connection, Holder> quarantine;
public ValidatingConnectionPool(Destination destination, int maxConnections, Callback requester, Scheduler scheduler, long timeout)
{
super(destination, maxConnections, requester);
this.scheduler = scheduler;
this.timeout = timeout;
this.quarantine = new HashMap<>(maxConnections);
}
@ManagedAttribute(value = "The number of validating connections", readonly = true)
public int getValidatingConnectionCount()
{
return quarantine.size();
}
@Override
public boolean release(Connection connection)
{
lock();
try
{
if (!getActiveConnections().remove(connection))
return false;
Holder holder = new Holder(connection);
holder.task = scheduler.schedule(holder, timeout, TimeUnit.MILLISECONDS);
quarantine.put(connection, holder);
if (LOG.isDebugEnabled())
LOG.debug("Validating for {}ms {}", timeout, connection);
}
finally
{
unlock();
}
released(connection);
return true;
}
@Override
public boolean remove(Connection connection)
{
Holder holder;
lock();
try
{
holder = quarantine.remove(connection);
}
finally
{
unlock();
}
if (holder == null)
return super.remove(connection);
if (LOG.isDebugEnabled())
LOG.debug("Removed while validating {}", connection);
boolean cancelled = holder.cancel();
if (cancelled)
return remove(connection, true);
return super.remove(connection);
}
@Override
public void dump(Appendable out, String indent) throws IOException
{
super.dump(out, indent);
ContainerLifeCycle.dump(out, indent, quarantine.values());
}
@Override
public String toString()
{
int size;
lock();
try
{
size = quarantine.size();
}
finally
{
unlock();
}
return String.format("%s[v=%d]", super.toString(), size);
}
private class Holder implements Runnable
{
private final long timestamp = System.nanoTime();
private final AtomicBoolean latch = new AtomicBoolean();
private final Connection connection;
public Scheduler.Task task;
public Holder(Connection connection)
{
this.connection = connection;
}
@Override
public void run()
{
if (latch.compareAndSet(false, true))
{
boolean idle;
lock();
try
{
quarantine.remove(connection);
idle = offerIdle(connection);
if (LOG.isDebugEnabled())
LOG.debug("Validated {}", connection);
}
finally
{
unlock();
}
if (idle(connection, idle))
proceed();
}
}
public boolean cancel()
{
if (latch.compareAndSet(false, true))
{
task.cancel();
return true;
}
return false;
}
@Override
public String toString()
{
return String.format("%s[validationLeft=%dms]",
connection,
timeout - TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - timestamp)
);
}
}
}

View File

@ -98,7 +98,7 @@ public class HttpConnectionOverHTTP extends AbstractConnection implements Connec
protected boolean onReadTimeout()
{
if (LOG.isDebugEnabled())
LOG.debug("{} idle timeout", this);
LOG.debug("Idle timeout {}", this);
close(new TimeoutException());
return false;
}
@ -141,10 +141,10 @@ public class HttpConnectionOverHTTP extends AbstractConnection implements Connec
getHttpDestination().close(this);
getEndPoint().shutdownOutput();
if (LOG.isDebugEnabled())
LOG.debug("{} oshut", this);
LOG.debug("Shutdown {}", this);
getEndPoint().close();
if (LOG.isDebugEnabled())
LOG.debug("{} closed", this);
LOG.debug("Closed {}", this);
abort(failure);
}
@ -166,10 +166,8 @@ public class HttpConnectionOverHTTP extends AbstractConnection implements Connec
{
if (!closed.get())
return false;
if (sweeps.incrementAndGet() < 4)
return false;
return true;
}

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.client;
import java.util.Arrays;
import java.util.Collection;
import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.NetworkConnector;
@ -84,10 +85,15 @@ public abstract class AbstractHttpClientServerTest
}
protected void startClient() throws Exception
{
startClient(new HttpClientTransportOverHTTP(1));
}
protected void startClient(HttpClientTransport transport) throws Exception
{
QueuedThreadPool clientThreads = new QueuedThreadPool();
clientThreads.setName("client");
client = new HttpClient(sslContextFactory);
client = new HttpClient(transport, sslContextFactory);
client.setExecutor(clientThreads);
client.start();
}

View File

@ -881,9 +881,16 @@ public class HttpClientTest extends AbstractHttpClientServerTest
@Test
public void testConnectHostWithMultipleAddresses() throws Exception
{
// Likely that the DNS for google.com returns multiple addresses.
String host = "google.com";
Assume.assumeTrue(InetAddress.getAllByName(host).length > 1);
try
{
// Likely that the DNS for google.com returns multiple addresses.
Assume.assumeTrue(InetAddress.getAllByName(host).length > 1);
}
catch (Throwable x)
{
Assume.assumeNoException(x);
}
startClient();
client.setFollowRedirects(false); // Avoid redirects from 80 to 443.

View File

@ -21,7 +21,7 @@ package org.eclipse.jetty.client;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.concurrent.BlockingQueue;
import java.util.Queue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@ -71,10 +71,10 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
HttpDestinationOverHTTP destination = (HttpDestinationOverHTTP)client.getDestination(scheme, host, port);
ConnectionPool connectionPool = destination.getConnectionPool();
final BlockingQueue<Connection> idleConnections = connectionPool.getIdleConnections();
final Queue<Connection> idleConnections = connectionPool.getIdleConnections();
Assert.assertEquals(0, idleConnections.size());
final BlockingQueue<Connection> activeConnections = connectionPool.getActiveConnections();
final Queue<Connection> activeConnections = connectionPool.getActiveConnections();
Assert.assertEquals(0, activeConnections.size());
final CountDownLatch headersLatch = new CountDownLatch(1);
@ -132,10 +132,10 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
HttpDestinationOverHTTP destination = (HttpDestinationOverHTTP)client.getDestination(scheme, host, port);
ConnectionPool connectionPool = destination.getConnectionPool();
final BlockingQueue<Connection> idleConnections = connectionPool.getIdleConnections();
final Queue<Connection> idleConnections = connectionPool.getIdleConnections();
Assert.assertEquals(0, idleConnections.size());
final BlockingQueue<Connection> activeConnections = connectionPool.getActiveConnections();
final Queue<Connection> activeConnections = connectionPool.getActiveConnections();
Assert.assertEquals(0, activeConnections.size());
final CountDownLatch beginLatch = new CountDownLatch(1);
@ -183,10 +183,10 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
HttpDestinationOverHTTP destination = (HttpDestinationOverHTTP)client.getDestination(scheme, host, port);
ConnectionPool connectionPool = destination.getConnectionPool();
final BlockingQueue<Connection> idleConnections = connectionPool.getIdleConnections();
final Queue<Connection> idleConnections = connectionPool.getIdleConnections();
Assert.assertEquals(0, idleConnections.size());
final BlockingQueue<Connection> activeConnections = connectionPool.getActiveConnections();
final Queue<Connection> activeConnections = connectionPool.getActiveConnections();
Assert.assertEquals(0, activeConnections.size());
final CountDownLatch successLatch = new CountDownLatch(3);
@ -243,10 +243,10 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
HttpDestinationOverHTTP destination = (HttpDestinationOverHTTP)client.getDestination(scheme, host, port);
ConnectionPool connectionPool = destination.getConnectionPool();
final BlockingQueue<Connection> idleConnections = connectionPool.getIdleConnections();
final Queue<Connection> idleConnections = connectionPool.getIdleConnections();
Assert.assertEquals(0, idleConnections.size());
final BlockingQueue<Connection> activeConnections = connectionPool.getActiveConnections();
final Queue<Connection> activeConnections = connectionPool.getActiveConnections();
Assert.assertEquals(0, activeConnections.size());
final long delay = 1000;
@ -316,10 +316,10 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
HttpDestinationOverHTTP destination = (HttpDestinationOverHTTP)client.getDestination(scheme, host, port);
ConnectionPool connectionPool = destination.getConnectionPool();
final BlockingQueue<Connection> idleConnections = connectionPool.getIdleConnections();
final Queue<Connection> idleConnections = connectionPool.getIdleConnections();
Assert.assertEquals(0, idleConnections.size());
final BlockingQueue<Connection> activeConnections = connectionPool.getActiveConnections();
final Queue<Connection> activeConnections = connectionPool.getActiveConnections();
Assert.assertEquals(0, activeConnections.size());
server.stop();
@ -369,10 +369,10 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
HttpDestinationOverHTTP destination = (HttpDestinationOverHTTP)client.getDestination(scheme, host, port);
ConnectionPool connectionPool = destination.getConnectionPool();
final BlockingQueue<Connection> idleConnections = connectionPool.getIdleConnections();
final Queue<Connection> idleConnections = connectionPool.getIdleConnections();
Assert.assertEquals(0, idleConnections.size());
final BlockingQueue<Connection> activeConnections = connectionPool.getActiveConnections();
final Queue<Connection> activeConnections = connectionPool.getActiveConnections();
Assert.assertEquals(0, activeConnections.size());
final CountDownLatch latch = new CountDownLatch(1);
@ -419,10 +419,10 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
HttpDestinationOverHTTP destination = (HttpDestinationOverHTTP)client.getDestination(scheme, host, port);
ConnectionPool connectionPool = destination.getConnectionPool();
final BlockingQueue<Connection> idleConnections = connectionPool.getIdleConnections();
final Queue<Connection> idleConnections = connectionPool.getIdleConnections();
Assert.assertEquals(0, idleConnections.size());
final BlockingQueue<Connection> activeConnections = connectionPool.getActiveConnections();
final Queue<Connection> activeConnections = connectionPool.getActiveConnections();
Assert.assertEquals(0, activeConnections.size());
Log.getLogger(HttpConnection.class).info("Expecting java.lang.IllegalStateException: HttpParser{s=CLOSED,...");
@ -449,7 +449,7 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
Assert.assertEquals(0, idleConnections.size());
Assert.assertEquals(0, activeConnections.size());
server.stop();
}
finally
@ -469,10 +469,10 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
HttpDestinationOverHTTP destination = (HttpDestinationOverHTTP)client.getDestination(scheme, host, port);
ConnectionPool connectionPool = destination.getConnectionPool();
final BlockingQueue<Connection> idleConnections = connectionPool.getIdleConnections();
final Queue<Connection> idleConnections = connectionPool.getIdleConnections();
Assert.assertEquals(0, idleConnections.size());
final BlockingQueue<Connection> activeConnections = connectionPool.getActiveConnections();
final Queue<Connection> activeConnections = connectionPool.getActiveConnections();
Assert.assertEquals(0, activeConnections.size());
ContentResponse response = client.newRequest(host, port)
@ -501,10 +501,10 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
HttpDestinationOverHTTP destination = (HttpDestinationOverHTTP)client.getDestination(scheme, host, port);
ConnectionPool connectionPool = destination.getConnectionPool();
final BlockingQueue<Connection> idleConnections = connectionPool.getIdleConnections();
final Queue<Connection> idleConnections = connectionPool.getIdleConnections();
Assert.assertEquals(0, idleConnections.size());
final BlockingQueue<Connection> activeConnections = connectionPool.getActiveConnections();
final Queue<Connection> activeConnections = connectionPool.getActiveConnections();
Assert.assertEquals(0, activeConnections.size());
client.setStrictEventOrdering(false);

View File

@ -0,0 +1,204 @@
//
// ========================================================================
// Copyright (c) 1995-2015 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.client;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP;
import org.eclipse.jetty.client.http.HttpDestinationOverHTTP;
import org.eclipse.jetty.client.util.FutureResponseListener;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpHeaderValue;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.Assert;
import org.junit.Test;
public class ValidatingConnectionPoolTest extends AbstractHttpClientServerTest
{
public ValidatingConnectionPoolTest(SslContextFactory sslContextFactory)
{
super(sslContextFactory);
}
@Override
protected void startClient() throws Exception
{
startClient(new ValidatingHttpClientTransportOverHTTP(1000));
}
@Test
public void testRequestAfterValidation() throws Exception
{
start(new EmptyServerHandler());
client.setMaxConnectionsPerDestination(1);
ContentResponse response = client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme)
.send();
Assert.assertEquals(200, response.getStatus());
// The second request should be sent after the validating timeout.
response = client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme)
.send();
Assert.assertEquals(200, response.getStatus());
}
@Test
public void testServerClosesConnectionAfterRedirectWithoutConnectionCloseHeader() throws Exception
{
start(new AbstractHandler()
{
@Override
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
if (target.endsWith("/redirect"))
{
response.setStatus(HttpStatus.TEMPORARY_REDIRECT_307);
response.setContentLength(0);
response.setHeader(HttpHeader.LOCATION.asString(), scheme + "://localhost:" + connector.getLocalPort() + "/");
response.flushBuffer();
baseRequest.getHttpChannel().getEndPoint().shutdownOutput();
}
else
{
response.setStatus(HttpStatus.OK_200);
response.setContentLength(0);
response.setHeader(HttpHeader.CONNECTION.asString(), HttpHeaderValue.CLOSE.asString());
}
}
});
ContentResponse response = client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme)
.path("/redirect")
.send();
Assert.assertEquals(200, response.getStatus());
}
@Test
public void testServerClosesConnectionAfterResponseWithQueuedRequestWithMaxConnectionsWithConnectionCloseHeader() throws Exception
{
testServerClosesConnectionAfterResponseWithQueuedRequestWithMaxConnections(new AbstractHandler()
{
@Override
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
response.setStatus(HttpStatus.OK_200);
response.setContentLength(0);
response.setHeader(HttpHeader.CONNECTION.asString(), HttpHeaderValue.CLOSE.asString());
}
});
}
@Test
public void testServerClosesConnectionAfterResponseWithQueuedRequestWithMaxConnectionsWithoutConnectionCloseHeader() throws Exception
{
testServerClosesConnectionAfterResponseWithQueuedRequestWithMaxConnections(new AbstractHandler()
{
@Override
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
response.setStatus(HttpStatus.OK_200);
response.setContentLength(0);
response.flushBuffer();
baseRequest.getHttpChannel().getEndPoint().shutdownOutput();
}
});
}
private void testServerClosesConnectionAfterResponseWithQueuedRequestWithMaxConnections(Handler handler) throws Exception
{
start(handler);
client.setMaxConnectionsPerDestination(1);
final CountDownLatch latch = new CountDownLatch(1);
Request request1 = client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme)
.path("/one")
.onRequestBegin(r ->
{
try
{
latch.await();
}
catch (InterruptedException x)
{
r.abort(x);
}
});
FutureResponseListener listener1 = new FutureResponseListener(request1);
request1.send(listener1);
Request request2 = client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme)
.path("/two");
FutureResponseListener listener2 = new FutureResponseListener(request2);
request2.send(listener2);
// Now we have one request about to be sent, and one queued.
latch.countDown();
ContentResponse response1 = listener1.get(5, TimeUnit.SECONDS);
Assert.assertEquals(200, response1.getStatus());
ContentResponse response2 = listener2.get(5, TimeUnit.SECONDS);
Assert.assertEquals(200, response2.getStatus());
}
private static class ValidatingHttpClientTransportOverHTTP extends HttpClientTransportOverHTTP
{
private final long timeout;
public ValidatingHttpClientTransportOverHTTP(long timeout)
{
super(1);
this.timeout = timeout;
}
@Override
public HttpDestination newHttpDestination(Origin origin)
{
return new HttpDestinationOverHTTP(getHttpClient(), origin)
{
@Override
protected ConnectionPool newConnectionPool(HttpClient client)
{
return new ValidatingConnectionPool(this, client.getMaxConnectionsPerDestination(), this, client.getScheduler(), timeout);
}
};
}
}
}

View File

@ -18,6 +18,7 @@
package org.eclipse.jetty.client.http;
import java.util.Queue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
@ -62,7 +63,7 @@ public class HttpDestinationOverHTTPTest extends AbstractHttpClientServerTest
if (connection == null)
{
// There are no queued requests, so the newly created connection will be idle
connection = destination.getConnectionPool().getIdleConnections().poll(5, TimeUnit.SECONDS);
connection = timedPoll(destination.getConnectionPool().getIdleConnections(), 5, TimeUnit.SECONDS);
}
Assert.assertNotNull(connection);
}
@ -133,9 +134,10 @@ public class HttpDestinationOverHTTPTest extends AbstractHttpClientServerTest
latch.countDown();
// There must be 2 idle connections.
Connection connection = destination.getConnectionPool().getIdleConnections().poll(5, TimeUnit.SECONDS);
Queue<Connection> idleConnections = destination.getConnectionPool().getIdleConnections();
Connection connection = timedPoll(idleConnections, 5, TimeUnit.SECONDS);
Assert.assertNotNull(connection);
connection = destination.getConnectionPool().getIdleConnections().poll(5, TimeUnit.SECONDS);
connection = timedPoll(idleConnections, 5, TimeUnit.SECONDS);
Assert.assertNotNull(connection);
}
@ -272,4 +274,17 @@ public class HttpDestinationOverHTTPTest extends AbstractHttpClientServerTest
destinationAfter = client.getDestination(scheme, host, port);
Assert.assertNotSame(destinationBefore, destinationAfter);
}
private Connection timedPoll(Queue<Connection> connections, long time, TimeUnit unit) throws InterruptedException
{
long start = System.nanoTime();
while (unit.toNanos(time) > System.nanoTime() - start)
{
Connection connection = connections.poll();
if (connection != null)
return connection;
TimeUnit.MILLISECONDS.sleep(5);
}
return connections.poll();
}
}

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-continuation</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-deploy</artifactId>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<artifactId>jetty-distribution</artifactId>
<name>Jetty :: Distribution Assemblies</name>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.fcgi</groupId>
<artifactId>fcgi-parent</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.fcgi</groupId>
<artifactId>fcgi-parent</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-http-spi</artifactId>

View File

@ -3,7 +3,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-http</artifactId>

View File

@ -86,6 +86,19 @@ public class HttpParserTest
assertEquals(HttpMethod.GET,HttpMethod.lookAheadGet(b));
}
@Test
public void testLineParse_Mock_IP() throws Exception
{
ByteBuffer buffer= BufferUtil.toBuffer("POST /mock/127.0.0.1 HTTP/1.1\015\012" + "\015\012");
HttpParser.RequestHandler handler = new Handler();
HttpParser parser= new HttpParser(handler);
parseAll(parser,buffer);
assertEquals("POST", _methodOrVersion);
assertEquals("/mock/127.0.0.1", _uriOrStatus);
assertEquals("HTTP/1.1", _versionOrReason);
assertEquals(-1, _headers);
}
@Test
public void testLineParse0() throws Exception

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-parent</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-parent</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-parent</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-parent</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-parent</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-parent</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -3,7 +3,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-infinispan</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-io</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jaas</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jaspi</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jmx</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jndi</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jspc-maven-plugin</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-maven-plugin</artifactId>

View File

@ -19,7 +19,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-monitor</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-nosql</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-osgi-alpn</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-osgi-boot-jsp</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-osgi-boot</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-httpservice</artifactId>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>test-jetty-osgi-context</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-plus</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-proxy</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty</groupId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-rewrite</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-runner</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-security</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-server</artifactId>

View File

@ -19,7 +19,6 @@
package org.eclipse.jetty.server;
import java.security.cert.X509Certificate;
import java.util.List;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
@ -79,23 +78,26 @@ public class SecureRequestCustomizer implements HttpConfiguration.Customizer
}
/**
* <p>Customizes the request attributes to be set for SSL requests.</p>
* <p>The requirements of the Servlet specs are:</p>
* <p>
* Customizes the request attributes to be set for SSL requests.
* </p>
* <p>
* The requirements of the Servlet specs are:
* </p>
* <ul>
* <li> an attribute named "javax.servlet.request.ssl_session_id" of type
* String (since Servlet Spec 3.0).</li>
* <li> an attribute named "javax.servlet.request.cipher_suite" of type
* String.</li>
* <li> an attribute named "javax.servlet.request.key_size" of type Integer.</li>
* <li> an attribute named "javax.servlet.request.X509Certificate" of type
* java.security.cert.X509Certificate[]. This is an array of objects of type
* X509Certificate, the order of this array is defined as being in ascending
* order of trust. The first certificate in the chain is the one set by the
* client, the next is the one used to authenticate the first, and so on.
* </li>
* <li>an attribute named "javax.servlet.request.ssl_session_id" of type String (since Servlet Spec 3.0).</li>
* <li>an attribute named "javax.servlet.request.cipher_suite" of type String.</li>
* <li>an attribute named "javax.servlet.request.key_size" of type Integer.</li>
* <li>an attribute named "javax.servlet.request.X509Certificate" of type java.security.cert.X509Certificate[]. This
* is an array of objects of type X509Certificate, the order of this array is defined as being in ascending order of
* trust. The first certificate in the chain is the one set by the client, the next is the one used to authenticate
* the first, and so on.</li>
* </ul>
*
* @param request HttpRequest to be customized.
*
* @param sslEngine
* the sslEngine to be customized.
* @param request
* HttpRequest to be customized.
*/
public void customize(SSLEngine sslEngine, Request request)
{
@ -105,16 +107,14 @@ public class SecureRequestCustomizer implements HttpConfiguration.Customizer
if (_sniHostCheck)
{
String name = request.getServerName();
@SuppressWarnings("unchecked")
X509 x509 = (X509)sslSession.getValue(SniX509ExtendedKeyManager.SNI_X509);
if (x509!=null && !x509.matches(name))
{
LOG.warn("Host {} does not match SNI {}",name,x509);
throw new BadMessageException(400,"Host does not match SNI");
}
if (LOG.isDebugEnabled())
LOG.debug("Host {} matched SNI {}",name,x509);
}

View File

@ -3,7 +3,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-servlet</artifactId>

View File

@ -3,7 +3,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-servlets</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-spring</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-start</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-util-ajax</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-util</artifactId>

View File

@ -299,7 +299,7 @@ public class SslContextFactory extends AbstractLifeCycle
{
return _aliasX509.get(alias);
}
/**
* Create the SSLContext object and start the lifecycle
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
@ -359,7 +359,7 @@ public class SslContextFactory extends AbstractLifeCycle
}
X509 x509 = new X509(alias,x509C);
_aliasX509.put(alias,x509);
if (_validateCerts)
{
CertificateValidator validator = new CertificateValidator(trustStore, crls);
@ -371,7 +371,7 @@ public class SslContextFactory extends AbstractLifeCycle
}
LOG.info("x509={} for {}",x509,this);
for (String h:x509.getHosts())
_certHosts.put(h,x509);
for (String w:x509.getWilds())
@ -405,7 +405,7 @@ public class SslContextFactory extends AbstractLifeCycle
LOG.debug("Selected Ciphers {} of {}",Arrays.asList(_selectedCipherSuites),Arrays.asList(sslEngine.getSupportedCipherSuites()));
}
}
@Override
protected void doStop() throws Exception
{
@ -1710,15 +1710,15 @@ public class SslContextFactory extends AbstractLifeCycle
{
String host = _host = ((SNIHostName)serverName).getAsciiName();
host=StringUtil.asciiToLowerCase(host);
// Try an exact match
_x509 = _certHosts.get(host);
// Else try an exact wild match
if (_x509==null)
{
_x509 = _certWilds.get(host);
// Else try an 1 deep wild match
if (_x509==null)
{
@ -1733,10 +1733,12 @@ public class SslContextFactory extends AbstractLifeCycle
if (LOG.isDebugEnabled())
LOG.debug("SNI matched {}->{}",host,_x509);
}
else if (LOG.isDebugEnabled())
LOG.debug("SNI no match for {}", serverName);
else
{
if (LOG.isDebugEnabled())
LOG.debug("SNI no match for {}", serverName);
}
// Return true and allow the KeyManager to accept or reject when choosing a certificate.
// If we don't have a SNI host, or didn't see any certificate aliases,

View File

@ -32,14 +32,13 @@ import javax.naming.ldap.Rdn;
import javax.security.auth.x500.X500Principal;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class X509
{
static final Logger LOG = Log.getLogger(X509.class);
private static final Logger LOG = Log.getLogger(X509.class);
/*
* @see {@link X509Certificate#getKeyUsage()}
*/
@ -51,26 +50,22 @@ public class X509
*/
private static final int SUBJECT_ALTERNATIVE_NAMES__DNS_NAME=2;
public static boolean isCertSign(X509Certificate x509)
{
boolean[] key_usage=x509.getKeyUsage();
return key_usage!=null && key_usage[KEY_USAGE__KEY_CERT_SIGN];
}
private final X509Certificate _x509;
private final String _alias;
private final List<String> _hosts=new ArrayList<>();
private final List<String> _wilds=new ArrayList<>();
public X509(String alias,X509Certificate x509) throws CertificateParsingException, InvalidNameException
{
_alias=alias;
_x509 = x509;
// Look for alternative name extensions
boolean named=false;
Collection<List<?>> altNames = x509.getSubjectAlternativeNames();
@ -82,7 +77,7 @@ public class X509
{
String cn = list.get(1).toString();
if (LOG.isDebugEnabled())
LOG.debug("Certificate SAN alias={} cn={} in {}",alias,cn,this);
LOG.debug("Certificate SAN alias={} CN={} in {}",alias,cn,this);
if (cn!=null)
{
named=true;
@ -92,28 +87,27 @@ public class X509
}
}
// If no names found, look up the cn from the subject
// If no names found, look up the CN from the subject
if (!named)
{
LdapName name=new LdapName(x509.getSubjectX500Principal().getName(X500Principal.RFC2253));
for (Rdn rdn : name.getRdns())
{
if (rdn.getType().equalsIgnoreCase("cn"))
if (rdn.getType().equalsIgnoreCase("CN"))
{
String cn = rdn.getValue().toString();
if (LOG.isDebugEnabled())
LOG.debug("Certificate cn alias={} cn={} in {}",alias,cn,this);
LOG.debug("Certificate CN alias={} CN={} in {}",alias,cn,this);
if (cn!=null && cn.contains(".") && !cn.contains(" "))
addName(cn);
}
}
}
}
protected void addName(String cn)
{
cn=StringUtil.asciiToLowerCase(cn);
cn.toLowerCase();
if (cn.startsWith("*."))
_wilds.add(cn.substring(2));
else
@ -124,17 +118,17 @@ public class X509
{
return _alias;
}
public X509Certificate getCertificate()
{
return _x509;
}
public Set<String> getHosts()
{
return new HashSet<>(_hosts);
}
public Set<String> getWilds()
{
return new HashSet<>(_wilds);
@ -156,7 +150,6 @@ public class X509
return false;
}
@Override
public String toString()
{

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-webapp</artifactId>

View File

@ -470,7 +470,10 @@ public class WebAppClassLoader extends URLClassLoader
c= _parent.loadClass(name);
if (c == null && ex!=null)
{
LOG.debug("not found {} from {}",name,this,ex);
throw ex;
}
if (resolve)
resolveClass(c);

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-parent</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-parent</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -3,7 +3,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-parent</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -18,33 +18,38 @@
package org.eclipse.jetty.websocket.api;
import java.nio.charset.StandardCharsets;
public class CloseStatus
{
private static final int MAX_CONTROL_PAYLOAD = 125;
private static final int MAX_REASON_PHRASE = MAX_CONTROL_PAYLOAD - 2;
public static final int MAX_REASON_PHRASE = MAX_CONTROL_PAYLOAD - 2;
/**
* Convenience method for trimming a long reason phrase at the maximum reason phrase length.
* Convenience method for trimming a long reason phrase at the maximum reason phrase length of 123 UTF-8 bytes (per WebSocket spec).
*
* @param reason
* the proposed reason phrase
* @return the reason phrase (trimmed if needed)
* @deprecated use of this method is strongly discouraged, as it creates too many new objects that are just thrown away to accomplish its goals.
*/
@Deprecated
public static String trimMaxReasonLength(String reason)
{
if (reason == null)
{
return null;
}
byte[] reasonBytes = reason.getBytes(StandardCharsets.UTF_8);
if (reasonBytes.length > MAX_REASON_PHRASE)
{
byte[] trimmed = new byte[MAX_REASON_PHRASE];
System.arraycopy(reasonBytes,0,trimmed,0,MAX_REASON_PHRASE);
return new String(trimmed,StandardCharsets.UTF_8);
}
if (reason.length() > MAX_REASON_PHRASE)
{
return reason.substring(0,MAX_REASON_PHRASE);
}
else
{
return reason;
}
return reason;
}
private int code;

View File

@ -152,6 +152,15 @@ public interface RemoteEndpoint
*/
BatchMode getBatchMode();
/**
* Set the batch mode with which messages are sent.
*
* @param mode
* the batch mode to use
* @see #flush()
*/
void setBatchMode(BatchMode mode);
/**
* Flushes messages that may have been batched by the implementation.
*

View File

@ -24,6 +24,8 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.eclipse.jetty.websocket.api.BatchMode;
/**
* Tags a POJO as being a WebSocket class.
*/
@ -40,4 +42,6 @@ public @interface WebSocket
int maxIdleTime() default -2;
int maxTextMessageSize() default -2;
BatchMode batchMode() default BatchMode.AUTO;
}

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-parent</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-parent</artifactId>
<version>9.3.3-SNAPSHOT</version>
<version>9.3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -19,14 +19,13 @@
package org.eclipse.jetty.websocket.common;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.Utf8Appendable.NotUtf8Exception;
import org.eclipse.jetty.util.Utf8StringBuilder;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.Utf8Appendable.NotUtf8Exception;
import org.eclipse.jetty.websocket.api.BadPayloadException;
import org.eclipse.jetty.websocket.api.CloseStatus;
import org.eclipse.jetty.websocket.api.ProtocolException;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.extensions.Frame;
@ -34,19 +33,23 @@ import org.eclipse.jetty.websocket.common.frames.CloseFrame;
public class CloseInfo
{
private static final Logger LOG = Log.getLogger(CloseInfo.class);
private int statusCode;
private String reason;
private byte[] reasonBytes;
public CloseInfo()
{
this(StatusCode.NO_CODE,null);
}
/**
* Parse the Close Frame payload.
*
* @param payload the raw close frame payload.
* @param validate true if payload should be validated per WebSocket spec.
*/
public CloseInfo(ByteBuffer payload, boolean validate)
{
this.statusCode = StatusCode.NO_CODE;
this.reason = null;
if ((payload == null) || (payload.remaining() == 0))
{
@ -77,34 +80,24 @@ public class CloseInfo
if (data.remaining() > 0)
{
// Reason
try
// Reason (trimmed to max reason size)
int len = Math.min(data.remaining(), CloseStatus.MAX_REASON_PHRASE);
reasonBytes = new byte[len];
data.get(reasonBytes,0,len);
// Spec Requirement : throw BadPayloadException on invalid UTF8
if(validate)
{
Utf8StringBuilder utf = new Utf8StringBuilder();
utf.append(data);
reason = utf.toString();
}
catch (NotUtf8Exception e)
{
if (validate)
try
{
Utf8StringBuilder utf = new Utf8StringBuilder();
// if this throws, we know we have bad UTF8
utf.append(reasonBytes,0,reasonBytes.length);
}
catch (NotUtf8Exception e)
{
throw new BadPayloadException("Invalid Close Reason",e);
}
else
{
LOG.warn(e);
}
}
catch (RuntimeException e)
{
if (validate)
{
throw new ProtocolException("Invalid Close Reason",e);
}
else
{
LOG.warn(e);
}
}
}
}
@ -125,10 +118,28 @@ public class CloseInfo
this(statusCode,null);
}
/**
* Create a CloseInfo, trimming the reason to {@link CloseStatus#MAX_REASON_PHRASE} UTF-8 bytes if needed.
*
* @param statusCode the status code
* @param reason the raw reason code
*/
public CloseInfo(int statusCode, String reason)
{
this.statusCode = statusCode;
this.reason = reason;
if (reason != null)
{
byte[] utf8Bytes = reason.getBytes(StandardCharsets.UTF_8);
if (utf8Bytes.length > CloseStatus.MAX_REASON_PHRASE)
{
this.reasonBytes = new byte[CloseStatus.MAX_REASON_PHRASE];
System.arraycopy(utf8Bytes,0,this.reasonBytes,0,CloseStatus.MAX_REASON_PHRASE);
}
else
{
this.reasonBytes = utf8Bytes;
}
}
}
private ByteBuffer asByteBuffer()
@ -140,11 +151,10 @@ public class CloseInfo
}
int len = 2; // status code
byte utf[] = null;
if (StringUtil.isNotBlank(reason))
boolean hasReason = (this.reasonBytes != null) && (this.reasonBytes.length > 0);
if (hasReason)
{
utf = StringUtil.getUtf8Bytes(reason);
len += utf.length;
len += this.reasonBytes.length;
}
ByteBuffer buf = BufferUtil.allocate(len);
@ -152,9 +162,9 @@ public class CloseInfo
buf.put((byte)((statusCode >>> 8) & 0xFF));
buf.put((byte)((statusCode >>> 0) & 0xFF));
if (utf != null)
if (hasReason)
{
buf.put(utf,0,utf.length);
buf.put(this.reasonBytes,0,this.reasonBytes.length);
}
BufferUtil.flipToFlush(buf,0);
@ -178,7 +188,11 @@ public class CloseInfo
public String getReason()
{
return reason;
if (this.reasonBytes == null)
{
return null;
}
return new String(this.reasonBytes,StandardCharsets.UTF_8);
}
public int getStatusCode()
@ -199,6 +213,6 @@ public class CloseInfo
@Override
public String toString()
{
return String.format("CloseInfo[code=%d,reason=%s]",statusCode,reason);
return String.format("CloseInfo[code=%d,reason=%s]",statusCode,getReason());
}
}

View File

@ -436,9 +436,7 @@ public class WebSocketRemoteEndpoint implements RemoteEndpoint
return batchMode;
}
// Only the JSR needs to have this method exposed.
// In the Jetty implementation the batching is set
// at the moment of opening the session.
@Override
public void setBatchMode(BatchMode batchMode)
{
this.batchMode = batchMode;

View File

@ -98,7 +98,7 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Web
@Override
public void close()
{
this.close(StatusCode.NORMAL,null);
connection.close();
}
@Override

View File

@ -25,6 +25,7 @@ import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Utf8Appendable.NotUtf8Exception;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.BatchMode;
import org.eclipse.jetty.websocket.api.CloseException;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
@ -208,6 +209,12 @@ public abstract class AbstractEventDriver implements IncomingFrames, EventDriver
{
/* TODO: provide annotation in future */
}
@Override
public BatchMode getBatchMode()
{
return null;
}
@Override
public void openSession(WebSocketSession session)

View File

@ -23,6 +23,7 @@ import java.io.InputStream;
import java.io.Reader;
import java.nio.ByteBuffer;
import org.eclipse.jetty.websocket.api.BatchMode;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
@ -34,6 +35,8 @@ public interface EventDriver extends IncomingFrames
public WebSocketPolicy getPolicy();
public WebSocketSession getSession();
public BatchMode getBatchMode();
public void onBinaryFrame(ByteBuffer buffer, boolean fin) throws IOException;

View File

@ -23,6 +23,7 @@ import java.io.InputStream;
import java.io.Reader;
import java.nio.ByteBuffer;
import org.eclipse.jetty.websocket.api.BatchMode;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.api.extensions.Frame;
@ -40,6 +41,7 @@ public class JettyAnnotatedEventDriver extends AbstractEventDriver
{
private final JettyAnnotatedMetadata events;
private boolean hasCloseBeenCalled = false;
private BatchMode batchMode;
public JettyAnnotatedEventDriver(WebSocketPolicy policy, Object websocket, JettyAnnotatedMetadata events)
{
@ -64,6 +66,13 @@ public class JettyAnnotatedEventDriver extends AbstractEventDriver
{
this.policy.setIdleTimeout(anno.maxIdleTime());
}
this.batchMode = anno.batchMode();
}
@Override
public BatchMode getBatchMode()
{
return this.batchMode;
}
@Override

View File

@ -244,10 +244,14 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp
return super.getExecutor();
}
/**
* Close without a close code or reason
*/
@Override
public void close()
{
close(StatusCode.NORMAL,null);
CloseInfo close = new CloseInfo();
this.outgoingFrame(close.asFrame(),new OnCloseLocalCallback(close),BatchMode.OFF);
}
/**

Some files were not shown because too many files have changed in this diff Show More