def _handle_message(self, msg):
        '''
        'Handle a message, lock is already held
        '''
        if not self.session_open:
            return

        try:
            tree = etree.parse(io.BytesIO(msg.encode('utf-8')))
            if not tree:
                raise ncerror.SessionError(msg, "Invalid XML from client.")
        except etree.XMLSyntaxError:
            GlobalModule.EM_LOGGER.warning(
                "202010 Closing session due to malformed message")
            raise ncerror.SessionError(msg, "Invalid XML from client.")

        rpcs = tree.xpath("/nc:rpc", namespaces=NSMAP)
        if not rpcs:
            raise ncerror.SessionError(msg, "No rpc found")

        for rpc in rpcs:
            try:
                msg_id = rpc.get('message-id')
                if self.debug:
                    GlobalModule.EM_LOGGER.debug(
                        "%s: Received rpc message-id: %s", str(self), msg_id)
            except (TypeError, ValueError):
                raise ncerror.SessionError(
                    msg, "No valid message-id attribute found")

            try:
                rpc_method = rpc.getchildren()
                if len(rpc_method) != 1:
                    if self.debug:
                        GlobalModule.EM_LOGGER.debug("%s: Bad Msg: msg-id: %s",
                                                     str(self), msg_id)
                    raise ncerror.RPCSvrErrBadMsg(rpc)
                rpc_method = rpc_method[0]

                rpcname = rpc_method.tag.replace(qmap('nc'), "")
                params = rpc_method.getchildren()
                paramslen = len(params)

                if rpcname == "close-session":
                    if self.debug:
                        GlobalModule.EM_LOGGER.debug(
                            "%s: Received close-session msg-id: %s", str(self),
                            msg_id)
                    GlobalModule.EM_LOGGER.info("102007 Connection Closed: %s",
                                                str(self))
                    EmNetconfSessionDate.del_session_date(self.session_id)
                    self.send_rpc_reply(etree.Element("ok"), rpc)
                    self.close()
                    return
                elif rpcname == "kill-session":
                    if self.debug:
                        GlobalModule.EM_LOGGER.debug(
                            "%s: Received kill-session msg-id: %s", str(self),
                            msg_id)
                    self.send_rpc_reply(etree.Element("ok"), rpc)
                    self.close()
                    return
                elif rpcname == "get":

                    if paramslen > 1:
                        raise ncerror.RPCSvrErrBadMsg(rpc)
                    if params and not util.filter_tag_match(
                            params[0], "nc:filter"):
                        raise ncerror.RPCSvrUnknownElement(rpc, params[0])
                    if not params:
                        params = [None]
                elif rpcname == "get-config":

                    GlobalModule.EM_LOGGER.info("102004 Receiving get-config")

                    if paramslen > 2:
                        raise ncerror.RPCSvrErrBadMsg(rpc)
                    source_param = rpc_method.find("nc:source",
                                                   namespaces=NSMAP)
                    if source_param is None:
                        raise ncerror.RPCSvrMissingElement(
                            rpc, util.elm("nc:source"))
                    filter_param = None
                    if paramslen == 2:
                        filter_param = rpc_method.find("nc:filter",
                                                       namespaces=NSMAP)
                        if filter_param is None:
                            unknown_elm = params[
                                0] if params[0] != source_param else params[1]
                            raise ncerror.RPCSvrUnknownElement(
                                rpc, unknown_elm)
                    params = [source_param, filter_param]

                elif rpcname == "edit-config":
                    GlobalModule.EM_LOGGER.info("102008 Receiving edit-config")

                    if paramslen > 2:
                        raise ncerror.RPCSvrErrBadMsg(rpc)

                    target_param = rpc_method.find("nc:target",
                                                   namespaces=NSMAP)
                    if target_param is None:
                        raise ncerror.RPCSvrMissingElement(
                            rpc, util.elm("nc:target"))

                    config_param = None
                    if paramslen == 2:
                        config_param = rpc_method.find("nc:config",
                                                       namespaces=NSMAP)
                        if config_param is None:
                            unknown_elm = params[
                                0] if params[0] != config_param else params[1]
                            raise ncerror.RPCSvrUnknownElement(
                                rpc, unknown_elm)
                    params = [target_param, config_param]

                try:
                    rpcname = rpcname.rpartition("}")[-1]
                    method_name = "rpc_" + rpcname.replace('-', '_')
                    method = getattr(self.methods, method_name,
                                     self._rpc_not_implemented)
                    result, reply = method(self.session_id, rpc, *params)

                    if result is not True:
                        self.send_rpc_reply(reply, rpc)

                except NotImplementedError:
                    raise ncerror.RPCSvrErrNotImpl(rpc)
            except ncerror.RPCSvrErrBadMsg as msgerr:
                if self.new_framing:
                    self.send_message(msgerr.get_reply_msg())
                else:
                    GlobalModule.EM_LOGGER.warning(
                        "Closing 1.0 session due to malformed message")
                    raise ncerror.SessionError(msg, "Malformed message")
            except ncerror.RPCServerError as error:
                self.send_message(error.get_reply_msg())
            except Exception as exception:
                GlobalModule.EM_LOGGER.debug(traceback.format_exc())
                error = ncerror.RPCSvrException(rpc, exception)
                self.send_message(error.get_reply_msg())
