X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fnetconf%2Fnetconf-util%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fnetconf%2Futil%2Fhandler%2FNetconfXMLToHelloMessageDecoder.java;h=361d4fcee908018eac90a54844569ced70c22a21;hp=b930b65b9742625071f6f0618be9461add72a2c7;hb=e159106bc148e76fc1e3e3c780bdd740d99e74ed;hpb=567792806ed799ac649cc125bffb4debde40d254 diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfXMLToHelloMessageDecoder.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfXMLToHelloMessageDecoder.java index b930b65b97..361d4fcee9 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfXMLToHelloMessageDecoder.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfXMLToHelloMessageDecoder.java @@ -7,6 +7,8 @@ */ package org.opendaylight.controller.netconf.util.handler; +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; @@ -36,7 +38,12 @@ import org.xml.sax.SAXException; * Customized NetconfXMLToMessageDecoder that reads additional header with * session metadata from * {@link org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage} - * . Used by netconf server to retrieve information about session metadata. + * + * + * This handler should be replaced in pipeline by regular message handler as last step of negotiation. + * It serves as a message barrier and halts all non-hello netconf messages. + * Netconf messages after hello should be processed once the negotiation succeeded. + * */ public final class NetconfXMLToHelloMessageDecoder extends ByteToMessageDecoder { private static final Logger LOG = LoggerFactory.getLogger(NetconfXMLToHelloMessageDecoder.class); @@ -49,6 +56,12 @@ public final class NetconfXMLToHelloMessageDecoder extends ByteToMessageDecoder new byte[] { '\r', '\n', '[' }, new byte[] { '\n', '[' }); + // State variables do not have to by synchronized + // Netty uses always the same (1) thread per pipeline + // We use instance of this per pipeline + private List nonHelloMessages = Lists.newArrayList(); + private boolean helloReceived = false; + @Override @VisibleForTesting public void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws IOException, SAXException, NetconfDocumentedException { @@ -79,18 +92,39 @@ public final class NetconfXMLToHelloMessageDecoder extends ByteToMessageDecoder Document doc = XmlUtil.readXmlToDocument(new ByteArrayInputStream(bytes)); - final NetconfMessage message; - if (additionalHeader != null) { - message = new NetconfHelloMessage(doc, NetconfHelloMessageAdditionalHeader.fromString(additionalHeader)); + final NetconfMessage message = getNetconfMessage(additionalHeader, doc); + if (message instanceof NetconfHelloMessage) { + Preconditions.checkState(helloReceived == false, + "Multiple hello messages received, unexpected hello: %s", + XmlUtil.toString(message.getDocument())); + out.add(message); + helloReceived = true; + // Non hello message, suspend the message and insert into cache } else { - message = new NetconfHelloMessage(doc); + Preconditions.checkState(helloReceived, "Hello message not received, instead received: %s", + XmlUtil.toString(message.getDocument())); + LOG.debug("Netconf message received during negotiation, caching {}", + XmlUtil.toString(message.getDocument())); + nonHelloMessages.add(message); } - out.add(message); } finally { in.discardReadBytes(); } } + private NetconfMessage getNetconfMessage(final String additionalHeader, final Document doc) throws NetconfDocumentedException { + NetconfMessage msg = new NetconfMessage(doc); + if(NetconfHelloMessage.isHelloMessage(msg)) { + if (additionalHeader != null) { + return new NetconfHelloMessage(doc, NetconfHelloMessageAdditionalHeader.fromString(additionalHeader)); + } else { + return new NetconfHelloMessage(doc); + } + } + + return msg; + } + private int getAdditionalHeaderEndIndex(byte[] bytes) { for (byte[] possibleEnd : POSSIBLE_ENDS) { int idx = findByteSequence(bytes, possibleEnd); @@ -155,4 +189,10 @@ public final class NetconfXMLToHelloMessageDecoder extends ByteToMessageDecoder return Charsets.UTF_8.decode(ByteBuffer.wrap(bytes)).toString(); } + /** + * @return Collection of NetconfMessages that were not hello, but were received during negotiation + */ + public Iterable getPostHelloNetconfMessages() { + return nonHelloMessages; + } }