./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 2 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 15 TFun = pa:bind(fun set_incoming_request_tr/5, CallID, ReqID, From, To, JingleEl),
63 15 run_transaction(TFun).
64
65 set_incoming_request_tr(CallID, ReqID, From, To, JingleEl) ->
66 15 Owner = jid:to_lus(To),
67 15 case mnesia:wread({jingle_sip_session, CallID}) of
68 [_] ->
69
:-(
{error, sid_already_exists};
70 _ ->
71 15 Meta = #{init_stanza => JingleEl},
72 15 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 15 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 18 TFun = pa:bind(fun set_outgoing_request_tr/4, CallID, ReqID, From, To),
91 18 run_transaction(TFun).
92
93 set_outgoing_request_tr(CallID, ReqID, From, To) ->
94 18 Owner = jid:to_lus(From),
95 18 case mnesia:wread({jingle_sip_session, CallID}) of
96 [_] ->
97
:-(
{error, sid_already_exists};
98 _ ->
99 18 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 18 mnesia:write(Session)
111 end.
112
113 run_transaction(TFun) ->
114 85 case mnesia:transaction(TFun) of
115 {atomic, Result} ->
116 85 Result;
117 {aborted, Reason} ->
118
:-(
{error, Reason}
119 end.
120
121
122 set_incoming_handle(CallID, DialogHandle) ->
123 15 TFun = pa:bind(fun set_incoming_handle_tr/2, CallID, DialogHandle),
124 15 run_transaction(TFun).
125
126 set_incoming_handle_tr(CallID, DialogHandle) ->
127 15 case mnesia:wread({jingle_sip_session, CallID}) of
128 [#jingle_sip_session{dialog = undefined, direction = in} = Session] ->
129 15 Session2 = Session#jingle_sip_session{dialog = DialogHandle,
130 node = node()},
131 15 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 17 TFun = pa:bind(fun set_outgoing_handle_tr/4, CallID, DialogHandle, From, To),
140 17 run_transaction(TFun).
141
142 set_outgoing_handle_tr(CallID, DialogHandle, _From, _To) ->
143 17 case mnesia:wread({jingle_sip_session, CallID}) of
144 [#jingle_sip_session{dialog = undefined, direction = out} = Session] ->
145 17 Session2 = Session#jingle_sip_session{dialog = DialogHandle,
146 node = node()},
147 17 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 9 TFun = pa:bind(fun set_incoming_accepted_tr/1, CallID),
161 9 run_transaction(TFun).
162
163 set_incoming_accepted_tr(CallID) ->
164 9 case mnesia:wread({jingle_sip_session, CallID}) of
165 [#jingle_sip_session{direction = in, meta = Meta} = Session] ->
166 9 MetaWithoutInitStanza = maps:without([init_stanza], Meta),
167 9 Session2 = Session#jingle_sip_session{state = accepted,
168 meta = MetaWithoutInitStanza},
169 9 mnesia:write(Session2);
170 _ ->
171
:-(
{error, not_found}
172 end.
173
174 set_outgoing_accepted(CallID) ->
175 11 TFun = pa:bind(fun set_outgoing_accepted_tr/1, CallID),
176 11 run_transaction(TFun).
177
178 set_outgoing_accepted_tr(CallID) ->
179 11 case mnesia:wread({jingle_sip_session, CallID}) of
180 [#jingle_sip_session{direction = out} = Session] ->
181 11 Session2 = Session#jingle_sip_session{state = accepted},
182 11 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 10 UserUS = jid:to_lus(User),
191 10 case mnesia:dirty_read(jingle_sip_session, CallID) of
192 [#jingle_sip_session{request = ReqID, node = Node, owner = UserUS}] ->
193 9 {ok, {Node, ReqID}};
194 _ ->
195 1 {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 3 UserUS = jid:to_lus(User),
202 3 case mnesia:dirty_read(jingle_sip_session, SID) of
203 [#jingle_sip_session{dialog = Handle, owner = UserUS}] ->
204 3 {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 8 UserUS = jid:to_lus(User),
213 8 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 7 {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 1 {error, not_found}
235 end.
236
237 remove_session(CallID) ->
238
:-(
mnesia:dirty_delete(jingle_sip_session, CallID).
Line Hits Source