aboutsummaryrefslogtreecommitdiffstats
path: root/lib/megaco/src/tcp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/megaco/src/tcp')
-rw-r--r--lib/megaco/src/tcp/Makefile107
-rw-r--r--lib/megaco/src/tcp/depend.mk42
-rw-r--r--lib/megaco/src/tcp/megaco_tcp.erl692
-rw-r--r--lib/megaco/src/tcp/megaco_tcp.hrl68
-rw-r--r--lib/megaco/src/tcp/megaco_tcp_accept.erl123
-rw-r--r--lib/megaco/src/tcp/megaco_tcp_accept_sup.erl95
-rw-r--r--lib/megaco/src/tcp/megaco_tcp_connection.erl275
-rw-r--r--lib/megaco/src/tcp/megaco_tcp_connection_sup.erl114
-rw-r--r--lib/megaco/src/tcp/megaco_tcp_sup.erl145
-rw-r--r--lib/megaco/src/tcp/modules.mk33
10 files changed, 1694 insertions, 0 deletions
diff --git a/lib/megaco/src/tcp/Makefile b/lib/megaco/src/tcp/Makefile
new file mode 100644
index 0000000000..0bd4b7c4ee
--- /dev/null
+++ b/lib/megaco/src/tcp/Makefile
@@ -0,0 +1,107 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2000-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%
+
+include $(ERL_TOP)/make/target.mk
+
+EBIN = ../../ebin
+MEGACO_INCLUDEDIR = ../../include
+
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../../vsn.mk
+VSN=$(MEGACO_VSN)
+
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/megaco-$(VSN)
+
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+
+include modules.mk
+
+ERL_FILES = $(MODULES:%=%.erl)
+
+TARGET_FILES = \
+ $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+ifeq ($(TYPE),debug)
+ERL_COMPILE_FLAGS += -Ddebug
+endif
+
+include ../app/megaco.mk
+
+ERL_COMPILE_FLAGS += \
+ $(MEGACO_ERL_COMPILE_FLAGS) \
+ -I../../include
+
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+debug:
+ @${MAKE} TYPE=debug opt
+
+opt: $(TARGET_FILES)
+
+clean:
+ rm -f $(TARGET_FILES)
+ rm -f errs core *~
+
+docs:
+
+# ----------------------------------------------------
+# Special Build Targets
+# ----------------------------------------------------
+
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+
+release_spec: opt
+ $(INSTALL_DIR) $(RELSYSDIR)/ebin
+ $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) $(RELSYSDIR)/src
+ $(INSTALL_DIR) $(RELSYSDIR)/src/tcp
+ $(INSTALL_DATA) $(ERL_FILES) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src/tcp
+
+
+release_docs_spec:
+
+
+# ----------------------------------------------------
+# Include dependencies
+# ----------------------------------------------------
+
+include depend.mk
+
diff --git a/lib/megaco/src/tcp/depend.mk b/lib/megaco/src/tcp/depend.mk
new file mode 100644
index 0000000000..27b0feec94
--- /dev/null
+++ b/lib/megaco/src/tcp/depend.mk
@@ -0,0 +1,42 @@
+#-*-makefile-*- ; force emacs to enter makefile-mode
+
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2007-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%
+
+$(EBIN)/megaco_tcp.$(EMULATOR): megaco_tcp.erl \
+ megaco_tcp.hrl \
+ ../app/megaco_internal.hrl \
+ $(MEGACO_INCLUDEDIR)/megaco.hrl
+
+$(EBIN)/megaco_tcp_accept.$(EMULATOR): megaco_tcp_accept.erl \
+ ../app/megaco_internal.hrl \
+ $(MEGACO_INCLUDEDIR)/megaco.hrl
+
+$(EBIN)/megaco_tcp_connection.$(EMULATOR): megaco_tcp_connection.erl \
+ megaco_tcp.hrl \
+ ../app/megaco_internal.hrl \
+ $(MEGACO_INCLUDEDIR)/megaco.hrl
+
+$(EBIN)/megaco_tcp_sup.$(EMULATOR): megaco_tcp_sup.erl \
+ $(MEGACO_INCLUDEDIR)/megaco.hrl
+
+$(EBIN)/megaco_tcp_connection_sup.$(EMULATOR): megaco_tcp_connection_sup.erl \
+ $(MEGACO_INCLUDEDIR)/megaco.hrl
+
+$(EBIN)/megaco_tcp_accept_sup.$(EMULATOR): megaco_tcp_accept_sup.erl \
+ $(MEGACO_INCLUDEDIR)/megaco.hrl
+
diff --git a/lib/megaco/src/tcp/megaco_tcp.erl b/lib/megaco/src/tcp/megaco_tcp.erl
new file mode 100644
index 0000000000..45fd35eabc
--- /dev/null
+++ b/lib/megaco/src/tcp/megaco_tcp.erl
@@ -0,0 +1,692 @@
+%%
+%% %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:
+%% Interface the TPKT (TCP/IP) transport module for Megaco/H.248
+%%
+%%-----------------------------------------------------------------
+-module(megaco_tcp).
+
+-behaviour(gen_server).
+
+
+%%-----------------------------------------------------------------
+%% Include files
+%%-----------------------------------------------------------------
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/src/tcp/megaco_tcp.hrl").
+-include_lib("megaco/src/app/megaco_internal.hrl").
+
+
+-define(d1(F, A), ?d("~p " ++ F, [self()|A])).
+-define(d2(F), ?d1(F, [])).
+
+
+%%-----------------------------------------------------------------
+%% External exports
+%%-----------------------------------------------------------------
+-export([
+ start_transport/0, %% Start TPKT transport service
+ stop_transport/1, %% Stop TPKT transport service
+ listen/2, %% Starts a new listener socket
+ connect/2, %% Used on client side to connect server
+ socket/1, %% Returns the inet socket
+ send_message/2, %% Used to send data on connection
+ block/1, %% Used to block the socket for incomming
+ %% messages
+ unblock/1, %% Used to unblock the node
+ close/1, %% Used on both sides to close connection
+
+ 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([
+ start_link/1, %% Start TCP/IP net server
+ init/1, %%
+ terminate/2,
+ handle_call/3,
+ handle_cast/2,
+ handle_info/2,
+ code_change/3,
+ start_connection/2
+ ]).
+
+
+%%-----------------------------------------------------------------
+%% Server state record
+%%-----------------------------------------------------------------
+-record(state, {supervisor_pid, linkdb}).
+
+
+%%-----------------------------------------------------------------
+%% 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_tcp_stats).
+
+get_stats(Socket) ->
+ megaco_stats:get_stats(megaco_tcp_stats, Socket).
+
+get_stats(Socket, Counter) ->
+ megaco_stats:get_stats(megaco_tcp_stats, Socket, Counter).
+
+
+%%-----------------------------------------------------------------
+%% Func: reset_stats/0, reaet_stats/1
+%% Description: Reset statistics (counters) for TCP
+%%-----------------------------------------------------------------
+reset_stats() ->
+ megaco_stats:reset_stats(megaco_tcp_stats).
+
+reset_stats(Socket) ->
+ megaco_stats:reset_stats(megaco_tcp_stats, Socket).
+
+
+%%-----------------------------------------------------------------
+%% Func: start_transport/0
+%% Description: Starts the TPKT transport service
+%%-----------------------------------------------------------------
+start_transport() ->
+ ?d2("start_transport -> entry"),
+ (catch megaco_stats:init(megaco_tcp_stats)),
+ megaco_tcp_sup:start_link().
+
+
+%%-----------------------------------------------------------------
+%% Func: stop_transport/1, 2
+%% Description: Stop the TPKT transport service
+%%-----------------------------------------------------------------
+stop_transport(Pid) ->
+ (catch unlink(Pid)),
+ stop_transport(Pid, shutdown).
+
+stop_transport(Pid, Reason) ->
+ ?d1("stop_transport -> entry with"
+ "~n Pid: ~p"
+ "~n Reason: ~p", [Pid, Reason]),
+ exit(Pid, Reason).
+
+
+%%-----------------------------------------------------------------
+%% Func: listen/2
+%% Description: Starts new TPKT listener sockets
+%%-----------------------------------------------------------------
+listen(SupPid, Parameters) ->
+ ?d1("listen -> entry with"
+ "~n SupPid: ~p"
+ "~n Parameters: ~p", [SupPid, Parameters]),
+ ProcList = supervisor:which_children(SupPid),
+ case lists:keysearch(megaco_tcp, 1, ProcList) of
+ {value, {_Name, Pid, _Type, _Modules}} ->
+ ?d1("listen -> found listener: "
+ "~n Pid: ~p", [Pid]),
+ call(Pid, {add_listener, Parameters});
+ false ->
+ {error, no_tcp_server}
+ end.
+
+
+%%-----------------------------------------------------------------
+%% Func: connect
+%% Description: Function is used when opening an TCP socket
+%% at the MG side when trying to connect an MGC
+%%-----------------------------------------------------------------
+connect(SupPid, Parameters) ->
+ ?d1("connect -> entry with"
+ "~n SupPid: ~p"
+ "~n Parameters: ~p", [SupPid, Parameters]),
+ Mand = [host, port, receive_handle],
+ case parse_options(Parameters, #megaco_tcp{}, Mand) of
+ {ok, Rec} ->
+
+ ?d1("connect -> options parsed: "
+ "~n Rec: ~p", [Rec]),
+
+ #megaco_tcp{host = Host,
+ port = Port,
+ options = Options} = Rec,
+
+ IpOpt = [binary, {packet, tpkt}, {active, once} | Options],
+
+ %%------------------------------------------------------
+ %% Connect the other side
+ case (catch gen_tcp:connect(Host, Port, IpOpt)) of
+ {ok, Socket} ->
+ ?d1("connect -> connected: "
+ "~n Socket: ~p", [Socket]),
+ %%----------------------------------------------
+ %% Socket up start a new control process
+ Rec2 = Rec#megaco_tcp{socket = Socket},
+ case start_connection(SupPid, Rec2) of
+ {ok, Pid} ->
+ ?d1("connect -> connection started: "
+ "~n Pid: ~p", [Pid]),
+ gen_tcp:controlling_process(Socket, Pid),
+ ?d2("connect -> control transferred"),
+ {ok, Socket, Pid};
+ {error, Reason} ->
+ ?d1("connect -> failed starting connection: "
+ "~n Reason: ~p", [Reason]),
+ {error, Reason}
+ end;
+
+ {error, Reason} ->
+ ?d1("connect -> failed connecting: "
+ "~n Reason: ~p", [Reason]),
+ Error = {error, {gen_tcp_connect, Reason}},
+ ?tcp_debug(Rec, "tcp connect failed", [Error]),
+ Error;
+
+ {'EXIT', _Reason} = Exit ->
+ ?d1("connect -> connect exited: "
+ "~n Exit: ~p", [Exit]),
+ Error = {error, {gen_tcp_connect, Exit}},
+ ?tcp_debug(Rec, "tcp connect failed", [Error]),
+ Error
+
+ end;
+
+ {error, _Reason} = Error ->
+ ?d1("connect -> failed parsing options: "
+ "~n Error: ~p", [Error]),
+ ?tcp_debug(#megaco_tcp{}, "tcp connect failed",
+ [Error, {options, Parameters}]),
+ Error
+ end.
+
+
+%%-----------------------------------------------------------------
+%% Func: send_message
+%% Description: Function is used for sending data on the TCP socket
+%%-----------------------------------------------------------------
+send_message(Socket, Data) ->
+ ?d1("send_message -> entry with"
+ "~n Socket: ~p"
+ "~n size(Data): ~p", [Socket, sz(Data)]),
+ {Size, NewData} = add_tpkt_header(Data),
+ Res = gen_tcp:send(Socket, NewData),
+ case Res of
+ ok ->
+ incNumOutMessages(Socket),
+ incNumOutOctets(Socket, Size);
+ _ ->
+ ok
+ end,
+ Res.
+
+-ifdef(megaco_debug).
+sz(Bin) when is_binary(Bin) ->
+ size(Bin);
+sz(List) when is_list(List) ->
+ length(List).
+-endif.
+
+
+%%-----------------------------------------------------------------
+%% Func: block
+%% Description: Function is used for blocking incomming messages
+%% on the TCP socket
+%%-----------------------------------------------------------------
+block(Socket) ->
+ ?tcp_debug({socket, Socket}, "tcp block", []),
+ inet:setopts(Socket, [{active, false}]).
+
+
+%%-----------------------------------------------------------------
+%% Func: unblock
+%% Description: Function is used for blocking incomming messages
+%% on the TCP socket
+%%-----------------------------------------------------------------
+unblock(Socket) ->
+ ?tcp_debug({socket, Socket}, "tcp unblock", []),
+ inet:setopts(Socket, [{active, once}]).
+
+
+%%-----------------------------------------------------------------
+%% Func: close
+%% Description: Function is used for closing the TCP socket
+%%-----------------------------------------------------------------
+close(Socket) ->
+ ?tcp_debug({socket, Socket}, "tcp close", []),
+ gen_tcp:close(Socket).
+
+
+%%-----------------------------------------------------------------
+%% Func: socket
+%% Description: Returns the inet socket
+%%-----------------------------------------------------------------
+socket(Socket) ->
+ Socket.
+
+upgrade_receive_handle(Pid, NewHandle)
+ when is_pid(Pid) andalso is_record(NewHandle, megaco_receive_handle) ->
+ megaco_tcp_connection:upgrade_receive_handle(Pid, NewHandle).
+
+
+%%-----------------------------------------------------------------
+%% Internal Interface functions
+%%-----------------------------------------------------------------
+%%-----------------------------------------------------------------
+%% Func: start_link/1
+%% Description: Starts the net server
+%%-----------------------------------------------------------------
+start_link(Args) ->
+ gen_server:start_link(?MODULE, Args, []).
+
+
+%%-----------------------------------------------------------------
+%% Func: start_connection
+%% Description: Function is used for starting up a connection
+%% process
+%%-----------------------------------------------------------------
+start_connection(SupPid, #megaco_tcp{socket = Socket} = TcpRec) ->
+ ?d1("start_connection -> entry with"
+ "~n SupPid: ~p"
+ "~n Socket: ~p", [SupPid, Socket]),
+
+ case connection_sup(SupPid) of
+ {ok, ConnSupPid} ->
+ ?d1("start_connection -> found connection supervisor: "
+ "~n ConnSupPid: ~p", [ConnSupPid]),
+ ?tcp_debug(TcpRec, "tcp connect", []),
+ case create_connection(ConnSupPid, TcpRec) of
+ {ok, Pid} ->
+ ?d1("start_connection -> started: "
+ "~n Pid: ~p", [Pid]),
+ ?tcp_debug(TcpRec, "connect handler started", [Pid]),
+ create_snmp_counters(Socket),
+ {ok, Pid};
+ {error, Reason} ->
+ ?d1("start_connection -> failed starting: "
+ "~n Reason: ~p", [Reason]),
+ Error = {error, {controlling_process_not_started, Reason}},
+ ?tcp_debug(TcpRec, "tcp connect failed", [Error]),
+ Error
+ end;
+ {error, _Reason} ->
+ ?d2("start_connection -> could not find connection supervisor"),
+ Error = {error, no_connection_supervisor},
+ ?tcp_debug(TcpRec, "tcp connect failed", [Error]),
+ Error
+ end.
+
+connection_sup(Pid) ->
+ megaco_tcp_sup:which_connection_sup(Pid).
+
+create_connection(Pid, Rec) ->
+ megaco_tcp_connection_sup:start_child(Pid, Rec).
+
+create_snmp_counters(Socket) ->
+ Counters = [medGwyGatewayNumInMessages,
+ medGwyGatewayNumInOctets,
+ medGwyGatewayNumOutMessages,
+ medGwyGatewayNumOutOctets,
+ medGwyGatewayNumErrors],
+ create_snmp_counters(Socket, Counters).
+
+create_snmp_counters(_Socket, []) ->
+ ok;
+create_snmp_counters(Socket, [Counter|Counters]) ->
+ Key = {Socket, Counter},
+ ets:insert(megaco_tcp_stats, {Key, 0}),
+ create_snmp_counters(Socket, Counters).
+
+
+%%-----------------------------------------------------------------
+%% Server functions
+%%-----------------------------------------------------------------
+%%-----------------------------------------------------------------
+%% Func: init/1
+%% Description: Init funcion for the supervisor
+%%-----------------------------------------------------------------
+init({SupPid, _}) ->
+ process_flag(trap_exit, true),
+ {ok, #state{supervisor_pid = SupPid}}.
+
+%%-----------------------------------------------------------------
+%% Func: terminate/1
+%% Description: Termination function for the generic server
+%%-----------------------------------------------------------------
+terminate(_Reason, _State) ->
+ ok.
+
+
+%%-----------------------------------------------------------------
+%% Internal Functions
+%%-----------------------------------------------------------------
+
+%%-----------------------------------------------------------------
+%% Func: start_tcp_listener/2
+%% Description: Function which parses the list of transport layers
+%% to start
+%%-----------------------------------------------------------------
+start_tcp_listener(P, State) ->
+ ?d1("start_tcp_listener -> entry with"
+ "~n P: ~p", [P]),
+ case setup(State#state.supervisor_pid, P) of
+ {ok, Pid, Data} ->
+ ?d1("start_tcp_listener -> setup ok"
+ "~n Pid: ~p"
+ "~n Data: ~p", [Pid, Data]),
+ link(Pid),
+ {reply, ok,
+ State#state{linkdb=[{Pid, Data} | State#state.linkdb]}};
+ {error, Reason} ->
+ ?d1("start_tcp_listener -> setup failed"
+ "~n Reason: ~p", [Reason]),
+ {reply, {error, {could_not_start_listener, Reason}}, State}
+ end.
+
+
+%%-----------------------------------------------------------------
+%% Func: handle_call/3
+%% Description: Handling call messages (really just garbage)
+%%-----------------------------------------------------------------
+handle_call({add_listener, Parameters}, _From, State) ->
+ ?d1("handle_call(add_listener) -> entry with"
+ "~n Parameters: ~p", [Parameters]),
+ start_tcp_listener(Parameters, State);
+handle_call(Req, From, State) ->
+ warning_msg("received unexpected request from ~p: "
+ "~n~w", [From, Req]),
+ {noreply, State}.
+
+
+%%------------------------------------------------------------
+%% Func: handle_cast/2
+%% Description: Handling cast messages (really just garbage)
+%%------------------------------------------------------------
+handle_cast(Msg, State) ->
+ warning_msg("received unexpected message: "
+ "~n~w", [Msg]),
+ {noreply, State}.
+
+
+%%-----------------------------------------------------------------
+%% Func: handle_info/2
+%% Description: Handling non call/cast messages, eg exit messages
+%%-----------------------------------------------------------------
+handle_info({'EXIT', Pid, Reason}, State) when is_pid(Pid) ->
+ %% Accept process died
+ NewState = resetup(Pid, Reason, State),
+ {noreply, NewState};
+handle_info(Info, State) ->
+ warning_msg("received unexpected info: "
+ "~n~w", [Info]),
+ {noreply, State}.
+
+
+%%-----------------------------------------------------------------
+%% Func: code_change/3
+%% Descrition: Handles code change messages during upgrade.
+%%-----------------------------------------------------------------
+code_change(_Vsn, State, _Extra) ->
+ {ok, State}.
+
+
+%%-----------------------------------------------------------------
+%% Internal functions
+%%-----------------------------------------------------------------
+%%-----------------------------------------------------------------
+%% Func: setup/2
+%% Description: Function is used when setting up an TCP listen
+%% socket in the MGC
+%%-----------------------------------------------------------------
+setup(SupPid, Options) ->
+ ?d1("setup -> entry with"
+ "~n SupPid: ~p"
+ "~n Options: ~p", [SupPid, Options]),
+ Mand = [port, receive_handle],
+ case parse_options(Options, #megaco_tcp{}, Mand) of
+ {ok, TcpRec} ->
+
+ ?d1("setup -> options parsed"
+ "~n TcpRec: ~p", [TcpRec]),
+
+ %%------------------------------------------------------
+ %% Setup the listen socket
+ IpOpts = [binary, {packet, tpkt}, {active, once},
+ {reuseaddr, true} | TcpRec#megaco_tcp.options],
+ case catch gen_tcp:listen(TcpRec#megaco_tcp.port, IpOpts) of
+ {ok, Listen} ->
+
+ ?d1("setup -> listen ok"
+ "~n Listen: ~p", [Listen]),
+
+ %%-----------------------------------------------
+ %% Startup the accept process that will wait for
+ %% connect attempts
+ case start_accept(SupPid, TcpRec, Listen) of
+ {ok, Pid} ->
+
+ ?d1("setup -> accept process started"
+ "~n Pid: ~p", [Pid]),
+
+ ?tcp_debug(TcpRec, "tcp listen setup", []),
+ {ok, Pid, {TcpRec, Listen}};
+ {error, _Reason} = Error ->
+ ?d1("setup -> failed starting accept process"
+ "~n Error: ~p", [Error]),
+ ?tcp_debug(TcpRec, "tcp listen setup failed",
+ [Error]),
+ Error
+ end;
+ {error, Reason} ->
+ ?d1("setup -> listen failed"
+ "~n Reason: ~p", [Reason]),
+ Error = {error, {gen_tcp_listen, Reason}},
+ ?tcp_debug(TcpRec, "tcp listen setup failed", [Error]),
+ Error;
+ {'EXIT', _Reason} = Exit ->
+ ?d1("setup -> listen exited"
+ "~n Exit: ~p", [Exit]),
+ Error = {error, {gen_tcp_listen, Exit}},
+ ?tcp_debug(TcpRec, "tcp listen setup failed", [Error]),
+ Error
+ end;
+ {error, _Reason} = Error ->
+ ?d1("setup -> failed parsing options"
+ "~n Error: ~p", [Error]),
+ ?tcp_debug(#megaco_tcp{}, "tcp listen setup failed",
+ [Error, {options, Options}]),
+ Error
+ end.
+
+
+%%-----------------------------------------------------------------
+%% Func: resetup
+%% Description: Function is used when restarting the accept process
+%% if it died for some reason.
+%%-----------------------------------------------------------------
+
+resetup(Pid, Reason, State) ->
+ ?d1("resetup -> entry with"
+ "~n Pid: ~p"
+ "~n Reason: ~p", [Pid, Reason]),
+ case lists:keysearch(Pid, 1, State#state.linkdb) of
+ {value, {Pid, {TcpRec, Listener}}} ->
+ ?d1("resetup -> found accept process: "
+ "~n TcpRec: ~p"
+ "~n Listener: ~p", [TcpRec, Listener]),
+ ?tcp_debug(TcpRec, "tcp listen resetup", [{error, Reason}]),
+ unlink(Pid),
+ warning_msg("received unexpected 'EXIT' signal "
+ "from accept process ~p: "
+ "~n~w", [Pid, Reason]),
+ case start_accept(State#state.supervisor_pid, TcpRec, Listener) of
+ {ok, NewPid} ->
+ ?d1("resetup -> start new accept process ok: "
+ "~n NewPid: ~p", [NewPid]),
+ link(NewPid),
+ NewList = lists:keyreplace(Pid, 1, State#state.linkdb,
+ {NewPid, {TcpRec, Listener}}),
+ State#state{linkdb = NewList};
+ {error, Reason} ->
+ ?d1("resetup -> failed starting new accept process: "
+ "~n :Reason ~p", [Reason]),
+ ?tcp_debug(TcpRec,
+ "tcp listen resetup failed", [{error, Reason}]),
+ State
+ end;
+ false ->
+ warning_msg("received unexpected 'EXIT' signal from ~p: "
+ "~n~w", [Pid, Reason]),
+ State
+ end.
+
+
+%%-----------------------------------------------------------------
+%% Func: start_accept
+%% Description: Function is used for starting up an TCP accept
+%% process
+%%-----------------------------------------------------------------
+start_accept(SupPid, TcpRec, Listen) ->
+ ?d1("start_accept -> entry with"
+ "~n SupPid: ~p"
+ "~n TcpRec: ~p"
+ "~n Reason: ~p", [SupPid, TcpRec, Listen]),
+ case accept_sup(SupPid) of
+ {ok, AcceptSupPid} ->
+ ?d1("start_accept -> found accept supervisor"
+ "~n AcceptSupPid: ~p", [AcceptSupPid]),
+ case create_acceptor(AcceptSupPid, TcpRec, SupPid, Listen) of
+ {ok, Pid} ->
+ ?d1("start_accept -> accept process started"
+ "~n Pid: ~p", [Pid]),
+ {ok, Pid};
+ {error, Reason} ->
+ ?d1("start_accept -> failed starting accept process: "
+ "~n Reason: ~p", [Reason]),
+ {error, {accept_not_started, Reason}}
+ end;
+ {error, Reason} ->
+ ?d1("start_accept -> could not find acceept supervisor: "
+ "~n Reason: ~p", [Reason]),
+ {error, {no_tcp_accept_sup, Reason}}
+ end.
+
+accept_sup(Pid) ->
+ megaco_tcp_sup:which_accept_sup(Pid).
+
+create_acceptor(Pid, Rec, TopSup, Listen) ->
+ megaco_tcp_accept_sup:start_child(Pid, Rec, TopSup, Listen).
+
+
+%%-----------------------------------------------------------------
+%% Func: add_tpkt_header
+%% Description: Function is used to add the TPKT header
+%%-----------------------------------------------------------------
+add_tpkt_header(Data) when is_binary(Data) ->
+ L = size(Data) + 4,
+ {L, [3, 0, ((L) bsr 8) band 16#ff, (L) band 16#ff ,Data]};
+add_tpkt_header(IOList) when is_list(IOList) ->
+ Binary = list_to_binary(IOList),
+ L = size(Binary) + 4,
+ {L, [3, 0, ((L) bsr 8) band 16#ff, (L) band 16#ff , Binary]}.
+
+%%-----------------------------------------------------------------
+%% Func: parse_options
+%% Description: Function that parses the options sent to the TCP
+%% module.
+%%-----------------------------------------------------------------
+parse_options([{Tag, Val} | T], TcpRec, Mand) ->
+ ?d1("parse_options -> entry with"
+ "~n Tag: ~p"
+ "~n Val: ~p", [Tag, Val]),
+ Mand2 = Mand -- [Tag],
+ case Tag of
+ port ->
+ parse_options(T, TcpRec#megaco_tcp{port = Val}, Mand2);
+ host ->
+ parse_options(T, TcpRec#megaco_tcp{host = Val}, Mand2);
+ tcp_options when is_list(Val) ->
+ parse_options(T, TcpRec#megaco_tcp{options = Val}, Mand2);
+ receive_handle ->
+ parse_options(T, TcpRec#megaco_tcp{receive_handle = Val}, Mand2);
+ module when is_atom(Val) ->
+ parse_options(T, TcpRec#megaco_tcp{module = Val}, Mand2);
+ serialize when (Val =:= true) orelse (Val =:= false) ->
+ parse_options(T, TcpRec#megaco_tcp{serialize = Val}, Mand2);
+ Bad ->
+ ?d1("parse_options -> bad option: "
+ "~n Tag: ~p", [Tag]),
+ {error, {bad_option, Bad}}
+ end;
+parse_options([], TcpRec, []) ->
+ ?d2("parse_options -> done"),
+ {ok, TcpRec};
+parse_options([], _TcpRec, Mand) ->
+ ?d1("parse_options -> entry with"
+ "~n Mand: ~p", [Mand]),
+ {error, {missing_options, Mand}};
+parse_options(BadList, _TcpRec, _Mand) ->
+ ?d1("parse_options -> entry with"
+ "~n BadList: ~p", [BadList]),
+ {error, {bad_option_list, BadList}}.
+
+
+%%-----------------------------------------------------------------
+%% Func: incNumOutMessages/1, incNumOutOctets/2, incNumErrors/1
+%% Description: SNMP counter increment functions
+%%
+%%-----------------------------------------------------------------
+incNumOutMessages(Socket) ->
+ incCounter({Socket, medGwyGatewayNumOutMessages}, 1).
+
+incNumOutOctets(Socket, NumOctets) ->
+ incCounter({Socket, medGwyGatewayNumOutOctets}, NumOctets).
+
+incCounter(Key, Inc) ->
+ ets:update_counter(megaco_tcp_stats, Key, Inc).
+
+% incNumErrors(Socket) ->
+% ets:update_counter(megaco_tcp_stats,
+% {Socket, medGwyGatewayNumErrors}, 1).
+
+
+%%-----------------------------------------------------------------
+
+
+warning_msg(F, A) ->
+ ?megaco_warning("TCP server: " ++ F, A).
+
+%% error_msg(F, A) ->
+%% ?megaco_error("TCP server: " ++ F, A).
+
+
+call(Pid, Req) ->
+ gen_server:call(Pid, Req, infinity).
diff --git a/lib/megaco/src/tcp/megaco_tcp.hrl b/lib/megaco/src/tcp/megaco_tcp.hrl
new file mode 100644
index 0000000000..5de1dd9070
--- /dev/null
+++ b/lib/megaco/src/tcp/megaco_tcp.hrl
@@ -0,0 +1,68 @@
+%%
+%% %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: Define the protocol options for Megaco/H.248 IP connections
+%%-----------------------------------------------------------------
+
+%%----------------------------------------------------------------------
+%% IP options
+%%----------------------------------------------------------------------
+-record(megaco_tcp,
+ {host,
+ port,
+ options = [],
+ socket,
+ proxy_pid,
+ receive_handle,
+ module = megaco,
+ serialize = false % false: Spawn a new process for each message
+ }).
+
+
+-define(GC_MSG_LIMIT,1000).
+-define(HEAP_SIZE(S),5000 + 2*(S)).
+
+
+%%----------------------------------------------------------------------
+%% Event Trace
+%%----------------------------------------------------------------------
+
+-define(tcp_report(Level, TcpRec, From, To, Label, Contents),
+ megaco:report_event(Level, From, To, Label,
+ [{line, ?MODULE, ?LINE}, TcpRec | Contents])).
+
+-define(tcp_debug(TcpRec, Label, Contents),
+ ?tcp_report_debug(TcpRec,
+ megaco_tcp,
+ megaco_tcp,
+ Label,
+ Contents)).
+
+-define(tcp_report_important(C, From, To, Label, Contents),
+ ?tcp_report(20, C, From, To, Label, Contents)).
+-define(tcp_report_verbose(C, From, To, Label, Contents),
+ ?tcp_report(40, C, From, To, Label, Contents)).
+-define(tcp_report_debug(C, From, To, Label, Contents),
+ ?tcp_report(60, C, From, To, Label, Contents)).
+-define(tcp_report_trace(C, From, To, Label, Contents),
+ ?tcp_report(80, C, From, To, Label, Contents)).
+
+
diff --git a/lib/megaco/src/tcp/megaco_tcp_accept.erl b/lib/megaco/src/tcp/megaco_tcp_accept.erl
new file mode 100644
index 0000000000..68bda8a340
--- /dev/null
+++ b/lib/megaco/src/tcp/megaco_tcp_accept.erl
@@ -0,0 +1,123 @@
+%%
+%% %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: Waiting in accept for new connections.
+%%-----------------------------------------------------------------
+-module(megaco_tcp_accept).
+
+%%-----------------------------------------------------------------
+%% Include files
+%%-----------------------------------------------------------------
+-include_lib("megaco/src/tcp/megaco_tcp.hrl").
+-include_lib("megaco/src/app/megaco_internal.hrl").
+
+
+-define(d1(F, A), ?d("~p " ++ F, [self()|A])).
+-define(d2(F), ?d1(F, [])).
+
+
+%%-----------------------------------------------------------------
+%% External exports
+%%-----------------------------------------------------------------
+-export([
+ start_link/1
+ ]).
+
+
+%%-----------------------------------------------------------------
+%% Internal exports
+%%-----------------------------------------------------------------
+-export([
+ net_accept/4
+ ]).
+
+
+%%-----------------------------------------------------------------
+%% External interface functions
+%%-----------------------------------------------------------------
+%%-----------------------------------------------------------------
+%% Func: start
+%% Description: Starts the proces that makes the accept call.
+%%-----------------------------------------------------------------
+start_link({TcpRec, SupPid, Listen}) ->
+ Args = [TcpRec, SupPid, Listen, self()],
+ Pid = proc_lib:spawn_link(?MODULE, net_accept, Args),
+ {ok, Pid}.
+
+%%-----------------------------------------------------------------
+%% Internal Interface Functions
+%%-----------------------------------------------------------------
+%%-----------------------------------------------------------------
+%% Func: net_accept
+%% Description: Loop function which calls accept and
+%% spawns a connection process when there is an initial
+%% contact.
+%%-----------------------------------------------------------------
+net_accept(TcpRec, SupPid, ListenFd, Parent) ->
+ do_accept(TcpRec, SupPid, ListenFd),
+ net_accept(TcpRec, SupPid, ListenFd, Parent).
+
+do_accept(Tcp, Sup, Fd) ->
+ case gen_tcp:accept(Fd) of
+ {ok, S} ->
+ ?d1("do_accept -> accepted: "
+ "~n S: ~p", [S]),
+ case megaco_tcp:start_connection(Sup,
+ Tcp#megaco_tcp{socket = S}) of
+ {ok, Pid} ->
+ ?d1("do_accept -> connection started"
+ "~n Pid: ~p", [Pid]),
+ case gen_tcp:controlling_process(S, Pid) of
+ ok ->
+ ?d2("do_accept -> control transferred"),
+ ok;
+ {error, _Reason} ->
+ ?d1("do_accept -> "
+ "failed changing controlling process: "
+ "n _Reason: ~p", [_Reason]),
+ tcp_clear(S),
+ gen_tcp:close(S)
+ end;
+
+ {error, _Reason} ->
+ ?d1("do_accept -> failed starting connection: "
+ "~n _Reason: ~p", [_Reason]),
+ tcp_clear(S),
+ gen_tcp:close(S)
+ end;
+ {error, _Reason} ->
+ ?d1("do_accept -> accept failed: "
+ "~n _Reason: ~p", [_Reason]),
+ ok
+ end.
+
+
+tcp_clear(Socket) ->
+ receive
+ {tcp, Socket, _Data} ->
+ tcp_clear(Socket);
+ {tcp_closed, Socket} ->
+ tcp_clear(Socket);
+ {tcp_error, Socket} ->
+ tcp_clear(Socket)
+ after 0 ->
+ ok
+ end.
diff --git a/lib/megaco/src/tcp/megaco_tcp_accept_sup.erl b/lib/megaco/src/tcp/megaco_tcp_accept_sup.erl
new file mode 100644
index 0000000000..a601f32558
--- /dev/null
+++ b/lib/megaco/src/tcp/megaco_tcp_accept_sup.erl
@@ -0,0 +1,95 @@
+%%
+%% %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: Supervisor for the tcp "accept" processes.
+%%-----------------------------------------------------------------
+-module(megaco_tcp_accept_sup).
+
+-behaviour(supervisor).
+
+
+%%-----------------------------------------------------------------
+%% External exports
+%%-----------------------------------------------------------------
+-export([
+ start_link/0,
+ start_child/4
+ ]).
+
+%%-----------------------------------------------------------------
+%% Internal exports
+%%-----------------------------------------------------------------
+-export([
+ init/1,
+ terminate/2
+ ]).
+
+%%-----------------------------------------------------------------
+%% External interface functions
+%%-----------------------------------------------------------------
+
+%%-----------------------------------------------------------------
+%% Func: start_link/1
+%% Description: Starts the process that keeps track of the TCP
+%% accept processes
+%%-----------------------------------------------------------------
+start_link() ->
+ supervisor:start_link(?MODULE, []).
+
+
+%%-----------------------------------------------------------------
+%% Func: start_link/1
+%% Description: Starts the acceptor process (the TCP accept
+%% processes)
+%%-----------------------------------------------------------------
+start_child(Pid, Rec, Ref, Listen) ->
+ ChildSpec = [{Rec, Ref, Listen}], % Simple one-for-one
+ supervisor:start_child(Pid, ChildSpec).
+
+
+%%-----------------------------------------------------------------
+%% Server functions
+%%-----------------------------------------------------------------
+%%-----------------------------------------------------------------
+%% Func: init/1
+%% Description: Init funcion for the supervisor
+%%-----------------------------------------------------------------
+init(_Options) ->
+ SupFlags = {simple_one_for_one, 500, 100},
+ ChildSpec = [
+ {megaco_accept,
+ {megaco_tcp_accept, start_link, []},
+ temporary, 10000, worker, []}
+ ],
+ {ok, {SupFlags, ChildSpec}}.
+
+
+%%-----------------------------------------------------------------
+%% Func: terminate/2
+%% Description: Termination function for the supervisor
+%%-----------------------------------------------------------------
+terminate(_Reason, _State) ->
+ ok.
+
+%%-----------------------------------------------------------------
+%% Internal functions
+%%-----------------------------------------------------------------
+
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).
+
diff --git a/lib/megaco/src/tcp/megaco_tcp_connection_sup.erl b/lib/megaco/src/tcp/megaco_tcp_connection_sup.erl
new file mode 100644
index 0000000000..0ca8697418
--- /dev/null
+++ b/lib/megaco/src/tcp/megaco_tcp_connection_sup.erl
@@ -0,0 +1,114 @@
+%%
+%% %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: Supervisor for all active connections
+%% independent of transport protocol.
+%%-----------------------------------------------------------------
+
+-module(megaco_tcp_connection_sup).
+
+-behaviour(supervisor).
+
+%%-----------------------------------------------------------------
+%% Include files
+%%-----------------------------------------------------------------
+-include_lib("megaco/include/megaco.hrl").
+
+%%-----------------------------------------------------------------
+%% External exports
+%%-----------------------------------------------------------------
+-export([
+ start_link/0,
+ start_child/2
+ ]).
+
+
+%%-----------------------------------------------------------------
+%% Internal exports
+%%-----------------------------------------------------------------
+-export([
+ init/1,
+ terminate/2,
+ start_connection/1
+ ]).
+
+
+%%-----------------------------------------------------------------
+%% External interface functions
+%%-----------------------------------------------------------------
+%%-----------------------------------------------------------------
+%% Func: start_link
+%% Description: Starts the connection supervisor
+%%-----------------------------------------------------------------
+start_link() ->
+ supervisor:start_link(?MODULE, [[]]).
+
+
+%% -----------------------------------------------------------------
+%% Func: start_child/2
+%% DEscription: Start a child (the connection) process
+%% -----------------------------------------------------------------
+start_child(Pid, TcpRec) ->
+ supervisor:start_child(Pid, [TcpRec]).
+
+
+%%-----------------------------------------------------------------
+%% Internal interface functions
+%%-----------------------------------------------------------------
+
+%%-----------------------------------------------------------------
+%% Func: start_connection/1
+%% Description: Function which the supervisor calls to start a child
+%%-----------------------------------------------------------------
+start_connection(Args) ->
+ megaco_tcp_connection:start_link(Args).
+
+
+%%-----------------------------------------------------------------
+%% Server functions
+%%-----------------------------------------------------------------
+%%-----------------------------------------------------------------
+%% Func: init/1
+%% Description: Init funcion for the supervisor
+%%-----------------------------------------------------------------
+init(_) ->
+ SupFlags = {simple_one_for_one, 500, 100},
+ ChildSpec = [
+ {megaco_tcp_connection,
+ {?MODULE, start_connection, []},
+ temporary,
+ 10000,
+ worker,
+ []}
+ ],
+ {ok, {SupFlags, ChildSpec}}.
+
+
+%%-----------------------------------------------------------------
+%% Func: terminate/1
+%% Description: Termination function for the supervisor
+%%-----------------------------------------------------------------
+terminate(_Reason, _State) ->
+ ok.
+
+%%-----------------------------------------------------------------
+%% Internal functions
+%%-----------------------------------------------------------------
diff --git a/lib/megaco/src/tcp/megaco_tcp_sup.erl b/lib/megaco/src/tcp/megaco_tcp_sup.erl
new file mode 100644
index 0000000000..6afc7582ec
--- /dev/null
+++ b/lib/megaco/src/tcp/megaco_tcp_sup.erl
@@ -0,0 +1,145 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-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: Supervisor
+%%-----------------------------------------------------------------
+-module(megaco_tcp_sup).
+
+-behaviour(supervisor).
+
+%%-----------------------------------------------------------------
+%% Include files
+%%-----------------------------------------------------------------
+
+%%-----------------------------------------------------------------
+%% External exports
+%%-----------------------------------------------------------------
+-export([
+ start_link/0,
+ which_accept_sup/1,
+ which_connection_sup/1,
+ start_accept_child/2
+ ]).
+
+%%-----------------------------------------------------------------
+%% Internal exports
+%%-----------------------------------------------------------------
+-export([
+ init/1,
+ terminate/2
+ ]).
+
+%%-----------------------------------------------------------------
+%% External interface functions
+%%-----------------------------------------------------------------
+%%-----------------------------------------------------------------
+%% Func: start_link/1
+%% Description: Start an megaco net element supervisor
+%%-----------------------------------------------------------------
+start_link() ->
+ supervisor:start_link(?MODULE, []).
+
+
+%%-----------------------------------------------------------------
+%% Func: which_accept_sup/1
+%% Description: Get the pid() of the accept supervisor process
+%%-----------------------------------------------------------------
+which_accept_sup(Pid) ->
+ which_child(Pid, megaco_tcp_accept_sup).
+
+
+%%-----------------------------------------------------------------
+%% Func: which_connection_sup/1
+%% Description: Get the pid() of the connection supervisor process
+%%-----------------------------------------------------------------
+which_connection_sup(Pid) ->
+ which_child(Pid, megaco_tcp_connection_sup).
+
+
+%%-----------------------------------------------------------------
+%% Func: start_accept_child/1
+%% Description: Starts the process that keeps track of the TCP
+%% accept processes
+%%-----------------------------------------------------------------
+start_accept_child(SupPid, Data) ->
+ case supervisor:start_child(SupPid,
+ {megaco_tcp_accept,
+ {megaco_tcp_accept, start_link, [Data]},
+ temporary, 10000, worker,
+ [megaco_tcp_accept]}) of
+ {ok, ChildPid} ->
+ ChildPid;
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+
+%%-----------------------------------------------------------------
+%% Internal interface functions
+%%-----------------------------------------------------------------
+
+%%-----------------------------------------------------------------
+%% Server functions
+%%-----------------------------------------------------------------
+%%-----------------------------------------------------------------
+%% Func: init/1
+%% Description: Init funcion for the supervisor
+%%-----------------------------------------------------------------
+init([]) ->
+ SupFlags = {one_for_one, 5, 1000}, % Max 5 restarts in 1 second
+ ChildSpec = [sup_spec(megaco_tcp_accept_sup, []),
+ sup_spec(megaco_tcp_connection_sup,[]),
+ worker_spec(megaco_tcp, [{self(), []}], [gen_server])],
+ {ok, {SupFlags, ChildSpec}}.
+
+
+%%-----------------------------------------------------------------
+%% Func: terminate/2
+%% Description: Termination function for the supervisor
+%%-----------------------------------------------------------------
+terminate(_Reason, _State) ->
+ ok.
+
+
+%%-----------------------------------------------------------------
+%% Local functions
+%%-----------------------------------------------------------------
+
+which_child(Pid, Name) ->
+ ProcList = supervisor:which_children(Pid),
+ %% ProcList of type [{Name, Pid, Type, Modules}]
+ case lists:keysearch(Name, 1, ProcList) of
+ {value, {_Name, ChildPid, _Type, _Modules}} ->
+ {ok, ChildPid};
+ false ->
+ {error, no_such_process}
+ end.
+
+
+sup_spec(Name, Args) ->
+ {Name,
+ {Name, start_link, Args},
+ permanent, 10000, supervisor, [Name, supervisor]}.
+
+worker_spec(Name, Args, Mods) ->
+ {Name, {Name, start_link, Args},
+ permanent, 10000, worker, [Name] ++ Mods}.
+
diff --git a/lib/megaco/src/tcp/modules.mk b/lib/megaco/src/tcp/modules.mk
new file mode 100644
index 0000000000..505bd67792
--- /dev/null
+++ b/lib/megaco/src/tcp/modules.mk
@@ -0,0 +1,33 @@
+#-*-makefile-*- ; force emacs to enter makefile-mode
+
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2001-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%
+
+MODULES = \
+ megaco_tcp \
+ megaco_tcp_sup \
+ megaco_tcp_accept \
+ megaco_tcp_accept_sup \
+ megaco_tcp_connection \
+ megaco_tcp_connection_sup
+
+
+INTERNAL_HRL_FILES = \
+ megaco_tcp.hrl
+
+
+