Changeset 9877 for branches/bosh_support/src/common/xmpp/client_nb.py
- Timestamp:
- 07/03/08 01:29:10 (5 months ago)
- Files:
-
- 1 modified
Legend:
- Unmodified
- Added
- Removed
-
branches/bosh_support/src/common/xmpp/client_nb.py
r9870 r9877 23 23 24 24 import socket 25 import debug26 import random27 25 28 26 import transports_nb, tls_nb, dispatcher_nb, auth_nb, roster_nb, protocol … … 32 30 log = logging.getLogger('gajim.c.x.client_nb') 33 31 34 consoleloghandler = logging.StreamHandler()35 consoleloghandler.setLevel(logging.DEBUG)36 consoleloghandler.setFormatter(37 logging.Formatter('%(levelname)s: %(message)s')38 )39 log.setLevel(logging.DEBUG)40 log.addHandler(consoleloghandler)41 log.propagate = False42 43 32 44 33 class NBCommonClient: 45 34 ''' Base for Client and Component classes.''' 46 def __init__(self, hostname, idlequeue, port=5222, debug=['always', 'nodebuilder'], caller=None):35 def __init__(self, domain, idlequeue, caller=None): 47 36 48 37 ''' Caches connection data: 49 :param hostname: hostname of machine where the XMPP server is running (from Account 50 of from SRV request) and port to connect to. 38 :param domain: domain - for to: attribute (from account info) 51 39 :param idlequeue: processing idlequeue 52 40 :param port: port of listening XMPP server 53 :param debug: specifies the debug IDs that will go into debug output. You can either54 specifiy an "include" or "exclude" list. The latter is done via adding "always"55 pseudo-ID to the list. Full list: ['nodebuilder', 'dispatcher', 'gen_auth',56 'SASL_auth', 'bind', 'socket', 'CONNECTproxy', 'TLS', 'roster', 'browser', 'ibb'].57 TODO: get rid of debug.py using58 41 :param caller: calling object - it has to implement certain methods (necessary?) 59 42 60 43 ''' 61 44 62 self.DBG = DBG_CLIENT63 64 45 self.Namespace = protocol.NS_CLIENT 65 46 … … 68 49 self.disconnect_handlers = [] 69 50 70 # XMPP server and port from account or SRV 71 self.Server = hostname 72 self.Port = port 51 self.Server = domain 73 52 74 53 # caller is who initiated this client, it is sed to register the EventDispatcher 75 54 self._caller = caller 76 if debug and type(debug) != list:77 debug = ['always', 'nodebuilder']78 self._DEBUG = Debug.Debug(debug)79 self.DEBUG = self._DEBUG.Show80 self.debug_flags = self._DEBUG.debug_flags81 self.debug_flags.append(self.DBG)82 55 self._owner = self 83 56 self._registered_name = None … … 99 72 100 73 self.connected='' 101 self.DEBUG(self.DBG,'Disconnect detected','stop')74 log.debug('Client disconnected..') 102 75 for i in reversed(self.disconnect_handlers): 103 self.DEBUG(self.DBG, 'Calling disc handler %s' % i, 'stop')76 log.debug('Calling disconnect handler %s' % i) 104 77 i() 105 78 if self.__dict__.has_key('NonBlockingRoster'): … … 121 94 122 95 123 def send(self, stanza, is_message = False,now = False):96 def send(self, stanza, now = False): 124 97 ''' interface for putting stanzas on wire. Puts ID to stanza if needed and 125 98 sends it via socket wrapper''' 126 99 (id, stanza_to_send) = self.Dispatcher.assign_id(stanza) 127 100 128 if is_message: 129 # somehow zeroconf-specific 130 self.Connection.send(stanza_to_send, True, now = now) 131 else: 132 self.Connection.send(stanza_to_send, now = now) 101 self.Connection.send(stanza_to_send, now = now) 133 102 return id 134 103 135 104 136 105 137 def connect(self, on_connect, on_connect_failure, on_proxy_failure=None, proxy=None, secure=None): 106 def connect(self, on_connect, on_connect_failure, hostname=None, port=5222, 107 on_proxy_failure=None, proxy=None, secure=None): 138 108 ''' 139 109 Open XMPP connection (open streams in both directions). 110 :param hostname: hostname of XMPP server from SRV request 111 :param port: port number of XMPP server 140 112 :param on_connect: called after stream is successfully opened 141 113 :param on_connect_failure: called when error occures during connection … … 147 119 :param secure: 148 120 ''' 149 121 self.Port = port 122 if hostname: 123 xmpp_hostname = hostname 124 else: 125 xmpp_hostname = self.Server 126 150 127 self.on_connect = on_connect 151 128 self.on_connect_failure=on_connect_failure … … 156 133 if proxy: 157 134 # with proxies, client connects to proxy instead of directly to 158 # XMPP server from __init__.159 # tcp_server is hostname used for socket connecting135 # XMPP server ((hostname, port)) 136 # tcp_server is machine used for socket connection 160 137 tcp_server=proxy['host'] 161 138 tcp_port=proxy['port'] … … 169 146 type_ = proxy['type'] 170 147 if type_ == 'socks5': 148 # SOCKS5 proxy 171 149 self.socket = transports_nb.NBSOCKS5ProxySocket( 172 150 on_disconnect=self.on_disconnect, 173 151 proxy_creds=proxy_creds, 174 xmpp_server=( self.Server, self.Port))152 xmpp_server=(xmpp_hostname, self.Port)) 175 153 elif type_ == 'http': 154 # HTTP CONNECT to proxy 176 155 self.socket = transports_nb.NBHTTPProxySocket( 177 156 on_disconnect=self.on_disconnect, 178 157 proxy_creds=proxy_creds, 179 xmpp_server=( self.Server, self.Port))158 xmpp_server=(xmpp_hostname, self.Port)) 180 159 elif type_ == 'bosh': 160 # BOSH - XMPP over HTTP 181 161 tcp_server = transports_nb.urisplit(tcp_server)[1] 182 self.socket = transports_nb.NonBlockingH ttpBOSH(162 self.socket = transports_nb.NonBlockingHTTP( 183 163 on_disconnect=self.on_disconnect, 184 bosh_uri = proxy['host'],185 bosh_port = tcp_port)164 http_uri = proxy['host'], 165 http_port = tcp_port) 186 166 else: 187 167 # HTTP CONNECT to proxy from environment variables … … 189 169 on_disconnect=self.on_disconnect, 190 170 proxy_creds=(None, None), 191 xmpp_server=( self.Server, self.Port))171 xmpp_server=(xmpp_hostname, self.Port)) 192 172 else: 193 173 self._on_tcp_failure = self._on_connect_failure 194 tcp_server= self.Server174 tcp_server=xmpp_hostname 195 175 tcp_port=self.Port 196 176 self.socket = transports_nb.NonBlockingTcp(on_disconnect = self.on_disconnect) … … 222 202 '''iterates over IP addresses from getaddinfo''' 223 203 if err_message: 224 self.DEBUG(self.DBG,err_message,'connect')204 log.debug('While looping over DNS A records: %s' % connect) 225 205 if self.ip_addresses == []: 226 206 self._on_tcp_failure(err_message='Run out of hosts for name %s:%s' % … … 306 286 self.connected = None 307 287 if err_message: 308 self.DEBUG(self.DBG, err_message, 'connecting')288 log.debug('While connecting: %s' % err_message) 309 289 if self.socket: 310 290 self.socket.disconnect() … … 461 441 462 442 463 class BOSHClient(NBCommonClient):464 '''465 Client class implementing BOSH.466 '''467 def __init__(self, *args, **kw):468 '''Preceeds constructor of NBCommonClient and sets some of values that will469 be used as attributes in <body> tag'''470 self.Namespace = NS_HTTP_BIND471 # BOSH parameters should be given via Advanced Configuration Editor472 self.bosh_hold = 1473 self.bosh_wait=60474 self.bosh_rid=-1475 self.bosh_httpversion = 'HTTP/1.1'476 NBCommonClient.__init__(self, *args, **kw)477 478 479 def connect(self, *args, **kw):480 proxy = kw['proxy']481 self.bosh_protocol, self.bosh_host, self.bosh_uri = self.urisplit(proxy['host'])482 self.bosh_port = proxy['port']483 NBCommonClient.connect(*args, **kw)484 485 486 def _on_stream_start(self):487 '''488 Called after XMPP stream is opened. In BOSH TLS is negotiated on tranport layer489 so success callback can be invoked.490 (authentication is started from auth() method)491 '''492 self.onreceive(None)493 if self.connected == 'tcp':494 self._on_connect()495 496 497 498 499 500 def bosh_raise_event(self, realm, event, data):501 # should to extract stanza from body502 self.DEBUG(self.DBG,'realm: %s, event: %s, data: %s' % (realm, event, data),503 'BOSH EventHandler')504 self._caller._event_dispatcher(realm, event, data)505 506 507 def StreamInit(self):508 '''509 Init of BOSH session. Called instead of Dispatcher.StreamInit()510 Initial body tag is created and sent.511 '''512 #self.Dispatcher.RegisterEventHandler(self.bosh_event_handler)513 self.Dispatcher.Stream = simplexml.NodeBuilder()514 self.Dispatcher.Stream._dispatch_depth = 2515 self.Dispatcher.Stream.dispatch = self.Dispatcher.dispatch516 self.Dispatcher.Stream.stream_header_received = self._check_stream_start517 self.Dispatcher.Stream.features = None518 519 r = random.Random()520 r.seed()521 # with 50-bit random initial rid, session would have to go up522 # to 7881299347898368 messages to raise rid over 2**53523 # (see http://www.xmpp.org/extensions/xep-0124.html#rids)524 self.bosh_rid = r.getrandbits(50)525 526 initial_body_tag = BOSHBody(527 attrs={'content': 'text/xml; charset=utf-8',528 'hold': str(self.bosh_hold),529 # "to" should be domain, not hostname of machine530 'to': self.Server,531 'wait': str(self.bosh_wait),532 'rid': str(self.bosh_rid),533 'xmpp:version': '1.0',534 'xmlns:xmpp': 'urn:xmpp:xbosh'}535 )536 537 if locale.getdefaultlocale()[0]:538 initial_body_tag.setAttr('xml:lang',539 locale.getdefaultlocale()[0].split('_')[0])540 initial_body_tag.setAttr('xmpp:version', '1.0')541 initial_body_tag.setAttr('xmlns:xmpp', 'urn:xmpp:xbosh')542 self.send(initial_body_tag)
