source:
ralphm-patches/c2s_server_factory.patch
@
56:fa1511cccfe2
Last change on this file since 56:fa1511cccfe2 was 54:03ec57713c90, checked in by Ralph Meijer <ralphm@…>, 11 years ago | |
---|---|
File size: 4.1 KB |
-
wokkel/client.py
# HG changeset patch # Parent 52b9931fa5f5c6aeee617a4dad3e09d041ae4361 Add factory for accepting client connections. The new XMPPC2SServerFactory is a server factory for accepting client connections. It uses `XMPPClientListenAuthenticator` to perform the steps for authentication and binding of a resource, and keeps a list of all streams. Upon loss of the connection, the service is called with `unbindResource`. Received stanzas cause the service's `onElement` to be called. The factory has a `deliverStanza` method to deliver stanzas to a particular recipient. This is used for stanzas that have different recipient addressing than the actual recipient (for presence and messages from a different (or no) resource). TODO: * Add docstrings. * Add tests. diff -r 52b9931fa5f5 wokkel/client.py
a b 16 16 from twisted.internet import reactor 17 17 from twisted.names.srvconnect import SRVConnector 18 18 from twisted.words.protocols.jabber import client, error, sasl, xmlstream 19 from twisted.words.xish import domish, utility 19 20 20 21 from wokkel import generic 21 22 from wokkel.subprotocols import StreamManager 23 from wokkel.compat import XmlStreamServerFactory 22 24 23 25 NS_CLIENT = 'jabber:client' 24 26 … … 345 347 346 348 347 349 350 class RecipientUnavailable(Exception): 351 """ 352 The addressed entity is not, or no longer, available. 353 """ 354 355 356 357 class XMPPC2SServerFactory(XmlStreamServerFactory): 358 359 def __init__(self, service): 360 self.service = service 361 362 def authenticatorFactory(): 363 return XMPPClientListenAuthenticator(service) 364 365 XmlStreamServerFactory.__init__(self, authenticatorFactory) 366 self.addBootstrap(xmlstream.STREAM_CONNECTED_EVENT, 367 self.onConnectionMade) 368 self.addBootstrap(xmlstream.STREAM_AUTHD_EVENT, 369 self.onAuthenticated) 370 371 self.serial = 0 372 self.streams = {} 373 374 375 def onConnectionMade(self, xs): 376 """ 377 Called when a client-to-server connection was made. 378 379 This enables traffic debugging on incoming streams. 380 """ 381 xs.serial = self.serial 382 self.serial += 1 383 384 log.msg("Client connection %d made" % xs.serial) 385 386 def logDataIn(buf): 387 log.msg("RECV (%d): %r" % (xs.serial, buf)) 388 389 def logDataOut(buf): 390 log.msg("SEND (%d): %r" % (xs.serial, buf)) 391 392 if self.logTraffic: 393 xs.rawDataInFn = logDataIn 394 xs.rawDataOutFn = logDataOut 395 396 xs.addObserver(xmlstream.STREAM_ERROR_EVENT, self.onError) 397 398 399 def onAuthenticated(self, xs): 400 log.msg("Client connection %d authenticated" % xs.serial) 401 402 xs.addObserver(xmlstream.STREAM_END_EVENT, self.onConnectionLost, 403 0, xs) 404 xs.addObserver('/*', self.onElement, 0, xs) 405 406 # Record this stream as bound to the authenticated JID 407 self.streams[xs.otherEntity] = xs 408 409 410 def onConnectionLost(self, xs, reason): 411 log.msg("Client connection %d disconnected" % xs.serial) 412 413 entity = xs.otherEntity 414 self.service.unbindResource(entity.user, 415 entity.host, 416 entity.resource, 417 reason) 418 419 # If the lost connections had been bound, remove the reference 420 if xs.otherEntity in self.streams: 421 del self.streams[xs.otherEntity] 422 423 424 def onError(self, reason): 425 log.err(reason, "Stream Error") 426 427 428 def onElement(self, xs, stanza): 429 """ 430 Called when an element was received from one of the connected streams. 431 432 """ 433 if stanza.handled: 434 return 435 else: 436 self.service.onElement(stanza, xs.otherEntity) 437 438 439 def deliverStanza(self, element, recipient): 440 if recipient in self.streams: 441 self.streams[recipient].send(element) 442 else: 443 raise RecipientUnavailable(u"There is no connection for %s" % 444 recipient.full())
Note: See TracBrowser
for help on using the repository browser.