pespin has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/36198?usp=email )


Change subject: gsup_server: Look up epdg_ue_fsm process each time it needs to 
be accessed
......................................................................

gsup_server: Look up epdg_ue_fsm process each time it needs to be accessed

This allows simplifying a lot gsup_server state, make it far less prone
to bugs due to state ending up in an unconsistent state.
Nowadays the state is held in the epdg_ue_fsm.
It also allows easily spawning a process per rx msg, since no
start_monitor() is required (monitor would need to be passed to parent
gen_server process then from the per message spawned process).

Change-Id: I80203a7cf0efe82eec3773ee773d25310c07a2c3
---
M src/epdg_ue_fsm.erl
M src/gsup_server.erl
2 files changed, 51 insertions(+), 105 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/erlang/osmo-epdg 
refs/changes/98/36198/1

diff --git a/src/epdg_ue_fsm.erl b/src/epdg_ue_fsm.erl
index fd0d7f9..fc3a7e9 100644
--- a/src/epdg_ue_fsm.erl
+++ b/src/epdg_ue_fsm.erl
@@ -39,7 +39,7 @@
 -include_lib("gtp_utils.hrl").
 -include("conv.hrl").

--export([start_monitor/1, stop/1]).
+-export([start/1, stop/1]).
 -export([init/1,callback_mode/0,terminate/3]).
 -export([get_server_name_by_imsi/1, get_pid_by_imsi/1]).
 -export([auth_request/2, lu_request/1, tunnel_request/2, purge_ms_request/1]).
@@ -68,10 +68,10 @@
         ServerName = get_server_name_by_imsi(Imsi),
         whereis(ServerName).

-start_monitor(Imsi) ->
+start(Imsi) ->
         ServerName = get_server_name_by_imsi(Imsi),
-        lager:info("ue_fsm start_monitor(~p)~n", [ServerName]),
-        gen_statem:start_monitor({local, ServerName}, ?MODULE, Imsi, [{debug, 
[trace]}]).
+        lager:info("ue_fsm start(~p)~n", [ServerName]),
+        gen_statem:start({local, ServerName}, ?MODULE, Imsi, [{debug, 
[trace]}]).

 stop(SrvRef) ->
         try
diff --git a/src/gsup_server.erl b/src/gsup_server.erl
index 4299e95..ef87b67 100644
--- a/src/gsup_server.erl
+++ b/src/gsup_server.erl
@@ -49,14 +49,7 @@
        lsocket, % listening socket
        lport, % local port. only interesting if we bind with port 0
        socket, % current active socket. we only support a single tcp connection
-       ccm_options, % ipa ccm options
-       ues = sets:new()
-       }).
-
--record(gsups_ue, {
-       imsi                   :: binary(),
-       pid                    :: pid(),
-       mref                   :: reference()
+       ccm_options % ipa ccm options
        }).

 -export([start_link/3]).
@@ -180,9 +173,9 @@
        tx_gsup(Socket, Resp),
        {noreply, State};

-handle_cast({purge_ms_response, {Imsi, Result}}, State0) ->
+handle_cast({purge_ms_response, {Imsi, Result}}, State) ->
        lager:info("purge_ms_response for ~p: ~p~n", [Imsi, Result]),
-       Socket = State0#gsups_state.socket,
+       Socket = State#gsups_state.socket,
        case Result of
                ok ->
                        Resp = #{message_type => purge_ms_res,
@@ -196,8 +189,11 @@
                                }
        end,
        tx_gsup(Socket, Resp),
-       State1 = delete_gsups_ue_by_imsi(Imsi, State0),
-       {noreply, State1};
+       case epdg_ue_fsm:get_pid_by_imsi(Imsi) of
+               Pid when is_pid(Pid) -> epdg_ue_fsm:stop(Pid);
+               undefined -> ok
+       end,
+       {noreply, State};

 % Our GSUP CEAI implementation for "IKEv2 Information Delete Request"
 handle_cast({cancel_location_request, Imsi}, State) ->
@@ -233,11 +229,6 @@
        lager:info("GSUP: Rx ~p~n", [GsupMsgRx]),
        rx_gsup(Socket, GsupMsgRx, State);

-handle_info({'DOWN', MRef, process, Pid, Reason}, State0) ->
-       lager:notice("GSUP: epdg_ue_fsm ~p exited, reason: ~p~n", [Pid, 
Reason]),
-       State1 = delete_gsups_ue_by_mref(MRef, State0),
-       {noreply, State1};
-
 handle_info(Info, S) ->
        error_logger:error_report(["unknown handle_info", {module, ?MODULE}, 
{info, Info}, {state, S}]),
        {noreply, S}.
@@ -274,7 +265,7 @@
 %% ------------------------------------------------------------------

 % Rx send auth info / requesting authentication tuples
-rx_gsup(Socket, GsupMsgRx = #{message_type := send_auth_info_req, imsi := 
Imsi}, State0) ->
+rx_gsup(Socket, GsupMsgRx = #{message_type := send_auth_info_req, imsi := 
Imsi}, State) ->
        case maps:find(pdp_info_list, GsupMsgRx) of
        {ok, [PdpInfo]} ->
                #{pdp_context_id := _PDPCtxId,
@@ -287,9 +278,12 @@
                PdpTypeNr = ?GTP_PDP_ADDR_TYPE_NR_IPv4,
                Apn = "*"
        end,
-       {UE, State1} = find_or_new_gsups_ue(Imsi, State0),
-       case epdg_ue_fsm:auth_request(UE#gsups_ue.pid, {PdpTypeNr, Apn}) of
-       ok -> State2 = State1;
+       case epdg_ue_fsm:get_pid_by_imsi(Imsi) of
+               undefined -> {ok, Pid} = epdg_ue_fsm:start(Imsi);
+               Pid -> Pid
+       end,
+       case epdg_ue_fsm:auth_request(Pid, {PdpTypeNr, Apn}) of
+       ok -> ok;
        {error, Err} ->
                lager:error("Auth Req for Imsi ~p failed: ~p~n", [Imsi, Err]),
                Resp = #{message_type => send_auth_info_err,
@@ -298,17 +292,15 @@
                         cause => ?GSUP_CAUSE_NET_FAIL
                },
                tx_gsup(Socket, Resp),
-               State2 = delete_gsups_ue(UE, State1),
-               epdg_ue_fsm:stop(UE#gsups_ue.pid)
+               epdg_ue_fsm:stop(Pid)
        end,
-       {noreply, State2};
+       {noreply, State};

 % location update request / when a UE wants to connect to a specific APN. This 
will trigger a AAA->HLR Request Server Assignment Request
 rx_gsup(Socket, _GsupMsgRx = #{message_type := location_upd_req, imsi := 
Imsi}, State) ->
-       UE = find_gsups_ue_by_imsi(Imsi, State),
-       case UE of
-       #gsups_ue{imsi = Imsi} ->
-               case epdg_ue_fsm:lu_request(UE#gsups_ue.pid) of
+       case epdg_ue_fsm:get_pid_by_imsi(Imsi) of
+       Pid when is_pid(Pid) ->
+               case epdg_ue_fsm:lu_request(Pid) of
                ok -> ok;
                {error, _} ->
                        Resp = #{message_type => location_upd_err,
@@ -331,10 +323,9 @@
 % epdg tunnel request / trigger the establishment to the PGW and prepares 
everything for the user traffic to flow
 % When sending a epdg_tunnel_response everything must be ready for the UE 
traffic
 rx_gsup(Socket, _GsupMsgRx = #{message_type := epdg_tunnel_request, imsi := 
Imsi, pco := PCO}, State) ->
-       UE = find_gsups_ue_by_imsi(Imsi, State),
-       case UE of
-       #gsups_ue{imsi = Imsi} ->
-               case epdg_ue_fsm:tunnel_request(UE#gsups_ue.pid, PCO) of
+       case epdg_ue_fsm:get_pid_by_imsi(Imsi) of
+       Pid when is_pid(Pid) ->
+               case epdg_ue_fsm:tunnel_request(Pid, PCO) of
                ok -> ok;
                {error, _} ->
                        Resp = #{message_type => epdg_tunnel_error,
@@ -356,10 +347,9 @@

 % Purge MS / trigger the delete of session to the PGW
 rx_gsup(Socket, _GsupMsgRx = #{message_type := purge_ms_req, imsi := Imsi}, 
State) ->
-       UE = find_gsups_ue_by_imsi(Imsi, State),
-       case UE of
-       #gsups_ue{imsi = Imsi} ->
-               case epdg_ue_fsm:purge_ms_request(UE#gsups_ue.pid) of
+       case epdg_ue_fsm:get_pid_by_imsi(Imsi) of
+       Pid when is_pid(Pid) ->
+               case epdg_ue_fsm:purge_ms_request(Pid) of
                ok ->   ok;
                _  ->   Resp = #{message_type => purge_ms_err,
                                imsi => Imsi,
@@ -379,13 +369,12 @@
        {noreply, State};

 % Our GSUP CEAI implementation for "IKEv2 Information Delete Response".
-rx_gsup(_Socket, _GsupMsgRx = #{message_type := location_cancellation_res, 
imsi := Imsi}, State0) ->
-       UE = find_gsups_ue_by_imsi(Imsi, State0),
-       case UE of
-       #gsups_ue{imsi = Imsi} -> State1 = delete_gsups_ue(UE, State0);
-       undefined -> State1 = State0
+rx_gsup(_Socket, _GsupMsgRx = #{message_type := location_cancellation_res, 
imsi := Imsi}, State) ->
+       case epdg_ue_fsm:get_pid_by_imsi(Imsi) of
+               Pid when is_pid(Pid) -> epdg_ue_fsm:stop(Pid);
+               undefined -> State
        end,
