aboutsummaryrefslogtreecommitdiffstats
path: root/src/sccp_scrc.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/sccp_scrc.erl')
-rw-r--r--src/sccp_scrc.erl116
1 files changed, 63 insertions, 53 deletions
diff --git a/src/sccp_scrc.erl b/src/sccp_scrc.erl
index 27fd9af..53e6c08 100644
--- a/src/sccp_scrc.erl
+++ b/src/sccp_scrc.erl
@@ -69,7 +69,7 @@ terminate(Reason, _State, _LoopDat) ->
ok.
% helper function to create new SCOC instance
-spawn_new_scoc(LoopDat) ->
+spawn_new_scoc(LoopDat) when is_record(LoopDat, scrc_state) ->
% create new SCOC instance
UserPid = LoopDat#scrc_state.user_pid,
% Compute the new local reference
@@ -92,7 +92,8 @@ is_cr_or_connless(SccpMsg) when is_record(SccpMsg, sccp_msg) ->
end.
% deliver message to local SCOC or SCLC
-deliver_to_scoc_sclc(LoopDat, Msg, UserPid) when is_record(Msg, sccp_msg) ->
+deliver_to_scoc_sclc(LoopDat, Msg, UserPid) when is_record(Msg, sccp_msg),
+ is_record(LoopDat, scrc_state) ->
case Msg of
% special handling for CR message here in SCRC
#sccp_msg{msg_type = ?SCCP_MSGT_CR} ->
@@ -138,7 +139,7 @@ deliver_to_scoc_sclc(LoopDat, Msg, UserPid) when is_record(Msg, sccp_msg) ->
% N-CONNECT.req from user: spawn new SCOC and deliver primitive to it
idle(P = #primitive{subsystem = 'N', gen_name = 'CONNECT',
- spec_name = request, parameters = Params}, LoopDat) ->
+ spec_name = request}, LoopDat) ->
% Start new SCOC instance
{LoopDat1, ScocPid} = spawn_new_scoc(LoopDat),
% Deliver primitive to new SCOC instance
@@ -146,33 +147,39 @@ idle(P = #primitive{subsystem = 'N', gen_name = 'CONNECT',
{next_state, idle, LoopDat1};
% N-UNITDATA.req from user (normally this is SCLC, but we don't have SCLC)
-idle(P= #primitive{subsystem = 'N', gen_name = 'UNITDATA',
+idle(#primitive{subsystem = 'N', gen_name = 'UNITDATA',
spec_name = request, parameters = Params}, LoopDat) ->
% User needs to specify: Protocol Class, Called Party, Calling Party, Data
SccpMsg = #sccp_msg{msg_type = ?SCCP_MSGT_UDT, parameters = Params},
- case sccp_routing:route_local_out(SccpMsg) of
- {remote, SccpMsg2, LsName} ->
- % FIXME: get to MTP-TRANSFER.req
- {ok, M3} = create_mtp3_out(SccpMsg2, LsName),
- % generate a MTP-TRANSFER.req primitive to the lower layer
- send_mtp_transfer_down(LoopDat, M3, LsName),
- LoopDat1 = LoopDat;
- {local, SccpMsg2, UserPid} ->
- LoopDat1 = deliver_to_scoc_sclc(LoopDat, SccpMsg2, UserPid)
- end,
- {next_state, idle, LoopDat1};
+ LoopDat2 = send_sccp_local_out(LoopDat, SccpMsg),
+ {next_state, idle, LoopDat2};
% MTP-TRANSFER.ind from lower layer is passed into SCRC
idle(#primitive{subsystem = 'MTP', gen_name = 'TRANSFER',
- spec_name = indication, parameters = Params}, LoopDat) ->
- case sccp_routing:route_mtp3_sccp_in(Params) of
+ spec_name = indication, parameters = Mtp3}, LoopDat) ->
+ case sccp_routing:route_mtp3_sccp_in(Mtp3) of
{remote, SccpMsg2, LsName} ->
+ io:format("routed to remote?!?~n"),
{ok, M3} = create_mtp3_out(SccpMsg2, LsName),
% generate a MTP-TRANSFER.req primitive to the lower layer
- send_mtp_transfer_down(LoopDat, M3, LsName),
+ send_mtp_transfer_down(M3, LsName),
LoopDat1 = LoopDat;
{local, SccpMsg, UserPid} ->
- LoopDat1 = deliver_to_scoc_sclc(LoopDat, SccpMsg, UserPid)
+ % store the MTP3 routing label in case of CC, as SCCP
+ % needs to know it in order to send CO messages later
+ if SccpMsg#sccp_msg.msg_type == ?SCCP_MSGT_CC;
+ SccpMsg#sccp_msg.msg_type == ?SCCP_MSGT_CR ->
+ Params = SccpMsg#sccp_msg.parameters,
+ Mtp3Label = Mtp3#mtp3_msg.routing_label,
+ ParamsNew = [{mtp3_label, Mtp3Label}],
+ SccpMsg2 = SccpMsg#sccp_msg{parameters = Params ++ ParamsNew};
+ true ->
+ SccpMsg2 = SccpMsg
+ end,
+ LoopDat1 = deliver_to_scoc_sclc(LoopDat, SccpMsg2, UserPid);
+ {error, Reason} ->
+ io:format("route_mtp3_sccp_in: Error ~w~n", [Reason]),
+ LoopDat1 = LoopDat
end,
{next_state, idle, LoopDat1};
idle({sclc_scrc_connless_msg, SccpMsg}, LoopDat) ->
@@ -180,38 +187,41 @@ idle({sclc_scrc_connless_msg, SccpMsg}, LoopDat) ->
{next_state, idle, LoopDat};
% connection oriented messages like N-DATA.req from user
idle(#primitive{subsystem = 'OCRC', gen_name = 'CONNECTION-MSG',
- spec_name = request, parameters = Msg}, LoopDat) ->
- % encode the actual SCCP message
- EncMsg = sccp_codec:encode_sccp_msg(Msg),
- % FIXME: routing and create_mtp3_out()
- % generate a MTP-TRANSFER.req primitive to the lower layer
- send_mtp_transfer_down(LoopDat, EncMsg),
+ spec_name = request, parameters = [SccpMsg, Label]}, LoopDat) ->
+ % use the label to route, not the SCCP header!!
+ % according to (2) of sheet 5 SCRC state machine Q.714
+ SccpEnc = sccp_codec:encode_sccp_msg(SccpMsg),
+ M3 = #mtp3_msg{network_ind = ?MTP3_NETIND_INTERNATIONAL,
+ service_ind = ?MTP3_SERV_SCCP,
+ routing_label = Label,
+ payload = SccpEnc},
+ case ss7_routes:route_dpc(Label#mtp3_routing_label.dest_pc) of
+ {ok, LsName} ->
+ send_mtp_transfer_down(M3, LsName);
+ {error, Error} ->
+ io:format("unable to find linkset fo Dpc ~p CONNECTION-MSG~n",
+ [Label#mtp3_routing_label.dest_pc])
+ end,
{next_state, idle, LoopDat};
% SCOC has received confirmation about new incoming connection from user
idle(#primitive{subsystem = 'OCRC', gen_name = 'CONNECTION',
spec_name = confirm, parameters = Params}, LoopDat) ->
- % encode the actual SCCP message
- EncMsg = sccp_codec:encode_sccp_msgt(?SCCP_MSGT_CC, Params),
- % FIXME: routing and create_mtp3_out()
- % generate a MTP-TRANSFER.req primitive to the lower layer
- send_mtp_transfer_down(LoopDat, EncMsg),
- {next_state, idle, LoopDat};
+ SccpMsg = #sccp_msg{msg_type=?SCCP_MSGT_CC, parameters=Params},
+ LoopDat2 = send_sccp_local_out(LoopDat, SccpMsg),
+ {next_state, idle, LoopDat2};
% triggered by N-CONNECT.req from user to SCOC:
idle(#primitive{subsystem = 'OCRC', gen_name = 'CONNECTION',
spec_name = indication, parameters = Params}, LoopDat) ->
- % encode the actual SCCP message
- EncMsg = sccp_codec:encode_sccp_msgt(?SCCP_MSGT_CR, Params),
- % FIXME: routing and create_mtp3_out()
- % generate a MTP-TRANSFER.req primitive to the lower layer
- send_mtp_transfer_down(LoopDat, EncMsg),
- {next_state, idle, LoopDat}.
+ SccpMsg = #sccp_msg{msg_type=?SCCP_MSGT_CR, parameters=Params},
+ LoopDat2 = send_sccp_local_out(LoopDat, SccpMsg),
+ {next_state, idle, LoopDat2}.
-send_mtp_transfer_down(LoopDat, Mtp3) when is_record(Mtp3, mtp3_msg) ->
+send_mtp_transfer_down(Mtp3) when is_record(Mtp3, mtp3_msg) ->
ss7_links:mtp3_tx(Mtp3).
-send_mtp_transfer_down(LoopDat, Mtp3, LsName) when is_record(Mtp3, mtp3_msg) ->
+send_mtp_transfer_down(Mtp3, LsName) when is_record(Mtp3, mtp3_msg) ->
ss7_links:mtp3_tx(Mtp3, LsName).
create_mtp3_out(SccpMsg, LsName) when is_record(SccpMsg, sccp_msg) ->
@@ -242,24 +252,24 @@ create_mtp3_out(SccpMsg, LsName) when is_record(SccpMsg, sccp_msg) ->
end
end.
-% FIXME: the MTP3 code should net send a gen_serve:cast ?!?
-handle_info({'$gen_cast', P=#primitive{}}, State, LoopDat) ->
- #primitive{subsystem = 'MTP', gen_name = 'TRANSFER',
- spec_name = indication, parameters = Mtp3} = P,
- {ok, SccpMsg} = sccp_codec:parse_sccp_msg(Mtp3#mtp3_msg.payload),
- % User needs to specify: Protocol Class, Called Party, Calling Party, Data
+send_sccp_local_out(LoopDat, SccpMsg) when is_record(SccpMsg, sccp_msg) ->
case sccp_routing:route_local_out(SccpMsg) of
- {error, routing} ->
- % routing tells us local subsystem not equipped
- LoopDat1 = LoopDat;
{remote, SccpMsg2, LsName} ->
% FIXME: get to MTP-TRANSFER.req
{ok, M3} = create_mtp3_out(SccpMsg2, LsName),
% generate a MTP-TRANSFER.req primitive to the lower layer
- send_mtp_transfer_down(LoopDat, M3, LsName),
- LoopDat1 = LoopDat;
+ send_mtp_transfer_down(M3, LsName),
+ LoopDat;
{local, SccpMsg2, UserPid} ->
- LoopDat1 = deliver_to_scoc_sclc(LoopDat, SccpMsg2, UserPid)
- end,
- {next_state, idle, LoopDat1}.
+ deliver_to_scoc_sclc(LoopDat, SccpMsg2, UserPid);
+ {error, Reason} ->
+ io:format("sccp_local_out Routing Failure ~p~n", [SccpMsg]),
+ LoopDat
+ end.
+% FIXME: the MTP3 code should net send a gen_serve:cast ?!?
+handle_info({'$gen_cast', P=#primitive{}}, _State, LoopDat) ->
+ #primitive{subsystem = 'MTP', gen_name = 'TRANSFER',
+ spec_name = indication, parameters = Mtp3} = P,
+ gen_fsm:send_event(self(), P),
+ {next_state, idle, LoopDat}.