Changeset 14
- Timestamp:
- 02/01/04 19:07:42 (5 years ago)
- Files:
-
- trunk/jjigw.py (modified) (17 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/jjigw.py
r13 r14 11 11 import string 12 12 import random 13 import signal 13 14 14 15 from pyxmpp import ClientStream,JID,Iq,Presence,Message,StreamError … … 348 349 pass 349 350 350 def irc_cmd_324(self,prefix,command,params): 351 def irc_cmd_324(self,prefix,command,params): # RPL_CHANNELMODEIS 351 352 for m in self.toggle_modes: 352 353 try: … … 496 497 self.nick=nick 497 498 self.thread=threading.Thread(name=u"%s on %s as %s" % (jid,config.network.jid,nick), 498 target=self.thread_loop) 499 self.exit=0 499 target=self.thread_run) 500 self.thread.setDaemon(1) 501 self.exit=None 502 self.exited=0 500 503 self.socket=None 501 504 self.lock=threading.RLock() 502 505 self.cond=threading.Condition(self.lock) 503 506 self.servers_left=self.network.get_servers() 504 self.thread.setDaemon(1)505 self.thread.start()506 507 self.input_buffer="" 507 508 self.used_for=[] 508 509 self.server="" 510 self.join_requests=[] 511 self.messages_to_channel=[] 512 self.messages_to_user=[] 509 513 self.ready=0 510 514 self.channels={} 511 515 self.users={} 512 516 self.user=IRCUser(self,nick) 517 self.thread.start() 513 518 514 519 def register_user(self,user): … … 562 567 563 568 def thread_run(self): 569 clean_exit=1 564 570 try: 565 571 self.thread_loop() 566 572 except: 573 clean_exit=0 567 574 self.print_exception() 568 575 self.lock.acquire() 569 576 try: 577 if not self.exited and self.socket: 578 if clean_exit and self.component.shutdown: 579 self._send("QUIT :JJIGW shutdown") 580 elif clean_exit and self.exit: 581 self._send("QUIT :%s" % (self.exit.encode(self.default_encoding,"replace"))) 582 else: 583 self._send("QUIT :Internal JJIGW error") 584 self.exited=1 570 585 if self.socket: 571 586 try: … … 580 595 finally: 581 596 self.lock.release() 597 for j in self.used_for: 598 p=Presence(fr=j,to=self.jid,type="unavailable") 599 self.component.send(p) 600 self.used_for=[] 582 601 583 602 def thread_loop(self): 584 603 self.debug("thread_loop()") 585 while not self.exit :604 while not self.exit and not self.component.shutdown: 586 605 self.lock.acquire() 587 606 try: … … 598 617 while self.input_buffer.find("\r\n")>-1: 599 618 input,self.input_buffer=self.input_buffer.split("\r\n",1) 600 self._ process_input(input)619 self._safe_process_input(input) 601 620 finally: 602 621 self.lock.release() … … 612 631 if not self.servers_left: 613 632 self.debug("No servers left, quitting") 614 self.exit= 1633 self.exit="No servers left, quitting" 615 634 return 616 635 if self.socket: … … 635 654 self._send("USER %s 0 * :JJIGW User %s" % (user,user)) 636 655 self.server=server[0] 637 self.ready=1638 656 self.cond.notify() 639 657 640 658 def _send(self,str): 641 self.debug("IRC OUT: %r" % (str,)) 642 self.socket.send(str+"\r\n") 659 if self.socket and not self.exited: 660 self.debug("IRC OUT: %r" % (str,)) 661 self.socket.send(str+"\r\n") 662 else: 663 self.debug("ignoring out: %r" % (str,)) 643 664 644 665 def send(self,str): … … 649 670 self.lock.release() 650 671 672 def _safe_process_input(self,input): 673 try: 674 self._process_input(input) 675 except: 676 self.print_exception() 677 651 678 def _process_input(self,input): 652 679 self.debug("Server message: %r" % (input,)) … … 724 751 m=Message(type=typ,fr=fr,to=self.jid,body=remove_evil_characters(strip_colors(body))) 725 752 self.component.send(m) 753 754 def login_error(self,join_condition,message_condition): 755 self.lock.acquire() 756 try: 757 if join_condition: 758 for s in self.join_requests: 759 p=s.make_error_response(join_condition) 760 self.component.send(p) 761 try: 762 self.used_for.remove(s.get_to()) 763 except ValueError: 764 pass 765 self.join_requests=[] 766 if message_condition: 767 for s in self.messages_to_user+self.messages_to_channel: 768 p=s.make_error_response(message_condition) 769 self.component.send(p) 770 self.messages_to_user=[] 771 self.messages_to_channel=[] 772 self.exit="IRC user registration failed" 773 finally: 774 self.lock.release() 775 776 def irc_cmd_001(self,prefix,command,params): # RPL_WELCOME 777 self.lock.acquire() 778 try: 779 self.debug("Connected successfully") 780 self.ready=1 781 for s in self.join_requests: 782 self.join(s) 783 for s in self.messages_to_user: 784 self.message_to_user(s) 785 for s in self.messages_to_channel: 786 self.message_to_channel(s) 787 finally: 788 self.lock.release() 789 790 def irc_cmd_431(self,prefix,command,params): # ERR_NONICKNAMEGIVEN 791 if self.ready: 792 return 793 self.login_error("undefined-condition","not-authorized") 794 795 def irc_cmd_432(self,prefix,command,params): # ERR_ERRONEUSNICKNAME 796 if self.ready: 797 return 798 self.login_error("bad-request","not-authorized") 799 800 def irc_cmd_433(self,prefix,command,params): # ERR_NICKNAMEINUSE 801 if self.ready: 802 return 803 self.login_error("conflict","not-authorized") 804 805 def irc_cmd_436(self,prefix,command,params): # ERR_NICKCOLLISION 806 if self.ready: 807 return 808 self.login_error("conflict","not-authorized") 809 810 def irc_cmd_437(self,prefix,command,params): # ERR_UNAVAILRESOURCE 811 if self.ready: 812 return 813 self.login_error("resource-constraint","not-authorized") 814 815 def irc_cmd_437(self,prefix,command,params): # ERR_RESTRICTED 816 if self.ready: 817 return 818 pass 726 819 727 820 def irc_cmd_QUIT(self,prefix,command,params): … … 730 823 self.unregister_user(user) 731 824 732 def irc_cmd_352(self,prefix,command,params): 825 def irc_cmd_352(self,prefix,command,params): # RPL_WHOREPLY 733 826 self.debug("WHO reply received") 734 827 if len(params)<7: … … 766 859 767 860 def join(self,stanza): 861 self.cond.acquire() 862 try: 863 if not self.ready: 864 self.join_requests.append(stanza) 865 return 866 finally: 867 self.cond.release() 768 868 to=stanza.get_to() 769 869 channel=node_to_channel(to.node,self.default_encoding) 770 870 if self.channels.has_key(normalize(channel)): 771 871 return 772 self.cond.acquire()773 try:774 # FIXME: may hang the main thread775 while not self.ready and not self.exit:776 self.cond.wait()777 finally:778 self.cond.release()779 if self.exit:780 return781 872 channel=Channel(self,channel) 782 873 channel.join(stanza) … … 784 875 785 876 def message_to_channel(self,stanza): 786 if not self.ready: 787 return 877 self.cond.acquire() 878 try: 879 if not self.ready: 880 self.messages_to_channel.append(stanza) 881 return 882 finally: 883 self.cond.release() 788 884 channel=stanza.get_to().node 789 885 channel=node_to_channel(channel,self.default_encoding) … … 801 897 802 898 def message_to_user(self,stanza): 803 if not self.ready: 804 return 899 self.cond.acquire() 900 try: 901 if not self.ready: 902 self.messages_to_user.append(stanza) 903 return 904 finally: 905 self.cond.release() 805 906 to=stanza.get_to() 806 907 if to.resource and (to.node[0] in "#+!" or to.node.startswith(",amp,")): … … 827 928 reason="Unknown reason" 828 929 self.send("QUIT :%s" % (reason,)) 829 self.exit=1 930 self.exit=reason 931 self.exited=1 830 932 831 933 def debug(self,msg): … … 840 942 config.connect.secret,config.connect.host,config.connect.port, 841 943 category="gateway",type="irc") 842 self.exit=0 944 self.shutdown=0 945 signal.signal(signal.SIGINT,self.signal_handler) 946 signal.signal(signal.SIGTERM,self.signal_handler) 843 947 self.irc_sessions={} 844 948 self.config=config 949 950 def signal_handler(self,signum,frame): 951 self.debug("Signal %i received, shutting down..." % (signum,)) 952 self.shutdown=1 953 954 def run(self,timeout): 955 self.connect() 956 while (not self.shutdown and self.stream 957 and not self.stream.eof and self.stream.socket is not None): 958 self.stream.loop_iter(timeout) 959 if self.shutdown: 960 for sess in self.irc_sessions.values(): 961 sess.disconnect("JJIGW shutdown") 962 threads=threading.enumerate() 963 for th in threads: 964 try: 965 th.join(10*timeout) 966 except: 967 pass 968 for th in threads: 969 try: 970 th.join(timeout) 971 except: 972 pass 973 self.disconnect() 974 self.debug("Exitting normally") 845 975 846 976 def send(self,stanza): … … 1040 1170 c=Component(config) 1041 1171 1042 print "connecting..." 1043 c.connect() 1044 1045 print "looping..." 1046 try: 1047 c.loop(1) 1048 except KeyboardInterrupt: 1049 print "disconnecting..." 1050 c.disconnect() 1051 pass 1052 1053 print "exiting..." 1172 print "starting..." 1173 c.run(1) 1054 1174 1055 1175 # vi: sw=4 ts=8 sts=4