-       {noreply, State1};
+       {noreply, State};

 rx_gsup(_Socket, GsupMsgRx, State) ->
        lager:error("GSUP: Rx unimplemented msg: ~p~n", [GsupMsgRx]),
@@ -394,62 +383,3 @@
 tx_gsup(Socket, Msg) ->
        lager:info("GSUP: Tx ~p~n", [Msg]),
        ipa_proto:send(Socket, ?IPAC_PROTO_EXT_GSUP, Msg).
-
-
-new_gsups_ue(Imsi, State) ->
-       case epdg_ue_fsm:start_monitor(Imsi) of
-       {ok, {Pid, MRef}} -> ok;
-       {error,{already_started,PrevPid}} ->
-               lager:notice("epdg_ue_fsm for Imsi ~p already existed, 
reusing!: ~p~n", [Imsi, PrevPid]),
-               Pid = PrevPid,
-               MRef = erlang:monitor(process, Pid)
-       end,
-       UE = #gsups_ue{imsi = Imsi, pid = Pid, mref = MRef},
-       NewSt = State#gsups_state{ues = sets:add_element(UE, 
State#gsups_state.ues)},
-       {UE, NewSt}.
-
-% returns gsups_ue if found, undefined it not
-find_gsups_ue_by_imsi(Imsi, State) ->
-       {Imsi, Res} = sets:fold(
-                       fun(SessIt = #gsups_ue{imsi = LookupImsi}, {LookupImsi, 
_AccIn}) -> {LookupImsi, SessIt};
-                          (_, AccIn) -> AccIn
-                       end,
-                       {Imsi, undefined},
-                       State#gsups_state.ues),
-       Res.
-
-find_gsups_ue_by_mref(MRef, State) ->
-       {MRef, Res} = sets:fold(
-                       fun(SessIt = #gsups_ue{imsi = LookupMRef}, {LookupMRef, 
_AccIn}) -> {LookupMRef, SessIt};
-                               (_, AccIn) -> AccIn
-                       end,
-                       {MRef, undefined},
-                       State#gsups_state.ues),
-       Res.
-
-find_or_new_gsups_ue(Imsi, State) ->
-       UE = find_gsups_ue_by_imsi(Imsi, State),
-       case UE of
-           #gsups_ue{imsi = Imsi} ->
-               {UE, State};
-           undefined ->
-               new_gsups_ue(Imsi, State)
-       end.
-
-delete_gsups_ue(UE, State) ->
-       erlang:demonitor(UE#gsups_ue.mref, [flush]),
-       SetRemoved = sets:del_element(UE, State#gsups_state.ues),
-       lager:debug("Removed UE ~p from ~p~n", [UE, SetRemoved]),
-       State#gsups_state{ues = SetRemoved}.
-
-delete_gsups_ue_by_imsi(Imsi, State) ->
-       case find_gsups_ue_by_imsi(Imsi, State) of
-       undefined -> State;
-       UE-> delete_gsups_ue(UE, State)
-       end.
-
-delete_gsups_ue_by_mref(MRef, State) ->
-       case find_gsups_ue_by_mref(MRef, State) of
-       undefined -> State;
-       UE-> delete_gsups_ue(UE, State)
-       end.
\ No newline at end of file

--
To view, visit https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/36198?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: erlang/osmo-epdg
Gerrit-Branch: master
Gerrit-Change-Id: I80203a7cf0efe82eec3773ee773d25310c07a2c3
Gerrit-Change-Number: 36198
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pes...@sysmocom.de>
Gerrit-MessageType: newchange

Reply via email to