core (xmpp): advanced handling of connection termination
factory's clientConnectionFailed and clientConnectionLost methods are monkey patched to allow client to tune termination:
- a warning when connection is lost in an unclean way
- connector is saved to allow to disable automatic reconnection and retry manually later
- new triggers connection_failed and connection_lost allow plugins to tune connection termination workflow
This commit is contained in:
parent
9186fd1a3c
commit
5b3aa5c60f
1 changed files with 46 additions and 1 deletions
|
|
@ -17,10 +17,11 @@
|
|||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from functools import partial
|
||||
from sat.core.i18n import _
|
||||
from sat.core.constants import Const as C
|
||||
from sat.memory import cache
|
||||
from twisted.internet import defer
|
||||
from twisted.internet import defer, error as internet_error
|
||||
from twisted.words.protocols.jabber.xmlstream import XMPPHandler
|
||||
from twisted.words.protocols.jabber import xmlstream
|
||||
from twisted.words.protocols.jabber import error
|
||||
|
|
@ -53,6 +54,16 @@ class SatXMPPEntity(object):
|
|||
|
||||
def __init__(self, host_app, profile, max_retries):
|
||||
factory = self.factory
|
||||
|
||||
# we monkey patch clientConnectionLost to handle networkEnabled/networkDisabled
|
||||
# and to allow plugins to tune reconnection mechanism
|
||||
clientConnectionFailed_ori = factory.clientConnectionFailed
|
||||
clientConnectionLost_ori = factory.clientConnectionLost
|
||||
factory.clientConnectionFailed = partial(
|
||||
self.connectionTerminated, term_type=u"failed", cb=clientConnectionFailed_ori)
|
||||
factory.clientConnectionLost = partial(
|
||||
self.connectionTerminated, term_type=u"lost", cb=clientConnectionLost_ori)
|
||||
|
||||
factory.maxRetries = max_retries
|
||||
factory.maxDelay = 30
|
||||
# when self._connected_d is None, we are not connected
|
||||
|
|
@ -275,6 +286,40 @@ class SatXMPPEntity(object):
|
|||
|
||||
## connection ##
|
||||
|
||||
def connectionTerminated(self, connector, reason, term_type, cb):
|
||||
"""Display disconnection reason, and call factory method
|
||||
|
||||
This method is monkey patched to factory, allowing plugins to handle finely
|
||||
reconnection with the triggers.
|
||||
@param connector(twisted.internet.base.BaseConnector): current connector
|
||||
@param reason(failure.Failure): why connection has been terminated
|
||||
@param term_type(unicode): on of 'failed' or 'lost'
|
||||
@param cb(callable): original factory method
|
||||
|
||||
@trigger connection_failed(connector, reason): connection can't be established
|
||||
@trigger connection_lost(connector, reason): connection was available but it not
|
||||
anymore
|
||||
"""
|
||||
# we save connector because it may be deleted when connection will be dropped
|
||||
# if reconnection is disabled
|
||||
self._saved_connector = connector
|
||||
if reason is not None and not isinstance(reason.value,
|
||||
internet_error.ConnectionDone):
|
||||
try:
|
||||
reason_str = unicode(reason.value)
|
||||
except Exception:
|
||||
# FIXME: workaround for Android were p4a strips docstrings
|
||||
# while Twisted use docstring in __str__
|
||||
# TODO: create a ticket upstream, Twisted should work when optimization
|
||||
# is used
|
||||
reason_str = unicode(reason.value.__class__)
|
||||
log.warning(u"Connection {term_type}: {reason}".format(
|
||||
term_type = term_type,
|
||||
reason=reason_str))
|
||||
if not self.host_app.trigger.point(u"connection_" + term_type, connector, reason):
|
||||
return
|
||||
return cb(connector, reason)
|
||||
|
||||
def _connected(self, xs):
|
||||
send_hooks = []
|
||||
receive_hooks = []
|
||||
|
|
|
|||
Loading…
Reference in a new issue