* Fixes #9166 - Jetty 12: review/remove ByteBufferPool * Replaced usages of ByteBufferPool with RetainableByteBufferPool. * Removed ByteBufferPool and related classes. * Renamed oej.http2.frames.DataFrame.getData() -> getByteBuffer() for consistency. * Removed Accumulator.acquire(), and updated code to use RetainableByteBufferPool.acquire() instead. * Fixed HttpOutput callbacks to correctly call super.onCompleteSuccess() and super.onCompleteFailure(). Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
This commit is contained in:
parent
63d963d526
commit
ded18f523d
|
@ -33,7 +33,7 @@ The `ClientConnector` primarily wraps the link:{javadoc-url}/org/eclipse/jetty/i
|
|||
|
||||
* a thread pool (in form of an `java.util.concurrent.Executor`)
|
||||
* a scheduler (in form of `org.eclipse.jetty.util.thread.Scheduler`)
|
||||
* a byte buffer pool (in form of `org.eclipse.jetty.io.ByteBufferPool`)
|
||||
* a byte buffer pool (in form of `org.eclipse.jetty.io.RetainableByteBufferPool`)
|
||||
* a TLS factory (in form of `org.eclipse.jetty.util.ssl.SslContextFactory.Client`)
|
||||
|
||||
The `ClientConnector` is where you want to set those components after you have configured them.
|
||||
|
|
|
@ -72,7 +72,7 @@ public class HTTP2Docs
|
|||
}
|
||||
|
||||
// Get the content buffer.
|
||||
ByteBuffer byteBuffer = data.frame().getData();
|
||||
ByteBuffer byteBuffer = data.frame().getByteBuffer();
|
||||
|
||||
// Unwrap the Data object, converting it to a Chunk.
|
||||
// The Data.release() semantic is maintained in the completion of the Callback.
|
||||
|
|
|
@ -387,7 +387,7 @@ public class ClientConnectorDocs
|
|||
|
||||
// Wrap the "telnet" ClientConnectionFactory with the SslClientConnectionFactory.
|
||||
connectionFactory = new SslClientConnectionFactory(clientConnector.getSslContextFactory(),
|
||||
clientConnector.getByteBufferPool(), clientConnector.getExecutor(), connectionFactory);
|
||||
clientConnector.getRetainableByteBufferPool(), clientConnector.getExecutor(), connectionFactory);
|
||||
|
||||
// We will obtain a SslConnection now.
|
||||
CompletableFuture<SslConnection> connectionPromise = new Promise.Completable<>();
|
||||
|
|
|
@ -63,7 +63,6 @@ import org.eclipse.jetty.http2.client.transport.ClientConnectionFactoryOverHTTP2
|
|||
import org.eclipse.jetty.http2.client.transport.HttpClientTransportOverHTTP2;
|
||||
import org.eclipse.jetty.http3.client.HTTP3Client;
|
||||
import org.eclipse.jetty.http3.client.transport.HttpClientTransportOverHTTP3;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.ClientConnectionFactory;
|
||||
import org.eclipse.jetty.io.ClientConnector;
|
||||
import org.eclipse.jetty.io.Content;
|
||||
|
@ -334,14 +333,13 @@ public class HTTPClientDocs
|
|||
// An event happens in some other class, in some other thread.
|
||||
class ContentPublisher
|
||||
{
|
||||
void publish(ByteBufferPool bufferPool, byte[] bytes, boolean lastContent)
|
||||
void publish(byte[] bytes, boolean lastContent)
|
||||
{
|
||||
// Wrap the bytes into a new ByteBuffer.
|
||||
ByteBuffer buffer = ByteBuffer.wrap(bytes);
|
||||
|
||||
// Offer the content, and release the ByteBuffer
|
||||
// to the pool when the Callback is completed.
|
||||
content.write(buffer, Callback.from(() -> bufferPool.release(buffer)));
|
||||
// Write the content.
|
||||
content.write(buffer, Callback.NOOP);
|
||||
|
||||
// Close AsyncRequestContent when all the content is arrived.
|
||||
if (lastContent)
|
||||
|
|
|
@ -254,7 +254,7 @@ public class HTTP2ClientDocs
|
|||
}
|
||||
|
||||
// Get the content buffer.
|
||||
ByteBuffer buffer = data.frame().getData();
|
||||
ByteBuffer buffer = data.frame().getByteBuffer();
|
||||
|
||||
// Consume the buffer, here - as an example - just log it.
|
||||
System.getLogger("http2").log(INFO, "Consuming buffer {0}", buffer);
|
||||
|
@ -368,7 +368,7 @@ public class HTTP2ClientDocs
|
|||
}
|
||||
|
||||
// The pushed stream "response" content bytes.
|
||||
ByteBuffer buffer = data.frame().getData();
|
||||
ByteBuffer buffer = data.frame().getByteBuffer();
|
||||
// Consume the buffer and release the Data object.
|
||||
data.release();
|
||||
|
||||
|
|
|
@ -159,7 +159,7 @@ public class HTTP2ServerDocs
|
|||
}
|
||||
|
||||
// Get the content buffer.
|
||||
ByteBuffer buffer = data.frame().getData();
|
||||
ByteBuffer buffer = data.frame().getByteBuffer();
|
||||
|
||||
// Consume the buffer, here - as an example - just log it.
|
||||
System.getLogger("http2").log(INFO, "Consuming buffer {0}", buffer);
|
||||
|
|
|
@ -52,7 +52,7 @@ public abstract class AbstractConnectorHttpClientTransport extends AbstractHttpC
|
|||
{
|
||||
HttpClient httpClient = getHttpClient();
|
||||
connector.setBindAddress(httpClient.getBindAddress());
|
||||
connector.setByteBufferPool(httpClient.getByteBufferPool());
|
||||
connector.setRetainableByteBufferPool(httpClient.getRetainableByteBufferPool());
|
||||
connector.setConnectBlocking(httpClient.isConnectBlocking());
|
||||
connector.setConnectTimeout(Duration.ofMillis(httpClient.getConnectTimeout()));
|
||||
connector.setExecutor(httpClient.getExecutor());
|
||||
|
|
|
@ -20,6 +20,7 @@ import java.util.Map;
|
|||
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
|
||||
/**
|
||||
* {@link ContentDecoder} decodes content bytes of a response.
|
||||
|
@ -29,21 +30,14 @@ import org.eclipse.jetty.http.HttpHeader;
|
|||
public interface ContentDecoder
|
||||
{
|
||||
/**
|
||||
* <p>Decodes the bytes in the given {@code buffer} and returns decoded bytes, if any.</p>
|
||||
* <p>Decodes the bytes in the given {@code buffer} and returns the decoded bytes.</p>
|
||||
* <p>The returned {@link RetainableByteBuffer} containing the decoded bytes may
|
||||
* be empty and <b>must</b> be released via {@link RetainableByteBuffer#release()}.</p>
|
||||
*
|
||||
* @param buffer the buffer containing encoded bytes
|
||||
* @return a buffer containing decoded bytes, if any
|
||||
* @return a buffer containing decoded bytes that must be released
|
||||
*/
|
||||
public abstract ByteBuffer decode(ByteBuffer buffer);
|
||||
|
||||
/**
|
||||
* <p>Releases the ByteBuffer returned by {@link #decode(ByteBuffer)}.</p>
|
||||
*
|
||||
* @param decoded the ByteBuffer returned by {@link #decode(ByteBuffer)}
|
||||
*/
|
||||
public default void release(ByteBuffer decoded)
|
||||
{
|
||||
}
|
||||
public abstract RetainableByteBuffer decode(ByteBuffer buffer);
|
||||
|
||||
/**
|
||||
* Factory for {@link ContentDecoder}s; subclasses must implement {@link #newContentDecoder()}.
|
||||
|
|
|
@ -13,9 +13,8 @@
|
|||
|
||||
package org.eclipse.jetty.client;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
|
||||
/**
|
||||
* {@link ContentDecoder} for the "gzip" encoding.
|
||||
|
@ -34,13 +33,13 @@ public class GZIPContentDecoder extends org.eclipse.jetty.http.GZIPContentDecode
|
|||
this(null, bufferSize);
|
||||
}
|
||||
|
||||
public GZIPContentDecoder(ByteBufferPool byteBufferPool, int bufferSize)
|
||||
public GZIPContentDecoder(RetainableByteBufferPool retainableByteBufferPool, int bufferSize)
|
||||
{
|
||||
super(byteBufferPool, bufferSize);
|
||||
super(retainableByteBufferPool, bufferSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean decodedChunk(ByteBuffer chunk)
|
||||
protected boolean decodedChunk(RetainableByteBuffer chunk)
|
||||
{
|
||||
super.decodedChunk(chunk);
|
||||
return true;
|
||||
|
@ -51,8 +50,8 @@ public class GZIPContentDecoder extends org.eclipse.jetty.http.GZIPContentDecode
|
|||
*/
|
||||
public static class Factory extends ContentDecoder.Factory
|
||||
{
|
||||
private final RetainableByteBufferPool retainableByteBufferPool;
|
||||
private final int bufferSize;
|
||||
private final ByteBufferPool byteBufferPool;
|
||||
|
||||
public Factory()
|
||||
{
|
||||
|
@ -64,22 +63,22 @@ public class GZIPContentDecoder extends org.eclipse.jetty.http.GZIPContentDecode
|
|||
this(null, bufferSize);
|
||||
}
|
||||
|
||||
public Factory(ByteBufferPool byteBufferPool)
|
||||
public Factory(RetainableByteBufferPool retainableByteBufferPool)
|
||||
{
|
||||
this(byteBufferPool, DEFAULT_BUFFER_SIZE);
|
||||
this(retainableByteBufferPool, DEFAULT_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
public Factory(ByteBufferPool byteBufferPool, int bufferSize)
|
||||
public Factory(RetainableByteBufferPool retainableByteBufferPool, int bufferSize)
|
||||
{
|
||||
super("gzip");
|
||||
this.byteBufferPool = byteBufferPool;
|
||||
this.retainableByteBufferPool = retainableByteBufferPool;
|
||||
this.bufferSize = bufferSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentDecoder newContentDecoder()
|
||||
{
|
||||
return new GZIPContentDecoder(byteBufferPool, bufferSize);
|
||||
return new GZIPContentDecoder(retainableByteBufferPool, bufferSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,10 +49,8 @@ import org.eclipse.jetty.http.HttpMethod;
|
|||
import org.eclipse.jetty.http.HttpParser;
|
||||
import org.eclipse.jetty.http.HttpScheme;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.ClientConnectionFactory;
|
||||
import org.eclipse.jetty.io.ClientConnector;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.ssl.SslClientConnectionFactory;
|
||||
import org.eclipse.jetty.util.Fields;
|
||||
|
@ -201,11 +199,9 @@ public class HttpClient extends ContainerLifeCycle
|
|||
int maxBucketSize = executor instanceof ThreadPool.SizedThreadPool
|
||||
? ((ThreadPool.SizedThreadPool)executor).getMaxThreads() / 2
|
||||
: ProcessorUtils.availableProcessors() * 2;
|
||||
ByteBufferPool byteBufferPool = getByteBufferPool();
|
||||
if (byteBufferPool == null)
|
||||
setByteBufferPool(new MappedByteBufferPool(2048, maxBucketSize));
|
||||
if (getBean(RetainableByteBufferPool.class) == null)
|
||||
addBean(new ArrayRetainableByteBufferPool(0, 2048, 65536, maxBucketSize));
|
||||
RetainableByteBufferPool retainableByteBufferPool = getRetainableByteBufferPool();
|
||||
if (retainableByteBufferPool == null)
|
||||
setRetainableByteBufferPool(new ArrayRetainableByteBufferPool(0, 2048, 65536, maxBucketSize));
|
||||
Scheduler scheduler = getScheduler();
|
||||
if (scheduler == null)
|
||||
{
|
||||
|
@ -224,7 +220,7 @@ public class HttpClient extends ContainerLifeCycle
|
|||
handlers.put(new ProxyAuthenticationProtocolHandler(this));
|
||||
handlers.put(new UpgradeProtocolHandler());
|
||||
|
||||
decoderFactories.put(new GZIPContentDecoder.Factory(byteBufferPool));
|
||||
decoderFactories.put(new GZIPContentDecoder.Factory(retainableByteBufferPool));
|
||||
|
||||
cookieManager = newCookieManager();
|
||||
cookieStore = cookieManager.getCookieStore();
|
||||
|
@ -650,19 +646,19 @@ public class HttpClient extends ContainerLifeCycle
|
|||
}
|
||||
|
||||
/**
|
||||
* @return the {@link ByteBufferPool} of this HttpClient
|
||||
* @return the {@link RetainableByteBufferPool} of this HttpClient
|
||||
*/
|
||||
public ByteBufferPool getByteBufferPool()
|
||||
public RetainableByteBufferPool getRetainableByteBufferPool()
|
||||
{
|
||||
return connector.getByteBufferPool();
|
||||
return connector.getRetainableByteBufferPool();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param byteBufferPool the {@link ByteBufferPool} of this HttpClient
|
||||
* @param retainableByteBufferPool the {@link RetainableByteBufferPool} of this HttpClient
|
||||
*/
|
||||
public void setByteBufferPool(ByteBufferPool byteBufferPool)
|
||||
public void setRetainableByteBufferPool(RetainableByteBufferPool retainableByteBufferPool)
|
||||
{
|
||||
connector.setByteBufferPool(byteBufferPool);
|
||||
connector.setRetainableByteBufferPool(retainableByteBufferPool);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1156,6 +1152,6 @@ public class HttpClient extends ContainerLifeCycle
|
|||
{
|
||||
if (sslContextFactory == null)
|
||||
sslContextFactory = getSslContextFactory();
|
||||
return new SslClientConnectionFactory(sslContextFactory, getByteBufferPool(), getExecutor(), connectionFactory);
|
||||
return new SslClientConnectionFactory(sslContextFactory, getRetainableByteBufferPool(), getExecutor(), connectionFactory);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
package org.eclipse.jetty.client.internal;
|
||||
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
|
@ -27,8 +26,8 @@ import org.eclipse.jetty.http.HttpField;
|
|||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.io.Content;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.content.ContentSourceTransformer;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.Promise;
|
||||
import org.eclipse.jetty.util.thread.AutoLock;
|
||||
import org.eclipse.jetty.util.thread.SerializedInvoker;
|
||||
|
@ -578,17 +577,17 @@ public abstract class HttpReceiver
|
|||
_chunk.retain();
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("decoding: {}", _chunk);
|
||||
ByteBuffer decodedBuffer = _decoder.decode(_chunk.getByteBuffer());
|
||||
RetainableByteBuffer decodedBuffer = _decoder.decode(_chunk.getByteBuffer());
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("decoded: {}", BufferUtil.toDetailString(decodedBuffer));
|
||||
LOG.debug("decoded: {}", decodedBuffer);
|
||||
|
||||
if (BufferUtil.hasContent(decodedBuffer))
|
||||
if (decodedBuffer != null && decodedBuffer.hasRemaining())
|
||||
{
|
||||
// The decoded ByteBuffer is a transformed "copy" of the
|
||||
// compressed one, so it has its own reference counter.
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("returning decoded content");
|
||||
return Content.Chunk.from(decodedBuffer, false, _decoder::release);
|
||||
return Content.Chunk.asChunk(decodedBuffer.getByteBuffer(), false, decodedBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -66,7 +66,7 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
|
|||
parser.setHeaderCacheSize(httpTransport.getHeaderCacheSize());
|
||||
parser.setHeaderCacheCaseSensitive(httpTransport.isHeaderCacheCaseSensitive());
|
||||
}
|
||||
retainableByteBufferPool = httpClient.getByteBufferPool().asRetainableByteBufferPool();
|
||||
retainableByteBufferPool = httpClient.getRetainableByteBufferPool();
|
||||
}
|
||||
|
||||
void receive()
|
||||
|
@ -169,7 +169,7 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
|
|||
|
||||
protected ByteBuffer getResponseBuffer()
|
||||
{
|
||||
return networkBuffer == null ? null : networkBuffer.getBuffer();
|
||||
return networkBuffer == null ? null : networkBuffer.getByteBuffer();
|
||||
}
|
||||
|
||||
private void acquireNetworkBuffer()
|
||||
|
@ -222,7 +222,7 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
|
|||
HttpClient client = getHttpDestination().getHttpClient();
|
||||
upgradeBuffer = BufferUtil.allocate(networkBuffer.remaining(), client.isUseInputDirectByteBuffers());
|
||||
BufferUtil.clearToFill(upgradeBuffer);
|
||||
BufferUtil.put(networkBuffer.getBuffer(), upgradeBuffer);
|
||||
BufferUtil.put(networkBuffer.getByteBuffer(), upgradeBuffer);
|
||||
BufferUtil.flipToFlush(upgradeBuffer, 0);
|
||||
}
|
||||
releaseNetworkBuffer();
|
||||
|
@ -245,7 +245,7 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
|
|||
while (true)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Parsing {} in {}", BufferUtil.toDetailString(networkBuffer.getBuffer()), this);
|
||||
LOG.debug("Parsing {} in {}", BufferUtil.toDetailString(networkBuffer.getByteBuffer()), this);
|
||||
// Always parse even empty buffers to advance the parser.
|
||||
if (parse())
|
||||
{
|
||||
|
@ -269,7 +269,7 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
|
|||
reacquireNetworkBuffer();
|
||||
|
||||
// The networkBuffer may have been reacquired.
|
||||
int read = endPoint.fill(networkBuffer.getBuffer());
|
||||
int read = endPoint.fill(networkBuffer.getByteBuffer());
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Read {} bytes in {} from {} in {}", read, networkBuffer, endPoint, this);
|
||||
|
||||
|
@ -309,7 +309,7 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
|
|||
{
|
||||
while (true)
|
||||
{
|
||||
boolean handle = parser.parseNext(networkBuffer.getBuffer());
|
||||
boolean handle = parser.parseNext(networkBuffer.getByteBuffer());
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Parse result={} on {}", handle, this);
|
||||
Runnable action = getAndSetAction(null);
|
||||
|
@ -347,7 +347,7 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
|
|||
if (getHttpChannel().isTunnel(method, status))
|
||||
return true;
|
||||
|
||||
if (networkBuffer.isEmpty())
|
||||
if (!networkBuffer.hasRemaining())
|
||||
return false;
|
||||
|
||||
if (!HttpStatus.isInformational(status))
|
||||
|
@ -359,7 +359,7 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
|
|||
return false;
|
||||
}
|
||||
|
||||
if (networkBuffer.isEmpty())
|
||||
if (!networkBuffer.hasRemaining())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,9 +23,10 @@ import org.eclipse.jetty.client.internal.HttpSender;
|
|||
import org.eclipse.jetty.http.HttpGenerator;
|
||||
import org.eclipse.jetty.http.HttpURI;
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.Content;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.IteratingCallback;
|
||||
|
@ -41,7 +42,7 @@ public class HttpSenderOverHTTP extends HttpSender
|
|||
private final HttpGenerator generator = new HttpGenerator();
|
||||
private HttpExchange exchange;
|
||||
private MetaData.Request metaData;
|
||||
private ByteBuffer contentBuffer;
|
||||
private ByteBuffer contentByteBuffer;
|
||||
private boolean lastContent;
|
||||
private Callback callback;
|
||||
private boolean shutdown;
|
||||
|
@ -63,7 +64,7 @@ public class HttpSenderOverHTTP extends HttpSender
|
|||
try
|
||||
{
|
||||
this.exchange = exchange;
|
||||
this.contentBuffer = contentBuffer;
|
||||
this.contentByteBuffer = contentBuffer;
|
||||
this.lastContent = lastContent;
|
||||
this.callback = callback;
|
||||
HttpRequest request = exchange.getRequest();
|
||||
|
@ -92,7 +93,7 @@ public class HttpSenderOverHTTP extends HttpSender
|
|||
try
|
||||
{
|
||||
this.exchange = exchange;
|
||||
this.contentBuffer = contentBuffer;
|
||||
this.contentByteBuffer = contentBuffer;
|
||||
this.lastContent = lastContent;
|
||||
this.callback = callback;
|
||||
if (LOG.isDebugEnabled())
|
||||
|
@ -144,8 +145,8 @@ public class HttpSenderOverHTTP extends HttpSender
|
|||
|
||||
private class HeadersCallback extends IteratingCallback
|
||||
{
|
||||
private ByteBuffer headerBuffer;
|
||||
private ByteBuffer chunkBuffer;
|
||||
private RetainableByteBuffer headerBuffer;
|
||||
private RetainableByteBuffer chunkBuffer;
|
||||
private boolean generated;
|
||||
|
||||
private HeadersCallback()
|
||||
|
@ -157,52 +158,54 @@ public class HttpSenderOverHTTP extends HttpSender
|
|||
protected Action process() throws Exception
|
||||
{
|
||||
HttpClient httpClient = getHttpChannel().getHttpDestination().getHttpClient();
|
||||
ByteBufferPool byteBufferPool = httpClient.getByteBufferPool();
|
||||
RetainableByteBufferPool bufferPool = httpClient.getRetainableByteBufferPool();
|
||||
boolean useDirectByteBuffers = httpClient.isUseOutputDirectByteBuffers();
|
||||
while (true)
|
||||
{
|
||||
HttpGenerator.Result result = generator.generateRequest(metaData, headerBuffer, chunkBuffer, contentBuffer, lastContent);
|
||||
ByteBuffer headerByteBuffer = headerBuffer == null ? null : headerBuffer.getByteBuffer();
|
||||
ByteBuffer chunkByteBuffer = chunkBuffer == null ? null : chunkBuffer.getByteBuffer();
|
||||
HttpGenerator.Result result = generator.generateRequest(metaData, headerByteBuffer, chunkByteBuffer, contentByteBuffer, lastContent);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Generated headers ({} bytes), chunk ({} bytes), content ({} bytes) - {}/{} for {}",
|
||||
headerBuffer == null ? -1 : headerBuffer.remaining(),
|
||||
chunkBuffer == null ? -1 : chunkBuffer.remaining(),
|
||||
contentBuffer == null ? -1 : contentBuffer.remaining(),
|
||||
headerByteBuffer == null ? -1 : headerByteBuffer.remaining(),
|
||||
chunkByteBuffer == null ? -1 : chunkByteBuffer.remaining(),
|
||||
contentByteBuffer == null ? -1 : contentByteBuffer.remaining(),
|
||||
result, generator, exchange.getRequest());
|
||||
switch (result)
|
||||
{
|
||||
case NEED_HEADER:
|
||||
{
|
||||
headerBuffer = byteBufferPool.acquire(httpClient.getRequestBufferSize(), useDirectByteBuffers);
|
||||
headerBuffer = bufferPool.acquire(httpClient.getRequestBufferSize(), useDirectByteBuffers);
|
||||
break;
|
||||
}
|
||||
case HEADER_OVERFLOW:
|
||||
{
|
||||
httpClient.getByteBufferPool().release(headerBuffer);
|
||||
headerBuffer.release();
|
||||
headerBuffer = null;
|
||||
throw new IllegalArgumentException("Request header too large");
|
||||
}
|
||||
case NEED_CHUNK:
|
||||
{
|
||||
chunkBuffer = byteBufferPool.acquire(HttpGenerator.CHUNK_SIZE, useDirectByteBuffers);
|
||||
chunkBuffer = bufferPool.acquire(HttpGenerator.CHUNK_SIZE, useDirectByteBuffers);
|
||||
break;
|
||||
}
|
||||
case NEED_CHUNK_TRAILER:
|
||||
{
|
||||
chunkBuffer = byteBufferPool.acquire(httpClient.getRequestBufferSize(), useDirectByteBuffers);
|
||||
chunkBuffer = bufferPool.acquire(httpClient.getRequestBufferSize(), useDirectByteBuffers);
|
||||
break;
|
||||
}
|
||||
case FLUSH:
|
||||
{
|
||||
EndPoint endPoint = getHttpChannel().getHttpConnection().getEndPoint();
|
||||
if (headerBuffer == null)
|
||||
headerBuffer = BufferUtil.EMPTY_BUFFER;
|
||||
if (chunkBuffer == null)
|
||||
chunkBuffer = BufferUtil.EMPTY_BUFFER;
|
||||
if (contentBuffer == null)
|
||||
contentBuffer = BufferUtil.EMPTY_BUFFER;
|
||||
long bytes = headerBuffer.remaining() + chunkBuffer.remaining() + contentBuffer.remaining();
|
||||
if (headerByteBuffer == null)
|
||||
headerByteBuffer = BufferUtil.EMPTY_BUFFER;
|
||||
if (chunkByteBuffer == null)
|
||||
chunkByteBuffer = BufferUtil.EMPTY_BUFFER;
|
||||
if (contentByteBuffer == null)
|
||||
contentByteBuffer = BufferUtil.EMPTY_BUFFER;
|
||||
long bytes = headerByteBuffer.remaining() + chunkByteBuffer.remaining() + contentByteBuffer.remaining();
|
||||
getHttpChannel().getHttpConnection().addBytesOut(bytes);
|
||||
endPoint.write(this, headerBuffer, chunkBuffer, contentBuffer);
|
||||
endPoint.write(this, headerByteBuffer, chunkByteBuffer, contentByteBuffer);
|
||||
generated = true;
|
||||
return Action.SCHEDULED;
|
||||
}
|
||||
|
@ -263,21 +266,19 @@ public class HttpSenderOverHTTP extends HttpSender
|
|||
|
||||
private void release()
|
||||
{
|
||||
HttpClient httpClient = getHttpChannel().getHttpDestination().getHttpClient();
|
||||
ByteBufferPool bufferPool = httpClient.getByteBufferPool();
|
||||
if (!BufferUtil.isTheEmptyBuffer(headerBuffer))
|
||||
bufferPool.release(headerBuffer);
|
||||
if (headerBuffer != null)
|
||||
headerBuffer.release();
|
||||
headerBuffer = null;
|
||||
if (!BufferUtil.isTheEmptyBuffer(chunkBuffer))
|
||||
bufferPool.release(chunkBuffer);
|
||||
if (chunkBuffer != null)
|
||||
chunkBuffer.release();
|
||||
chunkBuffer = null;
|
||||
contentBuffer = null;
|
||||
contentByteBuffer = null;
|
||||
}
|
||||
}
|
||||
|
||||
private class ContentCallback extends IteratingCallback
|
||||
{
|
||||
private ByteBuffer chunkBuffer;
|
||||
private RetainableByteBuffer chunkBuffer;
|
||||
|
||||
public ContentCallback()
|
||||
{
|
||||
|
@ -288,14 +289,15 @@ public class HttpSenderOverHTTP extends HttpSender
|
|||
protected Action process() throws Exception
|
||||
{
|
||||
HttpClient httpClient = getHttpChannel().getHttpDestination().getHttpClient();
|
||||
ByteBufferPool bufferPool = httpClient.getByteBufferPool();
|
||||
RetainableByteBufferPool bufferPool = httpClient.getRetainableByteBufferPool();
|
||||
boolean useDirectByteBuffers = httpClient.isUseOutputDirectByteBuffers();
|
||||
while (true)
|
||||
{
|
||||
HttpGenerator.Result result = generator.generateRequest(null, null, chunkBuffer, contentBuffer, lastContent);
|
||||
ByteBuffer chunkByteBuffer = chunkBuffer == null ? null : chunkBuffer.getByteBuffer();
|
||||
HttpGenerator.Result result = generator.generateRequest(null, null, chunkByteBuffer, contentByteBuffer, lastContent);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Generated content ({} bytes, last={}) - {}/{}",
|
||||
contentBuffer == null ? -1 : contentBuffer.remaining(),
|
||||
contentByteBuffer == null ? -1 : contentByteBuffer.remaining(),
|
||||
lastContent, result, generator);
|
||||
switch (result)
|
||||
{
|
||||
|
@ -312,10 +314,10 @@ public class HttpSenderOverHTTP extends HttpSender
|
|||
case FLUSH:
|
||||
{
|
||||
EndPoint endPoint = getHttpChannel().getHttpConnection().getEndPoint();
|
||||
if (chunkBuffer != null)
|
||||
endPoint.write(this, chunkBuffer, contentBuffer);
|
||||
if (chunkByteBuffer != null)
|
||||
endPoint.write(this, chunkByteBuffer, contentByteBuffer);
|
||||
else
|
||||
endPoint.write(this, contentBuffer);
|
||||
endPoint.write(this, contentByteBuffer);
|
||||
return Action.SCHEDULED;
|
||||
}
|
||||
case SHUTDOWN_OUT:
|
||||
|
@ -350,11 +352,10 @@ public class HttpSenderOverHTTP extends HttpSender
|
|||
|
||||
private void release()
|
||||
{
|
||||
HttpClient httpClient = getHttpChannel().getHttpDestination().getHttpClient();
|
||||
ByteBufferPool bufferPool = httpClient.getByteBufferPool();
|
||||
bufferPool.release(chunkBuffer);
|
||||
if (chunkBuffer != null)
|
||||
chunkBuffer.release();
|
||||
chunkBuffer = null;
|
||||
contentBuffer = null;
|
||||
contentByteBuffer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,9 +27,9 @@ import java.util.zip.GZIPOutputStream;
|
|||
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.Content;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
|
@ -242,9 +242,9 @@ public class HttpClientGZIPTest extends AbstractHttpClientServerTest
|
|||
}
|
||||
});
|
||||
|
||||
ByteBufferPool pool = client.getByteBufferPool();
|
||||
assumeTrue(pool instanceof MappedByteBufferPool);
|
||||
MappedByteBufferPool bufferPool = (MappedByteBufferPool)pool;
|
||||
RetainableByteBufferPool pool = client.getRetainableByteBufferPool();
|
||||
assumeTrue(pool instanceof ArrayRetainableByteBufferPool);
|
||||
ArrayRetainableByteBufferPool bufferPool = (ArrayRetainableByteBufferPool)pool;
|
||||
|
||||
ContentResponse response = client.newRequest("localhost", connector.getLocalPort())
|
||||
.scheme(scenario.getScheme())
|
||||
|
@ -254,9 +254,9 @@ public class HttpClientGZIPTest extends AbstractHttpClientServerTest
|
|||
assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||
assertArrayEquals(content, response.getContent());
|
||||
|
||||
long directMemory = bufferPool.getMemory(true);
|
||||
long directMemory = bufferPool.getDirectMemory();
|
||||
assertThat(directMemory, lessThan((long)content.length));
|
||||
long heapMemory = bufferPool.getMemory(false);
|
||||
long heapMemory = bufferPool.getHeapMemory();
|
||||
assertThat(heapMemory, lessThan((long)content.length));
|
||||
}
|
||||
|
||||
|
|
|
@ -44,9 +44,7 @@ import org.eclipse.jetty.http.HttpHeader;
|
|||
import org.eclipse.jetty.http.HttpHeaderValue;
|
||||
import org.eclipse.jetty.http.HttpScheme;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.io.ArrayByteBufferPool;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.ClientConnectionFactory;
|
||||
import org.eclipse.jetty.io.ClientConnector;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
|
@ -632,7 +630,7 @@ public class HttpClientTLSTest
|
|||
@Override
|
||||
protected SslConnection newSslConnection(Connector connector, EndPoint endPoint, SSLEngine engine)
|
||||
{
|
||||
return new SslConnection(connector.getByteBufferPool(), connector.getExecutor(), endPoint, engine, isDirectBuffersForEncryption(), isDirectBuffersForDecryption())
|
||||
return new SslConnection(connector.getRetainableByteBufferPool(), connector.getExecutor(), endPoint, engine, isDirectBuffersForEncryption(), isDirectBuffersForDecryption())
|
||||
{
|
||||
@Override
|
||||
protected int networkFill(ByteBuffer input) throws IOException
|
||||
|
@ -666,12 +664,12 @@ public class HttpClientTLSTest
|
|||
{
|
||||
if (sslContextFactory == null)
|
||||
sslContextFactory = getSslContextFactory();
|
||||
return new SslClientConnectionFactory(sslContextFactory, getByteBufferPool(), getExecutor(), connectionFactory)
|
||||
return new SslClientConnectionFactory(sslContextFactory, getRetainableByteBufferPool(), getExecutor(), connectionFactory)
|
||||
{
|
||||
@Override
|
||||
protected SslConnection newSslConnection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, SSLEngine engine)
|
||||
protected SslConnection newSslConnection(RetainableByteBufferPool bufferPool, Executor executor, EndPoint endPoint, SSLEngine engine)
|
||||
{
|
||||
return new SslConnection(byteBufferPool, executor, endPoint, engine, isDirectBuffersForEncryption(), isDirectBuffersForDecryption())
|
||||
return new SslConnection(bufferPool, executor, endPoint, engine, isDirectBuffersForEncryption(), isDirectBuffersForDecryption())
|
||||
{
|
||||
@Override
|
||||
protected int networkFill(ByteBuffer input) throws IOException
|
||||
|
@ -707,50 +705,6 @@ public class HttpClientTLSTest
|
|||
assertEquals(0, clientBytes.get());
|
||||
}
|
||||
|
||||
protected class TestRetained extends ArrayRetainableByteBufferPool
|
||||
{
|
||||
private final ByteBufferPool _pool;
|
||||
|
||||
public TestRetained(ByteBufferPool pool, int factor, int maxCapacity, int maxBucketSize, long retainedHeapMemory, long retainedDirectMemory)
|
||||
{
|
||||
super(0, factor, maxCapacity, maxBucketSize, retainedHeapMemory, retainedDirectMemory);
|
||||
_pool = pool;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteBuffer allocate(int capacity)
|
||||
{
|
||||
return _pool.acquire(capacity, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteBuffer allocateDirect(int capacity)
|
||||
{
|
||||
return _pool.acquire(capacity, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removed(RetainableByteBuffer retainedBuffer)
|
||||
{
|
||||
_pool.release(retainedBuffer.getBuffer());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pool<RetainableByteBuffer> poolFor(int capacity, boolean direct)
|
||||
{
|
||||
return super.poolFor(capacity, direct);
|
||||
}
|
||||
}
|
||||
|
||||
private class TestByteBufferPool extends ArrayByteBufferPool
|
||||
{
|
||||
@Override
|
||||
protected RetainableByteBufferPool newRetainableByteBufferPool(int factor, int maxCapacity, int maxBucketSize, long retainedHeapMemory, long retainedDirectMemory)
|
||||
{
|
||||
return new TestRetained(this, factor, maxCapacity, maxBucketSize, retainedHeapMemory, retainedDirectMemory);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncryptedInputBufferRepooling() throws Exception
|
||||
{
|
||||
|
@ -759,9 +713,6 @@ public class HttpClientTLSTest
|
|||
serverThreads.setName("server");
|
||||
server = new Server(serverThreads);
|
||||
|
||||
ArrayByteBufferPool byteBufferPool = new TestByteBufferPool();
|
||||
RetainableByteBufferPool retainableByteBufferPool = byteBufferPool.asRetainableByteBufferPool();
|
||||
server.addBean(byteBufferPool);
|
||||
HttpConfiguration httpConfig = new HttpConfiguration();
|
||||
httpConfig.addCustomizer(new SecureRequestCustomizer());
|
||||
HttpConnectionFactory http = new HttpConnectionFactory(httpConfig);
|
||||
|
@ -770,9 +721,8 @@ public class HttpClientTLSTest
|
|||
@Override
|
||||
protected SslConnection newSslConnection(Connector connector, EndPoint endPoint, SSLEngine engine)
|
||||
{
|
||||
ByteBufferPool byteBufferPool = connector.getByteBufferPool();
|
||||
RetainableByteBufferPool retainableByteBufferPool = connector.getBean(RetainableByteBufferPool.class);
|
||||
return new SslConnection(retainableByteBufferPool, byteBufferPool, connector.getExecutor(), endPoint, engine, isDirectBuffersForEncryption(), isDirectBuffersForDecryption())
|
||||
RetainableByteBufferPool bufferPool = connector.getRetainableByteBufferPool();
|
||||
return new SslConnection(bufferPool, connector.getExecutor(), endPoint, engine, isDirectBuffersForEncryption(), isDirectBuffersForDecryption())
|
||||
{
|
||||
@Override
|
||||
protected int networkFill(ByteBuffer input) throws IOException
|
||||
|
@ -803,11 +753,12 @@ public class HttpClientTLSTest
|
|||
|
||||
assertThrows(Exception.class, () -> client.newRequest("localhost", connector.getLocalPort()).scheme(HttpScheme.HTTPS.asString()).send());
|
||||
|
||||
Pool<RetainableByteBuffer> bucket = ((TestRetained)retainableByteBufferPool).poolFor(16 * 1024 + 1, connector.getConnectionFactory(HttpConnectionFactory.class).isUseInputDirectByteBuffers());
|
||||
ArrayRetainableByteBufferPool bufferPool = (ArrayRetainableByteBufferPool)server.getRetainableByteBufferPool();
|
||||
Pool<RetainableByteBuffer> bucket = bufferPool.poolFor(16 * 1024 + 1, connector.getConnectionFactory(HttpConnectionFactory.class).isUseInputDirectByteBuffers());
|
||||
assertEquals(1, bucket.size());
|
||||
assertEquals(1, bucket.getIdleCount());
|
||||
|
||||
long count = ssl.isDirectBuffersForDecryption() ? byteBufferPool.getDirectByteBufferCount() : byteBufferPool.getHeapByteBufferCount();
|
||||
long count = ssl.isDirectBuffersForDecryption() ? bufferPool.getDirectByteBufferCount() : bufferPool.getHeapByteBufferCount();
|
||||
assertEquals(1, count);
|
||||
}
|
||||
|
||||
|
@ -817,26 +768,28 @@ public class HttpClientTLSTest
|
|||
SslContextFactory.Server serverTLSFactory = createServerSslContextFactory();
|
||||
QueuedThreadPool serverThreads = new QueuedThreadPool();
|
||||
serverThreads.setName("server");
|
||||
server = new Server(serverThreads);
|
||||
List<ByteBuffer> leakedBuffers = new CopyOnWriteArrayList<>();
|
||||
ArrayByteBufferPool byteBufferPool = new ArrayByteBufferPool()
|
||||
List<RetainableByteBuffer> leakedBuffers = new CopyOnWriteArrayList<>();
|
||||
RetainableByteBufferPool bufferPool = new RetainableByteBufferPool.Wrapper(new ArrayRetainableByteBufferPool())
|
||||
{
|
||||
@Override
|
||||
public ByteBuffer acquire(int size, boolean direct)
|
||||
public RetainableByteBuffer acquire(int size, boolean direct)
|
||||
{
|
||||
ByteBuffer acquired = super.acquire(size, direct);
|
||||
leakedBuffers.add(acquired);
|
||||
return acquired;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release(ByteBuffer buffer)
|
||||
{
|
||||
leakedBuffers.remove(buffer);
|
||||
super.release(buffer);
|
||||
RetainableByteBuffer.Wrapper buffer = new RetainableByteBuffer.Wrapper(super.acquire(size, direct))
|
||||
{
|
||||
@Override
|
||||
public boolean release()
|
||||
{
|
||||
boolean released = super.release();
|
||||
if (released)
|
||||
leakedBuffers.remove(this);
|
||||
return released;
|
||||
}
|
||||
};
|
||||
leakedBuffers.add(buffer);
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
server.addBean(byteBufferPool);
|
||||
server = new Server(serverThreads, null, bufferPool);
|
||||
HttpConfiguration httpConfig = new HttpConfiguration();
|
||||
httpConfig.addCustomizer(new SecureRequestCustomizer());
|
||||
HttpConnectionFactory http = new HttpConnectionFactory(httpConfig);
|
||||
|
@ -845,9 +798,8 @@ public class HttpClientTLSTest
|
|||
@Override
|
||||
protected SslConnection newSslConnection(Connector connector, EndPoint endPoint, SSLEngine engine)
|
||||
{
|
||||
ByteBufferPool byteBufferPool = connector.getByteBufferPool();
|
||||
RetainableByteBufferPool retainableByteBufferPool = connector.getBean(RetainableByteBufferPool.class);
|
||||
return new SslConnection(retainableByteBufferPool, byteBufferPool, connector.getExecutor(), endPoint, engine, isDirectBuffersForEncryption(), isDirectBuffersForDecryption())
|
||||
RetainableByteBufferPool bufferPool = connector.getRetainableByteBufferPool();
|
||||
return new SslConnection(bufferPool, connector.getExecutor(), endPoint, engine, isDirectBuffersForEncryption(), isDirectBuffersForDecryption())
|
||||
{
|
||||
@Override
|
||||
protected boolean networkFlush(ByteBuffer output) throws IOException
|
||||
|
@ -875,7 +827,7 @@ public class HttpClientTLSTest
|
|||
|
||||
assertThrows(Exception.class, () -> client.newRequest("localhost", connector.getLocalPort()).scheme(HttpScheme.HTTPS.asString()).send());
|
||||
|
||||
byteBufferPool.asRetainableByteBufferPool().clear();
|
||||
bufferPool.clear();
|
||||
await().atMost(5, TimeUnit.SECONDS).until(() -> leakedBuffers, is(empty()));
|
||||
}
|
||||
|
||||
|
@ -886,26 +838,28 @@ public class HttpClientTLSTest
|
|||
SslContextFactory.Server serverTLSFactory = createServerSslContextFactory();
|
||||
QueuedThreadPool serverThreads = new QueuedThreadPool();
|
||||
serverThreads.setName("server");
|
||||
server = new Server(serverThreads);
|
||||
List<ByteBuffer> leakedBuffers = new CopyOnWriteArrayList<>();
|
||||
ArrayByteBufferPool byteBufferPool = new ArrayByteBufferPool()
|
||||
List<RetainableByteBuffer> leakedBuffers = new CopyOnWriteArrayList<>();
|
||||
RetainableByteBufferPool bufferPool = new RetainableByteBufferPool.Wrapper(new ArrayRetainableByteBufferPool())
|
||||
{
|
||||
@Override
|
||||
public ByteBuffer acquire(int size, boolean direct)
|
||||
public RetainableByteBuffer acquire(int size, boolean direct)
|
||||
{
|
||||
ByteBuffer acquired = super.acquire(size, direct);
|
||||
leakedBuffers.add(acquired);
|
||||
return acquired;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release(ByteBuffer buffer)
|
||||
{
|
||||
leakedBuffers.remove(buffer);
|
||||
super.release(buffer);
|
||||
RetainableByteBuffer.Wrapper buffer = new RetainableByteBuffer.Wrapper(super.acquire(size, direct))
|
||||
{
|
||||
@Override
|
||||
public boolean release()
|
||||
{
|
||||
boolean released = super.release();
|
||||
if (released)
|
||||
leakedBuffers.remove(this);
|
||||
return released;
|
||||
}
|
||||
};
|
||||
leakedBuffers.add(buffer);
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
server.addBean(byteBufferPool);
|
||||
server = new Server(serverThreads, null, bufferPool);
|
||||
HttpConfiguration httpConfig = new HttpConfiguration();
|
||||
httpConfig.addCustomizer(new SecureRequestCustomizer());
|
||||
HttpConnectionFactory http = new HttpConnectionFactory(httpConfig);
|
||||
|
@ -915,9 +869,8 @@ public class HttpClientTLSTest
|
|||
@Override
|
||||
protected SslConnection newSslConnection(Connector connector, EndPoint endPoint, SSLEngine engine)
|
||||
{
|
||||
ByteBufferPool byteBufferPool = connector.getByteBufferPool();
|
||||
RetainableByteBufferPool retainableByteBufferPool = connector.getBean(RetainableByteBufferPool.class);
|
||||
return new SslConnection(retainableByteBufferPool, byteBufferPool, connector.getExecutor(), endPoint, engine, isDirectBuffersForEncryption(), isDirectBuffersForDecryption())
|
||||
RetainableByteBufferPool bufferPool = connector.getRetainableByteBufferPool();
|
||||
return new SslConnection(bufferPool, connector.getExecutor(), endPoint, engine, isDirectBuffersForEncryption(), isDirectBuffersForDecryption())
|
||||
{
|
||||
@Override
|
||||
protected boolean networkFlush(ByteBuffer output) throws IOException
|
||||
|
@ -934,7 +887,7 @@ public class HttpClientTLSTest
|
|||
server.setHandler(new EmptyServerHandler()
|
||||
{
|
||||
@Override
|
||||
protected void service(Request request, Response response) throws Throwable
|
||||
protected void service(Request request, Response response)
|
||||
{
|
||||
failFlush.set(true);
|
||||
EndPoint endPoint = request.getConnectionMetaData().getConnection().getEndPoint();
|
||||
|
@ -959,7 +912,7 @@ public class HttpClientTLSTest
|
|||
|
||||
assertThrows(Exception.class, () -> client.newRequest("localhost", connector.getLocalPort()).scheme(HttpScheme.HTTPS.asString()).send());
|
||||
|
||||
byteBufferPool.asRetainableByteBufferPool().clear();
|
||||
bufferPool.clear();
|
||||
await().atMost(5, TimeUnit.SECONDS).until(() -> leakedBuffers, is(empty()));
|
||||
}
|
||||
|
||||
|
@ -970,26 +923,28 @@ public class HttpClientTLSTest
|
|||
SslContextFactory.Server serverTLSFactory = createServerSslContextFactory();
|
||||
QueuedThreadPool serverThreads = new QueuedThreadPool();
|
||||
serverThreads.setName("server");
|
||||
server = new Server(serverThreads);
|
||||
List<ByteBuffer> leakedBuffers = new CopyOnWriteArrayList<>();
|
||||
ArrayByteBufferPool byteBufferPool = new ArrayByteBufferPool()
|
||||
List<RetainableByteBuffer> leakedBuffers = new CopyOnWriteArrayList<>();
|
||||
RetainableByteBufferPool bufferPool = new RetainableByteBufferPool.Wrapper(new ArrayRetainableByteBufferPool())
|
||||
{
|
||||
@Override
|
||||
public ByteBuffer acquire(int size, boolean direct)
|
||||
public RetainableByteBuffer acquire(int size, boolean direct)
|
||||
{
|
||||
ByteBuffer acquired = super.acquire(size, direct);
|
||||
leakedBuffers.add(acquired);
|
||||
return acquired;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release(ByteBuffer buffer)
|
||||
{
|
||||
leakedBuffers.remove(buffer);
|
||||
super.release(buffer);
|
||||
RetainableByteBuffer.Wrapper buffer = new RetainableByteBuffer.Wrapper(super.acquire(size, direct))
|
||||
{
|
||||
@Override
|
||||
public boolean release()
|
||||
{
|
||||
boolean released = super.release();
|
||||
if (released)
|
||||
leakedBuffers.remove(this);
|
||||
return released;
|
||||
}
|
||||
};
|
||||
leakedBuffers.add(buffer);
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
server.addBean(byteBufferPool);
|
||||
server = new Server(serverThreads, null, bufferPool);
|
||||
HttpConfiguration httpConfig = new HttpConfiguration();
|
||||
httpConfig.addCustomizer(new SecureRequestCustomizer());
|
||||
HttpConnectionFactory http = new HttpConnectionFactory(httpConfig);
|
||||
|
@ -999,9 +954,8 @@ public class HttpClientTLSTest
|
|||
@Override
|
||||
protected SslConnection newSslConnection(Connector connector, EndPoint endPoint, SSLEngine engine)
|
||||
{
|
||||
ByteBufferPool byteBufferPool = connector.getByteBufferPool();
|
||||
RetainableByteBufferPool retainableByteBufferPool = connector.getBean(RetainableByteBufferPool.class);
|
||||
return new SslConnection(retainableByteBufferPool, byteBufferPool, connector.getExecutor(), endPoint, engine, isDirectBuffersForEncryption(), isDirectBuffersForDecryption())
|
||||
RetainableByteBufferPool bufferPool = connector.getRetainableByteBufferPool();
|
||||
return new SslConnection(bufferPool, connector.getExecutor(), endPoint, engine, isDirectBuffersForEncryption(), isDirectBuffersForDecryption())
|
||||
{
|
||||
@Override
|
||||
protected boolean networkFlush(ByteBuffer output) throws IOException
|
||||
|
@ -1018,7 +972,7 @@ public class HttpClientTLSTest
|
|||
server.setHandler(new EmptyServerHandler()
|
||||
{
|
||||
@Override
|
||||
protected void service(Request request, Response response) throws Throwable
|
||||
protected void service(Request request, Response response)
|
||||
{
|
||||
failFlush.set(true);
|
||||
EndPoint endPoint = request.getConnectionMetaData().getConnection().getEndPoint();
|
||||
|
@ -1043,7 +997,7 @@ public class HttpClientTLSTest
|
|||
|
||||
assertThrows(Exception.class, () -> client.newRequest("localhost", connector.getLocalPort()).scheme(HttpScheme.HTTPS.asString()).send());
|
||||
|
||||
byteBufferPool.asRetainableByteBufferPool().clear();
|
||||
bufferPool.clear();
|
||||
await().atMost(5, TimeUnit.SECONDS).until(() -> leakedBuffers, is(empty()));
|
||||
}
|
||||
|
||||
|
@ -1063,7 +1017,7 @@ public class HttpClientTLSTest
|
|||
@Override
|
||||
protected SslConnection newSslConnection(Connector connector, EndPoint endPoint, SSLEngine engine)
|
||||
{
|
||||
return new SslConnection(connector.getByteBufferPool(), connector.getExecutor(), endPoint, engine, isDirectBuffersForEncryption(), isDirectBuffersForDecryption())
|
||||
return new SslConnection(connector.getRetainableByteBufferPool(), connector.getExecutor(), endPoint, engine, isDirectBuffersForEncryption(), isDirectBuffersForDecryption())
|
||||
{
|
||||
@Override
|
||||
protected int networkFill(ByteBuffer input) throws IOException
|
||||
|
@ -1098,12 +1052,12 @@ public class HttpClientTLSTest
|
|||
{
|
||||
if (sslContextFactory == null)
|
||||
sslContextFactory = getSslContextFactory();
|
||||
return new SslClientConnectionFactory(sslContextFactory, getByteBufferPool(), getExecutor(), connectionFactory)
|
||||
return new SslClientConnectionFactory(sslContextFactory, getRetainableByteBufferPool(), getExecutor(), connectionFactory)
|
||||
{
|
||||
@Override
|
||||
protected SslConnection newSslConnection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, SSLEngine engine)
|
||||
protected SslConnection newSslConnection(RetainableByteBufferPool bufferPool, Executor executor, EndPoint endPoint, SSLEngine engine)
|
||||
{
|
||||
return new SslConnection(byteBufferPool, executor, endPoint, engine, isDirectBuffersForEncryption(), isDirectBuffersForDecryption())
|
||||
return new SslConnection(bufferPool, executor, endPoint, engine, isDirectBuffersForEncryption(), isDirectBuffersForDecryption())
|
||||
{
|
||||
@Override
|
||||
protected int networkFill(ByteBuffer input) throws IOException
|
||||
|
@ -1160,12 +1114,12 @@ public class HttpClientTLSTest
|
|||
{
|
||||
if (sslContextFactory == null)
|
||||
sslContextFactory = getSslContextFactory();
|
||||
return new SslClientConnectionFactory(sslContextFactory, getByteBufferPool(), getExecutor(), connectionFactory)
|
||||
return new SslClientConnectionFactory(sslContextFactory, getRetainableByteBufferPool(), getExecutor(), connectionFactory)
|
||||
{
|
||||
@Override
|
||||
protected SslConnection newSslConnection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, SSLEngine engine)
|
||||
protected SslConnection newSslConnection(RetainableByteBufferPool bufferPool, Executor executor, EndPoint endPoint, SSLEngine engine)
|
||||
{
|
||||
return new SslConnection(byteBufferPool, executor, endPoint, engine, isDirectBuffersForEncryption(), isDirectBuffersForDecryption())
|
||||
return new SslConnection(bufferPool, executor, endPoint, engine, isDirectBuffersForEncryption(), isDirectBuffersForDecryption())
|
||||
{
|
||||
@Override
|
||||
protected SSLEngineResult wrap(SSLEngine sslEngine, ByteBuffer[] input, ByteBuffer output) throws SSLException
|
||||
|
@ -1204,7 +1158,7 @@ public class HttpClientTLSTest
|
|||
@Override
|
||||
protected SslConnection newSslConnection(Connector connector, EndPoint endPoint, SSLEngine engine)
|
||||
{
|
||||
return new SslConnection(connector.getByteBufferPool(), connector.getExecutor(), endPoint, engine, isDirectBuffersForEncryption(), isDirectBuffersForDecryption())
|
||||
return new SslConnection(connector.getRetainableByteBufferPool(), connector.getExecutor(), endPoint, engine, isDirectBuffersForEncryption(), isDirectBuffersForDecryption())
|
||||
{
|
||||
@Override
|
||||
protected SSLEngineResult unwrap(SSLEngine sslEngine, ByteBuffer input, ByteBuffer output) throws SSLException
|
||||
|
@ -1240,12 +1194,12 @@ public class HttpClientTLSTest
|
|||
{
|
||||
if (sslContextFactory == null)
|
||||
sslContextFactory = getSslContextFactory();
|
||||
return new SslClientConnectionFactory(sslContextFactory, getByteBufferPool(), getExecutor(), connectionFactory)
|
||||
return new SslClientConnectionFactory(sslContextFactory, getRetainableByteBufferPool(), getExecutor(), connectionFactory)
|
||||
{
|
||||
@Override
|
||||
protected SslConnection newSslConnection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, SSLEngine engine)
|
||||
protected SslConnection newSslConnection(RetainableByteBufferPool bufferPool, Executor executor, EndPoint endPoint, SSLEngine engine)
|
||||
{
|
||||
return new SslConnection(byteBufferPool, executor, endPoint, engine, isDirectBuffersForEncryption(), isDirectBuffersForDecryption())
|
||||
return new SslConnection(bufferPool, executor, endPoint, engine, isDirectBuffersForEncryption(), isDirectBuffersForDecryption())
|
||||
{
|
||||
@Override
|
||||
protected SSLEngineResult wrap(SSLEngine sslEngine, ByteBuffer[] input, ByteBuffer output) throws SSLException
|
||||
|
|
|
@ -19,10 +19,10 @@ import javax.net.ssl.SSLEngine;
|
|||
import javax.net.ssl.SSLHandshakeException;
|
||||
|
||||
import org.eclipse.jetty.io.AbstractConnection;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.ByteArrayEndPoint;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.ssl.SslConnection;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
@ -43,13 +43,13 @@ public class SslConnectionTest
|
|||
sslContextFactory.setKeyStorePassword("storepwd");
|
||||
sslContextFactory.start();
|
||||
|
||||
ByteBufferPool byteBufferPool = new MappedByteBufferPool();
|
||||
RetainableByteBufferPool bufferPool = new ArrayRetainableByteBufferPool();
|
||||
QueuedThreadPool threadPool = new QueuedThreadPool();
|
||||
threadPool.start();
|
||||
ByteArrayEndPoint endPoint = new ByteArrayEndPoint();
|
||||
SSLEngine sslEngine = sslContextFactory.newSSLEngine();
|
||||
sslEngine.setUseClientMode(false);
|
||||
SslConnection sslConnection = new SslConnection(byteBufferPool, threadPool, endPoint, sslEngine);
|
||||
SslConnection sslConnection = new SslConnection(bufferPool, threadPool, endPoint, sslEngine);
|
||||
EndPoint sslEndPoint = sslConnection.getDecryptedEndPoint();
|
||||
sslEndPoint.setConnection(new AbstractConnection(sslEndPoint, threadPool)
|
||||
{
|
||||
|
|
|
@ -283,7 +283,7 @@ public class MultiPartRequestContentTest extends AbstractHttpClientServerTest
|
|||
});
|
||||
|
||||
MultiPartRequestContent multiPart = new MultiPartRequestContent();
|
||||
PathRequestContent content = new PathRequestContent(contentType, tmpPath, client.getByteBufferPool().asRetainableByteBufferPool());
|
||||
PathRequestContent content = new PathRequestContent(contentType, tmpPath, client.getRetainableByteBufferPool());
|
||||
content.setUseDirectByteBuffers(client.isUseOutputDirectByteBuffers());
|
||||
multiPart.addPart(new MultiPart.ContentSourcePart(name, tmpPath.getFileName().toString(), null, content));
|
||||
multiPart.close();
|
||||
|
|
|
@ -42,8 +42,8 @@
|
|||
<!-- Consult the javadoc of o.e.j.util.thread.QueuedThreadPool -->
|
||||
<!-- for all configuration that may be set here. -->
|
||||
<!-- =========================================================== -->
|
||||
<!-- uncomment to change type of threadpool
|
||||
<Arg name="threadpool"><New id="threadpool" class="org.eclipse.jetty.util.thread.QueuedThreadPool"/></Arg>
|
||||
<!-- uncomment to change type of thread pool
|
||||
<Arg name="threadPool"><New id="threadPool" class="org.eclipse.jetty.util.thread.QueuedThreadPool"/></Arg>
|
||||
-->
|
||||
<Get name="ThreadPool">
|
||||
<Set name="minThreads" type="int"><Property name="jetty.threadPool.minThreads" default="10"/></Set>
|
||||
|
|
|
@ -21,12 +21,13 @@ import org.eclipse.jetty.client.internal.HttpExchange;
|
|||
import org.eclipse.jetty.client.internal.HttpReceiver;
|
||||
import org.eclipse.jetty.client.internal.HttpSender;
|
||||
import org.eclipse.jetty.fcgi.generator.Flusher;
|
||||
import org.eclipse.jetty.fcgi.generator.Generator;
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.io.Content;
|
||||
import org.eclipse.jetty.io.IdleTimeout;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.Promise;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -161,9 +162,9 @@ public class HttpChannelOverFCGI extends HttpChannel
|
|||
release();
|
||||
}
|
||||
|
||||
protected void flush(Generator.Result... results)
|
||||
protected void flush(RetainableByteBufferPool.Accumulator accumulator, Callback callback)
|
||||
{
|
||||
flusher.flush(results);
|
||||
flusher.flush(accumulator, callback);
|
||||
}
|
||||
|
||||
void receive()
|
||||
|
|
|
@ -81,7 +81,7 @@ public class HttpConnectionOverFCGI extends AbstractConnection implements IConne
|
|||
this.parser = new ClientParser(new ResponseListener());
|
||||
requests.addLast(0);
|
||||
HttpClient client = destination.getHttpClient();
|
||||
this.networkByteBufferPool = client.getByteBufferPool().asRetainableByteBufferPool();
|
||||
this.networkByteBufferPool = client.getRetainableByteBufferPool();
|
||||
}
|
||||
|
||||
public HttpDestination getHttpDestination()
|
||||
|
@ -161,14 +161,14 @@ public class HttpConnectionOverFCGI extends AbstractConnection implements IConne
|
|||
{
|
||||
while (true)
|
||||
{
|
||||
if (parse(networkBuffer.getBuffer()))
|
||||
if (parse(networkBuffer.getByteBuffer()))
|
||||
return false;
|
||||
|
||||
if (networkBuffer.isRetained())
|
||||
reacquireNetworkBuffer();
|
||||
|
||||
// The networkBuffer may have been reacquired.
|
||||
int read = endPoint.fill(networkBuffer.getBuffer());
|
||||
int read = endPoint.fill(networkBuffer.getByteBuffer());
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Read {} bytes from {}", read, endPoint);
|
||||
|
||||
|
|
|
@ -26,10 +26,10 @@ import org.eclipse.jetty.client.internal.HttpSender;
|
|||
import org.eclipse.jetty.fcgi.FCGI;
|
||||
import org.eclipse.jetty.fcgi.client.transport.HttpClientTransportOverFCGI;
|
||||
import org.eclipse.jetty.fcgi.generator.ClientGenerator;
|
||||
import org.eclipse.jetty.fcgi.generator.Generator;
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.Jetty;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
|
@ -42,7 +42,7 @@ public class HttpSenderOverFCGI extends HttpSender
|
|||
{
|
||||
super(channel);
|
||||
HttpClient httpClient = channel.getHttpDestination().getHttpClient();
|
||||
this.generator = new ClientGenerator(httpClient.getByteBufferPool(), httpClient.isUseOutputDirectByteBuffers());
|
||||
this.generator = new ClientGenerator(httpClient.getRetainableByteBufferPool(), httpClient.isUseOutputDirectByteBuffers());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -98,18 +98,18 @@ public class HttpSenderOverFCGI extends HttpSender
|
|||
HttpClientTransportOverFCGI transport = (HttpClientTransportOverFCGI)getHttpChannel().getHttpDestination().getHttpClient().getTransport();
|
||||
transport.customize(request, fcgiHeaders);
|
||||
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
int id = getHttpChannel().getRequest();
|
||||
if (contentBuffer.hasRemaining() || lastContent)
|
||||
{
|
||||
Generator.Result headersResult = generator.generateRequestHeaders(id, fcgiHeaders, Callback.NOOP);
|
||||
Generator.Result contentResult = generator.generateRequestContent(id, contentBuffer, lastContent, callback);
|
||||
getHttpChannel().flush(headersResult, contentResult);
|
||||
generator.generateRequestHeaders(accumulator, id, fcgiHeaders);
|
||||
generator.generateRequestContent(accumulator, id, contentBuffer, lastContent);
|
||||
}
|
||||
else
|
||||
{
|
||||
Generator.Result headersResult = generator.generateRequestHeaders(id, fcgiHeaders, callback);
|
||||
getHttpChannel().flush(headersResult);
|
||||
generator.generateRequestHeaders(accumulator, id, fcgiHeaders);
|
||||
}
|
||||
getHttpChannel().flush(accumulator, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -117,9 +117,10 @@ public class HttpSenderOverFCGI extends HttpSender
|
|||
{
|
||||
if (contentBuffer.hasRemaining() || lastContent)
|
||||
{
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
int request = getHttpChannel().getRequest();
|
||||
Generator.Result result = generator.generateRequestContent(request, contentBuffer, lastContent, callback);
|
||||
getHttpChannel().flush(result);
|
||||
generator.generateRequestContent(accumulator, request, contentBuffer, lastContent);
|
||||
getHttpChannel().flush(accumulator, callback);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -22,9 +22,9 @@ import java.util.List;
|
|||
import org.eclipse.jetty.fcgi.FCGI;
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
|
||||
public class ClientGenerator extends Generator
|
||||
{
|
||||
|
@ -33,17 +33,17 @@ public class ClientGenerator extends Generator
|
|||
// 0x7F_FF - 4 (the 4 is to make room for the name (or value) length).
|
||||
public static final int MAX_PARAM_LENGTH = 0x7F_FF - 4;
|
||||
|
||||
public ClientGenerator(ByteBufferPool byteBufferPool)
|
||||
public ClientGenerator(RetainableByteBufferPool bufferPool)
|
||||
{
|
||||
this(byteBufferPool, true);
|
||||
this(bufferPool, true);
|
||||
}
|
||||
|
||||
public ClientGenerator(ByteBufferPool byteBufferPool, boolean useDirectByteBuffers)
|
||||
public ClientGenerator(RetainableByteBufferPool bufferPool, boolean useDirectByteBuffers)
|
||||
{
|
||||
super(byteBufferPool, useDirectByteBuffers);
|
||||
super(bufferPool, useDirectByteBuffers);
|
||||
}
|
||||
|
||||
public Result generateRequestHeaders(int request, HttpFields fields, Callback callback)
|
||||
public void generateRequestHeaders(RetainableByteBufferPool.Accumulator accumulator, int request, HttpFields fields)
|
||||
{
|
||||
request &= 0xFF_FF;
|
||||
|
||||
|
@ -79,30 +79,31 @@ public class ClientGenerator extends Generator
|
|||
|
||||
// One FCGI_BEGIN_REQUEST + N FCGI_PARAMS + one last FCGI_PARAMS
|
||||
|
||||
ByteBuffer beginRequestBuffer = acquire(16);
|
||||
BufferUtil.clearToFill(beginRequestBuffer);
|
||||
Result result = new Result(getByteBufferPool(), callback);
|
||||
result = result.append(beginRequestBuffer, true);
|
||||
RetainableByteBuffer beginBuffer = getRetainableByteBufferPool().acquire(16, isUseDirectByteBuffers());
|
||||
accumulator.append(beginBuffer);
|
||||
ByteBuffer beginByteBuffer = beginBuffer.getByteBuffer();
|
||||
BufferUtil.clearToFill(beginByteBuffer);
|
||||
|
||||
// Generate the FCGI_BEGIN_REQUEST frame
|
||||
beginRequestBuffer.putInt(0x01_01_00_00 + request);
|
||||
beginRequestBuffer.putInt(0x00_08_00_00);
|
||||
beginByteBuffer.putInt(0x01_01_00_00 + request);
|
||||
beginByteBuffer.putInt(0x00_08_00_00);
|
||||
// Hardcode RESPONDER role and KEEP_ALIVE flag
|
||||
beginRequestBuffer.putLong(0x00_01_01_00_00_00_00_00L);
|
||||
BufferUtil.flipToFlush(beginRequestBuffer, 0);
|
||||
beginByteBuffer.putLong(0x00_01_01_00_00_00_00_00L);
|
||||
BufferUtil.flipToFlush(beginByteBuffer, 0);
|
||||
|
||||
int index = 0;
|
||||
while (fieldsLength > 0)
|
||||
{
|
||||
int capacity = 8 + Math.min(maxCapacity, fieldsLength);
|
||||
ByteBuffer buffer = acquire(capacity);
|
||||
BufferUtil.clearToFill(buffer);
|
||||
result = result.append(buffer, true);
|
||||
RetainableByteBuffer buffer = getRetainableByteBufferPool().acquire(capacity, isUseDirectByteBuffers());
|
||||
accumulator.append(buffer);
|
||||
ByteBuffer byteBuffer = buffer.getByteBuffer();
|
||||
BufferUtil.clearToFill(byteBuffer);
|
||||
|
||||
// Generate the FCGI_PARAMS frame
|
||||
buffer.putInt(0x01_04_00_00 + request);
|
||||
buffer.putShort((short)0);
|
||||
buffer.putShort((short)0);
|
||||
byteBuffer.putInt(0x01_04_00_00 + request);
|
||||
byteBuffer.putShort((short)0);
|
||||
byteBuffer.putShort((short)0);
|
||||
capacity -= 8;
|
||||
|
||||
int length = 0;
|
||||
|
@ -117,10 +118,10 @@ public class ClientGenerator extends Generator
|
|||
if (required > capacity)
|
||||
break;
|
||||
|
||||
putParamLength(buffer, nameLength);
|
||||
putParamLength(buffer, valueLength);
|
||||
buffer.put(nameBytes);
|
||||
buffer.put(valueBytes);
|
||||
putParamLength(byteBuffer, nameLength);
|
||||
putParamLength(byteBuffer, valueLength);
|
||||
byteBuffer.put(nameBytes);
|
||||
byteBuffer.put(valueBytes);
|
||||
|
||||
length += required;
|
||||
fieldsLength -= required;
|
||||
|
@ -128,20 +129,19 @@ public class ClientGenerator extends Generator
|
|||
index += 2;
|
||||
}
|
||||
|
||||
buffer.putShort(4, (short)length);
|
||||
BufferUtil.flipToFlush(buffer, 0);
|
||||
byteBuffer.putShort(4, (short)length);
|
||||
BufferUtil.flipToFlush(byteBuffer, 0);
|
||||
}
|
||||
|
||||
ByteBuffer lastParamsBuffer = acquire(8);
|
||||
BufferUtil.clearToFill(lastParamsBuffer);
|
||||
result = result.append(lastParamsBuffer, true);
|
||||
RetainableByteBuffer lastBuffer = getRetainableByteBufferPool().acquire(8, isUseDirectByteBuffers());
|
||||
accumulator.append(lastBuffer);
|
||||
ByteBuffer lastByteBuffer = lastBuffer.getByteBuffer();
|
||||
BufferUtil.clearToFill(lastByteBuffer);
|
||||
|
||||
// Generate the last FCGI_PARAMS frame
|
||||
lastParamsBuffer.putInt(0x01_04_00_00 + request);
|
||||
lastParamsBuffer.putInt(0x00_00_00_00);
|
||||
BufferUtil.flipToFlush(lastParamsBuffer, 0);
|
||||
|
||||
return result;
|
||||
lastByteBuffer.putInt(0x01_04_00_00 + request);
|
||||
lastByteBuffer.putInt(0x00_00_00_00);
|
||||
BufferUtil.flipToFlush(lastByteBuffer, 0);
|
||||
}
|
||||
|
||||
private int putParamLength(ByteBuffer buffer, int length)
|
||||
|
@ -159,8 +159,8 @@ public class ClientGenerator extends Generator
|
|||
return length > 127 ? 4 : 1;
|
||||
}
|
||||
|
||||
public Result generateRequestContent(int request, ByteBuffer content, boolean lastContent, Callback callback)
|
||||
public void generateRequestContent(RetainableByteBufferPool.Accumulator accumulator, int request, ByteBuffer content, boolean lastContent)
|
||||
{
|
||||
return generateContent(request, content, false, lastContent, callback, FCGI.FrameType.STDIN);
|
||||
generateContent(accumulator, request, content, lastContent, FCGI.FrameType.STDIN);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,9 +15,12 @@ package org.eclipse.jetty.fcgi.generator;
|
|||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.IteratingCallback;
|
||||
import org.eclipse.jetty.util.thread.AutoLock;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -28,7 +31,7 @@ public class Flusher
|
|||
private static final Logger LOG = LoggerFactory.getLogger(Flusher.class);
|
||||
|
||||
private final AutoLock lock = new AutoLock();
|
||||
private final Queue<Generator.Result> queue = new ArrayDeque<>();
|
||||
private final Queue<Entry> queue = new ArrayDeque<>();
|
||||
private final IteratingCallback flushCallback = new FlushCallback();
|
||||
private final EndPoint endPoint;
|
||||
|
||||
|
@ -37,24 +40,21 @@ public class Flusher
|
|||
this.endPoint = endPoint;
|
||||
}
|
||||
|
||||
public void flush(Generator.Result... results)
|
||||
public void flush(RetainableByteBufferPool.Accumulator accumulator, Callback callback)
|
||||
{
|
||||
for (Generator.Result result : results)
|
||||
{
|
||||
offer(result);
|
||||
}
|
||||
offer(new Entry(accumulator, callback));
|
||||
flushCallback.iterate();
|
||||
}
|
||||
|
||||
private void offer(Generator.Result result)
|
||||
private void offer(Entry entry)
|
||||
{
|
||||
try (AutoLock ignored = lock.lock())
|
||||
{
|
||||
queue.offer(result);
|
||||
queue.offer(entry);
|
||||
}
|
||||
}
|
||||
|
||||
private Generator.Result poll()
|
||||
private Entry poll()
|
||||
{
|
||||
try (AutoLock ignored = lock.lock())
|
||||
{
|
||||
|
@ -64,35 +64,32 @@ public class Flusher
|
|||
|
||||
public void shutdown()
|
||||
{
|
||||
flush(new ShutdownResult());
|
||||
flush(null, Callback.from(() ->
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Shutting down {}", endPoint);
|
||||
endPoint.shutdownOutput();
|
||||
}));
|
||||
}
|
||||
|
||||
private class FlushCallback extends IteratingCallback
|
||||
{
|
||||
private Generator.Result active;
|
||||
private Entry active;
|
||||
|
||||
@Override
|
||||
protected Action process() throws Exception
|
||||
{
|
||||
// Look if other writes are needed.
|
||||
Generator.Result result = poll();
|
||||
if (result == null)
|
||||
Entry entry = poll();
|
||||
if (entry == null)
|
||||
{
|
||||
// No more writes to do, return.
|
||||
return Action.IDLE;
|
||||
}
|
||||
|
||||
// Attempt to gather another result.
|
||||
// Most often there is another result in the
|
||||
// queue so this is a real optimization because
|
||||
// it sends both results in just one TCP packet.
|
||||
Generator.Result other = poll();
|
||||
if (other != null)
|
||||
result = result.join(other);
|
||||
|
||||
active = result;
|
||||
ByteBuffer[] buffers = result.getByteBuffers();
|
||||
endPoint.write(this, buffers);
|
||||
active = entry;
|
||||
List<ByteBuffer> buffers = entry.accumulator.getByteBuffers();
|
||||
endPoint.write(this, buffers.toArray(ByteBuffer[]::new));
|
||||
return Action.SCHEDULED;
|
||||
}
|
||||
|
||||
|
@ -121,38 +118,30 @@ public class Flusher
|
|||
|
||||
while (true)
|
||||
{
|
||||
Generator.Result result = poll();
|
||||
if (result == null)
|
||||
Entry entry = poll();
|
||||
if (entry == null)
|
||||
break;
|
||||
result.failed(x);
|
||||
entry.failed(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ShutdownResult extends Generator.Result
|
||||
private record Entry(RetainableByteBufferPool.Accumulator accumulator, Callback callback) implements Callback
|
||||
{
|
||||
private ShutdownResult()
|
||||
{
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void succeeded()
|
||||
{
|
||||
shutdown();
|
||||
if (accumulator != null)
|
||||
accumulator.release();
|
||||
callback.succeeded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Throwable x)
|
||||
{
|
||||
shutdown();
|
||||
}
|
||||
|
||||
private void shutdown()
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Shutting down {}", endPoint);
|
||||
endPoint.shutdownOutput();
|
||||
if (accumulator != null)
|
||||
accumulator.release();
|
||||
callback.failed(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,150 +14,69 @@
|
|||
package org.eclipse.jetty.fcgi.generator;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.fcgi.FCGI;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
|
||||
public class Generator
|
||||
{
|
||||
public static final int MAX_CONTENT_LENGTH = 0xFF_FF;
|
||||
|
||||
private final ByteBufferPool byteBufferPool;
|
||||
private final RetainableByteBufferPool bufferPool;
|
||||
private final boolean useDirectByteBuffers;
|
||||
|
||||
public Generator(ByteBufferPool byteBufferPool, boolean useDirectByteBuffers)
|
||||
public Generator(RetainableByteBufferPool bufferPool, boolean useDirectByteBuffers)
|
||||
{
|
||||
this.byteBufferPool = byteBufferPool;
|
||||
this.bufferPool = bufferPool;
|
||||
this.useDirectByteBuffers = useDirectByteBuffers;
|
||||
}
|
||||
|
||||
ByteBufferPool getByteBufferPool()
|
||||
public RetainableByteBufferPool getRetainableByteBufferPool()
|
||||
{
|
||||
return byteBufferPool;
|
||||
return bufferPool;
|
||||
}
|
||||
|
||||
ByteBuffer acquire(int capacity)
|
||||
public boolean isUseDirectByteBuffers()
|
||||
{
|
||||
return byteBufferPool.acquire(capacity, useDirectByteBuffers);
|
||||
return useDirectByteBuffers;
|
||||
}
|
||||
|
||||
protected Result generateContent(int id, ByteBuffer content, boolean recycle, boolean lastContent, Callback callback, FCGI.FrameType frameType)
|
||||
protected void generateContent(RetainableByteBufferPool.Accumulator accumulator, int id, ByteBuffer content, boolean lastContent, FCGI.FrameType frameType)
|
||||
{
|
||||
id &= 0xFF_FF;
|
||||
|
||||
int contentLength = content == null ? 0 : content.remaining();
|
||||
Result result = new Result(byteBufferPool, callback);
|
||||
|
||||
while (contentLength > 0 || lastContent)
|
||||
{
|
||||
ByteBuffer buffer = acquire(8);
|
||||
BufferUtil.clearToFill(buffer);
|
||||
result = result.append(buffer, true);
|
||||
RetainableByteBuffer buffer = getRetainableByteBufferPool().acquire(8, isUseDirectByteBuffers());
|
||||
accumulator.append(buffer);
|
||||
ByteBuffer byteBuffer = buffer.getByteBuffer();
|
||||
BufferUtil.clearToFill(byteBuffer);
|
||||
|
||||
// Generate the frame header
|
||||
buffer.put((byte)0x01);
|
||||
buffer.put((byte)frameType.code);
|
||||
buffer.putShort((short)id);
|
||||
// Generate the frame header.
|
||||
byteBuffer.put((byte)0x01);
|
||||
byteBuffer.put((byte)frameType.code);
|
||||
byteBuffer.putShort((short)id);
|
||||
int length = Math.min(MAX_CONTENT_LENGTH, contentLength);
|
||||
buffer.putShort((short)length);
|
||||
buffer.putShort((short)0);
|
||||
BufferUtil.flipToFlush(buffer, 0);
|
||||
byteBuffer.putShort((short)length);
|
||||
byteBuffer.putShort((short)0);
|
||||
BufferUtil.flipToFlush(byteBuffer, 0);
|
||||
|
||||
if (contentLength == 0)
|
||||
break;
|
||||
|
||||
// Slice the content to avoid copying
|
||||
// Slice the content to avoid copying.
|
||||
int limit = content.limit();
|
||||
content.limit(content.position() + length);
|
||||
ByteBuffer slice = content.slice();
|
||||
// Don't recycle the slice
|
||||
result = result.append(slice, false);
|
||||
// Don't recycle the slice.
|
||||
accumulator.append(RetainableByteBuffer.wrap(slice));
|
||||
content.position(content.limit());
|
||||
content.limit(limit);
|
||||
contentLength -= length;
|
||||
// Recycle the content buffer if needed
|
||||
if (recycle && contentLength == 0)
|
||||
result = result.append(content, true);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO: rewrite this class in light of ByteBufferPool.Lease.
|
||||
public static class Result implements Callback
|
||||
{
|
||||
private final List<Callback> callbacks = new ArrayList<>(2);
|
||||
private final List<ByteBuffer> buffers = new ArrayList<>(8);
|
||||
private final List<Boolean> recycles = new ArrayList<>(8);
|
||||
private final ByteBufferPool byteBufferPool;
|
||||
|
||||
public Result(ByteBufferPool byteBufferPool, Callback callback)
|
||||
{
|
||||
this.byteBufferPool = byteBufferPool;
|
||||
this.callbacks.add(callback);
|
||||
}
|
||||
|
||||
public Result append(ByteBuffer buffer, boolean recycle)
|
||||
{
|
||||
if (buffer != null)
|
||||
{
|
||||
buffers.add(buffer);
|
||||
recycles.add(recycle);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Result join(Result that)
|
||||
{
|
||||
callbacks.addAll(that.callbacks);
|
||||
buffers.addAll(that.buffers);
|
||||
recycles.addAll(that.recycles);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ByteBuffer[] getByteBuffers()
|
||||
{
|
||||
return buffers.toArray(new ByteBuffer[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("ForLoopReplaceableByForEach")
|
||||
public void succeeded()
|
||||
{
|
||||
recycle();
|
||||
for (int i = 0; i < callbacks.size(); ++i)
|
||||
{
|
||||
Callback callback = callbacks.get(i);
|
||||
if (callback != null)
|
||||
callback.succeeded();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("ForLoopReplaceableByForEach")
|
||||
public void failed(Throwable x)
|
||||
{
|
||||
recycle();
|
||||
for (int i = 0; i < callbacks.size(); ++i)
|
||||
{
|
||||
Callback callback = callbacks.get(i);
|
||||
if (callback != null)
|
||||
callback.failed(x);
|
||||
}
|
||||
}
|
||||
|
||||
protected void recycle()
|
||||
{
|
||||
for (int i = 0; i < buffers.size(); ++i)
|
||||
{
|
||||
ByteBuffer buffer = buffers.get(i);
|
||||
if (recycles.get(i))
|
||||
byteBufferPool.release(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,9 +23,9 @@ import org.eclipse.jetty.fcgi.FCGI;
|
|||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
|
||||
public class ServerGenerator extends Generator
|
||||
{
|
||||
|
@ -35,18 +35,18 @@ public class ServerGenerator extends Generator
|
|||
|
||||
private final boolean sendStatus200;
|
||||
|
||||
public ServerGenerator(ByteBufferPool byteBufferPool)
|
||||
public ServerGenerator(RetainableByteBufferPool bufferPool)
|
||||
{
|
||||
this(byteBufferPool, true, true);
|
||||
this(bufferPool, true, true);
|
||||
}
|
||||
|
||||
public ServerGenerator(ByteBufferPool byteBufferPool, boolean useDirectByteBuffers, boolean sendStatus200)
|
||||
public ServerGenerator(RetainableByteBufferPool bufferPool, boolean useDirectByteBuffers, boolean sendStatus200)
|
||||
{
|
||||
super(byteBufferPool, useDirectByteBuffers);
|
||||
super(bufferPool, useDirectByteBuffers);
|
||||
this.sendStatus200 = sendStatus200;
|
||||
}
|
||||
|
||||
public Result generateResponseHeaders(int request, int code, String reason, HttpFields fields, Callback callback)
|
||||
public void generateResponseHeaders(RetainableByteBufferPool.Accumulator accumulator, int request, int code, String reason, HttpFields fields)
|
||||
{
|
||||
request &= 0xFF_FF;
|
||||
|
||||
|
@ -83,50 +83,48 @@ public class ServerGenerator extends Generator
|
|||
// End of headers
|
||||
length += EOL.length;
|
||||
|
||||
ByteBuffer buffer = acquire(length);
|
||||
BufferUtil.clearToFill(buffer);
|
||||
ByteBuffer byteBuffer = BufferUtil.allocate(length, isUseDirectByteBuffers());
|
||||
BufferUtil.clearToFill(byteBuffer);
|
||||
|
||||
for (int i = 0; i < bytes.size(); i += 2)
|
||||
{
|
||||
buffer.put(bytes.get(i)).put(COLON).put(bytes.get(i + 1)).put(EOL);
|
||||
byteBuffer.put(bytes.get(i)).put(COLON).put(bytes.get(i + 1)).put(EOL);
|
||||
}
|
||||
buffer.put(EOL);
|
||||
byteBuffer.put(EOL);
|
||||
|
||||
BufferUtil.flipToFlush(buffer, 0);
|
||||
BufferUtil.flipToFlush(byteBuffer, 0);
|
||||
|
||||
return generateContent(request, buffer, true, false, callback, FCGI.FrameType.STDOUT);
|
||||
generateContent(accumulator, request, byteBuffer, false, FCGI.FrameType.STDOUT);
|
||||
}
|
||||
|
||||
public Result generateResponseContent(int request, ByteBuffer content, boolean lastContent, boolean aborted, Callback callback)
|
||||
public void generateResponseContent(RetainableByteBufferPool.Accumulator accumulator, int request, ByteBuffer content, boolean lastContent, boolean aborted)
|
||||
{
|
||||
if (aborted)
|
||||
{
|
||||
Result result = new Result(getByteBufferPool(), callback);
|
||||
if (lastContent)
|
||||
result.append(generateEndRequest(request, true), true);
|
||||
accumulator.append(generateEndRequest(request, true));
|
||||
else
|
||||
result.append(BufferUtil.EMPTY_BUFFER, false);
|
||||
return result;
|
||||
accumulator.append(RetainableByteBuffer.wrap(BufferUtil.EMPTY_BUFFER));
|
||||
}
|
||||
else
|
||||
{
|
||||
Result result = generateContent(request, content, false, lastContent, callback, FCGI.FrameType.STDOUT);
|
||||
generateContent(accumulator, request, content, lastContent, FCGI.FrameType.STDOUT);
|
||||
if (lastContent)
|
||||
result.append(generateEndRequest(request, false), true);
|
||||
return result;
|
||||
accumulator.append(generateEndRequest(request, false));
|
||||
}
|
||||
}
|
||||
|
||||
private ByteBuffer generateEndRequest(int request, boolean aborted)
|
||||
private RetainableByteBuffer generateEndRequest(int request, boolean aborted)
|
||||
{
|
||||
request &= 0xFF_FF;
|
||||
ByteBuffer endRequestBuffer = acquire(16);
|
||||
BufferUtil.clearToFill(endRequestBuffer);
|
||||
endRequestBuffer.putInt(0x01_03_00_00 + request);
|
||||
endRequestBuffer.putInt(0x00_08_00_00);
|
||||
endRequestBuffer.putInt(aborted ? 1 : 0);
|
||||
endRequestBuffer.putInt(0);
|
||||
BufferUtil.flipToFlush(endRequestBuffer, 0);
|
||||
RetainableByteBuffer endRequestBuffer = getRetainableByteBufferPool().acquire(16, isUseDirectByteBuffers());
|
||||
ByteBuffer byteBuffer = endRequestBuffer.getByteBuffer();
|
||||
BufferUtil.clearToFill(byteBuffer);
|
||||
byteBuffer.putInt(0x01_03_00_00 + request);
|
||||
byteBuffer.putInt(0x00_08_00_00);
|
||||
byteBuffer.putInt(aborted ? 1 : 0);
|
||||
byteBuffer.putInt(0);
|
||||
BufferUtil.flipToFlush(byteBuffer, 0);
|
||||
return endRequestBuffer;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,8 @@ import org.eclipse.jetty.fcgi.FCGI;
|
|||
import org.eclipse.jetty.fcgi.parser.ServerParser;
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
@ -31,50 +31,51 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
|
|||
public class ClientGeneratorTest
|
||||
{
|
||||
@Test
|
||||
public void testGenerateRequestHeaders() throws Exception
|
||||
public void testGenerateRequestHeaders()
|
||||
{
|
||||
HttpFields.Mutable fields = HttpFields.build();
|
||||
|
||||
// Short name, short value
|
||||
final String shortShortName = "REQUEST_METHOD";
|
||||
final String shortShortValue = "GET";
|
||||
String shortShortValue = "GET";
|
||||
fields.put(new HttpField(shortShortName, shortShortValue));
|
||||
|
||||
// Short name, long value
|
||||
final String shortLongName = "REQUEST_URI";
|
||||
// Be sure it's longer than 127 chars to test the large value
|
||||
final String shortLongValue = "/api/0.6/map?bbox=-64.217736,-31.456810,-64.187736,-31.432322,filler=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
||||
String shortLongValue = "/api/0.6/map?bbox=-64.217736,-31.456810,-64.187736,-31.432322,filler=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
||||
fields.put(new HttpField(shortLongName, shortLongValue));
|
||||
|
||||
// Long name, short value
|
||||
// Be sure it's longer than 127 chars to test the large name
|
||||
final String longShortName = "FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210";
|
||||
final String longShortValue = "api.openstreetmap.org";
|
||||
String longShortValue = "api.openstreetmap.org";
|
||||
fields.put(new HttpField(longShortName, longShortValue));
|
||||
|
||||
// Long name, long value
|
||||
char[] chars = new char[ClientGenerator.MAX_PARAM_LENGTH];
|
||||
Arrays.fill(chars, 'z');
|
||||
final String longLongName = new String(chars);
|
||||
final String longLongValue = new String(chars);
|
||||
String longLongName = new String(chars);
|
||||
String longLongValue = new String(chars);
|
||||
fields.put(new HttpField(longLongName, longLongValue));
|
||||
|
||||
ByteBufferPool byteBufferPool = new MappedByteBufferPool();
|
||||
ClientGenerator generator = new ClientGenerator(byteBufferPool);
|
||||
final int id = 13;
|
||||
Generator.Result result = generator.generateRequestHeaders(id, fields, null);
|
||||
RetainableByteBufferPool bufferPool = new ArrayRetainableByteBufferPool();
|
||||
ClientGenerator generator = new ClientGenerator(bufferPool);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
int id = 13;
|
||||
generator.generateRequestHeaders(accumulator, id, fields);
|
||||
|
||||
// Use the fundamental theorem of arithmetic to test the results.
|
||||
// This way we know onHeader() has been called the right number of
|
||||
// times with the right arguments, and so onHeaders().
|
||||
final int[] primes = new int[]{2, 3, 5, 7, 11};
|
||||
int[] primes = new int[]{2, 3, 5, 7, 11};
|
||||
int value = 1;
|
||||
for (int prime : primes)
|
||||
{
|
||||
value *= prime;
|
||||
}
|
||||
|
||||
final AtomicInteger params = new AtomicInteger(1);
|
||||
AtomicInteger params = new AtomicInteger(1);
|
||||
ServerParser parser = new ServerParser(new ServerParser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
|
@ -83,23 +84,27 @@ public class ClientGeneratorTest
|
|||
assertEquals(id, request);
|
||||
switch (field.getName())
|
||||
{
|
||||
case shortShortName:
|
||||
case shortShortName ->
|
||||
{
|
||||
assertEquals(shortShortValue, field.getValue());
|
||||
params.set(params.get() * primes[0]);
|
||||
break;
|
||||
case shortLongName:
|
||||
}
|
||||
case shortLongName ->
|
||||
{
|
||||
assertEquals(shortLongValue, field.getValue());
|
||||
params.set(params.get() * primes[1]);
|
||||
break;
|
||||
case longShortName:
|
||||
}
|
||||
case longShortName ->
|
||||
{
|
||||
assertEquals(longShortValue, field.getValue());
|
||||
params.set(params.get() * primes[2]);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
default ->
|
||||
{
|
||||
assertEquals(longLongName, field.getName());
|
||||
assertEquals(longLongValue, field.getValue());
|
||||
params.set(params.get() * primes[3]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,7 +117,7 @@ public class ClientGeneratorTest
|
|||
}
|
||||
});
|
||||
|
||||
for (ByteBuffer buffer : result.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
parser.parse(buffer);
|
||||
assertFalse(buffer.hasRemaining());
|
||||
|
@ -122,17 +127,18 @@ public class ClientGeneratorTest
|
|||
|
||||
// Parse again byte by byte
|
||||
params.set(1);
|
||||
for (ByteBuffer buffer : result.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
buffer.flip();
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
parser.parse(ByteBuffer.wrap(new byte[]{buffer.get()}));
|
||||
}
|
||||
assertFalse(buffer.hasRemaining());
|
||||
}
|
||||
|
||||
assertEquals(value, params.get());
|
||||
|
||||
accumulator.release();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -147,16 +153,17 @@ public class ClientGeneratorTest
|
|||
testGenerateRequestContent(128 * 1024);
|
||||
}
|
||||
|
||||
private void testGenerateRequestContent(final int contentLength) throws Exception
|
||||
private void testGenerateRequestContent(int contentLength) throws Exception
|
||||
{
|
||||
ByteBuffer content = ByteBuffer.allocate(contentLength);
|
||||
|
||||
ByteBufferPool byteBufferPool = new MappedByteBufferPool();
|
||||
ClientGenerator generator = new ClientGenerator(byteBufferPool);
|
||||
final int id = 13;
|
||||
Generator.Result result = generator.generateRequestContent(id, content, true, null);
|
||||
RetainableByteBufferPool bufferPool = new ArrayRetainableByteBufferPool();
|
||||
ClientGenerator generator = new ClientGenerator(bufferPool);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
int id = 13;
|
||||
generator.generateRequestContent(accumulator, id, content, true);
|
||||
|
||||
final AtomicInteger totalLength = new AtomicInteger();
|
||||
AtomicInteger totalLength = new AtomicInteger();
|
||||
ServerParser parser = new ServerParser(new ServerParser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
|
@ -175,21 +182,22 @@ public class ClientGeneratorTest
|
|||
}
|
||||
});
|
||||
|
||||
for (ByteBuffer buffer : result.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
parser.parse(buffer);
|
||||
assertFalse(buffer.hasRemaining());
|
||||
}
|
||||
|
||||
// Parse again one byte at a time
|
||||
for (ByteBuffer buffer : result.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
buffer.flip();
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
parser.parse(ByteBuffer.wrap(new byte[]{buffer.get()}));
|
||||
}
|
||||
assertFalse(buffer.hasRemaining());
|
||||
}
|
||||
|
||||
accumulator.release();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,12 +19,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.eclipse.jetty.fcgi.FCGI;
|
||||
import org.eclipse.jetty.fcgi.generator.Generator;
|
||||
import org.eclipse.jetty.fcgi.generator.ServerGenerator;
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
@ -34,32 +33,33 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
public class ClientParserTest
|
||||
{
|
||||
@Test
|
||||
public void testParseResponseHeaders() throws Exception
|
||||
public void testParseResponseHeaders()
|
||||
{
|
||||
final int id = 13;
|
||||
int id = 13;
|
||||
HttpFields.Mutable fields = HttpFields.build();
|
||||
|
||||
final int statusCode = 200;
|
||||
final String statusMessage = "OK";
|
||||
final String contentTypeName = "Content-Type";
|
||||
final String contentTypeValue = "text/html;charset=utf-8";
|
||||
int statusCode = 200;
|
||||
String statusMessage = "OK";
|
||||
String contentTypeName = "Content-Type";
|
||||
String contentTypeValue = "text/html;charset=utf-8";
|
||||
fields.put(contentTypeName, contentTypeValue);
|
||||
|
||||
ByteBufferPool byteBufferPool = new MappedByteBufferPool();
|
||||
ServerGenerator generator = new ServerGenerator(byteBufferPool);
|
||||
Generator.Result result = generator.generateResponseHeaders(id, statusCode, statusMessage, fields, null);
|
||||
RetainableByteBufferPool bufferPool = new ArrayRetainableByteBufferPool();
|
||||
ServerGenerator generator = new ServerGenerator(bufferPool);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.generateResponseHeaders(accumulator, id, statusCode, statusMessage, fields);
|
||||
|
||||
// Use the fundamental theorem of arithmetic to test the results.
|
||||
// This way we know onHeader() has been called the right number of
|
||||
// times with the right arguments, and so onHeaders().
|
||||
final int[] primes = new int[]{2, 3, 5};
|
||||
int[] primes = new int[]{2, 3, 5};
|
||||
int value = 1;
|
||||
for (int prime : primes)
|
||||
{
|
||||
value *= prime;
|
||||
}
|
||||
|
||||
final AtomicInteger params = new AtomicInteger(1);
|
||||
AtomicInteger params = new AtomicInteger(1);
|
||||
ClientParser parser = new ClientParser(new ClientParser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
|
@ -74,14 +74,10 @@ public class ClientParserTest
|
|||
public void onHeader(int request, HttpField field)
|
||||
{
|
||||
assertEquals(id, request);
|
||||
switch (field.getName())
|
||||
if (field.getName().equals(contentTypeName))
|
||||
{
|
||||
case contentTypeName:
|
||||
assertEquals(contentTypeValue, field.getValue().toLowerCase(Locale.ENGLISH));
|
||||
params.set(params.get() * primes[1]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
assertEquals(contentTypeValue, field.getValue().toLowerCase(Locale.ENGLISH));
|
||||
params.set(params.get() * primes[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,28 +90,31 @@ public class ClientParserTest
|
|||
}
|
||||
});
|
||||
|
||||
for (ByteBuffer buffer : result.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
parser.parse(buffer);
|
||||
assertFalse(buffer.hasRemaining());
|
||||
}
|
||||
|
||||
assertEquals(value, params.get());
|
||||
|
||||
accumulator.release();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseNoResponseContent() throws Exception
|
||||
{
|
||||
final int id = 13;
|
||||
int id = 13;
|
||||
HttpFields fields = HttpFields.build()
|
||||
.put("Content-Length", "0");
|
||||
|
||||
ByteBufferPool byteBufferPool = new MappedByteBufferPool();
|
||||
ServerGenerator generator = new ServerGenerator(byteBufferPool);
|
||||
Generator.Result result1 = generator.generateResponseHeaders(id, 200, "OK", fields, null);
|
||||
Generator.Result result2 = generator.generateResponseContent(id, null, true, false, null);
|
||||
RetainableByteBufferPool bufferPool = new ArrayRetainableByteBufferPool();
|
||||
ServerGenerator generator = new ServerGenerator(bufferPool);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.generateResponseHeaders(accumulator, id, 200, "OK", fields);
|
||||
generator.generateResponseContent(accumulator, id, null, true, false);
|
||||
|
||||
final AtomicInteger verifier = new AtomicInteger();
|
||||
AtomicInteger verifier = new AtomicInteger();
|
||||
ClientParser parser = new ClientParser(new ClientParser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
|
@ -134,40 +133,38 @@ public class ClientParserTest
|
|||
}
|
||||
});
|
||||
|
||||
for (ByteBuffer buffer : result1.getByteBuffers())
|
||||
{
|
||||
parser.parse(buffer);
|
||||
assertFalse(buffer.hasRemaining());
|
||||
}
|
||||
for (ByteBuffer buffer : result2.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
parser.parse(buffer);
|
||||
assertFalse(buffer.hasRemaining());
|
||||
}
|
||||
|
||||
assertEquals(3, verifier.get());
|
||||
|
||||
accumulator.release();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseSmallResponseContent() throws Exception
|
||||
{
|
||||
final int id = 13;
|
||||
int id = 13;
|
||||
HttpFields.Mutable fields = HttpFields.build();
|
||||
|
||||
ByteBuffer content = ByteBuffer.wrap(new byte[1024]);
|
||||
final int contentLength = content.remaining();
|
||||
int contentLength = content.remaining();
|
||||
|
||||
final int code = 200;
|
||||
final String contentTypeName = "Content-Length";
|
||||
final String contentTypeValue = String.valueOf(contentLength);
|
||||
int code = 200;
|
||||
String contentTypeName = "Content-Length";
|
||||
String contentTypeValue = String.valueOf(contentLength);
|
||||
fields.put(contentTypeName, contentTypeValue);
|
||||
|
||||
ByteBufferPool byteBufferPool = new MappedByteBufferPool();
|
||||
ServerGenerator generator = new ServerGenerator(byteBufferPool);
|
||||
Generator.Result result1 = generator.generateResponseHeaders(id, code, "OK", fields, null);
|
||||
Generator.Result result2 = generator.generateResponseContent(id, content, true, false, null);
|
||||
RetainableByteBufferPool bufferPool = new ArrayRetainableByteBufferPool();
|
||||
ServerGenerator generator = new ServerGenerator(bufferPool);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.generateResponseHeaders(accumulator, id, code, "OK", fields);
|
||||
generator.generateResponseContent(accumulator, id, content, true, false);
|
||||
|
||||
final AtomicInteger verifier = new AtomicInteger();
|
||||
AtomicInteger verifier = new AtomicInteger();
|
||||
ClientParser parser = new ClientParser(new ClientParser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
|
@ -187,41 +184,39 @@ public class ClientParserTest
|
|||
}
|
||||
});
|
||||
|
||||
for (ByteBuffer buffer : result1.getByteBuffers())
|
||||
{
|
||||
parser.parse(buffer);
|
||||
assertFalse(buffer.hasRemaining());
|
||||
}
|
||||
for (ByteBuffer buffer : result2.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
parser.parse(buffer);
|
||||
assertFalse(buffer.hasRemaining());
|
||||
}
|
||||
|
||||
assertEquals(5, verifier.get());
|
||||
|
||||
accumulator.release();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseLargeResponseContent() throws Exception
|
||||
{
|
||||
final int id = 13;
|
||||
int id = 13;
|
||||
HttpFields.Mutable fields = HttpFields.build();
|
||||
|
||||
ByteBuffer content = ByteBuffer.wrap(new byte[128 * 1024]);
|
||||
final int contentLength = content.remaining();
|
||||
int contentLength = content.remaining();
|
||||
|
||||
final int code = 200;
|
||||
final String contentTypeName = "Content-Length";
|
||||
final String contentTypeValue = String.valueOf(contentLength);
|
||||
int code = 200;
|
||||
String contentTypeName = "Content-Length";
|
||||
String contentTypeValue = String.valueOf(contentLength);
|
||||
fields.put(contentTypeName, contentTypeValue);
|
||||
|
||||
ByteBufferPool byteBufferPool = new MappedByteBufferPool();
|
||||
ServerGenerator generator = new ServerGenerator(byteBufferPool);
|
||||
Generator.Result result1 = generator.generateResponseHeaders(id, code, "OK", fields, null);
|
||||
Generator.Result result2 = generator.generateResponseContent(id, content, true, false, null);
|
||||
RetainableByteBufferPool bufferPool = new ArrayRetainableByteBufferPool();
|
||||
ServerGenerator generator = new ServerGenerator(bufferPool);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.generateResponseHeaders(accumulator, id, code, "OK", fields);
|
||||
generator.generateResponseContent(accumulator, id, content, true, false);
|
||||
|
||||
final AtomicInteger totalLength = new AtomicInteger();
|
||||
final AtomicBoolean verifier = new AtomicBoolean();
|
||||
AtomicInteger totalLength = new AtomicInteger();
|
||||
AtomicBoolean verifier = new AtomicBoolean();
|
||||
ClientParser parser = new ClientParser(new ClientParser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
|
@ -241,17 +236,14 @@ public class ClientParserTest
|
|||
}
|
||||
});
|
||||
|
||||
for (ByteBuffer buffer : result1.getByteBuffers())
|
||||
{
|
||||
parser.parse(buffer);
|
||||
assertFalse(buffer.hasRemaining());
|
||||
}
|
||||
for (ByteBuffer buffer : result2.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
parser.parse(buffer);
|
||||
assertFalse(buffer.hasRemaining());
|
||||
}
|
||||
|
||||
assertTrue(verifier.get());
|
||||
|
||||
accumulator.release();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ import java.util.Locale;
|
|||
|
||||
import org.eclipse.jetty.fcgi.FCGI;
|
||||
import org.eclipse.jetty.fcgi.generator.Flusher;
|
||||
import org.eclipse.jetty.fcgi.generator.Generator;
|
||||
import org.eclipse.jetty.fcgi.generator.ServerGenerator;
|
||||
import org.eclipse.jetty.http.HostPortHttpField;
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
|
@ -30,6 +29,7 @@ import org.eclipse.jetty.http.HttpScheme;
|
|||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.io.Content;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.server.HttpChannel;
|
||||
import org.eclipse.jetty.server.HttpStream;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
@ -229,8 +229,9 @@ public class HttpStreamOverFCGI implements HttpStream
|
|||
{
|
||||
if (last)
|
||||
{
|
||||
Generator.Result result = generateResponseContent(true, BufferUtil.EMPTY_BUFFER, callback);
|
||||
flusher.flush(result);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generateResponseContent(accumulator, true, BufferUtil.EMPTY_BUFFER);
|
||||
flusher.flush(accumulator, callback);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -240,8 +241,9 @@ public class HttpStreamOverFCGI implements HttpStream
|
|||
}
|
||||
else
|
||||
{
|
||||
Generator.Result result = generateResponseContent(last, content, callback);
|
||||
flusher.flush(result);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generateResponseContent(accumulator, last, content);
|
||||
flusher.flush(accumulator, callback);
|
||||
}
|
||||
|
||||
if (last && _shutdown)
|
||||
|
@ -258,40 +260,42 @@ public class HttpStreamOverFCGI implements HttpStream
|
|||
|
||||
boolean shutdown = _shutdown = info.getFields().contains(HttpHeader.CONNECTION, HttpHeaderValue.CLOSE.asString());
|
||||
|
||||
RetainableByteBufferPool bufferPool = _generator.getRetainableByteBufferPool();
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
Flusher flusher = _connection.getFlusher();
|
||||
if (head)
|
||||
{
|
||||
if (last)
|
||||
{
|
||||
Generator.Result headersResult = generateResponseHeaders(info, Callback.NOOP);
|
||||
Generator.Result contentResult = generateResponseContent(true, BufferUtil.EMPTY_BUFFER, callback);
|
||||
flusher.flush(headersResult, contentResult);
|
||||
generateResponseHeaders(accumulator, info);
|
||||
generateResponseContent(accumulator, true, BufferUtil.EMPTY_BUFFER);
|
||||
flusher.flush(accumulator, callback);
|
||||
}
|
||||
else
|
||||
{
|
||||
Generator.Result headersResult = generateResponseHeaders(info, callback);
|
||||
flusher.flush(headersResult);
|
||||
generateResponseHeaders(accumulator, info);
|
||||
flusher.flush(accumulator, callback);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Generator.Result headersResult = generateResponseHeaders(info, Callback.NOOP);
|
||||
Generator.Result contentResult = generateResponseContent(last, content, callback);
|
||||
flusher.flush(headersResult, contentResult);
|
||||
generateResponseHeaders(accumulator, info);
|
||||
generateResponseContent(accumulator, last, content);
|
||||
flusher.flush(accumulator, callback);
|
||||
}
|
||||
|
||||
if (last && shutdown)
|
||||
flusher.shutdown();
|
||||
}
|
||||
|
||||
private Generator.Result generateResponseHeaders(MetaData.Response info, Callback callback)
|
||||
private void generateResponseHeaders(RetainableByteBufferPool.Accumulator accumulator, MetaData.Response info)
|
||||
{
|
||||
return _generator.generateResponseHeaders(_id, info.getStatus(), info.getReason(), info.getFields(), callback);
|
||||
_generator.generateResponseHeaders(accumulator, _id, info.getStatus(), info.getReason(), info.getFields());
|
||||
}
|
||||
|
||||
private Generator.Result generateResponseContent(boolean last, ByteBuffer buffer, Callback callback)
|
||||
private void generateResponseContent(RetainableByteBufferPool.Accumulator accumulator, boolean last, ByteBuffer buffer)
|
||||
{
|
||||
return _generator.generateResponseContent(_id, buffer, last, _aborted, callback);
|
||||
_generator.generateResponseContent(accumulator, _id, buffer, last, _aborted);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -63,7 +63,7 @@ public class ServerFCGIConnection extends AbstractConnection implements Connecti
|
|||
{
|
||||
super(endPoint, connector.getExecutor());
|
||||
this.connector = connector;
|
||||
this.networkByteBufferPool = connector.getByteBufferPool().asRetainableByteBufferPool();
|
||||
this.networkByteBufferPool = connector.getRetainableByteBufferPool();
|
||||
this.flusher = new Flusher(endPoint);
|
||||
this.configuration = configuration;
|
||||
this.sendStatus200 = sendStatus200;
|
||||
|
@ -212,7 +212,7 @@ public class ServerFCGIConnection extends AbstractConnection implements Connecti
|
|||
LOG.debug("Read {} bytes from {} {}", read, getEndPoint(), this);
|
||||
if (read > 0)
|
||||
{
|
||||
if (parse(networkBuffer.getBuffer()))
|
||||
if (parse(networkBuffer.getByteBuffer()))
|
||||
return;
|
||||
}
|
||||
else if (read == 0)
|
||||
|
@ -252,7 +252,7 @@ public class ServerFCGIConnection extends AbstractConnection implements Connecti
|
|||
// See also HttpConnection.parseAndFillForContent().
|
||||
while (stream != null)
|
||||
{
|
||||
if (parse(networkBuffer.getBuffer()))
|
||||
if (parse(networkBuffer.getByteBuffer()))
|
||||
return;
|
||||
// Check if the request was completed by the parsing.
|
||||
if (stream == null)
|
||||
|
@ -281,7 +281,7 @@ public class ServerFCGIConnection extends AbstractConnection implements Connecti
|
|||
{
|
||||
try
|
||||
{
|
||||
return getEndPoint().fill(networkBuffer.getBuffer());
|
||||
return getEndPoint().fill(networkBuffer.getByteBuffer());
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
|
@ -333,7 +333,7 @@ public class ServerFCGIConnection extends AbstractConnection implements Connecti
|
|||
if (stream != null)
|
||||
throw new UnsupportedOperationException("FastCGI Multiplexing");
|
||||
HttpChannel channel = httpChannelFactory.newHttpChannel(ServerFCGIConnection.this);
|
||||
ServerGenerator generator = new ServerGenerator(connector.getByteBufferPool(), isUseOutputDirectByteBuffers(), sendStatus200);
|
||||
ServerGenerator generator = new ServerGenerator(connector.getRetainableByteBufferPool(), isUseOutputDirectByteBuffers(), sendStatus200);
|
||||
stream = new HttpStreamOverFCGI(ServerFCGIConnection.this, generator, channel, request);
|
||||
channel.setHttpStream(stream);
|
||||
if (LOG.isDebugEnabled())
|
||||
|
|
|
@ -21,10 +21,9 @@ import org.eclipse.jetty.client.HttpClientTransport;
|
|||
import org.eclipse.jetty.client.LeakTrackingConnectionPool;
|
||||
import org.eclipse.jetty.fcgi.client.transport.HttpClientTransportOverFCGI;
|
||||
import org.eclipse.jetty.http.HttpScheme;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.ClientConnector;
|
||||
import org.eclipse.jetty.io.LeakTrackingByteBufferPool;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
|
@ -39,8 +38,8 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
|||
|
||||
public abstract class AbstractHttpClientServerTest
|
||||
{
|
||||
private LeakTrackingByteBufferPool serverBufferPool;
|
||||
protected ByteBufferPool clientBufferPool;
|
||||
private RetainableByteBufferPool serverBufferPool;
|
||||
protected RetainableByteBufferPool clientBufferPool;
|
||||
private final AtomicLong connectionLeaks = new AtomicLong();
|
||||
protected Server server;
|
||||
protected ServerConnector connector;
|
||||
|
@ -53,7 +52,8 @@ public abstract class AbstractHttpClientServerTest
|
|||
serverThreads.setName("server");
|
||||
server = new Server(serverThreads);
|
||||
ServerFCGIConnectionFactory fcgiConnectionFactory = new ServerFCGIConnectionFactory(new HttpConfiguration());
|
||||
serverBufferPool = new LeakTrackingByteBufferPool(new MappedByteBufferPool.Tagged());
|
||||
// TODO: restore leak tracking.
|
||||
serverBufferPool = new ArrayRetainableByteBufferPool();
|
||||
connector = new ServerConnector(server, null, null, serverBufferPool,
|
||||
1, Math.max(1, ProcessorUtils.availableProcessors() / 2), fcgiConnectionFactory);
|
||||
server.addConnector(connector);
|
||||
|
@ -65,9 +65,10 @@ public abstract class AbstractHttpClientServerTest
|
|||
QueuedThreadPool clientThreads = new QueuedThreadPool();
|
||||
clientThreads.setName("client");
|
||||
clientConnector.setExecutor(clientThreads);
|
||||
// TODO: restore leak tracking.
|
||||
if (clientBufferPool == null)
|
||||
clientBufferPool = new LeakTrackingByteBufferPool(new MappedByteBufferPool.Tagged());
|
||||
clientConnector.setByteBufferPool(clientBufferPool);
|
||||
clientBufferPool = new ArrayRetainableByteBufferPool();
|
||||
clientConnector.setRetainableByteBufferPool(clientBufferPool);
|
||||
HttpClientTransport transport = new HttpClientTransportOverFCGI(clientConnector, "");
|
||||
transport.setConnectionPoolFactory(destination -> new LeakTrackingConnectionPool(destination, client.getMaxConnectionsPerDestination())
|
||||
{
|
||||
|
@ -86,22 +87,6 @@ public abstract class AbstractHttpClientServerTest
|
|||
{
|
||||
System.gc();
|
||||
|
||||
if (serverBufferPool != null)
|
||||
{
|
||||
assertThat("Server BufferPool - leaked acquires", serverBufferPool.getLeakedAcquires(), Matchers.is(0L));
|
||||
assertThat("Server BufferPool - leaked releases", serverBufferPool.getLeakedReleases(), Matchers.is(0L));
|
||||
assertThat("Server BufferPool - leaked removes", serverBufferPool.getLeakedRemoves(), Matchers.is(0L));
|
||||
assertThat("Server BufferPool - unreleased", serverBufferPool.getLeakedResources(), Matchers.is(0L));
|
||||
}
|
||||
|
||||
if ((clientBufferPool != null) && (clientBufferPool instanceof LeakTrackingByteBufferPool pool))
|
||||
{
|
||||
assertThat("Client BufferPool - leaked acquires", pool.getLeakedAcquires(), Matchers.is(0L));
|
||||
assertThat("Client BufferPool - leaked releases", pool.getLeakedReleases(), Matchers.is(0L));
|
||||
assertThat("Client BufferPool - leaked removes", pool.getLeakedRemoves(), Matchers.is(0L));
|
||||
assertThat("Client BufferPool - unreleased", pool.getLeakedResources(), Matchers.is(0L));
|
||||
}
|
||||
|
||||
assertThat("Connection Leaks", connectionLeaks.get(), Matchers.is(0L));
|
||||
|
||||
if (client != null)
|
||||
|
|
|
@ -36,7 +36,6 @@ import org.eclipse.jetty.client.Response;
|
|||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.io.Content;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.logging.StacklessLogging;
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.HttpChannel;
|
||||
|
@ -400,11 +399,6 @@ public class HttpClientTest extends AbstractHttpClientServerTest
|
|||
@Test
|
||||
public void testGZIPContentEncoding() throws Exception
|
||||
{
|
||||
// GZIPContentDecoder returns to application pooled
|
||||
// buffers, which is fine, but in this test they will
|
||||
// appear as "leaked", so we use a normal ByteBufferPool.
|
||||
clientBufferPool = new MappedByteBufferPool.Tagged();
|
||||
|
||||
byte[] data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
start(new Handler.Abstract()
|
||||
{
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
|
||||
package org.eclipse.jetty.http;
|
||||
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -21,7 +20,8 @@ import java.util.zip.DataFormatException;
|
|||
import java.util.zip.Inflater;
|
||||
import java.util.zip.ZipException;
|
||||
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.component.Destroyable;
|
||||
import org.eclipse.jetty.util.compression.InflaterPool;
|
||||
|
@ -36,8 +36,8 @@ public class GZIPContentDecoder implements Destroyable
|
|||
// Unsigned Integer Max == 2^32
|
||||
private static final long UINT_MAX = 0xFFFFFFFFL;
|
||||
|
||||
private final List<ByteBuffer> _inflateds = new ArrayList<>();
|
||||
private final ByteBufferPool _pool;
|
||||
private final List<RetainableByteBuffer> _inflateds = new ArrayList<>();
|
||||
private final RetainableByteBufferPool _pool;
|
||||
private final int _bufferSize;
|
||||
private InflaterPool.Entry _inflaterEntry;
|
||||
private Inflater _inflater;
|
||||
|
@ -45,7 +45,7 @@ public class GZIPContentDecoder implements Destroyable
|
|||
private int _size;
|
||||
private long _value;
|
||||
private byte _flags;
|
||||
private ByteBuffer _inflated;
|
||||
private RetainableByteBuffer _inflated;
|
||||
|
||||
public GZIPContentDecoder()
|
||||
{
|
||||
|
@ -57,24 +57,24 @@ public class GZIPContentDecoder implements Destroyable
|
|||
this(null, bufferSize);
|
||||
}
|
||||
|
||||
public GZIPContentDecoder(ByteBufferPool pool, int bufferSize)
|
||||
public GZIPContentDecoder(RetainableByteBufferPool retainableByteBufferPool, int bufferSize)
|
||||
{
|
||||
this(new InflaterPool(0, true), pool, bufferSize);
|
||||
this(new InflaterPool(0, true), retainableByteBufferPool, bufferSize);
|
||||
}
|
||||
|
||||
public GZIPContentDecoder(InflaterPool inflaterPool, ByteBufferPool pool, int bufferSize)
|
||||
public GZIPContentDecoder(InflaterPool inflaterPool, RetainableByteBufferPool retainableByteBufferPool, int bufferSize)
|
||||
{
|
||||
_inflaterEntry = inflaterPool.acquire();
|
||||
_inflater = _inflaterEntry.get();
|
||||
_bufferSize = bufferSize;
|
||||
_pool = pool;
|
||||
_pool = retainableByteBufferPool != null ? retainableByteBufferPool : new RetainableByteBufferPool.NonPooling();
|
||||
reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Inflates compressed data from a buffer.</p>
|
||||
* <p>The buffers returned by this method should be released
|
||||
* via {@link #release(ByteBuffer)}.</p>
|
||||
* <p>The {@link RetainableByteBuffer} returned by this method
|
||||
* <b>must</b> be released via {@link RetainableByteBuffer#release()}.</p>
|
||||
* <p>This method may fully consume the input buffer, but return
|
||||
* only a chunk of the inflated bytes, to allow applications to
|
||||
* consume the inflated chunk before performing further inflation,
|
||||
|
@ -83,21 +83,21 @@ public class GZIPContentDecoder implements Destroyable
|
|||
* it's already fully consumed) and that will produce another
|
||||
* chunk of inflated bytes. Termination happens when the input
|
||||
* buffer is fully consumed, and the returned buffer is empty.</p>
|
||||
* <p>See {@link #decodedChunk(ByteBuffer)} to perform inflating
|
||||
* <p>See {@link #decodedChunk(RetainableByteBuffer)} to perform inflating
|
||||
* in a non-blocking way that allows to apply backpressure.</p>
|
||||
*
|
||||
* @param compressed the buffer containing compressed data.
|
||||
* @return a buffer containing inflated data.
|
||||
*/
|
||||
public ByteBuffer decode(ByteBuffer compressed)
|
||||
public RetainableByteBuffer decode(ByteBuffer compressed)
|
||||
{
|
||||
decodeChunks(compressed);
|
||||
|
||||
if (_inflateds.isEmpty())
|
||||
{
|
||||
if (BufferUtil.isEmpty(_inflated) || _state == State.CRC || _state == State.ISIZE)
|
||||
return BufferUtil.EMPTY_BUFFER;
|
||||
ByteBuffer result = _inflated;
|
||||
if ((_inflated == null || !_inflated.hasRemaining()) || _state == State.CRC || _state == State.ISIZE)
|
||||
return acquire(0);
|
||||
RetainableByteBuffer result = _inflated;
|
||||
_inflated = null;
|
||||
return result;
|
||||
}
|
||||
|
@ -105,12 +105,12 @@ public class GZIPContentDecoder implements Destroyable
|
|||
{
|
||||
_inflateds.add(_inflated);
|
||||
_inflated = null;
|
||||
int length = _inflateds.stream().mapToInt(Buffer::remaining).sum();
|
||||
ByteBuffer result = acquire(length);
|
||||
for (ByteBuffer buffer : _inflateds)
|
||||
int length = _inflateds.stream().mapToInt(RetainableByteBuffer::remaining).sum();
|
||||
RetainableByteBuffer result = acquire(length);
|
||||
for (RetainableByteBuffer buffer : _inflateds)
|
||||
{
|
||||
BufferUtil.append(result, buffer);
|
||||
release(buffer);
|
||||
BufferUtil.append(result.getByteBuffer(), buffer.getByteBuffer());
|
||||
buffer.release();
|
||||
}
|
||||
_inflateds.clear();
|
||||
return result;
|
||||
|
@ -132,38 +132,26 @@ public class GZIPContentDecoder implements Destroyable
|
|||
* should return, allowing to consume the inflated chunk and apply
|
||||
* backpressure
|
||||
*/
|
||||
protected boolean decodedChunk(ByteBuffer chunk)
|
||||
protected boolean decodedChunk(RetainableByteBuffer chunk)
|
||||
{
|
||||
if (_inflated == null)
|
||||
{
|
||||
_inflated = chunk;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BufferUtil.space(_inflated) >= chunk.remaining())
|
||||
{
|
||||
BufferUtil.append(_inflated, chunk);
|
||||
release(chunk);
|
||||
}
|
||||
else
|
||||
{
|
||||
_inflateds.add(_inflated);
|
||||
_inflated = chunk;
|
||||
}
|
||||
}
|
||||
// Retain the chunk because it is stored for later use.
|
||||
chunk.retain();
|
||||
if (_inflated != null)
|
||||
_inflateds.add(_inflated);
|
||||
_inflated = chunk;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Inflates compressed data.</p>
|
||||
* <p>Inflation continues until the compressed block end is reached, there is no
|
||||
* more compressed data or a call to {@link #decodedChunk(ByteBuffer)} returns true.</p>
|
||||
* more compressed data or a call to {@link #decodedChunk(RetainableByteBuffer)} returns true.</p>
|
||||
*
|
||||
* @param compressed the buffer of compressed data to inflate
|
||||
*/
|
||||
protected void decodeChunks(ByteBuffer compressed)
|
||||
{
|
||||
ByteBuffer buffer = null;
|
||||
RetainableByteBuffer buffer = null;
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
|
@ -211,9 +199,10 @@ public class GZIPContentDecoder implements Destroyable
|
|||
|
||||
try
|
||||
{
|
||||
int pos = BufferUtil.flipToFill(buffer);
|
||||
_inflater.inflate(buffer);
|
||||
BufferUtil.flipToFlush(buffer, pos);
|
||||
ByteBuffer decoded = buffer.getByteBuffer();
|
||||
int pos = BufferUtil.flipToFill(decoded);
|
||||
_inflater.inflate(decoded);
|
||||
BufferUtil.flipToFlush(decoded, pos);
|
||||
}
|
||||
catch (DataFormatException x)
|
||||
{
|
||||
|
@ -222,9 +211,10 @@ public class GZIPContentDecoder implements Destroyable
|
|||
|
||||
if (buffer.hasRemaining())
|
||||
{
|
||||
ByteBuffer decoded = buffer;
|
||||
boolean stop = decodedChunk(buffer);
|
||||
buffer.release();
|
||||
buffer = null;
|
||||
if (decodedChunk(decoded))
|
||||
if (stop)
|
||||
return;
|
||||
}
|
||||
else if (_inflater.needsInput())
|
||||
|
@ -395,7 +385,7 @@ public class GZIPContentDecoder implements Destroyable
|
|||
finally
|
||||
{
|
||||
if (buffer != null)
|
||||
release(buffer);
|
||||
buffer.release();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -430,23 +420,8 @@ public class GZIPContentDecoder implements Destroyable
|
|||
* @param capacity capacity of the ByteBuffer to acquire
|
||||
* @return a heap buffer of the configured capacity either from the pool or freshly allocated.
|
||||
*/
|
||||
public ByteBuffer acquire(int capacity)
|
||||
public RetainableByteBuffer acquire(int capacity)
|
||||
{
|
||||
return _pool == null ? BufferUtil.allocate(capacity) : _pool.acquire(capacity, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Releases an allocated buffer.</p>
|
||||
* <p>This method calls {@link ByteBufferPool#release(ByteBuffer)} if a buffer pool has
|
||||
* been configured.</p>
|
||||
* <p>This method should be called once for all buffers returned from {@link #decode(ByteBuffer)}
|
||||
* or passed to {@link #decodedChunk(ByteBuffer)}.</p>
|
||||
*
|
||||
* @param buffer the buffer to release.
|
||||
*/
|
||||
public void release(ByteBuffer buffer)
|
||||
{
|
||||
if (_pool != null && !BufferUtil.isTheEmptyBuffer(buffer))
|
||||
_pool.release(buffer);
|
||||
return _pool.acquire(capacity, false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,9 +30,9 @@ import org.eclipse.jetty.http.HttpField;
|
|||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.MimeTypes;
|
||||
import org.eclipse.jetty.http.PreEncodedHttpField;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.NoopByteBufferPool;
|
||||
import org.eclipse.jetty.io.Retainable;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.NanoTime;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
|
@ -69,16 +69,16 @@ public class CachingHttpContentFactory implements HttpContent.Factory
|
|||
private final HttpContent.Factory _authority;
|
||||
private final ConcurrentHashMap<String, CachingHttpContent> _cache = new ConcurrentHashMap<>();
|
||||
private final AtomicLong _cachedSize = new AtomicLong();
|
||||
private final ByteBufferPool _byteBufferPool;
|
||||
private final RetainableByteBufferPool _bufferPool;
|
||||
private int _maxCachedFileSize = DEFAULT_MAX_CACHED_FILE_SIZE;
|
||||
private int _maxCachedFiles = DEFAULT_MAX_CACHED_FILES;
|
||||
private long _maxCacheSize = DEFAULT_MAX_CACHE_SIZE;
|
||||
private boolean _useDirectByteBuffers = true;
|
||||
|
||||
public CachingHttpContentFactory(HttpContent.Factory authority, ByteBufferPool byteBufferPool)
|
||||
public CachingHttpContentFactory(HttpContent.Factory authority, RetainableByteBufferPool bufferPool)
|
||||
{
|
||||
_authority = authority;
|
||||
_byteBufferPool = (byteBufferPool == null) ? new NoopByteBufferPool() : byteBufferPool;
|
||||
_bufferPool = bufferPool != null ? bufferPool : new RetainableByteBufferPool.NonPooling();
|
||||
}
|
||||
|
||||
protected ConcurrentMap<String, CachingHttpContent> getCache()
|
||||
|
@ -294,7 +294,7 @@ public class CachingHttpContentFactory implements HttpContent.Factory
|
|||
|
||||
protected class CachedHttpContent extends HttpContent.Wrapper implements CachingHttpContent
|
||||
{
|
||||
private final ByteBuffer _buffer;
|
||||
private final RetainableByteBuffer _buffer;
|
||||
private final String _cacheKey;
|
||||
private final HttpField _etagField;
|
||||
private final long _contentLengthValue;
|
||||
|
@ -327,21 +327,23 @@ public class CachingHttpContentFactory implements HttpContent.Factory
|
|||
boolean isValid = true;
|
||||
|
||||
// Read the content into memory if the HttpContent does not already have a buffer.
|
||||
RetainableByteBuffer buffer;
|
||||
ByteBuffer byteBuffer = httpContent.getByteBuffer();
|
||||
if (byteBuffer == null)
|
||||
{
|
||||
buffer = _bufferPool.acquire((int)_contentLengthValue, _useDirectByteBuffers);
|
||||
try
|
||||
{
|
||||
if (_contentLengthValue <= _maxCachedFileSize)
|
||||
{
|
||||
byteBuffer = _byteBufferPool.acquire((int)_contentLengthValue, _useDirectByteBuffers);
|
||||
try (ReadableByteChannel readableByteChannel = httpContent.getResource().newReadableByteChannel())
|
||||
{
|
||||
byteBuffer = buffer.getByteBuffer();
|
||||
int read = BufferUtil.readFrom(readableByteChannel, byteBuffer);
|
||||
if (read != _contentLengthValue)
|
||||
{
|
||||
_byteBufferPool.release(byteBuffer);
|
||||
byteBuffer = null;
|
||||
buffer.release();
|
||||
buffer = null;
|
||||
isValid = false;
|
||||
}
|
||||
}
|
||||
|
@ -349,17 +351,19 @@ public class CachingHttpContentFactory implements HttpContent.Factory
|
|||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
if (buffer != null)
|
||||
buffer.release();
|
||||
buffer = null;
|
||||
isValid = false;
|
||||
if (byteBuffer != null)
|
||||
{
|
||||
_byteBufferPool.release(byteBuffer);
|
||||
byteBuffer = null;
|
||||
}
|
||||
LOG.warn("Failed to read Resource", t);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = RetainableByteBuffer.wrap(byteBuffer);
|
||||
}
|
||||
|
||||
_buffer = byteBuffer;
|
||||
_buffer = buffer;
|
||||
_isValid = isValid;
|
||||
_bytesOccupied = httpContent.getBytesOccupied();
|
||||
_lastModifiedValue = httpContent.getLastModifiedValue();
|
||||
|
@ -381,7 +385,7 @@ public class CachingHttpContentFactory implements HttpContent.Factory
|
|||
@Override
|
||||
public ByteBuffer getByteBuffer()
|
||||
{
|
||||
return _buffer == null ? null : _buffer.asReadOnlyBuffer();
|
||||
return _buffer == null ? null : _buffer.getByteBuffer().asReadOnlyBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -420,7 +424,7 @@ public class CachingHttpContentFactory implements HttpContent.Factory
|
|||
if (_referenceCount.release())
|
||||
{
|
||||
if (_buffer != null)
|
||||
_byteBufferPool.release(_buffer);
|
||||
_buffer.release();
|
||||
super.release();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import java.util.concurrent.ConcurrentMap;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.NanoTime;
|
||||
import org.eclipse.jetty.util.annotation.Name;
|
||||
import org.eclipse.jetty.util.thread.Scheduler;
|
||||
|
@ -55,13 +55,13 @@ public class ValidatingCachingHttpContentFactory extends CachingHttpContentFacto
|
|||
*
|
||||
* @param authority the wrapped {@link HttpContent.Factory} to use.
|
||||
* @param validationPeriod time between filesystem checks in ms to see if an {@link HttpContent} is still valid (-1 never validate, 0 always validate).
|
||||
* @param byteBufferPool the {@link org.eclipse.jetty.io.ByteBufferPool} to use.
|
||||
* @param bufferPool the {@link org.eclipse.jetty.io.RetainableByteBufferPool} to use.
|
||||
*/
|
||||
public ValidatingCachingHttpContentFactory(@Name("authority") HttpContent.Factory authority,
|
||||
@Name("validationPeriod") long validationPeriod,
|
||||
@Name("byteBufferPool") ByteBufferPool byteBufferPool)
|
||||
@Name("bufferPool") RetainableByteBufferPool bufferPool)
|
||||
{
|
||||
this(authority, validationPeriod, byteBufferPool, null, -1, -1);
|
||||
this(authority, validationPeriod, bufferPool, null, -1, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -70,19 +70,19 @@ public class ValidatingCachingHttpContentFactory extends CachingHttpContentFacto
|
|||
*
|
||||
* @param authority the wrapped {@link HttpContent.Factory} to use.
|
||||
* @param validationPeriod time between filesystem checks in ms to see if an {@link HttpContent} is still valid (-1 never validate, 0 always validate).
|
||||
* @param byteBufferPool the {@link org.eclipse.jetty.io.ByteBufferPool} to use.
|
||||
* @param bufferPool the {@link org.eclipse.jetty.io.RetainableByteBufferPool} to use.
|
||||
* @param scheduler scheduler to use for the sweeper, can be null to not use sweeper.
|
||||
* @param sweepPeriod time between runs of the sweeper in ms (if 0 never sweep for invalid entries).
|
||||
* @param idleTimeout amount of time in ms an entry can be unused before evicted by the sweeper (if 0 never evict unused entries).
|
||||
*/
|
||||
public ValidatingCachingHttpContentFactory(@Name("authority") HttpContent.Factory authority,
|
||||
@Name("validationPeriod") long validationPeriod,
|
||||
@Name("byteBufferPool") ByteBufferPool byteBufferPool,
|
||||
@Name("byteBufferPool") RetainableByteBufferPool bufferPool,
|
||||
@Name("scheduler") Scheduler scheduler,
|
||||
@Name("sweepPeriod") long sweepPeriod,
|
||||
@Name("idleTimeout") long idleTimeout)
|
||||
{
|
||||
super(authority, byteBufferPool);
|
||||
super(authority, bufferPool);
|
||||
_validationTime = validationPeriod;
|
||||
_scheduler = scheduler;
|
||||
_sweepDelay = sweepPeriod;
|
||||
|
|
|
@ -23,7 +23,9 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import org.eclipse.jetty.io.ArrayByteBufferPool;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -39,28 +41,29 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
|
||||
public class GZIPContentDecoderTest
|
||||
{
|
||||
private ArrayByteBufferPool pool;
|
||||
private AtomicInteger buffers = new AtomicInteger(0);
|
||||
private final AtomicInteger counter = new AtomicInteger();
|
||||
private RetainableByteBufferPool pool;
|
||||
|
||||
@BeforeEach
|
||||
public void before()
|
||||
{
|
||||
buffers.set(0);
|
||||
pool = new ArrayByteBufferPool()
|
||||
pool = new RetainableByteBufferPool.Wrapper(new ArrayRetainableByteBufferPool())
|
||||
{
|
||||
|
||||
@Override
|
||||
public ByteBuffer acquire(int size, boolean direct)
|
||||
public RetainableByteBuffer acquire(int size, boolean direct)
|
||||
{
|
||||
buffers.incrementAndGet();
|
||||
return super.acquire(size, direct);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release(ByteBuffer buffer)
|
||||
{
|
||||
buffers.decrementAndGet();
|
||||
super.release(buffer);
|
||||
counter.incrementAndGet();
|
||||
return new RetainableByteBuffer.Wrapper(super.acquire(size, direct))
|
||||
{
|
||||
@Override
|
||||
public boolean release()
|
||||
{
|
||||
boolean released = super.release();
|
||||
if (released)
|
||||
counter.decrementAndGet();
|
||||
return released;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -68,7 +71,7 @@ public class GZIPContentDecoderTest
|
|||
@AfterEach
|
||||
public void after()
|
||||
{
|
||||
assertEquals(0, buffers.get());
|
||||
assertThat(counter.get(), is(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -126,8 +129,9 @@ public class GZIPContentDecoderTest
|
|||
byte[] bytes = baos.toByteArray();
|
||||
|
||||
GZIPContentDecoder decoder = new GZIPContentDecoder(pool, 2048);
|
||||
ByteBuffer decoded = decoder.decode(ByteBuffer.wrap(bytes));
|
||||
RetainableByteBuffer decoded = decoder.decode(ByteBuffer.wrap(bytes));
|
||||
assertEquals(0, decoded.remaining());
|
||||
decoded.release();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -142,9 +146,9 @@ public class GZIPContentDecoderTest
|
|||
byte[] bytes = baos.toByteArray();
|
||||
|
||||
GZIPContentDecoder decoder = new GZIPContentDecoder(pool, 2048);
|
||||
ByteBuffer decoded = decoder.decode(ByteBuffer.wrap(bytes));
|
||||
assertEquals(data, StandardCharsets.UTF_8.decode(decoded).toString());
|
||||
decoder.release(decoded);
|
||||
RetainableByteBuffer decoded = decoder.decode(ByteBuffer.wrap(bytes));
|
||||
assertEquals(data, StandardCharsets.UTF_8.decode(decoded.getByteBuffer()).toString());
|
||||
decoded.release();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -165,11 +169,12 @@ public class GZIPContentDecoderTest
|
|||
System.arraycopy(bytes, bytes1.length, bytes2, 0, bytes2.length);
|
||||
|
||||
GZIPContentDecoder decoder = new GZIPContentDecoder(pool, 2048);
|
||||
ByteBuffer decoded = decoder.decode(ByteBuffer.wrap(bytes1));
|
||||
assertEquals(0, decoded.capacity());
|
||||
RetainableByteBuffer decoded = decoder.decode(ByteBuffer.wrap(bytes1));
|
||||
assertEquals(0, decoded.remaining());
|
||||
decoded.release();
|
||||
decoded = decoder.decode(ByteBuffer.wrap(bytes2));
|
||||
assertEquals(data, StandardCharsets.UTF_8.decode(decoded).toString());
|
||||
decoder.release(decoded);
|
||||
assertEquals(data, StandardCharsets.UTF_8.decode(decoded.getByteBuffer()).toString());
|
||||
decoded.release();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -190,14 +195,14 @@ public class GZIPContentDecoderTest
|
|||
System.arraycopy(bytes, bytes1.length, bytes2, 0, bytes2.length);
|
||||
|
||||
GZIPContentDecoder decoder = new GZIPContentDecoder(pool, 2048);
|
||||
ByteBuffer decoded = decoder.decode(ByteBuffer.wrap(bytes1));
|
||||
assertEquals(data, StandardCharsets.UTF_8.decode(decoded).toString());
|
||||
RetainableByteBuffer decoded = decoder.decode(ByteBuffer.wrap(bytes1));
|
||||
assertEquals(data, StandardCharsets.UTF_8.decode(decoded.getByteBuffer()).toString());
|
||||
assertFalse(decoder.isFinished());
|
||||
decoder.release(decoded);
|
||||
decoded.release();
|
||||
decoded = decoder.decode(ByteBuffer.wrap(bytes2));
|
||||
assertEquals(0, decoded.remaining());
|
||||
assertTrue(decoder.isFinished());
|
||||
decoder.release(decoded);
|
||||
decoded.release();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -218,12 +223,12 @@ public class GZIPContentDecoderTest
|
|||
System.arraycopy(bytes, bytes1.length, bytes2, 0, bytes2.length);
|
||||
|
||||
GZIPContentDecoder decoder = new GZIPContentDecoder(pool, 2048);
|
||||
ByteBuffer decoded = decoder.decode(ByteBuffer.wrap(bytes1));
|
||||
assertEquals(0, decoded.capacity());
|
||||
decoder.release(decoded);
|
||||
RetainableByteBuffer decoded = decoder.decode(ByteBuffer.wrap(bytes1));
|
||||
assertEquals(0, decoded.remaining());
|
||||
decoded.release();
|
||||
decoded = decoder.decode(ByteBuffer.wrap(bytes2));
|
||||
assertEquals(data, StandardCharsets.UTF_8.decode(decoded).toString());
|
||||
decoder.release(decoded);
|
||||
assertEquals(data, StandardCharsets.UTF_8.decode(decoded.getByteBuffer()).toString());
|
||||
decoded.release();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -249,16 +254,16 @@ public class GZIPContentDecoderTest
|
|||
|
||||
GZIPContentDecoder decoder = new GZIPContentDecoder(pool, 2048);
|
||||
ByteBuffer buffer = ByteBuffer.wrap(bytes);
|
||||
ByteBuffer decoded = decoder.decode(buffer);
|
||||
assertEquals(data1, StandardCharsets.UTF_8.decode(decoded).toString());
|
||||
RetainableByteBuffer decoded = decoder.decode(buffer);
|
||||
assertEquals(data1, StandardCharsets.UTF_8.decode(decoded.getByteBuffer()).toString());
|
||||
assertTrue(decoder.isFinished());
|
||||
assertTrue(buffer.hasRemaining());
|
||||
decoder.release(decoded);
|
||||
decoded.release();
|
||||
decoded = decoder.decode(buffer);
|
||||
assertEquals(data2, StandardCharsets.UTF_8.decode(decoded).toString());
|
||||
assertEquals(data2, StandardCharsets.UTF_8.decode(decoded.getByteBuffer()).toString());
|
||||
assertTrue(decoder.isFinished());
|
||||
assertFalse(buffer.hasRemaining());
|
||||
decoder.release(decoded);
|
||||
decoded.release();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -280,9 +285,9 @@ public class GZIPContentDecoderTest
|
|||
ByteBuffer buffer = ByteBuffer.wrap(bytes);
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
ByteBuffer decoded = decoder.decode(buffer);
|
||||
result += StandardCharsets.UTF_8.decode(decoded).toString();
|
||||
decoder.release(decoded);
|
||||
RetainableByteBuffer decoded = decoder.decode(buffer);
|
||||
result += StandardCharsets.UTF_8.decode(decoded.getByteBuffer()).toString();
|
||||
decoded.release();
|
||||
}
|
||||
assertEquals(data, result);
|
||||
}
|
||||
|
@ -306,10 +311,10 @@ public class GZIPContentDecoderTest
|
|||
ByteBuffer buffer = ByteBuffer.wrap(bytes);
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
ByteBuffer decoded = decoder.decode(ByteBuffer.wrap(new byte[]{buffer.get()}));
|
||||
RetainableByteBuffer decoded = decoder.decode(ByteBuffer.wrap(new byte[]{buffer.get()}));
|
||||
if (decoded.hasRemaining())
|
||||
result += StandardCharsets.UTF_8.decode(decoded).toString();
|
||||
decoder.release(decoded);
|
||||
result += StandardCharsets.UTF_8.decode(decoded.getByteBuffer()).toString();
|
||||
decoded.release();
|
||||
}
|
||||
assertEquals(data, result);
|
||||
assertTrue(decoder.isFinished());
|
||||
|
@ -341,10 +346,10 @@ public class GZIPContentDecoderTest
|
|||
ByteBuffer buffer = ByteBuffer.wrap(bytes);
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
ByteBuffer decoded = decoder.decode(buffer);
|
||||
RetainableByteBuffer decoded = decoder.decode(buffer);
|
||||
if (decoded.hasRemaining())
|
||||
result += StandardCharsets.UTF_8.decode(decoded).toString();
|
||||
decoder.release(decoded);
|
||||
result += StandardCharsets.UTF_8.decode(decoded.getByteBuffer()).toString();
|
||||
decoded.release();
|
||||
if (decoder.isFinished())
|
||||
break;
|
||||
}
|
||||
|
@ -414,12 +419,12 @@ public class GZIPContentDecoderTest
|
|||
ByteBuffer buf = ByteBuffer.wrap(b, off, len);
|
||||
while (buf.hasRemaining())
|
||||
{
|
||||
ByteBuffer decoded = decoder.decode(buf);
|
||||
RetainableByteBuffer decoded = decoder.decode(buf);
|
||||
if (decoded.hasRemaining())
|
||||
{
|
||||
decodedByteCount += decoded.remaining();
|
||||
}
|
||||
decoder.release(decoded);
|
||||
decoded.release();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ public class HttpClientTransportOverHTTP2 extends AbstractHttpClientTransport
|
|||
HttpClient httpClient = getHttpClient();
|
||||
client.setExecutor(httpClient.getExecutor());
|
||||
client.setScheduler(httpClient.getScheduler());
|
||||
client.setByteBufferPool(httpClient.getByteBufferPool());
|
||||
client.setRetainableByteBufferPool(httpClient.getRetainableByteBufferPool());
|
||||
client.setConnectTimeout(httpClient.getConnectTimeout());
|
||||
client.setIdleTimeout(httpClient.getIdleTimeout());
|
||||
client.setInputBufferSize(httpClient.getResponseBufferSize());
|
||||
|
|
|
@ -76,7 +76,7 @@ public class HttpReceiverOverHTTP2 extends HttpReceiver implements HTTP2Channel.
|
|||
DataFrame frame = data.frame();
|
||||
boolean last = frame.remaining() == 0 && frame.isEndStream();
|
||||
if (!last)
|
||||
return Content.Chunk.asChunk(frame.getData(), last, data);
|
||||
return Content.Chunk.asChunk(frame.getByteBuffer(), last, data);
|
||||
data.release();
|
||||
responseSuccess(getHttpExchange(), null);
|
||||
return Content.Chunk.EOF;
|
||||
|
|
|
@ -28,9 +28,9 @@ import org.eclipse.jetty.http2.FlowControlStrategy;
|
|||
import org.eclipse.jetty.http2.api.Session;
|
||||
import org.eclipse.jetty.http2.frames.Frame;
|
||||
import org.eclipse.jetty.http2.frames.SettingsFrame;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.ClientConnectionFactory;
|
||||
import org.eclipse.jetty.io.ClientConnector;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.ssl.SslClientConnectionFactory;
|
||||
import org.eclipse.jetty.util.Promise;
|
||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||
|
@ -153,14 +153,14 @@ public class HTTP2Client extends ContainerLifeCycle
|
|||
connector.setScheduler(scheduler);
|
||||
}
|
||||
|
||||
public ByteBufferPool getByteBufferPool()
|
||||
public RetainableByteBufferPool getRetainableByteBufferPool()
|
||||
{
|
||||
return connector.getByteBufferPool();
|
||||
return connector.getRetainableByteBufferPool();
|
||||
}
|
||||
|
||||
public void setByteBufferPool(ByteBufferPool bufferPool)
|
||||
public void setRetainableByteBufferPool(RetainableByteBufferPool bufferPool)
|
||||
{
|
||||
connector.setByteBufferPool(bufferPool);
|
||||
connector.setRetainableByteBufferPool(bufferPool);
|
||||
}
|
||||
|
||||
public FlowControlStrategy.Factory getFlowControlStrategyFactory()
|
||||
|
@ -435,7 +435,7 @@ public class HTTP2Client extends ContainerLifeCycle
|
|||
{
|
||||
if (isUseALPN())
|
||||
factory = new ALPNClientConnectionFactory(getExecutor(), factory, getProtocols());
|
||||
factory = new SslClientConnectionFactory(sslContextFactory, getByteBufferPool(), getExecutor(), factory);
|
||||
factory = new SslClientConnectionFactory(sslContextFactory, getRetainableByteBufferPool(), getExecutor(), factory);
|
||||
}
|
||||
return factory;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ import org.eclipse.jetty.http2.internal.HTTP2Connection;
|
|||
import org.eclipse.jetty.http2.internal.HTTP2Session;
|
||||
import org.eclipse.jetty.http2.internal.generator.Generator;
|
||||
import org.eclipse.jetty.http2.internal.parser.Parser;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.ClientConnectionFactory;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
|
@ -49,14 +48,14 @@ public class HTTP2ClientConnectionFactory implements ClientConnectionFactory
|
|||
public Connection newConnection(EndPoint endPoint, Map<String, Object> context)
|
||||
{
|
||||
HTTP2Client client = (HTTP2Client)context.get(CLIENT_CONTEXT_KEY);
|
||||
ByteBufferPool byteBufferPool = client.getByteBufferPool();
|
||||
RetainableByteBufferPool bufferPool = client.getRetainableByteBufferPool();
|
||||
Executor executor = client.getExecutor();
|
||||
Scheduler scheduler = client.getScheduler();
|
||||
Session.Listener listener = (Session.Listener)context.get(SESSION_LISTENER_CONTEXT_KEY);
|
||||
@SuppressWarnings("unchecked")
|
||||
Promise<Session> promise = (Promise<Session>)context.get(SESSION_PROMISE_CONTEXT_KEY);
|
||||
|
||||
Generator generator = new Generator(byteBufferPool, client.getMaxDynamicTableSize(), client.getMaxHeaderBlockFragment());
|
||||
Generator generator = new Generator(bufferPool, client.getMaxDynamicTableSize(), client.getMaxHeaderBlockFragment());
|
||||
FlowControlStrategy flowControl = client.getFlowControlStrategyFactory().newFlowControlStrategy();
|
||||
HTTP2ClientSession session = new HTTP2ClientSession(scheduler, endPoint, generator, listener, flowControl);
|
||||
session.setMaxRemoteStreams(client.getMaxConcurrentPushedStreams());
|
||||
|
@ -64,13 +63,11 @@ public class HTTP2ClientConnectionFactory implements ClientConnectionFactory
|
|||
if (streamIdleTimeout > 0)
|
||||
session.setStreamIdleTimeout(streamIdleTimeout);
|
||||
|
||||
Parser parser = new Parser(byteBufferPool, session, 4096, 8192);
|
||||
Parser parser = new Parser(bufferPool, session, 4096, 8192);
|
||||
parser.setMaxFrameLength(client.getMaxFrameLength());
|
||||
parser.setMaxSettingsKeys(client.getMaxSettingsKeys());
|
||||
|
||||
RetainableByteBufferPool retainableByteBufferPool = byteBufferPool.asRetainableByteBufferPool();
|
||||
|
||||
HTTP2ClientConnection connection = new HTTP2ClientConnection(client, retainableByteBufferPool, executor, endPoint,
|
||||
HTTP2ClientConnection connection = new HTTP2ClientConnection(client, bufferPool, executor, endPoint,
|
||||
parser, session, client.getInputBufferSize(), promise, listener);
|
||||
connection.setUseInputDirectByteBuffers(client.isUseInputDirectByteBuffers());
|
||||
connection.setUseOutputDirectByteBuffers(client.isUseOutputDirectByteBuffers());
|
||||
|
|
|
@ -313,10 +313,10 @@ public interface Stream
|
|||
* <p>It is always guaranteed that invoking {@link Stream#demand()}
|
||||
* from within this method will not cause a {@link StackOverflowError}.</p>
|
||||
* <p>Typical usage:</p>
|
||||
* <pre>
|
||||
* <pre>{@code
|
||||
* class MyStreamListener implements Stream.Listener
|
||||
* {
|
||||
* @Override
|
||||
* @Override
|
||||
* public void onDataAvailable(Stream stream)
|
||||
* {
|
||||
* // Read a chunk of the content.
|
||||
|
@ -329,7 +329,7 @@ public interface Stream
|
|||
* else
|
||||
* {
|
||||
* // Process the content.
|
||||
* process(data.getByteBuffer());
|
||||
* process(data.frame().getByteBuffer());
|
||||
* // Notify that the content has been consumed.
|
||||
* data.release();
|
||||
* if (!data.frame().isEndStream())
|
||||
|
@ -340,7 +340,7 @@ public interface Stream
|
|||
* }
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
* }</pre>
|
||||
*
|
||||
* @param stream the stream
|
||||
* @see Stream#demand()
|
||||
|
|
|
@ -39,7 +39,7 @@ public class DataFrame extends StreamFrame
|
|||
this.padding = padding;
|
||||
}
|
||||
|
||||
public ByteBuffer getData()
|
||||
public ByteBuffer getByteBuffer()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
@ -68,12 +68,12 @@ public class DataFrame extends StreamFrame
|
|||
@Override
|
||||
public DataFrame withStreamId(int streamId)
|
||||
{
|
||||
return new DataFrame(streamId, getData(), isEndStream());
|
||||
return new DataFrame(streamId, getByteBuffer(), isEndStream());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s#%d{length:%d,end=%b}", super.toString(), getStreamId(), data.remaining(), endStream);
|
||||
return String.format("%s#%d{length:%d,end=%b}", super.toString(), getStreamId(), remaining(), isEndStream());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -455,7 +455,7 @@ public class HTTP2Connection extends AbstractConnection implements WriteFlusher.
|
|||
|
||||
public ByteBuffer getBuffer()
|
||||
{
|
||||
return delegate.getBuffer();
|
||||
return delegate.getByteBuffer();
|
||||
}
|
||||
|
||||
public boolean isRetained()
|
||||
|
@ -494,7 +494,7 @@ public class HTTP2Connection extends AbstractConnection implements WriteFlusher.
|
|||
|
||||
private void put(ByteBuffer source)
|
||||
{
|
||||
BufferUtil.append(delegate.getBuffer(), source);
|
||||
BufferUtil.append(delegate.getByteBuffer(), source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,8 +30,8 @@ import org.eclipse.jetty.http2.frames.Frame;
|
|||
import org.eclipse.jetty.http2.frames.FrameType;
|
||||
import org.eclipse.jetty.http2.frames.WindowUpdateFrame;
|
||||
import org.eclipse.jetty.http2.hpack.HpackException;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.EofException;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.IteratingCallback;
|
||||
import org.eclipse.jetty.util.component.Dumpable;
|
||||
|
@ -51,7 +51,7 @@ public class HTTP2Flusher extends IteratingCallback implements Dumpable
|
|||
private final Queue<Entry> pendingEntries = new ArrayDeque<>();
|
||||
private final Collection<Entry> processedEntries = new ArrayList<>();
|
||||
private final HTTP2Session session;
|
||||
private final ByteBufferPool.Lease lease;
|
||||
private final RetainableByteBufferPool.Accumulator accumulator;
|
||||
private InvocationType invocationType = InvocationType.NON_BLOCKING;
|
||||
private Throwable terminated;
|
||||
private Entry stalledEntry;
|
||||
|
@ -59,7 +59,7 @@ public class HTTP2Flusher extends IteratingCallback implements Dumpable
|
|||
public HTTP2Flusher(HTTP2Session session)
|
||||
{
|
||||
this.session = session;
|
||||
this.lease = new ByteBufferPool.Lease(session.getGenerator().getByteBufferPool());
|
||||
this.accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -213,7 +213,7 @@ public class HTTP2Flusher extends IteratingCallback implements Dumpable
|
|||
|
||||
try
|
||||
{
|
||||
if (entry.generate(lease))
|
||||
if (entry.generate(accumulator))
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Generated {} frame bytes for {}", entry.getFrameBytesGenerated(), entry);
|
||||
|
@ -266,7 +266,7 @@ public class HTTP2Flusher extends IteratingCallback implements Dumpable
|
|||
break;
|
||||
|
||||
int writeThreshold = session.getWriteThreshold();
|
||||
if (lease.getTotalLength() >= writeThreshold)
|
||||
if (accumulator.getTotalLength() >= writeThreshold)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Write threshold {} exceeded", writeThreshold);
|
||||
|
@ -274,7 +274,7 @@ public class HTTP2Flusher extends IteratingCallback implements Dumpable
|
|||
}
|
||||
}
|
||||
|
||||
List<ByteBuffer> byteBuffers = lease.getByteBuffers();
|
||||
List<ByteBuffer> byteBuffers = accumulator.getByteBuffers();
|
||||
if (byteBuffers.isEmpty())
|
||||
{
|
||||
finish();
|
||||
|
@ -284,7 +284,7 @@ public class HTTP2Flusher extends IteratingCallback implements Dumpable
|
|||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Writing {} buffers ({} bytes) - entries processed/pending {}/{}: {}/{}",
|
||||
byteBuffers.size(),
|
||||
lease.getTotalLength(),
|
||||
accumulator.getTotalLength(),
|
||||
processedEntries.size(),
|
||||
pendingEntries.size(),
|
||||
processedEntries,
|
||||
|
@ -308,7 +308,7 @@ public class HTTP2Flusher extends IteratingCallback implements Dumpable
|
|||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Written {} buffers - entries processed/pending {}/{}: {}/{}",
|
||||
lease.getByteBuffers().size(),
|
||||
accumulator.getByteBuffers().size(),
|
||||
processedEntries.size(),
|
||||
pendingEntries.size(),
|
||||
processedEntries,
|
||||
|
@ -319,7 +319,7 @@ public class HTTP2Flusher extends IteratingCallback implements Dumpable
|
|||
|
||||
private void finish()
|
||||
{
|
||||
lease.recycle();
|
||||
accumulator.release();
|
||||
|
||||
processedEntries.forEach(Entry::succeeded);
|
||||
processedEntries.clear();
|
||||
|
@ -349,7 +349,7 @@ public class HTTP2Flusher extends IteratingCallback implements Dumpable
|
|||
@Override
|
||||
protected void onCompleteFailure(Throwable x)
|
||||
{
|
||||
lease.recycle();
|
||||
accumulator.release();
|
||||
|
||||
Throwable closed;
|
||||
Set<Entry> allEntries;
|
||||
|
@ -440,7 +440,7 @@ public class HTTP2Flusher extends IteratingCallback implements Dumpable
|
|||
return 0;
|
||||
}
|
||||
|
||||
protected abstract boolean generate(ByteBufferPool.Lease lease) throws HpackException;
|
||||
protected abstract boolean generate(RetainableByteBufferPool.Accumulator accumulator) throws HpackException;
|
||||
|
||||
public abstract long onFlushed(long bytes) throws IOException;
|
||||
|
||||
|
|
|
@ -57,9 +57,9 @@ import org.eclipse.jetty.http2.frames.WindowUpdateFrame;
|
|||
import org.eclipse.jetty.http2.hpack.HpackException;
|
||||
import org.eclipse.jetty.http2.internal.generator.Generator;
|
||||
import org.eclipse.jetty.http2.internal.parser.Parser;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.CyclicTimeouts;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.WriteFlusher;
|
||||
import org.eclipse.jetty.util.AtomicBiInteger;
|
||||
import org.eclipse.jetty.util.Atomics;
|
||||
|
@ -1206,9 +1206,9 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements Session
|
|||
}
|
||||
|
||||
@Override
|
||||
protected boolean generate(ByteBufferPool.Lease lease) throws HpackException
|
||||
protected boolean generate(RetainableByteBufferPool.Accumulator accumulator) throws HpackException
|
||||
{
|
||||
frameBytes = generator.control(lease, frame);
|
||||
frameBytes = generator.control(accumulator, frame);
|
||||
beforeSend();
|
||||
return true;
|
||||
}
|
||||
|
@ -1320,7 +1320,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements Session
|
|||
}
|
||||
|
||||
@Override
|
||||
protected boolean generate(ByteBufferPool.Lease lease)
|
||||
protected boolean generate(RetainableByteBufferPool.Accumulator accumulator)
|
||||
{
|
||||
int dataRemaining = getDataBytesRemaining();
|
||||
|
||||
|
@ -1334,7 +1334,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements Session
|
|||
|
||||
// Only one DATA frame is generated.
|
||||
DataFrame dataFrame = (DataFrame)frame;
|
||||
int frameBytes = generator.data(lease, dataFrame, length);
|
||||
int frameBytes = generator.data(accumulator, dataFrame, length);
|
||||
this.frameBytes += frameBytes;
|
||||
this.frameRemaining += frameBytes;
|
||||
|
||||
|
|
|
@ -215,7 +215,7 @@ public abstract class HTTP2StreamEndPoint implements EndPoint
|
|||
private int fillFromData(Stream.Data data, ByteBuffer sink)
|
||||
{
|
||||
int length = 0;
|
||||
ByteBuffer source = data.frame().getData();
|
||||
ByteBuffer source = data.frame().getByteBuffer();
|
||||
boolean hasContent = source.hasRemaining();
|
||||
if (hasContent)
|
||||
{
|
||||
|
|
|
@ -19,7 +19,8 @@ import org.eclipse.jetty.http2.frames.DataFrame;
|
|||
import org.eclipse.jetty.http2.frames.Frame;
|
||||
import org.eclipse.jetty.http2.frames.FrameType;
|
||||
import org.eclipse.jetty.http2.internal.Flags;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
||||
public class DataGenerator
|
||||
|
@ -31,12 +32,12 @@ public class DataGenerator
|
|||
this.headerGenerator = headerGenerator;
|
||||
}
|
||||
|
||||
public int generate(ByteBufferPool.Lease lease, DataFrame frame, int maxLength)
|
||||
public int generate(RetainableByteBufferPool.Accumulator accumulator, DataFrame frame, int maxLength)
|
||||
{
|
||||
return generateData(lease, frame.getStreamId(), frame.getData(), frame.isEndStream(), maxLength);
|
||||
return generateData(accumulator, frame.getStreamId(), frame.getByteBuffer(), frame.isEndStream(), maxLength);
|
||||
}
|
||||
|
||||
public int generateData(ByteBufferPool.Lease lease, int streamId, ByteBuffer data, boolean last, int maxLength)
|
||||
public int generateData(RetainableByteBufferPool.Accumulator accumulator, int streamId, ByteBuffer data, boolean last, int maxLength)
|
||||
{
|
||||
if (streamId < 0)
|
||||
throw new IllegalArgumentException("Invalid stream id: " + streamId);
|
||||
|
@ -46,7 +47,7 @@ public class DataGenerator
|
|||
int length = Math.min(dataLength, Math.min(maxFrameSize, maxLength));
|
||||
if (length == dataLength)
|
||||
{
|
||||
generateFrame(lease, streamId, data, last);
|
||||
generateFrame(accumulator, streamId, data, last);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -56,12 +57,12 @@ public class DataGenerator
|
|||
ByteBuffer slice = data.slice();
|
||||
data.position(newLimit);
|
||||
data.limit(limit);
|
||||
generateFrame(lease, streamId, slice, false);
|
||||
generateFrame(accumulator, streamId, slice, false);
|
||||
}
|
||||
return Frame.HEADER_LENGTH + length;
|
||||
}
|
||||
|
||||
private void generateFrame(ByteBufferPool.Lease lease, int streamId, ByteBuffer data, boolean last)
|
||||
private void generateFrame(RetainableByteBufferPool.Accumulator accumulator, int streamId, ByteBuffer data, boolean last)
|
||||
{
|
||||
int length = data.remaining();
|
||||
|
||||
|
@ -69,11 +70,11 @@ public class DataGenerator
|
|||
if (last)
|
||||
flags |= Flags.END_STREAM;
|
||||
|
||||
ByteBuffer header = headerGenerator.generate(lease, FrameType.DATA, Frame.HEADER_LENGTH + length, length, flags, streamId);
|
||||
BufferUtil.flipToFlush(header, 0);
|
||||
lease.append(header, true);
|
||||
RetainableByteBuffer header = headerGenerator.generate(FrameType.DATA, Frame.HEADER_LENGTH + length, length, flags, streamId);
|
||||
BufferUtil.flipToFlush(header.getByteBuffer(), 0);
|
||||
accumulator.append(header);
|
||||
// Skip empty data buffers.
|
||||
if (data.remaining() > 0)
|
||||
lease.append(data, false);
|
||||
accumulator.append(RetainableByteBuffer.wrap(data));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,9 @@ import org.eclipse.jetty.http2.frames.Frame;
|
|||
import org.eclipse.jetty.http2.frames.FrameType;
|
||||
import org.eclipse.jetty.http2.hpack.HpackEncoder;
|
||||
import org.eclipse.jetty.http2.hpack.HpackException;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
||||
public abstract class FrameGenerator
|
||||
{
|
||||
|
@ -31,11 +33,11 @@ public abstract class FrameGenerator
|
|||
this.headerGenerator = headerGenerator;
|
||||
}
|
||||
|
||||
public abstract int generate(ByteBufferPool.Lease lease, Frame frame) throws HpackException;
|
||||
public abstract int generate(RetainableByteBufferPool.Accumulator accumulator, Frame frame) throws HpackException;
|
||||
|
||||
protected ByteBuffer generateHeader(ByteBufferPool.Lease lease, FrameType frameType, int length, int flags, int streamId)
|
||||
protected RetainableByteBuffer generateHeader(FrameType frameType, int length, int flags, int streamId)
|
||||
{
|
||||
return headerGenerator.generate(lease, frameType, Frame.HEADER_LENGTH + length, length, flags, streamId);
|
||||
return headerGenerator.generate(frameType, Frame.HEADER_LENGTH + length, length, flags, streamId);
|
||||
}
|
||||
|
||||
public int getMaxFrameSize()
|
||||
|
@ -48,17 +50,19 @@ public abstract class FrameGenerator
|
|||
return headerGenerator.isUseDirectByteBuffers();
|
||||
}
|
||||
|
||||
protected ByteBuffer encode(HpackEncoder encoder, ByteBufferPool.Lease lease, MetaData metaData, int maxFrameSize) throws HpackException
|
||||
protected RetainableByteBuffer encode(HpackEncoder encoder, MetaData metaData, int maxFrameSize) throws HpackException
|
||||
{
|
||||
ByteBuffer hpacked = lease.acquire(maxFrameSize, isUseDirectByteBuffers());
|
||||
RetainableByteBuffer hpacked = headerGenerator.getRetainableByteBufferPool().acquire(maxFrameSize, isUseDirectByteBuffers());
|
||||
try
|
||||
{
|
||||
encoder.encode(hpacked, metaData);
|
||||
ByteBuffer byteBuffer = hpacked.getByteBuffer();
|
||||
BufferUtil.clearToFill(byteBuffer);
|
||||
encoder.encode(byteBuffer, metaData);
|
||||
return hpacked;
|
||||
}
|
||||
catch (HpackException x)
|
||||
{
|
||||
lease.release(hpacked);
|
||||
hpacked.release();
|
||||
throw x;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,31 +18,31 @@ import org.eclipse.jetty.http2.frames.Frame;
|
|||
import org.eclipse.jetty.http2.frames.FrameType;
|
||||
import org.eclipse.jetty.http2.hpack.HpackEncoder;
|
||||
import org.eclipse.jetty.http2.hpack.HpackException;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
|
||||
public class Generator
|
||||
{
|
||||
private final ByteBufferPool byteBufferPool;
|
||||
private final RetainableByteBufferPool bufferPool;
|
||||
private final HeaderGenerator headerGenerator;
|
||||
private final HpackEncoder hpackEncoder;
|
||||
private final FrameGenerator[] generators;
|
||||
private final DataGenerator dataGenerator;
|
||||
|
||||
public Generator(ByteBufferPool byteBufferPool)
|
||||
public Generator(RetainableByteBufferPool bufferPool)
|
||||
{
|
||||
this(byteBufferPool, 4096, 0);
|
||||
this(bufferPool, 4096, 0);
|
||||
}
|
||||
|
||||
public Generator(ByteBufferPool byteBufferPool, int maxDynamicTableSize, int maxHeaderBlockFragment)
|
||||
public Generator(RetainableByteBufferPool bufferPool, int maxDynamicTableSize, int maxHeaderBlockFragment)
|
||||
{
|
||||
this(byteBufferPool, true, maxDynamicTableSize, maxHeaderBlockFragment);
|
||||
this(bufferPool, true, maxDynamicTableSize, maxHeaderBlockFragment);
|
||||
}
|
||||
|
||||
public Generator(ByteBufferPool byteBufferPool, boolean useDirectByteBuffers, int maxDynamicTableSize, int maxHeaderBlockFragment)
|
||||
public Generator(RetainableByteBufferPool bufferPool, boolean useDirectByteBuffers, int maxDynamicTableSize, int maxHeaderBlockFragment)
|
||||
{
|
||||
this.byteBufferPool = byteBufferPool;
|
||||
this.bufferPool = bufferPool;
|
||||
|
||||
headerGenerator = new HeaderGenerator(useDirectByteBuffers);
|
||||
headerGenerator = new HeaderGenerator(bufferPool, useDirectByteBuffers);
|
||||
hpackEncoder = new HpackEncoder(maxDynamicTableSize);
|
||||
|
||||
this.generators = new FrameGenerator[FrameType.values().length];
|
||||
|
@ -61,9 +61,9 @@ public class Generator
|
|||
this.dataGenerator = new DataGenerator(headerGenerator);
|
||||
}
|
||||
|
||||
public ByteBufferPool getByteBufferPool()
|
||||
public RetainableByteBufferPool getRetainableByteBufferPool()
|
||||
{
|
||||
return byteBufferPool;
|
||||
return bufferPool;
|
||||
}
|
||||
|
||||
public void setValidateHpackEncoding(boolean validateEncoding)
|
||||
|
@ -81,14 +81,14 @@ public class Generator
|
|||
headerGenerator.setMaxFrameSize(maxFrameSize);
|
||||
}
|
||||
|
||||
public int control(ByteBufferPool.Lease lease, Frame frame) throws HpackException
|
||||
public int control(RetainableByteBufferPool.Accumulator accumulator, Frame frame) throws HpackException
|
||||
{
|
||||
return generators[frame.getType().getType()].generate(lease, frame);
|
||||
return generators[frame.getType().getType()].generate(accumulator, frame);
|
||||
}
|
||||
|
||||
public int data(ByteBufferPool.Lease lease, DataFrame frame, int maxLength)
|
||||
public int data(RetainableByteBufferPool.Accumulator accumulator, DataFrame frame, int maxLength)
|
||||
{
|
||||
return dataGenerator.generate(lease, frame, maxLength);
|
||||
return dataGenerator.generate(accumulator, frame, maxLength);
|
||||
}
|
||||
|
||||
public void setMaxHeaderListSize(int value)
|
||||
|
|
|
@ -20,7 +20,8 @@ import org.eclipse.jetty.http2.frames.Frame;
|
|||
import org.eclipse.jetty.http2.frames.FrameType;
|
||||
import org.eclipse.jetty.http2.frames.GoAwayFrame;
|
||||
import org.eclipse.jetty.http2.internal.Flags;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
||||
public class GoAwayGenerator extends FrameGenerator
|
||||
|
@ -31,13 +32,13 @@ public class GoAwayGenerator extends FrameGenerator
|
|||
}
|
||||
|
||||
@Override
|
||||
public int generate(ByteBufferPool.Lease lease, Frame frame)
|
||||
public int generate(RetainableByteBufferPool.Accumulator accumulator, Frame frame)
|
||||
{
|
||||
GoAwayFrame goAwayFrame = (GoAwayFrame)frame;
|
||||
return generateGoAway(lease, goAwayFrame.getLastStreamId(), goAwayFrame.getError(), goAwayFrame.getPayload());
|
||||
return generateGoAway(accumulator, goAwayFrame.getLastStreamId(), goAwayFrame.getError(), goAwayFrame.getPayload());
|
||||
}
|
||||
|
||||
public int generateGoAway(ByteBufferPool.Lease lease, int lastStreamId, int error, byte[] payload)
|
||||
public int generateGoAway(RetainableByteBufferPool.Accumulator accumulator, int lastStreamId, int error, byte[] payload)
|
||||
{
|
||||
if (lastStreamId < 0)
|
||||
lastStreamId = 0;
|
||||
|
@ -51,16 +52,17 @@ public class GoAwayGenerator extends FrameGenerator
|
|||
payload = Arrays.copyOfRange(payload, 0, maxPayloadLength);
|
||||
|
||||
int length = fixedLength + (payload != null ? payload.length : 0);
|
||||
ByteBuffer header = generateHeader(lease, FrameType.GO_AWAY, length, Flags.NONE, 0);
|
||||
RetainableByteBuffer header = generateHeader(FrameType.GO_AWAY, length, Flags.NONE, 0);
|
||||
ByteBuffer byteBuffer = header.getByteBuffer();
|
||||
|
||||
header.putInt(lastStreamId);
|
||||
header.putInt(error);
|
||||
byteBuffer.putInt(lastStreamId);
|
||||
byteBuffer.putInt(error);
|
||||
|
||||
if (payload != null)
|
||||
header.put(payload);
|
||||
byteBuffer.put(payload);
|
||||
|
||||
BufferUtil.flipToFlush(header, 0);
|
||||
lease.append(header, true);
|
||||
BufferUtil.flipToFlush(byteBuffer, 0);
|
||||
accumulator.append(header);
|
||||
|
||||
return Frame.HEADER_LENGTH + length;
|
||||
}
|
||||
|
|
|
@ -17,38 +17,49 @@ import java.nio.ByteBuffer;
|
|||
|
||||
import org.eclipse.jetty.http2.frames.Frame;
|
||||
import org.eclipse.jetty.http2.frames.FrameType;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
||||
public class HeaderGenerator
|
||||
{
|
||||
private int maxFrameSize = Frame.DEFAULT_MAX_LENGTH;
|
||||
private final RetainableByteBufferPool bufferPool;
|
||||
private final boolean useDirectByteBuffers;
|
||||
|
||||
public HeaderGenerator()
|
||||
public HeaderGenerator(RetainableByteBufferPool bufferPool)
|
||||
{
|
||||
this(true);
|
||||
this(bufferPool, true);
|
||||
}
|
||||
|
||||
public HeaderGenerator(boolean useDirectByteBuffers)
|
||||
public HeaderGenerator(RetainableByteBufferPool bufferPool, boolean useDirectByteBuffers)
|
||||
{
|
||||
this.bufferPool = bufferPool;
|
||||
this.useDirectByteBuffers = useDirectByteBuffers;
|
||||
}
|
||||
|
||||
public RetainableByteBufferPool getRetainableByteBufferPool()
|
||||
{
|
||||
return bufferPool;
|
||||
}
|
||||
|
||||
public boolean isUseDirectByteBuffers()
|
||||
{
|
||||
return useDirectByteBuffers;
|
||||
}
|
||||
|
||||
public ByteBuffer generate(ByteBufferPool.Lease lease, FrameType frameType, int capacity, int length, int flags, int streamId)
|
||||
public RetainableByteBuffer generate(FrameType frameType, int capacity, int length, int flags, int streamId)
|
||||
{
|
||||
ByteBuffer header = lease.acquire(capacity, isUseDirectByteBuffers());
|
||||
RetainableByteBuffer buffer = getRetainableByteBufferPool().acquire(capacity, isUseDirectByteBuffers());
|
||||
ByteBuffer header = buffer.getByteBuffer();
|
||||
BufferUtil.clearToFill(header);
|
||||
header.put((byte)((length & 0x00_FF_00_00) >>> 16));
|
||||
header.put((byte)((length & 0x00_00_FF_00) >>> 8));
|
||||
header.put((byte)((length & 0x00_00_00_FF)));
|
||||
header.put((byte)frameType.getType());
|
||||
header.put((byte)flags);
|
||||
header.putInt(streamId);
|
||||
return header;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public int getMaxFrameSize()
|
||||
|
|
|
@ -23,7 +23,8 @@ import org.eclipse.jetty.http2.frames.PriorityFrame;
|
|||
import org.eclipse.jetty.http2.hpack.HpackEncoder;
|
||||
import org.eclipse.jetty.http2.hpack.HpackException;
|
||||
import org.eclipse.jetty.http2.internal.Flags;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
||||
public class HeadersGenerator extends FrameGenerator
|
||||
|
@ -46,13 +47,13 @@ public class HeadersGenerator extends FrameGenerator
|
|||
}
|
||||
|
||||
@Override
|
||||
public int generate(ByteBufferPool.Lease lease, Frame frame) throws HpackException
|
||||
public int generate(RetainableByteBufferPool.Accumulator accumulator, Frame frame) throws HpackException
|
||||
{
|
||||
HeadersFrame headersFrame = (HeadersFrame)frame;
|
||||
return generateHeaders(lease, headersFrame.getStreamId(), headersFrame.getMetaData(), headersFrame.getPriority(), headersFrame.isEndStream());
|
||||
return generateHeaders(accumulator, headersFrame.getStreamId(), headersFrame.getMetaData(), headersFrame.getPriority(), headersFrame.isEndStream());
|
||||
}
|
||||
|
||||
public int generateHeaders(ByteBufferPool.Lease lease, int streamId, MetaData metaData, PriorityFrame priority, boolean endStream) throws HpackException
|
||||
public int generateHeaders(RetainableByteBufferPool.Accumulator accumulator, int streamId, MetaData metaData, PriorityFrame priority, boolean endStream) throws HpackException
|
||||
{
|
||||
if (streamId < 0)
|
||||
throw new IllegalArgumentException("Invalid stream id: " + streamId);
|
||||
|
@ -62,12 +63,13 @@ public class HeadersGenerator extends FrameGenerator
|
|||
if (priority != null)
|
||||
flags = Flags.PRIORITY;
|
||||
|
||||
ByteBuffer hpacked = encode(encoder, lease, metaData, getMaxFrameSize());
|
||||
int hpackedLength = hpacked.position();
|
||||
BufferUtil.flipToFlush(hpacked, 0);
|
||||
RetainableByteBuffer hpack = encode(encoder, metaData, getMaxFrameSize());
|
||||
ByteBuffer hpackByteBuffer = hpack.getByteBuffer();
|
||||
int hpackLength = hpackByteBuffer.position();
|
||||
BufferUtil.flipToFlush(hpackByteBuffer, 0);
|
||||
|
||||
// Split into CONTINUATION frames if necessary.
|
||||
if (maxHeaderBlockFragment > 0 && hpackedLength > maxHeaderBlockFragment)
|
||||
if (maxHeaderBlockFragment > 0 && hpackLength > maxHeaderBlockFragment)
|
||||
{
|
||||
if (endStream)
|
||||
flags |= Flags.END_STREAM;
|
||||
|
@ -76,35 +78,38 @@ public class HeadersGenerator extends FrameGenerator
|
|||
if (priority != null)
|
||||
length += PriorityFrame.PRIORITY_LENGTH;
|
||||
|
||||
ByteBuffer header = generateHeader(lease, FrameType.HEADERS, length, flags, streamId);
|
||||
generatePriority(header, priority);
|
||||
BufferUtil.flipToFlush(header, 0);
|
||||
lease.append(header, true);
|
||||
hpacked.limit(maxHeaderBlockFragment);
|
||||
lease.append(hpacked.slice(), false);
|
||||
RetainableByteBuffer header = generateHeader(FrameType.HEADERS, length, flags, streamId);
|
||||
ByteBuffer headerByteBuffer = header.getByteBuffer();
|
||||
generatePriority(headerByteBuffer, priority);
|
||||
BufferUtil.flipToFlush(headerByteBuffer, 0);
|
||||
accumulator.append(header);
|
||||
hpackByteBuffer.limit(maxHeaderBlockFragment);
|
||||
accumulator.append(RetainableByteBuffer.wrap(hpackByteBuffer.slice()));
|
||||
|
||||
int totalLength = Frame.HEADER_LENGTH + length;
|
||||
|
||||
int position = maxHeaderBlockFragment;
|
||||
int limit = position + maxHeaderBlockFragment;
|
||||
while (limit < hpackedLength)
|
||||
while (limit < hpackLength)
|
||||
{
|
||||
hpacked.position(position).limit(limit);
|
||||
header = generateHeader(lease, FrameType.CONTINUATION, maxHeaderBlockFragment, Flags.NONE, streamId);
|
||||
BufferUtil.flipToFlush(header, 0);
|
||||
lease.append(header, true);
|
||||
lease.append(hpacked.slice(), false);
|
||||
hpackByteBuffer.position(position).limit(limit);
|
||||
header = generateHeader(FrameType.CONTINUATION, maxHeaderBlockFragment, Flags.NONE, streamId);
|
||||
headerByteBuffer = header.getByteBuffer();
|
||||
BufferUtil.flipToFlush(headerByteBuffer, 0);
|
||||
accumulator.append(header);
|
||||
accumulator.append(RetainableByteBuffer.wrap(hpackByteBuffer.slice()));
|
||||
position += maxHeaderBlockFragment;
|
||||
limit += maxHeaderBlockFragment;
|
||||
totalLength += Frame.HEADER_LENGTH + maxHeaderBlockFragment;
|
||||
}
|
||||
|
||||
hpacked.position(position).limit(hpackedLength);
|
||||
header = generateHeader(lease, FrameType.CONTINUATION, hpacked.remaining(), Flags.END_HEADERS, streamId);
|
||||
BufferUtil.flipToFlush(header, 0);
|
||||
lease.append(header, true);
|
||||
lease.append(hpacked, true);
|
||||
totalLength += Frame.HEADER_LENGTH + hpacked.remaining();
|
||||
hpackByteBuffer.position(position).limit(hpackLength);
|
||||
header = generateHeader(FrameType.CONTINUATION, hpack.remaining(), Flags.END_HEADERS, streamId);
|
||||
headerByteBuffer = header.getByteBuffer();
|
||||
BufferUtil.flipToFlush(headerByteBuffer, 0);
|
||||
accumulator.append(header);
|
||||
accumulator.append(hpack);
|
||||
totalLength += Frame.HEADER_LENGTH + hpack.remaining();
|
||||
|
||||
return totalLength;
|
||||
}
|
||||
|
@ -114,15 +119,16 @@ public class HeadersGenerator extends FrameGenerator
|
|||
if (endStream)
|
||||
flags |= Flags.END_STREAM;
|
||||
|
||||
int length = hpackedLength;
|
||||
int length = hpackLength;
|
||||
if (priority != null)
|
||||
length += PriorityFrame.PRIORITY_LENGTH;
|
||||
|
||||
ByteBuffer header = generateHeader(lease, FrameType.HEADERS, length, flags, streamId);
|
||||
generatePriority(header, priority);
|
||||
BufferUtil.flipToFlush(header, 0);
|
||||
lease.append(header, true);
|
||||
lease.append(hpacked, true);
|
||||
RetainableByteBuffer header = generateHeader(FrameType.HEADERS, length, flags, streamId);
|
||||
ByteBuffer headerByteBuffer = header.getByteBuffer();
|
||||
generatePriority(headerByteBuffer, priority);
|
||||
BufferUtil.flipToFlush(headerByteBuffer, 0);
|
||||
accumulator.append(header);
|
||||
accumulator.append(hpack);
|
||||
|
||||
return Frame.HEADER_LENGTH + length;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
package org.eclipse.jetty.http2.internal.generator;
|
||||
|
||||
import org.eclipse.jetty.http2.frames.Frame;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
|
||||
public class NoOpGenerator extends FrameGenerator
|
||||
{
|
||||
|
@ -24,7 +24,7 @@ public class NoOpGenerator extends FrameGenerator
|
|||
}
|
||||
|
||||
@Override
|
||||
public int generate(ByteBufferPool.Lease lease, Frame frame)
|
||||
public int generate(RetainableByteBufferPool.Accumulator accumulator, Frame frame)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,8 @@ import org.eclipse.jetty.http2.frames.Frame;
|
|||
import org.eclipse.jetty.http2.frames.FrameType;
|
||||
import org.eclipse.jetty.http2.frames.PingFrame;
|
||||
import org.eclipse.jetty.http2.internal.Flags;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
||||
public class PingGenerator extends FrameGenerator
|
||||
|
@ -30,23 +31,24 @@ public class PingGenerator extends FrameGenerator
|
|||
}
|
||||
|
||||
@Override
|
||||
public int generate(ByteBufferPool.Lease lease, Frame frame)
|
||||
public int generate(RetainableByteBufferPool.Accumulator accumulator, Frame frame)
|
||||
{
|
||||
PingFrame pingFrame = (PingFrame)frame;
|
||||
return generatePing(lease, pingFrame.getPayload(), pingFrame.isReply());
|
||||
return generatePing(accumulator, pingFrame.getPayload(), pingFrame.isReply());
|
||||
}
|
||||
|
||||
public int generatePing(ByteBufferPool.Lease lease, byte[] payload, boolean reply)
|
||||
public int generatePing(RetainableByteBufferPool.Accumulator accumulator, byte[] payload, boolean reply)
|
||||
{
|
||||
if (payload.length != PingFrame.PING_LENGTH)
|
||||
throw new IllegalArgumentException("Invalid payload length: " + payload.length);
|
||||
|
||||
ByteBuffer header = generateHeader(lease, FrameType.PING, PingFrame.PING_LENGTH, reply ? Flags.ACK : Flags.NONE, 0);
|
||||
RetainableByteBuffer header = generateHeader(FrameType.PING, PingFrame.PING_LENGTH, reply ? Flags.ACK : Flags.NONE, 0);
|
||||
ByteBuffer byteBuffer = header.getByteBuffer();
|
||||
|
||||
header.put(payload);
|
||||
byteBuffer.put(payload);
|
||||
|
||||
BufferUtil.flipToFlush(header, 0);
|
||||
lease.append(header, true);
|
||||
BufferUtil.flipToFlush(byteBuffer, 0);
|
||||
accumulator.append(header);
|
||||
|
||||
return Frame.HEADER_LENGTH + PingFrame.PING_LENGTH;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,8 @@ import java.nio.ByteBuffer;
|
|||
|
||||
import org.eclipse.jetty.http2.frames.Frame;
|
||||
import org.eclipse.jetty.http2.frames.PrefaceFrame;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
|
||||
public class PrefaceGenerator extends FrameGenerator
|
||||
{
|
||||
|
@ -27,9 +28,9 @@ public class PrefaceGenerator extends FrameGenerator
|
|||
}
|
||||
|
||||
@Override
|
||||
public int generate(ByteBufferPool.Lease lease, Frame frame)
|
||||
public int generate(RetainableByteBufferPool.Accumulator accumulator, Frame frame)
|
||||
{
|
||||
lease.append(ByteBuffer.wrap(PrefaceFrame.PREFACE_BYTES), false);
|
||||
accumulator.append(RetainableByteBuffer.wrap(ByteBuffer.wrap(PrefaceFrame.PREFACE_BYTES)));
|
||||
return PrefaceFrame.PREFACE_BYTES.length;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,8 @@ import org.eclipse.jetty.http2.frames.Frame;
|
|||
import org.eclipse.jetty.http2.frames.FrameType;
|
||||
import org.eclipse.jetty.http2.frames.PriorityFrame;
|
||||
import org.eclipse.jetty.http2.internal.Flags;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
||||
public class PriorityGenerator extends FrameGenerator
|
||||
|
@ -30,18 +31,19 @@ public class PriorityGenerator extends FrameGenerator
|
|||
}
|
||||
|
||||
@Override
|
||||
public int generate(ByteBufferPool.Lease lease, Frame frame)
|
||||
public int generate(RetainableByteBufferPool.Accumulator accumulator, Frame frame)
|
||||
{
|
||||
PriorityFrame priorityFrame = (PriorityFrame)frame;
|
||||
return generatePriority(lease, priorityFrame.getStreamId(), priorityFrame.getParentStreamId(), priorityFrame.getWeight(), priorityFrame.isExclusive());
|
||||
return generatePriority(accumulator, priorityFrame.getStreamId(), priorityFrame.getParentStreamId(), priorityFrame.getWeight(), priorityFrame.isExclusive());
|
||||
}
|
||||
|
||||
public int generatePriority(ByteBufferPool.Lease lease, int streamId, int parentStreamId, int weight, boolean exclusive)
|
||||
public int generatePriority(RetainableByteBufferPool.Accumulator accumulator, int streamId, int parentStreamId, int weight, boolean exclusive)
|
||||
{
|
||||
ByteBuffer header = generateHeader(lease, FrameType.PRIORITY, PriorityFrame.PRIORITY_LENGTH, Flags.NONE, streamId);
|
||||
generatePriorityBody(header, streamId, parentStreamId, weight, exclusive);
|
||||
BufferUtil.flipToFlush(header, 0);
|
||||
lease.append(header, true);
|
||||
RetainableByteBuffer header = generateHeader(FrameType.PRIORITY, PriorityFrame.PRIORITY_LENGTH, Flags.NONE, streamId);
|
||||
ByteBuffer byteBuffer = header.getByteBuffer();
|
||||
generatePriorityBody(byteBuffer, streamId, parentStreamId, weight, exclusive);
|
||||
BufferUtil.flipToFlush(byteBuffer, 0);
|
||||
accumulator.append(header);
|
||||
return Frame.HEADER_LENGTH + PriorityFrame.PRIORITY_LENGTH;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,8 @@ import org.eclipse.jetty.http2.frames.PushPromiseFrame;
|
|||
import org.eclipse.jetty.http2.hpack.HpackEncoder;
|
||||
import org.eclipse.jetty.http2.hpack.HpackException;
|
||||
import org.eclipse.jetty.http2.internal.Flags;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
||||
public class PushPromiseGenerator extends FrameGenerator
|
||||
|
@ -36,13 +37,13 @@ public class PushPromiseGenerator extends FrameGenerator
|
|||
}
|
||||
|
||||
@Override
|
||||
public int generate(ByteBufferPool.Lease lease, Frame frame) throws HpackException
|
||||
public int generate(RetainableByteBufferPool.Accumulator accumulator, Frame frame) throws HpackException
|
||||
{
|
||||
PushPromiseFrame pushPromiseFrame = (PushPromiseFrame)frame;
|
||||
return generatePushPromise(lease, pushPromiseFrame.getStreamId(), pushPromiseFrame.getPromisedStreamId(), pushPromiseFrame.getMetaData());
|
||||
return generatePushPromise(accumulator, pushPromiseFrame.getStreamId(), pushPromiseFrame.getPromisedStreamId(), pushPromiseFrame.getMetaData());
|
||||
}
|
||||
|
||||
public int generatePushPromise(ByteBufferPool.Lease lease, int streamId, int promisedStreamId, MetaData metaData) throws HpackException
|
||||
public int generatePushPromise(RetainableByteBufferPool.Accumulator accumulator, int streamId, int promisedStreamId, MetaData metaData) throws HpackException
|
||||
{
|
||||
if (streamId < 0)
|
||||
throw new IllegalArgumentException("Invalid stream id: " + streamId);
|
||||
|
@ -54,19 +55,21 @@ public class PushPromiseGenerator extends FrameGenerator
|
|||
int extraSpace = 4;
|
||||
maxFrameSize -= extraSpace;
|
||||
|
||||
ByteBuffer hpacked = encode(encoder, lease, metaData, maxFrameSize);
|
||||
int hpackedLength = hpacked.position();
|
||||
BufferUtil.flipToFlush(hpacked, 0);
|
||||
RetainableByteBuffer hpack = encode(encoder, metaData, maxFrameSize);
|
||||
ByteBuffer hpackByteBuffer = hpack.getByteBuffer();
|
||||
int hpackLength = hpackByteBuffer.position();
|
||||
BufferUtil.flipToFlush(hpackByteBuffer, 0);
|
||||
|
||||
int length = hpackedLength + extraSpace;
|
||||
int length = hpackLength + extraSpace;
|
||||
int flags = Flags.END_HEADERS;
|
||||
|
||||
ByteBuffer header = generateHeader(lease, FrameType.PUSH_PROMISE, length, flags, streamId);
|
||||
header.putInt(promisedStreamId);
|
||||
BufferUtil.flipToFlush(header, 0);
|
||||
RetainableByteBuffer header = generateHeader(FrameType.PUSH_PROMISE, length, flags, streamId);
|
||||
ByteBuffer headerByteBuffer = header.getByteBuffer();
|
||||
headerByteBuffer.putInt(promisedStreamId);
|
||||
BufferUtil.flipToFlush(headerByteBuffer, 0);
|
||||
|
||||
lease.append(header, true);
|
||||
lease.append(hpacked, true);
|
||||
accumulator.append(header);
|
||||
accumulator.append(hpack);
|
||||
|
||||
return Frame.HEADER_LENGTH + length;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,8 @@ import org.eclipse.jetty.http2.frames.Frame;
|
|||
import org.eclipse.jetty.http2.frames.FrameType;
|
||||
import org.eclipse.jetty.http2.frames.ResetFrame;
|
||||
import org.eclipse.jetty.http2.internal.Flags;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
||||
public class ResetGenerator extends FrameGenerator
|
||||
|
@ -30,21 +31,22 @@ public class ResetGenerator extends FrameGenerator
|
|||
}
|
||||
|
||||
@Override
|
||||
public int generate(ByteBufferPool.Lease lease, Frame frame)
|
||||
public int generate(RetainableByteBufferPool.Accumulator accumulator, Frame frame)
|
||||
{
|
||||
ResetFrame resetFrame = (ResetFrame)frame;
|
||||
return generateReset(lease, resetFrame.getStreamId(), resetFrame.getError());
|
||||
return generateReset(accumulator, resetFrame.getStreamId(), resetFrame.getError());
|
||||
}
|
||||
|
||||
public int generateReset(ByteBufferPool.Lease lease, int streamId, int error)
|
||||
public int generateReset(RetainableByteBufferPool.Accumulator accumulator, int streamId, int error)
|
||||
{
|
||||
if (streamId < 0)
|
||||
throw new IllegalArgumentException("Invalid stream id: " + streamId);
|
||||
|
||||
ByteBuffer header = generateHeader(lease, FrameType.RST_STREAM, ResetFrame.RESET_LENGTH, Flags.NONE, streamId);
|
||||
header.putInt(error);
|
||||
BufferUtil.flipToFlush(header, 0);
|
||||
lease.append(header, true);
|
||||
RetainableByteBuffer header = generateHeader(FrameType.RST_STREAM, ResetFrame.RESET_LENGTH, Flags.NONE, streamId);
|
||||
ByteBuffer byteBuffer = header.getByteBuffer();
|
||||
byteBuffer.putInt(error);
|
||||
BufferUtil.flipToFlush(byteBuffer, 0);
|
||||
accumulator.append(header);
|
||||
|
||||
return Frame.HEADER_LENGTH + ResetFrame.RESET_LENGTH;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,8 @@ import org.eclipse.jetty.http2.frames.Frame;
|
|||
import org.eclipse.jetty.http2.frames.FrameType;
|
||||
import org.eclipse.jetty.http2.frames.SettingsFrame;
|
||||
import org.eclipse.jetty.http2.internal.Flags;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
||||
public class SettingsGenerator extends FrameGenerator
|
||||
|
@ -31,13 +32,13 @@ public class SettingsGenerator extends FrameGenerator
|
|||
}
|
||||
|
||||
@Override
|
||||
public int generate(ByteBufferPool.Lease lease, Frame frame)
|
||||
public int generate(RetainableByteBufferPool.Accumulator accumulator, Frame frame)
|
||||
{
|
||||
SettingsFrame settingsFrame = (SettingsFrame)frame;
|
||||
return generateSettings(lease, settingsFrame.getSettings(), settingsFrame.isReply());
|
||||
return generateSettings(accumulator, settingsFrame.getSettings(), settingsFrame.isReply());
|
||||
}
|
||||
|
||||
public int generateSettings(ByteBufferPool.Lease lease, Map<Integer, Integer> settings, boolean reply)
|
||||
public int generateSettings(RetainableByteBufferPool.Accumulator accumulator, Map<Integer, Integer> settings, boolean reply)
|
||||
{
|
||||
// Two bytes for the identifier, four bytes for the value.
|
||||
int entryLength = 2 + 4;
|
||||
|
@ -45,16 +46,17 @@ public class SettingsGenerator extends FrameGenerator
|
|||
if (length > getMaxFrameSize())
|
||||
throw new IllegalArgumentException("Invalid settings, too big");
|
||||
|
||||
ByteBuffer header = generateHeader(lease, FrameType.SETTINGS, length, reply ? Flags.ACK : Flags.NONE, 0);
|
||||
RetainableByteBuffer header = generateHeader(FrameType.SETTINGS, length, reply ? Flags.ACK : Flags.NONE, 0);
|
||||
ByteBuffer byteBuffer = header.getByteBuffer();
|
||||
|
||||
for (Map.Entry<Integer, Integer> entry : settings.entrySet())
|
||||
{
|
||||
header.putShort(entry.getKey().shortValue());
|
||||
header.putInt(entry.getValue());
|
||||
byteBuffer.putShort(entry.getKey().shortValue());
|
||||
byteBuffer.putInt(entry.getValue());
|
||||
}
|
||||
|
||||
BufferUtil.flipToFlush(header, 0);
|
||||
lease.append(header, true);
|
||||
BufferUtil.flipToFlush(byteBuffer, 0);
|
||||
accumulator.append(header);
|
||||
|
||||
return Frame.HEADER_LENGTH + length;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,8 @@ import org.eclipse.jetty.http2.frames.Frame;
|
|||
import org.eclipse.jetty.http2.frames.FrameType;
|
||||
import org.eclipse.jetty.http2.frames.WindowUpdateFrame;
|
||||
import org.eclipse.jetty.http2.internal.Flags;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
||||
public class WindowUpdateGenerator extends FrameGenerator
|
||||
|
@ -30,21 +31,22 @@ public class WindowUpdateGenerator extends FrameGenerator
|
|||
}
|
||||
|
||||
@Override
|
||||
public int generate(ByteBufferPool.Lease lease, Frame frame)
|
||||
public int generate(RetainableByteBufferPool.Accumulator accumulator, Frame frame)
|
||||
{
|
||||
WindowUpdateFrame windowUpdateFrame = (WindowUpdateFrame)frame;
|
||||
return generateWindowUpdate(lease, windowUpdateFrame.getStreamId(), windowUpdateFrame.getWindowDelta());
|
||||
return generateWindowUpdate(accumulator, windowUpdateFrame.getStreamId(), windowUpdateFrame.getWindowDelta());
|
||||
}
|
||||
|
||||
public int generateWindowUpdate(ByteBufferPool.Lease lease, int streamId, int windowUpdate)
|
||||
public int generateWindowUpdate(RetainableByteBufferPool.Accumulator accumulator, int streamId, int windowUpdate)
|
||||
{
|
||||
if (windowUpdate < 0)
|
||||
throw new IllegalArgumentException("Invalid window update: " + windowUpdate);
|
||||
|
||||
ByteBuffer header = generateHeader(lease, FrameType.WINDOW_UPDATE, WindowUpdateFrame.WINDOW_UPDATE_LENGTH, Flags.NONE, streamId);
|
||||
header.putInt(windowUpdate);
|
||||
BufferUtil.flipToFlush(header, 0);
|
||||
lease.append(header, true);
|
||||
RetainableByteBuffer header = generateHeader(FrameType.WINDOW_UPDATE, WindowUpdateFrame.WINDOW_UPDATE_LENGTH, Flags.NONE, streamId);
|
||||
ByteBuffer byteBuffer = header.getByteBuffer();
|
||||
byteBuffer.putInt(windowUpdate);
|
||||
BufferUtil.flipToFlush(byteBuffer, 0);
|
||||
accumulator.append(header);
|
||||
|
||||
return Frame.HEADER_LENGTH + WindowUpdateFrame.WINDOW_UPDATE_LENGTH;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.eclipse.jetty.http2.frames.ContinuationFrame;
|
|||
import org.eclipse.jetty.http2.frames.HeadersFrame;
|
||||
import org.eclipse.jetty.http2.internal.ErrorCode;
|
||||
import org.eclipse.jetty.http2.internal.Flags;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
|
||||
public class ContinuationBodyParser extends BodyParser
|
||||
{
|
||||
|
@ -100,9 +101,9 @@ public class ContinuationBodyParser extends BodyParser
|
|||
|
||||
private boolean onHeaders(ByteBuffer buffer)
|
||||
{
|
||||
ByteBuffer headerBlock = headerBlockFragments.complete();
|
||||
MetaData metaData = headerBlockParser.parse(headerBlock, headerBlock.remaining());
|
||||
headerBlockFragments.getByteBufferPool().release(headerBlock);
|
||||
RetainableByteBuffer headerBlock = headerBlockFragments.complete();
|
||||
MetaData metaData = headerBlockParser.parse(headerBlock.getByteBuffer(), headerBlock.remaining());
|
||||
headerBlock.release();
|
||||
if (metaData == null)
|
||||
return true;
|
||||
if (metaData == HeaderBlockParser.SESSION_FAILURE)
|
||||
|
|
|
@ -16,24 +16,21 @@ package org.eclipse.jetty.http2.internal.parser;
|
|||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.http2.frames.PriorityFrame;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
||||
public class HeaderBlockFragments
|
||||
{
|
||||
private final ByteBufferPool byteBufferPool;
|
||||
private final RetainableByteBufferPool bufferPool;
|
||||
private PriorityFrame priorityFrame;
|
||||
private boolean endStream;
|
||||
private int streamId;
|
||||
private ByteBuffer storage;
|
||||
private RetainableByteBuffer storage;
|
||||
|
||||
public HeaderBlockFragments(ByteBufferPool byteBufferPool)
|
||||
public HeaderBlockFragments(RetainableByteBufferPool bufferPool)
|
||||
{
|
||||
this.byteBufferPool = byteBufferPool;
|
||||
}
|
||||
|
||||
public ByteBufferPool getByteBufferPool()
|
||||
{
|
||||
return byteBufferPool;
|
||||
this.bufferPool = bufferPool;
|
||||
}
|
||||
|
||||
public void storeFragment(ByteBuffer fragment, int length, boolean last)
|
||||
|
@ -41,27 +38,28 @@ public class HeaderBlockFragments
|
|||
if (storage == null)
|
||||
{
|
||||
int space = last ? length : length * 2;
|
||||
storage = byteBufferPool.acquire(space, fragment.isDirect());
|
||||
storage.clear();
|
||||
storage = bufferPool.acquire(space, fragment.isDirect());
|
||||
BufferUtil.flipToFill(storage.getByteBuffer());
|
||||
}
|
||||
|
||||
// Grow the storage if necessary.
|
||||
if (storage.remaining() < length)
|
||||
{
|
||||
ByteBuffer byteBuffer = storage.getByteBuffer();
|
||||
int space = last ? length : length * 2;
|
||||
int capacity = storage.position() + space;
|
||||
ByteBuffer newStorage = byteBufferPool.acquire(capacity, storage.isDirect());
|
||||
newStorage.clear();
|
||||
storage.flip();
|
||||
newStorage.put(storage);
|
||||
byteBufferPool.release(storage);
|
||||
int capacity = byteBuffer.position() + space;
|
||||
RetainableByteBuffer newStorage = bufferPool.acquire(capacity, storage.isDirect());
|
||||
BufferUtil.flipToFill(newStorage.getByteBuffer());
|
||||
byteBuffer.flip();
|
||||
newStorage.getByteBuffer().put(byteBuffer);
|
||||
storage.release();
|
||||
storage = newStorage;
|
||||
}
|
||||
|
||||
// Copy the fragment into the storage.
|
||||
int limit = fragment.limit();
|
||||
fragment.limit(fragment.position() + length);
|
||||
storage.put(fragment);
|
||||
storage.getByteBuffer().put(fragment);
|
||||
fragment.limit(limit);
|
||||
}
|
||||
|
||||
|
@ -85,11 +83,11 @@ public class HeaderBlockFragments
|
|||
this.endStream = endStream;
|
||||
}
|
||||
|
||||
public ByteBuffer complete()
|
||||
public RetainableByteBuffer complete()
|
||||
{
|
||||
ByteBuffer result = storage;
|
||||
RetainableByteBuffer result = storage;
|
||||
storage = null;
|
||||
result.flip();
|
||||
result.getByteBuffer().flip();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,8 @@ import org.eclipse.jetty.http.MetaData;
|
|||
import org.eclipse.jetty.http2.hpack.HpackDecoder;
|
||||
import org.eclipse.jetty.http2.hpack.HpackException;
|
||||
import org.eclipse.jetty.http2.internal.ErrorCode;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -32,15 +33,15 @@ public class HeaderBlockParser
|
|||
private static final Logger LOG = LoggerFactory.getLogger(HeaderBlockParser.class);
|
||||
|
||||
private final HeaderParser headerParser;
|
||||
private final ByteBufferPool byteBufferPool;
|
||||
private final RetainableByteBufferPool bufferPool;
|
||||
private final HpackDecoder hpackDecoder;
|
||||
private final BodyParser notifier;
|
||||
private ByteBuffer blockBuffer;
|
||||
private RetainableByteBuffer blockBuffer;
|
||||
|
||||
public HeaderBlockParser(HeaderParser headerParser, ByteBufferPool byteBufferPool, HpackDecoder hpackDecoder, BodyParser notifier)
|
||||
public HeaderBlockParser(HeaderParser headerParser, RetainableByteBufferPool bufferPool, HpackDecoder hpackDecoder, BodyParser notifier)
|
||||
{
|
||||
this.headerParser = headerParser;
|
||||
this.byteBufferPool = byteBufferPool;
|
||||
this.bufferPool = bufferPool;
|
||||
this.hpackDecoder = hpackDecoder;
|
||||
this.notifier = notifier;
|
||||
}
|
||||
|
@ -61,17 +62,19 @@ public class HeaderBlockParser
|
|||
// If they are not all available, accumulate them.
|
||||
// When all are available, decode them.
|
||||
|
||||
int accumulated = blockBuffer == null ? 0 : blockBuffer.position();
|
||||
ByteBuffer byteBuffer = blockBuffer == null ? null : blockBuffer.getByteBuffer();
|
||||
int accumulated = byteBuffer == null ? 0 : byteBuffer.position();
|
||||
int remaining = blockLength - accumulated;
|
||||
|
||||
if (buffer.remaining() < remaining)
|
||||
{
|
||||
if (blockBuffer == null)
|
||||
{
|
||||
blockBuffer = byteBufferPool.acquire(blockLength, buffer.isDirect());
|
||||
BufferUtil.clearToFill(blockBuffer);
|
||||
blockBuffer = bufferPool.acquire(blockLength, buffer.isDirect());
|
||||
byteBuffer = blockBuffer.getByteBuffer();
|
||||
BufferUtil.flipToFill(byteBuffer);
|
||||
}
|
||||
blockBuffer.put(buffer);
|
||||
byteBuffer.put(buffer);
|
||||
return null;
|
||||
}
|
||||
else
|
||||
|
@ -79,11 +82,11 @@ public class HeaderBlockParser
|
|||
int limit = buffer.limit();
|
||||
buffer.limit(buffer.position() + remaining);
|
||||
ByteBuffer toDecode;
|
||||
if (blockBuffer != null)
|
||||
if (byteBuffer != null)
|
||||
{
|
||||
blockBuffer.put(buffer);
|
||||
BufferUtil.flipToFlush(blockBuffer, 0);
|
||||
toDecode = blockBuffer;
|
||||
byteBuffer.put(buffer);
|
||||
BufferUtil.flipToFlush(byteBuffer, 0);
|
||||
toDecode = byteBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -121,7 +124,7 @@ public class HeaderBlockParser
|
|||
|
||||
if (blockBuffer != null)
|
||||
{
|
||||
byteBufferPool.release(blockBuffer);
|
||||
blockBuffer.release();
|
||||
blockBuffer = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ import org.eclipse.jetty.http2.frames.WindowUpdateFrame;
|
|||
import org.eclipse.jetty.http2.hpack.HpackDecoder;
|
||||
import org.eclipse.jetty.http2.internal.ErrorCode;
|
||||
import org.eclipse.jetty.http2.internal.Flags;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -44,7 +44,7 @@ public class Parser
|
|||
{
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Parser.class);
|
||||
|
||||
private final ByteBufferPool byteBufferPool;
|
||||
private final RetainableByteBufferPool bufferPool;
|
||||
private final Listener listener;
|
||||
private final HeaderParser headerParser;
|
||||
private final HpackDecoder hpackDecoder;
|
||||
|
@ -55,14 +55,14 @@ public class Parser
|
|||
private boolean continuation;
|
||||
private State state = State.HEADER;
|
||||
|
||||
public Parser(ByteBufferPool byteBufferPool, Listener listener, int maxDynamicTableSize, int maxHeaderSize)
|
||||
public Parser(RetainableByteBufferPool bufferPool, Listener listener, int maxDynamicTableSize, int maxHeaderSize)
|
||||
{
|
||||
this(byteBufferPool, listener, maxDynamicTableSize, maxHeaderSize, RateControl.NO_RATE_CONTROL);
|
||||
this(bufferPool, listener, maxDynamicTableSize, maxHeaderSize, RateControl.NO_RATE_CONTROL);
|
||||
}
|
||||
|
||||
public Parser(ByteBufferPool byteBufferPool, Listener listener, int maxDynamicTableSize, int maxHeaderSize, RateControl rateControl)
|
||||
public Parser(RetainableByteBufferPool bufferPool, Listener listener, int maxDynamicTableSize, int maxHeaderSize, RateControl rateControl)
|
||||
{
|
||||
this.byteBufferPool = byteBufferPool;
|
||||
this.bufferPool = bufferPool;
|
||||
this.listener = listener;
|
||||
this.headerParser = new HeaderParser(rateControl == null ? RateControl.NO_RATE_CONTROL : rateControl);
|
||||
this.hpackDecoder = new HpackDecoder(maxDynamicTableSize, maxHeaderSize);
|
||||
|
@ -73,8 +73,8 @@ public class Parser
|
|||
{
|
||||
Listener listener = wrapper.apply(this.listener);
|
||||
unknownBodyParser = new UnknownBodyParser(headerParser, listener);
|
||||
HeaderBlockParser headerBlockParser = new HeaderBlockParser(headerParser, byteBufferPool, hpackDecoder, unknownBodyParser);
|
||||
HeaderBlockFragments headerBlockFragments = new HeaderBlockFragments(byteBufferPool);
|
||||
HeaderBlockParser headerBlockParser = new HeaderBlockParser(headerParser, bufferPool, hpackDecoder, unknownBodyParser);
|
||||
HeaderBlockFragments headerBlockFragments = new HeaderBlockFragments(bufferPool);
|
||||
bodyParsers[FrameType.DATA.getType()] = new DataBodyParser(headerParser, listener);
|
||||
bodyParsers[FrameType.HEADERS.getType()] = new HeadersBodyParser(headerParser, listener, headerBlockParser, headerBlockFragments);
|
||||
bodyParsers[FrameType.PRIORITY.getType()] = new PriorityBodyParser(headerParser, listener);
|
||||
|
|
|
@ -19,7 +19,7 @@ import org.eclipse.jetty.http2.RateControl;
|
|||
import org.eclipse.jetty.http2.frames.FrameType;
|
||||
import org.eclipse.jetty.http2.internal.ErrorCode;
|
||||
import org.eclipse.jetty.http2.internal.Flags;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -33,9 +33,9 @@ public class ServerParser extends Parser
|
|||
private State state = State.PREFACE;
|
||||
private boolean notifyPreface = true;
|
||||
|
||||
public ServerParser(ByteBufferPool byteBufferPool, Listener listener, int maxDynamicTableSize, int maxHeaderSize, RateControl rateControl)
|
||||
public ServerParser(RetainableByteBufferPool bufferPool, Listener listener, int maxDynamicTableSize, int maxHeaderSize, RateControl rateControl)
|
||||
{
|
||||
super(byteBufferPool, listener, maxDynamicTableSize, maxHeaderSize, rateControl);
|
||||
super(bufferPool, listener, maxDynamicTableSize, maxHeaderSize, rateControl);
|
||||
this.listener = listener;
|
||||
this.prefaceParser = new PrefaceParser(listener);
|
||||
}
|
||||
|
|
|
@ -29,8 +29,8 @@ import org.eclipse.jetty.http2.internal.Flags;
|
|||
import org.eclipse.jetty.http2.internal.generator.HeaderGenerator;
|
||||
import org.eclipse.jetty.http2.internal.generator.HeadersGenerator;
|
||||
import org.eclipse.jetty.http2.internal.parser.Parser;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
@ -42,11 +42,11 @@ public class ContinuationParseTest
|
|||
@Test
|
||||
public void testParseOneByteAtATime() throws Exception
|
||||
{
|
||||
ByteBufferPool byteBufferPool = new MappedByteBufferPool();
|
||||
HeadersGenerator generator = new HeadersGenerator(new HeaderGenerator(), new HpackEncoder());
|
||||
RetainableByteBufferPool bufferPool = new ArrayRetainableByteBufferPool();
|
||||
HeadersGenerator generator = new HeadersGenerator(new HeaderGenerator(bufferPool), new HpackEncoder());
|
||||
|
||||
final List<HeadersFrame> frames = new ArrayList<>();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onHeaders(HeadersFrame frame)
|
||||
|
@ -71,10 +71,10 @@ public class ContinuationParseTest
|
|||
.put("User-Agent", "Jetty");
|
||||
MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields, -1);
|
||||
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.generateHeaders(lease, streamId, metaData, null, true);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.generateHeaders(accumulator, streamId, metaData, null, true);
|
||||
|
||||
List<ByteBuffer> byteBuffers = lease.getByteBuffers();
|
||||
List<ByteBuffer> byteBuffers = accumulator.getByteBuffers();
|
||||
assertEquals(2, byteBuffers.size());
|
||||
|
||||
ByteBuffer headersBody = byteBuffers.remove(1);
|
||||
|
@ -131,7 +131,7 @@ public class ContinuationParseTest
|
|||
byteBuffers.add(headersBody.slice());
|
||||
|
||||
frames.clear();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
|
|
|
@ -22,8 +22,8 @@ import java.util.function.UnaryOperator;
|
|||
import org.eclipse.jetty.http2.internal.generator.DataGenerator;
|
||||
import org.eclipse.jetty.http2.internal.generator.HeaderGenerator;
|
||||
import org.eclipse.jetty.http2.internal.parser.Parser;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
@ -34,7 +34,7 @@ public class DataGenerateParseTest
|
|||
{
|
||||
private final byte[] smallContent = new byte[128];
|
||||
private final byte[] largeContent = new byte[128 * 1024];
|
||||
private final ByteBufferPool byteBufferPool = new MappedByteBufferPool();
|
||||
private final RetainableByteBufferPool bufferPool = new ArrayRetainableByteBufferPool();
|
||||
|
||||
public DataGenerateParseTest()
|
||||
{
|
||||
|
@ -62,7 +62,7 @@ public class DataGenerateParseTest
|
|||
DataFrame frame = frames.get(0);
|
||||
assertTrue(frame.getStreamId() != 0);
|
||||
assertTrue(frame.isEndStream());
|
||||
assertEquals(content, frame.getData());
|
||||
assertEquals(content, frame.getByteBuffer());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -77,7 +77,7 @@ public class DataGenerateParseTest
|
|||
DataFrame frame = frames.get(i - 1);
|
||||
assertTrue(frame.getStreamId() != 0);
|
||||
assertEquals(i == frames.size(), frame.isEndStream());
|
||||
aggregate.put(frame.getData());
|
||||
aggregate.put(frame.getByteBuffer());
|
||||
}
|
||||
aggregate.flip();
|
||||
assertEquals(content, aggregate);
|
||||
|
@ -85,10 +85,10 @@ public class DataGenerateParseTest
|
|||
|
||||
private List<DataFrame> testGenerateParse(ByteBuffer data)
|
||||
{
|
||||
DataGenerator generator = new DataGenerator(new HeaderGenerator());
|
||||
DataGenerator generator = new DataGenerator(new HeaderGenerator(bufferPool));
|
||||
|
||||
final List<DataFrame> frames = new ArrayList<>();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onData(DataFrame frame)
|
||||
|
@ -101,19 +101,19 @@ public class DataGenerateParseTest
|
|||
// Iterate a few times to be sure generator and parser are properly reset.
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
ByteBuffer slice = data.slice();
|
||||
int generated = 0;
|
||||
while (true)
|
||||
{
|
||||
generated += generator.generateData(lease, 13, slice, true, slice.remaining());
|
||||
generated += generator.generateData(accumulator, 13, slice, true, slice.remaining());
|
||||
generated -= Frame.HEADER_LENGTH;
|
||||
if (generated == data.remaining())
|
||||
break;
|
||||
}
|
||||
|
||||
frames.clear();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
parser.parse(buffer);
|
||||
}
|
||||
|
@ -125,10 +125,10 @@ public class DataGenerateParseTest
|
|||
@Test
|
||||
public void testGenerateParseOneByteAtATime()
|
||||
{
|
||||
DataGenerator generator = new DataGenerator(new HeaderGenerator());
|
||||
DataGenerator generator = new DataGenerator(new HeaderGenerator(bufferPool));
|
||||
|
||||
final List<DataFrame> frames = new ArrayList<>();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onData(DataFrame frame)
|
||||
|
@ -141,20 +141,20 @@ public class DataGenerateParseTest
|
|||
// Iterate a few times to be sure generator and parser are properly reset.
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
ByteBuffer data = ByteBuffer.wrap(largeContent);
|
||||
ByteBuffer slice = data.slice();
|
||||
int generated = 0;
|
||||
while (true)
|
||||
{
|
||||
generated += generator.generateData(lease, 13, slice, true, slice.remaining());
|
||||
generated += generator.generateData(accumulator, 13, slice, true, slice.remaining());
|
||||
generated -= Frame.HEADER_LENGTH;
|
||||
if (generated == data.remaining())
|
||||
break;
|
||||
}
|
||||
|
||||
frames.clear();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
|
|
|
@ -24,8 +24,8 @@ import org.eclipse.jetty.http2.WindowRateControl;
|
|||
import org.eclipse.jetty.http2.hpack.HpackEncoder;
|
||||
import org.eclipse.jetty.http2.internal.Flags;
|
||||
import org.eclipse.jetty.http2.internal.parser.Parser;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
@ -33,7 +33,7 @@ import static org.hamcrest.Matchers.lessThan;
|
|||
|
||||
public class FrameFloodTest
|
||||
{
|
||||
private final ByteBufferPool byteBufferPool = new MappedByteBufferPool();
|
||||
private final RetainableByteBufferPool bufferPool = new ArrayRetainableByteBufferPool();
|
||||
|
||||
// Frame structure:
|
||||
// | Len0 | Len1 | Len2 | Type | Flags | StreamID0 |StreamID1 |StreamID2 |StreamID3 | Payload... |
|
||||
|
@ -72,7 +72,7 @@ public class FrameFloodTest
|
|||
public void testInvalidHeadersFrameFlood() throws Exception
|
||||
{
|
||||
// Invalid MetaData (no method, no scheme, etc).
|
||||
MetaData.Request metadata = new MetaData.Request(null, (String)null, null, null, HttpVersion.HTTP_2, null, -1);
|
||||
MetaData.Request metadata = new MetaData.Request(null, null, null, null, HttpVersion.HTTP_2, null, -1);
|
||||
HpackEncoder encoder = new HpackEncoder();
|
||||
ByteBuffer buffer = ByteBuffer.allocate(1024);
|
||||
encoder.encode(buffer, metadata);
|
||||
|
@ -123,7 +123,7 @@ public class FrameFloodTest
|
|||
private void testFrameFlood(byte[] preamble, byte[] bytes)
|
||||
{
|
||||
AtomicBoolean failed = new AtomicBoolean();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onConnectionFailure(int error, String reason)
|
||||
|
|
|
@ -22,8 +22,8 @@ import java.util.function.UnaryOperator;
|
|||
import org.eclipse.jetty.http2.internal.generator.GoAwayGenerator;
|
||||
import org.eclipse.jetty.http2.internal.generator.HeaderGenerator;
|
||||
import org.eclipse.jetty.http2.internal.parser.Parser;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
|
@ -32,15 +32,15 @@ import static org.junit.jupiter.api.Assertions.assertNull;
|
|||
|
||||
public class GoAwayGenerateParseTest
|
||||
{
|
||||
private final ByteBufferPool byteBufferPool = new MappedByteBufferPool();
|
||||
private final RetainableByteBufferPool bufferPool = new ArrayRetainableByteBufferPool();
|
||||
|
||||
@Test
|
||||
public void testGenerateParse() throws Exception
|
||||
{
|
||||
GoAwayGenerator generator = new GoAwayGenerator(new HeaderGenerator());
|
||||
GoAwayGenerator generator = new GoAwayGenerator(new HeaderGenerator(bufferPool));
|
||||
|
||||
final List<GoAwayFrame> frames = new ArrayList<>();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onGoAway(GoAwayFrame frame)
|
||||
|
@ -56,11 +56,11 @@ public class GoAwayGenerateParseTest
|
|||
// Iterate a few times to be sure generator and parser are properly reset.
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.generateGoAway(lease, lastStreamId, error, null);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.generateGoAway(accumulator, lastStreamId, error, null);
|
||||
|
||||
frames.clear();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
|
@ -79,10 +79,10 @@ public class GoAwayGenerateParseTest
|
|||
@Test
|
||||
public void testGenerateParseOneByteAtATime() throws Exception
|
||||
{
|
||||
GoAwayGenerator generator = new GoAwayGenerator(new HeaderGenerator());
|
||||
GoAwayGenerator generator = new GoAwayGenerator(new HeaderGenerator(bufferPool));
|
||||
|
||||
final List<GoAwayFrame> frames = new ArrayList<>();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onGoAway(GoAwayFrame frame)
|
||||
|
@ -100,11 +100,11 @@ public class GoAwayGenerateParseTest
|
|||
// Iterate a few times to be sure generator and parser are properly reset.
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.generateGoAway(lease, lastStreamId, error, payload);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.generateGoAway(accumulator, lastStreamId, error, payload);
|
||||
|
||||
frames.clear();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
|
|
|
@ -28,8 +28,8 @@ import org.eclipse.jetty.http2.hpack.HpackEncoder;
|
|||
import org.eclipse.jetty.http2.internal.generator.HeaderGenerator;
|
||||
import org.eclipse.jetty.http2.internal.generator.HeadersGenerator;
|
||||
import org.eclipse.jetty.http2.internal.parser.Parser;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
@ -38,12 +38,12 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
|
||||
public class HeadersGenerateParseTest
|
||||
{
|
||||
private final ByteBufferPool byteBufferPool = new MappedByteBufferPool();
|
||||
private final RetainableByteBufferPool bufferPool = new ArrayRetainableByteBufferPool();
|
||||
|
||||
@Test
|
||||
public void testGenerateParse() throws Exception
|
||||
{
|
||||
HeadersGenerator generator = new HeadersGenerator(new HeaderGenerator(), new HpackEncoder());
|
||||
HeadersGenerator generator = new HeadersGenerator(new HeaderGenerator(bufferPool), new HpackEncoder());
|
||||
|
||||
int streamId = 13;
|
||||
HttpFields fields = HttpFields.build()
|
||||
|
@ -52,7 +52,7 @@ public class HeadersGenerateParseTest
|
|||
MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields, -1);
|
||||
|
||||
final List<HeadersFrame> frames = new ArrayList<>();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onHeaders(HeadersFrame frame)
|
||||
|
@ -65,12 +65,12 @@ public class HeadersGenerateParseTest
|
|||
// Iterate a few times to be sure generator and parser are properly reset.
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
PriorityFrame priorityFrame = new PriorityFrame(streamId, 3 * streamId, 200, true);
|
||||
generator.generateHeaders(lease, streamId, metaData, priorityFrame, true);
|
||||
generator.generateHeaders(accumulator, streamId, metaData, priorityFrame, true);
|
||||
|
||||
frames.clear();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
|
@ -102,10 +102,10 @@ public class HeadersGenerateParseTest
|
|||
@Test
|
||||
public void testGenerateParseOneByteAtATime() throws Exception
|
||||
{
|
||||
HeadersGenerator generator = new HeadersGenerator(new HeaderGenerator(), new HpackEncoder());
|
||||
HeadersGenerator generator = new HeadersGenerator(new HeaderGenerator(bufferPool), new HpackEncoder());
|
||||
|
||||
final List<HeadersFrame> frames = new ArrayList<>();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onHeaders(HeadersFrame frame)
|
||||
|
@ -124,12 +124,12 @@ public class HeadersGenerateParseTest
|
|||
.put("User-Agent", "Jetty");
|
||||
MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields, -1);
|
||||
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
PriorityFrame priorityFrame = new PriorityFrame(streamId, 3 * streamId, 200, true);
|
||||
generator.generateHeaders(lease, streamId, metaData, priorityFrame, true);
|
||||
generator.generateHeaders(accumulator, streamId, metaData, priorityFrame, true);
|
||||
|
||||
frames.clear();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
buffer = buffer.slice();
|
||||
while (buffer.hasRemaining())
|
||||
|
|
|
@ -28,8 +28,8 @@ import org.eclipse.jetty.http2.internal.ErrorCode;
|
|||
import org.eclipse.jetty.http2.internal.generator.HeaderGenerator;
|
||||
import org.eclipse.jetty.http2.internal.generator.HeadersGenerator;
|
||||
import org.eclipse.jetty.http2.internal.parser.Parser;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
@ -37,7 +37,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
|
||||
public class HeadersTooLargeParseTest
|
||||
{
|
||||
private final ByteBufferPool byteBufferPool = new MappedByteBufferPool();
|
||||
private final RetainableByteBufferPool bufferPool = new ArrayRetainableByteBufferPool();
|
||||
|
||||
@Test
|
||||
public void testProtocolErrorURITooLong() throws HpackException
|
||||
|
@ -64,10 +64,10 @@ public class HeadersTooLargeParseTest
|
|||
|
||||
private void assertProtocolError(int maxHeaderSize, MetaData.Request metaData) throws HpackException
|
||||
{
|
||||
HeadersGenerator generator = new HeadersGenerator(new HeaderGenerator(), new HpackEncoder());
|
||||
HeadersGenerator generator = new HeadersGenerator(new HeaderGenerator(bufferPool), new HpackEncoder());
|
||||
|
||||
AtomicInteger failure = new AtomicInteger();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onConnectionFailure(int error, String reason)
|
||||
|
@ -78,11 +78,11 @@ public class HeadersTooLargeParseTest
|
|||
parser.init(UnaryOperator.identity());
|
||||
|
||||
int streamId = 48;
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
PriorityFrame priorityFrame = new PriorityFrame(streamId, 3 * streamId, 200, true);
|
||||
int len = generator.generateHeaders(lease, streamId, metaData, priorityFrame, true);
|
||||
int len = generator.generateHeaders(accumulator, streamId, metaData, priorityFrame, true);
|
||||
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
while (buffer.hasRemaining() && failure.get() == 0)
|
||||
{
|
||||
|
|
|
@ -19,15 +19,15 @@ import java.util.function.UnaryOperator;
|
|||
|
||||
import org.eclipse.jetty.http2.internal.ErrorCode;
|
||||
import org.eclipse.jetty.http2.internal.parser.Parser;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class MaxFrameSizeParseTest
|
||||
{
|
||||
private final ByteBufferPool byteBufferPool = new MappedByteBufferPool();
|
||||
private final RetainableByteBufferPool bufferPool = new ArrayRetainableByteBufferPool();
|
||||
|
||||
@Test
|
||||
public void testMaxFrameSize()
|
||||
|
@ -35,7 +35,7 @@ public class MaxFrameSizeParseTest
|
|||
int maxFrameLength = Frame.DEFAULT_MAX_LENGTH + 16;
|
||||
|
||||
AtomicInteger failure = new AtomicInteger();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onConnectionFailure(int error, String reason)
|
||||
|
|
|
@ -22,8 +22,8 @@ import java.util.function.UnaryOperator;
|
|||
import org.eclipse.jetty.http2.internal.generator.HeaderGenerator;
|
||||
import org.eclipse.jetty.http2.internal.generator.PingGenerator;
|
||||
import org.eclipse.jetty.http2.internal.parser.Parser;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.NanoTime;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
@ -33,15 +33,15 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
|
||||
public class PingGenerateParseTest
|
||||
{
|
||||
private final ByteBufferPool byteBufferPool = new MappedByteBufferPool();
|
||||
private final RetainableByteBufferPool bufferPool = new ArrayRetainableByteBufferPool();
|
||||
|
||||
@Test
|
||||
public void testGenerateParse() throws Exception
|
||||
{
|
||||
PingGenerator generator = new PingGenerator(new HeaderGenerator());
|
||||
PingGenerator generator = new PingGenerator(new HeaderGenerator(bufferPool));
|
||||
|
||||
final List<PingFrame> frames = new ArrayList<>();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onPing(PingFrame frame)
|
||||
|
@ -57,11 +57,11 @@ public class PingGenerateParseTest
|
|||
// Iterate a few times to be sure generator and parser are properly reset.
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.generatePing(lease, payload, true);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.generatePing(accumulator, payload, true);
|
||||
|
||||
frames.clear();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
|
@ -79,10 +79,10 @@ public class PingGenerateParseTest
|
|||
@Test
|
||||
public void testGenerateParseOneByteAtATime() throws Exception
|
||||
{
|
||||
PingGenerator generator = new PingGenerator(new HeaderGenerator());
|
||||
PingGenerator generator = new PingGenerator(new HeaderGenerator(bufferPool));
|
||||
|
||||
final List<PingFrame> frames = new ArrayList<>();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onPing(PingFrame frame)
|
||||
|
@ -98,11 +98,11 @@ public class PingGenerateParseTest
|
|||
// Iterate a few times to be sure generator and parser are properly reset.
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.generatePing(lease, payload, true);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.generatePing(accumulator, payload, true);
|
||||
|
||||
frames.clear();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
|
@ -120,10 +120,10 @@ public class PingGenerateParseTest
|
|||
@Test
|
||||
public void testPayloadAsLong() throws Exception
|
||||
{
|
||||
PingGenerator generator = new PingGenerator(new HeaderGenerator());
|
||||
PingGenerator generator = new PingGenerator(new HeaderGenerator(bufferPool));
|
||||
|
||||
final List<PingFrame> frames = new ArrayList<>();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onPing(PingFrame frame)
|
||||
|
@ -133,11 +133,11 @@ public class PingGenerateParseTest
|
|||
}, 4096, 8192);
|
||||
parser.init(UnaryOperator.identity());
|
||||
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
PingFrame ping = new PingFrame(NanoTime.now(), true);
|
||||
generator.generate(lease, ping);
|
||||
generator.generate(accumulator, ping);
|
||||
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
|
|
|
@ -21,23 +21,23 @@ import java.util.function.UnaryOperator;
|
|||
import org.eclipse.jetty.http2.internal.generator.HeaderGenerator;
|
||||
import org.eclipse.jetty.http2.internal.generator.PriorityGenerator;
|
||||
import org.eclipse.jetty.http2.internal.parser.Parser;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class PriorityGenerateParseTest
|
||||
{
|
||||
private final ByteBufferPool byteBufferPool = new MappedByteBufferPool();
|
||||
private final RetainableByteBufferPool bufferPool = new ArrayRetainableByteBufferPool();
|
||||
|
||||
@Test
|
||||
public void testGenerateParse() throws Exception
|
||||
{
|
||||
PriorityGenerator generator = new PriorityGenerator(new HeaderGenerator());
|
||||
PriorityGenerator generator = new PriorityGenerator(new HeaderGenerator(bufferPool));
|
||||
|
||||
final List<PriorityFrame> frames = new ArrayList<>();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onPriority(PriorityFrame frame)
|
||||
|
@ -55,11 +55,11 @@ public class PriorityGenerateParseTest
|
|||
// Iterate a few times to be sure generator and parser are properly reset.
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.generatePriority(lease, streamId, parentStreamId, weight, exclusive);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.generatePriority(accumulator, streamId, parentStreamId, weight, exclusive);
|
||||
|
||||
frames.clear();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
|
@ -79,10 +79,10 @@ public class PriorityGenerateParseTest
|
|||
@Test
|
||||
public void testGenerateParseOneByteAtATime() throws Exception
|
||||
{
|
||||
PriorityGenerator generator = new PriorityGenerator(new HeaderGenerator());
|
||||
PriorityGenerator generator = new PriorityGenerator(new HeaderGenerator(bufferPool));
|
||||
|
||||
final List<PriorityFrame> frames = new ArrayList<>();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onPriority(PriorityFrame frame)
|
||||
|
@ -100,11 +100,11 @@ public class PriorityGenerateParseTest
|
|||
// Iterate a few times to be sure generator and parser are properly reset.
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.generatePriority(lease, streamId, parentStreamId, weight, exclusive);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.generatePriority(accumulator, streamId, parentStreamId, weight, exclusive);
|
||||
|
||||
frames.clear();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
|
|
|
@ -28,8 +28,8 @@ import org.eclipse.jetty.http2.hpack.HpackEncoder;
|
|||
import org.eclipse.jetty.http2.internal.generator.HeaderGenerator;
|
||||
import org.eclipse.jetty.http2.internal.generator.PushPromiseGenerator;
|
||||
import org.eclipse.jetty.http2.internal.parser.Parser;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
@ -37,15 +37,15 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
|
||||
public class PushPromiseGenerateParseTest
|
||||
{
|
||||
private final ByteBufferPool byteBufferPool = new MappedByteBufferPool();
|
||||
private final RetainableByteBufferPool bufferPool = new ArrayRetainableByteBufferPool();
|
||||
|
||||
@Test
|
||||
public void testGenerateParse() throws Exception
|
||||
{
|
||||
PushPromiseGenerator generator = new PushPromiseGenerator(new HeaderGenerator(), new HpackEncoder());
|
||||
PushPromiseGenerator generator = new PushPromiseGenerator(new HeaderGenerator(bufferPool), new HpackEncoder());
|
||||
|
||||
final List<PushPromiseFrame> frames = new ArrayList<>();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onPushPromise(PushPromiseFrame frame)
|
||||
|
@ -65,11 +65,11 @@ public class PushPromiseGenerateParseTest
|
|||
// Iterate a few times to be sure generator and parser are properly reset.
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.generatePushPromise(lease, streamId, promisedStreamId, metaData);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.generatePushPromise(accumulator, streamId, promisedStreamId, metaData);
|
||||
|
||||
frames.clear();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
|
@ -95,10 +95,10 @@ public class PushPromiseGenerateParseTest
|
|||
@Test
|
||||
public void testGenerateParseOneByteAtATime() throws Exception
|
||||
{
|
||||
PushPromiseGenerator generator = new PushPromiseGenerator(new HeaderGenerator(), new HpackEncoder());
|
||||
PushPromiseGenerator generator = new PushPromiseGenerator(new HeaderGenerator(bufferPool), new HpackEncoder());
|
||||
|
||||
final List<PushPromiseFrame> frames = new ArrayList<>();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onPushPromise(PushPromiseFrame frame)
|
||||
|
@ -118,11 +118,11 @@ public class PushPromiseGenerateParseTest
|
|||
// Iterate a few times to be sure generator and parser are properly reset.
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.generatePushPromise(lease, streamId, promisedStreamId, metaData);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.generatePushPromise(accumulator, streamId, promisedStreamId, metaData);
|
||||
|
||||
frames.clear();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
|
@ -134,7 +134,7 @@ public class PushPromiseGenerateParseTest
|
|||
PushPromiseFrame frame = frames.get(0);
|
||||
assertEquals(streamId, frame.getStreamId());
|
||||
assertEquals(promisedStreamId, frame.getPromisedStreamId());
|
||||
MetaData.Request request = (MetaData.Request)frame.getMetaData();
|
||||
MetaData.Request request = frame.getMetaData();
|
||||
assertEquals(metaData.getMethod(), request.getMethod());
|
||||
assertEquals(metaData.getURI(), request.getURI());
|
||||
for (int j = 0; j < fields.size(); ++j)
|
||||
|
|
|
@ -21,23 +21,23 @@ import java.util.function.UnaryOperator;
|
|||
import org.eclipse.jetty.http2.internal.generator.HeaderGenerator;
|
||||
import org.eclipse.jetty.http2.internal.generator.ResetGenerator;
|
||||
import org.eclipse.jetty.http2.internal.parser.Parser;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class ResetGenerateParseTest
|
||||
{
|
||||
private final ByteBufferPool byteBufferPool = new MappedByteBufferPool();
|
||||
private final RetainableByteBufferPool bufferPool = new ArrayRetainableByteBufferPool();
|
||||
|
||||
@Test
|
||||
public void testGenerateParse() throws Exception
|
||||
{
|
||||
ResetGenerator generator = new ResetGenerator(new HeaderGenerator());
|
||||
ResetGenerator generator = new ResetGenerator(new HeaderGenerator(bufferPool));
|
||||
|
||||
final List<ResetFrame> frames = new ArrayList<>();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onReset(ResetFrame frame)
|
||||
|
@ -53,11 +53,11 @@ public class ResetGenerateParseTest
|
|||
// Iterate a few times to be sure generator and parser are properly reset.
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.generateReset(lease, streamId, error);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.generateReset(accumulator, streamId, error);
|
||||
|
||||
frames.clear();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
|
@ -75,10 +75,10 @@ public class ResetGenerateParseTest
|
|||
@Test
|
||||
public void testGenerateParseOneByteAtATime() throws Exception
|
||||
{
|
||||
ResetGenerator generator = new ResetGenerator(new HeaderGenerator());
|
||||
ResetGenerator generator = new ResetGenerator(new HeaderGenerator(bufferPool));
|
||||
|
||||
final List<ResetFrame> frames = new ArrayList<>();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onReset(ResetFrame frame)
|
||||
|
@ -94,11 +94,11 @@ public class ResetGenerateParseTest
|
|||
// Iterate a few times to be sure generator and parser are properly reset.
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.generateReset(lease, streamId, error);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.generateReset(accumulator, streamId, error);
|
||||
|
||||
frames.clear();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
|
|
|
@ -26,8 +26,8 @@ import org.eclipse.jetty.http2.internal.ErrorCode;
|
|||
import org.eclipse.jetty.http2.internal.generator.HeaderGenerator;
|
||||
import org.eclipse.jetty.http2.internal.generator.SettingsGenerator;
|
||||
import org.eclipse.jetty.http2.internal.parser.Parser;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
@ -35,7 +35,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
|
||||
public class SettingsGenerateParseTest
|
||||
{
|
||||
private final ByteBufferPool byteBufferPool = new MappedByteBufferPool();
|
||||
private final RetainableByteBufferPool bufferPool = new ArrayRetainableByteBufferPool();
|
||||
|
||||
@Test
|
||||
public void testGenerateParseNoSettings()
|
||||
|
@ -69,10 +69,10 @@ public class SettingsGenerateParseTest
|
|||
|
||||
private List<SettingsFrame> testGenerateParse(Map<Integer, Integer> settings)
|
||||
{
|
||||
SettingsGenerator generator = new SettingsGenerator(new HeaderGenerator());
|
||||
SettingsGenerator generator = new SettingsGenerator(new HeaderGenerator(bufferPool));
|
||||
|
||||
List<SettingsFrame> frames = new ArrayList<>();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onSettings(SettingsFrame frame)
|
||||
|
@ -85,11 +85,11 @@ public class SettingsGenerateParseTest
|
|||
// Iterate a few times to be sure generator and parser are properly reset.
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.generateSettings(lease, settings, true);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.generateSettings(accumulator, settings, true);
|
||||
|
||||
frames.clear();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
|
@ -104,10 +104,10 @@ public class SettingsGenerateParseTest
|
|||
@Test
|
||||
public void testGenerateParseInvalidSettings()
|
||||
{
|
||||
SettingsGenerator generator = new SettingsGenerator(new HeaderGenerator());
|
||||
SettingsGenerator generator = new SettingsGenerator(new HeaderGenerator(bufferPool));
|
||||
|
||||
AtomicInteger errorRef = new AtomicInteger();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onConnectionFailure(int error, String reason)
|
||||
|
@ -119,13 +119,13 @@ public class SettingsGenerateParseTest
|
|||
|
||||
Map<Integer, Integer> settings1 = new HashMap<>();
|
||||
settings1.put(13, 17);
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.generateSettings(lease, settings1, true);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.generateSettings(accumulator, settings1, true);
|
||||
// Modify the length of the frame to make it invalid
|
||||
ByteBuffer bytes = lease.getByteBuffers().get(0);
|
||||
ByteBuffer bytes = accumulator.getByteBuffers().get(0);
|
||||
bytes.putShort(1, (short)(bytes.getShort(1) - 1));
|
||||
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
|
@ -139,10 +139,10 @@ public class SettingsGenerateParseTest
|
|||
@Test
|
||||
public void testGenerateParseOneByteAtATime()
|
||||
{
|
||||
SettingsGenerator generator = new SettingsGenerator(new HeaderGenerator());
|
||||
SettingsGenerator generator = new SettingsGenerator(new HeaderGenerator(bufferPool));
|
||||
|
||||
List<SettingsFrame> frames = new ArrayList<>();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onSettings(SettingsFrame frame)
|
||||
|
@ -160,11 +160,11 @@ public class SettingsGenerateParseTest
|
|||
// Iterate a few times to be sure generator and parser are properly reset.
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.generateSettings(lease, settings1, true);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.generateSettings(accumulator, settings1, true);
|
||||
|
||||
frames.clear();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
|
@ -184,10 +184,10 @@ public class SettingsGenerateParseTest
|
|||
@Test
|
||||
public void testGenerateParseTooManyDifferentSettingsInOneFrame()
|
||||
{
|
||||
SettingsGenerator generator = new SettingsGenerator(new HeaderGenerator());
|
||||
SettingsGenerator generator = new SettingsGenerator(new HeaderGenerator(bufferPool));
|
||||
|
||||
AtomicInteger errorRef = new AtomicInteger();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onConnectionFailure(int error, String reason)
|
||||
|
@ -205,10 +205,10 @@ public class SettingsGenerateParseTest
|
|||
settings.put(i + 10, i);
|
||||
}
|
||||
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.generateSettings(lease, settings, false);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.generateSettings(accumulator, settings, false);
|
||||
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
|
@ -227,7 +227,7 @@ public class SettingsGenerateParseTest
|
|||
int maxSettingsKeys = pairs / 2;
|
||||
|
||||
AtomicInteger errorRef = new AtomicInteger();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter(), 4096, 8192);
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter(), 4096, 8192);
|
||||
parser.setMaxSettingsKeys(maxSettingsKeys);
|
||||
parser.setMaxFrameLength(Frame.DEFAULT_MAX_LENGTH);
|
||||
parser.init(listener -> new Parser.Listener.Wrapper(listener)
|
||||
|
@ -265,10 +265,10 @@ public class SettingsGenerateParseTest
|
|||
@Test
|
||||
public void testGenerateParseTooManySettingsInMultipleFrames()
|
||||
{
|
||||
SettingsGenerator generator = new SettingsGenerator(new HeaderGenerator());
|
||||
SettingsGenerator generator = new SettingsGenerator(new HeaderGenerator(bufferPool));
|
||||
|
||||
AtomicInteger errorRef = new AtomicInteger();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onConnectionFailure(int error, String reason)
|
||||
|
@ -283,13 +283,13 @@ public class SettingsGenerateParseTest
|
|||
Map<Integer, Integer> settings = new HashMap<>();
|
||||
settings.put(13, 17);
|
||||
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
for (int i = 0; i < maxSettingsKeys + 1; ++i)
|
||||
{
|
||||
generator.generateSettings(lease, settings, false);
|
||||
generator.generateSettings(accumulator, settings, false);
|
||||
}
|
||||
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
|
|
|
@ -21,8 +21,8 @@ import java.util.function.UnaryOperator;
|
|||
|
||||
import org.eclipse.jetty.http2.internal.ErrorCode;
|
||||
import org.eclipse.jetty.http2.internal.parser.Parser;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
@ -30,7 +30,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
|
|||
|
||||
public class UnknownParseTest
|
||||
{
|
||||
private final ByteBufferPool byteBufferPool = new MappedByteBufferPool();
|
||||
private final RetainableByteBufferPool bufferPool = new ArrayRetainableByteBufferPool();
|
||||
|
||||
@Test
|
||||
public void testParse()
|
||||
|
@ -48,7 +48,7 @@ public class UnknownParseTest
|
|||
public void testInvalidFrameSize()
|
||||
{
|
||||
AtomicInteger failure = new AtomicInteger();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter(), 4096, 8192);
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter(), 4096, 8192);
|
||||
parser.init(listener -> new Parser.Listener.Wrapper(listener)
|
||||
{
|
||||
@Override
|
||||
|
@ -73,7 +73,7 @@ public class UnknownParseTest
|
|||
private void testParse(Function<ByteBuffer, ByteBuffer> fn)
|
||||
{
|
||||
AtomicBoolean failure = new AtomicBoolean();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onConnectionFailure(int error, String reason)
|
||||
|
|
|
@ -21,23 +21,23 @@ import java.util.function.UnaryOperator;
|
|||
import org.eclipse.jetty.http2.internal.generator.HeaderGenerator;
|
||||
import org.eclipse.jetty.http2.internal.generator.WindowUpdateGenerator;
|
||||
import org.eclipse.jetty.http2.internal.parser.Parser;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class WindowUpdateGenerateParseTest
|
||||
{
|
||||
private final ByteBufferPool byteBufferPool = new MappedByteBufferPool();
|
||||
private final RetainableByteBufferPool bufferPool = new ArrayRetainableByteBufferPool();
|
||||
|
||||
@Test
|
||||
public void testGenerateParse() throws Exception
|
||||
{
|
||||
WindowUpdateGenerator generator = new WindowUpdateGenerator(new HeaderGenerator());
|
||||
WindowUpdateGenerator generator = new WindowUpdateGenerator(new HeaderGenerator(bufferPool));
|
||||
|
||||
final List<WindowUpdateFrame> frames = new ArrayList<>();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onWindowUpdate(WindowUpdateFrame frame)
|
||||
|
@ -53,11 +53,11 @@ public class WindowUpdateGenerateParseTest
|
|||
// Iterate a few times to be sure generator and parser are properly reset.
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.generateWindowUpdate(lease, streamId, windowUpdate);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.generateWindowUpdate(accumulator, streamId, windowUpdate);
|
||||
|
||||
frames.clear();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
|
@ -75,10 +75,10 @@ public class WindowUpdateGenerateParseTest
|
|||
@Test
|
||||
public void testGenerateParseOneByteAtATime() throws Exception
|
||||
{
|
||||
WindowUpdateGenerator generator = new WindowUpdateGenerator(new HeaderGenerator());
|
||||
WindowUpdateGenerator generator = new WindowUpdateGenerator(new HeaderGenerator(bufferPool));
|
||||
|
||||
final List<WindowUpdateFrame> frames = new ArrayList<>();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onWindowUpdate(WindowUpdateFrame frame)
|
||||
|
@ -94,11 +94,11 @@ public class WindowUpdateGenerateParseTest
|
|||
// Iterate a few times to be sure generator and parser are properly reset.
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.generateWindowUpdate(lease, streamId, windowUpdate);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.generateWindowUpdate(accumulator, streamId, windowUpdate);
|
||||
|
||||
frames.clear();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
while (buffer.hasRemaining())
|
||||
{
|
||||
|
|
|
@ -271,7 +271,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
|||
{
|
||||
ServerSessionListener listener = newSessionListener(connector, endPoint);
|
||||
|
||||
Generator generator = new Generator(connector.getByteBufferPool(), isUseOutputDirectByteBuffers(), getMaxDynamicTableSize(), getMaxHeaderBlockFragment());
|
||||
Generator generator = new Generator(connector.getRetainableByteBufferPool(), isUseOutputDirectByteBuffers(), getMaxDynamicTableSize(), getMaxHeaderBlockFragment());
|
||||
FlowControlStrategy flowControl = getFlowControlStrategyFactory().newFlowControlStrategy();
|
||||
HTTP2ServerSession session = new HTTP2ServerSession(connector.getScheduler(), endPoint, generator, listener, flowControl);
|
||||
session.setMaxLocalStreams(getMaxConcurrentStreams());
|
||||
|
@ -291,7 +291,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
|||
parser.setMaxFrameLength(getMaxFrameLength());
|
||||
parser.setMaxSettingsKeys(getMaxSettingsKeys());
|
||||
|
||||
RetainableByteBufferPool retainableByteBufferPool = connector.getByteBufferPool().asRetainableByteBufferPool();
|
||||
RetainableByteBufferPool retainableByteBufferPool = connector.getRetainableByteBufferPool();
|
||||
|
||||
HTTP2Connection connection = new HTTP2ServerConnection(retainableByteBufferPool, connector,
|
||||
endPoint, httpConfiguration, parser, session, getInputBufferSize(), listener);
|
||||
|
@ -305,7 +305,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
|||
|
||||
private ServerParser newServerParser(Connector connector, ServerParser.Listener listener, RateControl rateControl)
|
||||
{
|
||||
return new ServerParser(connector.getByteBufferPool(), listener, getMaxDynamicTableSize(), getHttpConfiguration().getRequestHeaderSize(), rateControl);
|
||||
return new ServerParser(connector.getRetainableByteBufferPool(), listener, getMaxDynamicTableSize(), getHttpConfiguration().getRequestHeaderSize(), rateControl);
|
||||
}
|
||||
|
||||
@ManagedObject("The container of HTTP/2 sessions")
|
||||
|
|
|
@ -253,7 +253,7 @@ public class HttpStreamOverHTTP2 implements HttpStream, HTTP2Channel.Server
|
|||
data.release();
|
||||
return Content.Chunk.EOF;
|
||||
}
|
||||
return Content.Chunk.asChunk(frame.getData(), frame.isEndStream(), data);
|
||||
return Content.Chunk.asChunk(frame.getByteBuffer(), frame.isEndStream(), data);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -29,8 +29,8 @@ import org.eclipse.jetty.http2.internal.generator.Generator;
|
|||
import org.eclipse.jetty.http2.internal.parser.Parser;
|
||||
import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
|
||||
import org.eclipse.jetty.http2.server.RawHTTP2ServerConnectionFactory;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.server.ConnectionFactory;
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
|
@ -42,7 +42,7 @@ import org.junit.jupiter.api.AfterEach;
|
|||
public class AbstractServerTest
|
||||
{
|
||||
protected ServerConnector connector;
|
||||
protected ByteBufferPool byteBufferPool;
|
||||
protected RetainableByteBufferPool bufferPool;
|
||||
protected Generator generator;
|
||||
protected Server server;
|
||||
protected String path;
|
||||
|
@ -68,8 +68,8 @@ public class AbstractServerTest
|
|||
connector = new ServerConnector(server, connectionFactory);
|
||||
server.addConnector(connector);
|
||||
path = "/test";
|
||||
byteBufferPool = new MappedByteBufferPool();
|
||||
generator = new Generator(byteBufferPool);
|
||||
bufferPool = new ArrayRetainableByteBufferPool();
|
||||
generator = new Generator(bufferPool);
|
||||
}
|
||||
|
||||
protected MetaData.Request newRequest(String method, HttpFields fields)
|
||||
|
|
|
@ -31,7 +31,7 @@ import org.eclipse.jetty.http2.frames.PrefaceFrame;
|
|||
import org.eclipse.jetty.http2.frames.SettingsFrame;
|
||||
import org.eclipse.jetty.http2.internal.generator.Generator;
|
||||
import org.eclipse.jetty.http2.server.HTTP2CServerConnectionFactory;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
|
@ -97,8 +97,8 @@ public class BadURITest
|
|||
}
|
||||
});
|
||||
|
||||
ByteBufferPool byteBufferPool = connector.getByteBufferPool();
|
||||
Generator generator = new Generator(byteBufferPool);
|
||||
RetainableByteBufferPool bufferPool = connector.getRetainableByteBufferPool();
|
||||
Generator generator = new Generator(bufferPool);
|
||||
|
||||
// Craft a request with a bad URI, it will not hit the Handler.
|
||||
MetaData.Request metaData1 = new MetaData.Request(
|
||||
|
@ -111,15 +111,15 @@ public class BadURITest
|
|||
HttpFields.EMPTY,
|
||||
-1
|
||||
);
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.control(lease, new PrefaceFrame());
|
||||
generator.control(lease, new SettingsFrame(new HashMap<>(), false));
|
||||
generator.control(lease, new HeadersFrame(1, metaData1, null, true));
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.control(accumulator, new PrefaceFrame());
|
||||
generator.control(accumulator, new SettingsFrame(new HashMap<>(), false));
|
||||
generator.control(accumulator, new HeadersFrame(1, metaData1, null, true));
|
||||
|
||||
try (Socket client = new Socket("localhost", connector.getLocalPort()))
|
||||
{
|
||||
OutputStream output = client.getOutputStream();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
output.write(BufferUtil.toArray(buffer));
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ public class BadURITest
|
|||
Thread.sleep(1000);
|
||||
|
||||
// Send a second request and verify that it hits the Handler.
|
||||
lease.recycle();
|
||||
accumulator.release();
|
||||
MetaData.Request metaData2 = new MetaData.Request(
|
||||
HttpMethod.GET.asString(),
|
||||
HttpScheme.HTTP.asString(),
|
||||
|
@ -138,8 +138,8 @@ public class BadURITest
|
|||
HttpFields.EMPTY,
|
||||
-1
|
||||
);
|
||||
generator.control(lease, new HeadersFrame(3, metaData2, null, true));
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
generator.control(accumulator, new HeadersFrame(3, metaData2, null, true));
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
output.write(BufferUtil.toArray(buffer));
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ import org.eclipse.jetty.http2.frames.SettingsFrame;
|
|||
import org.eclipse.jetty.http2.internal.ErrorCode;
|
||||
import org.eclipse.jetty.http2.internal.HTTP2Session;
|
||||
import org.eclipse.jetty.http2.internal.parser.Parser;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.RuntimeIOException;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
|
@ -74,21 +74,21 @@ public class CloseTest extends AbstractServerTest
|
|||
}
|
||||
});
|
||||
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.control(lease, new PrefaceFrame());
|
||||
generator.control(lease, new SettingsFrame(new HashMap<>(), false));
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.control(accumulator, new PrefaceFrame());
|
||||
generator.control(accumulator, new SettingsFrame(new HashMap<>(), false));
|
||||
MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY);
|
||||
generator.control(lease, new HeadersFrame(1, metaData, null, true));
|
||||
generator.control(accumulator, new HeadersFrame(1, metaData, null, true));
|
||||
|
||||
try (Socket client = new Socket("localhost", connector.getLocalPort()))
|
||||
{
|
||||
OutputStream output = client.getOutputStream();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
output.write(BufferUtil.toArray(buffer));
|
||||
}
|
||||
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onHeaders(HeadersFrame frame)
|
||||
|
@ -135,17 +135,17 @@ public class CloseTest extends AbstractServerTest
|
|||
}
|
||||
});
|
||||
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.control(lease, new PrefaceFrame());
|
||||
generator.control(lease, new SettingsFrame(new HashMap<>(), false));
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.control(accumulator, new PrefaceFrame());
|
||||
generator.control(accumulator, new SettingsFrame(new HashMap<>(), false));
|
||||
MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY);
|
||||
generator.control(lease, new HeadersFrame(1, metaData, null, true));
|
||||
generator.control(lease, new GoAwayFrame(1, ErrorCode.NO_ERROR.code, "OK".getBytes(StandardCharsets.UTF_8)));
|
||||
generator.control(accumulator, new HeadersFrame(1, metaData, null, true));
|
||||
generator.control(accumulator, new GoAwayFrame(1, ErrorCode.NO_ERROR.code, "OK".getBytes(StandardCharsets.UTF_8)));
|
||||
|
||||
try (Socket client = new Socket("localhost", connector.getLocalPort()))
|
||||
{
|
||||
OutputStream output = client.getOutputStream();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
output.write(BufferUtil.toArray(buffer));
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ public class CloseTest extends AbstractServerTest
|
|||
// Don't close the connection; the server should close.
|
||||
|
||||
final CountDownLatch responseLatch = new CountDownLatch(1);
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onHeaders(HeadersFrame frame)
|
||||
|
@ -202,23 +202,23 @@ public class CloseTest extends AbstractServerTest
|
|||
});
|
||||
connector.setIdleTimeout(idleTimeout);
|
||||
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.control(lease, new PrefaceFrame());
|
||||
generator.control(lease, new SettingsFrame(new HashMap<>(), false));
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.control(accumulator, new PrefaceFrame());
|
||||
generator.control(accumulator, new SettingsFrame(new HashMap<>(), false));
|
||||
MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY);
|
||||
generator.control(lease, new HeadersFrame(1, metaData, null, true));
|
||||
generator.control(accumulator, new HeadersFrame(1, metaData, null, true));
|
||||
|
||||
try (Socket client = new Socket("localhost", connector.getLocalPort()))
|
||||
{
|
||||
OutputStream output = client.getOutputStream();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
output.write(BufferUtil.toArray(buffer));
|
||||
}
|
||||
|
||||
final CountDownLatch responseLatch = new CountDownLatch(1);
|
||||
final CountDownLatch closeLatch = new CountDownLatch(1);
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onHeaders(HeadersFrame frame)
|
||||
|
|
|
@ -35,8 +35,8 @@ import org.eclipse.jetty.http2.frames.DataFrame;
|
|||
import org.eclipse.jetty.http2.frames.HeadersFrame;
|
||||
import org.eclipse.jetty.http2.internal.HTTP2Session;
|
||||
import org.eclipse.jetty.http2.internal.generator.Generator;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.FuturePromise;
|
||||
import org.eclipse.jetty.util.Promise;
|
||||
|
@ -119,7 +119,7 @@ public class DataDemandTest extends AbstractTest
|
|||
await().atMost(1, TimeUnit.SECONDS).until(() -> serverQueue.size() == count.get() + 1);
|
||||
count.incrementAndGet();
|
||||
long sum = serverQueue.stream()
|
||||
.mapToLong(data -> data.frame().getData().remaining())
|
||||
.mapToLong(data -> data.frame().getByteBuffer().remaining())
|
||||
.sum();
|
||||
if (sum == length)
|
||||
break;
|
||||
|
@ -155,7 +155,7 @@ public class DataDemandTest extends AbstractTest
|
|||
await().atMost(1, TimeUnit.SECONDS).until(() -> clientQueue.size() == count.get() + 1);
|
||||
count.incrementAndGet();
|
||||
long sum = clientQueue.stream()
|
||||
.mapToLong(data -> data.frame().getData().remaining())
|
||||
.mapToLong(data -> data.frame().getByteBuffer().remaining())
|
||||
.sum();
|
||||
if (sum == length)
|
||||
break;
|
||||
|
@ -365,17 +365,17 @@ public class DataDemandTest extends AbstractTest
|
|||
// Generate a lot of small DATA frames and write them in a single
|
||||
// write so that the server will continuously be notified and demand,
|
||||
// which will test that it won't throw StackOverflowError.
|
||||
MappedByteBufferPool byteBufferPool = new MappedByteBufferPool();
|
||||
Generator generator = new Generator(byteBufferPool);
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
RetainableByteBufferPool bufferPool = new ArrayRetainableByteBufferPool();
|
||||
Generator generator = new Generator(bufferPool);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
for (int i = 512; i >= 0; --i)
|
||||
generator.data(lease, new DataFrame(clientStream.getId(), ByteBuffer.allocate(1), i == 0), 1);
|
||||
generator.data(accumulator, new DataFrame(clientStream.getId(), ByteBuffer.allocate(1), i == 0), 1);
|
||||
|
||||
// Since this is a naked write, we need to wait that the
|
||||
// client finishes writing the SETTINGS reply to the server
|
||||
// during connection initialization, or we risk a WritePendingException.
|
||||
Thread.sleep(1000);
|
||||
((HTTP2Session)clientStream.getSession()).getEndPoint().write(Callback.NOOP, lease.getByteBuffers().toArray(new ByteBuffer[0]));
|
||||
((HTTP2Session)clientStream.getSession()).getEndPoint().write(Callback.NOOP, accumulator.getByteBuffers().toArray(ByteBuffer[]::new));
|
||||
|
||||
assertTrue(latch.await(15, TimeUnit.SECONDS));
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ import org.eclipse.jetty.http2.internal.ErrorCode;
|
|||
import org.eclipse.jetty.http2.internal.HTTP2Session;
|
||||
import org.eclipse.jetty.http2.internal.HTTP2Stream;
|
||||
import org.eclipse.jetty.http2.server.RawHTTP2ServerConnectionFactory;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
|
@ -667,7 +667,7 @@ public abstract class FlowControlStrategyTest
|
|||
Stream.Data data = stream.readData();
|
||||
DataFrame frame = data.frame();
|
||||
int remaining = frame.remaining();
|
||||
frame.getData().get(bytes, received, remaining);
|
||||
frame.getByteBuffer().get(bytes, received, remaining);
|
||||
this.received += remaining;
|
||||
data.release();
|
||||
if (frame.isEndStream())
|
||||
|
@ -737,7 +737,7 @@ public abstract class FlowControlStrategyTest
|
|||
public void onDataAvailable(Stream stream)
|
||||
{
|
||||
Stream.Data data = stream.readData();
|
||||
responseContent.put(data.frame().getData());
|
||||
responseContent.put(data.frame().getByteBuffer());
|
||||
data.release();
|
||||
if (data.frame().isEndStream())
|
||||
latch.countDown();
|
||||
|
@ -844,10 +844,10 @@ public abstract class FlowControlStrategyTest
|
|||
// Now the client is supposed to not send more frames.
|
||||
// If it does, the connection must be closed.
|
||||
HTTP2Session http2Session = (HTTP2Session)session;
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(connector.getByteBufferPool());
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
ByteBuffer extraData = ByteBuffer.allocate(1024);
|
||||
http2Session.getGenerator().data(lease, new DataFrame(stream.getId(), extraData, true), extraData.remaining());
|
||||
List<ByteBuffer> buffers = lease.getByteBuffers();
|
||||
http2Session.getGenerator().data(accumulator, new DataFrame(stream.getId(), extraData, true), extraData.remaining());
|
||||
List<ByteBuffer> buffers = accumulator.getByteBuffers();
|
||||
http2Session.getEndPoint().write(Callback.NOOP, buffers.toArray(new ByteBuffer[0]));
|
||||
|
||||
// Expect the connection to be closed.
|
||||
|
@ -949,10 +949,10 @@ public abstract class FlowControlStrategyTest
|
|||
// Now the client is supposed to not send more frames.
|
||||
// If it does, the connection must be closed.
|
||||
HTTP2Session http2Session = (HTTP2Session)session;
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(connector.getByteBufferPool());
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
ByteBuffer extraData = ByteBuffer.allocate(1024);
|
||||
http2Session.getGenerator().data(lease, new DataFrame(stream.getId(), extraData, true), extraData.remaining());
|
||||
List<ByteBuffer> buffers = lease.getByteBuffers();
|
||||
http2Session.getGenerator().data(accumulator, new DataFrame(stream.getId(), extraData, true), extraData.remaining());
|
||||
List<ByteBuffer> buffers = accumulator.getByteBuffers();
|
||||
http2Session.getEndPoint().write(Callback.NOOP, buffers.toArray(new ByteBuffer[0]));
|
||||
|
||||
// Expect the connection to be closed.
|
||||
|
|
|
@ -38,10 +38,10 @@ import org.eclipse.jetty.http2.frames.PrefaceFrame;
|
|||
import org.eclipse.jetty.http2.frames.SettingsFrame;
|
||||
import org.eclipse.jetty.http2.internal.generator.Generator;
|
||||
import org.eclipse.jetty.http2.internal.parser.Parser;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
|
@ -150,13 +150,13 @@ public class HTTP2CServerTest extends AbstractServerTest
|
|||
|
||||
assertTrue(upgrade.toString().startsWith("HTTP/1.1 101 "));
|
||||
|
||||
byteBufferPool = new MappedByteBufferPool();
|
||||
generator = new Generator(byteBufferPool);
|
||||
bufferPool = new ArrayRetainableByteBufferPool();
|
||||
generator = new Generator(bufferPool);
|
||||
|
||||
final AtomicReference<HeadersFrame> headersRef = new AtomicReference<>();
|
||||
final AtomicReference<DataFrame> dataRef = new AtomicReference<>();
|
||||
final AtomicReference<CountDownLatch> latchRef = new AtomicReference<>(new CountDownLatch(2));
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onHeaders(HeadersFrame frame)
|
||||
|
@ -186,7 +186,7 @@ public class HTTP2CServerTest extends AbstractServerTest
|
|||
DataFrame responseData = dataRef.get();
|
||||
assertNotNull(responseData);
|
||||
|
||||
String content = BufferUtil.toString(responseData.getData());
|
||||
String content = BufferUtil.toString(responseData.getByteBuffer());
|
||||
|
||||
// The upgrade request is seen as HTTP/1.1.
|
||||
assertThat(content, containsString("Hello from Jetty using HTTP/2.0"));
|
||||
|
@ -196,12 +196,12 @@ public class HTTP2CServerTest extends AbstractServerTest
|
|||
headersRef.set(null);
|
||||
dataRef.set(null);
|
||||
latchRef.set(new CountDownLatch(2));
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.control(lease, new PrefaceFrame());
|
||||
generator.control(lease, new SettingsFrame(new HashMap<>(), false));
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.control(accumulator, new PrefaceFrame());
|
||||
generator.control(accumulator, new SettingsFrame(new HashMap<>(), false));
|
||||
MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:" + connector.getLocalPort()), "/two", HttpVersion.HTTP_2, HttpFields.EMPTY, -1);
|
||||
generator.control(lease, new HeadersFrame(3, metaData, null, true));
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
generator.control(accumulator, new HeadersFrame(3, metaData, null, true));
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
output.write(BufferUtil.toArray(buffer));
|
||||
}
|
||||
|
@ -219,7 +219,7 @@ public class HTTP2CServerTest extends AbstractServerTest
|
|||
responseData = dataRef.get();
|
||||
assertNotNull(responseData);
|
||||
|
||||
content = BufferUtil.toString(responseData.getData());
|
||||
content = BufferUtil.toString(responseData.getByteBuffer());
|
||||
|
||||
assertThat(content, containsString("Hello from Jetty using HTTP/2.0"));
|
||||
assertThat(content, containsString("uri=/two"));
|
||||
|
@ -231,28 +231,28 @@ public class HTTP2CServerTest extends AbstractServerTest
|
|||
{
|
||||
final CountDownLatch latch = new CountDownLatch(3);
|
||||
|
||||
byteBufferPool = new MappedByteBufferPool();
|
||||
generator = new Generator(byteBufferPool);
|
||||
bufferPool = new ArrayRetainableByteBufferPool();
|
||||
generator = new Generator(bufferPool);
|
||||
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.control(lease, new PrefaceFrame());
|
||||
generator.control(lease, new SettingsFrame(new HashMap<>(), false));
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.control(accumulator, new PrefaceFrame());
|
||||
generator.control(accumulator, new SettingsFrame(new HashMap<>(), false));
|
||||
MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:" + connector.getLocalPort()), "/test", HttpVersion.HTTP_2, HttpFields.EMPTY, -1);
|
||||
generator.control(lease, new HeadersFrame(1, metaData, null, true));
|
||||
generator.control(accumulator, new HeadersFrame(1, metaData, null, true));
|
||||
|
||||
try (Socket client = new Socket("localhost", connector.getLocalPort()))
|
||||
{
|
||||
client.setSoTimeout(5000);
|
||||
|
||||
OutputStream output = client.getOutputStream();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
output.write(BufferUtil.toArray(buffer));
|
||||
}
|
||||
|
||||
final AtomicReference<HeadersFrame> headersRef = new AtomicReference<>();
|
||||
final AtomicReference<DataFrame> dataRef = new AtomicReference<>();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onSettings(SettingsFrame frame)
|
||||
|
@ -288,7 +288,7 @@ public class HTTP2CServerTest extends AbstractServerTest
|
|||
DataFrame responseData = dataRef.get();
|
||||
assertNotNull(responseData);
|
||||
|
||||
String s = BufferUtil.toString(responseData.getData());
|
||||
String s = BufferUtil.toString(responseData.getByteBuffer());
|
||||
|
||||
assertThat(s, containsString("Hello from Jetty using HTTP/2.0"));
|
||||
assertThat(s, containsString("uri=/test"));
|
||||
|
@ -328,18 +328,18 @@ public class HTTP2CServerTest extends AbstractServerTest
|
|||
// Now send an HTTP/2 direct request, which
|
||||
// will have the PRI * HTTP/2.0 preface.
|
||||
|
||||
byteBufferPool = new MappedByteBufferPool();
|
||||
generator = new Generator(byteBufferPool);
|
||||
bufferPool = new ArrayRetainableByteBufferPool();
|
||||
generator = new Generator(bufferPool);
|
||||
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.control(lease, new PrefaceFrame());
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.control(accumulator, new PrefaceFrame());
|
||||
|
||||
try (Socket client = new Socket("localhost", connector.getLocalPort()))
|
||||
{
|
||||
client.setSoTimeout(5000);
|
||||
|
||||
OutputStream output = client.getOutputStream();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
output.write(BufferUtil.toArray(buffer));
|
||||
}
|
||||
|
|
|
@ -47,8 +47,9 @@ import org.eclipse.jetty.http2.internal.Flags;
|
|||
import org.eclipse.jetty.http2.internal.generator.Generator;
|
||||
import org.eclipse.jetty.http2.internal.parser.Parser;
|
||||
import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.ManagedSelector;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.SocketChannelEndPoint;
|
||||
import org.eclipse.jetty.logging.StacklessLogging;
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
|
@ -84,19 +85,19 @@ public class HTTP2ServerTest extends AbstractServerTest
|
|||
|
||||
// No preface bytes.
|
||||
MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY);
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.control(lease, new HeadersFrame(1, metaData, null, true));
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.control(accumulator, new HeadersFrame(1, metaData, null, true));
|
||||
|
||||
try (Socket client = new Socket("localhost", connector.getLocalPort()))
|
||||
{
|
||||
OutputStream output = client.getOutputStream();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
output.write(BufferUtil.toArray(buffer));
|
||||
}
|
||||
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onGoAway(GoAwayFrame frame)
|
||||
|
@ -115,7 +116,7 @@ public class HTTP2ServerTest extends AbstractServerTest
|
|||
@Test
|
||||
public void testRequestResponseNoContent() throws Exception
|
||||
{
|
||||
final CountDownLatch latch = new CountDownLatch(3);
|
||||
CountDownLatch latch = new CountDownLatch(3);
|
||||
startServer(new Handler.Abstract()
|
||||
{
|
||||
@Override
|
||||
|
@ -127,22 +128,22 @@ public class HTTP2ServerTest extends AbstractServerTest
|
|||
}
|
||||
});
|
||||
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.control(lease, new PrefaceFrame());
|
||||
generator.control(lease, new SettingsFrame(new HashMap<>(), false));
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.control(accumulator, new PrefaceFrame());
|
||||
generator.control(accumulator, new SettingsFrame(new HashMap<>(), false));
|
||||
MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY);
|
||||
generator.control(lease, new HeadersFrame(1, metaData, null, true));
|
||||
generator.control(accumulator, new HeadersFrame(1, metaData, null, true));
|
||||
|
||||
try (Socket client = new Socket("localhost", connector.getLocalPort()))
|
||||
{
|
||||
OutputStream output = client.getOutputStream();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
output.write(BufferUtil.toArray(buffer));
|
||||
}
|
||||
|
||||
final AtomicReference<HeadersFrame> frameRef = new AtomicReference<>();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
AtomicReference<HeadersFrame> frameRef = new AtomicReference<>();
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onSettings(SettingsFrame frame)
|
||||
|
@ -173,8 +174,8 @@ public class HTTP2ServerTest extends AbstractServerTest
|
|||
@Test
|
||||
public void testRequestResponseContent() throws Exception
|
||||
{
|
||||
final byte[] content = "Hello, world!".getBytes(StandardCharsets.UTF_8);
|
||||
final CountDownLatch latch = new CountDownLatch(4);
|
||||
byte[] content = "Hello, world!".getBytes(StandardCharsets.UTF_8);
|
||||
CountDownLatch latch = new CountDownLatch(4);
|
||||
startServer(new Handler.Abstract()
|
||||
{
|
||||
@Override
|
||||
|
@ -186,23 +187,23 @@ public class HTTP2ServerTest extends AbstractServerTest
|
|||
}
|
||||
});
|
||||
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.control(lease, new PrefaceFrame());
|
||||
generator.control(lease, new SettingsFrame(new HashMap<>(), false));
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.control(accumulator, new PrefaceFrame());
|
||||
generator.control(accumulator, new SettingsFrame(new HashMap<>(), false));
|
||||
MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY);
|
||||
generator.control(lease, new HeadersFrame(1, metaData, null, true));
|
||||
generator.control(accumulator, new HeadersFrame(1, metaData, null, true));
|
||||
|
||||
try (Socket client = new Socket("localhost", connector.getLocalPort()))
|
||||
{
|
||||
OutputStream output = client.getOutputStream();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
output.write(BufferUtil.toArray(buffer));
|
||||
}
|
||||
|
||||
final AtomicReference<HeadersFrame> headersRef = new AtomicReference<>();
|
||||
final AtomicReference<DataFrame> dataRef = new AtomicReference<>();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
AtomicReference<HeadersFrame> headersRef = new AtomicReference<>();
|
||||
AtomicReference<DataFrame> dataRef = new AtomicReference<>();
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onSettings(SettingsFrame frame)
|
||||
|
@ -237,7 +238,7 @@ public class HTTP2ServerTest extends AbstractServerTest
|
|||
|
||||
DataFrame responseData = dataRef.get();
|
||||
assertNotNull(responseData);
|
||||
assertArrayEquals(content, BufferUtil.toArray(responseData.getData()));
|
||||
assertArrayEquals(content, BufferUtil.toArray(responseData.getByteBuffer()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -254,23 +255,23 @@ public class HTTP2ServerTest extends AbstractServerTest
|
|||
}
|
||||
});
|
||||
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.control(lease, new PrefaceFrame());
|
||||
generator.control(lease, new SettingsFrame(new HashMap<>(), false));
|
||||
generator.control(lease, new PingFrame(new byte[8], false));
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.control(accumulator, new PrefaceFrame());
|
||||
generator.control(accumulator, new SettingsFrame(new HashMap<>(), false));
|
||||
generator.control(accumulator, new PingFrame(new byte[8], false));
|
||||
// Modify the length of the frame to a wrong one.
|
||||
lease.getByteBuffers().get(2).putShort(0, (short)7);
|
||||
accumulator.getByteBuffers().get(2).putShort(0, (short)7);
|
||||
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
try (Socket client = new Socket("localhost", connector.getLocalPort()))
|
||||
{
|
||||
OutputStream output = client.getOutputStream();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
output.write(BufferUtil.toArray(buffer));
|
||||
}
|
||||
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onGoAway(GoAwayFrame frame)
|
||||
|
@ -300,23 +301,23 @@ public class HTTP2ServerTest extends AbstractServerTest
|
|||
}
|
||||
});
|
||||
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.control(lease, new PrefaceFrame());
|
||||
generator.control(lease, new SettingsFrame(new HashMap<>(), false));
|
||||
generator.control(lease, new PingFrame(new byte[8], false));
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.control(accumulator, new PrefaceFrame());
|
||||
generator.control(accumulator, new SettingsFrame(new HashMap<>(), false));
|
||||
generator.control(accumulator, new PingFrame(new byte[8], false));
|
||||
// Modify the streamId of the frame to non zero.
|
||||
lease.getByteBuffers().get(2).putInt(4, 1);
|
||||
accumulator.getByteBuffers().get(2).putInt(4, 1);
|
||||
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
try (Socket client = new Socket("localhost", connector.getLocalPort()))
|
||||
{
|
||||
OutputStream output = client.getOutputStream();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
output.write(BufferUtil.toArray(buffer));
|
||||
}
|
||||
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onGoAway(GoAwayFrame frame)
|
||||
|
@ -336,8 +337,8 @@ public class HTTP2ServerTest extends AbstractServerTest
|
|||
@Test
|
||||
public void testCommitFailure() throws Exception
|
||||
{
|
||||
final long delay = 1000;
|
||||
final AtomicBoolean broken = new AtomicBoolean();
|
||||
long delay = 1000;
|
||||
AtomicBoolean broken = new AtomicBoolean();
|
||||
startServer(new Handler.Abstract()
|
||||
{
|
||||
@Override
|
||||
|
@ -373,22 +374,22 @@ public class HTTP2ServerTest extends AbstractServerTest
|
|||
server.addConnector(connector2);
|
||||
server.start();
|
||||
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.control(lease, new PrefaceFrame());
|
||||
generator.control(lease, new SettingsFrame(new HashMap<>(), false));
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.control(accumulator, new PrefaceFrame());
|
||||
generator.control(accumulator, new SettingsFrame(new HashMap<>(), false));
|
||||
MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY);
|
||||
generator.control(lease, new HeadersFrame(1, metaData, null, true));
|
||||
generator.control(accumulator, new HeadersFrame(1, metaData, null, true));
|
||||
try (Socket client = new Socket("localhost", connector2.getLocalPort()))
|
||||
{
|
||||
OutputStream output = client.getOutputStream();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
output.write(BufferUtil.toArray(buffer));
|
||||
}
|
||||
|
||||
// The server will close the connection abruptly since it
|
||||
// cannot write and therefore cannot even send the GO_AWAY.
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter(), 4096, 8192);
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter(), 4096, 8192);
|
||||
parser.init(UnaryOperator.identity());
|
||||
boolean closed = parseResponse(client, parser, 2 * delay);
|
||||
assertTrue(closed);
|
||||
|
@ -413,22 +414,22 @@ public class HTTP2ServerTest extends AbstractServerTest
|
|||
}
|
||||
});
|
||||
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.control(lease, new PrefaceFrame());
|
||||
generator.control(lease, new SettingsFrame(new HashMap<>(), false));
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.control(accumulator, new PrefaceFrame());
|
||||
generator.control(accumulator, new SettingsFrame(new HashMap<>(), false));
|
||||
MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY);
|
||||
generator.control(lease, new HeadersFrame(1, metaData, null, true));
|
||||
generator.control(accumulator, new HeadersFrame(1, metaData, null, true));
|
||||
|
||||
try (Socket client = new Socket("localhost", connector.getLocalPort()))
|
||||
{
|
||||
OutputStream output = client.getOutputStream();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
output.write(BufferUtil.toArray(buffer));
|
||||
}
|
||||
output.flush();
|
||||
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter(), 4096, 8192);
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter(), 4096, 8192);
|
||||
parser.init(UnaryOperator.identity());
|
||||
boolean closed = parseResponse(client, parser);
|
||||
|
||||
|
@ -442,12 +443,12 @@ public class HTTP2ServerTest extends AbstractServerTest
|
|||
{
|
||||
testRequestWithContinuationFrames(null, () ->
|
||||
{
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.control(lease, new PrefaceFrame());
|
||||
generator.control(lease, new SettingsFrame(new HashMap<>(), false));
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.control(accumulator, new PrefaceFrame());
|
||||
generator.control(accumulator, new SettingsFrame(new HashMap<>(), false));
|
||||
MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY);
|
||||
generator.control(lease, new HeadersFrame(1, metaData, null, true));
|
||||
return lease;
|
||||
generator.control(accumulator, new HeadersFrame(1, metaData, null, true));
|
||||
return accumulator;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -457,12 +458,12 @@ public class HTTP2ServerTest extends AbstractServerTest
|
|||
PriorityFrame priority = new PriorityFrame(1, 13, 200, true);
|
||||
testRequestWithContinuationFrames(priority, () ->
|
||||
{
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.control(lease, new PrefaceFrame());
|
||||
generator.control(lease, new SettingsFrame(new HashMap<>(), false));
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.control(accumulator, new PrefaceFrame());
|
||||
generator.control(accumulator, new SettingsFrame(new HashMap<>(), false));
|
||||
MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY);
|
||||
generator.control(lease, new HeadersFrame(1, metaData, priority, true));
|
||||
return lease;
|
||||
generator.control(accumulator, new HeadersFrame(1, metaData, priority, true));
|
||||
return accumulator;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -471,19 +472,19 @@ public class HTTP2ServerTest extends AbstractServerTest
|
|||
{
|
||||
testRequestWithContinuationFrames(null, () ->
|
||||
{
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.control(lease, new PrefaceFrame());
|
||||
generator.control(lease, new SettingsFrame(new HashMap<>(), false));
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.control(accumulator, new PrefaceFrame());
|
||||
generator.control(accumulator, new SettingsFrame(new HashMap<>(), false));
|
||||
MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY);
|
||||
generator.control(lease, new HeadersFrame(1, metaData, null, true));
|
||||
generator.control(accumulator, new HeadersFrame(1, metaData, null, true));
|
||||
// Take the HeadersFrame header and set the length to zero.
|
||||
List<ByteBuffer> buffers = lease.getByteBuffers();
|
||||
List<ByteBuffer> buffers = accumulator.getByteBuffers();
|
||||
ByteBuffer headersFrameHeader = buffers.get(2);
|
||||
headersFrameHeader.put(0, (byte)0);
|
||||
headersFrameHeader.putShort(1, (short)0);
|
||||
// Insert a CONTINUATION frame header for the body of the HEADERS frame.
|
||||
lease.insert(3, buffers.get(4).slice(), false);
|
||||
return lease;
|
||||
accumulator.insert(3, RetainableByteBuffer.wrap(buffers.get(4).slice()));
|
||||
return accumulator;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -493,19 +494,19 @@ public class HTTP2ServerTest extends AbstractServerTest
|
|||
PriorityFrame priority = new PriorityFrame(1, 13, 200, true);
|
||||
testRequestWithContinuationFrames(null, () ->
|
||||
{
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.control(lease, new PrefaceFrame());
|
||||
generator.control(lease, new SettingsFrame(new HashMap<>(), false));
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.control(accumulator, new PrefaceFrame());
|
||||
generator.control(accumulator, new SettingsFrame(new HashMap<>(), false));
|
||||
MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY);
|
||||
generator.control(lease, new HeadersFrame(1, metaData, priority, true));
|
||||
generator.control(accumulator, new HeadersFrame(1, metaData, priority, true));
|
||||
// Take the HeadersFrame header and set the length to just the priority frame.
|
||||
List<ByteBuffer> buffers = lease.getByteBuffers();
|
||||
List<ByteBuffer> buffers = accumulator.getByteBuffers();
|
||||
ByteBuffer headersFrameHeader = buffers.get(2);
|
||||
headersFrameHeader.put(0, (byte)0);
|
||||
headersFrameHeader.putShort(1, (short)PriorityFrame.PRIORITY_LENGTH);
|
||||
// Insert a CONTINUATION frame header for the body of the HEADERS frame.
|
||||
lease.insert(3, buffers.get(4).slice(), false);
|
||||
return lease;
|
||||
accumulator.insert(3, RetainableByteBuffer.wrap(buffers.get(4).slice()));
|
||||
return accumulator;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -514,13 +515,13 @@ public class HTTP2ServerTest extends AbstractServerTest
|
|||
{
|
||||
testRequestWithContinuationFrames(null, () ->
|
||||
{
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.control(lease, new PrefaceFrame());
|
||||
generator.control(lease, new SettingsFrame(new HashMap<>(), false));
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.control(accumulator, new PrefaceFrame());
|
||||
generator.control(accumulator, new SettingsFrame(new HashMap<>(), false));
|
||||
MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY);
|
||||
generator.control(lease, new HeadersFrame(1, metaData, null, true));
|
||||
generator.control(accumulator, new HeadersFrame(1, metaData, null, true));
|
||||
// Take the ContinuationFrame header, duplicate it, and set the length to zero.
|
||||
List<ByteBuffer> buffers = lease.getByteBuffers();
|
||||
List<ByteBuffer> buffers = accumulator.getByteBuffers();
|
||||
ByteBuffer continuationFrameHeader = buffers.get(4);
|
||||
ByteBuffer duplicate = ByteBuffer.allocate(continuationFrameHeader.remaining());
|
||||
duplicate.put(continuationFrameHeader).flip();
|
||||
|
@ -528,8 +529,8 @@ public class HTTP2ServerTest extends AbstractServerTest
|
|||
continuationFrameHeader.put(0, (byte)0);
|
||||
continuationFrameHeader.putShort(1, (short)0);
|
||||
// Insert a CONTINUATION frame header for the body of the previous CONTINUATION frame.
|
||||
lease.insert(5, duplicate, false);
|
||||
return lease;
|
||||
accumulator.insert(5, RetainableByteBuffer.wrap(duplicate));
|
||||
return accumulator;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -538,13 +539,13 @@ public class HTTP2ServerTest extends AbstractServerTest
|
|||
{
|
||||
testRequestWithContinuationFrames(null, () ->
|
||||
{
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.control(lease, new PrefaceFrame());
|
||||
generator.control(lease, new SettingsFrame(new HashMap<>(), false));
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.control(accumulator, new PrefaceFrame());
|
||||
generator.control(accumulator, new SettingsFrame(new HashMap<>(), false));
|
||||
MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY);
|
||||
generator.control(lease, new HeadersFrame(1, metaData, null, true));
|
||||
generator.control(accumulator, new HeadersFrame(1, metaData, null, true));
|
||||
// Take the last CONTINUATION frame and reset the flag.
|
||||
List<ByteBuffer> buffers = lease.getByteBuffers();
|
||||
List<ByteBuffer> buffers = accumulator.getByteBuffers();
|
||||
ByteBuffer continuationFrameHeader = buffers.get(buffers.size() - 2);
|
||||
continuationFrameHeader.put(4, (byte)0);
|
||||
// Add a last, empty, CONTINUATION frame.
|
||||
|
@ -554,14 +555,14 @@ public class HTTP2ServerTest extends AbstractServerTest
|
|||
(byte)Flags.END_HEADERS,
|
||||
0, 0, 0, 1 // Stream ID
|
||||
});
|
||||
lease.append(last, false);
|
||||
return lease;
|
||||
accumulator.append(RetainableByteBuffer.wrap(last));
|
||||
return accumulator;
|
||||
});
|
||||
}
|
||||
|
||||
private void testRequestWithContinuationFrames(PriorityFrame priorityFrame, Callable<ByteBufferPool.Lease> frames) throws Exception
|
||||
private void testRequestWithContinuationFrames(PriorityFrame priorityFrame, Callable<RetainableByteBufferPool.Accumulator> frames) throws Exception
|
||||
{
|
||||
final CountDownLatch serverLatch = new CountDownLatch(1);
|
||||
CountDownLatch serverLatch = new CountDownLatch(1);
|
||||
startServer(new ServerSessionListener()
|
||||
{
|
||||
@Override
|
||||
|
@ -585,14 +586,14 @@ public class HTTP2ServerTest extends AbstractServerTest
|
|||
return null;
|
||||
}
|
||||
});
|
||||
generator = new Generator(byteBufferPool, 4096, 4);
|
||||
generator = new Generator(bufferPool, 4096, 4);
|
||||
|
||||
ByteBufferPool.Lease lease = frames.call();
|
||||
RetainableByteBufferPool.Accumulator accumulator = frames.call();
|
||||
|
||||
try (Socket client = new Socket("localhost", connector.getLocalPort()))
|
||||
{
|
||||
OutputStream output = client.getOutputStream();
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
output.write(BufferUtil.toArray(buffer));
|
||||
}
|
||||
|
@ -600,8 +601,8 @@ public class HTTP2ServerTest extends AbstractServerTest
|
|||
|
||||
assertTrue(serverLatch.await(5, TimeUnit.SECONDS));
|
||||
|
||||
final CountDownLatch clientLatch = new CountDownLatch(1);
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
CountDownLatch clientLatch = new CountDownLatch(1);
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onHeaders(HeadersFrame frame)
|
||||
|
|
|
@ -201,7 +201,7 @@ public class HTTP2Test extends AbstractTest
|
|||
Stream.Data data = stream.readData();
|
||||
DataFrame frame = data.frame();
|
||||
assertTrue(frame.isEndStream());
|
||||
assertEquals(ByteBuffer.wrap(content), frame.getData());
|
||||
assertEquals(ByteBuffer.wrap(content), frame.getByteBuffer());
|
||||
data.release();
|
||||
latch.countDown();
|
||||
}
|
||||
|
@ -593,10 +593,10 @@ public class HTTP2Test extends AbstractTest
|
|||
DataFrame data1 = new DataFrame(stream.getId(), ByteBuffer.allocate(1024), false)
|
||||
{
|
||||
@Override
|
||||
public ByteBuffer getData()
|
||||
public ByteBuffer getByteBuffer()
|
||||
{
|
||||
sleep(2 * sleep);
|
||||
return super.getData();
|
||||
return super.getByteBuffer();
|
||||
}
|
||||
};
|
||||
DataFrame data2 = new DataFrame(stream.getId(), BufferUtil.EMPTY_BUFFER, true);
|
||||
|
|
|
@ -67,10 +67,10 @@ import org.eclipse.jetty.http2.internal.HTTP2Session;
|
|||
import org.eclipse.jetty.http2.internal.generator.Generator;
|
||||
import org.eclipse.jetty.http2.internal.parser.ServerParser;
|
||||
import org.eclipse.jetty.http2.server.RawHTTP2ServerConnectionFactory;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.ClientConnector;
|
||||
import org.eclipse.jetty.io.Content;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
|
@ -111,7 +111,7 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest
|
|||
assertTrue(http2Client.isStarted());
|
||||
assertSame(httpClient.getExecutor(), http2Client.getExecutor());
|
||||
assertSame(httpClient.getScheduler(), http2Client.getScheduler());
|
||||
assertSame(httpClient.getByteBufferPool(), http2Client.getByteBufferPool());
|
||||
assertSame(httpClient.getRetainableByteBufferPool(), http2Client.getRetainableByteBufferPool());
|
||||
assertEquals(httpClient.getConnectTimeout(), http2Client.getConnectTimeout());
|
||||
assertEquals(httpClient.getIdleTimeout(), http2Client.getIdleTimeout());
|
||||
assertEquals(httpClient.isUseInputDirectByteBuffers(), http2Client.isUseInputDirectByteBuffers());
|
||||
|
@ -541,9 +541,9 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest
|
|||
resultLatch.countDown();
|
||||
});
|
||||
|
||||
ByteBufferPool byteBufferPool = new MappedByteBufferPool();
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
Generator generator = new Generator(byteBufferPool);
|
||||
RetainableByteBufferPool bufferPool = new ArrayRetainableByteBufferPool();
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
Generator generator = new Generator(bufferPool);
|
||||
|
||||
try (Socket socket = server.accept())
|
||||
{
|
||||
|
@ -551,7 +551,7 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest
|
|||
OutputStream output = socket.getOutputStream();
|
||||
InputStream input = socket.getInputStream();
|
||||
|
||||
ServerParser parser = new ServerParser(byteBufferPool, new ServerParser.Listener.Adapter()
|
||||
ServerParser parser = new ServerParser(bufferPool, new ServerParser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onPreface()
|
||||
|
@ -559,9 +559,9 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest
|
|||
try
|
||||
{
|
||||
// Server's preface.
|
||||
generator.control(lease, new SettingsFrame(new HashMap<>(), false));
|
||||
generator.control(accumulator, new SettingsFrame(new HashMap<>(), false));
|
||||
// Reply to client's SETTINGS.
|
||||
generator.control(lease, new SettingsFrame(new HashMap<>(), true));
|
||||
generator.control(accumulator, new SettingsFrame(new HashMap<>(), true));
|
||||
writeFrames();
|
||||
}
|
||||
catch (HpackException x)
|
||||
|
@ -578,7 +578,7 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest
|
|||
// Response.
|
||||
MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY);
|
||||
HeadersFrame response = new HeadersFrame(request.getStreamId(), metaData, null, true);
|
||||
generator.control(lease, response);
|
||||
generator.control(accumulator, response);
|
||||
writeFrames();
|
||||
}
|
||||
catch (HpackException x)
|
||||
|
@ -592,11 +592,11 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest
|
|||
try
|
||||
{
|
||||
// Write the frames.
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
for (ByteBuffer buffer : accumulator.getByteBuffers())
|
||||
{
|
||||
output.write(BufferUtil.toArray(buffer));
|
||||
}
|
||||
lease.recycle();
|
||||
accumulator.release();
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
|
|
|
@ -158,7 +158,7 @@ public class InterleavingTest extends AbstractTest
|
|||
if (dataFrame.isEndStream())
|
||||
++finished;
|
||||
|
||||
BufferUtil.writeTo(dataFrame.getData(), contents.get(streamId));
|
||||
BufferUtil.writeTo(dataFrame.getByteBuffer(), contents.get(streamId));
|
||||
|
||||
data.release();
|
||||
}
|
||||
|
|
|
@ -50,9 +50,9 @@ import org.eclipse.jetty.http2.internal.ErrorCode;
|
|||
import org.eclipse.jetty.http2.internal.generator.Generator;
|
||||
import org.eclipse.jetty.http2.internal.parser.Parser;
|
||||
import org.eclipse.jetty.http2.server.HTTP2CServerConnectionFactory;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.ArrayRetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||
|
@ -148,26 +148,26 @@ public class PrefaceTest extends AbstractTest
|
|||
}
|
||||
});
|
||||
|
||||
ByteBufferPool byteBufferPool = http2Client.getByteBufferPool();
|
||||
RetainableByteBufferPool bufferPool = http2Client.getRetainableByteBufferPool();
|
||||
try (SocketChannel socket = SocketChannel.open())
|
||||
{
|
||||
socket.connect(new InetSocketAddress("localhost", connector.getLocalPort()));
|
||||
|
||||
Generator generator = new Generator(byteBufferPool);
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.control(lease, new PrefaceFrame());
|
||||
Generator generator = new Generator(bufferPool);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.control(accumulator, new PrefaceFrame());
|
||||
Map<Integer, Integer> clientSettings = new HashMap<>();
|
||||
clientSettings.put(SettingsFrame.ENABLE_PUSH, 0);
|
||||
generator.control(lease, new SettingsFrame(clientSettings, false));
|
||||
generator.control(accumulator, new SettingsFrame(clientSettings, false));
|
||||
// The PING frame just to make sure the client stops reading.
|
||||
generator.control(lease, new PingFrame(true));
|
||||
generator.control(accumulator, new PingFrame(true));
|
||||
|
||||
List<ByteBuffer> buffers = lease.getByteBuffers();
|
||||
List<ByteBuffer> buffers = accumulator.getByteBuffers();
|
||||
socket.write(buffers.toArray(new ByteBuffer[0]));
|
||||
|
||||
Queue<SettingsFrame> settings = new ArrayDeque<>();
|
||||
AtomicBoolean closed = new AtomicBoolean();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onSettings(SettingsFrame frame)
|
||||
|
@ -183,7 +183,7 @@ public class PrefaceTest extends AbstractTest
|
|||
}, 4096, 8192);
|
||||
parser.init(UnaryOperator.identity());
|
||||
|
||||
ByteBuffer buffer = byteBufferPool.acquire(1024, true);
|
||||
ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
|
||||
while (true)
|
||||
{
|
||||
BufferUtil.clearToFill(buffer);
|
||||
|
@ -247,7 +247,7 @@ public class PrefaceTest extends AbstractTest
|
|||
});
|
||||
server.start();
|
||||
|
||||
ByteBufferPool byteBufferPool = new MappedByteBufferPool();
|
||||
RetainableByteBufferPool bufferPool = new ArrayRetainableByteBufferPool();
|
||||
try (SocketChannel socket = SocketChannel.open())
|
||||
{
|
||||
socket.connect(new InetSocketAddress("localhost", connector.getLocalPort()));
|
||||
|
@ -268,7 +268,7 @@ public class PrefaceTest extends AbstractTest
|
|||
assertTrue(serverSettingsLatch.get().await(5, TimeUnit.SECONDS));
|
||||
|
||||
// The 101 response is the reply to the client preface SETTINGS frame.
|
||||
ByteBuffer buffer = byteBufferPool.acquire(1024, true);
|
||||
ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
|
||||
http1:
|
||||
while (true)
|
||||
{
|
||||
|
@ -295,13 +295,13 @@ public class PrefaceTest extends AbstractTest
|
|||
serverSettingsLatch.set(new CountDownLatch(1));
|
||||
|
||||
// After the 101, the client must send the connection preface.
|
||||
Generator generator = new Generator(byteBufferPool);
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.control(lease, new PrefaceFrame());
|
||||
Generator generator = new Generator(bufferPool);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.control(accumulator, new PrefaceFrame());
|
||||
Map<Integer, Integer> clientSettings = new HashMap<>();
|
||||
clientSettings.put(SettingsFrame.ENABLE_PUSH, 1);
|
||||
generator.control(lease, new SettingsFrame(clientSettings, false));
|
||||
List<ByteBuffer> buffers = lease.getByteBuffers();
|
||||
generator.control(accumulator, new SettingsFrame(clientSettings, false));
|
||||
List<ByteBuffer> buffers = accumulator.getByteBuffers();
|
||||
socket.write(buffers.toArray(new ByteBuffer[0]));
|
||||
|
||||
// However, we should not call onPreface() again.
|
||||
|
@ -311,7 +311,7 @@ public class PrefaceTest extends AbstractTest
|
|||
|
||||
CountDownLatch clientSettingsLatch = new CountDownLatch(1);
|
||||
AtomicBoolean responded = new AtomicBoolean();
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
Parser parser = new Parser(bufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onSettings(SettingsFrame frame)
|
||||
|
|
|
@ -223,7 +223,7 @@ public class RawHTTP2ProxyTest
|
|||
DataFrame frame = data.frame();
|
||||
if (LOGGER.isDebugEnabled())
|
||||
LOGGER.debug("CLIENT received {}", frame);
|
||||
assertEquals(buffer1.slice(), frame.getData());
|
||||
assertEquals(buffer1.slice(), frame.getByteBuffer());
|
||||
data.release();
|
||||
latch1.countDown();
|
||||
if (!data.frame().isEndStream())
|
||||
|
@ -461,7 +461,7 @@ public class RawHTTP2ProxyTest
|
|||
case DATA ->
|
||||
{
|
||||
DataFrame clientToProxyFrame = (DataFrame)frameInfo.frame;
|
||||
DataFrame proxyToServerFrame = new DataFrame(proxyToServerStream.getId(), clientToProxyFrame.getData(), clientToProxyFrame.isEndStream());
|
||||
DataFrame proxyToServerFrame = new DataFrame(proxyToServerStream.getId(), clientToProxyFrame.getByteBuffer(), clientToProxyFrame.isEndStream());
|
||||
proxyToServerStream.data(proxyToServerFrame, this);
|
||||
yield Action.SCHEDULED;
|
||||
}
|
||||
|
@ -609,7 +609,7 @@ public class RawHTTP2ProxyTest
|
|||
case DATA ->
|
||||
{
|
||||
DataFrame clientToProxyFrame = (DataFrame)frameInfo.frame;
|
||||
DataFrame proxyToServerFrame = new DataFrame(serverToProxyStream.getId(), clientToProxyFrame.getData(), clientToProxyFrame.isEndStream());
|
||||
DataFrame proxyToServerFrame = new DataFrame(serverToProxyStream.getId(), clientToProxyFrame.getByteBuffer(), clientToProxyFrame.isEndStream());
|
||||
proxyToClientStream.data(proxyToServerFrame, this);
|
||||
yield Action.SCHEDULED;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ import org.eclipse.jetty.http2.frames.ResetFrame;
|
|||
import org.eclipse.jetty.http2.frames.SettingsFrame;
|
||||
import org.eclipse.jetty.http2.internal.HTTP2Session;
|
||||
import org.eclipse.jetty.http2.internal.generator.Generator;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.FuturePromise;
|
||||
|
@ -201,10 +201,10 @@ public class StreamCountTest extends AbstractTest
|
|||
HeadersFrame frame3 = new HeadersFrame(streamId3, metaData, null, false);
|
||||
DataFrame data3 = new DataFrame(streamId3, BufferUtil.EMPTY_BUFFER, true);
|
||||
Generator generator = ((HTTP2Session)session).getGenerator();
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(generator.getByteBufferPool());
|
||||
generator.control(lease, frame3);
|
||||
generator.data(lease, data3, data3.remaining());
|
||||
((HTTP2Session)session).getEndPoint().write(Callback.NOOP, lease.getByteBuffers().toArray(new ByteBuffer[0]));
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.control(accumulator, frame3);
|
||||
generator.data(accumulator, data3, data3.remaining());
|
||||
((HTTP2Session)session).getEndPoint().write(Callback.NOOP, accumulator.getByteBuffers().toArray(ByteBuffer[]::new));
|
||||
// Expect 2 RST_STREAM frames.
|
||||
assertTrue(sessionResetLatch.await(5, TimeUnit.SECONDS));
|
||||
|
||||
|
|
|
@ -64,8 +64,8 @@ import org.eclipse.jetty.http2.internal.generator.Generator;
|
|||
import org.eclipse.jetty.http2.server.AbstractHTTP2ServerConnectionFactory;
|
||||
import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
|
||||
import org.eclipse.jetty.io.AbstractEndPoint;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.Content;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.io.WriteFlusher;
|
||||
import org.eclipse.jetty.logging.StacklessLogging;
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
|
@ -671,7 +671,7 @@ public class StreamResetTest extends AbstractTest
|
|||
Stream.Data data = stream.readData();
|
||||
dataQueue.offer(data);
|
||||
// Do not consume the data yet.
|
||||
if (received.addAndGet(data.frame().getData().remaining()) == windowSize)
|
||||
if (received.addAndGet(data.frame().getByteBuffer().remaining()) == windowSize)
|
||||
latch.countDown();
|
||||
else
|
||||
stream.demand();
|
||||
|
@ -724,7 +724,7 @@ public class StreamResetTest extends AbstractTest
|
|||
Stream.Data data = stream.readData();
|
||||
dataList.add(data);
|
||||
// Do not release to stall the flow control window.
|
||||
if (received.addAndGet(data.frame().getData().remaining()) == windowSize)
|
||||
if (received.addAndGet(data.frame().getByteBuffer().remaining()) == windowSize)
|
||||
latch.countDown();
|
||||
else
|
||||
stream.demand();
|
||||
|
@ -784,7 +784,7 @@ public class StreamResetTest extends AbstractTest
|
|||
Stream.Data data = stream.readData();
|
||||
dataQueue.offer(data);
|
||||
// Do not consume the data yet.
|
||||
if (received.addAndGet(data.frame().getData().remaining()) == windowSize)
|
||||
if (received.addAndGet(data.frame().getByteBuffer().remaining()) == windowSize)
|
||||
latch.countDown();
|
||||
else
|
||||
stream.demand();
|
||||
|
@ -887,30 +887,30 @@ public class StreamResetTest extends AbstractTest
|
|||
}
|
||||
});
|
||||
|
||||
ByteBufferPool byteBufferPool = http2Client.getByteBufferPool();
|
||||
RetainableByteBufferPool bufferPool = http2Client.getRetainableByteBufferPool();
|
||||
try (SocketChannel socket = SocketChannel.open())
|
||||
{
|
||||
String host = "localhost";
|
||||
int port = connector.getLocalPort();
|
||||
socket.connect(new InetSocketAddress(host, port));
|
||||
|
||||
Generator generator = new Generator(byteBufferPool);
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.control(lease, new PrefaceFrame());
|
||||
Generator generator = new Generator(bufferPool);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.control(accumulator, new PrefaceFrame());
|
||||
Map<Integer, Integer> clientSettings = new HashMap<>();
|
||||
// Max stream HTTP/2 flow control window.
|
||||
clientSettings.put(SettingsFrame.INITIAL_WINDOW_SIZE, Integer.MAX_VALUE);
|
||||
generator.control(lease, new SettingsFrame(clientSettings, false));
|
||||
generator.control(accumulator, new SettingsFrame(clientSettings, false));
|
||||
// Max session HTTP/2 flow control window.
|
||||
generator.control(lease, new WindowUpdateFrame(0, Integer.MAX_VALUE - FlowControlStrategy.DEFAULT_WINDOW_SIZE));
|
||||
generator.control(accumulator, new WindowUpdateFrame(0, Integer.MAX_VALUE - FlowControlStrategy.DEFAULT_WINDOW_SIZE));
|
||||
|
||||
HttpURI uri = HttpURI.from("http", host, port, "/");
|
||||
MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.EMPTY);
|
||||
int streamId = 3;
|
||||
HeadersFrame headersFrame = new HeadersFrame(streamId, request, null, true);
|
||||
generator.control(lease, headersFrame);
|
||||
generator.control(accumulator, headersFrame);
|
||||
|
||||
List<ByteBuffer> buffers = lease.getByteBuffers();
|
||||
List<ByteBuffer> buffers = accumulator.getByteBuffers();
|
||||
socket.write(buffers.toArray(new ByteBuffer[0]));
|
||||
|
||||
// Wait until the server is TCP congested.
|
||||
|
@ -918,9 +918,9 @@ public class StreamResetTest extends AbstractTest
|
|||
WriteFlusher flusher = flusherRef.get();
|
||||
waitUntilTCPCongested(flusher);
|
||||
|
||||
lease.recycle();
|
||||
generator.control(lease, new ResetFrame(streamId, ErrorCode.CANCEL_STREAM_ERROR.code));
|
||||
buffers = lease.getByteBuffers();
|
||||
accumulator.release();
|
||||
generator.control(accumulator, new ResetFrame(streamId, ErrorCode.CANCEL_STREAM_ERROR.code));
|
||||
buffers = accumulator.getByteBuffers();
|
||||
socket.write(buffers.toArray(new ByteBuffer[0]));
|
||||
|
||||
assertTrue(writeLatch1.await(5, TimeUnit.SECONDS));
|
||||
|
@ -978,29 +978,29 @@ public class StreamResetTest extends AbstractTest
|
|||
}
|
||||
});
|
||||
|
||||
ByteBufferPool byteBufferPool = http2Client.getByteBufferPool();
|
||||
RetainableByteBufferPool bufferPool = http2Client.getRetainableByteBufferPool();
|
||||
try (SocketChannel socket = SocketChannel.open())
|
||||
{
|
||||
String host = "localhost";
|
||||
int port = connector.getLocalPort();
|
||||
socket.connect(new InetSocketAddress(host, port));
|
||||
|
||||
Generator generator = new Generator(byteBufferPool);
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.control(lease, new PrefaceFrame());
|
||||
Generator generator = new Generator(bufferPool);
|
||||
RetainableByteBufferPool.Accumulator accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
generator.control(accumulator, new PrefaceFrame());
|
||||
Map<Integer, Integer> clientSettings = new HashMap<>();
|
||||
// Max stream HTTP/2 flow control window.
|
||||
clientSettings.put(SettingsFrame.INITIAL_WINDOW_SIZE, Integer.MAX_VALUE);
|
||||
generator.control(lease, new SettingsFrame(clientSettings, false));
|
||||
generator.control(accumulator, new SettingsFrame(clientSettings, false));
|
||||
// Max session HTTP/2 flow control window.
|
||||
generator.control(lease, new WindowUpdateFrame(0, Integer.MAX_VALUE - FlowControlStrategy.DEFAULT_WINDOW_SIZE));
|
||||
generator.control(accumulator, new WindowUpdateFrame(0, Integer.MAX_VALUE - FlowControlStrategy.DEFAULT_WINDOW_SIZE));
|
||||
|
||||
HttpURI uri = HttpURI.from("http", host, port, "/1");
|
||||
MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.EMPTY);
|
||||
HeadersFrame headersFrame = new HeadersFrame(3, request, null, true);
|
||||
generator.control(lease, headersFrame);
|
||||
generator.control(accumulator, headersFrame);
|
||||
|
||||
List<ByteBuffer> buffers = lease.getByteBuffers();
|
||||
List<ByteBuffer> buffers = accumulator.getByteBuffers();
|
||||
socket.write(buffers.toArray(new ByteBuffer[0]));
|
||||
|
||||
waitUntilTCPCongested(exchanger.exchange(null));
|
||||
|
@ -1010,15 +1010,15 @@ public class StreamResetTest extends AbstractTest
|
|||
request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.EMPTY);
|
||||
int streamId = 5;
|
||||
headersFrame = new HeadersFrame(streamId, request, null, true);
|
||||
generator.control(lease, headersFrame);
|
||||
buffers = lease.getByteBuffers();
|
||||
generator.control(accumulator, headersFrame);
|
||||
buffers = accumulator.getByteBuffers();
|
||||
socket.write(buffers.toArray(new ByteBuffer[0]));
|
||||
assertTrue(requestLatch1.await(5, TimeUnit.SECONDS));
|
||||
|
||||
// Now reset the second request, which has not started writing yet.
|
||||
lease.recycle();
|
||||
generator.control(lease, new ResetFrame(streamId, ErrorCode.CANCEL_STREAM_ERROR.code));
|
||||
buffers = lease.getByteBuffers();
|
||||
accumulator.release();
|
||||
generator.control(accumulator, new ResetFrame(streamId, ErrorCode.CANCEL_STREAM_ERROR.code));
|
||||
buffers = accumulator.getByteBuffers();
|
||||
socket.write(buffers.toArray(new ByteBuffer[0]));
|
||||
// Wait to be sure that the server processed the reset.
|
||||
Thread.sleep(1000);
|
||||
|
|
|
@ -69,7 +69,7 @@ public class HttpClientTransportOverHTTP3 extends AbstractHttpClientTransport im
|
|||
ClientConnector clientConnector = this.client.getClientConnector();
|
||||
clientConnector.setExecutor(httpClient.getExecutor());
|
||||
clientConnector.setScheduler(httpClient.getScheduler());
|
||||
clientConnector.setByteBufferPool(httpClient.getByteBufferPool());
|
||||
clientConnector.setRetainableByteBufferPool(httpClient.getRetainableByteBufferPool());
|
||||
clientConnector.setConnectTimeout(Duration.ofMillis(httpClient.getConnectTimeout()));
|
||||
clientConnector.setConnectBlocking(httpClient.isConnectBlocking());
|
||||
clientConnector.setBindAddress(httpClient.getBindAddress());
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.eclipse.jetty.http3.internal.MessageFlusher;
|
|||
import org.eclipse.jetty.http3.internal.UnidirectionalStreamConnection;
|
||||
import org.eclipse.jetty.http3.qpack.QpackDecoder;
|
||||
import org.eclipse.jetty.http3.qpack.QpackEncoder;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.quic.client.ClientProtocolSession;
|
||||
import org.eclipse.jetty.quic.client.ClientQuicSession;
|
||||
import org.eclipse.jetty.quic.common.QuicStreamEndPoint;
|
||||
|
@ -63,7 +64,8 @@ public class ClientHTTP3Session extends ClientProtocolSession
|
|||
long encoderStreamId = getQuicSession().newStreamId(StreamType.CLIENT_UNIDIRECTIONAL);
|
||||
QuicStreamEndPoint encoderEndPoint = openInstructionEndPoint(encoderStreamId);
|
||||
InstructionFlusher encoderInstructionFlusher = new InstructionFlusher(quicSession, encoderEndPoint, EncoderStreamConnection.STREAM_TYPE);
|
||||
this.encoder = new QpackEncoder(new InstructionHandler(encoderInstructionFlusher), configuration.getMaxBlockedStreams());
|
||||
RetainableByteBufferPool bufferPool = quicSession.getRetainableByteBufferPool();
|
||||
this.encoder = new QpackEncoder(bufferPool, new InstructionHandler(encoderInstructionFlusher), configuration.getMaxBlockedStreams());
|
||||
addBean(encoder);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("created encoder stream #{} on {}", encoderStreamId, encoderEndPoint);
|
||||
|
@ -71,7 +73,7 @@ public class ClientHTTP3Session extends ClientProtocolSession
|
|||
long decoderStreamId = getQuicSession().newStreamId(StreamType.CLIENT_UNIDIRECTIONAL);
|
||||
QuicStreamEndPoint decoderEndPoint = openInstructionEndPoint(decoderStreamId);
|
||||
InstructionFlusher decoderInstructionFlusher = new InstructionFlusher(quicSession, decoderEndPoint, DecoderStreamConnection.STREAM_TYPE);
|
||||
this.decoder = new QpackDecoder(new InstructionHandler(decoderInstructionFlusher), configuration.getMaxResponseHeadersSize());
|
||||
this.decoder = new QpackDecoder(bufferPool, new InstructionHandler(decoderInstructionFlusher), configuration.getMaxResponseHeadersSize());
|
||||
addBean(decoder);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("created decoder stream #{} on {}", decoderStreamId, decoderEndPoint);
|
||||
|
@ -83,7 +85,7 @@ public class ClientHTTP3Session extends ClientProtocolSession
|
|||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("created control stream #{} on {}", controlStreamId, controlEndPoint);
|
||||
|
||||
this.messageFlusher = new MessageFlusher(quicSession.getByteBufferPool(), encoder, configuration.getMaxRequestHeadersSize(), configuration.isUseOutputDirectByteBuffers());
|
||||
this.messageFlusher = new MessageFlusher(quicSession.getRetainableByteBufferPool(), encoder, configuration.getMaxRequestHeadersSize(), configuration.isUseOutputDirectByteBuffers());
|
||||
addBean(messageFlusher);
|
||||
}
|
||||
|
||||
|
@ -197,7 +199,7 @@ public class ClientHTTP3Session extends ClientProtocolSession
|
|||
|
||||
private void openUnidirectionalStreamEndPoint(QuicStreamEndPoint endPoint)
|
||||
{
|
||||
UnidirectionalStreamConnection connection = new UnidirectionalStreamConnection(endPoint, getQuicSession().getExecutor(), getQuicSession().getByteBufferPool(), encoder, decoder, session);
|
||||
UnidirectionalStreamConnection connection = new UnidirectionalStreamConnection(endPoint, getQuicSession().getExecutor(), getQuicSession().getRetainableByteBufferPool(), encoder, decoder, session);
|
||||
endPoint.setConnection(connection);
|
||||
endPoint.opened();
|
||||
}
|
||||
|
|
|
@ -21,6 +21,6 @@ public class ClientHTTP3StreamConnection extends HTTP3StreamConnection
|
|||
{
|
||||
public ClientHTTP3StreamConnection(QuicStreamEndPoint endPoint, ClientHTTP3Session session, MessageParser parser)
|
||||
{
|
||||
super(endPoint, session.getQuicSession().getExecutor(), session.getQuicSession().getByteBufferPool(), parser);
|
||||
super(endPoint, session.getQuicSession().getExecutor(), session.getQuicSession().getRetainableByteBufferPool(), parser);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,8 @@ import java.util.Queue;
|
|||
|
||||
import org.eclipse.jetty.http3.frames.Frame;
|
||||
import org.eclipse.jetty.http3.internal.generator.ControlGenerator;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.quic.common.QuicSession;
|
||||
import org.eclipse.jetty.quic.common.QuicStreamEndPoint;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
|
@ -37,9 +38,9 @@ public class ControlFlusher extends IteratingCallback
|
|||
|
||||
private final AutoLock lock = new AutoLock();
|
||||
private final Queue<Entry> queue = new ArrayDeque<>();
|
||||
private final ByteBufferPool.Lease lease;
|
||||
private final ControlGenerator generator;
|
||||
private final QuicStreamEndPoint endPoint;
|
||||
private final ControlGenerator generator;
|
||||
private final RetainableByteBufferPool.Accumulator accumulator;
|
||||
private boolean initialized;
|
||||
private Throwable terminated;
|
||||
private List<Entry> entries;
|
||||
|
@ -47,15 +48,16 @@ public class ControlFlusher extends IteratingCallback
|
|||
|
||||
public ControlFlusher(QuicSession session, QuicStreamEndPoint endPoint, boolean useDirectByteBuffers)
|
||||
{
|
||||
this.lease = new ByteBufferPool.Lease(session.getByteBufferPool());
|
||||
this.endPoint = endPoint;
|
||||
this.generator = new ControlGenerator(useDirectByteBuffers);
|
||||
RetainableByteBufferPool bufferPool = session.getRetainableByteBufferPool();
|
||||
this.generator = new ControlGenerator(bufferPool, useDirectByteBuffers);
|
||||
this.accumulator = new RetainableByteBufferPool.Accumulator();
|
||||
}
|
||||
|
||||
public boolean offer(Frame frame, Callback callback)
|
||||
{
|
||||
Throwable closed;
|
||||
try (AutoLock l = lock.lock())
|
||||
try (AutoLock ignored = lock.lock())
|
||||
{
|
||||
closed = terminated;
|
||||
if (closed == null)
|
||||
|
@ -70,7 +72,7 @@ public class ControlFlusher extends IteratingCallback
|
|||
@Override
|
||||
protected Action process()
|
||||
{
|
||||
try (AutoLock l = lock.lock())
|
||||
try (AutoLock ignored = lock.lock())
|
||||
{
|
||||
if (queue.isEmpty())
|
||||
return Action.IDLE;
|
||||
|
@ -83,7 +85,7 @@ public class ControlFlusher extends IteratingCallback
|
|||
|
||||
for (Entry entry : entries)
|
||||
{
|
||||
generator.generate(lease, endPoint.getStreamId(), entry.frame, null);
|
||||
generator.generate(accumulator, endPoint.getStreamId(), entry.frame, null);
|
||||
invocationType = Invocable.combine(invocationType, entry.callback.getInvocationType());
|
||||
}
|
||||
|
||||
|
@ -93,12 +95,12 @@ public class ControlFlusher extends IteratingCallback
|
|||
ByteBuffer buffer = ByteBuffer.allocate(VarLenInt.length(ControlStreamConnection.STREAM_TYPE));
|
||||
VarLenInt.encode(buffer, ControlStreamConnection.STREAM_TYPE);
|
||||
buffer.flip();
|
||||
lease.insert(0, buffer, false);
|
||||
accumulator.insert(0, RetainableByteBuffer.wrap(buffer));
|
||||
}
|
||||
|
||||
List<ByteBuffer> buffers = lease.getByteBuffers();
|
||||
List<ByteBuffer> buffers = accumulator.getByteBuffers();
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("writing {} buffers ({} bytes) on {}", buffers.size(), lease.getTotalLength(), this);
|
||||
LOG.debug("writing {} buffers ({} bytes) on {}", buffers.size(), accumulator.getTotalLength(), this);
|
||||
endPoint.write(this, buffers.toArray(ByteBuffer[]::new));
|
||||
return Action.SCHEDULED;
|
||||
}
|
||||
|
@ -109,7 +111,7 @@ public class ControlFlusher extends IteratingCallback
|
|||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("succeeded to write {} on {}", entries, this);
|
||||
|
||||
lease.recycle();
|
||||
accumulator.release();
|
||||
|
||||
entries.forEach(e -> e.callback.succeeded());
|
||||
entries.clear();
|
||||
|
@ -125,11 +127,11 @@ public class ControlFlusher extends IteratingCallback
|
|||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("failed to write {} on {}", entries, this, failure);
|
||||
|
||||
lease.recycle();
|
||||
accumulator.release();
|
||||
|
||||
List<Entry> allEntries = new ArrayList<>(entries);
|
||||
entries.clear();
|
||||
try (AutoLock l = lock.lock())
|
||||
try (AutoLock ignored = lock.lock())
|
||||
{
|
||||
terminated = failure;
|
||||
allEntries.addAll(queue);
|
||||
|
@ -157,21 +159,7 @@ public class ControlFlusher extends IteratingCallback
|
|||
return String.format("%s#%s", super.toString(), endPoint.getStreamId());
|
||||
}
|
||||
|
||||
private static class Entry
|
||||
private record Entry(Frame frame, Callback callback)
|
||||
{
|
||||
private final Frame frame;
|
||||
private final Callback callback;
|
||||
|
||||
private Entry(Frame frame, Callback callback)
|
||||
{
|
||||
this.frame = frame;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return frame.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,9 +18,10 @@ import java.util.concurrent.Executor;
|
|||
|
||||
import org.eclipse.jetty.http3.internal.parser.ControlParser;
|
||||
import org.eclipse.jetty.io.AbstractConnection;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -31,15 +32,15 @@ public class ControlStreamConnection extends AbstractConnection implements Conne
|
|||
public static final long STREAM_TYPE = 0x00;
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ControlStreamConnection.class);
|
||||
|
||||
private final ByteBufferPool byteBufferPool;
|
||||
private final RetainableByteBufferPool bufferPool;
|
||||
private final ControlParser parser;
|
||||
private boolean useInputDirectByteBuffers = true;
|
||||
private ByteBuffer buffer;
|
||||
private RetainableByteBuffer buffer;
|
||||
|
||||
public ControlStreamConnection(EndPoint endPoint, Executor executor, ByteBufferPool byteBufferPool, ControlParser parser)
|
||||
public ControlStreamConnection(EndPoint endPoint, Executor executor, RetainableByteBufferPool bufferPool, ControlParser parser)
|
||||
{
|
||||
super(endPoint, executor);
|
||||
this.byteBufferPool = byteBufferPool;
|
||||
this.bufferPool = bufferPool;
|
||||
this.parser = parser;
|
||||
}
|
||||
|
||||
|
@ -57,17 +58,18 @@ public class ControlStreamConnection extends AbstractConnection implements Conne
|
|||
public void onUpgradeTo(ByteBuffer upgrade)
|
||||
{
|
||||
int capacity = Math.max(upgrade.remaining(), getInputBufferSize());
|
||||
buffer = byteBufferPool.acquire(capacity, isUseInputDirectByteBuffers());
|
||||
int position = BufferUtil.flipToFill(buffer);
|
||||
buffer.put(upgrade);
|
||||
BufferUtil.flipToFlush(buffer, position);
|
||||
buffer = bufferPool.acquire(capacity, isUseInputDirectByteBuffers());
|
||||
ByteBuffer byteBuffer = buffer.getByteBuffer();
|
||||
int position = BufferUtil.flipToFill(byteBuffer);
|
||||
byteBuffer.put(upgrade);
|
||||
BufferUtil.flipToFlush(byteBuffer, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen()
|
||||
{
|
||||
super.onOpen();
|
||||
if (BufferUtil.hasContent(buffer))
|
||||
if (buffer != null && buffer.hasRemaining())
|
||||
onFillable();
|
||||
else
|
||||
fillInterested();
|
||||
|
@ -79,28 +81,28 @@ public class ControlStreamConnection extends AbstractConnection implements Conne
|
|||
try
|
||||
{
|
||||
if (buffer == null)
|
||||
buffer = byteBufferPool.acquire(getInputBufferSize(), isUseInputDirectByteBuffers());
|
||||
|
||||
buffer = bufferPool.acquire(getInputBufferSize(), isUseInputDirectByteBuffers());
|
||||
ByteBuffer byteBuffer = buffer.getByteBuffer();
|
||||
while (true)
|
||||
{
|
||||
// Parse first in case of bytes from the upgrade.
|
||||
parser.parse(buffer);
|
||||
parser.parse(byteBuffer);
|
||||
|
||||
// Then read from the EndPoint.
|
||||
int filled = getEndPoint().fill(buffer);
|
||||
int filled = getEndPoint().fill(byteBuffer);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("filled {} on {}", filled, this);
|
||||
|
||||
if (filled == 0)
|
||||
{
|
||||
byteBufferPool.release(buffer);
|
||||
buffer.release();
|
||||
buffer = null;
|
||||
fillInterested();
|
||||
break;
|
||||
}
|
||||
else if (filled < 0)
|
||||
{
|
||||
byteBufferPool.release(buffer);
|
||||
buffer.release();
|
||||
buffer = null;
|
||||
getEndPoint().close();
|
||||
break;
|
||||
|
@ -111,7 +113,7 @@ public class ControlStreamConnection extends AbstractConnection implements Conne
|
|||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("could not process control stream {}", getEndPoint(), x);
|
||||
byteBufferPool.release(buffer);
|
||||
buffer.release();
|
||||
buffer = null;
|
||||
getEndPoint().close(x);
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@ import java.util.concurrent.Executor;
|
|||
|
||||
import org.eclipse.jetty.http3.qpack.QpackEncoder;
|
||||
import org.eclipse.jetty.http3.qpack.QpackException;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.RetainableByteBufferPool;
|
||||
|
||||
public class DecoderStreamConnection extends InstructionStreamConnection
|
||||
{
|
||||
|
@ -28,9 +28,9 @@ public class DecoderStreamConnection extends InstructionStreamConnection
|
|||
|
||||
private final QpackEncoder encoder;
|
||||
|
||||
public DecoderStreamConnection(EndPoint endPoint, Executor executor, ByteBufferPool byteBufferPool, QpackEncoder encoder)
|
||||
public DecoderStreamConnection(EndPoint endPoint, Executor executor, RetainableByteBufferPool bufferPool, QpackEncoder encoder)
|
||||
{
|
||||
super(endPoint, executor, byteBufferPool);
|
||||
super(endPoint, executor, bufferPool);
|
||||
this.encoder = encoder;
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue