Reputation: 1325
so... I have a simple chat client like so:
class ChatClient(sleekxmpp.ClientXMPP):
def __init__(self, jid, password, server):
sleekxmpp.ClientXMPP.__init__(self, jid, password, ssl=True)
self.add_event_handler("session_start", self.start)
self.register_plugin('xep_0030')
self.register_plugin('xep_0004')
self.register_plugin('xep_0060')
self.register_plugin('xep_0199')
self.ssl_version = ssl.PROTOCOL_SSLv3
self.connected = self.connect()
if self.connected:
self.process(threaded=True)
def start(self, event):
self.send_presence(priority = "-9001")
self.get_roster(blocking = True, timeout = 3)
def message(self, targets, msg):
for target in targets:
self.send_message(target, msg)
and I have an "verify" function to make sure you input your username/pass right:
def authenticate(username, password, server):
xmppuser = username + '@' + server
passTester = ChatClient(xmppuser, password)
passTester.disconnect(wait = True)
authenticated = passTester.authenticated
return authenticated
Now, the problem comes in where I have the chat client as threaded, I run into the situation where I try to check ChatClient.authenticated before the server had a chance to actually connect. As you can see, I tried to "wait" on the disconnect but there's nothing in the send queue so it disconnects right away.
An alternate I tried is this:
def authenticate(username, password, server):
xmppuser = username + '@' + server
passTester = ChatClient(xmppuser, password)
passTester.message('bogusName', 'ladfhkjdglkhjdfg')
passTester.disconnect(wait = True)
authenticated = passTester.authenticated
return authenticated
Now that I sent a bogus message the disconnect call has something to wait for. when I input a correct username/pass with this code, the disconnect waits for a message to get sent (which involves waiting for a real connection), sends nothing and ChatClient.authenticated is set to True!
Unfortunately, when I input a wrong username/pass the message never gets sent and the disconnect(wait=True) never disconnects as the message never gets sent.
Does anyone else have a more proper way to "authenticate"?
Upvotes: 0
Views: 2032
Reputation:
This would be a good reason for changing the .authenticated
and related fields to be threading.Event
objects so that you could use wait()
for situations like this, but I'm not sure how much that would break existing user code.
But short of modifying SleekXMPP, what you will need to do is wait for certain events to fire. For example, if your client successfully authenticated, then there will be a session_start
event (I may add an auth_success
or similar event later). Likewise, if authentication failed for a single mechanism, there will be a failed_auth
event. If no authentication methods at all succeeded (which is what you'd be interested in), there will be a no_auth
event.
So you can add handlers for these events, and have those handlers place a token in a queue, and then wait for the desired token to arrive.
class ChatClient(ClientXMPP):
def __init__(self, ...):
...
self.auth_queue = queue.Queue()
self.add_event_handler('no_auth', self.failed)
def start(self, event):
self.auth_queue.put('success')
...
def failed(self, event):
self.auth_queue.put('failed')
def authenticate(username, password, server):
xmppuser = username + '@' + server
passTester = ChatClient(xmppuser, password)
try:
result = passTester.auth_queue.get(timeout=10)
except queue.Empty:
result = 'failed'
passTester.disconnect()
return result == 'success'
Don't forget that we also have the chat room at [email protected].
-- Lance
Upvotes: 3