package org.opendaylight.controller.netconf.client;
-import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
-import io.netty.util.Timer;
-import io.netty.util.concurrent.Promise;
+import java.util.Collection;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+
import org.opendaylight.controller.netconf.api.NetconfClientSessionPreferences;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.util.AbstractNetconfSessionNegotiator;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil;
+import org.opendaylight.controller.netconf.util.messages.NetconfStartExiMessage;
import org.opendaylight.controller.netconf.util.xml.XMLNetconfUtil;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathExpression;
+import io.netty.channel.Channel;
+import io.netty.util.Timer;
+import io.netty.util.concurrent.Promise;
public class NetconfClientSessionNegotiator extends
AbstractNetconfSessionNegotiator<NetconfClientSessionPreferences, NetconfClientSession, NetconfClientSessionListener>
@Override
protected void handleMessage(NetconfHelloMessage netconfMessage) throws NetconfDocumentedException {
- NetconfClientSession session = super.getSessionForHelloMessage(netconfMessage);
-
- if (shouldUseExi(netconfMessage.getDocument())){
- logger.info("Netconf session: {} should use exi.", session);
- tryToStartExi(session);
+ final NetconfClientSession session = getSessionForHelloMessage(netconfMessage);
+ replaceHelloMessageInboundHandler(session);
+
+ // If exi should be used, try to initiate exi communication
+ // Call negotiationSuccessFul after exi negotiation is finished successfully or not
+ if (shouldUseExi(netconfMessage)) {
+ logger.debug("Netconf session {} should use exi.", session);
+ NetconfStartExiMessage startExiMessage = (NetconfStartExiMessage) sessionPreferences.getStartExiMessage();
+ tryToInitiateExi(session, startExiMessage);
+ // Exi is not supported, release session immediately
} else {
- logger.info("Netconf session {} isn't capable using exi.", session);
+ logger.debug("Netconf session {} isn't capable using exi.", session);
negotiationSuccessful(session);
}
}
- private boolean shouldUseExi(Document doc) {
- return containsExi10Capability(doc)
+ /**
+ * Initiates exi communication by sending start-exi message and waiting for positive/negative response.
+ *
+ * @param startExiMessage
+ */
+ void tryToInitiateExi(final NetconfClientSession session, final NetconfStartExiMessage startExiMessage) {
+ session.sendMessage(startExiMessage).addListener(new ChannelFutureListener() {
+ @Override
+ public void operationComplete(final ChannelFuture f) {
+ if (!f.isSuccess()) {
+ logger.warn("Failed to send start-exi message {} on session {}", startExiMessage, this, f.cause());
+ } else {
+ logger.trace("Start-exi message {} sent to socket on session {}", startExiMessage, this);
+ channel.pipeline().addAfter(
+ AbstractChannelInitializer.NETCONF_MESSAGE_DECODER, ExiConfirmationInboundHandler.EXI_CONFIRMED_HANDLER,
+ new ExiConfirmationInboundHandler(session, startExiMessage));
+ }
+ }
+ });
+ }
+
+ private boolean shouldUseExi(NetconfHelloMessage helloMsg) {
+ return containsExi10Capability(helloMsg.getDocument())
&& containsExi10Capability(sessionPreferences.getHelloMessage().getDocument());
}
return false;
}
- private void tryToStartExi(final NetconfClientSession session) {
- final NetconfMessage startExi = sessionPreferences.getStartExiMessage();
- session.sendMessage(startExi).addListener(new ChannelFutureListener() {
- @Override
- public void operationComplete(final ChannelFuture f) {
- if (!f.isSuccess()) {
- logger.warn("Failed to send start-exi message {} on session {}", startExi, session, f.cause());
- } else {
- logger.trace("Start-exi message {} sent to socket on session {}", startExi, session);
- NetconfClientSessionNegotiator.this.channel.pipeline().addAfter(
- AbstractChannelInitializer.NETCONF_MESSAGE_DECODER, ExiConfirmationInboundHandler.EXI_CONFIRMED_HANDLER,
- new ExiConfirmationInboundHandler(session));
- }
- }
- });
- }
-
private long extractSessionId(Document doc) {
final Node sessionIdNode = (Node) XmlUtil.evaluateXPath(sessionIdXPath, doc, XPathConstants.NODE);
String textContent = sessionIdNode.getTextContent();
}
@Override
- protected NetconfClientSession getSession(NetconfClientSessionListener sessionListener, Channel channel, NetconfHelloMessage message) throws NetconfDocumentedException {
- return new NetconfClientSession(sessionListener, channel, extractSessionId(message.getDocument()),
- NetconfMessageUtil.extractCapabilitiesFromHello(message.getDocument()));
+ protected NetconfClientSession getSession(NetconfClientSessionListener sessionListener, Channel channel,
+ NetconfHelloMessage message) throws NetconfDocumentedException {
+ long sessionId = extractSessionId(message.getDocument());
+ Collection<String> capabilities = NetconfMessageUtil.extractCapabilitiesFromHello(message.getDocument());
+ return new NetconfClientSession(sessionListener, channel, sessionId, capabilities);
}
/**
private static final String EXI_CONFIRMED_HANDLER = "exiConfirmedHandler";
private final NetconfClientSession session;
+ private NetconfStartExiMessage startExiMessage;
- ExiConfirmationInboundHandler(NetconfClientSession session) {
+ ExiConfirmationInboundHandler(NetconfClientSession session, final NetconfStartExiMessage startExiMessage) {
this.session = session;
+ this.startExiMessage = startExiMessage;
}
@Override
if (NetconfMessageUtil.isOKMessage(netconfMessage)) {
logger.trace("Positive response on start-exi call received on session {}", session);
try {
- session.startExiCommunication(sessionPreferences.getStartExiMessage());
+ session.startExiCommunication(startExiMessage);
} catch (RuntimeException e) {
// Unable to add exi, continue without exi
logger.warn("Unable to start exi communication, Communication will continue without exi on session {}", session, e);
}
- // Error response
+ // Error response
} else if(NetconfMessageUtil.isErrorMessage(netconfMessage)) {
logger.warn(
"Error response to start-exi message {}, Communication will continue without exi on session {}",
XmlUtil.toString(netconfMessage.getDocument()), session);
- // Unexpected response to start-exi, throwing message away, continue without exi
+ // Unexpected response to start-exi, throwing message away, continue without exi
} else {
logger.warn(
"Unexpected response to start-exi message, should be ok, was {}, " +
negotiationSuccessful(session);
}
}
+
}