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 10
View file
libosmo-netif.spec
Changed
@@ -14,21 +14,22 @@ Name: libosmo-netif Requires: osmocom-latest -Version: 1.6.1 +Version: 1.7.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.1.tar.xz +Source: libosmo-netif_1.7.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 +BuildRequires: pkgconfig(libosmocore) >= 1.12.0 +BuildRequires: pkgconfig(libosmogsm) >= 1.12.0 +BuildRequires: pkgconfig(libosmocodec) >= 1.12.0 +BuildRequires: pkgconfig(libosmovty) >= 1.12.0 %description Network interface demuxer library for OsmoCom projects.
View file
libosmo-netif_1.6.1.dsc -> libosmo-netif_1.7.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.6.1 +Version: 1.7.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.11.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.12.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: - e19e217ef381b08f73e1d4a8ccc31a8e8c44cab5 200256 libosmo-netif_1.6.1.tar.xz + 84ad59fac1c44e87f3f1cfabdfd5271b59a51304 248640 libosmo-netif_1.7.0.tar.xz Checksums-Sha256: - 99b76386ff5ee519282b303fb7ce9644f8651ad4f1b6bac52b0fd87f61908cd1 200256 libosmo-netif_1.6.1.tar.xz + 55b5c12f68bf51a99c7bb2e263c33312ef958467500a44b0f69803f614936431 248640 libosmo-netif_1.7.0.tar.xz Files: - 0f36032ca1abdc8424e239777eda23e9 200256 libosmo-netif_1.6.1.tar.xz + 226d92d66e3b0bf08632dfaa4f275524 248640 libosmo-netif_1.7.0.tar.xz
View file
libosmo-netif_1.6.1.tar.xz/.tarball-version -> libosmo-netif_1.7.0.tar.xz/.tarball-version
Changed
@@ -1 +1 @@ -1.6.1 +1.7.0
View file
libosmo-netif_1.6.1.tar.xz/configure.ac -> libosmo-netif_1.7.0.tar.xz/configure.ac
Changed
@@ -89,9 +89,10 @@ dnl Generate the output AM_CONFIG_HEADER(config.h) -PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.11.0) -PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.11.0) -PKG_CHECK_MODULES(LIBOSMOCODEC, libosmocodec >= 1.11.0) +PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.12.0) +PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.12.0) +PKG_CHECK_MODULES(LIBOSMOCODEC, libosmocodec >= 1.12.0) +PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.12.0) AC_ARG_ENABLE(libsctp, AS_HELP_STRING(--disable-libsctp, Do not enable socket multiaddr APIs requiring libsctp), ENABLE_LIBSCTP=$enableval, ENABLE_LIBSCTP="yes")
View file
libosmo-netif_1.6.1.tar.xz/contrib/libosmo-netif.spec.in -> libosmo-netif_1.7.0.tar.xz/contrib/libosmo-netif.spec.in
Changed
@@ -25,9 +25,10 @@ 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 +BuildRequires: pkgconfig(libosmocore) >= 1.12.0 +BuildRequires: pkgconfig(libosmogsm) >= 1.12.0 +BuildRequires: pkgconfig(libosmocodec) >= 1.12.0 +BuildRequires: pkgconfig(libosmovty) >= 1.12.0 %description Network interface demuxer library for OsmoCom projects.
View file
libosmo-netif_1.6.1.tar.xz/debian/changelog -> libosmo-netif_1.7.0.tar.xz/debian/changelog
Changed
@@ -1,9 +1,35 @@ -libosmo-netif (1.6.1) unstable; urgency=medium +libosmo-netif (1.7.0) unstable; urgency=medium + Mychaela N. Falconia + * .gitignore: add utils/osmo-amr-inspect + * bring twjit into libosmo-netif + * bring twrtp into libosmo-netif + * doc: add twrtp guide document + + Vadim Yanitskiy + * stream_{cli,srv}: fix copy-paste in API docs + + Pau Espin Pedrol + * cosmetic: stream: Fix line indentation + * stream: Improve error logging sctp_recvmsg without sctp_sndrcvinfo + * stream_srv: Improve API documentation + * stream: Support configuring TCP keep-alive pars + * stream: Support configuring TCP_USER_TIMEOUT parameter + * osmux: Use while loop to tear down entire llist + * cosmetic: Fix typo in doc of osmo_stream_srv_get_sockname() + * stream: Support overwriting tx_queue_max_length per srv conn + * netif/sctp.h: Add missing dep netinet/sctp.h + + Neels Hofmeyr + * add osmo_stream_*_set_name_f() + + Oliver Smith + * include/osmocom/netif/Makefile: format osmonetif_HEADERS + * Generate a version.h file * Fix time_t prints for debian 13 armv7l * Use %zu for size_t - -- Oliver Smith <osmith@sysmocom.de> Tue, 26 Aug 2025 15:44:56 +0200 + -- Pau Espin Pedrol <pespin@sysmocom.de> Wed, 03 Dec 2025 17:37:54 +0100 libosmo-netif (1.6.0) unstable; urgency=medium
View file
libosmo-netif_1.6.1.tar.xz/debian/control -> libosmo-netif_1.7.0.tar.xz/debian/control
Changed
@@ -11,7 +11,7 @@ libdpkg-perl, git, doxygen, - libosmocore-dev (>= 1.11.0), + libosmocore-dev (>= 1.12.0), pkg-config, libpcap0.8-dev, libsctp-dev
View file
libosmo-netif_1.7.0.tar.xz/doc
Added
+(directory)
View file
libosmo-netif_1.7.0.tar.xz/doc/twrtp
Added
+(directory)
View file
libosmo-netif_1.7.0.tar.xz/doc/twrtp/README
Added
@@ -0,0 +1,22 @@ +Themyscira Wireless RTP endpoint library is a software component that was +originally developed externally to Osmocom prior to being integrated into +libosmo-netif, hence its documentation has been done in a different manner +than is usual in Osmocom. + +There is a detailed document titled _Guide to ThemWi RTP endpoint library_; +its original/official ThemWi version resides here: + +https://www.freecalypso.org/TW-doc/twrtp-guide-latest.pdf +(See TW-doc directory listing for other formats and previous versions.) + +There also exists a version of this document whose content has been updated +to reflect changes to twrtp & twjit made as part of Osmocom integration, +and which can be edited further in sync with code changes - however, the +formatting language in which this document is written is still troff. +twrtp-guide.t is the troff source for the Osmocom-adapted version of twrtp +guide document; to compile it into readable PDF, run this command: + +groff -p -t -ms -Tpdf twrtp-guide.t > twrtp-guide.pdf + +groff is classic, old school GNU software that should be easily available +in any GNU+Linux distribution.
View file
libosmo-netif_1.7.0.tar.xz/doc/twrtp/twrtp-guide.t
Added
@@ -0,0 +1,2387 @@ +.\" This document is written in troff language, using -ms macros +.\" plus pic and tbl preprocessors. The original ThemWi version +.\" of this document was produced on a MicroVAX 4.3BSD system +.\" using Quasijarus troff; the present Osmocom-adapted version +.\" has been modified to format with groff, an implementation of +.\" troff that is available in most GNU+Linux distributions. +.nr LL 6.5i +.TL +Guide to ThemWi RTP endpoint library (Osmocom version) +.AU +Mychaela N. Falconia +.AI +Themyscira Wireless +.\" Any additional authors editing this document in the future, +.\" please add another stanza of this form: +.\" +.\" .AU +.\" Your name +.\" .AI +.\" Your "institution", e.g., sysmocom GmbH or Osmocom Community etc. +.\" +.hw hand-over +.hw time-stamp +.hw trans-port +.hw wrap-around +.NH 1 +Introduction +.PP +This document describes the version of Themyscira Wireless RTP endpoint +library (\fBtwrtp\fP) that is integrated into \&\fClibosmo\-netif\fP. +This version of \fBtwrtp\fP is a derivative work based on the original +author's \&\fCtwrtp\-native\fP version, used by ThemWi network elements +in Osmocom+ThemWi hybrid networks, and this version of the manual +is a derivative work based on the original \fBtwrtp\fP guide document. +.NH 2 +Principal function +.PP +ThemWi RTP endpoint library, consisting of \%\fC<osmocom/netif/twrtp.h>\fP +and \%\fC<osmocom/netif/twjit.h>\fP blocks in the present version, +is intended for interworking between an RTP stream and a fixed timing system +such as GSM Um interface TCH or T1/E1 TDM. Such interworking consists of two +fundamental elements: +.IP \(bu +In every fixed time quantum, the interworking element receives a unit of +speech or CSData media from the fixed source and emits an RTP packet +carrying that quantum of speech or CSData. +.IP \(bu +In the opposite direction, the fixed timing system requires a quantum of +speech or CSData to be fed to it on every tick without fail, yet the +interworking element has no control over when RTP packets may arrive +from the IP network. This direction of interworking requires a rather +complex element called a jitter buffer, an element whose design and +configuration always involves some trade-offs and compromises. +.NH 2 +Domain of application +.PP +The present library is \fBnot\fP intended to be an all-purpose implementation +of IETF RFCs 3550 and 3551, supporting all possible RTP use cases as +envisioned by IETF. Instead it is intended to support RTP \fIas it is used\fP +in these two specific telecom network environments: +.IP \(bu +3GPP networks that use RTP according to TS\ 26.102 and TS\ 48.103; +.IP \(bu +The way RTP is used to transport G.711 PSTN traffic across the public +Internet in what may be colloquially referred to as IP-PSTN. +.LP +The two 3GPP specs referenced above prescribe a fixed packetization time +of 20\ ms for all codecs on AoIP interface. Furthermore, they stipulate +that: +.IP \(bu +In the case of compressed speech transport, each RTP packet carries +exactly one frame of the speech codec in use; +.IP \(bu +In the case of uncompressed G.711 speech or CSData transport, each RTP +packet carries exactly 160 payload octets (20\ ms worth) of what would +have been a 64\ kbit/s timeslot in T1/E1 transport. +.LP +This fixed-quantum property, namely the property that every RTP packet +carries exactly one fixed quantum of speech or CSData, where the duration +of this quantum is known at connection setup time and cannot suddenly +change from one packet to the next, is required by the present ThemWi +RTP endpoint library \(em this requirement constitutes a fundamental aspect +of its architectural design. +.PP +An RTP endpoint implementation library that imposes the just-described +requirement is sufficient for the purpose of building IP-based GSM networks +that follow 3GPP TS\ 48.103 (the requirements of that spec are in agreement +with the library constraint), and it is also sufficient for interfacing +to IP-PSTN by way of common commercial PSTN-via-SIP connectivity providers. +.PP +In the case of IP-PSTN, the author of the present library has experience +only with North American PSTN-via-SIP connectivity providers. In all +of our operational experience so far, these IP-PSTN connectivity providers +behave in ways that are fully compatible with the expectations of the +present RTP library, as long as the following conditions are met: +.IP \(bu +No attempt is made to use any codecs other than PCMU or PCMA: +don't include any other codecs in the SDP offer, and send only SDP answers +that select either PCMU or PCMA out of the received multi-codec offer. +.IP \(bu +No attempt is made to use any other \&\fCptime\fP besides the most common +industry standard of 20\ ms. +.LP +In all operational experience so far, incoming INVITE SDPs indicate either +\&\fCa=ptime:20\fP or \&\fCa=maxptime:20\fP, and when we indicate +\&\fCa=ptime:20\fP in all SDPs we send out, the IP-PSTN peer always sends us +20\ ms RTP packets, as opposed to some other packetization interval which +would break the fixed-quantum model assumed by the present RTP library. +.PP +However, it needs to be acknowledged that the present library is \fBnot\fP +suitable for general-purpose, IETF-style applications outside of +``walled garden'' 3GPP networks or the semi-walled environment of +IP-PSTN with ``well-behaved'' entities: there are many behaviors that +are perfectly legal per the RFCs, but are not supported by the present +library. Having a peer send RTP with a packetization interval that is +different from what we asked for via \&\fCptime\fP attribute is one of those +behaviors that is allowed by IETF, but not supported by this library. +.NH 3 +Expectation of continuous streaming +.PP +In addition to the just-described requirement for a fixed packetization +interval, the domain of application for \fBtwrtp\fP is subject to one more +constraint: our jitter buffer component (\fBtwjit\fP) is designed for +environments that implement continuous streaming, and may perform suboptimally +in those that do not. +.PP +Continuous streaming is an operational policy under which an RTP endpoint +\fIalways\fP emits an RTP packet in \fIevery\fP 20\ ms (or whatever other +packetization interval is used) time window, be it rain or shine, even if +it has no data to send because nothing was received on the air interface +(DTX pause on the radio link, reception errors, frame stealing) or because +E1 TRAU frame decoding failed, etc. +Continuous streaming may be implemented by sending an RTP packet with a +zero-length payload when the endpoint has nothing else to send in a given +quantum time window \(em this method allows any existing RTP payload format +standard to be operationally modified for continuous streaming. +There also exist Themyscira-defined enhanced RTP payload formats for GSM +speech codecs that not only mandate continuous streaming, but additionally +convey errored frame bits and the Time Alignment Flag in every 20\ ms frame +position, exactly like TRAU-UL frames in the world of TDM-based GSM. +.PP +The opposite of continuous streaming is the practice of intentional gaps. +Under this operational policy, an RTP endpoint may create intentional gaps +in the RTP stream it emits, simply by sending no RTP packets at all when +it deems that there are no useful data to be transmitted. +An intentional gap is distinguished from packet loss in that the sequence +number in the RTP header increments by one while the timestamp increments +by a greater than normal amount. +Unfortunately for \fBtwjit\fP, intentional gaps in RTP were the design intent +of IETF. +Even more unfortunately, this IETF-ism has been canonized +by 3GPP in TS\ 26.102 and TS\ 48.103 \(em hence those operators who prefer a +continuous streaming model now have to explicitly deviate from 3GPP +specifications. +.PP +In an Osmocom GSM network, 3GPP-compliant operation with intentional gaps +is the default \(em however, the operator can switch to continuous streaming +model +by setting \%\fCrtp\ continuous\-streaming\fP in OsmoBTS vty configuration. +.PP +Fortunately for \fBtwjit\fP, however, the situation is better in the world +of IP-PSTN, the other RTP environment for which the present library was +designed. +At least on North American IP-PSTN and at least when uncompressed PCMU or +PCMA codecs are used, all PSTN-via-SIP connectivity providers in our +operational experience so far always emit perfectly continuous RTP streams, +without any intentional gaps. +.PP +If an application uses \fBtwrtp\fP with \fBtwjit\fP to receive an RTP stream +that incurs intentional gaps, the resulting performance may be acceptable +or unacceptable depending on additional factors: +.IP \(bu +If RTP gaps are incurred only during frame erasure events (radio +errors or FACCH stealing) without DTX, the resulting \fBtwjit\fP performance +will most likely still be acceptable for speech applications. +All transmitted speech frames will still be delivered to the receiver, +but the frame erasure gap may lengthen or shorten depending on exact jitter +buffer conditions at the time of the intentional gap in the Tx stream \(em +in other words, a phase shift may be incurred. +.IP \(bu +If RTP stream gaps are enabled in conjunction with DTX, \fBtwjit\fP will not +be able to receive such a stream according to common expectations. +When RTP stream gaps are used together with DTX, the stream will typically +feature occasional single packets of comfort noise update, sent every +160, 240 or 480 ms depending on the codec, surrounded by gaps. +When \fBtwjit\fP receives such a stream and the flow-starting fill level +is set to 2 or greater (the default and usually necessary configuration), +all of these ``isolated island'' comfort noise update packets will be dropped +\(em a behavior counter to the way DTX is expected to work. +.LP +The take-away is that if an operator wishes to use DTX with \fBtwrtp\fP, +they need to enable \%\fCrtp\ continuous\-streaming\fP. +.NH 2 +Configurable quantum duration and time scale +.LP +For every RTP stream it handles, the library needs to know two key +parameters: +.IP \(bu +The scale or ``clock rate'' used for RTP timestamps, i.e., how many
View file
libosmo-netif_1.6.1.tar.xz/include/osmocom/netif/Makefile.am -> libosmo-netif_1.7.0.tar.xz/include/osmocom/netif/Makefile.am
Changed
@@ -1,18 +1,37 @@ noinst_HEADERS = \ + rtcp_defs.h \ stream_private.h \ + twjit_private.h \ $(NULL) -osmonetif_HEADERS = amr.h \ - datagram.h \ - ipa.h \ - ipa_unit.h \ - jibuf.h \ - osmux.h \ - prim.h \ - rs232.h \ - rtp.h \ - stream.h \ - $(NULL) +version.h: version.h.tpl + $(AM_V_GEN)$(MKDIR_P) $(dir $@) + $(AM_V_GEN)sed \ + -e "s/{{VERSION}}/$$(echo '@VERSION@' | cut -d. -f1-3)/g" \ + -e "s/{{VERSION_MAJOR}}/$$(echo '@VERSION@' | cut -d. -f1)/g" \ + -e "s/{{VERSION_MINOR}}/$$(echo '@VERSION@' | cut -d. -f2)/g" \ + -e "s/{{VERSION_PATCH}}/$$(echo '@VERSION@' | cut -d. -f3)/g" \ + $< > $@ + +EXTRA_DIST = \ + version.h.tpl \ + $(NULL) + +osmonetif_HEADERS = \ + amr.h \ + datagram.h \ + ipa.h \ + ipa_unit.h \ + jibuf.h \ + osmux.h \ + prim.h \ + rs232.h \ + rtp.h \ + stream.h \ + twjit.h \ + twrtp.h \ + version.h \ + $(NULL) if ENABLE_LIBSCTP osmonetif_HEADERS += sctp.h
View file
libosmo-netif_1.7.0.tar.xz/include/osmocom/netif/rtcp_defs.h
Added
@@ -0,0 +1,49 @@ +/* + * Some definitions for RTCP, just enough to implement SR and RR + * generation and parsing in twrtp. + */ + +#pragma once + +#include <stdint.h> + +struct rtcp_sr_rr_hdr { + uint8_t v_p_rc; + uint8_t pt; + uint16_t len; + uint32_t ssrc; +} __attribute__((packed)); + +struct rtcp_sr_block { + uint32_t ntp_sec; + uint32_t ntp_fract; + uint32_t rtp_ts; + uint32_t pkt_count; + uint32_t octet_count; +} __attribute__((packed)); + +struct rtcp_rr_block { + uint32_t ssrc; + uint32_t lost_word; + uint32_t max_seq_ext; + uint32_t jitter; + uint16_t lsr_sec; + uint16_t lsr_fract; + uint16_t dlsr_sec; + uint16_t dlsr_fract; +} __attribute__((packed)); + +#define RTCP_PT_SR 200 +#define RTCP_PT_RR 201 +#define RTCP_PT_SDES 202 +#define RTCP_PT_BYE 203 +#define RTCP_PT_APP 204 + +#define SDES_ITEM_CNAME 1 +#define SDES_ITEM_NAME 2 +#define SDES_ITEM_EMAIL 3 +#define SDES_ITEM_PHONE 4 +#define SDES_ITEM_LOC 5 +#define SDES_ITEM_TOOL 6 +#define SDES_ITEM_NOTE 7 +#define SDES_ITEM_PRIV 8
View file
libosmo-netif_1.6.1.tar.xz/include/osmocom/netif/sctp.h -> libosmo-netif_1.7.0.tar.xz/include/osmocom/netif/sctp.h
Changed
@@ -1,6 +1,7 @@ #pragma once #include <osmocom/core/utils.h> +#include <netinet/sctp.h> /* Relevant SCTP RFCs: * rfc9260 (obsoletes rfc4960): SCTP protocol @@ -8,22 +9,18 @@ * rfc6458: SCTP Sockets API Extensions */ -enum sctp_sac_state; extern const struct value_string osmo_sctp_assoc_chg_strs; static inline const char *osmo_sctp_assoc_chg_str(enum sctp_sac_state val) { return get_value_string(osmo_sctp_assoc_chg_strs, val); } -enum sctp_spc_state; extern const struct value_string osmo_sctp_paddr_chg_strs; static inline const char *osmo_sctp_paddr_chg_str(enum sctp_spc_state val) { return get_value_string(osmo_sctp_paddr_chg_strs, val); } -enum sctp_sn_type; extern const struct value_string osmo_sctp_sn_type_strs; static inline const char *osmo_sctp_sn_type_str(enum sctp_sn_type val) { return get_value_string(osmo_sctp_sn_type_strs, val); } -enum sctp_sn_error; extern const struct value_string osmo_sctp_sn_error_strs; static inline const char *osmo_sctp_sn_error_str(enum sctp_sn_error val) { return get_value_string(osmo_sctp_sn_error_strs, val); } @@ -43,18 +40,14 @@ OSMO_SCTP_OP_ERR_UNER_INITED_ABORT = 12, OSMO_SCTP_OP_ERR_PROTO_VERSION = 13, }; - - extern const struct value_string osmo_sctp_op_error_strs; static inline const char *osmo_sctp_op_error_str(enum osmo_sctp_op_error val) { return get_value_string(osmo_sctp_op_error_strs, val); } -enum sctp_spinfo_state; extern const struct value_string osmo_sctp_spinfo_state_strs; static inline const char *osmo_sctp_spinfo_state_str(enum sctp_spinfo_state val) { return get_value_string(osmo_sctp_spinfo_state_strs, val); } -enum sctp_sstat_state; extern const struct value_string osmo_sctp_sstat_state_strs; static inline const char *osmo_sctp_sstat_state_str(enum sctp_sstat_state val) { return get_value_string(osmo_sctp_sstat_state_strs, val); }
View file
libosmo-netif_1.6.1.tar.xz/include/osmocom/netif/stream.h -> libosmo-netif_1.7.0.tar.xz/include/osmocom/netif/stream.h
Changed
@@ -98,6 +98,12 @@ OSMO_STREAM_SRV_LINK_PAR_SCTP_SOCKOPT_ASCONF_SUPPORTED, /* uint8_t: 0 disable, 1 enable, 2 force disable, 3 force enable */ OSMO_STREAM_SRV_LINK_PAR_SCTP_INIT_NUM_OSTREAMS, /* uint16_t: amount of streams */ OSMO_STREAM_SRV_LINK_PAR_SCTP_INIT_MAX_INSTREAMS, /* uint16_t: amount of streams */ + + OSMO_STREAM_SRV_LINK_PAR_TCP_SOCKOPT_KEEPALIVE = 256, /* uint8_t: 0 disable, 1 enable */ + OSMO_STREAM_SRV_LINK_PAR_TCP_SOCKOPT_KEEPIDLE, /* int: seconds */ + OSMO_STREAM_SRV_LINK_PAR_TCP_SOCKOPT_KEEPINTVL, /* int: seconds */ + OSMO_STREAM_SRV_LINK_PAR_TCP_SOCKOPT_KEEPCNT, /* int: Number of probes */ + OSMO_STREAM_SRV_LINK_PAR_TCP_SOCKOPT_USER_TIMEOUT, /* unsigned int: 0 "system default", >0 see sockopt TCP_USER_TIMEOUT */ }; int osmo_stream_srv_link_set_param(struct osmo_stream_srv_link *link, enum osmo_stream_srv_link_param par, @@ -126,10 +132,12 @@ void *data); struct osmo_stream_srv *osmo_stream_srv_create2(void *ctx, struct osmo_stream_srv_link *link, int fd, void *data); void osmo_stream_srv_set_name(struct osmo_stream_srv *conn, const char *name); +void osmo_stream_srv_set_name_f(struct osmo_stream_srv *conn, const char *fmt, ...); const char *osmo_stream_srv_get_name(const struct osmo_stream_srv *conn); void osmo_stream_srv_set_read_cb(struct osmo_stream_srv *conn, osmo_stream_srv_read_cb2_t read_cb); void osmo_stream_srv_set_closed_cb(struct osmo_stream_srv *conn, osmo_stream_srv_closed_cb_t close_cb); void *osmo_stream_srv_get_data(struct osmo_stream_srv *conn); +int osmo_stream_srv_set_tx_queue_max_length(struct osmo_stream_srv *conn, unsigned int size); struct osmo_stream_srv_link *osmo_stream_srv_get_master(struct osmo_stream_srv *conn); const char *osmo_stream_srv_get_sockname(const struct osmo_stream_srv *conn); struct osmo_fd *osmo_stream_srv_get_ofd(struct osmo_stream_srv *srv); @@ -148,6 +156,16 @@ void osmo_stream_srv_clear_tx_queue(struct osmo_stream_srv *conn); +enum osmo_stream_srv_param { + OSMO_STREAM_SRV_PAR_TCP_SOCKOPT_KEEPALIVE = 256, /* uint8_t: 0 disable, 1 enable */ + OSMO_STREAM_SRV_PAR_TCP_SOCKOPT_KEEPIDLE, /* int: seconds */ + OSMO_STREAM_SRV_PAR_TCP_SOCKOPT_KEEPINTVL, /* int: seconds */ + OSMO_STREAM_SRV_PAR_TCP_SOCKOPT_KEEPCNT, /* int: Number of probes */ + OSMO_STREAM_SRV_PAR_TCP_SOCKOPT_USER_TIMEOUT, /* unsigned int: 0 "system default", >0 see sockopt TCP_USER_TIMEOUT */ +}; +int osmo_stream_srv_set_param(struct osmo_stream_srv *conn, enum osmo_stream_srv_param par, + void *val, size_t val_len); + /*! @} */ /*! \defgroup stream_cli Osmocom Stream Client @@ -203,6 +221,7 @@ 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); +void osmo_stream_cli_set_name_f(struct osmo_stream_cli *cli, const char *fmt, ...); 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); @@ -253,6 +272,12 @@ OSMO_STREAM_CLI_PAR_SCTP_INIT_MAX_INSTREAMS, /* uint16_t: amount of streams */ OSMO_STREAM_CLI_PAR_SCTP_INIT_MAX_ATTEMPTS, /* uint16_t: amount of attempts */ OSMO_STREAM_CLI_PAR_SCTP_INIT_TIMEOUT, /* uint16_t: milliseconds */ + + OSMO_STREAM_CLI_PAR_TCP_SOCKOPT_KEEPALIVE = 256, /* uint8_t: 0 disable, 1 enable */ + OSMO_STREAM_CLI_PAR_TCP_SOCKOPT_KEEPIDLE, /* int: seconds */ + OSMO_STREAM_CLI_PAR_TCP_SOCKOPT_KEEPINTVL, /* int: seconds */ + OSMO_STREAM_CLI_PAR_TCP_SOCKOPT_KEEPCNT, /* int: Number of probes */ + OSMO_STREAM_CLI_PAR_TCP_SOCKOPT_USER_TIMEOUT, /* unsigned int: 0 "system default", >0 see sockopt TCP_USER_TIMEOUT */ }; int osmo_stream_cli_set_param(struct osmo_stream_cli *cli, enum osmo_stream_cli_param par,
View file
libosmo-netif_1.6.1.tar.xz/include/osmocom/netif/stream_private.h -> libosmo-netif_1.7.0.tar.xz/include/osmocom/netif/stream_private.h
Changed
@@ -29,6 +29,28 @@ OSMO_STREAM_MODE_OSMO_IO, }; +struct stream_tcp_keepalive_pars { + bool enable; + bool time_present; + bool intvl_present; + bool probes_present; + int time_value; /* seconds */ + int intvl_value; /* seconds */ + int probes_value; +}; +int stream_setsockopt_tcp_keepalive(int fd, int on); +int stream_setsockopt_tcp_keepidle(int fd, int keepalive_time); +int stream_setsockopt_tcp_keepintvl(int fd, int keepalive_intvl); +int stream_setsockopt_tcp_keepcnt(int fd, int keepalive_probes); +int stream_tcp_keepalive_pars_apply(int fd, const struct stream_tcp_keepalive_pars *tkp); + +struct stream_tcp_pars { + struct stream_tcp_keepalive_pars ka; + bool user_timeout_present; + unsigned int user_timeout_value; +}; +int stream_setsockopt_tcp_user_timeout(int fd, unsigned int user_timeout); + struct osmo_io_fd; struct msghdr;
View file
libosmo-netif_1.7.0.tar.xz/include/osmocom/netif/twjit.h
Added
@@ -0,0 +1,190 @@ +/* + * Themyscira Wireless RTP jitter buffer implementation: + * public API definition for Osmocom-integrated version. + * + * This code was contributed to Osmocom Cellular Network Infrastructure + * project by Mother Mychaela N. Falconia of Themyscira Wireless. + * Mother Mychaela's contributions are NOT subject to copyright: + * no rights reserved, all rights relinquished. + */ + +#pragma once + +#include <stdint.h> +#include <stdbool.h> + +#include <osmocom/core/msgb.h> + +/*! \defgroup twjit Themyscira Wireless RTP jitter buffer implementation + * @{ + * + * The present twjit layer is an interface mechanism from an incoming + * RTP stream to an output application that has fixed timing requirements, + * e.g., the Tx side of GSM Um TCH or a T1/E1 TDM interface. + * + * For a more detailed description, please consult the full twrtp guide + * document that can be found in doc/twrtp directory. This document is + * required reading for anyone seeking to properly understand the present + * jitter buffer facility, its domain of application and how to use it. + * Specific section references to this document will be made in subsequent + * comments. + */ + +/*! Each instance of twjit in the present version exists as struct osmo_twjit. + * This structure is opaque, and always constitutes a talloc context. */ +struct osmo_twjit; + +/*! A config structure is also needed, containing tunable settings + * that are usually managed via vty. This config structure is separate + * from individual twjit instances because there will be many more + * twjit instances than config instances: there will be a separate + * twjit instance for every call or other RTP stream handled by the + * application, but only one twjit config structure in the app's + * vty config tree, or a few such config instances as appropriate + * per app design. + * + * This config structure is likewise opaque and also constitutes a talloc + * context. */ +struct osmo_twjit_config; + +/*! Stats collected during the lifetime of a twjit instance. + * For a detailed description of each of these counters, see Chapter 3 + * of twrtp guide document. + * + * This stats structure is never allocated or accessed in a writable + * manner by applications; instead it is allocated inside the library + * as part of opaque struct osmo_twjit, while applications are given + * const pointers to these structs. + */ +struct osmo_twjit_stats { + /* For ABI reasons, none of the following fields may be deleted + * or reordered! */ + + /* normal operation */ + uint32_t rx_packets; + uint32_t delivered_pkt; + uint32_t handovers_in; + uint32_t handovers_out; + uint32_t marker_resets; + /* undesirable, but not totally unexpected */ + uint32_t too_old; + uint32_t underruns; + uint32_t ho_underruns; + uint32_t output_gaps; + uint32_t thinning_drops; + /* unusual error events */ + uint32_t bad_packets; + uint32_t duplicate_ts; + /* independent analysis of Rx packet stream */ + uint32_t ssrc_changes; + uint32_t seq_skips; + uint32_t seq_backwards; + uint32_t seq_repeats; + uint32_t intentional_gaps; + uint32_t ts_resets; + uint32_t jitter_max; + /* New fields may be added here at the end; once added, they become + * permanent like the initially defined ones. */ +}; + +/*! Info collected from the incoming RTP data stream + * for the purpose of generating RTCP reception report blocks. + * See twrtp guide document section 5.1. + * + * Key point: unlike the counters in struct osmo_twjit_stats, + * all RR info is reset to initial whenever incoming SSRC changes, + * as necessitated by RTCP data model being organized per SSRC. + * + * The same ABI considerations apply to this struct as osmo_twjit_stats. + */ +struct osmo_twjit_rr_info { + /* For ABI reasons, none of the following fields may be deleted + * or reordered! */ + + /*! received SSRC to which all following info applies */ + uint32_t ssrc; + /*! count of "received packets" for RTCP RR packet loss calculation */ + uint32_t rx_packets; + /*! "base" sequence number for "expected packets" computation */ + uint32_t base_seq; + /*! "extended highest sequence number" field of RTCP RR */ + uint32_t max_seq_ext; + /*! count of "expected packets" for RTCP RR packet loss calculation */ + uint32_t expected_pkt; + /*! "interarrival jitter" measure of RFC 3550, accumulator for the + * leaky integrator algorithm prescribed by the RFC, sans-FP version. + * Right-shift this accumulator by 4 bits when emitting RTCP RR. */ + uint32_t jitter_accum; + /* New fields may be added here at the end; once added, they become + * permanent like the initially defined ones. */ +}; + +/* twjit API: managing configuration structures */ + +struct osmo_twjit_config *osmo_twjit_config_alloc(void *ctx); +void osmo_twjit_config_free(struct osmo_twjit_config *conf); + +int osmo_twjit_config_set_buffer_depth(struct osmo_twjit_config *conf, + uint16_t bd_start, uint16_t bd_hiwat); +int osmo_twjit_config_set_thinning_int(struct osmo_twjit_config *conf, + uint16_t thinning_int); +int osmo_twjit_config_set_max_future_sec(struct osmo_twjit_config *conf, + uint16_t max_future_sec); +int osmo_twjit_config_set_start_min_delta(struct osmo_twjit_config *conf, + uint16_t delta_ms); +int osmo_twjit_config_set_start_max_delta(struct osmo_twjit_config *conf, + uint16_t delta_ms); +int osmo_twjit_config_set_handover_on_marker(struct osmo_twjit_config *conf, + bool hom); + +/* twjit API: actual twjit instances */ + +struct osmo_twjit *osmo_twjit_create(void *ctx, uint16_t clock_khz, + uint16_t quantum_ms, + const struct osmo_twjit_config *config); +void osmo_twjit_destroy(struct osmo_twjit *twjit); + +int osmo_twjit_set_config(struct osmo_twjit *twjit, + const struct osmo_twjit_config *config); +void osmo_twjit_reset(struct osmo_twjit *twjit); + +/* RTP input, takes ownership of msgb */ +void osmo_twjit_input(struct osmo_twjit *twjit, struct msgb *msg); + +/* output function, to be called by TDM/GSM/etc fixed-timing side */ +struct msgb *osmo_twjit_output(struct osmo_twjit *twjit); + +/* Stats and RR info structures are contained inside opaque struct osmo_twjit. + * We need to provide access to these stats and RR info structures to API + * users, but we don't want to make the whole twjit instance struct public. + * Also we would like to have fast external access to these stats, hence an API + * that copies our stats to caller-provided storage would be very inefficient. + * Compromise: we allow direct external access to just these selected parts + * of the full internal state structure by providing API functions that + * return pointers to these selected parts. + */ +const struct osmo_twjit_stats * +osmo_twjit_get_stats(struct osmo_twjit *twjit); + +const struct osmo_twjit_rr_info * +osmo_twjit_get_rr_info(struct osmo_twjit *twjit); + +/* When we compose outgoing RTCP packets in the upper layer of twrtp, + * we need to know whether or not we have received at least one valid + * RTP data packet so far. If we haven't received any RTP yet, then + * we have no Rx SSRC, all data in struct osmo_twjit_rr_info are invalid, + * and we cannot send RTCP reception reports. + */ +bool osmo_twjit_rr_info_valid(struct osmo_twjit *twjit); + +/* vty configuration functions */ + +void osmo_twjit_vty_init(int twjit_node); + +struct vty; + +int osmo_twjit_config_write(struct vty *vty, + const struct osmo_twjit_config *conf, + const char *prefix); + +/*! @} */
View file
libosmo-netif_1.7.0.tar.xz/include/osmocom/netif/twjit_private.h
Added
@@ -0,0 +1,61 @@ +/* + * Themyscira Wireless RTP jitter buffer implementation: + * internal config structure. + * + * This code was contributed to Osmocom Cellular Network Infrastructure + * project by Mother Mychaela N. Falconia of Themyscira Wireless. + * Mother Mychaela's contributions are NOT subject to copyright: + * no rights reserved, all rights relinquished. + */ + +#pragma once + +#include <stdint.h> +#include <stdbool.h> + +/*! \cond private */ + +/*! twjit configuration tunings, usually set via vty. + * This config structure always has to be provided in order to + * create a twjit instance. However, due to ABI concerns + * (retaining ability to add new fields to this structure), + * the struct itself has been made opaque, with actual definition + * visible only inside the library. + * + * In most twjit-using applications, the library's vty module + * will take care of both displaying and changing these tunable + * settings. However, setter APIs are also provided for non-vty + * users. + * + * The set of configurable parameters contained in this structure + * is covered in twrtp guide document section 2.4. + */ +struct osmo_twjit_config { + /*! buffer depth: starting minimum, formally called flow-starting + * fill level. Document section: 2.3.3. */ + uint16_t bd_start; + /*! buffer depth: high water mark, formally called high water mark + * fill level. Document section: 2.3.4.2. */ + uint16_t bd_hiwat; + /*! interval for thinning of too-deep standing queue; + * document section: 2.3.4.2. */ + uint16_t thinning_int; + /*! guard against time traveler RTP packets, 1 s units; + * document section: 2.3.4.3. */ + uint16_t max_future_sec; + /*! min time delta in starting state, 1 ms units, 0 means not set; + * document section: 2.3.3.2. */ + uint16_t start_min_delta; + /*! max time delta in starting state, 1 ms units, 0 means not set; + * document section: 2.3.3.2. */ + uint16_t start_max_delta; + /*! Osmocom addition, not in ThemWi original: should RTP packets + * with M bit set cause a handover or HUNT state reset just like + * an SSRC change? With this option enabled, M bit is treated + * like an SSRC change in that the timestamp is not considered + * at all, on the reasoning that the sender may have switched + * to an entirely unrelated source of timestamps. */ + bool handover_on_marker; +}; + +/*! \endcond */
View file
libosmo-netif_1.7.0.tar.xz/include/osmocom/netif/twrtp.h
Added
@@ -0,0 +1,228 @@ +/* + * Themyscira Wireless RTP endpoint implementation: + * public API definition for Osmocom-integrated version. + * + * This code was contributed to Osmocom Cellular Network Infrastructure + * project by Mother Mychaela N. Falconia of Themyscira Wireless. + * Mother Mychaela's contributions are NOT subject to copyright: + * no rights reserved, all rights relinquished. + */ + +#pragma once + +#include <stdint.h> +#include <stdbool.h> + +#include <osmocom/core/msgb.h> +#include <osmocom/core/socket.h> + +/*! \defgroup twrtp Themyscira Wireless RTP endpoint implementation + * @{ + * + * osmo_twrtp is a complete RTP endpoint. It is primarily designed + * to be used together with twjit to build a bidirectional interface + * between an RTP stream and a fixed timing system such as GSM Um TCH + * or T1/E1 Abis, but it also has limited support for endpoints without + * twjit. A twrtp endpoint without twjit is either an output-only + * endpoint (playout of in-band tones and announcements etc), or one + * side of a pair of endpoints that forward RTP packets to each other + * without delay. + * + * The basic workflow is: + * + * 1. Create a twrtp instance with osmo_twrtp_create(). The decision + * to use or not use twjit is fixed at this time; if twjit is to be + * used, struct osmo_twjit_config needs to be provided. + * + * 2. Create and bind a pair of local UDP sockets for RTP and RTCP, + * or supply osmo_twrtp with an already-obtained pair of file descriptors + * for the same. Most users will find the high-level API + * osmo_twrtp_bind_local() most suitable, but some applications may + * prefer to use the low-level API osmo_twrtp_supply_fds() instead. + * + * 3. Set the IP:port address of the remote RTP end with + * osmo_twrtp_set_remote(). + * + * 4. Traffic can now be sent and received as detailed below. + * + * Receiving RTP traffic, interworking to a fixed timing system: + * + * 1. Provide struct osmo_twjit_config to osmo_twrtp_create(), so the twrtp + * instance will be created with twjit included. + * + * 2. When you are ready to start receiving traffic, call + * osmo_twrtp_twjit_rx_ctrl() with rx_enable argument set to true. + * + * 3. Once you've made the above call, commit to calling + * osmo_twrtp_twjit_rx_poll() every 20 ms (or whatever your quantum + * duration is) as timed by your GSM Um TCH or TDM system, every tick + * without fail. + * + * 4. You can pause operation by calling osmo_twrtp_twjit_rx_ctrl() with + * rx_enable argument set to false, and then later restart by returning + * to step 2 above. When you pause, the Rx jitter buffer will be + * flushed, and when you restart Rx, twjit will restart from empty state. + * + * Sending RTP traffic, coming from a fixed timing system: + * + * 1. Make the first call to osmo_twrtp_tx_quantum() whenever you are ready + * to send out the first quantum. + * + * 2. Once you've made that first call, commit to sending either another + * quantum or an intentional gap (osmo_twrtp_tx_skip()) every 20 ms + * without fail, as timed by your GSM Um TCH, T1/E1 TDM or other fixed + * timing system. + * + * 3. If you need to pause Tx output and restart later, or if some + * discontinuity occurs in your fixed timing system where you know that + * your interval between quantum sends is not the proper 20 ms or whatever + * your quantum duration is, call osmo_twrtp_tx_restart(), telling the + * library to reset the RTP timescale in its subsequent output. + * + * No-delay forwarding operation from one twrtp endpoint to another: + * + * 1. On the receiving side, call osmo_twrtp_set_raw_rx_cb() to set up an + * unbuffered/non-delayed Rx callback function. + * + * 2. In that Rx callback function, forward the packet to the other endpoint + * with osmo_twrtp_tx_forward(). + * + * 3. If you are building an MGW that mostly does forwarding as described here, + * but occasionally inserts its own in-band tones or announcements, you can + * switch in real time between just-described forwarding and "native" + * osmo_twrtp_tx_quantum() output. The receiving RTP end will see + * "handover" events as SSRC switches between the one emitted by twrtp + * and the one coming from the other remote party. Actual timing will + * also switch, as there is no realistic way your own 20 ms timing for + * announcement playout will exactly match the timing of the RTP stream + * switched from the other remote party. + * + * RTCP handling is mostly internal to the library - as a user, you don't need + * to concern yourself with it. More precisely, incoming RTCP packets are + * always handled internally; if you wish to send out RTCP, you have to set + * SDES and decide if you wish to send out SR or RR packets. Automatic + * emission of an SR packet after every so many RTP packets, with an RR block + * included in that SR, is the most common and most useful mode. OTOH, if + * your RTP application does not use RTCP, you don't need to concern yourself + * with RTCP at all: don't configure or enable RTCP sending, and ignore the + * existence of the built-in RTCP receiver. Any received RTCP packets will + * still be parsed, but you can ignore the data that result from this parsing. + * + * For a more detailed description, please consult the full twrtp guide + * document that can be found in doc/twrtp directory. This document is + * required reading for anyone seeking to properly understand twrtp, its + * domain of application and all of its capabilities, beyond the brief + * summary given above. Specific section references to this document + * will be made in subsequent comments. + */ + +/*! Each instance of twrtp in the present version exists as struct osmo_twrtp. + * This structure is opaque, and always constitutes a talloc context. */ +struct osmo_twrtp; + +/*! Stats collected during the lifetime of a twrtp instance. + * For a detailed description of each of these counters, see Chapter 6 + * of twrtp guide document. + * + * This stats structure is never allocated or accessed in a writable + * manner by applications; instead it is allocated inside the library + * as part of opaque struct osmo_twrtp, while applications are given + * const pointers to these structs. + */ +struct osmo_twrtp_stats { + /* For ABI reasons, none of the following fields may be deleted + * or reordered! */ + uint32_t rx_rtp_pkt; + uint32_t rx_rtp_badsrc; + uint32_t rx_rtcp_pkt; + uint32_t rx_rtcp_badsrc; + uint32_t rx_rtcp_invalid; + uint32_t rx_rtcp_wrong_ssrc; + uint32_t tx_rtp_pkt; + uint32_t tx_rtp_bytes; + uint32_t tx_rtcp_pkt; + /* New fields may be added here at the end; once added, they become + * permanent like the initially defined ones. */ +}; + +/* declare structs that are used in our API */ + +struct osmo_twjit; +struct osmo_twjit_config; +struct osmo_twjit_stats; +struct osmo_twjit_rr_info; + +/* public API functions: create & destroy, local and remote addresses */ + +struct osmo_twrtp * +osmo_twrtp_create(void *ctx, uint16_t clock_khz, uint16_t quantum_ms, + bool random_ts_seq, + const struct osmo_twjit_config *twjit_config); +void osmo_twrtp_destroy(struct osmo_twrtp *endp); + +int osmo_twrtp_supply_fds(struct osmo_twrtp *endp, int rtp_fd, int rtcp_fd); +int osmo_twrtp_bind_local(struct osmo_twrtp *endp, + const struct osmo_sockaddr *rtp_addr, bool bind_rtcp); +int osmo_twrtp_set_remote(struct osmo_twrtp *endp, + const struct osmo_sockaddr *rtp_addr); + +/* receiving incoming RTP via twjit */ + +void osmo_twrtp_twjit_rx_ctrl(struct osmo_twrtp *endp, bool rx_enable); + +/* output function, to be called by TDM/GSM/etc fixed-timing side */ +struct msgb *osmo_twrtp_twjit_rx_poll(struct osmo_twrtp *endp); + +/* receiving incoming RTP without twjit */ + +/* callback function takes ownership of msgb *if* it returns true */ +typedef bool (*osmo_twrtp_raw_rx_cb)(struct osmo_twrtp *endp, void *user_data, + struct msgb *msg); + +void osmo_twrtp_set_raw_rx_cb(struct osmo_twrtp *endp, osmo_twrtp_raw_rx_cb cb, + void *user_data); + +/* RTP Tx direction */ + +int osmo_twrtp_tx_quantum(struct osmo_twrtp *endp, const uint8_t *payload, + unsigned payload_len, uint8_t payload_type, + bool marker, bool auto_marker, bool send_rtcp); +void osmo_twrtp_tx_skip(struct osmo_twrtp *endp); +void osmo_twrtp_tx_restart(struct osmo_twrtp *endp); + +int osmo_twrtp_tx_forward(struct osmo_twrtp *endp, struct msgb *msg); + +/* support for emitting RTCP SR & RR */ + +int osmo_twrtp_set_sdes(struct osmo_twrtp *endp, const char *cname, + const char *name, const char *email, const char *phone, + const char *loc, const char *tool, const char *note);
View file
libosmo-netif_1.7.0.tar.xz/include/osmocom/netif/version.h.tpl
Added
@@ -0,0 +1,16 @@ +#pragma once + +#define LIBOSMO_NETIF_VERSION {{VERSION}} +#define LIBOSMO_NETIF_VERSION_STR "{{VERSION}}" + +#define LIBOSMO_NETIF_VERSION_MAJOR {{VERSION_MAJOR}} +#define LIBOSMO_NETIF_VERSION_MINOR {{VERSION_MINOR}} +#define LIBOSMO_NETIF_VERSION_PATCH {{VERSION_PATCH}} + +#define LIBOSMO_NETIF_VERSION_GREATER_EQUAL(major, minor, patch) \ + (LIBOSMO_NETIF_VERSION_MAJOR > (major) || \ + (LIBOSMO_NETIF_VERSION_MAJOR == (major) && \ + LIBOSMO_NETIF_VERSION_MINOR > (minor)) || \ + (LIBOSMO_NETIF_VERSION_MAJOR == (major) && \ + LIBOSMO_NETIF_VERSION_MINOR == (minor) && \ + LIBOSMO_NETIF_VERSION_PATCH >= (patch)))
View file
libosmo-netif_1.6.1.tar.xz/src/Makefile.am -> libosmo-netif_1.7.0.tar.xz/src/Makefile.am
Changed
@@ -1,14 +1,16 @@ # 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=14:1:3 +LIBVERSION=15:0:4 AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir) -AM_CFLAGS= -fPIC -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(COVERAGE_CFLAGS) $(LIBSCTP_CFLAGS) +AM_CFLAGS= -fPIC -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) \ + $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS) $(LIBSCTP_CFLAGS) AM_LDFLAGS = $(COVERAGE_LDFLAGS) lib_LTLIBRARIES = libosmonetif.la -libosmonetif_la_LIBADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBSCTP_LIBS) +libosmonetif_la_LIBADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) \ + $(LIBOSMOVTY_LIBS) $(LIBSCTP_LIBS) libosmonetif_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(LIBVERSION) -no-undefined libosmonetif_la_SOURCES = amr.c \ @@ -26,6 +28,9 @@ stream.c \ stream_cli.c \ stream_srv.c \ + twjit.c \ + twjit_conf.c \ + twrtp.c \ $(NULL) if ENABLE_LIBSCTP
View file
libosmo-netif_1.6.1.tar.xz/src/osmux_input.c -> libosmo-netif_1.7.0.tar.xz/src/osmux_input.c
Changed
@@ -144,8 +144,8 @@ static void osmux_circuit_del_msgs(struct osmux_link *link, struct osmux_circuit *circuit) { - struct msgb *cur, *tmp; - llist_for_each_entry_safe(cur, tmp, &circuit->msg_list, list) { + struct msgb *cur; + while ((cur = llist_first_entry_or_null(&circuit->msg_list, struct msgb, list))) { osmux_circuit_dequeue(circuit, cur); msgb_free(cur); link->nmsgs--; @@ -687,9 +687,9 @@ static int osmux_xfrm_input_talloc_destructor(struct osmux_in_handle *h) { struct osmux_link *link = (struct osmux_link *)h->internal_data; - struct osmux_circuit *circuit, *next; + struct osmux_circuit *circuit; - llist_for_each_entry_safe(circuit, next, &link->circuit_list, head) + while ((circuit = llist_first_entry_or_null(&link->circuit_list, struct osmux_circuit, head))) osmux_link_del_circuit(link, circuit); osmo_timer_del(&link->timer);
View file
libosmo-netif_1.6.1.tar.xz/src/stream.c -> libosmo-netif_1.7.0.tar.xz/src/stream.c
Changed
@@ -196,6 +196,89 @@ return rc; } +int stream_setsockopt_tcp_keepalive(int fd, int on) +{ + int ret = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)); + if (ret < 0) { + ret = errno; + LOGP(DLINP, LOGL_ERROR, "Failed to enable TCP keepalive on fd %d: %s\n", fd, strerror(ret)); + return -ret; + } + return 0; +} + +int stream_setsockopt_tcp_keepidle(int fd, int keepalive_time) +{ + int ret = setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepalive_time, sizeof(keepalive_time)); + if (ret < 0) { + ret = errno; + LOGP(DLINP, LOGL_ERROR, "Failed to set TCP_KEEPIDLE on fd %d: %s\n", fd, strerror(ret)); + return -ret; + } + return 0; +} + +int stream_setsockopt_tcp_keepintvl(int fd, int keepalive_intvl) +{ + int ret = setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &keepalive_intvl, sizeof(keepalive_intvl)); + if (ret < 0) { + ret = errno; + LOGP(DLINP, LOGL_ERROR, "Failed to set TCP_KEEPINTVL on fd %d: %s\n", fd, strerror(ret)); + return -ret; + } + return 0; +} + +int stream_setsockopt_tcp_keepcnt(int fd, int keepalive_probes) +{ + int ret = setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &keepalive_probes, sizeof(keepalive_probes)); + if (ret < 0) { + ret = errno; + LOGP(DLINP, LOGL_ERROR, "Failed to set TCP_KEEPCNT on fd %d: %s\n", fd, strerror(ret)); + return -ret; + } + return 0; +} + +int stream_setsockopt_tcp_user_timeout(int fd, unsigned int user_timeout) +{ + int ret = setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &user_timeout, sizeof(user_timeout)); + if (ret < 0) { + ret = errno; + LOGP(DLINP, LOGL_ERROR, "Failed to set TCP_USER_TIMEOUT on fd %d: %s\n", fd, strerror(ret)); + return -ret; + } + return 0; +} + +int stream_tcp_keepalive_pars_apply(int fd, const struct stream_tcp_keepalive_pars *tkp) +{ + int ret; + + if (!tkp->enable) + return 0; + + if ((ret = stream_setsockopt_tcp_keepalive(fd, tkp->enable)) < 0) + return ret; + + if (tkp->time_present) { + if ((ret = stream_setsockopt_tcp_keepidle(fd, tkp->time_value)) < 0) + return ret; + } + + if (tkp->intvl_present) { + if ((ret = stream_setsockopt_tcp_keepintvl(fd, tkp->intvl_value)) < 0) + return ret; + } + + if (tkp->probes_present) { + if ((ret = stream_setsockopt_tcp_keepcnt(fd, tkp->probes_value)) < 0) + return ret; + } + + return 0; +} + #ifdef HAVE_LIBSCTP static int stream_sctp_recvmsg_trailer(const char *log_pfx, struct msgb *msg, int ret, const struct sctp_sndrcvinfo *sinfo, int flags) { @@ -266,8 +349,11 @@ return ret; } - if (OSMO_UNLIKELY(ret > 0 && !sinfo)) - LOGP(DLINP, LOGL_ERROR, "%s sctp_recvmsg without SNDRCV cmsg?!?\n", log_pfx); + if (OSMO_UNLIKELY(ret > 0 && !sinfo)) { + char buf512; + LOGP(DLINP, LOGL_ERROR, "%s sctp_recvmsg without SNDRCV cmsg?!? ret=%d, flags=0x%x, %s\n", + log_pfx, ret, flags, msgb_hexdump_buf(buf, sizeof(buf), msg)); + } return ret; } @@ -296,7 +382,7 @@ struct cmsghdr *cmsg = NULL; for (cmsg = CMSG_FIRSTHDR((struct msghdr *) msgh); cmsg != NULL; - cmsg = CMSG_NXTHDR((struct msghdr *) msgh, cmsg)) { + cmsg = CMSG_NXTHDR((struct msghdr *) msgh, cmsg)) { if (cmsg->cmsg_level == IPPROTO_SCTP && cmsg->cmsg_type == SCTP_SNDRCV) { sinfo = (const struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); break;
View file
libosmo-netif_1.6.1.tar.xz/src/stream_cli.c -> libosmo-netif_1.7.0.tar.xz/src/stream_cli.c
Changed
@@ -122,6 +122,7 @@ int flags; int reconnect_timeout; struct osmo_sock_init2_multiaddr_pars ma_pars; + struct stream_tcp_pars tcp_pars; uint8_t in_cb_mask; /* IN_CB_MASK_* */ bool delay_free; }; @@ -667,9 +668,31 @@ */ void osmo_stream_cli_set_name(struct osmo_stream_cli *cli, const char *name) { - osmo_talloc_replace_string(cli, &cli->name, name); + osmo_stream_cli_set_name_f(cli, "%s", name); +} + +/*! Set a name on the cli object using arguments like printf() (used during logging). + * \paramin cli stream_cli whose name is to be set + * \paramin name the name to be set on cli + */ +void osmo_stream_cli_set_name_f(struct osmo_stream_cli *cli, const char *fmt, ...) +{ + char *name = NULL; + + if (fmt) { + va_list ap; + + va_start(ap, fmt); + name = talloc_vasprintf(cli, fmt, ap); + va_end(ap); + } + + if (cli->name) + talloc_free((void *)cli->name); + cli->name = name; + if (cli->mode == OSMO_STREAM_MODE_OSMO_IO && cli->iofd) - osmo_iofd_set_name(cli->iofd, name); + osmo_iofd_set_name(cli->iofd, cli->name); } /*! Retrieve name previously set on the cli object (see osmo_stream_cli_set_name()). @@ -873,10 +896,10 @@ return 0; } -/*! Set the socket type for the stream server link. +/*! Set the socket domain for the stream client link. * Any changes to this setting will only become active upon next (re)connect. * \paramin cli Stream Client to modify - * \paramin type Socket Domain (like AF_UNSPEC (default for IP), AF_UNIX, AF_INET, ...) + * \paramin domain Socket Domain (like AF_UNSPEC (default for IP), AF_UNIX, AF_INET, ...) * \returns zero on success, negative -errno on error. */ int osmo_stream_cli_set_domain(struct osmo_stream_cli *cli, int domain) @@ -1264,6 +1287,17 @@ goto error_close_socket; } + if (cli->proto == IPPROTO_TCP) { + ret = stream_tcp_keepalive_pars_apply(fd, &cli->tcp_pars.ka); + if (ret < 0) + goto error_close_socket; + if (cli->tcp_pars.user_timeout_present) { + ret = stream_setsockopt_tcp_user_timeout(fd, cli->tcp_pars.user_timeout_value); + if (ret < 0) + goto error_close_socket; + } + } + switch (cli->mode) { case OSMO_STREAM_MODE_OSMO_FD: osmo_fd_setup(&cli->ofd, fd, OSMO_FD_READ | OSMO_FD_WRITE, osmo_stream_cli_fd_cb, cli, 0); @@ -1510,6 +1544,46 @@ cli->ma_pars.sctp.sockopt_initmsg.max_init_timeo_present = true; cli->ma_pars.sctp.sockopt_initmsg.max_init_timeo_value = *(uint16_t *)val; break; + /* TCP keepalive params: */ + case OSMO_STREAM_CLI_PAR_TCP_SOCKOPT_KEEPALIVE: + if (!val || val_len != sizeof(uint8_t)) + return -EINVAL; + cli->tcp_pars.ka.enable = !!*(uint8_t *)val; + if (stream_cli_is_opened(cli)) + return stream_setsockopt_tcp_keepalive(osmo_stream_cli_get_fd(cli), cli->tcp_pars.ka.enable); + break; + case OSMO_STREAM_CLI_PAR_TCP_SOCKOPT_KEEPIDLE: + if (!val || val_len != sizeof(int)) + return -EINVAL; + cli->tcp_pars.ka.time_present = true; + cli->tcp_pars.ka.time_value = *(int *)val; + if (stream_cli_is_opened(cli)) + return stream_setsockopt_tcp_keepidle(osmo_stream_cli_get_fd(cli), cli->tcp_pars.ka.time_value); + break; + case OSMO_STREAM_CLI_PAR_TCP_SOCKOPT_KEEPINTVL: + if (!val || val_len != sizeof(int)) + return -EINVAL; + cli->tcp_pars.ka.intvl_present = true; + cli->tcp_pars.ka.intvl_value = *(int *)val; + if (stream_cli_is_opened(cli)) + return stream_setsockopt_tcp_keepintvl(osmo_stream_cli_get_fd(cli), cli->tcp_pars.ka.intvl_value); + break; + case OSMO_STREAM_CLI_PAR_TCP_SOCKOPT_KEEPCNT: + if (!val || val_len != sizeof(int)) + return -EINVAL; + cli->tcp_pars.ka.probes_present = true; + cli->tcp_pars.ka.probes_value = *(int *)val; + if (stream_cli_is_opened(cli)) + return stream_setsockopt_tcp_keepcnt(osmo_stream_cli_get_fd(cli), cli->tcp_pars.ka.probes_value); + break; + case OSMO_STREAM_CLI_PAR_TCP_SOCKOPT_USER_TIMEOUT: + if (!val || val_len != sizeof(unsigned int)) + return -EINVAL; + cli->tcp_pars.user_timeout_present = true; + cli->tcp_pars.user_timeout_value = *(int *)val; + if (stream_cli_is_opened(cli)) + return stream_setsockopt_tcp_user_timeout(osmo_stream_cli_get_fd(cli), cli->tcp_pars.user_timeout_value); + break; default: return -ENOENT; };
View file
libosmo-netif_1.6.1.tar.xz/src/stream_srv.c -> libosmo-netif_1.7.0.tar.xz/src/stream_srv.c
Changed
@@ -99,6 +99,7 @@ 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; + struct stream_tcp_pars tcp_pars; }; static int _setsockopt_nosigpipe(struct osmo_stream_srv_link *link, int new_fd) @@ -142,11 +143,25 @@ LOGSLNK(link, LOGL_INFO, "accept()ed new link from %s\n", osmo_sockaddr_to_str(&osa)); - if (link->proto == IPPROTO_SCTP) { + switch (link->proto) { + case IPPROTO_TCP: + ret = stream_tcp_keepalive_pars_apply(sock_fd, &link->tcp_pars.ka); + if (ret < 0) { + LOGSLNK(link, LOGL_ERROR, "failed applying TCP keep-alive pars on fd %d\n", sock_fd); + goto error_close_socket; + } + /* tcp_pars.user_timeout (sockopt TCP_USER_TIMEOUT) is + * inherited by accept() connected sockets automatically, + * no need to re-apply it here. */ + break; + case IPPROTO_SCTP: _setsockopt_nosigpipe(link, sock_fd); ret = stream_sctp_sock_activate_events(sock_fd); if (ret < 0) goto error_close_socket; + break; + default: + break; } break; default: @@ -366,10 +381,10 @@ return 0; } -/*! Set the socket type for the stream server link. +/*! Set the socket domain for the stream server link. * Any changes to this setting will only become active upon next (re)connect. * \paramin link Stream Server Link to modify - * \paramin type Socket Domain (like AF_UNSPEC (default for IP), AF_UNIX, AF_INET, ...) + * \paramin domain Socket Domain (like AF_UNSPEC (default for IP), AF_UNIX, AF_INET, ...) * \returns zero on success, negative on error. */ int osmo_stream_srv_link_set_domain(struct osmo_stream_srv_link *link, int domain) @@ -628,7 +643,7 @@ } /*! Set given parameter of stream_srv_link to given value. - * \paramin cli stream client on which to set parameter. + * \paramin link stream server link on which to set parameter. * \paramin par identifier of the parameter to be set. * \paramin val value of the parameter to be set. * \paramin val_len length of the parameter value. @@ -670,6 +685,43 @@ link->ma_pars.sctp.sockopt_initmsg.max_instreams_present = true; link->ma_pars.sctp.sockopt_initmsg.max_instreams_value = *(uint16_t *)val; break; + /* TCP keepalive params: */ + case OSMO_STREAM_SRV_LINK_PAR_TCP_SOCKOPT_KEEPALIVE: + if (!val || val_len != sizeof(uint8_t)) + return -EINVAL; + link->tcp_pars.ka.enable = !!*(uint8_t *)val; + /* Will be applied on accepted sockets */ + break; + case OSMO_STREAM_SRV_LINK_PAR_TCP_SOCKOPT_KEEPIDLE: + if (!val || val_len != sizeof(int)) + return -EINVAL; + link->tcp_pars.ka.time_present = true; + link->tcp_pars.ka.time_value = *(int *)val; + /* Will be applied on accepted sockets */ + break; + case OSMO_STREAM_SRV_LINK_PAR_TCP_SOCKOPT_KEEPINTVL: + if (!val || val_len != sizeof(int)) + return -EINVAL; + link->tcp_pars.ka.intvl_present = true; + link->tcp_pars.ka.intvl_value = *(int *)val; + /* Will be applied on accepted sockets */ + break; + case OSMO_STREAM_SRV_LINK_PAR_TCP_SOCKOPT_KEEPCNT: + if (!val || val_len != sizeof(int)) + return -EINVAL; + link->tcp_pars.ka.probes_present = true; + link->tcp_pars.ka.probes_value = *(int *)val; + /* Will be applied on accepted sockets */ + break; + case OSMO_STREAM_SRV_LINK_PAR_TCP_SOCKOPT_USER_TIMEOUT: + if (!val || val_len != sizeof(unsigned int)) + return -EINVAL; + link->tcp_pars.user_timeout_present = true; + link->tcp_pars.user_timeout_value = *(int *)val; + /* This value is inherited by accept() connected sockets (hence by child stream_srv): */ + if (osmo_stream_srv_link_is_opened(link)) + return stream_setsockopt_tcp_user_timeout(osmo_stream_srv_link_get_fd(link), + link->tcp_pars.user_timeout_value); default: return -ENOENT; }; @@ -691,6 +743,7 @@ }; 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 */ 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; @@ -916,7 +969,10 @@ * \paramin read_cb Call-back to call when the socket is readable * \paramin closed_cb Call-back to call when the connection is closed * \paramin data User data to save in the new Stream Server struct - * \returns Stream Server in case of success; NULL on error */ + * \returns Stream Server in case of success; NULL on error + * + * Note: In case of error, the caller is responsible for closing the fd. + */ 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, @@ -941,6 +997,8 @@ osmo_sock_get_name_buf(conn->sockname, sizeof(conn->sockname), fd); + conn->tx_queue_max_length = conn->srv->tx_queue_max_length; + if (osmo_fd_register(&conn->ofd) < 0) { LOGSSRV(conn, LOGL_ERROR, "could not register FD\n"); talloc_free(conn); @@ -959,7 +1017,10 @@ * \paramin link Stream Server Link to which we belong * \paramin fd system file descriptor of the new connection * \paramin data User data to save in the new Stream Server struct - * \returns Stream Server in case of success; NULL on error */ + * \returns Stream Server in case of success; NULL on error + * + * Note: In case of error, the caller is responsible for closing the fd. + */ struct osmo_stream_srv * osmo_stream_srv_create2(void *ctx, struct osmo_stream_srv_link *link, int fd, void *data) { @@ -991,7 +1052,8 @@ return NULL; } - osmo_iofd_set_txqueue_max_length(conn->iofd, conn->srv->tx_queue_max_length); + conn->tx_queue_max_length = conn->srv->tx_queue_max_length; + osmo_iofd_set_txqueue_max_length(conn->iofd, conn->tx_queue_max_length); if (conn->srv->msgb_alloc.set_by_user) osmo_iofd_set_alloc_info(conn->iofd, conn->srv->msgb_alloc.size, conn->srv->msgb_alloc.headroom); @@ -1011,9 +1073,31 @@ */ void osmo_stream_srv_set_name(struct osmo_stream_srv *conn, const char *name) { - osmo_talloc_replace_string(conn, &conn->name, name); + osmo_stream_srv_set_name_f(conn, "%s", name); +} + +/*! Set a name on the srv object using arguments like printf() (used during logging). + * \paramin srv stream_srv whose name is to be set + * \paramin name the name to be set on srv + */ +void osmo_stream_srv_set_name_f(struct osmo_stream_srv *conn, const char *fmt, ...) +{ + char *name = NULL; + + if (fmt) { + va_list ap; + + va_start(ap, fmt); + name = talloc_vasprintf(conn, fmt, ap); + va_end(ap); + } + + if (conn->name) + talloc_free((void *)conn->name); + conn->name = name; + if (conn->mode == OSMO_STREAM_MODE_OSMO_IO && conn->iofd) - osmo_iofd_set_name(conn->iofd, name); + osmo_iofd_set_name(conn->iofd, conn->name); } /*! Retrieve name previously set on the srv object (see osmo_stream_srv_set_name()). @@ -1153,9 +1237,24 @@ return conn->data; } +/*! Set the maximum length queue of the stream server connection. + * \paramin conn Stream Server 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 default queue size of a osmo_stream_srv is inherited during creation time from + * osmo_stream_srv_link. */ +int osmo_stream_srv_set_tx_queue_max_length(struct osmo_stream_srv *conn, unsigned int size) +{ + conn->tx_queue_max_length = size;
View file
libosmo-netif_1.7.0.tar.xz/src/twjit.c
Added
@@ -0,0 +1,706 @@ +/* + * Themyscira Wireless RTP jitter buffer implementation: main body. + * + * This code was contributed to Osmocom Cellular Network Infrastructure + * project by Mother Mychaela N. Falconia of Themyscira Wireless. + * Mother Mychaela's contributions are NOT subject to copyright: + * no rights reserved, all rights relinquished. + */ + +#include <stdint.h> +#include <stdbool.h> +#include <string.h> +#include <errno.h> +#include <arpa/inet.h> /* for network byte order functions */ + +#include <osmocom/core/linuxlist.h> +#include <osmocom/core/msgb.h> +#include <osmocom/core/talloc.h> +#include <osmocom/core/timer.h> +#include <osmocom/core/utils.h> + +#include <osmocom/netif/twjit.h> +#include <osmocom/netif/twjit_private.h> +#include <osmocom/netif/rtp.h> + +/*! \addgroup twjit + * @{ + */ + +/*! \cond private */ + +/*! Each twjit instance has two sub-buffers; each subbuf is a queue of + * received RTP packets that have the same SSRC and whose timestamps + * increment in the expected cadence, with each ts delta being an + * integral multiple of the samples-per-quantum constant. + * See document section 2.3.2. + */ +struct twjit_subbuf { + /*! SSRC of the stream portion captured in this subbuf */ + uint32_t ssrc; + /*! Current timestamp at the head of the queue */ + uint32_t head_ts; + /*! Queue of packets held by this subbuf */ + struct llist_head queue; + /*! Current depth as defined in document section 2.3.2 */ + uint32_t depth; + /*! Time delta in ms between arrival times of the two most recently + * received packets, used only in starting state */ + uint32_t delta_ms; + /*! thinning mechanism: countdown before next quantum deletion */ + uint16_t drop_int_count; +}; + +/*! Each twjit instance is in one of 4 fundamental states at any moment, + * as enumerated here. See document section 2.3.1 for state transition + * diagram. + */ +enum twjit_state { + /*! completely empty: neither subbuf is valid */ + TWJIT_STATE_EMPTY, + /*! one subbuf is non-empty, but it hasn't started flowing out yet */ + TWJIT_STATE_HUNT, + /*! one subbuf is both flowing out and accepting new packets */ + TWJIT_STATE_FLOWING, + /*! one subbuf is flowing out while another receives new packets */ + TWJIT_STATE_HANDOVER, +}; + +/*! Main structure for one instance of twjit */ +struct osmo_twjit { + /*! twjit tuning config, can be changed with osmo_twjit_set_config() */ + struct osmo_twjit_config config; + /*! count of RTP timestamp units per quantum */ + uint32_t ts_quantum; + /*! quanta per second, used to scale max_future_sec */ + uint16_t quanta_per_sec; + /* scaling factors for time delta conversions */ + /*! RTP timestamp units per millisecond */ + uint16_t ts_units_per_ms; + /*! RTP timestamp units per second */ + uint32_t ts_units_per_sec; + /*! divisor to go from nanoseconds to RTP timestamp units */ + uint32_t ns_to_ts_units; + /*! current fundamental state of this twjit instance */ + enum twjit_state state; + /*! the two sub-buffers */ + struct twjit_subbuf sb2; + /*! current subbuf being read, 0 or 1 */ + uint8_t read_sb; + /*! current subbuf being written, 0 or 1 */ + uint8_t write_sb; + /*! RTP timestamp of the most recently received packet */ + uint32_t last_ts; + /*! RTP sequence number of the most recently received packet */ + uint16_t last_seq; + /*! Have we received at least one packet? This bool serves as + * the validity flag for last_ts, last_ts and rr_info. */ + bool got_first_packet; + /*! CLOCK_MONOTONIC time of last packet arrival */ + struct timespec last_arrival; + /*! Delta between the two most recent RTP packet arrival times, + * converted to RTP timestamp units. */ + uint32_t last_arrival_delta; + /*! analytics for RTCP RR, also remembers last SSRC */ + struct osmo_twjit_rr_info rr_info; + /*! stats over lifetime of this instance */ + struct osmo_twjit_stats stats; +}; + +/*! \endcond */ + +/* create and destroy functions */ + +/*! Create a twjit instance + * + * \paramin ctx Parent talloc context under which struct osmo_twjit + * should be allocated. + * \paramin clock_khz RTP clock rate in kHz, i.e., number of RTP timestamp + * units per millisecond. The most common value is 8. + * \paramin quantum_ms Duration of a single quantum (unit of speech or data + * carried in one RTP packet) in milliseconds. The most common value is 20. + * \paramin config Set of tunable configuration parameters to be used. + * \returns pointer to the newly created twjit instance, or NULL on errors. + * + * In contrast to the original twrtp-proto version, this version of + * osmo_twjit_create() copies the config structure, thus the application + * is not required to maintain it in the originally passed memory. + */ +struct osmo_twjit *osmo_twjit_create(void *ctx, uint16_t clock_khz, + uint16_t quantum_ms, + const struct osmo_twjit_config *config) +{ + struct osmo_twjit *twjit; + + /* Note to developers comparing this function against its twrtp-native + * counterpart: the original version performed a validity check on + * the passed config structure at this point, but that check has been + * omitted in this version. Rationale: since the config structure + * has been made opaque, it is now impossible for applications + * to pass in a config structure that has not been constructed + * by the library itself and thus known to be valid. */ + + twjit = talloc_zero(ctx, struct osmo_twjit); + if (!twjit) + return NULL; + + memcpy(&twjit->config, config, sizeof(struct osmo_twjit_config)); + twjit->state = TWJIT_STATE_EMPTY; + INIT_LLIST_HEAD(&twjit->sb0.queue); + INIT_LLIST_HEAD(&twjit->sb1.queue); + twjit->ts_quantum = (uint32_t) quantum_ms * clock_khz; + twjit->quanta_per_sec = 1000 / quantum_ms; + twjit->ts_units_per_ms = clock_khz; + twjit->ts_units_per_sec = (uint32_t) clock_khz * 1000; + twjit->ns_to_ts_units = 1000000 / clock_khz; + + return twjit; +} + +/*! Destroy a twjit instance + * + * \paramin twjit Instance to be freed + * + * Memory freed by this function includes not only the instance structure, + * but also any msgbs that are held by this instance. + */ +void osmo_twjit_destroy(struct osmo_twjit *twjit) +{ + if (!twjit) + return; + msgb_queue_free(&twjit->sb0.queue); + msgb_queue_free(&twjit->sb1.queue); + talloc_free(twjit); +} + +/*! Change twjit config parameters + * + * \paramin twjit Instance to be reconfigured + * \paramin config Structure with new tuning parameters to be used + * \returns 0 if successful, negative on errors + * + * The intended use for this API is applications that can use one of + * several different twjit config profiles depending on various + * conditions, but might not know the correct choice of profile + * at the time they create the twjit instance - or more likely, + * the containing twrtp instance. + */ +int osmo_twjit_set_config(struct osmo_twjit *twjit, + const struct osmo_twjit_config *config) +{ + /* Note to developers comparing this function against its twrtp-native + * counterpart: the original version performed a validity check on + * the passed config structure at this point, but that check has been + * omitted in this version. Rationale: since the config structure + * has been made opaque, it is now impossible for applications + * to pass in a config structure that has not been constructed + * by the library itself and thus known to be valid. */ + + memcpy(&twjit->config, config, sizeof(struct osmo_twjit_config));
View file
libosmo-netif_1.7.0.tar.xz/src/twjit_conf.c
Added
@@ -0,0 +1,345 @@ +/* + * Themyscira Wireless RTP jitter buffer implementation: + * configuration by vty or otherwise. + * + * This code was contributed to Osmocom Cellular Network Infrastructure + * project by Mother Mychaela N. Falconia of Themyscira Wireless. + * Mother Mychaela's contributions are NOT subject to copyright: + * no rights reserved, all rights relinquished. + */ + +#include <stdint.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include <osmocom/core/talloc.h> +#include <osmocom/core/utils.h> +#include <osmocom/vty/vty.h> +#include <osmocom/vty/command.h> + +#include <osmocom/netif/twjit.h> +#include <osmocom/netif/twjit_private.h> + +/*! \addgroup twjit + * @{ + */ + +/*! Allocate and initialize twjit config structure + * + * \paramin ctx Parent talloc context under which struct osmo_twjit_config + * should be allocated. + * \returns pointer to the newly created twjit config instance, or NULL on + * errors. + * + * A typical application will have a struct osmo_twjit_config somewhere + * in the application config data structures, editable via vty. + * More complex applications may even have several such twjit config + * structures, to be used in different contexts such as GSM vs PSTN. + * However, in the present Osmocom-integrated version of twjit, this config + * structure has been made opaque for ABI reasons - hence config instances + * now have to be allocated by the library, rather than merely initialized + * in content. + */ +struct osmo_twjit_config *osmo_twjit_config_alloc(void *ctx) +{ + struct osmo_twjit_config *config; + + config = talloc_zero(ctx, struct osmo_twjit_config); + if (!config) + return NULL; + + /* Initialize defaults, corresponding to twna_twjit_config_init() + * in twrtp-native version. */ + + /* While the theoretical minimum starting fill level is 1, the + * practically useful minimum (achieving lowest latency, but not + * incurring underruns in normal healthy operation) is 2 for typical + * network configurations that combine elements with "perfect" 20 ms + * timing (T1/E1 interfaces, external IP-PSTN links, software + * transcoders timed by system clock etc) and GSM-to-IP OsmoBTS + * whose 20 ms timing contains the small inherent jitter of TDMA. */ + config->bd_start = 2; + + /* The high water mark setting determines when the standing queue + * thinning mechanism kicks in. A standing queue that is longer + * than the starting fill level will occur when the flow starts + * during a network latency spike, but then the network latency + * goes down. If this setting is too high, deep standing queues + * will persist, adding needless latency to speech or CSD. + * If this setting is too low, the thinning mechanism will be + * too invasive, needlessly and perhaps frequently deleting a quantum + * of speech or data from the stream and incurring a phase shift. + * Starting fill level plus 2 seems like a good default. */ + config->bd_hiwat = 4; + + /* When the standing queue thinning mechanism does kick in, + * it drops every Nth packet, where N is the thinning interval. + * Given that this mechanism forcibly deletes a quantum of speech + * or data from the stream, these induced disruptions should be + * spaced out, and the managing operator should also keep in mind + * that the incurred phase shift may be a problem for some + * applications, particularly CSD. Our current default is + * a prime number, reducing the probability that the thinning + * mechanism will interfere badly with intrinsic features of the + * stream being thinned. 17 quantum units at 20 ms per quantum + * is 340 ms, which should be sufficiently long spacing to make + * speech quantum deletions tolerable. */ + config->thinning_int = 17; + + /* Guard against time traveler packets, + * see document section 2.3.4.3. */ + config->max_future_sec = 10; + + return config; +} + +/*! Free a twjit config instance + * + * \paramin conf Instance to be freed + */ +void osmo_twjit_config_free(struct osmo_twjit_config *conf) +{ + if (!conf) + return; + talloc_free(conf); +} + +/*! Write out vty form of twjit config structure + * + * \paramin vty The vty instance to which vty_out() calls should be made + * \paramin conf The config structure to write out + * \paramin prefix Additional indent prefix to be prepended to each output + * line, defaults to "" if NULL + * \returns CMD_SUCCESS for vty system + */ +int osmo_twjit_config_write(struct vty *vty, + const struct osmo_twjit_config *conf, + const char *prefix) +{ + if (!prefix) + prefix = ""; + vty_out(vty, "%s buffer-depth %u %u%s", prefix, conf->bd_start, + conf->bd_hiwat, VTY_NEWLINE); + vty_out(vty, "%s thinning-interval %u%s", prefix, conf->thinning_int, + VTY_NEWLINE); + vty_out(vty, "%s max-future-sec %u%s", prefix, conf->max_future_sec, + VTY_NEWLINE); + + if (conf->start_min_delta) { + vty_out(vty, "%s start-min-delta %u%s", prefix, + conf->start_min_delta, VTY_NEWLINE); + } + if (conf->start_max_delta) { + vty_out(vty, "%s start-max-delta %u%s", prefix, + conf->start_max_delta, VTY_NEWLINE); + } + + vty_out(vty, "%s marker-handling %s%s", prefix, + conf->handover_on_marker ? "handover" : "ignore", VTY_NEWLINE); + + return CMD_SUCCESS; +} + +DEFUN(cfg_buffer_depth, cfg_buffer_depth_cmd, + "buffer-depth <1-65535> <1-65535>", + "Buffer depth configuration\n" + "Minimum fill required to start flow\n" + "High water mark fill level\n") +{ + struct osmo_twjit_config *conf = vty->index; + unsigned bd_start = atoi(argv0); + unsigned bd_hiwat = atoi(argv1); + + if (bd_hiwat < bd_start) { + vty_out(vty, "%% Error: high water mark cannot be less than starting level%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + conf->bd_start = bd_start; + conf->bd_hiwat = bd_hiwat; + + return CMD_SUCCESS; +} + +DEFUN(cfg_thinning, cfg_thinning_cmd, + "thinning-interval <2-65535>", + "Standing queue thinning configuration\n" + "Drop every Nth packet\n") +{ + struct osmo_twjit_config *conf = vty->index; + conf->thinning_int = atoi(argv0); + return CMD_SUCCESS; +} + +DEFUN(cfg_max_future, cfg_max_future_cmd, + "max-future-sec <1-65535>", + "Guard against time traveler packets\n" + "Maximum permissible number of seconds into the future\n") +{ + struct osmo_twjit_config *conf = vty->index; + conf->max_future_sec = atoi(argv0); + return CMD_SUCCESS; +} + +DEFUN(cfg_start_min_delta, cfg_start_min_delta_cmd, + "start-min-delta <1-65535>", + "Minimum required delta in time-of-arrival to start flow\n" + "Time delta value in ms\n") +{ + struct osmo_twjit_config *conf = vty->index; + conf->start_min_delta = atoi(argv0); + return CMD_SUCCESS; +} + +DEFUN(cfg_no_start_min_delta, cfg_no_start_min_delta_cmd, + "no start-min-delta", + NO_STR "Minimum required delta in time-of-arrival to start flow\n")
View file
libosmo-netif_1.7.0.tar.xz/src/twrtp.c
Added
@@ -0,0 +1,1273 @@ +/* + * Themyscira Wireless RTP endpoint implementation: main body. + * + * This code was contributed to Osmocom Cellular Network Infrastructure + * project by Mother Mychaela N. Falconia of Themyscira Wireless. + * Mother Mychaela's contributions are NOT subject to copyright: + * no rights reserved, all rights relinquished. + */ + +#include <stdint.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <arpa/inet.h> /* for network byte order functions */ + +#include <osmocom/core/msgb.h> +#include <osmocom/core/osmo_io.h> +#include <osmocom/core/socket.h> +#include <osmocom/core/talloc.h> +#include <osmocom/core/timer.h> +#include <osmocom/core/utils.h> + +#include <osmocom/netif/twrtp.h> +#include <osmocom/netif/twjit.h> +#include <osmocom/netif/rtp.h> +#include <osmocom/netif/rtcp_defs.h> + +/*! \addgroup twrtp + * @{ + */ + +/*! \cond private */ + +/*! This structure captures info that has been extracted from + * received and decoded RTCP SR and/or RR packets. + * See twrtp guide document section 5.2. + */ +struct rtcp_rx_state { + /* sender info extracted from SR packets */ + /*! sender SSRC from the most recently received SR packet */ + uint32_t sr_ssrc; + /*! NTP timestamp from SR: lower 16 bits of seconds word */ + uint16_t sr_ntp_sec; + /*! NTP timestamp from SR: upper 16 bits of fraction word */ + uint16_t sr_ntp_fract; + /*! CLOCK_MONOTONIC time-of-arrival of most recently received SR */ + struct timespec sr_rx_time; + /* info extracted from reception report blocks in SR/RR packets */ + /*! lost packets word from most recently received RR block */ + uint32_t rr_lost_word; + /*! interarrival jitter from most recently received RR block */ + uint32_t rr_jitter; + /*! highest value received in the interarrival jitter word */ + uint32_t rr_jitter_max; + /* bool flags at the end for structure packing optimization */ + /*! received at least one SR packet */ + bool got_sr; + /*! received at least one RR block */ + bool got_rr; +}; + +/*! This structure holds state for emission of RTCP reception report + * blocks based on RR info from twjit. This additional state element + * (beyond struct osmo_twjit_rr_info) is needed in order to compute + * the "fraction lost" field, which is based on the delta since + * the last emitted report and thus requires memory of previous + * "received" and "expected" counts. + */ +struct rtcp_tx_state { + uint32_t last_received; + uint32_t last_expected; +}; + +/*! Main structure for one instance of twrtp */ +struct osmo_twrtp { + /*! UDP socket for RTP data packets */ + struct osmo_io_fd *iofd_rtp; + /*! UDP socket for RTCP */ + struct osmo_io_fd *iofd_rtcp; + /*! remote IP:port address for RTP data packets */ + struct osmo_sockaddr rtp_remote; + /*! remote IP:port address for RTCP */ + struct osmo_sockaddr rtcp_remote; + /*! count of RTP timestamp units per quantum */ + uint32_t ts_quantum; + /* scaling factors for RTP Tx timestamp computation */ + /*! RTP timestamp units per second */ + uint32_t ts_units_per_sec; + /*! divisor to go from nanoseconds to RTP timestamp units */ + uint32_t ns_to_ts_units; + /* RTP Rx path: twjit and raw options */ + /*! twjit instance owned by the present twrtp instance */ + struct osmo_twjit *twjit; + /*! registered callback for unbuffered/non-delayed Rx path */ + osmo_twrtp_raw_rx_cb raw_rx_cb; + /*! user data for \ref raw_rx_cb */ + void *raw_rx_cb_data; + /*! RTP Tx state */ + struct { + /*! random SSRC chosen for RTP output we generate */ + uint32_t ssrc; + /*! output stream current timestamp */ + uint32_t ts; + /*! random addend for RTP timestamps we emit */ + uint32_t ts_addend; + /*! output stream current sequence number */ + uint16_t seq; + /*! we started output with osmo_twrtp_tx_quantum() */ + bool started; + /*! output timestamp needs to be reset discontinuously */ + bool restart; + } tx; + /* RTCP info */ + /*! RTCP Rx state */ + struct rtcp_rx_state rtcp_rx; + /*! RTCP Tx state */ + struct rtcp_tx_state rtcp_tx; + /*! buffer holding SDES packet of RFC 3550 section 6.5 */ + uint8_t *sdes_buf; + /*! length (in bytes) of SDES packet in \ref sdes_buf */ + uint16_t sdes_len; + /*! automatically emit RTCP SR after this many RTP data packets */ + uint16_t auto_rtcp_interval; + /*! current count within \ref auto_rtcp_interval */ + uint16_t auto_rtcp_count; + /*! twrtp-level stats over lifetime of this instance */ + struct osmo_twrtp_stats stats; + /* bool flags at the end for structure packing optimization */ + /*! \ref rtp_remote and \ref rtcp_remote are valid */ + bool remote_set; + /*! received RTP packets are to be fed to our subordinate twjit */ + bool twjit_rx_enable; +}; + +/* We need to know maximum expected sizes of RTP and RTCP Rx packets + * for osmo_io msgb allocation. For RTP, the largest packet size in + * 3GPP and IP-PSTN applications is 176 bytes: 12 bytes of RTP header + * plus 160 bytes of payload for 20 ms of uncompressed G.711 audio + * or CSData. Of course there may be other applications that use + * larger RTP packets, in which case we may have to add an API function + * that overrides our default msgb alloc size setting - but let's + * cross that bridge if and when we actually have such users. + * + * In case of RTCP, we fully process all received packets inside + * the present library, hence we can set osmo_io msgb alloc size + * based on what our RTCP Rx code can parse and make use of. Any + * additional RTCP Rx data, such as very long SDES strings, will + * simply be truncated at osmo_io level - but the subsequent parsing + * code will never get to those bits anyway. + */ + +#define MAX_RTP_RX_PACKET (sizeof(struct rtp_hdr) + 160) +#define MAX_RTCP_RX_PACKET (sizeof(struct rtcp_sr_rr_hdr) + \ + sizeof(struct rtcp_sr_block) + \ + sizeof(struct rtcp_rr_block) * 31) + +/* RTCP includes NTP timestamps, hence we need to convert from Unix-style + * CLOCK_REALTIME into NTP time format. */ + +#define NTP_EPOCH_MJD 15020 +#define UNIX_EPOCH_MJD 40587 + +#define NTP_UNIX_EPOCH_DIFF ((UNIX_EPOCH_MJD-NTP_EPOCH_MJD) * 86400UL) +#define TWO_TO_32_DOUBLE 4294967296.0 + +/* forward declarations for internal functions */ + +static void rtp_rx_cb(struct osmo_io_fd *iofd, int res, struct msgb *msg, + const struct osmo_sockaddr *saddr); +static void rtcp_rx_cb(struct osmo_io_fd *iofd, int res, struct msgb *msg, + const struct osmo_sockaddr *saddr); +static int send_rtcp_sr_rr(struct osmo_twrtp *endp, bool send_sr, + const struct timespec *utc, uint32_t rtp_ts); + +static const struct osmo_io_ops twrtp_iops_rtp = { + .recvfrom_cb = rtp_rx_cb, +}; + +static const struct osmo_io_ops twrtp_iops_rtcp = { + .recvfrom_cb = rtcp_rx_cb, +}; + +/*! \endcond */ + +/*! Create a twrtp endpoint + * + * \paramin ctx Parent talloc context under which struct osmo_twrtp + * should be allocated. + * \paramin clock_khz RTP clock rate in kHz, i.e., number of RTP timestamp + * units per millisecond. The most common value is 8. + * \paramin quantum_ms Duration of a single quantum (unit of speech or data + * carried in one RTP packet) in milliseconds. The most common value is 20. + * \paramin random_ts_seq For RTP packets we generate and emit, randomize + * not only SSRC for this session, but also the starting timestamp and the + * starting sequence number. Pass true to satisfy the SHOULD directive in + * RFC 3550 and for feature parity with ortp, or false for ease of debugging. + * \paramin twjit_config If this RTP endpoint is to be equipped with twjit,
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
.