1 |
|
-module(mongoose_s2s_mnesia). |
2 |
|
-behaviour(mongoose_s2s_backend). |
3 |
|
|
4 |
|
-export([init/1, |
5 |
|
get_s2s_out_pids/1, |
6 |
|
try_register/2, |
7 |
|
remove_connection/2, |
8 |
|
node_cleanup/1]). |
9 |
|
|
10 |
|
-export([register_secret/2, |
11 |
|
get_shared_secret/1]). |
12 |
|
|
13 |
|
-record(s2s, { |
14 |
|
fromto :: ejabberd_s2s:fromto() | '_', |
15 |
|
pid :: pid() | '$1' |
16 |
|
}). |
17 |
|
|
18 |
|
-record(s2s_shared, { |
19 |
|
host_type :: mongooseim:host_type(), |
20 |
|
secret :: ejabberd_s2s:base16_secret() |
21 |
|
}). |
22 |
|
|
23 |
|
-include("mongoose_logger.hrl"). |
24 |
|
|
25 |
|
-spec init(map()) -> ok. |
26 |
|
init(_) -> |
27 |
93 |
init_pids(), |
28 |
93 |
init_secrets(), |
29 |
93 |
ok. |
30 |
|
|
31 |
|
%% Pid lists |
32 |
|
init_pids() -> |
33 |
93 |
Opts = [{ram_copies, [node()]}, {type, bag}, |
34 |
|
{attributes, record_info(fields, s2s)}], |
35 |
93 |
mongoose_mnesia:create_table(s2s, Opts). |
36 |
|
|
37 |
|
-spec get_s2s_out_pids(ejabberd_s2s:fromto()) -> ejabberd_s2s:s2s_pids(). |
38 |
|
get_s2s_out_pids(FromTo) -> |
39 |
67 |
s2s_to_pids(mnesia:dirty_read(s2s, FromTo)). |
40 |
|
|
41 |
|
-spec try_register(Pid :: pid(), |
42 |
|
FromTo :: ejabberd_s2s:fromto()) -> boolean(). |
43 |
|
try_register(Pid, FromTo) -> |
44 |
11 |
F = fun() -> |
45 |
11 |
Pids = get_s2s_out_pids(FromTo), |
46 |
11 |
case mongoose_s2s_lib:need_more_connections(FromTo, Pids) of |
47 |
|
true -> |
48 |
8 |
mnesia:write(#s2s{fromto = FromTo, pid = Pid}), |
49 |
8 |
true; |
50 |
|
false -> |
51 |
3 |
false |
52 |
|
end |
53 |
|
end, |
54 |
11 |
case mnesia:transaction(F) of |
55 |
|
{atomic, Bool} -> |
56 |
11 |
Bool; |
57 |
|
Other -> |
58 |
:-( |
?LOG_ERROR(#{what => s2s_try_register_failed, |
59 |
|
s2s_pid => Pid, from_to => FromTo, |
60 |
:-( |
reason => Other}), |
61 |
:-( |
false |
62 |
|
end. |
63 |
|
|
64 |
|
-spec remove_connection(FromTo :: ejabberd_s2s:fromto(), Pid :: pid()) -> ok. |
65 |
|
remove_connection(FromTo, Pid) -> |
66 |
11 |
Rec = #s2s{fromto = FromTo, pid = Pid}, |
67 |
11 |
F = fun() -> |
68 |
12 |
mnesia:delete_object(Rec) |
69 |
|
end, |
70 |
11 |
case mnesia:transaction(F) of |
71 |
|
{atomic, _} -> |
72 |
11 |
ok; |
73 |
|
Other -> |
74 |
:-( |
?LOG_ERROR(#{what => s2s_remove_connection, |
75 |
:-( |
from_to => FromTo, reason => Other}), |
76 |
:-( |
ok |
77 |
|
end. |
78 |
|
|
79 |
|
-spec node_cleanup(Node :: node()) -> ok. |
80 |
|
node_cleanup(Node) -> |
81 |
8 |
F = fun() -> |
82 |
8 |
Es = mnesia:select( |
83 |
|
s2s, |
84 |
|
[{#s2s{pid = '$1', _ = '_'}, |
85 |
|
[{'==', {node, '$1'}, Node}], |
86 |
|
['$_']}]), |
87 |
8 |
lists:foreach(fun(E) -> |
88 |
:-( |
mnesia:delete_object(E) |
89 |
|
end, Es) |
90 |
|
end, |
91 |
8 |
mnesia:async_dirty(F), |
92 |
8 |
ok. |
93 |
|
|
94 |
|
s2s_to_pids(List) -> |
95 |
67 |
[Pid || #s2s{pid = Pid} <- List]. |
96 |
|
|
97 |
|
%% Secrets |
98 |
|
init_secrets() -> |
99 |
93 |
Opts = [{ram_copies, [node()]}, {attributes, record_info(fields, s2s_shared)}], |
100 |
93 |
mongoose_mnesia:create_table(s2s_shared, Opts). |
101 |
|
|
102 |
|
-spec register_secret(HostType :: mongooseim:host_type(), |
103 |
|
Secret :: ejabberd_s2s:base16_secret()) -> ok. |
104 |
|
register_secret(HostType, Secret) -> |
105 |
341 |
Rec = #s2s_shared{host_type = HostType, secret = Secret}, |
106 |
341 |
{atomic, _} = mnesia:transaction(fun() -> mnesia:write(Rec) end), |
107 |
341 |
ok. |
108 |
|
|
109 |
|
-spec get_shared_secret(mongooseim:host_type()) -> |
110 |
|
{ok, ejabberd_s2s:base16_secret()} | {error, not_found}. |
111 |
|
get_shared_secret(HostType) -> |
112 |
508 |
case mnesia:dirty_read(s2s_shared, HostType) of |
113 |
|
[#s2s_shared{secret = Secret}] -> |
114 |
167 |
{ok, Secret}; |
115 |
|
[] -> |
116 |
341 |
{error, not_found} |
117 |
|
end. |