Beispiel #1
0
class XMPPClient(object):
    def __init__(self):
        self.jid = JID(config.get('im', 'account'))
        self.jid.setResource('xtunnel')
        self.password = config.get('im', 'password')
        self.debug = config.get('config', 'debug') == 'true'

        self.status = 'Internal %s %s' % (tap.ip, tap.mac)
        if config.has_option('im', 'ip'):
            eip = config.get('im', 'ip')
            eport = int(config.get('im', 'port'))
            self.status = 'External %s %s %s %s' % (tap.ip, tap.mac, eip,
                                                    eport)

        self.reconnect()

    def connect(self):
        if not self.client.connect():
            print 'Failed to connect to the XMPP server.\nExiting...'
            return False

        auth = self.client.auth(self.jid.getNode(), self.password,
                                self.jid.getResource())
        if not auth:
            print 'Failed to authenticate you.\nExiting...'
            return False

        self.client.RegisterHandler('message', self.handle_message)
        self.client.RegisterHandler('presence', self.handle_presence)
        self.client.send(Presence(status=self.status))

        return True

    def handle_presence(self, dispatcher, presence):
        type_ = presence.getType()
        jid = presence.getFrom()

        # When I login to the gtalk server, I have set my resource name to
        # 'xtunnel'.  But when I get the presence information, the server
        # will add some random characters after the resource string.
        # Following lines is to deal with this situation.
        if not jid.getResource().startswith('xtunnel'):
            return
        jid.setResource('xtunnel')

        if jid == self.jid:
            return  # TODO google kick me out?

        if type_ is None:  # available
            if presence.getStatus():
                info = presence.getStatus().split()
                if len(info) == 3 and info[0] == 'Internal':
                    [ip, mac] = info[1:]
                    host = Host(jid, ip, mac)
                    hosts.add_host(host)
                elif len(info) == 5 and info[0] == 'External':
                    [ip, mac, eip, eport] = info[1:]
                    if self.status.startswith('External') and tap.mac > mac:
                        host = Host(jid, ip, mac)
                    else:
                        host = Host(jid, ip, mac, eip, int(eport))
                    hosts.add_host(host)
        elif type_ == 'unavailable':
            hosts.remove_host(jid)

    def handle_message(self, dispatcher, message):
        if message.getType() != 'normal':
            return
        tap.write(base64.b64decode(message.getBody()))

    def read(self):
        try:
            self.client.Process()
        except:
            self.reconnect()

    def send_frame(self, jid, frame):
        message = base64.b64encode(repr(frame))
        try:
            self.client.send(Message(to=jid, typ='normal', body=message))
        except:
            self.reconnect()

    def fileno(self):
        return self.client.Connection._sock.fileno()

    def reconnect(self):
        try:
            time.sleep(7)
            self.client.disconnect()
        except:
            pass

        if self.debug:
            self.client = Client(self.jid.getDomain())
        else:
            self.client = Client(self.jid.getDomain(), debug=[])

        try:
            if not self.connect():
                self.reconnect()
        except:
            self.reconnect()