fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/39664?usp=email )
Change subject: sctp_common: new module with common SCTP/S1AP API ......................................................................
sctp_common: new module with common SCTP/S1AP API
Move send_data/2 and shutdown/1 from sctp_client into their own module. Make use of this API from sctp_server to avoid code duplication.
Change-Id: I49511b0860f45ff1410f1b6fe2f027606c7f0ae8 --- M src/sctp_client.erl A src/sctp_common.erl M src/sctp_proxy.erl M src/sctp_server.erl 4 files changed, 78 insertions(+), 30 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/erlang/osmo-s1gw refs/changes/64/39664/1
diff --git a/src/sctp_client.erl b/src/sctp_client.erl index 72d5bd1..5875f61 100644 --- a/src/sctp_client.erl +++ b/src/sctp_client.erl @@ -36,9 +36,7 @@
-export([connect/0, connect/1, - connect/2, - send_data/2, - disconnect/1]). + connect/2]).
-include_lib("kernel/include/logger.hrl"). -include_lib("kernel/include/inet.hrl"). @@ -51,14 +49,11 @@ -type rem_addr() :: localhost | list() | inet:ip_address(). -type loc_rem_addr() :: {loc_addr(), rem_addr()}. -type connect_result() :: {ok, gen_sctp:sctp_socket()}. --type sock_aid() :: {gen_sctp:sctp_socket(), - gen_sctp:assoc_id()}.
-export_type([loc_addr/0, rem_addr/0, loc_rem_addr/0, - connect_result/0, - sock_aid/0]). + connect_result/0]).
%% ------------------------------------------------------------------ @@ -111,15 +106,4 @@ {ok, Sock}.
--spec send_data(sock_aid(), binary()) -> ok | {error, term()}. -send_data({Sock, Aid}, Data) -> - gen_sctp:send(Sock, #sctp_sndrcvinfo{stream = ?S1AP_SCTP_STREAM, - ppid = ?S1AP_SCTP_PPID, - assoc_id = Aid}, Data). - - --spec disconnect(sock_aid()) -> ok | {error, term()}. -disconnect({Sock, Aid}) -> - gen_sctp:eof(Sock, #sctp_assoc_change{assoc_id = Aid}). - %% vim:set ts=4 sw=4 et: diff --git a/src/sctp_common.erl b/src/sctp_common.erl new file mode 100644 index 0000000..0d28f81 --- /dev/null +++ b/src/sctp_common.erl @@ -0,0 +1,66 @@ +%% Copyright (C) 2025 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(sctp_common). + +-export([send_data/2, + shutdown/1]). + +-include_lib("kernel/include/logger.hrl"). +-include_lib("kernel/include/inet_sctp.hrl"). + +-include("s1ap.hrl"). + + +-type sock_aid() :: {gen_sctp:sctp_socket(), + gen_sctp:assoc_id()}. + + +%% ------------------------------------------------------------------ +%% public API +%% ------------------------------------------------------------------ + +-spec send_data(sock_aid(), binary()) -> ok | {error, term()}. +send_data({Sock, Aid}, Data) -> + gen_sctp:send(Sock, #sctp_sndrcvinfo{stream = ?S1AP_SCTP_STREAM, + ppid = ?S1AP_SCTP_PPID, + assoc_id = Aid}, Data). + + +-spec shutdown(sock_aid()) -> ok | {error, term()}. +shutdown({Sock, Aid}) -> + gen_sctp:eof(Sock, #sctp_assoc_change{assoc_id = Aid}). + + +%% vim:set ts=4 sw=4 et: diff --git a/src/sctp_proxy.erl b/src/sctp_proxy.erl index 4ea5e19..94ff36a 100644 --- a/src/sctp_proxy.erl +++ b/src/sctp_proxy.erl @@ -197,7 +197,7 @@ {forward, FwdData} -> sctp_server:send_data(EnbAid, FwdData); {reply, ReData} -> - ok = sctp_client:send_data({Sock, Aid}, ReData) + ok = sctp_common:send_data({Sock, Aid}, ReData) end, {keep_state, S};
@@ -240,7 +240,7 @@ case S of #{sock := Sock, mme_aid := Aid} -> - sctp_client:disconnect({Sock, Aid}), + sctp_common:shutdown({Sock, Aid}), gen_sctp:close(Sock); #{sock := Sock} -> gen_sctp:close(Sock); @@ -260,7 +260,7 @@ handler := Pid}) -> case s1ap_proxy:process_pdu(Pid, Data) of {forward, FwdData} -> - ok = sctp_client:send_data({Sock, Aid}, FwdData); + ok = sctp_common:send_data({Sock, Aid}, FwdData); {reply, ReData} -> sctp_server:send_data(EnbAid, ReData) end. diff --git a/src/sctp_server.erl b/src/sctp_server.erl index f269afe..27752d8 100644 --- a/src/sctp_server.erl +++ b/src/sctp_server.erl @@ -131,11 +131,9 @@ {reply, {error, not_implemented}, S}.
-handle_cast({send_data, Aid, Data}, S) -> - gen_sctp:send(S#server_state.sock, - #sctp_sndrcvinfo{stream = ?S1AP_SCTP_STREAM, - ppid = ?S1AP_SCTP_PPID, - assoc_id = Aid}, Data), +handle_cast({send_data, Aid, Data}, + #server_state{sock = Sock} = S) -> + sctp_common:send_data({Sock, Aid}, Data), {noreply, S};
handle_cast(Info, S) -> @@ -154,8 +152,8 @@ ?LOG_DEBUG("Child process ~p terminated with reason ~p", [Pid, Reason]), case client_find(Pid, S0) of {ok, {Aid, C0}} -> - %% gracefully close the eNB connection - gen_sctp:eof(Sock, #sctp_assoc_change{assoc_id = Aid}), + %% shutdown the eNB connection gracefully + sctp_common:shutdown({Sock, Aid}), %% invalidate pid in the client's state C1 = C0#client_state{pid = undefined}, S1 = S0#server_state{clients = dict:store(Aid, C1, Clients)}, @@ -291,8 +289,8 @@ %% the handler process might be already dead, so we guard %% against exceptions like noproc or {nodedown,Node}. catch Handler:shutdown(Client#client_state.pid), - %% gracefully close an eNB connection - gen_sctp:eof(Sock, #sctp_assoc_change{assoc_id = Aid}), + %% shutdown an eNB connection gracefully + sctp_common:shutdown({Sock, Aid}), %% ... and so for the remaining clients close_conns(Sock, Handler, Clients);