1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2007-2020. 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: Utility module used by the codec suites when testing flex
24%%          configured text codec(s).
25%%----------------------------------------------------------------------
26
27-module(megaco_codec_flex_lib).
28
29%% ----
30
31-include("megaco_test_lib.hrl").
32
33%% ----
34
35-export([
36	 init/1,
37	 finish/1,
38	 scanner_conf/1,
39	 start/0,
40	 stop/1
41	 ]).
42
43-export([
44	 handler/1
45	]).
46
47
48%% ----
49
50%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
51
52init(Config) when is_list(Config) ->
53    %% io:format("~w:init -> entry with"
54    %% 	      "~n   Config: ~p"
55    %% 	      "~n", [?MODULE, Config]),
56    Flag = process_flag(trap_exit, true),
57    Res = (catch start()),
58    %% io:format("~w:init -> start result"
59    %% 	      "~n   Res: ~p"
60    %% 	      "~n", [?MODULE, Res]),
61    process_flag(trap_exit, Flag),
62    case Res of
63	{error, {failed_loading_flex_scanner_driver, Reason}} ->
64	    skip(?F("Failed loading flex driver: ~p", [Reason]));
65	{error, Reason} ->
66	    skip(Reason);
67	{ok, FlexConfig} ->
68	    [{flex_scanner, FlexConfig} | Config]
69    end.
70
71
72finish(Config) when is_list(Config) ->
73    case lists:keysearch(flex_scanner, 1, Config) of
74	{value, {flex_scanner, {Pid, _Conf}}} ->
75	    stop(Pid),
76	    lists:keydelete(flex_scanner, 1, Config);
77	false ->
78	    Config
79    end.
80
81
82start() ->
83    Pid = proc_lib:spawn(?MODULE, handler, [self()]),
84    receive
85	{flex_scanner_started, Pid, Conf} ->
86	    {ok, {Pid, Conf}};
87	{flex_scanner_error, {failed_loading_flex_scanner_driver, Reason}} ->
88 	    ?LOG("start_flex_scanner -> failed loading flex scanner driver: "
89 		 "~n   Reason: ~p~n", [Reason]),
90	    {error, {failed_loading_flex_scanner_driver, Reason}};
91	{flex_scanner_error, Reason} ->
92 	    ?LOG("start_flex_scanner -> error: "
93 		 "~n   Reason: ~p~n", [Reason]),
94	    {error, {failed_loading_flex_scanner_driver, Reason}}
95    after 10000 ->
96	    exit(Pid, kill),
97	    {error, {failed_starting_flex_scanner, timeout}}
98    end.
99
100
101scanner_conf(Config) when is_list(Config) ->
102    case lists:keysearch(flex_scanner, 1, Config) of
103	{value, {flex_scanner, {Pid, Conf}}} ->
104	    case ping_flex_scanner(Pid) of
105		ok ->
106		    Conf;
107		Else ->
108		    skip({no_response_from_flex_scanner_handler, Else})
109	    end;
110	false ->
111	    skip("Flex scanner driver not loaded")
112    end.
113
114
115ping_flex_scanner(Pid) ->
116    Pid ! {ping, self()},
117    receive
118	{pong, Pid} ->
119	    ok
120    after 5000 ->
121	    timeout
122    end.
123
124
125stop(Pid) ->
126    Pid ! stop.
127
128
129handler(Pid) ->
130    SMP = erlang:system_info(smp_support),
131    case (catch megaco_flex_scanner:start(SMP)) of
132	{ok, PortOrPorts} ->
133	    Pid ! {flex_scanner_started, self(), {flex, PortOrPorts}},
134	    handler(Pid, PortOrPorts);
135	{error, {load_driver, {open_error, Reason}}} ->
136	    Error = {failed_loading_flex_scanner_driver, Reason},
137	    Pid ! {flex_scanner_error, Error},
138	    exit(Error);
139	{error, {load_driver, Reason}} ->
140	    Error = {failed_loading_flex_scanner_driver, Reason},
141	    Pid ! {flex_scanner_error, Error},
142	    exit(Error);
143	Else ->
144	    Error = {unknown_result_from_start_flex_scanner, Else},
145	    Pid ! {flex_scanner_error, Error},
146	    exit(Error)
147    end.
148
149handler(Pid, PortOrPorts) ->
150    receive
151	{ping, Pinger} ->
152	    Pinger ! {pong, self()},
153	    handler(Pid, PortOrPorts);
154	{'EXIT', Port, Reason} when (PortOrPorts =:= Port) ->
155	    Pid ! {flex_scanner_exit, Reason},
156	    exit({flex_scanner_exit, Reason});
157	{'EXIT', Port, Reason} when is_port(Port) ->
158	    case megaco_flex_scanner:is_scanner_port(Port, PortOrPorts) of
159		true ->
160		    Pid ! {flex_scanner_exit, Reason},
161		    exit({flex_scanner_exit, Reason});
162		false ->
163		    io:format("flex scanner handler got port exit "
164			      "from unknown:"
165			      "~n   ~p: ~p", [Port, Reason]),
166		    ok
167	    end,
168	    handler(Pid, PortOrPorts);
169	stop ->
170	    megaco_flex_scanner:stop(PortOrPorts),
171	    exit(normal);
172	Other ->
173	    io:format("flex scanner handler got something:~n"
174		      "~p", [Other]),
175	    handler(Pid, PortOrPorts)
176    end.
177
178
179%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
180
181skip(Reason) ->
182    megaco_codec_test_lib:skip(Reason).
183
184