Unverified Commit 2fbcf384 authored by Maxime Buquet's avatar Maxime Buquet
Browse files

ibr: DO NOT COMMIT: make the example work



This will have the example create an account via IBR, bind on the same
stream and then disconnect.

The hacky bits here are about event handling, and also about how XMPP
features are handled.

At the moment, we need to register the IBR plugin before we register
stream features, otherwise slixmpp will attempt to bind before even
considering IBR.

We also have to make slixmpp wait that the registration is finished and
not hand over the processing to other handlers, which causes it to fail
horribly (attempt bind while doing registration, etc.).

Signed-off-by: Maxime Buquet's avatarMaxime “pep” Buquet <pep@bouah.net>
parent 8854e1b9
......@@ -87,9 +87,6 @@ class RegisterBot(slixmpp.ClientXMPP):
iq['register']['fields']
"""
# TODO: Reply with requested fields
await iq
username = self.boundjid.user
password = self.password
......@@ -107,16 +104,6 @@ class RegisterBot(slixmpp.ClientXMPP):
e.iq['error']['text'])
except IqTimeout:
logging.error("No response from server.")
finally:
self.del_event_handler('register', self.register)
self.register_plugin('feature_bind')
self.register_plugin('feature_session')
self.register_plugin('feature_rosterver')
self.register_plugin('feature_preapproval')
self.register_plugin('feature_mechanisms')
self.reconnect()
if __name__ == '__main__':
......
......@@ -127,15 +127,17 @@ class ClientXMPP(BaseXMPP):
# Setup default stream features
self.register_plugin('feature_starttls')
if not ibr_registration:
self.register_plugin('feature_bind')
self.register_plugin('feature_session')
self.register_plugin('feature_rosterver')
self.register_plugin('feature_preapproval')
self.register_plugin('feature_mechanisms')
if sasl_mech:
self['feature_mechanisms'].use_mech = sasl_mech
if ibr_registration:
self.register_plugin('xep_0077')
self.register_plugin('feature_bind')
self.register_plugin('feature_session')
self.register_plugin('feature_rosterver')
self.register_plugin('feature_preapproval')
self.register_plugin('feature_mechanisms')
if sasl_mech:
self['feature_mechanisms'].use_mech = sasl_mech
@property
def password(self):
......
......@@ -31,7 +31,8 @@ class XEP_0077(BasePlugin):
default_config = {
'create_account': True,
'force_registration': False,
'order': 50
'order': 50,
'restart_if_successful': True,
}
def plugin_init(self):
......@@ -70,15 +71,16 @@ class XEP_0077(BasePlugin):
self.xmpp.del_filter('in', self._force_stream_feature)
return stanza
def _handle_register_feature(self, features):
async def _handle_register_feature(self, features):
if 'mechanisms' in self.xmpp.features:
# We have already logged in with an account
return False
if self.create_account and self.xmpp.event_handled('register'):
form = self.get_registration()
self.xmpp.event('register', form)
return True
form = await self.get_registration()
await self.xmpp.event_async('register', form)
# TODO: Use the config value instead.
# return self.restart_if_successful
return False
def get_registration(self, jid=None, ifrom=None,
......
......@@ -761,6 +761,48 @@ class XMLStream(asyncio.BaseProtocol):
"""
return len(self.__event_handlers.get(name, []))
async def event_async(self, name, data={}):
"""Manually trigger a custom event.
:param name: The name of the event to trigger.
:param data: Data that will be passed to each event handler.
Defaults to an empty dictionary, but is usually
a stanza object.
"""
log.debug("Event async triggered: %s", name)
handlers = self.__event_handlers.get(name, [])
for handler in handlers:
handler_callback, disposable = handler
old_exception = getattr(data, 'exception', None)
# If the callback is a coroutine, schedule it instead of
# running it directly
if asyncio.iscoroutinefunction(handler_callback):
try:
await handler_callback(data)
except Exception as e:
if old_exception:
old_exception(e)
else:
self.exception(e)
else:
try:
handler_callback(data)
except Exception as e:
if old_exception:
old_exception(e)
else:
self.exception(e)
if disposable:
# If the handler is disposable, we will go ahead and
# remove it now instead of waiting for it to be
# processed in the queue.
try:
self.__event_handlers[name].remove(handler)
except ValueError:
pass
def event(self, name, data={}):
"""Manually trigger a custom event.
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment