TCO: make sure transaciton IDs are always converted from binary to int

This commit is contained in:
Harald Welte 2012-01-31 20:43:17 +01:00
parent 67f6051009
commit 250b36f2d8
1 changed files with 110 additions and 107 deletions

View File

@ -179,6 +179,7 @@ behaviour_info(Other) ->
gen_server:behaviour_info(Other). gen_server:behaviour_info(Other).
-include("TCAPMessages.hrl"). -include("TCAPMessages.hrl").
%-include("TR.hrl").
-include("tcap.hrl"). -include("tcap.hrl").
-include("sccp.hrl"). -include("sccp.hrl").
@ -268,87 +269,83 @@ handle_call(Request, From, State) ->
% reference: Figure A.3/Q.774 (sheet 1 of 4) % reference: Figure A.3/Q.774 (sheet 1 of 4)
handle_cast({'N', 'UNITDATA', indication, UdataParams}, State) handle_cast({'N', 'UNITDATA', indication, UdataParams}, State)
when is_record(UdataParams, 'N-UNITDATA') -> when is_record(UdataParams, 'N-UNITDATA') ->
DecRes = 'TR':decode('TCMessage', UdataParams#'N-UNITDATA'.userData), {ok, {Tag, ActRes}} = 'TR':decode('TCMessage', UdataParams#'N-UNITDATA'.userData),
io:format("Decoded TCMessage: ~p~n", [DecRes]), PpRes = {Tag, postproc_tcmessage(ActRes)},
case DecRes of io:format("Decoded TCMessage: ~p~n", [PpRes]),
{ok, {unidirectional, TPDU}} -> case PpRes of
case 'TR':decode('Unidirectional', TPDU) of {unidirectional, Unidirectional = #'Unidirectional'{}} ->
{ok, Unidirectional} -> % Create a Dialogue Handler (DHA)
% Create a Dialogue Handler (DHA) DialogueID = new_tid(),
DialogueID = new_tid(), StartFunc = get_start(dialogue, DialogueID, State),
StartFunc = get_start(dialogue, DialogueID, State), ChildSpec = {DialogueID, StartFunc, temporary, 4000, worker, [tcap_dha_fsm]},
ChildSpec = {DialogueID, StartFunc, temporary, 4000, worker, [tcap_dha_fsm]}, {ok, DHA} = supervisor:start_child(State#state.supervisor, ChildSpec),
{ok, DHA} = supervisor:start_child(State#state.supervisor, ChildSpec), % TR-UNI indication CSL <- TSL
% TR-UNI indication CSL <- TSL UserData = #'TR-user-data'{dialoguePortion = Unidirectional#'Unidirectional'.dialoguePortion,
UserData = #'TR-user-data'{dialoguePortion = Unidirectional#'Unidirectional'.dialoguePortion, componentPortion = Unidirectional#'Unidirectional'.components},
componentPortion = Unidirectional#'Unidirectional'.components}, TrParams = #'TR-UNI'{qos =
TrParams = #'TR-UNI'{qos = destAddress = UdataParams#'N-UNITDATA'.calledAddress,
destAddress = UdataParams#'N-UNITDATA'.calledAddress, origAddress = UdataParams#'N-UNITDATA'.callingAddress,
origAddress = UdataParams#'N-UNITDATA'.callingAddress, userData = UserData},
userData = UserData}, gen_fsm:send_event(DHA, {'TR', 'UNI', indication, TrParams}),
gen_fsm:send_event(DHA, {'TR', 'UNI', indication, TrParams}), {noreply, State};
{noreply, State}; % {error, Reason} ->
{error, Reason} -> % % Discard received message
% Discard received message % % reference: Figure A.3/Q/774 (sheet 4 of 4) label (3)
% reference: Figure A.3/Q/774 (sheet 4 of 4) label (3) % error_logger:error_report(["Syntax error in received N-UNI", {error, Reason},
error_logger:error_report(["Syntax error in received N-UNI", {error, Reason}, % {caller, UdataParams#'N-UNITDATA'.callingAddress},
% {called, UdataParams#'N-UNITDATA'.calledAddress}]),
% {noreply, State}
% end;
{'begin', TPDU = #'Begin'{}} ->
% Assign local transaction ID
TransactionID = new_tid(),
StartFunc = get_start(in_transaction, TransactionID, State),
ChildSpec = {TransactionID, StartFunc, temporary, infinity, supervisor, [tcap_tsm_fsm]},
% Is TID = no TID?
% Note: The assignment of the ID above just gets the next available
% value and doesn't ensure that it is not in use (unlikely)
% or that there are enough resources available. The real
% test is in whether the start succeeds.
case supervisor:start_child(State#state.supervisor, ChildSpec) of
% FIXME: the entire mobile-termianted
% transaction handling needs to reflect tcap_transaction_sup
{ok, TSM} ->
% Created a Transaction State Machine (TSM)
TsmParams = UdataParams#'N-UNITDATA'{userData = TPDU},
% BEGIN received TSM <- TCO
gen_fsm:send_event(TSM, {'BEGIN', received, TsmParams});
_Other ->
% TID = no TID
% Build ABORT message (P-Abort Cause = Resource Limitation)
Abort = {abort, #'Abort'{dtid = TPDU#'Begin'.otid,
reason = {'p-abortCause', resourceLimitation}}},
NewTPDU = list_to_binary('TCMessage':encode('TCMessage', Abort)),
SccpParams = #'N-UNITDATA'{calledAddress = UdataParams#'N-UNITDATA'.callingAddress,
callingAddress = UdataParams#'N-UNITDATA'.calledAddress,
sequenceControl = false, returnOption = false, importance = none,
userData = NewTPDU},
% TR-UNI request TSL -> SCCP
Module = State#state.module,
Module:send_primitive({'N', 'UNITDATA', request, SccpParams}, State#state.ext_state),
error_logger:error_report(["Unable to create TSM for received N-BEGIN",
{caller, UdataParams#'N-UNITDATA'.callingAddress}, {caller, UdataParams#'N-UNITDATA'.callingAddress},
{called, UdataParams#'N-UNITDATA'.calledAddress}]), {called, UdataParams#'N-UNITDATA'.calledAddress}])
{noreply, State} end,
end; {noreply, State};
{ok, {'begin', TPDU}} -> % {error, Reason} ->
case 'TR':decode('Begin', TPDU) of
{ok, Begin} ->
% Assign local transaction ID
TransactionID = new_tid(),
StartFunc = get_start(in_transaction, TransactionID, State),
ChildSpec = {TransactionID, StartFunc, temporary, infinity, supervisor, [tcap_tsm_fsm]},
% Is TID = no TID?
% Note: The assignment of the ID above just gets the next available
% value and doesn't ensure that it is not in use (unlikely)
% or that there are enough resources available. The real
% test is in whether the start succeeds.
case supervisor:start_child(State#state.supervisor, ChildSpec) of
% FIXME: the entire mobile-termianted
% transaction handling needs to reflect tcap_transaction_sup
{ok, TSM} ->
% Created a Transaction State Machine (TSM)
TsmParams = UdataParams#'N-UNITDATA'{userData = Begin},
% BEGIN received TSM <- TCO
gen_fsm:send_event(TSM, {'BEGIN', received, TsmParams});
_Other ->
% TID = no TID
% Build ABORT message (P-Abort Cause = Resource Limitation)
Abort = {abort, #'Abort'{dtid = TPDU#'Begin'.otid,
reason = {'p-abortCause', resourceLimitation}}},
NewTPDU = list_to_binary('TCMessage':encode('TCMessage', Abort)),
SccpParams = #'N-UNITDATA'{calledAddress = UdataParams#'N-UNITDATA'.callingAddress,
callingAddress = UdataParams#'N-UNITDATA'.calledAddress,
sequenceControl = false, returnOption = false, importance = none,
userData = NewTPDU},
% TR-UNI request TSL -> SCCP
Module = State#state.module,
Module:send_primitive({'N', 'UNITDATA', request, SccpParams}, State#state.ext_state),
error_logger:error_report(["Unable to create TSM for received N-BEGIN",
{caller, UdataParams#'N-UNITDATA'.callingAddress},
{called, UdataParams#'N-UNITDATA'.calledAddress}])
end,
{noreply, State};
{error, Reason} ->
% TODO % TODO
% is OTID derivable? % % is OTID derivable?
% Build ABORT message with appropraite P-Abort Cause value % % Build ABORT message with appropraite P-Abort Cause value
% N-UNITDATA request TSL -> SCCP % % N-UNITDATA request TSL -> SCCP
% Discard received message % % Discard received message
% reference: Figure A.3/Q/774 (sheet 4 of 4) label (4) % % reference: Figure A.3/Q/774 (sheet 4 of 4) label (4)
error_logger:error_report(["Syntax error in received N-BEGIN", {error, Reason}, % error_logger:error_report(["Syntax error in received N-BEGIN", {error, Reason},
{caller, UdataParams#'N-UNITDATA'.callingAddress}, % {caller, UdataParams#'N-UNITDATA'.callingAddress},
{called, UdataParams#'N-UNITDATA'.calledAddress}]), % {called, UdataParams#'N-UNITDATA'.calledAddress}]),
{noreply, State} % {noreply, State}
end; {continue, TPDU = #'Continue'{dtid = Dtid}} ->
{ok, {continue, TPDU = #'Continue'{dtid = Dtid}}} ->
% DTID assigned? % DTID assigned?
case ets:lookup_element(tcap_transaction, decode_tid(Dtid), 2) of case ets:lookup_element(tcap_transaction, Dtid, 2) of
{error, _Reason} -> {error, _Reason} ->
error_logger:error_report(["DTID not found in received N-CONTINUE", error_logger:error_report(["DTID not found in received N-CONTINUE",
{dtid, Dtid}, {dtid, Dtid},
@ -380,9 +377,9 @@ handle_cast({'N', 'UNITDATA', indication, UdataParams}, State)
% {called, UdataParams#'N-UNITDATA'.calledAddress}]), % {called, UdataParams#'N-UNITDATA'.calledAddress}]),
% {noreply, State} % {noreply, State}
% end; % end;
{ok, {'end', TPDU = #'End'{dtid = Dtid}}} -> {'end', TPDU = #'End'{dtid = Dtid}} ->
% DTID assigned? % DTID assigned?
case ets:lookup_element(tcap_transaction, decode_tid(Dtid), 2) of case ets:lookup_element(tcap_transaction, Dtid, 2) of
{error, _Reason} -> {error, _Reason} ->
error_logger:error_report(["DTID not found in received N-END", error_logger:error_report(["DTID not found in received N-END",
{dtid, Dtid}, {dtid, Dtid},
@ -408,37 +405,35 @@ handle_cast({'N', 'UNITDATA', indication, UdataParams}, State)
% {called, UdataParams#'N-UNITDATA'.calledAddress}]), % {called, UdataParams#'N-UNITDATA'.calledAddress}]),
% {noreply, State} % {noreply, State}
% end; % end;
{ok, {abort, TPDU}} -> {abort, TPDU = #'Abort'{}} ->
case 'TR':decode('Abort', TPDU) of % DTID assigned?
{ok, Abort} -> case catch ets:lookup(tcap_transaction, TPDU#'Abort'.dtid, 2) of
% DTID assigned? {error, _Reason} ->
case catch ets:lookup(tcap_transaction, TPDU#'Abort'.dtid, 2) of error_logger:error_report(["DTID not found in received N-ABORT",
{error, _Reason} -> {dtid, TPDU#'Abort'.dtid},
error_logger:error_report(["DTID not found in received N-ABORT",
{dtid, TPDU#'Abort'.dtid},
{caller, UdataParams#'N-UNITDATA'.callingAddress},
{called, UdataParams#'N-UNITDATA'.calledAddress}]),
% Discard received message
% reference: Figure A.3/Q/774 (sheet 4 of 4) label (3)
{noreply, State};
TSM ->
TsmParams = UdataParams#'N-UNITDATA'{userData = Abort},
% Abort received TSM <- TCO
gen_fsm:send_event(TSM, {'ABORT', received, TsmParams}),
{noreply, State}
end;
{error, Reason} ->
% TODO
% DTID assigned?
% Local Abort TSM <- TCO
% Discard received message
% reference: Figure A.3/Q/774 (sheet 4 of 4) label (5)
error_logger:error_report(["Syntax error in received N-ABORT", {error, Reason},
{caller, UdataParams#'N-UNITDATA'.callingAddress}, {caller, UdataParams#'N-UNITDATA'.callingAddress},
{called, UdataParams#'N-UNITDATA'.calledAddress}]), {called, UdataParams#'N-UNITDATA'.calledAddress}]),
% Discard received message
% reference: Figure A.3/Q/774 (sheet 4 of 4) label (3)
{noreply, State};
TSM ->
TsmParams = UdataParams#'N-UNITDATA'{userData = TPDU},
% Abort received TSM <- TCO
gen_fsm:send_event(TSM, {'ABORT', received, TsmParams}),
{noreply, State} {noreply, State}
end; end;
{ok, {error, Reason}} -> % {error, Reason} ->
% TODO
% % DTID assigned?
% % Local Abort TSM <- TCO
% % Discard received message
% % reference: Figure A.3/Q/774 (sheet 4 of 4) label (5)
% error_logger:error_report(["Syntax error in received N-ABORT", {error, Reason},
% {caller, UdataParams#'N-UNITDATA'.callingAddress},
% {called, UdataParams#'N-UNITDATA'.calledAddress}]),
% {noreply, State}
% end;
{error, Reason} ->
% TODO % TODO
% Message type unknown % Message type unknown
% OTID derivable? % OTID derivable?
@ -739,3 +734,11 @@ decode_tid(Bin) when is_binary(Bin) ->
binary:decode_unsigned(Bin); binary:decode_unsigned(Bin);
decode_tid(List) when is_list(List) -> decode_tid(List) when is_list(List) ->
decode_tid(list_to_binary(List)). decode_tid(list_to_binary(List)).
postproc_tcmessage(C=#'Continue'{otid = Otid, dtid = Dtid}) ->
C#'Continue'{otid = decode_tid(Otid), dtid = decode_tid(Dtid)};
postproc_tcmessage(E=#'End'{dtid = Dtid}) ->
E#'End'{dtid = decode_tid(Dtid)};
postproc_tcmessage(B=#'Begin'{otid = Otid}) ->
B#'Begin'{otid = decode_tid(Otid)}.