annotate sat/plugins/plugin_xep_0198.py @ 2891:6a0f42e9410a

core (xmpp): implemented roster versioning
author Goffi <goffi@goffi.org>
date Sun, 07 Apr 2019 18:47:17 +0200
parents 9213c6dff48d
children c8c68a3b0a79
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2691
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
1 #!/usr/bin/env python2
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
2 # -*- coding: utf-8 -*-
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
3
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
4 # SàT plugin for managing raw XML log
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
5 # Copyright (C) 2011 Jérôme Poisson (goffi@goffi.org)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
6
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
7 # This program is free software: you can redistribute it and/or modify
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
8 # it under the terms of the GNU Affero General Public License as published by
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
9 # the Free Software Foundation, either version 3 of the License, or
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
10 # (at your option) any later version.
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
11
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
12 # This program is distributed in the hope that it will be useful,
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
15 # GNU Affero General Public License for more details.
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
16
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
17 # You should have received a copy of the GNU Affero General Public License
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
19
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
20 from sat.core.i18n import _
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
21 from sat.core.constants import Const as C
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
22 from sat.core import exceptions
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
23 from sat.core.log import getLogger
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
24 from twisted.words.protocols.jabber import client as jabber_client
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
25 from twisted.words.protocols.jabber import xmlstream
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
26 from twisted.words.xish import domish
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
27 from twisted.internet import defer
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
28 from twisted.internet import task, reactor
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
29 from functools import partial
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
30 from wokkel import disco, iwokkel
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
31 from zope.interface import implements
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
32 import collections
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
33 import time
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
34
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
35 log = getLogger(__name__)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
36
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
37 PLUGIN_INFO = {
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
38 C.PI_NAME: "Stream Management",
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
39 C.PI_IMPORT_NAME: "XEP-0198",
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
40 C.PI_TYPE: "XEP",
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
41 C.PI_MODES: C.PLUG_MODE_BOTH,
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
42 C.PI_PROTOCOLS: ["XEP-0198"],
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
43 C.PI_DEPENDENCIES: [],
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
44 C.PI_MAIN: "XEP_0198",
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
45 C.PI_HANDLER: "yes",
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
46 C.PI_DESCRIPTION: _(u"""Implementation of Stream Management"""),
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
47 }
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
48
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
49 NS_SM = u"urn:xmpp:sm:3"
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
50 SM_ENABLED = '/enabled[@xmlns="' + NS_SM + '"]'
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
51 SM_RESUMED = '/resumed[@xmlns="' + NS_SM + '"]'
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
52 SM_FAILED = '/failed[@xmlns="' + NS_SM + '"]'
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
53 SM_R_REQUEST = '/r[@xmlns="' + NS_SM + '"]'
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
54 SM_A_REQUEST = '/a[@xmlns="' + NS_SM + '"]'
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
55 SM_H_REQUEST = '/h[@xmlns="' + NS_SM + '"]'
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
56 # Max number of stanza to send before requesting ack
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
57 MAX_STANZA_ACK_R = 5
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
58 # Max number of seconds before requesting ack
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
59 MAX_DELAY_ACK_R = 30
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
60 MAX_COUNTER = 2**32
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
61 RESUME_MAX = 5*60
2725
d0466af33483 plugin XEP-0198: abort connection if ack is not received after a timeout:
Goffi <goffi@goffi.org>
parents: 2691
diff changeset
62 # if we don't have an answer to ACK REQUEST after this delay, connection is aborted
2729
edd230651138 plugin XEP-0198: rised ACK_TIMEOUT + set req_time to None when timing out to be ready after resuming
Goffi <goffi@goffi.org>
parents: 2727
diff changeset
63 ACK_TIMEOUT = 35
2691
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
64
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
65
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
66 class ProfileSessionData(object):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
67 out_counter = 0
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
68 in_counter = 0
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
69 session_id = None
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
70 location = None
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
71 session_max = None
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
72 # True when an ack answer is expected
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
73 ack_requested = False
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
74 last_ack_r = 0
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
75 disconnected_time = None
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
76
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
77 def __init__(self, callback, **kw):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
78 self.buffer = collections.deque()
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
79 self.buffer_idx = 0
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
80 self._enabled = False
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
81 self.timer = None
2725
d0466af33483 plugin XEP-0198: abort connection if ack is not received after a timeout:
Goffi <goffi@goffi.org>
parents: 2691
diff changeset
82 # time used when doing a ack request
d0466af33483 plugin XEP-0198: abort connection if ack is not received after a timeout:
Goffi <goffi@goffi.org>
parents: 2691
diff changeset
83 # when it times out, connection is aborted
d0466af33483 plugin XEP-0198: abort connection if ack is not received after a timeout:
Goffi <goffi@goffi.org>
parents: 2691
diff changeset
84 self.req_timer = None
2691
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
85 self.callback_data = (callback, kw)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
86
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
87 @property
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
88 def enabled(self):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
89 return self._enabled
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
90
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
91 @enabled.setter
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
92 def enabled(self, enabled):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
93 if enabled:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
94 if self._enabled:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
95 raise exceptions.InternalError(
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
96 u"Stream Management can't be enabled twice")
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
97 self._enabled = True
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
98 callback, kw = self.callback_data
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
99 self.timer = task.LoopingCall(callback, **kw)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
100 self.timer.start(MAX_DELAY_ACK_R, now=False)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
101 else:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
102 self._enabled = False
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
103 if self.timer is not None:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
104 self.timer.stop()
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
105 self.timer = None
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
106
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
107 @property
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
108 def resume_enabled(self):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
109 return self.session_id is not None
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
110
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
111 def reset(self):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
112 self.enabled = False
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
113 self.buffer.clear()
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
114 self.buffer_idx = 0
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
115 self.in_counter = self.out_counter = 0
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
116 self.session_id = self.location = None
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
117 self.ack_requested = False
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
118 self.last_ack_r = 0
2865
9213c6dff48d plugin XEP-0198: reset req_timer on session.reset():
Goffi <goffi@goffi.org>
parents: 2796
diff changeset
119 if self.req_timer is not None:
9213c6dff48d plugin XEP-0198: reset req_timer on session.reset():
Goffi <goffi@goffi.org>
parents: 2796
diff changeset
120 if self.req_timer.active():
9213c6dff48d plugin XEP-0198: reset req_timer on session.reset():
Goffi <goffi@goffi.org>
parents: 2796
diff changeset
121 log.error(u"req_timer has been called/cancelled but not reset")
9213c6dff48d plugin XEP-0198: reset req_timer on session.reset():
Goffi <goffi@goffi.org>
parents: 2796
diff changeset
122 else:
9213c6dff48d plugin XEP-0198: reset req_timer on session.reset():
Goffi <goffi@goffi.org>
parents: 2796
diff changeset
123 self.req_timer.cancel()
9213c6dff48d plugin XEP-0198: reset req_timer on session.reset():
Goffi <goffi@goffi.org>
parents: 2796
diff changeset
124 self.req_timer = None
2691
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
125
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
126
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
127 class XEP_0198(object):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
128 # FIXME: location is not handled yet
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
129
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
130 def __init__(self, host):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
131 log.info(_("Plugin Stream Management initialization"))
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
132 self.host = host
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
133 host.registerNamespace(u'sm', NS_SM)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
134 host.trigger.add("stream_hooks", self.addHooks)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
135 host.trigger.add("xml_init", self._XMLInitTrigger)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
136 host.trigger.add("disconnecting", self._disconnectingTrigger)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
137 host.trigger.add("disconnected", self._disconnectedTrigger)
2727
59ac9284dee8 plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents: 2725
diff changeset
138 try:
59ac9284dee8 plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents: 2725
diff changeset
139 self._ack_timeout = int(host.memory.getConfig("", "ack_timeout", ACK_TIMEOUT))
59ac9284dee8 plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents: 2725
diff changeset
140 except ValueError:
59ac9284dee8 plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents: 2725
diff changeset
141 log.error(_(u"Invalid ack_timeout value, please check your configuration"))
59ac9284dee8 plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents: 2725
diff changeset
142 self._ack_timeout = ACK_TIMEOUT
59ac9284dee8 plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents: 2725
diff changeset
143 if not self._ack_timeout:
59ac9284dee8 plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents: 2725
diff changeset
144 log.info(_(u"Ack timeout disabled"))
59ac9284dee8 plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents: 2725
diff changeset
145 else:
2729
edd230651138 plugin XEP-0198: rised ACK_TIMEOUT + set req_time to None when timing out to be ready after resuming
Goffi <goffi@goffi.org>
parents: 2727
diff changeset
146 log.info(_(u"Ack timeout set to {timeout}s").format(
2727
59ac9284dee8 plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents: 2725
diff changeset
147 timeout=self._ack_timeout))
2691
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
148
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
149 def profileConnecting(self, client):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
150 client._xep_0198_session = ProfileSessionData(callback=self.checkAcks,
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
151 client=client)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
152
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
153 def getHandler(self, client):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
154 return XEP_0198_handler(self)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
155
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
156 def addHooks(self, client, receive_hooks, send_hooks):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
157 """Add hooks to handle in/out stanzas counters"""
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
158 receive_hooks.append(partial(self.onReceive, client=client))
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
159 send_hooks.append(partial(self.onSend, client=client))
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
160 return True
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
161
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
162 def _XMLInitTrigger(self, client):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
163 """Enable or resume a stream mangement"""
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
164 if not (NS_SM, u'sm') in client.xmlstream.features:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
165 log.warning(_(
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
166 u"Your server doesn't support stream management ({namespace}), this is "
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
167 u"used to improve connection problems detection (like network outages). "
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
168 u"Please ask your server administrator to enable this feature.".format(
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
169 namespace=NS_SM)))
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
170 return True
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
171 session = client._xep_0198_session
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
172
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
173 # a disconnect timer from a previous disconnection may still be active
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
174 try:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
175 disconnect_timer = session.disconnect_timer
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
176 except AttributeError:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
177 pass
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
178 else:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
179 if disconnect_timer.active():
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
180 disconnect_timer.cancel()
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
181 del session.disconnect_timer
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
182
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
183 if session.resume_enabled:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
184 # we are resuming a session
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
185 resume_elt = domish.Element((NS_SM, 'resume'))
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
186 resume_elt['h'] = unicode(session.in_counter)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
187 resume_elt['previd'] = session.session_id
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
188 client.send(resume_elt)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
189 session.resuming = True
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
190 # session.enabled will be set on <resumed/> reception
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
191 return False
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
192 else:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
193 # we start a new session
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
194 assert session.out_counter == 0
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
195 enable_elt = domish.Element((NS_SM, 'enable'))
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
196 enable_elt[u'resume'] = u'true'
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
197 client.send(enable_elt)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
198 session.enabled = True
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
199 return True
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
200
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
201 def _disconnectingTrigger(self, client):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
202 session = client._xep_0198_session
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
203 if session.enabled:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
204 self.sendAck(client)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
205 # This is a requested disconnection, so we can reset the session
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
206 # to disable resuming and close normally the stream
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
207 session.reset()
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
208 return True
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
209
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
210 def _disconnectedTrigger(self, client, reason):
2796
fdc53c8a5439 plugin XEP-0198: don't use hooks on components
Goffi <goffi@goffi.org>
parents: 2795
diff changeset
211 if client.is_component:
fdc53c8a5439 plugin XEP-0198: don't use hooks on components
Goffi <goffi@goffi.org>
parents: 2795
diff changeset
212 return True
2691
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
213 session = client._xep_0198_session
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
214 session.enabled = False
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
215 if session.resume_enabled:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
216 session.disconnected_time = time.time()
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
217 session.disconnect_timer = reactor.callLater(session.session_max,
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
218 client.disconnectProfile,
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
219 reason)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
220 # disconnectProfile must not be called at this point
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
221 # because session can be resumed
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
222 return False
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
223 else:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
224 return True
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
225
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
226 def checkAcks(self, client):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
227 """Request ack if needed"""
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
228 session = client._xep_0198_session
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
229 # log.debug("checkAcks (in_counter={}, out_counter={}, buf len={}, buf idx={})"
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
230 # .format(session.in_counter, session.out_counter, len(session.buffer),
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
231 # session.buffer_idx))
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
232 if session.ack_requested or not session.buffer:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
233 return
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
234 if (session.out_counter - session.buffer_idx >= MAX_STANZA_ACK_R
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
235 or time.time() - session.last_ack_r >= MAX_DELAY_ACK_R):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
236 self.requestAck(client)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
237 session.ack_requested = True
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
238 session.last_ack_r = time.time()
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
239
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
240 def updateBuffer(self, session, server_acked):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
241 """Update buffer and buffer_index"""
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
242 if server_acked > session.buffer_idx:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
243 diff = server_acked - session.buffer_idx
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
244 for i in xrange(diff):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
245 session.buffer.pop()
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
246 session.buffer_idx += diff
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
247
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
248 def sendAck(self, client):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
249 """Send an answer element with current IN counter"""
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
250 a_elt = domish.Element((NS_SM, 'a'))
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
251 a_elt['h'] = unicode(client._xep_0198_session.in_counter)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
252 client.send(a_elt)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
253
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
254 def requestAck(self, client):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
255 """Send a request element"""
2725
d0466af33483 plugin XEP-0198: abort connection if ack is not received after a timeout:
Goffi <goffi@goffi.org>
parents: 2691
diff changeset
256 session = client._xep_0198_session
2691
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
257 r_elt = domish.Element((NS_SM, 'r'))
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
258 client.send(r_elt)
2725
d0466af33483 plugin XEP-0198: abort connection if ack is not received after a timeout:
Goffi <goffi@goffi.org>
parents: 2691
diff changeset
259 if session.req_timer is not None:
d0466af33483 plugin XEP-0198: abort connection if ack is not received after a timeout:
Goffi <goffi@goffi.org>
parents: 2691
diff changeset
260 raise exceptions.InternalError("req_timer should not be set")
2727
59ac9284dee8 plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents: 2725
diff changeset
261 if self._ack_timeout:
59ac9284dee8 plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents: 2725
diff changeset
262 session.req_timer = reactor.callLater(self._ack_timeout, self.onAckTimeOut,
59ac9284dee8 plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents: 2725
diff changeset
263 client)
2691
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
264
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
265 def _connectionFailed(self, failure_, connector):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
266 normal_host, normal_port = connector.normal_location
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
267 del connector.normal_location
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
268 log.warning(_(
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
269 u"Connection failed using location given by server (host: {host}, port: "
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
270 u"{port}), switching to normal host and port (host: {normal_host}, port: "
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
271 u"{normal_port})".format(host=connector.host, port=connector.port,
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
272 normal_host=normal_host, normal_port=normal_port)))
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
273 connector.host, connector.port = normal_host, normal_port
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
274 connector.connectionFailed = connector.connectionFailed_ori
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
275 del connector.connectionFailed_ori
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
276 return connector.connectionFailed(failure_)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
277
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
278 def onEnabled(self, enabled_elt, client):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
279 session = client._xep_0198_session
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
280 session.in_counter = 0
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
281
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
282 # we check that resuming is possible and that we have a session id
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
283 resume = C.bool(enabled_elt.getAttribute(u'resume'))
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
284 session_id = enabled_elt.getAttribute(u'id')
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
285 if not session_id:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
286 log.warning(_(u'Incorrect <enabled/> element received, no "id" attribute'))
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
287 if not resume or not session_id:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
288 log.warning(_(
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
289 u"You're server doesn't support session resuming with stream management, "
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
290 u"please contact your server administrator to enable it"))
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
291 return
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
292
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
293 session.session_id = session_id
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
294
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
295 # XXX: we disable resource binding, which must not be done
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
296 # when we resume the session.
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
297 client.factory.authenticator.res_binding = False
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
298
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
299 # location, in case server want resuming session to be elsewhere
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
300 try:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
301 location = enabled_elt[u'location']
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
302 except KeyError:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
303 pass
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
304 else:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
305 # TODO: handle IPv6 here (in brackets, cf. XEP)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
306 try:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
307 domain, port = location.split(':', 1)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
308 port = int(port)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
309 except ValueError:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
310 log.warning(_(u"Invalid location received: {location}")
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
311 .format(location=location))
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
312 else:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
313 session.location = (domain, port)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
314 # we monkey patch connector to use the new location
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
315 connector = client.xmlstream.transport.connector
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
316 connector.normal_location = connector.host, connector.port
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
317 connector.host = domain
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
318 connector.port = port
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
319 connector.connectionFailed_ori = connector.connectionFailed
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
320 connector.connectionFailed = partial(self._connectionFailed,
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
321 connector=connector)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
322
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
323 # resuming time
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
324 try:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
325 max_s = int(enabled_elt[u'max'])
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
326 except (ValueError, KeyError) as e:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
327 if isinstance(e, ValueError):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
328 log.warning(_(u'Invalid "max" attribute'))
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
329 max_s = RESUME_MAX
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
330 log.info(_(u"Using default session max value ({max_s} s).".format(
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
331 max_s=max_s)))
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
332 log.info(_(u"Stream Management enabled"))
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
333 else:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
334 log.info(_(
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
335 u"Stream Management enabled, with a resumption time of {res_m} min"
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
336 .format(res_m = max_s/60)))
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
337 session.session_max = max_s
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
338
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
339 def onResumed(self, enabled_elt, client):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
340 session = client._xep_0198_session
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
341 assert not session.enabled
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
342 del session.resuming
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
343 server_acked = int(enabled_elt['h'])
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
344 self.updateBuffer(session, server_acked)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
345 resend_count = len(session.buffer)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
346 # we resend all stanza which have not been received properly
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
347 while True:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
348 try:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
349 stanza = session.buffer.pop()
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
350 except IndexError:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
351 break
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
352 else:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
353 client.send(stanza)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
354 # now we can continue the session
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
355 session.enabled = True
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
356 d_time = time.time() - session.disconnected_time
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
357 log.info(_(u"Stream session resumed (disconnected for {d_time} s, {count} "
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
358 u"stanza(s) resent)").format(d_time=int(d_time), count=resend_count))
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
359
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
360 def onFailed(self, failed_elt, client):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
361 session = client._xep_0198_session
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
362 condition_elt = failed_elt.firstChildElement()
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
363 session.reset()
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
364
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
365 try:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
366 del session.resuming
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
367 except AttributeError:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
368 # stream management can't be started at all
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
369 msg = _(u"Can't use stream management")
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
370 if condition_elt is None:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
371 log.error(msg + u'.')
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
372 else:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
373 log.error(_(u"{msg}: {reason}").format(
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
374 msg=msg, reason=condition_elt.name))
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
375 else:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
376 # only stream resumption failed, we can try full session init
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
377 # XXX: we try to start full session init from this point, with many
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
378 # variables/attributes already initialised with a potentially different
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
379 # jid. This is experimental and may not be safe. It may be more
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
380 # secured to abord the connection and restart everything with a fresh
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
381 # client.
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
382 msg = _(u"stream resumption not possible, restarting full session")
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
383
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
384 if condition_elt is None:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
385 log.warning(u'{msg}.'.format(msg=msg))
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
386 else:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
387 log.warning(u"{msg}: {reason}".format(
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
388 msg=msg, reason=condition_elt.name))
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
389 # stream resumption failed, but we still can do normal stream management
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
390 # we restore attributes as if the session was new, and init stream
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
391 # we keep everything initialized, and only do binding, roster request
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
392 # and initial presence sending.
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
393 if client.conn_deferred.called:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
394 client.conn_deferred = defer.Deferred()
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
395 else:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
396 log.error(u"conn_deferred should be called at this point")
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
397 # we need to recreate roster
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
398 client.handlers.remove(client.roster)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
399 client.roster = client.roster.__class__(self.host)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
400 client.roster.setHandlerParent(client)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
401 # bind init is not done when resuming is possible, so we have to do it now
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
402 bind_init = jabber_client.BindInitializer(client.xmlstream)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
403 bind_init.required = True
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
404 d = bind_init.start()
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
405 # we set the jid, which may have changed
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
406 d.addCallback(lambda __: setattr(client.factory.authenticator, "jid", client.jid))
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
407 # we call the trigger who will send the <enable/> element
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
408 d.addCallback(lambda __: self._XMLInitTrigger(client))
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
409 # then we have to re-request the roster, as changes may have occured
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
410 d.addCallback(lambda __: client.roster.requestRoster())
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
411 # we add got_roster to be sure to have roster before sending initial presence
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
412 d.addCallback(lambda __: client.roster.got_roster)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
413 # initial presence must be sent manually
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
414 d.addCallback(lambda __: client.presence.available())
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
415
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
416 def onReceive(self, element, client):
2796
fdc53c8a5439 plugin XEP-0198: don't use hooks on components
Goffi <goffi@goffi.org>
parents: 2795
diff changeset
417 if not client.is_component:
fdc53c8a5439 plugin XEP-0198: don't use hooks on components
Goffi <goffi@goffi.org>
parents: 2795
diff changeset
418 session = client._xep_0198_session
fdc53c8a5439 plugin XEP-0198: don't use hooks on components
Goffi <goffi@goffi.org>
parents: 2795
diff changeset
419 if session.enabled and element.name.lower() in C.STANZA_NAMES:
fdc53c8a5439 plugin XEP-0198: don't use hooks on components
Goffi <goffi@goffi.org>
parents: 2795
diff changeset
420 session.in_counter += 1 % MAX_COUNTER
2691
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
421
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
422 def onSend(self, obj, client):
2796
fdc53c8a5439 plugin XEP-0198: don't use hooks on components
Goffi <goffi@goffi.org>
parents: 2795
diff changeset
423 if not client.is_component:
fdc53c8a5439 plugin XEP-0198: don't use hooks on components
Goffi <goffi@goffi.org>
parents: 2795
diff changeset
424 session = client._xep_0198_session
fdc53c8a5439 plugin XEP-0198: don't use hooks on components
Goffi <goffi@goffi.org>
parents: 2795
diff changeset
425 if (session.enabled
fdc53c8a5439 plugin XEP-0198: don't use hooks on components
Goffi <goffi@goffi.org>
parents: 2795
diff changeset
426 and domish.IElement.providedBy(obj)
fdc53c8a5439 plugin XEP-0198: don't use hooks on components
Goffi <goffi@goffi.org>
parents: 2795
diff changeset
427 and obj.name.lower() in C.STANZA_NAMES):
fdc53c8a5439 plugin XEP-0198: don't use hooks on components
Goffi <goffi@goffi.org>
parents: 2795
diff changeset
428 session.out_counter += 1 % MAX_COUNTER
fdc53c8a5439 plugin XEP-0198: don't use hooks on components
Goffi <goffi@goffi.org>
parents: 2795
diff changeset
429 session.buffer.appendleft(obj)
fdc53c8a5439 plugin XEP-0198: don't use hooks on components
Goffi <goffi@goffi.org>
parents: 2795
diff changeset
430 self.checkAcks(client)
2691
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
431
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
432 def onAckRequest(self, r_elt, client):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
433 self.sendAck(client)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
434
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
435 def onAckAnswer(self, a_elt, client):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
436 session = client._xep_0198_session
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
437 session.ack_requested = False
2727
59ac9284dee8 plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents: 2725
diff changeset
438 if self._ack_timeout:
59ac9284dee8 plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents: 2725
diff changeset
439 if session.req_timer is None:
59ac9284dee8 plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents: 2725
diff changeset
440 log.error("reg_timer should be set")
59ac9284dee8 plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents: 2725
diff changeset
441 else:
59ac9284dee8 plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents: 2725
diff changeset
442 session.req_timer.cancel()
59ac9284dee8 plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents: 2725
diff changeset
443 session.req_timer = None
2691
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
444 try:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
445 server_acked = int(a_elt['h'])
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
446 except ValueError:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
447 log.warning(_(u"Server returned invalid ack element, disabling stream "
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
448 u"management: {xml}").format(xml=a_elt))
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
449 session.enabled = False
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
450 return
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
451
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
452 if server_acked > session.out_counter:
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
453 log.error(_(u"Server acked more stanzas than we have sent, disabling stream "
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
454 u"management."))
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
455 session.reset()
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
456 return
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
457
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
458 self.updateBuffer(session, server_acked)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
459 self.checkAcks(client)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
460
2725
d0466af33483 plugin XEP-0198: abort connection if ack is not received after a timeout:
Goffi <goffi@goffi.org>
parents: 2691
diff changeset
461 def onAckTimeOut(self, client):
d0466af33483 plugin XEP-0198: abort connection if ack is not received after a timeout:
Goffi <goffi@goffi.org>
parents: 2691
diff changeset
462 """Called when a requested ACK has not been received in time"""
d0466af33483 plugin XEP-0198: abort connection if ack is not received after a timeout:
Goffi <goffi@goffi.org>
parents: 2691
diff changeset
463 log.info(_(u"Ack was not received in time, aborting connection"))
d0466af33483 plugin XEP-0198: abort connection if ack is not received after a timeout:
Goffi <goffi@goffi.org>
parents: 2691
diff changeset
464 client.xmlstream.transport.abortConnection()
2795
25639611c303 plugin XEP-0198: fixed typo resulting in a crash on resume
Goffi <goffi@goffi.org>
parents: 2729
diff changeset
465 client._xep_0198_session.req_timer = None
2725
d0466af33483 plugin XEP-0198: abort connection if ack is not received after a timeout:
Goffi <goffi@goffi.org>
parents: 2691
diff changeset
466
2691
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
467
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
468 class XEP_0198_handler(xmlstream.XMPPHandler):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
469 implements(iwokkel.IDisco)
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
470
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
471 def __init__(self, plugin_parent):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
472 self.plugin_parent = plugin_parent
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
473 self.host = plugin_parent.host
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
474
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
475 def connectionInitialized(self):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
476 self.xmlstream.addObserver(
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
477 SM_ENABLED, self.plugin_parent.onEnabled, client=self.parent
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
478 )
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
479 self.xmlstream.addObserver(
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
480 SM_RESUMED, self.plugin_parent.onResumed, client=self.parent
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
481 )
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
482 self.xmlstream.addObserver(
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
483 SM_FAILED, self.plugin_parent.onFailed, client=self.parent
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
484 )
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
485 self.xmlstream.addObserver(
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
486 SM_R_REQUEST, self.plugin_parent.onAckRequest, client=self.parent
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
487 )
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
488 self.xmlstream.addObserver(
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
489 SM_A_REQUEST, self.plugin_parent.onAckAnswer, client=self.parent
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
490 )
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
491
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
492 def getDiscoInfo(self, requestor, target, nodeIdentifier=""):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
493 return [disco.DiscoFeature(NS_SM)]
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
494
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
495 def getDiscoItems(self, requestor, target, nodeIdentifier=""):
1ecceac3df96 plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
496 return []