Exemple #1
0
    def data_received(self, data):
        """Called when incoming data is received on the socket.

        We feed that data to the parser and the see if this produced any XML
        event.  This could trigger one or more event (a stanza is received,
        the stream is opened, etc).
        """
        self.parser.feed(data)
        for event, xml in self.parser.read_events():
            if event == 'start':
                if self.xml_depth == 0:
                    # We have received the start of the root element.
                    self.xml_root = xml
                    log.debug('RECV: %s', highlight(tostring(self.xml_root, xmlns=self.default_ns,
                                                         stream=self,
                                                         top_level=True,
                                                         open_only=True)))
                    self.start_stream_handler(self.xml_root)
                self.xml_depth += 1
            if event == 'end':
                self.xml_depth -= 1
                if self.xml_depth == 0:
                    # The stream's root element has closed,
                    # terminating the stream.
                    log.debug("End of stream received")
                    self.abort()
                elif self.xml_depth == 1:
                    # A stanza is an XML element that is a direct child of
                    # the root element, hence the check of depth == 1
                    self.loop.idle_call(functools.partial(self.__spawn_event, xml))
                    if self.xml_root is not None:
                        # Keep the root element empty of children to
                        # save on memory use.
                        self.xml_root.clear()
Exemple #2
0
    def send_raw(self, data):
        """Send raw data across the stream.

        :param string data: Any bytes or utf-8 string value.
        """
        log.debug("SEND: %s", highlight(data))
        if not self.transport:
            raise NotConnectedError()
        if isinstance(data, str):
            data = data.encode('utf-8')
        self.transport.write(data)
Exemple #3
0
    def data_received(self, data):
        """Called when incoming data is received on the socket.

        We feed that data to the parser and the see if this produced any XML
        event.  This could trigger one or more event (a stanza is received,
        the stream is opened, etc).
        """
        if self.parser is None:
            log.warning(
                'Received data before the connection is established: %r', data)
            return
        self.parser.feed(data)
        try:
            for event, xml in self.parser.read_events():
                if event == 'start':
                    if self.xml_depth == 0:
                        # We have received the start of the root element.
                        self.xml_root = xml
                        log.debug(
                            'RECV: %s',
                            highlight(
                                tostring(self.xml_root,
                                         xmlns=self.default_ns,
                                         stream=self,
                                         top_level=True,
                                         open_only=True)))
                        self.start_stream_handler(self.xml_root)
                    self.xml_depth += 1
                if event == 'end':
                    self.xml_depth -= 1
                    if self.xml_depth == 0:
                        # The stream's root element has closed,
                        # terminating the stream.
                        log.debug("End of stream received")
                        self.abort()
                    elif self.xml_depth == 1:
                        # A stanza is an XML element that is a direct child of
                        # the root element, hence the check of depth == 1
                        self._spawn_event(xml)
                        if self.xml_root is not None:
                            # Keep the root element empty of children to
                            # save on memory use.
                            self.xml_root.clear()
        except ET.ParseError:
            log.error('Parse error: %r', data)

            # Due to cyclic dependencies, this can’t be imported at the module
            # level.
            from slixmpp.stanza.stream_error import StreamError
            error = StreamError()
            error['condition'] = 'not-well-formed'
            error['text'] = 'Server sent: %r' % data
            self.send(error)
            self.disconnect()
Exemple #4
0
    def __spawn_event(self, xml):
        """
        Analyze incoming XML stanzas and convert them into stanza
        objects if applicable and queue stream events to be processed
        by matching handlers.

        :param xml: The :class:`~slixmpp.xmlstream.stanzabase.ElementBase`
                    stanza to analyze.
        """
        # Apply any preprocessing filters.
        xml = self.incoming_filter(xml)

        # Convert the raw XML object into a stanza object. If no registered
        # stanza type applies, a generic StanzaBase stanza will be used.
        stanza = self._build_stanza(xml)
        for filter in self.__filters['in']:
            if stanza is not None:
                stanza = filter(stanza)
        if stanza is None:
            return

        log.debug("RECV: %s", highlight(stanza))

        # Match the stanza against registered handlers. Handlers marked
        # to run "in stream" will be executed immediately; the rest will
        # be queued.
        handled = False
        matched_handlers = [h for h in self.__handlers if h.match(stanza)]
        for handler in matched_handlers:
            handler.prerun(stanza)
            try:
                handler.run(stanza)
            except Exception as e:
                stanza.exception(e)
            if handler.check_delete():
                self.__handlers.remove(handler)
            handled = True

        # Some stanzas require responses, such as Iq queries. A default
        # handler will be executed immediately for this case.
        if not handled:
            stanza.unhandled()