📄 megaco_config.erl
字号:
%% ``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: Handle configuration of Megaco/H.248%%-----------------------------------------------------------------------module(megaco_config).-behaviour(gen_server).%% Application internal exports-export([ start_link/0, start_user/2, stop_user/1, user_info/2, update_user_info/3, conn_info/2, update_conn_info/3, system_info/1, %% incr_counter/2, incr_trans_id_counter/1, incr_trans_id_counter/2, %% Verification functions verify_val/2, verify_strict_uint/1, verify_strict_int/1, verify_uint/1, verify_int/1, %% Pending limit counter cre_pending_counter/3, get_pending_counter/2, incr_pending_counter/2, del_pending_counter/2, %% Backward compatibillity functions (to be removed in later versions) cre_pending_counter/1, get_pending_counter/1, incr_pending_counter/1, del_pending_counter/1, lookup_local_conn/1, connect/4, disconnect/1, connect_remote/3, disconnect_remote/2, init_conn_data/4, trans_sender_exit/2 ]).%% gen_server callbacks-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).-define(SERVER, ?MODULE).-record(state, {parent_pid}).-include_lib("megaco/include/megaco.hrl").-include_lib("megaco/src/app/megaco_internal.hrl").-ifdef(MEGACO_TEST_CODE).-define(megaco_test_init(), (catch ets:new(megaco_test_data, [set, public, named_table]))).-else.-define(megaco_test_init(), ok).-endif.%%%----------------------------------------------------------------------%%% API%%%----------------------------------------------------------------------start_link() -> ?d("start_link -> entry", []), gen_server:start_link({local, ?SERVER}, ?MODULE, [self()], []).start_user(UserMid, Config) -> call({start_user, UserMid, Config}).stop_user(UserMid) -> call({stop_user, UserMid}).user_info(UserMid, all) -> All0 = ets:match_object(megaco_config, {{UserMid, '_'}, '_'}), All1 = [{Item, Val} || {{_, Item}, Val} <- All0, Item /= trans_sender], case lists:keysearch(trans_id_counter, 1, All1) of {value, {_, Val}} -> lists:keyreplace(trans_id_counter, 1, All1, {trans_id, Val}); false when UserMid /= default -> [{trans_id, undefined_serial}|All1]; false -> All1 end;user_info(UserMid, receive_handle) -> case call({receive_handle, UserMid}) of {ok, RH} -> RH; {error, Reason} -> exit(Reason) end;user_info(UserMid, conn_data) -> HandlePat = #megaco_conn_handle{local_mid = UserMid, remote_mid = '_'}, Pat = #conn_data{conn_handle = HandlePat, serial = '_', max_serial = '_', request_timer = '_', long_request_timer = '_', auto_ack = '_', trans_ack = '_', trans_ack_maxcount = '_', trans_req = '_', trans_req_maxcount = '_', trans_req_maxsize = '_', trans_timer = '_', trans_sender = '_', pending_timer = '_', sent_pending_limit = '_', recv_pending_limit = '_', reply_timer = '_', control_pid = '_', monitor_ref = '_', send_mod = '_', send_handle = '_', encoding_mod = '_', encoding_config = '_', protocol_version = '_', auth_data = '_', user_mod = '_', user_args = '_', reply_action = '_', reply_data = '_', threaded = '_', strict_version = '_', long_request_resend = '_', cancel = '_', resend_indication = '_'}, %% ok = io:format("PATTERN: ~p~n", [Pat]), ets:match_object(megaco_local_conn, Pat);user_info(UserMid, connections) -> [C#conn_data.conn_handle || C <- user_info(UserMid, conn_data)];user_info(UserMid, mid) -> ets:lookup_element(megaco_config, {UserMid, mid}, 2);user_info(UserMid, orig_pending_limit) -> user_info(UserMid, sent_pending_limit);user_info(UserMid, trans_id) -> case (catch user_info(UserMid, trans_id_counter)) of {'EXIT', _} -> %% There is only two cases where this can occure: %% 1) The user does not exist %% 2) Called before the first message is sent, use %% undefined_serial, since there is no %% "current transaction id" case (catch user_info(UserMid, mid)) of {'EXIT', _} -> %% case 1: exit({no_such_user, UserMid}); _ -> undefined_serial end; Else -> Else end;user_info(UserMid, Item) -> ets:lookup_element(megaco_config, {UserMid, Item}, 2).update_user_info(UserMid, orig_pending_limit, Val) -> update_user_info(UserMid, sent_pending_limit, Val);update_user_info(UserMid, Item, Val) -> call({update_user_info, UserMid, Item, Val}).conn_info(CH, Item) when is_record(CH, megaco_conn_handle) and (Item /= cancel) -> case Item of conn_handle -> CH; mid -> CH#megaco_conn_handle.local_mid; local_mid -> CH#megaco_conn_handle.local_mid; remote_mid -> CH#megaco_conn_handle.remote_mid; conn_data -> case lookup_local_conn(CH) of [] -> exit({no_such_connection, CH}); [ConnData] -> ConnData end; _ -> case lookup_local_conn(CH) of [] -> exit({no_such_connection, CH}); [ConnData] -> conn_info(ConnData, Item) end end;conn_info(#conn_data{conn_handle = CH}, cancel) -> %% To minimise raise-condition propabillity, %% we always look in the table instead of %% in the record for this one ets:lookup_element(megaco_local_conn, CH, #conn_data.cancel);conn_info(CD, Item) when is_record(CD, conn_data) -> case Item of all -> Tags0 = record_info(fields, conn_data), Tags1 = replace(serial, trans_id, Tags0), Tags = [mid, local_mid, remote_mid] ++ replace(max_serial, max_trans_id, Tags1), [{Tag, conn_info(CD,Tag)} || Tag <- Tags, Tag /= conn_data, Tag /= trans_sender, Tag /= cancel]; conn_data -> CD; conn_handle -> CD#conn_data.conn_handle; mid -> (CD#conn_data.conn_handle)#megaco_conn_handle.local_mid; local_mid -> (CD#conn_data.conn_handle)#megaco_conn_handle.local_mid; remote_mid -> (CD#conn_data.conn_handle)#megaco_conn_handle.remote_mid; trans_id -> CH = CD#conn_data.conn_handle, LocalMid = CH#megaco_conn_handle.local_mid, Item2 = {LocalMid, trans_id_counter}, case (catch ets:lookup(megaco_config, Item2)) of {'EXIT', _} -> undefined_serial; [] -> user_info(LocalMid, min_trans_id); [{_, Serial}] -> Max = CD#conn_data.max_serial, if Max == infinity, integer(Serial), Serial < 4294967295 -> Serial + 1; Max == infinity, integer(Serial), Serial == 4294967295 -> user_info(LocalMid, min_trans_id); Serial < Max -> Serial + 1; Serial == 4294967295 -> user_info(LocalMid, min_trans_id); true -> undefined_serial end end; max_trans_id -> CD#conn_data.max_serial; request_timer -> CD#conn_data.request_timer; long_request_timer -> CD#conn_data.long_request_timer; auto_ack -> CD#conn_data.auto_ack; trans_ack -> CD#conn_data.trans_ack; trans_ack_maxcount -> CD#conn_data.trans_ack_maxcount; trans_req -> CD#conn_data.trans_req; trans_req_maxcount -> CD#conn_data.trans_req_maxcount; trans_req_maxsize -> CD#conn_data.trans_req_maxsize; trans_timer -> CD#conn_data.trans_timer; pending_timer -> CD#conn_data.pending_timer; orig_pending_limit -> CD#conn_data.sent_pending_limit; sent_pending_limit -> CD#conn_data.sent_pending_limit; recv_pending_limit -> CD#conn_data.recv_pending_limit; reply_timer -> CD#conn_data.reply_timer; control_pid -> CD#conn_data.control_pid; monitor_ref -> CD#conn_data.monitor_ref; send_mod -> CD#conn_data.send_mod; send_handle -> CD#conn_data.send_handle; encoding_mod -> CD#conn_data.encoding_mod; encoding_config -> CD#conn_data.encoding_config; protocol_version -> CD#conn_data.protocol_version; auth_data -> CD#conn_data.auth_data; user_mod -> CD#conn_data.user_mod; user_args -> CD#conn_data.user_args; reply_action -> CD#conn_data.reply_action; reply_data -> CD#conn_data.reply_data; threaded -> CD#conn_data.threaded; strict_version -> CD#conn_data.strict_version; long_request_resend -> CD#conn_data.long_request_resend; receive_handle -> LocalMid = (CD#conn_data.conn_handle)#megaco_conn_handle.local_mid, #megaco_receive_handle{local_mid = LocalMid, encoding_mod = CD#conn_data.encoding_mod, encoding_config = CD#conn_data.encoding_config, send_mod = CD#conn_data.send_mod}; cancel -> CD#conn_data.cancel; resend_indication -> CD#conn_data.resend_indication; _ -> exit({no_such_item, Item}) end;conn_info(BadHandle, _Item) -> {error, {no_such_connection, BadHandle}}.replace(_, _, []) -> [];replace(Item, WithItem, [Item|List]) -> [WithItem|List];replace(Item, WithItem, [OtherItem|List]) -> [OtherItem | replace(Item, WithItem, List)].update_conn_info(#conn_data{conn_handle = CH}, Item, Val) -> do_update_conn_info(CH, Item, Val);update_conn_info(CH, Item, Val) when is_record(CH, megaco_conn_handle) and (Item /= cancel) -> do_update_conn_info(CH, Item, Val);update_conn_info(BadHandle, _Item, _Val) -> {error, {no_such_connection, BadHandle}}.do_update_conn_info(CH, orig_pending_limit, Val) -> do_update_conn_info(CH, sent_pending_limit, Val);do_update_conn_info(CH, Item, Val) -> call({update_conn_data, CH, Item, Val}).system_info(Item) -> case Item of n_active_requests -> ets:info(megaco_requests, size); n_active_replies -> ets:info(megaco_replies, size); n_active_connections -> ets:info(megaco_local_conn, size); users -> Pat = {{'_', mid}, '_'}, [Mid || {_, Mid} <- ets:match_object(megaco_config, Pat)]; connections -> [C#conn_data.conn_handle || C <- ets:tab2list(megaco_local_conn)]; text_config -> case ets:lookup(megaco_config, text_config) of [] -> []; [{text_config, Conf}] -> [Conf] end; BadItem ->
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -