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: 25%% Interface the TPKT (TCP/IP) transport module for Megaco/H.248 26%% 27%%----------------------------------------------------------------- 28-module(megaco_tcp). 29 30-behaviour(gen_server). 31 32 33%%----------------------------------------------------------------- 34%% Include files 35%%----------------------------------------------------------------- 36-include_lib("megaco/include/megaco.hrl"). 37-include_lib("megaco/src/tcp/megaco_tcp.hrl"). 38-include_lib("megaco/src/app/megaco_internal.hrl"). 39 40 41-define(d1(F, A), ?d("~p " ++ F, [self()|A])). 42-define(d2(F), ?d1(F, [])). 43 44 45%%----------------------------------------------------------------- 46%% External exports 47%%----------------------------------------------------------------- 48-export([ 49 start_transport/0, %% Start TPKT transport service 50 stop_transport/1, %% Stop TPKT transport service 51 listen/2, %% Starts a new listener socket 52 connect/2, %% Used on client side to connect server 53 socket/1, %% Returns the inet socket 54 send_message/2, %% Used to send data on connection 55 block/1, %% Used to block the socket for incomming 56 %% messages 57 unblock/1, %% Used to unblock the node 58 close/1, %% Used on both sides to close connection 59 60 upgrade_receive_handle/2 61 ]). 62 63%% Statistics exports 64-export([ 65 get_stats/0, get_stats/1, get_stats/2, 66 reset_stats/0, reset_stats/1 67 ]). 68 69 70%%----------------------------------------------------------------- 71%% Internal exports 72%%----------------------------------------------------------------- 73-export([ 74 start_link/1, %% Start TCP/IP net server 75 init/1, %% 76 terminate/2, 77 handle_call/3, 78 handle_cast/2, 79 handle_info/2, 80 code_change/3, 81 start_connection/2 82 ]). 83 84 85%%----------------------------------------------------------------- 86%% Server state record 87%%----------------------------------------------------------------- 88-record(state, {supervisor_pid, linkdb}). 89 90 91%%----------------------------------------------------------------- 92%% External interface functions 93%%----------------------------------------------------------------- 94 95%%----------------------------------------------------------------- 96%% Func: get_stats/0, get_stats/1, get_stats/2 97%% Description: Retreive statistics (counters) for TCP 98%%----------------------------------------------------------------- 99get_stats() -> 100 megaco_stats:get_stats(megaco_tcp_stats). 101 102get_stats(Socket) -> 103 megaco_stats:get_stats(megaco_tcp_stats, Socket). 104 105get_stats(Socket, Counter) -> 106 megaco_stats:get_stats(megaco_tcp_stats, Socket, Counter). 107 108 109%%----------------------------------------------------------------- 110%% Func: reset_stats/0, reaet_stats/1 111%% Description: Reset statistics (counters) for TCP 112%%----------------------------------------------------------------- 113reset_stats() -> 114 megaco_stats:reset_stats(megaco_tcp_stats). 115 116reset_stats(Socket) -> 117 megaco_stats:reset_stats(megaco_tcp_stats, Socket). 118 119 120%%----------------------------------------------------------------- 121%% Func: start_transport/0 122%% Description: Starts the TPKT transport service 123%%----------------------------------------------------------------- 124start_transport() -> 125 ?d2("start_transport -> entry"), 126 (catch megaco_stats:init(megaco_tcp_stats)), 127 megaco_tcp_sup:start_link(). 128 129 130%%----------------------------------------------------------------- 131%% Func: stop_transport/1, 2 132%% Description: Stop the TPKT transport service 133%%----------------------------------------------------------------- 134stop_transport(Pid) -> 135 (catch unlink(Pid)), 136 stop_transport(Pid, shutdown). 137 138stop_transport(Pid, Reason) -> 139 ?d1("stop_transport -> entry with" 140 "~n Pid: ~p" 141 "~n Reason: ~p", [Pid, Reason]), 142 exit(Pid, Reason). 143 144 145%%----------------------------------------------------------------- 146%% Func: listen/2 147%% Description: Starts new TPKT listener sockets 148%%----------------------------------------------------------------- 149listen(SupPid, Parameters) -> 150 ?d1("listen -> entry with" 151 "~n SupPid: ~p" 152 "~n Parameters: ~p", [SupPid, Parameters]), 153 ProcList = supervisor:which_children(SupPid), 154 case lists:keysearch(megaco_tcp, 1, ProcList) of 155 {value, {_Name, Pid, _Type, _Modules}} -> 156 ?d1("listen -> found listener: " 157 "~n Pid: ~p", [Pid]), 158 call(Pid, {add_listener, Parameters}); 159 false -> 160 {error, no_tcp_server} 161 end. 162 163 164%%----------------------------------------------------------------- 165%% Func: connect 166%% Description: Function is used when opening an TCP socket 167%% at the MG side when trying to connect an MGC 168%%----------------------------------------------------------------- 169connect(SupPid, Parameters) -> 170 ?d1("connect -> entry with" 171 "~n SupPid: ~p" 172 "~n Parameters: ~p", [SupPid, Parameters]), 173 Mand = [host, port, receive_handle], 174 case parse_options(Parameters, #megaco_tcp{}, Mand) of 175 {ok, Rec} -> 176 177 ?d1("connect -> options parsed: " 178 "~n Rec: ~p", [Rec]), 179 180 #megaco_tcp{host = Host, 181 port = Port, 182 options = Options} = Rec, 183 184 IpOpt = [binary, {packet, tpkt}, {active, once} | Options], 185 186 %%------------------------------------------------------ 187 %% Connect the other side 188 case (catch gen_tcp:connect(Host, Port, IpOpt)) of 189 {ok, Socket} -> 190 ?d1("connect -> connected: " 191 "~n Socket: ~p", [Socket]), 192 %%---------------------------------------------- 193 %% Socket up start a new control process 194 Rec2 = Rec#megaco_tcp{socket = Socket}, 195 case start_connection(SupPid, Rec2) of 196 {ok, Pid} -> 197 ?d1("connect -> connection started: " 198 "~n Pid: ~p", [Pid]), 199 gen_tcp:controlling_process(Socket, Pid), 200 ?d2("connect -> control transferred"), 201 {ok, Socket, Pid}; 202 {error, Reason} -> 203 ?d1("connect -> failed starting connection: " 204 "~n Reason: ~p", [Reason]), 205 {error, Reason} 206 end; 207 208 {error, Reason} -> 209 ?d1("connect -> failed connecting: " 210 "~n Reason: ~p", [Reason]), 211 Error = {error, {gen_tcp_connect, Reason}}, 212 ?tcp_debug(Rec, "tcp connect failed", [Error]), 213 Error; 214 215 {'EXIT', _Reason} = Exit -> 216 ?d1("connect -> connect exited: " 217 "~n Exit: ~p", [Exit]), 218 Error = {error, {gen_tcp_connect, Exit}}, 219 ?tcp_debug(Rec, "tcp connect failed", [Error]), 220 Error 221 222 end; 223 224 {error, _Reason} = Error -> 225 ?d1("connect -> failed parsing options: " 226 "~n Error: ~p", [Error]), 227 ?tcp_debug(#megaco_tcp{}, "tcp connect failed", 228 [Error, {options, Parameters}]), 229 Error 230 end. 231 232 233%%----------------------------------------------------------------- 234%% Func: send_message 235%% Description: Function is used for sending data on the TCP socket 236%%----------------------------------------------------------------- 237send_message(Socket, Data) -> 238 ?d1("send_message -> entry with" 239 "~n Socket: ~p" 240 "~n size(Data): ~p", [Socket, sz(Data)]), 241 {Size, NewData} = add_tpkt_header(Data), 242 Res = gen_tcp:send(Socket, NewData), 243 case Res of 244 ok -> 245 incNumOutMessages(Socket), 246 incNumOutOctets(Socket, Size); 247 _ -> 248 ok 249 end, 250 Res. 251 252-ifdef(megaco_debug). 253sz(Bin) when is_binary(Bin) -> 254 size(Bin); 255sz(List) when is_list(List) -> 256 length(List). 257-endif. 258 259 260%%----------------------------------------------------------------- 261%% Func: block 262%% Description: Function is used for blocking incomming messages 263%% on the TCP socket 264%%----------------------------------------------------------------- 265block(Socket) -> 266 ?tcp_debug({socket, Socket}, "tcp block", []), 267 inet:setopts(Socket, [{active, false}]). 268 269 270%%----------------------------------------------------------------- 271%% Func: unblock 272%% Description: Function is used for blocking incomming messages 273%% on the TCP socket 274%%----------------------------------------------------------------- 275unblock(Socket) -> 276 ?tcp_debug({socket, Socket}, "tcp unblock", []), 277 inet:setopts(Socket, [{active, once}]). 278 279 280%%----------------------------------------------------------------- 281%% Func: close 282%% Description: Function is used for closing the TCP socket 283%%----------------------------------------------------------------- 284close(Socket) -> 285 ?tcp_debug({socket, Socket}, "tcp close", []), 286 gen_tcp:close(Socket). 287 288 289%%----------------------------------------------------------------- 290%% Func: socket 291%% Description: Returns the inet socket 292%%----------------------------------------------------------------- 293socket(Socket) -> 294 Socket. 295 296upgrade_receive_handle(Pid, NewHandle) 297 when is_pid(Pid) andalso is_record(NewHandle, megaco_receive_handle) -> 298 megaco_tcp_connection:upgrade_receive_handle(Pid, NewHandle). 299 300 301%%----------------------------------------------------------------- 302%% Internal Interface functions 303%%----------------------------------------------------------------- 304%%----------------------------------------------------------------- 305%% Func: start_link/1 306%% Description: Starts the net server 307%%----------------------------------------------------------------- 308start_link(Args) -> 309 gen_server:start_link(?MODULE, Args, []). 310 311 312%%----------------------------------------------------------------- 313%% Func: start_connection 314%% Description: Function is used for starting up a connection 315%% process 316%%----------------------------------------------------------------- 317start_connection(SupPid, #megaco_tcp{socket = Socket} = TcpRec) -> 318 ?d1("start_connection -> entry with" 319 "~n SupPid: ~p" 320 "~n Socket: ~p", [SupPid, Socket]), 321 322 case connection_sup(SupPid) of 323 {ok, ConnSupPid} -> 324 ?d1("start_connection -> found connection supervisor: " 325 "~n ConnSupPid: ~p", [ConnSupPid]), 326 ?tcp_debug(TcpRec, "tcp connect", []), 327 case create_connection(ConnSupPid, TcpRec) of 328 {ok, Pid} -> 329 ?d1("start_connection -> started: " 330 "~n Pid: ~p", [Pid]), 331 ?tcp_debug(TcpRec, "connect handler started", [Pid]), 332 create_snmp_counters(Socket), 333 {ok, Pid}; 334 {error, Reason} -> 335 ?d1("start_connection -> failed starting: " 336 "~n Reason: ~p", [Reason]), 337 Error = {error, {controlling_process_not_started, Reason}}, 338 ?tcp_debug(TcpRec, "tcp connect failed", [Error]), 339 Error 340 end; 341 {error, _Reason} -> 342 ?d2("start_connection -> could not find connection supervisor"), 343 Error = {error, no_connection_supervisor}, 344 ?tcp_debug(TcpRec, "tcp connect failed", [Error]), 345 Error 346 end. 347 348connection_sup(Pid) -> 349 megaco_tcp_sup:which_connection_sup(Pid). 350 351create_connection(Pid, Rec) -> 352 megaco_tcp_connection_sup:start_child(Pid, Rec). 353 354create_snmp_counters(Socket) -> 355 Counters = [medGwyGatewayNumInMessages, 356 medGwyGatewayNumInOctets, 357 medGwyGatewayNumOutMessages, 358 medGwyGatewayNumOutOctets, 359 medGwyGatewayNumErrors], 360 create_snmp_counters(Socket, Counters). 361 362create_snmp_counters(_Socket, []) -> 363 ok; 364create_snmp_counters(Socket, [Counter|Counters]) -> 365 Key = {Socket, Counter}, 366 ets:insert(megaco_tcp_stats, {Key, 0}), 367 create_snmp_counters(Socket, Counters). 368 369 370%%----------------------------------------------------------------- 371%% Server functions 372%%----------------------------------------------------------------- 373%%----------------------------------------------------------------- 374%% Func: init/1 375%% Description: Init funcion for the supervisor 376%%----------------------------------------------------------------- 377init({SupPid, _}) -> 378 process_flag(trap_exit, true), 379 {ok, #state{supervisor_pid = SupPid}}. 380 381%%----------------------------------------------------------------- 382%% Func: terminate/1 383%% Description: Termination function for the generic server 384%%----------------------------------------------------------------- 385terminate(_Reason, _State) -> 386 ok. 387 388 389%%----------------------------------------------------------------- 390%% Internal Functions 391%%----------------------------------------------------------------- 392 393%%----------------------------------------------------------------- 394%% Func: start_tcp_listener/2 395%% Description: Function which parses the list of transport layers 396%% to start 397%%----------------------------------------------------------------- 398start_tcp_listener(P, State) -> 399 ?d1("start_tcp_listener -> entry with" 400 "~n P: ~p", [P]), 401 case setup(State#state.supervisor_pid, P) of 402 {ok, Pid, Data} -> 403 ?d1("start_tcp_listener -> setup ok" 404 "~n Pid: ~p" 405 "~n Data: ~p", [Pid, Data]), 406 link(Pid), 407 {reply, ok, 408 State#state{linkdb=[{Pid, Data} | State#state.linkdb]}}; 409 {error, Reason} -> 410 ?d1("start_tcp_listener -> setup failed" 411 "~n Reason: ~p", [Reason]), 412 {reply, {error, {could_not_start_listener, Reason}}, State} 413 end. 414 415 416%%----------------------------------------------------------------- 417%% Func: handle_call/3 418%% Description: Handling call messages (really just garbage) 419%%----------------------------------------------------------------- 420handle_call({add_listener, Parameters}, _From, State) -> 421 ?d1("handle_call(add_listener) -> entry with" 422 "~n Parameters: ~p", [Parameters]), 423 start_tcp_listener(Parameters, State); 424handle_call(Req, From, State) -> 425 warning_msg("received unexpected request from ~p: " 426 "~n~w", [From, Req]), 427 {noreply, State}. 428 429 430%%------------------------------------------------------------ 431%% Func: handle_cast/2 432%% Description: Handling cast messages (really just garbage) 433%%------------------------------------------------------------ 434handle_cast(Msg, State) -> 435 warning_msg("received unexpected message: " 436 "~n~w", [Msg]), 437 {noreply, State}. 438 439 440%%----------------------------------------------------------------- 441%% Func: handle_info/2 442%% Description: Handling non call/cast messages, eg exit messages 443%%----------------------------------------------------------------- 444handle_info({'EXIT', Pid, Reason}, State) when is_pid(Pid) -> 445 %% Accept process died 446 NewState = resetup(Pid, Reason, State), 447 {noreply, NewState}; 448handle_info(Info, State) -> 449 warning_msg("received unexpected info: " 450 "~n~w", [Info]), 451 {noreply, State}. 452 453 454%%----------------------------------------------------------------- 455%% Func: code_change/3 456%% Descrition: Handles code change messages during upgrade. 457%%----------------------------------------------------------------- 458code_change(_Vsn, State, _Extra) -> 459 {ok, State}. 460 461 462%%----------------------------------------------------------------- 463%% Internal functions 464%%----------------------------------------------------------------- 465%%----------------------------------------------------------------- 466%% Func: setup/2 467%% Description: Function is used when setting up an TCP listen 468%% socket in the MGC 469%%----------------------------------------------------------------- 470setup(SupPid, Options) -> 471 ?d1("setup -> entry with" 472 "~n SupPid: ~p" 473 "~n Options: ~p", [SupPid, Options]), 474 Mand = [port, receive_handle], 475 case parse_options(Options, #megaco_tcp{}, Mand) of 476 {ok, TcpRec} -> 477 478 ?d1("setup -> options parsed" 479 "~n TcpRec: ~p", [TcpRec]), 480 481 %%------------------------------------------------------ 482 %% Setup the listen socket 483 IpOpts = [binary, {packet, tpkt}, {active, once}, 484 {reuseaddr, true} | TcpRec#megaco_tcp.options], 485 case catch gen_tcp:listen(TcpRec#megaco_tcp.port, IpOpts) of 486 {ok, Listen} -> 487 488 ?d1("setup -> listen ok" 489 "~n Listen: ~p", [Listen]), 490 491 %%----------------------------------------------- 492 %% Startup the accept process that will wait for 493 %% connect attempts 494 case start_accept(SupPid, TcpRec, Listen) of 495 {ok, Pid} -> 496 497 ?d1("setup -> accept process started" 498 "~n Pid: ~p", [Pid]), 499 500 ?tcp_debug(TcpRec, "tcp listen setup", []), 501 {ok, Pid, {TcpRec, Listen}}; 502 {error, _Reason} = Error -> 503 ?d1("setup -> failed starting accept process" 504 "~n Error: ~p", [Error]), 505 ?tcp_debug(TcpRec, "tcp listen setup failed", 506 [Error]), 507 Error 508 end; 509 {error, Reason} -> 510 ?d1("setup -> listen failed" 511 "~n Reason: ~p", [Reason]), 512 Error = {error, {gen_tcp_listen, Reason}}, 513 ?tcp_debug(TcpRec, "tcp listen setup failed", [Error]), 514 Error; 515 {'EXIT', _Reason} = Exit -> 516 ?d1("setup -> listen exited" 517 "~n Exit: ~p", [Exit]), 518 Error = {error, {gen_tcp_listen, Exit}}, 519 ?tcp_debug(TcpRec, "tcp listen setup failed", [Error]), 520 Error 521 end; 522 {error, _Reason} = Error -> 523 ?d1("setup -> failed parsing options" 524 "~n Error: ~p", [Error]), 525 ?tcp_debug(#megaco_tcp{}, "tcp listen setup failed", 526 [Error, {options, Options}]), 527 Error 528 end. 529 530 531%%----------------------------------------------------------------- 532%% Func: resetup 533%% Description: Function is used when restarting the accept process 534%% if it died for some reason. 535%%----------------------------------------------------------------- 536 537resetup(Pid, Reason, State) -> 538 ?d1("resetup -> entry with" 539 "~n Pid: ~p" 540 "~n Reason: ~p", [Pid, Reason]), 541 case lists:keysearch(Pid, 1, State#state.linkdb) of 542 {value, {Pid, {TcpRec, Listener}}} -> 543 ?d1("resetup -> found accept process: " 544 "~n TcpRec: ~p" 545 "~n Listener: ~p", [TcpRec, Listener]), 546 ?tcp_debug(TcpRec, "tcp listen resetup", [{error, Reason}]), 547 unlink(Pid), 548 warning_msg("received unexpected 'EXIT' signal " 549 "from accept process ~p: " 550 "~n~w", [Pid, Reason]), 551 case start_accept(State#state.supervisor_pid, TcpRec, Listener) of 552 {ok, NewPid} -> 553 ?d1("resetup -> start new accept process ok: " 554 "~n NewPid: ~p", [NewPid]), 555 link(NewPid), 556 NewList = lists:keyreplace(Pid, 1, State#state.linkdb, 557 {NewPid, {TcpRec, Listener}}), 558 State#state{linkdb = NewList}; 559 {error, Reason} -> 560 ?d1("resetup -> failed starting new accept process: " 561 "~n :Reason ~p", [Reason]), 562 ?tcp_debug(TcpRec, 563 "tcp listen resetup failed", [{error, Reason}]), 564 State 565 end; 566 false -> 567 warning_msg("received unexpected 'EXIT' signal from ~p: " 568 "~n~w", [Pid, Reason]), 569 State 570 end. 571 572 573%%----------------------------------------------------------------- 574%% Func: start_accept 575%% Description: Function is used for starting up an TCP accept 576%% process 577%%----------------------------------------------------------------- 578start_accept(SupPid, TcpRec, Listen) -> 579 ?d1("start_accept -> entry with" 580 "~n SupPid: ~p" 581 "~n TcpRec: ~p" 582 "~n Reason: ~p", [SupPid, TcpRec, Listen]), 583 case accept_sup(SupPid) of 584 {ok, AcceptSupPid} -> 585 ?d1("start_accept -> found accept supervisor" 586 "~n AcceptSupPid: ~p", [AcceptSupPid]), 587 case create_acceptor(AcceptSupPid, TcpRec, SupPid, Listen) of 588 {ok, Pid} -> 589 ?d1("start_accept -> accept process started" 590 "~n Pid: ~p", [Pid]), 591 {ok, Pid}; 592 {error, Reason} -> 593 ?d1("start_accept -> failed starting accept process: " 594 "~n Reason: ~p", [Reason]), 595 {error, {accept_not_started, Reason}} 596 end; 597 {error, Reason} -> 598 ?d1("start_accept -> could not find acceept supervisor: " 599 "~n Reason: ~p", [Reason]), 600 {error, {no_tcp_accept_sup, Reason}} 601 end. 602 603accept_sup(Pid) -> 604 megaco_tcp_sup:which_accept_sup(Pid). 605 606create_acceptor(Pid, Rec, TopSup, Listen) -> 607 megaco_tcp_accept_sup:start_child(Pid, Rec, TopSup, Listen). 608 609 610%%----------------------------------------------------------------- 611%% Func: add_tpkt_header 612%% Description: Function is used to add the TPKT header 613%%----------------------------------------------------------------- 614add_tpkt_header(Data) when is_binary(Data) -> 615 L = size(Data) + 4, 616 {L, [3, 0, ((L) bsr 8) band 16#ff, (L) band 16#ff ,Data]}; 617add_tpkt_header(IOList) when is_list(IOList) -> 618 Binary = list_to_binary(IOList), 619 L = size(Binary) + 4, 620 {L, [3, 0, ((L) bsr 8) band 16#ff, (L) band 16#ff , Binary]}. 621 622%%----------------------------------------------------------------- 623%% Func: parse_options 624%% Description: Function that parses the options sent to the TCP 625%% module. 626%%----------------------------------------------------------------- 627parse_options([{Tag, Val} | T], TcpRec, Mand) -> 628 ?d1("parse_options -> entry with" 629 "~n Tag: ~p" 630 "~n Val: ~p", [Tag, Val]), 631 Mand2 = Mand -- [Tag], 632 case Tag of 633 port -> 634 parse_options(T, TcpRec#megaco_tcp{port = Val}, Mand2); 635 host -> 636 parse_options(T, TcpRec#megaco_tcp{host = Val}, Mand2); 637 tcp_options when is_list(Val) -> 638 parse_options(T, TcpRec#megaco_tcp{options = Val}, Mand2); 639 receive_handle -> 640 parse_options(T, TcpRec#megaco_tcp{receive_handle = Val}, Mand2); 641 module when is_atom(Val) -> 642 parse_options(T, TcpRec#megaco_tcp{module = Val}, Mand2); 643 serialize when (Val =:= true) orelse (Val =:= false) -> 644 parse_options(T, TcpRec#megaco_tcp{serialize = Val}, Mand2); 645 Bad -> 646 ?d1("parse_options -> bad option: " 647 "~n Tag: ~p", [Tag]), 648 {error, {bad_option, Bad}} 649 end; 650parse_options([], TcpRec, []) -> 651 ?d2("parse_options -> done"), 652 {ok, TcpRec}; 653parse_options([], _TcpRec, Mand) -> 654 ?d1("parse_options -> entry with" 655 "~n Mand: ~p", [Mand]), 656 {error, {missing_options, Mand}}; 657parse_options(BadList, _TcpRec, _Mand) -> 658 ?d1("parse_options -> entry with" 659 "~n BadList: ~p", [BadList]), 660 {error, {bad_option_list, BadList}}. 661 662 663%%----------------------------------------------------------------- 664%% Func: incNumOutMessages/1, incNumOutOctets/2, incNumErrors/1 665%% Description: SNMP counter increment functions 666%% 667%%----------------------------------------------------------------- 668incNumOutMessages(Socket) -> 669 incCounter({Socket, medGwyGatewayNumOutMessages}, 1). 670 671incNumOutOctets(Socket, NumOctets) -> 672 incCounter({Socket, medGwyGatewayNumOutOctets}, NumOctets). 673 674incCounter(Key, Inc) -> 675 ets:update_counter(megaco_tcp_stats, Key, Inc). 676 677% incNumErrors(Socket) -> 678% ets:update_counter(megaco_tcp_stats, 679% {Socket, medGwyGatewayNumErrors}, 1). 680 681 682%%----------------------------------------------------------------- 683 684 685warning_msg(F, A) -> 686 ?megaco_warning("TCP server: " ++ F, A). 687 688%% error_msg(F, A) -> 689%% ?megaco_error("TCP server: " ++ F, A). 690 691 692call(Pid, Req) -> 693 gen_server:call(Pid, Req, infinity). 694