annotate plugins/mod_message.lua @ 13652:a08065207ef0

net.server_epoll: Call :shutdown() on TLS sockets when supported Comment from Matthew: This fixes a potential issue where the Prosody process gets blocked on sockets waiting for them to close. Unlike non-TLS sockets, closing a TLS socket sends layer 7 data, and this can cause problems for sockets which are in the process of being cleaned up. This depends on LuaSec changes which are not yet upstream. From Martijn's original email: So first my analysis of luasec. in ssl.c the socket is put into blocking mode right before calling SSL_shutdown() inside meth_destroy(). My best guess to why this is is because meth_destroy is linked to the __close and __gc methods, which can't exactly be called multiple times and luasec does want to make sure that a tls session is shutdown as clean as possible. I can't say I disagree with this reasoning and don't want to change this behaviour. My solution to this without changing the current behaviour is to introduce a shutdown() method. I am aware that this overlaps in a conflicting way with tcp's shutdown method, but it stays close to the OpenSSL name. This method calls SSL_shutdown() in the current (non)blocking mode of the underlying socket and returns a boolean whether or not the shutdown is completed (matching SSL_shutdown()'s 0 or 1 return values), and returns the familiar ssl_ioerror() strings on error with a false for completion. This error can then be used to determine if we have wantread/wantwrite to finalize things. Once meth_shutdown() has been called once a shutdown flag will be set, which indicates to meth_destroy() that the SSL_shutdown() has been handled by the application and it shouldn't be needed to set the socket to blocking mode. I've left the SSL_shutdown() call in the LSEC_STATE_CONNECTED to prevent TOCTOU if the application reaches a timeout for the shutdown code, which might allow SSL_shutdown() to clean up anyway at the last possible moment. Another thing I've changed to luasec is the call to socket_setblocking() right before calling close(2) in socket_destroy() in usocket.c. According to the latest POSIX[0]: Note that the requirement for close() on a socket to block for up to the current linger interval is not conditional on the O_NONBLOCK setting. Which I read to mean that removing O_NONBLOCK on the socket before close doesn't impact the behaviour and only causes noise in system call tracers. I didn't touch the windows bits of this, since I don't do windows. For the prosody side of things I've made the TLS shutdown bits resemble interface:onwritable(), and put it under a combined guard of self._tls and self.conn.shutdown. The self._tls bit is there to prevent getting stuck on this condition, and self.conn.shutdown is there to prevent the code being called by instances where the patched luasec isn't deployed. The destroy() method can be called from various places and is read by me as the "we give up" error path. To accommodate for these unexpected entrypoints I've added a single call to self.conn:shutdown() to prevent the socket being put into blocking mode. I have no expectations that there is any other use here. Same as previous, the self.conn.shutdown check is there to make sure it's not called on unpatched luasec deployments and self._tls is there to make sure we don't call shutdown() on tcp sockets. I wouldn't recommend logging of the conn:shutdown() error inside close(), since a lot of clients simply close the connection before SSL_shutdown() is done.
author Martijn van Duren <martijn@openbsd.org>
date Thu, 06 Feb 2025 15:04:38 +0000
parents 74b9e05af71e
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1522
569d58d21612 Add copyright header to those files missing one
Matthew Wild <mwild1@gmail.com>
parents: 1423
diff changeset
1 -- Prosody IM
2923
b7049746bd29 Update copyright headers for 2010
Matthew Wild <mwild1@gmail.com>
parents: 1522
diff changeset
2 -- Copyright (C) 2008-2010 Matthew Wild
b7049746bd29 Update copyright headers for 2010
Matthew Wild <mwild1@gmail.com>
parents: 1522
diff changeset
3 -- Copyright (C) 2008-2010 Waqas Hussain
5776
bd0ff8ae98a8 Remove all trailing whitespace
Florian Zeitz <florob@babelmonkeys.de>
parents: 5370
diff changeset
4 --
1522
569d58d21612 Add copyright header to those files missing one
Matthew Wild <mwild1@gmail.com>
parents: 1423
diff changeset
5 -- This project is MIT/X11 licensed. Please see the
569d58d21612 Add copyright header to those files missing one
Matthew Wild <mwild1@gmail.com>
parents: 1423
diff changeset
6 -- COPYING file in the source package for more information.
569d58d21612 Add copyright header to those files missing one
Matthew Wild <mwild1@gmail.com>
parents: 1423
diff changeset
7 --
569d58d21612 Add copyright header to those files missing one
Matthew Wild <mwild1@gmail.com>
parents: 1423
diff changeset
8
1232
6ddbb583f067 mod_message: Initial commit
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
9
5370
7838acadb0fa mod_announce, mod_auth_anonymous, mod_c2s, mod_c2s, mod_component, mod_iq, mod_message, mod_presence, mod_tls: Access prosody.{hosts,bare_sessions,full_sessions} instead of the old globals
Kim Alvefur <zash@zash.se>
parents: 4965
diff changeset
10 local full_sessions = prosody.full_sessions;
7838acadb0fa mod_announce, mod_auth_anonymous, mod_c2s, mod_c2s, mod_component, mod_iq, mod_message, mod_presence, mod_tls: Access prosody.{hosts,bare_sessions,full_sessions} instead of the old globals
Kim Alvefur <zash@zash.se>
parents: 4965
diff changeset
11 local bare_sessions = prosody.bare_sessions;
1232
6ddbb583f067 mod_message: Initial commit
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
12
12977
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 11815
diff changeset
13 local st = require "prosody.util.stanza";
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 11815
diff changeset
14 local jid_bare = require "prosody.util.jid".bare;
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 11815
diff changeset
15 local jid_split = require "prosody.util.jid".split;
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 11815
diff changeset
16 local user_exists = require "prosody.core.usermanager".user_exists;
1274
50babb72edac mod_message: mod_message now handles all cases
Waqas Hussain <waqas20@gmail.com>
parents: 1272
diff changeset
17
1271
e78c161944ab mod_message: Move bare JID processing to it's own function
Waqas Hussain <waqas20@gmail.com>
parents: 1234
diff changeset
18 local function process_to_bare(bare, origin, stanza)
1274
50babb72edac mod_message: mod_message now handles all cases
Waqas Hussain <waqas20@gmail.com>
parents: 1272
diff changeset
19 local user = bare_sessions[bare];
5776
bd0ff8ae98a8 Remove all trailing whitespace
Florian Zeitz <florob@babelmonkeys.de>
parents: 5370
diff changeset
20
1272
28f9041d8c55 mod_message: Added code to handle error groupchat and headline messages to bare JID
Waqas Hussain <waqas20@gmail.com>
parents: 1271
diff changeset
21 local t = stanza.attr.type;
1275
850cf92b8ad4 mod_message: A little cleanup
Waqas Hussain <waqas20@gmail.com>
parents: 1274
diff changeset
22 if t == "error" then
7956
beaeafedc2d7 mod_message: Return early on messages of type error (silences empty if branch warning) [luacheck]
Kim Alvefur <zash@zash.se>
parents: 7718
diff changeset
23 return true; -- discard
1275
850cf92b8ad4 mod_message: A little cleanup
Waqas Hussain <waqas20@gmail.com>
parents: 1274
diff changeset
24 elseif t == "groupchat" then
11815
df1d3df2204a mod_message: Fire event for groupchat messages sent to bare JID
Matthew Wild <mwild1@gmail.com>
parents: 11797
diff changeset
25 local node, host = jid_split(bare);
df1d3df2204a mod_message: Fire event for groupchat messages sent to bare JID
Matthew Wild <mwild1@gmail.com>
parents: 11797
diff changeset
26 if user_exists(node, host) then
df1d3df2204a mod_message: Fire event for groupchat messages sent to bare JID
Matthew Wild <mwild1@gmail.com>
parents: 11797
diff changeset
27 if module:fire_event("message/bare/groupchat", {
df1d3df2204a mod_message: Fire event for groupchat messages sent to bare JID
Matthew Wild <mwild1@gmail.com>
parents: 11797
diff changeset
28 origin = origin, stanza = stanza;
df1d3df2204a mod_message: Fire event for groupchat messages sent to bare JID
Matthew Wild <mwild1@gmail.com>
parents: 11797
diff changeset
29 }) then
df1d3df2204a mod_message: Fire event for groupchat messages sent to bare JID
Matthew Wild <mwild1@gmail.com>
parents: 11797
diff changeset
30 return true;
df1d3df2204a mod_message: Fire event for groupchat messages sent to bare JID
Matthew Wild <mwild1@gmail.com>
parents: 11797
diff changeset
31 end
df1d3df2204a mod_message: Fire event for groupchat messages sent to bare JID
Matthew Wild <mwild1@gmail.com>
parents: 11797
diff changeset
32 end
df1d3df2204a mod_message: Fire event for groupchat messages sent to bare JID
Matthew Wild <mwild1@gmail.com>
parents: 11797
diff changeset
33
1272
28f9041d8c55 mod_message: Added code to handle error groupchat and headline messages to bare JID
Waqas Hussain <waqas20@gmail.com>
parents: 1271
diff changeset
34 origin.send(st.error_reply(stanza, "cancel", "service-unavailable"));
1275
850cf92b8ad4 mod_message: A little cleanup
Waqas Hussain <waqas20@gmail.com>
parents: 1274
diff changeset
35 elseif t == "headline" then
3408
e03fd9a16e19 mod_message: Discard headline messages sent to offline full JIDs (to follow latest spec updates).
Waqas Hussain <waqas20@gmail.com>
parents: 2923
diff changeset
36 if user and stanza.attr.to == bare then
1274
50babb72edac mod_message: mod_message now handles all cases
Waqas Hussain <waqas20@gmail.com>
parents: 1272
diff changeset
37 for _, session in pairs(user.sessions) do
1272
28f9041d8c55 mod_message: Added code to handle error groupchat and headline messages to bare JID
Waqas Hussain <waqas20@gmail.com>
parents: 1271
diff changeset
38 if session.presence and session.priority >= 0 then
28f9041d8c55 mod_message: Added code to handle error groupchat and headline messages to bare JID
Waqas Hussain <waqas20@gmail.com>
parents: 1271
diff changeset
39 session.send(stanza);
28f9041d8c55 mod_message: Added code to handle error groupchat and headline messages to bare JID
Waqas Hussain <waqas20@gmail.com>
parents: 1271
diff changeset
40 end
28f9041d8c55 mod_message: Added code to handle error groupchat and headline messages to bare JID
Waqas Hussain <waqas20@gmail.com>
parents: 1271
diff changeset
41 end
1274
50babb72edac mod_message: mod_message now handles all cases
Waqas Hussain <waqas20@gmail.com>
parents: 1272
diff changeset
42 end -- current policy is to discard headlines if no recipient is available
1275
850cf92b8ad4 mod_message: A little cleanup
Waqas Hussain <waqas20@gmail.com>
parents: 1274
diff changeset
43 else -- chat or normal message
850cf92b8ad4 mod_message: A little cleanup
Waqas Hussain <waqas20@gmail.com>
parents: 1274
diff changeset
44 if user then -- some resources are connected
1418
d14de6cb8b5b mod_message, mod_presence: Maintain list of top resources. Less work in routing messages to bare JIDs. - #optimization
Waqas Hussain <waqas20@gmail.com>
parents: 1329
diff changeset
45 local recipients = user.top_resources;
d14de6cb8b5b mod_message, mod_presence: Maintain list of top resources. Less work in routing messages to bare JIDs. - #optimization
Waqas Hussain <waqas20@gmail.com>
parents: 1329
diff changeset
46 if recipients then
4965
c1685f0441b7 mod_message: Don't treat a message as delivered ok if session.send() returns false
Matthew Wild <mwild1@gmail.com>
parents: 4759
diff changeset
47 local sent;
1275
850cf92b8ad4 mod_message: A little cleanup
Waqas Hussain <waqas20@gmail.com>
parents: 1274
diff changeset
48 for i=1,#recipients do
4965
c1685f0441b7 mod_message: Don't treat a message as delivered ok if session.send() returns false
Matthew Wild <mwild1@gmail.com>
parents: 4759
diff changeset
49 sent = recipients[i].send(stanza) or sent;
1275
850cf92b8ad4 mod_message: A little cleanup
Waqas Hussain <waqas20@gmail.com>
parents: 1274
diff changeset
50 end
4965
c1685f0441b7 mod_message: Don't treat a message as delivered ok if session.send() returns false
Matthew Wild <mwild1@gmail.com>
parents: 4759
diff changeset
51 if sent then
c1685f0441b7 mod_message: Don't treat a message as delivered ok if session.send() returns false
Matthew Wild <mwild1@gmail.com>
parents: 4759
diff changeset
52 return true;
c1685f0441b7 mod_message: Don't treat a message as delivered ok if session.send() returns false
Matthew Wild <mwild1@gmail.com>
parents: 4759
diff changeset
53 end
1274
50babb72edac mod_message: mod_message now handles all cases
Waqas Hussain <waqas20@gmail.com>
parents: 1272
diff changeset
54 end
1272
28f9041d8c55 mod_message: Added code to handle error groupchat and headline messages to bare JID
Waqas Hussain <waqas20@gmail.com>
parents: 1271
diff changeset
55 end
1275
850cf92b8ad4 mod_message: A little cleanup
Waqas Hussain <waqas20@gmail.com>
parents: 1274
diff changeset
56 -- no resources are online
850cf92b8ad4 mod_message: A little cleanup
Waqas Hussain <waqas20@gmail.com>
parents: 1274
diff changeset
57 local node, host = jid_split(bare);
3970
0f9ab57a1aee mod_message: Send service-unavailable if offline storage fails.
Robert Hoelz <rob@hoelz.ro>
parents: 3968
diff changeset
58 local ok
1275
850cf92b8ad4 mod_message: A little cleanup
Waqas Hussain <waqas20@gmail.com>
parents: 1274
diff changeset
59 if user_exists(node, host) then
3972
a05cf5d9c7ab mod_message, mod_offline: Change message/offline/store -> message/offline/handle
Robert Hoelz <rob@hoelz.ro>
parents: 3970
diff changeset
60 ok = module:fire_event('message/offline/handle', {
11797
72a2b85c0537 mod_message: Clarify purpose of username field in offline message event
Kim Alvefur <zash@zash.se>
parents: 11482
diff changeset
61 username = node, -- username of the recipient of the offline message
72a2b85c0537 mod_message: Clarify purpose of username field in offline message event
Kim Alvefur <zash@zash.se>
parents: 11482
diff changeset
62 origin = origin, -- the sender
8139
4119cca64064 mod_message: Normalize indentation
Kim Alvefur <zash@zash.se>
parents: 8136
diff changeset
63 stanza = stanza,
3970
0f9ab57a1aee mod_message: Send service-unavailable if offline storage fails.
Robert Hoelz <rob@hoelz.ro>
parents: 3968
diff changeset
64 });
0f9ab57a1aee mod_message: Send service-unavailable if offline storage fails.
Robert Hoelz <rob@hoelz.ro>
parents: 3968
diff changeset
65 end
0f9ab57a1aee mod_message: Send service-unavailable if offline storage fails.
Robert Hoelz <rob@hoelz.ro>
parents: 3968
diff changeset
66
0f9ab57a1aee mod_message: Send service-unavailable if offline storage fails.
Robert Hoelz <rob@hoelz.ro>
parents: 3968
diff changeset
67 if not ok then
1275
850cf92b8ad4 mod_message: A little cleanup
Waqas Hussain <waqas20@gmail.com>
parents: 1274
diff changeset
68 origin.send(st.error_reply(stanza, "cancel", "service-unavailable"));
850cf92b8ad4 mod_message: A little cleanup
Waqas Hussain <waqas20@gmail.com>
parents: 1274
diff changeset
69 end
1274
50babb72edac mod_message: mod_message now handles all cases
Waqas Hussain <waqas20@gmail.com>
parents: 1272
diff changeset
70 end
50babb72edac mod_message: mod_message now handles all cases
Waqas Hussain <waqas20@gmail.com>
parents: 1272
diff changeset
71 return true;
1271
e78c161944ab mod_message: Move bare JID processing to it's own function
Waqas Hussain <waqas20@gmail.com>
parents: 1234
diff changeset
72 end
e78c161944ab mod_message: Move bare JID processing to it's own function
Waqas Hussain <waqas20@gmail.com>
parents: 1234
diff changeset
73
e78c161944ab mod_message: Move bare JID processing to it's own function
Waqas Hussain <waqas20@gmail.com>
parents: 1234
diff changeset
74 module:hook("message/full", function(data)
8728
41c959c5c84b Fix spelling throughout the codebase [codespell]
Kim Alvefur <zash@zash.se>
parents: 8141
diff changeset
75 -- message to full JID received
1271
e78c161944ab mod_message: Move bare JID processing to it's own function
Waqas Hussain <waqas20@gmail.com>
parents: 1234
diff changeset
76 local origin, stanza = data.origin, data.stanza;
5776
bd0ff8ae98a8 Remove all trailing whitespace
Florian Zeitz <florob@babelmonkeys.de>
parents: 5370
diff changeset
77
1271
e78c161944ab mod_message: Move bare JID processing to it's own function
Waqas Hussain <waqas20@gmail.com>
parents: 1234
diff changeset
78 local session = full_sessions[stanza.attr.to];
4965
c1685f0441b7 mod_message: Don't treat a message as delivered ok if session.send() returns false
Matthew Wild <mwild1@gmail.com>
parents: 4759
diff changeset
79 if session and session.send(stanza) then
1271
e78c161944ab mod_message: Move bare JID processing to it's own function
Waqas Hussain <waqas20@gmail.com>
parents: 1234
diff changeset
80 return true;
e78c161944ab mod_message: Move bare JID processing to it's own function
Waqas Hussain <waqas20@gmail.com>
parents: 1234
diff changeset
81 else -- resource not online
e78c161944ab mod_message: Move bare JID processing to it's own function
Waqas Hussain <waqas20@gmail.com>
parents: 1234
diff changeset
82 return process_to_bare(jid_bare(stanza.attr.to), origin, stanza);
e78c161944ab mod_message: Move bare JID processing to it's own function
Waqas Hussain <waqas20@gmail.com>
parents: 1234
diff changeset
83 end
7718
c58075c4d375 mod_message, mod_carbons: Adjust event hook priorities to negative (core modules should do this to make overriding from other modules easier)
Kim Alvefur <zash@zash.se>
parents: 5776
diff changeset
84 end, -1);
1271
e78c161944ab mod_message: Move bare JID processing to it's own function
Waqas Hussain <waqas20@gmail.com>
parents: 1234
diff changeset
85
e78c161944ab mod_message: Move bare JID processing to it's own function
Waqas Hussain <waqas20@gmail.com>
parents: 1234
diff changeset
86 module:hook("message/bare", function(data)
8728
41c959c5c84b Fix spelling throughout the codebase [codespell]
Kim Alvefur <zash@zash.se>
parents: 8141
diff changeset
87 -- message to bare JID received
1271
e78c161944ab mod_message: Move bare JID processing to it's own function
Waqas Hussain <waqas20@gmail.com>
parents: 1234
diff changeset
88 local origin, stanza = data.origin, data.stanza;
e78c161944ab mod_message: Move bare JID processing to it's own function
Waqas Hussain <waqas20@gmail.com>
parents: 1234
diff changeset
89
e78c161944ab mod_message: Move bare JID processing to it's own function
Waqas Hussain <waqas20@gmail.com>
parents: 1234
diff changeset
90 return process_to_bare(stanza.attr.to or (origin.username..'@'..origin.host), origin, stanza);
7718
c58075c4d375 mod_message, mod_carbons: Adjust event hook priorities to negative (core modules should do this to make overriding from other modules easier)
Kim Alvefur <zash@zash.se>
parents: 5776
diff changeset
91 end, -1);