summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThorsten Alteholz <debian@alteholz.de>2017-11-28 18:55:37 +0100
committerThorsten Alteholz <debian@alteholz.de>2018-04-09 19:46:24 +0200
commitb43c9cd3ac22673617613415fa17878d53d7f168 (patch)
treeec94b50759c9f2b015d1a717e2004dec62cea47f
parent13338adce55fd369fbff0f78fa4af2545899032b (diff)
parent2ad447fb95a63d80584b2792a4f4fbb6ddbfd55d (diff)
Import Debian changes 0.4.0-1
libosmo-abis (0.4.0-1) experimental; urgency=medium * New upstream release * debian/control: SONAME bump of libosmoabis6 and libosmotrau2 * debian/control: bump standard to 4.1.1 (no changes) * update symbols files * add spelling patch
-rw-r--r--.gitignore4
-rw-r--r--.gitreview3
-rw-r--r--Makefile.am4
-rw-r--r--README.md66
-rw-r--r--TODO-RELEASE8
-rw-r--r--configure.ac67
-rwxr-xr-xcontrib/jenkins.sh38
-rw-r--r--debian/changelog10
-rw-r--r--debian/control17
-rw-r--r--debian/libosmoabis5.symbols90
-rw-r--r--debian/libosmoabis6.install (renamed from debian/libosmoabis5.install)0
-rw-r--r--debian/libosmoabis6.symbols105
-rw-r--r--debian/libosmotrau1.symbols14
-rw-r--r--debian/libosmotrau2.install (renamed from debian/libosmotrau1.install)0
-rw-r--r--debian/libosmotrau2.symbols16
-rw-r--r--debian/patches/series1
-rw-r--r--debian/patches/spelling.patch15
-rw-r--r--debian/watch4
-rw-r--r--include/Makefile.am3
-rw-r--r--include/internal.h3
-rw-r--r--include/osmocom/abis/e1_input.h38
-rw-r--r--include/osmocom/abis/ipa.h6
-rw-r--r--include/osmocom/abis/lapd.h9
-rw-r--r--include/osmocom/abis/lapd_pcap.h4
-rw-r--r--include/osmocom/abis/unixsocket_proto.h31
-rw-r--r--include/osmocom/trau/osmo_ortp.h18
-rw-r--r--src/Makefile.am10
-rw-r--r--src/e1_input.c134
-rw-r--r--src/e1_input_vty.c44
-rw-r--r--src/input/dahdi.c156
-rw-r--r--src/input/ipa.c81
-rw-r--r--src/input/ipaccess.c70
-rw-r--r--src/input/lapd.c37
-rw-r--r--src/input/lapd_pcap.c41
-rw-r--r--src/input/misdn.c107
-rw-r--r--src/input/rs232.c2
-rw-r--r--src/input/unixsocket.c346
-rw-r--r--src/subchan_demux.c13
-rw-r--r--src/trau/osmo_ortp.c208
39 files changed, 1538 insertions, 285 deletions
diff --git a/.gitignore b/.gitignore
index fa9f1fc..08b34f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,10 +21,12 @@ missing
ltmain.sh
install-sh
stamp-h1
-libtool
#libosmo-abis-*
tests/*_test
+# libtool and e.g. arm-poky-linux-gnueabi-libtool
+*libtool
+
.tarball-version
.version
.dirstamp
diff --git a/.gitreview b/.gitreview
new file mode 100644
index 0000000..2e575db
--- /dev/null
+++ b/.gitreview
@@ -0,0 +1,3 @@
+[gerrit]
+host=gerrit.osmocom.org
+project=libosmo-abis
diff --git a/Makefile.am b/Makefile.am
index 9c82f09..a8774c4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -11,3 +11,7 @@ $(top_srcdir)/.version:
echo $(VERSION) > $@-t && mv $@-t $@
dist-hook:
echo $(VERSION) > $(distdir)/.tarball-version
+
+EXTRA_DIST = .version README.md
+
+@RELMAKE@
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..c5df874
--- /dev/null
+++ b/README.md
@@ -0,0 +1,66 @@
+libosmo-abis - Osmocom Abis interface library
+=============================================
+
+This repository contains a set of C-language libraries that form the
+A-bis interface library of [Osmocom](https://osmocom.org/) Open Source
+Mobile Communications projects such as OpenBSC / OsmoBSC.
+
+Historically, a lot of this code was developed as part of the
+[OpenBSC](https://osmocom.org/projects/openbsc) project, but which are
+of a more generic nature and thus useful to (at least) other programs
+that we develop in the sphere of Free Software / Open Source mobile
+communications.
+
+The libosmo-abis.git repository build multiple libraries:
+
+* **libosmoabis** contains some abstraction layer over E1/T1 and IP
+ based ETSI/3GPP A-bis interface. It can use mISDN and DAHDI as
+ underlying driver/hardware.
+* **libosmotrau** contains routines related to A-bis TRAU frame handling
+
+Homepage
+--------
+
+The official homepage of the project is
+<https://osmocom.org/projects/libosmo-abis>
+
+GIT Repository
+--------------
+
+You can clone from the official libosmo-abis.git repository using
+
+ git clone git://git.osmocom.org/libosmo-abis.git
+
+There is a cgit interface at <http://git.osmocom.org/libosmo-abis/>
+
+Documentation
+-------------
+
+There is no Doxygen-generated API documentation yet for this library. It
+would be great to some day have it, comparable to libosmocore.
+
+Mailing List
+------------
+
+Discussions related to libosmo-abis are happening on the
+openbsc@lists.osmocom.org mailing list, please see
+<https://lists.osmocom.org/mailman/listinfo/openbsc> for subscription
+options and the list archive.
+
+Please observe the [Osmocom Mailing List
+Rules](https://osmocom.org/projects/cellular-infrastructure/wiki/Mailing_List_Rules)
+when posting.
+
+Contributing
+------------
+
+Our coding standards are described at
+<https://osmocom.org/projects/cellular-infrastructure/wiki/Coding_standards>
+
+We us a gerrit based patch submission/review process for managing
+contributions. Please see
+<https://osmocom.org/projects/cellular-infrastructure/wiki/Gerrit> for
+more details
+
+The current patch queue for libosmo-abis can be seen at
+<https://gerrit.osmocom.org/#/q/project:libosmo-abis+status:open>
diff --git a/TODO-RELEASE b/TODO-RELEASE
index 43b1e8e..d0852fc 100644
--- a/TODO-RELEASE
+++ b/TODO-RELEASE
@@ -1 +1,9 @@
+# When cleaning up this file: bump API version in corresponding Makefile.am and rename corresponding debian/lib*.install
+# according to https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info
+# In short:
+# LIBVERSION=c:r:a
+# If the library source code has changed at all since the last update, then increment revision: c:r + 1:a.
+# If any interfaces have been added, removed, or changed since the last update: c + 1:0:0.
+# If any interfaces have been added since the last public release: c:r:a + 1.
+# If any interfaces have been removed or changed since the last public release: c:r:0.
#library what description / commit summary line
diff --git a/configure.ac b/configure.ac
index 7d88eb4..eb7733e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,20 +2,37 @@ AC_INIT([libosmo-abis],
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([foreign dist-bzip2 no-dist-gzip 1.6 subdir-objects])
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([pic-only])
+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])
+
AC_CONFIG_MACRO_DIR([m4])
+CFLAGS="$CFLAGS -Wall"
+CPPFLAGS="$CPPFLAGS -Wall"
+
# The following test is taken from WebKit's webkit.m4
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -fvisibility=hidden "
@@ -33,18 +50,50 @@ AM_CONFIG_HEADER(config.h)
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.3.0)
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.3.0)
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 0.3.10)
-PKG_CHECK_MODULES([ORTP], [ortp >= 0.13.1],
- [
- PKG_CHECK_MODULES([ORTP_VERSION], [ortp >= 0.21],
- [AC_DEFINE(HAVE_ORTP_021, 1,
- [libortp >= 0.21])],
- [AC_DEFINE(HAVE_ORTP_021, 0,
- [libortp < 0.21])])
- ]
-)
+PKG_CHECK_MODULES(ORTP, ortp >= 0.22.0)
AC_CHECK_HEADERS(dahdi/user.h,,AC_MSG_WARN(DAHDI input driver will not be built))
+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
+
+_cflags_save=$CFLAGS
+CFLAGS="$CFLAGS $ORTP_CFLAGS"
+AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <ortp/ortp.h>]],
+ [[ortp_set_log_level_mask(NULL, 0xffff);]]
+ )],
+ [AC_DEFINE([HAVE_ORTP_LOG_DOMAIN], [1],
+ [ortp_set_log_level_mask requires domain parameter])],
+ [AC_DEFINE([HAVE_ORTP_LOG_DOMAIN], [0],
+ [ortp_set_log_level_mask has no domain parameter])])
+CFLAGS=$_cflags_save
+
+_cflags_save=$CFLAGS
+CFLAGS="$CFLAGS $ORTP_CFLAGS"
+AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <ortp/ortp.h>
+ void fake_cb(struct _RtpSession *r, void *arg1, void *arg2, void *arg3) { return; }]],
+ [[rtp_session_signal_connect(NULL, "", fake_cb, (void*) fake_cb);]]
+ )],
+ [AC_DEFINE([RTP_SIGNAL_PTR_CAST(arg)], [(void*)(arg)],
+ [rtp_session_signal_connect requires pointer parameter])],
+ [AC_DEFINE([RTP_SIGNAL_PTR_CAST(arg)], [(unsigned long)(arg)],
+ [rtp_session_signal_connect requires ulong parameter])])
+CFLAGS=$_cflags_save
+
+
AC_OUTPUT(
libosmoabis.pc
libosmotrau.pc
diff --git a/contrib/jenkins.sh b/contrib/jenkins.sh
new file mode 100755
index 0000000..769d5a7
--- /dev/null
+++ b/contrib/jenkins.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+# jenkins build helper script for libosmo-abis. This is how we build on jenkins.osmocom.org
+
+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
+
+mkdir "$deps" || true
+rm -rf "$inst"
+
+osmo-build-dep.sh libosmocore
+
+"$deps"/libosmocore/contrib/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"
+
+set +x
+echo
+echo
+echo
+echo " =============================== libosmo-abis ==============================="
+echo
+set -x
+
+autoreconf --install --force
+./configure --enable-sanitize CFLAGS="-Werror" CPPFLAGS="-Werror"
+$MAKE $PARALLEL_MAKE
+$MAKE distcheck \
+ || cat-testlogs.sh
diff --git a/debian/changelog b/debian/changelog
index d2d3175..2e4b3bd 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,13 @@
+libosmo-abis (0.4.0-1) experimental; urgency=medium
+
+ * New upstream release
+ * debian/control: SONAME bump of libosmoabis6 and libosmotrau2
+ * debian/control: bump standard to 4.1.1 (no changes)
+ * update symbols files
+ * add spelling patch
+
+ -- Thorsten Alteholz <debian@alteholz.de> Tue, 28 Nov 2017 18:55:37 +0100
+
libosmo-abis (0.3.2+20151106git86fc3c8-3) unstable; urgency=medium
* debian/control: add myself to uploaders
diff --git a/debian/control b/debian/control
index 632f6f5..87988cf 100644
--- a/debian/control
+++ b/debian/control
@@ -6,15 +6,16 @@ Section: libs
Priority: optional
Build-Depends: debhelper (>= 10),
libdpkg-perl,
- libosmocore-dev,
+ libosmocore-dev (>= 0.9.1),
+ libtalloc-dev,
pkg-config,
libortp-dev
-Standards-Version: 4.1.0
+Standards-Version: 4.1.1
Vcs-Browser: https://anonscm.debian.org/cgit/debian-mobcom/libosmo-abis.git
Vcs-Git: https://anonscm.debian.org/git/debian-mobcom/libosmo-abis.git
Homepage: http://openbsc.osmocom.org/trac/wiki/libosmo-abis
-Package: libosmoabis5
+Package: libosmoabis6
Architecture: any
Multi-Arch: same
Depends: ${shlibs:Depends},
@@ -26,7 +27,7 @@ Description: GSM A-bis handling
It also implements drivers for mISDN and DAHDI based E1 cards, as well as some
A-bis/IP dialects.
-Package: libosmotrau1
+Package: libosmotrau2
Architecture: any
Multi-Arch: same
Depends: ${shlibs:Depends},
@@ -43,8 +44,8 @@ Architecture: any
Multi-Arch: same
Section: libdevel
Depends: ${misc:Depends},
- libosmotrau1 (= ${binary:Version}),
- libosmoabis5 (= ${binary:Version})
+ libosmotrau2 (= ${binary:Version}),
+ libosmoabis6 (= ${binary:Version})
Description: Development headers for A-bis interface
The libosmo-abis library contains common/shared code regarding the A-bis
interface between GSM BTS and BSC. This package in particular contains the
@@ -56,8 +57,8 @@ Description: Development headers for A-bis interface
#Multi-Arch: same
#Section: debug
#Priority: extra
-#Depends: libosmoabis5 (= ${binary:Version}),
-# libosmotrau1 (= ${binary:Version}),
+#Depends: libosmoabis6 (= ${binary:Version}),
+# libosmotrau2 (= ${binary:Version}),
# ${misc:Depends}
#Description: Debug symbols for A-bis interface
# The libosmo-abis library contains common/shared code regarding the A-bis
diff --git a/debian/libosmoabis5.symbols b/debian/libosmoabis5.symbols
deleted file mode 100644
index 82e65b7..0000000
--- a/debian/libosmoabis5.symbols
+++ /dev/null
@@ -1,90 +0,0 @@
-libosmoabis.so.5 libosmoabis5 #MINVER#
- abis_rsl_sendmsg@Base 0.3.2+20151106git86fc3c8
- abis_sendmsg@Base 0.3.2+20151106git86fc3c8
- decode_trau_frame@Base 0.3.2+20151106git86fc3c8
- e1_set_pcap_fd@Base 0.3.2+20151106git86fc3c8
- e1inp_close_socket@Base 0.3.2+20151106git86fc3c8
- e1inp_dlsap_up@Base 0.3.2+20151106git86fc3c8
- e1inp_driver_find@Base 0.3.2+20151106git86fc3c8
- e1inp_driver_list@Base 0.3.2+20151106git86fc3c8
- e1inp_driver_register@Base 0.3.2+20151106git86fc3c8
- e1inp_event@Base 0.3.2+20151106git86fc3c8
- e1inp_get_mux@Base 0.3.2+20151106git86fc3c8
- e1inp_init@Base 0.3.2+20151106git86fc3c8
- e1inp_ipa_bts_rsl_connect@Base 0.3.2+20151106git86fc3c8
- e1inp_ipa_bts_rsl_connect_n@Base 0.3.2+20151106git86fc3c8
- e1inp_ipaccess_init@Base 0.3.2+20151106git86fc3c8
- e1inp_line_bind_ops@Base 0.3.2+20151106git86fc3c8
- e1inp_line_clone@Base 0.3.2+20151106git86fc3c8
- e1inp_line_create@Base 0.3.2+20151106git86fc3c8
- e1inp_line_find@Base 0.3.2+20151106git86fc3c8
- e1inp_line_get@Base 0.3.2+20151106git86fc3c8
- e1inp_line_list@Base 0.3.2+20151106git86fc3c8
- e1inp_line_put@Base 0.3.2+20151106git86fc3c8
- e1inp_line_update@Base 0.3.2+20151106git86fc3c8
- e1inp_lookup_sign_link@Base 0.3.2+20151106git86fc3c8
- e1inp_misdn_init@Base 0.3.2+20151106git86fc3c8
- e1inp_node@Base 0.3.2+20151106git86fc3c8
- e1inp_rs232_init@Base 0.3.2+20151106git86fc3c8
- e1inp_rx_ts@Base 0.3.2+20151106git86fc3c8
- e1inp_rx_ts_lapd@Base 0.3.2+20151106git86fc3c8
- e1inp_sign_link_create@Base 0.3.2+20151106git86fc3c8
- e1inp_sign_link_destroy@Base 0.3.2+20151106git86fc3c8
- e1inp_signtype_name@Base 0.3.2+20151106git86fc3c8
- e1inp_ts_config_sign@Base 0.3.2+20151106git86fc3c8
- e1inp_ts_config_trau@Base 0.3.2+20151106git86fc3c8
- e1inp_tstype_name@Base 0.3.2+20151106git86fc3c8
- e1inp_tx_ts@Base 0.3.2+20151106git86fc3c8
- e1inp_vty_init@Base 0.3.2+20151106git86fc3c8
- encode_trau_frame@Base 0.3.2+20151106git86fc3c8
- ft_data_down_bits@Base 0.3.2+20151106git86fc3c8
- ft_fr_down_bits@Base 0.3.2+20151106git86fc3c8
- ft_idle_down_bits@Base 0.3.2+20151106git86fc3c8
- ipa_client_conn_clear_queue@Base 0.3.2+20151106git86fc3c8
- ipa_client_conn_close@Base 0.3.2+20151106git86fc3c8
- ipa_client_conn_create@Base 0.3.2+20151106git86fc3c8
- ipa_client_conn_destroy@Base 0.3.2+20151106git86fc3c8
- ipa_client_conn_open@Base 0.3.2+20151106git86fc3c8
- ipa_client_conn_send@Base 0.3.2+20151106git86fc3c8
- ipa_msg_push_header@Base 0.3.2+20151106git86fc3c8
- ipa_node@Base 0.3.2+20151106git86fc3c8
- ipa_proxy_vty_init@Base 0.3.2+20151106git86fc3c8
- ipa_server_conn_create@Base 0.3.2+20151106git86fc3c8
- ipa_server_conn_destroy@Base 0.3.2+20151106git86fc3c8
- ipa_server_conn_send@Base 0.3.2+20151106git86fc3c8
- ipa_server_link_close@Base 0.3.2+20151106git86fc3c8
- ipa_server_link_create@Base 0.3.2+20151106git86fc3c8
- ipa_server_link_destroy@Base 0.3.2+20151106git86fc3c8
- ipa_server_link_open@Base 0.3.2+20151106git86fc3c8
- ipaccess_bts_handle_ccm@Base 0.3.2+20151106git86fc3c8
- ipaccess_driver@Base 0.3.2+20151106git86fc3c8
- ipaccess_fd_cb@Base 0.3.2+20151106git86fc3c8
- lapd_instance_alloc@Base 0.3.2+20151106git86fc3c8
- lapd_instance_free@Base 0.3.2+20151106git86fc3c8
- lapd_profile_abis@Base 0.3.2+20151106git86fc3c8
- lapd_profile_isdn@Base 0.3.2+20151106git86fc3c8
- lapd_profile_sat@Base 0.3.2+20151106git86fc3c8
- lapd_receive@Base 0.3.2+20151106git86fc3c8
- lapd_sap_start@Base 0.3.2+20151106git86fc3c8
- lapd_sap_stop@Base 0.3.2+20151106git86fc3c8
- lapd_tei_alloc@Base 0.3.2+20151106git86fc3c8
- lapd_tei_states@Base 0.3.2+20151106git86fc3c8
- lapd_transmit@Base 0.3.2+20151106git86fc3c8
- libosmo_abis_ctx@Base 0.3.2+20151106git86fc3c8
- libosmo_abis_init@Base 0.3.2+20151106git86fc3c8
- misdn_driver@Base 0.3.2+20151106git86fc3c8
- misdn_lapd_driver@Base 0.3.2+20151106git86fc3c8
- osmo_pcap_lapd_close@Base 0.3.2+20151106git86fc3c8
- osmo_pcap_lapd_open@Base 0.3.2+20151106git86fc3c8
- osmo_pcap_lapd_write@Base 0.3.2+20151106git86fc3c8
- prim_names@Base 0.3.2+20151106git86fc3c8
- subch_demux_activate@Base 0.3.2+20151106git86fc3c8
- subch_demux_deactivate@Base 0.3.2+20151106git86fc3c8
- subch_demux_in@Base 0.3.2+20151106git86fc3c8
- subch_demux_init@Base 0.3.2+20151106git86fc3c8
- subchan_mux_enqueue@Base 0.3.2+20151106git86fc3c8
- subchan_mux_init@Base 0.3.2+20151106git86fc3c8
- subchan_mux_out@Base 0.3.2+20151106git86fc3c8
- tall_tqe_ctx@Base 0.3.2+20151106git86fc3c8
- trau_frame_up2down@Base 0.3.2+20151106git86fc3c8
- trau_idle_frame@Base 0.3.2+20151106git86fc3c8
diff --git a/debian/libosmoabis5.install b/debian/libosmoabis6.install
index 79c51a9..79c51a9 100644
--- a/debian/libosmoabis5.install
+++ b/debian/libosmoabis6.install
diff --git a/debian/libosmoabis6.symbols b/debian/libosmoabis6.symbols
new file mode 100644
index 0000000..5b9c03b
--- /dev/null
+++ b/debian/libosmoabis6.symbols
@@ -0,0 +1,105 @@
+libosmoabis.so.6 libosmoabis6 #MINVER#
+ abis_rsl_sendmsg@Base 0.4.0
+ abis_sendmsg@Base 0.4.0
+ decode_trau_frame@Base 0.4.0
+ e1_set_pcap_fd@Base 0.4.0
+ e1inp_close_socket@Base 0.4.0
+ e1inp_dlsap_up@Base 0.4.0
+ e1inp_driver_find@Base 0.4.0
+ e1inp_driver_list@Base 0.4.0
+ e1inp_driver_register@Base 0.4.0
+ e1inp_ericsson_set_altc@Base 0.4.0
+ e1inp_event@Base 0.4.0
+ e1inp_get_mux@Base 0.4.0
+ e1inp_init@Base 0.4.0
+ e1inp_ipa_bts_rsl_connect@Base 0.4.0
+ e1inp_ipa_bts_rsl_connect_n@Base 0.4.0
+ e1inp_ipa_get_bind_addr@Base 0.4.0
+ e1inp_ipa_set_bind_addr@Base 0.4.0
+ e1inp_ipaccess_init@Base 0.4.0
+ e1inp_line_bind_ops@Base 0.4.0
+ e1inp_line_clone@Base 0.4.0
+ e1inp_line_create@Base 0.4.0
+ e1inp_line_find@Base 0.4.0
+ e1inp_line_get@Base 0.4.0
+ e1inp_line_list@Base 0.4.0
+ e1inp_line_put@Base 0.4.0
+ e1inp_line_update@Base 0.4.0
+ e1inp_lookup_sign_link@Base 0.4.0
+ e1inp_misdn_init@Base 0.4.0
+ e1inp_node@Base 0.4.0
+ e1inp_rs232_init@Base 0.4.0
+ e1inp_rx_ts@Base 0.4.0
+ e1inp_rx_ts_lapd@Base 0.4.0
+ e1inp_sign_link_create@Base 0.4.0
+ e1inp_sign_link_destroy@Base 0.4.0
+ e1inp_sign_type_names@Base 0.4.0
+ e1inp_signal_names@Base 0.4.0
+ e1inp_signtype_name@Base 0.4.0
+ e1inp_ts_config_hdlc@Base 0.4.0
+ e1inp_ts_config_raw@Base 0.4.0
+ e1inp_ts_config_sign@Base 0.4.0
+ e1inp_ts_config_trau@Base 0.4.0
+ e1inp_ts_type_names@Base 0.4.0
+ e1inp_tstype_name@Base 0.4.0
+ e1inp_tx_ts@Base 0.4.0
+ e1inp_unixsocket_init@Base 0.4.0
+ e1inp_vty_init@Base 0.4.0
+ encode_trau_frame@Base 0.4.0
+ ft_data_down_bits@Base 0.4.0
+ ft_fr_down_bits@Base 0.4.0
+ ft_idle_down_bits@Base 0.4.0
+ ipa_client_conn_clear_queue@Base 0.4.0
+ ipa_client_conn_close@Base 0.4.0
+ ipa_client_conn_create@Base 0.4.0
+ ipa_client_conn_destroy@Base 0.4.0
+ ipa_client_conn_open@Base 0.4.0
+ ipa_client_conn_send@Base 0.4.0
+ ipa_msg_push_header@Base 0.4.0
+ ipa_node@Base 0.4.0
+ ipa_proxy_vty_init@Base 0.4.0
+ ipa_server_conn_ccm@Base 0.4.0
+ ipa_server_conn_create@Base 0.4.0
+ ipa_server_conn_destroy@Base 0.4.0
+ ipa_server_conn_send@Base 0.4.0
+ ipa_server_link_close@Base 0.4.0
+ ipa_server_link_create@Base 0.4.0
+ ipa_server_link_destroy@Base 0.4.0
+ ipa_server_link_open@Base 0.4.0
+ ipaccess_bts_handle_ccm@Base 0.4.0
+ ipaccess_driver@Base 0.4.0
+ ipaccess_fd_cb@Base 0.4.0
+ lapd_instance_alloc@Base 0.4.0
+ lapd_instance_free@Base 0.4.0
+ lapd_instance_set_profile@Base 0.4.0
+ lapd_profile_abis@Base 0.4.0
+ lapd_profile_abis_ericsson@Base 0.4.0
+ lapd_profile_isdn@Base 0.4.0
+ lapd_profile_sat@Base 0.4.0
+ lapd_receive@Base 0.4.0
+ lapd_sap_start@Base 0.4.0
+ lapd_sap_stop@Base 0.4.0
+ lapd_tei_alloc@Base 0.4.0
+ lapd_tei_states@Base 0.4.0
+ lapd_transmit@Base 0.4.0
+ libosmo_abis_ctx@Base 0.4.0
+ libosmo_abis_init@Base 0.4.0
+ misdn_driver@Base 0.4.0
+ misdn_lapd_driver@Base 0.4.0
+ osmo_pcap_lapd_close@Base 0.4.0
+ osmo_pcap_lapd_open@Base 0.4.0
+ osmo_pcap_lapd_set_fd@Base 0.4.0
+ osmo_pcap_lapd_write@Base 0.4.0
+ prim_names@Base 0.4.0
+ subch_demux_activate@Base 0.4.0
+ subch_demux_deactivate@Base 0.4.0
+ subch_demux_in@Base 0.4.0
+ subch_demux_init@Base 0.4.0
+ subchan_mux_enqueue@Base 0.4.0
+ subchan_mux_init@Base 0.4.0
+ subchan_mux_out@Base 0.4.0
+ tall_tqe_ctx@Base 0.4.0
+ tall_unixsocket_ctx@Base 0.4.0
+ trau_frame_up2down@Base 0.4.0
+ trau_idle_frame@Base 0.4.0
+ unixsocket_driver@Base 0.4.0
diff --git a/debian/libosmotrau1.symbols b/debian/libosmotrau1.symbols
deleted file mode 100644
index ac4d040..0000000
--- a/debian/libosmotrau1.symbols
+++ /dev/null
@@ -1,14 +0,0 @@
-libosmotrau.so.1 libosmotrau1 #MINVER#
- osmo_rtp_get_bound_addr@Base 0.3.2+20151106git86fc3c8
- osmo_rtp_get_bound_ip_port@Base 0.3.2+20151106git86fc3c8
- osmo_rtp_init@Base 0.3.2+20151106git86fc3c8
- osmo_rtp_send_frame@Base 0.3.2+20151106git86fc3c8
- osmo_rtp_socket_bind@Base 0.3.2+20151106git86fc3c8
- osmo_rtp_socket_connect@Base 0.3.2+20151106git86fc3c8
- osmo_rtp_socket_create@Base 0.3.2+20151106git86fc3c8
- osmo_rtp_socket_free@Base 0.3.2+20151106git86fc3c8
- osmo_rtp_socket_log_stats@Base 0.3.2+20151106git86fc3c8
- osmo_rtp_socket_poll@Base 0.3.2+20151106git86fc3c8
- osmo_rtp_socket_set_param@Base 0.3.2+20151106git86fc3c8
- osmo_rtp_socket_set_pt@Base 0.3.2+20151106git86fc3c8
- osmo_rtp_socket_stats@Base 0.3.2+20151106git86fc3c8
diff --git a/debian/libosmotrau1.install b/debian/libosmotrau2.install
index 5a25619..5a25619 100644
--- a/debian/libosmotrau1.install
+++ b/debian/libosmotrau2.install
diff --git a/debian/libosmotrau2.symbols b/debian/libosmotrau2.symbols
new file mode 100644
index 0000000..8fce9ea
--- /dev/null
+++ b/debian/libosmotrau2.symbols
@@ -0,0 +1,16 @@
+libosmotrau.so.2 libosmotrau2 #MINVER#
+ osmo_rtp_get_bound_addr@Base 0.4.0
+ osmo_rtp_get_bound_ip_port@Base 0.4.0
+ osmo_rtp_init@Base 0.4.0
+ osmo_rtp_send_frame@Base 0.4.0
+ osmo_rtp_send_frame_ext@Base 0.4.0
+ osmo_rtp_skipped_frame@Base 0.4.0
+ osmo_rtp_socket_bind@Base 0.4.0
+ osmo_rtp_socket_connect@Base 0.4.0
+ osmo_rtp_socket_create@Base 0.4.0
+ osmo_rtp_socket_free@Base 0.4.0
+ osmo_rtp_socket_log_stats@Base 0.4.0
+ osmo_rtp_socket_poll@Base 0.4.0
+ osmo_rtp_socket_set_param@Base 0.4.0
+ osmo_rtp_socket_set_pt@Base 0.4.0
+ osmo_rtp_socket_stats@Base 0.4.0
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 0000000..5299247
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1 @@
+spelling.patch
diff --git a/debian/patches/spelling.patch b/debian/patches/spelling.patch
new file mode 100644
index 0000000..a123a1c
--- /dev/null
+++ b/debian/patches/spelling.patch
@@ -0,0 +1,15 @@
+Description: fix spelling that was detected by lintian
+Author: Thorsten Alteholz <debian@alteholz.de>
+Index: libosmo-abis-0.4.0/src/input/ipa.c
+===================================================================
+--- libosmo-abis-0.4.0.orig/src/input/ipa.c 2017-08-25 16:12:37.000000000 +0200
++++ libosmo-abis-0.4.0/src/input/ipa.c 2017-11-28 15:29:11.274860753 +0100
+@@ -265,7 +265,7 @@
+ ret = link->accept_cb(link, fd);
+ if (ret < 0) {
+ LOGP(DLINP, LOGL_ERROR,
+- "failed to processs accept()ed new link, "
++ "failed to process accept()ed new link, "
+ "reason=`%s'\n", strerror(-ret));
+ close(fd);
+ return ret;
diff --git a/debian/watch b/debian/watch
index 3a54a41..892feca 100644
--- a/debian/watch
+++ b/debian/watch
@@ -1,2 +1,2 @@
-version=3
-https://github.com/osmocom/libosmo-abis/releases /osmocom/libosmo-abis/archive/(\d\S+)\.tar\.(?:bz2|gz|xz)
+version=4
+opts="mode=git, dversionmangle=s/\+ds//" https://git.osmocom.org/libosmo-abis refs/tags/([\d\.]+) debian uupdate
diff --git a/include/Makefile.am b/include/Makefile.am
index 16fa506..2048520 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -3,4 +3,5 @@ noinst_HEADERS=mISDNif.h internal.h
nobase_include_HEADERS = osmocom/abis/ipa.h osmocom/abis/trau_frame.h \
osmocom/abis/ipa_proxy.h osmocom/abis/ipaccess.h osmocom/abis/abis.h \
osmocom/abis/subchan_demux.h osmocom/abis/e1_input.h \
- osmocom/abis/lapd.h osmocom/abis/lapd_pcap.h osmocom/trau/osmo_ortp.h
+ osmocom/abis/lapd.h osmocom/abis/lapd_pcap.h osmocom/trau/osmo_ortp.h \
+ osmocom/abis/unixsocket_proto.h
diff --git a/include/internal.h b/include/internal.h
index 7f6e31a..c931d4f 100644
--- a/include/internal.h
+++ b/include/internal.h
@@ -13,6 +13,9 @@ extern void *libosmo_abis_ctx;
/* use libosmo_abis_init, this is only for internal use. */
void e1inp_init(void);
+void e1inp_ipa_set_bind_addr(const char *ip_bind_addr);
+const char *e1inp_ipa_get_bind_addr(void);
+
/* ipaccess.c requires these functions defined here */
struct msgb;
struct msgb *ipa_msg_alloc(int headroom);
diff --git a/include/osmocom/abis/e1_input.h b/include/osmocom/abis/e1_input.h
index e5d2991..1a701f9 100644
--- a/include/osmocom/abis/e1_input.h
+++ b/include/osmocom/abis/e1_input.h
@@ -21,6 +21,7 @@ enum e1inp_sign_type {
E1INP_SIGN_OSMO, /* IPA CCM OSMO sub-type */
};
const char *e1inp_signtype_name(enum e1inp_sign_type tp);
+extern const struct value_string e1inp_sign_type_names[5];
enum e1inp_ctr {
E1I_CTR_HDLC_ABORT,
@@ -63,8 +64,11 @@ enum e1inp_ts_type {
E1INP_TS_TYPE_NONE,
E1INP_TS_TYPE_SIGN,
E1INP_TS_TYPE_TRAU,
+ E1INP_TS_TYPE_RAW,
+ E1INP_TS_TYPE_HDLC,
};
const char *e1inp_tstype_name(enum e1inp_ts_type tp);
+extern const struct value_string e1inp_ts_type_names[6];
/* A timeslot in the E1 interface */
struct e1inp_ts {
@@ -92,6 +96,18 @@ struct e1inp_ts {
/* subchannel muxer for frames to E1 */
struct subch_mux mux;
} trau;
+ struct {
+ /* call-back for every received frame */
+ void (*recv_cb)(struct e1inp_ts *ts, struct msgb *msg);
+ /* queue of pending to-be-transmitted msgbs */
+ struct llist_head tx_queue;
+ } raw;
+ struct {
+ /* call-back for every received frame */
+ void (*recv_cb)(struct e1inp_ts *ts, struct msgb *msg);
+ /* queue of pending to-be-transmitted msgbs */
+ struct llist_head tx_queue;
+ } hdlc;
};
union {
struct {
@@ -139,6 +155,7 @@ struct e1inp_driver {
void (*vty_show)(struct vty *vty, struct e1inp_line *line);
int default_delay;
int has_keepalive;
+ const char *bind_addr;
};
struct e1inp_line_ops {
@@ -166,6 +183,7 @@ struct e1inp_line {
unsigned int num;
const char *name;
unsigned int port_nr;
+ char *sock_path;
struct rate_ctr_group *rate_ctr;
/* keepalive configuration */
@@ -194,15 +212,14 @@ enum e1inp_signal_input {
S_L_INP_LINE_NOALARM,
};
+extern const struct value_string e1inp_signal_names[];
+
/* register a driver with the E1 core */
int e1inp_driver_register(struct e1inp_driver *drv);
/* fine a previously registered driver */
struct e1inp_driver *e1inp_driver_find(const char *name);
-/* register a line with the E1 core */
-int e1inp_line_register(struct e1inp_line *line);
-
/* get a line by its ID */
struct e1inp_line *e1inp_line_find(uint8_t e1_nr);
@@ -240,8 +257,15 @@ int e1inp_ts_config_trau(struct e1inp_ts *ts, struct e1inp_line *line,
int (*trau_rcv_cb)(struct subch_demux *dmx, int ch,
uint8_t *data, int len, void *_priv));
-/* Call from the Stack: configuration of this TS has changed */
-int e1inp_update_ts(struct e1inp_ts *ts);
+/* configure and initialize one timeslot dedicated to RAW frames */
+int e1inp_ts_config_raw(struct e1inp_ts *ts, struct e1inp_line *line,
+ void (*raw_recv_cb)(struct e1inp_ts *ts,
+ struct msgb *msg));
+
+/* configure and initialize one timeslot dedicated to HDLC frames */
+int e1inp_ts_config_hdlc(struct e1inp_ts *ts, struct e1inp_line *line,
+ void (*hdlc_recv_cb)(struct e1inp_ts *ts,
+ struct msgb *msg));
/* Receive a packet from the E1 driver */
int e1inp_rx_ts(struct e1inp_ts *ts, struct msgb *msg,
@@ -282,6 +306,9 @@ int e1inp_vty_init(void);
struct gsm_network;
int ipaccess_setup(struct gsm_network *gsmnet);
+/* activate superchannel or deactive to use timeslots. only valid for unixsocket driver */
+void e1inp_ericsson_set_altc(struct e1inp_line *unixlinue, int superchannel);
+
extern struct llist_head e1inp_driver_list;
extern struct llist_head e1inp_line_list;
@@ -290,6 +317,7 @@ struct input_signal_data {
int link_type;
uint8_t tei;
uint8_t sapi;
+ uint8_t ts_nr;
struct gsm_bts_trx *trx;
struct e1inp_line *line;
};
diff --git a/include/osmocom/abis/ipa.h b/include/osmocom/abis/ipa.h
index 6e9f9dd..a157889 100644
--- a/include/osmocom/abis/ipa.h
+++ b/include/osmocom/abis/ipa.h
@@ -35,9 +35,14 @@ struct ipa_server_conn {
struct osmo_fd ofd;
struct llist_head tx_queue;
int (*closed_cb)(struct ipa_server_conn *peer);
+ int (*ccm_cb)(struct ipa_server_conn *peer, struct msgb *msg,
+ struct tlv_parsed *tlvp, struct ipaccess_unit *ud);
int (*cb)(struct ipa_server_conn *peer, struct msgb *msg);
void *data;
struct msgb *pending_msg;
+ /* remote address information */
+ const char *addr;
+ uint16_t port;
};
struct ipa_server_conn *
@@ -48,6 +53,7 @@ ipa_server_conn_create(void *ctx, struct ipa_server_link *link, int fd,
void ipa_server_conn_destroy(struct ipa_server_conn *peer);
void ipa_server_conn_send(struct ipa_server_conn *peer, struct msgb *msg);
+int ipa_server_conn_ccm(struct ipa_server_conn *conn, struct msgb *msg);
enum ipa_client_conn_state {
IPA_CLIENT_LINK_STATE_NONE = 0,
diff --git a/include/osmocom/abis/lapd.h b/include/osmocom/abis/lapd.h
index 2987633..d618187 100644
--- a/include/osmocom/abis/lapd.h
+++ b/include/osmocom/abis/lapd.h
@@ -18,8 +18,10 @@ struct lapd_profile {
int short_address;
};
+/* predefined lapd profiles (see lapd.c for definition) */
extern const struct lapd_profile lapd_profile_isdn;
extern const struct lapd_profile lapd_profile_abis;
+extern const struct lapd_profile lapd_profile_abis_ericsson;
extern const struct lapd_profile lapd_profile_sat;
struct lapd_instance {
@@ -63,6 +65,13 @@ struct lapd_instance *lapd_instance_alloc(int network_side,
void *rx_cbdata), void *rx_cbdata,
const struct lapd_profile *profile);
+/* In rare cases (e.g. Ericsson's lapd dialect), it may be necessary to
+ * exchange the lapd profile on the fly. lapd_instance_set_profile()
+ * allwos to set the lapd profile on a lapd instance danymically to
+ * one of the lapd profiles define above. */
+void lapd_instance_set_profile(struct lapd_instance *li,
+ const struct lapd_profile *profile);
+
void lapd_instance_free(struct lapd_instance *li);
/* Start a (user-side) SAP for the specified TEI/SAPI on the LAPD instance */
diff --git a/include/osmocom/abis/lapd_pcap.h b/include/osmocom/abis/lapd_pcap.h
index 1c0d555..36ddd7f 100644
--- a/include/osmocom/abis/lapd_pcap.h
+++ b/include/osmocom/abis/lapd_pcap.h
@@ -1,10 +1,14 @@
#ifndef _LAPD_PCAP_H_
#define _LAPD_PCAP_H_
+#include <sys/types.h>
+#include <osmocom/core/msgb.h>
+
#define OSMO_LAPD_PCAP_INPUT 0
#define OSMO_LAPD_PCAP_OUTPUT 1
int osmo_pcap_lapd_open(char *filename, mode_t mode);
+int osmo_pcap_lapd_set_fd(int fd);
int osmo_pcap_lapd_write(int fd, int direction, struct msgb *msg);
int osmo_pcap_lapd_close(int fd);
diff --git a/include/osmocom/abis/unixsocket_proto.h b/include/osmocom/abis/unixsocket_proto.h
new file mode 100644
index 0000000..25718ff
--- /dev/null
+++ b/include/osmocom/abis/unixsocket_proto.h
@@ -0,0 +1,31 @@
+
+#ifndef UNIXSOCKET_PROTO_H
+#define UNIXSOCKET_PROTO_H
+
+/* The unix socket protocol is using a 2 byte header
+ * containg the version and type.
+ *
+ * header: | 1b version | 1b type |
+ *
+ * for data packets it would be
+ *
+ * data: | 0x1 | 0x0 | lapd ..|
+ * control: | 0x1 | 0x1 | control payload |
+ *
+ * Atm there is only one control packet:
+ * - set_altc (superchannel or timeslot)
+ *
+ * set_altc payload:
+ * | 4b magic | 1b new_state|
+ * | 0x23004200 | 0x0 | to timeslot
+ * | 0x23004200 | 0x1 | to superchannel
+ */
+
+#define UNIXSOCKET_PROTO_VERSION 0x1
+
+enum {
+ UNIXSOCKET_PROTO_DATA = 0x0,
+ UNIXSOCKET_PROTO_CONTROL = 0x1,
+};
+
+#endif /* UNIXSOCKET_PROTO_H */
diff --git a/include/osmocom/trau/osmo_ortp.h b/include/osmocom/trau/osmo_ortp.h
index c02cca8..578b1cb 100644
--- a/include/osmocom/trau/osmo_ortp.h
+++ b/include/osmocom/trau/osmo_ortp.h
@@ -2,6 +2,7 @@
#define _OSMO_ORTP_H
#include <stdint.h>
+#include <stdbool.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/select.h>
@@ -21,6 +22,15 @@ struct _RtpSession;
/*! \brief Osmocom pseudo-static paylaod type for Adaptive Multi Rate (AMR) */
#define RTP_PT_AMR 98
+#define GSM_VOICE_SAMPLE_RATE_HZ 8000
+#define GSM_VOICE_SAMPLES_PER_MS (GSM_VOICE_SAMPLE_RATE_HZ / 1000)
+#define GSM_VOICE_MULTIFRAME 26
+#define GSM_RTP_FRAME_DURATION_MS 20
+#define GSM_SAMPLES_PER_RTP_FRAME (GSM_RTP_FRAME_DURATION_MS * GSM_VOICE_SAMPLES_PER_MS)
+#define GSM_TDMA_FRAME_MS (120 / GSM_VOICE_MULTIFRAME)
+#define GSM_MS_TO_SAMPLES(ms) ((ms) * GSM_VOICE_SAMPLES_PER_MS)
+#define GSM_FN_TO_MS(fn) ((fn) * GSM_TDMA_FRAME_MS)
+
/*! \brief Parameter to osmo_rtp_socket_param_set() */
enum osmo_rtp_param {
OSMO_RTP_P_JITBUF = 1,
@@ -29,6 +39,7 @@ enum osmo_rtp_param {
/*! \brief Flag to indicate the socket is in polling-only mode */
#define OSMO_RTP_F_POLL 0x0001
+#define OSMO_RTP_F_DISABLED 0x0002
/*! \brief A structure representing one RTP socket */
struct osmo_rtp_socket {
@@ -44,7 +55,8 @@ struct osmo_rtp_socket {
/*! \brief callback for incoming data */
void (*rx_cb)(struct osmo_rtp_socket *rs, const uint8_t *payload,
- unsigned int payload_len);
+ unsigned int payload_len, uint16_t seq_number,
+ uint32_t timestamp, bool marker);
/*! \brief Receive user timestamp, to be incremented by user */
uint32_t rx_user_ts;
@@ -64,8 +76,12 @@ int osmo_rtp_socket_bind(struct osmo_rtp_socket *rs, const char *ip, int port);
int osmo_rtp_socket_connect(struct osmo_rtp_socket *rs, const char *ip, uint16_t port);
int osmo_rtp_socket_set_pt(struct osmo_rtp_socket *rs, int payload_type);
int osmo_rtp_socket_free(struct osmo_rtp_socket *rs);
+int osmo_rtp_skipped_frame(struct osmo_rtp_socket *rs, unsigned int duration);
int osmo_rtp_send_frame(struct osmo_rtp_socket *rs, const uint8_t *payload,
unsigned int payload_len, unsigned int duration);
+int osmo_rtp_send_frame_ext(struct osmo_rtp_socket *rs, const uint8_t *payload,
+ unsigned int payload_len, unsigned int duration,
+ bool marker);
int osmo_rtp_socket_poll(struct osmo_rtp_socket *rs);
int osmo_rtp_get_bound_ip_port(struct osmo_rtp_socket *rs,
diff --git a/src/Makefile.am b/src/Makefile.am
index b24f2cf..7395d17 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,7 +1,8 @@
# This is _NOT_ the library release version, it's an API version.
-# Please read Chapter 6 "Library interface versions" of the libtool documentation before making any modification
-ABIS_LIBVERSION=5:0:0
-TRAU_LIBVERSION=1:0:0
+# Please read chapter "Library interface versions" of the libtool documentation
+# before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html
+ABIS_LIBVERSION=6:0:0
+TRAU_LIBVERSION=2:0:0
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
AM_CFLAGS= -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
@@ -24,7 +25,8 @@ libosmoabis_la_SOURCES = init.c \
input/lapd.c \
input/lapd_pcap.c \
input/misdn.c \
- input/rs232.c
+ input/rs232.c \
+ input/unixsocket.c
libosmotrau_la_CFLAGS = $(AM_CFLAGS) $(ORTP_CFLAGS)
libosmotrau_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(TRAU_LIBVERSION)
diff --git a/src/e1_input.c b/src/e1_input.c
index c454b4a..3cf810f 100644
--- a/src/e1_input.c
+++ b/src/e1_input.c
@@ -28,21 +28,13 @@
#include <errno.h>
#include <string.h>
#include <time.h>
-#include <sys/fcntl.h>
+#include <fcntl.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
-#include <mISDNif.h>
#include <osmocom/abis/lapd.h>
-//#define AF_COMPATIBILITY_FUNC
-//#include <compat_af_isdn.h>
-#ifndef AF_ISDN
-#define AF_ISDN 34
-#define PF_ISDN AF_ISDN
-#endif
-
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/rate_ctr.h>
@@ -200,30 +192,31 @@ static void write_pcap_packet(int direction, int sapi, int tei,
write(pcap_fd, msg->l2h, msgb_l2len(msg));
}
-static const char *sign_types[] = {
- [E1INP_SIGN_NONE] = "None",
- [E1INP_SIGN_OML] = "OML",
- [E1INP_SIGN_RSL] = "RSL",
- [E1INP_SIGN_OSMO] = "OSMO",
+const struct value_string e1inp_sign_type_names[5] = {
+ { E1INP_SIGN_NONE, "None" },
+ { E1INP_SIGN_OML, "OML" },
+ { E1INP_SIGN_RSL, "RSL" },
+ { E1INP_SIGN_OSMO, "OSMO" },
+ { 0, NULL }
};
+
const char *e1inp_signtype_name(enum e1inp_sign_type tp)
{
- if (tp >= ARRAY_SIZE(sign_types))
- return "undefined";
- return sign_types[tp];
+ return get_value_string(e1inp_sign_type_names, tp);
}
-static const char *ts_types[] = {
- [E1INP_TS_TYPE_NONE] = "None",
- [E1INP_TS_TYPE_SIGN] = "Signalling",
- [E1INP_TS_TYPE_TRAU] = "TRAU",
+const struct value_string e1inp_ts_type_names[6] = {
+ { E1INP_TS_TYPE_NONE, "None" },
+ { E1INP_TS_TYPE_SIGN, "Signalling" },
+ { E1INP_TS_TYPE_TRAU, "TRAU" },
+ { E1INP_TS_TYPE_RAW, "RAW" },
+ { E1INP_TS_TYPE_HDLC, "HDLC" },
+ { 0, NULL }
};
const char *e1inp_tstype_name(enum e1inp_ts_type tp)
{
- if (tp >= ARRAY_SIZE(ts_types))
- return "undefined";
- return ts_types[tp];
+ return get_value_string(e1inp_ts_type_names, tp);
}
int abis_sendmsg(struct msgb *msg)
@@ -231,7 +224,7 @@ int abis_sendmsg(struct msgb *msg)
struct e1inp_sign_link *sign_link = msg->dst;
struct e1inp_driver *e1inp_driver;
struct e1inp_ts *e1i_ts;
-;
+
msg->l2h = msg->data;
/* don't know how to route this message. */
@@ -249,8 +242,14 @@ int abis_sendmsg(struct msgb *msg)
}
msgb_enqueue(&sign_link->tx_list, msg);
- /* dump it */
- write_pcap_packet(PCAP_OUTPUT, sign_link->sapi, sign_link->tei, msg);
+ /* we only need to write a 'Fake LAPD' packet here, if the
+ * underlying driver hides LAPD from us. If we use the
+ * libosmocore LAPD implementation, it will take care of writing
+ * the _actual_ LAPD packet */
+ if (!e1i_ts->lapd) {
+ write_pcap_packet(PCAP_OUTPUT, sign_link->sapi,
+ sign_link->tei, msg);
+ }
return 0;
}
@@ -294,6 +293,36 @@ int e1inp_ts_config_sign(struct e1inp_ts *ts, struct e1inp_line *line)
return 0;
}
+int e1inp_ts_config_raw(struct e1inp_ts *ts, struct e1inp_line *line,
+ void (*raw_recv_cb)(struct e1inp_ts *ts,
+ struct msgb *msg))
+{
+ if (ts->type == E1INP_TS_TYPE_RAW && ts->line && line)
+ return 0;
+
+ ts->type = E1INP_TS_TYPE_RAW;
+ ts->line = line;
+ ts->raw.recv_cb = raw_recv_cb;
+ INIT_LLIST_HEAD(&ts->raw.tx_queue);
+
+ return 0;
+}
+
+int e1inp_ts_config_hdlc(struct e1inp_ts *ts, struct e1inp_line *line,
+ void (*hdlc_recv_cb)(struct e1inp_ts *ts,
+ struct msgb *msg))
+{
+ if (ts->type == E1INP_TS_TYPE_HDLC && ts->line && line)
+ return 0;
+
+ ts->type = E1INP_TS_TYPE_HDLC;
+ ts->line = line;
+ ts->hdlc.recv_cb = hdlc_recv_cb;
+ INIT_LLIST_HEAD(&ts->hdlc.tx_queue);
+
+ return 0;
+}
+
struct e1inp_line *e1inp_line_find(uint8_t e1_nr)
{
struct e1inp_line *e1i_line;
@@ -335,6 +364,11 @@ e1inp_line_create(uint8_t e1_nr, const char *driver_name)
line->num = e1_nr;
line->rate_ctr = rate_ctr_group_alloc(line, &e1inp_ctr_g_d, line->num);
+ if (!line->rate_ctr) {
+ LOGP(DLINP, LOGL_ERROR, "Cannot allocate counter group\n");
+ talloc_free(line);
+ return NULL;
+ }
line->num_ts = NUM_E1_TS;
for (i = 0; i < line->num_ts; i++) {
@@ -499,8 +533,13 @@ int e1inp_rx_ts(struct e1inp_ts *ts, struct msgb *msg,
switch (ts->type) {
case E1INP_TS_TYPE_SIGN:
+ /* we only need to write a 'Fake LAPD' packet here, if
+ * the underlying driver hides LAPD from us. If we use
+ * the libosmocore LAPD implementation, it will take
+ * care of writing the _actual_ LAPD packet */
+ if (!ts->lapd)
+ write_pcap_packet(PCAP_INPUT, sapi, tei, msg);
/* consult the list of signalling links */
- write_pcap_packet(PCAP_INPUT, sapi, tei, msg);
link = e1inp_lookup_sign_link(ts, tei, sapi);
if (!link) {
LOGP(DLMI, LOGL_ERROR, "didn't find signalling link for "
@@ -521,6 +560,12 @@ int e1inp_rx_ts(struct e1inp_ts *ts, struct msgb *msg,
ret = subch_demux_in(&ts->trau.demux, msg->l2h, msgb_l2len(msg));
msgb_free(msg);
break;
+ case E1INP_TS_TYPE_RAW:
+ ts->raw.recv_cb(ts, msg);
+ break;
+ case E1INP_TS_TYPE_HDLC:
+ ts->hdlc.recv_cb(ts, msg);
+ break;
default:
ret = -EINVAL;
LOGP(DLMI, LOGL_ERROR, "unknown TS type %u\n", ts->type);
@@ -644,6 +689,14 @@ struct msgb *e1inp_tx_ts(struct e1inp_ts *e1i_ts,
}
msgb_put(msg, 40);
break;
+ case E1INP_TS_TYPE_RAW:
+ /* Get msgb from tx_queue */
+ msg = msgb_dequeue(&e1i_ts->raw.tx_queue);
+ break;
+ case E1INP_TS_TYPE_HDLC:
+ /* Get msgb from tx_queue */
+ msg = msgb_dequeue(&e1i_ts->hdlc.tx_queue);
+ break;
default:
LOGP(DLMI, LOGL_ERROR, "unsupported E1 TS type %u\n", e1i_ts->type);
return NULL;
@@ -656,6 +709,7 @@ static int e1inp_int_snd_event(struct e1inp_ts *ts,
{
struct input_signal_data isd;
isd.line = ts->line;
+ isd.ts_nr = ts->num;
isd.link_type = link->type;
isd.trx = link->trx;
isd.tei = link->tei;
@@ -712,7 +766,7 @@ struct e1inp_driver *e1inp_driver_find(const char *name)
int e1inp_line_update(struct e1inp_line *line)
{
struct input_signal_data isd;
- int rc;
+ int i, rc;
e1inp_line_get(line);
@@ -721,6 +775,15 @@ int e1inp_line_update(struct e1inp_line *line)
} else
rc = 0;
+ /* Set the PCAP file descriptor for all timeslots that have
+ * software LAPD instances, to ensure the osmo_lapd_pcap code is
+ * used to write PCAP files (if requested) */
+ for (i = 0; i < ARRAY_SIZE(line->ts); i++) {
+ struct e1inp_ts *e1i_ts = &line->ts[i];
+ if (e1i_ts->lapd)
+ e1i_ts->lapd->pcap_fd = pcap_fd;
+ }
+
/* Send a signal to anyone who is interested in new lines being
* configured */
memset(&isd, 0, sizeof(isd));
@@ -745,10 +808,22 @@ static int e1i_sig_cb(unsigned int subsys, unsigned int signal,
return 0;
}
+const struct value_string e1inp_signal_names[] = {
+ { S_L_INP_NONE, "NONE" },
+ { S_L_INP_TEI_UP, "TEI-UP" },
+ { S_L_INP_TEI_DN, "TEI-DOWN" },
+ { S_L_INP_TEI_UNKNOWN, "TEI-UNKNOWN" },
+ { S_L_INP_LINE_INIT, "LINE-INIT" },
+ { S_L_INP_LINE_ALARM, "LINE-ALARM" },
+ { S_L_INP_LINE_NOALARM, "LINE-NOALARM" },
+ { 0, NULL }
+};
+
void e1inp_misdn_init(void);
void e1inp_dahdi_init(void);
void e1inp_ipaccess_init(void);
void e1inp_rs232_init(void);
+void e1inp_unixsocket_init(void);
void e1inp_init(void)
{
@@ -763,4 +838,5 @@ void e1inp_init(void)
#endif
e1inp_ipaccess_init();
e1inp_rs232_init();
+ e1inp_unixsocket_init();
}
diff --git a/src/e1_input_vty.c b/src/e1_input_vty.c
index 0b4adb2..9d69586 100644
--- a/src/e1_input_vty.c
+++ b/src/e1_input_vty.c
@@ -38,12 +38,13 @@
/* CONFIG */
-#define E1_DRIVER_NAMES "(misdn|misdn_lapd|dahdi|ipa)"
+#define E1_DRIVER_NAMES "(misdn|misdn_lapd|dahdi|ipa|unixsocket)"
#define E1_DRIVER_HELP "mISDN supported E1 Card (kernel LAPD)\n" \
"mISDN supported E1 Card (userspace LAPD)\n" \
"DAHDI supported E1/T1/J1 Card\n" \
"IPA TCP/IP input\n" \
- "HSL TCP/IP input"
+ "HSL TCP/IP input\n" \
+ "Unix socket input\n"
#define E1_LINE_HELP "Configure E1/T1/J1 Line\n" "Line Number\n"
@@ -88,6 +89,25 @@ DEFUN(cfg_e1line_port, cfg_e1_line_port_cmd,
return CMD_SUCCESS;
}
+DEFUN(cfg_e1line_socket, cfg_e1_line_socket_cmd,
+ "e1_line <0-255> socket .SOCKET",
+ E1_LINE_HELP "Set socket path for unixsocket\n"
+ "socket path\n")
+{
+ struct e1inp_line *line;
+ int e1_nr = atoi(argv[0]);
+
+ line = e1inp_line_find(e1_nr);
+ if (!line) {
+ vty_out(vty, "%% Line %d doesn't exist%s", e1_nr, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ line->sock_path = talloc_strdup(line, argv[1]);
+
+ return CMD_SUCCESS;
+}
+
#define KEEPALIVE_HELP "Enable keep-alive probing\n"
static int set_keepalive_params(struct vty *vty, int e1_nr,
int idle, int num_probes, int probe_interval)
@@ -168,6 +188,17 @@ DEFUN(cfg_e1inp, cfg_e1inp_cmd,
return CMD_SUCCESS;
}
+DEFUN(cfg_ipa_bind,
+ cfg_ipa_bind_cmd,
+ "ipa bind A.B.C.D",
+ "ipa driver config\n"
+ "Set ipa local bind address\n"
+ "Listen on this IP address (default 0.0.0.0)\n")
+{
+ e1inp_ipa_set_bind_addr(argv[0]);
+ return CMD_SUCCESS;
+}
+
static int e1inp_config_write(struct vty *vty)
{
struct e1inp_line *line;
@@ -202,6 +233,12 @@ static int e1inp_config_write(struct vty *vty)
VTY_NEWLINE);
}
+
+ const char *ipa_bind = e1inp_ipa_get_bind_addr();
+ if (ipa_bind && (strcmp(ipa_bind, "0.0.0.0") != 0))
+ vty_out(vty, " ipa bind %s%s",
+ ipa_bind, VTY_NEWLINE);
+
return CMD_SUCCESS;
}
@@ -346,11 +383,14 @@ int e1inp_vty_init(void)
vty_install_default(L_E1INP_NODE);
install_element(L_E1INP_NODE, &cfg_e1_line_driver_cmd);
install_element(L_E1INP_NODE, &cfg_e1_line_port_cmd);
+ install_element(L_E1INP_NODE, &cfg_e1_line_socket_cmd);
install_element(L_E1INP_NODE, &cfg_e1_line_name_cmd);
install_element(L_E1INP_NODE, &cfg_e1_line_keepalive_cmd);
install_element(L_E1INP_NODE, &cfg_e1_line_keepalive_params_cmd);
install_element(L_E1INP_NODE, &cfg_e1_line_no_keepalive_cmd);
+ install_element(L_E1INP_NODE, &cfg_ipa_bind_cmd);
+
install_element_ve(&show_e1drv_cmd);
install_element_ve(&show_e1line_cmd);
install_element_ve(&show_e1ts_cmd);
diff --git a/src/input/dahdi.c b/src/input/dahdi.c
index 9f1f2bb..911f862 100644
--- a/src/input/dahdi.c
+++ b/src/input/dahdi.c
@@ -139,6 +139,7 @@ static void handle_dahdi_exception(struct e1inp_ts *ts)
get_value_string(dahdi_evt_names, evt));
isd.line = ts->line;
+ isd.ts_nr = ts->num;
switch (evt) {
case DAHDI_EVENT_ALARM:
@@ -251,13 +252,57 @@ static int handle_ts1_write(struct osmo_fd *bfd)
sign_link->sapi, msg);
/* set tx delay timer for next event */
- e1i_ts->sign.tx_timer.cb = timeout_ts1_write;
- e1i_ts->sign.tx_timer.data = e1i_ts;
+ osmo_timer_setup(&e1i_ts->sign.tx_timer, timeout_ts1_write, e1i_ts);
osmo_timer_schedule(&e1i_ts->sign.tx_timer, 0, 50000);
return 0;
}
+static void handle_hdlc_write(struct osmo_fd *bfd)
+{
+ struct e1inp_line *line = bfd->data;
+ unsigned int ts_nr = bfd->priv_nr;
+ struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
+ struct msgb *msg;
+ int ret;
+
+ /* get the next msg for this timeslot */
+ msg = e1inp_tx_ts(e1i_ts, NULL);
+ if (!msg)
+ return;
+
+ ret = write(bfd->fd, msg->data, msg->len + 2);
+ msgb_free(msg);
+ if (ret == -1)
+ handle_dahdi_exception(e1i_ts);
+ else if (ret < 0)
+ LOGP(DLMI, LOGL_NOTICE, "%s write failed %d\n", __func__, ret);
+}
+
+static int handle_hdlc_read(struct osmo_fd *bfd)
+{
+ struct e1inp_line *line = bfd->data;
+ unsigned int ts_nr = bfd->priv_nr;
+ struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
+ struct msgb *msg = msgb_alloc(TS1_ALLOC_SIZE, "DAHDI HDLC Rx");
+ int ret;
+
+ if (!msg)
+ return -ENOMEM;
+
+ ret = read(bfd->fd, msg->data, TS1_ALLOC_SIZE - 16);
+ if (ret == -1)
+ handle_dahdi_exception(e1i_ts);
+ else if (ret < 0) {
+ perror("read ");
+ }
+ msgb_put(msg, ret - 2);
+ if (ret <= 3) {
+ perror("read ");
+ }
+
+ return e1inp_rx_ts(e1i_ts, msg, 0, 0);
+}
static int invertbits = 1;
@@ -359,6 +404,79 @@ static int handle_tsX_read(struct osmo_fd *bfd)
return ret;
}
+/* write to a raw channel TS */
+static int handle_ts_raw_write(struct osmo_fd *bfd)
+{
+ struct e1inp_line *line = bfd->data;
+ unsigned int ts_nr = bfd->priv_nr;
+ struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
+ struct msgb *msg;
+ int ret;
+
+ /* get the next msg for this timeslot */
+ msg = e1inp_tx_ts(e1i_ts, NULL);
+ if (!msg)
+ return 0;
+
+ if (msg->len != D_BCHAN_TX_GRAN) {
+ /* This might lead to a transmit underrun, as we call tx
+ * from the rx path, as there's no select/poll on dahdi
+ * */
+ LOGP(DLINP, LOGL_NOTICE, "unexpected msg->len = %u, "
+ "expected %u\n", msg->len, D_BCHAN_TX_GRAN);
+ }
+
+ DEBUGP(DLMIB, "RAW CHAN TX: %s\n",
+ osmo_hexdump(msg->data, msg->len));
+
+ if (0/*invertbits*/) {
+ flip_buf_bits(msg->data, msg->len);
+ }
+
+ ret = write(bfd->fd, msg->data, msg->len);
+ if (ret < msg->len)
+ LOGP(DLINP, LOGL_DEBUG, "send returns %d instead of %d\n",
+ ret, msg->len);
+ msgb_free(msg);
+
+ return ret;
+}
+
+static int handle_ts_raw_read(struct osmo_fd *bfd)
+{
+ struct e1inp_line *line = bfd->data;
+ unsigned int ts_nr = bfd->priv_nr;
+ struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
+ struct msgb *msg = msgb_alloc(D_TSX_ALLOC_SIZE, "DAHDI Raw TS");
+ int ret;
+
+ if (!msg)
+ return -ENOMEM;
+
+ ret = read(bfd->fd, msg->data, D_TSX_ALLOC_SIZE);
+ if (ret < 0 || ret != D_TSX_ALLOC_SIZE) {
+ LOGP(DLINP, LOGL_DEBUG, "read error %d %s\n",
+ ret, strerror(errno));
+ return ret;
+ }
+
+ if (0/*invertbits*/) {
+ flip_buf_bits(msg->data, ret);
+ }
+
+ msgb_put(msg, ret);
+
+ msg->l2h = msg->data;
+ DEBUGP(DLMIB, "RAW CHAN RX: %s\n",
+ osmo_hexdump(msgb_l2(msg), ret));
+ ret = e1inp_rx_ts(e1i_ts, msg, 0, 0);
+ /* physical layer indicates that data has been sent,
+ * we thus can send some more data */
+ ret = handle_ts_raw_write(bfd);
+
+ return ret;
+}
+
/* callback from select.c in case one of the fd's can be read/written */
static int dahdi_fd_cb(struct osmo_fd *bfd, unsigned int what)
{
@@ -377,6 +495,14 @@ static int dahdi_fd_cb(struct osmo_fd *bfd, unsigned int what)
if (what & BSC_FD_WRITE)
rc = handle_ts1_write(bfd);
break;
+ case E1INP_TS_TYPE_HDLC:
+ if (what & BSC_FD_EXCEPT)
+ handle_dahdi_exception(e1i_ts);
+ if (what & BSC_FD_READ)
+ rc = handle_hdlc_read(bfd);
+ if (what & BSC_FD_WRITE)
+ handle_hdlc_write(bfd);
+ break;
case E1INP_TS_TYPE_TRAU:
if (what & BSC_FD_EXCEPT)
handle_dahdi_exception(e1i_ts);
@@ -388,6 +514,17 @@ static int dahdi_fd_cb(struct osmo_fd *bfd, unsigned int what)
* writeset, since it doesn't support poll() based
* write flow control */
break;
+ case E1INP_TS_TYPE_RAW:
+ if (what & BSC_FD_EXCEPT)
+ handle_dahdi_exception(e1i_ts);
+ if (what & BSC_FD_READ)
+ rc = handle_ts_raw_read(bfd);
+ if (what & BSC_FD_WRITE)
+ rc = handle_ts_raw_write(bfd);
+ /* We never include the DAHDI B-Channel FD into the
+ * writeset, since it doesn't support poll() based
+ * write flow control */
+ break;
default:
LOGP(DLINP, LOGL_NOTICE,
"unknown E1 TS type %u\n", e1i_ts->type);
@@ -535,7 +672,22 @@ static int dahdi_e1_setup(struct e1inp_line *line)
dahdi_write_msg, bfd, e1inp_dlsap_up,
e1i_ts, &lapd_profile_abis);
break;
+ case E1INP_TS_TYPE_HDLC:
+ if (!bfd->fd)
+ bfd->fd = open(openstr, O_RDWR | O_NONBLOCK);
+ if (bfd->fd == -1) {
+ LOGP(DLINP, LOGL_ERROR,
+ "%s could not open %s %s\n",
+ __func__, openstr, strerror(errno));
+ return -EIO;
+ }
+ bfd->when = BSC_FD_READ | BSC_FD_EXCEPT;
+ ret = dahdi_set_bufinfo(bfd->fd, 1);
+ if (ret < 0)
+ return ret;
+ break;
case E1INP_TS_TYPE_TRAU:
+ case E1INP_TS_TYPE_RAW:
/* close/release LAPD instance, if any */
if (e1i_ts->lapd) {
lapd_instance_free(e1i_ts->lapd);
diff --git a/src/input/ipa.c b/src/input/ipa.c
index a10a418..ce155ce 100644
--- a/src/input/ipa.c
+++ b/src/input/ipa.c
@@ -213,10 +213,8 @@ int ipa_client_conn_open(struct ipa_client_conn *link)
ret = osmo_sock_init(AF_INET, SOCK_STREAM, IPPROTO_TCP,
link->addr, link->port,
OSMO_SOCK_F_CONNECT|OSMO_SOCK_F_NONBLOCK);
- if (ret < 0) {
- if (errno != EINPROGRESS)
- return ret;
- }
+ if (ret < 0)
+ return ret;
link->ofd->fd = ret;
link->ofd->when |= BSC_FD_WRITE;
if (osmo_fd_register(link->ofd) < 0) {
@@ -401,6 +399,8 @@ ipa_server_conn_create(void *ctx, struct ipa_server_link *link, int fd,
int (*closed_cb)(struct ipa_server_conn *conn), void *data)
{
struct ipa_server_conn *conn;
+ struct sockaddr_in sa;
+ socklen_t sa_len = sizeof(sa);
conn = talloc_zero(ctx, struct ipa_server_conn);
if (conn == NULL) {
@@ -418,6 +418,12 @@ ipa_server_conn_create(void *ctx, struct ipa_server_link *link, int fd,
conn->data = data;
INIT_LLIST_HEAD(&conn->tx_queue);
+ if (!getpeername(fd, (struct sockaddr *)&sa, &sa_len)) {
+ char *str = inet_ntoa(sa.sin_addr);
+ conn->addr = talloc_strdup(conn, str);
+ conn->port = ntohs(sa.sin_port);
+ }
+
if (osmo_fd_register(&conn->ofd) < 0) {
LOGP(DLINP, LOGL_ERROR, "could not register FD\n");
talloc_free(conn);
@@ -426,6 +432,73 @@ ipa_server_conn_create(void *ctx, struct ipa_server_link *link, int fd,
return conn;
}
+int ipa_server_conn_ccm(struct ipa_server_conn *conn, struct msgb *msg)
+{
+ struct tlv_parsed tlvp;
+ uint8_t msg_type = *(msg->l2h);
+ struct ipaccess_unit unit_data = {};
+ char *unitid;
+ int len, rc;
+
+ /* shared CCM handling on both server and client */
+ rc = ipa_ccm_rcvmsg_base(msg, &conn->ofd);
+ switch (rc) {
+ case -1:
+ /* error in IPA CCM processing */
+ goto err;
+ case 1:
+ /* IPA CCM message that was handled in _base */
+ return 0;
+ case 0:
+ /* IPA CCM message that we need to handle */
+ break;
+ default:
+ /* Error */
+ LOGP(DLINP, LOGL_ERROR, "Unexpected return from "
+ "ipa_ccm_rcvmsg_base: %d\n", rc);
+ goto err;
+ }
+
+ switch (msg_type) {
+ case IPAC_MSGT_ID_RESP:
+ rc = ipa_ccm_idtag_parse(&tlvp, (uint8_t *)msg->l2h + 2,
+ msgb_l2len(msg)-2);
+ if (rc < 0) {
+ LOGP(DLINP, LOGL_ERROR, "IPA CCM RESPonse with "
+ "malformed TLVs\n");
+ goto err;
+ }
+ if (!TLVP_PRESENT(&tlvp, IPAC_IDTAG_UNIT)) {
+ LOGP(DLINP, LOGL_ERROR, "IPA CCM RESP without "
+ "unit ID\n");
+ goto err;
+ }
+ len = TLVP_LEN(&tlvp, IPAC_IDTAG_UNIT);
+ if (len < 1) {
+ LOGP(DLINP, LOGL_ERROR, "IPA CCM RESP with short"
+ "unit ID\n");
+ goto err;
+ }
+ unitid = (char *) TLVP_VAL(&tlvp, IPAC_IDTAG_UNIT);
+ unitid[len-1] = '\0';
+ ipa_parse_unitid(unitid, &unit_data);
+
+ /* FIXME */
+ rc = conn->ccm_cb(conn, msg, &tlvp, &unit_data);
+ if (rc < 0)
+ goto err;
+ break;
+ default:
+ LOGP(DLINP, LOGL_ERROR, "Unknown IPA message type\n");
+ break;
+ }
+ return 0;
+err:
+ /* in case of any error, we close the connection */
+ ipa_server_conn_destroy(conn);
+ return -1;
+}
+
void ipa_server_conn_destroy(struct ipa_server_conn *conn)
{
close(conn->ofd.fd);
diff --git a/src/input/ipaccess.c b/src/input/ipaccess.c
index 8ffdb19..63ee167 100644
--- a/src/input/ipaccess.c
+++ b/src/input/ipaccess.c
@@ -31,7 +31,7 @@
#include <netinet/tcp.h>
#include <string.h>
#include <time.h>
-#include <sys/fcntl.h>
+#include <fcntl.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
@@ -196,7 +196,12 @@ static int ipaccess_rcvmsg(struct e1inp_line *line, struct msgb *msg,
newbfd->priv_nr = E1INP_SIGN_RSL + unit_data.trx_id;
osmo_fd_unregister(bfd);
bfd->fd = -1;
- osmo_fd_register(newbfd);
+ ret = osmo_fd_register(newbfd);
+ if (ret < 0) {
+ LOGP(DLINP, LOGL_ERROR,
+ "could not register FD\n");
+ goto err;
+ }
/* now we can release the dummy RSL line. */
e1inp_line_put(line);
}
@@ -223,7 +228,7 @@ static int handle_ts1_read(struct osmo_fd *bfd)
struct e1inp_sign_link *link;
struct ipaccess_head *hh;
struct msgb *msg = NULL;
- int ret;
+ int ret, rc;
ret = ipa_msg_recv_buffered(bfd->fd, &msg, &e1i_ts->pending_msg);
if (ret < 0) {
@@ -268,13 +273,14 @@ static int handle_ts1_read(struct osmo_fd *bfd)
ret = -EINVAL;
goto err_msg;
}
- if (e1i_ts->line->ops->sign_link(msg) < 0) {
+ rc = e1i_ts->line->ops->sign_link(msg);
+ if (rc < 0) {
/* Don't close the signalling link if the upper layers report
* an error, that's too strict. BTW, the signalling layer is
* resposible for releasing the message.
*/
LOGP(DLINP, LOGL_ERROR, "Bad signalling message,"
- "sign_link returned error\n");
+ " sign_link returned error: %s.\n", strerror(-rc));
}
return 0;
@@ -348,8 +354,7 @@ static int __handle_ts1_write(struct osmo_fd *bfd, struct e1inp_line *line)
}
/* set tx delay timer for next event */
- e1i_ts->sign.tx_timer.cb = timeout_ts1_write;
- e1i_ts->sign.tx_timer.data = e1i_ts;
+ osmo_timer_setup(&e1i_ts->sign.tx_timer, timeout_ts1_write, e1i_ts);
/* Reducing this might break the nanoBTS 900 init. */
osmo_timer_schedule(&e1i_ts->sign.tx_timer, 0, e1i_ts->sign.delay);
@@ -570,6 +575,8 @@ ipa_bts_id_resp(struct ipaccess_unit *dev, uint8_t *data, int len, int trx_nr)
char str[IPA_STRING_MAX];
uint8_t *tag;
+ memset(str, 0, sizeof(str));
+
nmsg = ipa_msg_alloc(0);
if (!nmsg)
return NULL;
@@ -595,16 +602,20 @@ ipa_bts_id_resp(struct ipaccess_unit *dev, uint8_t *data, int len, int trx_nr)
dev->mac_addr[4], dev->mac_addr[5]);
break;
case IPAC_IDTAG_LOCATION1:
- strncpy(str, dev->location1, IPA_STRING_MAX);
+ if (dev->location1)
+ strncpy(str, dev->location1, IPA_STRING_MAX);
break;
case IPAC_IDTAG_LOCATION2:
- strncpy(str, dev->location2, IPA_STRING_MAX);
+ if (dev->location2)
+ strncpy(str, dev->location2, IPA_STRING_MAX);
break;
case IPAC_IDTAG_EQUIPVERS:
- strncpy(str, dev->equipvers, IPA_STRING_MAX);
+ if (dev->equipvers)
+ strncpy(str, dev->equipvers, IPA_STRING_MAX);
break;
case IPAC_IDTAG_SWVERSION:
- strncpy(str, dev->swversion, IPA_STRING_MAX);
+ if (dev->swversion)
+ strncpy(str, dev->swversion, IPA_STRING_MAX);
break;
case IPAC_IDTAG_UNITNAME:
snprintf(str, sizeof(str),
@@ -615,7 +626,8 @@ ipa_bts_id_resp(struct ipaccess_unit *dev, uint8_t *data, int len, int trx_nr)
dev->mac_addr[4], dev->mac_addr[5]);
break;
case IPAC_IDTAG_SERNR:
- strncpy(str, dev->serno, IPA_STRING_MAX);
+ if (dev->serno)
+ strncpy(str, dev->serno, IPA_STRING_MAX);
break;
default:
LOGP(DLINP, LOGL_NOTICE,
@@ -827,11 +839,14 @@ static int ipaccess_line_update(struct e1inp_line *line)
switch(line->ops->cfg.ipa.role) {
case E1INP_LINE_R_BSC: {
struct ipa_server_link *oml_link, *rsl_link;
+ const char *ipa = e1inp_ipa_get_bind_addr();
- LOGP(DLINP, LOGL_NOTICE, "enabling ipaccess BSC mode\n");
+ LOGP(DLINP, LOGL_NOTICE, "enabling ipaccess BSC mode on %s "
+ "with OML %u and RSL %u TCP ports\n", ipa,
+ IPA_TCP_PORT_OML, IPA_TCP_PORT_RSL);
- oml_link = ipa_server_link_create(tall_ipa_ctx, line,
- "0.0.0.0", IPA_TCP_PORT_OML,
+ oml_link = ipa_server_link_create(tall_ipa_ctx, line, ipa,
+ IPA_TCP_PORT_OML,
ipaccess_bsc_oml_cb, NULL);
if (oml_link == NULL) {
LOGP(DLINP, LOGL_ERROR, "cannot create OML "
@@ -844,8 +859,8 @@ static int ipaccess_line_update(struct e1inp_line *line)
ipa_server_link_destroy(oml_link);
return -EIO;
}
- rsl_link = ipa_server_link_create(tall_ipa_ctx, line,
- "0.0.0.0", IPA_TCP_PORT_RSL,
+ rsl_link = ipa_server_link_create(tall_ipa_ctx, line, ipa,
+ IPA_TCP_PORT_RSL,
ipaccess_bsc_rsl_cb, NULL);
if (rsl_link == NULL) {
LOGP(DLINP, LOGL_ERROR, "cannot create RSL "
@@ -864,7 +879,9 @@ static int ipaccess_line_update(struct e1inp_line *line)
case E1INP_LINE_R_BTS: {
struct ipa_client_conn *link;
- LOGP(DLINP, LOGL_NOTICE, "enabling ipaccess BTS mode\n");
+ LOGP(DLINP, LOGL_NOTICE, "enabling ipaccess BTS mode, "
+ "OML connecting to %s:%u\n", line->ops->cfg.ipa.addr,
+ IPA_TCP_PORT_OML);
link = ipa_client_conn_create(tall_ipa_ctx,
&line->ts[E1INP_SIGN_OML-1],
@@ -944,3 +961,20 @@ void e1inp_ipaccess_init(void)
tall_ipa_ctx = talloc_named_const(libosmo_abis_ctx, 1, "ipa");
e1inp_driver_register(&ipaccess_driver);
}
+
+void e1inp_ipa_set_bind_addr(const char *ip_bind_addr)
+{
+ talloc_free((char*)ipaccess_driver.bind_addr);
+ ipaccess_driver.bind_addr = NULL;
+
+ if (ip_bind_addr)
+ ipaccess_driver.bind_addr = talloc_strdup(tall_ipa_ctx,
+ ip_bind_addr);
+}
+
+const char *e1inp_ipa_get_bind_addr(void)
+{
+ return ipaccess_driver.bind_addr?
+ ipaccess_driver.bind_addr
+ : "0.0.0.0";
+}
diff --git a/src/input/lapd.c b/src/input/lapd.c
index ac24fd8..4b5077b 100644
--- a/src/input/lapd.c
+++ b/src/input/lapd.c
@@ -95,6 +95,27 @@ const struct lapd_profile lapd_profile_abis = {
.short_address = 0
};
+/* Ericssons OM2000 lapd dialect requires a sabm frame retransmission
+ * timeout of exactly 300 msek. Shorter or longer retransmission will
+ * cause the link establishment to fail permanently. Since the BTS is
+ * periodically scanning through all timeslots to find the timeslot
+ * where the bsc is transmitting its sabm frames the normal maximum
+ * retransmission (n200) of 3 is not enough. In order not to miss
+ * the bts, n200 has been increased to 50, which is an educated
+ * guess. */
+
+const struct lapd_profile lapd_profile_abis_ericsson = {
+ .k = LAPD_SET_K(2,1),
+ .n200 = 50,
+ .n201 = 260,
+ .n202 = 0, /* infinite */
+ .t200_sec = 0, .t200_usec = 300000,
+ .t201_sec = 1, .t201_usec = 0,
+ .t202_sec = 2, .t202_usec = 0,
+ .t203_sec = 10, .t203_usec = 0,
+ .short_address = 0
+};
+
const struct lapd_profile lapd_profile_sat = {
.k = LAPD_SET_K(15,15),
.n200 = 5,
@@ -208,8 +229,9 @@ static struct lapd_sap *lapd_sap_alloc(struct lapd_tei *teip, uint8_t sapi)
if (!sap)
return NULL;
- LOGP(DLLAPD, LOGL_NOTICE, "LAPD Allocating SAP for SAPI=%u / TEI=%u\n",
- sapi, teip->tei);
+ LOGP(DLLAPD, LOGL_NOTICE,
+ "LAPD Allocating SAP for SAPI=%u / TEI=%u (dl=%p, sap=%p)\n",
+ sapi, teip->tei, &sap->dl, sap);
sap->sapi = sapi;
sap->tei = teip;
@@ -245,6 +267,10 @@ static struct lapd_sap *lapd_sap_alloc(struct lapd_tei *teip, uint8_t sapi)
/* Free SAP instance, including the datalink */
static void lapd_sap_free(struct lapd_sap *sap)
{
+ LOGP(DLLAPD, LOGL_NOTICE,
+ "LAPD Freeing SAP for SAPI=%u / TEI=%u (dl=%p, sap=%p)\n",
+ sap->sapi, sap->tei->tei, &sap->dl, sap);
+
/* free datalink structures and timers */
lapd_dl_exit(&sap->dl);
@@ -664,6 +690,13 @@ struct lapd_instance *lapd_instance_alloc(int network_side,
return li;
}
+/* Change lapd-profile on the fly (use with caution!) */
+void lapd_instance_set_profile(struct lapd_instance *li,
+ const struct lapd_profile *profile)
+{
+ memcpy(&li->profile, profile, sizeof(li->profile));
+}
+
void lapd_instance_free(struct lapd_instance *li)
{
struct lapd_tei *teip, *teip2;
diff --git a/src/input/lapd_pcap.c b/src/input/lapd_pcap.c
index c83bc60..7374694 100644
--- a/src/input/lapd_pcap.c
+++ b/src/input/lapd_pcap.c
@@ -43,6 +43,8 @@
* pcap format is from http://wiki.wireshark.org/Development/LibpcapFileFormat
*/
#define DLT_LINUX_LAPD 177
+#define LINUX_SLL_HOST 0
+#define LINUX_SLL_OUTGOING 4
struct pcap_hdr {
uint32_t magic_number;
@@ -65,7 +67,7 @@ struct pcap_lapdhdr {
uint16_t pkttype;
uint16_t hatype;
uint16_t halen;
- uint64_t addr;
+ uint8_t addr[8];
int16_t protocol;
} __attribute__((packed));
@@ -75,10 +77,9 @@ osmo_static_assert(offsetof(struct pcap_lapdhdr, addr) == 6, addr_offset);
osmo_static_assert(offsetof(struct pcap_lapdhdr, protocol) == 14, proto_offset);
osmo_static_assert(sizeof(struct pcap_lapdhdr) == 16, lapd_header_size);
-int osmo_pcap_lapd_open(char *filename, mode_t mode)
+int osmo_pcap_lapd_set_fd(int fd)
{
- int fd;
- struct pcap_hdr pcap_header = {
+ struct pcap_hdr pcap_header = {
.magic_number = 0xa1b2c3d4,
.version_major = 2,
.version_minor = 4,
@@ -88,6 +89,21 @@ int osmo_pcap_lapd_open(char *filename, mode_t mode)
.network = DLT_LINUX_LAPD,
};
+ if (write(fd, &pcap_header, sizeof(pcap_header))
+ != sizeof(pcap_header)) {
+ LOGP(DLLAPD, LOGL_ERROR, "cannot write PCAP header: %s\n",
+ strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ return 0;
+}
+
+int osmo_pcap_lapd_open(char *filename, mode_t mode)
+{
+ int fd, rc;
+
LOGP(DLLAPD, LOGL_NOTICE, "opening LAPD pcap file `%s'\n", filename);
fd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, mode);
@@ -96,13 +112,13 @@ int osmo_pcap_lapd_open(char *filename, mode_t mode)
strerror(errno));
return -1;
}
- if (write(fd, &pcap_header, sizeof(pcap_header))
- != sizeof(pcap_header)) {
- LOGP(DLLAPD, LOGL_ERROR, "cannot write PCAP header: %s\n",
- strerror(errno));
+
+ rc = osmo_pcap_lapd_set_fd(fd);
+ if (rc < 0) {
close(fd);
- return -1;
+ return rc;
}
+
return fd;
}
@@ -125,10 +141,13 @@ int osmo_pcap_lapd_write(int fd, int direction, struct msgb *msg)
pcap_rechdr.incl_len = msg->len + sizeof(struct pcap_lapdhdr);
pcap_rechdr.orig_len = msg->len + sizeof(struct pcap_lapdhdr);
- header.pkttype = 4;
+ if (direction == OSMO_LAPD_PCAP_OUTPUT)
+ header.pkttype = htons(LINUX_SLL_OUTGOING);
+ else
+ header.pkttype = htons(LINUX_SLL_HOST);
header.hatype = 0;
header.halen = 0;
- header.addr = direction == OSMO_LAPD_PCAP_OUTPUT ? 0x0 : 0x1;
+ header.addr[0] = 0x01; /* we are the network side */
header.protocol = ntohs(48);
gettimeofday(&tv, NULL);
diff --git a/src/input/misdn.c b/src/input/misdn.c
index 330e3b3..347b7bf 100644
--- a/src/input/misdn.c
+++ b/src/input/misdn.c
@@ -41,8 +41,8 @@
#include <errno.h>
#include <string.h>
#include <time.h>
-#include <sys/fcntl.h>
#include <sys/socket.h>
+#include <sys/types.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <mISDNif.h>
@@ -283,8 +283,7 @@ static int handle_ts1_write(struct osmo_fd *bfd)
/* set tx delay timer for next event */
- e1i_ts->sign.tx_timer.cb = timeout_ts1_write;
- e1i_ts->sign.tx_timer.data = e1i_ts;
+ osmo_timer_setup(&e1i_ts->sign.tx_timer, timeout_ts1_write, e1i_ts);
osmo_timer_schedule(&e1i_ts->sign.tx_timer, 0, e1i_ts->sign.delay);
return ret;
@@ -391,6 +390,92 @@ static int handle_tsX_read(struct osmo_fd *bfd)
return ret;
}
+/* write to a raw channel TS */
+static int handle_ts_raw_write(struct osmo_fd *bfd, unsigned int len)
+{
+ struct e1inp_line *line = bfd->data;
+ unsigned int ts_nr = bfd->priv_nr;
+ struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
+ struct msgb *msg;
+ struct mISDNhead *hh;
+ int ret;
+
+ /* get the next msg for this timeslot */
+ msg = e1inp_tx_ts(e1i_ts, NULL);
+ if (!msg)
+ return 0;
+
+ if (msg->len != len) {
+ /* This might lead to a transmit underrun, as we call tx
+ * from the rx path, as there's no select/poll on dahdi
+ * */
+ LOGP(DLINP, LOGL_NOTICE, "unexpected msg->len = %u, "
+ "expected %u\n", msg->len, len);
+ }
+
+ DEBUGP(DLMIB, "RAW CHAN TX: %s\n",
+ osmo_hexdump(msg->data, msg->len));
+
+ hh = (struct mISDNhead *) msgb_push(msg, sizeof(*hh));
+ hh->prim = PH_DATA_REQ;
+ hh->id = 0;
+
+ ret = write(bfd->fd, msg->data, msg->len);
+ if (ret < msg->len)
+ LOGP(DLINP, LOGL_DEBUG, "send returns %d instead of %d\n",
+ ret, msg->len);
+ msgb_free(msg);
+
+ return ret;
+}
+
+static int handle_ts_raw_read(struct osmo_fd *bfd)
+{
+ struct e1inp_line *line = bfd->data;
+ unsigned int ts_nr = bfd->priv_nr;
+ struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
+ struct msgb *msg = msgb_alloc(TSX_ALLOC_SIZE, "mISDN Tx RAW");
+ struct mISDNhead *hh;
+ int ret;
+
+ if (!msg)
+ return -ENOMEM;
+
+ hh = (struct mISDNhead *) msg->data;
+
+ ret = recv(bfd->fd, msg->data, TSX_ALLOC_SIZE, 0);
+ if (ret < 0) {
+ fprintf(stderr, "recvfrom error %s\n", strerror(errno));
+ return ret;
+ }
+
+ msgb_put(msg, ret);
+
+ if (hh->prim != PH_CONTROL_IND)
+ DEBUGP(DLMIB, "<= RAW CHAN len = %d, prim(0x%x) id(0x%x): %s\n",
+ ret, hh->prim, hh->id,
+ get_value_string(prim_names, hh->prim));
+
+ switch (hh->prim) {
+ case PH_DATA_IND:
+ msg->l2h = msg->data + MISDN_HEADER_LEN;
+ DEBUGP(DLMIB, "RAW CHAN RX: %s\n",
+ osmo_hexdump(msgb_l2(msg), ret - MISDN_HEADER_LEN));
+ /* the number of bytes received indicates that data to send */
+ handle_ts_raw_write(bfd, msgb_l2len(msg));
+ return e1inp_rx_ts(e1i_ts, msg, 0, 0);
+ case PH_ACTIVATE_IND:
+ case PH_DATA_CNF:
+ break;
+ default:
+ break;
+ }
+ /* FIXME: why do we free signalling msgs in the caller, and trau not? */
+ msgb_free(msg);
+
+ return ret;
+}
+
/* callback from select.c in case one of the fd's can be read/written */
static int misdn_fd_cb(struct osmo_fd *bfd, unsigned int what)
{
@@ -414,6 +499,13 @@ static int misdn_fd_cb(struct osmo_fd *bfd, unsigned int what)
* writeset, since it doesn't support poll() based
* write flow control */
break;
+ case E1INP_TS_TYPE_RAW:
+ if (what & BSC_FD_READ)
+ rc = handle_ts_raw_read(bfd);
+ /* We never include the mISDN B-Channel FD into the
+ * writeset, since it doesn't support poll() based
+ * write flow control */
+ break;
default:
fprintf(stderr, "unknown E1 TS type %u\n", e1i_ts->type);
break;
@@ -514,6 +606,11 @@ static int mi_e1_setup(struct e1inp_line *line, int release_l2)
case E1INP_TS_TYPE_NONE:
continue;
break;
+ case E1INP_TS_TYPE_HDLC:
+ bfd->fd = socket(PF_ISDN, SOCK_DGRAM,
+ ISDN_P_B_HDLC);
+ bfd->when = BSC_FD_READ;
+ break;
case E1INP_TS_TYPE_SIGN:
if (mline->use_userspace_lapd)
bfd->fd = socket(PF_ISDN, SOCK_DGRAM,
@@ -524,6 +621,7 @@ static int mi_e1_setup(struct e1inp_line *line, int release_l2)
bfd->when = BSC_FD_READ;
break;
case E1INP_TS_TYPE_TRAU:
+ case E1INP_TS_TYPE_RAW:
bfd->fd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_RAW);
/* We never include the mISDN B-Channel FD into the
* writeset, since it doesn't support poll() based
@@ -556,6 +654,7 @@ static int mi_e1_setup(struct e1inp_line *line, int release_l2)
addr.tei = GROUP_TEI;
}
break;
+ case E1INP_TS_TYPE_HDLC:
case E1INP_TS_TYPE_TRAU:
addr.channel = ts;
break;
@@ -591,7 +690,7 @@ static int mi_e1_setup(struct e1inp_line *line, int release_l2)
ret = osmo_fd_register(bfd);
if (ret < 0) {
fprintf(stderr, "could not register FD: %s\n",
- strerror(ret));
+ strerror(-ret));
return ret;
}
}
diff --git a/src/input/rs232.c b/src/input/rs232.c
index 2fd2a09..9da01a3 100644
--- a/src/input/rs232.c
+++ b/src/input/rs232.c
@@ -270,7 +270,7 @@ rs232_setup(struct e1inp_line *line, const char *serial_port, unsigned int delay
if (rc < 0) {
close(bfd->fd);
LOGP(DLMI, LOGL_ERROR, "rs232: could not register FD: %s\n",
- strerror(rc));
+ strerror(-rc));
return rc;
}
diff --git a/src/input/unixsocket.c b/src/input/unixsocket.c
new file mode 100644
index 0000000..63bd796
--- /dev/null
+++ b/src/input/unixsocket.c
@@ -0,0 +1,346 @@
+/* OpenBSC Abis receive lapd over a unix socket */
+
+/* (C) 2016 by sysmocom s.f.m.c. GmbH
+ *
+ * Author: Alexander Couzens <lynxis@fe80.eu>
+ * Based on other e1_input drivers.
+ *
+ * All Rights Reserved
+ *
+ * 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 2 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <limits.h>
+#include <string.h>
+
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/logging.h>
+#include <osmocom/core/socket.h>
+
+#include <osmocom/abis/e1_input.h>
+#include <osmocom/abis/lapd.h>
+#include <osmocom/abis/e1_input.h>
+
+#include <osmocom/abis/unixsocket_proto.h>
+#include "internal.h"
+
+void *tall_unixsocket_ctx;
+#define UNIXSOCKET_ALLOC_SIZE 1600
+#define UNIXSOCKET_SOCK_PATH_DEFAULT "/tmp/osmo_abis_line_"
+
+struct unixsocket_line {
+ struct osmo_fd fd;
+};
+
+static int unixsocket_line_update(struct e1inp_line *line);
+static int ts_want_write(struct e1inp_ts *e1i_ts);
+
+static int unixsocket_exception_cb(struct osmo_fd *bfd)
+{
+ struct e1inp_line *line = bfd->data;
+
+ LOGP(DLINP, LOGL_ERROR,
+ "Socket connection failure, reconnecting... (line=%p, fd=%d)\n",
+ line, bfd->fd);
+
+ /* Unregister faulty file descriptor from select loop */
+ if(osmo_fd_is_registered(bfd)) {
+ LOGP(DLINP, LOGL_DEBUG,
+ "removing inactive socket from select loop... (line=%p, fd=%d)\n",
+ line, bfd->fd);
+ osmo_fd_unregister(bfd);
+ }
+
+ /* Close faulty file descriptor */
+ close(bfd->fd);
+
+ unixsocket_line_update(line);
+
+ return 0;
+}
+
+static int unixsocket_read_cb(struct osmo_fd *bfd)
+{
+ struct e1inp_line *line = bfd->data;
+ struct msgb *msg = msgb_alloc(UNIXSOCKET_ALLOC_SIZE, "UNIXSOCKET TS");
+ uint8_t version;
+ uint8_t controldata;
+ int ret;
+
+ if (!msg)
+ return -ENOMEM;
+
+ ret = read(bfd->fd, msg->data, UNIXSOCKET_ALLOC_SIZE - 16);
+ if (ret == 0) {
+ unixsocket_exception_cb(bfd);
+ goto fail;
+ } else if (ret < 0) {
+ perror("read ");
+ goto fail;
+ } else if (ret < 2) {
+ /* packet must be at least 2 byte long to hold version + control/data header */
+ LOGP(DLMI, LOGL_ERROR, "received to small packet: %d < 2", ret);
+ ret = -1;
+ goto fail;
+ }
+ msgb_put(msg, ret);
+
+ LOGP(DLMI, LOGL_DEBUG, "rx msg: %s (fd=%d)\n",
+ osmo_hexdump_nospc(msg->data, msg->len), bfd->fd);
+
+ /* check version header */
+ version = msgb_pull_u8(msg);
+ controldata = msgb_pull_u8(msg);
+
+ if (version != UNIXSOCKET_PROTO_VERSION) {
+ LOGP(DLMI, LOGL_ERROR, "received message with invalid version %d. valid: %d",
+ ret, UNIXSOCKET_PROTO_VERSION);
+ ret = -1;
+ goto fail;
+ }
+
+ switch (controldata) {
+ case UNIXSOCKET_PROTO_DATA:
+ return e1inp_rx_ts_lapd(&line->ts[0], msg);
+ case UNIXSOCKET_PROTO_CONTROL:
+ LOGP(DLMI, LOGL_ERROR, "received (invalid) control message.");
+ ret = -1;
+ break;
+ default:
+ LOGP(DLMI, LOGL_ERROR, "received invalid message.");
+ ret = -1;
+ break;
+ }
+fail:
+ msgb_free(msg);
+ return ret;
+}
+
+static void timeout_ts1_write(void *data)
+{
+ struct e1inp_ts *e1i_ts = (struct e1inp_ts *)data;
+
+ /* trigger write of ts1, due to tx delay timer */
+ ts_want_write(e1i_ts);
+}
+
+static int unixsocket_write_cb(struct osmo_fd *bfd)
+{
+ struct e1inp_line *line = bfd->data;
+ struct e1inp_ts *e1i_ts = &line->ts[0];
+ struct msgb *msg;
+ struct e1inp_sign_link *sign_link;
+
+ bfd->when &= ~BSC_FD_WRITE;
+
+ /* get the next msg for this timeslot */
+ msg = e1inp_tx_ts(e1i_ts, &sign_link);
+ if (!msg) {
+ /* no message after tx delay timer */
+ LOGP(DLINP, LOGL_INFO,
+ "no message available (line=%p)\n", line);
+ return 0;
+ }
+
+ /* set tx delay timer for next event */
+ osmo_timer_setup(&e1i_ts->sign.tx_timer, timeout_ts1_write, e1i_ts);
+
+ osmo_timer_schedule(&e1i_ts->sign.tx_timer, 0, e1i_ts->sign.delay);
+
+ LOGP(DLINP, LOGL_DEBUG, "sending: %s (line=%p)\n",
+ msgb_hexdump(msg), line);
+ lapd_transmit(e1i_ts->lapd, sign_link->tei,
+ sign_link->sapi, msg);
+
+ return 0;
+}
+
+static int unixsocket_cb(struct osmo_fd *bfd, unsigned int what)
+{
+ int ret = 0;
+
+ if (what & BSC_FD_READ)
+ ret = unixsocket_read_cb(bfd);
+ if (what & BSC_FD_WRITE)
+ ret = unixsocket_write_cb(bfd);
+
+ return ret;
+}
+
+static int ts_want_write(struct e1inp_ts *e1i_ts)
+{
+ struct unixsocket_line *line = e1i_ts->line->driver_data;
+
+ line->fd.when |= BSC_FD_WRITE;
+
+ return 0;
+}
+
+static void unixsocket_write_msg(struct msgb *msg, struct osmo_fd *bfd) {
+ int ret;
+
+ LOGP(DLMI, LOGL_DEBUG, "tx msg: %s (fd=%d)\n",
+ osmo_hexdump_nospc(msg->data, msg->len), bfd->fd);
+
+ ret = write(bfd->fd, msg->data, msg->len);
+ msgb_free(msg);
+ if (ret == -1)
+ unixsocket_exception_cb(bfd);
+ else if (ret < 0)
+ LOGP(DLMI, LOGL_NOTICE, "%s write failed %d\n", __func__, ret);
+}
+
+/*!
+ * \brief unixsocket_write_msg lapd callback for data to unixsocket
+ * \param msg
+ * \param cbdata
+ */
+static void unixsocket_write_msg_lapd_cb(struct msgb *msg, void *cbdata)
+{
+ struct osmo_fd *bfd = cbdata;
+
+ /* data|control */
+ msgb_push_u8(msg, UNIXSOCKET_PROTO_DATA);
+ /* add version header */
+ msgb_push_u8(msg, UNIXSOCKET_PROTO_VERSION);
+
+ unixsocket_write_msg(msg, bfd);
+}
+
+static int unixsocket_line_update(struct e1inp_line *line)
+{
+ struct unixsocket_line *config;
+ char sock_path[PATH_MAX];
+ int ret = 0;
+ int i;
+
+ if (line->sock_path)
+ strcpy(sock_path, line->sock_path);
+ else
+ sprintf(sock_path, "%s%d", UNIXSOCKET_SOCK_PATH_DEFAULT,
+ line->num);
+
+ LOGP(DLINP, LOGL_NOTICE, "line update (line=%p)\n", line);
+
+ if (!line->driver_data)
+ line->driver_data = talloc_zero(line, struct unixsocket_line);
+
+ if (!line->driver_data) {
+ LOGP(DLINP, LOGL_ERROR,
+ "OOM in line update (line=%p)\n", line);
+ return -ENOMEM;
+ }
+
+ config = line->driver_data;
+ config->fd.data = line;
+ config->fd.when = BSC_FD_READ;
+ config->fd.cb = unixsocket_cb;
+
+ /* Open unix domain socket */
+ ret = osmo_sock_unix_init(SOCK_SEQPACKET, 0, sock_path,
+ OSMO_SOCK_F_CONNECT);
+ if (ret < 0) {
+ /* Note: We will not free the allocated driver_data memory if
+ * opening the socket fails. The caller may want to call this
+ * function multiple times using config->fd.data as line
+ * parameter. Freeing now would destroy that reference. */
+ LOGP(DLINP, LOGL_ERROR,
+ "unable to open socket: %s (line=%p, fd=%d)\n", sock_path,
+ line, config->fd.fd);
+ return ret;
+ }
+ LOGP(DLINP, LOGL_DEBUG,
+ "successfully opend (new) socket: %s (line=%p, fd=%d, ret=%d)\n",
+ sock_path, line, config->fd.fd, ret);
+ config->fd.fd = ret;
+
+ /* Register socket in select loop */
+ if (osmo_fd_register(&config->fd) < 0) {
+ LOGP(DLINP, LOGL_ERROR,
+ "error registering new socket (line=%p, fd=%d)\n",
+ line, config->fd.fd);
+ close(config->fd.fd);
+ return -EIO;
+ }
+
+ /* Set line parameter */
+ for (i = 0; i < ARRAY_SIZE(line->ts); i++) {
+ struct e1inp_ts *e1i_ts = &line->ts[i];
+ if (!e1i_ts->lapd) {
+ e1i_ts->lapd = lapd_instance_alloc(1,
+ unixsocket_write_msg_lapd_cb, &config->fd,
+ e1inp_dlsap_up, e1i_ts, &lapd_profile_abis);
+ }
+ }
+
+ /* Ensure ericsson-superchannel is turned of when
+ * a new connection is made */
+ e1inp_ericsson_set_altc(line, 0);
+
+ return ret;
+}
+
+struct e1inp_driver unixsocket_driver = {
+ .name = "unixsocket",
+ .want_write = ts_want_write,
+ .line_update = unixsocket_line_update,
+ .default_delay = 0,
+};
+
+void e1inp_unixsocket_init(void)
+{
+ tall_unixsocket_ctx = talloc_named_const(libosmo_abis_ctx, 1, "unixsocket");
+ e1inp_driver_register(&unixsocket_driver);
+}
+
+void e1inp_ericsson_set_altc(struct e1inp_line *unixline, int superchannel)
+{
+ struct unixsocket_line *config;
+ struct msgb *msg;
+
+ if (!unixline)
+ return;
+
+ if (unixline->driver != &unixsocket_driver) {
+ LOGP(DLMI, LOGL_NOTICE, "altc is only supported by unixsocket\n");
+ return;
+ }
+
+ config = unixline->driver_data;
+ if (!config) {
+ LOGP(DLMI, LOGL_NOTICE, "e1inp driver not yet initialized.\n");
+ return;
+ }
+
+
+ msg = msgb_alloc_headroom(200, 100, "ALTC");
+
+ /* version header */
+ msgb_put_u8(msg, UNIXSOCKET_PROTO_VERSION);
+ /* data|control */
+ msgb_put_u8(msg, UNIXSOCKET_PROTO_CONTROL);
+
+ /* magic */
+ msgb_put_u32(msg, 0x23004200);
+ msgb_put_u8(msg, superchannel ? 1 : 0);
+
+ unixsocket_write_msg(msg, &config->fd);
+}
+
diff --git a/src/subchan_demux.c b/src/subchan_demux.c
index f965490..238056c 100644
--- a/src/subchan_demux.c
+++ b/src/subchan_demux.c
@@ -289,17 +289,6 @@ int subchan_mux_out(struct subch_mux *mx, uint8_t *data, int len)
return i;
}
-static int llist_len(struct llist_head *head)
-{
- struct llist_head *entry;
- int i = 0;
-
- llist_for_each(entry, head)
- i++;
-
- return i;
-}
-
/* evict the 'num_evict' number of oldest entries in the queue */
static void tx_queue_evict(struct mux_subch *sch, int num_evict)
{
@@ -327,7 +316,7 @@ int subchan_mux_enqueue(struct subch_mux *mx, int s_nr, const uint8_t *data,
int len)
{
struct mux_subch *sch = &mx->subch[s_nr];
- int list_len = llist_len(&sch->tx_queue);
+ unsigned int list_len = llist_count(&sch->tx_queue);
struct subch_txq_entry *tqe = talloc_zero_size(tall_tqe_ctx,
sizeof(*tqe) + len);
if (!tqe)
diff --git a/src/trau/osmo_ortp.c b/src/trau/osmo_ortp.c
index 65ec269..c49a23d 100644
--- a/src/trau/osmo_ortp.c
+++ b/src/trau/osmo_ortp.c
@@ -23,6 +23,7 @@
*/
#include <stdint.h>
+#include <stdbool.h>
#include <inttypes.h>
#include <netdb.h>
@@ -93,8 +94,11 @@ static int ortp_to_osmo_lvl(OrtpLogLevel lev)
return LOGL_ERROR;
}
-static void my_ortp_logfn(OrtpLogLevel lev, const char *fmt,
- va_list args)
+static void my_ortp_logfn(
+#if HAVE_ORTP_LOG_DOMAIN
+ const char *domain,
+#endif
+ OrtpLogLevel lev, const char *fmt, va_list args)
{
osmo_vlogp(DLMIB, ortp_to_osmo_lvl(lev), __FILE__, 0,
0, fmt, args);
@@ -105,11 +109,7 @@ static void my_ortp_logfn(OrtpLogLevel lev, const char *fmt,
static void ortp_sig_cb_ssrc(RtpSession *rs, void *data)
{
int port = rtp_session_get_local_port(rs);
-#if 0 /* post 0.20.0 ORTP has this function */
uint32_t ssrc = rtp_session_get_recv_ssrc(rs);
-#else
- uint32_t ssrc = rs->rcv.ssrc;
-#endif
LOGP(DLMIB, LOGL_INFO,
"osmo-ortp(%d): ssrc_changed to 0x%08x\n", port, ssrc);
@@ -129,7 +129,7 @@ static void ortp_sig_cb_net(RtpSession *rs, void *data)
int port = rtp_session_get_local_port(rs);
LOGP(DLMIB, LOGL_ERROR,
- "osmo-ortp(%d): network_error\n", port);
+ "osmo-ortp(%d): network_error %s\n", port, (char *)data);
}
static void ortp_sig_cb_ts(RtpSession *rs, void *data)
@@ -138,9 +138,27 @@ static void ortp_sig_cb_ts(RtpSession *rs, void *data)
uint32_t ts = rtp_session_get_current_recv_ts(rs);
LOGP(DLMIB, LOGL_NOTICE,
- "osmo-ortp(%d): timestamp_jump, new TS %d\n", port, ts);
+ "osmo-ortp(%d): timestamp_jump, new TS %d, resyncing\n", port, ts);
+ rtp_session_resync(rs);
}
+static inline bool recv_with_cb(struct osmo_rtp_socket *rs)
+{
+ uint8_t *payload;
+ mblk_t *mblk = rtp_session_recvm_with_ts(rs->sess, rs->rx_user_ts);
+ if (!mblk)
+ return false;
+
+ int plen = rtp_get_payload(mblk, &payload);
+ /* hand into receiver */
+ if (rs->rx_cb && plen > 0)
+ rs->rx_cb(rs, payload, plen, rtp_get_seqnumber(mblk),
+ rtp_get_timestamp(mblk), rtp_get_markbit(mblk));
+ freemsg(mblk);
+ if (plen > 0)
+ return true;
+ return false;
+}
/*! \brief poll the socket for incoming data
* \param[in] rs the socket to be polled
@@ -148,23 +166,15 @@ static void ortp_sig_cb_ts(RtpSession *rs, void *data)
*/
int osmo_rtp_socket_poll(struct osmo_rtp_socket *rs)
{
- mblk_t *mblk;
+ if (rs->flags & OSMO_RTP_F_DISABLED)
+ return 0;
- mblk = rtp_session_recvm_with_ts(rs->sess, rs->rx_user_ts);
- if (mblk) {
- rtp_get_payload(mblk, &mblk->b_rptr);
- /* hand into receiver */
- if (rs->rx_cb)
- rs->rx_cb(rs, mblk->b_rptr,
- mblk->b_wptr - mblk->b_rptr);
- //rs->rx_user_ts += 160;
- freemsg(mblk);
+ if (recv_with_cb(rs))
return 1;
- } else {
- LOGP(DLMIB, LOGL_INFO, "osmo_rtp_poll(%u): ERROR!\n",
- rs->rx_user_ts);
- return 0;
- }
+
+ LOGP(DLMIB, LOGL_INFO, "osmo_rtp_socket_poll(%u): ERROR!\n",
+ rs->rx_user_ts);
+ return 0;
}
/* Osmo FD callbacks */
@@ -172,7 +182,6 @@ int osmo_rtp_socket_poll(struct osmo_rtp_socket *rs)
static int osmo_rtp_fd_cb(struct osmo_fd *fd, unsigned int what)
{
struct osmo_rtp_socket *rs = fd->data;
- mblk_t *mblk;
if (what & BSC_FD_READ) {
/* in polling mode, we don't want to be called here */
@@ -180,15 +189,7 @@ static int osmo_rtp_fd_cb(struct osmo_fd *fd, unsigned int what)
fd->when &= ~BSC_FD_READ;
return 0;
}
- mblk = rtp_session_recvm_with_ts(rs->sess, rs->rx_user_ts);
- if (mblk) {
- rtp_get_payload(mblk, &mblk->b_rptr);
- /* hand into receiver */
- if (rs->rx_cb)
- rs->rx_cb(rs, mblk->b_rptr,
- mblk->b_wptr - mblk->b_rptr);
- freemsg(mblk);
- } else
+ if (!recv_with_cb(rs))
LOGP(DLMIB, LOGL_INFO, "recvm_with_ts(%u): ERROR!\n",
rs->rx_user_ts);
rs->rx_user_ts += 160;
@@ -198,6 +199,10 @@ static int osmo_rtp_fd_cb(struct osmo_fd *fd, unsigned int what)
return 0;
}
+/* Internal API coming from rtpsession_priv.h, used in osmo_rtcp_fd_cb */
+#pragma message ("Using internal ortp API: rtp_session_rtcp_rec")
+int rtp_session_rtcp_recv(RtpSession * session);
+
static int osmo_rtcp_fd_cb(struct osmo_fd *fd, unsigned int what)
{
struct osmo_rtp_socket *rs = fd->data;
@@ -210,16 +215,24 @@ static int osmo_rtcp_fd_cb(struct osmo_fd *fd, unsigned int what)
static int osmo_rtp_socket_fdreg(struct osmo_rtp_socket *rs)
{
+ int rc;
+
rs->rtp_bfd.fd = rtp_session_get_rtp_socket(rs->sess);
rs->rtcp_bfd.fd = rtp_session_get_rtcp_socket(rs->sess);
rs->rtp_bfd.when = rs->rtcp_bfd.when = BSC_FD_READ;
- rs->rtp_bfd.when = rs->rtcp_bfd.when = 0;
rs->rtp_bfd.data = rs->rtcp_bfd.data = rs;
rs->rtp_bfd.cb = osmo_rtp_fd_cb;
rs->rtcp_bfd.cb = osmo_rtcp_fd_cb;
- osmo_fd_register(&rs->rtp_bfd);
- osmo_fd_register(&rs->rtcp_bfd);
+ rc = osmo_fd_register(&rs->rtp_bfd);
+ if (rc < 0)
+ return rc;
+
+ rc = osmo_fd_register(&rs->rtcp_bfd);
+ if (rc < 0) {
+ osmo_fd_unregister(&rs->rtp_bfd);
+ return rc;
+ }
return 0;
}
@@ -267,33 +280,45 @@ void osmo_rtp_init(void *ctx)
tall_rtp_ctx = ctx;
ortp_set_memory_functions(&osmo_ortp_memfn);
ortp_init();
- ortp_set_log_level_mask(0xffff);
+ ortp_set_log_level_mask(
+#if HAVE_ORTP_LOG_DOMAIN
+ ORTP_LOG_DOMAIN,
+#endif
+ 0xffff);
+
ortp_set_log_handler(my_ortp_logfn);
create_payload_types();
}
+/*! \brief Set Osmocom RTP socket parameters
+ * \param[in] rs OsmoRTP socket
+ * \param[in] param defined which parameter to set
+ OSMO_RTP_P_JITBUF - enables regular jitter buffering
+ OSMO_RTP_P_JIT_ADAP - enables adaptive jitter buffering
+ * \param[in] val Size of jitter buffer (in ms), 0 means disable buffering
+ * \returns negative value on error, 0 or 1 otherwise
+ (depending on whether given jitter buffering is enabled)
+ */
int osmo_rtp_socket_set_param(struct osmo_rtp_socket *rs,
enum osmo_rtp_param param, int val)
{
- int rc = 0;
-
switch (param) {
+ case OSMO_RTP_P_JIT_ADAP:
+ rtp_session_enable_adaptive_jitter_compensation(rs->sess,
+ (bool)val);
+ /* fall-through on-purpose - we have to set val anyway */
case OSMO_RTP_P_JITBUF:
rtp_session_enable_jitter_buffer(rs->sess,
(val) ? TRUE : FALSE);
if (val)
rtp_session_set_jitter_compensation(rs->sess, val);
break;
-#if 0
- case OSMO_RTP_P_JIT_ADAP:
- rc = jitter_control_enable_adaptive(rs->sess, val);
- break;
-#endif
default:
return -EINVAL;
}
-
- return rc;
+ if (param == OSMO_RTP_P_JIT_ADAP)
+ return rtp_session_adaptive_jitter_compensation_enabled(rs->sess);
+ return rtp_session_jitter_buffer_enabled(rs->sess);
}
/*! \brief Create a new RTP socket
@@ -313,7 +338,7 @@ struct osmo_rtp_socket *osmo_rtp_socket_create(void *talloc_ctx, unsigned int fl
if (!rs)
return NULL;
- rs->flags = flags;
+ rs->flags = OSMO_RTP_F_DISABLED | flags;
rs->sess = rtp_session_new(RTP_SESSION_SENDRECV);
if (!rs->sess) {
talloc_free(rs);
@@ -322,25 +347,27 @@ struct osmo_rtp_socket *osmo_rtp_socket_create(void *talloc_ctx, unsigned int fl
rtp_session_set_data(rs->sess, rs);
rtp_session_set_profile(rs->sess, osmo_pt_profile);
rtp_session_set_jitter_compensation(rs->sess, 100);
- //jitter_control_enable_adaptive(rs->sess, 0);
rtp_session_signal_connect(rs->sess, "ssrc_changed",
(RtpCallback) ortp_sig_cb_ssrc,
- (unsigned long) rs);
+ RTP_SIGNAL_PTR_CAST(rs));
+
rtp_session_signal_connect(rs->sess, "payload_type_changed",
(RtpCallback) ortp_sig_cb_pt,
- (unsigned long) rs);
+ RTP_SIGNAL_PTR_CAST(rs));
+
rtp_session_signal_connect(rs->sess, "network_error",
(RtpCallback) ortp_sig_cb_net,
- (unsigned long) rs);
+ RTP_SIGNAL_PTR_CAST(rs));
+
rtp_session_signal_connect(rs->sess, "timestamp_jump",
(RtpCallback) ortp_sig_cb_ts,
- (unsigned long) rs);
+ RTP_SIGNAL_PTR_CAST(rs));
/* initialize according to the RFC */
rtp_session_set_seq_number(rs->sess, random());
rs->tx_timestamp = random();
-
+
return rs;
}
@@ -353,12 +380,9 @@ struct osmo_rtp_socket *osmo_rtp_socket_create(void *talloc_ctx, unsigned int fl
*/
int osmo_rtp_socket_bind(struct osmo_rtp_socket *rs, const char *ip, int port)
{
- int rc;
-#if HAVE_ORTP_021
- rc = rtp_session_set_local_addr(rs->sess, ip, port, port+1);
-#else
- rc = rtp_session_set_local_addr(rs->sess, ip, port);
-#endif
+ int rc, rtcp = (-1 != port) ? port + 1 : -1;
+ rc = rtp_session_set_local_addr(rs->sess, ip, port, rtcp);
+
if (rc < 0)
return rc;
@@ -382,22 +406,58 @@ int osmo_rtp_socket_bind(struct osmo_rtp_socket *rs, const char *ip, int port)
int osmo_rtp_socket_connect(struct osmo_rtp_socket *rs, const char *ip, uint16_t port)
{
int rc;
+ if (!port) {
+ LOGP(DLMIB, LOGL_INFO, "osmo_rtp_socket_connect() refused to "
+ "set remote %s:%u\n", ip, port);
+ return 0;
+ }
- /* enable the use of connect() so later getsockname() will
- * actually return the IP address that was chosen for the local
- * sid of the connection */
- rtp_session_set_connected_mode(rs->sess, 1);
+ /* We don't want the connected mode enabled during
+ * rtp_session_set_remote_addr(), because that will already setup a
+ * connection and updating the remote address will no longer have an
+ * effect. Contrary to what one may expect, this must be 0 at first,
+ * and we're setting to 1 further down to establish a connection once
+ * the first RTP packet is received (OS#1661). */
+ rtp_session_set_connected_mode(rs->sess, 0);
rc = rtp_session_set_remote_addr(rs->sess, ip, port);
if (rc < 0)
return rc;
+ /* enable the use of connect() so later getsockname() will
+ * actually return the IP address that was chosen for the local
+ * sid of the connection */
+ rtp_session_set_connected_mode(rs->sess, 1);
+ rs->flags &= ~OSMO_RTP_F_DISABLED;
+
if (rs->flags & OSMO_RTP_F_POLL)
return rc;
else
return osmo_rtp_socket_fdreg(rs);
}
+/*! \brief Increment timestamp on a RTP socket without sending any packet
+ * \param[in] rs OsmoRTP socket
+ * \param[in] duration duration in number of RTP clock ticks
+ *
+ * Useful to keep the RTP internal clock up to date if an RTP frame should be
+ * send at a given time but no audio content is available. When next packet is
+ * sent, the receiver will see a different increase on the sequence number and
+ * the timestamp, and it should then take it as a synchronization point. For
+ * that same reason, it is advisable to enable the marker bit on the next RTP
+ * packet to be sent after calling this function.
+ *
+ * \returns 0 on success, <0 in case of error.
+ */
+int osmo_rtp_skipped_frame(struct osmo_rtp_socket *rs, unsigned int duration)
+{
+ if (rs->flags & OSMO_RTP_F_DISABLED)
+ return 0;
+
+ rs->tx_timestamp += duration;
+ return 0;
+}
+
/*! \brief Send one RTP frame via a RTP socket
* \param[in] rs OsmoRTP socket
* \param[in] payload pointer to buffer with RTP payload data
@@ -408,14 +468,34 @@ int osmo_rtp_socket_connect(struct osmo_rtp_socket *rs, const char *ip, uint16_t
int osmo_rtp_send_frame(struct osmo_rtp_socket *rs, const uint8_t *payload,
unsigned int payload_len, unsigned int duration)
{
+ return osmo_rtp_send_frame_ext(rs, payload, payload_len, duration,
+ false);
+}
+
+/*! \brief Send one RTP frame via a RTP socket
+ * \param[in] rs OsmoRTP socket
+ * \param[in] payload pointer to buffer with RTP payload data
+ * \param[in] payload_len length of \a payload in bytes
+ * \param[in] duration duration in number of RTP clock ticks
+ * \param[in] marker the status of Marker bit in RTP header
+ * \returns 0 on success, <0 in case of error.
+ */
+int osmo_rtp_send_frame_ext(struct osmo_rtp_socket *rs, const uint8_t *payload,
+ unsigned int payload_len, unsigned int duration,
+ bool marker)
+{
mblk_t *mblk;
int rc;
+ if (rs->flags & OSMO_RTP_F_DISABLED)
+ return 0;
+
mblk = rtp_session_create_packet(rs->sess, RTP_FIXED_HEADER_SIZE,
payload, payload_len);
if (!mblk)
return -ENOMEM;
+ rtp_set_markbit(mblk, marker);
rc = rtp_session_sendm_with_ts(rs->sess, mblk,
rs->tx_timestamp);
rs->tx_timestamp += duration;
@@ -567,11 +647,9 @@ void osmo_rtp_socket_stats(struct osmo_rtp_socket *rs,
*recv_lost = stats->cum_packet_loss;
}
-#if HAVE_ORTP_021
const jitter_stats_t *jitter;
jitter = rtp_session_get_jitter_stats(rs->sess);
if (jitter)
*last_jitter = jitter->jitter;
-#endif
}