Philipp Hörist pushed to branch master at gajim / gajim
Commits:
4 changed files:
- gajim/common/client.py
- − gajim/common/connection.py
- gajim/common/connection_handlers_events.py
- gajim/common/zeroconf/connection_zeroconf.py
Changes:
| ... | ... | @@ -44,8 +44,6 @@ |
| 44 | 44 |
from gajim.common.idle import Monitor
|
| 45 | 45 |
from gajim.common.i18n import _
|
| 46 | 46 |
|
| 47 |
-from gajim.common.connection_handlers_events import MessageSentEvent
|
|
| 48 |
- |
|
| 49 | 47 |
from gajim.gui.util import open_window
|
| 50 | 48 |
|
| 51 | 49 |
|
| ... | ... | @@ -507,7 +505,7 @@ def _send_message(self, message): |
| 507 | 505 |
message.message_id = self.send_stanza(message.stanza)
|
| 508 | 506 |
|
| 509 | 507 |
app.nec.push_incoming_event(
|
| 510 |
- MessageSentEvent(None, jid=message.jid, **vars(message)))
|
|
| 508 |
+ NetworkEvent('message-sent', jid=message.jid, **vars(message)))
|
|
| 511 | 509 |
|
| 512 | 510 |
if message.is_groupchat:
|
| 513 | 511 |
return
|
| 1 |
-# Copyright (C) 2003-2005 Vincent Hanquez <tab AT snarc.org>
|
|
| 2 |
-# Copyright (C) 2003-2014 Yann Leboulanger <asterix AT lagaule.org>
|
|
| 3 |
-# Copyright (C) 2005 Alex Mauer <hawke AT hawkesnest.net>
|
|
| 4 |
-# Stéphan Kochen <stephan AT kochen.nl>
|
|
| 5 |
-# Copyright (C) 2005-2006 Dimitur Kirov <dkirov AT gmail.com>
|
|
| 6 |
-# Travis Shirk <travis AT pobox.com>
|
|
| 7 |
-# Nikos Kouremenos <kourem AT gmail.com>
|
|
| 8 |
-# Copyright (C) 2006 Junglecow J <junglecow AT gmail.com>
|
|
| 9 |
-# Stefan Bethge <stefan AT lanpartei.de>
|
|
| 10 |
-# Copyright (C) 2006-2008 Jean-Marie Traissard <jim AT lapin.org>
|
|
| 11 |
-# Copyright (C) 2007 Tomasz Melcer <liori AT exroot.org>
|
|
| 12 |
-# Julien Pivotto <roidelapluie AT gmail.com>
|
|
| 13 |
-# Copyright (C) 2007-2008 Stephan Erb <steve-e AT h3c.de>
|
|
| 14 |
-# Copyright (C) 2008 Brendan Taylor <whateley AT gmail.com>
|
|
| 15 |
-# Jonathan Schleifer <js-gajim AT webkeks.org>
|
|
| 16 |
-#
|
|
| 17 |
-# This file is part of Gajim.
|
|
| 18 |
-#
|
|
| 19 |
-# Gajim is free software; you can redistribute it and/or modify
|
|
| 20 |
-# it under the terms of the GNU General Public License as published
|
|
| 21 |
-# by the Free Software Foundation; version 3 only.
|
|
| 22 |
-#
|
|
| 23 |
-# Gajim is distributed in the hope that it will be useful,
|
|
| 24 |
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
| 25 |
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
| 26 |
-# GNU General Public License for more details.
|
|
| 27 |
-#
|
|
| 28 |
-# You should have received a copy of the GNU General Public License
|
|
| 29 |
-# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
|
| 30 |
- |
|
| 31 |
-import time
|
|
| 32 |
-import logging
|
|
| 33 |
- |
|
| 34 |
-from gajim.common import helpers
|
|
| 35 |
-from gajim.common import app
|
|
| 36 |
-from gajim.common import idle
|
|
| 37 |
-from gajim.common import modules
|
|
| 38 |
-from gajim.common.nec import NetworkEvent
|
|
| 39 |
-from gajim.common.const import ClientState
|
|
| 40 |
- |
|
| 41 |
- |
|
| 42 |
-log = logging.getLogger('gajim.c.connection')
|
|
| 43 |
- |
|
| 44 |
-SERVICE_START_TLS = 'xmpp-client'
|
|
| 45 |
-SERVICE_DIRECT_TLS = 'xmpps-client'
|
|
| 46 |
- |
|
| 47 |
-class CommonConnection:
|
|
| 48 |
- """
|
|
| 49 |
- Common connection class, can be derived for normal connection or zeroconf
|
|
| 50 |
- connection
|
|
| 51 |
- """
|
|
| 52 |
- |
|
| 53 |
- def __init__(self, name):
|
|
| 54 |
- self.name = name
|
|
| 55 |
- self._modules = {}
|
|
| 56 |
- self.connection = None # xmpppy ClientCommon instance
|
|
| 57 |
- self.is_zeroconf = False
|
|
| 58 |
- self.password = None
|
|
| 59 |
- self.server_resource = helpers.get_resource(self.name)
|
|
| 60 |
- self.priority = app.get_priority(name, 'offline')
|
|
| 61 |
- self.time_to_reconnect = None
|
|
| 62 |
- self._reconnect_timer_source = None
|
|
| 63 |
- |
|
| 64 |
- self._state = ClientState.DISCONNECTED
|
|
| 65 |
- self._status = 'offline'
|
|
| 66 |
- self._status_message = ''
|
|
| 67 |
- |
|
| 68 |
- # If handlers have been registered
|
|
| 69 |
- self.handlers_registered = False
|
|
| 70 |
- |
|
| 71 |
- self.pep = {}
|
|
| 72 |
- |
|
| 73 |
- self.roster_supported = True
|
|
| 74 |
- |
|
| 75 |
- self._stun_servers = [] # STUN servers of our jabber server
|
|
| 76 |
- |
|
| 77 |
- # Tracks the calls of the connect_machine() method
|
|
| 78 |
- self._connect_machine_calls = 0
|
|
| 79 |
- |
|
| 80 |
- self.get_config_values_or_default()
|
|
| 81 |
- |
|
| 82 |
- def _set_state(self, state):
|
|
| 83 |
- log.info('State: %s', state)
|
|
| 84 |
- self._state = state
|
|
| 85 |
- |
|
| 86 |
- @property
|
|
| 87 |
- def state(self):
|
|
| 88 |
- return self._state
|
|
| 89 |
- |
|
| 90 |
- @property
|
|
| 91 |
- def status(self):
|
|
| 92 |
- return self._status
|
|
| 93 |
- |
|
| 94 |
- @property
|
|
| 95 |
- def status_message(self):
|
|
| 96 |
- return self._status_message
|
|
| 97 |
- |
|
| 98 |
- def _register_new_handlers(self, con):
|
|
| 99 |
- for handler in modules.get_handlers(self):
|
|
| 100 |
- if len(handler) == 5:
|
|
| 101 |
- name, func, typ, ns, priority = handler
|
|
| 102 |
- con.RegisterHandler(name, func, typ, ns, priority=priority)
|
|
| 103 |
- else:
|
|
| 104 |
- con.RegisterHandler(*handler)
|
|
| 105 |
- self.handlers_registered = True
|
|
| 106 |
- |
|
| 107 |
- def _unregister_new_handlers(self, con):
|
|
| 108 |
- if not con:
|
|
| 109 |
- return
|
|
| 110 |
- for handler in modules.get_handlers(self):
|
|
| 111 |
- if len(handler) > 4:
|
|
| 112 |
- handler = handler[:4]
|
|
| 113 |
- con.UnregisterHandler(*handler)
|
|
| 114 |
- self.handlers_registered = False
|
|
| 115 |
- |
|
| 116 |
- def get_module(self, name):
|
|
| 117 |
- return modules.get(self.name, name)
|
|
| 118 |
- |
|
| 119 |
- def reconnect(self):
|
|
| 120 |
- """
|
|
| 121 |
- To be implemented by derived classes
|
|
| 122 |
- """
|
|
| 123 |
- raise NotImplementedError
|
|
| 124 |
- |
|
| 125 |
- def quit(self, kill_core):
|
|
| 126 |
- if kill_core and app.account_is_connected(self.name):
|
|
| 127 |
- self.disconnect(reconnect=False)
|
|
| 128 |
- |
|
| 129 |
- def new_account(self, name, config, sync=False):
|
|
| 130 |
- """
|
|
| 131 |
- To be implemented by derived classes
|
|
| 132 |
- """
|
|
| 133 |
- raise NotImplementedError
|
|
| 134 |
- |
|
| 135 |
- def _on_new_account(self, con=None, con_type=None):
|
|
| 136 |
- """
|
|
| 137 |
- To be implemented by derived classes
|
|
| 138 |
- """
|
|
| 139 |
- raise NotImplementedError
|
|
| 140 |
- |
|
| 141 |
- def _event_dispatcher(self, realm, event, data):
|
|
| 142 |
- if realm == '':
|
|
| 143 |
- if event == 'STANZA RECEIVED':
|
|
| 144 |
- app.nec.push_incoming_event(
|
|
| 145 |
- NetworkEvent('stanza-received',
|
|
| 146 |
- conn=self,
|
|
| 147 |
- stanza_str=str(data)))
|
|
| 148 |
- elif event == 'DATA SENT':
|
|
| 149 |
- app.nec.push_incoming_event(
|
|
| 150 |
- NetworkEvent('stanza-sent',
|
|
| 151 |
- conn=self,
|
|
| 152 |
- stanza_str=str(data)))
|
|
| 153 |
- |
|
| 154 |
- def change_status(self, show, msg, auto=False):
|
|
| 155 |
- if not msg:
|
|
| 156 |
- msg = ''
|
|
| 157 |
- |
|
| 158 |
- self._status = show
|
|
| 159 |
- self._status_message = msg
|
|
| 160 |
- |
|
| 161 |
- if self._state.is_disconnected:
|
|
| 162 |
- if show == 'offline':
|
|
| 163 |
- return
|
|
| 164 |
- |
|
| 165 |
- self.server_resource = helpers.get_resource(self.name)
|
|
| 166 |
- self.connect_and_init(show, msg)
|
|
| 167 |
- return
|
|
| 168 |
- |
|
| 169 |
- if self._state.is_connecting or self._state.is_reconnect_scheduled:
|
|
| 170 |
- if show == 'offline':
|
|
| 171 |
- self.disconnect(reconnect=False)
|
|
| 172 |
- elif self._state.is_reconnect_scheduled:
|
|
| 173 |
- self.reconnect()
|
|
| 174 |
- return
|
|
| 175 |
- |
|
| 176 |
- # We are connected
|
|
| 177 |
- if show == 'offline':
|
|
| 178 |
- presence = self.get_module('Presence').get_presence(
|
|
| 179 |
- typ='unavailable',
|
|
| 180 |
- status=msg,
|
|
| 181 |
- caps=False)
|
|
| 182 |
- |
|
| 183 |
- self.connection.send(presence, now=True)
|
|
| 184 |
- self.disconnect(reconnect=False)
|
|
| 185 |
- return
|
|
| 186 |
- |
|
| 187 |
- idle_time = None
|
|
| 188 |
- if auto:
|
|
| 189 |
- if app.is_installed('IDLE') and app.settings.get('autoaway'):
|
|
| 190 |
- idle_sec = idle.Monitor.get_idle_sec()
|
|
| 191 |
- idle_time = time.strftime(
|
|
| 192 |
- '%Y-%m-%dT%H:%M:%SZ',
|
|
| 193 |
- time.gmtime(time.time() - idle_sec))
|
|
| 194 |
- |
|
| 195 |
- self._update_status(show, msg, idle_time=idle_time)
|
| ... | ... | @@ -29,36 +29,6 @@ |
| 29 | 29 |
log = logging.getLogger('gajim.c.connection_handlers_events')
|
| 30 | 30 |
|
| 31 | 31 |
|
| 32 |
-class PresenceReceivedEvent(nec.NetworkIncomingEvent):
|
|
| 33 |
- |
|
| 34 |
- name = 'presence-received'
|
|
| 35 |
- |
|
| 36 |
- |
|
| 37 |
-class OurShowEvent(nec.NetworkIncomingEvent):
|
|
| 38 |
- |
|
| 39 |
- name = 'our-show'
|
|
| 40 |
- |
|
| 41 |
- def init(self):
|
|
| 42 |
- self.reconnect = False
|
|
| 43 |
- |
|
| 44 |
- |
|
| 45 |
-class MessageSentEvent(nec.NetworkIncomingEvent):
|
|
| 46 |
- |
|
| 47 |
- name = 'message-sent'
|
|
| 48 |
- |
|
| 49 |
- |
|
| 50 |
-class ConnectionLostEvent(nec.NetworkIncomingEvent):
|
|
| 51 |
- |
|
| 52 |
- name = 'connection-lost'
|
|
| 53 |
- |
|
| 54 |
- def generate(self):
|
|
| 55 |
- app.nec.push_incoming_event(OurShowEvent(
|
|
| 56 |
- None,
|
|
| 57 |
- conn=self.conn,
|
|
| 58 |
- show='offline'))
|
|
| 59 |
- return True
|
|
| 60 |
- |
|
| 61 |
- |
|
| 62 | 32 |
class FileRequestReceivedEvent(nec.NetworkIncomingEvent):
|
| 63 | 33 |
|
| 64 | 34 |
name = 'file-request-received'
|
| ... | ... | @@ -37,22 +37,41 @@ |
| 37 | 37 |
|
| 38 | 38 |
from gajim.common import app
|
| 39 | 39 |
from gajim.common import modules
|
| 40 |
+from gajim.common import helpers
|
|
| 41 |
+from gajim.common import idle
|
|
| 42 |
+from gajim.common import nec
|
|
| 40 | 43 |
from gajim.common.nec import NetworkEvent
|
| 41 | 44 |
from gajim.common.i18n import _
|
| 42 | 45 |
from gajim.common.const import ClientState
|
| 43 |
-from gajim.common.connection import CommonConnection
|
|
| 44 | 46 |
from gajim.common.zeroconf import client_zeroconf
|
| 45 | 47 |
from gajim.common.zeroconf import zeroconf
|
| 46 | 48 |
from gajim.common.zeroconf.connection_handlers_zeroconf import ConnectionHandlersZeroconf
|
| 47 |
-from gajim.common.connection_handlers_events import OurShowEvent
|
|
| 48 | 49 |
from gajim.common.connection_handlers_events import InformationEvent
|
| 49 |
-from gajim.common.connection_handlers_events import ConnectionLostEvent
|
|
| 50 |
-from gajim.common.connection_handlers_events import MessageSentEvent
|
|
| 51 | 50 |
|
| 52 | 51 |
log = logging.getLogger('gajim.c.connection_zeroconf')
|
| 53 | 52 |
|
| 54 | 53 |
|
| 55 |
-class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf):
|
|
| 54 |
+class OurShowEvent(nec.NetworkIncomingEvent):
|
|
| 55 |
+ |
|
| 56 |
+ name = 'our-show'
|
|
| 57 |
+ |
|
| 58 |
+ def init(self):
|
|
| 59 |
+ self.reconnect = False
|
|
| 60 |
+ |
|
| 61 |
+ |
|
| 62 |
+class ConnectionLostEvent(nec.NetworkIncomingEvent):
|
|
| 63 |
+ |
|
| 64 |
+ name = 'connection-lost'
|
|
| 65 |
+ |
|
| 66 |
+ def generate(self):
|
|
| 67 |
+ app.nec.push_incoming_event(OurShowEvent(
|
|
| 68 |
+ None,
|
|
| 69 |
+ conn=self.conn,
|
|
| 70 |
+ show='offline'))
|
|
| 71 |
+ return True
|
|
| 72 |
+ |
|
| 73 |
+ |
|
| 74 |
+class ConnectionZeroconf(ConnectionHandlersZeroconf):
|
|
| 56 | 75 |
def __init__(self, name):
|
| 57 | 76 |
ConnectionHandlersZeroconf.__init__(self)
|
| 58 | 77 |
# system username
|
| ... | ... | @@ -64,12 +83,135 @@ def __init__(self, name): |
| 64 | 83 |
self.autoconnect = False
|
| 65 | 84 |
self.httpupload = False
|
| 66 | 85 |
|
| 67 |
- CommonConnection.__init__(self, name)
|
|
| 86 |
+ self.name = name
|
|
| 87 |
+ self._modules = {}
|
|
| 88 |
+ self.connection = None # xmpppy ClientCommon instance
|
|
| 89 |
+ self.is_zeroconf = False
|
|
| 90 |
+ self.password = None
|
|
| 91 |
+ self.server_resource = helpers.get_resource(self.name)
|
|
| 92 |
+ self.priority = app.get_priority(name, 'offline')
|
|
| 93 |
+ self.time_to_reconnect = None
|
|
| 94 |
+ self._reconnect_timer_source = None
|
|
| 95 |
+ |
|
| 96 |
+ self._state = ClientState.DISCONNECTED
|
|
| 97 |
+ self._status = 'offline'
|
|
| 98 |
+ self._status_message = ''
|
|
| 99 |
+ |
|
| 100 |
+ # If handlers have been registered
|
|
| 101 |
+ self.handlers_registered = False
|
|
| 102 |
+ |
|
| 103 |
+ self.pep = {}
|
|
| 104 |
+ |
|
| 105 |
+ self.roster_supported = True
|
|
| 106 |
+ |
|
| 107 |
+ self._stun_servers = [] # STUN servers of our jabber server
|
|
| 108 |
+ |
|
| 109 |
+ # Tracks the calls of the connect_machine() method
|
|
| 110 |
+ self._connect_machine_calls = 0
|
|
| 111 |
+ |
|
| 112 |
+ self.get_config_values_or_default()
|
|
| 113 |
+ |
|
| 68 | 114 |
self.is_zeroconf = True
|
| 69 | 115 |
|
| 70 | 116 |
# Register all modules
|
| 71 | 117 |
modules.register_modules(self)
|
| 72 | 118 |
|
| 119 |
+ def _set_state(self, state):
|
|
| 120 |
+ log.info('State: %s', state)
|
|
| 121 |
+ self._state = state
|
|
| 122 |
+ |
|
| 123 |
+ @property
|
|
| 124 |
+ def state(self):
|
|
| 125 |
+ return self._state
|
|
| 126 |
+ |
|
| 127 |
+ @property
|
|
| 128 |
+ def status(self):
|
|
| 129 |
+ return self._status
|
|
| 130 |
+ |
|
| 131 |
+ @property
|
|
| 132 |
+ def status_message(self):
|
|
| 133 |
+ return self._status_message
|
|
| 134 |
+ |
|
| 135 |
+ def _register_new_handlers(self, con):
|
|
| 136 |
+ for handler in modules.get_handlers(self):
|
|
| 137 |
+ if len(handler) == 5:
|
|
| 138 |
+ name, func, typ, ns, priority = handler
|
|
| 139 |
+ con.RegisterHandler(name, func, typ, ns, priority=priority)
|
|
| 140 |
+ else:
|
|
| 141 |
+ con.RegisterHandler(*handler)
|
|
| 142 |
+ self.handlers_registered = True
|
|
| 143 |
+ |
|
| 144 |
+ def _unregister_new_handlers(self, con):
|
|
| 145 |
+ if not con:
|
|
| 146 |
+ return
|
|
| 147 |
+ for handler in modules.get_handlers(self):
|
|
| 148 |
+ if len(handler) > 4:
|
|
| 149 |
+ handler = handler[:4]
|
|
| 150 |
+ con.UnregisterHandler(*handler)
|
|
| 151 |
+ self.handlers_registered = False
|
|
| 152 |
+ |
|
| 153 |
+ def get_module(self, name):
|
|
| 154 |
+ return modules.get(self.name, name)
|
|
| 155 |
+ |
|
| 156 |
+ def quit(self, kill_core):
|
|
| 157 |
+ if kill_core and app.account_is_connected(self.name):
|
|
| 158 |
+ self.disconnect(reconnect=False)
|
|
| 159 |
+ |
|
| 160 |
+ def new_account(self, name, config, sync=False):
|
|
| 161 |
+ """
|
|
| 162 |
+ To be implemented by derived classes
|
|
| 163 |
+ """
|
|
| 164 |
+ raise NotImplementedError
|
|
| 165 |
+ |
|
| 166 |
+ def _on_new_account(self, con=None, con_type=None):
|
|
| 167 |
+ """
|
|
| 168 |
+ To be implemented by derived classes
|
|
| 169 |
+ """
|
|
| 170 |
+ raise NotImplementedError
|
|
| 171 |
+ |
|
| 172 |
+ def change_status(self, show, msg, auto=False):
|
|
| 173 |
+ if not msg:
|
|
| 174 |
+ msg = ''
|
|
| 175 |
+ |
|
| 176 |
+ self._status = show
|
|
| 177 |
+ self._status_message = msg
|
|
| 178 |
+ |
|
| 179 |
+ if self._state.is_disconnected:
|
|
| 180 |
+ if show == 'offline':
|
|
| 181 |
+ return
|
|
| 182 |
+ |
|
| 183 |
+ self.server_resource = helpers.get_resource(self.name)
|
|
| 184 |
+ self.connect_and_init(show, msg)
|
|
| 185 |
+ return
|
|
| 186 |
+ |
|
| 187 |
+ if self._state.is_connecting or self._state.is_reconnect_scheduled:
|
|
| 188 |
+ if show == 'offline':
|
|
| 189 |
+ self.disconnect(reconnect=False)
|
|
| 190 |
+ elif self._state.is_reconnect_scheduled:
|
|
| 191 |
+ self.reconnect()
|
|
| 192 |
+ return
|
|
| 193 |
+ |
|
| 194 |
+ # We are connected
|
|
| 195 |
+ if show == 'offline':
|
|
| 196 |
+ presence = self.get_module('Presence').get_presence(
|
|
| 197 |
+ typ='unavailable',
|
|
| 198 |
+ status=msg,
|
|
| 199 |
+ caps=False)
|
|
| 200 |
+ |
|
| 201 |
+ self.connection.send(presence, now=True)
|
|
| 202 |
+ self.disconnect(reconnect=False)
|
|
| 203 |
+ return
|
|
| 204 |
+ |
|
| 205 |
+ idle_time = None
|
|
| 206 |
+ if auto:
|
|
| 207 |
+ if app.is_installed('IDLE') and app.settings.get('autoaway'):
|
|
| 208 |
+ idle_sec = idle.Monitor.get_idle_sec()
|
|
| 209 |
+ idle_time = time.strftime(
|
|
| 210 |
+ '%Y-%m-%dT%H:%M:%SZ',
|
|
| 211 |
+ time.gmtime(time.time() - idle_sec))
|
|
| 212 |
+ |
|
| 213 |
+ self._update_status(show, msg, idle_time=idle_time)
|
|
| 214 |
+ |
|
| 73 | 215 |
def get_config_values_or_default(self):
|
| 74 | 216 |
"""
|
| 75 | 217 |
Get name, host, port from config, or create zeroconf account with default
|
| ... | ... | @@ -397,7 +539,9 @@ def send_message(self, message): |
| 397 | 539 |
def _send_message(self, message):
|
| 398 | 540 |
def on_send_ok(stanza_id):
|
| 399 | 541 |
app.nec.push_incoming_event(
|
| 400 |
- MessageSentEvent(None, jid=message.jid, **vars(message)))
|
|
| 542 |
+ NetworkEvent('messasge-sent',
|
|
| 543 |
+ jid=message.jid,
|
|
| 544 |
+ **vars(message)))
|
|
| 401 | 545 |
self.get_module('Message').log_message(message)
|
| 402 | 546 |
|
| 403 | 547 |
def on_send_not_ok(reason):
|
| ... | ... | @@ -433,8 +577,18 @@ def send_stanza(self, stanza): |
| 433 | 577 |
self.connection.send(stanza)
|
| 434 | 578 |
|
| 435 | 579 |
def _event_dispatcher(self, realm, event, data):
|
| 436 |
- CommonConnection._event_dispatcher(self, realm, event, data)
|
|
| 437 | 580 |
if realm == '':
|
| 581 |
+ if event == 'STANZA RECEIVED':
|
|
| 582 |
+ app.nec.push_incoming_event(
|
|
| 583 |
+ NetworkEvent('stanza-received',
|
|
| 584 |
+ conn=self,
|
|
| 585 |
+ stanza_str=str(data)))
|
|
| 586 |
+ elif event == 'DATA SENT':
|
|
| 587 |
+ app.nec.push_incoming_event(
|
|
| 588 |
+ NetworkEvent('stanza-sent',
|
|
| 589 |
+ conn=self,
|
|
| 590 |
+ stanza_str=str(data)))
|
|
| 591 |
+ |
|
| 438 | 592 |
if event == nbxmpp.transports.DATA_ERROR:
|
| 439 | 593 |
frm = data[0]
|
| 440 | 594 |
error_message = _(
|