From a907e66c93e54ffd9b4c8c84f500cd267a28ddd8 Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Mon, 27 Aug 2012 10:26:08 +0200 Subject: Maintain service_info callback data in process dictionary To be used by diameter_service in constructing service_info. --- lib/diameter/src/transport/diameter_etcp.erl | 22 ++++++-- lib/diameter/src/transport/diameter_sctp.erl | 41 ++++++++++++--- lib/diameter/src/transport/diameter_tcp.erl | 77 ++++++++++++++++++++++++---- 3 files changed, 118 insertions(+), 22 deletions(-) (limited to 'lib/diameter') diff --git a/lib/diameter/src/transport/diameter_etcp.erl b/lib/diameter/src/transport/diameter_etcp.erl index d925d62545..cd62cf34fa 100644 --- a/lib/diameter/src/transport/diameter_etcp.erl +++ b/lib/diameter/src/transport/diameter_etcp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2011. All Rights Reserved. +%% Copyright Ericsson AB 2010-2012. 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 @@ -36,7 +36,9 @@ send/2, close/1, setopts/2, - port/1]). + sockname/1, + peername/1, + getstat/1]). %% child start -export([start_link/1]). @@ -113,10 +115,20 @@ close(Pid) -> setopts(_, _) -> ok. -%% port/1 +%% sockname/1 -port(_) -> - 3868. %% We have no local port: fake it. +sockname(_) -> + {error, ?MODULE}. + +%% peername/1 + +peername(_) -> + {error, ?MODULE}. + +%% getstat/1 + +getstat(_) -> + {error, ?MODULE}. %% start_link/1 diff --git a/lib/diameter/src/transport/diameter_sctp.erl b/lib/diameter/src/transport/diameter_sctp.erl index 68b0342cd5..9a65834647 100644 --- a/lib/diameter/src/transport/diameter_sctp.erl +++ b/lib/diameter/src/transport/diameter_sctp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2011. All Rights Reserved. +%% Copyright Ericsson AB 2010-2012. 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 @@ -37,12 +37,18 @@ code_change/3, terminate/2]). +-export([info/1]). %% service_info callback + -export([ports/0, ports/1]). -include_lib("kernel/include/inet_sctp.hrl"). -include_lib("diameter/include/diameter.hrl"). +%% Keys into process dictionary. +-define(INFO_KEY, info). +-define(REF_KEY, ref). + -define(ERROR(T), erlang:error({T, ?MODULE, ?LINE})). %% The default port for a listener. @@ -133,6 +139,24 @@ start_link(T) -> infinity, diameter_lib:spawn_opts(server, [])). +%% --------------------------------------------------------------------------- +%% # info/1 +%% --------------------------------------------------------------------------- + +info({gen_sctp, Sock}) -> + lists:flatmap(fun(K) -> info(K, Sock) end, + [{socket, sockname}, + {peer, peername}, + {statistics, getstat}]). + +info({K,F}, Sock) -> + case inet:F(Sock) of + {ok, V} -> + [{K,V}]; + _ -> + [] + end. + %% --------------------------------------------------------------------------- %% # init/1 %% --------------------------------------------------------------------------- @@ -157,7 +181,7 @@ i({connect, Pid, Opts, Addrs, Ref}) -> RAs = [diameter_lib:ipaddr(A) || {raddr, A} <- As], [RP] = [P || {rport, P} <- Ps] ++ [P || P <- [?DEFAULT_PORT], [] == Ps], {LAs, Sock} = open(Addrs, Rest, 0), - putr(ref, Ref), + putr(?REF_KEY, Ref), proc_lib:init_ack({ok, self(), LAs}), erlang:monitor(process, Pid), #transport{parent = Pid, @@ -169,7 +193,7 @@ i({connect, _, _, _} = T) -> %% from old code %% An accepting transport spawned by diameter. i({accept, Pid, LPid, Sock, Ref}) when is_pid(Pid) -> - putr(ref, Ref), + putr(?REF_KEY, Ref), proc_lib:init_ack({ok, self()}), erlang:monitor(process, Pid), erlang:monitor(process, LPid), @@ -181,7 +205,7 @@ i({accept, _, _, _} = T) -> %% from old code %% An accepting transport spawned at association establishment. i({accept, Ref, LPid, Sock, Id}) -> - putr(ref, Ref), + putr(?REF_KEY, Ref), proc_lib:init_ack({ok, self()}), MRef = erlang:monitor(process, LPid), %% Wait for a signal that the transport has been started before @@ -554,10 +578,9 @@ recv({_, #sctp_assoc_change{state = comm_up, mode = {T, _}, socket = Sock} = S) -> - Ref = getr(ref), + Ref = getr(?REF_KEY), is_reference(Ref) %% started in new code - andalso - (true = diameter_reg:add_new({?MODULE, T, {Ref, {Id, Sock}}})), + andalso publish(T, Ref, Id, Sock), up(S#transport{assoc_id = Id, streams = {IS, OS}}); @@ -599,6 +622,10 @@ recv({_, #sctp_paddr_change{}}, _) -> recv({_, #sctp_pdapi_event{}}, _) -> ok. +publish(T, Ref, Id, Sock) -> + true = diameter_reg:add_new({?MODULE, T, {Ref, {Id, Sock}}}), + putr(?INFO_KEY, {gen_sctp, Sock}). %% for info/1 + %% up/1 up(#transport{parent = Pid, diff --git a/lib/diameter/src/transport/diameter_tcp.erl b/lib/diameter/src/transport/diameter_tcp.erl index 78dbda6888..597f2f14d7 100644 --- a/lib/diameter/src/transport/diameter_tcp.erl +++ b/lib/diameter/src/transport/diameter_tcp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2011. All Rights Reserved. +%% Copyright Ericsson AB 2010-2012. 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 @@ -37,11 +37,17 @@ code_change/3, terminate/2]). +-export([info/1]). %% service_info callback + -export([ports/0, ports/1]). -include_lib("diameter/include/diameter.hrl"). +%% Keys into process dictionary. +-define(INFO_KEY, info). +-define(REF_KEY, ref). + -define(ERROR(T), erlang:error({T, ?MODULE, ?LINE})). -define(DEFAULT_PORT, 3868). %% RFC 3588, ch 2.1 @@ -110,6 +116,33 @@ start_link(T) -> infinity, diameter_lib:spawn_opts(server, [])). +%% --------------------------------------------------------------------------- +%% # info/1 +%% --------------------------------------------------------------------------- + +info({Mod, Sock}) -> + lists:flatmap(fun(K) -> info(Mod, K, Sock) end, + [{socket, fun sockname/2}, + {peer, fun peername/2}, + {statistics, fun getstat/2} + | ssl_info(Mod, Sock)]). + +info(Mod, {K,F}, Sock) -> + case F(Mod, Sock) of + {ok, V} -> + [{K,V}]; + _ -> + [] + end. + +ssl_info(ssl = M, Sock) -> + [{M, ssl_info(Sock)}]; +ssl_info(_, _) -> + []. + +ssl_info(Sock) -> + [{peercert, C} || {ok, C} <- [ssl:peercert(Sock)]]. + %% --------------------------------------------------------------------------- %% # init/1 %% --------------------------------------------------------------------------- @@ -133,7 +166,7 @@ i({T, Ref, Mod, Pid, Opts, Addrs}) MPid ! {stop, self()}, %% tell the monitor to die M = if SslOpts -> ssl; true -> Mod end, setopts(M, Sock), - putr(ref, Ref), + putr(?REF_KEY, Ref), #transport{parent = Pid, module = M, socket = Sock, @@ -191,7 +224,7 @@ i(accept = T, Ref, Mod, Pid, Opts, Addrs) -> {LAddr, LSock} = listener(Ref, {Mod, Opts, Addrs}), proc_lib:init_ack({ok, self(), [LAddr]}), Sock = ok(accept(Mod, LSock)), - true = diameter_reg:add_new({?MODULE, T, {Ref, Sock}}), + publish(Mod, T, Ref, Sock), diameter_peer:up(Pid), Sock; @@ -202,10 +235,14 @@ i(connect = T, Ref, Mod, Pid, Opts, Addrs) -> RPort = get_port(RP), proc_lib:init_ack({ok, self(), [LAddr]}), Sock = ok(connect(Mod, RAddr, RPort, gen_opts(LAddr, Rest))), - true = diameter_reg:add_new({?MODULE, T, {Ref, Sock}}), + publish(Mod, T, Ref, Sock), diameter_peer:up(Pid, {RAddr, RPort}), Sock. +publish(Mod, T, Ref, Sock) -> + true = diameter_reg:add_new({?MODULE, T, {Ref, Sock}}), + putr(?INFO_KEY, {Mod, Sock}). %% for info/1 + ok({ok, T}) -> T; ok(No) -> @@ -521,7 +558,7 @@ tls_handshake(Type, true, #transport{socket = Sock, ssl = Opts} = S) -> {ok, SSock} = tls(Type, Sock, [{cb_info, ?TCP_CB(M)} | Opts]), - Ref = getr(ref), + Ref = getr(?REF_KEY), is_reference(Ref) %% started in new code andalso (true = diameter_reg:add_new({?MODULE, Type, {Ref, SSock}})), @@ -696,12 +733,32 @@ setopts(M, Sock) -> portnr(gen_tcp, Sock) -> inet:port(Sock); -portnr(ssl, Sock) -> - case ssl:sockname(Sock) of +portnr(M, Sock) -> + case M:sockname(Sock) of {ok, {_Addr, PortNr}} -> {ok, PortNr}; {error, _} = No -> No - end; -portnr(M, Sock) -> - M:port(Sock). + end. + +%% sockname/2 + +sockname(gen_tcp, Sock) -> + inet:sockname(Sock); +sockname(M, Sock) -> + M:sockname(Sock). + +%% peername/2 + +peername(gen_tcp, Sock) -> + inet:peername(Sock); +peername(M, Sock) -> + M:peername(Sock). + +%% getstat/2 + +getstat(gen_tcp, Sock) -> + inet:getstat(Sock); +getstat(M, Sock) -> + M:getstat(Sock). +%% Note that ssl:getstat/1 doesn't yet exist in R15B01. -- cgit v1.2.3