1%% This Source Code Form is subject to the terms of the Mozilla Public 2%% License, v. 2.0. If a copy of the MPL was not distributed with this 3%% file, You can obtain one at https://mozilla.org/MPL/2.0/. 4%% 5%% Copyright (c) 2007-2021 VMware, Inc. or its affiliates. All rights reserved. 6%% 7 8-module(tcp_listener). 9 10%% Represents a running TCP listener (a process that listens for inbound 11%% TCP or TLS connections). Every protocol supported typically has one 12%% or two listeners, plain TCP and (optionally) TLS, but there can 13%% be more, e.g. when multiple network interfaces are involved. 14%% 15%% A listener has 6 properties (is a tuple of 6): 16%% 17%% * IP address 18%% * Port 19%% * Node 20%% * Label (human-friendly name, e.g. AMQP 0-9-1) 21%% * Startup callback 22%% * Shutdown callback 23%% 24%% Listeners use Ranch in embedded mode to accept and "bridge" client 25%% connections with protocol entry points such as rabbit_reader. 26%% 27%% Listeners are tracked in a Mnesia table so that they can be 28%% 29%% * Shut down 30%% * Listed (e.g. in the management UI) 31%% 32%% Every tcp_listener process has callbacks that are executed on start 33%% and termination. Those must take care of listener registration 34%% among other things. 35%% 36%% Listeners are supervised by tcp_listener_sup (one supervisor per protocol). 37%% 38%% See also rabbit_networking and tcp_listener_sup. 39 40-behaviour(gen_server). 41 42-export([start_link/5]). 43 44-export([init/1, handle_call/3, handle_cast/2, handle_info/2, 45 terminate/2, code_change/3]). 46 47-record(state, {on_shutdown, label, ip, port}). 48 49%%---------------------------------------------------------------------------- 50 51-type mfargs() :: {atom(), atom(), [any()]}. 52 53-spec start_link 54 (inet:ip_address(), inet:port_number(), 55 mfargs(), mfargs(), string()) -> 56 rabbit_types:ok_pid_or_error(). 57 58start_link(IPAddress, Port, 59 OnStartup, OnShutdown, Label) -> 60 gen_server:start_link( 61 ?MODULE, {IPAddress, Port, 62 OnStartup, OnShutdown, Label}, []). 63 64%%-------------------------------------------------------------------- 65 66init({IPAddress, Port, {M, F, A}, OnShutdown, Label}) -> 67 process_flag(trap_exit, true), 68 logger:info("started ~s on ~s:~p", [Label, rabbit_misc:ntoab(IPAddress), Port]), 69 apply(M, F, A ++ [IPAddress, Port]), 70 State0 = #state{ 71 on_shutdown = OnShutdown, 72 label = Label, 73 ip = IPAddress, 74 port = Port 75 }, 76 {ok, obfuscate_state(State0)}. 77 78handle_call(_Request, _From, State) -> 79 {noreply, State}. 80 81handle_cast(_Msg, State) -> 82 {noreply, State}. 83 84handle_info(_Info, State) -> 85 {noreply, State}. 86 87terminate(_Reason, #state{on_shutdown = OnShutdown, label = Label, ip = IPAddress, port = Port}) -> 88 logger:info("stopped ~s on ~s:~p", [Label, rabbit_misc:ntoab(IPAddress), Port]), 89 try 90 OnShutdown(IPAddress, Port) 91 catch _:Error -> 92 logger:error("Failed to stop ~s on ~s:~p: ~p", 93 [Label, rabbit_misc:ntoab(IPAddress), Port, Error]) 94 end. 95 96code_change(_OldVsn, State, _Extra) -> 97 {ok, State}. 98 99obfuscate_state(#state{on_shutdown = OnShutdown} = State) -> 100 {M, F, A} = OnShutdown, 101 State#state{ 102 %% avoids arguments from being logged in case of an exception 103 on_shutdown = fun(IPAddress, Port) -> 104 apply(M, F, A ++ [IPAddress, Port]) 105 end 106 }.