BOSH (or HTTP binding) is a technique designed for asynchronous XMPP communication between client and server using HTTP. Unlike Jabber HTTP Polling (XEP-0025), it uses multiple request/response pairs to improve responsiveness and to avoid unnecessary polling. Besides client and server, there is a Connection Manager entity in BOSH architecture, that serves as a mediator handling HTTP requests from clients and communicating with server. In practice, CM can be standalone HTTP server or extension of XMPP server.
BOSH implementation should ideally concern the xmpppy library only (does anyone else use it instead of original xmpppy? No). There is one common.connection.Connection instance for each account. BOSH connection should be account-specific. Ordinar XMPP Connection has one common.xmpp.NonBlockingClient instance with certain socket wrapper. My first concept is making a BOSHClient class derived from !NBCommonClient holding NonBlockingHttp instance(s).
BOSHClient - handling of BOSH sessions, building the
☑ What about connection handlers classes? Is it even possible/necessary to have all of them in all connection-types? At the moment, ConnectionZeroconf implements two of them - ConnectionVcard and ConnectionByteStream. As for BOSH, existing XMPP handlers can be used. Child stanzas from <body> are passed to dispatcher that calls appropriate handlers
☑ Can existing SASL module be used for BOSH authentication?? - *they can, as long as (plugged) Client.send() will wrap sent data in body tag before putting them on wire
☑ Connection._event_dispatcher is called from NonBlockingTcp._do_receive (well via Dispatcher.Event resp. Dispatcher._eventHandler) and all received data are passed to there - in BOSH case it's whole HTTP message.. How to workaround that?? Possibly - assign other method to Dispatcher._eventHandler in BOSHClinet.StreamInit(). Solved with callback reference in Transport constructor
☑ Due to spec it should be possible to employ two HTTP connections for one "client->ConnectionManager" connection.
Scenario: Client sends request to connection manager that doesn't support persistent connections (hence can't do pipelining either), CM forwards message to server and waits for answer. Now client wants to send another message and thus has to open another TCP connection to CM. In current xmpppy, roughly said, one TCP connection is represented by one transport class instance and only one transport of a kind can be plugged to a client.
New transport class for both connections (.send() and other exported methods in Transport class) to be plugged to client NonBlockingClient or BOSHClient
– code duplication between the new transport class and NonBlockingTcp -
could be plugged to NonBlockingClient - no need for BOSHClient maybe?
The right way - NonBlockingBOSH in xmpp/bosh.py. No code dupe with new NonBlockingTransport interface, no need for BOSHClient
Two NonBlockingTcp instances owned (but not plugged to) by BOSHClient (would have to implement methods that are exported from transports).
would be messy
☑ implement autodetect of capability of persistent HTTP connections - if Connection Manager/Proxy force disconnect after first req-resp pair, fall back to nonpersistent connections
☑ make zeroconf running again - I had to broke it during xmpppy refactoring and didn't try yet
☑ make SOCKS5 proxy running again, same reason as above.
☑ implement SSL connection to Conenction Mangaer. to achieve this, NonBlockingTLS has to be plugged to NonBlockingTCP and ancestors instead of to Client class.
☑ better handle of disconnect - if stream terminating stanza is sent, don't allow send on any of the HTTP connections. Force disconnect after timeout.