159 lines
5.5 KiB
Erlang
159 lines
5.5 KiB
Erlang
% SUA behaviour call-back for sctp_core
|
|
|
|
% (C) 2011-2012 by Harald Welte <laforge@gnumonks.org>
|
|
%
|
|
% All Rights Reserved
|
|
%
|
|
% This program is free software; you can redistribute it and/or modify
|
|
% it under the terms of the GNU Affero General Public License as
|
|
% published by the Free Software Foundation; either version 3 of the
|
|
% License, or (at your option) any later version.
|
|
%
|
|
% This program is distributed in the hope that it will be useful,
|
|
% but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
% GNU General Public License for more details.
|
|
%
|
|
% You should have received a copy of the GNU Affero General Public License
|
|
% along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
%
|
|
% Additional Permission under GNU AGPL version 3 section 7:
|
|
%
|
|
% If you modify this Program, or any covered work, by linking or
|
|
% combining it with runtime libraries of Erlang/OTP as released by
|
|
% Ericsson on http://www.erlang.org (or a modified version of these
|
|
% libraries), containing parts covered by the terms of the Erlang Public
|
|
% License (http://www.erlang.org/EPLICENSE), the licensors of this
|
|
% Program grant you additional permission to convey the resulting work
|
|
% without the need to license the runtime libraries of Erlang/OTP under
|
|
% the GNU Affero General Public License. Corresponding Source for a
|
|
% non-source form of such a combination shall include the source code
|
|
% for the parts of the runtime libraries of Erlang/OTP used as well as
|
|
% that of the covered work.
|
|
|
|
-module(sctp_sua).
|
|
-author('Harald Welte <laforge@gnumonks.org>').
|
|
-behaviour(sctp_core).
|
|
|
|
-include_lib("kernel/include/inet_sctp.hrl").
|
|
-include("osmo_util.hrl").
|
|
-include("xua.hrl").
|
|
-include("sua.hrl").
|
|
-include("m3ua.hrl").
|
|
|
|
-export([init/1, terminate/3, code_change/4, handle_event/3, handle_info/3]).
|
|
|
|
-export([rx_sctp/4, mtp_xfer/2, state_change/3, prim_up/3]).
|
|
|
|
-record(sua_state, {
|
|
asp_pid
|
|
}).
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
% gen_fsm callbacks
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
init([Role]) ->
|
|
% start SUA ASP
|
|
Fun = fun(Prim, Args) -> asp_prim_to_user(Prim, Args) end,
|
|
AsPid = undefined,
|
|
{ok, Asp} = gen_fsm:start_link(xua_asp_fsm, [AsPid, sua_asp, [], Fun, [self()], self(), Role], [{debug, [trace]}]),
|
|
{ok, #sua_state{asp_pid=Asp}}.
|
|
|
|
terminate(Reason, _State, _LoopDat) ->
|
|
io:format("Terminating ~p (Reason ~p)~n", [?MODULE, Reason]),
|
|
ok.
|
|
|
|
code_change(_OldVsn, _State, LoopDat, _Extra) ->
|
|
{ok, LoopDat}.
|
|
|
|
handle_event(_Event, State, LoopDat) ->
|
|
{next_state, State, LoopDat}.
|
|
|
|
handle_info(_Info, State, LoopDat) ->
|
|
{next_state, State, LoopDat}.
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
% sctp_core callbacks
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
prim_up(#primitive{subsystem='M', gen_name = 'SCTP_ESTABLISH', spec_name = confirm}, State, LoopDat) ->
|
|
Asp = LoopDat#sua_state.asp_pid,
|
|
gen_fsm:send_event(Asp, osmo_util:make_prim('M','ASP_UP',request)),
|
|
{ignore, LoopDat};
|
|
prim_up(#primitive{subsystem='M', gen_name = 'ASP_UP', spec_name = confirm}, State, LoopDat) ->
|
|
Asp = LoopDat#sua_state.asp_pid,
|
|
gen_fsm:send_event(Asp, osmo_util:make_prim('M','ASP_ACTIVE',request)),
|
|
{ignore, LoopDat};
|
|
prim_up(Prim, State, LoopDat) ->
|
|
% default: forward all primitives to the user
|
|
{ok, Prim, LoopDat}.
|
|
|
|
|
|
% sctp_core indicates that ew have received some data...
|
|
rx_sctp(#sctp_sndrcvinfo{ppid = ?SUA_PPID}, Data, State, LoopDat) ->
|
|
Asp = LoopDat#sua_state.asp_pid,
|
|
Sua = xua_codec:parse_msg(Data),
|
|
case Sua of
|
|
#xua_msg{msg_class = ?M3UA_MSGC_MGMT,
|
|
msg_type = ?M3UA_MSGT_MGMT_NTFY} ->
|
|
Prim = osmo_util:make_prim('M','NOTIFY',indication,Sua),
|
|
{ok, Prim, LoopDat};
|
|
#xua_msg{msg_class = ?M3UA_MSGC_MGMT,
|
|
msg_type = ?M3UA_MSGT_MGMT_ERR} ->
|
|
Prim = osmo_util:make_prim('M','ERROR',indication,Sua),
|
|
{ok, Prim, LoopDat};
|
|
#xua_msg{msg_class = ?M3UA_MSGC_SSNM} ->
|
|
% FIXME
|
|
{ignore, LoopDat};
|
|
#xua_msg{msg_class = ?M3UA_MSGC_ASPSM} ->
|
|
gen_fsm:send_event(Asp, Sua),
|
|
{ignore, LoopDat};
|
|
#xua_msg{msg_class = ?M3UA_MSGC_ASPTM} ->
|
|
gen_fsm:send_event(Asp, Sua),
|
|
{ignore, LoopDat};
|
|
#xua_msg{msg_class = ?SUA_MSGC_CL} ->
|
|
Prim = sua_to_prim(Sua, LoopDat),
|
|
{ok, Prim, LoopDat};
|
|
%#xua_msg{msg_class = ?SUA_MSGC_C0} ->
|
|
_ ->
|
|
% do something with link related msgs
|
|
io:format("SUA Unknown message ~p in state ~p~n", [Sua, State]),
|
|
{ignore, State, LoopDat}
|
|
end.
|
|
|
|
% MTP-TRANSFER.req has arrived at sctp_core, encapsulate+tx it
|
|
mtp_xfer(Sua, LoopDat) when is_record(Sua, xua_msg) ->
|
|
SuaBin = xua_codec:encode_msg(Sua),
|
|
tx_sctp(1, SuaBin),
|
|
LoopDat.
|
|
|
|
state_change(_, established, LoopDat) ->
|
|
% emulate a 'start' from LSC
|
|
%gen_fsm:send_event(LoopDat#sua_state.lsc_pid, start),
|
|
LoopDat;
|
|
state_change(established, _, LoopDat) ->
|
|
%gen_fsm:send_event(LoopDat#sua_state.lsc_pid, link_failure),
|
|
LoopDat;
|
|
state_change(_, _, LoopDat) ->
|
|
LoopDat.
|
|
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
% helper functions
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
tx_sctp(Stream, Payload) when is_integer(Stream), is_binary(Payload) ->
|
|
Param = {Stream, ?SUA_PPID, Payload},
|
|
% sent to 'ourselves' (behaviour master module)
|
|
gen_fsm:send_event(self(), osmo_util:make_prim('SCTP','TRANSFER',request,Param)).
|
|
|
|
% callback fun for ASP FMS
|
|
asp_prim_to_user(Prim, [SctpPid]) ->
|
|
gen_fsm:send_event(SctpPid, Prim).
|
|
|
|
|
|
sua_to_prim(Sua, LoopDat) when is_record(Sua, xua_msg) ->
|
|
Sccp = sua_sccp_conv:sua_to_sccp(Sua),
|
|
osmo_util:make_prim('N','UNITADATA',indication, Sccp).
|