19 local BOSH_DEFAULT_HOLD = tonumber(config.get("*", "core", "bosh_default_hold")) or 1; |
19 local BOSH_DEFAULT_HOLD = tonumber(config.get("*", "core", "bosh_default_hold")) or 1; |
20 local BOSH_DEFAULT_INACTIVITY = tonumber(config.get("*", "core", "bosh_max_inactivity")) or 60; |
20 local BOSH_DEFAULT_INACTIVITY = tonumber(config.get("*", "core", "bosh_max_inactivity")) or 60; |
21 local BOSH_DEFAULT_POLLING = tonumber(config.get("*", "core", "bosh_max_polling")) or 5; |
21 local BOSH_DEFAULT_POLLING = tonumber(config.get("*", "core", "bosh_max_polling")) or 5; |
22 local BOSH_DEFAULT_REQUESTS = tonumber(config.get("*", "core", "bosh_max_requests")) or 2; |
22 local BOSH_DEFAULT_REQUESTS = tonumber(config.get("*", "core", "bosh_max_requests")) or 2; |
23 local BOSH_DEFAULT_MAXPAUSE = tonumber(config.get("*", "core", "bosh_max_pause")) or 300; |
23 local BOSH_DEFAULT_MAXPAUSE = tonumber(config.get("*", "core", "bosh_max_pause")) or 300; |
|
24 |
|
25 local default_headers = { ["Content-Type"] = "text/xml; charset=utf-8" }; |
24 |
26 |
25 local t_insert, t_remove, t_concat = table.insert, table.remove, table.concat; |
27 local t_insert, t_remove, t_concat = table.insert, table.remove, table.concat; |
26 local os_time = os.time; |
28 local os_time = os.time; |
27 |
29 |
28 local sessions = {}; |
30 local sessions = {}; |
98 end |
100 end |
99 |
101 |
100 |
102 |
101 local function bosh_reset_stream(session) session.notopen = true; end |
103 local function bosh_reset_stream(session) session.notopen = true; end |
102 |
104 |
103 local session_close_reply = st.stanza("body", { xmlns = xmlns_bosh, type = "terminate" }); |
105 local session_close_reply = { headers = default_headers, body = st.stanza("body", { xmlns = xmlns_bosh, type = "terminate" }) }; |
104 local function bosh_close_stream(session, reason) |
106 local function bosh_close_stream(session, reason) |
105 (session.log or log)("info", "BOSH client disconnected"); |
107 (session.log or log)("info", "BOSH client disconnected"); |
106 session_close_reply.attr.condition = reason; |
108 session_close_reply.attr.condition = reason; |
107 local session_close_reply = tostring(session_close_reply); |
109 local session_close_reply = tostring(session_close_reply); |
108 for _, held_request in ipairs(session.requests) do |
110 for _, held_request in ipairs(session.requests) do |
122 |
124 |
123 -- TODO: Sanity checks here (rid, to, known host, etc.) |
125 -- TODO: Sanity checks here (rid, to, known host, etc.) |
124 if not hosts[attr.to] then |
126 if not hosts[attr.to] then |
125 -- Unknown host |
127 -- Unknown host |
126 session_close_reply.attr.condition = "host-unknown"; |
128 session_close_reply.attr.condition = "host-unknown"; |
127 request:send(tostring(session_close_reply)); |
129 request:send{ headers = default_headers, body = tostring(session_close_reply) }; |
128 request.notopen = nil |
130 request.notopen = nil |
129 return; |
131 return; |
130 end |
132 end |
131 |
133 |
132 -- New session |
134 -- New session |
135 bosh_hold = BOSH_DEFAULT_HOLD, bosh_max_inactive = BOSH_DEFAULT_INACTIVITY, |
137 bosh_hold = BOSH_DEFAULT_HOLD, bosh_max_inactive = BOSH_DEFAULT_INACTIVITY, |
136 requests = { }, send_buffer = {}, reset_stream = bosh_reset_stream, close = bosh_close_stream, dispatch_stanza = core_process_stanza }; |
138 requests = { }, send_buffer = {}, reset_stream = bosh_reset_stream, close = bosh_close_stream, dispatch_stanza = core_process_stanza }; |
137 sessions[sid] = session; |
139 sessions[sid] = session; |
138 log("info", "New BOSH session, assigned it sid '%s'", sid); |
140 log("info", "New BOSH session, assigned it sid '%s'", sid); |
139 local r, send_buffer = session.requests, session.send_buffer; |
141 local r, send_buffer = session.requests, session.send_buffer; |
140 local response = { } |
142 local response = { headers = default_headers } |
141 function session.send(s) |
143 function session.send(s) |
142 log("debug", "Sending BOSH data: %s", tostring(s)); |
144 log("debug", "Sending BOSH data: %s", tostring(s)); |
143 local oldest_request = r[1]; |
145 local oldest_request = r[1]; |
144 while oldest_request and oldest_request.destroyed do |
146 while oldest_request and oldest_request.destroyed do |
145 t_remove(r, 1); |
147 t_remove(r, 1); |
177 --xmpp:version='1.0' xmlns:xmpp='urn:xmpp:xbosh' |
179 --xmpp:version='1.0' xmlns:xmpp='urn:xmpp:xbosh' |
178 local response = st.stanza("body", { xmlns = xmlns_bosh, |
180 local response = st.stanza("body", { xmlns = xmlns_bosh, |
179 inactivity = tostring(BOSH_DEFAULT_INACTIVITY), polling = tostring(BOSH_DEFAULT_POLLING), requests = tostring(BOSH_DEFAULT_REQUESTS), hold = tostring(session.bosh_hold), maxpause = "120", |
181 inactivity = tostring(BOSH_DEFAULT_INACTIVITY), polling = tostring(BOSH_DEFAULT_POLLING), requests = tostring(BOSH_DEFAULT_REQUESTS), hold = tostring(session.bosh_hold), maxpause = "120", |
180 sid = sid, ver = '1.6', from = session.host, secure = 'true', ["xmpp:version"] = "1.0", |
182 sid = sid, ver = '1.6', from = session.host, secure = 'true', ["xmpp:version"] = "1.0", |
181 ["xmlns:xmpp"] = "urn:xmpp:xbosh", ["xmlns:stream"] = "http://etherx.jabber.org/streams" }):add_child(features); |
183 ["xmlns:xmpp"] = "urn:xmpp:xbosh", ["xmlns:stream"] = "http://etherx.jabber.org/streams" }):add_child(features); |
182 request:send(tostring(response)); |
184 request:send{ headers = default_headers, body = tostring(response) }; |
183 |
185 |
184 request.sid = sid; |
186 request.sid = sid; |
185 return; |
187 return; |
186 end |
188 end |
187 |
189 |
188 local session = sessions[sid]; |
190 local session = sessions[sid]; |
189 if not session then |
191 if not session then |
190 -- Unknown sid |
192 -- Unknown sid |
191 log("info", "Client tried to use sid '%s' which we don't know about", sid); |
193 log("info", "Client tried to use sid '%s' which we don't know about", sid); |
192 request:send(tostring(st.stanza("body", { xmlns = xmlns_bosh, type = "terminate", condition = "item-not-found" }))); |
194 request:send{ headers = default_headers, body = tostring(st.stanza("body", { xmlns = xmlns_bosh, type = "terminate", condition = "item-not-found" })) }; |
193 request.notopen = nil; |
195 request.notopen = nil; |
194 return; |
196 return; |
195 end |
197 end |
196 |
198 |
197 if attr.type == "terminate" then |
199 if attr.type == "terminate" then |