X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fnetconf%2Fnetconf-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fnetconf%2Fimpl%2FNetconfServerSessionListener.java;h=b3245fff2b812775803acf59e1c2e53aa875d77e;hp=686adcad8550a3401809235cc0bda6e660782738;hb=9c9d6e69da3aff2d0576d8c15ea0fa0692595b6d;hpb=9d2212483a4fca225d5ad58e7f924f58b638ddb6 diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListener.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListener.java index 686adcad85..b3245fff2b 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListener.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListener.java @@ -8,48 +8,65 @@ package org.opendaylight.controller.netconf.impl; -import static com.google.common.base.Preconditions.checkState; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfMessage; -import org.opendaylight.controller.netconf.api.NetconfSession; +import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouter; +import org.opendaylight.controller.netconf.api.NetconfSessionListener; import org.opendaylight.controller.netconf.api.NetconfTerminationReason; -import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouterImpl; +import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCloseSession; +import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService; import org.opendaylight.controller.netconf.util.messages.SendErrorExceptionUtil; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; import org.opendaylight.controller.netconf.util.xml.XmlUtil; -import org.opendaylight.protocol.framework.SessionListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; +import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; -public class NetconfServerSessionListener implements - SessionListener { +public class NetconfServerSessionListener implements NetconfSessionListener { static final Logger logger = LoggerFactory.getLogger(NetconfServerSessionListener.class); - public static final String MESSAGE_ID = "message-id"; + private final SessionMonitoringService monitoringService; + private final NetconfOperationRouter operationRouter; + private final AutoCloseable onSessionDownCloseable; - private NetconfOperationRouterImpl operationRouter; - - public NetconfServerSessionListener(NetconfOperationRouterImpl operationRouter) { + public NetconfServerSessionListener(NetconfOperationRouter operationRouter, SessionMonitoringService monitoringService, + AutoCloseable onSessionDownCloseable) { this.operationRouter = operationRouter; + this.monitoringService = monitoringService; + this.onSessionDownCloseable = onSessionDownCloseable; } @Override public void onSessionUp(NetconfServerSession netconfNetconfServerSession) { - + monitoringService.onSessionUp(netconfNetconfServerSession); } @Override - public void onSessionDown(NetconfServerSession netconfNetconfServerSession, Exception e) { - logger.debug("Session {} down, reason: {}", netconfNetconfServerSession, e.getMessage()); + public void onSessionDown(NetconfServerSession netconfNetconfServerSession, Exception cause) { + logger.debug("Session {} down, reason: {}", netconfNetconfServerSession, cause.getMessage()); + onDown(netconfNetconfServerSession); + } - operationRouter.close(); + public void onDown(NetconfServerSession netconfNetconfServerSession) { + monitoringService.onSessionDown(netconfNetconfServerSession); + + try { + operationRouter.close(); + } catch (Exception closingEx) { + logger.debug("Ignoring exception while closing operationRouter", closingEx); + } + try { + onSessionDownCloseable.close(); + } catch(Exception ex){ + logger.debug("Ignoring exception while closing onSessionDownCloseable", ex); + } } @Override @@ -57,8 +74,7 @@ public class NetconfServerSessionListener implements NetconfTerminationReason netconfTerminationReason) { logger.debug("Session {} terminated, reason: {}", netconfNetconfServerSession, netconfTerminationReason.getErrorMessage()); - - operationRouter.close(); + onDown(netconfNetconfServerSession); } @Override @@ -70,7 +86,7 @@ public class NetconfServerSessionListener implements // schemas final NetconfMessage message = processDocument(netconfMessage, session); - logger.debug("Respondign with message {}", XmlUtil.toString(message.getDocument())); + logger.debug("Responding with message {}", XmlUtil.toString(message.getDocument())); session.sendMessage(message); if (isCloseSession(netconfMessage)) { @@ -78,10 +94,13 @@ public class NetconfServerSessionListener implements } } catch (final RuntimeException e) { - logger.error("Unexpected exception", e); // TODO: should send generic error or close session? + logger.error("Unexpected exception", e); + session.onIncommingRpcFail(); throw new RuntimeException("Unable to process incoming message " + netconfMessage, e); } catch (NetconfDocumentedException e) { + session.onOutgoingRpcError(); + session.onIncommingRpcFail(); SendErrorExceptionUtil.sendErrorMessage(session, e, netconfMessage); } } @@ -92,18 +111,20 @@ public class NetconfServerSessionListener implements logger.info("Session {} closed successfully", session.getSessionId()); } - private NetconfMessage processDocument(final NetconfMessage netconfMessage, - NetconfSession session) throws NetconfDocumentedException { + private NetconfMessage processDocument(final NetconfMessage netconfMessage, NetconfServerSession session) + throws NetconfDocumentedException { - final Document incommingDocument = netconfMessage.getDocument(); - final Node rootNode = incommingDocument.getDocumentElement(); + final Document incomingDocument = netconfMessage.getDocument(); + final Node rootNode = incomingDocument.getDocumentElement(); if (rootNode.getLocalName().equals(XmlNetconfConstants.RPC_KEY)) { - final String messageId = rootNode.getAttributes().getNamedItem(MESSAGE_ID).getTextContent(); - checkState(messageId != null); final Document responseDocument = XmlUtil.newDocument(); - Document rpcReply = operationRouter.onNetconfMessage( - incommingDocument, session); + checkMessageId(rootNode); + + Document rpcReply = operationRouter.onNetconfMessage(incomingDocument, session); + + session.onIncommingRpcSuccess(); + responseDocument.appendChild(responseDocument.importNode(rpcReply.getDocumentElement(), true)); return new NetconfMessage(responseDocument); } else { @@ -121,11 +142,28 @@ public class NetconfServerSessionListener implements } } - private static boolean isCloseSession(final NetconfMessage incommingDocument) { - final Document document = incommingDocument.getDocument(); + private void checkMessageId(Node rootNode) throws NetconfDocumentedException { + NamedNodeMap attributes = rootNode.getAttributes(); + if(attributes.getNamedItemNS(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, XmlNetconfConstants.MESSAGE_ID)!=null) { + return; + } + + if(attributes.getNamedItem(XmlNetconfConstants.MESSAGE_ID)!=null) { + return; + } + + throw new NetconfDocumentedException("Missing attribute" + rootNode.getNodeName(), + NetconfDocumentedException.ErrorType.protocol, NetconfDocumentedException.ErrorTag.missing_attribute, + NetconfDocumentedException.ErrorSeverity.error, ImmutableMap.of(NetconfDocumentedException.ErrorTag.missing_attribute.toString(), + XmlNetconfConstants.MESSAGE_ID)); + } + + private static boolean isCloseSession(final NetconfMessage incomingDocument) { + final Document document = incomingDocument.getDocument(); XmlElement rpcElement = XmlElement.fromDomDocument(document); - if (rpcElement.getOnlyChildElementOptionally("close-session").isPresent()) + if (rpcElement.getOnlyChildElementOptionally(DefaultCloseSession.CLOSE_SESSION).isPresent()) { return true; + } return false; }