Mercurial > libervia-backend
annotate sat/plugins/plugin_xep_0198.py @ 3101:ab7e8ade848a
plugin XEP-0045: added room statuses to metadata:
room statuses are now sent with other metadata on bridge signals, and saved in Room
instance. They give useful data on the room, for instance they can be used to know if a
full jid is used in this room.
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 30 Dec 2019 20:44:02 +0100 |
parents | ab2696e34d29 |
children | 87b8808ac49d |
rev | line source |
---|---|
3028 | 1 #!/usr/bin/env python3 |
2691
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 |
3028 | 31 from zope.interface import implementer |
2691
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 = { |
3028 | 38 C.PI_NAME: "Stream Management", |
39 C.PI_IMPORT_NAME: "XEP-0198", | |
40 C.PI_TYPE: "XEP", | |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
41 C.PI_MODES: C.PLUG_MODE_BOTH, |
3028 | 42 C.PI_PROTOCOLS: ["XEP-0198"], |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
43 C.PI_DEPENDENCIES: [], |
3028 | 44 C.PI_RECOMMENDATIONS: ["XEP-0045", "XEP-0313"], |
45 C.PI_MAIN: "XEP_0198", | |
46 C.PI_HANDLER: "yes", | |
47 C.PI_DESCRIPTION: _("""Implementation of Stream Management"""), | |
2691
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 |
3028 | 50 NS_SM = "urn:xmpp:sm:3" |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
51 SM_ENABLED = '/enabled[@xmlns="' + NS_SM + '"]' |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
52 SM_RESUMED = '/resumed[@xmlns="' + NS_SM + '"]' |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
53 SM_FAILED = '/failed[@xmlns="' + NS_SM + '"]' |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
54 SM_R_REQUEST = '/r[@xmlns="' + NS_SM + '"]' |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
55 SM_A_REQUEST = '/a[@xmlns="' + NS_SM + '"]' |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
56 SM_H_REQUEST = '/h[@xmlns="' + NS_SM + '"]' |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
57 # Max number of stanza to send before requesting ack |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
58 MAX_STANZA_ACK_R = 5 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
59 # Max number of seconds before requesting ack |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
60 MAX_DELAY_ACK_R = 30 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
61 MAX_COUNTER = 2**32 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
62 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
|
63 # 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
|
64 ACK_TIMEOUT = 35 |
2691
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 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
67 class ProfileSessionData(object): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
68 out_counter = 0 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
69 in_counter = 0 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
70 session_id = None |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
71 location = None |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
72 session_max = None |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
73 # True when an ack answer is expected |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
74 ack_requested = False |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
75 last_ack_r = 0 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
76 disconnected_time = None |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
77 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
78 def __init__(self, callback, **kw): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
79 self.buffer = collections.deque() |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
80 self.buffer_idx = 0 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
81 self._enabled = False |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
82 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
|
83 # 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
|
84 # 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
|
85 self.req_timer = None |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
86 self.callback_data = (callback, kw) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
87 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
88 @property |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
89 def enabled(self): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
90 return self._enabled |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
91 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
92 @enabled.setter |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
93 def enabled(self, enabled): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
94 if enabled: |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
95 if self._enabled: |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
96 raise exceptions.InternalError( |
3028 | 97 "Stream Management can't be enabled twice") |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
98 self._enabled = True |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
99 callback, kw = self.callback_data |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
100 self.timer = task.LoopingCall(callback, **kw) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
101 self.timer.start(MAX_DELAY_ACK_R, now=False) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
102 else: |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
103 self._enabled = False |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
104 if self.timer is not None: |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
105 self.timer.stop() |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
106 self.timer = None |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
107 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
108 @property |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
109 def resume_enabled(self): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
110 return self.session_id is not None |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
111 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
112 def reset(self): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
113 self.enabled = False |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
114 self.buffer.clear() |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
115 self.buffer_idx = 0 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
116 self.in_counter = self.out_counter = 0 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
117 self.session_id = self.location = None |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
118 self.ack_requested = False |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
119 self.last_ack_r = 0 |
2865
9213c6dff48d
plugin XEP-0198: reset req_timer on session.reset():
Goffi <goffi@goffi.org>
parents:
2796
diff
changeset
|
120 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
|
121 if self.req_timer.active(): |
3028 | 122 log.error("req_timer has been called/cancelled but not reset") |
2865
9213c6dff48d
plugin XEP-0198: reset req_timer on session.reset():
Goffi <goffi@goffi.org>
parents:
2796
diff
changeset
|
123 else: |
9213c6dff48d
plugin XEP-0198: reset req_timer on session.reset():
Goffi <goffi@goffi.org>
parents:
2796
diff
changeset
|
124 self.req_timer.cancel() |
9213c6dff48d
plugin XEP-0198: reset req_timer on session.reset():
Goffi <goffi@goffi.org>
parents:
2796
diff
changeset
|
125 self.req_timer = None |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
126 |
3011
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
127 def getBufferCopy(self): |
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
128 return list(self.buffer) |
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
129 |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
130 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
131 class XEP_0198(object): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
132 # FIXME: location is not handled yet |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
133 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
134 def __init__(self, host): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
135 log.info(_("Plugin Stream Management initialization")) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
136 self.host = host |
3028 | 137 host.registerNamespace('sm', NS_SM) |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
138 host.trigger.add("stream_hooks", self.addHooks) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
139 host.trigger.add("xml_init", self._XMLInitTrigger) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
140 host.trigger.add("disconnecting", self._disconnectingTrigger) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
141 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
|
142 try: |
59ac9284dee8
plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents:
2725
diff
changeset
|
143 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
|
144 except ValueError: |
3028 | 145 log.error(_("Invalid ack_timeout value, please check your configuration")) |
2727
59ac9284dee8
plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents:
2725
diff
changeset
|
146 self._ack_timeout = ACK_TIMEOUT |
59ac9284dee8
plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents:
2725
diff
changeset
|
147 if not self._ack_timeout: |
3028 | 148 log.info(_("Ack timeout disabled")) |
2727
59ac9284dee8
plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents:
2725
diff
changeset
|
149 else: |
3028 | 150 log.info(_("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
|
151 timeout=self._ack_timeout)) |
2691
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 profileConnecting(self, client): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
154 client._xep_0198_session = ProfileSessionData(callback=self.checkAcks, |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
155 client=client) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
156 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
157 def getHandler(self, client): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
158 return XEP_0198_handler(self) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
159 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
160 def addHooks(self, client, receive_hooks, send_hooks): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
161 """Add hooks to handle in/out stanzas counters""" |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
162 receive_hooks.append(partial(self.onReceive, client=client)) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
163 send_hooks.append(partial(self.onSend, client=client)) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
164 return True |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
165 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
166 def _XMLInitTrigger(self, client): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
167 """Enable or resume a stream mangement""" |
3028 | 168 if not (NS_SM, 'sm') in client.xmlstream.features: |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
169 log.warning(_( |
3028 | 170 "Your server doesn't support stream management ({namespace}), this is " |
171 "used to improve connection problems detection (like network outages). " | |
172 "Please ask your server administrator to enable this feature.".format( | |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
173 namespace=NS_SM))) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
174 return True |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
175 session = client._xep_0198_session |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
176 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
177 # 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
|
178 try: |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
179 disconnect_timer = session.disconnect_timer |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
180 except AttributeError: |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
181 pass |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
182 else: |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
183 if disconnect_timer.active(): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
184 disconnect_timer.cancel() |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
185 del session.disconnect_timer |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
186 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
187 if session.resume_enabled: |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
188 # we are resuming a session |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
189 resume_elt = domish.Element((NS_SM, 'resume')) |
3028 | 190 resume_elt['h'] = str(session.in_counter) |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
191 resume_elt['previd'] = session.session_id |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
192 client.send(resume_elt) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
193 session.resuming = True |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
194 # session.enabled will be set on <resumed/> reception |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
195 return False |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
196 else: |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
197 # we start a new session |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
198 assert session.out_counter == 0 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
199 enable_elt = domish.Element((NS_SM, 'enable')) |
3028 | 200 enable_elt['resume'] = 'true' |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
201 client.send(enable_elt) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
202 session.enabled = True |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
203 return True |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
204 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
205 def _disconnectingTrigger(self, client): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
206 session = client._xep_0198_session |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
207 if session.enabled: |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
208 self.sendAck(client) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
209 # 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
|
210 # to disable resuming and close normally the stream |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
211 session.reset() |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
212 return True |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
213 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
214 def _disconnectedTrigger(self, client, reason): |
2796
fdc53c8a5439
plugin XEP-0198: don't use hooks on components
Goffi <goffi@goffi.org>
parents:
2795
diff
changeset
|
215 if client.is_component: |
fdc53c8a5439
plugin XEP-0198: don't use hooks on components
Goffi <goffi@goffi.org>
parents:
2795
diff
changeset
|
216 return True |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
217 session = client._xep_0198_session |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
218 session.enabled = False |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
219 if session.resume_enabled: |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
220 session.disconnected_time = time.time() |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
221 session.disconnect_timer = reactor.callLater(session.session_max, |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
222 client.disconnectProfile, |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
223 reason) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
224 # disconnectProfile must not be called at this point |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
225 # because session can be resumed |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
226 return False |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
227 else: |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
228 return True |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
229 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
230 def checkAcks(self, client): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
231 """Request ack if needed""" |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
232 session = client._xep_0198_session |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
233 # 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
|
234 # .format(session.in_counter, session.out_counter, len(session.buffer), |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
235 # session.buffer_idx)) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
236 if session.ack_requested or not session.buffer: |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
237 return |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
238 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
|
239 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
|
240 self.requestAck(client) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
241 session.ack_requested = True |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
242 session.last_ack_r = time.time() |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
243 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
244 def updateBuffer(self, session, server_acked): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
245 """Update buffer and buffer_index""" |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
246 if server_acked > session.buffer_idx: |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
247 diff = server_acked - session.buffer_idx |
3019
c9f03b1eb64d
plugin XEP-0198: catch and log an error if buffer is unexpectedly empty
Goffi <goffi@goffi.org>
parents:
3011
diff
changeset
|
248 try: |
3028 | 249 for i in range(diff): |
3019
c9f03b1eb64d
plugin XEP-0198: catch and log an error if buffer is unexpectedly empty
Goffi <goffi@goffi.org>
parents:
3011
diff
changeset
|
250 session.buffer.pop() |
c9f03b1eb64d
plugin XEP-0198: catch and log an error if buffer is unexpectedly empty
Goffi <goffi@goffi.org>
parents:
3011
diff
changeset
|
251 except IndexError: |
c9f03b1eb64d
plugin XEP-0198: catch and log an error if buffer is unexpectedly empty
Goffi <goffi@goffi.org>
parents:
3011
diff
changeset
|
252 log.error( |
3028 | 253 "error while cleaning buffer, invalid index (buffer is empty):\n" |
254 "diff = {diff}\n" | |
255 "server_acked = {server_acked}\n" | |
256 "buffer_idx = {buffer_id}".format( | |
3019
c9f03b1eb64d
plugin XEP-0198: catch and log an error if buffer is unexpectedly empty
Goffi <goffi@goffi.org>
parents:
3011
diff
changeset
|
257 diff=diff, server_acked=server_acked, |
c9f03b1eb64d
plugin XEP-0198: catch and log an error if buffer is unexpectedly empty
Goffi <goffi@goffi.org>
parents:
3011
diff
changeset
|
258 buffer_id=session.buffer_idx)) |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
259 session.buffer_idx += diff |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
260 |
3011
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
261 def replayBuffer(self, client, buffer_, discard_results=False): |
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
262 """Resend all stanza in buffer |
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
263 |
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
264 @param buffer_(collection.deque, list): buffer to replay |
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
265 the buffer will be cleared by this method |
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
266 @param discard_results(bool): if True, don't replay IQ result stanzas |
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
267 """ |
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
268 while True: |
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
269 try: |
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
270 stanza = buffer_.pop() |
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
271 except IndexError: |
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
272 break |
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
273 else: |
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
274 if ((discard_results |
3028 | 275 and stanza.name == 'iq' |
276 and stanza.getAttribute('type') == 'result')): | |
3011
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
277 continue |
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
278 client.send(stanza) |
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
279 |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
280 def sendAck(self, client): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
281 """Send an answer element with current IN counter""" |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
282 a_elt = domish.Element((NS_SM, 'a')) |
3028 | 283 a_elt['h'] = str(client._xep_0198_session.in_counter) |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
284 client.send(a_elt) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
285 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
286 def requestAck(self, client): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
287 """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
|
288 session = client._xep_0198_session |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
289 r_elt = domish.Element((NS_SM, 'r')) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
290 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
|
291 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
|
292 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
|
293 if self._ack_timeout: |
59ac9284dee8
plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents:
2725
diff
changeset
|
294 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
|
295 client) |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
296 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
297 def _connectionFailed(self, failure_, connector): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
298 normal_host, normal_port = connector.normal_location |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
299 del connector.normal_location |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
300 log.warning(_( |
3028 | 301 "Connection failed using location given by server (host: {host}, port: " |
302 "{port}), switching to normal host and port (host: {normal_host}, port: " | |
303 "{normal_port})".format(host=connector.host, port=connector.port, | |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
304 normal_host=normal_host, normal_port=normal_port))) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
305 connector.host, connector.port = normal_host, normal_port |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
306 connector.connectionFailed = connector.connectionFailed_ori |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
307 del connector.connectionFailed_ori |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
308 return connector.connectionFailed(failure_) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
309 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
310 def onEnabled(self, enabled_elt, client): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
311 session = client._xep_0198_session |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
312 session.in_counter = 0 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
313 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
314 # we check that resuming is possible and that we have a session id |
3028 | 315 resume = C.bool(enabled_elt.getAttribute('resume')) |
316 session_id = enabled_elt.getAttribute('id') | |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
317 if not session_id: |
3028 | 318 log.warning(_('Incorrect <enabled/> element received, no "id" attribute')) |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
319 if not resume or not session_id: |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
320 log.warning(_( |
3028 | 321 "You're server doesn't support session resuming with stream management, " |
322 "please contact your server administrator to enable it")) | |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
323 return |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
324 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
325 session.session_id = session_id |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
326 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
327 # XXX: we disable resource binding, which must not be done |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
328 # when we resume the session. |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
329 client.factory.authenticator.res_binding = False |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
330 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
331 # location, in case server want resuming session to be elsewhere |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
332 try: |
3028 | 333 location = enabled_elt['location'] |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
334 except KeyError: |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
335 pass |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
336 else: |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
337 # TODO: handle IPv6 here (in brackets, cf. XEP) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
338 try: |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
339 domain, port = location.split(':', 1) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
340 port = int(port) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
341 except ValueError: |
3028 | 342 log.warning(_("Invalid location received: {location}") |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
343 .format(location=location)) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
344 else: |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
345 session.location = (domain, port) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
346 # we monkey patch connector to use the new location |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
347 connector = client.xmlstream.transport.connector |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
348 connector.normal_location = connector.host, connector.port |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
349 connector.host = domain |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
350 connector.port = port |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
351 connector.connectionFailed_ori = connector.connectionFailed |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
352 connector.connectionFailed = partial(self._connectionFailed, |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
353 connector=connector) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
354 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
355 # resuming time |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
356 try: |
3028 | 357 max_s = int(enabled_elt['max']) |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
358 except (ValueError, KeyError) as e: |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
359 if isinstance(e, ValueError): |
3028 | 360 log.warning(_('Invalid "max" attribute')) |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
361 max_s = RESUME_MAX |
3028 | 362 log.info(_("Using default session max value ({max_s} s).".format( |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
363 max_s=max_s))) |
3028 | 364 log.info(_("Stream Management enabled")) |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
365 else: |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
366 log.info(_( |
3028 | 367 "Stream Management enabled, with a resumption time of {res_m} min" |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
368 .format(res_m = max_s/60))) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
369 session.session_max = max_s |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
370 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
371 def onResumed(self, enabled_elt, client): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
372 session = client._xep_0198_session |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
373 assert not session.enabled |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
374 del session.resuming |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
375 server_acked = int(enabled_elt['h']) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
376 self.updateBuffer(session, server_acked) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
377 resend_count = len(session.buffer) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
378 # we resend all stanza which have not been received properly |
3011
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
379 self.replayBuffer(client, session.buffer) |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
380 # now we can continue the session |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
381 session.enabled = True |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
382 d_time = time.time() - session.disconnected_time |
3028 | 383 log.info(_("Stream session resumed (disconnected for {d_time} s, {count} " |
384 "stanza(s) resent)").format(d_time=int(d_time), count=resend_count)) | |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
385 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
386 def onFailed(self, failed_elt, client): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
387 session = client._xep_0198_session |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
388 condition_elt = failed_elt.firstChildElement() |
3011
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
389 buffer_ = session.getBufferCopy() |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
390 session.reset() |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
391 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
392 try: |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
393 del session.resuming |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
394 except AttributeError: |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
395 # stream management can't be started at all |
3028 | 396 msg = _("Can't use stream management") |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
397 if condition_elt is None: |
3028 | 398 log.error(msg + '.') |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
399 else: |
3028 | 400 log.error(_("{msg}: {reason}").format( |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
401 msg=msg, reason=condition_elt.name)) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
402 else: |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
403 # only stream resumption failed, we can try full session init |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
404 # 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
|
405 # variables/attributes already initialised with a potentially different |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
406 # 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
|
407 # 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
|
408 # client. |
3028 | 409 msg = _("stream resumption not possible, restarting full session") |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
410 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
411 if condition_elt is None: |
3028 | 412 log.warning('{msg}.'.format(msg=msg)) |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
413 else: |
3028 | 414 log.warning("{msg}: {reason}".format( |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
415 msg=msg, reason=condition_elt.name)) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
416 # 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
|
417 # 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
|
418 # we keep everything initialized, and only do binding, roster request |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
419 # and initial presence sending. |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
420 if client.conn_deferred.called: |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
421 client.conn_deferred = defer.Deferred() |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
422 else: |
3028 | 423 log.error("conn_deferred should be called at this point") |
424 plg_0045 = self.host.plugins.get('XEP-0045') | |
425 plg_0313 = self.host.plugins.get('XEP-0313') | |
3011
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
426 |
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
427 # FIXME: we should call all loaded plugins with generic callbacks |
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
428 # (e.g. prepareResume and resume), so a hot resuming can be done |
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
429 # properly for all plugins. |
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
430 |
3008
c8c68a3b0a79
plugins XEP-0045, XEP-0198: rejoin MUC rooms while a hot reconnection is done:
Goffi <goffi@goffi.org>
parents:
2865
diff
changeset
|
431 if plg_0045 is not None: |
c8c68a3b0a79
plugins XEP-0045, XEP-0198: rejoin MUC rooms while a hot reconnection is done:
Goffi <goffi@goffi.org>
parents:
2865
diff
changeset
|
432 # we have to remove joined rooms |
c8c68a3b0a79
plugins XEP-0045, XEP-0198: rejoin MUC rooms while a hot reconnection is done:
Goffi <goffi@goffi.org>
parents:
2865
diff
changeset
|
433 muc_join_args = plg_0045.popRooms(client) |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
434 # we need to recreate roster |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
435 client.handlers.remove(client.roster) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
436 client.roster = client.roster.__class__(self.host) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
437 client.roster.setHandlerParent(client) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
438 # 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
|
439 bind_init = jabber_client.BindInitializer(client.xmlstream) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
440 bind_init.required = True |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
441 d = bind_init.start() |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
442 # we set the jid, which may have changed |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
443 d.addCallback(lambda __: setattr(client.factory.authenticator, "jid", client.jid)) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
444 # we call the trigger who will send the <enable/> element |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
445 d.addCallback(lambda __: self._XMLInitTrigger(client)) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
446 # 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
|
447 d.addCallback(lambda __: client.roster.requestRoster()) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
448 # 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
|
449 d.addCallback(lambda __: client.roster.got_roster) |
3011
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
450 if plg_0313 is not None: |
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
451 # we retrieve one2one MAM archives |
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
452 d.addCallback(lambda __: plg_0313.resume(client)) |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
453 # initial presence must be sent manually |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
454 d.addCallback(lambda __: client.presence.available()) |
3008
c8c68a3b0a79
plugins XEP-0045, XEP-0198: rejoin MUC rooms while a hot reconnection is done:
Goffi <goffi@goffi.org>
parents:
2865
diff
changeset
|
455 if plg_0045 is not None: |
3011
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
456 # we re-join MUC rooms |
3008
c8c68a3b0a79
plugins XEP-0045, XEP-0198: rejoin MUC rooms while a hot reconnection is done:
Goffi <goffi@goffi.org>
parents:
2865
diff
changeset
|
457 muc_d_list = defer.DeferredList( |
c8c68a3b0a79
plugins XEP-0045, XEP-0198: rejoin MUC rooms while a hot reconnection is done:
Goffi <goffi@goffi.org>
parents:
2865
diff
changeset
|
458 [plg_0045.join(*args) for args in muc_join_args]) |
c8c68a3b0a79
plugins XEP-0045, XEP-0198: rejoin MUC rooms while a hot reconnection is done:
Goffi <goffi@goffi.org>
parents:
2865
diff
changeset
|
459 d.addCallback(lambda __: muc_d_list) |
3011
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
460 # at the end we replay the buffer, as those stanzas have probably not |
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
461 # been received |
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
462 d.addCallback(lambda __: self.replayBuffer(client, buffer_, |
93da7c6f8e0c
plugin XEP-0198: retrieve missing messages + send buffered ones on hot reconnection:
Goffi <goffi@goffi.org>
parents:
3008
diff
changeset
|
463 discard_results=True)) |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
464 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
465 def onReceive(self, element, client): |
2796
fdc53c8a5439
plugin XEP-0198: don't use hooks on components
Goffi <goffi@goffi.org>
parents:
2795
diff
changeset
|
466 if not client.is_component: |
fdc53c8a5439
plugin XEP-0198: don't use hooks on components
Goffi <goffi@goffi.org>
parents:
2795
diff
changeset
|
467 session = client._xep_0198_session |
fdc53c8a5439
plugin XEP-0198: don't use hooks on components
Goffi <goffi@goffi.org>
parents:
2795
diff
changeset
|
468 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
|
469 session.in_counter += 1 % MAX_COUNTER |
2691
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 onSend(self, obj, client): |
2796
fdc53c8a5439
plugin XEP-0198: don't use hooks on components
Goffi <goffi@goffi.org>
parents:
2795
diff
changeset
|
472 if not client.is_component: |
fdc53c8a5439
plugin XEP-0198: don't use hooks on components
Goffi <goffi@goffi.org>
parents:
2795
diff
changeset
|
473 session = client._xep_0198_session |
fdc53c8a5439
plugin XEP-0198: don't use hooks on components
Goffi <goffi@goffi.org>
parents:
2795
diff
changeset
|
474 if (session.enabled |
fdc53c8a5439
plugin XEP-0198: don't use hooks on components
Goffi <goffi@goffi.org>
parents:
2795
diff
changeset
|
475 and domish.IElement.providedBy(obj) |
fdc53c8a5439
plugin XEP-0198: don't use hooks on components
Goffi <goffi@goffi.org>
parents:
2795
diff
changeset
|
476 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
|
477 session.out_counter += 1 % MAX_COUNTER |
fdc53c8a5439
plugin XEP-0198: don't use hooks on components
Goffi <goffi@goffi.org>
parents:
2795
diff
changeset
|
478 session.buffer.appendleft(obj) |
fdc53c8a5439
plugin XEP-0198: don't use hooks on components
Goffi <goffi@goffi.org>
parents:
2795
diff
changeset
|
479 self.checkAcks(client) |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
480 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
481 def onAckRequest(self, r_elt, client): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
482 self.sendAck(client) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
483 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
484 def onAckAnswer(self, a_elt, client): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
485 session = client._xep_0198_session |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
486 session.ack_requested = False |
2727
59ac9284dee8
plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents:
2725
diff
changeset
|
487 if self._ack_timeout: |
59ac9284dee8
plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents:
2725
diff
changeset
|
488 if session.req_timer is None: |
3008
c8c68a3b0a79
plugins XEP-0045, XEP-0198: rejoin MUC rooms while a hot reconnection is done:
Goffi <goffi@goffi.org>
parents:
2865
diff
changeset
|
489 log.error("req_timer should be set") |
2727
59ac9284dee8
plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents:
2725
diff
changeset
|
490 else: |
59ac9284dee8
plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents:
2725
diff
changeset
|
491 session.req_timer.cancel() |
59ac9284dee8
plugin XEP-0198: allow to customise/disable ack_timeout:
Goffi <goffi@goffi.org>
parents:
2725
diff
changeset
|
492 session.req_timer = None |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
493 try: |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
494 server_acked = int(a_elt['h']) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
495 except ValueError: |
3028 | 496 log.warning(_("Server returned invalid ack element, disabling stream " |
497 "management: {xml}").format(xml=a_elt)) | |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
498 session.enabled = False |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
499 return |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
500 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
501 if server_acked > session.out_counter: |
3028 | 502 log.error(_("Server acked more stanzas than we have sent, disabling stream " |
503 "management.")) | |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
504 session.reset() |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
505 return |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
506 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
507 self.updateBuffer(session, server_acked) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
508 self.checkAcks(client) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
509 |
2725
d0466af33483
plugin XEP-0198: abort connection if ack is not received after a timeout:
Goffi <goffi@goffi.org>
parents:
2691
diff
changeset
|
510 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
|
511 """Called when a requested ACK has not been received in time""" |
3028 | 512 log.info(_("Ack was not received in time, aborting connection")) |
3020
af9d71303605
plugin XEP-0198: don't crash if transport is None in onAckTimeOut
Goffi <goffi@goffi.org>
parents:
3019
diff
changeset
|
513 transport = client.xmlstream.transport |
af9d71303605
plugin XEP-0198: don't crash if transport is None in onAckTimeOut
Goffi <goffi@goffi.org>
parents:
3019
diff
changeset
|
514 if transport is None: |
3028 | 515 log.warning("transport was already removed") |
3020
af9d71303605
plugin XEP-0198: don't crash if transport is None in onAckTimeOut
Goffi <goffi@goffi.org>
parents:
3019
diff
changeset
|
516 else: |
af9d71303605
plugin XEP-0198: don't crash if transport is None in onAckTimeOut
Goffi <goffi@goffi.org>
parents:
3019
diff
changeset
|
517 transport.abortConnection() |
2795
25639611c303
plugin XEP-0198: fixed typo resulting in a crash on resume
Goffi <goffi@goffi.org>
parents:
2729
diff
changeset
|
518 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
|
519 |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
520 |
3028 | 521 @implementer(iwokkel.IDisco) |
2691
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
522 class XEP_0198_handler(xmlstream.XMPPHandler): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
523 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
524 def __init__(self, plugin_parent): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
525 self.plugin_parent = plugin_parent |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
526 self.host = plugin_parent.host |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
527 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
528 def connectionInitialized(self): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
529 self.xmlstream.addObserver( |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
530 SM_ENABLED, self.plugin_parent.onEnabled, client=self.parent |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
531 ) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
532 self.xmlstream.addObserver( |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
533 SM_RESUMED, self.plugin_parent.onResumed, client=self.parent |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
534 ) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
535 self.xmlstream.addObserver( |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
536 SM_FAILED, self.plugin_parent.onFailed, client=self.parent |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
537 ) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
538 self.xmlstream.addObserver( |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
539 SM_R_REQUEST, self.plugin_parent.onAckRequest, client=self.parent |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
540 ) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
541 self.xmlstream.addObserver( |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
542 SM_A_REQUEST, self.plugin_parent.onAckAnswer, client=self.parent |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
543 ) |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
544 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
545 def getDiscoInfo(self, requestor, target, nodeIdentifier=""): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
546 return [disco.DiscoFeature(NS_SM)] |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
547 |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
548 def getDiscoItems(self, requestor, target, nodeIdentifier=""): |
1ecceac3df96
plugin XEP-0198: Stream Management implementation:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
549 return [] |