Software / code / prosody
Comparison
plugins/mod_c2s.lua @ 11120:b2331f3dfeea
Merge 0.11->trunk
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Wed, 30 Sep 2020 09:50:33 +0100 |
| parent | 11118:ece430d49809 |
| parent | 10850:bd2814f900dd |
| child | 11359:db146bf7b120 |
comparison
equal
deleted
inserted
replaced
| 11119:68df52bf08d5 | 11120:b2331f3dfeea |
|---|---|
| 54 | 54 |
| 55 --- Stream events handlers | 55 --- Stream events handlers |
| 56 local stream_xmlns_attr = {xmlns='urn:ietf:params:xml:ns:xmpp-streams'}; | 56 local stream_xmlns_attr = {xmlns='urn:ietf:params:xml:ns:xmpp-streams'}; |
| 57 | 57 |
| 58 function stream_callbacks.streamopened(session, attr) | 58 function stream_callbacks.streamopened(session, attr) |
| 59 -- run _streamopened in async context | |
| 60 session.thread:run({ stream = "opened", attr = attr }); | |
| 61 end | |
| 62 | |
| 63 function stream_callbacks._streamopened(session, attr) | |
| 59 local send = session.send; | 64 local send = session.send; |
| 65 if not attr.to then | |
| 66 session:close{ condition = "improper-addressing", | |
| 67 text = "A 'to' attribute is required on stream headers" }; | |
| 68 return; | |
| 69 end | |
| 60 local host = nameprep(attr.to); | 70 local host = nameprep(attr.to); |
| 61 if not host then | 71 if not host then |
| 62 session:close{ condition = "improper-addressing", | 72 session:close{ condition = "improper-addressing", |
| 63 text = "A valid 'to' attribute is required on stream headers" }; | 73 text = "A valid 'to' attribute is required on stream headers" }; |
| 64 return; | 74 return; |
| 96 local info = sock:info(); | 106 local info = sock:info(); |
| 97 (session.log or log)("info", "Stream encrypted (%s with %s)", info.protocol, info.cipher); | 107 (session.log or log)("info", "Stream encrypted (%s with %s)", info.protocol, info.cipher); |
| 98 session.compressed = info.compression; | 108 session.compressed = info.compression; |
| 99 else | 109 else |
| 100 (session.log or log)("info", "Stream encrypted"); | 110 (session.log or log)("info", "Stream encrypted"); |
| 101 session.compressed = sock.compression and sock:compression(); --COMPAT mw/luasec-hg | |
| 102 end | 111 end |
| 103 end | 112 end |
| 104 | 113 |
| 105 local features = st.stanza("stream:features"); | 114 local features = st.stanza("stream:features"); |
| 106 hosts[session.host].events.fire_event("stream-features", { origin = session, features = features }); | 115 hosts[session.host].events.fire_event("stream-features", { origin = session, features = features }); |
| 107 if features.tags[1] or session.full_jid then | 116 if features.tags[1] or session.full_jid then |
| 108 send(features); | 117 send(features); |
| 109 else | 118 else |
| 110 (session.log or log)("warn", "No stream features to offer"); | 119 if session.secure then |
| 120 -- Here SASL should be offered | |
| 121 (session.log or log)("warn", "No stream features to offer on secure session. Check authentication settings."); | |
| 122 else | |
| 123 -- Normally STARTTLS would be offered | |
| 124 (session.log or log)("warn", "No stream features to offer on insecure session. Check encryption and security settings."); | |
| 125 end | |
| 111 session:close{ condition = "undefined-condition", text = "No stream features to proceed with" }; | 126 session:close{ condition = "undefined-condition", text = "No stream features to proceed with" }; |
| 112 end | 127 end |
| 113 end | 128 end |
| 114 | 129 |
| 115 function stream_callbacks.streamclosed(session) | 130 function stream_callbacks.streamclosed(session, attr) |
| 131 -- run _streamclosed in async context | |
| 132 session.thread:run({ stream = "closed", attr = attr }); | |
| 133 end | |
| 134 | |
| 135 function stream_callbacks._streamclosed(session) | |
| 116 session.log("debug", "Received </stream:stream>"); | 136 session.log("debug", "Received </stream:stream>"); |
| 117 session:close(false); | 137 session:close(false); |
| 118 end | 138 end |
| 119 | 139 |
| 120 function stream_callbacks.error(session, error, data) | 140 function stream_callbacks.error(session, error, data) |
| 121 if error == "no-stream" then | 141 if error == "no-stream" then |
| 122 session.log("debug", "Invalid opening stream header (%s)", (data:gsub("^([^\1]+)\1", "{%1}"))); | 142 session.log("debug", "Invalid opening stream header (%s)", (data:gsub("^([^\1]+)\1", "{%1}"))); |
| 123 session:close("invalid-namespace"); | 143 session:close("invalid-namespace"); |
| 124 elseif error == "parse-error" then | 144 elseif error == "parse-error" then |
| 125 (session.log or log)("debug", "Client XML parse error: %s", tostring(data)); | 145 (session.log or log)("debug", "Client XML parse error: %s", data); |
| 126 session:close("not-well-formed"); | 146 session:close("not-well-formed"); |
| 127 elseif error == "stream-error" then | 147 elseif error == "stream-error" then |
| 128 local condition, text = "undefined-condition"; | 148 local condition, text = "undefined-condition"; |
| 129 for child in data:childtags(nil, xmlns_xmpp_streams) do | 149 for child in data:childtags(nil, xmlns_xmpp_streams) do |
| 130 if child.name ~= "text" then | 150 if child.name ~= "text" then |
| 250 | 270 |
| 251 -- Check if TLS compression is used | 271 -- Check if TLS compression is used |
| 252 local sock = conn:socket(); | 272 local sock = conn:socket(); |
| 253 if sock.info then | 273 if sock.info then |
| 254 session.compressed = sock:info"compression"; | 274 session.compressed = sock:info"compression"; |
| 255 elseif sock.compression then | |
| 256 session.compressed = sock:compression(); --COMPAT mw/luasec-hg | |
| 257 end | 275 end |
| 258 end | 276 end |
| 259 | 277 |
| 260 if opt_keepalives then | 278 if opt_keepalives then |
| 261 conn:setoption("keepalive", opt_keepalives); | 279 conn:setoption("keepalive", opt_keepalives); |
| 271 session.notopen = true; | 289 session.notopen = true; |
| 272 session.stream:reset(); | 290 session.stream:reset(); |
| 273 end | 291 end |
| 274 | 292 |
| 275 session.thread = runner(function (stanza) | 293 session.thread = runner(function (stanza) |
| 276 core_process_stanza(session, stanza); | 294 if st.is_stanza(stanza) then |
| 295 core_process_stanza(session, stanza); | |
| 296 elseif stanza.stream == "opened" then | |
| 297 stream_callbacks._streamopened(session, stanza.attr); | |
| 298 elseif stanza.stream == "closed" then | |
| 299 stream_callbacks._streamclosed(session, stanza.attr); | |
| 300 end | |
| 277 end, runner_callbacks, session); | 301 end, runner_callbacks, session); |
| 278 | 302 |
| 279 local filter = session.filter; | 303 local filter = session.filter; |
| 280 function session.data(data) | 304 function session.data(data) |
| 281 -- Parse the data, which will store stanzas in session.pending_stanzas | 305 -- Parse the data, which will store stanzas in session.pending_stanzas |
| 282 if data then | 306 if data then |
| 283 data = filter("bytes/in", data); | 307 data = filter("bytes/in", data); |
| 284 if data then | 308 if data then |
| 285 local ok, err = stream:feed(data); | 309 local ok, err = stream:feed(data); |
| 286 if not ok then | 310 if not ok then |
| 287 log("debug", "Received invalid XML (%s) %d bytes: %s", tostring(err), #data, data:sub(1, 300):gsub("[\r\n]+", " "):gsub("[%z\1-\31]", "_")); | 311 log("debug", "Received invalid XML (%s) %d bytes: %q", err, #data, data:sub(1, 300)); |
| 288 session:close("not-well-formed"); | 312 if err == "stanza-too-large" then |
| 313 session:close({ condition = "policy-violation", text = "XML stanza is too big" }); | |
| 314 else | |
| 315 session:close("not-well-formed"); | |
| 316 end | |
| 289 end | 317 end |
| 290 end | 318 end |
| 291 end | 319 end |
| 292 end | 320 end |
| 293 | 321 |
| 326 if session then | 354 if session then |
| 327 return (hosts[session.host] or prosody).events.fire_event("c2s-read-timeout", { session = session }); | 355 return (hosts[session.host] or prosody).events.fire_event("c2s-read-timeout", { session = session }); |
| 328 end | 356 end |
| 329 end | 357 end |
| 330 | 358 |
| 359 function listener.ondrain(conn) | |
| 360 local session = sessions[conn]; | |
| 361 if session then | |
| 362 return (hosts[session.host] or prosody).events.fire_event("c2s-ondrain", { session = session }); | |
| 363 end | |
| 364 end | |
| 365 | |
| 331 local function keepalive(event) | 366 local function keepalive(event) |
| 332 local session = event.session; | 367 local session = event.session; |
| 333 if not session.notopen then | 368 if not session.notopen then |
| 334 return event.session.send(' '); | 369 return event.session.send(' '); |
| 335 end | 370 end |
| 358 name = "c2s"; | 393 name = "c2s"; |
| 359 listener = listener; | 394 listener = listener; |
| 360 default_port = 5222; | 395 default_port = 5222; |
| 361 encryption = "starttls"; | 396 encryption = "starttls"; |
| 362 multiplex = { | 397 multiplex = { |
| 398 protocol = "xmpp-client"; | |
| 363 pattern = "^<.*:stream.*%sxmlns%s*=%s*(['\"])jabber:client%1.*>"; | 399 pattern = "^<.*:stream.*%sxmlns%s*=%s*(['\"])jabber:client%1.*>"; |
| 364 }; | 400 }; |
| 365 }); | 401 }); |
| 366 | 402 |
| 367 module:provides("net", { | 403 module:provides("net", { |