Mercurial > libervia-backend
comparison sat/core/xmpp.py @ 3153:2c7b42f53e9a
core (xmpp): avoid starting several clients at the same time:
a check is done to avoid running startConnection several times at once, which would lead
to the creation of several SatXMPPEntity instances at the same time, resulting in many
issues.
If startConnection is called while a previous one is not finished yet, a CancelError is
now raised.
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 03 Feb 2020 13:46:24 +0100 |
parents | f3700175c6a3 |
children | b5c058c7692e |
comparison
equal
deleted
inserted
replaced
3152:7ce31f347ca3 | 3153:2c7b42f53e9a |
---|---|
54 # we use 2 "@" which is illegal in a jid, to be sure we are not mixing keys | 54 # we use 2 "@" which is illegal in a jid, to be sure we are not mixing keys |
55 # with roster jids | 55 # with roster jids |
56 ROSTER_VER_KEY = "@version@" | 56 ROSTER_VER_KEY = "@version@" |
57 | 57 |
58 | 58 |
59 class SatXMPPEntity(object): | 59 class SatXMPPEntity: |
60 """Common code for Client and Component""" | 60 """Common code for Client and Component""" |
61 # profile is added there when startConnection begins and removed when it is finished | |
62 profiles_connecting = set() | |
61 | 63 |
62 def __init__(self, host_app, profile, max_retries): | 64 def __init__(self, host_app, profile, max_retries): |
63 factory = self.factory | 65 factory = self.factory |
64 | 66 |
65 # we monkey patch clientConnectionLost to handle networkEnabled/networkDisabled | 67 # we monkey patch clientConnectionLost to handle networkEnabled/networkDisabled |
152 # (client is deleted then recreated from scratch) | 154 # (client is deleted then recreated from scratch) |
153 # most of methods called here should be called once on first connection | 155 # most of methods called here should be called once on first connection |
154 # (e.g. adding subprotocols) | 156 # (e.g. adding subprotocols) |
155 # but client should not be deleted except if session is finished | 157 # but client should not be deleted except if session is finished |
156 # (independently of connection/deconnection) | 158 # (independently of connection/deconnection) |
159 if profile in cls.profiles_connecting: | |
160 raise exceptions.CancelError(f"{profile} is already being connected") | |
161 cls.profiles_connecting.add(profile) | |
157 try: | 162 try: |
158 port = int( | 163 port = int( |
159 host.memory.getParamA( | 164 host.memory.getParamA( |
160 C.FORCE_PORT_PARAM, "Connection", profile_key=profile | 165 C.FORCE_PORT_PARAM, "Connection", profile_key=profile |
161 ) | 166 ) |
167 ) # will use default value 5222 or be retrieved from a DNS SRV record | 172 ) # will use default value 5222 or be retrieved from a DNS SRV record |
168 | 173 |
169 password = yield host.memory.asyncGetParamA( | 174 password = yield host.memory.asyncGetParamA( |
170 "Password", "Connection", profile_key=profile | 175 "Password", "Connection", profile_key=profile |
171 ) | 176 ) |
172 if profile in host.profiles: | |
173 raise exceptions.InternalError( | |
174 f"There is already a profile of name {profile} in host") | |
175 | 177 |
176 entity_jid_s = yield host.memory.asyncGetParamA( | 178 entity_jid_s = yield host.memory.asyncGetParamA( |
177 "JabberID", "Connection", profile_key=profile) | 179 "JabberID", "Connection", profile_key=profile) |
178 entity_jid = jid.JID(entity_jid_s) | 180 entity_jid = jid.JID(entity_jid_s) |
179 | 181 |
193 | 195 |
194 log.info(_("We'll use the stable resource {resource}").format( | 196 log.info(_("We'll use the stable resource {resource}").format( |
195 resource=resource)) | 197 resource=resource)) |
196 entity_jid.resource = resource | 198 entity_jid.resource = resource |
197 | 199 |
200 if profile in host.profiles: | |
201 raise exceptions.InternalError( | |
202 f"There is already a profile of name {profile} in host") | |
198 entity = host.profiles[profile] = cls( | 203 entity = host.profiles[profile] = cls( |
199 host, profile, entity_jid, password, | 204 host, profile, entity_jid, password, |
200 host.memory.getParamA(C.FORCE_SERVER_PARAM, "Connection", | 205 host.memory.getParamA(C.FORCE_SERVER_PARAM, "Connection", |
201 profile_key=profile) or None, | 206 profile_key=profile) or None, |
202 port, max_retries, | 207 port, max_retries, |
246 | 251 |
247 yield list_d.addCallback( | 252 yield list_d.addCallback( |
248 logPluginResults | 253 logPluginResults |
249 ) # FIXME: we should have a timeout here, and a way to know if a plugin freeze | 254 ) # FIXME: we should have a timeout here, and a way to know if a plugin freeze |
250 # TODO: mesure launch time of each plugin | 255 # TODO: mesure launch time of each plugin |
256 | |
257 cls.profiles_connecting.remove(profile) | |
251 | 258 |
252 def _disconnectionCb(self, __): | 259 def _disconnectionCb(self, __): |
253 self._connected_d = None | 260 self._connected_d = None |
254 | 261 |
255 def _disconnectionEb(self, failure_): | 262 def _disconnectionEb(self, failure_): |
782 self.presence.setHandlerParent(self) | 789 self.presence.setHandlerParent(self) |
783 | 790 |
784 @classmethod | 791 @classmethod |
785 @defer.inlineCallbacks | 792 @defer.inlineCallbacks |
786 def startConnection(cls, host, profile, max_retries): | 793 def startConnection(cls, host, profile, max_retries): |
787 yield super(SatXMPPClient, cls).startConnection(host, profile, max_retries) | 794 try: |
795 yield super(SatXMPPClient, cls).startConnection(host, profile, max_retries) | |
796 except exceptions.CancelError as e: | |
797 log.warning(f"startConnection cancelled: {e}") | |
798 return | |
788 entity = host.profiles[profile] | 799 entity = host.profiles[profile] |
789 # we finally send our presence | 800 # we finally send our presence |
790 entity.presence.available() | 801 entity.presence.available() |
791 | 802 |
792 def entityConnected(self): | 803 def entityConnected(self): |