Pitfalls to avoid ################# These are corner cases which should not happen in the common usages, but if they do, what happens may be very confusing. Here are some tips. When my application exits uncleanly, it still appears to be online to other resources ===================================================================================== Congratulations! You are using a server with support for :xep:`Stream Management <198>`. As you might know, :mod:`aioxmpp` transparently and automatically uses Stream Management whenever it is available. This means that :class:`aioxmpp.Client` instances must *always* be :meth:`aioxmpp.Client.stop`\ -ed properly, so that the stream can be shut down to prevent it from lingering on the server side. The preferred way to do this is to use the :meth:`aioxmpp.Client.connected` :term:`asynchronous context manager`: .. code-block:: python client = aioxmpp.Client() with client.connected() as stream: # stream is the aioxmpp.stream.StanzaStream of the client # do something When the context manager is left (either with an exception or normally), the connection is closed cleanly. If the context manager cannot be used, other means to ensure that :meth:`aioxmpp.Client.stop` is called and the client is given enough time to shut the connection down cleanly need to be applied. This can be done in the following manner: .. code-block:: python if client.running: fut = asyncio.Future() client.on_stopped.connect(fut, client.on_stopped.AUTO_FUTURE) client.on_failure.connect(fut, client.on_failure.AUTO_FUTURE) try: yield from fut except: # we are shutting down, ignore any exceptions from on_failure pass Ensure that this snippet is executed before the application exits, even in the case that an error occurred. .. note:: You may be asking "But why is the Connection Reset by Peer the server must be getting after my application crashed not enough?". The whole reason for Stream Management is to make it possible for the server to ignore such errors which may very well occur if network connectivity is briefly interrupted (for example when switching between networks, or your ISP has a power failure, or you reboot your modem or something like that). Stream Management allows to resume an uncleanly closed stream up to a certain timeout (as (possibly dynamically) determined by the server). Making errors such as Connection Reset by Peer break such a stream would defeat the purpose of Stream Management. .. note:: As of version 0.9, you can disable the resumption capaibility of Stream Management using the :attr:`.Client.resumption_timeout` attribute. However, that alone is no guarantee that sessions die quickly; it still depends a lot on the way in which the network connection got interrupted and whether or not the server is sending data to the (disconnected) client. There are other timeouts, such as the ones from TCP, at play here which need to be tweaked properly on the server-side. How to do so is out of scope for aioxmpp. (If you happen to find a client-side way, e.g. in another XMPP library, to achieve the behaviour of letting the session die quickly in case of a hard disconnect (e.g. a pulled cable), let me know. I’m quite convinced that this is impossible, so I’d like to be proven wrong.) I am trying to connect to a bare IP and I get a DNS error ========================================================= For example, when trying to connect to ``192.168.122.1``, you may see:: Traceback (most recent call last): File "/home/horazont/aioxmpp/aioxmpp/network.py", line 272, in repeated_query raise_on_no_answer=False File "/usr/lib/python3.4/asyncio/futures.py", line 388, in __iter__ yield self # This tells Task to wait for completion. File "/usr/lib/python3.4/asyncio/tasks.py", line 286, in _wakeup value = future.result() File "/usr/lib/python3.4/asyncio/futures.py", line 277, in result raise self._exception File "/usr/lib/python3.4/concurrent/futures/thread.py", line 54, in run result = self.fn(*self.args, **self.kwargs) File "/home/horazont/.local/lib/python3.4/site-packages/dns/resolver.py", line 1051, in query raise NXDOMAIN(qnames=qnames_to_try, responses=nxdomain_responses) dns.resolver.NXDOMAIN: None of DNS query names exist: _xmpp-client._tcp.192.168.122.1., _xmpp-client._tcp.192.168.122.1. During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/home/horazont/aioxmpp/aioxmpp/node.py", line 710, in _on_main_done task.result() File "/usr/lib/python3.4/asyncio/futures.py", line 277, in result raise self._exception File "/usr/lib/python3.4/asyncio/tasks.py", line 233, in _step result = coro.throw(exc) File "/home/horazont/aioxmpp/aioxmpp/node.py", line 868, in _main yield from self._main_impl() File "/home/horazont/aioxmpp/aioxmpp/node.py", line 830, in _main_impl logger=self.logger) File "/home/horazont/aioxmpp/aioxmpp/node.py", line 337, in connect_xmlstream logger=logger, File "/home/horazont/aioxmpp/aioxmpp/node.py", line 142, in discover_connectors "xmpp-client", File "/home/horazont/aioxmpp/aioxmpp/network.py", line 318, in lookup_srv **kwargs) File "/home/horazont/aioxmpp/aioxmpp/network.py", line 280, in repeated_query "nameserver error, most likely DNSSEC validation failed", aioxmpp.network.ValidationError: nameserver error, most likely DNSSEC validation failed You should be using :attr:`aioxmpp.Client.override_peer` or an equivalent mechanism. Note that the exception will still occur if the connection attempt to the override fails. Bare IPs as target hosts are generally not a good idea.