/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.camel.component.lumberjack.io;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.apache.camel.component.lumberjack.io.LumberjackConstants.FRAME_ACKNOWLEDGE_LENGTH;
import static org.apache.camel.component.lumberjack.io.LumberjackConstants.TYPE_ACKNOWLEDGE;
import static org.apache.camel.component.lumberjack.io.LumberjackConstants.VERSION_V1;
import static org.apache.camel.component.lumberjack.io.LumberjackConstants.VERSION_V2;
/**
* Handles lumberjack window and send acknowledge when required.
*/
final class LumberjackSessionHandler {
private static final Logger LOG = LoggerFactory.getLogger(LumberjackSessionHandler.class);
private static final int ACK_UNSET = -1;
private volatile int version = -1;
private volatile int windowSize = 1;
private volatile int nextAck = ACK_UNSET;
void versionRead(int version) {
if (this.version == -1) {
if (version != VERSION_V1 && version != VERSION_V2) {
throw new RuntimeException("Unsupported frame version=" + version);
}
LOG.debug("Lumberjack protocol version is {}", (char) version);
this.version = version;
} else if (this.version != version) {
throw new IllegalStateException("Protocol version changed during session from " + this.version + " to " + version);
}
}
void windowSizeRead(int windowSize) {
LOG.debug("Lumberjack window size is {}", windowSize);
this.windowSize = windowSize;
nextAck = ACK_UNSET;
}
void notifyMessageProcessed(ChannelHandlerContext ctx, int sequenceNumber) {
if (nextAck == ACK_UNSET) {
nextAck = sequenceNumber + windowSize - 1;
}
if (sequenceNumber == nextAck) {
LOG.debug("Sequence number is {}. Sending ACK", sequenceNumber);
ByteBuf response = ctx.alloc().heapBuffer(FRAME_ACKNOWLEDGE_LENGTH, FRAME_ACKNOWLEDGE_LENGTH);
response.writeByte(version);
response.writeByte(TYPE_ACKNOWLEDGE);
response.writeInt(sequenceNumber);
ctx.writeAndFlush(response);
}
}
}