signerl/MAP/src/gsm/map_dsm_fsm.erl

707 lines
28 KiB
Erlang

%%% $Id: map_dsm_fsm.erl,v 1.2 2005/02/13 09:45:06 vances Exp $
%%%---------------------------------------------------------------------
%%% @copyright 2005 Motivity Telecom
%%% @author Vance Shipley <vances@motivity.ca> [http://www.motivity.ca]
%%% @end
%%%
%%% Copyright (c) 2005, Motivity Telecom
%%%
%%% All rights reserved.
%%%
%%% Redistribution and use in source and binary forms, with or without
%%% modification, are permitted provided that the following conditions
%%% are met:
%%%
%%% - Redistributions of source code must retain the above copyright
%%% notice, this list of conditions and the following disclaimer.
%%% - Redistributions in binary form must reproduce the above copyright
%%% notice, this list of conditions and the following disclaimer in
%%% the documentation and/or other materials provided with the
%%% distribution.
%%% - Neither the name of Motivity Telecom nor the names of its
%%% contributors may be used to endorse or promote products derived
%%% from this software without specific prior written permission.
%%%
%%% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
%%% "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
%%% LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
%%% A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
%%% OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
%%% SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
%%% LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
%%% DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
%%% THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
%%% (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
%%% OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
%%%
%%%---------------------------------------------------------------------
%%%
%%% @doc GSM MAP Dialogue State Machine (DSM).
%%%
%%% @reference 3GPP TS 29.02 Figure 15.6/3: Process Secure_MAP_DSM
%%%
-module(map_dsm_fsm).
-copyright('Copyright (c) 2005 Motivity Telecom Inc.').
-author('vances@motivity.ca').
-behaviour(gen_fsm).
%% behaviour modules must export this function
-export([behaviour_info/1]).
%% export the gen_fsm interface
-export([start/3, start/4, start_link/3, start_link/4,
send_event/2, sync_send_event/2, sync_send_event/3,
send_all_state_event/2, sync_send_all_state_event/2,
sync_send_all_state_event/3, reply/2, send_event_after/2,
start_timer/2, cancel_timer/1]).
%% export the gen_fsm state handler call backs
%-export([statename/2, statename/3]).
%% export the gen_fsm common call backs
-export([init/1, terminate/3, code_change/4]).
%% define what callbacks users must export
%%
%% @hidden
behaviour_info(callbacks) ->
gen_fsm:behaviour_info(callbacks);
behaviour_info(Other) ->
gen_fsm:behaviour_info(Other).
%% include record definitions for TC service primitives
-include_lib("tcap/include/tcap.hrl").
%% include record definitions for MAP service primitives
-include_lib("map/include/map.hrl").
%% StateData record definition
-record(state, {module, ext_statename, ext_statedata,
applicaton_context, requests = [],
% @reference 3GPP TS 2902 Figure 15.6/3a: Process Secure_MAP_DSM (sheet 1) DCL
secure_transport_required, components_present, ac_name_unchanged,
encapsulated_ac_name_unchanged, ac_included, ac_supported,
invoke_id_active, last_component, operation_exists,
alternative_name_exists, user_info_included, op_code}).
%%----------------------------------------------------------------------
%% The gen_fsm API functions
%%----------------------------------------------------------------------
%% @hidden
start(Module, Args, Options) ->
gen_fsm:start(?MODULE, [Module, Args], Options).
%% @hidden
start(FsmRef, Module, Args, Options) ->
gen_fsm:start(FsmRef, ?MODULE, [Module, Args], Options).
%% @hidden
start_link(Module, Args, Options) ->
gen_fsm:start_link(?MODULE, [Module, Args], Options).
%% @hidden
start_link(FsmRef, Module, Args, Options) ->
gen_fsm:start_link(FsmRef, ?MODULE, [Module, Args], Options).
%% @hidden
send_event(FsmRef, Event) ->
gen_fsm:send_event(FsmRef, Event).
%% @hidden
sync_send_event(FsmRef, Event) ->
gen_fsm:sync_send_event(FsmRef, Event).
%% @hidden
sync_send_event(FsmRef, Event, Timeout) ->
gen_fsm:sync_send_event(FsmRef, Event, Timeout).
%% @hidden
send_all_state_event(FsmRef, Event) ->
gen_fsm:send_all_state_event(FsmRef, Event).
%% @hidden
sync_send_all_state_event(FsmRef, Event) ->
gen_fsm:sync_send_all_state_event(FsmRef, Event).
%% @hidden
sync_send_all_state_event(FsmRef, Event, Timeout) ->
gen_fsm:sync_send_all_state_event(FsmRef, Event, Timeout).
%% @hidden
reply(Caller, Reply) ->
gen_fsm:reply(Caller, Reply).
%% @hidden
send_event_after(Time, Event) ->
gen_fsm:send_event_after(Time, Event).
%% @hidden
start_timer(Time, Msg) ->
gen_fsm:start_timer(Time, Msg).
%% @hidden
cancel_timer(Ref) ->
gen_fsm:cancel_timer(Ref).
%%----------------------------------------------------------------------
%% The gen_fsm call backs
%%----------------------------------------------------------------------
%% @hidden
init([Module, Args]) ->
process_flag(trap_exit, true),
% initialize user callback module
case Module:init(Args) of
{ok, ExtStateName, ExtStateData} ->
StateData = #state{module = Module, ext_statename = ExtStateName, ext_statedata = ExtStateData},
{ok, idle, StateData};
{ok, ExtStateName, ExtStateData, Timeout} ->
StateData = #state{module = Module, ext_statename = ExtStateName, ext_statedata = ExtStateData},
{ok, idle, State, Timeout};
{stop, Reason} ->
{stop, Reason};
ignore ->
ignore;
Other ->
Other
end.
%% @spec(Event, StateData) -> Result
%%
%% @doc State handler for the idle state.
%%
%% @hidden
%%
%
% @reference 3GPP TS 29.002 15.2.1 Behaviour at the initiating side
% @reference 3GPP TS 29.002 Figure 15.6/3a: Process_Secure_MAP_DSM (sheet 1)
%
idle({'MAP', 'OPEN', request, Open} = Event, StateData) ->
AC = Open#'MAP-OPEN'.application_context_name,
AC_PDU = Open#'MAP-OPEN'.specific_information,
% secure transport required? -- according to the AC and the identity of responder
case secure_transport_required(AC, AC_PDU) of
% true
true ->
% set AC: Secure_Transport
% build encapsulated AC PDU
NewStateData = build_encapsulated_ac_pdu(AC, AC_PDU),
{next_state, wait_for_user_requests, NewStateData#state{secure_transport_required = true}};
% false
false ->
% store AC and user data
NewStateData = StateData#state{application_context = AC, user_data = AC_PDU},
{next_state, wait_for_user_requests, StateData#state{secure_transport_required = false}}
end;
% @reference 3GPP TS 29.002 Figure 15.6/3j: Process_Secure_MAP_DSM (sheet 10)
idle({'TC', 'BEGIN', indication, #'TR-BEGIN'{userInfo = undefined, componentsPresent = true}}, StateData) ->
% AC included? (false)
% components present? (true)
{next_state, wait_for_init_data, StateData};
idle({'TC', 'BEGIN', indication, Begin#'TR-BEGIN'{userInfo = AC}}, StateData) ->
% AC included? (true)
% AC version = 1? (true)
% TODO: the rest of it!
{next_state, idle, StateData};
idle({'TC', 'BEGIN', indication, Parms} = Event, StateData) ->
{next_state, wait_for_load_check_result1, StateData};
% forward unrecognized events to user callback module
idle(Event, StateData) ->
Module = StateData#state.module,
ExtStateName = State#state.ext_statename,
case Module:StateName(Event, StateData#state.ext_statedata) of
{next_state, NextExtStateName, NewExtStateData} ->
NewStateData = StateData#state{ext_statename = NextExtStateName, ext_statedata = NewExtStateData},
{next_state, idle, NewStateData};
{next_state, NextExtStateName, NewExtStateData, Timeout} ->
NewStateData = StateData#state{ext_statename = NextExtStateName, ext_statedata = NewExtStateData},
{next_state, idle, NewStateData, Timeout};
{stop, Reason, NewExtStateData} ->
NewStateData = StateData#state{ext_statedata = NewExtStateData},
{stop, Reason, NewStateData};
Other ->
Other
end.
%% @spec(Event, StateData) -> Result
%%
%% @doc State handler for the wait_for_user_requests state.
%%
%% @hidden
%%
% @reference 3GPP TS 29.002 15.2.1 Behaviour at the initiating side
% @reference 3GPP TS 29.002 Figure 15.6/3b: Process_Secure_MAP_DSM (sheet 2)
wait_for_user_requests({'MAP', 'DELIMITER', request, Parms} = Event, StateData) ->
% TC_BEGIN_req_VIA_TC1
{next_state, dialogue_initiated, StateData};
wait_for_user_requests({'MAP', 'U-ABORT', request, Parms} = Event, StateData) ->
% Set_Abort_Reason: User_Specific
% Set_User_Info: MAP_User_Abort_PDU
% TC_U_ABORT_req_VIA_TC1
% secure transport required?
% true
% Note: To all active SRSSMs
% Terminated_VIA_Intern4
% false
% Note: To all active RSSMs
% Terminated_VIA_Intern2
{next_state, idle, StateData};
% any MAP specific request primitive
%wait_for_user_requests({'MAP', MapSpecificRequest, request, Parms} = Event, StateData) ->
% secure transport required?
% case StateData#state.secure_transport_required of
% true
% store request
% spawn Secure_Requesting_MAP_SSM
% Service_Invoked_VIA_Intern4
% false
% spawn Requesting_MAP_SSM
% Service_Invoked_VIA_Intern2
% {next_state, wait_for_user_requests, StateData};
% forward unrecognized events to user callback module
wait_for_user_requests(Event, StateData) ->
Module = StateData#state.module,
ExtStateName = State#state.ext_statename,
case Module:StateName(Event, StateData#state.ext_statedata) of
{next_state, NextExtStateName, NewExtStateData} ->
NewStateData = StateData#state{ext_statename = NextExtStateName, ext_statedata = NewExtStateData},
{next_state, wait_for_user_requests, NewStateData};
{next_state, NextExtStateName, NewExtStateData, Timeout} ->
NewStateData = StateData#state{ext_statename = NextExtStateName, ext_statedata = NewExtStateData},
{next_state, wait_for_user_requests, NewStateData, Timeout};
{stop, Reason, NewExtStateData} ->
NewStateData = StateData#state{ext_statedata = NewExtStateData},
{stop, Reason, NewStateData};
Other ->
Other
end.
%% @spec(Event, StateData) -> Result
%%
%% @doc State handler for the dialogue_initiated state.
%%
%% @hidden
%%
% @reference 3GPP TS 29.002 Figure 15.6/3c: Process_Secure_MAP_DSM (sheet 3)
dialogue_initiated({'TC', 'END', indication, End#'TC-END'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, idle, StateData};
dialogue_initiated({'TC', 'NOTICE', indication, Notice#'TC-NOTICE'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, idle, StateData};
% @reference 3GPP TS 29.002 Figure 15.6/3d: Process_Secure_MAP_DSM (sheet 4)
dialogue_initiated({'TC', 'P-ABORT', indication, Abort#'TC-P-ABORT'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, idle, StateData};
% @reference 3GPP TS 29.002 Figure 15.6/3e: Process_Secure_MAP_DSM (sheet 5)
dialogue_initiated({'TC', 'U-ABORT', indication, Abort#'TC-U-ABORT'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, idle, StateData};
% @reference 3GPP TS 29.002 Figure 15.6/3e: Process_Secure_MAP_DSM (sheet 5)
% @reference 3GPP TS 29.002 Figure 15.6/3f: Process_Secure_MAP_DSM (sheet 6)
% @reference 3GPP TS 29.002 Figure 15.6/3g: Process_Secure_MAP_DSM (sheet 7)
dialogue_initiated({'TC', 'U-ABORT', indication, Abort#'TC-U-ABORT'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, dialogue_initiated, StateData};
dialogue_initiated({'TC', 'L-CANCEL', indication, Cancel#'TC-L-CANCEL'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, dialogue_initiated, StateData};
% @reference 3GPP TS 29.002 Figure 15.6/3h: Process_Secure_MAP_DSM (sheet 8)
dialogue_initiated({'MAP', 'U-ABORT', request, Abort#'MAP-U-ABORT'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, idle, StateData};
dialogue_initiated({'MAP', 'CLOSE', request, Close#'MAP-CLOSE'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, idle, StateData};
% @reference 3GPP TS 29.002 Figure 15.6/3i: Process_Secure_MAP_DSM (sheet 9)
dialogue_initiated({'TC', 'CONTINUE', indication, Continue#'TC-Continue'{}} = Event, StateData) ->
% Note: the first one
% TODO: the rest!
{next_state, dialogue_established, StateData};
% forward unrecognized events to user callback module
dialogue_initiated(Event, StateData) ->
Module = StateData#state.module,
ExtStateName = State#state.ext_statename,
case Module:StateName(Event, StateData#state.ext_statedata) of
{next_state, NextExtStateName, NewExtStateData} ->
NewStateData = StateData#state{ext_statename = NextExtStateName, ext_statedata = NewExtStateData},
{next_state, dialogue_initiated, NewStateData};
{next_state, NextExtStateName, NewExtStateData, Timeout} ->
NewStateData = StateData#state{ext_statename = NextExtStateName, ext_statedata = NewExtStateData},
{next_state, dialogue_initiated, NewStateData, Timeout};
{stop, Reason, NewExtStateData} ->
NewStateData = StateData#state{ext_statedata = NewExtStateData},
{stop, Reason, NewStateData};
Other ->
Other
end.
%% @spec(Event, StateData) -> Result
%%
%% @doc State handler for the wait_for_init_data state.
%%
%% @hidden
%%
% @reference 3GPP TS 29.002 Figure 15.6/3k: Process_Secure_MAP_DSM (sheet 11)
wait_for_init_data({'TC', 'INVOKE', indication, Invoke#'TC-INVOKE'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, wait_for_load_check_result2, StateData};
wait_for_init_data({'TC', 'L-REJECT', indication, Reject#'TC-L-REJECT'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, idle, StateData};
% any other indication
wait_for_init_data({'TC', _, indication, _} = Event, StateData) ->
% TC_U_ABORT_req_VIA_TC1
{next_state, idle, StateData};
% forward unrecognized events to user callback
wait_for_init_data(Event, StateData) ->
Module = StateData#state.module,
ExtStateName = State#state.ext_statename,
case Module:StateName(Event, StateData#state.ext_statedata) of
{next_state, NextExtStateName, NewExtStateData} ->
NewStateData = StateData#state{ext_statename = NextExtStateName, ext_statedata = NewExtStateData},
{next_state, wait_for_init_data, NewStateData};
{next_state, NextExtStateName, NewExtStateData, Timeout} ->
NewStateData = StateData#state{ext_statename = NextExtStateName, ext_statedata = NewExtStateData},
{next_state, wait_for_init_data, NewStateData, Timeout};
{stop, Reason, NewExtStateData} ->
NewStateData = StateData#state{ext_statedata = NewExtStateData},
{stop, Reason, NewStateData};
Other ->
Other
end.
%% @spec(Event, StateData) -> Result
%%
%% @doc State handler for the wait_for_load_check_result2 state.
%%
%% @hidden
%%
% @reference 3GPP TS 29.002 Figure 15.6/3k: Process_Secure_MAP_DSM (sheet 11)
wait_for_load_check_result2('Load_OK', StateData) ->
% TODO: the rest!
{next_state, idle, StateData};
wait_for_load_check_result2('Overload', StateData) ->
{next_state, idle, StateData};
% any other indication
wait_for_load_check_result2({'TC', _, indication, _} = Event, StateData) ->
% TC_U_ABORT_req_VIA_TC1
{next_state, idle, StateData};
% forward unrecognized events to user callback module
wait_for_load_check_result2(Event, StateData) ->
Module = StateData#state.module,
ExtStateName = State#state.ext_statename,
case Module:StateName(Event, StateData#state.ext_statedata) of
{next_state, NextExtStateName, NewExtStateData} ->
NewStateData = StateData#state{ext_statename = NextExtStateName, ext_statedata = NewExtStateData},
{next_state, wait_for_load_check_result2, NewStateData};
{next_state, NextExtStateName, NewExtStateData, Timeout} ->
NewStateData = StateData#state{ext_statename = NextExtStateName, ext_statedata = NewExtStateData},
{next_state, wait_for_load_check_result2, NewStateData, Timeout};
{stop, Reason, NewExtStateData} ->
NewStateData = StateData#state{ext_statedata = NewExtStateData},
{stop, Reason, NewStateData};
Other ->
Other
end.
%% @spec(Event, StateData) -> Result
%%
%% @doc State handler for the wait_for_load_check_result1 state.
%%
%% @hidden
%%
% @reference 3GPP TS 29.002 Figure 15.6/3l: Process_Secure_MAP_DSM (sheet 12)
wait_for_load_check_result1('Load_OK', StateData) ->
% TODO: the rest!
{next_state, idle, StateData};
wait_for_load_check_result1('Load_OK', StateData) ->
% TODO: the rest!
{next_state, dialogue_pending, StateData};
wait_for_load_check_result1('Overload', StateData) ->
{next_state, idle, StateData};
% any other indication
wait_for_load_check_result1({'TC', _, indication, _} = Event, StateData) ->
% TC_U_ABORT_req_VIA_TC1
{next_state, idle, StateData};
% forward unrecognized events to user callback module
wait_for_load_check_result1(Event, StateData) ->
Module = StateData#state.module,
ExtStateName = State#state.ext_statename,
case Module:StateName(Event, StateData#state.ext_statedata) of
{next_state, NextExtStateName, NewExtStateData} ->
NewStateData = StateData#state{ext_statename = NextExtStateName, ext_statedata = NewExtStateData},
{next_state, wait_for_load_check_result1, NewStateData};
{next_state, NextExtStateName, NewExtStateData, Timeout} ->
NewStateData = StateData#state{ext_statename = NextExtStateName, ext_statedata = NewExtStateData},
{next_state, wait_for_load_check_result1, NewStateData, Timeout};
{stop, Reason, NewExtStateData} ->
NewStateData = StateData#state{ext_statedata = NewExtStateData},
{stop, Reason, NewStateData};
Other ->
Other
end.
%% @spec(Event, StateData) -> Result
%%
%% @doc State handler for the dialogue_pending state.
%%
%% @hidden
%%
% @reference 3GPP TS 29.002 Figure 15.6/3m: Process_Secure_MAP_DSM (sheet 13)
dialogue_pending({'MAP', 'OPEN', response, Open#'MAP-OPEN'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, dialogue_accepted, StateData};
dialogue_pending({'MAP', 'OPEN', response, Open#'MAP-OPEN'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, idle, StateData};
dialogue_pending({'MAP', 'U-ABORT', request, Abort#'MAP-U-ABORT'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, idle, StateData};
% forward unrecognized events to user callback module
dialogue_pending(Event, StateData) ->
Module = StateData#state.module,
ExtStateName = State#state.ext_statename,
case Module:StateName(Event, StateData#state.ext_statedata) of
{next_state, NextExtStateName, NewExtStateData} ->
NewStateData = StateData#state{ext_statename = NextExtStateName, ext_statedata = NewExtStateData},
{next_state, dialogue_pending, NewStateData};
{next_state, NextExtStateName, NewExtStateData, Timeout} ->
NewStateData = StateData#state{ext_statename = NextExtStateName, ext_statedata = NewExtStateData},
{next_state, dialogue_pending, NewStateData, Timeout};
{stop, Reason, NewExtStateData} ->
NewStateData = StateData#state{ext_statedata = NewExtStateData},
{stop, Reason, NewStateData};
Other ->
Other
end.
%% @spec(Event, StateData) -> Result
%%
%% @doc State handler for the dialogue_accepted state.
%%
%% @hidden
%%
% @reference 3GPP TS 29.002 Figure 15.6/3n: Process_Secure_MAP_DSM (sheet 14)
dialogue_accepted({'MAP', 'CLOSE', request, Close#'MAP-CLOSE'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, idle, StateData};
dialogue_accepted({'MAP', 'DELIMITER', request, Delimiter#'MAP-DELIMITER'{}} = Event, StateData) ->
% TC_CONTINUE_req_VIA_TC1
{next_state, dialogue_established, StateData};
% any MAP specific request primitive
dialogue_accepted({'MAP', Request, request, Parm} = Event, StateData) ->
% TODO: the rest!
{next_state, dialogue_accepted, StateData};
% any MAP specific response primitive
dialogue_accepted({'MAP', Response, response, Parm} = Event, StateData) ->
% TODO: the rest!
{next_state, dialogue_accepted, StateData};
% forward unrecognized events to user callback module
dialogue_accepted(Event, StateData) ->
Module = StateData#state.module,
ExtStateName = State#state.ext_statename,
case Module:StateName(Event, StateData#state.ext_statedata) of
{next_state, NextExtStateName, NewExtStateData} ->
NewStateData = StateData#state{ext_statename = NextExtStateName, ext_statedata = NewExtStateData},
{next_state, dialogue_accepted, NewStateData};
{next_state, NextExtStateName, NewExtStateData, Timeout} ->
NewStateData = StateData#state{ext_statename = NextExtStateName, ext_statedata = NewExtStateData},
{next_state, dialogue_accepted, NewStateData, Timeout};
{stop, Reason, NewExtStateData} ->
NewStateData = StateData#state{ext_statedata = NewExtStateData},
{stop, Reason, NewStateData};
Other ->
Other
end.
%% @spec(Event, StateData) -> Result
%%
%% @doc State handler for the dialogue_established state.
%%
%% @hidden
%%
% @reference 3GPP TS 29.002 Figure 15.6/3o: Process_Secure_MAP_DSM (sheet 15)
dialogue_established({'TC', 'L-CANCEL', indication, Cancel#'TC-L-CANCEL'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, dialogue_established, StateData};
dialogue_established({'TC', 'NOTICE', indication, Notice#'TC-NOTICE'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, dialogue_established, StateData};
dialogue_established({'TC', 'CONTINUE', indication, Continue#'TC-CONTINUE'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, dialogue_established, StateData};
dialogue_established({'MAP', 'DELIMITER', request, Delimiter#'MAP-DELIMITER'{}} = Event, StateData) ->
% TC_CONTINUE_req_VIA_TC1
{next_state, dialogue_established, StateData};
% @reference 3GPP TS 29.002 Figure 15.6/3p: Process_Secure_MAP_DSM (sheet 16)
dialogue_established({'TC', 'END', indication, End#'TC-END'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, idle, StateData};
dialogue_established({'MAP', 'CLOSE', request, Close#'MAP-CLOSE'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, dialogue_established, StateData};
% @reference 3GPP TS 29.002 Figure 15.6/3q: Process_Secure_MAP_DSM (sheet 17)
dialogue_established({'TC', 'U-ABORT', indication, Abort#'TC-U-ABORT'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, idle, StateData};
dialogue_established({'TC', 'P-ABORT', indication, Abort#'TC-P-ABORT'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, idle, StateData};
dialogue_established({'TC', 'U-ABORT', request, Abort#'TC-U-ABORT'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, idle, StateData};
% @reference 3GPP TS 29.002 Figure 15.6/3o: Process_Secure_MAP_DSM (sheet 15)
% any MAP specific request primitive
dialogue_established({'MAP', Request, request, Parm} = Event, StateData) ->
% TODO: the rest!
{next_state, dialogue_established, StateData};
% any MAP specific response primitive
dialogue_established({'MAP', Response, response, Parm} = Event, StateData) ->
% TODO: the rest!
{next_state, dialogue_established, StateData};
% forward unrecognized events to user callback module
dialogue_established(Event, StateData) ->
Module = StateData#state.module,
ExtStateName = State#state.ext_statename,
case Module:StateName(Event, StateData#state.ext_statedata) of
{next_state, NextExtStateName, NewExtStateData} ->
NewStateData = StateData#state{ext_statename = NextExtStateName, ext_statedata = NewExtStateData},
{next_state, dialogue_established, NewStateData};
{next_state, NextExtStateName, NewExtStateData, Timeout} ->
NewStateData = StateData#state{ext_statename = NextExtStateName, ext_statedata = NewExtStateData},
{next_state, dialogue_established, NewStateData, Timeout};
{stop, Reason, NewExtStateData} ->
NewStateData = StateData#state{ext_statedata = NewExtStateData},
{stop, Reason, NewStateData};
Other ->
Other
end.
%% @spec(Event, StateData) -> Result
%%
%% @doc State handler for the wait_for_components state.
%%
%% @hidden
%%
% @reference 3GPP TS 29.002 Figure 15.6/4a: Procedure Process_Components (sheet 1)
% @reference 3GPP TS 29.002 Figure 15.6/4b: Procedure Process_Components (sheet 2)
wait_for_components({'TC', 'INVOKE', indication, Invoke#'TC-INVOKE'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, wait_for_components, StateData};
% @reference 3GPP TS 29.002 Figure 15.6/4c: Procedure Process_Components (sheet 3)
wait_for_components({'TC', 'RESULT-L', indication, Result#'TC-RESULT-L'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, wait_for_components, StateData};
wait_for_components({'TC', 'RESULT-NL', indication, Result#'TC-RESULT-NL'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, wait_for_components, StateData};
wait_for_components({'TC', 'U-ERROR', indication, Error#'TC-U-ERROR'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, wait_for_components, StateData};
% @reference 3GPP TS 29.002 Figure 15.6/4d: Procedure Process_Components (sheet 4)
wait_for_components({'TC', 'L-REJECT', indication, Reject#'TC-L-REJECT'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, wait_for_components, StateData};
wait_for_components({'TC', 'R-REJECT', indication, Reject#'TC-R-REJECT'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, wait_for_components, StateData};
% @reference 3GPP TS 29.002 Figure 15.6/4e: Procedure Process_Components (sheet 5)
wait_for_components({'TC', 'U-REJECT', indication, Reject#'TC-U-REJECT'{}} = Event, StateData) ->
% TODO: the rest!
{next_state, wait_for_components, StateData};
% forward unrecognized events to user callback module
wait_for_components(Event, StateData) ->
Module = StateData#state.module,
ExtStateName = State#state.ext_statename,
case Module:StateName(Event, StateData#state.ext_statedata) of
{next_state, NextExtStateName, NewExtStateData} ->
NewStateData = StateData#state{ext_statename = NextExtStateName, ext_statedata = NewExtStateData},
{next_state, wait_for_components, NewStateData};
{next_state, NextExtStateName, NewExtStateData, Timeout} ->
NewStateData = StateData#state{ext_statename = NextExtStateName, ext_statedata = NewExtStateData},
{next_state, wait_for_components, NewStateData, Timeout};
{stop, Reason, NewExtStateData} ->
NewStateData = StateData#state{ext_statedata = NewExtStateData},
{stop, Reason, NewStateData};
Other ->
Other
end.
%% @hidden
% accept TC service primitives sent with ! or erlang:send/2,3
handle_info({'TC', _Primitive, indication, _Parms} = Info, StateName, StateData) ->
?MODULE:StateName(Info, StateData);
% forward unrecognized info to user callback module
handle_info(Event, Statename, StateData) ->
Module = StateData#state.module,
ExtStateName = StateData#state.ext_statename,
ExtStateData = StateData#state.ext_statedata,
case Module:handle_info(Event, ExtStateName, StateData#state.ext_statedata) of
{next_state, NextExtStateName, NewExtStateData} ->
NewStateData = StateData#state{ext_statename = NextExtStateName, ext_statedata = NewExtStateData},
{next_state, StateName, NewStateData};
{next_state, NextExtStateName, NewExtStateData, Timeout} ->
NewStateData = StateData#state{ext_statename = NextExtStateName, ext_statedata = NewExtStateData},
{next_state, StateName, NewStateData, Timeout};
{stop, Reason, NewExtStateData} ->
NewStateData = StateData#state{ext_statedata = NewExtStateData},
{stop, Reason, NewStateData};
Other ->
Other
end.
%% @hidden
terminate(Reason, StateName, StateData) ->
Module = StateData#state.module,
ExtStateName = StateData#state.ext_statename,
ExtStateData = StateData#state.ext_statedata,
Module:terminate(Reason, ExtStateName, ExtStateData).
%% @hidden
code_change(OldVersion, StateName, StateData, Extra) ->
Module = StateData#state.module,
ExtStateName = StateData#state.ext_statename,
ExtStateData = StateData#state.ext_statedata,
case Module:code_change(OldVersion, ExtStateName, ExtStateData, Extra) of
{ok, NextExtStateName, NewExtStateData} ->
NewStateData = StateData#state{ext_statename = NextExtStateName, ext_statedata = NewExtStateData},
{ok, StateName, NewStateData};
Other ->
Other
end.
%%----------------------------------------------------------------------
%% internal functions
%%----------------------------------------------------------------------
%% @spec(Parms, StateData) -> boolean()
%%
%% @doc Check whether secure transport is required.
%%
%% @reference 3GPP TS 29.002 15.2.1 Behaviour at the initiating side
%% @reference 3GPP TS 33.200
%%
%% @hidden
%%
secure_transport_required(Parms, #state{application_context = 'secureTransportHandlingContext-v3'}) ->
true;
secure_transport_required(Parms, #state{}) ->
false;
%% @spec(StateData) -> NewStateData
%%
%% @doc Build an encapsulted AC PDU.
%%
%% @reference 3GPP TS 29.002 15.2.1 Behaviour at the initiating side
%% @reference 3GPP TS 33.200
%%
%% @hidden
%%
build_encapsulated_ac_pdu(StateData) ->
% TODO: Build an encapsulted AC PDU.
StateData.