1 from protocol import Acks
2 from protocol import NS_STREAM_MGMT
3 import logging
4 log = logging.getLogger('nbxmpp.smacks')
5
7 '''
8 This is Smacks is the Stream Management class. It takes care of requesting
9 and sending acks. Also, it keeps track of the unhandled outgoing stanzas.
10
11 The dispatcher has to be able to access this class to increment the
12 number of handled stanzas
13 '''
14
16 self.con = con
17 self.out_h = 0
18 self.in_h = 0
19 self.uqueue = []
20 self.session_id = None
21 self.resumption = False
22
23 self.max_queue = 5
24 self._owner = None
25 self.resuming = False
26 self.enabled = False
27 self.location = None
28
30 self._owner = owner
31
32
33 owner.Dispatcher.RegisterNamespace(NS_STREAM_MGMT)
34 owner.Dispatcher.RegisterHandler('enabled', self._neg_response,
35 xmlns=NS_STREAM_MGMT)
36 owner.Dispatcher.RegisterHandler('r', self.send_ack,
37 xmlns=NS_STREAM_MGMT)
38 owner.Dispatcher.RegisterHandler('a', self.check_ack,
39 xmlns=NS_STREAM_MGMT)
40 owner.Dispatcher.RegisterHandler('resumed', self.check_ack,
41 xmlns=NS_STREAM_MGMT)
42 owner.Dispatcher.RegisterHandler('failed', self.error_handling,
43 xmlns=NS_STREAM_MGMT)
44
46 r = stanza.getAttr('resume')
47 if r == 'true' or r == 'True' or r == '1':
48 self.resumption = True
49 self.session_id = stanza.getAttr('id')
50
51 if r == 'false' or r == 'False' or r == '0':
52 self.negociate(False)
53
54 l = stanza.getAttr('location')
55 if l:
56 self.location = l
57
59
60
61 self.uqueue = []
62 self.in_h = 0
63 self.out_h = 0
64 self.session_id = None
65 self.enabled = True
66
67 stanza = Acks()
68 stanza.buildEnable(resume)
69 self._owner.Connection.send(stanza, now=True)
70
72 if not self.session_id:
73 self.resuming = False
74 log.error('Attempted to resume without a valid session id ')
75 return
76 resume = Acks()
77 resume.buildResume(self.in_h, self.session_id)
78 self._owner.Connection.send(resume, False)
79
84
89
91 '''
92 Checks if the number of stanzas sent are the same as the
93 number of stanzas received by the server. Pops stanzas that were
94 handled by the server from the queue.
95 '''
96 h = int(stanza.getAttr('h'))
97 diff = self.out_h - h
98
99 if len(self.uqueue) < diff or diff < 0:
100 log.error('Server and client number of stanzas handled mismatch ')
101 else:
102 while (len(self.uqueue) > diff):
103 self.uqueue.pop(0)
104
105 if stanza.getName() == 'resumed':
106 self.enabled = True
107 self.resuming = True
108 self.con.set_oldst()
109 if self.uqueue != []:
110 for i in self.uqueue:
111 self._owner.Connection.send(i, False)
112
114
115
116 if stanza.getTag('item-not-found'):
117 self.resuming = False
118 self.enabled = False
119
120 self._owner.NonBlockingBind.resuming = False
121 self._owner._on_auth_bind(None)
122 return
123
124
125 if stanza.getTag('feature-not-implemented'):
126 self.negociate(False)
127 return
128
129 if stanza.getTag('unexpected-request'):
130 self.enabled = False
131 log.error('Gajim failed to negociate Stream Management')
132 return
133