aboutsummaryrefslogtreecommitdiffstats
path: root/lib/megaco/src/tcp/megaco_tcp_connection.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/megaco/src/tcp/megaco_tcp_connection.erl')
-rw-r--r--lib/megaco/src/tcp/megaco_tcp_connection.erl275
1 files changed, 275 insertions, 0 deletions
diff --git a/lib/megaco/src/tcp/megaco_tcp_connection.erl b/lib/megaco/src/tcp/megaco_tcp_connection.erl
new file mode 100644
index 0000000000..614edf513a
--- /dev/null
+++ b/lib/megaco/src/tcp/megaco_tcp_connection.erl
@@ -0,0 +1,275 @@
+%%
+%% %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%
+%%
+
+%%
+%%-----------------------------------------------------------------
+%%
+%% Purpose: Handles the Megaco/H.248 TCP connections.
+%%
+%%-----------------------------------------------------------------
+-module(megaco_tcp_connection).
+
+-behaviour(gen_server).
+
+
+%%-----------------------------------------------------------------
+%% Include files
+%%-----------------------------------------------------------------
+
+-include_lib("megaco/src/tcp/megaco_tcp.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 proces that keeps track of an TCP
+%% connection.
+%%-----------------------------------------------------------------
+
+start_link(Arg) ->
+ gen_server:start_link(?MODULE, Arg, []).
+
+
+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) ->
+ %% process_flag(trap_exit, true),
+ ?tcp_debug(Arg, "tcp connection handler starting", [self()]),
+%% info_msg("starting with"
+%% "~n Arg: ~p", [Arg]),
+ {ok, Arg}.
+
+
+%%-----------------------------------------------------------------
+%% Func: handle_call/3
+%% Description: Handling call messages (really just stop and garbage)
+%%-----------------------------------------------------------------
+handle_call(stop, _From, TcpRec) ->
+ {stop, shutdown, ok, TcpRec};
+handle_call({upgrade_receive_handle, NewHandle}, _From, TcpRec) ->
+ {reply, ok, TcpRec#megaco_tcp{receive_handle = NewHandle}};
+handle_call(Req, From, TcpRec) ->
+ warning_msg("received unexpected request from ~p: "
+ "~n~w", [From, Req]),
+ {reply, {error, {invalid_request, Req}}, TcpRec}.
+
+
+%%-----------------------------------------------------------------
+%% Func: handle_cast/2
+%% Description: Handling cast messages (really just stop and garbage)
+%%-----------------------------------------------------------------
+handle_cast(stop, TcpRec) ->
+ {stop, shutdown, TcpRec};
+handle_cast(Msg, TcpRec) ->
+ warning_msg("received unexpected message: "
+ "~n~w", [Msg]),
+ {noreply, TcpRec}.
+
+%%-----------------------------------------------------------------
+%% Func: handle_info/2
+%% Description: Handling non call/cast messages. Incomming messages
+%% from the socket and exit messages.
+%%-----------------------------------------------------------------
+handle_info({tcp_closed, _Socket}, TcpRec) ->
+ {stop, shutdown, TcpRec};
+handle_info({tcp_error, _Socket}, TcpRec) ->
+ {stop, shutdown, TcpRec};
+handle_info({tcp, Socket, <<3:8, _X:8, Length:16, Msg/binary>>},
+ #megaco_tcp{socket = Socket, serialize = false} = TcpRec)
+ when Length < ?GC_MSG_LIMIT ->
+ #megaco_tcp{module = Mod, receive_handle = RH} = TcpRec,
+ incNumInMessages(Socket),
+ incNumInOctets(Socket, 4+size(Msg)),
+ apply(Mod, receive_message, [RH, self(), Socket, Msg]),
+ inet:setopts(Socket, [{active, once}]),
+ {noreply, TcpRec};
+handle_info({tcp, Socket, <<3:8, _X:8, Length:16, Msg/binary>>},
+ #megaco_tcp{socket = Socket, serialize = false} = TcpRec) ->
+ #megaco_tcp{module = Mod, receive_handle = RH} = TcpRec,
+ incNumInMessages(Socket),
+ incNumInOctets(Socket, 4+size(Msg)),
+ receive_message(Mod, RH, Socket, Length, Msg),
+ inet:setopts(Socket, [{active, once}]),
+ {noreply, TcpRec};
+handle_info({tcp, Socket, <<3:8, _X:8, _Length:16, Msg/binary>>},
+ #megaco_tcp{socket = Socket, serialize = true} = TcpRec) ->
+ #megaco_tcp{module = Mod, receive_handle = RH} = TcpRec,
+ incNumInMessages(Socket),
+ incNumInOctets(Socket, 4+size(Msg)),
+ process_received_message(Mod, RH, Socket, Msg),
+ inet:setopts(Socket, [{active, once}]),
+ {noreply, TcpRec};
+handle_info({tcp, Socket, Msg}, TcpRec) ->
+ incNumErrors(Socket),
+ error_msg("received bad tpkt packet: "
+ "~n~w", [Msg]),
+ {noreply, TcpRec};
+handle_info(Info, TcpRec) ->
+ warning_msg("received unexpected info: "
+ "~n~p", [Info]),
+ {noreply, TcpRec}.
+
+
+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),
+ ok.
+
+
+handle_received_message(Mod, RH, Parent, SH, Msg) ->
+ Mod:process_received_message(RH, Parent, SH, Msg),
+ unlink(Parent),
+ exit(normal).
+
+
+%%-----------------------------------------------------------------
+%% Func: terminate/2
+%% Description: Termination function for the generic server
+%%-----------------------------------------------------------------
+terminate(shutdown = _Reason, TcpRec) ->
+ ?tcp_debug(TcpRec, "tcp connection handler terminating", [self(),_Reason]),
+ ok;
+
+terminate(Reason, TcpRec) ->
+ ?tcp_debug(TcpRec, "tcp connection handler terminating", [self(), Reason]),
+ SchedId = erlang:system_info(scheduler_id),
+ SchedNum = erlang:system_info(schedulers),
+ ProcCount = erlang:system_info(process_count),
+ ProcLimit = erlang:system_info(process_limit),
+ ProcMemUsed = erlang:memory(processes_used),
+ ProcMemAlloc = erlang:memory(processes),
+ MemTot = erlang:memory(total),
+ error_msg("abormal termination: "
+ "~n Scheduler id: ~p"
+ "~n Num scheduler: ~p"
+ "~n Process count: ~p"
+ "~n Process limit: ~p"
+ "~n Memory used by erlang processes: ~p"
+ "~n Memory allocated by erlang processes: ~p"
+ "~n The total amount of memory allocated: ~p"
+ "~n~p",
+ [SchedId, SchedNum, ProcCount, ProcLimit,
+ ProcMemUsed, ProcMemAlloc, MemTot, Reason]),
+ ok.
+
+
+%%-----------------------------------------------------------------
+%% Func: code_change/3
+%% Descrition: Handles code change messages during upgrade.
+%%-----------------------------------------------------------------
+code_change(_OldVsn, S, _Extra) ->
+ ?d("code_change -> entry with"
+ "~n OldVsn: ~p"
+ "~n S: ~p"
+ "~n Extra: ~p", [_OldVsn, S, _Extra]),
+ {ok, S}.
+
+
+
+%%-----------------------------------------------------------------
+%% Func: incNumInMessages/1, incNumInOctets/2, incNumErrors/1
+%% Description: SNMP counter increment functions
+%%
+%%-----------------------------------------------------------------
+incNumInMessages(Socket) ->
+ incCounter({Socket, medGwyGatewayNumInMessages}, 1).
+
+incNumInOctets(Socket, NumOctets) ->
+ incCounter({Socket, medGwyGatewayNumInOctets}, NumOctets).
+
+incNumErrors(Socket) ->
+ incCounter({Socket, medGwyGatewayNumErrors}, 1).
+
+incCounter(Key, Inc) ->
+ ets:update_counter(megaco_tcp_stats, Key, Inc).
+
+
+%% info_msg(F, A) ->
+%% ?megaco_info("TCP connection handler " ++ F, A).
+
+warning_msg(F, A) ->
+ ?megaco_warning("TCP connection handler: " ++ F, A).
+
+error_msg(F, A) ->
+ ?megaco_error("TCP connection handler: " ++ F, A).
+
+
+call(Pid, Req) ->
+ gen_server:call(Pid, Req, infinity).
+