Projects
osmocom:latest
libosmo-netif
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 8
View file
libosmo-netif.spec
Added
@@ -0,0 +1,88 @@ +# +# spec file for package libosmo-netif +# +# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. +# +# All modifications and additions to the file contributed by third parties +# remain the property of their copyright owners, unless otherwise agreed +# upon. The license for this file, and modifications and additions to the +# file, is the same license as for the pristine package itself (unless the +# license for the pristine package is not an Open Source License, in which +# case the license is the MIT License). An "Open Source License" is a +# license that conforms to the Open Source Definition (Version 1.9) +# published by the Open Source Initiative. + +Name: libosmo-netif +Requires: osmocom-latest +Version: 1.6.0 +Release: 0 +Summary: Osmocom library for muxed audio +License: GPL-2.0-or-later +Group: Productivity/Telephony/Utilities +URL: https://osmocom.org/projects/libosmo-netif +Source: libosmo-netif_1.6.0.tar.xz +Source1: rpmlintrc +BuildRequires: automake +BuildRequires: libtool >= 2 +BuildRequires: lksctp-tools-devel +BuildRequires: pkgconfig >= 0.20 +BuildRequires: pkgconfig(libosmocore) >= 1.11.0 +BuildRequires: pkgconfig(libosmogsm) >= 1.11.0 +BuildRequires: pkgconfig(libosmocodec) >= 1.11.0 + +%description +Network interface demuxer library for OsmoCom projects. + +%package -n libosmonetif11 +Requires: osmocom-latest +Summary: Osmocom library for muxed audio +License: AGPL-3.0-or-later +Group: System/Libraries + +%description -n libosmonetif11 +Network interface demuxer library for OsmoCom projects. + +%package -n libosmonetif-devel +Requires: osmocom-latest +Summary: Development files for the Osmocom muxed audio library +License: AGPL-3.0-or-later +Group: Development/Libraries/C and C++ +Requires: libosmonetif11 = %{version} + +%description -n libosmonetif-devel +Network interface demuxer library for OsmoCom projects. + +This subpackage contains libraries and header files for developing +applications that want to make use of libosmo-netif. + +%prep +%setup -n libosmo-netif -q + +%build +echo "%{version}" >.tarball-version +autoreconf -fiv +%configure --enable-shared --disable-static --includedir="%{_includedir}/%{name}" +make %{?_smp_mflags} + +%install +%make_install +find %{buildroot} -type f -name "*.la" -delete -print + +%check +make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +) + +%post -n libosmonetif11 -p /sbin/ldconfig +%postun -n libosmonetif11 -p /sbin/ldconfig + +%files -n libosmonetif11 +%{_libdir}/libosmonetif.so.11* + +%files -n libosmonetif-devel +%license COPYING +%dir %{_includedir}/%{name} +%dir %{_includedir}/%{name}/osmocom +%{_includedir}/%{name}/osmocom/netif/ +%{_libdir}/libosmonetif.so +%{_libdir}/pkgconfig/libosmo-netif.pc + +%changelog
View file
libosmo-netif_1.5.1.tar.xz/examples/lapd-over-datagram-network.c
Deleted
@@ -1,177 +0,0 @@ -/* LAPD over datagram network-mode example. */ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include <osmocom/core/talloc.h> -#include <osmocom/core/msgb.h> -#include <osmocom/core/logging.h> -#include <osmocom/core/application.h> -#include <osmocom/core/select.h> - -#include <osmocom/abis/lapd.h> - -#include <osmocom/netif/datagram.h> - -static void *tall_test; - -#define DLAPDTEST 0 - -struct log_info_cat lapd_test_cat = { - DLAPDTEST = { - .name = "DLAPDTEST", - .description = "LAPD-mode test", - .color = "\0331;35m", - .enabled = 1, .loglevel = LOGL_DEBUG, - }, -}; - -const struct log_info lapd_test_log_info = { - .filter_fn = NULL, - .cat = lapd_test_cat, - .num_cat = ARRAY_SIZE(lapd_test_cat), -}; - -static struct osmo_dgram *conn; -static struct lapd_instance *lapd; -static int tei = 0; - -void sighandler(int foo) -{ - lapd_instance_free(lapd); - LOGP(DLAPDTEST, LOGL_NOTICE, "closing LAPD.\n"); - exit(EXIT_SUCCESS); -} - -int read_cb(struct osmo_dgram *conn) -{ - int error; - struct msgb *msg; - - LOGP(DLAPDTEST, LOGL_DEBUG, "received message from datagram\n"); - - msg = msgb_alloc(1200, "LAPD/test"); - if (msg == NULL) { - LOGP(DLAPDTEST, LOGL_ERROR, "cannot allocate message\n"); - return -1; - } - if (osmo_dgram_recv(conn, msg) < 0) { - LOGP(DLAPDTEST, LOGL_ERROR, "cannot receive message\n"); - return -1; - } - if (lapd_receive(lapd, msg, &error) < 0) { - LOGP(DLAPDTEST, LOGL_ERROR, "lapd_receive returned error!\n"); - return -1; - } - - return 0; -} - -void lapd_tx_cb(struct msgb *msg, void *cbdata) -{ - struct osmo_dgram *conn = cbdata; - - LOGP(DLAPDTEST, LOGL_DEBUG, "sending message over datagram\n"); - osmo_dgram_send(conn, msg); -} - -void lapd_rx_cb(struct osmo_dlsap_prim *dp, uint8_t tei, uint8_t sapi, - void *rx_cbdata) -{ - struct msgb *msg = dp->oph.msg; - - switch (dp->oph.primitive) { - case PRIM_DL_EST: - DEBUGP(DLAPDTEST, "DL_EST: sapi(%d) tei(%d)\n", sapi, tei); - break; - case PRIM_DL_REL: - DEBUGP(DLAPDTEST, "DL_REL: sapi(%d) tei(%d)\n", sapi, tei); - break; - case PRIM_DL_DATA: - case PRIM_DL_UNIT_DATA: - if (dp->oph.operation == PRIM_OP_INDICATION) { - struct msgb *nmsg; - char *ptr; - int x; - - msg->l2h = msg->l3h; - - DEBUGP(DLAPDTEST, "RX: %s sapi=%d tei=%d\n", - osmo_hexdump(msgb_l2(msg), msgb_l2len(msg)), - sapi, tei); - - LOGP(DLAPDTEST, LOGL_DEBUG, "forwarding message\n"); - - nmsg = msgb_alloc(1024, "LAPD/test"); - if (nmsg == NULL) { - LOGP(DLAPDTEST, LOGL_ERROR, "cannot alloc msg\n"); - return; - } - ptr = (char *)msgb_put(nmsg, sizeof(int)); - - x = *((int *)msg->data); - memcpy(ptr, &x, sizeof(int)); - - /* send the message back to client over LAPD */ - lapd_transmit(lapd, tei, sapi, msg); - return; - } - break; - case PRIM_MDL_ERROR: - DEBUGP(DLMI, "MDL_EERROR: cause(%d)\n", dp->u.error_ind.cause); - break; - default: - printf("ERROR: unknown prim\n"); - break; - } -} - -int main(int argc, char *argv) -{ - struct lapd_tei *teip; - - tall_test = talloc_named_const(NULL, 1, "lapd_test"); - msgb_talloc_ctx_init(tall_test, 0); - osmo_init_logging2(tall_test, &lapd_test_log_info); - log_set_log_level(osmo_stderr_target, LOGL_NOTICE); - - /* - * initialize datagram server. - */ - - conn = osmo_dgram_create(tall_test); - if (conn == NULL) { - fprintf(stderr, "cannot create client\n"); - exit(EXIT_FAILURE); - } - osmo_dgram_set_local_addr(conn, "127.0.0.1"); - osmo_dgram_set_local_port(conn, 10001); - osmo_dgram_set_remote_addr(conn, "127.0.0.1"); - osmo_dgram_set_remote_port(conn, 10000); - osmo_dgram_set_read_cb(conn, read_cb); - - lapd = lapd_instance_alloc(1, lapd_tx_cb, conn, lapd_rx_cb, conn, - &lapd_profile_sat); - if (lapd == NULL) { - LOGP(DLAPDTEST, LOGL_ERROR, "cannot allocate instance\n"); - exit(EXIT_FAILURE); - } - - teip = lapd_tei_alloc(lapd, tei); - if (teip == NULL) { - LOGP(DLAPDTEST, LOGL_ERROR, "cannot assign TEI\n"); - exit(EXIT_FAILURE); - } - - if (osmo_dgram_open(conn) < 0) { - fprintf(stderr, "cannot open client\n"); - exit(EXIT_FAILURE); - } - - LOGP(DLAPDTEST, LOGL_NOTICE, "Entering main loop\n"); - - while(1) { - osmo_select_main(0); - } -}
View file
libosmo-netif_1.5.1.tar.xz/examples/lapd-over-datagram-user.c
Deleted
@@ -1,241 +0,0 @@ -/* LAPD over datagram user-mode example. */ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <signal.h> -#include <unistd.h> -#include <arpa/inet.h> - -#include <osmocom/core/linuxlist.h> -#include <osmocom/core/talloc.h> -#include <osmocom/core/msgb.h> -#include <osmocom/core/logging.h> -#include <osmocom/core/application.h> -#include <osmocom/core/select.h> - -#include <osmocom/abis/lapd.h> - -#include <osmocom/netif/datagram.h> - -static LLIST_HEAD(msg_sent_list); - -struct msg_sent { - struct llist_head head; - struct msgb *msg; - int num; - struct timeval tv; -}; - -#define DLAPDTEST 0 - -struct log_info_cat lapd_test_cat = { - DLAPDTEST = { - .name = "DLAPDTEST", - .description = "LAPD-mode test", - .color = "\0331;35m", - .enabled = 1, .loglevel = LOGL_DEBUG, - }, -}; - -const struct log_info lapd_test_log_info = { - .filter_fn = NULL, - .cat = lapd_test_cat, - .num_cat = ARRAY_SIZE(lapd_test_cat), -}; - -static struct osmo_dgram *conn; -static struct lapd_instance *lapd; -static int sapi = 63, tei = 0; - -void sighandler(int foo) -{ - lapd_sap_stop(lapd, tei, sapi); - lapd_instance_free(lapd); - LOGP(DLINP, LOGL_NOTICE, "closing LAPD.\n"); - exit(EXIT_SUCCESS); -} - -static int read_cb(struct osmo_dgram *conn) -{ - int error; - struct msgb *msg; - - msg = msgb_alloc(1200, "LAPD/test"); - if (msg == NULL) { - LOGP(DLAPDTEST, LOGL_ERROR, "cannot allocate message\n"); - return -1; - } - if (osmo_dgram_recv(conn, msg) < 0) { - msgb_free(msg); - LOGP(DLAPDTEST, LOGL_ERROR, "cannot receive message\n"); - return -1; - } - if (lapd_receive(lapd, msg, &error) < 0) { - msgb_free(msg); - LOGP(DLINP, LOGL_ERROR, "lapd_receive returned error!\n"); - return -1; - } - return 0; -} - -static void *tall_test; - -void lapd_tx_cb(struct msgb *msg, void *cbdata) -{ - LOGP(DLINP, LOGL_DEBUG, "sending message over datagram\n"); - osmo_dgram_send(conn, msg); -} - -void lapd_rx_cb(struct osmo_dlsap_prim *dp, uint8_t tei, uint8_t sapi, - void *rx_cbdata) -{ - struct msgb *msg = dp->oph.msg; - int *__msgs = rx_cbdata; - int num_msgs = *__msgs; - - switch (dp->oph.primitive) { - case PRIM_DL_EST: - DEBUGP(DLAPDTEST, "DL_EST: sapi(%d) tei(%d)\n", sapi, tei); - - int i; - for (i=0; i<num_msgs; i++) { - struct msgb *msg; - struct msg_sent *msg_sent; - char *ptr; - int x; - - msg = msgb_alloc(1024, "LAPD/test"); - if (msg == NULL) { - LOGP(DLINP, LOGL_ERROR, "cannot alloc msg\n"); - return; - } - ptr = (char *)msgb_put(msg, sizeof(int)); - - x = htonl(i); - memcpy(ptr, &x, sizeof(int)); - - msg_sent = talloc_zero(NULL, struct msg_sent); - if (msg_sent == NULL) { - LOGP(DLINP, LOGL_ERROR, "can't alloc struct\n"); - return; - } - msg_sent->msg = msg; - gettimeofday(&msg_sent->tv, NULL); - msg_sent->num = i; - llist_add(&msg_sent->head, &msg_sent_list); - - lapd_transmit(lapd, tei, sapi, msg); - - LOGP(DLAPDTEST, LOGL_DEBUG, "enqueueing msg %d of " - "%d bytes to be sent over LAPD\n", i, msg->len); - } - break; - case PRIM_DL_REL: - DEBUGP(DLAPDTEST, "DL_REL: sapi(%d) tei(%d)\n", sapi, tei); - break; - case PRIM_DL_DATA: - case PRIM_DL_UNIT_DATA: - if (dp->oph.operation == PRIM_OP_INDICATION) { - msg->l2h = msg->l3h; - DEBUGP(DLAPDTEST, "RX: %s sapi=%d tei=%d\n", - osmo_hexdump(msgb_l2(msg), msgb_l2len(msg)), - sapi, tei); - - int num; - struct msg_sent *cur, *tmp, *found = NULL; - - num = ntohl(*((int *)msg->data)); - LOGP(DLINP, LOGL_DEBUG, - "received msg number %d\n", num); - - llist_for_each_entry_safe(cur, tmp, - &msg_sent_list, head) { - if (cur->num == num) { - llist_del(&cur->head); - found = cur; - break; - } - } - if (found) { - struct timeval tv, diff; - - gettimeofday(&tv, NULL); - timersub(&tv, &found->tv, &diff); - - LOGP(DLINP, LOGL_NOTICE, "message %d replied " - "in %lu.%.6lu\n", - num, diff.tv_sec, diff.tv_usec); - talloc_free(found); - } else { - LOGP(DLINP, LOGL_ERROR, - "message %d not found!\n", num); - } - } - break; - case PRIM_MDL_ERROR: - DEBUGP(DLMI, "MDL_EERROR: cause(%d)\n", dp->u.error_ind.cause); - break; - default: - printf("ERROR: unknown prim\n"); - break; - } -} - -int main(int argc, char *argv) -{ - int num_msgs; - - signal(SIGINT, sighandler); - - if (argc != 2) { - printf("Usage: %s num_msgs\n", argv0); - exit(EXIT_FAILURE); - } - num_msgs = atoi(argv1); - - tall_test = talloc_named_const(NULL, 1, "lapd_test"); - msgb_talloc_ctx_init(tall_test, 0); - osmo_init_logging2(tall_test, &lapd_test_log_info); - log_set_log_level(osmo_stderr_target, LOGL_NOTICE);
View file
libosmo-netif_1.5.1.dsc -> libosmo-netif_1.6.0.dsc
Changed
@@ -2,21 +2,21 @@ Source: libosmo-netif Binary: libosmonetif11, libosmo-netif-dev, libosmo-netif-doc, libosmo-netif-dbg Architecture: any all -Version: 1.5.1 +Version: 1.6.0 Maintainer: Osmocom team <openbsc@lists.osmocom.org> Homepage: https://projects.osmocom.org/projects/libosmo-netif Standards-Version: 3.9.6 Vcs-Browser: https://gitea.osmocom.org/osmocom/libosmo-netif Vcs-Git: https://gitea.osmocom.org/osmocom/libosmo-netif -Build-Depends: debhelper (>= 10), autotools-dev, autoconf, automake, libtool, dh-autoreconf, libdpkg-perl, git, doxygen, libosmocore-dev (>= 1.10.0), pkg-config, libpcap0.8-dev, libsctp-dev +Build-Depends: debhelper (>= 10), autotools-dev, autoconf, automake, libtool, dh-autoreconf, libdpkg-perl, git, doxygen, libosmocore-dev (>= 1.11.0), pkg-config, libpcap0.8-dev, libsctp-dev Package-List: libosmo-netif-dbg deb debug extra arch=any libosmo-netif-dev deb libdevel optional arch=any libosmo-netif-doc deb doc optional arch=all libosmonetif11 deb libs optional arch=any Checksums-Sha1: - 0dc84bed056bfacd0fd34a906437c520108bf7b4 193920 libosmo-netif_1.5.1.tar.xz + cbca1e98841ef72f31496d14386a0da2e27f1350 199208 libosmo-netif_1.6.0.tar.xz Checksums-Sha256: - a8566de108b03450b119d71ac5c75e6883a486d1d4c559c79e10d360592396dd 193920 libosmo-netif_1.5.1.tar.xz + 76f2334acef97398995178dd94722c2a62412f4514a052268aa2ffc77df58ac7 199208 libosmo-netif_1.6.0.tar.xz Files: - 16608100282ac7ba4b342c9c6ff46b0c 193920 libosmo-netif_1.5.1.tar.xz + bed32e77acc2f045f94147a4cd375568 199208 libosmo-netif_1.6.0.tar.xz
View file
libosmo-netif_1.5.1.tar.xz/.tarball-version -> libosmo-netif_1.6.0.tar.xz/.tarball-version
Changed
@@ -1 +1 @@ -1.5.1 +1.6.0
View file
libosmo-netif_1.5.1.tar.xz/Makefile.am -> libosmo-netif_1.6.0.tar.xz/Makefile.am
Changed
@@ -9,6 +9,7 @@ EXTRA_DIST = \ .version \ README.md \ + contrib/libosmo-netif.spec.in \ debian \ git-version-gen \ $(NULL)
View file
libosmo-netif_1.5.1.tar.xz/configure.ac -> libosmo-netif_1.6.0.tar.xz/configure.ac
Changed
@@ -89,22 +89,9 @@ dnl Generate the output AM_CONFIG_HEADER(config.h) -PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.10.0) -PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.10.0) -PKG_CHECK_MODULES(LIBOSMOCODEC, libosmocodec >= 1.10.0) - -AC_ARG_ENABLE(lapd_examples, - AS_HELP_STRING( - --enable-lapd-examples, - Build some lapd examples - ), - lapd_examples=$enableval, lapd_examples="no") -AS_IF(test "x$lapd_examples" = "xyes", - PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 1.5.0) - AC_DEFINE(ENABLE_LAPD, 1, Enable LAPD examples) -) -AM_CONDITIONAL(ENABLE_LAPD, test "x$lapd_examples" = "xyes") -AC_SUBST(ENABLE_LAPD) +PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.11.0) +PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.11.0) +PKG_CHECK_MODULES(LIBOSMOCODEC, libosmocodec >= 1.11.0) AC_ARG_ENABLE(libsctp, AS_HELP_STRING(--disable-libsctp, Do not enable socket multiaddr APIs requiring libsctp), ENABLE_LIBSCTP=$enableval, ENABLE_LIBSCTP="yes") @@ -148,4 +135,5 @@ utils/Makefile tests/Makefile Doxyfile - Makefile) + Makefile + contrib/libosmo-netif.spec)
View file
libosmo-netif_1.5.1.tar.xz/contrib/jenkins.sh -> libosmo-netif_1.6.0.tar.xz/contrib/jenkins.sh
Changed
@@ -24,7 +24,6 @@ export LD_LIBRARY_PATH="$inst/lib" osmo-build-dep.sh libosmocore "" --disable-doxygen -osmo-build-dep.sh libosmo-abis set +x echo
View file
libosmo-netif_1.6.0.tar.xz/contrib/libosmo-netif.spec.in
Added
@@ -0,0 +1,87 @@ +# +# spec file for package libosmo-netif +# +# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. +# +# All modifications and additions to the file contributed by third parties +# remain the property of their copyright owners, unless otherwise agreed +# upon. The license for this file, and modifications and additions to the +# file, is the same license as for the pristine package itself (unless the +# license for the pristine package is not an Open Source License, in which +# case the license is the MIT License). An "Open Source License" is a +# license that conforms to the Open Source Definition (Version 1.9) +# published by the Open Source Initiative. + +Name: libosmo-netif +Requires: osmocom-latest +Version: @VERSION@ +Release: 0 +Summary: Osmocom library for muxed audio +License: GPL-2.0-or-later +Group: Productivity/Telephony/Utilities +URL: https://osmocom.org/projects/libosmo-netif +Source: %{name}-%{version}.tar.xz +BuildRequires: automake +BuildRequires: libtool >= 2 +BuildRequires: lksctp-tools-devel +BuildRequires: pkgconfig >= 0.20 +BuildRequires: pkgconfig(libosmocore) >= 1.11.0 +BuildRequires: pkgconfig(libosmogsm) >= 1.11.0 +BuildRequires: pkgconfig(libosmocodec) >= 1.11.0 + +%description +Network interface demuxer library for OsmoCom projects. + +%package -n libosmonetif11 +Requires: osmocom-latest +Summary: Osmocom library for muxed audio +License: AGPL-3.0-or-later +Group: System/Libraries + +%description -n libosmonetif11 +Network interface demuxer library for OsmoCom projects. + +%package -n libosmonetif-devel +Requires: osmocom-latest +Summary: Development files for the Osmocom muxed audio library +License: AGPL-3.0-or-later +Group: Development/Libraries/C and C++ +Requires: libosmonetif11 = %{version} + +%description -n libosmonetif-devel +Network interface demuxer library for OsmoCom projects. + +This subpackage contains libraries and header files for developing +applications that want to make use of libosmo-netif. + +%prep +%setup -q + +%build +echo "%{version}" >.tarball-version +autoreconf -fiv +%configure --enable-shared --disable-static --includedir="%{_includedir}/%{name}" +make %{?_smp_mflags} + +%install +%make_install +find %{buildroot} -type f -name "*.la" -delete -print + +%check +make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +) + +%post -n libosmonetif11 -p /sbin/ldconfig +%postun -n libosmonetif11 -p /sbin/ldconfig + +%files -n libosmonetif11 +%{_libdir}/libosmonetif.so.11* + +%files -n libosmonetif-devel +%license COPYING +%dir %{_includedir}/%{name} +%dir %{_includedir}/%{name}/osmocom +%{_includedir}/%{name}/osmocom/netif/ +%{_libdir}/libosmonetif.so +%{_libdir}/pkgconfig/libosmo-netif.pc + +%changelog
View file
libosmo-netif_1.5.1.tar.xz/debian/changelog -> libosmo-netif_1.6.0.tar.xz/debian/changelog
Changed
@@ -1,3 +1,51 @@ +libosmo-netif (1.6.0) unstable; urgency=medium + + Harald Welte + * stream_test: don't check if uint8_t is negative + * src/stream.c: Use sctp_assoc_id 'canary' to detect misisng sinfo + + Neels Hofmeyr + * osmo_rtp_get_payload(): fix bounds check for padding + * coverity CID#216829 + * api doc: stream.h: hint at how to select modern vs legacy mode + + Pau Espin Pedrol + * rtp: osmo_rtp_get_payload(): Fix return ptr if RTP pkt contains padding + * Drop libosmo-abis cond dep together with examples/lapd-over-datagram + * stream_cli: Allow setting nodelay sockopt after opening sock + * examples/ipa-stream-client: Fix wrong call to osmo_ipa_process_msg() + * stream: Explicitly document MSG_NOTIFICATION case in recv() API + * stream: Improve logging around recv() failure + * stream_cli: Log all code paths ending up in close/reconnect + * stream_cli: Announce failed connect() if reconnect is disabled + * stream_cli: Add osmo_stream_cli_set_{ip_dscp,priority}() APIs + * stream_srv: Add osmo_stream_srv_link_set_{ip_dscp,priority}() APIs + * stream_cli: Rename private functions + * stream_cli: Move osmo_stream_cli_close() before osmo_stream_cli_reconnect() + * stream_cli: Support destroy object within user callback + * stream_cli: Add API osmo_stream_cli_set_tx_queue_max_length() + * stream_srv: Add API osmo_stream_srv_link_set_tx_queue_max_length() + * stream: Allow null ptr in destroy() functions + * stream_cli: steal talloc ctx upon delaying free to avoid use after free + * stream_cli: Assert reentrant disconnect_cb() never happens + * stream_cli: Explicitly ignore return code of stream_cli_close + * stream_cli: Explicitly ignore return code of internal functions + * stream_cli: Fix discard 1st msg received quick after connect + * ipa: Add osmo_ipa_ka_fsm_inst APIs + * stream: Introduce osmo_stream_{cli,srv}_set_segmentation_cb2 + * stream: Add osmo_stream_srv_link_set_msgb_alloc_info() + * stream: Undeprecate osmo_stream_srv_set_segmentation_cb() + * stream: osmo_stream_{cli,srv}_set_segmentation_cb(2): documentation improvements + + Mychaela N. Falconia + * include/osmocom/netif/Makefile.am cosmetic: make it easier to extend + * src/Makefile.am cosmetic: make it easier to extend + + Oliver Smith + * Revert "contrib: remove rpm spec file" + + -- Oliver Smith <osmith@sysmocom.de> Wed, 12 Feb 2025 11:01:12 +0100 + libosmo-netif (1.5.1) unstable; urgency=medium Daniel Willmann
View file
libosmo-netif_1.5.1.tar.xz/debian/control -> libosmo-netif_1.6.0.tar.xz/debian/control
Changed
@@ -11,7 +11,7 @@ libdpkg-perl, git, doxygen, - libosmocore-dev (>= 1.10.0), + libosmocore-dev (>= 1.11.0), pkg-config, libpcap0.8-dev, libsctp-dev
View file
libosmo-netif_1.5.1.tar.xz/examples/Makefile.am -> libosmo-netif_1.6.0.tar.xz/examples/Makefile.am
Changed
@@ -1,5 +1,5 @@ AM_CPPFLAGS = -I$(top_srcdir)/include -AM_CFLAGS=-Wall -g $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(COVERAGE_CFLAGS) +AM_CFLAGS=-Wall -g $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(COVERAGE_CFLAGS) AM_LDFLAGS = $(COVERAGE_LDFLAGS) noinst_PROGRAMS = ipa-stream-client \ @@ -25,19 +25,6 @@ ipa_stream_server_LDADD = $(top_builddir)/src/libosmonetif.la \ $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) -if ENABLE_LAPD -noinst_PROGRAMS += lapd-over-datagram-user lapd-over-datagram-network -lapd_over_datagram_user_SOURCES = lapd-over-datagram-user.c -lapd_over_datagram_user_LDADD = $(top_builddir)/src/libosmonetif.la \ - $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) \ - $(LIBOSMOABIS_LIBS) - -lapd_over_datagram_network_SOURCES = lapd-over-datagram-network.c -lapd_over_datagram_network_LDADD = $(top_builddir)/src/libosmonetif.la \ - $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) \ - $(LIBOSMOABIS_LIBS) -endif - stream_client_SOURCES = stream-client.c stream_client_LDADD = $(top_builddir)/src/libosmonetif.la \ $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS)
View file
libosmo-netif_1.5.1.tar.xz/examples/ipa-stream-client.c -> libosmo-netif_1.6.0.tar.xz/examples/ipa-stream-client.c
Changed
@@ -115,13 +115,7 @@ return 0; } - if (osmo_ipa_process_msg(msg) < 0) { - LOGP(DIPATEST, LOGL_ERROR, "bad IPA message\n"); - msgb_free(msg); - return 0; - } - - num = osmo_load32be(msg->data); + num = osmo_load32be(msgb_l2(msg)); LOGP(DLINP, LOGL_DEBUG, "received msg number %d\n", num); llist_for_each_entry_safe(cur, tmp, &msg_sent_list, head) {
View file
libosmo-netif_1.5.1.tar.xz/include/osmocom/netif/Makefile.am -> libosmo-netif_1.6.0.tar.xz/include/osmocom/netif/Makefile.am
Changed
@@ -4,14 +4,15 @@ osmonetif_HEADERS = amr.h \ datagram.h \ - jibuf.h \ - osmux.h \ ipa.h \ ipa_unit.h \ + jibuf.h \ + osmux.h \ prim.h \ rs232.h \ rtp.h \ - stream.h + stream.h \ + $(NULL) if ENABLE_LIBSCTP osmonetif_HEADERS += sctp.h
View file
libosmo-netif_1.5.1.tar.xz/include/osmocom/netif/ipa.h -> libosmo-netif_1.6.0.tar.xz/include/osmocom/netif/ipa.h
Changed
@@ -67,4 +67,28 @@ void osmo_ipa_msg_push_headers(struct msgb *msg, enum ipaccess_proto p, enum ipaccess_proto_ext pe); +/*********************************************************************** + * IPA Keep-Alive FSM + ***********************************************************************/ +struct osmo_ipa_ka_fsm_inst; +typedef int (*osmo_ipa_ka_fsm_timeout_cb_t)(struct osmo_ipa_ka_fsm_inst *ka_fi, void *data); + +typedef int (*osmo_ipa_ka_fsm_send_cb_t)(struct osmo_ipa_ka_fsm_inst *ka_fi, struct msgb *msg, void *data); + +struct osmo_ipa_ka_fsm_inst *osmo_ipa_ka_fsm_alloc(void *ctx, const char *id); +void osmo_ipa_ka_fsm_free(struct osmo_ipa_ka_fsm_inst *ka_fi); + +int osmo_ipa_ka_fsm_set_id(struct osmo_ipa_ka_fsm_inst *ka_fi, const char *id); +int osmo_ipa_ka_fsm_set_ping_interval(struct osmo_ipa_ka_fsm_inst *ka_fi, unsigned int interval); +int osmo_ipa_ka_fsm_set_pong_timeout(struct osmo_ipa_ka_fsm_inst *ka_fi, unsigned int timeout); +void osmo_ipa_ka_fsm_set_data(struct osmo_ipa_ka_fsm_inst *ka_fi, void *cb_data); +void *osmo_ipa_ka_fsm_get_data(const struct osmo_ipa_ka_fsm_inst *ka_fi); + +void osmo_ipa_ka_fsm_set_send_cb(struct osmo_ipa_ka_fsm_inst *ka_fi, osmo_ipa_ka_fsm_send_cb_t send_cb); +void osmo_ipa_ka_fsm_set_timeout_cb(struct osmo_ipa_ka_fsm_inst *ka_fi, osmo_ipa_ka_fsm_timeout_cb_t timeout_cb); + +void osmo_ipa_ka_fsm_start(struct osmo_ipa_ka_fsm_inst *ka_fi); +void osmo_ipa_ka_fsm_pong_received(struct osmo_ipa_ka_fsm_inst *ka_fi); +void osmo_ipa_ka_fsm_stop(struct osmo_ipa_ka_fsm_inst *ka_fi); + #endif
View file
libosmo-netif_1.5.1.tar.xz/include/osmocom/netif/stream.h -> libosmo-netif_1.6.0.tar.xz/include/osmocom/netif/stream.h
Changed
@@ -32,6 +32,9 @@ * For any new applications, you definitely should use the modern mode, as it provides you with a higher * layer of abstraction and allows you to perform efficient I/O using the io_uring backend of osmo_io. * + * The modern mode is chosen by invoking osmo_stream_srv_create2(). + * The legacy mode is chosen by invoking the older osmo_stream_srv_create(). + * * The two main objects are osmo_stream_srv_link (main server accept()ing incoming connections) and * osmo_stream_srv (a single given connection from a remote client). * @@ -70,6 +73,8 @@ void osmo_stream_srv_link_set_name(struct osmo_stream_srv_link *link, const char *name); const char *osmo_stream_srv_link_get_name(const struct osmo_stream_srv_link *link); void osmo_stream_srv_link_set_nodelay(struct osmo_stream_srv_link *link, bool nodelay); +int osmo_stream_srv_link_set_priority(struct osmo_stream_srv_link *link, int sk_prio); +int osmo_stream_srv_link_set_ip_dscp(struct osmo_stream_srv_link *link, uint8_t ip_dscp); void osmo_stream_srv_link_set_addr(struct osmo_stream_srv_link *link, const char *addr); int osmo_stream_srv_link_set_addrs(struct osmo_stream_srv_link *link, const char **addr, size_t addrcnt); void osmo_stream_srv_link_set_port(struct osmo_stream_srv_link *link, uint16_t port); @@ -79,9 +84,11 @@ void osmo_stream_srv_link_set_accept_cb(struct osmo_stream_srv_link *link, osmo_stream_srv_link_accept_cb_t accept_cb); void osmo_stream_srv_link_set_data(struct osmo_stream_srv_link *link, void *data); void *osmo_stream_srv_link_get_data(struct osmo_stream_srv_link *link); +int osmo_stream_srv_link_set_tx_queue_max_length(struct osmo_stream_srv_link *link, unsigned int size); char *osmo_stream_srv_link_get_sockname(const struct osmo_stream_srv_link *link); struct osmo_fd *osmo_stream_srv_link_get_ofd(struct osmo_stream_srv_link *link); int osmo_stream_srv_link_get_fd(const struct osmo_stream_srv_link *link); +int osmo_stream_srv_link_set_msgb_alloc_info(struct osmo_stream_srv_link *link, unsigned int size, unsigned int headroom); bool osmo_stream_srv_link_is_opened(const struct osmo_stream_srv_link *link); int osmo_stream_srv_link_open(struct osmo_stream_srv_link *link); void osmo_stream_srv_link_close(struct osmo_stream_srv_link *link); @@ -111,6 +118,7 @@ typedef int (*osmo_stream_srv_read_cb2_t)(struct osmo_stream_srv *conn, int res, struct msgb *msg); typedef int (*osmo_stream_srv_segmentation_cb_t)(struct msgb *msg); +typedef int (*osmo_stream_srv_segmentation_cb2_t)(struct osmo_stream_srv *conn, struct msgb *msg); struct osmo_stream_srv *osmo_stream_srv_create(void *ctx, struct osmo_stream_srv_link *link, int fd, osmo_stream_srv_read_cb_t read_cb, @@ -133,6 +141,7 @@ void osmo_stream_srv_set_data(struct osmo_stream_srv *conn, void *data); void osmo_stream_srv_set_segmentation_cb(struct osmo_stream_srv *conn, osmo_stream_srv_segmentation_cb_t segmentation_cb); +void osmo_stream_srv_set_segmentation_cb2(struct osmo_stream_srv *conn, osmo_stream_srv_segmentation_cb2_t segmentation_cb2); void osmo_stream_srv_send(struct osmo_stream_srv *conn, struct msgb *msg); int osmo_stream_srv_recv(struct osmo_stream_srv *conn, struct msgb *msg); @@ -157,6 +166,9 @@ * For any new applications, you definitely should use the modern mode, as it provides you with a higher * layer of abstraction and allows you to perform efficient I/O using the io_uring backend of osmo_io. * + * The modern mode is chosen by invoking osmo_stream_cli_set_read_cb2(). + * The legacy mode is chosen by invoking the older osmo_stream_cli_set_read_cb(). + * * A typical usage of osmo_stream_cli would look as follows: * * * call osmo_stream_cli_create() to create a new osmo_stream_cli @@ -188,10 +200,13 @@ typedef int (*osmo_stream_cli_read_cb2_t)(struct osmo_stream_cli *cli, int res, struct msgb *msg); typedef int (*osmo_stream_cli_segmentation_cb_t)(struct msgb *msg); +typedef int (*osmo_stream_cli_segmentation_cb2_t)(struct osmo_stream_cli *cli, struct msgb *msg); void osmo_stream_cli_set_name(struct osmo_stream_cli *cli, const char *name); const char *osmo_stream_cli_get_name(const struct osmo_stream_cli *cli); void osmo_stream_cli_set_nodelay(struct osmo_stream_cli *cli, bool nodelay); +int osmo_stream_cli_set_priority(struct osmo_stream_cli *cli, int sk_prio); +int osmo_stream_cli_set_ip_dscp(struct osmo_stream_cli *cli, uint8_t ip_dscp); void osmo_stream_cli_set_addr(struct osmo_stream_cli *cli, const char *addr); int osmo_stream_cli_set_addrs(struct osmo_stream_cli *cli, const char **addr, size_t addrcnt); void osmo_stream_cli_set_port(struct osmo_stream_cli *cli, uint16_t port); @@ -204,6 +219,7 @@ void osmo_stream_cli_set_data(struct osmo_stream_cli *cli, void *data); void osmo_stream_cli_set_reconnect_timeout(struct osmo_stream_cli *cli, int timeout); void *osmo_stream_cli_get_data(struct osmo_stream_cli *cli); +int osmo_stream_cli_set_tx_queue_max_length(struct osmo_stream_cli *cli, unsigned int size); char *osmo_stream_cli_get_sockname(const struct osmo_stream_cli *cli); struct osmo_fd *osmo_stream_cli_get_ofd(struct osmo_stream_cli *cli); int osmo_stream_cli_get_fd(const struct osmo_stream_cli *cli); @@ -213,6 +229,7 @@ void osmo_stream_cli_set_read_cb(struct osmo_stream_cli *cli, osmo_stream_cli_read_cb_t read_cb); void osmo_stream_cli_set_read_cb2(struct osmo_stream_cli *cli, osmo_stream_cli_read_cb2_t read_cb); void osmo_stream_cli_set_segmentation_cb(struct osmo_stream_cli *cli, osmo_stream_cli_segmentation_cb_t segmentation_cb); +void osmo_stream_cli_set_segmentation_cb2(struct osmo_stream_cli *cli, osmo_stream_cli_segmentation_cb2_t segmentation_cb2); void osmo_stream_cli_reconnect(struct osmo_stream_cli *cli); bool osmo_stream_cli_is_connected(struct osmo_stream_cli *cli);
View file
libosmo-netif_1.5.1.tar.xz/src/Makefile.am -> libosmo-netif_1.6.0.tar.xz/src/Makefile.am
Changed
@@ -1,9 +1,9 @@ # 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 -LIBVERSION=13:1:2 +LIBVERSION=14:0:3 AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir) -AM_CFLAGS= -fPIC -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(COVERAGE_CFLAGS) $(LIBSCTP_CFLAGS) +AM_CFLAGS= -fPIC -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(COVERAGE_CFLAGS) $(LIBSCTP_CFLAGS) AM_LDFLAGS = $(COVERAGE_LDFLAGS) lib_LTLIBRARIES = libosmonetif.la @@ -14,6 +14,7 @@ libosmonetif_la_SOURCES = amr.c \ datagram.c \ ipa.c \ + ipa_keepalive.c \ ipa_unit.c \ jibuf.c \ osmux.c \ @@ -22,9 +23,10 @@ prim.c \ rs232.c \ rtp.c \ + stream.c \ stream_cli.c \ stream_srv.c \ - stream.c + $(NULL) if ENABLE_LIBSCTP libosmonetif_la_SOURCES += sctp.c
View file
libosmo-netif_1.6.0.tar.xz/src/ipa_keepalive.c
Added
@@ -0,0 +1,353 @@ +/* IPA keep-alive FSM; Periodically transmit IPA_PING and expect IPA_PONG in return. + * + * (C) 2024 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de + * (C) 2019 by Harald Welte <laforge@gnumonks.org> + * + * All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ + * + * 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. + * + */ + +#include <osmocom/core/fsm.h> +#include <osmocom/core/timer.h> +#include <osmocom/core/msgb.h> +#include <osmocom/core/logging.h> + +#include <osmocom/gsm/protocol/ipaccess.h> + +#include <osmocom/netif/ipa.h> + +#define KA_FI_DEFAULT_PING_INTERVAL 30 /* seconds */ +#define KA_FI_DEFAULT_PONG_TIMEOUT 10 /* seconds */ + +enum osmo_ipa_keepalive_event { + OSMO_IPA_KA_E_START, + OSMO_IPA_KA_E_STOP, + OSMO_IPA_KA_E_PONG, +}; + +static const struct value_string ipa_keepalive_event_names = { + OSMO_VALUE_STRING(OSMO_IPA_KA_E_START), + OSMO_VALUE_STRING(OSMO_IPA_KA_E_STOP), + OSMO_VALUE_STRING(OSMO_IPA_KA_E_PONG), + { 0, NULL } +}; + +struct osmo_ipa_ka_fsm_inst { + struct osmo_fsm_inst *fi; + /*! interval in which to send IPA CCM PING requests to the peer. */ + unsigned int ping_interval; + /*! time to wait for an IPA CCM PONG in response to a IPA CCM PING before giving up. */ + unsigned int pong_timeout; + osmo_ipa_ka_fsm_send_cb_t send_cb; + osmo_ipa_ka_fsm_timeout_cb_t timeout_cb; + void *cb_data; +}; + +/* generate a msgb containing an IPA CCM PING message */ +static struct msgb *gen_ipa_ping(void) +{ + struct msgb *msg = msgb_alloc_headroom(64, 32, "IPA PING"); + if (!msg) + return NULL; + + msgb_put_u8(msg, IPAC_MSGT_PING); + ipa_prepend_header(msg, IPAC_PROTO_IPACCESS); + + return msg; +} + +/******** + * FSM: + *******/ + +#define S(x) (1 << (x)) + +enum osmo_ipa_keepalive_state { + OSMO_IPA_KA_S_INIT, + OSMO_IPA_KA_S_IDLE, /* waiting for next interval */ + OSMO_IPA_KA_S_WAIT_RESP, /* waiting for response to keepalive */ +}; + +enum ipa_fsm_timer { + T_SEND_NEXT_PING = 1, + T_PONG_NOT_RECEIVED = 2, +}; + +static void ipa_ka_init(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct osmo_ipa_ka_fsm_inst *ka_fi = fi->priv; + + switch (event) { + case OSMO_IPA_KA_E_START: + osmo_fsm_inst_state_chg(fi, OSMO_IPA_KA_S_WAIT_RESP, + ka_fi->pong_timeout, T_PONG_NOT_RECEIVED); + break; + default: + OSMO_ASSERT(0); + break; + } +} + +static void ipa_ka_wait_resp_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state) +{ + struct osmo_ipa_ka_fsm_inst *ka_fi = fi->priv; + struct msgb *msg; + + if (!ka_fi->send_cb) + osmo_panic("osmo_ipa_ka_fsm_inst running without send_cb, fix your code!"); + + /* Send an IPA PING to the peer */ + msg = gen_ipa_ping(); + OSMO_ASSERT(msg); + + ka_fi->send_cb(ka_fi, msg, ka_fi->cb_data); +} + +static void ipa_ka_wait_resp(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct osmo_ipa_ka_fsm_inst *ka_fi = fi->priv; + + switch (event) { + case OSMO_IPA_KA_E_PONG: + osmo_fsm_inst_state_chg(fi, OSMO_IPA_KA_S_IDLE, + ka_fi->ping_interval, T_SEND_NEXT_PING); + break; + default: + OSMO_ASSERT(0); + } +} + +static int ipa_ka_fsm_timer_cb(struct osmo_fsm_inst *fi) +{ + struct osmo_ipa_ka_fsm_inst *ka_fi = fi->priv; + + switch (fi->T) { + case T_SEND_NEXT_PING: + /* send another PING */ + osmo_fsm_inst_state_chg(fi, OSMO_IPA_KA_S_WAIT_RESP, + ka_fi->pong_timeout, T_PONG_NOT_RECEIVED); + return 0; + case T_PONG_NOT_RECEIVED: + /* PONG not received within time */ + LOGPFSML(fi, LOGL_NOTICE, "IPA keep-alive FSM timed out: PONG not received\n"); + /* Keep FSM alive, move to INIT state */ + osmo_fsm_inst_state_chg(fi, OSMO_IPA_KA_S_INIT, 0, 0); + if (ka_fi->timeout_cb) + ka_fi->timeout_cb(ka_fi, ka_fi->cb_data); + return 0; + default: + OSMO_ASSERT(0); + } +} + +static void ipa_ka_allstate_action(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + switch (event) { + case OSMO_IPA_KA_E_STOP: + osmo_fsm_inst_state_chg(fi, OSMO_IPA_KA_S_INIT, 0, 0); + break; + default: + OSMO_ASSERT(0); + break; + } +} + +static const struct osmo_fsm_state ipa_keepalive_states = { + OSMO_IPA_KA_S_INIT = { + .name = "INIT", + .in_event_mask = S(OSMO_IPA_KA_E_START), + .out_state_mask = S(OSMO_IPA_KA_S_WAIT_RESP) | S(OSMO_IPA_KA_S_INIT), + .action = ipa_ka_init, + }, + OSMO_IPA_KA_S_IDLE = { + .name = "IDLE", + .out_state_mask = S(OSMO_IPA_KA_S_WAIT_RESP) | S(OSMO_IPA_KA_S_INIT), + /* no permitted events aside from E_STOP, which is handled in allstate_events */ + }, + OSMO_IPA_KA_S_WAIT_RESP = { + .name = "WAIT_RESP", + .in_event_mask = S(OSMO_IPA_KA_E_PONG), + .out_state_mask = S(OSMO_IPA_KA_S_IDLE) | S(OSMO_IPA_KA_S_INIT), + .action = ipa_ka_wait_resp, + .onenter = ipa_ka_wait_resp_onenter, + }, +}; + +static struct osmo_fsm ipa_keepalive_fsm = { + .name = "IPA-KA", + .states = ipa_keepalive_states, + .num_states = ARRAY_SIZE(ipa_keepalive_states), + .log_subsys = DLINP, + .allstate_event_mask = S(OSMO_IPA_KA_E_STOP), + .allstate_action = ipa_ka_allstate_action, + .event_names = ipa_keepalive_event_names, + .timer_cb = ipa_ka_fsm_timer_cb, +}; + +static __attribute__((constructor)) void on_dso_load(void)
View file
libosmo-netif_1.5.1.tar.xz/src/rtp.c -> libosmo-netif_1.6.0.tar.xz/src/rtp.c
Changed
@@ -115,14 +115,21 @@ int x_len; int csrc_len; - csrc_len = rtph->csrc_count << 2; - payload = msg->data + sizeof(struct rtp_hdr) + csrc_len; - payload_len = msg->len - sizeof(struct rtp_hdr) - csrc_len; - if (payload_len < 0) { - DEBUGPC(DLMUX, "received RTP frame too short (len = %d, " - "csrc count = %d)\n", msg->len, rtph->csrc_count); + if (msg->len < sizeof(struct rtp_hdr)) { + DEBUGPC(DLMUX, "received RTP frame too short for an RTP header (%d < %zu)\n", + msg->len, sizeof(*rtph)); return NULL; } + + csrc_len = sizeof(struct rtp_hdr) + (rtph->csrc_count << 2); + if (msg->len < csrc_len) { + DEBUGPC(DLMUX, "received RTP frame too short for its csrc (%u < %d, csrc_count = %d)\n", + msg->len, csrc_len, rtph->csrc_count); + return NULL; + } + payload = msg->data + csrc_len; + payload_len = msg->len - csrc_len; + if (rtph->extension) { if (payload_len < sizeof(struct rtp_x_hdr)) { DEBUGPC(DLMUX, "received RTP frame too short for " @@ -131,30 +138,31 @@ } rtpxh = (struct rtp_x_hdr *)payload; x_len = ntohs(rtpxh->length) * 4 + sizeof(struct rtp_x_hdr); - payload += x_len; - payload_len -= x_len; - if (payload_len < 0) { + if (x_len > payload_len) { DEBUGPC(DLMUX, "received RTP frame too short, " "extension header exceeds frame length\n"); return NULL; } + payload += x_len; + payload_len -= x_len; } if (rtph->padding) { - if (payload_len < 0) { + uint8_t padding_len; + if (payload_len < 1) { DEBUGPC(DLMUX, "received RTP frame too short for " "padding length\n"); return NULL; } - payload_len -= payloadpayload_len - 1; - if (payload_len < 0) { - DEBUGPC(DLMUX, "received RTP frame with padding " - "greater than payload\n"); + padding_len = payloadpayload_len - 1; + if (payload_len < padding_len) { + DEBUGPC(DLMUX, "received RTP frame with padding greater than payload\n"); return NULL; } + payload_len -= padding_len; } *plen = payload_len; - return (uint8_t *)msg->data + msg->len - payload_len; + return payload; } struct msgb *
View file
libosmo-netif_1.5.1.tar.xz/src/stream.c -> libosmo-netif_1.6.0.tar.xz/src/stream.c
Changed
@@ -279,8 +279,14 @@ int flags = 0; int ret; + /* Canary to detect if kernel returns sinfo; see https://github.com/sctp/lksctp-tools/issues/37 */ + sinfo.sinfo_assoc_id = 0; + ret = sctp_recvmsg(fd, msg->tail, msgb_tailroom(msg), NULL, NULL, &sinfo, &flags); - return stream_sctp_recvmsg_trailer(log_pfx, msg, ret, &sinfo, flags); + if (sinfo.sinfo_assoc_id) + return stream_sctp_recvmsg_trailer(log_pfx, msg, ret, &sinfo, flags); + else + return stream_sctp_recvmsg_trailer(log_pfx, msg, ret, NULL, flags); } /*! wrapper for osmo_io asynchronous recvmsg response */
View file
libosmo-netif_1.5.1.tar.xz/src/stream_cli.c -> libosmo-netif_1.6.0.tar.xz/src/stream_cli.c
Changed
@@ -83,6 +83,11 @@ #define OSMO_STREAM_CLI_F_RECONF (1 << 0) #define OSMO_STREAM_CLI_F_NODELAY (1 << 1) +/* Mark whether the object is currently in a user callback. */ +#define IN_CB_MASK_CONNECT_CB (1 << 0) +#define IN_CB_MASK_DISCONNECT_CB (1 << 1) +#define IN_CB_MASK_READ_CB (1 << 2) + struct osmo_stream_cli { char *name; char socknameOSMO_SOCK_NAME_MAXLEN; @@ -91,7 +96,9 @@ struct osmo_fd ofd; struct osmo_io_fd *iofd; }; - struct llist_head tx_queue; + struct llist_head tx_queue; /* osmo_ofd mode (only): Queue of msgbs */ + unsigned int tx_queue_count; /* osmo_ofd mode (only): Current amount of msgbs queued */ + unsigned int tx_queue_max_length; /* Max amount of msgbs which can be enqueued */ struct osmo_timer_list timer; enum osmo_stream_cli_state state; char *addrOSMO_STREAM_MAX_ADDRS; @@ -102,53 +109,47 @@ uint16_t local_port; int sk_domain; int sk_type; + int sk_prio; /* socket priority, SO_PRIORITY, default=0=unset */ uint16_t proto; + uint8_t ip_dscp; /* IP Differentiated services, 0..63, default=0=unset */ osmo_stream_cli_connect_cb_t connect_cb; osmo_stream_cli_disconnect_cb_t disconnect_cb; osmo_stream_cli_read_cb_t read_cb; osmo_stream_cli_read_cb2_t iofd_read_cb; osmo_stream_cli_segmentation_cb_t segmentation_cb; + osmo_stream_cli_segmentation_cb2_t segmentation_cb2; void *data; int flags; int reconnect_timeout; struct osmo_sock_init2_multiaddr_pars ma_pars; + uint8_t in_cb_mask; /* IN_CB_MASK_* */ + bool delay_free; }; -void osmo_stream_cli_close(struct osmo_stream_cli *cli); - /*! \addtogroup stream_cli * @{ */ -/*! Re-connect an Osmocom Stream Client. - * If re-connection is enabled for this client - * (which is the case unless negative timeout was explicitly set via osmo_stream_cli_set_reconnect_timeout() call), - * we close any existing connection (if any) and schedule a re-connect timer */ -void osmo_stream_cli_reconnect(struct osmo_stream_cli *cli) +/* return true if freed */ +static inline bool free_delayed_if_needed(struct osmo_stream_cli *cli) { - osmo_stream_cli_close(cli); + /* Nobody requested delayed free, skip */ + if (!cli->delay_free) + return false; + /* Check for other callbacks active in case we were e.g. in: + * read_cb() -> user -> osmo_steam_client_close() -> disconnect_cb() --> user --> osmo_stream_client_destroy() + * or: + * connect_cb() -> user -> osmo_steam_client_close() -> disconnect_cb() --> user --> osmo_stream_client_destroy() + */ + if (cli->in_cb_mask != 0) + return false; - if (cli->reconnect_timeout < 0) { - LOGSCLI(cli, LOGL_INFO, "not reconnecting, disabled\n"); - return; - } - - cli->state = STREAM_CLI_STATE_WAIT_RECONNECT; - LOGSCLI(cli, LOGL_INFO, "retrying reconnect in %d seconds...\n", - cli->reconnect_timeout); - osmo_timer_schedule(&cli->timer, cli->reconnect_timeout, 0); -} - -/*! Check if Osmocom Stream Client is in connected state. - * \paramin cli Osmocom Stream Client - * \return true if connected, false otherwise - */ -bool osmo_stream_cli_is_connected(struct osmo_stream_cli *cli) -{ - return cli->state == STREAM_CLI_STATE_CONNECTED; + LOGSCLI(cli, LOGL_DEBUG, "free(delayed)\n"); + talloc_free(cli); + return true; } -static void osmo_stream_cli_close_iofd(struct osmo_stream_cli *cli) +static void stream_cli_close_iofd(struct osmo_stream_cli *cli) { if (!cli->iofd) return; @@ -157,7 +158,7 @@ cli->iofd = NULL; } -static void osmo_stream_cli_close_ofd(struct osmo_stream_cli *cli) +static void stream_cli_close_ofd(struct osmo_stream_cli *cli) { if (cli->ofd.fd == -1) return; @@ -168,27 +169,30 @@ /*! Close an Osmocom Stream Client. * \paramin cli Osmocom Stream Client to be closed + * \return true if stream was freed due to disconnect_cb, false otherwise * We unregister the socket fd from the osmocom select() loop * abstraction and close the socket */ -void osmo_stream_cli_close(struct osmo_stream_cli *cli) +static bool stream_cli_close(struct osmo_stream_cli *cli) { int old_state = cli->state; + LOGSCLI(cli, LOGL_DEBUG, "close()\n"); + /* This guards against reentrant close through disconnect_cb(): */ if (cli->state == STREAM_CLI_STATE_CLOSED) - return; + return false; if (cli->state == STREAM_CLI_STATE_WAIT_RECONNECT) { osmo_timer_del(&cli->timer); cli->state = STREAM_CLI_STATE_CLOSED; - return; + return false; } switch (cli->mode) { case OSMO_STREAM_MODE_OSMO_FD: - osmo_stream_cli_close_ofd(cli); + stream_cli_close_ofd(cli); break; case OSMO_STREAM_MODE_OSMO_IO: - osmo_stream_cli_close_iofd(cli); + stream_cli_close_iofd(cli); break; default: OSMO_ASSERT(false); @@ -196,11 +200,79 @@ cli->state = STREAM_CLI_STATE_CLOSED; - if (old_state == STREAM_CLI_STATE_CONNECTED) { - LOGSCLI(cli, LOGL_DEBUG, "connection closed\n"); + /* If conn was established, notify the disconnection to the user: + * Also, if reconnect is disabled by user, notify the user that connect() failed: */ + if (old_state == STREAM_CLI_STATE_CONNECTED || + (old_state == STREAM_CLI_STATE_CONNECTING && cli->reconnect_timeout < 0)) { + OSMO_ASSERT(!(cli->in_cb_mask & IN_CB_MASK_DISCONNECT_CB)); + cli->in_cb_mask |= IN_CB_MASK_DISCONNECT_CB; if (cli->disconnect_cb) cli->disconnect_cb(cli); + cli->in_cb_mask &= ~IN_CB_MASK_DISCONNECT_CB; + return free_delayed_if_needed(cli); + } + return false; +} + +/*! Close an Osmocom Stream Client. + * \paramin cli Osmocom Stream Client to be closed + * We unregister the socket fd from the osmocom select() loop + * abstraction and close the socket */ +void osmo_stream_cli_close(struct osmo_stream_cli *cli) +{ + (void)stream_cli_close(cli); +} + +/*! Re-connect an Osmocom Stream Client. + * If re-connection is enabled for this client + * (which is the case unless negative timeout was explicitly set via osmo_stream_cli_set_reconnect_timeout() call), + * we close any existing connection (if any) and schedule a re-connect timer */ +static bool stream_cli_reconnect(struct osmo_stream_cli *cli) +{ + bool freed = stream_cli_close(cli); + + if (freed) + return true; + + if (cli->reconnect_timeout < 0) { + LOGSCLI(cli, LOGL_INFO, "not reconnecting, disabled\n"); + return false; } + + cli->state = STREAM_CLI_STATE_WAIT_RECONNECT; + LOGSCLI(cli, LOGL_INFO, "retrying reconnect in %d seconds...\n", + cli->reconnect_timeout); + osmo_timer_schedule(&cli->timer, cli->reconnect_timeout, 0); + return false; +} + +/*! Re-connect an Osmocom Stream Client. + * If re-connection is enabled for this client + * (which is the case unless negative timeout was explicitly set via osmo_stream_cli_set_reconnect_timeout() call), + * we close any existing connection (if any) and schedule a re-connect timer */ +void osmo_stream_cli_reconnect(struct osmo_stream_cli *cli)
View file
libosmo-netif_1.5.1.tar.xz/src/stream_srv.c -> libosmo-netif_1.6.0.tar.xz/src/stream_srv.c
Changed
@@ -69,6 +69,15 @@ * Server side. */ +struct msgb_alloc_info { + /*! Whether it was set by user or we use iofd defaults */ + bool set_by_user; + /*! size of msgb to allocate (excluding headroom) */ + unsigned int size; + /*! headroom to allocate when allocating msgb's */ + unsigned int headroom; +}; + #define OSMO_STREAM_SRV_F_RECONF (1 << 0) #define OSMO_STREAM_SRV_F_NODELAY (1 << 1) @@ -81,10 +90,14 @@ uint16_t port; int sk_domain; int sk_type; + int sk_prio; /* socket priority, SO_PRIORITY, default=0=unset */ uint16_t proto; + uint8_t ip_dscp; /* IP Differentiated services, 0..63, default=0=unset */ osmo_stream_srv_link_accept_cb_t accept_cb; void *data; int flags; + unsigned int tx_queue_max_length; /* Max amount of msgbs which can be enqueued */ + struct msgb_alloc_info msgb_alloc; struct osmo_sock_init2_multiaddr_pars ma_pars; }; @@ -148,6 +161,24 @@ goto error_close_socket; } + if (link->ip_dscp > 0) { + ret = osmo_sock_set_dscp(sock_fd, link->ip_dscp); + if (ret < 0) { + LOGSLNK(link, LOGL_ERROR, "set_ip_dscp(%u): failed setsockopt err=%d\n", + link->ip_dscp, errno); + goto error_close_socket; + } + } + + if (link->sk_prio > 0) { + ret = osmo_sock_set_priority(sock_fd, link->sk_prio); + if (ret < 0) { + LOGSLNK(link, LOGL_ERROR, "set_priority(%d): failed setsockopt err=%d\n", + link->sk_prio, errno); + goto error_close_socket; + } + } + if (!link->accept_cb) { ret = -ENOTSUP; goto error_close_socket; @@ -183,6 +214,7 @@ link->sk_domain = AF_UNSPEC; link->sk_type = SOCK_STREAM; link->proto = IPPROTO_TCP; + link->tx_queue_max_length = 1024; /* Default tx queue size, msgbs. */ osmo_fd_setup(&link->ofd, -1, OSMO_FD_READ | OSMO_FD_WRITE, osmo_stream_srv_link_ofd_cb, link, 0); link->ma_pars.sctp.version = 0; @@ -224,6 +256,33 @@ link->flags &= ~OSMO_STREAM_SRV_F_NODELAY; } +/*! Set the priority value of the stream socket. + * Setting this will automatically set the socket priority + * option on any socket established via this server link, before + * calling the accept_cb(). + * \paramin link server link whose sockets are to be configured + * \paramin sk_prio priority value. Values outside 0..6 require CAP_NET_ADMIN. + * \return negative on error, 0 on success + */ +int osmo_stream_srv_link_set_priority(struct osmo_stream_srv_link *link, int sk_prio) +{ + link->sk_prio = sk_prio; + return 0; +} + +/*! Set the DSCP (differentiated services code point) of the stream socket. + * Setting this will automatically set the IP DSCP option on any socket on any + * socket established via this server link, before calling the accept_cb(). + * \paramin link server link whose sockets are to be configured + * \paramin ip_dscp DSCP value. Value range 0..63. + * \return negative on error, 0 on success + */ +int osmo_stream_srv_link_set_ip_dscp(struct osmo_stream_srv_link *link, uint8_t ip_dscp) +{ + link->ip_dscp = ip_dscp; + return 0; +} + /*! Set the local address to which we bind. * Any changes to this setting will only become active upon next (re)connect. * \paramin link Stream Server Link to modify @@ -347,6 +406,18 @@ return link->data; } +/*! Set the maximum length queue of the stream servers accepted and allocated from this server link. + * \paramin link Stream Server Link to modify + * \paramin size maximum amount of msgbs which can be queued in the internal tx queue. + * \returns 0 on success, negative on error. + * + * The maximum length queue default value is 1024 msgbs. */ +int osmo_stream_srv_link_set_tx_queue_max_length(struct osmo_stream_srv_link *link, unsigned int size) +{ + link->tx_queue_max_length = size; + return 0; +} + /* Similar to osmo_sock_multiaddr_get_name_buf(), but aimed at listening sockets (only local part): */ static char *get_local_sockname_buf(char *buf, size_t buf_len, const struct osmo_stream_srv_link *link) { @@ -445,10 +516,32 @@ link->accept_cb = accept_cb; } +/*! Set the msgb allocation parameters on child osmo_stream_srv objects + * \paramin link Stream Server Link + * \paramin size Size of msgb to allocate (excluding headroom) + * \paramin headroom Headroom to allocate when allocating msgb's + * + * The parameters are applied to osmo_stream_srv objects upon creation. + * Setting both to 0 leaves it as implementation default. + **/ +int osmo_stream_srv_link_set_msgb_alloc_info(struct osmo_stream_srv_link *link, unsigned int size, unsigned int headroom) +{ + if (size == 0 && headroom == 0) { + link->msgb_alloc.set_by_user = false; + } else { + link->msgb_alloc.set_by_user = true; + link->msgb_alloc.headroom = headroom; + link->msgb_alloc.size = size; + } + return 0; +} + /*! Destroy the stream server link. Closes + Releases Memory. * \paramin link Stream Server Link */ void osmo_stream_srv_link_destroy(struct osmo_stream_srv_link *link) { + if (!link) + return; osmo_stream_srv_link_close(link); talloc_free(link); } @@ -596,10 +689,13 @@ struct osmo_fd ofd; struct osmo_io_fd *iofd; }; - struct llist_head tx_queue; + struct llist_head tx_queue; /* osmo_ofd mode (only): Queue of msgbs */ + unsigned int tx_queue_count; /* osmo_ofd mode (only): Current amount of msgbs queued */ osmo_stream_srv_closed_cb_t closed_cb; osmo_stream_srv_read_cb_t read_cb; osmo_stream_srv_read_cb2_t iofd_read_cb; + osmo_stream_srv_segmentation_cb_t segmentation_cb; + osmo_stream_srv_segmentation_cb2_t segmentation_cb2; void *data; int flags; }; @@ -722,12 +818,11 @@ struct msgb *msg; int ret; - if (llist_empty(&conn->tx_queue)) { + msg = msgb_dequeue_count(&conn->tx_queue, &conn->tx_queue_count); + if (!msg) { /* done, tx_queue empty */ osmo_fd_write_disable(&conn->ofd); return; } - msg = llist_first_entry(&conn->tx_queue, struct msgb, list); - llist_del(&msg->list); LOGSSRV(conn, LOGL_DEBUG, "sending %u bytes of data\n", msg->len); @@ -764,6 +859,7 @@ /* Update msgb and re-add it at the start of the queue: */ msgb_pull(msg, ret); llist_add(&msg->list, &conn->tx_queue); + conn->tx_queue_count++; return; } @@ -773,6 +869,7 @@ if (err == EAGAIN) { /* Re-add at the start of the queue to re-attempt: */ llist_add(&msg->list, &conn->tx_queue); + conn->tx_queue_count++; return; } msgb_free(msg); @@ -876,6 +973,7 @@ conn->mode = OSMO_STREAM_MODE_OSMO_IO; conn->srv = link;
View file
libosmo-netif_1.5.1.tar.xz/tests/stream/stream_test.c -> libosmo-netif_1.6.0.tar.xz/tests/stream/stream_test.c
Changed
@@ -516,7 +516,7 @@ } LOGCLI(osc, "Received message from stream (payload len = %" PRIu16 ")\n", msgb_length(msg)); - if (ipac_msg_type < 0 || 5 < ipac_msg_type) { + if (5 < ipac_msg_type) { fprintf(stderr, "Received unexpected IPAC message type %"PRIu8"\n", ipac_msg_type); msgb_free(msg); return -ENOMSG;
View file
libosmo-netif_1.5.1.tar.xz/tests/stream/stream_test.err -> libosmo-netif_1.6.0.tar.xz/tests/stream/stream_test.err
Changed
@@ -1,3 +1,4 @@ +CLICONN(cli_test,){CLOSED} close() SRV(srv_link_test,127.0.0.11:1111) accept()ed new link from 127.0.0.1:8976 CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CONNECTING} connection established @@ -32,7 +33,7 @@ CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CONNECTED} connected read CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CONNECTED} message received CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CONNECTED} connection closed with srv -CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CLOSED} connection closed +CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CONNECTED} close() CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){WAIT_RECONNECT} retrying reconnect in 9 seconds... {11.000008} autoreconnecting test step 4 client OK, server OK, FD reg 0 @@ -41,7 +42,7 @@ {11.000009} autoreconnecting test step 3 client OK, server OK, FD reg 1 SRV(srv_link_test,127.0.0.11:1111) accept()ed new link from 127.0.0.1:8976 CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CONNECTING} connection established -CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CLOSED} connection closed +CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CONNECTED} close() {11.000010} autoreconnecting test step 2 client OK, server OK, FD reg 0 SRVCONN(srv_test,r=127.0.0.1:8976<->l=127.0.0.11:1111) connected read/write (what=0x1) @@ -49,6 +50,10 @@ SRVCONN(srv_test,r=127.0.0.1:8976<->l=127.0.0.11:1111) connection closed with client {11.000011} autoreconnecting test step 1 client OK, server NA, FD reg 0 +CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CLOSED} destroy() +CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CLOSED} close() +CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CLOSED} free(destroy) +CLICONN(cli_test,){CLOSED} close() SRV(srv_link_test,127.0.0.11:1111) accept()ed new link from 127.0.0.1:8976 CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CONNECTING} connection established @@ -83,10 +88,13 @@ CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CONNECTED} connected read CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CONNECTED} message received CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CONNECTED} connection closed with srv -CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CLOSED} connection closed +CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CONNECTED} close() CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CLOSED} not reconnecting, disabled {20.000019} non-reconnecting test step 0 client OK, server OK, FD reg 0 +CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CLOSED} destroy() +CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CLOSED} close() +CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CLOSED} free(destroy) SRV(srv_link_test,127.0.0.11:1111) accept()ed new link from 127.0.0.1:8977 CLICONN(,r=127.0.0.11:1111<->l=127.0.0.1:8977){CONNECTING} connection established SRVCONN(,r=127.0.0.1:8977<->l=127.0.0.11:1111) received 24 bytes from client @@ -98,7 +106,9 @@ SRVCONN(,r=127.0.0.1:8977<->l=127.0.0.11:1111) received 10 bytes from client SRVCONN(,r=127.0.0.1:8977<->l=127.0.0.11:1111) received 10 bytes from client SRVCONN(,r=127.0.0.1:8977<->l=127.0.0.11:1111) received 10 bytes from client -CLICONN(,r=127.0.0.11:1111<->l=127.0.0.1:8977){CLOSED} connection closed +CLICONN(,r=127.0.0.11:1111<->l=127.0.0.1:8977){CONNECTED} destroy() +CLICONN(,r=127.0.0.11:1111<->l=127.0.0.1:8977){CONNECTED} close() +CLICONN(,r=127.0.0.11:1111<->l=127.0.0.1:8977){CLOSED} free(destroy) SRV(srv_link_test,127.0.0.11:1112) accept()ed new link from 127.0.0.1:8977 CLICONN(,r=127.0.0.11:1112<->l=127.0.0.1:8977){CONNECTING} connection established SRVCONN(,r=127.0.0.1:8977<->l=127.0.0.11:1112) connected write @@ -112,4 +122,6 @@ CLICONN(,r=127.0.0.11:1112<->l=127.0.0.1:8977){CONNECTED} received 10 bytes from srv CLICONN(,r=127.0.0.11:1112<->l=127.0.0.1:8977){CONNECTED} received 10 bytes from srv CLICONN(,r=127.0.0.11:1112<->l=127.0.0.1:8977){CONNECTED} received 10 bytes from srv -CLICONN(,r=127.0.0.11:1112<->l=127.0.0.1:8977){CLOSED} connection closed +CLICONN(,r=127.0.0.11:1112<->l=127.0.0.1:8977){CONNECTED} destroy() +CLICONN(,r=127.0.0.11:1112<->l=127.0.0.1:8977){CONNECTED} close() +CLICONN(,r=127.0.0.11:1112<->l=127.0.0.1:8977){CLOSED} free(destroy)
View file
rpmlintrc
Added
@@ -0,0 +1,5 @@ +# Don't abort the build when finding a library that depends on a package with +# a specific version. This is intentional for nightly builds, we don't want +# libraries from different build dates to be mixed as they might have ABI +# incompatibilities. +setBadness('shlib-fixed-dependency', 0)
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.