Initial (building) start of OsmoCBC (Cell Broadcast Centre)
this is far from doing anything useful yet. Stay tuned. Change-Id: I64a6833ce068db60d713d0fa318a1d8093e37be9changes/50/16450/1
parent
6c8bf25d11
commit
63b7905fa3
|
@ -0,0 +1,59 @@
|
|||
*.o
|
||||
*.a
|
||||
*.lo
|
||||
*.la
|
||||
.deps
|
||||
Makefile
|
||||
Makefile.in
|
||||
config.h
|
||||
config.h.in
|
||||
|
||||
#configure
|
||||
aclocal.m4
|
||||
autom4te.cache/
|
||||
compile
|
||||
config.log
|
||||
config.status
|
||||
configure
|
||||
configure.lineno
|
||||
depcomp
|
||||
install-sh
|
||||
missing
|
||||
stamp-h1
|
||||
|
||||
# libtool
|
||||
ltmain.sh
|
||||
libtool
|
||||
.libs
|
||||
|
||||
# git-version-gen magic
|
||||
.tarball-version
|
||||
.version
|
||||
|
||||
# apps and app data
|
||||
src/osmo-cbc
|
||||
|
||||
#tests
|
||||
tests/*/*_test
|
||||
|
||||
tests/atconfig
|
||||
tests/package.m4
|
||||
tests/testsuite
|
||||
tests/testsuite.log
|
||||
|
||||
*.pc
|
||||
config.*
|
||||
|
||||
tags
|
||||
/Doxyfile
|
||||
|
||||
# manuals
|
||||
doc/manuals/*.html
|
||||
doc/manuals/*.svg
|
||||
doc/manuals/*.pdf
|
||||
doc/manuals/*__*.png
|
||||
doc/manuals/*.check
|
||||
doc/manuals/generated/
|
||||
doc/manuals/osmomsc-usermanual.xml
|
||||
doc/manuals/common
|
||||
doc/manuals/build
|
|
@ -0,0 +1,17 @@
|
|||
AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6
|
||||
|
||||
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
|
||||
SUBDIRS = src
|
||||
|
||||
EXTRA_DIST = .version git-version-gen osmoappdesc.py doc/examples/osmo-cbc.cfg
|
||||
|
||||
AM_DISTCHECK_CONFIGURE_FLAGS = \
|
||||
--with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
|
||||
|
||||
@RELMAKE@
|
||||
|
||||
BUILT_SOURCES = $(top_srcdir)/.version
|
||||
$(top_srcdir)/.version:
|
||||
echo $(VERSION) > $@-t && mv $@-t $@
|
||||
dist-hook:
|
||||
echo $(VERSION) > $(distdir)/.tarball-version
|
|
@ -0,0 +1,169 @@
|
|||
dnl Process this file with autoconf to produce a configure script
|
||||
AC_INIT([osmo-cbc],
|
||||
m4_esyscmd([./git-version-gen .tarball-version]),
|
||||
[openbsc@lists.osmocom.org])
|
||||
|
||||
dnl *This* is the root dir, even if an install-sh exists in ../ or ../../
|
||||
AC_CONFIG_AUX_DIR([.])
|
||||
|
||||
AM_INIT_AUTOMAKE([dist-bzip2])
|
||||
AC_CONFIG_TESTDIR(tests)
|
||||
|
||||
dnl kernel style compile messages
|
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
|
||||
dnl include release helper
|
||||
RELMAKE='-include osmo-release.mk'
|
||||
AC_SUBST([RELMAKE])
|
||||
|
||||
dnl checks for programs
|
||||
AC_PROG_MAKE_SET
|
||||
AC_PROG_CC
|
||||
AC_PROG_INSTALL
|
||||
LT_INIT
|
||||
|
||||
dnl check for pkg-config (explained in detail in libosmocore/configure.ac)
|
||||
AC_PATH_PROG(PKG_CONFIG_INSTALLED, pkg-config, no)
|
||||
if test "x$PKG_CONFIG_INSTALLED" = "xno"; then
|
||||
AC_MSG_WARN([You need to install pkg-config])
|
||||
fi
|
||||
PKG_PROG_PKG_CONFIG([0.20])
|
||||
|
||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.0.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.0.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.0.0)
|
||||
PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 0.4.0)
|
||||
|
||||
AC_ARG_ENABLE(sanitize,
|
||||
[AS_HELP_STRING(
|
||||
[--enable-sanitize],
|
||||
[Compile with address sanitizer enabled],
|
||||
)],
|
||||
[sanitize=$enableval], [sanitize="no"])
|
||||
if test x"$sanitize" = x"yes"
|
||||
then
|
||||
CFLAGS="$CFLAGS -fsanitize=address -fsanitize=undefined"
|
||||
CPPFLAGS="$CPPFLAGS -fsanitize=address -fsanitize=undefined"
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(werror,
|
||||
[AS_HELP_STRING(
|
||||
[--enable-werror],
|
||||
[Turn all compiler warnings into errors, with exceptions:
|
||||
a) deprecation (allow upstream to mark deprecation without breaking builds);
|
||||
b) "#warning" pragmas (allow to remind ourselves of errors without breaking builds)
|
||||
]
|
||||
)],
|
||||
[werror=$enableval], [werror="no"])
|
||||
if test x"$werror" = x"yes"
|
||||
then
|
||||
WERROR_FLAGS="-Werror"
|
||||
WERROR_FLAGS+=" -Wno-error=deprecated -Wno-error=deprecated-declarations"
|
||||
WERROR_FLAGS+=" -Wno-error=cpp" # "#warning"
|
||||
CFLAGS="$CFLAGS $WERROR_FLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $WERROR_FLAGS"
|
||||
fi
|
||||
|
||||
# The following test is taken from WebKit's webkit.m4
|
||||
saved_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -fvisibility=hidden "
|
||||
AC_MSG_CHECKING([if ${CC} supports -fvisibility=hidden])
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([char foo;])],
|
||||
[ AC_MSG_RESULT([yes])
|
||||
SYMBOL_VISIBILITY="-fvisibility=hidden"],
|
||||
AC_MSG_RESULT([no]))
|
||||
CFLAGS="$saved_CFLAGS"
|
||||
AC_SUBST(SYMBOL_VISIBILITY)
|
||||
|
||||
CFLAGS="$CFLAGS -Wall"
|
||||
CPPFLAGS="$CPPFLAGS -Wall"
|
||||
|
||||
AC_ARG_ENABLE(doxygen,
|
||||
[AS_HELP_STRING(
|
||||
[--disable-doxygen],
|
||||
[Disable generation of documentation using doxygen],
|
||||
)],
|
||||
[doxygen=$enableval], [doxygen="yes"])
|
||||
AC_PATH_PROG(DOXYGEN,doxygen,false)
|
||||
AM_CONDITIONAL(HAVE_DOXYGEN, test $DOXYGEN != false && test "x$doxygen" = "xyes")
|
||||
|
||||
# Generate manuals
|
||||
AC_ARG_ENABLE(manuals,
|
||||
[AS_HELP_STRING(
|
||||
[--enable-manuals],
|
||||
[Generate manual PDFs [default=no]],
|
||||
)],
|
||||
[osmo_ac_build_manuals=$enableval], [osmo_ac_build_manuals="no"])
|
||||
AM_CONDITIONAL([BUILD_MANUALS], [test x"$osmo_ac_build_manuals" = x"yes"])
|
||||
AC_ARG_VAR(OSMO_GSM_MANUALS_DIR, [path to common osmo-gsm-manuals files, overriding pkg-config and "../osmo-gsm-manuals"
|
||||
fallback])
|
||||
if test x"$osmo_ac_build_manuals" = x"yes"
|
||||
then
|
||||
# Find OSMO_GSM_MANUALS_DIR (env, pkg-conf, fallback)
|
||||
if test -n "$OSMO_GSM_MANUALS_DIR"; then
|
||||
echo "checking for OSMO_GSM_MANUALS_DIR... $OSMO_GSM_MANUALS_DIR (from env)"
|
||||
else
|
||||
OSMO_GSM_MANUALS_DIR="$($PKG_CONFIG osmo-gsm-manuals --variable=osmogsmmanualsdir 2>/dev/null)"
|
||||
if test -n "$OSMO_GSM_MANUALS_DIR"; then
|
||||
echo "checking for OSMO_GSM_MANUALS_DIR... $OSMO_GSM_MANUALS_DIR (from pkg-conf)"
|
||||
else
|
||||
OSMO_GSM_MANUALS_DIR="../osmo-gsm-manuals"
|
||||
echo "checking for OSMO_GSM_MANUALS_DIR... $OSMO_GSM_MANUALS_DIR (fallback)"
|
||||
fi
|
||||
fi
|
||||
if ! test -d "$OSMO_GSM_MANUALS_DIR"; then
|
||||
AC_MSG_ERROR("OSMO_GSM_MANUALS_DIR does not exist! Install osmo-gsm-manuals or set OSMO_GSM_MANUALS_DIR.")
|
||||
fi
|
||||
|
||||
# Find and run check-depends
|
||||
CHECK_DEPENDS="$OSMO_GSM_MANUALS_DIR/check-depends.sh"
|
||||
if ! test -x "$CHECK_DEPENDS"; then
|
||||
CHECK_DEPENDS="osmo-gsm-manuals-check-depends"
|
||||
fi
|
||||
if ! $CHECK_DEPENDS; then
|
||||
AC_MSG_ERROR("missing dependencies for --enable-manuals")
|
||||
fi
|
||||
|
||||
# Put in Makefile with absolute path
|
||||
OSMO_GSM_MANUALS_DIR="$(realpath "$OSMO_GSM_MANUALS_DIR")"
|
||||
AC_SUBST([OSMO_GSM_MANUALS_DIR])
|
||||
fi
|
||||
|
||||
# https://www.freedesktop.org/software/systemd/man/daemon.html
|
||||
AC_ARG_WITH([systemdsystemunitdir],
|
||||
[AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files])],,
|
||||
[with_systemdsystemunitdir=auto])
|
||||
AS_IF([test "x$with_systemdsystemunitdir" = "xyes" -o "x$with_systemdsystemunitdir" = "xauto"], [
|
||||
def_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)
|
||||
AS_IF([test "x$def_systemdsystemunitdir" = "x"],
|
||||
[AS_IF([test "x$with_systemdsystemunitdir" = "xyes"],
|
||||
[AC_MSG_ERROR([systemd support requested but pkg-config unable to query systemd package])])
|
||||
with_systemdsystemunitdir=no],
|
||||
[with_systemdsystemunitdir="$def_systemdsystemunitdir"])])
|
||||
AS_IF([test "x$with_systemdsystemunitdir" != "xno"],
|
||||
[AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])])
|
||||
AM_CONDITIONAL([HAVE_SYSTEMD], [test "x$with_systemdsystemunitdir" != "xno"])
|
||||
|
||||
AC_ARG_ENABLE([external_tests],
|
||||
AC_HELP_STRING([--enable-external-tests],
|
||||
[Include the VTY/CTRL tests in make check [default=no]]),
|
||||
[enable_ext_tests="$enableval"],[enable_ext_tests="no"])
|
||||
if test "x$enable_ext_tests" = "xyes" ; then
|
||||
AM_PATH_PYTHON
|
||||
AC_CHECK_PROG(OSMOTESTEXT_CHECK,osmo_verify_transcript_vty.py,yes)
|
||||
if test "x$OSMOTESTEXT_CHECK" != "xyes" ; then
|
||||
AC_MSG_ERROR([Please install git://osmocom.org/python/osmo-python-tests to run the VTY/CTRL tests.])
|
||||
fi
|
||||
fi
|
||||
AC_MSG_CHECKING([whether to enable VTY/CTRL tests])
|
||||
AC_MSG_RESULT([$enable_ext_tests])
|
||||
AM_CONDITIONAL(ENABLE_EXT_TESTS, test "x$enable_ext_tests" = "xyes")
|
||||
|
||||
AC_MSG_RESULT([CFLAGS="$CFLAGS"])
|
||||
AC_MSG_RESULT([CPPFLAGS="$CPPFLAGS"])
|
||||
|
||||
AC_OUTPUT(
|
||||
src/Makefile
|
||||
contrib/Makefile
|
||||
contrib/systemd/Makefile
|
||||
Makefile)
|
|
@ -0,0 +1 @@
|
|||
SUBDIRS = systemd
|
|
@ -0,0 +1,61 @@
|
|||
#!/bin/sh
|
||||
# jenkins build helper script for osmo-cbc. This is how we build on jenkins.osmocom.org
|
||||
#
|
||||
# environment variables:
|
||||
# * WITH_MANUALS: build manual PDFs if set to "1"
|
||||
# * PUBLISH: upload manuals after building if set to "1" (ignored without WITH_MANUALS = "1")
|
||||
#
|
||||
|
||||
if ! [ -x "$(command -v osmo-build-dep.sh)" ]; then
|
||||
echo "Error: We need to have scripts/osmo-deps.sh from http://git.osmocom.org/osmo-ci/ in PATH !"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
|
||||
set -ex
|
||||
|
||||
base="$PWD"
|
||||
deps="$base/deps"
|
||||
inst="$deps/install"
|
||||
export deps inst
|
||||
|
||||
osmo-clean-workspace.sh
|
||||
|
||||
mkdir "$deps" || true
|
||||
|
||||
verify_value_string_arrays_are_terminated.py $(find . -name "*.[hc]")
|
||||
|
||||
export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
export LD_LIBRARY_PATH="$inst/lib"
|
||||
export PATH="$inst/bin:$PATH"
|
||||
|
||||
osmo-build-dep.sh libosmocore "" --disable-doxygen
|
||||
osmo-build-dep.sh libosmo-netif
|
||||
|
||||
# Additional configure options and depends
|
||||
CONFIG=""
|
||||
if [ "$WITH_MANUALS" = "1" ]; then
|
||||
osmo-build-dep.sh osmo-gsm-manuals
|
||||
CONFIG="--enable-manuals"
|
||||
fi
|
||||
|
||||
set +x
|
||||
echo
|
||||
echo
|
||||
echo
|
||||
echo " =============================== osmo-cbc ==============================="
|
||||
echo
|
||||
set -x
|
||||
|
||||
autoreconf --install --force
|
||||
./configure --enable-sanitize --enable-werror --enable-external-tests $CONFIG
|
||||
$MAKE $PARALLEL_MAKE
|
||||
DISTCHECK_CONFIGURE_FLAGS="--enable-external-tests $CONFIG" \
|
||||
$MAKE distcheck \
|
||||
|| cat-testlogs.sh
|
||||
|
||||
if [ "$WITH_MANUALS" = "1" ] && [ "$PUBLISH" = "1" ]; then
|
||||
make -C "$base/doc/manuals" publish
|
||||
fi
|
||||
|
||||
osmo-clean-workspace.sh
|
|
@ -0,0 +1,6 @@
|
|||
EXTRA_DIST = osmo-cbc.service
|
||||
|
||||
if HAVE_SYSTEMD
|
||||
systemdsystemunit_DATA = \
|
||||
osmo-cbc.service
|
||||
endif
|
|
@ -0,0 +1,11 @@
|
|||
[Unit]
|
||||
Description=Osmocom CBC (Cell Broadcasting Centre)
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=always
|
||||
ExecStart=/usr/bin/osmo-cbc -c /etc/osmocom/osmo-cbc.cfg
|
||||
RestartSec=2
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -0,0 +1,151 @@
|
|||
#!/bin/sh
|
||||
# Print a version string.
|
||||
scriptversion=2010-01-28.01
|
||||
|
||||
# Copyright (C) 2007-2010 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU 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 General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# This script is derived from GIT-VERSION-GEN from GIT: http://git.or.cz/.
|
||||
# It may be run two ways:
|
||||
# - from a git repository in which the "git describe" command below
|
||||
# produces useful output (thus requiring at least one signed tag)
|
||||
# - from a non-git-repo directory containing a .tarball-version file, which
|
||||
# presumes this script is invoked like "./git-version-gen .tarball-version".
|
||||
|
||||
# In order to use intra-version strings in your project, you will need two
|
||||
# separate generated version string files:
|
||||
#
|
||||
# .tarball-version - present only in a distribution tarball, and not in
|
||||
# a checked-out repository. Created with contents that were learned at
|
||||
# the last time autoconf was run, and used by git-version-gen. Must not
|
||||
# be present in either $(srcdir) or $(builddir) for git-version-gen to
|
||||
# give accurate answers during normal development with a checked out tree,
|
||||
# but must be present in a tarball when there is no version control system.
|
||||
# Therefore, it cannot be used in any dependencies. GNUmakefile has
|
||||
# hooks to force a reconfigure at distribution time to get the value
|
||||
# correct, without penalizing normal development with extra reconfigures.
|
||||
#
|
||||
# .version - present in a checked-out repository and in a distribution
|
||||
# tarball. Usable in dependencies, particularly for files that don't
|
||||
# want to depend on config.h but do want to track version changes.
|
||||
# Delete this file prior to any autoconf run where you want to rebuild
|
||||
# files to pick up a version string change; and leave it stale to
|
||||
# minimize rebuild time after unrelated changes to configure sources.
|
||||
#
|
||||
# It is probably wise to add these two files to .gitignore, so that you
|
||||
# don't accidentally commit either generated file.
|
||||
#
|
||||
# Use the following line in your configure.ac, so that $(VERSION) will
|
||||
# automatically be up-to-date each time configure is run (and note that
|
||||
# since configure.ac no longer includes a version string, Makefile rules
|
||||
# should not depend on configure.ac for version updates).
|
||||
#
|
||||
# AC_INIT([GNU project],
|
||||
# m4_esyscmd([build-aux/git-version-gen .tarball-version]),
|
||||
# [bug-project@example])
|
||||
#
|
||||
# Then use the following lines in your Makefile.am, so that .version
|
||||
# will be present for dependencies, and so that .tarball-version will
|
||||
# exist in distribution tarballs.
|
||||
#
|
||||
# BUILT_SOURCES = $(top_srcdir)/.version
|
||||
# $(top_srcdir)/.version:
|
||||
# echo $(VERSION) > $@-t && mv $@-t $@
|
||||
# dist-hook:
|
||||
# echo $(VERSION) > $(distdir)/.tarball-version
|
||||
|
||||
case $# in
|
||||
1) ;;
|
||||
*) echo 1>&2 "Usage: $0 \$srcdir/.tarball-version"; exit 1;;
|
||||
esac
|
||||
|
||||
tarball_version_file=$1
|
||||
nl='
|
||||
'
|
||||
|
||||
# First see if there is a tarball-only version file.
|
||||
# then try "git describe", then default.
|
||||
if test -f $tarball_version_file
|
||||
then
|
||||
v=`cat $tarball_version_file` || exit 1
|
||||
case $v in
|
||||
*$nl*) v= ;; # reject multi-line output
|
||||
[0-9]*) ;;
|
||||
*) v= ;;
|
||||
esac
|
||||
test -z "$v" \
|
||||
&& echo "$0: WARNING: $tarball_version_file seems to be damaged" 1>&2
|
||||
fi
|
||||
|
||||
if test -n "$v"
|
||||
then
|
||||
: # use $v
|
||||
elif
|
||||
v=`git describe --abbrev=4 --match='v*' HEAD 2>/dev/null \
|
||||
|| git describe --abbrev=4 HEAD 2>/dev/null` \
|
||||
&& case $v in
|
||||
[0-9]*) ;;
|
||||
v[0-9]*) ;;
|
||||
*) (exit 1) ;;
|
||||
esac
|
||||
then
|
||||
# Is this a new git that lists number of commits since the last
|
||||
# tag or the previous older version that did not?
|
||||
# Newer: v6.10-77-g0f8faeb
|
||||
# Older: v6.10-g0f8faeb
|
||||
case $v in
|
||||
*-*-*) : git describe is okay three part flavor ;;
|
||||
*-*)
|
||||
: git describe is older two part flavor
|
||||
# Recreate the number of commits and rewrite such that the
|
||||
# result is the same as if we were using the newer version
|
||||
# of git describe.
|
||||
vtag=`echo "$v" | sed 's/-.*//'`
|
||||
numcommits=`git rev-list "$vtag"..HEAD | wc -l`
|
||||
v=`echo "$v" | sed "s/\(.*\)-\(.*\)/\1-$numcommits-\2/"`;
|
||||
;;
|
||||
esac
|
||||
|
||||
# Change the first '-' to a '.', so version-comparing tools work properly.
|
||||
# Remove the "g" in git describe's output string, to save a byte.
|
||||
v=`echo "$v" | sed 's/-/./;s/\(.*\)-g/\1-/'`;
|
||||
else
|
||||
v=UNKNOWN
|
||||
fi
|
||||
|
||||
v=`echo "$v" |sed 's/^v//'`
|
||||
|
||||
# Don't declare a version "dirty" merely because a time stamp has changed.
|
||||
git status > /dev/null 2>&1
|
||||
|
||||
dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty=
|
||||
case "$dirty" in
|
||||
'') ;;
|
||||
*) # Append the suffix only if there isn't one already.
|
||||
case $v in
|
||||
*-dirty) ;;
|
||||
*) v="$v-dirty" ;;
|
||||
esac ;;
|
||||
esac
|
||||
|
||||
# Omit the trailing newline, so that m4_esyscmd can use the result directly.
|
||||
echo "$v" | tr -d '\012'
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# End:
|
|
@ -0,0 +1,9 @@
|
|||
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/src
|
||||
AM_CFLAGS=-Wall -g $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMONETIF_CFLAGS) $(COVERAGE_CFLAGS)
|
||||
AM_LDFLAGS=$(COVERAGE_LDFLAGS)
|
||||
|
||||
bin_PROGRAMS = osmo-cbc
|
||||
|
||||
osmo_cbc_SOURCES = cbc_main.c cbsp_server.c cbsp_server_fsm.c
|
||||
osmo_cbc_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMONETIF_LIBS)
|
||||
|
|
@ -0,0 +1,200 @@
|
|||
/* Osmocom CBC (Cell Broacast Centre) */
|
||||
|
||||
/* (C) 2019 by Harald Welte <laforge@gnumonks.org>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0+
|
||||
*
|
||||
* 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 Affero 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <osmocom/core/stats.h>
|
||||
#include <osmocom/core/select.h>
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/core/signal.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/core/logging.h>
|
||||
#include <osmocom/core/application.h>
|
||||
|
||||
#include <osmocom/vty/vty.h>
|
||||
#include <osmocom/vty/stats.h>
|
||||
#include <osmocom/vty/command.h>
|
||||
#include <osmocom/vty/ports.h>
|
||||
#include <osmocom/vty/telnet_interface.h>
|
||||
#include <osmocom/vty/logging.h>
|
||||
#include <osmocom/vty/misc.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "cbsp_server.h"
|
||||
|
||||
static void *tall_cbc_ctx;
|
||||
|
||||
static const struct log_info_cat log_info_cat[] = {
|
||||
[DCBSP] = {
|
||||
.name = "DCBSP",
|
||||
.description = "Cell Broadcast Service Protocol (CBC-BSC)",
|
||||
.color = "\033[1;31m",
|
||||
.enabled = 1,
|
||||
.loglevel = LOGL_NOTICE,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct log_info log_info = {
|
||||
.cat = log_info_cat,
|
||||
.num_cat = ARRAY_SIZE(log_info_cat),
|
||||
};
|
||||
|
||||
static const char cbc_copyright[] =
|
||||
"Copyright (C) 2019 by Harald Welte <laforge@gnumonks.org>\r\n"
|
||||
"License AGPLv3+: GNU Affero GPL Version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
|
||||
"This is free software: you are free ot change and redistribute it.\r\n"
|
||||
"There is NO WARRANTY, to the extent permitted by law.\r\n\r\n"
|
||||
"Free Software lives by contribution. If you use this, please contribute!\r\n";
|
||||
|
||||
static struct vty_app_info vty_info = {
|
||||
.name = "OsmoCBC",
|
||||
.copyright = cbc_copyright,
|
||||
.version = PACKAGE_VERSION,
|
||||
.go_parent_cb = NULL,
|
||||
.is_config_node = NULL,
|
||||
};
|
||||
|
||||
static struct {
|
||||
bool daemonize;
|
||||
const char *config_file;
|
||||
} cmdline_config = {
|
||||
.daemonize = false,
|
||||
.config_file = "osmo-cbc.cfg",
|
||||
};
|
||||
|
||||
static void print_help(void)
|
||||
{
|
||||
/* FIXME */
|
||||
}
|
||||
|
||||
static void handle_options(int argc, char **argv)
|
||||
{
|
||||
while (1) {
|
||||
int option_index = 0, c;
|
||||
static const struct option long_options[] = {
|
||||
{ "help", 0, 0, 'h' },
|
||||
{ "daemonize", 0, 0, 'D' },
|
||||
{ "config-file", 1, 0, 'c' },
|
||||
{ "version", 0, 0, 'V' },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "hDc:V", long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'h':
|
||||
print_help();
|
||||
exit(0);
|
||||
break;
|
||||
case 'D':
|
||||
cmdline_config.daemonize = true;
|
||||
break;
|
||||
case 'c':
|
||||
cmdline_config.config_file = optarg;
|
||||
break;
|
||||
case 'V':
|
||||
print_version(1);
|
||||
exit(0);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Error in command line options. Exiting\n");
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void signal_handler(int signal)
|
||||
{
|
||||
fprintf(stdout, "signal %d received\n", signal);
|
||||
|
||||
switch (signal){
|
||||
case SIGUSR1:
|
||||
talloc_report(tall_vty_ctx, stderr);
|
||||
talloc_report_full(tall_cbc_ctx, stderr);
|
||||
break;
|
||||
case SIGUSR2:
|
||||
talloc_report_full(tall_vty_ctx, stderr);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
extern int cbc_client_rx_cb(struct osmo_cbsp_cbc_client *client, struct osmo_cbsp_decoded *dec);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int rc;
|
||||
|
||||
tall_cbc_ctx = talloc_named_const(NULL, 1, "osmo-cbc");
|
||||
msgb_talloc_ctx_init(tall_cbc_ctx, 0);
|
||||
osmo_init_logging2(tall_cbc_ctx, &log_info);
|
||||
osmo_stats_init(tall_cbc_ctx);
|
||||
vty_init(&vty_info);
|
||||
|
||||
handle_options(argc, argv);
|
||||
|
||||
logging_vty_add_cmds();
|
||||
osmo_fsm_vty_add_cmds();
|
||||
|
||||
rc = vty_read_config_file(cmdline_config.config_file, NULL);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Failed ot parse the config file '%s'\n",
|
||||
cmdline_config.config_file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
rc = telnet_init_dynif(tall_cbc_ctx, NULL, vty_get_bind_addr(), OSMO_VTY_PORT_CBC);
|
||||
if (rc < 0) {
|
||||
perror("Error binding VTY port\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cbsp_cbc_create(tall_cbc_ctx, &cbc_client_rx_cb);
|
||||
|
||||
signal(SIGUSR1, &signal_handler);
|
||||
signal(SIGUSR2, &signal_handler);
|
||||
osmo_init_ignore_signals();
|
||||
|
||||
if (cmdline_config.daemonize) {
|
||||
rc = osmo_daemonize();
|
||||
if (rc < 0) {
|
||||
perror("Error during daemonize");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
while (1) {
|
||||
rc = osmo_select_main(0);
|
||||
if (rc < 0)
|
||||
exit(3);
|
||||
}
|
||||
}
|
|
@ -1,34 +1,38 @@
|
|||
/* (C) 2019 by Harald Welte <laforge@gnumonks.org>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0+
|
||||
*
|
||||
* 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 Affero 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/select.h>
|
||||
#include <osmocom/core/socket.h>
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/core/logging.h>
|
||||
#include <osmocom/gsm/cbsp.h>
|
||||
#include <osmocom/gsm/protocol/gsm_48_049.h>
|
||||
#include <osmocom/netif/stream.h>
|
||||
|
||||
/* a CBC server */
|
||||
struct osmo_cbsp_cbc {
|
||||
/* libosmo-netif stream server */
|
||||
struct osmo_stream_srv_link *link;
|
||||
|
||||
/* BSCs / clients connected to this CBC */
|
||||
struct llist_head clients;
|
||||
};
|
||||
|
||||
/* a single (remote) client connected to the (local) CBC server */
|
||||
struct osmo_cbsp_cbc_client {
|
||||
/* entry in osmo_cbsp_cbc.clients */
|
||||
struct llist_head list;
|
||||
/* stream server connection for this client */
|
||||
struct osmo_stream_srv *conn;
|
||||
/* partially received CBSP message (rx completion pending) */
|
||||
struct msgb *rx_msg;
|
||||
/* receive call-back; called for every received message */
|
||||
int (*rx_cb)(struct osmo_cbsp_cbc_client *client, struct osmo_cbsp_decoded *dec);
|
||||
};
|
||||
|
||||
#include "internal.h"
|
||||
#include "cbsp_server.h"
|
||||
|
||||
#if 0
|
||||
struct osmo_cbsp_bsc {
|
||||
|
@ -92,8 +96,9 @@ int osmo_cbsp_recv_buffered(int fd, struct msgb **rmsg, struct msgb **tmp_msg)
|
|||
msg->l2h = msg->tail;
|
||||
}
|
||||
|
||||
h = (struct cbsp_header *) msg->data;
|
||||
/* then read the length as specified in the header */
|
||||
len = h->len[0] << 16 | h->len[1] << 8 | h->len[0];
|
||||
len = h->len[0] << 16 | h->len[1] << 8 | h->len[2];
|
||||
|
||||
needed = len - msgb_l2len(msg);
|
||||
if (needed > 0) {
|
||||
|
@ -142,17 +147,25 @@ discard_msg:
|
|||
|
||||
|
||||
|
||||
|
||||
const char *cbsp_cbc_client_name(const struct osmo_cbsp_cbc_client *client)
|
||||
{
|
||||
struct osmo_fd *ofd = osmo_stream_srv_get_ofd(client->conn);
|
||||
return osmo_sock_get_name2(ofd->fd);
|
||||
}
|
||||
|
||||
/* data from BSC has arrived at CBC */
|
||||
static int cbsp_cbc_read_cb(struct osmo_stream_srv *conn)
|
||||
{
|
||||
struct osmo_stream_srv_link *link = osmo_stream_srv_get_master(conn);
|
||||
struct osmo_cbsp_cbc_client *client = osmo_stream_srv_get_data(conn);
|
||||
struct osmo_cbsp_cbc *cbc = osmo_stream_srv_link_get_data(link);
|
||||
struct osmo_fd *ofd = osmo_stream_srv_get_ofd(conn);
|
||||
struct osmo_cbsp_decoded *decoded;
|
||||
struct msgb *msg = NULL;
|
||||
int rc;
|
||||
|
||||
LOGPCC(client, LOGL_DEBUG, "read_cb rx_msg=%p\n", client->rx_msg);
|
||||
|
||||
/* message de-segmentation */
|
||||
rc = osmo_cbsp_recv_buffered(ofd->fd, &msg, &client->rx_msg);
|
||||
if (rc <= 0) {
|
||||
|
@ -163,16 +176,24 @@ static int cbsp_cbc_read_cb(struct osmo_stream_srv *conn)
|
|||
/* lost connection with server */
|
||||
} else if (rc == 0) {
|
||||
/* connection closed with server */
|
||||
|
||||
}
|
||||
/* destroy connection */
|
||||
osmo_stream_srv_destroy(conn);
|
||||
return -EBADF;
|
||||
}
|
||||
OSMO_ASSERT(msg);
|
||||
LOGPCC(client, LOGL_DEBUG, "Received CBSP %s\n", msgb_hexdump(msg));
|
||||
/* decode + dispatch message */
|
||||
decoded = osmo_cbsp_decode(client, msg);
|
||||
if (decoded) {
|
||||
LOGPCC(client, LOGL_INFO, "Received CBSP %s\n",
|
||||
get_value_string(cbsp_msg_type_names, decoded->msg_type));
|
||||
cbc->rx_cb(client, decoded);
|
||||
} else {
|
||||
LOGPCC(client, LOGL_ERROR, "Unable to decode %s\n", msgb_hexdump(msg));
|
||||
}
|
||||
msgb_free(msg);
|
||||
if (decoded)
|
||||
client->rx_cb(client, decoded);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -180,6 +201,7 @@ static int cbsp_cbc_read_cb(struct osmo_stream_srv *conn)
|
|||
static int cbsp_cbc_closed_cb(struct osmo_stream_srv *conn)
|
||||
{
|
||||
struct osmo_cbsp_cbc_client *client = osmo_stream_srv_get_data(conn);
|
||||
LOGPCC(client, LOGL_INFO, "connection closed\n");
|
||||
llist_del(&client->list);
|
||||
talloc_free(client);
|
||||
return 0;
|
||||
|
@ -194,9 +216,19 @@ static int cbsp_cbc_accept_cb(struct osmo_stream_srv_link *link, int fd)
|
|||
|
||||
client->conn = osmo_stream_srv_create(link, link, fd, cbsp_cbc_read_cb, cbsp_cbc_closed_cb, client);
|
||||
if (!client->conn) {
|
||||
LOGP(DCBSP, LOGL_ERROR, "Unable to create stream server for %s\n",
|
||||
osmo_sock_get_name2(fd));
|
||||
talloc_free(client);
|
||||
return -1;
|
||||
}
|
||||
client->fi = osmo_fsm_inst_alloc(&cbsp_server_fsm, client, client, LOGL_DEBUG, NULL);
|
||||
if (!client->fi) {
|
||||
LOGPCC(client, LOGL_ERROR, "Unable to allocate FSM\n");
|
||||
osmo_stream_srv_destroy(client->conn);
|
||||
talloc_free(client);
|
||||
return -1;
|
||||
}
|
||||
LOGPCC(client, LOGL_INFO, "New CBSP client connection\n");
|
||||
llist_add_tail(&client->list, &cbc->clients);
|
||||
|
||||
return 0;
|
||||
|
@ -205,29 +237,37 @@ static int cbsp_cbc_accept_cb(struct osmo_stream_srv_link *link, int fd)
|
|||
void cbsp_cbc_client_tx(struct osmo_cbsp_cbc_client *client, struct osmo_cbsp_decoded *cbsp)
|
||||
{
|
||||
struct msgb *msg = osmo_cbsp_encode(cbsp);
|
||||
talloc_free(cbsp);
|
||||
LOGPCC(client, LOGL_INFO, "Transmitting %s\n",
|
||||
get_value_string(cbsp_msg_type_names, cbsp->msg_type));
|
||||
if (!msg) {
|
||||
/* FIXME */
|
||||
LOGPCC(client, LOGL_ERROR, "Failed to encode CBSP %s\n",
|
||||
get_value_string(cbsp_msg_type_names, cbsp->msg_type));
|
||||
talloc_free(cbsp);
|
||||
return;
|
||||
}
|
||||
talloc_free(cbsp);
|
||||
osmo_stream_srv_send(client->conn, msg);
|
||||
}
|
||||
|
||||
/* initialize the CBC-side CBSP server */
|
||||
struct osmo_cbsp_cbc *cbsp_cbc_create(void *ctx)
|
||||
struct osmo_cbsp_cbc *cbsp_cbc_create(void *ctx, int (*rx_cb)(struct osmo_cbsp_cbc_client *client,
|
||||
struct osmo_cbsp_decoded *dec))
|
||||
{
|
||||
struct osmo_cbsp_cbc *cbc = talloc_zero(ctx, struct osmo_cbsp_cbc);
|
||||
int rc;
|
||||
|
||||
OSMO_ASSERT(cbc);
|
||||
cbc->rx_cb = rx_cb;
|
||||
INIT_LLIST_HEAD(&cbc->clients);
|
||||
cbc->link = osmo_stream_srv_link_create(cbc);
|
||||
osmo_stream_srv_link_set_data(cbc->link, cbc);
|
||||
osmo_stream_srv_link_set_nodelay(cbc->link, true);
|
||||
osmo_stream_srv_link_set_port(cbc->link, 48049);
|
||||
osmo_stream_srv_link_set_port(cbc->link, CBSP_TCP_PORT);
|
||||
osmo_stream_srv_link_set_accept_cb(cbc->link, cbsp_cbc_accept_cb);
|
||||
rc = osmo_stream_srv_link_open(cbc->link);
|
||||
OSMO_ASSERT(rc == 0);
|
||||
LOGP(DCBSP, LOGL_NOTICE, "Listening for CBSP at %s\n",
|
||||
osmo_stream_srv_link_get_sockname(cbc->link));
|
||||
|
||||
return cbc;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
#pragma once
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/gsm/cbsp.h>
|
||||
#include <osmocom/netif/stream.h>
|
||||
|
||||
#define LOGPCC(client, level, fmt, args...) \
|
||||
LOGP(DCBSP, level, "%s: " fmt, cbsp_cbc_client_name(client), ## args)
|
||||
|
||||
struct osmo_cbsp_cbc_client;
|
||||
struct osmo_fsm_inst;
|
||||
|
||||
/* a CBC server */
|
||||
struct osmo_cbsp_cbc {
|
||||
/* libosmo-netif stream server */
|
||||
struct osmo_stream_srv_link *link;
|
||||
|
||||
/* BSCs / clients connected to this CBC */
|
||||
struct llist_head clients;
|
||||
|
||||
/* receive call-back; called for every received message */
|
||||
int (*rx_cb)(struct osmo_cbsp_cbc_client *client, struct osmo_cbsp_decoded *dec);
|
||||
};
|
||||
|
||||
/* a single (remote) client connected to the (local) CBC server */
|
||||
struct osmo_cbsp_cbc_client {
|
||||
/* entry in osmo_cbsp_cbc.clients */
|
||||
struct llist_head list;
|
||||
/* stream server connection for this client */
|
||||
struct osmo_stream_srv *conn;
|
||||
/* partially received CBSP message (rx completion pending) */
|
||||
struct msgb *rx_msg;
|
||||
|
||||
struct osmo_fsm_inst *fi;
|
||||
};
|
||||
|
||||
const char *cbsp_cbc_client_name(const struct osmo_cbsp_cbc_client *client);
|
||||
void cbsp_cbc_client_tx(struct osmo_cbsp_cbc_client *client, struct osmo_cbsp_decoded *cbsp);
|
||||
struct osmo_cbsp_cbc *cbsp_cbc_create(void *ctx, int (*rx_cb)(struct osmo_cbsp_cbc_client *client,
|
||||
struct osmo_cbsp_decoded *dec));
|
|
@ -0,0 +1,216 @@
|
|||
/* (C) 2019 by Harald Welte <laforge@gnumonks.org>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0+
|
||||
*
|
||||
* 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 Affero 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <osmocom/core/fsm.h>
|
||||
|
||||
#include <osmocom/gsm/cbsp.h>
|
||||
|
||||
#include "cbsp_server.h"
|
||||
#include "internal.h"
|
||||
|
||||
#define S(x) (1 << (x))
|
||||
|
||||
#define T_KEEPALIVE 1
|
||||
#define T_KEEPALIVE_SECS 30
|
||||
|
||||
#define T_WAIT_KEEPALIVE_RESP 2
|
||||
#define T_WAIT_KEEPALIVE_RESP_SECS 10
|
||||
|
||||
#define T_WAIT_RESET_RESP 3
|
||||
#define T_WAIT_RESET_RESP_SECS 5
|
||||
|
||||
enum cbsp_server_state {
|
||||
/* initial state after client TCP connection established */
|
||||
CBSP_SRV_S_INIT,
|
||||
/* RESET has been sent to BSC, waiting for response */
|
||||
CBSP_SRV_S_RESET_PENDING,
|
||||
/* Keep-Alive has been sent, waiting for response */
|
||||
CBSP_SRV_S_KEEPALIVE_PENDING,
|
||||
/* normal operation (idle) */
|
||||
CBSP_SRV_S_IDLE,
|
||||
};
|
||||
|
||||
static const struct value_string cbsp_server_event_names[] = {
|
||||
{ CBSP_SRV_E_RX_RST_COMPL, "Rx Reset Complete" },
|
||||
{ CBSP_SRV_E_RX_RST_FAIL, "Rx Reset Failure" },
|
||||
{ CBSP_SRV_E_RX_KA_COMPL, "Rx Keep-Alive Complete" },
|
||||
{ CBSP_SRV_E_RX_RESTART, "Rx Restart" },
|
||||
{ CBSP_SRV_E_CMD_RESET, "RESET.cmd" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static void cbsp_server_s_init(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||
{
|
||||
switch (event) {
|
||||
case CBSP_SRV_E_CMD_RESET:
|
||||
osmo_fsm_inst_state_chg(fi, CBSP_SRV_S_RESET_PENDING, 0, 0);
|
||||
break;
|
||||
default:
|
||||
OSMO_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void cbsp_server_s_reset_pending_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
|
||||
{
|
||||
struct osmo_cbsp_cbc_client *client = (struct osmo_cbsp_cbc_client *) fi->priv;
|
||||
struct osmo_cbsp_decoded *cbspd;
|
||||
|
||||
if (prev_state == CBSP_SRV_S_RESET_PENDING)
|
||||
return;
|
||||
|
||||
cbspd = talloc_zero(fi, struct osmo_cbsp_decoded);
|
||||
OSMO_ASSERT(cbspd);
|
||||
cbspd->msg_type = CBSP_MSGT_RESET;
|
||||
cbspd->u.reset.cell_list.id_discr = CELL_IDENT_BSS;
|
||||
INIT_LLIST_HEAD(&cbspd->u.reset.cell_list.list);
|
||||
|
||||
cbsp_cbc_client_tx(client, cbspd);
|
||||
/* wait for response */
|
||||
osmo_fsm_inst_state_chg(fi, CBSP_SRV_S_RESET_PENDING, T_WAIT_RESET_RESP_SECS,
|
||||
T_WAIT_RESET_RESP);
|
||||
}
|
||||
|
||||
static void cbsp_server_s_reset_pending(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||
{
|
||||
switch (event) {
|
||||
case CBSP_SRV_E_RX_RST_COMPL:
|
||||
osmo_fsm_inst_state_chg(fi, CBSP_SRV_S_IDLE, 0, 0);
|
||||
break;
|
||||
case CBSP_SRV_E_RX_RST_FAIL:
|
||||
osmo_fsm_inst_state_chg(fi, CBSP_SRV_S_IDLE, 0, 0);
|
||||
break;
|
||||
default:
|
||||
OSMO_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void cbsp_server_s_keepalive_pending(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||
{
|
||||
switch (event) {
|
||||
case CBSP_SRV_E_RX_KA_COMPL:
|
||||
break;
|
||||
default:
|
||||
OSMO_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* a bit of a hack to ensure the keep-aliver timer is started every time we enter
|
||||
* the IDLE state, without putting the burden on the caller of
|
||||
* osmo_fsm_inst_state_chg() to specify T_KEEPALIVE + T_KEEPALIVE_SECS */
|
||||
static void cbsp_server_s_idle_onenter(struct osmo_fsm_inst *fi, uint32_t old_state)
|
||||
{
|
||||
fi->T = T_KEEPALIVE;
|
||||
osmo_timer_schedule(&fi->timer, T_KEEPALIVE_SECS, 0);
|
||||
}
|
||||
|
||||
static void cbsp_server_s_idle(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||
{
|
||||
switch (event) {
|
||||
default:
|
||||
OSMO_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
static int cbsp_server_fsm_timer_cb(struct osmo_fsm_inst *fi)
|
||||
{
|
||||
struct osmo_cbsp_cbc_client *client = (struct osmo_cbsp_cbc_client *) fi->priv;
|
||||
struct osmo_cbsp_decoded *cbspd;
|
||||
|
||||
switch (fi->T) {
|
||||
case T_KEEPALIVE:
|
||||
/* send keepalive to peer */
|
||||
cbspd = talloc_zero(fi, struct osmo_cbsp_decoded);
|
||||
OSMO_ASSERT(cbspd);
|
||||
cbspd->msg_type = CBSP_MSGT_KEEP_ALIVE;
|
||||
cbspd->u.keep_alive.repetition_period = T_KEEPALIVE_SECS;
|
||||
cbsp_cbc_client_tx(client, cbspd);
|
||||
/* wait for response */
|
||||
osmo_fsm_inst_state_chg(fi, CBSP_SRV_S_KEEPALIVE_PENDING, T_WAIT_KEEPALIVE_RESP_SECS,
|
||||
T_WAIT_KEEPALIVE_RESP);
|
||||
return 0;
|
||||
case T_WAIT_KEEPALIVE_RESP:
|
||||
case T_WAIT_RESET_RESP:
|
||||
/* ask core to terminate FSM which will terminate TCP connection */
|
||||
return 1;
|
||||
default:
|
||||
OSMO_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct osmo_fsm_state cbsp_server_fsm_states[] = {
|
||||
[CBSP_SRV_S_INIT] = {
|
||||
.name = "INIT",
|
||||
.in_event_mask = S(CBSP_SRV_E_CMD_RESET),
|
||||
.out_state_mask = S(CBSP_SRV_S_RESET_PENDING),
|
||||
.action = cbsp_server_s_init,
|
||||
},
|
||||
[CBSP_SRV_S_RESET_PENDING] = {
|
||||
.name = "RESET_PENDING",
|
||||
.in_event_mask = S(CBSP_SRV_E_RX_RST_COMPL) |
|
||||
S(CBSP_SRV_E_RX_RST_FAIL),
|
||||
.out_state_mask = S(CBSP_SRV_S_IDLE) |
|
||||
S(CBSP_SRV_S_RESET_PENDING),
|
||||
.action = cbsp_server_s_reset_pending,
|
||||
.onenter = cbsp_server_s_reset_pending_onenter,
|
||||
},
|
||||
[CBSP_SRV_S_KEEPALIVE_PENDING] = {
|
||||
.name = "KEEPALIVE_PENDING",
|
||||
.in_event_mask = S(CBSP_SRV_E_RX_KA_COMPL),
|
||||
.out_state_mask = S(CBSP_SRV_S_IDLE) |
|
||||
S(CBSP_SRV_S_KEEPALIVE_PENDING),
|
||||
.action = cbsp_server_s_keepalive_pending,
|
||||
},
|
||||
[CBSP_SRV_S_IDLE] = {
|
||||
.name = "IDLE",
|
||||
.in_event_mask = 0,
|
||||
.out_state_mask = S(CBSP_SRV_S_KEEPALIVE_PENDING),
|
||||
.action = cbsp_server_s_idle,
|
||||
.onenter = cbsp_server_s_idle_onenter,
|
||||
},
|
||||
};
|
||||
|
||||
struct osmo_fsm cbsp_server_fsm = {
|
||||
.name = "CBSP-SERVER",
|
||||
.states = cbsp_server_fsm_states,
|
||||
.num_states = ARRAY_SIZE(cbsp_server_fsm_states),
|
||||
.timer_cb = cbsp_server_fsm_timer_cb,
|
||||
.log_subsys = DCBSP,
|
||||
.event_names = cbsp_server_event_names,
|
||||
};
|
||||
|
||||
/* message was received from remote CBSP peer (BSC) */
|
||||
int cbc_client_rx_cb(struct osmo_cbsp_cbc_client *client, struct osmo_cbsp_decoded *dec)
|
||||
{
|
||||
switch (dec->msg_type) {
|
||||
case CBSP_MSGT_RESTART:
|
||||
osmo_fsm_inst_dispatch(client->fi, CBSP_SRV_E_RX_RESTART, dec);
|
||||
break;
|
||||
default:
|
||||
LOGPCC(client, LOGL_ERROR, "unknown/unhandled %s\n",
|
||||
get_value_string(cbsp_msg_type_names, dec->msg_type));
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __attribute__((constructor)) void on_dso_load_cbsp_srv_fsm(void)
|
||||
{
|
||||
osmo_fsm_register(&cbsp_server_fsm);
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
#include <osmocom/core/logging.h>
|
||||
#include <osmocom/core/fsm.h>
|
||||
|
||||
enum {
|
||||
DCBSP,
|
||||
};
|
||||
|
||||
extern struct osmo_fsm cbsp_server_fsm;
|
||||
|
||||
enum cbsp_server_event {
|
||||
CBSP_SRV_E_RX_RST_COMPL,
|
||||
CBSP_SRV_E_RX_RST_FAIL,
|
||||
CBSP_SRV_E_RX_KA_COMPL,
|
||||
CBSP_SRV_E_RX_RESTART,
|
||||
CBSP_SRV_E_CMD_RESET,
|
||||
};
|
Loading…
Reference in New Issue