From 6f9b5139f34d222a4e6348f0bdccc3a75aa341ec Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 2 Aug 2010 20:33:16 +0200 Subject: re-work MAP patching into recursive/overloaded functions this renders a much cleaner solution --- src/tcap_udp_server.erl | 219 +++++++++++++++++++++++++----------------------- 1 file changed, 112 insertions(+), 107 deletions(-) diff --git a/src/tcap_udp_server.erl b/src/tcap_udp_server.erl index 9abc03f..a7f2393 100644 --- a/src/tcap_udp_server.erl +++ b/src/tcap_udp_server.erl @@ -37,50 +37,137 @@ init(ServerPort) -> % patch a UpdateGprsLocationArg and replace SGSN number and SGSN address % !!! TESTING ONLY !!! -patch_UpdateGprsLocationArg(Arg) -> - Arg1 = Arg#'UpdateGprsLocationArg'{'sgsn-Number' = ?PATCH_SGSN_NUMBER}, - Arg1#'UpdateGprsLocationArg'{'sgsn-Address' = ?PATCH_SGSN_ADDRESS}. - +patch(#'UpdateGprsLocationArg'{} = P) -> + P#'UpdateGprsLocationArg'{'sgsn-Number'= ?PATCH_SGSN_NUMBER, + 'sgsn-Address' = ?PATCH_SGSN_ADDRESS}; % Some other SGSN is sendingu us a GPRS location update. In the response, % we indicate teh HLR number, which we need to masquerade -patch_UpdateGprsLocationRes(Arg) -> - Arg#'UpdateGprsLocationRes'{'hlr-Number' = ?PATCH_HLR_NUMBER}. +patch(#'UpdateGprsLocationRes'{} = P) -> + P#'UpdateGprsLocationRes'{'hlr-Number' = ?PATCH_HLR_NUMBER}; % Some other MSC/VLR is sendingu us a GSM location update. In the response, % we indicate teh HLR number, which we need to masquerade -patch_UpdateLocationRes(Arg) -> - Arg#'UpdateLocationRes'{'hlr-Number' = ?PATCH_HLR_NUMBER}. +patch(#'UpdateLocationRes'{} = P) -> + P#'UpdateLocationRes'{'hlr-Number' = ?PATCH_HLR_NUMBER}; % HLR responds to VLR's MAP_RESTORE_REQ (i.e. it has lost information) -patch_RestoreDataRes(Arg) -> - Arg#'RestoreDataRes'{'hlr-Number' = ?PATCH_HLR_NUMBER}. +patch(#'RestoreDataRes'{} = P) -> + P#'RestoreDataRes'{'hlr-Number' = ?PATCH_HLR_NUMBER}; % HLR sends subscriber data to VLR/SGSN, including CAMEL info -patch_InsertSubscriberDataArg(Arg) -> - VlrCamel = Arg#'InsertSubscriberDataArg'.'vlrCamelSubscriptionInfo', - Arg1 = Arg#'InsertSubscriberDataArg'{'vlrCamelSubscriptionInfo' = patch_vlrCamelSubscrInfo(VlrCamel)}, - %SgsnCamel = Arg#'InsertSubscriberDataArg'.'sgsn-CAMEL-SubscriptionInfo', - %Arg#'InsertSubscriberDataArg'{'sgsn-CAMEL-SubscriptionInfo' = patch_sgsnCamelSubscrInfo(SgsnCamel)}, - Arg1. +patch(#'InsertSubscriberDataArg'{'vlrCamelSubscriptionInfo'=VlrCamel, + 'sgsn-CAMEL-SubscriptionInfo'=SgsnCamel} = Arg) -> + Arg#'InsertSubscriberDataArg'{'vlrCamelSubscriptionInfo'=patch(VlrCamel), + 'sgsn-CAMEL-SubscriptionInfo'=patch(SgsnCamel)}; + +% HLR sends subscriber data to gsmSCF +patch(#'AnyTimeSubscriptionInterrogationRes'{'camel-SubscriptionInfo'=Csi} = P) -> + P#'AnyTimeSubscriptionInterrogationRes'{'camel-SubscriptionInfo'=patch(Csi)}; +patch(asn1_NOVALUE) -> + asn1_NOVALUE; % CAMEL related parsing +% this is part of the InsertSubscriberData HLR -> VLR +patch(#'VlrCamelSubscriptionInfo'{'o-CSI'=Ocsi, 'mo-sms-CSI'=MoSmsCsi, + 'mt-sms-CSI'=MtSmsCsi, 'ss-CSI'=SsCsi} = P) -> + P#'VlrCamelSubscriptionInfo'{'o-CSI'=patch(Ocsi), + 'mo-sms-CSI'=patch(MoSmsCsi), + 'mt-sms-CSI'=patch(MtSmsCsi), + 'ss-CSI'=patch(SsCsi)}; + +% this is part of the InsertSubscriberData HLR -> SGSN +patch(#'SGSN-CAMEL-SubscriptionInfo'{'gprs-CSI'=GprsCsi, + 'mo-sms-CSI'=MoSmsCsi, + 'mt-sms-CSI'=MtSmsCsi} = P) -> + P#'SGSN-CAMEL-SubscriptionInfo'{'gprs-CSI'=patch(GprsCsi), + 'mo-sms-CSI'=patch(MoSmsCsi), + 'mt-sms-CSI'=patch(MtSmsCsi)}; + +% this is part of the Anytime Subscription Interrogation Result HLR->gsmSCF +patch(#'CAMEL-SubscriptionInfo'{'o-CSI'=Ocsi, + 'd-CSI'=Dcsi, + 't-CSI'=Tcsi, + 'vt-CSI'=Vtcsi, + %'tif-CSI'=Tifcsi, + 'gprs-CSI'=GprsCsi, + 'mo-sms-CSI'=MoSmsCsi, + 'ss-CSI'=SsCsi, + 'm-CSI'=Mcsi, + 'mt-sms-CSI'=MtSmsCsi, + 'mg-csi'=MgCsi, + 'o-IM-CSI'=OimCsi, + 'd-IM-CSI'=DimCsi, + 'vt-IM-CSI'=VtImCsi} = P) -> + P#'CAMEL-SubscriptionInfo'{'o-CSI'=patch(Ocsi), + 'd-CSI'=patch(Dcsi), + 't-CSI'=patch(Tcsi), + 'vt-CSI'=patch(Vtcsi), + 'gprs-CSI'=patch(GprsCsi), + 'mo-sms-CSI'=patch(MoSmsCsi), + 'ss-CSI'=patch(SsCsi), + 'm-CSI'=patch(Mcsi), + 'mt-sms-CSI'=patch(MtSmsCsi), + 'mg-csi'=patch(MgCsi), + 'o-IM-CSI'=patch(OimCsi), + 'd-IM-CSI'=patch(DimCsi), + 'vt-IM-CSI'=patch(VtImCsi)}; + +patch(#'T-CSI'{'t-BcsmCamelTDPDataList'=TdpList} = P) -> + P#'T-CSI'{'t-BcsmCamelTDPDataList'=patch_tBcsmCamelTDPDataList(TdpList)}; +patch(#'M-CSI'{'gsmSCF-Address'=GsmScfAddr} = P) -> + P#'M-CSI'{'gsmSCF-Address'=?PATCH_GSMSCF_ADDRESS}; +patch(#'MG-CSI'{'gsmSCF-Address'=GsmScfAddr} = P) -> + P#'MG-CSI'{'gsmSCF-Address'=?PATCH_GSMSCF_ADDRESS}; +patch(#'O-CSI'{'o-BcsmCamelTDPDataList'=TdpList} = P) -> + P#'O-CSI'{'o-BcsmCamelTDPDataList'=patch_oBcsmCamelTDPDataList(TdpList)}; +patch(#'D-CSI'{'dp-AnalysedInfoCriteriaList'=List} = P) -> + P#'D-CSI'{'dp-AnalysedInfoCriteriaList'=patch_AnInfoCritList(List)}; +patch(#'SMS-CSI'{'sms-CAMEL-TDP-DataList'=TdpList} = P) -> + P#'SMS-CSI'{'sms-CAMEL-TDP-DataList'=patch_SmsCamelTDPDataList(TdpList)}; +patch(#'SS-CSI'{'ss-CamelData'=Sscd} = P) -> + P#'SS-CSI'{'ss-CamelData'=patch(Sscd)}; +patch(#'GPRS-CSI'{'gprs-CamelTDPDataList'=TdpList} = P) -> + P#'GPRS-CSI'{'gprs-CamelTDPDataList'=patch_GprsCamelTDPDataList(TdpList)}; +patch(#'SS-CamelData'{'gsmSCF-Address'=GsmScfAddr} = P) -> + P#'SS-CamelData'{'gsmSCF-Address'=?PATCH_GSMSCF_ADDRESS}; +patch(#'O-BcsmCamelTDPData'{'gsmSCF-Address'=GsmScfAddr} = P) -> + P#'O-BcsmCamelTDPData'{'gsmSCF-Address'=?PATCH_GSMSCF_ADDRESS}; +patch(#'SMS-CAMEL-TDP-Data'{'gsmSCF-Address'=GsmScfAddr} = P) -> + P#'SMS-CAMEL-TDP-Data'{'gsmSCF-Address'=?PATCH_GSMSCF_ADDRESS}; +patch(#'GPRS-CamelTDPData'{'gsmSCF-Address'=GsmScfAddr} = P) -> + P#'GPRS-CamelTDPData'{'gsmSCF-Address'=?PATCH_GSMSCF_ADDRESS}; +patch(#'DP-AnalysedInfoCriterium'{'gsmSCF-Address'=GsmScfAddr} = P) -> + P#'DP-AnalysedInfoCriterium'{'gsmSCF-Address'=?PATCH_GSMSCF_ADDRESS}. + patch_oBcsmCamelTDPDataList(List) -> % we reverse the origianl list, as the tail recursive _acc function % will invert the order of components again patch_oBcsmCamelTDPDataList_acc(lists:reverse(List), []). patch_oBcsmCamelTDPDataList_acc([], NewList) -> NewList; patch_oBcsmCamelTDPDataList_acc([TdpData|Tail], NewList) -> - case TdpData of - #'O-BcsmCamelTDPData'{'gsmSCF-Address'=ScfAddr} -> - NewTdpData = TdpData#'O-BcsmCamelTDPData'{'gsmSCF-Address'=?PATCH_GSMSCF_ADDRESS}; - _ -> - NewTdpData = TdpData - end, + NewTdpData = patch(TdpData#'O-BcsmCamelTDPData'{}), patch_oBcsmCamelTDPDataList_acc(Tail, [NewTdpData|NewList]). +patch_tBcsmCamelTDPDataList(List) -> + % we reverse the origianl list, as the tail recursive _acc function + % will invert the order of components again + patch_tBcsmCamelTDPDataList_acc(lists:reverse(List), []). +patch_tBcsmCamelTDPDataList_acc([], NewList) -> NewList; +patch_tBcsmCamelTDPDataList_acc([TdpData|Tail], NewList) -> + NewTdpData = patch(TdpData#'T-BcsmCamelTDPData'{}), + patch_tBcsmCamelTDPDataList_acc(Tail, [NewTdpData|NewList]). + +patch_AnInfoCritList(List) -> + % we reverse the origianl list, as the tail recursive _acc function + % will invert the order of components again + patch_AnInfoCritList_acc(lists:reverse(List), []). +patch_AnInfoCritList_acc([], NewList) -> NewList; +patch_AnInfoCritList_acc([Crit|Tail], NewList) -> + NewCrit = patch(Crit#'DP-AnalysedInfoCriterium'{}), + patch_AnInfoCritList_acc(Tail, [NewCrit|NewList]). patch_GprsCamelTDPDataList(List) -> % we reverse the origianl list, as the tail recursive _acc function @@ -88,107 +175,25 @@ patch_GprsCamelTDPDataList(List) -> patch_GprsCamelTDPDataList_acc(lists:reverse(List), []). patch_GprsCamelTDPDataList_acc([], NewList) -> NewList; patch_GprsCamelTDPDataList_acc([TdpData|Tail], NewList) -> - case TdpData of - #'GPRS-CamelTDPData'{'gsmSCF-Address'=ScfAddr} -> - NewTdpData = TdpData#'GPRS-CamelTDPData'{'gsmSCF-Address'=?PATCH_GSMSCF_ADDRESS}; - _ -> - NewTdpData = TdpData - end, + NewTdpData = patch(TdpData#'GPRS-CamelTDPData'{}), patch_GprsCamelTDPDataList_acc(Tail, [NewTdpData|NewList]). - patch_SmsCamelTDPDataList(List) -> % we reverse the origianl list, as the tail recursive _acc function % will invert the order of components again patch_SmsCamelTDPDataList_acc(lists:reverse(List), []). patch_SmsCamelTDPDataList_acc([], NewList) -> NewList; patch_SmsCamelTDPDataList_acc([TdpData|Tail], NewList) -> - case TdpData of - #'SMS-CAMEL-TDP-Data'{'gsmSCF-Address'=ScfAddr} -> - NewTdpData = TdpData#'SMS-CAMEL-TDP-Data'{'gsmSCF-Address'=?PATCH_GSMSCF_ADDRESS}; - _ -> - NewTdpData = TdpData - end, + NewTdpData = patch(TdpData#'SMS-CAMEL-TDP-Data'{}), patch_GprsCamelTDPDataList_acc(Tail, [NewTdpData|NewList]). -patch_vlrCamelSubscrInfo(VlrCamel) -> - case VlrCamel of - asn1_NOVALUE -> - % return the original (empty) VlrCamelSubscrInfo - VlrCamel; - #'VlrCamelSubscriptionInfo'{} -> - case VlrCamel of - #'VlrCamelSubscriptionInfo'{'o-CSI'={#'O-CSI'{'o-BcsmCamelTDPDataList'=TdpList}}} -> - NewTdpList = patch_oBcsmCamelTDPDataList(TdpList), - VlrCamel1 = VlrCamel#'VlrCamelSubscriptionInfo'{'o-CSI'={#'O-CSI'{'o-BcsmCamelTDPDataList'=NewTdpList}}}; - _ -> - VlrCamel1 = VlrCamel - end, - case VlrCamel1 of - #'VlrCamelSubscriptionInfo'{'mo-sms-CSI'={#'SMS-CSI'{'sms-CAMEL-TDP-DataList'=MoSmsTdpList}}} -> - NewMoSmsTdpList = patch_SmsCamelTDPDataList(MoSmsTdpList), - VlrCamel2 = VlrCamel1#'VlrCamelSubscriptionInfo'{'mo-sms-CSI'={#'SMS-CSI'{'sms-CAMEL-TDP-DataList'=NewMoSmsTdpList}}}; - _ -> - VlrCamel2 = VlrCamel1 - end, - case VlrCamel2 of - #'VlrCamelSubscriptionInfo'{'mt-sms-CSI'={#'SMS-CSI'{'sms-CAMEL-TDP-DataList'=MtSmsTdpList}}} -> - NewMtSmsTdpList = patch_SmsCamelTDPDataList(MtSmsTdpList), - VlrCamel3 = VlrCamel2#'VlrCamelSubscriptionInfo'{'mt-sms-CSI'={#'SMS-CSI'{'sms-CAMEL-TDP-DataList'=NewMtSmsTdpList}}}; - _ -> - VlrCamel3 = VlrCamel2 - end, - case VlrCamel3 of - #'VlrCamelSubscriptionInfo'{'ss-CSI'={#'SS-CSI'{'ss-CamelData'=#'SS-CamelData'{'gsmSCF-Address'=SSgsmSCF}}}} -> - VlrCamel4 = #'VlrCamelSubscriptionInfo'{'ss-CSI'={#'SS-CSI'{'ss-CamelData'=#'SS-CamelData'{'gsmSCF-Address'=?PATCH_GSMSCF_ADDRESS}}}}; - _ -> - VlrCamel4 = VlrCamel3 - end, - % return the VlrCamelSubscrInfo with replaced TdpList - VlrCamel4; - _ -> - % return the original VlrCamelSubscrInfo without TdpList - VlrCamel - end. - - -patch_sgsnCamelSubscrInfo(SgsnCamel) -> - case SgsnCamel of - asn1_NOVALUE -> - % return the original (empty) SgsnCamelSubscrInfo - SgsnCamel; - #'SGSN-CAMEL-SubscriptionInfo'{} -> - case SgsnCamel of #'SGSN-CAMEL-SubscriptionInfo'{'gprs-CSI'={#'GPRS-CSI'{'gprs-CamelTDPDataList'=GprsTdpList}}} -> - NewGprsTdpList = patch_GprsCamelTDPDataList(GprsTdpList), - SgsnCamel1 = SgsnCamel#'SGSN-CAMEL-SubscriptionInfo'{'gprs-CSI'={#'GPRS-CSI'{'gprs-CamelTDPDataList'=NewGprsTdpList}}}; - _ -> - SgsnCamel1 = SgsnCamel - end, - case SgsnCamel1 of #'SGSN-CAMEL-SubscriptionInfo'{'mo-sms-CSI'={#'SMS-CSI'{'sms-CAMEL-TDP-DataList'=MoSmsTdpList}}} -> - NewMoSmsTdpList = patch_SmsCamelTDPDataList(MoSmsTdpList), - SgsnCamel2 = SgsnCamel1#'SGSN-CAMEL-SubscriptionInfo'{'mo-sms-CSI'={#'SMS-CSI'{'sms-CAMEL-TDP-DataList'=NewMoSmsTdpList}}}; - _ -> - SgsnCamel2 = SgsnCamel1 - end, - case SgsnCamel1 of #'SGSN-CAMEL-SubscriptionInfo'{'mt-sms-CSI'={#'SMS-CSI'{'sms-CAMEL-TDP-DataList'=MtSmsTdpList}}} -> - NewMtSmsTdpList = patch_SmsCamelTDPDataList(MtSmsTdpList), - SgsnCamel3 = SgsnCamel2#'SGSN-CAMEL-SubscriptionInfo'{'mt-sms-CSI'={#'SMS-CSI'{'sms-CAMEL-TDP-DataList'=NewMtSmsTdpList}}}; - _ -> - SgsnCamel3 = SgsnCamel2 - end, - SgsnCamel3; - _ -> - % return the original VlrCamelSubscrInfo without TdpList - SgsnCamel - end. - % process the Argument of a particular MAP invocation process_component_arg(OpCode, Arg) -> case Arg of asn1_NOVALUE -> Arg; - _ -> patch_UpdateGprsLocationArg(Arg) + _ -> patch(Arg) end. % recurse over all components -- cgit v1.2.3