| | 1215 | |
| | 1216 | # keep track of sessions this connection has with other JIDs |
| | 1217 | self.sessions = {} |
| | 1218 | |
| | 1219 | def _FeatureNegCB(self, con, stanza, session): |
| | 1220 | gajim.log.debug('FeatureNegCB') |
| | 1221 | feature = stanza.getTag(name='feature', namespace=common.xmpp.NS_FEATURE) |
| | 1222 | form = common.xmpp.DataForm(node=feature.getTag('x')) |
| | 1223 | |
| | 1224 | if form['FORM_TYPE'] == 'urn:xmpp:ssn': |
| | 1225 | self.dispatch('SESSION_NEG', (stanza.getFrom(), session, form)) |
| | 1226 | else: |
| | 1227 | reply = stanza.buildReply() |
| | 1228 | reply.setType('error') |
| | 1229 | |
| | 1230 | reply.addChild(feature) |
| | 1231 | reply.addChild(node=common.xmpp.ErrorNode('service-unavailable', typ='cancel')) |
| | 1232 | |
| | 1233 | con.send(reply) |
| | 1234 | |
| | 1235 | raise common.xmpp.NodeProcessed |
| | 1236 | |
| | 1237 | def _InitE2ECB(self, con, stanza, session): |
| | 1238 | gajim.log.debug('InitE2ECB') |
| | 1239 | init = stanza.getTag(name='init', namespace=common.xmpp.NS_ESESSION_INIT) |
| | 1240 | form = common.xmpp.DataForm(node=init.getTag('x')) |
| | 1241 | |
| | 1242 | self.dispatch('SESSION_NEG', (stanza.getFrom(), session, form)) |
| | 1243 | |
| | 1244 | raise common.xmpp.NodeProcessed |
| | 1245 | |
| | 1246 | def get_or_create_session(self, jid, thread_id): |
| | 1247 | '''returns an existing session between this connection and 'jid', returns a new one if none exist.''' |
| | 1248 | |
| | 1249 | pm = True |
| | 1250 | if not gajim.interface.is_pm_contact(jid, self.name): |
| | 1251 | pm = False |
| | 1252 | jid = gajim.get_jid_without_resource(jid) |
| | 1253 | |
| | 1254 | session = self.find_session(jid, thread_id) |
| | 1255 | |
| | 1256 | if session: |
| | 1257 | return session |
| | 1258 | |
| | 1259 | if pm: |
| | 1260 | return self.make_new_session(jid, thread_id, type = 'pm') |
| | 1261 | else: |
| | 1262 | return self.make_new_session(jid, thread_id) |
| | 1263 | |
| | 1264 | def find_session(self, jid, thread_id): |
| | 1265 | try: |
| | 1266 | if not thread_id: |
| | 1267 | return self.find_null_session(jid) |
| | 1268 | else: |
| | 1269 | return self.sessions[jid][thread_id] |
| | 1270 | except KeyError: |
| | 1271 | return None |
| | 1272 | |
| | 1273 | def terminate_sessions(self): |
| | 1274 | '''send termination messages and delete all active sessions''' |
| | 1275 | for jid in self.sessions: |
| | 1276 | for thread_id in self.sessions[jid]: |
| | 1277 | self.sessions[jid][thread_id].terminate() |
| | 1278 | |
| | 1279 | self.sessions = {} |
| | 1280 | |
| | 1281 | def delete_session(self, jid, thread_id): |
| | 1282 | try: |
| | 1283 | del self.sessions[jid][thread_id] |
| | 1284 | |
| | 1285 | if not self.sessions[jid]: |
| | 1286 | del self.sessions[jid] |
| | 1287 | except KeyError: |
| | 1288 | pass |
| | 1289 | |
| | 1290 | def find_null_session(self, jid): |
| | 1291 | '''finds all of the sessions between us and a remote jid in which we |
| | 1292 | haven't received a thread_id yet and returns the session that we last |
| | 1293 | sent a message to.''' |
| | 1294 | |
| | 1295 | sessions = self.sessions[jid].values() |
| | 1296 | |
| | 1297 | # sessions that we haven't received a thread ID in |
| | 1298 | idless = filter(lambda s: not s.received_thread_id, sessions) |
| | 1299 | |
| | 1300 | # filter out everything exceptthe default session type |
| | 1301 | chat_sessions = filter(lambda s: isinstance(s, ChatControlSession), idless) |
| | 1302 | |
| | 1303 | if chat_sessions: |
| | 1304 | # return the session that we last sent a message in |
| | 1305 | chat_sessions.sort(key=lambda s: s.last_send) |
| | 1306 | return chat_sessions[-1] |
| | 1307 | else: |
| | 1308 | return None |
| | 1309 | |
| | 1310 | def make_new_session(self, jid, thread_id=None, type='chat', klass=None): |
| | 1311 | if not klass: |
| | 1312 | klass = ChatControlSession |
| | 1313 | |
| | 1314 | # determine if this session is a pm session |
| | 1315 | # if not, discard the resource |
| | 1316 | if not type == 'pm': |
| | 1317 | jid = gajim.get_jid_without_resource(jid) |
| | 1318 | |
| | 1319 | sess = klass(self, common.xmpp.JID(jid), thread_id, type) |
| | 1320 | |
| | 1321 | if not jid in self.sessions: |
| | 1322 | self.sessions[jid] = {} |
| | 1323 | |
| | 1324 | self.sessions[jid][sess.thread_id] = sess |
| | 1325 | |
| | 1326 | return sess |
| | 1327 | |
| | 1328 | class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, ConnectionCommands, ConnectionPubSub, ConnectionCaps, ConnectionHandlersBase): |
| | 1329 | def __init__(self): |
| | 1330 | ConnectionVcard.__init__(self) |
| | 1331 | ConnectionBytestream.__init__(self) |
| | 1332 | ConnectionCommands.__init__(self) |
| | 1333 | ConnectionPubSub.__init__(self) |
| | 1334 | ConnectionHandlersBase.__init__(self) |
| | 1335 | self.gmail_url = None |
| | 1336 | |
| 1249 | | raise common.xmpp.NodeProcessed |
| 1250 | | |
| 1251 | | def _FeatureNegCB(self, con, stanza, session): |
| 1252 | | gajim.log.debug('FeatureNegCB') |
| 1253 | | feature = stanza.getTag(name='feature', namespace=common.xmpp.NS_FEATURE) |
| 1254 | | form = common.xmpp.DataForm(node=feature.getTag('x')) |
| 1255 | | |
| 1256 | | if form['FORM_TYPE'] == 'urn:xmpp:ssn': |
| 1257 | | self.dispatch('SESSION_NEG', (stanza.getFrom(), session, form)) |
| 1258 | | else: |
| 1259 | | reply = stanza.buildReply() |
| 1260 | | reply.setType('error') |
| 1261 | | |
| 1262 | | reply.addChild(feature) |
| 1263 | | reply.addChild(node=common.xmpp.ErrorNode('service-unavailable', typ='cancel')) |
| 1264 | | |
| 1265 | | con.send(reply) |
| 1266 | | |
| 1267 | | raise common.xmpp.NodeProcessed |
| 1268 | | |
| 1269 | | def _InitE2ECB(self, con, stanza, session): |
| 1270 | | gajim.log.debug('InitE2ECB') |
| 1271 | | init = stanza.getTag(name='init', namespace=common.xmpp.NS_ESESSION_INIT) |
| 1272 | | form = common.xmpp.DataForm(node=init.getTag('x')) |
| 1273 | | |
| 1274 | | self.dispatch('SESSION_NEG', (stanza.getFrom(), session, form)) |
| 1275 | | |
| 1729 | | |
| 1730 | | def get_or_create_session(self, jid, thread_id): |
| 1731 | | '''returns an existing session between this connection and 'jid', returns a new one if none exist.''' |
| 1732 | | |
| 1733 | | pm = True |
| 1734 | | if not gajim.interface.is_pm_contact(jid, self.name): |
| 1735 | | pm = False |
| 1736 | | jid = gajim.get_jid_without_resource(jid) |
| 1737 | | |
| 1738 | | session = self.find_session(jid, thread_id) |
| 1739 | | |
| 1740 | | if session: |
| 1741 | | return session |
| 1742 | | |
| 1743 | | if pm: |
| 1744 | | return self.make_new_session(jid, thread_id, type = 'pm') |
| 1745 | | else: |
| 1746 | | return self.make_new_session(jid, thread_id) |
| 1747 | | |
| 1748 | | def find_session(self, jid, thread_id): |
| 1749 | | try: |
| 1750 | | if not thread_id: |
| 1751 | | return self.find_null_session(jid) |
| 1752 | | else: |
| 1753 | | return self.sessions[jid][thread_id] |
| 1754 | | except KeyError: |
| 1755 | | return None |
| 1756 | | |
| 1757 | | def terminate_sessions(self): |
| 1758 | | '''send termination messages and delete all active sessions''' |
| 1759 | | for jid in self.sessions: |
| 1760 | | for thread_id in self.sessions[jid]: |
| 1761 | | self.sessions[jid][thread_id].terminate() |
| 1762 | | |
| 1763 | | self.sessions = {} |
| 1764 | | |
| 1765 | | def delete_session(self, jid, thread_id): |
| 1766 | | try: |
| 1767 | | del self.sessions[jid][thread_id] |
| 1768 | | |
| 1769 | | if not self.sessions[jid]: |
| 1770 | | del self.sessions[jid] |
| 1771 | | except KeyError: |
| 1772 | | pass |
| 1773 | | |
| 1774 | | def find_null_session(self, jid): |
| 1775 | | '''finds all of the sessions between us and a remote jid in which we |
| 1776 | | haven't received a thread_id yet and returns the session that we last |
| 1777 | | sent a message to.''' |
| 1778 | | |
| 1779 | | sessions = self.sessions[jid].values() |
| 1780 | | |
| 1781 | | # sessions that we haven't received a thread ID in |
| 1782 | | idless = filter(lambda s: not s.received_thread_id, sessions) |
| 1783 | | |
| 1784 | | # filter out everything exceptthe default session type |
| 1785 | | chat_sessions = filter(lambda s: isinstance(s, ChatControlSession), idless) |
| 1786 | | |
| 1787 | | if chat_sessions: |
| 1788 | | # return the session that we last sent a message in |
| 1789 | | chat_sessions.sort(key=lambda s: s.last_send) |
| 1790 | | return chat_sessions[-1] |
| 1791 | | else: |
| 1792 | | return None |
| 1793 | | |
| 1794 | | def make_new_session(self, jid, thread_id=None, type='chat', klass=None): |
| 1795 | | if not klass: |
| 1796 | | klass = ChatControlSession |
| 1797 | | |
| 1798 | | # determine if this session is a pm session |
| 1799 | | # if not, discard the resource |
| 1800 | | if not type == 'pm': |
| 1801 | | jid = gajim.get_jid_without_resource(jid) |
| 1802 | | |
| 1803 | | sess = klass(self, common.xmpp.JID(jid), thread_id, type) |
| 1804 | | |
| 1805 | | if not jid in self.sessions: |
| 1806 | | self.sessions[jid] = {} |
| 1807 | | |
| 1808 | | self.sessions[jid][sess.thread_id] = sess |
| 1809 | | |
| 1810 | | return sess |