diff options
Diffstat (limited to 'lib/megaco/src/udp/megaco_udp_server.erl')
-rw-r--r-- | lib/megaco/src/udp/megaco_udp_server.erl | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/lib/megaco/src/udp/megaco_udp_server.erl b/lib/megaco/src/udp/megaco_udp_server.erl new file mode 100644 index 0000000000..f126043141 --- /dev/null +++ b/lib/megaco/src/udp/megaco_udp_server.erl @@ -0,0 +1,234 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%----------------------------------------------------------------- +%% +%% Description: +%% This file handles the H.248 UDP connections. +%% +%%----------------------------------------------------------------- +-module(megaco_udp_server). + +-behaviour(gen_server). + +%%----------------------------------------------------------------- +%% Include files +%%----------------------------------------------------------------- +-include_lib("megaco/src/udp/megaco_udp.hrl"). +-include_lib("megaco/src/app/megaco_internal.hrl"). + + +%%----------------------------------------------------------------- +%% External exports +%%----------------------------------------------------------------- +-export([ + start_link/1, + stop/1, + + upgrade_receive_handle/2 + ]). + +%%----------------------------------------------------------------- +%% Internal exports +%%----------------------------------------------------------------- +-export([ + init/1, + handle_call/3, + handle_cast/2, + handle_info/2, + code_change/3, + terminate/2, + + handle_received_message/5 + ]). + +%%----------------------------------------------------------------- +%% External interface functions +%%----------------------------------------------------------------- +%%----------------------------------------------------------------- +%% Func: start_link/1 +%% Description: Starts the process that keeps track of an UDP +%% socket. +%%----------------------------------------------------------------- +start_link(Arg) -> + gen_server:start_link(?MODULE, Arg, []). + +%%----------------------------------------------------------------- +%% Func: stop/1 +%% Description: Stops the process that keeps track of an UDP +%% socket. +%%----------------------------------------------------------------- +stop(Pid) -> + call(Pid, stop). + + +upgrade_receive_handle(Pid, NewHandle) -> + call(Pid, {upgrade_receive_handle, NewHandle}). + +%%----------------------------------------------------------------- +%% Internal interface functions +%%----------------------------------------------------------------- + +%%----------------------------------------------------------------- +%% Server functions +%%----------------------------------------------------------------- +%%----------------------------------------------------------------- +%% Func: init/1 +%% Description: Init funcion for the generic server +%%----------------------------------------------------------------- +init(Arg) -> + ?udp_debug(Arg, "udp server starting", [self()]), + {ok, Arg}. + +%%----------------------------------------------------------------- +%% Func: terminate/2 +%% Description: Termination function for the generic server +%%----------------------------------------------------------------- +terminate(Reason, State) -> + ?udp_debug(State, "udp server terminating", [self(), Reason]), + ok. + +%%----------------------------------------------------------------- +%% Func: handle_call/3 +%% Description: Handling call messages (really just stop and garbage) +%%----------------------------------------------------------------- +handle_call(stop, _From, UdpRec) -> + Reply = do_stop(UdpRec), + {stop, shutdown, Reply, UdpRec}; +handle_call({upgrade_receive_handle, NewHandle}, _From, UdpRec) -> + {reply, ok, UdpRec#megaco_udp{receive_handle = NewHandle}}; +handle_call(Req, From, UdpRec) -> + warning_msg("received unexpected request from ~p: " + "~n~p", [From, Req]), + {reply, {error, {invalid_request, Req}}, UdpRec}. + +%%----------------------------------------------------------------- +%% Func: handle_cast/2 +%% Description: Handling cast messages (really just stop and garbage) +%%----------------------------------------------------------------- +handle_cast(stop, UdpRec) -> + do_stop(UdpRec), + {stop, shutdown, UdpRec}; +handle_cast(Msg, UdpRec) -> + warning_msg("received unexpected message: " + "~n~w", [Msg]), + {noreply, UdpRec}. + +%%----------------------------------------------------------------- +%% Func: handle_info/2 +%% Description: Handling non call/cast messages. Incomming messages +%% from the socket and exit codes. +%%----------------------------------------------------------------- +handle_info({udp, _UdpId, Ip, Port, Msg}, + #megaco_udp{serialize = false} = UdpRec) -> + #megaco_udp{socket = Socket, module = Mod, receive_handle = RH} = UdpRec, + SH = megaco_udp:create_send_handle(Socket, Ip, Port), + MsgSize = size(Msg), + incNumInMessages(SH), + incNumInOctets(SH, MsgSize), + case MsgSize of + Sz when Sz < ?GC_MSG_LIMIT -> + apply(Mod, receive_message, [RH, self(), SH, Msg]); + Sz -> + receive_message(Mod, RH, SH, Sz, Msg) + end, + inet:setopts(Socket, [{active, once}]), + {noreply, UdpRec}; +handle_info({udp, _UdpId, Ip, Port, Msg}, + #megaco_udp{serialize = true} = UdpRec) -> + #megaco_udp{socket = Socket, module = Mod, receive_handle = RH} = UdpRec, + SH = megaco_udp:create_send_handle(Socket, Ip, Port), + MsgSize = size(Msg), + incNumInMessages(SH), + incNumInOctets(SH, MsgSize), + process_received_message(Mod, RH, SH, Msg), + inet:setopts(Socket, [{active, once}]), + {noreply, UdpRec}; +handle_info(Info, UdpRec) -> + warning_msg("received unexpected info: " + "~n~w", [Info]), + {noreply, UdpRec}. + + +process_received_message(Mod, RH, SH, Msg) -> + case (catch Mod:process_received_message(RH, self(), SH, Msg)) of + ok -> + ok; + Error -> + error_msg("failed processing received message: " + "~n~p", [Error]), + ok + end. + + +receive_message(Mod, RH, SendHandle, Length, Msg) -> + Opts = [link , {min_heap_size, ?HEAP_SIZE(Length)}], + spawn_opt(?MODULE, handle_received_message, + [Mod, RH, self(), SendHandle, Msg], Opts). + + +handle_received_message(Mod, RH, Parent, SH, Msg) -> + Mod:process_received_message(RH, Parent, SH, Msg), + unlink(Parent), + exit(normal). + + + +%%----------------------------------------------------------------- +%% Func: code_change/3 +%% Descrition: Handles code change messages during upgrade. +%%----------------------------------------------------------------- +code_change(_Vsn, State, _Extra) -> + {ok, State}. + +do_stop(#megaco_udp{socket = Socket}) -> + gen_udp:close(Socket). + + +%%----------------------------------------------------------------- +%% Func: incNumInMessages/1, incNumInOctets/2, incNumErrors/1 +%% Description: SNMP counter increment functions +%% +%%----------------------------------------------------------------- +incNumInMessages(SH) -> + incCounter({SH, medGwyGatewayNumInMessages}, 1). + +incNumInOctets(SH, NumOctets) -> + incCounter({SH, medGwyGatewayNumInOctets}, NumOctets). + +incCounter(Key, Inc) -> + ets:update_counter(megaco_udp_stats, Key, Inc). + +% incNumErrors(SH) -> +% incCounter({SH, medGwyGatewayNumErrors}, 1). + + +%% info_msg(F, A) -> +%% ?megaco_info("UDP server: " ++ F, A). + +warning_msg(F, A) -> + ?megaco_warning("UDP server: " ++ F, A). + +error_msg(F, A) -> + ?megaco_error("UDP server: " ++ F, A). + + +call(Pid, Req) -> + gen_server:call(Pid, Req, infinity). |