aboutsummaryrefslogtreecommitdiffstats
path: root/lib/diameter/src/app/diameter_peer.erl
diff options
context:
space:
mode:
authorAnders Svensson <[email protected]>2011-05-18 18:29:12 +0200
committerAnders Svensson <[email protected]>2011-05-18 18:29:12 +0200
commit3c15ff32e89e401b4dde2b8acc9699be2614b996 (patch)
tree184dc988fb2ab3af04a532bc59cc794a8d74fbd3 /lib/diameter/src/app/diameter_peer.erl
parentb1e768e86593178810c8a0b3c38443dcf6be5181 (diff)
downloadotp-3c15ff32e89e401b4dde2b8acc9699be2614b996.tar.gz
otp-3c15ff32e89e401b4dde2b8acc9699be2614b996.tar.bz2
otp-3c15ff32e89e401b4dde2b8acc9699be2614b996.zip
Initial commit of the diameter application.
The application provides an implementation of the Diameter protocol as defined in RFC 3588.
Diffstat (limited to 'lib/diameter/src/app/diameter_peer.erl')
-rw-r--r--lib/diameter/src/app/diameter_peer.erl230
1 files changed, 230 insertions, 0 deletions
diff --git a/lib/diameter/src/app/diameter_peer.erl b/lib/diameter/src/app/diameter_peer.erl
new file mode 100644
index 0000000000..6b8971b8ea
--- /dev/null
+++ b/lib/diameter/src/app/diameter_peer.erl
@@ -0,0 +1,230 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. 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%
+%%
+
+-module(diameter_peer).
+
+-behaviour(gen_server).
+
+%% Interface towards transport modules ...
+-export([recv/2,
+ up/1,
+ up/2]).
+
+%% ... and the stack.
+-export([start/3,
+ send/2,
+ close/1,
+ abort/1,
+ notify/2]).
+
+%% Server start.
+-export([start_link/0]).
+
+%% gen_server callbacks
+-export([init/1,
+ terminate/2,
+ handle_call/3,
+ handle_cast/2,
+ handle_info/2,
+ code_change/3]).
+
+%% debug
+-export([state/0,
+ uptime/0]).
+
+-include_lib("diameter/include/diameter.hrl").
+-include("diameter_internal.hrl").
+
+%% Registered name of the server.
+-define(SERVER, ?MODULE).
+
+%% Server state.
+-record(state, {id = now()}).
+
+%%% ---------------------------------------------------------------------------
+%%% # notify/2
+%%% ---------------------------------------------------------------------------
+
+notify(SvcName, T) ->
+ rpc:abcast(nodes(), ?SERVER, {notify, SvcName, T}).
+
+%%% ---------------------------------------------------------------------------
+%%% # start/3
+%%% ---------------------------------------------------------------------------
+
+start(T, Opts, #diameter_service{} = Svc) ->
+ {Mod, Cfg} = split_transport(Opts),
+ apply(Mod, start, [T, Svc, Cfg]).
+
+%%% ---------------------------------------------------------------------------
+%%% # up/[12]
+%%% ---------------------------------------------------------------------------
+
+up(Pid) -> %% accepting transport
+ ifc_send(Pid, {self(), connected}).
+
+up(Pid, Remote) -> %% connecting transport
+ ifc_send(Pid, {self(), connected, Remote}).
+
+%%% ---------------------------------------------------------------------------
+%%% # recv/2
+%%% ---------------------------------------------------------------------------
+
+recv(Pid, Pkt) ->
+ ifc_send(Pid, {recv, Pkt}).
+
+%%% ---------------------------------------------------------------------------
+%%% # send/2
+%%% ---------------------------------------------------------------------------
+
+send(Pid, #diameter_packet{transport_data = undefined,
+ bin = Bin}) ->
+ send(Pid, Bin);
+
+send(Pid, Pkt) ->
+ ifc_send(Pid, {send, Pkt}).
+
+%%% ---------------------------------------------------------------------------
+%%% # close/1
+%%% ---------------------------------------------------------------------------
+
+close(Pid) ->
+ ifc_send(Pid, {close, self()}).
+
+%%% ---------------------------------------------------------------------------
+%%% # abort/1
+%%% ---------------------------------------------------------------------------
+
+abort(Pid) ->
+ exit(Pid, shutdown).
+
+%% ---------------------------------------------------------------------------
+%% ---------------------------------------------------------------------------
+
+start_link() ->
+ ServerName = {local, ?SERVER},
+ Module = ?MODULE,
+ Args = [],
+ Options = [{spawn_opt, diameter_lib:spawn_opts(server, [])}],
+ gen_server:start_link(ServerName, Module, Args, Options).
+
+state() ->
+ call(state).
+
+uptime() ->
+ call(uptime).
+
+%%% ----------------------------------------------------------
+%%% # init(Role)
+%%% ----------------------------------------------------------
+
+init([]) ->
+ {ok, #state{}}.
+
+%%% ----------------------------------------------------------
+%%% # handle_call(Request, From, State)
+%%% ----------------------------------------------------------
+
+handle_call(state, _, State) ->
+ {reply, State, State};
+
+handle_call(uptime, _, #state{id = Time} = State) ->
+ {reply, diameter_lib:now_diff(Time), State};
+
+handle_call(Req, From, State) ->
+ warning_msg("received unexpected request from ~p:~n~w", [From, Req]),
+ {reply, nok, State}.
+
+%%% ----------------------------------------------------------
+%%% # handle_cast(Request, State)
+%%% ----------------------------------------------------------
+
+handle_cast(Msg, State) ->
+ warning_msg("received unexpected message:~n~w", [Msg]),
+ {noreply, State}.
+
+%%% ----------------------------------------------------------
+%%% # handle_info(Request, State)
+%%% ----------------------------------------------------------
+
+%% Remote service is distributing a message.
+handle_info({notify, SvcName, T}, S) ->
+ bang(diameter_service:whois(SvcName), T),
+ {noreply, S};
+
+handle_info(Info, State) ->
+ warning_msg("received unexpected info:~n~w", [Info]),
+ {noreply, State}.
+
+%% ----------------------------------------------------------
+%% terminate(Reason, State)
+%% ----------------------------------------------------------
+
+terminate(_Reason, _State) ->
+ ok.
+
+%% ----------------------------------------------------------
+%% code_change(OldVsn, State, Extra)
+%% ----------------------------------------------------------
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%% ---------------------------------------------------------
+%% INTERNAL FUNCTIONS
+%% ---------------------------------------------------------
+
+%% ifc_send/2
+%%
+%% Send something over the transport interface.
+
+ifc_send(Pid, T) ->
+ Pid ! {diameter, T}.
+
+%% bang/2
+
+bang(undefined = No, _) ->
+ No;
+bang(Pid, T) ->
+ Pid ! T.
+
+%% split_transport/1
+%%
+%% Split options into transport module, transport config and
+%% remaining options.
+
+split_transport(Opts) ->
+ {[M,C], _} = proplists:split(Opts, [transport_module,
+ transport_config]),
+ {value(M, diameter_tcp), value(C, [])}.
+
+value([{_,V}], _) ->
+ V;
+value([], V) ->
+ V.
+
+%% call/1
+
+call(Request) ->
+ gen_server:call(?SERVER, Request, infinity).
+
+%% warning_msg/2
+
+warning_msg(F, A) ->
+ ?diameter_warning("~p: " ++ F, [?MODULE | A]).