Example #2
0
 def rpc_edit_config(self, unused_session, rpc, *unused_params):
     raise ncerror.RPCSvrErrNotImpl(rpc)
Example #3
0
 def rpc_unlock(self, unused_session, rpc, *unused_params):
     raise ncerror.RPCSvrErrNotImpl(rpc)
Example #4
0
 def rpc_get_config(self, session, rpc, source_elm, filter_or_none):  # pylint: disable=W0613
     """Passed the source element"""
     raise ncerror.RPCSvrErrNotImpl(rpc)
Example #5
0
 def rpc_get(self, session, rpc, filter_or_none):  # pylint: disable=W0613
     """Passed the filter element or None if not present"""
     raise ncerror.RPCSvrErrNotImpl(rpc)
Example #6
0
    def reader_handle_message(self, msg):
        """Handle a message, lock is already held"""
        print('stpe 1')
        print(msg)
        if not self.session_open:
            return

        # Any error with XML encoding here is going to cause a session close
        # Technically we should be able to return malformed message I think.
        try:
            tree = etree.parse(io.BytesIO(msg.encode('utf-8')))
            print('step 1.5')
            print(etree.tostring(tree, pretty_print=True))
            if not tree:
                raise ncerror.SessionError(msg, "Invalid XML from client.")
        except etree.XMLSyntaxError:
            logger.warning("Closing session due to malformed message")
            raise ncerror.SessionError(msg, "Invalid XML from client.")

        rpcs = tree.xpath("/nc:rpc", namespaces=NSMAP)
        print('step 2')
        print(rpcs)
        if not rpcs:
            raise ncerror.SessionError(msg, "No rpc found")

        for rpc in rpcs:
            try:
                msg_id = rpc.get('message-id')
                print('step 3')
                print(msg_id)
                if self.debug:
                    logger.debug("%s: Received rpc message-id: %s", str(self),
                                 msg_id)
            except (TypeError, ValueError):
                raise ncerror.SessionError(
                    msg, "No valid message-id attribute found")

            try:
                # Get the first child of rpc as the method name
                rpc_method = rpc.getchildren()
                print('step 4')
                print(rpc_method)

                if len(rpc_method) != 1:
                    if self.debug:
                        logger.debug("%s: Bad Msg: msg-id: %s", str(self),
                                     msg_id)
                    raise ncerror.RPCSvrErrBadMsg(rpc)
                rpc_method = rpc_method[0]
                print('step 5')
                print(rpc_method)

                rpcname = rpc_method.tag.replace(qmap('nc'), "")
                print('stpe 6')
                print(rpcname)
                params = rpc_method.getchildren()
                print('stpe 7')
                print(params)
                paramslen = len(params)

                if self.debug:
                    logger.debug("%s: RPC: %s: paramslen: %s", str(self),
                                 rpcname, str(paramslen))

                if rpcname == "close-session":
                    # XXX should be RPC-unlocking if need be
                    if self.debug:
                        logger.debug("%s: Received close-session msg-id: %s",
                                     str(self), msg_id)
                    self.send_rpc_reply(etree.Element("ok"), rpc)
                    self.close()
                    # XXX should we also call the user method if it exists?
                    return
                elif rpcname == "kill-session":
                    # XXX we are supposed to cleanly abort anything underway
                    if self.debug:
                        logger.debug("%s: Received kill-session msg-id: %s",
                                     str(self), msg_id)
                    self.send_rpc_reply(etree.Element("ok"), rpc)
                    self.close()
                    # XXX should we also call the user method if it exists?
                    return
                elif rpcname == "get":
                    # Validate GET parameters

                    if paramslen > 1:
                        # XXX need to specify all elements not known
                        raise ncerror.RPCSvrErrBadMsg(rpc)
                    if params and not util.filter_tag_match(
                            params[0], "nc:filter"):
                        raise ncerror.RPCSvrUnknownElement(rpc, params[0])
                    if not params:
                        params = [None]
                elif rpcname == "get-config":
                    # Validate GET-CONFIG parameters

                    # XXX verify that the source parameter is present
                    if paramslen > 2:
                        # XXX need to specify all elements not known
                        raise ncerror.RPCSvrErrBadMsg(rpc)
                    source_param = rpc_method.find("nc:source",
                                                   namespaces=NSMAP)
                    if source_param is None:
                        raise ncerror.RPCSvrMissingElement(
                            rpc, util.elm("nc:source"))
                    filter_param = None
                    if paramslen == 2:
                        filter_param = rpc_method.find("nc:filter",
                                                       namespaces=NSMAP)
                        if filter_param is None:
                            unknown_elm = params[
                                0] if params[0] != source_param else params[1]
                            raise ncerror.RPCSvrUnknownElement(
                                rpc, unknown_elm)
                    params = [source_param, filter_param]

                #------------------
                # Call the method.
                #------------------

                try:
                    # Handle any namespaces or prefixes in the tag, other than
                    # "nc" which was removed above. Of course, this does not handle
                    # namespace collisions, but that seems reasonable for now.
                    rpcname = rpcname.rpartition("}")[-1]
                    print('step 8')
                    print(rpcname)
                    method_name = "rpc_" + rpcname.replace('-', '_')
                    method = getattr(self.methods, method_name,
                                     self._rpc_not_implemented)
                    if self.debug:
                        logger.debug("%s: Calling method: %s", str(self),
                                     method_name)
                    reply = method(self, rpc, *params)
                    print('stpe 9')
                    print(reply)
                    self.send_rpc_reply(reply, rpc)
                except NotImplementedError:
                    raise ncerror.RPCSvrErrNotImpl(rpc)
            except ncerror.RPCSvrErrBadMsg as msgerr:
                if self.new_framing:
                    if self.debug:
                        logger.debug("%s: RPCSvrErrBadMsg: %s", str(self),
                                     str(msgerr))
                    self.send_message(msgerr.get_reply_msg())
                else:
                    # If we are 1.0 we have to simply close the connection
                    # as we are not allowed to send this error
                    logger.warning(
                        "Closing 1.0 session due to malformed message")
                    raise ncerror.SessionError(msg, "Malformed message")
            except ncerror.RPCServerError as error:
                if self.debug:
                    logger.debug("%s: RPCServerError: %s", str(self),
                                 str(error))
                self.send_message(error.get_reply_msg())
            except EOFError:
                if self.debug:
                    logger.debug("%s: Got EOF in reader_handle_message",
                                 str(self))
                error = ncerror.RPCSvrException(rpc, EOFError("EOF"))
                self.send_message(error.get_reply_msg())
            except EOFError:
                if self.debug:
                    logger.debug("Got EOF in reader_handle_message")
            except Exception as exception:
                if self.debug:
                    logger.debug(
                        "%s: Got unexpected exception in reader_handle_message: %s",
                        str(self), str(exception))
                error = ncerror.RPCSvrException(rpc, exception)
                self.send_message(error.get_reply_msg())
Example #7
0
 def _rpc_not_implemented(self, unused_session, rpc, *unused_params):
     if self.debug:
         msg_id = rpc.get('message-id')
         logger.debug("%s: Not Impl msg-id: %s", str(self), msg_id)
     raise ncerror.RPCSvrErrNotImpl(rpc)
 def rpc_create_subscription(self, unused_session, rpc, *unused_params):
     raise ncerror.RPCSvrErrNotImpl(rpc)