Mercurial > libervia-backend
comparison sat/core/xmpp.py @ 3244:b10d207f95f9
core (xmpp): properly clean profile data in case of startConnection failure:
- profile is now always removed from profiles_connecting
- an exception is raised if client already exists only if client is connected. Otherwise,
it's deleted (this allow to keep session open to e.g. modify settings in case of failure
during connection)
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 01 Apr 2020 16:17:09 +0200 |
parents | 199fc4c551e9 |
children | f16c96c7a91a |
comparison
equal
deleted
inserted
replaced
3243:f2e30aa031e9 | 3244:b10d207f95f9 |
---|---|
161 # (independently of connection/deconnection) | 161 # (independently of connection/deconnection) |
162 if profile in cls.profiles_connecting: | 162 if profile in cls.profiles_connecting: |
163 raise exceptions.CancelError(f"{profile} is already being connected") | 163 raise exceptions.CancelError(f"{profile} is already being connected") |
164 cls.profiles_connecting.add(profile) | 164 cls.profiles_connecting.add(profile) |
165 try: | 165 try: |
166 port = int( | 166 try: |
167 host.memory.getParamA( | 167 port = int( |
168 C.FORCE_PORT_PARAM, "Connection", profile_key=profile | 168 host.memory.getParamA( |
169 C.FORCE_PORT_PARAM, "Connection", profile_key=profile | |
170 ) | |
169 ) | 171 ) |
172 except ValueError: | |
173 log.debug(_("Can't parse port value, using default value")) | |
174 port = ( | |
175 None | |
176 ) # will use default value 5222 or be retrieved from a DNS SRV record | |
177 | |
178 password = await host.memory.asyncGetParamA( | |
179 "Password", "Connection", profile_key=profile | |
170 ) | 180 ) |
171 except ValueError: | 181 |
172 log.debug(_("Can't parse port value, using default value")) | 182 entity_jid_s = await host.memory.asyncGetParamA( |
173 port = ( | 183 "JabberID", "Connection", profile_key=profile) |
174 None | 184 entity_jid = jid.JID(entity_jid_s) |
175 ) # will use default value 5222 or be retrieved from a DNS SRV record | 185 |
176 | 186 if not entity_jid.resource and not cls.is_component and entity_jid.user: |
177 password = await host.memory.asyncGetParamA( | 187 # if no resource is specified, we create our own instead of using |
178 "Password", "Connection", profile_key=profile | 188 # server returned one, as it will then stay stable in case of |
179 ) | 189 # reconnection. we only do that for client and if there is a user part, to |
180 | 190 # let server decide for anonymous login |
181 entity_jid_s = await host.memory.asyncGetParamA( | 191 resource_dict = await host.memory.storage.getPrivates( |
182 "JabberID", "Connection", profile_key=profile) | 192 "core:xmpp", ["resource"] , profile=profile) |
183 entity_jid = jid.JID(entity_jid_s) | 193 try: |
184 | 194 resource = resource_dict["resource"] |
185 if not entity_jid.resource and not cls.is_component and entity_jid.user: | 195 except KeyError: |
186 # if no resource is specified, we create our own instead of using | 196 resource = f"{C.APP_NAME_FILE}.{shortuuid.uuid()}" |
187 # server returned one, as it will then stay stable in case of reconnection. | 197 await host.memory.storage.setPrivateValue( |
188 # we only do that for client and if there is a user part, to let server | 198 "core:xmpp", "resource", resource, profile=profile) |
189 # decide for anonymous login | 199 |
190 resource_dict = await host.memory.storage.getPrivates( | 200 log.info(_("We'll use the stable resource {resource}").format( |
191 "core:xmpp", ["resource"] , profile=profile) | 201 resource=resource)) |
192 try: | 202 entity_jid.resource = resource |
193 resource = resource_dict["resource"] | 203 |
194 except KeyError: | 204 if profile in host.profiles: |
195 resource = f"{C.APP_NAME_FILE}.{shortuuid.uuid()}" | 205 if host.profiles[profile].isConnected(): |
196 await host.memory.storage.setPrivateValue( | 206 raise exceptions.InternalError( |
197 "core:xmpp", "resource", resource, profile=profile) | 207 f"There is already a connected profile of name {profile!r} in " |
198 | 208 f"host") |
199 log.info(_("We'll use the stable resource {resource}").format( | 209 log.debug( |
200 resource=resource)) | 210 "removing unconnected profile {profile!r}") |
201 entity_jid.resource = resource | 211 del host.profiles[profile] |
202 | 212 entity = host.profiles[profile] = cls( |
203 if profile in host.profiles: | 213 host, profile, entity_jid, password, |
204 raise exceptions.InternalError( | 214 host.memory.getParamA(C.FORCE_SERVER_PARAM, "Connection", |
205 f"There is already a profile of name {profile} in host") | 215 profile_key=profile) or None, |
206 entity = host.profiles[profile] = cls( | 216 port, max_retries, |
207 host, profile, entity_jid, password, | 217 ) |
208 host.memory.getParamA(C.FORCE_SERVER_PARAM, "Connection", | 218 |
209 profile_key=profile) or None, | 219 await entity.encryption.loadSessions() |
210 port, max_retries, | 220 |
211 ) | 221 entity._createSubProtocols() |
212 | 222 |
213 await entity.encryption.loadSessions() | 223 entity.fallBack = SatFallbackHandler(host) |
214 | 224 entity.fallBack.setHandlerParent(entity) |
215 entity._createSubProtocols() | 225 |
216 | 226 entity.versionHandler = SatVersionHandler(C.APP_NAME_FULL, host.full_version) |
217 entity.fallBack = SatFallbackHandler(host) | 227 entity.versionHandler.setHandlerParent(entity) |
218 entity.fallBack.setHandlerParent(entity) | 228 |
219 | 229 entity.identityHandler = SatIdentityHandler() |
220 entity.versionHandler = SatVersionHandler(C.APP_NAME_FULL, host.full_version) | 230 entity.identityHandler.setHandlerParent(entity) |
221 entity.versionHandler.setHandlerParent(entity) | 231 |
222 | 232 log.debug(_("setting plugins parents")) |
223 entity.identityHandler = SatIdentityHandler() | 233 |
224 entity.identityHandler.setHandlerParent(entity) | 234 plugin_conn_cb = await entity._callConnectionTriggers() |
225 | 235 |
226 log.debug(_("setting plugins parents")) | 236 entity.startService() |
227 | 237 |
228 plugin_conn_cb = await entity._callConnectionTriggers() | 238 await entity.conn_deferred |
229 | 239 |
230 entity.startService() | 240 await defer.maybeDeferred(entity.entityConnected) |
231 | 241 |
232 await entity.conn_deferred | 242 # Call profileConnected callback for all plugins, |
233 | 243 # and print error message if any of them fails |
234 await defer.maybeDeferred(entity.entityConnected) | 244 conn_cb_list = [] |
235 | 245 for __, callback in plugin_conn_cb: |
236 # Call profileConnected callback for all plugins, | 246 conn_cb_list.append(utils.asDeferred(callback, entity)) |
237 # and print error message if any of them fails | 247 list_d = defer.DeferredList(conn_cb_list) |
238 conn_cb_list = [] | 248 |
239 for __, callback in plugin_conn_cb: | 249 def logPluginResults(results): |
240 conn_cb_list.append(utils.asDeferred(callback, entity)) | 250 all_succeed = all([success for success, result in results]) |
241 list_d = defer.DeferredList(conn_cb_list) | 251 if not all_succeed: |
242 | 252 log.error(_("Plugins initialisation error")) |
243 def logPluginResults(results): | 253 for idx, (success, result) in enumerate(results): |
244 all_succeed = all([success for success, result in results]) | 254 if not success: |
245 if not all_succeed: | 255 log.error( |
246 log.error(_("Plugins initialisation error")) | 256 "error (plugin %(name)s): %(failure)s" |
247 for idx, (success, result) in enumerate(results): | 257 % { |
248 if not success: | 258 "name": plugin_conn_cb[idx][0]._info["import_name"], |
249 log.error( | 259 "failure": result, |
250 "error (plugin %(name)s): %(failure)s" | 260 } |
251 % { | 261 ) |
252 "name": plugin_conn_cb[idx][0]._info["import_name"], | 262 |
253 "failure": result, | 263 await list_d.addCallback( |
254 } | 264 logPluginResults |
255 ) | 265 ) # FIXME: we should have a timeout here, and a way to know if a plugin freeze |
256 | 266 # TODO: mesure launch time of each plugin |
257 await list_d.addCallback( | 267 finally: |
258 logPluginResults | 268 cls.profiles_connecting.remove(profile) |
259 ) # FIXME: we should have a timeout here, and a way to know if a plugin freeze | |
260 # TODO: mesure launch time of each plugin | |
261 | |
262 cls.profiles_connecting.remove(profile) | |
263 | 269 |
264 def _disconnectionCb(self, __): | 270 def _disconnectionCb(self, __): |
265 self._connected_d = None | 271 self._connected_d = None |
266 | 272 |
267 def _disconnectionEb(self, failure_): | 273 def _disconnectionEb(self, failure_): |