3

I have an application which shall send xmpp messages. Those occasions are rare (sometimes none for days) but then again maybe coming in bunches. I have no use of receiving anything, I just want to send. The straight-forward approach runs into undetected timeouts. The last send() does not take place (receiver does not get anything) but returns without reporting the problem (returns a simple id as if everything worked fine). Only the next call to send() then raises an IOError('Disconnected from server.').

I could do a constant disconnect/reconnect for each message but I don't like this because sometimes this will disconnect and reconnect very often (and I don't know if servers appreciate on this multiple times in a second).

I could try the approach given as answer in this question here, but I do not really have a need for receiving the XMPP replies.

Question: Is there a simple way to detect the connection timeout before or after sending without trying to send a second message (which would spam the receiver in case everything worked fine)?

My straight-forward-approach:

import xmpp

def connectXmppClient(fromJidName, password):
  fromJid = xmpp.protocol.JID(fromJidName)
  xmppClient = xmpp.Client(fromJid.getDomain(), debug=[])
  connection = xmppClient.connect()
  if not connection:
    raise Exception("could not setup connection", fromJid)
  authentication = xmppClient.auth(
    fromJid.getNode(), password, resource=fromJid.getResource())
  if not authentication:
    raise Exception("could not authenticate")
  return xmppClient

def sendXmppMessage(xmppClient, toJidName, text):
  return xmppClient.send(xmpp.protocol.Message(toJidName, text))

if __name__ == '__main__':
  import sys, os, time, getpass
  if len(sys.argv) < 2:
    print "Syntax: xsend fromJID toJID"
    sys.exit(0)
  fromJidName = sys.argv[1]
  toJidName = sys.argv[2]
  password = getpass.getpass()
  xmppClient = connectXmppClient(fromJidName, password)
  while True:
    line = sys.stdin.readline()
    if not line:
      break
    print xmppClient.isConnected()
    id = sendXmppMessage(xmppClient, toJidName, line)
    print id
Community
  • 1
  • 1
Alfe
  • 56,346
  • 20
  • 107
  • 159
  • Why don't you put your `xmppClient.send` in `try: catch:`? You could just check the type of the exception. If it is an `IOError` then call your `connectXmppClient` again. – Jermin Bazazian Apr 29 '12 at 16:09
  • I've got a try/catch in place. But as I wrote: The IOError does not occur in the first call. Only the next (which can be hours later) throws the exception I can catch. That's not good. I'd rather (of course) notice the connection breakdown on sending the first message, so I can quickly re-establish the connection and re-try to send that first message. – Alfe May 02 '12 at 16:10

1 Answers1

1

You need to register a disconnect handler using xmppClient.RegisterDisconnectHandler(). This lets you specify a function that will get called upon a disconnect.

Karl Bielefeldt
  • 47,314
  • 10
  • 60
  • 94
  • That disconnection handler (when registered using your way) gets not called upon sending the first message, sorry :-( It gets called later, though, when I try to send the second message. But then an exception is thrown anyway and I can react on that. Thanks for your hint nevertheless, but I will have to go the long way and also receive messages from the server I guess. – Alfe May 02 '12 at 16:12
  • Implemented receiving. Let's see whether this solves my silent-logout issue. – Alfe May 03 '12 at 15:36