% SUA behaviour call-back for sctp_core % (C) 2011-2012 by Harald Welte % % 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 . % % 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 https://www.erlang.org (or a modified version of these % libraries), containing parts covered by the terms of the Erlang Public % License (https://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 '). -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).