summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormathieui <mathieui@mathieui.net>2021-04-08 18:25:24 +0200
committermathieui <mathieui@mathieui.net>2021-04-08 18:47:51 +0200
commit3e5943f458d50b585b9e8dacd60b641d44db7856 (patch)
tree4f20225a48e93a96acf2a613bd7b57eb6c2d05f1
parent7ddcc3428fbc48814da301ce7cba9b1f855a0fa9 (diff)
downloadslixmpp-3e5943f458d50b585b9e8dacd60b641d44db7856.tar.gz
slixmpp-3e5943f458d50b585b9e8dacd60b641d44db7856.tar.bz2
slixmpp-3e5943f458d50b585b9e8dacd60b641d44db7856.tar.xz
slixmpp-3e5943f458d50b585b9e8dacd60b641d44db7856.zip
xmlstream: do not allow stanzas outside a session
except for the bind, obviously
-rw-r--r--slixmpp/test/slixtest.py1
-rw-r--r--slixmpp/xmlstream/xmlstream.py31
2 files changed, 32 insertions, 0 deletions
diff --git a/slixmpp/test/slixtest.py b/slixmpp/test/slixtest.py
index 64d60d8d..7c700fd2 100644
--- a/slixmpp/test/slixtest.py
+++ b/slixmpp/test/slixtest.py
@@ -334,6 +334,7 @@ class SlixTest(unittest.TestCase):
plugin_config=plugin_config)
else:
raise ValueError("Unknown XMPP connection mode.")
+ self.xmpp._always_send_everything = True
self.xmpp.connection_made(TestTransport(self.xmpp))
self.xmpp.session_bind_event.set()
diff --git a/slixmpp/xmlstream/xmlstream.py b/slixmpp/xmlstream/xmlstream.py
index 02f4598c..e0f85008 100644
--- a/slixmpp/xmlstream/xmlstream.py
+++ b/slixmpp/xmlstream/xmlstream.py
@@ -223,11 +223,20 @@ class XMLStream(asyncio.BaseProtocol):
#: An asyncio Future being done when the stream is disconnected.
self.disconnected: Future = Future()
+ # If the session has been started or not
+ self._session_started = False
+ # If we want to bypass the send() check (e.g. unit tests)
+ self._always_send_everything = False
+
self.add_event_handler('disconnected', self._remove_schedules)
+ self.add_event_handler('disconnected', self._set_disconnected)
self.add_event_handler('session_start', self._start_keepalive)
+ self.add_event_handler('session_start', self._set_session_start)
+ self.add_event_handler('session_resumed', self._set_session_start)
self._run_out_filters: Optional[Future] = None
self.__slow_tasks: List[Future] = []
+ self.__queued_stanzas: List[Tuple[StanzaBase, bool]] = []
@property
def loop(self):
@@ -248,6 +257,17 @@ class XMLStream(asyncio.BaseProtocol):
"""
return uuid.uuid4().hex
+ def _set_session_start(self, event):
+ """
+ On session start, queue all pending stanzas to be sent.
+ """
+ self._session_started = True
+ for stanza in self.__queued_stanzas:
+ self.waiting_queue.put_nowait(stanza)
+
+ def _set_disconnected(self, event):
+ self._session_started = False
+
def _set_disconnected_future(self):
"""Set the self.disconnected future on disconnect"""
if not self.disconnected.done():
@@ -1115,6 +1135,17 @@ class XMLStream(asyncio.BaseProtocol):
filters is useful when resending stanzas.
Defaults to ``True``.
"""
+ # When not connected, allow features/starttls/etc to go through
+ # but not stanzas or arbitrary payloads.
+ if not self._always_send_everything and not self._session_started:
+ # Avoid circular imports
+ from slixmpp.stanza.rootstanza import RootStanza
+ from slixmpp.stanza import Iq
+ is_bind = isinstance(data, Iq) and data.get_plugin('bind', check=True)
+ if isinstance(data, (RootStanza, str)) and not is_bind:
+ self.__queued_stanzas.append(data)
+ log.debug('NOT SENT: %s %s', type(data), data)
+ return
self.waiting_queue.put_nowait((data, use_filters))
def send_xml(self, data):