import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.requireNonNull;
+import com.google.common.annotations.Beta;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.concurrent.Promise;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
+import org.checkerframework.checker.index.qual.NonNegative;
import org.checkerframework.checker.lock.qual.GuardedBy;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.netconf.api.NetconfDocumentedException;
private static final Logger LOG = LoggerFactory.getLogger(AbstractNetconfSessionNegotiator.class);
private static final String NAME_OF_EXCEPTION_HANDLER = "lastExceptionHandler";
+ private static final String DEFAULT_MAXIMUM_CHUNK_SIZE_PROP = "org.opendaylight.netconf.default.maximum.chunk.size";
+ private static final int DEFAULT_MAXIMUM_CHUNK_SIZE_DEFAULT = 16 * 1024 * 1024;
+
+ /**
+ * Default upper bound on the size of an individual chunk. This value can be controlled through
+ * {@value #DEFAULT_MAXIMUM_CHUNK_SIZE_PROP} system property and defaults to
+ * {@value #DEFAULT_MAXIMUM_CHUNK_SIZE_DEFAULT} bytes.
+ */
+ @Beta
+ public static final @NonNegative int DEFAULT_MAXIMUM_INCOMING_CHUNK_SIZE;
+
+ static {
+ final int propValue = Integer.getInteger(DEFAULT_MAXIMUM_CHUNK_SIZE_PROP, DEFAULT_MAXIMUM_CHUNK_SIZE_DEFAULT);
+ if (propValue <= 0) {
+ LOG.warn("Ignoring invalid {} value {}", DEFAULT_MAXIMUM_CHUNK_SIZE_PROP, propValue);
+ DEFAULT_MAXIMUM_INCOMING_CHUNK_SIZE = DEFAULT_MAXIMUM_CHUNK_SIZE_DEFAULT;
+ } else {
+ DEFAULT_MAXIMUM_INCOMING_CHUNK_SIZE = propValue;
+ }
+ LOG.debug("Default maximum incoming NETCONF chunk size is {} bytes", DEFAULT_MAXIMUM_INCOMING_CHUNK_SIZE);
+ }
private final @NonNull NetconfHelloMessage localHello;
protected final Channel channel;
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-
package org.opendaylight.netconf.nettyutil.handler;
+import static com.google.common.base.Preconditions.checkArgument;
+
import io.netty.buffer.ByteBuf;
import io.netty.buffer.CompositeByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import java.util.List;
+import org.checkerframework.checker.index.qual.NonNegative;
+import org.opendaylight.netconf.nettyutil.AbstractNetconfSessionNegotiator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final String GOT_PARAM_WHILE_WAITING_FOR_PARAM_PARAM = "Got byte {} while waiting for {}-{}";
private static final String GOT_PARAM_WHILE_WAITING_FOR_PARAM_PARAM_PARAM =
"Got byte {} while waiting for {}-{}-{}";
- public static final int DEFAULT_MAXIMUM_CHUNK_SIZE = 16 * 1024 * 1024;
+
+ public static final @NonNegative int DEFAULT_MAXIMUM_CHUNK_SIZE =
+ AbstractNetconfSessionNegotiator.DEFAULT_MAXIMUM_INCOMING_CHUNK_SIZE;
private enum State {
HEADER_ONE, // \n
FOOTER_FOUR, // \n
}
- private final int maxChunkSize = DEFAULT_MAXIMUM_CHUNK_SIZE;
+ private final int maxChunkSize;
private State state = State.HEADER_ONE;
private long chunkSize;
private CompositeByteBuf chunk;
+ /**
+ * Construct an instance with maximum chunk size set to {@link #DEFAULT_MAXIMUM_CHUNK_SIZE}.
+ */
+ public NetconfChunkAggregator() {
+ this(DEFAULT_MAXIMUM_CHUNK_SIZE);
+ }
+
+ /**
+ * Construct an instance with specified maximum chunk size.
+ *
+ * @param maxChunkSize maximum chunk size
+ * @throws IllegalArgumentException if {@code maxChunkSize} is negative
+ */
+ public NetconfChunkAggregator(final @NonNegative int maxChunkSize) {
+ this.maxChunkSize = maxChunkSize;
+ checkArgument(maxChunkSize > 0, "Negative maximum chunk size %s", maxChunkSize);
+ }
+
private static void checkNewLine(final byte byteToCheck, final String errorMessage) {
if (byteToCheck != '\n') {
LOG.debug(GOT_PARAM_WHILE_WAITING_FOR_PARAM, byteToCheck, (byte)'\n');
private void checkChunkSize() {
if (chunkSize > maxChunkSize) {
LOG.debug("Parsed chunk size {}, maximum allowed is {}", chunkSize, maxChunkSize);
- throw new IllegalStateException("Maximum chunk size exceeded");
+ throw new IllegalStateException("Chunk size " + chunkSize + " exceeds maximum " + maxChunkSize);
}
}