%% Copyright (C) 2024 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
%% Author: Vadim Yanitskiy <vyanitskiy@sysmocom.de>
%%
%% All Rights Reserved
%%
%% SPDX-License-Identifier: AGPL-3.0-or-later
%%
%% 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 <https://www.gnu.org/licenses/>.
%%
%% 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(osmo_s1gw_sup).
-behaviour(supervisor).

-export([init/1,
         start_link/0]).

-include("s1ap.hrl").

-define(SERVER, ?MODULE).
-define(ENV_APP_NAME, osmo_s1gw).
-define(ENV_DEFAULT_SCTP_BUFSZ, 65536).
-define(ENV_DEFAULT_SCTP_NODELAY, true).
-define(ENV_DEFAULT_S1GW_BIND_ADDR, "127.0.1.1").
-define(ENV_DEFAULT_S1GW_BIND_PORT, ?S1AP_PORT).
-define(ENV_DEFAULT_MME_LOC_ADDR, "127.0.2.1").
-define(ENV_DEFAULT_MME_REM_ADDR, "127.0.2.10").
-define(ENV_DEFAULT_MME_REM_PORT, ?S1AP_PORT).
-define(ENV_DEFAULT_PFCP_LOC_ADDR, "127.0.1.1").
-define(ENV_DEFAULT_PFCP_REM_ADDR, "127.0.1.2").

%% ------------------------------------------------------------------
%% supervisor API
%% ------------------------------------------------------------------

start_link() ->
    supervisor:start_link({local, ?SERVER}, ?MODULE, []).


init([]) ->
    PfcpLocAddr = get_env(pfcp_loc_addr, ?ENV_DEFAULT_PFCP_LOC_ADDR),
    PfcpRemAddr = get_env(pfcp_rem_addr, ?ENV_DEFAULT_PFCP_REM_ADDR),

    SctpServer = {sctp_server, {sctp_server, start_link, [server_cfg()]},
                  permanent,
                  5000,
                  worker,
                  [sctp_server]},
    PfcpPeer = {pfcp_peer, {pfcp_peer, start_link,
                            [PfcpLocAddr, PfcpRemAddr]},
                permanent,
                5000,
                worker,
                [pfcp_peer]},

    s1gw_metrics:init(),
    {ok, {{one_for_one, 5, 10}, [SctpServer, PfcpPeer]}}.


%% ------------------------------------------------------------------
%% private API
%% ------------------------------------------------------------------

get_env(Param, Default) ->
    application:get_env(?ENV_APP_NAME, Param, Default).


-spec client_cfg() -> sctp_client:cfg().
client_cfg() ->
    SockOpts = #{sctp_nodelay => get_env(mme_nodelay, ?ENV_DEFAULT_SCTP_NODELAY),
                 recbuf => get_env(mme_recbuf, ?ENV_DEFAULT_SCTP_BUFSZ),
                 sndbuf => get_env(mme_sndbuf, ?ENV_DEFAULT_SCTP_BUFSZ)},
    #{laddr => get_env(mme_loc_addr, ?ENV_DEFAULT_MME_LOC_ADDR),
      raddr => get_env(mme_rem_addr, ?ENV_DEFAULT_MME_REM_ADDR),
      rport => get_env(mme_rem_port, ?ENV_DEFAULT_MME_REM_PORT),
      sockopts => maps:to_list(SockOpts)}.


-spec server_cfg() -> sctp_server:cfg().
server_cfg() ->
    SockOpts = #{sctp_nodelay => get_env(s1gw_nodelay, ?ENV_DEFAULT_SCTP_NODELAY),
                 recbuf => get_env(s1gw_recbuf, ?ENV_DEFAULT_SCTP_BUFSZ),
                 sndbuf => get_env(s1gw_sndbuf, ?ENV_DEFAULT_SCTP_BUFSZ)},
    #{laddr => get_env(s1gw_bind_addr, ?ENV_DEFAULT_S1GW_BIND_ADDR),
      lport => get_env(s1gw_bind_port, ?ENV_DEFAULT_S1GW_BIND_PORT),
      sockopts => maps:to_list(SockOpts),
      handler => sctp_proxy,
      priv => client_cfg()}.

%% vim:set ts=4 sw=4 et: