Refactor ping code into own module
This commit is contained in:
parent
81d9e1bcf2
commit
7b957a2876
|
@ -1230,14 +1230,16 @@ class ChatControl(ChatControlBase):
|
|||
return
|
||||
self.update_ui()
|
||||
|
||||
def _nec_ping_reply(self, obj):
|
||||
if obj.control:
|
||||
if obj.control != self:
|
||||
return
|
||||
else:
|
||||
if self.contact != obj.contact:
|
||||
return
|
||||
self.print_conversation(_('Pong! (%s s.)') % obj.seconds, 'status')
|
||||
def _nec_ping(self, obj):
|
||||
if self.contact != obj.contact:
|
||||
return
|
||||
if obj.name == 'ping-sent':
|
||||
self.print_conversation(_('Ping?'), 'status')
|
||||
elif obj.name == 'ping-reply':
|
||||
self.print_conversation(
|
||||
_('Pong! (%s s.)') % obj.seconds, 'status')
|
||||
elif obj.name == 'ping-error':
|
||||
self.print_conversation(_('Error.'), 'status')
|
||||
|
||||
def show_avatar(self):
|
||||
if not app.config.get('show_avatar_in_chat'):
|
||||
|
|
|
@ -193,16 +193,6 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
|
|||
if self.parent_win:
|
||||
self.parent_win.redraw_tab(self)
|
||||
|
||||
def _nec_ping_sent(self, obj):
|
||||
if self.contact != obj.contact:
|
||||
return
|
||||
self.print_conversation(_('Ping?'), 'status')
|
||||
|
||||
def _nec_ping_error(self, obj):
|
||||
if self.contact != obj.contact:
|
||||
return
|
||||
self.print_conversation(_('Error.'), 'status')
|
||||
|
||||
def status_url_clicked(self, widget, url):
|
||||
helpers.launch_browser_mailer('url', url)
|
||||
|
||||
|
@ -381,11 +371,11 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
|
|||
app.ged.register_event_handler('our-show', ged.GUI1,
|
||||
self._nec_our_status)
|
||||
app.ged.register_event_handler('ping-sent', ged.GUI1,
|
||||
self._nec_ping_sent)
|
||||
self._nec_ping)
|
||||
app.ged.register_event_handler('ping-reply', ged.GUI1,
|
||||
self._nec_ping_reply)
|
||||
self._nec_ping)
|
||||
app.ged.register_event_handler('ping-error', ged.GUI1,
|
||||
self._nec_ping_error)
|
||||
self._nec_ping)
|
||||
|
||||
# This is basically a very nasty hack to surpass the inability
|
||||
# to properly use the super, because of the old code.
|
||||
|
|
|
@ -178,7 +178,7 @@ class StandardCommonChatCommands(CommandContainer):
|
|||
def ping(self):
|
||||
if self.account == app.ZEROCONF_ACC_NAME:
|
||||
raise CommandError(_('Command is not supported for zeroconf accounts'))
|
||||
app.connections[self.account].sendPing(self.contact)
|
||||
app.connections[self.account].get_module('Ping').send_ping(self.contact)
|
||||
|
||||
@command
|
||||
@doc(_("Send DTMF sequence through an open audio session"))
|
||||
|
@ -391,5 +391,5 @@ class StandardGroupChatCommands(CommandContainer):
|
|||
if self.account == app.ZEROCONF_ACC_NAME:
|
||||
raise CommandError(_('Command is not supported for zeroconf accounts'))
|
||||
gc_c = app.contacts.get_gc_contact(self.account, self.room_jid, nick)
|
||||
app.connections[self.account].sendPing(gc_c, self)
|
||||
app.connections[self.account].get_module('Ping').send_ping(gc_c)
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@ from gajim.common import i18n
|
|||
from gajim.common import idle
|
||||
from gajim.common.modules.entity_time import EntityTime
|
||||
from gajim.common.modules.software_version import SoftwareVersion
|
||||
from gajim.common.modules.ping import Ping
|
||||
from gajim.common.connection_handlers import *
|
||||
from gajim.common.contacts import GC_Contact
|
||||
from gajim.gtkgui_helpers import get_action
|
||||
|
@ -661,6 +662,7 @@ class Connection(CommonConnection, ConnectionHandlers):
|
|||
|
||||
self.register_module('EntityTime', EntityTime, self)
|
||||
self.register_module('SoftwareVersion', SoftwareVersion, self)
|
||||
self.register_module('Ping', Ping, self)
|
||||
|
||||
app.ged.register_event_handler('privacy-list-received', ged.CORE,
|
||||
self._nec_privacy_list_received)
|
||||
|
@ -1527,45 +1529,6 @@ class Connection(CommonConnection, ConnectionHandlers):
|
|||
if self.connection:
|
||||
self.connection.send(' ')
|
||||
|
||||
def _on_xmpp_ping_answer(self, iq_obj):
|
||||
self.awaiting_xmpp_ping_id = None
|
||||
|
||||
def sendPing(self, pingTo=None, control=None):
|
||||
"""
|
||||
Send XMPP Ping (XEP-0199) request. If pingTo is not set, ping is sent to
|
||||
server to detect connection failure at application level
|
||||
If control is set, display result there
|
||||
"""
|
||||
if not app.account_is_connected(self.name):
|
||||
return
|
||||
id_ = self.connection.getAnID()
|
||||
if pingTo:
|
||||
to = pingTo.get_full_jid()
|
||||
app.nec.push_incoming_event(PingSentEvent(None, conn=self,
|
||||
contact=pingTo))
|
||||
else:
|
||||
to = app.config.get_per('accounts', self.name, 'hostname')
|
||||
self.awaiting_xmpp_ping_id = id_
|
||||
iq = nbxmpp.Iq('get', to=to)
|
||||
iq.addChild(name='ping', namespace=nbxmpp.NS_PING)
|
||||
iq.setID(id_)
|
||||
def _on_response(resp):
|
||||
timePong = time.time()
|
||||
if not nbxmpp.isResultNode(resp):
|
||||
app.nec.push_incoming_event(PingErrorEvent(None, conn=self,
|
||||
contact=pingTo))
|
||||
return
|
||||
timeDiff = round(timePong - timePing, 2)
|
||||
app.nec.push_incoming_event(PingReplyEvent(None, conn=self,
|
||||
contact=pingTo, seconds=timeDiff, control=control))
|
||||
if pingTo:
|
||||
timePing = time.time()
|
||||
self.connection.SendAndCallForResponse(iq, _on_response)
|
||||
else:
|
||||
self.connection.SendAndCallForResponse(iq, self._on_xmpp_ping_answer)
|
||||
app.idlequeue.set_alarm(self.check_pingalive, app.config.get_per(
|
||||
'accounts', self.name, 'time_for_ping_alive_answer'))
|
||||
|
||||
def get_active_default_lists(self):
|
||||
if not app.account_is_connected(self.name):
|
||||
return
|
||||
|
@ -1832,8 +1795,10 @@ class Connection(CommonConnection, ConnectionHandlers):
|
|||
self.connection = con
|
||||
if not app.account_is_connected(self.name):
|
||||
return
|
||||
|
||||
self.connection.set_send_timeout(self.keepalives, self.send_keepalive)
|
||||
self.connection.set_send_timeout2(self.pingalives, self.sendPing)
|
||||
self.connection.set_send_timeout2(
|
||||
self.pingalives, self.get_module('Ping').send_keepalive_ping)
|
||||
self.connection.onreceive(None)
|
||||
|
||||
self.privacy_rules_requested = False
|
||||
|
@ -2963,15 +2928,6 @@ class Connection(CommonConnection, ConnectionHandlers):
|
|||
|
||||
self.connection.send(message)
|
||||
|
||||
def check_pingalive(self):
|
||||
if not app.config.get_per('accounts', self.name, 'active'):
|
||||
# Account may have been disabled
|
||||
return
|
||||
if self.awaiting_xmpp_ping_id:
|
||||
# We haven't got the pong in time, disco and reconnect
|
||||
log.warning("No reply received for keepalive ping. Reconnecting.")
|
||||
self.disconnectedReconnCB()
|
||||
|
||||
def _reconnect_alarm(self):
|
||||
if not app.config.get_per('accounts', self.name, 'active'):
|
||||
# Account may have been disabled
|
||||
|
|
|
@ -1328,8 +1328,7 @@ ConnectionHTTPUpload):
|
|||
self.disco_items_ids = []
|
||||
# IDs of disco#info requests
|
||||
self.disco_info_ids = []
|
||||
# ID of urn:xmpp:ping requests
|
||||
self.awaiting_xmpp_ping_id = None
|
||||
|
||||
self.continue_connect_info = None
|
||||
|
||||
self.privacy_default_list = None
|
||||
|
@ -1363,8 +1362,6 @@ ConnectionHTTPUpload):
|
|||
self._nec_roster_received)
|
||||
app.ged.register_event_handler('iq-error-received', ged.CORE,
|
||||
self._nec_iq_error_received)
|
||||
app.ged.register_event_handler('ping-received', ged.CORE,
|
||||
self._nec_ping_received)
|
||||
app.ged.register_event_handler('subscribe-presence-received',
|
||||
ged.CORE, self._nec_subscribe_presence_received)
|
||||
app.ged.register_event_handler('subscribed-presence-received',
|
||||
|
@ -1404,8 +1401,6 @@ ConnectionHTTPUpload):
|
|||
self._nec_roster_received)
|
||||
app.ged.remove_event_handler('iq-error-received', ged.CORE,
|
||||
self._nec_iq_error_received)
|
||||
app.ged.remove_event_handler('ping-received', ged.CORE,
|
||||
self._nec_ping_received)
|
||||
app.ged.remove_event_handler('subscribe-presence-received',
|
||||
ged.CORE, self._nec_subscribe_presence_received)
|
||||
app.ged.remove_event_handler('subscribed-presence-received',
|
||||
|
@ -1902,23 +1897,6 @@ ConnectionHTTPUpload):
|
|||
app.nec.push_incoming_event(MucAdminReceivedEvent(None, conn=self,
|
||||
stanza=iq_obj))
|
||||
|
||||
def _IqPingCB(self, con, iq_obj):
|
||||
log.debug('IqPingCB')
|
||||
app.nec.push_incoming_event(PingReceivedEvent(None, conn=self,
|
||||
stanza=iq_obj))
|
||||
raise nbxmpp.NodeProcessed
|
||||
|
||||
def _nec_ping_received(self, obj):
|
||||
if obj.conn.name != self.name:
|
||||
return
|
||||
if not self.connection or self.connected < 2:
|
||||
return
|
||||
iq_obj = obj.stanza.buildReply('result')
|
||||
q = iq_obj.getTag('ping')
|
||||
if q:
|
||||
iq_obj.delChild(q)
|
||||
self.connection.send(iq_obj)
|
||||
|
||||
def _PrivacySetCB(self, con, iq_obj):
|
||||
"""
|
||||
Privacy lists (XEP 016)
|
||||
|
@ -2196,7 +2174,6 @@ ConnectionHTTPUpload):
|
|||
nbxmpp.NS_DISCO_INFO)
|
||||
con.RegisterHandler('iq', self._DiscoverItemsGetCB, 'get',
|
||||
nbxmpp.NS_DISCO_ITEMS)
|
||||
con.RegisterHandler('iq', self._IqPingCB, 'get', nbxmpp.NS_PING)
|
||||
con.RegisterHandler('iq', self._SearchCB, 'result', nbxmpp.NS_SEARCH)
|
||||
con.RegisterHandler('iq', self._PrivacySetCB, 'set', nbxmpp.NS_PRIVACY)
|
||||
con.RegisterHandler('iq', self._ArchiveCB, ns=nbxmpp.NS_MAM_1)
|
||||
|
|
|
@ -573,10 +573,6 @@ class IqErrorReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
|
|||
self.errcode = self.stanza.getErrorCode()
|
||||
return True
|
||||
|
||||
class PingReceivedEvent(nec.NetworkIncomingEvent):
|
||||
name = 'ping-received'
|
||||
base_network_events = []
|
||||
|
||||
class StreamReceivedEvent(nec.NetworkIncomingEvent):
|
||||
name = 'stream-received'
|
||||
base_network_events = []
|
||||
|
@ -1970,18 +1966,6 @@ class ConnectionLostEvent(nec.NetworkIncomingEvent):
|
|||
show='offline'))
|
||||
return True
|
||||
|
||||
class PingSentEvent(nec.NetworkIncomingEvent):
|
||||
name = 'ping-sent'
|
||||
base_network_events = []
|
||||
|
||||
class PingReplyEvent(nec.NetworkIncomingEvent):
|
||||
name = 'ping-reply'
|
||||
base_network_events = []
|
||||
|
||||
class PingErrorEvent(nec.NetworkIncomingEvent):
|
||||
name = 'ping-error'
|
||||
base_network_events = []
|
||||
|
||||
class CapsPresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent,
|
||||
PresenceHelperEvent):
|
||||
name = 'caps-presence-received'
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
# This file is part of Gajim.
|
||||
#
|
||||
# Gajim is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published
|
||||
# by the Free Software Foundation; version 3 only.
|
||||
#
|
||||
# Gajim is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# XEP-0199: XMPP Ping
|
||||
|
||||
import logging
|
||||
import time
|
||||
|
||||
import nbxmpp
|
||||
|
||||
from gajim.common import app
|
||||
from gajim.common.nec import NetworkIncomingEvent
|
||||
|
||||
log = logging.getLogger('gajim.c.m.ping')
|
||||
|
||||
|
||||
class Ping:
|
||||
def __init__(self, con):
|
||||
self._con = con
|
||||
self._account = con.name
|
||||
self._alarm_time = None
|
||||
|
||||
self.handlers = [
|
||||
('iq', self._answer_request, 'get', nbxmpp.NS_PING),
|
||||
]
|
||||
|
||||
def _get_ping_iq(self, to):
|
||||
iq = nbxmpp.Iq('get', to=to)
|
||||
iq.addChild(name='ping', namespace=nbxmpp.NS_PING)
|
||||
return iq
|
||||
|
||||
def send_keepalive_ping(self):
|
||||
if not app.account_is_connected(self._account):
|
||||
return
|
||||
|
||||
to = app.config.get_per('accounts', self._account, 'hostname')
|
||||
self._con.connection.SendAndCallForResponse(self._get_ping_iq(to),
|
||||
self._keepalive_received)
|
||||
|
||||
log.info('Send keepalive')
|
||||
|
||||
seconds = app.config.get_per('accounts', self._account,
|
||||
'time_for_ping_alive_answer')
|
||||
self._alarm_time = app.idlequeue.set_alarm(self._reconnect, seconds)
|
||||
|
||||
def _keepalive_received(self, stanza):
|
||||
log.info('Received keepalive')
|
||||
app.idlequeue.remove_alarm(self._reconnect, self._alarm_time)
|
||||
|
||||
def _reconnect(self):
|
||||
if not app.config.get_per('accounts', self._account, 'active'):
|
||||
# Account may have been disabled
|
||||
return
|
||||
|
||||
# We haven't got the pong in time, disco and reconnect
|
||||
log.warning('No reply received for keepalive ping. Reconnecting...')
|
||||
self._con.disconnectedReconnCB()
|
||||
|
||||
def send_ping(self, contact):
|
||||
if not app.account_is_connected(self._account):
|
||||
return
|
||||
|
||||
to = contact.get_full_jid()
|
||||
iq = self._get_ping_iq(to)
|
||||
|
||||
log.info('Send ping to %s', to)
|
||||
|
||||
self._con.connection.SendAndCallForResponse(
|
||||
iq, self._pong_received, {'ping_time': time.time(),
|
||||
'contact': contact})
|
||||
|
||||
app.nec.push_incoming_event(
|
||||
PingSentEvent(None, conn=self._con, contact=contact))
|
||||
|
||||
def _pong_received(self, con, stanza, ping_time, contact):
|
||||
if not nbxmpp.isResultNode(stanza):
|
||||
log.info('Error: %s', stanza.getError())
|
||||
app.nec.push_incoming_event(
|
||||
PingErrorEvent(None, conn=self._con, contact=contact))
|
||||
return
|
||||
diff = round(time.time() - ping_time, 2)
|
||||
log.info('Received pong from %s after %s seconds',
|
||||
stanza.getFrom(), diff)
|
||||
app.nec.push_incoming_event(
|
||||
PingReplyEvent(None, conn=self._con,
|
||||
contact=contact,
|
||||
seconds=diff))
|
||||
|
||||
def _answer_request(self, con, stanza):
|
||||
iq = stanza.buildReply('result')
|
||||
q = iq.getTag('ping')
|
||||
if q is not None:
|
||||
iq.delChild(q)
|
||||
self._con.connection.send(iq)
|
||||
log.info('Send pong to %s', stanza.getFrom())
|
||||
raise nbxmpp.NodeProcessed
|
||||
|
||||
|
||||
class PingSentEvent(NetworkIncomingEvent):
|
||||
name = 'ping-sent'
|
||||
base_network_events = []
|
||||
|
||||
|
||||
class PingReplyEvent(NetworkIncomingEvent):
|
||||
name = 'ping-reply'
|
||||
base_network_events = []
|
||||
|
||||
|
||||
class PingErrorEvent(NetworkIncomingEvent):
|
||||
name = 'ping-error'
|
||||
base_network_events = []
|
|
@ -1572,14 +1572,18 @@ class GroupchatControl(ChatControlBase):
|
|||
obj.xhtml, self.session, msg_log_id=obj.msg_log_id,
|
||||
encrypted=obj.encrypted, displaymarking=obj.displaymarking)
|
||||
|
||||
def _nec_ping_reply(self, obj):
|
||||
if obj.control:
|
||||
if obj.control != self:
|
||||
return
|
||||
else:
|
||||
if self.contact != obj.contact:
|
||||
return
|
||||
self.print_conversation(_('Pong! (%s s.)') % obj.seconds)
|
||||
def _nec_ping(self, obj):
|
||||
if self.contact.jid != obj.contact.room_jid:
|
||||
return
|
||||
|
||||
nick = obj.contact.get_shown_name()
|
||||
if obj.name == 'ping-sent':
|
||||
self.print_conversation(_('Ping? (%s)') % nick)
|
||||
elif obj.name == 'ping-reply':
|
||||
self.print_conversation(
|
||||
_('Pong! (%s %s s.)') % (nick, obj.seconds))
|
||||
elif obj.name == 'ping-error':
|
||||
self.print_conversation(_('Error.'))
|
||||
|
||||
def got_connected(self):
|
||||
# Make autorejoin stop.
|
||||
|
|
Loading…
Reference in New Issue