./ct_report/coverage/mod_jingle_sip_backend.COVER.html

1 %% @doc Backend module for mod_jingle_sip
2 %% @author Michal Piotrowski <michal.piotrowski@erlang-solutions.com>
3 %%
4 %%==============================================================================
5 %% Copyright 2018 Erlang Solutions Ltd.
6 %%
7 %% Licensed under the Apache License, Version 2.0 (the "License");
8 %% you may not use this file except in compliance with the License.
9 %% You may obtain a copy of the License at
10 %%
11 %% http://www.apache.org/licenses/LICENSE-2.0
12 %%
13 %% Unless required by applicable law or agreed to in writing, software
14 %% distributed under the License is distributed on an "AS IS" BASIS,
15 %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 %% See the License for the specific language governing permissions and
17 %% limitations under the License.
18 %%==============================================================================
19 -module(mod_jingle_sip_backend).
20
21 -include("mongoose.hrl").
22
23 -type call_id() :: binary().
24 -type incoming_request() :: {node(), binary()}.
25 -type outgoing_handle() :: binary().
26
27 -export([init/2]).
28 -export([set_incoming_request/5]).
29 -export([set_incoming_handle/2]).
30 -export([set_outgoing_request/4]).
31 -export([set_outgoing_handle/4]).
32 -export([set_outgoing_accepted/1]).
33 -export([set_incoming_accepted/1]).
34 -export([get_incoming_request/2]).
35 -export([get_outgoing_handle/2]).
36 -export([get_session_info/2]).
37 -export([remove_session/1]).
38
39 -ignore_xref([remove_session/1]).
40
41 -record(jingle_sip_session, {sid,
42 dialog,
43 state,
44 direction,
45 request,
46 node,
47 owner,
48 from,
49 to,
50 now,
51 meta}).
52
53 init(_Host, _Opts) ->
54
:-(
mnesia:create_table(jingle_sip_session,
55 [{ram_copies, [node()]},
56 {attributes, record_info(fields, jingle_sip_session)}]).
57
58 -spec set_incoming_request(CallID :: call_id(), ReqID :: binary(),
59 From :: jid:jid(), To :: jid:jid(), exml:element()) ->
60 ok | {error, any()}.
61 set_incoming_request(CallID, ReqID, From, To, JingleEl) ->
62
:-(
TFun = pa:bind(fun set_incoming_request_tr/5, CallID, ReqID, From, To, JingleEl),
63
:-(
run_transaction(TFun).
64
65 set_incoming_request_tr(CallID, ReqID, From, To, JingleEl) ->
66
:-(
Owner = jid:to_lus(To),
67
:-(
case mnesia:wread({jingle_sip_session, CallID}) of
68 [_] ->
69
:-(
{error, sid_already_exists};
70 _ ->
71
:-(
Meta = #{init_stanza => JingleEl},
72
:-(
Session = #jingle_sip_session{sid = CallID,
73 request = ReqID,
74 dialog = undefined,
75 state = undefined,
76 direction = in,
77 node = node(),
78 from = jid:to_lus(From),
79 to = Owner,
80 owner = Owner,
81 now = os:system_time(microsecond),
82 meta = Meta},
83
:-(
mnesia:write(Session)
84 end.
85
86 -spec set_outgoing_request(CallID :: call_id(), ReqID :: binary(),
87 From :: jid:jid(), To :: jid:jid()) ->
88 ok | {error, any()}.
89 set_outgoing_request(CallID, ReqID, From, To) ->
90
:-(
TFun = pa:bind(fun set_outgoing_request_tr/4, CallID, ReqID, From, To),
91
:-(
run_transaction(TFun).
92
93 set_outgoing_request_tr(CallID, ReqID, From, To) ->
94
:-(
Owner = jid:to_lus(From),
95
:-(
case mnesia:wread({jingle_sip_session, CallID}) of
96 [_] ->
97
:-(
{error, sid_already_exists};
98 _ ->
99
:-(
Session = #jingle_sip_session{sid = CallID,
100 request = ReqID,
101 dialog = undefined,
102 state = undefined,
103 direction = out,
104 node = node(),
105 from = Owner,
106 to = jid:to_lus(To),
107 owner = Owner,
108 now = os:system_time(microsecond),
109 meta = #{}},
110
:-(
mnesia:write(Session)
111 end.
112
113 run_transaction(TFun) ->
114
:-(
case mnesia:transaction(TFun) of
115 {atomic, Result} ->
116
:-(
Result;
117 {aborted, Reason} ->
118
:-(
{error, Reason}
119 end.
120
121
122 set_incoming_handle(CallID, DialogHandle) ->
123
:-(
TFun = pa:bind(fun set_incoming_handle_tr/2, CallID, DialogHandle),
124
:-(
run_transaction(TFun).
125
126 set_incoming_handle_tr(CallID, DialogHandle) ->
127
:-(
case mnesia:wread({jingle_sip_session, CallID}) of
128 [#jingle_sip_session{dialog = undefined, direction = in} = Session] ->
129
:-(
Session2 = Session#jingle_sip_session{dialog = DialogHandle,
130 node = node()},
131
:-(
mnesia:write(Session2);
132 [_] ->
133
:-(
{error, incoming_handle_exists};
134 _ ->
135
:-(
{error, not_found}
136 end.
137
138 set_outgoing_handle(CallID, DialogHandle, From, To) ->
139
:-(
TFun = pa:bind(fun set_outgoing_handle_tr/4, CallID, DialogHandle, From, To),
140
:-(
run_transaction(TFun).
141
142 set_outgoing_handle_tr(CallID, DialogHandle, _From, _To) ->
143
:-(
case mnesia:wread({jingle_sip_session, CallID}) of
144 [#jingle_sip_session{dialog = undefined, direction = out} = Session] ->
145
:-(
Session2 = Session#jingle_sip_session{dialog = DialogHandle,
146 node = node()},
147
:-(
mnesia:write(Session2);
148 [_] ->
149
:-(
{error, outgoing_handle_exists};
150 _ ->
151
:-(
Session = #jingle_sip_session{sid = CallID,
152 dialog = DialogHandle,
153 node = node(),
154 direction = out,
155 state = ringing},
156
:-(
mnesia:write(Session)
157 end.
158
159 set_incoming_accepted(CallID) ->
160
:-(
TFun = pa:bind(fun set_incoming_accepted_tr/1, CallID),
161
:-(
run_transaction(TFun).
162
163 set_incoming_accepted_tr(CallID) ->
164
:-(
case mnesia:wread({jingle_sip_session, CallID}) of
165 [#jingle_sip_session{direction = in, meta = Meta} = Session] ->
166
:-(
MetaWithoutInitStanza = maps:without([init_stanza], Meta),
167
:-(
Session2 = Session#jingle_sip_session{state = accepted,
168 meta = MetaWithoutInitStanza},
169
:-(
mnesia:write(Session2);
170 _ ->
171
:-(
{error, not_found}
172 end.
173
174 set_outgoing_accepted(CallID) ->
175
:-(
TFun = pa:bind(fun set_outgoing_accepted_tr/1, CallID),
176
:-(
run_transaction(TFun).
177
178 set_outgoing_accepted_tr(CallID) ->
179
:-(
case mnesia:wread({jingle_sip_session, CallID}) of
180 [#jingle_sip_session{direction = out} = Session] ->
181
:-(
Session2 = Session#jingle_sip_session{state = accepted},
182
:-(
mnesia:write(Session2);
183 _ ->
184
:-(
{error, not_found}
185 end.
186
187 -spec get_incoming_request(call_id(), jid:jid()) -> {ok, undefined | incoming_request()} |
188 {error, not_found}.
189 get_incoming_request(CallID, User) ->
190
:-(
UserUS = jid:to_lus(User),
191
:-(
case mnesia:dirty_read(jingle_sip_session, CallID) of
192 [#jingle_sip_session{request = ReqID, node = Node, owner = UserUS}] ->
193
:-(
{ok, {Node, ReqID}};
194 _ ->
195
:-(
{error, not_found}
196 end.
197
198 -spec get_outgoing_handle(call_id(), jid:jid()) -> {ok, undefined | outgoing_handle()} |
199 {error, not_found}.
200 get_outgoing_handle(SID, User) ->
201
:-(
UserUS = jid:to_lus(User),
202
:-(
case mnesia:dirty_read(jingle_sip_session, SID) of
203 [#jingle_sip_session{dialog = Handle, owner = UserUS}] ->
204
:-(
{ok, Handle};
205 _ ->
206
:-(
{error, not_found}
207 end.
208
209 -spec get_session_info(binary(), jid:jid()) ->
210 {ok, map()} | {error, any()}.
211 get_session_info(SID, User) ->
212
:-(
UserUS = jid:to_lus(User),
213
:-(
case mnesia:dirty_read(jingle_sip_session, SID) of
214 [#jingle_sip_session{sid = SID,
215 dialog = Handle,
216 request = Request,
217 state = State,
218 direction = Dir,
219 node = ONode,
220 owner = UserUS,
221 to = To,
222 from = From,
223 meta = Meta}] ->
224
:-(
{ok, #{sid => SID,
225 dialog => Handle,
226 request => Request,
227 state => State,
228 direction => Dir,
229 node => ONode,
230 from => From,
231 to => To,
232 meta => Meta}};
233 _ ->
234
:-(
{error, not_found}
235 end.
236
237 remove_session(CallID) ->
238
:-(
mnesia:dirty_delete(jingle_sip_session, CallID).
Line Hits Source