1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1999-2016. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20 21%% 22%%----------------------------------------------------------------- 23%% 24%% Purpose: Handles the Megaco/H.248 TCP connections. 25%% 26%%----------------------------------------------------------------- 27-module(megaco_tcp_connection). 28 29-behaviour(gen_server). 30 31 32%%----------------------------------------------------------------- 33%% Include files 34%%----------------------------------------------------------------- 35 36-include_lib("megaco/src/tcp/megaco_tcp.hrl"). 37-include_lib("megaco/src/app/megaco_internal.hrl"). 38 39 40%%----------------------------------------------------------------- 41%% External exports 42%%----------------------------------------------------------------- 43-export([ 44 start_link/1, 45 stop/1, 46 47 upgrade_receive_handle/2 48 ]). 49 50%%----------------------------------------------------------------- 51%% Internal exports 52%%----------------------------------------------------------------- 53 54-export([ 55 init/1, 56 handle_call/3, 57 handle_cast/2, 58 handle_info/2, 59 code_change/3, 60 terminate/2, 61 62 handle_received_message/5 63 ]). 64 65 66%%----------------------------------------------------------------- 67%% External interface functions 68%%----------------------------------------------------------------- 69 70%%----------------------------------------------------------------- 71%% Func: start_link/1 72%% Description: Starts the proces that keeps track of an TCP 73%% connection. 74%%----------------------------------------------------------------- 75 76start_link(Arg) -> 77 gen_server:start_link(?MODULE, Arg, []). 78 79 80stop(Pid) -> 81 call(Pid, stop). 82 83 84upgrade_receive_handle(Pid, NewHandle) -> 85 call(Pid, {upgrade_receive_handle, NewHandle}). 86 87 88%%----------------------------------------------------------------- 89%% Internal interface functions 90%%----------------------------------------------------------------- 91 92%%----------------------------------------------------------------- 93%% Server functions 94%%----------------------------------------------------------------- 95 96%%----------------------------------------------------------------- 97%% Func: init/1 98%% Description: Init funcion for the generic server 99%%----------------------------------------------------------------- 100init(Arg) -> 101 %% process_flag(trap_exit, true), 102 ?tcp_debug(Arg, "tcp connection handler starting", [self()]), 103%% info_msg("starting with" 104%% "~n Arg: ~p", [Arg]), 105 {ok, Arg}. 106 107 108%%----------------------------------------------------------------- 109%% Func: handle_call/3 110%% Description: Handling call messages (really just stop and garbage) 111%%----------------------------------------------------------------- 112handle_call(stop, _From, TcpRec) -> 113 {stop, shutdown, ok, TcpRec}; 114handle_call({upgrade_receive_handle, NewHandle}, _From, TcpRec) -> 115 {reply, ok, TcpRec#megaco_tcp{receive_handle = NewHandle}}; 116handle_call(Req, From, TcpRec) -> 117 warning_msg("received unexpected request from ~p: " 118 "~n~w", [From, Req]), 119 {reply, {error, {invalid_request, Req}}, TcpRec}. 120 121 122%%----------------------------------------------------------------- 123%% Func: handle_cast/2 124%% Description: Handling cast messages (really just stop and garbage) 125%%----------------------------------------------------------------- 126handle_cast(stop, TcpRec) -> 127 {stop, shutdown, TcpRec}; 128handle_cast(Msg, TcpRec) -> 129 warning_msg("received unexpected message: " 130 "~n~w", [Msg]), 131 {noreply, TcpRec}. 132 133%%----------------------------------------------------------------- 134%% Func: handle_info/2 135%% Description: Handling non call/cast messages. Incomming messages 136%% from the socket and exit messages. 137%%----------------------------------------------------------------- 138handle_info({tcp_closed, _Socket}, TcpRec) -> 139 {stop, shutdown, TcpRec}; 140handle_info({tcp_error, _Socket}, TcpRec) -> 141 {stop, shutdown, TcpRec}; 142handle_info({tcp, Socket, <<3:8, _X:8, Length:16, Msg/binary>>}, 143 #megaco_tcp{socket = Socket, serialize = false} = TcpRec) 144 when Length < ?GC_MSG_LIMIT -> 145 #megaco_tcp{module = Mod, receive_handle = RH} = TcpRec, 146 incNumInMessages(Socket), 147 incNumInOctets(Socket, 4+size(Msg)), 148 apply(Mod, receive_message, [RH, self(), Socket, Msg]), 149 inet:setopts(Socket, [{active, once}]), 150 {noreply, TcpRec}; 151handle_info({tcp, Socket, <<3:8, _X:8, Length:16, Msg/binary>>}, 152 #megaco_tcp{socket = Socket, serialize = false} = TcpRec) -> 153 #megaco_tcp{module = Mod, receive_handle = RH} = TcpRec, 154 incNumInMessages(Socket), 155 incNumInOctets(Socket, 4+size(Msg)), 156 receive_message(Mod, RH, Socket, Length, Msg), 157 inet:setopts(Socket, [{active, once}]), 158 {noreply, TcpRec}; 159handle_info({tcp, Socket, <<3:8, _X:8, _Length:16, Msg/binary>>}, 160 #megaco_tcp{socket = Socket, serialize = true} = TcpRec) -> 161 #megaco_tcp{module = Mod, receive_handle = RH} = TcpRec, 162 incNumInMessages(Socket), 163 incNumInOctets(Socket, 4+size(Msg)), 164 process_received_message(Mod, RH, Socket, Msg), 165 inet:setopts(Socket, [{active, once}]), 166 {noreply, TcpRec}; 167handle_info({tcp, Socket, Msg}, TcpRec) -> 168 incNumErrors(Socket), 169 error_msg("received bad tpkt packet: " 170 "~n~w", [Msg]), 171 {noreply, TcpRec}; 172handle_info(Info, TcpRec) -> 173 warning_msg("received unexpected info: " 174 "~n~p", [Info]), 175 {noreply, TcpRec}. 176 177 178process_received_message(Mod, RH, SH, Msg) -> 179 case (catch Mod:process_received_message(RH, self(), SH, Msg)) of 180 ok -> 181 ok; 182 Error -> 183 error_msg("failed processing received message: " 184 "~n~p", [Error]), 185 ok 186 end. 187 188 189receive_message(Mod, RH, SendHandle, Length, Msg) -> 190 Opts = [link , {min_heap_size, ?HEAP_SIZE(Length)}], 191 spawn_opt(?MODULE, handle_received_message, 192 [Mod, RH, self(), SendHandle, Msg], Opts), 193 ok. 194 195 196handle_received_message(Mod, RH, Parent, SH, Msg) -> 197 Mod:process_received_message(RH, Parent, SH, Msg), 198 unlink(Parent), 199 exit(normal). 200 201 202%%----------------------------------------------------------------- 203%% Func: terminate/2 204%% Description: Termination function for the generic server 205%%----------------------------------------------------------------- 206terminate(shutdown = _Reason, TcpRec) -> 207 ?tcp_debug(TcpRec, "tcp connection handler terminating", [self(),_Reason]), 208 ok; 209 210terminate(Reason, TcpRec) -> 211 ?tcp_debug(TcpRec, "tcp connection handler terminating", [self(), Reason]), 212 SchedId = erlang:system_info(scheduler_id), 213 SchedNum = erlang:system_info(schedulers), 214 ProcCount = erlang:system_info(process_count), 215 ProcLimit = erlang:system_info(process_limit), 216 ProcMemUsed = erlang:memory(processes_used), 217 ProcMemAlloc = erlang:memory(processes), 218 MemTot = erlang:memory(total), 219 error_msg("abormal termination: " 220 "~n Scheduler id: ~p" 221 "~n Num scheduler: ~p" 222 "~n Process count: ~p" 223 "~n Process limit: ~p" 224 "~n Memory used by erlang processes: ~p" 225 "~n Memory allocated by erlang processes: ~p" 226 "~n The total amount of memory allocated: ~p" 227 "~n~p", 228 [SchedId, SchedNum, ProcCount, ProcLimit, 229 ProcMemUsed, ProcMemAlloc, MemTot, Reason]), 230 ok. 231 232 233%%----------------------------------------------------------------- 234%% Func: code_change/3 235%% Descrition: Handles code change messages during upgrade. 236%%----------------------------------------------------------------- 237code_change(_OldVsn, S, _Extra) -> 238 ?d("code_change -> entry with" 239 "~n OldVsn: ~p" 240 "~n S: ~p" 241 "~n Extra: ~p", [_OldVsn, S, _Extra]), 242 {ok, S}. 243 244 245 246%%----------------------------------------------------------------- 247%% Func: incNumInMessages/1, incNumInOctets/2, incNumErrors/1 248%% Description: SNMP counter increment functions 249%% 250%%----------------------------------------------------------------- 251incNumInMessages(Socket) -> 252 incCounter({Socket, medGwyGatewayNumInMessages}, 1). 253 254incNumInOctets(Socket, NumOctets) -> 255 incCounter({Socket, medGwyGatewayNumInOctets}, NumOctets). 256 257incNumErrors(Socket) -> 258 incCounter({Socket, medGwyGatewayNumErrors}, 1). 259 260incCounter(Key, Inc) -> 261 ets:update_counter(megaco_tcp_stats, Key, Inc). 262 263 264%% info_msg(F, A) -> 265%% ?megaco_info("TCP connection handler " ++ F, A). 266 267warning_msg(F, A) -> 268 ?megaco_warning("TCP connection handler: " ++ F, A). 269 270error_msg(F, A) -> 271 ?megaco_error("TCP connection handler: " ++ F, A). 272 273 274call(Pid, Req) -> 275 gen_server:call(Pid, Req, infinity). 276 277