Use long for http2 ping payload.
Motivation: At the moment we use a ByteBuf as the payload for a http2 frame. This complicates life-time management a lot with no real gain and also may produce more objects then needed. We should just use a long as it is required to be 8 bytes anyway. Modifications: Use long for ping payloads. Result: Fixes [#7629].
This commit is contained in:
parent
40ae4fefc7
commit
501662a77f
@ -76,7 +76,7 @@ public class DecoratingHttp2FrameWriter implements Http2FrameWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelFuture writePing(ChannelHandlerContext ctx, boolean ack, ByteBuf data, ChannelPromise promise) {
|
public ChannelFuture writePing(ChannelHandlerContext ctx, boolean ack, long data, ChannelPromise promise) {
|
||||||
return delegate.writePing(ctx, ack, data, promise);
|
return delegate.writePing(ctx, ack, data, promise);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,16 +424,16 @@ public class DefaultHttp2ConnectionDecoder implements Http2ConnectionDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPingRead(ChannelHandlerContext ctx, ByteBuf data) throws Http2Exception {
|
public void onPingRead(ChannelHandlerContext ctx, long data) throws Http2Exception {
|
||||||
// Send an ack back to the remote client.
|
// Send an ack back to the remote client.
|
||||||
// Need to retain the buffer here since it will be released after the write completes.
|
// Need to retain the buffer here since it will be released after the write completes.
|
||||||
encoder.writePing(ctx, true, data.retainedSlice(), ctx.newPromise());
|
encoder.writePing(ctx, true, data, ctx.newPromise());
|
||||||
|
|
||||||
listener.onPingRead(ctx, data);
|
listener.onPingRead(ctx, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPingAckRead(ChannelHandlerContext ctx, ByteBuf data) throws Http2Exception {
|
public void onPingAckRead(ChannelHandlerContext ctx, long data) throws Http2Exception {
|
||||||
listener.onPingAckRead(ctx, data);
|
listener.onPingAckRead(ctx, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -636,13 +636,13 @@ public class DefaultHttp2ConnectionDecoder implements Http2ConnectionDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPingRead(ChannelHandlerContext ctx, ByteBuf data) throws Http2Exception {
|
public void onPingRead(ChannelHandlerContext ctx, long data) throws Http2Exception {
|
||||||
verifyPrefaceReceived();
|
verifyPrefaceReceived();
|
||||||
internalFrameListener.onPingRead(ctx, data);
|
internalFrameListener.onPingRead(ctx, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPingAckRead(ChannelHandlerContext ctx, ByteBuf data) throws Http2Exception {
|
public void onPingAckRead(ChannelHandlerContext ctx, long data) throws Http2Exception {
|
||||||
verifyPrefaceReceived();
|
verifyPrefaceReceived();
|
||||||
internalFrameListener.onPingAckRead(ctx, data);
|
internalFrameListener.onPingAckRead(ctx, data);
|
||||||
}
|
}
|
||||||
|
@ -272,7 +272,7 @@ public class DefaultHttp2ConnectionEncoder implements Http2ConnectionEncoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelFuture writePing(ChannelHandlerContext ctx, boolean ack, ByteBuf data, ChannelPromise promise) {
|
public ChannelFuture writePing(ChannelHandlerContext ctx, boolean ack, long data, ChannelPromise promise) {
|
||||||
return frameWriter.writePing(ctx, ack, data, promise);
|
return frameWriter.writePing(ctx, ack, data, promise);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,7 +266,7 @@ public class DefaultHttp2FrameReader implements Http2FrameReader, Http2FrameSize
|
|||||||
readPushPromiseFrame(ctx, payload, listener);
|
readPushPromiseFrame(ctx, payload, listener);
|
||||||
break;
|
break;
|
||||||
case PING:
|
case PING:
|
||||||
readPingFrame(ctx, payload, listener);
|
readPingFrame(ctx, payload.readLong(), listener);
|
||||||
break;
|
break;
|
||||||
case GO_AWAY:
|
case GO_AWAY:
|
||||||
readGoAwayFrame(ctx, payload, listener);
|
readGoAwayFrame(ctx, payload, listener);
|
||||||
@ -574,9 +574,8 @@ public class DefaultHttp2FrameReader implements Http2FrameReader, Http2FrameSize
|
|||||||
resetHeadersContinuationIfEnd(flags.endOfHeaders());
|
resetHeadersContinuationIfEnd(flags.endOfHeaders());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readPingFrame(ChannelHandlerContext ctx, ByteBuf payload,
|
private void readPingFrame(ChannelHandlerContext ctx, long data,
|
||||||
Http2FrameListener listener) throws Http2Exception {
|
Http2FrameListener listener) throws Http2Exception {
|
||||||
ByteBuf data = payload.readSlice(payload.readableBytes());
|
|
||||||
if (flags.ack()) {
|
if (flags.ack()) {
|
||||||
listener.onPingAckRead(ctx, data);
|
listener.onPingAckRead(ctx, data);
|
||||||
} else {
|
} else {
|
||||||
|
@ -332,36 +332,14 @@ public class DefaultHttp2FrameWriter implements Http2FrameWriter, Http2FrameSize
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelFuture writePing(ChannelHandlerContext ctx, boolean ack, ByteBuf data, ChannelPromise promise) {
|
public ChannelFuture writePing(ChannelHandlerContext ctx, boolean ack, long data, ChannelPromise promise) {
|
||||||
final SimpleChannelPromiseAggregator promiseAggregator =
|
Http2Flags flags = ack ? new Http2Flags().ack(true) : new Http2Flags();
|
||||||
new SimpleChannelPromiseAggregator(promise, ctx.channel(), ctx.executor());
|
ByteBuf buf = ctx.alloc().buffer(FRAME_HEADER_LENGTH + PING_FRAME_PAYLOAD_LENGTH);
|
||||||
try {
|
// Assume nothing below will throw until buf is written. That way we don't have to take care of ownership
|
||||||
verifyPingPayload(data);
|
// in the catch block.
|
||||||
Http2Flags flags = ack ? new Http2Flags().ack(true) : new Http2Flags();
|
writeFrameHeaderInternal(buf, PING_FRAME_PAYLOAD_LENGTH, PING, flags, 0);
|
||||||
int payloadLength = data.readableBytes();
|
buf.writeLong(data);
|
||||||
ByteBuf buf = ctx.alloc().buffer(FRAME_HEADER_LENGTH);
|
return ctx.write(buf, promise);
|
||||||
// Assume nothing below will throw until buf is written. That way we don't have to take care of ownership
|
|
||||||
// in the catch block.
|
|
||||||
writeFrameHeaderInternal(buf, payloadLength, PING, flags, 0);
|
|
||||||
ctx.write(buf, promiseAggregator.newPromise());
|
|
||||||
} catch (Throwable t) {
|
|
||||||
try {
|
|
||||||
data.release();
|
|
||||||
} finally {
|
|
||||||
promiseAggregator.setFailure(t);
|
|
||||||
promiseAggregator.doneAllocatingPromises();
|
|
||||||
}
|
|
||||||
return promiseAggregator;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Write the debug data.
|
|
||||||
ctx.write(data, promiseAggregator.newPromise());
|
|
||||||
} catch (Throwable t) {
|
|
||||||
promiseAggregator.setFailure(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
return promiseAggregator.doneAllocatingPromises();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
package io.netty.handler.codec.http2;
|
package io.netty.handler.codec.http2;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
|
||||||
import io.netty.buffer.DefaultByteBufHolder;
|
|
||||||
import io.netty.util.internal.StringUtil;
|
import io.netty.util.internal.StringUtil;
|
||||||
import io.netty.util.internal.UnstableApi;
|
import io.netty.util.internal.UnstableApi;
|
||||||
|
|
||||||
@ -25,19 +23,20 @@ import io.netty.util.internal.UnstableApi;
|
|||||||
* The default {@link Http2PingFrame} implementation.
|
* The default {@link Http2PingFrame} implementation.
|
||||||
*/
|
*/
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
public class DefaultHttp2PingFrame extends DefaultByteBufHolder implements Http2PingFrame {
|
public class DefaultHttp2PingFrame implements Http2PingFrame {
|
||||||
|
|
||||||
|
private final long content;
|
||||||
private final boolean ack;
|
private final boolean ack;
|
||||||
|
|
||||||
public DefaultHttp2PingFrame(ByteBuf content) {
|
public DefaultHttp2PingFrame(long content) {
|
||||||
this(content, false);
|
this(content, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A user cannot send a ping ack, as this is done automatically when a ping is received.
|
* A user cannot send a ping ack, as this is done automatically when a ping is received.
|
||||||
*/
|
*/
|
||||||
DefaultHttp2PingFrame(ByteBuf content, boolean ack) {
|
DefaultHttp2PingFrame(long content, boolean ack) {
|
||||||
super(mustBeEightBytes(content));
|
this.content = content;
|
||||||
this.ack = ack;
|
this.ack = ack;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,47 +51,8 @@ public class DefaultHttp2PingFrame extends DefaultByteBufHolder implements Http2
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DefaultHttp2PingFrame copy() {
|
public long content() {
|
||||||
return replace(content().copy());
|
return content;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DefaultHttp2PingFrame duplicate() {
|
|
||||||
return replace(content().duplicate());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DefaultHttp2PingFrame retainedDuplicate() {
|
|
||||||
return replace(content().retainedDuplicate());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DefaultHttp2PingFrame replace(ByteBuf content) {
|
|
||||||
return new DefaultHttp2PingFrame(content, ack);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DefaultHttp2PingFrame retain() {
|
|
||||||
super.retain();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DefaultHttp2PingFrame retain(int increment) {
|
|
||||||
super.retain(increment);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DefaultHttp2PingFrame touch() {
|
|
||||||
super.touch();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DefaultHttp2PingFrame touch(Object hint) {
|
|
||||||
super.touch(hint);
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -101,7 +61,7 @@ public class DefaultHttp2PingFrame extends DefaultByteBufHolder implements Http2
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Http2PingFrame other = (Http2PingFrame) o;
|
Http2PingFrame other = (Http2PingFrame) o;
|
||||||
return super.equals(o) && ack == other.ack();
|
return ack == other.ack() && content == other.content();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -111,16 +71,8 @@ public class DefaultHttp2PingFrame extends DefaultByteBufHolder implements Http2
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ByteBuf mustBeEightBytes(ByteBuf content) {
|
|
||||||
if (content.readableBytes() != 8) {
|
|
||||||
throw new IllegalArgumentException("PING frames require 8 bytes of content. Was " +
|
|
||||||
content.readableBytes() + " bytes.");
|
|
||||||
}
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return StringUtil.simpleClassName(this) + "(content=" + contentToString() + ", ack=" + ack + ')';
|
return StringUtil.simpleClassName(this) + "(content=" + content + ", ack=" + ack + ')';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,11 +58,11 @@ public class Http2EventAdapter implements Http2Connection.Listener, Http2FrameLi
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPingRead(ChannelHandlerContext ctx, ByteBuf data) throws Http2Exception {
|
public void onPingRead(ChannelHandlerContext ctx, long data) throws Http2Exception {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPingAckRead(ChannelHandlerContext ctx, ByteBuf data) throws Http2Exception {
|
public void onPingAckRead(ChannelHandlerContext ctx, long data) throws Http2Exception {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -61,11 +61,11 @@ public class Http2FrameAdapter implements Http2FrameListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPingRead(ChannelHandlerContext ctx, ByteBuf data) throws Http2Exception {
|
public void onPingRead(ChannelHandlerContext ctx, long data) throws Http2Exception {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPingAckRead(ChannelHandlerContext ctx, ByteBuf data) throws Http2Exception {
|
public void onPingAckRead(ChannelHandlerContext ctx, long data) throws Http2Exception {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -499,13 +499,13 @@ public class Http2FrameCodec extends Http2ConnectionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPingRead(ChannelHandlerContext ctx, ByteBuf data) {
|
public void onPingRead(ChannelHandlerContext ctx, long data) {
|
||||||
onHttp2Frame(ctx, new DefaultHttp2PingFrame(data, false).retain());
|
onHttp2Frame(ctx, new DefaultHttp2PingFrame(data, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPingAckRead(ChannelHandlerContext ctx, ByteBuf data) {
|
public void onPingAckRead(ChannelHandlerContext ctx, long data) {
|
||||||
onHttp2Frame(ctx, new DefaultHttp2PingFrame(data, true).retain());
|
onHttp2Frame(ctx, new DefaultHttp2PingFrame(data, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -144,19 +144,17 @@ public interface Http2FrameListener {
|
|||||||
* Handles an inbound {@code PING} frame.
|
* Handles an inbound {@code PING} frame.
|
||||||
*
|
*
|
||||||
* @param ctx the context from the handler where the frame was read.
|
* @param ctx the context from the handler where the frame was read.
|
||||||
* @param data the payload of the frame. If this buffer needs to be retained by the listener
|
* @param data the payload of the frame.
|
||||||
* they must make a copy.
|
|
||||||
*/
|
*/
|
||||||
void onPingRead(ChannelHandlerContext ctx, ByteBuf data) throws Http2Exception;
|
void onPingRead(ChannelHandlerContext ctx, long data) throws Http2Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles an inbound {@code PING} acknowledgment.
|
* Handles an inbound {@code PING} acknowledgment.
|
||||||
*
|
*
|
||||||
* @param ctx the context from the handler where the frame was read.
|
* @param ctx the context from the handler where the frame was read.
|
||||||
* @param data the payload of the frame. If this buffer needs to be retained by the listener
|
* @param data the payload of the frame.
|
||||||
* they must make a copy.
|
|
||||||
*/
|
*/
|
||||||
void onPingAckRead(ChannelHandlerContext ctx, ByteBuf data) throws Http2Exception;
|
void onPingAckRead(ChannelHandlerContext ctx, long data) throws Http2Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles an inbound {@code PUSH_PROMISE} frame. Only called if {@code END_HEADERS} encountered.
|
* Handles an inbound {@code PUSH_PROMISE} frame. Only called if {@code END_HEADERS} encountered.
|
||||||
|
@ -70,12 +70,12 @@ public class Http2FrameListenerDecorator implements Http2FrameListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPingRead(ChannelHandlerContext ctx, ByteBuf data) throws Http2Exception {
|
public void onPingRead(ChannelHandlerContext ctx, long data) throws Http2Exception {
|
||||||
listener.onPingRead(ctx, data);
|
listener.onPingRead(ctx, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPingAckRead(ChannelHandlerContext ctx, ByteBuf data) throws Http2Exception {
|
public void onPingAckRead(ChannelHandlerContext ctx, long data) throws Http2Exception {
|
||||||
listener.onPingAckRead(ctx, data);
|
listener.onPingAckRead(ctx, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,14 +98,14 @@ public class Http2FrameLogger extends ChannelHandlerAdapter {
|
|||||||
logger.log(level, "{} {} SETTINGS: ack=false settings={}", ctx.channel(), direction.name(), settings);
|
logger.log(level, "{} {} SETTINGS: ack=false settings={}", ctx.channel(), direction.name(), settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void logPing(Direction direction, ChannelHandlerContext ctx, ByteBuf data) {
|
public void logPing(Direction direction, ChannelHandlerContext ctx, long data) {
|
||||||
logger.log(level, "{} {} PING: ack=false length={} bytes={}", ctx.channel(),
|
logger.log(level, "{} {} PING: ack=false bytes={}", ctx.channel(),
|
||||||
direction.name(), data.readableBytes(), toString(data));
|
direction.name(), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void logPingAck(Direction direction, ChannelHandlerContext ctx, ByteBuf data) {
|
public void logPingAck(Direction direction, ChannelHandlerContext ctx, long data) {
|
||||||
logger.log(level, "{} {} PING: ack=true length={} bytes={}", ctx.channel(),
|
logger.log(level, "{} {} PING: ack=true bytes={}", ctx.channel(),
|
||||||
direction.name(), data.readableBytes(), toString(data));
|
direction.name(), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void logPushPromise(Direction direction, ChannelHandlerContext ctx, int streamId, int promisedStreamId,
|
public void logPushPromise(Direction direction, ChannelHandlerContext ctx, int streamId, int promisedStreamId,
|
||||||
|
@ -147,11 +147,11 @@ public interface Http2FrameWriter extends Http2DataWriter, Closeable {
|
|||||||
* @param ctx the context to use for writing.
|
* @param ctx the context to use for writing.
|
||||||
* @param ack indicates whether this is an ack of a PING frame previously received from the
|
* @param ack indicates whether this is an ack of a PING frame previously received from the
|
||||||
* remote endpoint.
|
* remote endpoint.
|
||||||
* @param data the payload of the frame. This will be released by this method.
|
* @param data the payload of the frame.
|
||||||
* @param promise the promise for the write.
|
* @param promise the promise for the write.
|
||||||
* @return the future for the write.
|
* @return the future for the write.
|
||||||
*/
|
*/
|
||||||
ChannelFuture writePing(ChannelHandlerContext ctx, boolean ack, ByteBuf data,
|
ChannelFuture writePing(ChannelHandlerContext ctx, boolean ack, long data,
|
||||||
ChannelPromise promise);
|
ChannelPromise promise);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -94,13 +94,13 @@ public class Http2InboundFrameLogger implements Http2FrameReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPingRead(ChannelHandlerContext ctx, ByteBuf data) throws Http2Exception {
|
public void onPingRead(ChannelHandlerContext ctx, long data) throws Http2Exception {
|
||||||
logger.logPing(INBOUND, ctx, data);
|
logger.logPing(INBOUND, ctx, data);
|
||||||
listener.onPingRead(ctx, data);
|
listener.onPingRead(ctx, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPingAckRead(ChannelHandlerContext ctx, ByteBuf data) throws Http2Exception {
|
public void onPingAckRead(ChannelHandlerContext ctx, long data) throws Http2Exception {
|
||||||
logger.logPingAck(INBOUND, ctx, data);
|
logger.logPingAck(INBOUND, ctx, data);
|
||||||
listener.onPingAckRead(ctx, data);
|
listener.onPingAckRead(ctx, data);
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ public class Http2OutboundFrameLogger implements Http2FrameWriter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelFuture writePing(ChannelHandlerContext ctx, boolean ack,
|
public ChannelFuture writePing(ChannelHandlerContext ctx, boolean ack,
|
||||||
ByteBuf data, ChannelPromise promise) {
|
long data, ChannelPromise promise) {
|
||||||
if (ack) {
|
if (ack) {
|
||||||
logger.logPingAck(OUTBOUND, ctx, data);
|
logger.logPingAck(OUTBOUND, ctx, data);
|
||||||
} else {
|
} else {
|
||||||
|
@ -16,15 +16,13 @@
|
|||||||
|
|
||||||
package io.netty.handler.codec.http2;
|
package io.netty.handler.codec.http2;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
|
||||||
import io.netty.buffer.ByteBufHolder;
|
|
||||||
import io.netty.util.internal.UnstableApi;
|
import io.netty.util.internal.UnstableApi;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTTP/2 PING Frame.
|
* HTTP/2 PING Frame.
|
||||||
*/
|
*/
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
public interface Http2PingFrame extends Http2Frame, ByteBufHolder {
|
public interface Http2PingFrame extends Http2Frame {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When {@code true}, indicates that this ping is a ping response.
|
* When {@code true}, indicates that this ping is a ping response.
|
||||||
@ -34,6 +32,5 @@ public interface Http2PingFrame extends Http2Frame, ByteBufHolder {
|
|||||||
/**
|
/**
|
||||||
* Returns the eight byte opaque data.
|
* Returns the eight byte opaque data.
|
||||||
*/
|
*/
|
||||||
@Override
|
long content();
|
||||||
ByteBuf content();
|
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,6 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
import static io.netty.buffer.Unpooled.EMPTY_BUFFER;
|
import static io.netty.buffer.Unpooled.EMPTY_BUFFER;
|
||||||
import static io.netty.buffer.Unpooled.wrappedBuffer;
|
import static io.netty.buffer.Unpooled.wrappedBuffer;
|
||||||
import static io.netty.handler.codec.http2.Http2CodecUtil.DEFAULT_PRIORITY_WEIGHT;
|
import static io.netty.handler.codec.http2.Http2CodecUtil.DEFAULT_PRIORITY_WEIGHT;
|
||||||
import static io.netty.handler.codec.http2.Http2CodecUtil.emptyPingBuf;
|
|
||||||
import static io.netty.handler.codec.http2.Http2Error.PROTOCOL_ERROR;
|
import static io.netty.handler.codec.http2.Http2Error.PROTOCOL_ERROR;
|
||||||
import static io.netty.handler.codec.http2.Http2Stream.State.IDLE;
|
import static io.netty.handler.codec.http2.Http2Stream.State.IDLE;
|
||||||
import static io.netty.handler.codec.http2.Http2Stream.State.OPEN;
|
import static io.netty.handler.codec.http2.Http2Stream.State.OPEN;
|
||||||
@ -714,15 +713,15 @@ public class DefaultHttp2ConnectionDecoderTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void pingReadWithAckShouldNotifyListener() throws Exception {
|
public void pingReadWithAckShouldNotifyListener() throws Exception {
|
||||||
decode().onPingAckRead(ctx, emptyPingBuf());
|
decode().onPingAckRead(ctx, 0L);
|
||||||
verify(listener).onPingAckRead(eq(ctx), eq(emptyPingBuf()));
|
verify(listener).onPingAckRead(eq(ctx), eq(0L));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void pingReadShouldReplyWithAck() throws Exception {
|
public void pingReadShouldReplyWithAck() throws Exception {
|
||||||
decode().onPingRead(ctx, emptyPingBuf());
|
decode().onPingRead(ctx, 0L);
|
||||||
verify(encoder).writePing(eq(ctx), eq(true), eq(emptyPingBuf()), eq(promise));
|
verify(encoder).writePing(eq(ctx), eq(true), eq(0L), eq(promise));
|
||||||
verify(listener, never()).onPingAckRead(eq(ctx), any(ByteBuf.class));
|
verify(listener, never()).onPingAckRead(eq(ctx), any(long.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -45,7 +45,6 @@ import java.util.List;
|
|||||||
import static io.netty.buffer.Unpooled.EMPTY_BUFFER;
|
import static io.netty.buffer.Unpooled.EMPTY_BUFFER;
|
||||||
import static io.netty.buffer.Unpooled.wrappedBuffer;
|
import static io.netty.buffer.Unpooled.wrappedBuffer;
|
||||||
import static io.netty.handler.codec.http2.Http2CodecUtil.DEFAULT_PRIORITY_WEIGHT;
|
import static io.netty.handler.codec.http2.Http2CodecUtil.DEFAULT_PRIORITY_WEIGHT;
|
||||||
import static io.netty.handler.codec.http2.Http2CodecUtil.emptyPingBuf;
|
|
||||||
import static io.netty.handler.codec.http2.Http2Error.PROTOCOL_ERROR;
|
import static io.netty.handler.codec.http2.Http2Error.PROTOCOL_ERROR;
|
||||||
import static io.netty.handler.codec.http2.Http2Stream.State.HALF_CLOSED_REMOTE;
|
import static io.netty.handler.codec.http2.Http2Stream.State.HALF_CLOSED_REMOTE;
|
||||||
import static io.netty.handler.codec.http2.Http2Stream.State.RESERVED_LOCAL;
|
import static io.netty.handler.codec.http2.Http2Stream.State.RESERVED_LOCAL;
|
||||||
@ -639,15 +638,15 @@ public class DefaultHttp2ConnectionEncoderTest {
|
|||||||
public void pingWriteAfterGoAwayShouldSucceed() throws Exception {
|
public void pingWriteAfterGoAwayShouldSucceed() throws Exception {
|
||||||
ChannelPromise promise = newPromise();
|
ChannelPromise promise = newPromise();
|
||||||
goAwayReceived(0);
|
goAwayReceived(0);
|
||||||
encoder.writePing(ctx, false, emptyPingBuf(), promise);
|
encoder.writePing(ctx, false, 0L, promise);
|
||||||
verify(writer).writePing(eq(ctx), eq(false), eq(emptyPingBuf()), eq(promise));
|
verify(writer).writePing(eq(ctx), eq(false), eq(0L), eq(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void pingWriteShouldSucceed() throws Exception {
|
public void pingWriteShouldSucceed() throws Exception {
|
||||||
ChannelPromise promise = newPromise();
|
ChannelPromise promise = newPromise();
|
||||||
encoder.writePing(ctx, false, emptyPingBuf(), promise);
|
encoder.writePing(ctx, false, 0L, promise);
|
||||||
verify(writer).writePing(eq(ctx), eq(false), eq(emptyPingBuf()), eq(promise));
|
verify(writer).writePing(eq(ctx), eq(false), eq(0L), eq(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -57,7 +57,6 @@ import static io.netty.handler.codec.http2.Http2CodecUtil.DEFAULT_PRIORITY_WEIGH
|
|||||||
import static io.netty.handler.codec.http2.Http2Error.PROTOCOL_ERROR;
|
import static io.netty.handler.codec.http2.Http2Error.PROTOCOL_ERROR;
|
||||||
import static io.netty.handler.codec.http2.Http2TestUtil.randomString;
|
import static io.netty.handler.codec.http2.Http2TestUtil.randomString;
|
||||||
import static io.netty.handler.codec.http2.Http2TestUtil.runInChannel;
|
import static io.netty.handler.codec.http2.Http2TestUtil.runInChannel;
|
||||||
import static io.netty.util.CharsetUtil.UTF_8;
|
|
||||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||||
import static org.hamcrest.CoreMatchers.not;
|
import static org.hamcrest.CoreMatchers.not;
|
||||||
@ -871,24 +870,23 @@ public class Http2ConnectionRoundtripTest {
|
|||||||
@Test
|
@Test
|
||||||
public void stressTest() throws Exception {
|
public void stressTest() throws Exception {
|
||||||
final Http2Headers headers = dummyHeaders();
|
final Http2Headers headers = dummyHeaders();
|
||||||
final String pingMsg = "12345678";
|
|
||||||
int length = 10;
|
int length = 10;
|
||||||
final ByteBuf data = randomBytes(length);
|
final ByteBuf data = randomBytes(length);
|
||||||
final String dataAsHex = ByteBufUtil.hexDump(data);
|
final String dataAsHex = ByteBufUtil.hexDump(data);
|
||||||
final ByteBuf pingData = Unpooled.copiedBuffer(pingMsg, UTF_8);
|
final long pingData = 8;
|
||||||
final int numStreams = 2000;
|
final int numStreams = 2000;
|
||||||
|
|
||||||
// Collect all the ping buffers as we receive them at the server.
|
// Collect all the ping buffers as we receive them at the server.
|
||||||
final String[] receivedPings = new String[numStreams];
|
final long[] receivedPings = new long[numStreams];
|
||||||
doAnswer(new Answer<Void>() {
|
doAnswer(new Answer<Void>() {
|
||||||
int nextIndex;
|
int nextIndex;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void answer(InvocationOnMock in) throws Throwable {
|
public Void answer(InvocationOnMock in) throws Throwable {
|
||||||
receivedPings[nextIndex++] = ((ByteBuf) in.getArguments()[1]).toString(UTF_8);
|
receivedPings[nextIndex++] = (Long) in.getArguments()[1];
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}).when(serverListener).onPingRead(any(ChannelHandlerContext.class), any(ByteBuf.class));
|
}).when(serverListener).onPingRead(any(ChannelHandlerContext.class), any(Long.class));
|
||||||
|
|
||||||
// Collect all the data buffers as we receive them at the server.
|
// Collect all the data buffers as we receive them at the server.
|
||||||
final StringBuilder[] receivedData = new StringBuilder[numStreams];
|
final StringBuilder[] receivedData = new StringBuilder[numStreams];
|
||||||
@ -921,7 +919,7 @@ public class Http2ConnectionRoundtripTest {
|
|||||||
// Send a bunch of data on each stream.
|
// Send a bunch of data on each stream.
|
||||||
http2Client.encoder().writeHeaders(ctx(), streamId, headers, 0, (short) 16,
|
http2Client.encoder().writeHeaders(ctx(), streamId, headers, 0, (short) 16,
|
||||||
false, 0, false, newPromise());
|
false, 0, false, newPromise());
|
||||||
http2Client.encoder().writePing(ctx(), false, pingData.retainedSlice(),
|
http2Client.encoder().writePing(ctx(), false, pingData,
|
||||||
newPromise());
|
newPromise());
|
||||||
http2Client.encoder().writeData(ctx(), streamId, data.retainedSlice(), 0,
|
http2Client.encoder().writeData(ctx(), streamId, data.retainedSlice(), 0,
|
||||||
false, newPromise());
|
false, newPromise());
|
||||||
@ -940,20 +938,19 @@ public class Http2ConnectionRoundtripTest {
|
|||||||
verify(serverListener, times(numStreams)).onHeadersRead(any(ChannelHandlerContext.class), anyInt(),
|
verify(serverListener, times(numStreams)).onHeadersRead(any(ChannelHandlerContext.class), anyInt(),
|
||||||
eq(headers), eq(0), eq((short) 16), eq(false), eq(0), eq(true));
|
eq(headers), eq(0), eq((short) 16), eq(false), eq(0), eq(true));
|
||||||
verify(serverListener, times(numStreams)).onPingRead(any(ChannelHandlerContext.class),
|
verify(serverListener, times(numStreams)).onPingRead(any(ChannelHandlerContext.class),
|
||||||
any(ByteBuf.class));
|
any(long.class));
|
||||||
verify(serverListener, never()).onDataRead(any(ChannelHandlerContext.class),
|
verify(serverListener, never()).onDataRead(any(ChannelHandlerContext.class),
|
||||||
anyInt(), any(ByteBuf.class), eq(0), eq(true));
|
anyInt(), any(ByteBuf.class), eq(0), eq(true));
|
||||||
for (StringBuilder builder : receivedData) {
|
for (StringBuilder builder : receivedData) {
|
||||||
assertEquals(dataAsHex, builder.toString());
|
assertEquals(dataAsHex, builder.toString());
|
||||||
}
|
}
|
||||||
for (String receivedPing : receivedPings) {
|
for (long receivedPing : receivedPings) {
|
||||||
assertEquals(pingMsg, receivedPing);
|
assertEquals(pingData, receivedPing);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
// Don't wait for server to close streams
|
// Don't wait for server to close streams
|
||||||
http2Client.gracefulShutdownTimeoutMillis(0);
|
http2Client.gracefulShutdownTimeoutMillis(0);
|
||||||
data.release();
|
data.release();
|
||||||
pingData.release();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -615,24 +615,20 @@ public class Http2FrameCodecTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void receivePing() throws Http2Exception {
|
public void receivePing() throws Http2Exception {
|
||||||
ByteBuf data = Unpooled.buffer(8).writeLong(12345);
|
frameListener.onPingRead(http2HandlerCtx, 12345L);
|
||||||
frameListener.onPingRead(http2HandlerCtx, data);
|
|
||||||
|
|
||||||
Http2PingFrame pingFrame = inboundHandler.readInbound();
|
Http2PingFrame pingFrame = inboundHandler.readInbound();
|
||||||
assertNotNull(pingFrame);
|
assertNotNull(pingFrame);
|
||||||
|
|
||||||
assertEquals(data, pingFrame.content());
|
assertEquals(12345, pingFrame.content());
|
||||||
assertFalse(pingFrame.ack());
|
assertFalse(pingFrame.ack());
|
||||||
pingFrame.release();
|
|
||||||
data.release();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sendPing() {
|
public void sendPing() {
|
||||||
ByteBuf data = Unpooled.buffer(8).writeLong(12345);
|
channel.writeAndFlush(new DefaultHttp2PingFrame(12345));
|
||||||
channel.writeAndFlush(new DefaultHttp2PingFrame(data));
|
|
||||||
|
|
||||||
verify(frameWriter).writePing(eq(http2HandlerCtx), eq(false), eq(data), anyChannelPromise());
|
verify(frameWriter).writePing(eq(http2HandlerCtx), eq(false), eq(12345L), anyChannelPromise());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -351,26 +351,22 @@ public class Http2FrameRoundtripTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void pingFrameShouldMatch() throws Exception {
|
public void pingFrameShouldMatch() throws Exception {
|
||||||
final ByteBuf data = buf("01234567".getBytes(UTF_8));
|
writer.writePing(ctx, false, 1234567, ctx.newPromise());
|
||||||
|
|
||||||
writer.writePing(ctx, false, data.slice(), ctx.newPromise());
|
|
||||||
readFrames();
|
readFrames();
|
||||||
|
|
||||||
ArgumentCaptor<ByteBuf> captor = ArgumentCaptor.forClass(ByteBuf.class);
|
ArgumentCaptor<Long> captor = ArgumentCaptor.forClass(long.class);
|
||||||
verify(listener).onPingRead(eq(ctx), captor.capture());
|
verify(listener).onPingRead(eq(ctx), captor.capture());
|
||||||
assertEquals(data, captor.getValue());
|
assertEquals(1234567, (long) captor.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void pingAckFrameShouldMatch() throws Exception {
|
public void pingAckFrameShouldMatch() throws Exception {
|
||||||
final ByteBuf data = buf("01234567".getBytes(UTF_8));
|
writer.writePing(ctx, true, 1234567, ctx.newPromise());
|
||||||
|
|
||||||
writer.writePing(ctx, true, data.slice(), ctx.newPromise());
|
|
||||||
readFrames();
|
readFrames();
|
||||||
|
|
||||||
ArgumentCaptor<ByteBuf> captor = ArgumentCaptor.forClass(ByteBuf.class);
|
ArgumentCaptor<Long> captor = ArgumentCaptor.forClass(long.class);
|
||||||
verify(listener).onPingAckRead(eq(ctx), captor.capture());
|
verify(listener).onPingAckRead(eq(ctx), captor.capture());
|
||||||
assertEquals(data, captor.getValue());
|
assertEquals(1234567, (long) captor.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -175,13 +175,11 @@ public class Http2MultiplexCodecTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void unhandledHttp2FramesShouldBePropagated() {
|
public void unhandledHttp2FramesShouldBePropagated() {
|
||||||
ByteBuf content = UnpooledByteBufAllocator.DEFAULT.buffer(8).writeLong(0);
|
Http2PingFrame decodedFrame = new DefaultHttp2PingFrame(0);
|
||||||
Http2PingFrame decodedFrame = new DefaultHttp2PingFrame(content);
|
|
||||||
|
|
||||||
codec.onHttp2Frame(decodedFrame);
|
codec.onHttp2Frame(decodedFrame);
|
||||||
Http2PingFrame receivedPing = parentChannel.readInbound();
|
Http2PingFrame receivedPing = parentChannel.readInbound();
|
||||||
assertSame(receivedPing, decodedFrame);
|
assertSame(receivedPing, decodedFrame);
|
||||||
assertTrue(receivedPing.release());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -249,13 +249,13 @@ public final class Http2TestUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPingRead(ChannelHandlerContext ctx, ByteBuf data) throws Http2Exception {
|
public void onPingRead(ChannelHandlerContext ctx, long data) throws Http2Exception {
|
||||||
listener.onPingRead(ctx, data);
|
listener.onPingRead(ctx, data);
|
||||||
latch.countDown();
|
latch.countDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPingAckRead(ChannelHandlerContext ctx, ByteBuf data) throws Http2Exception {
|
public void onPingAckRead(ChannelHandlerContext ctx, long data) throws Http2Exception {
|
||||||
listener.onPingAckRead(ctx, data);
|
listener.onPingAckRead(ctx, data);
|
||||||
latch.countDown();
|
latch.countDown();
|
||||||
}
|
}
|
||||||
@ -384,13 +384,13 @@ public final class Http2TestUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPingRead(ChannelHandlerContext ctx, ByteBuf data) throws Http2Exception {
|
public void onPingRead(ChannelHandlerContext ctx, long data) throws Http2Exception {
|
||||||
listener.onPingRead(ctx, data);
|
listener.onPingRead(ctx, data);
|
||||||
messageLatch.countDown();
|
messageLatch.countDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPingAckRead(ChannelHandlerContext ctx, ByteBuf data) throws Http2Exception {
|
public void onPingAckRead(ChannelHandlerContext ctx, long data) throws Http2Exception {
|
||||||
listener.onPingAckRead(ctx, data);
|
listener.onPingAckRead(ctx, data);
|
||||||
messageLatch.countDown();
|
messageLatch.countDown();
|
||||||
}
|
}
|
||||||
|
@ -138,11 +138,11 @@ public final class HelloWorldHttp2Handler extends Http2ConnectionHandler impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPingRead(ChannelHandlerContext ctx, ByteBuf data) {
|
public void onPingRead(ChannelHandlerContext ctx, long data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPingAckRead(ChannelHandlerContext ctx, ByteBuf data) {
|
public void onPingAckRead(ChannelHandlerContext ctx, long data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -138,11 +138,11 @@ public final class HelloWorldHttp2Handler extends Http2ConnectionHandler impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPingRead(ChannelHandlerContext ctx, ByteBuf data) {
|
public void onPingRead(ChannelHandlerContext ctx, long data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPingAckRead(ChannelHandlerContext ctx, ByteBuf data) {
|
public void onPingAckRead(ChannelHandlerContext ctx, long data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
Reference in New Issue
Block a user