Index: trunk/extensions/XMLRC/bridge/udp2xmpp.py |
— | — | @@ -84,17 +84,22 @@ |
85 | 85 | self.loglevel = LOG_VERBOSE |
86 | 86 | self.wiki_info = wiki_info; |
87 | 87 | |
| 88 | + def append_exec_info(self, message, error_type = None, error_value = None, trbk = None): |
| 89 | + if trbk and not error_type: |
| 90 | + message = message + "\n" + " ".join( traceback.format_tb( trbk ) ) |
| 91 | + elif error_type: |
| 92 | + message = message + " * " + " ".join( traceback.format_exception( error_type, error_value, trbk ) ) |
| 93 | + |
| 94 | + return message |
| 95 | + |
88 | 96 | def warn(self, message, error_type = None, error_value = None, trbk = None): |
89 | 97 | if self.loglevel >= LOG_QUIET: |
90 | | - if trbk and not error_type: |
91 | | - message = message + "\n" + " ".join( traceback.format_tb( trbk ) ) |
92 | | - elif error_type: |
93 | | - message = message + " * " + " ".join( traceback.format_exception( error_type, error_value, trbk ) ) |
94 | | - |
| 98 | + message = self.append_exec_info( message, error_type, error_value, trbk ) |
95 | 99 | sys.stderr.write( "WARNING: %s\n" % ( message.encode( self.console_encoding ) ) ) |
96 | 100 | |
97 | | - def info(self, message): |
| 101 | + def info(self, message, error_type = None, error_value = None, trbk = None): |
98 | 102 | if self.loglevel >= LOG_VERBOSE: |
| 103 | + message = self.append_exec_info( message, error_type, error_value, trbk ) |
99 | 104 | sys.stderr.write( "INFO: %s\n" % ( message.encode( self.console_encoding ) ) ) |
100 | 105 | |
101 | 106 | def debug(self, message): |
— | — | @@ -292,51 +297,55 @@ |
293 | 298 | self.debug( "relying RC message: %s" % m ) |
294 | 299 | return t.send_message( m, rc ) |
295 | 300 | |
| 301 | + def check_connections( self, connection_sockets, broken, context, exec_info = (), test = True ): |
| 302 | + remove = set() |
| 303 | + c = 0 |
| 304 | + |
| 305 | + for sock, conn in connection_sockets.items(): |
| 306 | + if ( not test and not conn.is_connected() ) or ( test and not conn.test_connection() ): |
| 307 | + if test: |
| 308 | + self.warn( "is_connected for connection %s returned false (%s)" % (repr(conn), context), *exec_info ); |
| 309 | + else: |
| 310 | + self.warn( "test_connection for connection %s failed (%s)" % (repr(conn), context), *exec_info ); |
| 311 | + |
| 312 | + broken.add(conn) |
| 313 | + remove.add(sock) |
| 314 | + c += 1 |
| 315 | + |
| 316 | + for sock in remove: |
| 317 | + del connection_sockets[ sock ] |
| 318 | + |
| 319 | + return c |
| 320 | + |
296 | 321 | def select_connections( self, connection_sockets, broken, timeout = 1 ): |
297 | | - waiting = [] |
| 322 | + waiting = set() |
298 | 323 | |
| 324 | + self.check_connections( connection_sockets, broken, "prior to socket-select", test = False ) |
| 325 | + |
299 | 326 | try: |
300 | 327 | (in_socks , out_socks, err_socks) = select.select(connection_sockets.keys(),[],connection_sockets.keys(),1) |
301 | 328 | |
302 | 329 | for sock in err_socks: |
303 | | - con = connection_sockets[ sock ] |
304 | | - self.warn("exception in socket %s, connection %s" % (repr(sock), repr(con))); |
| 330 | + conn = connection_sockets[ sock ] |
| 331 | + self.warn("exception in socket %s, connection %s" % (repr(sock), repr(conn))); |
305 | 332 | |
306 | | - broken.append( con ) |
| 333 | + broken.add( conn ) |
307 | 334 | del connection_sockets[ sock ] |
308 | 335 | |
309 | 336 | for sock in in_socks: |
310 | | - con = connection_sockets[ sock ] |
311 | | - waiting.append( con ) |
| 337 | + conn = connection_sockets[ sock ] |
| 338 | + waiting.add( conn ) |
312 | 339 | |
313 | 340 | except socket.error, e: |
314 | | - error_type, error_value, trbk = sys.exc_info() |
315 | | - found = False |
| 341 | + found = self.check_connections( connection_sockets, broken, "after exception", test = True, exec_info = sys.exc_info() ) |
316 | 342 | |
317 | | - for sock, conn in connection_sockets.items(): |
318 | | - if not conn.test_connection(): |
319 | | - self.warn("test_connection for connection %s failed after exception" % repr(con), error_type, error_value, trbk); |
320 | | - found = True |
321 | | - |
322 | | - broken.append(conn) |
323 | | - del connection_sockets[ sock ] |
324 | | - |
325 | | - if not found: |
| 343 | + if found == 0: |
326 | 344 | self.warn("exception ocurred, but all connections seem valid!", error_type, error_value, trbk); |
327 | 345 | |
328 | 346 | except IOError, e: |
329 | | - error_type, error_value, trbk = sys.exc_info() |
330 | | - found = False |
| 347 | + found = self.check_connections( connection_sockets, broken, "after exception", test = True, exec_info = sys.exc_info() ) |
331 | 348 | |
332 | | - for sock, conn in connection_sockets.items(): |
333 | | - if not conn.test_connection(): |
334 | | - self.warn("test_connection for connection %s failed after exception" % repr(con), error_type, error_value, trbk); |
335 | | - found = True |
336 | | - |
337 | | - broken.append(conn) |
338 | | - del connection_sockets[ sock ] |
339 | | - |
340 | | - if not found: |
| 349 | + if found == 0: |
341 | 350 | self.warn("exception ocurred, but all connections seem valid!", error_type, error_value, trbk); |
342 | 351 | |
343 | 352 | return waiting |
— | — | @@ -365,7 +374,6 @@ |
366 | 375 | try: |
367 | 376 | conn.reconnect() |
368 | 377 | |
369 | | - broken.remove( conn ) |
370 | 378 | connection_sockets[ conn.get_socket() ] = conn |
371 | 379 | self.info( "reconnected %s!" % repr(conn) ) |
372 | 380 | |
— | — | @@ -373,6 +381,9 @@ |
374 | 382 | error_type, error_value, trbk = sys.exc_info() |
375 | 383 | self.warn( "Error during reconnect for connection %s!" % repr(conn), error_type, error_value, trbk ) |
376 | 384 | |
| 385 | + if len(broken) >0: |
| 386 | + broken -= set( connection_sockets.values() ) |
| 387 | + |
377 | 388 | for conn in waiting: |
378 | 389 | try: |
379 | 390 | conn.process() |
— | — | @@ -381,7 +392,7 @@ |
382 | 393 | |
383 | 394 | if not conn.test_connection(): |
384 | 395 | self.warn("test_connection for connection %s failed after exception in process()" % repr(conn), error_type, error_value, trbk); |
385 | | - broken.append(conn) |
| 396 | + broken.add(conn) |
386 | 397 | del connection_sockets[ conn.get_socket() ] |
387 | 398 | else: |
388 | 399 | self.info("connection %s seems to be valid after exception in process()" % repr(conn), error_type, error_value, trbk); |
— | — | @@ -391,8 +402,8 @@ |
392 | 403 | |
393 | 404 | self.info("service loop terminated, disconnecting") |
394 | 405 | |
395 | | - for con in connections: |
396 | | - con.close() |
| 406 | + for conn in connections: |
| 407 | + conn.close() |
397 | 408 | |
398 | 409 | self.info("done.") |
399 | 410 | |
— | — | @@ -431,6 +442,8 @@ |
432 | 443 | self.backoff_factor = backoff_factor |
433 | 444 | self.backoff_max_tock = backoff_max_tock |
434 | 445 | |
| 446 | + self.connect_info = None |
| 447 | + |
435 | 448 | def process( self ): |
436 | 449 | self.jabber.Process(1) |
437 | 450 | |
— | — | @@ -458,14 +471,14 @@ |
459 | 472 | |
460 | 473 | return MucChannel( self, room_jid, room_nick ) |
461 | 474 | |
462 | | - def process_message(self, con, message): |
| 475 | + def process_message(self, conn, message): |
463 | 476 | if (message.getError()): |
464 | 477 | self.warn("received %s error from <%s>: %s" % (message.getType(), message.getError(), message.getFrom() )) |
465 | 478 | elif message.getBody(): |
466 | 479 | if message.getFrom().getResource() != self.jid.getNode(): #FIXME: this inly works if no different nick was specified when joining the channel |
467 | 480 | self.debug("discarding %s message from <%s>: %s" % (message.getType(), message.getFrom(), message.getBody().strip() )) |
468 | 481 | |
469 | | - def process_iq(self, con, iq): |
| 482 | + def process_iq(self, conn, iq): |
470 | 483 | self.debug("received iq: %s" % repr(iq)) |
471 | 484 | self.last_iq = iq |
472 | 485 | |
— | — | @@ -474,22 +487,27 @@ |
475 | 488 | |
476 | 489 | return resource; |
477 | 490 | |
478 | | - def connect( self, jid, password ): |
| 491 | + def connect( self, jid, password, port = 5222, host = None ): |
479 | 492 | |
| 493 | + self.connect_info = { 'jid': jid, 'password': password, 'port': port, 'host': host } |
| 494 | + |
480 | 495 | if type( jid ) != object: |
481 | 496 | jid = xmpp.protocol.JID( jid ) |
482 | 497 | |
483 | 498 | if jid.getResource() is None: |
484 | 499 | jid = xmpp.protocol.JID( host= jid.getDomain(), node= jid.getNode(), resource = self.guess_local_resource() ) |
485 | 500 | |
486 | | - self.jabber = xmpp.Client(jid.getDomain(),debug=self.xmpp_debug) |
487 | | - con= self.jabber.connect( secure = self.connection_security ) |
| 501 | + if host is None: |
| 502 | + host = jid.getDomain() |
488 | 503 | |
489 | | - if not con: |
490 | | - self.warn( 'could not connect to %s!' % jid.getDomain() ) |
| 504 | + self.jabber = xmpp.Client( host, port = port, debug = self.xmpp_debug ) |
| 505 | + conn= self.jabber.connect( secure = self.connection_security ) |
| 506 | + |
| 507 | + if not conn: |
| 508 | + self.warn( 'could not connect to %s:%s!' % (host, port) ) |
491 | 509 | return False |
492 | 510 | |
493 | | - self.debug( 'connected with %s' % con ) |
| 511 | + self.debug( 'connected with %s' % conn ) |
494 | 512 | |
495 | 513 | auth= self.jabber.auth( jid.getNode(), password, resource= jid.getResource() ) |
496 | 514 | |
— | — | @@ -512,7 +530,7 @@ |
513 | 531 | |
514 | 532 | self.on_connect() |
515 | 533 | |
516 | | - return con |
| 534 | + return conn |
517 | 535 | |
518 | 536 | def on_connect( self ): |
519 | 537 | self.jabber.sendInitPresence(self) |
— | — | @@ -525,8 +543,13 @@ |
526 | 544 | self.relay.join_channels() #FIXME: this re-joins *all* channels. not just the ones for this connection! |
527 | 545 | |
528 | 546 | def get_socket( self ): |
529 | | - return self.jabber.Connection._sock |
| 547 | + try: |
| 548 | + return self.jabber.Connection._sock |
| 549 | + except AttributeError: |
| 550 | + pass |
530 | 551 | |
| 552 | + return None |
| 553 | + |
531 | 554 | def is_connected( self ): |
532 | 555 | return self.jabber.isConnected() |
533 | 556 | |
— | — | @@ -578,7 +601,7 @@ |
579 | 602 | return self.last_iq |
580 | 603 | |
581 | 604 | def reconnect_backoff( self ): |
582 | | - self.debug( "reconnect_backoff: tick = %d, tock = %d" ) |
| 605 | + self.debug( "reconnect_backoff: tick = %d, tock = %d" % (self.backoff_tick, self.backoff_tock) ) |
583 | 606 | |
584 | 607 | if self.backoff_tick <= 0: |
585 | 608 | self.backoff_tock = min( self.backoff_tock + 1, self.backoff_max_tock ) |
— | — | @@ -595,8 +618,8 @@ |
596 | 619 | except: |
597 | 620 | pass |
598 | 621 | |
599 | | - self.jabber.reconnectAndReauth(self) |
600 | | - self.on_connect() |
| 622 | + if self.connect_info: |
| 623 | + self.connect( **self.connect_info ) |
601 | 624 | |
602 | 625 | class CommandConnection (Connection): |
603 | 626 | def __init__( self, relay, socket ): |
— | — | @@ -864,6 +887,8 @@ |
865 | 888 | config.set( 'XMPP', 'message-encoding', 'utf-8' ) |
866 | 889 | config.set( 'XMPP', 'debug-flags', 'client|component|got' ) |
867 | 890 | config.set( 'XMPP', 'security', 'auto' ) |
| 891 | + config.set( 'XMPP', 'port', '5222' ) |
| 892 | + config.set( 'XMPP', 'host', '' ) |
868 | 893 | |
869 | 894 | # read config file........ |
870 | 895 | if not config.read( cfg ): |
— | — | @@ -921,6 +946,12 @@ |
922 | 947 | |
923 | 948 | relay.loglevel = options.loglevel |
924 | 949 | |
| 950 | + xmpp_port = config.getint( 'XMPP', 'port' ) |
| 951 | + xmpp_host = config.get( 'XMPP', 'host' ) |
| 952 | + |
| 953 | + if xmpp_host == '': |
| 954 | + xmpp_host = None |
| 955 | + |
925 | 956 | xmpp_debug = [] |
926 | 957 | if options.xmpp_debug: |
927 | 958 | xmpp_debug = config.get( 'XMPP', 'debug-flags' ).split("|") |
— | — | @@ -938,7 +969,7 @@ |
939 | 970 | # -- DO STUFF ----------------------------------------------------------------------------------- |
940 | 971 | |
941 | 972 | # connect................ |
942 | | - if not xmpp_con.connect( jid = config.get( 'XMPP', 'jid' ), password = config.get( 'XMPP', 'password' ) ): |
| 973 | + if not xmpp_con.connect( jid = config.get( 'XMPP', 'jid' ), password = config.get( 'XMPP', 'password' ), port = xmpp_port, host = xmpp_host ): |
943 | 974 | sys.exit(1) |
944 | 975 | |
945 | 976 | if not udp_con.connect( port = config.getint( 'UDP', 'port' ), interface = config.get( 'UDP', 'interface' ) ): |