re-structure SS7 code and MGW NAT code into separate modules

This repository now only contains the SS7 code
diff --git a/src/bssmap_codec.erl b/src/bssmap_codec.erl
new file mode 100644
index 0000000..61cf85e
--- /dev/null
+++ b/src/bssmap_codec.erl
@@ -0,0 +1,197 @@
+% GSM TS 08.08 / 3GPP TS 48.008 BSSMAP
+
+% (C) 2010 by Harald Welte <laforge@gnumonks.org>
+%
+% 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 <http://www.gnu.org/licenses/>.
+
+-module(bssmap_codec).
+-author('Harald Welte <laforge@gnumonks.org>').
+-include("bssmap.hrl").
+
+-export([parse_bssmap_msg/1, encode_bssmap_msg/1]).
+
+parse_bssmap_msg(<<MsgType:8, Remain/binary>>) ->
+	parse_bssmap_msgt(MsgType, Remain).
+
+parse_bssmap_msgt(MsgType, Msg) when is_integer(MsgType), is_binary(Msg) ->
+	IeList = parse_ies(Msg, []),
+	{bssmap_msg, MsgType, IeList}.
+
+parse_ies(<<>>, ParsedIeList) ->
+	ParsedIeList;
+parse_ies(Msg, ParsedIeList) when is_binary(Msg) ->
+	CurIe = binary:first(Msg),
+	% Parse current IE and append it to list of Parsed IEs
+	case is_tv_ie(CurIe) of
+		true ->
+			Res = parse_ie_tv(CurIe, Msg);
+		false ->
+			Res = parse_ie(CurIe, Msg)
+	end,
+	{ok, BytesConsumed, ParsedIe} = Res,
+	{CurIe, Payload} = ParsedIe,
+	DecodedIe = decode_ie(CurIe, Payload),
+	ParsedIeList1 = ParsedIeList ++ [DecodedIe],
+	%ParsedIeList1 = ParsedIeList ++ [ParsedIe],
+	RemainMsg = binary:part(Msg, BytesConsumed, byte_size(Msg)-BytesConsumed),
+	parse_ies(RemainMsg, ParsedIeList1).
+
+% check if this element is of TV type
+is_tv_ie(T) when 
+	T == ?BSSMAP_IE_NUMBER_OF_MSS;
+	T == ?BSSMAP_IE_PERIODICITY;
+	T == ?BSSMAP_IE_EXTD_RES_IND;
+	T == ?BSSMAP_IE_INTERF_BAND_TO_USE;
+	T == ?BSSMAP_IE_RR_CAUSE;
+	T == ?BSSMAP_IE_DLCI;
+	T == ?BSSMAP_IE_DOWNLINK_DTX_FLAG;
+	T == ?BSSMAP_IE_RESPONSE_RQST;
+	T == ?BSSMAP_IE_RES_IND_METHOD;
+	T == ?BSSMAP_IE_CM_INFO_T1;
+	T == ?BSSMAP_IE_CHOSEN_CHANNEL;
+	T == ?BSSMAP_IE_CIPH_RESP_MODE;
+	T == ?BSSMAP_IE_TRACE_TYPE;
+	T == ?BSSMAP_IE_TRACE_REFERENCE;
+	T == ?BSSMAP_IE_FORWARD_INDICATOR;
+	T == ?BSSMAP_IE_CHOSEN_ENCR_ALG;
+	T == ?BSSMAP_IE_CIRCUIT_POOL;
+	T == ?BSSMAP_IE_TIME_INDICATION;
+	T == ?BSSMAP_IE_CUR_CHAN_TYPE_1;
+	T == ?BSSMAP_IE_QUEUEING_IND;
+	T == ?BSSMAP_IE_SPEECH_VERSION;
+	T == ?BSSMAP_IE_ASS_REQUIREMENT;
+	T == ?BSSMAP_IE_EMLPP_PRIORITY;
+	T == ?BSSMAP_IE_CONFIG_EVO_INDI;
+	T == ?BSSMAP_IE_LSA_ACCESS_CTRL_SUPPR ->
+		true;
+is_tv_ie(_T) ->
+		false.
+
+% Parser for any non-TLV and non-TV IEs
+parse_ie(?BSSMAP_IE_CIRC_ID_CODE, Msg) ->
+	<<?BSSMAP_IE_CIRC_ID_CODE:8, Cic:16/big>> = Msg,
+	{ok, 3, {?BSSMAP_IE_CIRC_ID_CODE, Cic}};
+parse_ie(?BSSMAP_IE_CONN_REL_RQSTED, Msg) ->
+	<<?BSSMAP_IE_CONN_REL_RQSTED:8>> = Msg,
+	{ok, 1, {?BSSMAP_IE_CONN_REL_RQSTED, 1}};
+parse_ie(?BSSMAP_IE_RES_AVAIL, Msg) ->
+	<<?BSSMAP_IE_RES_AVAIL:8, ResAvail:8/binary>> = Msg,
+	{ok, 9, {?BSSMAP_IE_RES_AVAIL, ResAvail}};
+parse_ie(?BSSMAP_IE_TOT_RES_ACCESS, Msg) ->
+	<<?BSSMAP_IE_TOT_RES_ACCESS:8, ResAvail:4/binary>> = Msg,
+	{ok, 5, {?BSSMAP_IE_TOT_RES_ACCESS, ResAvail}};
+parse_ie(?BSSMAP_IE_TALKER_FLAG, Msg) ->
+	<<?BSSMAP_IE_TALKER_FLAG:8>> = Msg,
+	{ok, 1, {?BSSMAP_IE_TALKER_FLAG, 1}};
+% Default: Parser for TLV IE
+parse_ie(MsgType, Msg) ->
+	<<MsgType:8, Length:8, Value:Length/binary, _/binary>> = Msg,
+	{ok, 2+Length, {MsgType, Value}}.
+
+% Parser for simple Tag-Value IE
+parse_ie_tv(IeType, Msg) ->
+	<<IeType:8, Par:8>> = Msg,
+	{ok, 2, {IeType, Par}}.
+
+
+% FIXME
+encode_bssmap_msg(_) ->
+	ok.
+
+
+
+
+
+decode_ie(?BSSMAP_IE_CIRC_ID_CODE, <<Pcm:11, Ts:5>>) ->
+	{circuit_id, Pcm, Ts};
+decode_ie(?BSSMAP_IE_IMSI, Remain) ->
+	{imsi, bin_bcd2str(Remain)};
+decode_ie(?BSSMAP_IE_TMSI, <<Tmsi:32>>) ->
+	{tmsi, Tmsi};
+decode_ie(?BSSMAP_IE_L3_HDR_INFO, <<Pdisc:8, Tid:8>>) ->
+	{l3_hdr_info, Pdisc, Tid};
+decode_ie(?BSSMAP_IE_ENCR_INFO, <<Algos:8, Key/binary>>) ->
+	{encr_info, Algos, Key};
+decode_ie(?BSSMAP_IE_CHANNEL_TYPE, <<_:4, Spdi:4, RateType:8, Remain/binary>>) ->
+	{chan_type, Spdi, RateType, Remain};
+decode_ie(?BSSMAP_IE_EXTD_RES_IND, Ri) ->
+	<<_:6, Sm:1, Tarr:1>> = <<Ri>>,
+	{extended_ri, Sm, Tarr};
+decode_ie(?BSSMAP_IE_TOT_RES_ACCESS, <<NumFr:16/big, NumHr:16/big>>) ->
+	{tot_res_access, NumFr, NumHr};
+decode_ie(?BSSMAP_IE_CELL_ID, <<_Spare:4, Discr:4, Remain/binary>>) ->
+	{cell_id, decode_cid_ie(Discr, Remain)};
+decode_ie(?BSSMAP_IE_PRIORITY, <<_:1, Pci:1, Prio:4, Qa:1, Pvi:1>>) ->
+	{priority, Pci, Prio, Qa, Pvi};
+decode_ie(?BSSMAP_IE_CELL_ID_LIST, <<_Spare:4, Discr:4, Remain/binary>>) ->
+	{cell_id_list, decode_cid_list(Discr, Remain, [])};
+decode_ie(?BSSMAP_IE_DIAGNOSTIC, <<ErrPtr:8, _:4, BitPtr:4, MsgRecv/binary>>) ->
+	{diagnostic, ErrPtr, BitPtr, MsgRecv};
+decode_ie(?BSSMAP_IE_CHOSEN_CHANNEL, Int) ->
+	<<Mode:4, Chan:4>> = <<Int:8>>,
+	{chosen_channel, Mode, Chan};
+decode_ie(?BSSMAP_IE_MOBILE_IDENTITY, Data) ->
+	% FIXME
+	fixme;
+% Default: don't decode
+decode_ie(IeI, Data) ->
+	{IeI, Data}.
+
+decode_cid_ie(?CELL_ID_WHOLE_GLOBAL, Remain) ->
+	<<Mcc2:4, Mcc1:4, Mnc3:4, Mcc3:4, Mnc2:4, Mnc1:4, Lac:16/big, Ci:16/big>> = Remain,
+	[{mcc, [Mcc1, Mcc2, Mcc3]}, {mnc, [Mnc1, Mnc2, Mnc3]}, {lac, Lac}, {cid, Ci}];
+decode_cid_ie(?CELL_ID_LAC_AND_CI, Remain) ->
+	<<Lac:16/big, Ci:16/big>> = Remain,
+	[{lac, Lac}, {cid, Ci}];
+decode_cid_ie(?CELL_ID_CI, Remain) ->
+	<<Ci:16/big>> = Remain,
+	[{cid, Ci}];
+decode_cid_ie(?CELL_ID_NO_CELL, _Remain) ->
+	[];
+decode_cid_ie(?CELL_ID_UTRAN_PLMN_LAC_RNC, Remain) ->
+	<<Mcc2:4, Mcc1:4, Mnc3:4, Mcc3:4, Mnc2:4, Mnc1:4, Lac:16/big, Rnc:16/big>> = Remain,
+	[{mcc, [Mcc1, Mcc2, Mcc3]}, {mnc, [Mnc1, Mnc2, Mnc3]}, {lac, Lac}, {rnc_id, Rnc}];
+decode_cid_ie(?CELL_ID_UTRAN_RNC, Remain) ->
+	<<Rnc:16/big>> = Remain,
+	[{rnc_id, Rnc}];
+decode_cid_ie(?CELL_ID_UTRAN_LAC_RNC, Remain) ->
+	<<Lac:16/big, Rnc:16/big>> = Remain,
+	[{lac, Lac}, {rnc_id, Rnc}].
+
+decode_cid_list(Discr, Data, List) ->
+	case Discr of
+		?CELL_ID_WHOLE_GLOBAL -> Len = 7;
+		?CELL_ID_LAC_AND_CI ->	 Len = 4;
+		?CELL_ID_CI ->		 Len = 2;
+		?CELL_ID_NO_CELL ->	 Len = 0;
+		?CELL_ID_UTRAN_PLMN_LAC_RNC -> Len = 7;
+		?CELL_ID_UTRAN_RNC ->	Len = 2;
+		?CELL_ID_UTRAN_LAC_RNC -> Len = 4
+	end,
+	<<Subset:Len/binary, Remain/binary>> = Data,
+	Elem = {cell_id, decode_cid_ie(Discr, Subset)},
+	decode_cid_list(Discr, Remain, List ++ [Elem]).
+
+
+
+bin_bcd2str(BcdBin) when is_binary(BcdBin) ->
+	bin_bcd2str(BcdBin, []).
+bin_bcd2str(<<>>, List) ->
+	List;
+bin_bcd2str(BcdBin, List) ->
+	<<Nibble:4, Remain/bitstring>> = BcdBin,
+	Char = "0" + Nibble,
+	bin_bcd2str(Remain, List ++ [Char]).