import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
-
import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.ssl.SslHandler;
import io.netty.util.Timeout;
import io.netty.util.Timer;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import io.netty.util.concurrent.Promise;
-
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.api.NetconfSession;
import org.opendaylight.controller.netconf.api.NetconfSessionPreferences;
// TODO what time ?
private static final long INITIAL_HOLDTIMER = 1;
+
private static final Logger logger = LoggerFactory.getLogger(AbstractNetconfSessionNegotiator.class);
+ public static final String NAME_OF_EXCEPTION_HANDLER = "lastExceptionHandler";
protected final P sessionPreferences;
private final SessionListener sessionListener;
+ private Timeout timeout;
/**
* Possible states for Finite State Machine
}
@Override
- protected void startNegotiation() throws Exception {
+ protected void startNegotiation() {
final Optional<SslHandler> sslHandler = getSslHandler(channel);
if (sslHandler.isPresent()) {
Future<Channel> future = sslHandler.get().handshakeFuture();
final NetconfMessage helloMessage = this.sessionPreferences.getHelloMessage();
logger.debug("Session negotiation started with hello message {}", XmlUtil.toString(helloMessage.getDocument()));
- sendMessage(helloMessage);
- changeState(State.OPEN_WAIT);
+ channel.pipeline().addLast(NAME_OF_EXCEPTION_HANDLER, new ChannelHandler() {
+ @Override
+ public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
+ }
+
+ @Override
+ public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
+ }
- this.timer.newTimeout(new TimerTask() {
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
+ logger.warn("An exception occurred during negotiation on channel {}", channel.localAddress(), cause);
+ cancelTimeout();
+ negotiationFailed(cause);
+ changeState(State.FAILED);
+ }
+ });
+
+ timeout = this.timer.newTimeout(new TimerTask() {
@Override
public void run(final Timeout timeout) throws Exception {
synchronized (this) {
"Session was not established after " + timeout);
negotiationFailed(cause);
changeState(State.FAILED);
- }
+ } else
+ channel.pipeline().remove(NAME_OF_EXCEPTION_HANDLER);
}
}
}, INITIAL_HOLDTIMER, TimeUnit.MINUTES);
+
+ sendMessage(helloMessage);
+ changeState(State.OPEN_WAIT);
+ }
+
+ private void cancelTimeout() {
+ if(timeout!=null)
+ timeout.cancel();
}
private void sendMessage(NetconfMessage message) {
channel.pipeline().addAfter("aggregator", "chunkDecoder", new NetconfMessageChunkDecoder());
}
changeState(State.ESTABLISHED);
- S session = getSession(sessionListener, channel, doc);
+ S session = getSession(sessionListener, channel, netconfMessage);
negotiationSuccessful(session);
} else {
final IllegalStateException cause = new IllegalStateException(
"Received message was not hello as expected, but was " + XmlUtil.toString(doc));
+ logger.warn("Negotiation of netconf session failed", cause);
negotiationFailed(cause);
}
}
- protected abstract S getSession(SessionListener sessionListener, Channel channel, Document doc);
+ protected abstract S getSession(SessionListener sessionListener, Channel channel, NetconfMessage message);
private boolean isHelloMessage(Document doc) {
try {