1
2
3
4
5
6
7
8
9
10
11
12
13
14 """
15 Handles Jingle contents (XEP 0166)
16 """
17
18 import xmpp
19
20 contents = {}
21
26
27
29 """
30 Exception that should be raised when a content fails to setup.
31 """
32
33
34 -class JingleContent(object):
35 """
36 An abstraction of content in Jingle sessions
37 """
38
39 - def __init__(self, session, transport):
40 self.session = session
41 self.transport = transport
42
43
44
45
46
47 self.accepted = False
48 self.sent = False
49 self.negotiated = False
50
51 self.media = None
52
53 self.senders = 'both'
54 self.allow_sending = True
55
56 self.callbacks = {
57
58 'content-accept': [self.__on_transport_info],
59 'content-add': [self.__on_transport_info],
60 'content-modify': [],
61 'content-reject': [],
62 'content-remove': [],
63 'description-info': [],
64 'security-info': [],
65 'session-accept': [self.__on_transport_info],
66 'session-info': [],
67 'session-initiate': [self.__on_transport_info],
68 'session-terminate': [],
69 'transport-info': [self.__on_transport_info],
70 'transport-replace': [],
71 'transport-accept': [],
72 'transport-reject': [],
73 'iq-result': [],
74 'iq-error': [],
75
76 'content-accept-sent': [self.__fill_jingle_stanza],
77 'content-add-sent': [self.__fill_jingle_stanza],
78 'session-initiate-sent': [self.__fill_jingle_stanza],
79 'session-accept-sent': [self.__fill_jingle_stanza],
80 'session-terminate-sent': [],
81 }
82
84 return self.accepted and not self.sent
85
86 - def on_negotiated(self):
87 if self.accepted:
88 self.negotiated = True
89 self.session.content_negotiated(self.media)
90
91 - def add_remote_candidates(self, candidates):
92 """
93 Add a list of candidates to the list of remote candidates
94 """
95 pass
96
97 - def on_stanza(self, stanza, content, error, action):
98 """
99 Called when something related to our content was sent by peer
100 """
101 if action in self.callbacks:
102 for callback in self.callbacks[action]:
103 callback(stanza, content, error, action)
104
105 - def __on_transport_info(self, stanza, content, error, action):
106 """
107 Got a new transport candidate
108 """
109 candidates = self.transport.parse_transport_stanza(
110 content.getTag('transport'))
111 if candidates:
112 self.add_remote_candidates(candidates)
113
114 - def __content(self, payload=[]):
115 """
116 Build a XML content-wrapper for our data
117 """
118 return xmpp.Node('content',
119 attrs={'name': self.name, 'creator': self.creator},
120 payload=payload)
121
122 - def send_candidate(self, candidate):
123 """
124 Send a transport candidate for a previously defined transport.
125 """
126 content = self.__content()
127 content.addChild(node=self.transport.make_transport([candidate]))
128 self.session.send_transport_info(content)
129
131 content = self.__content()
132 self._fill_content(content)
133 self.session.send_description_info(content)
134
135 - def __fill_jingle_stanza(self, stanza, content, error, action):
136 """
137 Add our things to session-initiate stanza
138 """
139 self._fill_content(content)
140 self.sent = True
141 content.addChild(node=self.transport.make_transport())
142
144 self.callbacks = None
145 del self.session.contents[(self.creator, self.name)]
146