Software /
code /
verse
Comparison
plugins/jingle.lua @ 380:0891b4e27766
Discard trailing whitespace
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Fri, 01 May 2015 23:27:29 +0200 |
parent | 341:a95890d86fe4 |
child | 392:cdea6a28369e |
comparison
equal
deleted
inserted
replaced
379:d80d27234e38 | 380:0891b4e27766 |
---|---|
14 | 14 |
15 function verse.plugins.jingle(stream) | 15 function verse.plugins.jingle(stream) |
16 stream:hook("ready", function () | 16 stream:hook("ready", function () |
17 stream:add_disco_feature(xmlns_jingle); | 17 stream:add_disco_feature(xmlns_jingle); |
18 end, 10); | 18 end, 10); |
19 | 19 |
20 function stream:jingle(to) | 20 function stream:jingle(to) |
21 return verse.eventable(setmetatable(base or { | 21 return verse.eventable(setmetatable(base or { |
22 role = "initiator"; | 22 role = "initiator"; |
23 peer = to; | 23 peer = to; |
24 sid = uuid_generate(); | 24 sid = uuid_generate(); |
25 stream = stream; | 25 stream = stream; |
26 }, jingle_mt)); | 26 }, jingle_mt)); |
27 end | 27 end |
28 | 28 |
29 function stream:register_jingle_transport(transport) | 29 function stream:register_jingle_transport(transport) |
30 -- transport is a function that receives a | 30 -- transport is a function that receives a |
31 -- <transport> element, and returns a connection | 31 -- <transport> element, and returns a connection |
32 -- We wait for 'connected' on that connection, | 32 -- We wait for 'connected' on that connection, |
33 -- and use :send() and 'incoming-raw'. | 33 -- and use :send() and 'incoming-raw'. |
34 end | 34 end |
35 | 35 |
36 function stream:register_jingle_content_type(content) | 36 function stream:register_jingle_content_type(content) |
37 -- Call content() for every 'incoming-raw'? | 37 -- Call content() for every 'incoming-raw'? |
38 -- I think content() returns the object we return | 38 -- I think content() returns the object we return |
39 -- on jingle:accept() | 39 -- on jingle:accept() |
40 end | 40 end |
41 | 41 |
42 local function handle_incoming_jingle(stanza) | 42 local function handle_incoming_jingle(stanza) |
43 local jingle_tag = stanza:get_child("jingle", xmlns_jingle); | 43 local jingle_tag = stanza:get_child("jingle", xmlns_jingle); |
44 local sid = jingle_tag.attr.sid; | 44 local sid = jingle_tag.attr.sid; |
45 local action = jingle_tag.attr.action; | 45 local action = jingle_tag.attr.action; |
46 local result = stream:event("jingle/"..sid, stanza); | 46 local result = stream:event("jingle/"..sid, stanza); |
55 local reply = verse.error_reply(stanza, "cancel", "item-not-found") | 55 local reply = verse.error_reply(stanza, "cancel", "item-not-found") |
56 :tag("unknown-session", { xmlns = xmlns_jingle_errors }):up(); | 56 :tag("unknown-session", { xmlns = xmlns_jingle_errors }):up(); |
57 stream:send(reply); | 57 stream:send(reply); |
58 return; | 58 return; |
59 end | 59 end |
60 | 60 |
61 -- Ok, session-initiate, new session | 61 -- Ok, session-initiate, new session |
62 | 62 |
63 -- Create new Jingle object | 63 -- Create new Jingle object |
64 local sid = jingle_tag.attr.sid; | 64 local sid = jingle_tag.attr.sid; |
65 | 65 |
66 local jingle = verse.eventable{ | 66 local jingle = verse.eventable{ |
67 role = "receiver"; | 67 role = "receiver"; |
68 peer = stanza.attr.from; | 68 peer = stanza.attr.from; |
69 sid = sid; | 69 sid = sid; |
70 stream = stream; | 70 stream = stream; |
71 }; | 71 }; |
72 | 72 |
73 setmetatable(jingle, jingle_mt); | 73 setmetatable(jingle, jingle_mt); |
74 | 74 |
75 local content_tag; | 75 local content_tag; |
76 local content, transport; | 76 local content, transport; |
77 for tag in jingle_tag:childtags() do | 77 for tag in jingle_tag:childtags() do |
78 if tag.name == "content" and tag.attr.xmlns == xmlns_jingle then | 78 if tag.name == "content" and tag.attr.xmlns == xmlns_jingle then |
79 local description_tag = tag:child_with_name("description"); | 79 local description_tag = tag:child_with_name("description"); |
82 local desc_handler = stream:event("jingle/content/"..description_xmlns, jingle, description_tag); | 82 local desc_handler = stream:event("jingle/content/"..description_xmlns, jingle, description_tag); |
83 if desc_handler then | 83 if desc_handler then |
84 content = desc_handler; | 84 content = desc_handler; |
85 end | 85 end |
86 end | 86 end |
87 | 87 |
88 local transport_tag = tag:child_with_name("transport"); | 88 local transport_tag = tag:child_with_name("transport"); |
89 local transport_xmlns = transport_tag.attr.xmlns; | 89 local transport_xmlns = transport_tag.attr.xmlns; |
90 | 90 |
91 transport = stream:event("jingle/transport/"..transport_xmlns, jingle, transport_tag); | 91 transport = stream:event("jingle/transport/"..transport_xmlns, jingle, transport_tag); |
92 if content and transport then | 92 if content and transport then |
93 content_tag = tag; | 93 content_tag = tag; |
94 break; | 94 break; |
95 end | 95 end |
98 if not content then | 98 if not content then |
99 -- FIXME: Fail, no content | 99 -- FIXME: Fail, no content |
100 stream:send(verse.error_reply(stanza, "cancel", "feature-not-implemented", "The specified content is not supported")); | 100 stream:send(verse.error_reply(stanza, "cancel", "feature-not-implemented", "The specified content is not supported")); |
101 return true; | 101 return true; |
102 end | 102 end |
103 | 103 |
104 if not transport then | 104 if not transport then |
105 -- FIXME: Refuse session, no transport | 105 -- FIXME: Refuse session, no transport |
106 stream:send(verse.error_reply(stanza, "cancel", "feature-not-implemented", "The specified transport is not supported")); | 106 stream:send(verse.error_reply(stanza, "cancel", "feature-not-implemented", "The specified transport is not supported")); |
107 return true; | 107 return true; |
108 end | 108 end |
109 | 109 |
110 stream:send(verse.reply(stanza)); | 110 stream:send(verse.reply(stanza)); |
111 | 111 |
112 jingle.content_tag = content_tag; | 112 jingle.content_tag = content_tag; |
113 jingle.creator, jingle.name = content_tag.attr.creator, content_tag.attr.name; | 113 jingle.creator, jingle.name = content_tag.attr.creator, content_tag.attr.name; |
114 jingle.content, jingle.transport = content, transport; | 114 jingle.content, jingle.transport = content, transport; |
115 | 115 |
116 function jingle:decline() | 116 function jingle:decline() |
117 -- FIXME: Decline session | 117 -- FIXME: Decline session |
118 end | 118 end |
119 | 119 |
120 stream:hook("jingle/"..sid, function (stanza) | 120 stream:hook("jingle/"..sid, function (stanza) |
121 if stanza.attr.from ~= jingle.peer then | 121 if stanza.attr.from ~= jingle.peer then |
122 return false; | 122 return false; |
123 end | 123 end |
124 local jingle_tag = stanza:get_child("jingle", xmlns_jingle); | 124 local jingle_tag = stanza:get_child("jingle", xmlns_jingle); |
125 return jingle:handle_command(jingle_tag); | 125 return jingle:handle_command(jingle_tag); |
126 end); | 126 end); |
127 | 127 |
128 stream:event("jingle", jingle); | 128 stream:event("jingle", jingle); |
129 return true; | 129 return true; |
130 end | 130 end |
131 | 131 |
132 function jingle_mt:handle_command(jingle_tag) | 132 function jingle_mt:handle_command(jingle_tag) |
133 local action = jingle_tag.attr.action; | 133 local action = jingle_tag.attr.action; |
134 stream:debug("Handling Jingle command: %s", action); | 134 stream:debug("Handling Jingle command: %s", action); |
135 if action == "session-terminate" then | 135 if action == "session-terminate" then |
136 self:destroy(); | 136 self:destroy(); |
164 self.stream:send(stanza); | 164 self.stream:send(stanza); |
165 else | 165 else |
166 self.stream:send_iq(stanza, callback); | 166 self.stream:send_iq(stanza, callback); |
167 end | 167 end |
168 end | 168 end |
169 | 169 |
170 function jingle_mt:accept(options) | 170 function jingle_mt:accept(options) |
171 local accept_stanza = verse.iq({ to = self.peer, type = "set" }) | 171 local accept_stanza = verse.iq({ to = self.peer, type = "set" }) |
172 :tag("jingle", { | 172 :tag("jingle", { |
173 xmlns = xmlns_jingle, | 173 xmlns = xmlns_jingle, |
174 sid = self.sid, | 174 sid = self.sid, |
175 action = "session-accept", | 175 action = "session-accept", |
176 responder = stream.jid, | 176 responder = stream.jid, |
177 }) | 177 }) |
178 :tag("content", { creator = self.creator, name = self.name }); | 178 :tag("content", { creator = self.creator, name = self.name }); |
179 | 179 |
180 local content_accept_tag = self.content:generate_accept(self.content_tag:child_with_name("description"), options); | 180 local content_accept_tag = self.content:generate_accept(self.content_tag:child_with_name("description"), options); |
181 accept_stanza:add_child(content_accept_tag); | 181 accept_stanza:add_child(content_accept_tag); |
182 | 182 |
183 local transport_accept_tag = self.transport:generate_accept(self.content_tag:child_with_name("transport"), options); | 183 local transport_accept_tag = self.transport:generate_accept(self.content_tag:child_with_name("transport"), options); |
184 accept_stanza:add_child(transport_accept_tag); | 184 accept_stanza:add_child(transport_accept_tag); |
185 | 185 |
186 local jingle = self; | 186 local jingle = self; |
187 stream:send_iq(accept_stanza, function (result) | 187 stream:send_iq(accept_stanza, function (result) |
188 if result.attr.type == "error" then | 188 if result.attr.type == "error" then |
189 local type, condition, text = result:get_error(); | 189 local type, condition, text = result:get_error(); |
190 stream:error("session-accept rejected: %s", condition); -- FIXME: Notify | 190 stream:error("session-accept rejected: %s", condition); -- FIXME: Notify |
195 jingle.state = "active"; | 195 jingle.state = "active"; |
196 jingle:event("connected", conn); | 196 jingle:event("connected", conn); |
197 end); | 197 end); |
198 end); | 198 end); |
199 end | 199 end |
200 | 200 |
201 | 201 |
202 stream:hook("iq/"..xmlns_jingle, handle_incoming_jingle); | 202 stream:hook("iq/"..xmlns_jingle, handle_incoming_jingle); |
203 return true; | 203 return true; |
204 end | 204 end |
205 | 205 |
206 function jingle_mt:offer(name, content) | 206 function jingle_mt:offer(name, content) |
207 local session_initiate = verse.iq({ to = self.peer, type = "set" }) | 207 local session_initiate = verse.iq({ to = self.peer, type = "set" }) |
208 :tag("jingle", { xmlns = xmlns_jingle, action = "session-initiate", | 208 :tag("jingle", { xmlns = xmlns_jingle, action = "session-initiate", |
209 initiator = self.stream.jid, sid = self.sid }); | 209 initiator = self.stream.jid, sid = self.sid }); |
210 | 210 |
211 -- Content tag | 211 -- Content tag |
212 session_initiate:tag("content", { creator = self.role, name = name }); | 212 session_initiate:tag("content", { creator = self.role, name = name }); |
213 | 213 |
214 -- Need description element from someone who can turn 'content' into XML | 214 -- Need description element from someone who can turn 'content' into XML |
215 local description = self.stream:event("jingle/describe/"..name, content); | 215 local description = self.stream:event("jingle/describe/"..name, content); |
216 | 216 |
217 if not description then | 217 if not description then |
218 return false, "Unknown content type"; | 218 return false, "Unknown content type"; |
219 end | 219 end |
220 | 220 |
221 session_initiate:add_child(description); | 221 session_initiate:add_child(description); |
222 | 222 |
223 -- FIXME: Sort transports by 1) recipient caps 2) priority (SOCKS vs IBB, etc.) | 223 -- FIXME: Sort transports by 1) recipient caps 2) priority (SOCKS vs IBB, etc.) |
224 -- Fixed to s5b in the meantime | 224 -- Fixed to s5b in the meantime |
225 local transport = self.stream:event("jingle/transport/".."urn:xmpp:jingle:transports:s5b:1", self); | 225 local transport = self.stream:event("jingle/transport/".."urn:xmpp:jingle:transports:s5b:1", self); |
226 self.transport = transport; | 226 self.transport = transport; |
227 | 227 |
228 session_initiate:add_child(transport:generate_initiate()); | 228 session_initiate:add_child(transport:generate_initiate()); |
229 | 229 |
230 self.stream:debug("Hooking %s", "jingle/"..self.sid); | 230 self.stream:debug("Hooking %s", "jingle/"..self.sid); |
231 self.stream:hook("jingle/"..self.sid, function (stanza) | 231 self.stream:hook("jingle/"..self.sid, function (stanza) |
232 if stanza.attr.from ~= self.peer then | 232 if stanza.attr.from ~= self.peer then |
233 return false; | 233 return false; |
234 end | 234 end |
235 local jingle_tag = stanza:get_child("jingle", xmlns_jingle); | 235 local jingle_tag = stanza:get_child("jingle", xmlns_jingle); |
236 return self:handle_command(jingle_tag) | 236 return self:handle_command(jingle_tag) |
237 end); | 237 end); |
238 | 238 |
239 self.stream:send_iq(session_initiate, function (result) | 239 self.stream:send_iq(session_initiate, function (result) |
240 if result.attr.type == "error" then | 240 if result.attr.type == "error" then |
241 self.state = "terminated"; | 241 self.state = "terminated"; |
242 local type, condition, text = result:get_error(); | 242 local type, condition, text = result:get_error(); |
243 return self:event("error", { type = type, condition = condition, text = text }); | 243 return self:event("error", { type = type, condition = condition, text = text }); |