Mercurial > xib
comparison bridge.py @ 24:4e1f27ea527b
First hack at locks for thread safety. Some other minor changes.
Signed-off-by: Charly COSTE <changaco@changaco.net>
author | Charly COSTE <changaco@changaco.net> |
---|---|
date | Thu, 20 Aug 2009 21:52:52 +0200 |
parents | e2bd4de698e5 |
children | 984e1e5c5e51 |
comparison
equal
deleted
inserted
replaced
23:abdb7a2b6c6d | 24:4e1f27ea527b |
---|---|
20 del muc | 20 del muc |
21 from participant import * | 21 from participant import * |
22 from encoding import * | 22 from encoding import * |
23 import traceback | 23 import traceback |
24 import re | 24 import re |
25 import threading | |
25 | 26 |
26 | 27 |
27 class NoSuchParticipantException(Exception): pass | 28 class NoSuchParticipantException(Exception): pass |
28 | 29 |
29 | 30 |
33 _info = 1 | 34 _info = 1 |
34 _notice = 2 | 35 _notice = 2 |
35 _warning = 3 | 36 _warning = 3 |
36 _error = 4 | 37 _error = 4 |
37 _nothing = 5 | 38 _nothing = 5 |
39 _modes = ['normal', 'limited', 'minimal'] | |
38 | 40 |
39 | 41 |
40 def __init__(self, owner_bot, xmpp_room_jid, irc_room, irc_server, mode, say_level, irc_port=6667): | 42 def __init__(self, owner_bot, xmpp_room_jid, irc_room, irc_server, mode, say_level, irc_port=6667): |
41 """Create a new bridge.""" | 43 """Create a new bridge.""" |
42 self.bot = owner_bot | 44 self.bot = owner_bot |
46 if hasattr(self.__class__, '_'+say_level): | 48 if hasattr(self.__class__, '_'+say_level): |
47 self.say_level = getattr(self.__class__, '_'+say_level) | 49 self.say_level = getattr(self.__class__, '_'+say_level) |
48 else: | 50 else: |
49 raise Exception('[Error] "'+say_level+'" is not a correct value for a bridge\'s "say_level" attribute') | 51 raise Exception('[Error] "'+say_level+'" is not a correct value for a bridge\'s "say_level" attribute') |
50 self.participants = [] | 52 self.participants = [] |
51 if mode not in ['normal', 'limited', 'minimal']: | 53 if mode not in self.__class__._modes: |
52 raise Exception('[Error] "'+mode+'" is not a correct value for a bridge\'s "mode" attribute') | 54 raise Exception('[Error] "'+mode+'" is not a correct value for a bridge\'s "mode" attribute') |
53 self.mode = mode | 55 self.mode = mode |
56 | |
57 self.lock = threading.Lock() | |
54 | 58 |
55 # Join XMPP room | 59 # Join XMPP room |
56 try: | 60 try: |
57 self.xmpp_room = xmpp.muc(xmpp_room_jid) | 61 self.xmpp_room = xmpp.muc(xmpp_room_jid) |
58 self.xmpp_room.join(self.bot.xmpp_c, self.bot.nickname, callback=self._xmpp_join_callback) | 62 self.xmpp_room.join(self.bot.xmpp_c, self.bot.nickname, callback=self._xmpp_join_callback) |
65 self.irc_connection = self.bot.irc.server(irc_server, irc_port, self.bot.nickname) | 69 self.irc_connection = self.bot.irc.server(irc_server, irc_port, self.bot.nickname) |
66 self.irc_connection.connect(nick_callback=self._irc_nick_callback) | 70 self.irc_connection.connect(nick_callback=self._irc_nick_callback) |
67 except: | 71 except: |
68 self.bot.error('[Error] joining IRC room failed') | 72 self.bot.error('[Error] joining IRC room failed') |
69 raise | 73 raise |
70 self.bot.error('[Notice] bridge "'+str(self)+'" is running in '+self.mode+' mode') | 74 |
75 self.bot.error('[Notice] bridge "'+str(self)+'" is running in '+self.mode+' mode and a say_level of "'+say_level+'"') | |
71 | 76 |
72 | 77 |
73 def _irc_nick_callback(self, error, arguments=[]): | 78 def _irc_nick_callback(self, error, arguments=[]): |
74 if error == None: | 79 if error == None: |
75 self.irc_connection.join(self.irc_room) | 80 self.irc_connection.join(self.irc_room) |
133 return p | 138 return p |
134 | 139 |
135 | 140 |
136 def getParticipant(self, nickname): | 141 def getParticipant(self, nickname): |
137 """Returns a participant object if there is a participant using nickname in the bridge. Raises a NoSuchParticipantException otherwise.""" | 142 """Returns a participant object if there is a participant using nickname in the bridge. Raises a NoSuchParticipantException otherwise.""" |
143 self.lock.acquire() | |
138 for participant_ in self.participants: | 144 for participant_ in self.participants: |
139 if participant_.nickname == nickname: | 145 if participant_.nickname == nickname: |
146 self.lock.release() | |
140 return participant_ | 147 return participant_ |
148 self.lock.release() | |
141 raise NoSuchParticipantException('there is no participant using the nickname "'+nickname+'" in this bridge') | 149 raise NoSuchParticipantException('there is no participant using the nickname "'+nickname+'" in this bridge') |
142 | 150 |
143 | 151 |
144 def get_participants_nicknames_list(self, protocols=['irc', 'xmpp']): | 152 def get_participants_nicknames_list(self, protocols=['irc', 'xmpp']): |
145 """Returns a list of the nicknames of the bridge's participants that are connected on the XMPP side.""" | 153 """Returns a list of the nicknames of the bridge's participants that are connected on the XMPP side.""" |
154 self.lock.acquire() | |
146 participants_nicknames = [] | 155 participants_nicknames = [] |
147 for p in self.participants: | 156 for p in self.participants: |
148 if p.protocol in protocols: | 157 if p.protocol in protocols: |
149 participants_nicknames.append('"'+p.nickname+'"') | 158 participants_nicknames.append('"'+p.nickname+'"') |
159 self.lock.release() | |
150 return participants_nicknames | 160 return participants_nicknames |
151 | 161 |
152 | 162 |
153 def removeParticipant(self, left_protocol, nickname, leave_message): | 163 def removeParticipant(self, left_protocol, nickname, leave_message): |
154 """Remove the participant using nickname from the bridge. Raises a NoSuchParticipantException if nickname is not used in the bridge.""" | 164 """Remove the participant using nickname from the bridge. Raises a NoSuchParticipantException if nickname is not used in the bridge.""" |
182 | 192 |
183 if was_on_both == True: | 193 if was_on_both == True: |
184 self.bot.error('===> Debug: "'+nickname+'" was on both sides of bridge "'+str(self)+'" but left '+left_protocol, debug=True) | 194 self.bot.error('===> Debug: "'+nickname+'" was on both sides of bridge "'+str(self)+'" but left '+left_protocol, debug=True) |
185 | 195 |
186 elif was_on_both == False: | 196 elif was_on_both == False: |
197 self.lock.acquire() | |
187 self.bot.error('===> Debug: removing participant "'+nickname+'" from bridge "'+str(self)+'"', debug=True) | 198 self.bot.error('===> Debug: removing participant "'+nickname+'" from bridge "'+str(self)+'"', debug=True) |
188 self.participants.remove(p) | 199 self.participants.remove(p) |
189 p.leave(leave_message) | 200 p.leave(leave_message) |
190 del p | 201 del p |
191 i = 0 | 202 i = 0 |
192 for p in self.participants: | 203 for p in self.participants: |
193 if p.protocol == 'xmpp': | 204 if p.protocol == 'xmpp': |
194 i += 1 | 205 i += 1 |
206 self.lock.release() | |
195 if left_protocol == 'xmpp': | 207 if left_protocol == 'xmpp': |
196 if self.irc_connections_limit != -1 and self.irc_connections_limit > i: | 208 if self.irc_connections_limit != -1 and self.irc_connections_limit > i: |
197 self.switchFromLimitedToNormalMode() | 209 self.switchFromLimitedToNormalMode() |
198 if self.mode != 'normal' and self.say_participants_list == True: | 210 if self.mode != 'normal': |
199 xmpp_participants_nicknames = self.get_participants_nicknames_list(protocols=['xmpp']) | 211 xmpp_participants_nicknames = self.get_participants_nicknames_list(protocols=['xmpp']) |
200 self.say('[Info] Participants on XMPP: '+' '.join(xmpp_participants_nicknames), on_xmpp=False) | 212 self.say('[Info] Participants on XMPP: '+' '.join(xmpp_participants_nicknames), on_xmpp=False) |
201 elif left_protocol == 'irc': | 213 elif left_protocol == 'irc': |
202 if self.mode == 'minimal' and self.say_participants_list == True: | 214 if self.mode == 'minimal': |
203 irc_participants_nicknames = self.get_participants_nicknames_list(protocols=['irc']) | 215 irc_participants_nicknames = self.get_participants_nicknames_list(protocols=['irc']) |
204 self.say('[Info] Participants on IRC: '+' '.join(irc_participants_nicknames), on_irc=False) | 216 self.say('[Info] Participants on IRC: '+' '.join(irc_participants_nicknames), on_irc=False) |
205 | 217 |
206 else: | 218 else: |
207 self.bot.error('=> Debug: Bad decision tree, p.protocol='+p.protocol+' left_protocol='+left_protocol+'\np.xmpp_c='+str(p.xmpp_c)+'\np.irc_connection='+str(p.irc_connection), debug=True) | 219 self.bot.error('=> Debug: Bad decision tree, p.protocol='+p.protocol+' left_protocol='+left_protocol+'\np.xmpp_c='+str(p.xmpp_c)+'\np.irc_connection='+str(p.irc_connection), debug=True) |