1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1999-2021. 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%% 24%% Description: 25%% This file handles the H.248 UDP connections. 26%% 27%%----------------------------------------------------------------- 28-module(megaco_udp_server). 29 30-behaviour(gen_server). 31 32 33%%----------------------------------------------------------------- 34%% Include files 35%%----------------------------------------------------------------- 36 37-include_lib("megaco/src/udp/megaco_udp.hrl"). 38-include_lib("megaco/src/app/megaco_internal.hrl"). 39 40 41%%----------------------------------------------------------------- 42%% External exports 43%%----------------------------------------------------------------- 44 45-export([ 46 start_link/1, 47 stop/1, 48 49 upgrade_receive_handle/2 50 ]). 51 52 53%%----------------------------------------------------------------- 54%% Internal exports 55%%----------------------------------------------------------------- 56 57-export([ 58 init/1, 59 handle_call/3, 60 handle_cast/2, 61 handle_info/2, 62 code_change/3, 63 terminate/2, 64 65 handle_received_message/5 66 ]). 67 68 69%%----------------------------------------------------------------- 70%% External interface functions 71%%----------------------------------------------------------------- 72%%----------------------------------------------------------------- 73%% Func: start_link/1 74%% Description: Starts the process that keeps track of an UDP 75%% socket. 76%%----------------------------------------------------------------- 77start_link(Arg) -> 78 gen_server:start_link(?MODULE, Arg, []). 79 80 81%%----------------------------------------------------------------- 82%% Func: stop/1 83%% Description: Stops the process that keeps track of an UDP 84%% socket. 85%%----------------------------------------------------------------- 86stop(Pid) -> 87 call(Pid, stop). 88 89 90upgrade_receive_handle(Pid, NewHandle) -> 91 call(Pid, {upgrade_receive_handle, NewHandle}). 92 93 94%%----------------------------------------------------------------- 95%% Internal interface functions 96%%----------------------------------------------------------------- 97 98%%----------------------------------------------------------------- 99%% Server functions 100%%----------------------------------------------------------------- 101%%----------------------------------------------------------------- 102%% Func: init/1 103%% Description: Init funcion for the generic server 104%%----------------------------------------------------------------- 105init(Arg) -> 106 ?udp_debug(Arg, "udp server starting", [self()]), 107 {ok, Arg}. 108 109 110%%----------------------------------------------------------------- 111%% Func: terminate/2 112%% Description: Termination function for the generic server 113%%----------------------------------------------------------------- 114terminate(Reason, State) -> 115 ?udp_debug(State, "udp server terminating", [self(), Reason]), 116 ok. 117 118 119%%----------------------------------------------------------------- 120%% Func: handle_call/3 121%% Description: Handling call messages (really just stop and garbage) 122%%----------------------------------------------------------------- 123handle_call(stop, _From, UdpRec) -> 124 Reply = do_stop(UdpRec), 125 {stop, shutdown, Reply, UdpRec}; 126handle_call({upgrade_receive_handle, NewHandle}, _From, UdpRec) -> 127 {reply, ok, UdpRec#megaco_udp{receive_handle = NewHandle}}; 128handle_call(Req, From, UdpRec) -> 129 warning_msg("received unexpected request from ~p: " 130 "~n~p", [From, Req]), 131 {reply, {error, {invalid_request, Req}}, UdpRec}. 132 133 134%%----------------------------------------------------------------- 135%% Func: handle_cast/2 136%% Description: Handling cast messages (really just stop and garbage) 137%%----------------------------------------------------------------- 138handle_cast(stop, UdpRec) -> 139 do_stop(UdpRec), 140 {stop, shutdown, UdpRec}; 141handle_cast(Msg, UdpRec) -> 142 warning_msg("received unexpected message: " 143 "~n~w", [Msg]), 144 {noreply, UdpRec}. 145 146 147%%----------------------------------------------------------------- 148%% Func: handle_info/2 149%% Description: Handling non call/cast messages. Incomming messages 150%% from the socket and exit codes. 151%%----------------------------------------------------------------- 152handle_info({udp, _Socket, Ip, Port, Msg}, 153 #megaco_udp{serialize = false} = UdpRec) -> 154 #megaco_udp{socket = Socket, module = Mod, receive_handle = RH} = UdpRec, 155 SH = megaco_udp:create_send_handle(Socket, Ip, Port), 156 MsgSize = size(Msg), 157 incNumInMessages(SH), 158 incNumInOctets(SH, MsgSize), 159 case MsgSize of 160 Sz when Sz < ?GC_MSG_LIMIT -> 161 apply(Mod, receive_message, [RH, self(), SH, Msg]); 162 Sz -> 163 receive_message(Mod, RH, SH, Sz, Msg) 164 end, 165 activate(Socket), 166 {noreply, UdpRec}; 167handle_info({udp, _Socket, Ip, Port, Msg}, 168 #megaco_udp{serialize = true} = UdpRec) -> 169 #megaco_udp{socket = Socket, module = Mod, receive_handle = RH} = UdpRec, 170 SH = megaco_udp:create_send_handle(Socket, Ip, Port), 171 MsgSize = size(Msg), 172 incNumInMessages(SH), 173 incNumInOctets(SH, MsgSize), 174 process_received_message(Mod, RH, SH, Msg), 175 activate(Socket), 176 {noreply, UdpRec}; 177handle_info(Info, UdpRec) -> 178 warning_msg("received unexpected info: " 179 "~n~w", [Info]), 180 {noreply, UdpRec}. 181 182 183process_received_message(Mod, RH, SH, Msg) -> 184 case (catch Mod:process_received_message(RH, self(), SH, Msg)) of 185 ok -> 186 ok; 187 Error -> 188 error_msg("failed processing received message: " 189 "~n~p", [Error]), 190 ok 191 end. 192 193 194receive_message(Mod, RH, SendHandle, Length, Msg) -> 195 Opts = [link , {min_heap_size, ?HEAP_SIZE(Length)}], 196 spawn_opt(?MODULE, handle_received_message, 197 [Mod, RH, self(), SendHandle, Msg], Opts). 198 199 200handle_received_message(Mod, RH, Parent, SH, Msg) -> 201 Mod:process_received_message(RH, Parent, SH, Msg), 202 unlink(Parent), 203 exit(normal). 204 205 206 207%%----------------------------------------------------------------- 208%% Func: code_change/3 209%% Descrition: Handles code change messages during upgrade. 210%%----------------------------------------------------------------- 211code_change(_Vsn, State, _Extra) -> 212 {ok, State}. 213 214do_stop(#megaco_udp{socket = Socket}) -> 215 gen_udp:close(Socket). 216 217 218-compile({inline, [activate/1]}). 219activate(Socket) -> 220 inet:setopts(Socket, [{active, once}]). 221 222 223%%----------------------------------------------------------------- 224%% Func: incNumInMessages/1, incNumInOctets/2, incNumErrors/1 225%% Description: SNMP counter increment functions 226%% 227%%----------------------------------------------------------------- 228incNumInMessages(SH) -> 229 incCounter({SH, medGwyGatewayNumInMessages}, 1). 230 231incNumInOctets(SH, NumOctets) -> 232 incCounter({SH, medGwyGatewayNumInOctets}, NumOctets). 233 234incCounter(Key, Inc) -> 235 ets:update_counter(megaco_udp_stats, Key, Inc). 236 237%% incNumErrors(SH) -> 238%% incCounter({SH, medGwyGatewayNumErrors}, 1). 239 240 241%% info_msg(F, A) -> 242%% ?megaco_info("UDP server: " ++ F, A). 243 244warning_msg(F, A) -> 245 ?megaco_warning("UDP server: " ++ F, A). 246 247error_msg(F, A) -> 248 ?megaco_error("UDP server: " ++ F, A). 249 250 251call(Pid, Req) -> 252 gen_server:call(Pid, Req, infinity). 253