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