% Osmocom adaptor to interface the IPA core with osmo_ss7 % (C) 2011 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(ss7_link_ipa_client). -author('Harald Welte '). -behavior(gen_server). -include_lib("osmo_ss7/include/osmo_util.hrl"). %-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, handle_info/2]). -record(loop_dat, { ipa_pid, socket, link }). start_link(Args) -> gen_server:start_link(?MODULE, Args, []). init(L = #sigtran_link{type = ipa_client, name = Name, linkset_name = LinksetName, 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), {noreply, 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}, {noreply, LoopDat}. reconnect(LoopDat = #loop_dat{link=Link}) -> #sigtran_link{local = Local, remote = Remote} = Link, #sigtran_peer{ip = LocalIp, port = LocalPort, point_code = LocalPc} = Local, #sigtran_peer{ip = RemoteIp, port = RemotePort, point_code = RemotePc} = Remote, case ipa_proto:connect(RemoteIp, RemotePort, [], 10000) of {ok, {Socket, IpaPid}} -> set_link_state(LoopDat, up), Mtp3Label = #mtp3_routing_label{sig_link_sel=0, origin_pc = RemotePc, dest_pc = LocalPc}, ipa_proto:register_stream(Socket, 253, {callback_fn, fun ipa_tx_to_sccp/4, [Mtp3Label]}), set_link_state(LoopDat, active), 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_sccp(_Socket, 253, Data, [Mtp3Label]) -> ss7_links:mtp3_rx(#mtp3_msg{service_ind=?MTP3_SERV_SCCP, routing_label=Mtp3Label, payload=Data}).