Software /
code /
verse
Comparison
component.lua @ 84:d85d2443478e
verse.component: XEP-0114 support \o/
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Tue, 03 Aug 2010 09:17:23 +0100 |
child | 150:728cc7f2f0c2 |
comparison
equal
deleted
inserted
replaced
83:8221f3c25fd4 | 84:d85d2443478e |
---|---|
1 local verse = require "verse"; | |
2 local stream = verse.stream_mt; | |
3 | |
4 local jid_split = require "util.jid".split; | |
5 local lxp = require "lxp"; | |
6 local st = require "util.stanza"; | |
7 local sha1 = require "util.sha1".sha1; | |
8 | |
9 -- Shortcuts to save having to load util.stanza | |
10 verse.message, verse.presence, verse.iq, verse.stanza, verse.reply, verse.error_reply = | |
11 st.message, st.presence, st.iq, st.stanza, st.reply, st.error_reply; | |
12 | |
13 local init_xmlhandlers = require "core.xmlhandlers"; | |
14 | |
15 local xmlns_stream = "http://etherx.jabber.org/streams"; | |
16 local xmlns_component = "jabber:component:accept"; | |
17 | |
18 local stream_callbacks = { | |
19 stream_ns = xmlns_stream, | |
20 stream_tag = "stream", | |
21 default_ns = "jabber:client" }; | |
22 | |
23 function stream_callbacks.streamopened(stream, attr) | |
24 stream.stream_id = attr.id; | |
25 if not stream:event("opened", attr) then | |
26 stream.notopen = nil; | |
27 end | |
28 return true; | |
29 end | |
30 | |
31 function stream_callbacks.streamclosed(stream) | |
32 return stream:event("closed"); | |
33 end | |
34 | |
35 function stream_callbacks.handlestanza(stream, stanza) | |
36 if stanza.attr.xmlns == xmlns_stream then | |
37 return stream:event("stream-"..stanza.name, stanza); | |
38 elseif stanza.attr.xmlns then | |
39 return stream:event("stream/"..stanza.attr.xmlns, stanza); | |
40 end | |
41 | |
42 return stream:event("stanza", stanza); | |
43 end | |
44 | |
45 function stream:reset() | |
46 -- Reset stream | |
47 local parser = lxp.new(init_xmlhandlers(self, stream_callbacks), "\1"); | |
48 self.parser = parser; | |
49 | |
50 self.notopen = true; | |
51 | |
52 return true; | |
53 end | |
54 | |
55 function stream:connect_component(jid, pass) | |
56 self.jid, self.password = jid, pass; | |
57 self.username, self.host, self.resource = jid_split(jid); | |
58 | |
59 function self.data(conn, data) | |
60 local ok, err = self.parser:parse(data); | |
61 if ok then return; end | |
62 stream:debug("debug", "Received invalid XML (%s) %d bytes: %s", tostring(err), #data, data:sub(1, 300):gsub("[\r\n]+", " ")); | |
63 stream:close("xml-not-well-formed"); | |
64 end | |
65 | |
66 self:hook("incoming-raw", function (data) return self.data(self.conn, data); end); | |
67 | |
68 self.curr_id = 0; | |
69 | |
70 self.tracked_iqs = {}; | |
71 self:hook("stanza", function (stanza) | |
72 local id, type = stanza.attr.id, stanza.attr.type; | |
73 if id and stanza.name == "iq" and (type == "result" or type == "error") and self.tracked_iqs[id] then | |
74 self.tracked_iqs[id](stanza); | |
75 self.tracked_iqs[id] = nil; | |
76 return true; | |
77 end | |
78 end); | |
79 | |
80 self:hook("stanza", function (stanza) | |
81 if stanza.attr.xmlns == nil or stanza.attr.xmlns == "jabber:client" then | |
82 if stanza.name == "iq" and (stanza.attr.type == "get" or stanza.attr.type == "set") then | |
83 local xmlns = stanza.tags[1] and stanza.tags[1].attr.xmlns; | |
84 if xmlns then | |
85 ret = self:event("iq/"..xmlns, stanza); | |
86 if not ret then | |
87 ret = self:event("iq", stanza); | |
88 end | |
89 end | |
90 if ret == nil then | |
91 self:send(verse.error_reply(stanza, "cancel", "service-unavailable")); | |
92 return true; | |
93 end | |
94 else | |
95 ret = self:event(stanza.name, stanza); | |
96 end | |
97 end | |
98 return ret; | |
99 end, -1); | |
100 | |
101 self:hook("opened", function (attr) | |
102 print(self.jid, self.stream_id, attr.id); | |
103 local token = sha1(self.stream_id..pass, true); | |
104 | |
105 self:send(st.stanza("handshake", { xmlns = xmlns_component }):text(token)); | |
106 self:hook("stream/"..xmlns_component, function (stanza) | |
107 if stanza.name == "handshake" then | |
108 self:event("authentication-success"); | |
109 end | |
110 end); | |
111 end); | |
112 | |
113 local function stream_ready() | |
114 self:event("ready"); | |
115 end | |
116 self:hook("authentication-success", stream_ready, -1); | |
117 | |
118 -- Initialise connection | |
119 self:connect(self.connect_host or self.host, self.connect_port or 5347); | |
120 self:reopen(); | |
121 end | |
122 | |
123 function stream:reopen() | |
124 self:reset(); | |
125 self:send(st.stanza("stream:stream", { to = self.host, ["xmlns:stream"]='http://etherx.jabber.org/streams', | |
126 xmlns = xmlns_component, version = "1.0" }):top_tag()); | |
127 end | |
128 | |
129 function stream:close(reason) | |
130 if not self.notopen then | |
131 self:send("</stream:stream>"); | |
132 end | |
133 local on_disconnect = self.conn.disconnect(); | |
134 self.conn:close(); | |
135 on_disconnect(conn, reason); | |
136 end | |
137 | |
138 function stream:send_iq(iq, callback) | |
139 local id = self:new_id(); | |
140 self.tracked_iqs[id] = callback; | |
141 iq.attr.id = id; | |
142 self:send(iq); | |
143 end | |
144 | |
145 function stream:new_id() | |
146 self.curr_id = self.curr_id + 1; | |
147 return tostring(self.curr_id); | |
148 end |