1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2001-2016. 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: Handle the flex scanner 24%%---------------------------------------------------------------------- 25 26-module(megaco_flex_scanner_handler). 27 28-behaviour(gen_server). 29 30 31%%----------------------------------------------------------------- 32%% Include files 33%%----------------------------------------------------------------- 34-include_lib("megaco/src/app/megaco_internal.hrl"). 35 36 37%% External exports 38-export([ 39 start_link/0, start_link/1, 40 stop/1, 41 get_config/1 42 ]). 43 44%% gen_server callbacks 45-export([ 46 init/1, 47 handle_call/3, handle_cast/2, handle_info/2, 48 terminate/2, 49 code_change/3 50 ]). 51 52-record(state, {conf}). 53 54 55%%%---------------------------------------------------------------------- 56%%% API 57%%%---------------------------------------------------------------------- 58 59start_link() -> 60 start_link([]). 61 62start_link(Opts) -> 63 case gen_server:start_link(?MODULE, Opts, []) of 64 {ok, Pid} -> 65 Conf = get_config(Pid), 66 {ok, Pid, Conf}; 67 Else -> 68 Else 69 end. 70 71stop(Pid) -> 72 gen_server:call(Pid, stop). 73 74get_config(Pid) -> 75 gen_server:call(Pid, get_config). 76 77 78%%%---------------------------------------------------------------------- 79%%% Callback functions from gen_server 80%%%---------------------------------------------------------------------- 81 82%%---------------------------------------------------------------------- 83%% Func: init/1 84%% Returns: {ok, State} | 85%% {ok, State, Timeout} | 86%% ignore | 87%% {stop, Reason} 88%%---------------------------------------------------------------------- 89init(_Opts) -> 90 process_flag(trap_exit, true), 91 case start_flex_scanners() of 92 {ok, PortOrPorts} -> 93 {ok, #state{conf = {flex, PortOrPorts}}}; 94 {error, Reason} -> 95 %% {stop, {failed_starting_scanner, Reason, Opts}}; 96 {stop, {failed_starting_scanner, Reason, []}}; 97 Else -> 98 {stop, {failed_starting_scanner, Else}} 99 end. 100 101 102%%---------------------------------------------------------------------- 103%% Func: handle_call/3 104%% Returns: {reply, Reply, State} | 105%% {reply, Reply, State, Timeout} | 106%% {noreply, State} | 107%% {noreply, State, Timeout} | 108%% {stop, Reason, Reply, State} | (terminate/2 is called) 109%% {stop, Reason, State} (terminate/2 is called) 110%%---------------------------------------------------------------------- 111handle_call(get_config, _From, #state{conf = Conf} = S) -> 112 {reply, Conf, S}; 113 114handle_call(stop, _From, #state{conf = {flex, PortOrPorts}} = S) -> 115 megaco_flex_scanner:stop(PortOrPorts), 116 Reason = normal, 117 Reply = ok, 118 {stop, Reason, Reply, S}; 119 120handle_call(Req, From, S) -> 121 warning_msg("received unexpected request from ~p: " 122 "~n~w", [From, Req]), 123 {reply, {error, {unknown_request, Req}}, S}. 124 125 126%%---------------------------------------------------------------------- 127%% Func: handle_cast/2 128%% Returns: {noreply, State} | 129%% {noreply, State, Timeout} | 130%% {stop, Reason, State} (terminate/2 is called) 131%%---------------------------------------------------------------------- 132handle_cast(Msg, S) -> 133 warning_msg("received unexpected message: " 134 "~n~w", [Msg]), 135 {noreply, S}. 136 137 138%%---------------------------------------------------------------------- 139%% Func: handle_info/2 140%% Returns: {noreply, State} | 141%% {noreply, State, Timeout} | 142%% {stop, Reason, State} (terminate/2 is called) 143%%---------------------------------------------------------------------- 144handle_info({'EXIT', Port, Error}, #state{conf = {flex, PortOrPorts}} = S) -> 145 case megaco_flex_scanner:is_scanner_port(Port, PortOrPorts) of 146 true -> 147 error_msg("Port [~p] exited:" 148 "~n~w", [Port, Error]), 149 {stop, {port_exit, Port, Error}, S}; 150 false -> 151 {noreply, S} 152 end; 153 154handle_info({'EXIT', Port, _Error}, S) when is_port(Port) -> 155 %% This is propably the old flex scanner, 156 %% terminating after a code change... 157 {noreply, S}; 158 159handle_info({'EXIT', Id, Error}, S) -> 160 warning_msg("received unexpected 'EXIT' signal from ~p:" 161 "~n~w", [Id, Error]), 162 {noreply, S}; 163 164handle_info(Info, S) -> 165 warning_msg("received unexpected info: " 166 "~n~w", [Info]), 167 {noreply, S}. 168 169 170%%---------------------------------------------------------------------- 171%% Func: terminate/2 172%% Purpose: Shutdown the server 173%% Returns: any (ignored by gen_server) 174%%---------------------------------------------------------------------- 175terminate(_Reason, _S) -> 176 ok. 177 178 179%%---------------------------------------------------------------------- 180%% Func: code_change/3 181%% Purpose: Called to change the internal state 182%% Returns: {ok, NewState} 183%%---------------------------------------------------------------------- 184 185code_change({down, _Vsn}, #state{conf = Conf} = State, downgrade_to_pre_3_17) -> 186 NewPorts = bump_flex_scanner(Conf), 187 {ok, State#state{conf = {flex, NewPorts}}}; 188 189code_change(_Vsn, #state{conf = Conf} = State, upgrade_from_pre_3_17) -> 190 NewPorts = bump_flex_scanner(Conf), 191 {ok, State#state{conf = {flex, NewPorts}}}; 192 193code_change(_Vsn, State, _Extra) -> 194 {ok, State}. 195 196bump_flex_scanner({flex, Ports}) -> 197 megaco_flex_scanner:stop(Ports), 198 case start_flex_scanners() of 199 {ok, NewPorts} -> 200 NewPorts; 201 Error -> 202 exit(Error) 203 end; 204bump_flex_scanner(BadConfig) -> 205 exit({invalid_config, BadConfig}). 206 207 208%%%---------------------------------------------------------------------- 209%%% Internal functions 210%%%---------------------------------------------------------------------- 211 212start_flex_scanners() -> 213 megaco_flex_scanner:start(). 214 215 216%% get_env(Key, Opts, Default) -> 217%% case lists:keysearch(Key, 1, Opts) of 218%% {value, {Key, Value}} -> 219%% Value; 220%% false -> 221%% Default 222%% end. 223 224warning_msg(F, A) -> 225 ?megaco_warning("Flex scanner handler: " ++ F, A). 226 227error_msg(F, A) -> 228 ?megaco_error("Flex scanner handler: " ++ F, A). 229 230 231 232% d(F, A) -> 233% io:format("~w:" ++ F ++ "~n", [?MODULE|A]). 234 235