1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2000-2019. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20
21%%
22%%----------------------------------------------------------------------
23%% Purpose: A fun implementation of user callbacks
24%%----------------------------------------------------------------------
25
26-module(megaco_mess_user_test).
27
28-behaviour(megaco_user).
29
30-export([
31         handle_connect/2, handle_connect/3,
32         handle_disconnect/3,
33         handle_syntax_error/3,        handle_syntax_error/4,
34         handle_message_error/3,       handle_message_error/4,
35         handle_trans_request/3,       handle_trans_request/4,
36         handle_trans_long_request/3,  handle_trans_long_request/4,
37         handle_trans_reply/4,         handle_trans_reply/5,
38         handle_trans_ack/4,           handle_trans_ack/5,
39	 handle_unexpected_trans/3,    handle_unexpected_trans/4,
40         handle_trans_request_abort/4, handle_trans_request_abort/5,
41         handle_segment_reply/5,       handle_segment_reply/6
42        ]).
43
44-export([
45	 start_proxy/0,
46	 stop_proxy/0,
47	 apply_proxy/1,
48	 reply/3,
49
50	 start_transport/2,
51	 loop_transport/1, % Internal only
52	 send_message/2,
53	 resend_message/2
54	]).
55
56-include("megaco_test_lib.hrl").
57-define(SERVER, ?MODULE).
58
59start_proxy() ->
60    yes = global:register_name(?SERVER, self()),
61    Pid = megaco_test_lib:proxy_start(?MODULE),
62    put(?MODULE, Pid),
63    Pid.
64
65stop_proxy() ->
66    global:unregister_name(?SERVER),
67    Pid = erase(?MODULE),
68    unlink(Pid),
69    exit(Pid, shutdown).
70
71whereis_proxy() ->
72    case get(?MODULE) of
73	undefined ->
74	    exit(no_server, ?MODULE);
75	Pid when is_pid(Pid) ->
76	    Pid
77    end.
78
79apply_proxy(Fun) ->
80    Pid = whereis_proxy(),
81    ?APPLY(Pid, Fun),
82    ok.
83
84reply(Mod, Line, Fun) when is_function(Fun) ->
85    receive
86	{?MODULE, Pid, UserCallback} ->
87	    UserReply = Fun(UserCallback),
88	    Pid ! {?MODULE, self(), UserReply},
89	    UserReply%% ;
90	%% Other ->
91	%%     megaco_test_lib:error(Other, Mod, Line),
92	%%     {error, Other}
93     after 10000 ->
94 	       megaco_test_lib:error(timeout, Mod, Line),
95 	       {error, timeout}
96    end.
97
98call(UserCallback) ->
99    Request = {?MODULE, self(), UserCallback},
100    case global:whereis_name(?SERVER) of
101	undefined ->
102	    exit({no_server, ?SERVER, Request});
103        Pid when is_pid(Pid) ->
104	    ?LOG("call[~p] -> bang request: "
105		 "~n   ~p"
106		 "~n", [Pid, Request]),
107	    Pid ! Request,
108	    call_await_reply(Pid)
109    end.
110
111call_await_reply(Pid) ->
112    receive
113	{?MODULE, Pid, UserReply} = _Reply ->
114	    case UserReply of
115		{ok, Good}   -> Good;
116		{error, Bad} -> exit(Bad)
117	    end;
118	{'EXIT', Pid, Reason} = Bad ->
119	    ?LOG("receive test case exit: ~p~n", [Bad]),
120	    exit(Reason);
121	{'EXIT', _, _Reason} = Bad ->
122	    ?LOG("receive unknown exit: ~p~n", [Bad]),
123	    call_await_reply(Pid);
124	Bad ->
125	    ?LOG("receive other: ~p~n", [Bad]),
126	    exit(Bad)
127    end.
128
129%%----------------------------------------------------------------------
130%% Megaco user callback
131%%----------------------------------------------------------------------
132
133%% -- handle_connect/2 --
134
135handle_connect(ConnHandle, ProtocolVersion) ->
136%%     io:format("~p~p[~p]: handle_connect -> entry with"
137%% 	      "~n   ConnHandle:      ~p"
138%% 	      "~n   ProtocolVersion: ~p"
139%% 	      "~n",
140%%      	      [self(), ?MODULE, ?LINE, ConnHandle, ProtocolVersion]),
141    call({connect, ConnHandle, ProtocolVersion, []}).
142
143handle_connect(ConnHandle, ProtocolVersion, Extra) ->
144%%     io:format(user,"~p~p[~p]: handle_connect -> entry with"
145%% 	      "~n   ConnHandle:      ~p"
146%% 	      "~n   ProtocolVersion: ~p"
147%% 	      "~n   Extra:           ~p"
148%% 	      "~n",
149%%     	      [self(), ?MODULE, ?LINE, ConnHandle, ProtocolVersion, Extra]),
150    call({connect, ConnHandle, ProtocolVersion, [Extra]}).
151
152
153%% -- handle_disconnect/3 --
154
155handle_disconnect(ConnHandle, ProtocolVersion, Reason) ->
156    %%     io:format("~w:~w:~p:handle_disconnect -> entry with"
157    %% 	      "~n   ConnHandle:      ~p"
158    %% 	      "~n   ProtocolVersion: ~p"
159    %% 	      "~n   Reason:          ~p"
160    %% 	      "~n",
161    %% 	      [?MODULE, ?LINE, self(), ConnHandle, ProtocolVersion, Reason]),
162    call({disconnect, ConnHandle, ProtocolVersion, [Reason]}).
163
164
165%% -- handle_syntax_error/3,4 --
166
167handle_syntax_error(ReceiveHandle, ProtocolVersion, ErrorDescriptor) ->
168    call({syntax_error, ReceiveHandle, ProtocolVersion, [ErrorDescriptor]}).
169
170handle_syntax_error(ReceiveHandle, ProtocolVersion, ErrorDescriptor, Extra) ->
171    call({syntax_error, ReceiveHandle, ProtocolVersion, [ErrorDescriptor, Extra]}).
172
173
174%% -- handle_message_error/3,4 --
175
176handle_message_error(ConnHandle, ProtocolVersion, ErrorDescriptor) ->
177    call({message_error, ConnHandle, ProtocolVersion, [ErrorDescriptor]}).
178
179handle_message_error(ConnHandle, ProtocolVersion, ErrorDescriptor, Extra) ->
180    call({message_error, ConnHandle, ProtocolVersion, [ErrorDescriptor, Extra]}).
181
182
183%% -- handle_trans_request/3,4 --
184
185handle_trans_request(ConnHandle, ProtocolVersion, ActionRequests) ->
186    call({request, ConnHandle, ProtocolVersion, [ActionRequests]}).
187
188handle_trans_request(ConnHandle, ProtocolVersion, ActionRequests, Extra) ->
189    call({request, ConnHandle, ProtocolVersion, [ActionRequests, Extra]}).
190
191%% -- handle_trans_long_request/3,4 --
192
193handle_trans_long_request(ConnHandle, ProtocolVersion, RequestData) ->
194    call({long_request, ConnHandle, ProtocolVersion, [RequestData]}).
195
196handle_trans_long_request(ConnHandle, ProtocolVersion, RequestData, Extra) ->
197    call({long_request, ConnHandle, ProtocolVersion, [RequestData, Extra]}).
198
199
200%% -- handle_trans_relpy/4,5 --
201
202handle_trans_reply(ConnHandle, ProtocolVersion, UserReply, UserData) ->
203    call({reply, ConnHandle, ProtocolVersion, [UserReply, UserData]}).
204
205handle_trans_reply(ConnHandle, ProtocolVersion, UserReply, UserData, Extra) ->
206    call({reply, ConnHandle, ProtocolVersion, [UserReply, UserData, Extra]}).
207
208
209%% -- handle_trans_relpy/4,5 --
210
211handle_trans_ack(ConnHandle, ProtocolVersion, AckStatus, AckData) ->
212    call({ack, ConnHandle, ProtocolVersion, [AckStatus, AckData]}).
213
214handle_trans_ack(ConnHandle, ProtocolVersion, AckStatus, AckData, Extra) ->
215    call({ack, ConnHandle, ProtocolVersion, [AckStatus, AckData, Extra]}).
216
217
218%% -- handle_unexpected_trans/3,4 --
219
220handle_unexpected_trans(ConnHandle, ProtocolVersion, Trans) ->
221    call({unepected_trans, ConnHandle, ProtocolVersion, [Trans]}).
222
223handle_unexpected_trans(ConnHandle, ProtocolVersion, Trans, Extra) ->
224    call({unepected_trans, ConnHandle, ProtocolVersion, [Trans, Extra]}).
225
226
227%% -- handle_trans_request_abort/4,5 --
228
229handle_trans_request_abort(ConnHandle, ProtocolVersion, TransId, Pid) ->
230    call({request_abort, ConnHandle, ProtocolVersion, [TransId, Pid]}).
231
232handle_trans_request_abort(ConnHandle, ProtocolVersion, TransId, Pid, Extra) ->
233    call({request_abort, ConnHandle, ProtocolVersion, [TransId, Pid, Extra]}).
234
235
236%% -- handle_segment_reply/5,6 --
237
238handle_segment_reply(ConnHandle, ProtocolVersion, TransId, SN, SC) ->
239    call({segment_reply, ConnHandle, ProtocolVersion, [TransId, SN, SC]}).
240
241handle_segment_reply(ConnHandle, ProtocolVersion, TransId, SN, SC, Extra) ->
242    call({segment_reply, ConnHandle, ProtocolVersion, [TransId, SN, SC, Extra]}).
243
244
245%%----------------------------------------------------------------------
246%% The ultimate Megaco transport callback
247%%----------------------------------------------------------------------
248
249start_transport(MgReceiveHandle, MgcReceiveHandle) ->
250    MgControlPid  = spawn_link(?MODULE, loop_transport, [self()]),
251    MgSendHandle  = {MgcReceiveHandle, MgControlPid},
252    MgcControlPid = spawn_link(?MODULE, loop_transport, [self()]),
253    MgcSendHandle = {MgReceiveHandle, MgcControlPid},
254    SendHandle    = {MgSendHandle, MgcSendHandle},
255    {ok, MgControlPid, SendHandle}.
256
257loop_transport(Parent) ->
258    receive
259	{'EXIT', _Pid, Reason} = Error ->
260	    ok = io:format("transport stopped: ~p~n", [{Parent, Error}]),
261	    exit(Reason)
262    end.
263
264send_message(Handles, Bin) ->
265    ?LOG("send_message -> entry with"
266	 "~n   Handles: ~p"
267	 "~n", [Handles]),
268    case megaco_tc_controller:lookup(allow_send_message) of
269	{value, ok} ->
270	    do_send_message(Handles, Bin);
271	{value, {fail, Reason}} ->
272	    {error, Reason};
273	{value, {cancel, Reason}} ->
274	    {cancel, Reason};
275	{value, {skip, Result}} ->
276	    Result;
277	false ->
278	    do_send_message(Handles, Bin)
279    end.
280
281resend_message(Handles, Bin) ->
282    ?LOG("resend_message -> entry with"
283	 "~n   Handles: ~p"
284	 "~n", [Handles]),
285    case megaco_tc_controller:lookup(allow_resend_message) of
286	{value, ok} ->
287	    do_send_message(Handles, Bin);
288	{value, {fail, Reason}} ->
289	    {error, Reason};
290	{value, {cancel, Reason}} ->
291	    {cancel, Reason};
292	{value, {skip, Result}} ->
293	    Result;
294	false ->
295	    do_send_message(Handles, Bin)
296    end.
297
298do_send_message({{RH, Pid} = LocalSendHandle, RemoteSendHandle}, Bin) ->
299    ?LOG("do_send_message -> entry with"
300	 "~n   RH:               ~p"
301	 "~n   Pid:              ~p"
302	 "~n   RemoteSendHandle: ~p"
303	 "~n", [RH, Pid, RemoteSendHandle]),
304    SwappedSendHandle = {RemoteSendHandle, LocalSendHandle},
305    case megaco_tc_controller:lookup(extra_transport_info) of
306	{value, Extra} ->
307	    megaco:receive_message(RH, Pid, SwappedSendHandle, Bin, Extra);
308	_ ->
309	    megaco:receive_message(RH, Pid, SwappedSendHandle, Bin)
310    end.
311