diff options
author | Harald Welte <laforge@gnumonks.org> | 2012-01-23 23:18:28 +0100 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2012-01-23 23:18:28 +0100 |
commit | 5cde762bd9bd6b336091a88e26aa0721d6cd6203 (patch) | |
tree | 1b70d53391ddedaa20f18eaae22a3c36c09a7230 | |
parent | 0bd3528871b56ab990687b3ea999a89283570a85 (diff) |
Integration between IPA protocol and ss7_links code to permit SCCP over IPA
-rw-r--r-- | src/ipa_proto.erl | 14 | ||||
-rw-r--r-- | src/osmo_ss7_sup.erl | 5 | ||||
-rw-r--r-- | src/ss7_link_ipa_client.erl | 107 |
3 files changed, 53 insertions, 73 deletions
diff --git a/src/ipa_proto.erl b/src/ipa_proto.erl index ebefe15..d4e9d96 100644 --- a/src/ipa_proto.erl +++ b/src/ipa_proto.erl @@ -147,8 +147,8 @@ send_close_signal([]) -> ok; send_close_signal([StreamSpec|Tail]) -> io:format("FIXME: send_close_signal ~p ~p~n", [StreamSpec, Tail]), - %[{{Socket, StreamID, Pid}}] = StreamSpec, - %Pid ! {ipa_closed, {Socket, StreamID}}, + [{{Socket, StreamID, Pid}}] = StreamSpec, + Pid ! {ipa_closed, {Socket, StreamID}}, send_close_signal(Tail). process_tcp_closed(S, StreamMap) -> @@ -222,9 +222,9 @@ process_ccm_msg(Socket, StreamID, ?IPAC_MSGT_PING, _) -> io:format("Socket ~p Stream ~p: PING -> PONG~n", [Socket, StreamID]), send(Socket, StreamID, <<?IPAC_MSGT_PONG>>); % Simply respond to ID_ACK with ID_ACK -process_ccm_msg(_Socket, _StreamID, ?IPAC_MSGT_ID_ACK, _) -> -% send(Socket, StreamID, <<?IPAC_MSGT_ID_ACK>>); - ok; +process_ccm_msg(Socket, StreamID, ?IPAC_MSGT_ID_ACK, _) -> + io:format("Socket ~p Stream ~p: ID_ACK -> ID_ACK~n", [Socket, StreamID]), + send(Socket, StreamID, <<?IPAC_MSGT_ID_ACK>>); % Simply respond to ID_RESP with ID_ACK process_ccm_msg(Socket, StreamID, ?IPAC_MSGT_ID_RESP, _) -> io:format("Socket ~p Stream ~p: ID_RESP -> ID_ACK~n", [Socket, StreamID]), @@ -265,8 +265,8 @@ connect(Address, Port, Options, Timeout) -> case gen_tcp:connect(Address, Port, ?IPA_SOCKOPTS ++ Options, Timeout) of {ok, Socket} -> case ipa_proto:register_socket(Socket) of - {ok, _} -> - {ok, Socket}; + {ok, IpaPid} -> + {ok, {Socket, IpaPid}}; {error, Reason} -> gen_tcp:close(Socket), {error, Reason} diff --git a/src/osmo_ss7_sup.erl b/src/osmo_ss7_sup.erl index ed31cb5..8daa7b6 100644 --- a/src/osmo_ss7_sup.erl +++ b/src/osmo_ss7_sup.erl @@ -42,6 +42,11 @@ add_mtp_link(L=#sigtran_link{type = m3ua, name = Name, ChildSpec = {ChildName, {ss7_link_m3ua, start_link, [L]}, permanent, 2000, worker, [ss7_link_m3ua]}, supervisor:start_child(?MODULE, ChildSpec); +add_mtp_link(L=#sigtran_link{type = ipa_client, name = Name}) -> + ChildName = list_to_atom("ss7_link_ipa_client_" ++ Name), + ChildSpec = {ChildName, {ss7_link_ipa_client, start_link, [L]}, + permanent, 2000, worker, [ss7_link_ipa_client]}, + supervisor:start_child(?MODULE, ChildSpec); add_mtp_link([]) -> ok; add_mtp_link([Head|Tail]) -> diff --git a/src/ss7_link_ipa_client.erl b/src/ss7_link_ipa_client.erl index 0bd1598..d77cc92 100644 --- a/src/ss7_link_ipa_client.erl +++ b/src/ss7_link_ipa_client.erl @@ -1,4 +1,4 @@ -% Osmocom adaptor to interface the IPA core with osmo_sccp +% Osmocom adaptor to interface the IPA core with osmo_ss7 % (C) 2011 by Harald Welte <laforge@gnumonks.org> % @@ -25,13 +25,15 @@ %-include_lib("osmo_ss7/include/ipa.hrl"). -include_lib("osmo_ss7/include/sccp.hrl"). -include_lib("osmo_ss7/include/osmo_ss7.hrl"). +-include_lib("osmo_ss7/include/mtp3.hrl"). -export([start_link/1, init/1]). --export([handle_cast/2]). +-export([handle_cast/2, handle_info/2]). -record(loop_dat, { ipa_pid, + socket, link }). @@ -39,70 +41,43 @@ start_link(Args) -> gen_server:start_link(?MODULE, Args, []). init(L = #sigtran_link{type = ipa_client, name = Name, linkset_name = LinksetName, - sls = Sls, local = Local, remote = Remote}) -> + sls = Sls}) -> + % start the IPA link to the SG + ok = ss7_links:register_link(LinksetName, Sls, Name), + {ok, LoopDat2} = reconnect(#loop_dat{link = L}), + {ok, LoopDat2}. + +handle_info({ipa_closed, {_Sock, _Stream}}, LoopDat) -> + set_link_state(LoopDat, down), + {ok, LoopDat2} = reconnect(LoopDat), + {no_reply, LoopDat2}. + +handle_cast(#primitive{subsystem='MTP', gen_name='TRANSFER', spec_name=request, + parameters = #mtp3_msg{service_ind = ?MTP3_SERV_SCCP, + payload = Data}}, LoopDat) -> + #loop_dat{socket = Socket, ipa_pid = Pid} = LoopDat, + Pid ! {ipa_send, Socket, 253, Data}, + {no_reply, LoopDat}. + +reconnect(LoopDat = #loop_dat{link=Link}) -> + #sigtran_link{local = Local, remote = Remote} = Link, #sigtran_peer{ip = LocalIp, port = LocalPort} = Local, #sigtran_peer{ip = RemoteIp, port = RemotePort} = Remote, - % start the IPA link to the SG - Opts = [{user_pid, self()}, {sctp_remote_ip, RemoteIp}, - {sctp_remote_port, RemotePort}, {sctp_local_port, LocalPort}, - {user_fun, fun ipa_tx_to_user/2}, {user_args, self()}], - {ok, IpaPid} = ipa_core:start_link(Opts), - % FIXME: register this link with SCCP_SCRC - ok = ss7_link:register_link(LinksetName, Sls, Name), - {ok, #loop_dat{ipa_pid = IpaPid, link = L}}. - -% % instantiate SCCP routing instance -% {ok, ScrcPid} = sccp_scrc:start_link([{mtp_tx_action, {callback_fn, fun scrc_tx_to_mtp/2, M3uaPid}}]), -% loop(#loop_dat{ipa_pid = M3uaPid, scrc_pid = ScrcPid}). - - -set_link_state(#sigtran_link{linkset_name = LinksetName, sls = Sls}, State) -> - ok = ss7_links:set_link_state(LinksetName, Sls, State). - -scrc_tx_to_mtp(Prim, Args) -> - M3uaPid = Args, - gen_fsm:send_event(M3uaPid, Prim). - -% Callback that we pass to the ipa_core, which it will call when it wants to + case ipa_proto:connect(RemoteIp, RemotePort, [], 10000) of + {ok, {Socket, IpaPid}} -> + set_link_state(LoopDat, up), + ipa_proto:register_stream(Socket, 253, {callback_fn, fun ipa_tx_to_sccp/4, []}), + ipa_proto:unblock(Socket), + {ok, LoopDat#loop_dat{ipa_pid=IpaPid, socket=Socket}}; + {error, Reason} -> + io:format("Reconnecting TCP (~w)~n", [Reason]), + reconnect(LoopDat) + end. + +set_link_state(#loop_dat{link = #sigtran_link{linkset_name = LinksetName, sls = Sls}}, State) -> + ss7_links:set_link_state(LinksetName, Sls, State). + +% Callback that we pass to the ipa_proto, which it will call when it wants to % send a primitive up the stack to SCCP -ipa_tx_to_user(Prim, Args) -> - UserPid = Args, - gen_server:cast(UserPid, Prim). - -% This is what we receive from ipa_tx_to_user/2 -handle_cast(#primitive{subsystem = 'M', gen_name = 'SCTP_ESTABLISH', spec_name = confirm}, L) -> - io:format("~p: SCTP_ESTABLISH.ind -> ASP_UP.req~n", [?MODULE]), - gen_fsm:send_event(L#loop_dat.ipa_pid, osmo_util:make_prim('M','ASP_UP',request)), - {noreply, L}; -handle_cast(#primitive{subsystem = 'M', gen_name = 'ASP_UP', spec_name = confirm}, L) -> - io:format("~p: ASP_UP.ind -> ASP_ACTIVE.req~n", [?MODULE]), - set_link_state(L#loop_dat.link, up), - gen_fsm:send_event(L#loop_dat.ipa_pid, osmo_util:make_prim('M','ASP_ACTIVE',request)), - {noreply, L}; -handle_cast(#primitive{subsystem = 'M', gen_name = 'ASP_ACTIVE', spec_name = confirm}, L) -> - io:format("~p: ASP_ACTIVE.ind - M3UA now active and ready~n", [?MODULE]), - set_link_state(L#loop_dat.link, active), - %tx_sccp_udt(L#loop_dat.scrc_pid), - {noreply, L}; -handle_cast(#primitive{subsystem = 'M', gen_name = 'ASP_DOWN'}, L) -> - io:format("~p: ASP_DOWN.ind~n", [?MODULE]), - set_link_state(L, down), - {noreply, L}; -handle_cast(#primitive{subsystem = 'M', gen_name = 'ASP_INACTIVE'}, L) -> - io:format("~p: ASP_DOWN.ind~n", [?MODULE]), - set_link_state(L, inactive), - {noreply, L}; -handle_cast(P, L) -> - io:format("~p: Ignoring M3UA prim ~p~n", [?MODULE, P]), - {noreply, L}. - - -tx_sccp_udt(ScrcPid) -> - CallingP = #sccp_addr{ssn = ?SCCP_SSN_MSC, point_code = osmo_util:pointcode2int(itu, {1,2,2})}, - CalledP = #sccp_addr{ssn = ?SCCP_SSN_HLR, point_code = osmo_util:pointcode2int(itu, {1,1,1})}, - Data = <<1,2,3,4>>, - Opts = [{protocol_class, 0}, {called_party_addr, CalledP}, - {calling_party_addr, CallingP}, {user_data, Data}], - io:format("~p: Sending N-UNITDATA.req to SCRC~n", [?MODULE]), - gen_fsm:send_event(ScrcPid, osmo_util:make_prim('N','UNITDATA',request,Opts)). - +ipa_tx_to_sccp(_Socket, 253, Data, _Args) -> + osmo_ss7:mtp3_rx(#mtp3_msg{service_ind=?MTP3_SERV_SCCP, payload=Data}). |