megaco_udp.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 307 行
ERL
307 行
%% ``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 via the world wide web 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.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %% $Id$%%%%-----------------------------------------------------------------%% Purpose: Interface to the UDP transport module for Megaco/H.248%%------------------------------------------------------------------module(megaco_udp).-include_lib("megaco/include/megaco.hrl").-include_lib("megaco/src/udp/megaco_udp.hrl").-record(send_handle, {socket, addr, port}).%%-----------------------------------------------------------------%% External exports%%------------------------------------------------------------------export([ start_transport/0, open/2, socket/1, create_send_handle/3, send_message/2, close/1, block/1, unblock/1, upgrade_receive_handle/2 ]).%% Statistics exports-export([get_stats/0, get_stats/1, get_stats/2, reset_stats/0, reset_stats/1]).%%-----------------------------------------------------------------%% Internal exports%%------------------------------------------------------------------export([]).%%-----------------------------------------------------------------%% External interface functions%%-----------------------------------------------------------------%%-----------------------------------------------------------------%% Func: get_stats/0, get_stats/1, get_stats/2%% Description: Retreive statistics (counters) for TCP%%-----------------------------------------------------------------get_stats() -> megaco_stats:get_stats(megaco_udp_stats).get_stats(SH) when record(SH, send_handle) -> megaco_stats:get_stats(megaco_udp_stats, SH).get_stats(SH, Counter) when record(SH, send_handle), atom(Counter) -> megaco_stats:get_stats(megaco_udp_stats, SH, Counter).%%-----------------------------------------------------------------%% Func: reset_stats/0, reaet_stats/1%% Description: Reset statistics (counters) for TCP%%-----------------------------------------------------------------reset_stats() -> megaco_stats:reset_stats(megaco_udp_stats).reset_stats(SH) when record(SH, send_handle) -> megaco_stats:reset_stats(megaco_udp_stats, SH).%%-----------------------------------------------------------------%% Func: start_transport%% Description: Starts the UDP transport service%%-----------------------------------------------------------------start_transport() -> (catch megaco_stats:init(megaco_udp_stats)), megaco_udp_sup:start_link().%%-----------------------------------------------------------------%% Func: open%% Description: Function is used when opening an UDP socket%%-----------------------------------------------------------------open(SupPid, Options) -> Mand = [port, receive_handle], case parse_options(Options, #megaco_udp{}, Mand) of {ok, UdpRec} -> %%------------------------------------------------------ %% Setup the socket IpOpts = [binary, {reuseaddr, true}, {active, once} | UdpRec#megaco_udp.options], case (catch gen_udp:open(UdpRec#megaco_udp.port, IpOpts)) of {ok, Socket} -> ?udp_debug(UdpRec, "udp open", []), NewUdpRec = UdpRec#megaco_udp{socket = Socket}, case start_udp_server(SupPid, NewUdpRec) of {ok, ControlPid} -> gen_udp:controlling_process(Socket, ControlPid), {ok, Socket, ControlPid}; {error, Reason} -> Error = {error, {could_not_start_udp_server, Reason}}, ?udp_debug({socket, Socket}, "udp close", []), gen_udp:close(Socket), Error end; {'EXIT', Reason} -> Error = {error, {could_not_open_udp_port, Reason}}, ?udp_debug(UdpRec, "udp open exited", [Error]), Error; {error, Reason} -> Error = {error, {could_not_open_udp_port, Reason}}, ?udp_debug(UdpRec, "udp open failed", [Error]), Error end; {error, Reason} = Error -> ?udp_debug(#megaco_udp{}, "udp open failed", [Error, {options, Options}]), {error, Reason} end.%%-----------------------------------------------------------------%% Func: socket%% Description: Returns the inet socket%%-----------------------------------------------------------------socket(SH) when record(SH, send_handle) -> SH#send_handle.socket;socket(Socket) -> Socket.upgrade_receive_handle(Pid, NewHandle) when pid(Pid), record(NewHandle, megaco_receive_handle) -> megaco_udp_server:upgrade_receive_handle(Pid, NewHandle).%%-----------------------------------------------------------------%% Func: create_send_handle%% Description: Function is used for creating the handle used when %% sending data on the UDP socket%%-----------------------------------------------------------------create_send_handle(Socket, {_, _, _, _} = Addr, Port) -> do_create_send_handle(Socket, Addr, Port);create_send_handle(Socket, Addr0, Port) -> {ok, Addr} = inet:getaddr(Addr0, inet), do_create_send_handle(Socket, Addr, Port).do_create_send_handle(Socket, Addr, Port) -> %% If neccessary create snmp counter's SH = #send_handle{socket = Socket, addr = Addr, port = Port}, maybe_create_snmp_counters(SH), SH.maybe_create_snmp_counters(SH) -> Counters = [medGwyGatewayNumInMessages, medGwyGatewayNumInOctets, medGwyGatewayNumOutMessages, medGwyGatewayNumOutOctets, medGwyGatewayNumErrors], %% Only need to check one of them, since either all of them exist %% or none of them exist: Key = {SH, medGwyGatewayNumInMessages}, case (catch ets:lookup(megaco_udp_stats, Key)) of [] -> create_snmp_counters(SH, Counters); [_] -> ok; _ -> ok end.create_snmp_counters(_SH, []) -> ok;create_snmp_counters(SH, [Counter|Counters]) -> Key = {SH, Counter}, ets:insert(megaco_udp_stats, {Key, 0}), create_snmp_counters(SH, Counters).%%-----------------------------------------------------------------%% Func: send_message%% Description: Function is used for sending data on the UDP socket%%-----------------------------------------------------------------send_message(SH, Data) when record(SH, send_handle) -> #send_handle{socket = Socket, addr = Addr, port = Port} = SH, Res = gen_udp:send(Socket, Addr, Port, Data), case Res of ok -> incNumOutMessages(SH), incNumOutOctets(SH, size(Data)); _ -> ok end, Res;send_message(SH, _Data) -> {error, {bad_send_handle, SH}}.%%-----------------------------------------------------------------%% Func: block%% Description: Function is used for blocking incomming messages%% on the TCP socket%%-----------------------------------------------------------------block(SH) when record(SH, send_handle) -> block(SH#send_handle.socket);block(Socket) -> ?udp_debug({socket, Socket}, "udp block", []), inet:setopts(Socket, [{active, false}]). %%-----------------------------------------------------------------%% Func: unblock%% Description: Function is used for blocking incomming messages%% on the TCP socket%%-----------------------------------------------------------------unblock(SH) when record(SH, send_handle) -> unblock(SH#send_handle.socket);unblock(Socket) -> ?udp_debug({socket, Socket}, "udp unblock", []), inet:setopts(Socket, [{active, once}]).%%-----------------------------------------------------------------%% Func: close%% Description: Function is used for closing the UDP socket%%-----------------------------------------------------------------close(#send_handle{socket = Socket}) -> close(Socket);close(Socket) -> ?udp_debug({socket, Socket}, "udp close", []), case erlang:port_info(Socket, connected) of {connected, ControlPid} -> megaco_udp_server:stop(ControlPid); undefined -> {error, already_closed} end.%%-----------------------------------------------------------------%% Internal functions%%-----------------------------------------------------------------%%-----------------------------------------------------------------%% Func: start_udp_server/1%% Description: Function is used for starting up a connection%% process%%-----------------------------------------------------------------start_udp_server(SupPid, UdpRec) -> supervisor:start_child(SupPid, [UdpRec]).%%-----------------------------------------------------------------%% Func: parse_options%% Description: Function that parses the options sent to the UDP %% module.%%-----------------------------------------------------------------parse_options([{Tag, Val} | T], UdpRec, Mand) -> Mand2 = Mand -- [Tag], case Tag of port -> parse_options(T, UdpRec#megaco_udp{port = Val}, Mand2); udp_options when list(Val)-> parse_options(T, UdpRec#megaco_udp{options = Val}, Mand2); receive_handle -> parse_options(T, UdpRec#megaco_udp{receive_handle = Val}, Mand2); module when atom(Val) -> parse_options(T, UdpRec#megaco_udp{module = Val}, Mand2); serialize when Val == true; Val == false -> parse_options(T, UdpRec#megaco_udp{serialize = Val}, Mand2); Bad -> {error, {bad_option, Bad}} end;parse_options([], UdpRec, []) -> {ok, UdpRec};parse_options([], _UdpRec, Mand) -> {error, {missing_options, Mand}};parse_options(BadList, _UdpRec, _Mand) -> {error, {bad_option_list, BadList}}.%%-----------------------------------------------------------------%% Func: incNumOutMessages/1, incNumOutOctets/2, incNumErrors/1%% Description: SNMP counter increment functions%% %%-----------------------------------------------------------------incNumOutMessages(SH) -> incCounter({SH, medGwyGatewayNumOutMessages}, 1).incNumOutOctets(SH, NumOctets) -> incCounter({SH, medGwyGatewayNumOutOctets}, NumOctets).incCounter(Key, Inc) -> ets:update_counter(megaco_udp_stats, Key, Inc).% incNumErrors(SH) ->% incCounter({SH, medGwyGatewayNumErrors}, 1).
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?