Projects
osmocom:latest
libosmo-netif
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 6
View file
libosmo-netif.spec
Deleted
@@ -1,88 +0,0 @@ -# -# 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.4.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.4.0.tar.xz -Source1: rpmlintrc -BuildRequires: automake -BuildRequires: libtool >= 2 -BuildRequires: lksctp-tools-devel -BuildRequires: pkgconfig >= 0.20 -BuildRequires: pkgconfig(libosmocore) >= 1.9.0 -BuildRequires: pkgconfig(libosmogsm) >= 1.9.0 -BuildRequires: pkgconfig(libosmocodec) >= 1.9.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.4.0.tar.xz/contrib/libosmo-netif.spec.in
Deleted
@@ -1,87 +0,0 @@ -# -# 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.9.0 -BuildRequires: pkgconfig(libosmogsm) >= 1.9.0 -BuildRequires: pkgconfig(libosmocodec) >= 1.9.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.4.0.dsc -> libosmo-netif_1.5.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.4.0 +Version: 1.5.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.9.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.10.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: - 6000513b1c6ecc605ffb1741089a304ceb7f406a 187720 libosmo-netif_1.4.0.tar.xz + 56f5f5a505ecd2d6112143c7d222555b5baa9f49 194716 libosmo-netif_1.5.0.tar.xz Checksums-Sha256: - 24eed47dc650822cc84fae35ace4b18b837c8e82427e788b271e96469cdfe4d9 187720 libosmo-netif_1.4.0.tar.xz + 84b90facdbe135354a4edcf6accdd5444149577f61be34956d50e71aec21be4a 194716 libosmo-netif_1.5.0.tar.xz Files: - 53c29e93fce3fd8cddefe8c745988dfd 187720 libosmo-netif_1.4.0.tar.xz + 8ac0328d19fa24ad80eca62d000bb77c 194716 libosmo-netif_1.5.0.tar.xz
View file
libosmo-netif_1.4.0.tar.xz/.tarball-version -> libosmo-netif_1.5.0.tar.xz/.tarball-version
Changed
@@ -1 +1 @@ -1.4.0 +1.5.0
View file
libosmo-netif_1.4.0.tar.xz/Doxyfile.in -> libosmo-netif_1.5.0.tar.xz/Doxyfile.in
Changed
@@ -150,7 +150,7 @@ # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) -JAVADOC_AUTOBRIEF = NO +JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style @@ -158,7 +158,7 @@ # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) -QT_AUTOBRIEF = NO +QT_AUTOBRIEF = YES # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// @@ -328,13 +328,13 @@ # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. -EXTRACT_STATIC = YES +EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. -EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_CLASSES = NO # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in
View file
libosmo-netif_1.4.0.tar.xz/Makefile.am -> libosmo-netif_1.5.0.tar.xz/Makefile.am
Changed
@@ -9,8 +9,8 @@ EXTRA_DIST = \ .version \ README.md \ - contrib/libosmo-netif.spec.in \ debian \ + git-version-gen \ $(NULL) @RELMAKE@ @@ -29,7 +29,7 @@ $(html_DATA): $(top_builddir)/doc/html/index.html cd $(top_builddir)/doc && tar cf html.tar html -$(top_builddir)/doc/html/index.html: $(SOURCES) Doxyfile +$(top_builddir)/doc/html/index.html: $(top_srcdir)/src/*.c $(top_srcdir)/include/osmocom/netif/*.h Doxyfile @rm -rf doc mkdir -p doc $(DOXYGEN) Doxyfile
View file
libosmo-netif_1.4.0.tar.xz/README.md -> libosmo-netif_1.5.0.tar.xz/README.md
Changed
@@ -45,7 +45,7 @@ Our coding standards are described at <https://osmocom.org/projects/cellular-infrastructure/wiki/Coding_standards> -We us a gerrit based patch submission/review process for managing +We use a Gerrit based patch submission/review process for managing contributions. Please see <https://osmocom.org/projects/cellular-infrastructure/wiki/Gerrit> for more details
View file
libosmo-netif_1.4.0.tar.xz/TODO-RELEASE -> libosmo-netif_1.5.0.tar.xz/TODO-RELEASE
Changed
@@ -1,9 +1,9 @@ # When cleaning up this file: bump API version in corresponding Makefile.am and rename corresponding debian/lib*.install -# according to https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info -# In short: +# according to https://osmocom.org/projects/cellular-infrastructure/wiki/Make_a_new_release +# In short: https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info # LIBVERSION=c:r:a # If the library source code has changed at all since the last update, then increment revision: c:r + 1:a. -# If any interfaces have been added, removed, or changed since the last update: c + 1:0:0. +# If any interfaces have been added, removed, or changed since the last update: c + 1:0:a. # If any interfaces have been added since the last public release: c:r:a + 1. # If any interfaces have been removed or changed since the last public release: c:r:0. -#library what description / commit summary line +#library what description / commit summary line
View file
libosmo-netif_1.4.0.tar.xz/configure.ac -> libosmo-netif_1.5.0.tar.xz/configure.ac
Changed
@@ -89,9 +89,9 @@ dnl Generate the output AM_CONFIG_HEADER(config.h) -PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.9.0) -PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.9.0) -PKG_CHECK_MODULES(LIBOSMOCODEC, libosmocodec >= 1.9.0) +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( @@ -148,5 +148,4 @@ utils/Makefile tests/Makefile Doxyfile - Makefile - contrib/libosmo-netif.spec) + Makefile)
View file
libosmo-netif_1.4.0.tar.xz/debian/changelog -> libosmo-netif_1.5.0.tar.xz/debian/changelog
Changed
@@ -1,3 +1,78 @@ +libosmo-netif (1.5.0) unstable; urgency=medium + + arehbein + * ipa: Don't break strict aliasing rule + * stream_srv: Set io_fd pointer to NULL after freeing + * stream_test: Disable nagling + * stream: Add client-side (segmentation) support for IPA + * stream (test): Fix Coverity CID 323456 + * stream: Add and use helper function osmo_ipa_push_headers() + * stream_test: Improve mem mgmt, fix connection mgmt + * stream_test: Fix memleaks + + Daniel Willmann + * stream_srv: Fix connection error handling + * stream_srv: Make osmo_stream_srv_clear_tx_queue() aware of osmo_io + * stream_test: Increase log level to debug + + Harald Welte + * stream_srv: osmo_stream_srv_get_ofd() works only in OSMO_FD mode + * Introduce generic osmo_stream_{cli,srv}_get_fd() API + * examples/stream-*: Support SCTP when called with "-s" argument + * examples/stream-{server,client}: Generate talloc report on SIGUSR1 + * stream_{cli,srv}: Add support for SCTP in OSMO_IO mode + * osmo_io: make use of osmo_iofd_get_ioops() + * osmo_stream_cli_send(): Drop data if client is not connected yet + * Makefile.am: Fix dependency: rebuild doxygen on src/include changes + * docs: Enable AUTOBRIEF feauture in doxygen + * docs: Use \defgroup and avoid repeated boilerplate text + * docs: Don't export documentation about static (internal) functions + * Ensure osmo_stream_{cli,srv}_recv() is used only in osmo_fd mode + * docs: More verbose stream_{cli,srv} API documentation/manual + * docs: Don't export internal structs declared in src files + * docs: Split Stream Server and Stream Client into separate groups + * docs: jibuf: Prevent internal #defines being documented + * Makefile.am: Remove $(SOURCES) which is not defined anywhere + * introduce osmo_stream_cli_get_iofd() API + * docs: various osmux API documentation updates + * docs: Improve/clean-up doxygen for datagram.ch + + Pau Espin Pedrol + * stream_cli: Fix opening sctp client socket if no local address set + * stream: Add missing osmo_stream_srv_link_get_fd() API + * netif: sctp.h: Introduce value_string for enum sctp_spinfo_state + * netif: sctp.h: Introduce value_string for enum sctp_sstat_state + * stream_cli: osmo_stream_cli_get_sockname() now returns the full set of addresses + * stream_cli: Introduce API osmo_stream_srv_get_sockname() + * stream_srv_link: osmo_stream_srv_link_get_sockname() now returns the full set of addresses + * osmo_prim_srv_send: assert prim_srv is not NULL + * stream: Add osmo_stream_*_get_name() APIs + * prim: Introduce osmo_prim_srv{_link}_set_name APIs + * stream_srv: Fix retrieve of srv_link sockname for AF_UNIX sockets + * examples/ipa-stream-client: Fix memleaks in read_cb() + * stream_cli: Remove unused write_cb field + * stream: Define types for each API callback + * tests/stream: Fix missing msgb_free() + * stream_{cli,srv}: Add 'res' param to read_cb2 + + Vadim Yanitskiy + * build: include git-version-gen into the release tarball + * osmo_stream_cli_write(): fix double-free of msgb + * README.md: cosmetic: fix a typo + + Andreas Eversberg + * examples/stream-*: Add options, to set local/remote peer + * stream_{cli,srv}: Fix memory leak, if sending a message fails + * stream_{cli,srv}: Free received messages when not forwarded + * stream_cli: Correctly setup and free osmo_io client instance + * stream_{client,server} example: Cleanup on exit + * stream_cli.c: Handle read / recvfrom error and close connection + + Oliver Smith + * contrib: remove rpm spec file + + -- Oliver Smith <osmith@sysmocom.de> Wed, 24 Jul 2024 11:58:42 +0200 + libosmo-netif (1.4.0) unstable; urgency=medium Max
View file
libosmo-netif_1.4.0.tar.xz/debian/control -> libosmo-netif_1.5.0.tar.xz/debian/control
Changed
@@ -11,7 +11,7 @@ libdpkg-perl, git, doxygen, - libosmocore-dev (>= 1.9.0), + libosmocore-dev (>= 1.10.0), pkg-config, libpcap0.8-dev, libsctp-dev
View file
libosmo-netif_1.4.0.tar.xz/examples/ipa-stream-client.c -> libosmo-netif_1.5.0.tar.xz/examples/ipa-stream-client.c
Changed
@@ -93,9 +93,7 @@ msg_sent->num = i; llist_add(&msg_sent->head, &msg_sent_list); - ipa_prepend_header_ext(msg, IPAC_PROTO_EXT_MGCP); - osmo_ipa_msg_push_header(msg, IPAC_PROTO_OSMO); - + osmo_ipa_msg_push_headers(msg, osmo_ipa_msgb_cb_proto(msg), osmo_ipa_msgb_cb_proto_ext(msg)); osmo_stream_cli_send(conn, msg); LOGP(DIPATEST, LOGL_DEBUG, "enqueueing msg %d of " @@ -104,19 +102,26 @@ return 0; } -static int read_cb(struct osmo_stream_cli *conn, struct msgb *msg) +static int read_cb(struct osmo_stream_cli *conn, int res, struct msgb *msg) { - LOGP(DIPATEST, LOGL_DEBUG, "received message from stream (len=%d)\n", msgb_length(msg)); + int num; + struct msg_sent *cur, *tmp, *found = NULL; + + LOGP(DIPATEST, LOGL_DEBUG, "received message from stream (payload len=%d)\n", msgb_length(msg)); + + if (res <= 0) { + LOGP(DIPATEST, LOGL_ERROR, "Event with no data! %d\n", res); + msgb_free(msg); + return 0; + } if (osmo_ipa_process_msg(msg) < 0) { LOGP(DIPATEST, LOGL_ERROR, "bad IPA message\n"); + msgb_free(msg); return 0; } - int num; - struct msg_sent *cur, *tmp, *found = NULL; - - num = ntohl(*((int *)(msg->data + sizeof(struct ipa_head) + sizeof(struct ipa_head_ext)))); + num = osmo_load32be(msg->data); LOGP(DLINP, LOGL_DEBUG, "received msg number %d\n", num); llist_for_each_entry_safe(cur, tmp, &msg_sent_list, head) { @@ -139,6 +144,7 @@ LOGP(DLINP, LOGL_ERROR, "message %d not found!\n", num); } + msgb_free(msg); return 0; } @@ -184,6 +190,8 @@ exit(EXIT_FAILURE); } + osmo_stream_cli_set_segmentation_cb(conn, osmo_ipa_segmentation_cb); + LOGP(DIPATEST, LOGL_NOTICE, "Entering main loop\n"); while(1) {
View file
libosmo-netif_1.4.0.tar.xz/examples/ipa-stream-server.c -> libosmo-netif_1.5.0.tar.xz/examples/ipa-stream-server.c
Changed
@@ -47,10 +47,18 @@ exit(EXIT_SUCCESS); } -int read_cb(struct osmo_stream_srv *conn, struct msgb *msg) +int read_cb(struct osmo_stream_srv *conn, int res, struct msgb *msg) { - LOGP(DSTREAMTEST, LOGL_DEBUG, "received message from stream (len=%d)\n", msgb_length(msg)); + if (res <= 0) { + LOGP(DSTREAMTEST, LOGL_ERROR, "cannot receive message (%d)\n", res); + msgb_free(msg); + osmo_stream_srv_destroy(conn); + return -EBADF; + } + LOGP(DSTREAMTEST, LOGL_DEBUG, "received message from stream (payload len=%d)\n", msgb_length(msg)); + + osmo_ipa_msg_push_headers(msg, osmo_ipa_msgb_cb_proto(msg), osmo_ipa_msgb_cb_proto_ext(msg)); osmo_stream_srv_send(conn, msg); return 0; }
View file
libosmo-netif_1.4.0.tar.xz/examples/stream-client.c -> libosmo-netif_1.5.0.tar.xz/examples/stream-client.c
Changed
@@ -3,6 +3,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <netinet/in.h> #include <osmocom/core/select.h> #include <osmocom/core/talloc.h> @@ -31,10 +32,13 @@ static struct osmo_stream_cli *conn; +static bool quit = false; + void sighandler(int foo) { LOGP(DSTREAMTEST, LOGL_NOTICE, "closing stream.\n"); - exit(EXIT_SUCCESS); + quit = true; + signal(SIGINT, SIG_DFL); } static int connect_cb(struct osmo_stream_cli *conn) @@ -50,10 +54,17 @@ return 0; } -static int read_cb(struct osmo_stream_cli *conn, struct msgb *msg) +static int read_cb(struct osmo_stream_cli *conn, int res, struct msgb *msg) { LOGP(DSTREAMTEST, LOGL_NOTICE, "receiving message from stream... "); + if (res < 0) { + LOGPC(DSTREAMTEST, LOGL_ERROR, "cannot receive message (res = %d)\n", res); + msgb_free(msg); + return 0; + } + + LOGPC(DSTREAMTEST, LOGL_NOTICE, "got %d bytes: %s\n", msg->len, msgb_hexdump(msg)); msgb_free(msg); @@ -82,17 +93,43 @@ ptr = msgb_put(msg, ret); memcpy(ptr, buf, ret); - osmo_stream_cli_send(conn, msg); + LOGP(DSTREAMTEST, LOGL_NOTICE, "sending %d bytes message: %s\n", msg->len, msgb_hexdump(msg)); - LOGP(DSTREAMTEST, LOGL_NOTICE, "sent %d bytes message: %s\n", msg->len, msgb_hexdump(msg)); + osmo_stream_cli_send(conn, msg); return 0; } -int main(void) +static void signal_handler(int signum) +{ + switch (signum) { + case SIGUSR1: + talloc_report_full(tall_test, stdout); + break; + } +} + +int main(int argc, char **argv) { struct osmo_fd *kbd_ofd; - int rc; + bool use_sctp = false; + const char *use_remote_addr = "127.0.0.1"; + int opt, rc; + + while ((opt = getopt(argc, argv, "sr:")) != -1) { + switch (opt) { + case 's': + use_sctp = true; + break; + case 'r': + use_remote_addr = optarg; + break; + default: + exit(0); + } + } + + signal(SIGUSR1, &signal_handler); tall_test = talloc_named_const(NULL, 1, "osmo_stream_cli_test"); msgb_talloc_ctx_init(tall_test, 0); @@ -109,14 +146,17 @@ exit(EXIT_FAILURE); } osmo_stream_cli_set_name(conn, "stream_client"); - osmo_stream_cli_set_addr(conn, "127.0.0.1"); + osmo_stream_cli_set_addr(conn, use_remote_addr); osmo_stream_cli_set_port(conn, 10000); + if (use_sctp) + osmo_stream_cli_set_proto(conn, IPPROTO_SCTP); osmo_stream_cli_set_connect_cb(conn, connect_cb); osmo_stream_cli_set_disconnect_cb(conn, disconnect_cb); osmo_stream_cli_set_read_cb2(conn, read_cb); - if (osmo_stream_cli_open(conn) < 0) { - fprintf(stderr, "cannot open cli\n"); + rc = osmo_stream_cli_open(conn); + if (rc < 0) { + fprintf(stderr, "cannot open cli: %d\n", rc); exit(EXIT_FAILURE); } @@ -132,9 +172,15 @@ exit(EXIT_FAILURE); } + signal(SIGINT, sighandler); + LOGP(DSTREAMTEST, LOGL_NOTICE, "Entering main loop\n"); - while(1) { + while (!quit) { osmo_select_main(0); } + + osmo_fd_unregister(kbd_ofd); + + osmo_stream_cli_destroy(conn); }
View file
libosmo-netif_1.4.0.tar.xz/examples/stream-server.c -> libosmo-netif_1.5.0.tar.xz/examples/stream-server.c
Changed
@@ -3,6 +3,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <errno.h> #include <osmocom/core/select.h> #include <osmocom/core/socket.h> @@ -35,17 +36,29 @@ static struct osmo_stream_srv_link *srv; static struct osmo_stream_srv *conn; +bool quit = false; void sighandler(int foo) { LOGP(DSTREAMTEST, LOGL_NOTICE, "closing STREAMSERVER.\n"); - exit(EXIT_SUCCESS); + quit = true; + signal(SIGINT, SIG_DFL); } -int read_cb(struct osmo_stream_srv *conn, struct msgb *msg) +int read_cb(struct osmo_stream_srv *conn, int res, struct msgb *msg) { LOGP(DSTREAMTEST, LOGL_NOTICE, "receiving message from stream... "); + if (res <= 0) { + if (res < 0) + LOGPC(DSTREAMTEST, LOGL_ERROR, "cannot receive message: %s\n", strerror(-res)); + else + LOGPC(DSTREAMTEST, LOGL_ERROR, "client closed connection\n"); + msgb_free(msg); + osmo_stream_srv_destroy(conn); + return -EBADF; + } + LOGPC(DSTREAMTEST, LOGL_NOTICE, "got %d bytes: %s\n", msg->len, msgb_hexdump(msg)); msgb_free(msg); @@ -112,14 +125,41 @@ memcpy(ptr, buf, ret); osmo_stream_srv_send(conn, msg); - LOGP(DSTREAMTEST, LOGL_NOTICE, "message of %d bytes sent\n", msg->len); + LOGP(DSTREAMTEST, LOGL_NOTICE, "message of %d bytes sent\n", ret); return 0; } -int main(void) +static void signal_handler(int signum) +{ + switch (signum) { + case SIGUSR1: + talloc_report(tall_test, stderr); + break; + } +} + +int main(int argc, char **argv) { struct osmo_fd *kbd_ofd; + bool use_sctp = false; + const char *use_local_addr = "127.0.0.1"; + int opt; + + while ((opt = getopt(argc, argv, "sl:")) != -1) { + switch (opt) { + case 's': + use_sctp = true; + break; + case 'l': + use_local_addr = optarg; + break; + default: + exit(0); + } + } + + signal(SIGUSR1, &signal_handler); tall_test = talloc_named_const(NULL, 1, "osmo_stream_srv_test"); msgb_talloc_ctx_init(tall_test, 0); @@ -135,8 +175,10 @@ fprintf(stderr, "cannot create server link\n"); exit(EXIT_FAILURE); } - osmo_stream_srv_link_set_addr(srv, "127.0.0.1"); + osmo_stream_srv_link_set_addr(srv, use_local_addr); osmo_stream_srv_link_set_port(srv, 10000); + if (use_sctp) + osmo_stream_srv_link_set_proto(srv, IPPROTO_SCTP); osmo_stream_srv_link_set_accept_cb(srv, accept_cb); if (osmo_stream_srv_link_open(srv) < 0) { @@ -152,9 +194,15 @@ osmo_fd_setup(kbd_ofd, STDIN_FILENO, OSMO_FD_READ, kbd_cb, srv, 0); osmo_fd_register(kbd_ofd); + signal(SIGINT, sighandler); + LOGP(DSTREAMTEST, LOGL_NOTICE, "Entering main loop on %s\n", osmo_stream_srv_link_get_sockname(srv)); - while(1) { + while (!quit) { osmo_select_main(0); } + + osmo_fd_unregister(kbd_ofd); + + osmo_stream_srv_link_destroy(srv); }
View file
libosmo-netif_1.4.0.tar.xz/include/osmocom/netif/datagram.h -> libosmo-netif_1.5.0.tar.xz/include/osmocom/netif/datagram.h
Changed
@@ -1,6 +1,19 @@ #ifndef _OSMO_DGRAM_H_ #define _OSMO_DGRAM_H_ +/*! \defgroup datagram Osmocom Datagram Socket + * @{ + * + * This code is intended to abstract any use of datagram type sockets, + * such as UDP. It offers both transmitter and receiver side + * implementations, fully integrated with the libosmocore select loop + * abstraction. + */ + +/*! \file datagram.h + * \brief Osmocom datagram socket helpers + */ + struct osmo_dgram_tx; struct osmo_dgram_tx *osmo_dgram_tx_create(void *ctx);
View file
libosmo-netif_1.4.0.tar.xz/include/osmocom/netif/ipa.h -> libosmo-netif_1.5.0.tar.xz/include/osmocom/netif/ipa.h
Changed
@@ -23,7 +23,19 @@ uint8_t proto_ext; } __attribute__ ((packed)); -#define OSMO_IPA_MSGB_CB(__msg) ((struct osmo_ipa_msgb_cb *)&((__msg)->cb0)) + +/* We don't just cast to 'struct osmo_ipa_msgb_cb *', because that would + * break the strict aliasing rule. Casting to a reference to a union with + * a compatible struct member seems to be allowed, though, see: + * N1570 Committee Draft — April 12, 2011 ISO/IEC 9899:201x, + * Section 6.5, §7 */ +#define OSMO_IPA_MSGB_CB(__msg) (&((( \ + union { \ + unsigned long cb; \ + struct osmo_ipa_msgb_cb _cb; \ + } \ + *)&((__msg)->cb0))->_cb)) + #define osmo_ipa_msgb_cb_proto(__x) OSMO_IPA_MSGB_CB(__x)->proto #define osmo_ipa_msgb_cb_proto_ext(__x) OSMO_IPA_MSGB_CB(__x)->proto_ext @@ -53,4 +65,6 @@ int osmo_ipa_segmentation_cb(struct msgb *msg); +void osmo_ipa_msg_push_headers(struct msgb *msg, enum ipaccess_proto p, enum ipaccess_proto_ext pe); + #endif
View file
libosmo-netif_1.4.0.tar.xz/include/osmocom/netif/osmux.h -> libosmo-netif_1.5.0.tar.xz/include/osmocom/netif/osmux.h
Changed
@@ -15,7 +15,8 @@ #define OSMUX_DEFAULT_PORT 1984 -/* OSmux header: +/*! \struct osmux_hdr + * OSmux header: * * rtp_m (1 bit): RTP M field (RFC3550, RFC4867) * ft (2 bits): 0=signalling, 1=voice, 2=dummy @@ -32,6 +33,7 @@ #define OSMUX_FT_VOICE_AMR 1 #define OSMUX_FT_DUMMY 2 +/*! Osmux protocol header */ struct osmux_hdr { #if OSMO_IS_LITTLE_ENDIAN uint8_t amr_q:1, @@ -56,9 +58,9 @@ uint8_t data0; } __attribute__((packed)); -/* one to handle all existing RTP flows */ +/*! one to handle all existing RTP flows */ struct osmux_in_handle { - /* Initial Osmux seqnum for each circuit, set during osmux_xfrm_input_open_circuit() */ + /*! Initial Osmux seqnum for each circuit, set during osmux_xfrm_input_open_circuit() */ uint8_t osmux_seq; uint8_t batch_factor; uint16_t batch_size; @@ -79,7 +81,7 @@ typedef struct msgb *(*rtp_msgb_alloc_cb_t)(void *rtp_msgb_alloc_priv_data, unsigned int msg_len); -/* one per OSmux circuit_id, ie. one per RTP flow. */ +/*! one per OSmux circuit_id, ie. one per RTP flow. */ struct osmux_out_handle { uint16_t rtp_seq; uint32_t rtp_timestamp; @@ -94,6 +96,7 @@ void *rtp_msgb_alloc_cb_data; /* Opaque data pointer set by user and passed in rtp_msgb_alloc_cb() */ }; +/*! return pointer to osmux payload (behind osmux_hdr) */ static inline uint8_t *osmux_get_payload(struct osmux_hdr *osmuxh) { return (uint8_t *)osmuxh + sizeof(struct osmux_hdr);
View file
libosmo-netif_1.4.0.tar.xz/include/osmocom/netif/prim.h -> libosmo-netif_1.5.0.tar.xz/include/osmocom/netif/prim.h
Changed
@@ -45,6 +45,7 @@ struct osmo_prim_srv_link *osmo_prim_srv_link_alloc(void *ctx); void osmo_prim_srv_link_free(struct osmo_prim_srv_link *prim_link); +void osmo_prim_srv_link_set_name(struct osmo_prim_srv_link *prim_link, const char *name); int osmo_prim_srv_link_set_addr(struct osmo_prim_srv_link *prim_link, const char *path); const char *osmo_prim_srv_link_get_addr(struct osmo_prim_srv_link *prim_link); void osmo_prim_srv_link_set_priv(struct osmo_prim_srv_link *prim_link, void *priv); @@ -59,6 +60,7 @@ int osmo_prim_srv_send(struct osmo_prim_srv *prim_srv, struct msgb *msg); struct osmo_prim_srv_link *osmo_prim_srv_get_link(struct osmo_prim_srv *prims_srv); +void osmo_prim_srv_set_name(struct osmo_prim_srv *prim_srv, const char *name); void osmo_prim_srv_set_priv(struct osmo_prim_srv *prim_srv, void *priv); void *osmo_prim_srv_get_priv(const struct osmo_prim_srv *prim_srv); void osmo_prim_srv_close(struct osmo_prim_srv *prim_srv);
View file
libosmo-netif_1.4.0.tar.xz/include/osmocom/netif/sctp.h -> libosmo-netif_1.5.0.tar.xz/include/osmocom/netif/sctp.h
Changed
@@ -48,3 +48,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.4.0.tar.xz/include/osmocom/netif/stream.h -> libosmo-netif_1.5.0.tar.xz/include/osmocom/netif/stream.h
Changed
@@ -6,9 +6,7 @@ #include <osmocom/core/msgb.h> -/*! \addtogroup stream - * @{ - */ +/*! \file stream.h */ /*! \brief Access SCTP flags from the msgb control buffer */ #define OSMO_STREAM_SCTP_MSG_FLAGS_NOTIFICATION 0x80 /* sctp_recvmsg() flags=MSG_NOTIFICATION, msgb_data() contains "union sctp_notification*" */ @@ -19,13 +17,58 @@ /*! \brief Access the SCTP Stream ID from the msgb control buffer */ #define msgb_sctp_stream(msg) (msg)->cb4 +/*! \defgroup stream_srv Osmocom Stream Server + * @{ + * + * This code is intended to abstract any server-side use of stream-type sockets, such as TCP and SCTP. + * + * The Osmocom stream socket helper is an abstraction layer for connected SOCK_STREAM/SOCK_SEQPACKET sockets. + * It encapsulates common functionality like binding, accepting client connections, etc. + * + * osmo_stream_srv can operate in two different modes: + * 1. The legacy mode using osmo_fd (from libosmocore) + * 2. The modern (2023) mode using osmo_io (from libosmocore) + * + * 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 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). + * + * A typical stream_srv usage would look like this: + * + * * create new osmo_stream_srv_link using osmo_stream_srv_link_create() + * * call osmo_stream_srv_link_set_addr() to set local bind address/port + * * call osmo_stream_srv_link_set_accept_cb() to register the accept call-back + * * optionally call further osmo_stream_srv_link_set_*() functions + * * call osmo_stream_srv_link_open() to create socket and start listening + * + * Whenever a client connects to your listening socket, the connection will now be automatically accept()ed + * and the registered accept_cb call-back called. From within that accept_cb, you then + * * call osmo_stream_srv_create() to create a osmo_stream_srv for that specific connection + * * call osmo_stream_srv_set_read_cb() to register the read call-back for incoming data + * * call osmo_stream_srv_set_closed_cb() to register the closed call-back + * * call osmo_stream_srv_set_data() to associate opaque application-layer state + * + * Whenever data from a client arrives on a connection, your registered read_cb will be called together + * with a message buffer containing the received data. Ownership of the message buffer is transferred + * into the call-back, i.e. in your application. It's your responsibility to eventually msgb_free() + * it after usage. + * + * Whenever your application wants to transmit something to a given connection, it uses the + * osmo_stream_srv_send() function. + */ + /*! \brief Osmocom Stream Server Link: A server socket listening/accepting */ struct osmo_stream_srv_link; +typedef int (*osmo_stream_srv_link_accept_cb_t)(struct osmo_stream_srv_link *link, int fd); + struct osmo_stream_srv_link *osmo_stream_srv_link_create(void *ctx); void osmo_stream_srv_link_destroy(struct osmo_stream_srv_link *link); 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); 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); @@ -33,11 +76,12 @@ void osmo_stream_srv_link_set_proto(struct osmo_stream_srv_link *link, uint16_t proto); int osmo_stream_srv_link_set_type(struct osmo_stream_srv_link *link, int type); int osmo_stream_srv_link_set_domain(struct osmo_stream_srv_link *link, int domain); -void osmo_stream_srv_link_set_accept_cb(struct osmo_stream_srv_link *link, int (*accept_cb)(struct osmo_stream_srv_link *link, int fd)); +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); 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); 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); @@ -56,31 +100,97 @@ * osmo_stream_srv_link */ struct osmo_stream_srv; -struct osmo_stream_srv *osmo_stream_srv_create(void *ctx, struct osmo_stream_srv_link *link, int fd, int (*read_cb)(struct osmo_stream_srv *conn), int (*closed_cb)(struct osmo_stream_srv *conn), void *data); +typedef int (*osmo_stream_srv_read_cb_t)(struct osmo_stream_srv *conn); +typedef int (*osmo_stream_srv_closed_cb_t)(struct osmo_stream_srv *conn); + +/*! Completion call-back function when something was read from from the stream client socket. + * \paramin conn Stream Server that got receive event. + * \paramin res return value of the read()/recvmsg()/... call, or -errno in case of error. + * \paramin msg message buffer containing the read data. Ownership is transferred to the + * call-back, and it must make sure to msgb_free() it eventually! */ +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); + +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, + osmo_stream_srv_closed_cb_t closed_cb, + 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_read_cb(struct osmo_stream_srv *conn, int (*read_cb)(struct osmo_stream_srv *conn, struct msgb *msg)); -void osmo_stream_srv_set_closed_cb(struct osmo_stream_srv *conn, int (*closed_cb)(struct osmo_stream_srv *conn)); +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); 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); +int osmo_stream_srv_get_fd(const struct osmo_stream_srv *srv); +struct osmo_io_fd *osmo_stream_srv_get_iofd(const struct osmo_stream_srv *srv); void osmo_stream_srv_destroy(struct osmo_stream_srv *conn); void osmo_stream_srv_set_flush_and_destroy(struct osmo_stream_srv *conn); 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, - int (*segmentation_cb)(struct msgb *msg)); +void osmo_stream_srv_set_segmentation_cb(struct osmo_stream_srv *conn, osmo_stream_srv_segmentation_cb_t segmentation_cb); 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); void osmo_stream_srv_clear_tx_queue(struct osmo_stream_srv *conn); +/*! @} */ + +/*! \defgroup stream_cli Osmocom Stream Client + * @{ + * + * This code is intended to abstract any client use of stream-type sockets, such as TCP and SCTP + * + * An osmo_stream_cli represents a client implementation of a SOCK_STREAM or SOCK_SEQPACKET socket. It + * contains all the common logic like non-blocking outbound connect to a remote server, re-connecting after + * disconnect or connect failure, etc. + * + * osmo_stream_cli can operate in two different modes: + * 1. The legacy mode using osmo_fd (from libosmocore) + * 2. The modern (2023) mode using osmo_io_fd (from libosmocore) + * + * 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. + * + * A typical usage of osmo_stream_cli would look as follows: + * + * * call osmo_stream_cli_create() to create a new osmo_stream_cli + * * call osmo_stream_cli_set_addr() / osmo_stream_cli_set_port() to specify the remote address/port to connect to + * * optionally call further functions of the osmo_stream_cli_set_*() family + * * call osmo_stream_cli_set_connect_cb() to register the call-back called on completion of outbound connect() + * * call osmo_stream_cli_set_read_cb2() to register the call-back called when incoming data has been read + * * call osmo_stream_cli_open() to open the connection (start outbound connect process) + * + * Once the connection is established, your connect_cb is called to notify you. + * + * You may send data to the connection using osmo_tream_cli_send(). + * + * Any received inbound data on the connection is reported vie the read_cb. + */ + /*! \brief Osmocom Stream Client: Single client connection */ struct osmo_stream_cli; +typedef int (*osmo_stream_cli_connect_cb_t)(struct osmo_stream_cli *cli); +typedef int (*osmo_stream_cli_disconnect_cb_t)(struct osmo_stream_cli *cli); +typedef int (*osmo_stream_cli_read_cb_t)(struct osmo_stream_cli *cli); + +/*! Completion call-back function when something was read from from the stream client socket. + * \paramin cli Stream Client that got receive event. + * \paramin res return value of the read()/recvmsg()/... call, or -errno in case of error. + * \paramin msg message buffer containing the read data. Ownership is transferred to the + * call-back, and it must make sure to msgb_free() it eventually! */ +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); + 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); 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); @@ -96,10 +206,13 @@ void *osmo_stream_cli_get_data(struct osmo_stream_cli *cli); 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); -void osmo_stream_cli_set_connect_cb(struct osmo_stream_cli *cli, int (*connect_cb)(struct osmo_stream_cli *cli)); -void osmo_stream_cli_set_disconnect_cb(struct osmo_stream_cli *cli, int (*disconnect_cb)(struct osmo_stream_cli *cli)); -void osmo_stream_cli_set_read_cb(struct osmo_stream_cli *cli, int (*read_cb)(struct osmo_stream_cli *cli)); -void osmo_stream_cli_set_read_cb2(struct osmo_stream_cli *cli, int (*read_cb)(struct osmo_stream_cli *cli, struct msgb *msg)); +int osmo_stream_cli_get_fd(const struct osmo_stream_cli *cli); +struct osmo_io_fd *osmo_stream_cli_get_iofd(const struct osmo_stream_cli *cli); +void osmo_stream_cli_set_connect_cb(struct osmo_stream_cli *cli, osmo_stream_cli_connect_cb_t connect_cb); +void osmo_stream_cli_set_disconnect_cb(struct osmo_stream_cli *cli, osmo_stream_cli_disconnect_cb_t disconnect_cb); +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_reconnect(struct osmo_stream_cli *cli); bool osmo_stream_cli_is_connected(struct osmo_stream_cli *cli);
View file
libosmo-netif_1.4.0.tar.xz/include/osmocom/netif/stream_private.h -> libosmo-netif_1.5.0.tar.xz/include/osmocom/netif/stream_private.h
Changed
@@ -21,9 +21,7 @@ #define OSMO_STREAM_MAX_ADDRS 1 #endif -/*! \addtogroup stream - * @{ - */ +/*! \cond private */ enum osmo_stream_mode { OSMO_STREAM_MODE_UNKNOWN, @@ -31,8 +29,14 @@ OSMO_STREAM_MODE_OSMO_IO, }; +struct osmo_io_fd; +struct msghdr; + int stream_sctp_sock_activate_events(int fd); int stream_setsockopt_nodelay(int fd, int proto, int on); int stream_sctp_recvmsg_wrapper(int fd, struct msgb *msg, const char *log_pfx); -/*! @} */ +int stream_iofd_sctp_send_msgb(struct osmo_io_fd *iofd, struct msgb *msg, int sendmsg_flags); +int stream_iofd_sctp_recvmsg_trailer(struct osmo_io_fd *iofd, struct msgb *msg, int ret, const struct msghdr *msgh); + +/*! \endcond */
View file
libosmo-netif_1.4.0.tar.xz/src/Makefile.am -> libosmo-netif_1.5.0.tar.xz/src/Makefile.am
Changed
@@ -1,6 +1,6 @@ # 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=12:0:1 +LIBVERSION=13:0:2 AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir) AM_CFLAGS= -fPIC -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(COVERAGE_CFLAGS) $(LIBSCTP_CFLAGS)
View file
libosmo-netif_1.4.0.tar.xz/src/datagram.c -> libosmo-netif_1.5.0.tar.xz/src/datagram.c
Changed
@@ -41,13 +41,12 @@ #include <osmocom/netif/datagram.h> -/*! \addtogroup datagram Osmocom Datagram Socket +#define OSMO_DGRAM_CLI_F_RECONF (1 << 0) + +#define OSMO_DGRAM_RX_F_RECONF (1 << 0) + +/*! \addtogroup datagram * @{ - * - * This code is intended to abstract any use of datagram type sockets, - * such as UDP. It offers both transmitter and receiver side - * implementations, fully integrated with the libosmocore select loop - * abstraction. */ /*! \file datagram.c @@ -59,8 +58,6 @@ * Client side. */ -#define OSMO_DGRAM_CLI_F_RECONF (1 << 0) - struct osmo_dgram_tx { struct osmo_fd ofd; struct llist_head tx_queue; @@ -243,8 +240,6 @@ * Server side. */ -#define OSMO_DGRAM_RX_F_RECONF (1 << 0) - struct osmo_dgram_rx { struct osmo_fd ofd; char *addr;
View file
libosmo-netif_1.4.0.tar.xz/src/ipa.c -> libosmo-netif_1.5.0.tar.xz/src/ipa.c
Changed
@@ -436,3 +436,15 @@ } return total_len; } + +/*! Push IPA headers to a message + * If we have IPAC_PROTO_OSMO this also takes care of the extension header + * \paramout msg Target message + * \param p Target IPA protocol + * \param pe Target IPA protocol extension. Ignored, unless p equals IPAC_PROTO_OSMO. */ +void osmo_ipa_msg_push_headers(struct msgb *msg, enum ipaccess_proto p, enum ipaccess_proto_ext pe) +{ + if (p == IPAC_PROTO_OSMO) + ipa_prepend_header_ext(msg, pe); + osmo_ipa_msg_push_header(msg, p); +}
View file
libosmo-netif_1.4.0.tar.xz/src/jibuf.c -> libosmo-netif_1.5.0.tar.xz/src/jibuf.c
Changed
@@ -26,10 +26,6 @@ #include <arpa/inet.h> -/*! \addtogroup jibuf Osmocom Jitter Buffer - * @{ - */ - /*! \file jibuf.c * \brief Osmocom Jitter Buffer helpers */ @@ -290,6 +286,11 @@ } +/*! \addtogroup jibuf Osmocom Jitter Buffer + * @{ + */ + + //---------------------------------- /*! \brief Allocate a new jitter buffer instance
View file
libosmo-netif_1.4.0.tar.xz/src/osmux.c -> libosmo-netif_1.5.0.tar.xz/src/osmux.c
Changed
@@ -27,6 +27,14 @@ #include <arpa/inet.h> +#define SNPRINTF_BUFFER_SIZE(ret, remain, offset) \ + if (ret < 0) \ + ret = 0; \ + offset += ret; \ + if (ret > remain) \ + ret = remain; \ + remain -= ret; + /*! \addtogroup osmux Osmocom Multiplex Protocol * @{ * @@ -49,14 +57,6 @@ return osmo_amr_bytes(osmuxh->amr_ft) * (osmuxh->ctr+1); } -#define SNPRINTF_BUFFER_SIZE(ret, remain, offset) \ - if (ret < 0) \ - ret = 0; \ - offset += ret; \ - if (ret > remain) \ - ret = remain; \ - remain -= ret; - static int osmux_snprintf_header(char *buf, size_t size, struct osmux_hdr *osmuxh) { unsigned int remain = size, offset = 0;
View file
libosmo-netif_1.4.0.tar.xz/src/osmux_input.c -> libosmo-netif_1.5.0.tar.xz/src/osmux_input.c
Changed
@@ -28,23 +28,6 @@ #include <arpa/inet.h> -/*! \addtogroup osmux Osmocom Multiplex Protocol - * @{ - * - * This code implements a variety of utility functions related to the - * OSMUX user-plane multiplexing protocol, an efficient alternative to - * plain UDP/RTP streams for voice transport in back-haul of cellular - * networks. - * - * For information about the OSMUX protocol design, please see the - * OSMUX reference manual at - * http://ftp.osmocom.org/docs/latest/osmux-reference.pdf - */ - -/*! \file osmux_input.c - * \brief Osmocom multiplex protocol helpers (input) - */ - /* This allows you to debug osmux message transformations (spamming) */ #if 0 #define DEBUG_MSG 0 @@ -68,6 +51,22 @@ LOGMUXLK_(link, lvl, "CID=%" PRIu8 ",batched=%u/%u " fmt, \ (circuit)->ccid, (circuit)->nmsgs, (link)->h->batch_factor, ## args) +/*! \addtogroup osmux Osmocom Multiplex Protocol + * @{ + * + * This code implements a variety of utility functions related to the + * OSMUX user-plane multiplexing protocol, an efficient alternative to + * plain UDP/RTP streams for voice transport in back-haul of cellular + * networks. + * + * For information about the OSMUX protocol design, please see the + * OSMUX reference manual at + * http://ftp.osmocom.org/docs/latest/osmux-reference.pdf + */ + +/*! \file osmux_input.c + * \brief Osmocom multiplex protocol helpers (input) + */ static void *osmux_ctx; @@ -698,6 +697,7 @@ return 0; } +static unsigned int next_default_name_idx = 0; /*! \brief Allocate a new osmux in handle (osmux source, tx side) * \paramin ctx talloc context to use when allocating the returned struct * \return Allocated osmux in handle @@ -708,7 +708,6 @@ * stack outgoing network Osmux messages. * Returned pointer can be freed with regular talloc_free, all pending messages * in queue and all internal data will be freed. */ -static unsigned int next_default_name_idx = 0; struct osmux_in_handle *osmux_xfrm_input_alloc(void *ctx) { struct osmux_in_handle *h; @@ -735,7 +734,7 @@ return h; } -/* DEPRECATED: Use osmux_xfrm_input_alloc() instead */ +/*! \deprecated: Use osmux_xfrm_input_alloc() instead */ void osmux_xfrm_input_init(struct osmux_in_handle *h) { struct osmux_link *link; @@ -849,7 +848,7 @@ osmux_link_del_circuit(link, circuit); } -/* DEPRECATED: Use talloc_free() instead (will call osmux_xfrm_input_talloc_destructor()) */ +/*! \deprecated: Use talloc_free() instead (will call osmux_xfrm_input_talloc_destructor()) */ void osmux_xfrm_input_fini(struct osmux_in_handle *h) { (void)osmux_xfrm_input_talloc_destructor(h);
View file
libosmo-netif_1.4.0.tar.xz/src/osmux_output.c -> libosmo-netif_1.5.0.tar.xz/src/osmux_output.c
Changed
@@ -27,6 +27,12 @@ #include <arpa/inet.h> +/* delta time between two RTP messages (in microseconds) */ +#define DELTA_RTP_MSG 20000 +/* delta time between two RTP messages (in samples, 8kHz) */ +#define DELTA_RTP_TIMESTAMP 160 + + /*! \addtogroup osmux Osmocom Multiplex Protocol * @{ * @@ -43,12 +49,6 @@ /*! \file osmux_output.c * \brief Osmocom multiplex protocol helpers (output) */ - -/* delta time between two RTP messages (in microseconds) */ -#define DELTA_RTP_MSG 20000 -/* delta time between two RTP messages (in samples, 8kHz) */ -#define DELTA_RTP_TIMESTAMP 160 - static uint32_t osmux_ft_dummy_size(uint8_t amr_ft, uint8_t batch_factor) { return sizeof(struct osmux_hdr) + (osmo_amr_bytes(amr_ft) * batch_factor); @@ -330,14 +330,14 @@ return h; } -/* DEPRECATED: Use osmux_xfrm_output_alloc() and osmux_xfrm_output_set_rtp_*() instead */ +/*! \deprecated: Use osmux_xfrm_output_alloc() and osmux_xfrm_output_set_rtp_*() instead */ void osmux_xfrm_output_init2(struct osmux_out_handle *h, uint32_t rtp_ssrc, uint8_t rtp_payload_type) { memset(h, 0, sizeof(*h)); _osmux_xfrm_output_init(h, rtp_ssrc, rtp_payload_type); } -/* DEPRECATED: Use osmux_xfrm_output_alloc() and osmux_xfrm_output_set_rtp_*() instead */ +/*! \deprecated: Use osmux_xfrm_output_alloc() and osmux_xfrm_output_set_rtp_*() instead */ void osmux_xfrm_output_init(struct osmux_out_handle *h, uint32_t rtp_ssrc) { /* backward compatibility with old users, where 98 was harcoded in osmux_rebuild_rtp() */
View file
libosmo-netif_1.4.0.tar.xz/src/prim.c -> libosmo-netif_1.5.0.tar.xz/src/prim.c
Changed
@@ -275,6 +275,8 @@ unsigned int primitive; enum osmo_prim_operation operation; + OSMO_ASSERT(prim_srv); + /* Serialize the oph: */ oph = (struct osmo_prim_hdr *)msgb_data(msg); OSMO_ASSERT(oph && msgb_length(msg) >= sizeof(*oph)); @@ -318,6 +320,11 @@ talloc_free(prim_srv); } +void osmo_prim_srv_set_name(struct osmo_prim_srv *prim_srv, const char *name) +{ + osmo_stream_srv_set_name(prim_srv->stream, name); +} + struct osmo_prim_srv_link *osmo_prim_srv_get_link(struct osmo_prim_srv *prim_srv) { return prim_srv->link; @@ -393,6 +400,11 @@ talloc_free(prim_link); } +void osmo_prim_srv_link_set_name(struct osmo_prim_srv_link *prim_link, const char *name) +{ + osmo_stream_srv_link_set_name(prim_link->stream, name); +} + int osmo_prim_srv_link_set_addr(struct osmo_prim_srv_link *prim_link, const char *path) { osmo_talloc_replace_string(prim_link, &prim_link->addr, path);
View file
libosmo-netif_1.4.0.tar.xz/src/sctp.c -> libosmo-netif_1.5.0.tar.xz/src/sctp.c
Changed
@@ -69,3 +69,27 @@ { OSMO_SCTP_OP_ERR_PROTO_VERSION, "Protocol Violation" }, { 0, NULL } }; + +/* linux/sctp.h enum sctp_spinfo_state */ +const struct value_string osmo_sctp_spinfo_state_strs = { + { SCTP_INACTIVE, "INACTIVE" }, + { SCTP_PF, "POTENTIALLY_FAILED" }, + { SCTP_ACTIVE, "ACTIVE" }, + { SCTP_UNCONFIRMED, "UNCONFIRMED" }, + { SCTP_UNKNOWN, "UNKNOWN" }, + { 0, NULL } +}; + +/* linux/sctp.h enum sctp_sstat_state */ +const struct value_string osmo_sctp_sstat_state_strs = { + { SCTP_EMPTY, "EMPTY" }, + { SCTP_CLOSED, "CLOSED" }, + { SCTP_COOKIE_WAIT, "COOKIE_WAIT" }, + { SCTP_COOKIE_ECHOED, "COOKIE_ECHOED" }, + { SCTP_ESTABLISHED, "ESTABLISHED" }, + { SCTP_SHUTDOWN_PENDING, "SHUTDOWN_PENDING" }, + { SCTP_SHUTDOWN_SENT, "SHUTDOWN_SENT" }, + { SCTP_SHUTDOWN_RECEIVED, "SHUTDOWN_RECEIVED" }, + { SCTP_SHUTDOWN_ACK_SENT, "SHUTDOWN_ACK_SENT" }, + { 0, NULL } +};
View file
libosmo-netif_1.4.0.tar.xz/src/stream.c -> libosmo-netif_1.5.0.tar.xz/src/stream.c
Changed
@@ -51,19 +51,7 @@ #include <osmocom/netif/sctp.h> - -/*! \addtogroup stream Osmocom Stream Socket - * @{ - * - * This code is intended to abstract any use of stream-type sockets, - * such as TCP and SCTP. It offers both server and client side - * implementations, fully integrated with the libosmocore select loop - * abstraction. - */ - -/*! \file stream.c - * \brief Osmocom stream socket helpers - */ +/*! \cond private */ #ifdef HAVE_LIBSCTP @@ -209,25 +197,19 @@ } #ifdef HAVE_LIBSCTP -#define LOGPFX(pfx, level, fmt, args...) \ - LOGP(DLINP, level, "%s " fmt, pfx, ## args) -int stream_sctp_recvmsg_wrapper(int fd, struct msgb *msg, const char *log_pfx) +static int stream_sctp_recvmsg_trailer(const char *log_pfx, struct msgb *msg, int ret, const struct sctp_sndrcvinfo *sinfo, int flags) { - struct sctp_sndrcvinfo sinfo; - int flags = 0; - int ret; - uint8_t *data = msg->tail; - - ret = sctp_recvmsg(fd, data, msgb_tailroom(msg), NULL, NULL, &sinfo, &flags); msgb_sctp_msg_flags(msg) = 0; - msgb_sctp_ppid(msg) = ntohl(sinfo.sinfo_ppid); - msgb_sctp_stream(msg) = sinfo.sinfo_stream; + if (OSMO_LIKELY(sinfo)) { + msgb_sctp_ppid(msg) = ntohl(sinfo->sinfo_ppid); + msgb_sctp_stream(msg) = sinfo->sinfo_stream; + } if (flags & MSG_NOTIFICATION) { char buf512; struct osmo_strbuf sb = { .buf = buf, .len = sizeof(buf) }; int logl = LOGL_INFO; - union sctp_notification *notif = (union sctp_notification *)data; + union sctp_notification *notif = (union sctp_notification *) msg->data; OSMO_STRBUF_PRINTF(sb, "%s NOTIFICATION %s flags=0x%x", log_pfx, osmo_sctp_sn_type_str(notif->sn_header.sn_type), notif->sn_header.sn_flags); @@ -283,9 +265,76 @@ LOGP(DLINP, logl, "%s\n", buf); return ret; } + + if (OSMO_UNLIKELY(ret > 0 && !sinfo)) + LOGP(DLINP, LOGL_ERROR, "%s sctp_recvmsg without SNDRCV cmsg?!?\n", log_pfx); + return ret; } -#endif +/*! wrapper for regular synchronous sctp_recvmsg(3) */ +int stream_sctp_recvmsg_wrapper(int fd, struct msgb *msg, const char *log_pfx) +{ + struct sctp_sndrcvinfo sinfo; + int flags = 0; + int ret; + + ret = sctp_recvmsg(fd, msg->tail, msgb_tailroom(msg), NULL, NULL, &sinfo, &flags); + return stream_sctp_recvmsg_trailer(log_pfx, msg, ret, &sinfo, flags); +} + +/*! wrapper for osmo_io asynchronous recvmsg response */ +int stream_iofd_sctp_recvmsg_trailer(struct osmo_io_fd *iofd, struct msgb *msg, int ret, const struct msghdr *msgh) +{ + const struct sctp_sndrcvinfo *sinfo = NULL; + struct cmsghdr *cmsg = NULL; + + for (cmsg = CMSG_FIRSTHDR((struct msghdr *) msgh); cmsg != NULL; + 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; + } + } + + return stream_sctp_recvmsg_trailer(osmo_iofd_get_name(iofd), msg, ret, sinfo, msgh->msg_flags); +} + +/*! Send a message through a connected SCTP socket, similar to sctp_sendmsg(). + * + * Appends the message to the internal transmit queue. + * If the function returns success (0), it will take ownership of the msgb and + * internally call msgb_free() after the write request completes. + * In case of an error the msgb needs to be freed by the caller. + * + * \paramin iofd file descriptor to write to + * \paramin msg message buffer to send; uses msgb_sctp_ppid/msg_sctp_stream + * \paramin sendmsg_flags Flags to pass to the send call + * \returns 0 in case of success; a negative value in case of error + */ +int stream_iofd_sctp_send_msgb(struct osmo_io_fd *iofd, struct msgb *msg, int sendmsg_flags) +{ + struct msghdr outmsg = {}; + char outcmsgCMSG_SPACE(sizeof(struct sctp_sndrcvinfo)); + struct sctp_sndrcvinfo *sinfo; + struct cmsghdr *cmsg; + + outmsg.msg_control = outcmsg; + outmsg.msg_controllen = sizeof(outcmsg); + + cmsg = CMSG_FIRSTHDR(&outmsg); + cmsg->cmsg_level = IPPROTO_SCTP; + cmsg->cmsg_type = SCTP_SNDRCV; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo)); + + outmsg.msg_controllen = cmsg->cmsg_len; + sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); + memset(sinfo, 0, sizeof(struct sctp_sndrcvinfo)); + sinfo->sinfo_ppid = htonl(msgb_sctp_ppid(msg)); + sinfo->sinfo_stream = msgb_sctp_stream(msg); + + return osmo_iofd_sendmsg_msgb(iofd, msg, sendmsg_flags, &outmsg); +} +#endif -/*! @} */ +/*! \endccond */
View file
libosmo-netif_1.4.0.tar.xz/src/stream_cli.c -> libosmo-netif_1.5.0.tar.xz/src/stream_cli.c
Changed
@@ -51,18 +51,7 @@ #include <osmocom/netif/sctp.h> - -/*! \addtogroup stream Osmocom Stream Socket (client side) - * @{ - * - * This code is intended to abstract any use of stream-type sockets, - * such as TCP and SCTP. It offers client side implementation, - * fully integrated with the libosmocore select loop abstraction. - */ - -/*! \file stream_cli.c - * \brief Osmocom stream socket helpers (client side) - */ +/*! \file stream_cli.c */ #define LOGSCLI(cli, level, fmt, args...) \ LOGP(DLINP, level, "CLICONN(%s,%s){%s} " fmt, \ @@ -114,11 +103,11 @@ int sk_domain; int sk_type; uint16_t proto; - int (*connect_cb)(struct osmo_stream_cli *cli); - int (*disconnect_cb)(struct osmo_stream_cli *cli); - int (*read_cb)(struct osmo_stream_cli *cli); - int (*iofd_read_cb)(struct osmo_stream_cli *cli, struct msgb *msg); - int (*write_cb)(struct osmo_stream_cli *cli); + 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; void *data; int flags; int reconnect_timeout; @@ -127,7 +116,11 @@ void osmo_stream_cli_close(struct osmo_stream_cli *cli); -/*! \brief Re-connect an Osmocom Stream Client +/*! \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 */ @@ -146,7 +139,7 @@ osmo_timer_schedule(&cli->timer, cli->reconnect_timeout, 0); } -/*! \brief Check if Osmocom Stream Client is in connected state +/*! Check if Osmocom Stream Client is in connected state. * \paramin cli Osmocom Stream Client * \return true if connected, false otherwise */ @@ -160,7 +153,8 @@ if (!cli->iofd) return; - osmo_iofd_close(cli->iofd); + osmo_iofd_free(cli->iofd); + cli->iofd = NULL; } static void osmo_stream_cli_close_ofd(struct osmo_stream_cli *cli) @@ -172,7 +166,7 @@ cli->ofd.fd = -1; } -/*! \brief Close an Osmocom Stream Client +/*! 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 */ @@ -209,7 +203,11 @@ } } -static inline int osmo_stream_cli_fd(const struct osmo_stream_cli *cli) +/*! Retrieve file descriptor of the stream client socket. + * \paramin cli Stream Client of which we want to obtain the file descriptor + * \returns File descriptor or negative in case of error */ +int +osmo_stream_cli_get_fd(const struct osmo_stream_cli *cli) { switch (cli->mode) { case OSMO_STREAM_MODE_OSMO_FD: @@ -223,6 +221,18 @@ return -EINVAL; } +/*! Retrieve osmo_io descriptor of the stream client socket. + * This function must not be called on a stream client in legacy osmo_fd mode! + * The iofd is only valid once/after osmo_stream_cli_open() has successfully returned. + * \paramin cli Stream Client of which we want to obtain the file descriptor + * \returns osmo_io_fd of stream client, or NULL if stream not yet opened. */ +struct osmo_io_fd * +osmo_stream_cli_get_iofd(const struct osmo_stream_cli *cli) +{ + OSMO_ASSERT(cli->mode == OSMO_STREAM_MODE_OSMO_IO); + return cli->iofd; +} + static void osmo_stream_cli_read(struct osmo_stream_cli *cli) { LOGSCLI(cli, LOGL_DEBUG, "message received\n"); @@ -298,6 +308,7 @@ } msgb_free(msg); osmo_stream_cli_reconnect(cli); + return 0; } msgb_free(msg); @@ -313,7 +324,7 @@ #ifdef SO_NOSIGPIPE int ret; int val = 1; - ret = setsockopt(osmo_stream_cli_fd(cli), SOL_SOCKET, SO_NOSIGPIPE, (void *)&val, sizeof(val)); + ret = setsockopt(osmo_stream_cli_get_fd(cli), SOL_SOCKET, SO_NOSIGPIPE, (void *)&val, sizeof(val)); if (ret < 0) LOGSCLI(cli, LOGL_ERROR, "Failed setting SO_NOSIGPIPE: %s\n", strerror(errno)); return ret; @@ -327,7 +338,7 @@ int error, ret = res; socklen_t len = sizeof(error); - int fd = osmo_stream_cli_fd(cli); + int fd = osmo_stream_cli_get_fd(cli); OSMO_ASSERT(fd >= 0); if (ret < 0) { @@ -346,7 +357,7 @@ osmo_fd_write_disable(&cli->ofd); /* Update sockname based on socket info: */ - osmo_sock_get_name_buf(cli->sockname, sizeof(cli->sockname), osmo_stream_cli_fd(cli)); + osmo_sock_get_name_buf(cli->sockname, sizeof(cli->sockname), osmo_stream_cli_get_fd(cli)); LOGSCLI(cli, LOGL_INFO, "connection established\n"); cli->state = STREAM_CLI_STATE_CONNECTED; @@ -397,7 +408,7 @@ static void cli_timer_cb(void *data); -/*! \brief Create an Osmocom stream client +/*! Create an Osmocom stream client. * \paramin ctx talloc context from which to allocate memory * This function allocates a new \ref osmo_stream_cli and initializes * it with default values (5s reconnect timer, TCP protocol) @@ -419,6 +430,7 @@ cli->state = STREAM_CLI_STATE_CLOSED; osmo_timer_setup(&cli->timer, cli_timer_cb, cli); cli->reconnect_timeout = 5; /* default is 5 seconds. */ + cli->segmentation_cb = NULL; INIT_LLIST_HEAD(&cli->tx_queue); cli->ma_pars.sctp.version = 0; @@ -432,13 +444,29 @@ switch (cli->state) { case STREAM_CLI_STATE_CONNECTING: + msgb_free(msg); stream_cli_handle_connecting(cli, res); break; case STREAM_CLI_STATE_CONNECTED: - if (res == 0) + switch (res) { + case -EPIPE: + case -ECONNRESET: + LOGSCLI(cli, LOGL_ERROR, "lost connection with srv (%d)\n", res); + osmo_stream_cli_reconnect(cli); + break; + case 0: + LOGSCLI(cli, LOGL_NOTICE, "connection closed with srv\n"); osmo_stream_cli_reconnect(cli); - else if (cli->iofd_read_cb) - cli->iofd_read_cb(cli, msg); + break; + default: + LOGSCLI(cli, LOGL_DEBUG, "received %d bytes from srv\n", res); + break; + } + /* Notify user of new data or error: */ + if (cli->iofd_read_cb) + cli->iofd_read_cb(cli, res, msg); + else + msgb_free(msg); break; default: osmo_panic("%s() called with unexpected state %d\n", __func__, cli->state); @@ -464,14 +492,60 @@ } } -static struct osmo_io_ops osmo_stream_cli_ioops = { +static const struct osmo_io_ops osmo_stream_cli_ioops = { .read_cb = stream_cli_iofd_read_cb, .write_cb = stream_cli_iofd_write_cb, .segmentation_cb = NULL, }; -/*! \brief Set a name on the cli object (used during logging) +#ifdef HAVE_LIBSCTP +static void stream_cli_iofd_recvmsg_cb(struct osmo_io_fd *iofd, int res, struct msgb *msg, const struct msghdr *msgh) +{ + struct osmo_stream_cli *cli = osmo_iofd_get_data(iofd); + + res = stream_iofd_sctp_recvmsg_trailer(iofd, msg, res, msgh); + + switch (cli->state) { + case STREAM_CLI_STATE_CONNECTING: + msgb_free(msg); + stream_cli_handle_connecting(cli, res); + break; + case STREAM_CLI_STATE_CONNECTED: + switch (res) { + case -EPIPE: + case -ECONNRESET: + LOGSCLI(cli, LOGL_ERROR, "lost connection with srv (%d)\n", res); + osmo_stream_cli_reconnect(cli); + break; + case 0: + LOGSCLI(cli, LOGL_NOTICE, "connection closed with srv\n"); + osmo_stream_cli_reconnect(cli); + break; + default: + break; + } + /* Notify user of new data or error: */ + if (cli->iofd_read_cb) + cli->iofd_read_cb(cli, res, msg); + else + msgb_free(msg); + break; + default: + osmo_panic("%s() called with unexpected state %d\n", __func__, cli->state); + } +} + +static const struct osmo_io_ops osmo_stream_cli_ioops_sctp = { + .recvmsg_cb = stream_cli_iofd_recvmsg_cb, + .sendmsg_cb = stream_cli_iofd_write_cb, + + .segmentation_cb = NULL, +}; +#endif + + +/*! Set a name on the cli object (used during logging). * \paramin cli stream_cli whose name is to be set * \paramin name the name to be set on cli */ @@ -482,7 +556,17 @@ osmo_iofd_set_name(cli->iofd, name); } -/*! \brief Set the remote address to which we connect +/*! Retrieve name previously set on the cli object (see osmo_stream_cli_set_name()). + * \paramin cli stream_cli whose name is to be retrieved + * \returns The name to be set on cli; NULL if never set + */ +const char *osmo_stream_cli_get_name(const struct osmo_stream_cli *cli) +{ + return cli->name; +} + +/*! Set the remote address to which we connect. + * Any changes to this setting will only become active upon next (re)connect. * \paramin cli Stream Client to modify * \paramin addr Remote IP address */ @@ -492,8 +576,9 @@ osmo_stream_cli_set_addrs(cli, &addr, 1); } -/*! \brief Set the remote address set to which we connect. +/*! Set the remote address set to which we connect. * Useful for protocols allowing connecting to more than one address (such as SCTP) + * Any changes to this setting will only become active upon next (re)connect. * \paramin cli Stream Client to modify * \paramin addr Remote IP address set * \return negative on error, 0 on success @@ -517,7 +602,8 @@ return 0; } -/*! \brief Set the remote port number to which we connect +/*! Set the remote port number to which we connect. + * Any changes to this setting will only become active upon next (re)connect. * \paramin cli Stream Client to modify * \paramin port Remote port number */ @@ -528,7 +614,8 @@ cli->flags |= OSMO_STREAM_CLI_F_RECONF; } -/*! \brief Set the local port number for the socket (to be bound to) +/*! Set the local port number for the socket (to be bound to). + * Any changes to this setting will only become active upon next (re)connect. * \paramin cli Stream Client to modify * \paramin port Local port number */ @@ -539,7 +626,8 @@ cli->flags |= OSMO_STREAM_CLI_F_RECONF; } -/*! \brief Set the local address for the socket (to be bound to) +/*! Set the local address for the socket (to be bound to). + * Any changes to this setting will only become active upon next (re)connect. * \paramin cli Stream Client to modify * \paramin port Local host name */ @@ -549,8 +637,9 @@ osmo_stream_cli_set_local_addrs(cli, &addr, 1); } -/*! \brief Set the local address set to which we connect. +/*! Set the local address set to which we bind. * Useful for protocols allowing bind to more than one address (such as SCTP) + * Any changes to this setting will only become active upon next (re)connect. * \paramin cli Stream Client to modify * \paramin addr Local IP address set * \return negative on error, 0 on success @@ -574,7 +663,8 @@ return 0; } -/*! \brief Set the protocol for the stream client socket +/*! Set the protocol for the stream client socket. + * Any changes to this setting will only become active upon next (re)connect. * \paramin cli Stream Client to modify * \paramin proto Protocol (like IPPROTO_TCP (default), IPPROTO_SCTP, ...) */ @@ -585,10 +675,35 @@ cli->flags |= OSMO_STREAM_CLI_F_RECONF; } -/*! \brief Set the socket type for the stream server link +/* Configure client side segmentation for the iofd */ +static void configure_cli_segmentation_cb(struct osmo_stream_cli *cli, + osmo_stream_cli_segmentation_cb_t segmentation_cb) +{ + /* Copy default settings */ + struct osmo_io_ops client_ops; + osmo_iofd_get_ioops(cli->iofd, &client_ops); + /* Set segmentation cb for this client */ + client_ops.segmentation_cb = segmentation_cb; + osmo_iofd_set_ioops(cli->iofd, &client_ops); +} + +/*! Set the segmentation callback for the client. + * \paramin,out cli Stream Client to modify + * \paramin segmentation_cb Target segmentation callback + */ +void osmo_stream_cli_set_segmentation_cb(struct osmo_stream_cli *cli, + osmo_stream_cli_segmentation_cb_t segmentation_cb) +{ + cli->segmentation_cb = segmentation_cb; + if (cli->iofd) /* Otherwise, this will be done in osmo_stream_cli_open() */ + configure_cli_segmentation_cb(cli, segmentation_cb); +} + +/*! Set the socket type for the stream server link. + * Any changes to this setting will only become active upon next (re)connect. * \paramin cli Stream Client to modify * \paramin type Socket Type (like SOCK_STREAM (default), SOCK_SEQPACKET, ...) - * \returns zero on success, negative on error. + * \returns zero on success, negative -errno on error. */ int osmo_stream_cli_set_type(struct osmo_stream_cli *cli, int type) { @@ -604,10 +719,11 @@ return 0; } -/*! \brief Set the socket type for the stream server link +/*! Set the socket type for the stream server 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, ...) - * \returns zero on success, negative on error. + * \returns zero on success, negative -errno on error. */ int osmo_stream_cli_set_domain(struct osmo_stream_cli *cli, int domain) { @@ -625,7 +741,7 @@ return 0; } -/*! \brief Set the reconnect time of the stream client socket +/*! Set the reconnect time of the stream client socket. * \paramin cli Stream Client to modify * \paramin timeout Re-connect timeout in seconds or negative value to disable auto-reconnection */ void @@ -634,7 +750,7 @@ cli->reconnect_timeout = timeout; } -/*! \brief Set application private data of the stream client socket +/*! Set application private data of the stream client socket. * \paramin cli Stream Client to modify * \paramin data User-specific data (available in call-back functions) */ void @@ -643,7 +759,7 @@ cli->data = data; } -/*! \brief Get application private data of the stream client socket +/*! Retrieve application private data of the stream client socket. * \paramin cli Stream Client to modify * \returns Application private data, as set by \ref osmo_stream_cli_set_data() */ void *osmo_stream_cli_get_data(struct osmo_stream_cli *cli) @@ -651,19 +767,23 @@ return cli->data; } -/*! \brief Get the stream client socket description. +/*! Retrieve the stream client socket description. + * Calling this function will build a string that describes the socket in terms of its local/remote + * address/port. The returned name is stored in a static buffer; it is hence not re-entrant or thread-safe. * \paramin cli Stream Client to examine * \returns Socket description or NULL in case of error */ char *osmo_stream_cli_get_sockname(const struct osmo_stream_cli *cli) { - static char bufOSMO_SOCK_NAME_MAXLEN; + static char bufOSMO_STREAM_MAX_ADDRS * OSMO_SOCK_NAME_MAXLEN; - osmo_sock_get_name_buf(buf, OSMO_SOCK_NAME_MAXLEN, osmo_stream_cli_fd(cli)); + osmo_sock_multiaddr_get_name_buf(buf, sizeof(buf), + osmo_stream_cli_get_fd(cli), cli->proto); return buf; } -/*! \brief Get Osmocom File Descriptor of the stream client socket +/*! Retrieve Osmocom File Descriptor of the stream client socket. + * This function only works in case you operate osmo_stream_cli in osmo_fd mode! * \paramin cli Stream Client to modify * \returns Pointer to \ref osmo_fd */ struct osmo_fd * @@ -673,52 +793,54 @@ return &cli->ofd; } -/*! \brief Set the call-back function called on connect of the stream client socket +/*! Set the call-back function called on connect of the stream client socket. + * The call-back function registered via this function will be called upon completion of the non-blocking + * outbound connect operation. * \paramin cli Stream Client to modify * \paramin connect_cb Call-back function to be called upon connect */ void osmo_stream_cli_set_connect_cb(struct osmo_stream_cli *cli, - int (*connect_cb)(struct osmo_stream_cli *cli)) + osmo_stream_cli_connect_cb_t connect_cb) { cli->connect_cb = connect_cb; } -/*! \brief Set the call-back function called on disconnect of the stream client socket +/*! Set the call-back function called on disconnect of the stream client socket. * \paramin cli Stream Client to modify * \paramin disconnect_cb Call-back function to be called upon disconnect */ void osmo_stream_cli_set_disconnect_cb(struct osmo_stream_cli *cli, - int (*disconnect_cb)(struct osmo_stream_cli *cli)) + osmo_stream_cli_disconnect_cb_t disconnect_cb) { cli->disconnect_cb = disconnect_cb; } -/*! \brief Set the call-back function called to read from the stream client socket - * This function will configure osmo_stream_cli to use osmo_ofd internally. +/*! Set the call-back function called to read from the stream client socket. + * This function will implicitly configure osmo_stream_cli to use legacy osmo_ofd mode. * \paramin cli Stream Client to modify * \paramin read_cb Call-back function to be called when we want to read */ void osmo_stream_cli_set_read_cb(struct osmo_stream_cli *cli, - int (*read_cb)(struct osmo_stream_cli *cli)) + osmo_stream_cli_read_cb_t read_cb) { OSMO_ASSERT(cli->mode != OSMO_STREAM_MODE_OSMO_IO); cli->mode = OSMO_STREAM_MODE_OSMO_FD; cli->read_cb = read_cb; } -/*! \brief Set the call-back function called to read from the stream client socket - * This function will configure osmo_stream_cli to use osmo_iofd internally. +/*! Set the call-back function called to read from the stream client socket. + * This function will implicitly configure osmo_stream_cli to use osmo_iofd mode. * \paramin cli Stream Client to modify * \paramin read_cb Call-back function to be called when data was read from the socket */ void osmo_stream_cli_set_read_cb2(struct osmo_stream_cli *cli, - int (*read_cb)(struct osmo_stream_cli *cli, struct msgb *msg)) + osmo_stream_cli_read_cb2_t read_cb) { OSMO_ASSERT(cli->mode != OSMO_STREAM_MODE_OSMO_FD); cli->mode = OSMO_STREAM_MODE_OSMO_IO; cli->iofd_read_cb = read_cb; } -/*! \brief Destroy a Osmocom stream client (includes close) +/*! Destroy a Osmocom stream client (includes close). * \paramin cli Stream Client to destroy */ void osmo_stream_cli_destroy(struct osmo_stream_cli *cli) { @@ -728,7 +850,7 @@ talloc_free(cli); } -/*! \brief DEPRECATED: use osmo_stream_cli_set_reconnect_timeout() or osmo_stream_cli_reconnect() instead! +/*! DEPRECATED: use osmo_stream_cli_set_reconnect_timeout() or osmo_stream_cli_reconnect() instead! * Open connection of an Osmocom stream client * \paramin cli Stream Client to connect * \paramin reconect 1 if we should not automatically reconnect @@ -786,7 +908,7 @@ return -EIO; } -/*! \brief Set the NODELAY socket option to avoid Nagle-like behavior +/*! Set the NODELAY socket option to avoid Nagle-like behavior. * Setting this to nodelay=true will automatically set the NODELAY * socket option on any socket established via \ref osmo_stream_cli_open * or any re-connect. You have to set this _before_ opening the @@ -802,17 +924,20 @@ cli->flags &= ~OSMO_STREAM_CLI_F_NODELAY; } -/*! \brief Open connection of an Osmocom stream client - * By default the client will automatically reconnect after default timeout. +/*! Open connection of an Osmocom stream client. + * This will initiate an non-blocking outbound connect to the configured destination (server) address. + * By default the client will automatically attempt to reconnect after default timeout. * To disable this, use osmo_stream_cli_set_reconnect_timeout() before calling this function. * \paramin cli Stream Client to connect * \return negative on error, 0 on success */ int osmo_stream_cli_open(struct osmo_stream_cli *cli) { - int ret, fd = -1; + int ret, flags; + int fd = -1; + unsigned int local_addrcnt; /* we are reconfiguring this socket, close existing first. */ - if ((cli->flags & OSMO_STREAM_CLI_F_RECONF) && osmo_stream_cli_fd(cli) >= 0) + if ((cli->flags & OSMO_STREAM_CLI_F_RECONF) && osmo_stream_cli_get_fd(cli) >= 0) osmo_stream_cli_close(cli); cli->flags &= ~OSMO_STREAM_CLI_F_RECONF; @@ -827,11 +952,18 @@ switch (cli->proto) { #ifdef HAVE_LIBSCTP case IPPROTO_SCTP: + local_addrcnt = cli->local_addrcnt; + flags = OSMO_SOCK_F_CONNECT|OSMO_SOCK_F_NONBLOCK; + if (cli->local_addrcnt > 0 || cli->local_port > 0) { /* explicit bind required? */ + flags |= OSMO_SOCK_F_BIND; + /* If no local addr configured, use local_addr0=NULL by default when creating the socket. */ + if (cli->local_addrcnt == 0) + local_addrcnt = 1; + } ret = osmo_sock_init2_multiaddr2(cli->sk_domain, cli->sk_type, cli->proto, - (const char **)cli->local_addr, cli->local_addrcnt, cli->local_port, + (const char **)cli->local_addr, local_addrcnt, cli->local_port, (const char **)cli->addr, cli->addrcnt, cli->port, - OSMO_SOCK_F_CONNECT|OSMO_SOCK_F_BIND|OSMO_SOCK_F_NONBLOCK, - &cli->ma_pars); + flags, &cli->ma_pars); break; #endif default: @@ -865,14 +997,30 @@ goto error_close_socket; break; case OSMO_STREAM_MODE_OSMO_IO: - if (!cli->iofd) - cli->iofd = osmo_iofd_setup(cli, fd, cli->name, OSMO_IO_FD_MODE_READ_WRITE, &osmo_stream_cli_ioops, cli); + /* Be sure that previous osmo_io instance is freed before creating a new one. */ + osmo_stream_cli_close_iofd(cli); +#ifdef HAVE_LIBSCTP + if (cli->proto == IPPROTO_SCTP) { + cli->iofd = osmo_iofd_setup(cli, fd, cli->name, OSMO_IO_FD_MODE_RECVMSG_SENDMSG, + &osmo_stream_cli_ioops_sctp, cli); + if (cli->iofd) + osmo_iofd_set_cmsg_size(cli->iofd, CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))); + } else { +#else + if (true) { +#endif + cli->iofd = osmo_iofd_setup(cli, fd, cli->name, OSMO_IO_FD_MODE_READ_WRITE, + &osmo_stream_cli_ioops, cli); + } if (!cli->iofd) goto error_close_socket; + osmo_iofd_notify_connected(cli->iofd); + + configure_cli_segmentation_cb(cli, cli->segmentation_cb); + if (osmo_iofd_register(cli->iofd, fd) < 0) goto error_close_socket; - osmo_iofd_notify_connected(cli->iofd); break; default: OSMO_ASSERT(false); @@ -897,32 +1045,52 @@ osmo_stream_cli_open(cli); } -/*! \brief Enqueue data to be sent via an Osmocom stream client +/*! Enqueue data to be sent via an Osmocom stream client.. + * This is the function you use for writing/sending/transmitting data via the osmo_stream_cli. * \paramin cli Stream Client through which we want to send * \paramin msg Message buffer to enqueue in transmit queue */ void osmo_stream_cli_send(struct osmo_stream_cli *cli, struct msgb *msg) { + int rc; + OSMO_ASSERT(cli); OSMO_ASSERT(msg); + if (!osmo_stream_cli_is_connected(cli)) { + LOGSCLI(cli, LOGL_ERROR, "send: not connected, dropping data!\n"); + msgb_free(msg); + return; + } + switch (cli->mode) { case OSMO_STREAM_MODE_OSMO_FD: msgb_enqueue(&cli->tx_queue, msg); osmo_fd_write_enable(&cli->ofd); break; case OSMO_STREAM_MODE_OSMO_IO: - osmo_iofd_write_msgb(cli->iofd, msg); + /* whenever osmo_stream_cli_is_connected() see above check, we should have an iofd */ + OSMO_ASSERT(cli->iofd); + if (cli->proto == IPPROTO_SCTP) + rc = stream_iofd_sctp_send_msgb(cli->iofd, msg, MSG_NOSIGNAL); + else + rc = osmo_iofd_write_msgb(cli->iofd, msg); + if (rc < 0) + msgb_free(msg); break; default: OSMO_ASSERT(false); } } -/*! \brief Receive data via an Osmocom stream client +/*! Receive data via an Osmocom stream client in osmo_fd mode. * \paramin cli Stream Client through which we want to send * \param msg pre-allocate message buffer to which received data is appended * \returns number of bytes read; <=0 in case of error * + * Application programs using the legacy osmo_fd mode of osmo_stream_cli will use + * this function to read/receive from a stream client socket after they have been notified that + * it is readable (via select/poll). + * * If conn is an SCTP connection, additional specific considerations shall be taken: * - msg->cb is always filled with SCTP ppid, and SCTP stream values, see msgb_sctp_*() APIs. * - If an SCTP notification was received when reading from the SCTP socket, @@ -938,6 +1106,7 @@ int ret; OSMO_ASSERT(cli); OSMO_ASSERT(msg); + OSMO_ASSERT(cli->mode == OSMO_STREAM_MODE_OSMO_FD); switch (cli->sk_domain) { case AF_UNIX: @@ -983,6 +1152,8 @@ return ret; } +/*! Clear the transmit queue of the stream client. + * Calling this function wil clear (delete) any pending, not-yet transmitted data from the transmit queue. */ void osmo_stream_cli_clear_tx_queue(struct osmo_stream_cli *cli) { switch (cli->mode) { @@ -1001,6 +1172,12 @@ } } +/*! Set given parameter of stream client to given value. + * \paramin cli stream client 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. + * \returns 0 in success; negative -errno on error. */ int osmo_stream_cli_set_param(struct osmo_stream_cli *cli, enum osmo_stream_cli_param par, void *val, size_t val_len) { OSMO_ASSERT(cli);
View file
libosmo-netif_1.4.0.tar.xz/src/stream_srv.c -> libosmo-netif_1.5.0.tar.xz/src/stream_srv.c
Changed
@@ -28,6 +28,7 @@ #include <time.h> #include <sys/fcntl.h> #include <sys/socket.h> +#include <sys/un.h> #include <sys/ioctl.h> #include <arpa/inet.h> #include <netinet/in.h> @@ -51,18 +52,7 @@ #include <osmocom/netif/sctp.h> - -/*! \addtogroup stream Osmocom Stream Socket (server side) - * @{ - * - * This code is intended to abstract any use of stream-type sockets, - * such as TCP and SCTP. It offers server side implementation, - * fully integrated with the libosmocore select loop abstraction. - */ - -/*! \file stream_srv.c - * \brief Osmocom stream socket helpers (server side) - */ +/*! \file stream_srv.c */ #define LOGSLNK(link, level, fmt, args...) \ LOGP(DLINP, level, "SRV(%s,%s) " fmt, \ @@ -85,14 +75,14 @@ struct osmo_stream_srv_link { struct osmo_fd ofd; char *name; - char socknameOSMO_SOCK_NAME_MAXLEN; + char socknameOSMO_SOCK_MULTIADDR_PEER_STR_MAXLEN; char *addrOSMO_STREAM_MAX_ADDRS; uint8_t addrcnt; uint16_t port; int sk_domain; int sk_type; uint16_t proto; - int (*accept_cb)(struct osmo_stream_srv_link *srv, int fd); + osmo_stream_srv_link_accept_cb_t accept_cb; void *data; int flags; struct osmo_sock_init2_multiaddr_pars ma_pars; @@ -173,11 +163,14 @@ return ret; } -/*! \brief Create an Osmocom Stream Server Link - * A Stream Server Link is the listen()+accept() "parent" to individual - * Stream Servers +/*! \addtogroup stream_srv + * @{ + */ + +/*! Create an Osmocom Stream Server Link. + * A Stream Server Link is the listen()+accept() "parent" to individual connections from remote clients. * \paramin ctx talloc allocation context - * \returns Stream Server Link with default values (TCP) + * \returns Stream Server Link with default values (AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP) */ struct osmo_stream_srv_link *osmo_stream_srv_link_create(void *ctx) { @@ -197,8 +190,9 @@ return link; } -/*! \brief Set a name on the srv_link object (used during logging) - * \paramin link server link whose name is to be set +/*! Set a name on the srv_link object (used during logging). + * \paramin link server link whose name is to be set. The name is copied into the osmo_stream_srv_link, so + * the caller memory is not required to be valid beyond the call of this function. * \paramin name the name to be set on link */ void osmo_stream_srv_link_set_name(struct osmo_stream_srv_link *link, const char *name) @@ -206,7 +200,16 @@ osmo_talloc_replace_string(link, &link->name, name); } -/*! \brief Set the NODELAY socket option to avoid Nagle-like behavior +/*! Retrieve name previously set on the srv_link object (see osmo_stream_srv_link_set_name()). + * \paramin link server link whose name is to be retrieved + * \returns The name to be set on link; NULL if never set + */ +const char *osmo_stream_srv_link_get_name(const struct osmo_stream_srv_link *link) +{ + return link->name; +} + +/*! Set the NODELAY socket option to avoid Nagle-like behavior. * Setting this to nodelay=true will automatically set the NODELAY * socket option on any socket established via this server link, before * calling the accept_cb() @@ -221,7 +224,8 @@ link->flags &= ~OSMO_STREAM_SRV_F_NODELAY; } -/*! \brief Set the local address to which we bind +/*! 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 * \paramin addr Local IP address */ @@ -231,8 +235,9 @@ osmo_stream_srv_link_set_addrs(link, &addr, 1); } -/*! \brief Set the local address set to which we bind. +/*! Set the local address set to which we bind. * Useful for protocols allowing bind on more than one address (such as SCTP) + * Any changes to this setting will only become active upon next (re)connect. * \paramin link Stream Server Link to modify * \paramin addr Local IP address * \return negative on error, 0 on success @@ -256,7 +261,8 @@ return 0; } -/*! \brief Set the local port number to which we bind +/*! Set the local port number to which we bind. + * Any changes to this setting will only become active upon next (re)connect. * \paramin link Stream Server Link to modify * \paramin port Local port number */ @@ -267,7 +273,8 @@ link->flags |= OSMO_STREAM_SRV_F_RECONF; } -/*! \brief Set the protocol for the stream server link +/*! Set the protocol 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 proto Protocol (like IPPROTO_TCP (default), IPPROTO_SCTP, ...) */ @@ -280,7 +287,8 @@ } -/*! \brief Set the socket type for the stream server link +/*! Set the socket type 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 Type (like SOCK_STREAM (default), SOCK_SEQPACKET, ...) * \returns zero on success, negative on error. @@ -299,7 +307,8 @@ return 0; } -/*! \brief Set the socket type for the stream server link +/*! Set the socket type 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, ...) * \returns zero on success, negative on error. @@ -320,7 +329,7 @@ return 0; } -/*! \brief Set application private data of the stream server link +/*! Set application private data of the stream server link. * \paramin link Stream Server Link to modify * \paramin data User-specific data (available in call-back functions) */ void @@ -330,7 +339,7 @@ link->data = data; } -/*! \brief Get application private data of the stream server link +/*! Retrieve application private data of the stream server link. * \paramin link Stream Server Link to modify * \returns Application private data, as set by \ref osmo_stream_cli_set_data() */ void *osmo_stream_srv_link_get_data(struct osmo_stream_srv_link *link) @@ -338,26 +347,75 @@ return link->data; } -/*! \brief Get description of the stream server link e. g. 127.0.0.1:1234 +/* 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) +{ + struct osmo_strbuf sb = { .buf = buf, .len = buf_len }; + int rc; + + if (buf_len > 0) + buf0 = '\0'; + + switch (link->sk_domain) { + case AF_UNSPEC: + /* we assume INET(6) by default upon link creation: */ + case AF_INET: + case AF_INET6: + { + char hostbufOSMO_STREAM_MAX_ADDRSINET6_ADDRSTRLEN; + size_t num_hostbuf = ARRAY_SIZE(hostbuf); + char portbuf6; + bool need_more_bufs; + rc = osmo_sock_multiaddr_get_ip_and_port(link->ofd.fd, link->proto, &hostbuf00, + &num_hostbuf, sizeof(hostbuf0), + portbuf, sizeof(portbuf), true); + if (rc < 0) + return NULL; + need_more_bufs = num_hostbuf > ARRAY_SIZE(hostbuf); + if (need_more_bufs) + num_hostbuf = ARRAY_SIZE(hostbuf); + OSMO_STRBUF_APPEND(sb, osmo_multiaddr_ip_and_port_snprintf, + &hostbuf00, num_hostbuf, sizeof(hostbuf0), portbuf); + if (need_more_bufs) + OSMO_STRBUF_PRINTF(sb, "<need-more-bufs!>"); + return buf; + } + case AF_UNIX: + { + struct osmo_sockaddr osa; + struct sockaddr_un *sun; + socklen_t len = sizeof(osa.u.sas); + rc = getsockname(link->ofd.fd, &osa.u.sa, &len); + if (rc < 0) { + OSMO_STRBUF_PRINTF(sb, "<error-in-getsockname>"); + return buf; + } + /* Make sure sun_path is NULL terminated: */ + sun = (struct sockaddr_un *)&osa.u.sa; + sun->sun_pathsizeof(sun->sun_path) - 1 = '\0'; + OSMO_STRBUF_PRINTF(sb, "%s", sun->sun_path); + return buf; + } + default: + return NULL; + } +} + +/*! Retrieve description of the stream server link e. g. 127.0.0.1:1234. + * Calling this function will build a string that describes the socket in terms of its local/remote + * address/port. The returned name is stored in a static buffer; it is hence not re-entrant or thread-safe. * \paramin link Stream Server Link to examine * \returns Link description or NULL in case of error */ char *osmo_stream_srv_link_get_sockname(const struct osmo_stream_srv_link *link) { - static char bufINET6_ADDRSTRLEN + 6; - int rc = osmo_sock_get_local_ip(link->ofd.fd, buf, INET6_ADDRSTRLEN); - if (rc < 0) - return NULL; + static char bufsizeof(link->sockname); - bufstrnlen(buf, INET6_ADDRSTRLEN + 6) = ':'; - - rc = osmo_sock_get_local_ip_port(link->ofd.fd, buf + strnlen(buf, INET6_ADDRSTRLEN + 6), 6); - if (rc < 0) + if (!get_local_sockname_buf(buf, sizeof(buf), link)) return NULL; - return buf; } -/*! \brief Get Osmocom File Descriptor of the stream server link +/*! Retrieve Osmocom File Descriptor of the stream server link. * \paramin link Stream Server Link * \returns Pointer to \ref osmo_fd */ struct osmo_fd * @@ -366,7 +424,18 @@ return &link->ofd; } -/*! \brief Set the accept() call-back of the stream server link +/*! Retrieve File Descriptor of the stream server link. + * \paramin conn Stream Server Link + * \returns file descriptor or negative on error */ +int osmo_stream_srv_link_get_fd(const struct osmo_stream_srv_link *link) +{ + return link->ofd.fd; +} + +/*! Set the accept() call-back of the stream server link. + * The provided call-back will be called whenever a new inbound connection + * is accept()ed. The call-back then typically creates a new osmo_stream_srv. + * If the call-back returns a negative value, the file descriptor will be closed. * \paramin link Stream Server Link * \paramin accept_cb Call-back function executed upon accept() */ void osmo_stream_srv_link_set_accept_cb(struct osmo_stream_srv_link *link, @@ -376,7 +445,7 @@ link->accept_cb = accept_cb; } -/*! \brief Destroy the stream server link. Closes + Releases Memory. +/*! 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) { @@ -384,8 +453,8 @@ talloc_free(link); } -/*! \brief Open the stream server link. This actually initializes the - * underlying socket and binds it to the configured ip/port +/*! Open the stream server link. This actually initializes the + * underlying socket and binds it to the configured ip/port. * \paramin link Stream Server Link to open * \return negative on error, 0 on success */ int osmo_stream_srv_link_open(struct osmo_stream_srv_link *link) @@ -435,11 +504,11 @@ return -EIO; } - OSMO_STRLCPY_ARRAY(link->sockname, osmo_stream_srv_link_get_sockname(link)); + get_local_sockname_buf(link->sockname, sizeof(link->sockname), link); return 0; } -/*! \brief Check whether the stream server link is opened +/*! Check whether the stream server link is opened. * \paramin link Stream Server Link to check */ bool osmo_stream_srv_link_is_opened(const struct osmo_stream_srv_link *link) { @@ -452,7 +521,7 @@ return true; } -/*! \brief Close the stream server link and unregister from select loop +/*! Close the stream server link and unregister from select loop. * Does not destroy the server link, merely closes it! * \paramin link Stream Server Link to close */ void osmo_stream_srv_link_close(struct osmo_stream_srv_link *link) @@ -465,6 +534,12 @@ link->ofd.fd = -1; } +/*! Set given parameter of stream_srv_link to given value. + * \paramin cli stream client 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. + * \returns 0 in success; negative -errno on error. */ int osmo_stream_srv_link_set_param(struct osmo_stream_srv_link *link, enum osmo_stream_srv_link_param par, void *val, size_t val_len) { @@ -508,6 +583,8 @@ return 0; } +/*! @} */ + #define OSMO_STREAM_SRV_F_FLUSH_DESTROY (1 << 0) struct osmo_stream_srv { @@ -520,31 +597,45 @@ struct osmo_io_fd *iofd; }; struct llist_head tx_queue; - int (*closed_cb)(struct osmo_stream_srv *peer); - int (*read_cb)(struct osmo_stream_srv *peer); - int (*iofd_read_cb)(struct osmo_stream_srv *peer, struct msgb *msg); + 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; void *data; int flags; }; +/*! \addtogroup stream_srv + * @{ + */ + static void stream_srv_iofd_read_cb(struct osmo_io_fd *iofd, int res, struct msgb *msg) { struct osmo_stream_srv *conn = osmo_iofd_get_data(iofd); - LOGSSRV(conn, LOGL_DEBUG, "message received (res=%d)\n", res); - if (conn->flags & OSMO_STREAM_SRV_F_FLUSH_DESTROY) { + switch (res) { + case -EPIPE: + case -ECONNRESET: + LOGSSRV(conn, LOGL_ERROR, "lost connection with client (%d)\n", res); + break; + case 0: + LOGSSRV(conn, LOGL_NOTICE, "connection closed with client\n"); + break; + default: + LOGSSRV(conn, LOGL_DEBUG, "received %d bytes from client\n", res); + break; + } + if (OSMO_UNLIKELY(conn->flags & OSMO_STREAM_SRV_F_FLUSH_DESTROY)) { LOGSSRV(conn, LOGL_INFO, "Connection is being flushed and closed; ignoring received message\n"); msgb_free(msg); - return; - } - - if (res <= 0) { - osmo_stream_srv_set_flush_and_destroy(conn); if (osmo_iofd_txqueue_len(iofd) == 0) osmo_stream_srv_destroy(conn); - } else if (conn->iofd_read_cb) { - conn->iofd_read_cb(conn, msg); + return; } + + if (conn->iofd_read_cb) + conn->iofd_read_cb(conn, res, msg); + else + msgb_free(msg); } static void stream_srv_iofd_write_cb(struct osmo_io_fd *iofd, int res, struct msgb *msg) @@ -552,7 +643,7 @@ struct osmo_stream_srv *conn = osmo_iofd_get_data(iofd); LOGSSRV(conn, LOGL_DEBUG, "connected write\n"); - if (res == -1) + if (res < 0) LOGSSRV(conn, LOGL_ERROR, "error to send: %s\n", strerror(errno)); if (osmo_iofd_txqueue_len(iofd) == 0) @@ -560,10 +651,52 @@ osmo_stream_srv_destroy(conn); } -static struct osmo_io_ops srv_ioops = { +static const struct osmo_io_ops srv_ioops = { .read_cb = stream_srv_iofd_read_cb, .write_cb = stream_srv_iofd_write_cb, }; + +#ifdef HAVE_LIBSCTP +static void stream_srv_iofd_recvmsg_cb(struct osmo_io_fd *iofd, int res, struct msgb *msg, const struct msghdr *msgh) +{ + struct osmo_stream_srv *conn = osmo_iofd_get_data(iofd); + LOGSSRV(conn, LOGL_DEBUG, "message received (res=%d)\n", res); + + res = stream_iofd_sctp_recvmsg_trailer(iofd, msg, res, msgh); + + switch (res) { + case -EPIPE: + case -ECONNRESET: + LOGSSRV(conn, LOGL_ERROR, "lost connection with client (%d)\n", res); + break; + case 0: + LOGSSRV(conn, LOGL_NOTICE, "connection closed with client\n"); + break; + default: + if (OSMO_LIKELY(res > 0)) + LOGSSRV(conn, LOGL_DEBUG, "received %u bytes from client\n", res); + break; + } + if (OSMO_UNLIKELY(conn->flags & OSMO_STREAM_SRV_F_FLUSH_DESTROY)) { + LOGSSRV(conn, LOGL_INFO, "Connection is being flushed and closed; ignoring received message\n"); + msgb_free(msg); + if (osmo_iofd_txqueue_len(iofd) == 0) + osmo_stream_srv_destroy(conn); + return; + } + + if (conn->iofd_read_cb) + conn->iofd_read_cb(conn, res, msg); + else + msgb_free(msg); +} + +static const struct osmo_io_ops srv_ioops_sctp = { + .recvmsg_cb = stream_srv_iofd_recvmsg_cb, + .sendmsg_cb = stream_srv_iofd_write_cb, +}; +#endif + static int osmo_stream_srv_read(struct osmo_stream_srv *conn) { int rc = 0; @@ -670,7 +803,16 @@ return rc; } -/*! \brief Create a Stream Server inside the specified link + +/*! Create a legacy osmo_fd mode Stream Server inside the specified link. + * + * This is the function an application traditionally calls from within the + * accept_cb call-back of the osmo_stream_srv_link. It creates a new + * osmo_stream_srv within that link. + * + * New users/programs should use osmo_stream_srv_create2 to operate in osmo_io + * mode instead. + * * \paramin ctx talloc allocation context from which to allocate * \paramin link Stream Server Link to which we belong * \paramin fd system file descriptor of the new connection @@ -679,10 +821,10 @@ * \paramin data User data to save in the new Stream Server struct * \returns Stream Server in case of success; NULL on error */ struct osmo_stream_srv * -osmo_stream_srv_create(void *ctx, struct osmo_stream_srv_link *link, - int fd, - int (*read_cb)(struct osmo_stream_srv *conn), - int (*closed_cb)(struct osmo_stream_srv *conn), void *data) +osmo_stream_srv_create(void *ctx, struct osmo_stream_srv_link *link, int fd, + osmo_stream_srv_read_cb_t read_cb, + osmo_stream_srv_closed_cb_t closed_cb, + void *data) { struct osmo_stream_srv *conn; @@ -710,7 +852,12 @@ return conn; } -/*! \brief Create a Stream Server inside the specified link +/*! Create an osmo_iofd mode Stream Server inside the specified link. + * + * This is the function an application typically calls from within the + * accept_cb call-back of the osmo_stream_srv_link. It creates a new + * osmo_stream_srv in osmo_io mode within that link. + * * \paramin ctx talloc allocation context from which to allocate * \paramin link Stream Server Link to which we belong * \paramin fd system file descriptor of the new connection @@ -732,8 +879,15 @@ osmo_sock_get_name_buf(conn->sockname, sizeof(conn->sockname), fd); - conn->iofd = osmo_iofd_setup(conn, fd, conn->sockname, - OSMO_IO_FD_MODE_READ_WRITE, &srv_ioops, conn); + if (link->proto == IPPROTO_SCTP) { + conn->iofd = osmo_iofd_setup(conn, fd, conn->sockname, OSMO_IO_FD_MODE_RECVMSG_SENDMSG, + &srv_ioops_sctp, conn); + if (conn->iofd) + osmo_iofd_set_cmsg_size(conn->iofd, CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))); + } else { + conn->iofd = osmo_iofd_setup(conn, fd, conn->sockname, OSMO_IO_FD_MODE_READ_WRITE, + &srv_ioops, conn); + } if (!conn->iofd) { talloc_free(conn); return NULL; @@ -749,8 +903,9 @@ return conn; } -/*! \brief Set a name on the srv object (used during logging) - * \paramin conn server whose name is to be set +/*! Set a name on the srv object (used during logging). + * \paramin conn server whose name is to be set. The name is copied into the osmo_stream_srv_link, so + * the caller memory is not required to be valid beyond the call of this function. * \paramin name the name to be set on conn */ void osmo_stream_srv_set_name(struct osmo_stream_srv *conn, const char *name) @@ -760,26 +915,45 @@ osmo_iofd_set_name(conn->iofd, name); } -/*! \brief Set the call-back function when data was read from the stream server socket - * Only for osmo_stream_srv created with osmo_stream_srv_create2() +/*! Retrieve name previously set on the srv object (see osmo_stream_srv_set_name()). + * \paramin conn server whose name is to be retrieved + * \returns The name to be set on conn; NULL if never set + */ +const char *osmo_stream_srv_get_name(const struct osmo_stream_srv *conn) +{ + return conn->name; +} + +/*! Set the call-back function for incoming data on an osmo_io stream_srv. + * + * This function only works with osmo_stream_srv in osmo_io mode, created by osmo_stream_srv_create2()! + * + * Whenever data is received on the osmo_stram_srv, the read_cb call-back function of the user application is + * called. + * * \paramin conn Stream Server to modify * \paramin read_cb Call-back function to be called when data was read */ -void osmo_stream_srv_set_read_cb(struct osmo_stream_srv *conn, int (*read_cb)(struct osmo_stream_srv *conn, struct msgb *msg)) +void osmo_stream_srv_set_read_cb(struct osmo_stream_srv *conn, + osmo_stream_srv_read_cb2_t read_cb) { OSMO_ASSERT(conn && conn->mode == OSMO_STREAM_MODE_OSMO_IO); conn->iofd_read_cb = read_cb; } -/*! \brief Set the call-back function called when the stream server socket was closed +/*! Set the call-back function called when the stream server socket was closed. + * Whenever the socket was closed (network error, client disconnect, etc.), the user-provided + * call-back function given here is called. This is typically used by the application to clean up any of its + * internal state related to this specific client/connection. * \paramin conn Stream Server to modify * \paramin closed_cb Call-back function to be called when the connection was closed */ -void osmo_stream_srv_set_closed_cb(struct osmo_stream_srv *conn, int (*closed_cb)(struct osmo_stream_srv *conn)) +void osmo_stream_srv_set_closed_cb(struct osmo_stream_srv *conn, + osmo_stream_srv_closed_cb_t closed_cb) { OSMO_ASSERT(conn); conn->closed_cb = closed_cb; } -/*! \brief Prepare to send out all pending messages on the connection's Tx queue +/*! Prepare to send out all pending messages on the connection's Tx queue. * and then automatically destroy the stream with osmo_stream_srv_destroy(). * This function disables queuing of new messages on the connection and also * disables reception of new messages on the connection. @@ -789,7 +963,7 @@ conn->flags |= OSMO_STREAM_SRV_F_FLUSH_DESTROY; } -/*! \brief Set application private data of the stream server +/*! Set application private data of the stream server. * \paramin conn Stream Server to modify * \paramin data User-specific data (available in call-back functions) */ void @@ -799,24 +973,33 @@ conn->data = data; } -/*! \brief Set the segmentation callback for target osmo_stream_srv structure. - * The connection has to have been established prior to calling this function. +/*! Set the segmentation callback for target osmo_stream_srv structure. + * + * A segmentation call-back can optionally be used when a packet based protocol (like TCP) is used within a + * STREAM style socket that does not preserve message boundaries within the stream. If a segmentation + * call-back is given, the osmo_stream_srv library code will makes sure that the read_cb called only for + * complete single messages, and not arbitrary segments of the stream. + * + * This function only works with osmo_stream_srv in osmo_io mode, created by osmo_stream_srv_create2()! + * The connection has to have been established prior to calling this function. + * * \paramin,out conn Target Stream Server to modify * \paramin segmentation_cb Segmentation callback to be set */ void osmo_stream_srv_set_segmentation_cb(struct osmo_stream_srv *conn, - int (*segmentation_cb)(struct msgb *msg)) + osmo_stream_srv_segmentation_cb_t segmentation_cb) { /* Note that the following implies that iofd != NULL, since * osmo_stream_srv_create2() creates the iofd member, too */ OSMO_ASSERT(conn->mode == OSMO_STREAM_MODE_OSMO_IO); /* Copy default settings */ - struct osmo_io_ops conn_ops = srv_ioops; + struct osmo_io_ops conn_ops; + osmo_iofd_get_ioops(conn->iofd, &conn_ops); /* Set segmentation cb for this connection */ conn_ops.segmentation_cb = segmentation_cb; osmo_iofd_set_ioops(conn->iofd, &conn_ops); } -/*! \brief Get application private data of the stream server +/*! Retrieve application private data of the stream server * \paramin conn Stream Server * \returns Application private data, as set by \ref osmo_stream_srv_set_data() */ void *osmo_stream_srv_get_data(struct osmo_stream_srv *conn) @@ -824,16 +1007,60 @@ return conn->data; } -/*! \brief Get Osmocom File Descriptor of the stream server +/*! Retrieve the stream server socket description. + * The returned name is stored in a static buffer; it is hence not re-entrant or thread-safe! + * \paramin cli Stream Server to examine + * \returns Socket description or NULL in case of error */ +const char *osmo_stream_srv_get_sockname(const struct osmo_stream_srv *conn) +{ + static char bufOSMO_STREAM_MAX_ADDRS * OSMO_SOCK_NAME_MAXLEN; + + osmo_sock_multiaddr_get_name_buf(buf, sizeof(buf), + osmo_stream_srv_get_fd(conn), conn->srv->proto); + + return buf; +} + +/*! Retrieve Osmocom File Descriptor of a stream server in osmo_fd mode. * \paramin conn Stream Server * \returns Pointer to \ref osmo_fd */ struct osmo_fd * osmo_stream_srv_get_ofd(struct osmo_stream_srv *conn) { + OSMO_ASSERT(conn->mode == OSMO_STREAM_MODE_OSMO_FD); return &conn->ofd; } -/*! \brief Get the master (Link) from a Stream Server +/*! Retrieve File Descriptor of the stream server + * \paramin conn Stream Server + * \returns file descriptor or negative on error */ +int +osmo_stream_srv_get_fd(const struct osmo_stream_srv *conn) +{ + switch (conn->mode) { + case OSMO_STREAM_MODE_OSMO_FD: + return conn->ofd.fd; + case OSMO_STREAM_MODE_OSMO_IO: + if (conn->iofd) + return osmo_iofd_get_fd(conn->iofd); + default: + break; + } + return -EINVAL; +} + +/*! Retrieve osmo_io descriptor of the stream server socket. + * This function must not be called on a stream server in legacy osmo_fd mode! + * \paramin srv Stream Server of which we want to obtain the osmo_io descriptor + * \returns osmo_io_fd of stream server. */ +struct osmo_io_fd * +osmo_stream_srv_get_iofd(const struct osmo_stream_srv *srv) +{ + OSMO_ASSERT(srv->mode == OSMO_STREAM_MODE_OSMO_IO); + return srv->iofd; +} + +/*! Retrieve the master (Link) from a Stream Server. * \paramin conn Stream Server of which we want to know the Link * \returns Link through which the given Stream Server is established */ struct osmo_stream_srv_link *osmo_stream_srv_get_master(struct osmo_stream_srv *conn) @@ -841,11 +1068,10 @@ return conn->srv; } -/*! \brief Destroy given Stream Server - * This function closes the Stream Server socket, unregisters from - * select loop, invokes the connection's closed_cb() callback to allow API - * users to clean up any associated state they have for this connection, - * and then de-allocates associated memory. +/*! Destroy given Stream Server. + * This function closes the Stream Server socket, unregisters from the underlying I/O mechanism, invokes the + * connection's closed_cb() callback to allow API users to clean up any associated state they have for this + * connection, and then de-allocates associated memory. * \paramin conn Stream Server to be destroyed */ void osmo_stream_srv_destroy(struct osmo_stream_srv *conn) { @@ -858,6 +1084,7 @@ break; case OSMO_STREAM_MODE_OSMO_IO: osmo_iofd_free(conn->iofd); + conn->iofd = NULL; break; default: OSMO_ASSERT(false); @@ -867,11 +1094,13 @@ talloc_free(conn); } -/*! \brief Enqueue data to be sent via an Osmocom stream server +/*! Enqueue data to be sent via an Osmocom stream server. * \paramin conn Stream Server through which we want to send * \paramin msg Message buffer to enqueue in transmit queue */ void osmo_stream_srv_send(struct osmo_stream_srv *conn, struct msgb *msg) { + int rc; + OSMO_ASSERT(conn); OSMO_ASSERT(msg); if (conn->flags & OSMO_STREAM_SRV_F_FLUSH_DESTROY) { @@ -886,18 +1115,27 @@ osmo_fd_write_enable(&conn->ofd); break; case OSMO_STREAM_MODE_OSMO_IO: - osmo_iofd_write_msgb(conn->iofd, msg); + if (conn->srv->proto == IPPROTO_SCTP) + rc = stream_iofd_sctp_send_msgb(conn->iofd, msg, MSG_NOSIGNAL); + else + rc = osmo_iofd_write_msgb(conn->iofd, msg); + if (rc < 0) + msgb_free(msg); break; default: OSMO_ASSERT(false); } } -/*! \brief Receive data via Osmocom stream server +/*! Receive data via an Osmocom stream server in osmo_fd mode. * \paramin conn Stream Server from which to receive * \param msg pre-allocate message buffer to which received data is appended * \returns number of bytes read, negative on error. * + * Application programs using the legacy osmo_fd mode of osmo_stream_srv will use + * this function to read/receive from a stream socket after they have been notified that + * it is readable (via select/poll). + * * If conn is an SCTP connection, additional specific considerations shall be taken: * - msg->cb is always filled with SCTP ppid, and SCTP stream values, see msgb_sctp_*() APIs. * - If an SCTP notification was received when reading from the SCTP socket, @@ -913,6 +1151,7 @@ int ret; OSMO_ASSERT(conn); OSMO_ASSERT(msg); + OSMO_ASSERT(conn->mode == OSMO_STREAM_MODE_OSMO_FD); switch (conn->srv->sk_domain) { case AF_UNIX: @@ -956,8 +1195,19 @@ void osmo_stream_srv_clear_tx_queue(struct osmo_stream_srv *conn) { - msgb_queue_free(&conn->tx_queue); - osmo_fd_write_disable(&conn->ofd); + switch (conn->mode) { + case OSMO_STREAM_MODE_OSMO_FD: + msgb_queue_free(&conn->tx_queue); + osmo_fd_write_disable(&conn->ofd); + break; + case OSMO_STREAM_MODE_OSMO_IO: + osmo_iofd_txqueue_clear(conn->iofd); + break; + case OSMO_STREAM_MODE_UNKNOWN: + default: + break; + } + if (conn->flags & OSMO_STREAM_SRV_F_FLUSH_DESTROY) osmo_stream_srv_destroy(conn); }
View file
libosmo-netif_1.4.0.tar.xz/tests/stream/stream_test.c -> libosmo-netif_1.5.0.tar.xz/tests/stream/stream_test.c
Changed
@@ -121,6 +121,7 @@ osmo_stream_cli_set_data(cli, msg); CLI_SND(cli, "Doh, responding to server :-D"); } + msgb_free(msg); return 0; } @@ -299,6 +300,7 @@ than it must be subsequent (after reconnect) call */ request_test_stop(srv); } + msgb_free(msg); osmo_stream_srv_destroy(srv); return -EINVAL; } else { @@ -340,10 +342,17 @@ bool autoreconnect) { struct timeval tv; - struct osmo_stream_cli *cli = make_client(ctx, host, port, autoreconnect); + struct osmo_stream_cli *cli; + if (osmo_stream_srv_link_open(lnk) < 0) { + printf("Unable to open server\n"); + osmo_stream_srv_link_destroy(lnk); + return; + } + cli = make_client(ctx, host, port, autoreconnect); if (!cli) return; + printf("=======================================\n"); printf("Client/Server entering %s event loop...\n", ASTR(autoreconnect)); printf("=======================================\n"); @@ -368,6 +377,7 @@ } osmo_stream_cli_destroy(cli); + osmo_stream_srv_link_close(lnk); printf("{%lu.%06lu} %s test complete.\n\n", tv.tv_sec, tv.tv_usec, ASTR(autoreconnect)); } @@ -384,12 +394,17 @@ IPAC_PROTO_IPACCESS, IPAC_MSGT_PONG }; +#define IPAC_MSG_IDREQ_PAYLOAD_INITIALIZER \ + IPAC_MSGT_ID_GET, \ + 0x01, IPAC_IDTAG_UNITNAME +static const uint8_t ipac_msg_idreq_payload = { + IPAC_MSG_IDREQ_PAYLOAD_INITIALIZER +}; #define IPAC_MSG_ID_REQ_LEN 0x03 static const uint8_t ipac_msg_idreq = { 0x00, IPAC_MSG_ID_REQ_LEN, IPAC_PROTO_IPACCESS, - IPAC_MSGT_ID_GET, - 0x01, IPAC_IDTAG_UNITNAME + IPAC_MSG_IDREQ_PAYLOAD_INITIALIZER }; #define ipac_msg_idreq_third (sizeof(ipac_msg_idreq)/3) #define ipac_msg_idreq_last_third (sizeof(ipac_msg_idreq) - 2 * ipac_msg_idreq_third) @@ -487,19 +502,23 @@ static struct osmo_timer_list fragmented_send_tl_cli; -static int test_segm_ipa_stream_srv_cli_read_cb(struct osmo_stream_cli *osc, struct msgb *msg) +static int test_segm_ipa_stream_srv_cli_read_cb(struct osmo_stream_cli *osc, int res, struct msgb *msg) { unsigned char *data; - struct ipa_head *h = (struct ipa_head *) msg->data; - uint8_t ipac_msg_type = ((uint8_t *)h)sizeof(struct ipa_head); - struct msgb *reply = msgb_alloc_headroom(128, 0, "IPA reply"); - if (reply == NULL) { - fprintf(stderr, "Cannot allocate message\n"); - return -ENOMEM; + struct ipa_head *h = (struct ipa_head *) msg->l1h; + uint8_t ipac_msg_type = *msg->data; + struct msgb *reply; + + if (res < 0) { + fprintf(stderr, "cannot receive message (res = %d)\n", res); + msgb_free(msg); + return -ENOMSG; } - LOGCLI(osc, "Received message from stream (total len = %" PRIu16 ")\n", msgb_length(msg)); + + LOGCLI(osc, "Received message from stream (payload len = %" PRIu16 ")\n", msgb_length(msg)); if (ipac_msg_type < 0 || 5 < ipac_msg_type) { fprintf(stderr, "Received unexpected IPAC message type %"PRIu8"\n", ipac_msg_type); + msgb_free(msg); return -ENOMSG; } LOGCLI(osc, "\tType: %s\n", IPAC_MSG_TYPESipac_msg_type); @@ -507,6 +526,11 @@ LOGCLI(osc, "Got IPAC_MSGT_ID_GET from server\n"); LOGCLI(osc, "(%u + 2/3) -cli Appending: Second third of IPAC_MSGT_ID_GET\n", test_segm_ipa_stream_srv_msglognum_cli); + reply = msgb_alloc_headroom(128, 0, "IPA reply"); + if (reply == NULL) { + fprintf(stderr, "Cannot allocate message\n"); + return -ENOMEM; + } data = msgb_put(reply, ipac_msg_idreq_third); memcpy(data, ipac_msg_idreq + ipac_msg_idreq_third, ipac_msg_idreq_third); @@ -522,17 +546,14 @@ LOGCLI(osc, "\texpected=%s\n", osmo_hexdump(ipac_msg_idresp, sizeof(ipac_msg_idresp))); } + msgb_free(msg); printf("\n"); return 0; } -static void *test_segm_ipa_stream_srv_run_client(void) +struct osmo_stream_cli *test_segm_ipa_stream_srv_run_client(void *ctx) { - struct osmo_stream_cli *osc; - void *ctx = talloc_named_const(NULL, 0, __func__); - - (void) msgb_talloc_ctx_init(ctx, 0); - osc = osmo_stream_cli_create(ctx); + struct osmo_stream_cli *osc = osmo_stream_cli_create(ctx); if (osc == NULL) { fprintf(stderr, "osmo_stream_cli_create_iofd()\n"); return NULL; @@ -541,55 +562,67 @@ osmo_stream_cli_set_local_port(osc, 8977); osmo_stream_cli_set_port(osc, 1111); osmo_stream_cli_set_connect_cb(osc, test_segm_ipa_stream_srv_cli_connect_cb); - osmo_stream_cli_set_data(osc, ctx); osmo_stream_cli_set_read_cb2(osc, test_segm_ipa_stream_srv_cli_read_cb); osmo_stream_cli_set_nodelay(osc, true); if (osmo_stream_cli_open(osc) < 0) { fprintf(stderr, "Cannot open stream client\n"); return NULL; } + osmo_stream_cli_set_segmentation_cb(osc, osmo_ipa_segmentation_cb); - return NULL; + return osc; } -int test_segm_ipa_stream_srv_srv_read_cb(struct osmo_stream_srv *conn, struct msgb *msg) +int test_segm_ipa_stream_srv_srv_read_cb(struct osmo_stream_srv *conn, int res, struct msgb *msg) { static unsigned msgnum_srv = 0; struct ipa_head *ih = (struct ipa_head *)msg->l1h; unsigned char *data; struct msgb *m; - uint8_t *msgt = msg->l2h; /* Octet right after IPA header */ + uint8_t msgt; + + if (res <= 0) { + if (res < 0) + LOGSRV(conn, "cannot receive message: %s\n", strerror(-res)); + else + LOGSRV(conn, "client closed connection\n"); + msgb_free(msg); + osmo_stream_srv_destroy(conn); + return -EBADF; + } + LOGSRV(conn, "%u-srv Received IPA message from stream (payload len = %" PRIu16 ")\n", ++msgnum_srv, msgb_length(msg)); LOGSRV(conn, "\tmsg buff data (including stripped headers): %s\n", osmo_hexdump((unsigned char *)ih, osmo_ntohs(ih->len) + sizeof(*ih))); LOGSRV(conn, "\tIPA payload: %s\n", osmo_hexdump(ih->data, osmo_ntohs(ih->len))); - LOGSRV(conn, "\tType: %s\n", IPAC_MSG_TYPES*msgt); + + msgt = *msg->l2h; /* Octet right after IPA header */ + LOGSRV(conn, "\tType: %s\n", IPAC_MSG_TYPESmsgt); LOGSRV(conn, "\t(msg dump: %s)\n", osmo_hexdump(msg->l1h, msg->len + sizeof(struct ipa_head))); - if (*msgt == IPAC_MSGT_ID_RESP) { /* */ + + msgb_free(msg); + + if (msgt == IPAC_MSGT_ID_RESP) { /* */ LOGSRV(conn, "Send IPAC_MSGT_ID_GET to trigger client to send next third\n\n"); - m = msgb_alloc_headroom(128, 0, "IPA messages"); + m = osmo_ipa_msg_alloc(128); if (m == NULL) { fprintf(stderr, "Cannot allocate message\n"); return -ENOMEM; } - put_ipa_msg(data, m, ipac_msg_idreq); + put_ipa_msg(data, m, ipac_msg_idreq_payload); + osmo_ipa_msg_push_headers(m, IPAC_PROTO_IPACCESS, -1); osmo_stream_srv_send(conn, m); - } else if (msgnum_srv == 7 && *msgt == IPAC_MSGT_PONG) { + } else if (msgnum_srv == 7 && msgt == IPAC_MSGT_PONG) { test_segm_ipa_stream_srv_all_msgs_processed = true; + osmo_stream_srv_destroy(conn); } return 0; } -static int test_segm_ipa_stream_srv_srv_close_cb(struct osmo_stream_srv *conn) -{ - osmo_stream_srv_set_segmentation_cb(conn, NULL); - return 0; -} - static int test_segm_ipa_stream_srv_srv_accept_cb(struct osmo_stream_srv_link *srv, int fd) { - void *ctx = talloc_named_const(NULL, 0, __func__); + void *ctx = osmo_stream_srv_link_get_data(srv); struct osmo_stream_srv *oss = osmo_stream_srv_create2(ctx, srv, fd, NULL); if (oss == NULL) { @@ -598,13 +631,13 @@ } osmo_stream_srv_set_segmentation_cb(oss, osmo_ipa_segmentation_cb); osmo_stream_srv_set_read_cb(oss, test_segm_ipa_stream_srv_srv_read_cb); - osmo_stream_srv_set_closed_cb(oss, test_segm_ipa_stream_srv_srv_close_cb); return 0; } static void test_segm_ipa_stream_srv_run(void *ctx, const char *host, unsigned port, struct osmo_stream_srv_link *srv) { + struct osmo_stream_cli *osc; const char *testname = "test_segm_ipa_stream_srv"; osmo_stream_srv_link_set_accept_cb(srv, test_segm_ipa_stream_srv_srv_accept_cb); @@ -612,7 +645,7 @@ printf("Unable to open server\n"); exit(1); } - test_segm_ipa_stream_srv_run_client(); + osc = test_segm_ipa_stream_srv_run_client(ctx); printf("______________________________________Running test %s______________________________________\n", testname); alarm(2); @@ -623,6 +656,9 @@ } alarm(0); printf("==================================Test %s complete========================================\n\n", testname); + if (osc) + osmo_stream_cli_destroy(osc); + osmo_stream_srv_link_close(srv); } static void sigalarm_handler(int _foo) @@ -631,6 +667,227 @@ exit(EXIT_FAILURE); } +static struct osmo_timer_list fragmented_send_tl_srv; +static struct osmo_timer_list fragmented_send_tl_srv_destroy; + +static unsigned test_segm_ipa_stream_cli_srv_msglognum = 0; + +/* Like CLI_APPEND_MSG, but for server side */ +#define SRV_APPEND_MSG(OSMO_STREAM_SRV_PTR, UCHAR_PTR_DST, STRUCT_MSGB_PTR, SRC_IPAC_MSG_BUF) do {\ + LOGSRV(OSMO_STREAM_SRV_PTR, "%u-srv Appending msg of type %s into buffer\n",\ + ++test_segm_ipa_stream_cli_srv_msglognum, IPAC_MSG_TYPESSRC_IPAC_MSG_BUFIPAC_MSGT_OFFSET);\ + LOGSRV(OSMO_STREAM_SRV_PTR, "\t(msg dump: %s)\n", osmo_hexdump(SRC_IPAC_MSG_BUF,\ + sizeof(SRC_IPAC_MSG_BUF)));\ + put_ipa_msg(UCHAR_PTR_DST, STRUCT_MSGB_PTR, SRC_IPAC_MSG_BUF);\ +} while (0) + +static void destroy_conn(void *osmo_stream_srv_arg) +{ + osmo_stream_srv_destroy(osmo_stream_srv_arg); +} + +static void send_last_third_srv(void *osmo_stream_srv_arg) +{ + struct osmo_stream_srv *oss = osmo_stream_srv_arg; + unsigned char *data; + struct msgb *reply = msgb_alloc_headroom(128, 0, "IPA delayed reply"); + + LOGSRV(oss, "Delay for sending last third of message is over\n"); + if (reply == NULL) { + fprintf(stderr, "Cannot allocate message\n"); + return; + } + LOGSRV(oss, "%u-srv Appending: Last third of IPAC_MSGT_ID_GET\n", + ++test_segm_ipa_stream_cli_srv_msglognum); + data = msgb_put(reply, ipac_msg_idreq_last_third); + memcpy(data, ipac_msg_idreq + 2 * ipac_msg_idreq_third, + ipac_msg_idreq_last_third); + /* Append two entire messages */ + SRV_APPEND_MSG(oss, data, reply, ipac_msg_pong); + SRV_APPEND_MSG(oss, data, reply, ipac_msg_pong); + LOGSRV(oss, "\tSending:" + " Last third of IPAC_MSGT_ID_GET | IPAC_MSGT_PONG | IPAC_MSGT_PONG \n"); + LOGSRV(oss, "\t(msg dump: %s)\n\n", osmo_hexdump(reply->data, reply->len)); + osmo_stream_srv_send(oss, reply); + osmo_timer_setup(&fragmented_send_tl_srv_destroy, destroy_conn, oss); + osmo_timer_add(&fragmented_send_tl_srv_destroy); + /* 2 select loop iterations needed, timing only 1 will leave the client side hanging while waiting + * to receive the last messages */ + osmo_timer_schedule(&fragmented_send_tl_srv_destroy, 0, 2); +} + +int test_segm_ipa_stream_cli_srv_read_cb(struct osmo_stream_srv *conn, int res, struct msgb *msg) +{ + unsigned char *data; + struct ipa_head *h = (struct ipa_head *) msg->l1h; + uint8_t ipa_msg_type; + struct msgb *reply; + + if (res <= 0) { + if (res < 0) + LOGSRV(conn, "cannot receive message: %s\n", strerror(-res)); + else + LOGSRV(conn, "client closed connection\n"); + msgb_free(msg); + osmo_stream_srv_destroy(conn); + return -EBADF; + } + + ipa_msg_type = ((uint8_t *)h)sizeof(struct ipa_head); + + reply = msgb_alloc_headroom(128, 0, "IPA reply"); + if (reply == NULL) { + fprintf(stderr, "Cannot allocate message\n"); + return -ENOMEM; + } + LOGSRV(conn, "Received message from stream (total len including stripped headers = %lu)\n", + osmo_ntohs(h->len) + sizeof(*h)); + if (5 < ipa_msg_type) { + fprintf(stderr, "Received unexpected IPAC message type %"PRIu8"\n", ipa_msg_type); + return -ENOMSG; + } + LOGSRV(conn, "\tType: %s\n", IPAC_MSG_TYPESipa_msg_type); + if (ipa_msg_type == IPAC_MSGT_ID_GET) { + LOGSRV(conn, "Got IPAC_MSGT_ID_GET from client\n"); + LOGSRV(conn, "(%u + 2/3) -srv Appending: Second third of IPAC_MSGT_ID_GET\n", + test_segm_ipa_stream_cli_srv_msglognum); + data = msgb_put(reply, ipac_msg_idreq_third); + memcpy(data, ipac_msg_idreq + ipac_msg_idreq_third, + ipac_msg_idreq_third); + LOGSRV(conn, "\tSending: Second third of IPAC_MSGT_ID_GET\n"); + LOGSRV(conn, "\t(msg dump: %s)\n", osmo_hexdump(reply->data, reply->len)); + osmo_stream_srv_send(conn, reply); + osmo_timer_setup(&fragmented_send_tl_srv, send_last_third_srv, conn); + osmo_timer_add(&fragmented_send_tl_srv); + osmo_timer_schedule(&fragmented_send_tl_srv, 0, 125000); + } else if (ipa_msg_type == IPAC_MSGT_ID_RESP) { + LOGSRV(conn, "\tresult= %s\n", + osmo_hexdump((const unsigned char *)h, sizeof(*h) + h->len)); + LOGSRV(conn, "\texpected=%s\n", + osmo_hexdump(ipac_msg_idresp, sizeof(ipac_msg_idresp))); + } + printf("\n"); + return 0; +} + +static int test_segm_ipa_stream_cli_srv_accept_cb(struct osmo_stream_srv_link *srv, int fd) +{ + void *ctx = osmo_stream_srv_link_get_data(srv); + struct osmo_stream_srv *oss = + osmo_stream_srv_create2(ctx, srv, fd, NULL); + unsigned char *data; + struct msgb *m = msgb_alloc_headroom(128, 0, "IPA messages"); + if (oss == NULL) { + fprintf(stderr, "Error while creating connection\n"); + return -1; + } + if (m == NULL) { + fprintf(stderr, "Cannot allocate message\n"); + return -ENOMEM; + } + osmo_stream_srv_set_segmentation_cb(oss, osmo_ipa_segmentation_cb); + osmo_stream_srv_set_read_cb(oss, test_segm_ipa_stream_cli_srv_read_cb); + + /* Send 4 and 1/3 messages, as done analogously in test_segm_ipa_stream_srv_cli_connect_cb() */ + /* Append 4 */ + SRV_APPEND_MSG(oss, data, m, ipac_msg_ping); + SRV_APPEND_MSG(oss, data, m, ipac_msg_pong); + SRV_APPEND_MSG(oss, data, m, ipac_msg_ping); + SRV_APPEND_MSG(oss, data, m, ipac_msg_idresp); + /* Append 1/3 */ + LOGSRV(oss, "(0%u + 1/3)-srv Appending 1st third of msg of type %s into buffer\n", + test_segm_ipa_stream_cli_srv_msglognum, IPAC_MSG_TYPESipac_msg_idreq3); + LOGSRV(oss, "\t(dump: %s)\n", osmo_hexdump(ipac_msg_idreq, ipac_msg_idreq_third)); + data = msgb_put(m, ipac_msg_idreq_third); + memcpy(data, ipac_msg_idreq, ipac_msg_idreq_third); + + LOGSRV(oss, "Sending 4 + 1/3 messages as one:\n"); + LOGSRV(oss, "\t(msg dump: %s)\n\n", osmo_hexdump(m->data, m->len)); + osmo_stream_srv_send(oss, m); + return 0; +} + +static bool test_segm_ipa_stream_cli_all_msgs_processed = false; + +static int test_segm_ipa_stream_cli_cli_read_cb(struct osmo_stream_cli *osc, int res, struct msgb *msg) +{ + static unsigned msgnum_cli = 0; + unsigned char *data; + struct msgb *m; + uint8_t *msgt = msg->data; + LOGCLI(osc, "%u-cli Received message from stream (len = %" PRIu16 ")\n", + ++msgnum_cli, msgb_length(msg)); + LOGCLI(osc, "\tmsg buff data: %s\n", osmo_hexdump(msg->data, msg->len)); + LOGCLI(osc, "\tIPA payload: %s\n", osmo_hexdump(msg->data, msg->len)); + LOGCLI(osc, "\tType: %s\n", IPAC_MSG_TYPES*msgt); + LOGCLI(osc, "\t(msg dump (including stripped headers): %s)\n", + osmo_hexdump(msg->l1h, sizeof(struct ipa_head) + msg->len)); + if (*msgt == IPAC_MSGT_ID_RESP) { + LOGCLI(osc, "Send IPAC_MSGT_ID_GET to trigger server to send next third\n\n"); + m = msgb_alloc_headroom(128, sizeof(struct ipa_head) + + sizeof(struct ipa_head_ext), "IPA messages"); + if (m == NULL) { + fprintf(stderr, "Cannot allocate message\n"); + return -ENOMEM; + } + put_ipa_msg(data, m, ipac_msg_idreq_payload); + osmo_ipa_msg_push_headers(m, IPAC_PROTO_IPACCESS, -1); + osmo_stream_cli_send(osc, m); + } else if (msgnum_cli == 7 && *msgt == IPAC_MSGT_PONG) { + test_segm_ipa_stream_cli_all_msgs_processed = true; + } + return 0; +} + +static struct osmo_stream_cli *test_segm_ipa_stream_cli_run_client(void *ctx) +{ + struct osmo_stream_cli *osc = osmo_stream_cli_create(ctx); + if (osc == NULL) { + fprintf(stderr, "osmo_stream_cli_create_iofd()\n"); + return NULL; + } + osmo_stream_cli_set_addr(osc, "127.0.0.11"); + osmo_stream_cli_set_local_port(osc, 8977); + osmo_stream_cli_set_port(osc, 1112); + osmo_stream_cli_set_read_cb2(osc, test_segm_ipa_stream_cli_cli_read_cb); + osmo_stream_cli_set_nodelay(osc, true); + osmo_stream_cli_set_segmentation_cb(osc, osmo_ipa_segmentation_cb); + if (osmo_stream_cli_open(osc) < 0) { + fprintf(stderr, "Cannot open stream client\n"); + return NULL; + } + + return osc; +} + +static void test_segm_ipa_stream_cli_run(void *ctx, const char *host, unsigned port, + struct osmo_stream_srv_link *srv) +{ + const char *testname = "test_segm_ipa_stream_cli"; + struct osmo_stream_cli *osc = NULL; + osmo_stream_srv_link_set_accept_cb(srv, + test_segm_ipa_stream_cli_srv_accept_cb); + osmo_stream_srv_link_set_port(srv, 1112); + if (osmo_stream_srv_link_open(srv) < 0) { + printf("Unable to open server\n"); + exit(1); + } + osc = test_segm_ipa_stream_cli_run_client(ctx); + + printf("______________________________________Running test %s______________________________________\n", testname); + alarm(2); + + while (!test_segm_ipa_stream_cli_all_msgs_processed) { + osmo_gettimeofday_override_add(0, 1); /* small increment to easily spot iterations */ + osmo_select_main(1); + } + alarm(0); + printf("==================================Test %s complete========================================\n\n", testname); + if (osc) + osmo_stream_cli_destroy(osc); + osmo_stream_srv_link_close(srv); +} + int main(void) { @@ -648,9 +905,8 @@ osmo_gettimeofday_override_time.tv_sec = 2; osmo_gettimeofday_override_time.tv_usec = 0; - msgb_talloc_ctx_init(tall_test, 0); osmo_init_logging2(tall_test, &osmo_stream_test_log_info); - log_set_log_level(osmo_stderr_target, LOGL_INFO); + log_set_log_level(osmo_stderr_target, LOGL_DEBUG); log_set_use_color(osmo_stderr_target, 0); log_set_print_category_hex(osmo_stderr_target, 0); log_set_print_category(osmo_stderr_target, 0); @@ -667,20 +923,19 @@ osmo_stream_srv_link_set_addr(srv, host); osmo_stream_srv_link_set_port(srv, port); osmo_stream_srv_link_set_accept_cb(srv, accept_cb_srv); - - if (osmo_stream_srv_link_open(srv) < 0) { - printf("Unable to open server\n"); - osmo_stream_srv_link_destroy(srv); - return EXIT_FAILURE; - } + osmo_stream_srv_link_set_nodelay(srv, true); test_recon(tall_test, host, port, 12, srv, true); test_recon(tall_test, host, port, 8, srv, false); + osmo_stream_srv_link_set_data(srv, tall_test); test_segm_ipa_stream_srv_run(tall_test, host, port, srv); + test_segm_ipa_stream_cli_run(tall_test, host, port, srv); printf("Stream tests completed\n"); osmo_stream_srv_link_destroy(srv); + log_fini(); + talloc_free(tall_test); return EXIT_SUCCESS; }
View file
libosmo-netif_1.4.0.tar.xz/tests/stream/stream_test.err -> libosmo-netif_1.5.0.tar.xz/tests/stream/stream_test.err
Changed
@@ -2,28 +2,50 @@ CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CONNECTING} connection established {2.000001} autoreconnecting test step 11 client NA, server OK, FD reg 1 +CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CONNECTED} connected write +CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CONNECTED} sending 29 bytes of data {2.000002} autoreconnecting test step 10 client NA, server OK, FD reg 1 +SRVCONN(srv_test,r=127.0.0.1:8976<->l=127.0.0.11:1111) connected read/write (what=0x1) +SRVCONN(srv_test,r=127.0.0.1:8976<->l=127.0.0.11:1111) message received +SRVCONN(srv_test,r=127.0.0.1:8976<->l=127.0.0.11:1111) received 29 bytes from client {2.000003} autoreconnecting test step 9 client NA, server OK, FD reg 1 +SRVCONN(srv_test,r=127.0.0.1:8976<->l=127.0.0.11:1111) connected read/write (what=0x2) +SRVCONN(srv_test,r=127.0.0.1:8976<->l=127.0.0.11:1111) sending 11 bytes of data {2.000004} autoreconnecting test step 8 client NA, server OK, FD reg 1 +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} received 11 bytes from srv {2.000005} autoreconnecting test step 7 client OK, server OK, FD reg 1 +CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CONNECTED} connected write +CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CONNECTED} sending 29 bytes of data {2.000006} autoreconnecting test step 6 client OK, server OK, FD reg 1 +SRVCONN(srv_test,r=127.0.0.1:8976<->l=127.0.0.11:1111) connected read/write (what=0x1) +SRVCONN(srv_test,r=127.0.0.1:8976<->l=127.0.0.11:1111) message received +SRVCONN(srv_test,r=127.0.0.1:8976<->l=127.0.0.11:1111) received 29 bytes from client {2.000007} autoreconnecting test step 5 client OK, server OK, FD reg 1 +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){WAIT_RECONNECT} retrying reconnect in 9 seconds... {11.000008} autoreconnecting test step 4 client OK, server OK, FD reg 0 +CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){WAIT_RECONNECT} reconnecting {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 {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) +SRVCONN(srv_test,r=127.0.0.1:8976<->l=127.0.0.11:1111) message received 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 @@ -31,21 +53,63 @@ CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CONNECTING} connection established {11.000012} non-reconnecting test step 7 client NA, server OK, FD reg 1 +CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CONNECTED} connected write +CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CONNECTED} sending 29 bytes of data {11.000013} non-reconnecting test step 6 client NA, server OK, FD reg 1 +SRVCONN(srv_test,r=127.0.0.1:8976<->l=127.0.0.11:1111) connected read/write (what=0x1) +SRVCONN(srv_test,r=127.0.0.1:8976<->l=127.0.0.11:1111) message received +SRVCONN(srv_test,r=127.0.0.1:8976<->l=127.0.0.11:1111) received 29 bytes from client {11.000014} non-reconnecting test step 5 client NA, server OK, FD reg 1 +SRVCONN(srv_test,r=127.0.0.1:8976<->l=127.0.0.11:1111) connected read/write (what=0x2) +SRVCONN(srv_test,r=127.0.0.1:8976<->l=127.0.0.11:1111) sending 11 bytes of data {11.000015} non-reconnecting test step 4 client NA, server OK, FD reg 1 +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} received 11 bytes from srv {11.000016} non-reconnecting test step 3 client OK, server OK, FD reg 1 +CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CONNECTED} connected write +CLICONN(cli_test,r=127.0.0.11:1111<->l=127.0.0.1:8976){CONNECTED} sending 29 bytes of data {11.000017} non-reconnecting test step 2 client OK, server OK, FD reg 1 +SRVCONN(srv_test,r=127.0.0.1:8976<->l=127.0.0.11:1111) connected read/write (what=0x1) +SRVCONN(srv_test,r=127.0.0.1:8976<->l=127.0.0.11:1111) message received +SRVCONN(srv_test,r=127.0.0.1:8976<->l=127.0.0.11:1111) received 29 bytes from client {11.000018} non-reconnecting test step 1 client OK, server OK, FD reg 1 +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){CLOSED} not reconnecting, disabled {20.000019} non-reconnecting test step 0 client OK, server OK, FD reg 0 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 +SRVCONN(,r=127.0.0.1:8977<->l=127.0.0.11:1111) received 24 bytes from client +SRVCONN(,r=127.0.0.1:8977<->l=127.0.0.11:1111) received 24 bytes from client +SRVCONN(,r=127.0.0.1:8977<->l=127.0.0.11:1111) received 24 bytes from client +SRVCONN(,r=127.0.0.1:8977<->l=127.0.0.11:1111) connected write +CLICONN(,r=127.0.0.11:1111<->l=127.0.0.1:8977){CONNECTED} received 6 bytes from srv +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 +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 +CLICONN(,r=127.0.0.11:1112<->l=127.0.0.1:8977){CONNECTED} received 24 bytes from srv +CLICONN(,r=127.0.0.11:1112<->l=127.0.0.1:8977){CONNECTED} received 24 bytes from srv +CLICONN(,r=127.0.0.11:1112<->l=127.0.0.1:8977){CONNECTED} received 24 bytes from srv +CLICONN(,r=127.0.0.11:1112<->l=127.0.0.1:8977){CONNECTED} received 24 bytes from srv +SRVCONN(,r=127.0.0.1:8977<->l=127.0.0.11:1112) received 6 bytes from client +SRVCONN(,r=127.0.0.1:8977<->l=127.0.0.11:1112) connected write +SRVCONN(,r=127.0.0.1:8977<->l=127.0.0.11:1112) connected write +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
View file
libosmo-netif_1.4.0.tar.xz/tests/stream/stream_test.ok -> libosmo-netif_1.5.0.tar.xz/tests/stream/stream_test.ok
Changed
@@ -49,18 +49,18 @@ {20.000019} non-reconnecting test complete. ______________________________________Running test test_segm_ipa_stream_srv______________________________________ -{20.000020} OK Client's test_segm_ipa_stream_srv_cli_connect_cb(): 1-cli Appending msg of type IPAC_MSGT_PING into buffer -{20.000020} OK Client's test_segm_ipa_stream_srv_cli_connect_cb(): (msg dump: 00 01 fe 00 ) -{20.000020} OK Client's test_segm_ipa_stream_srv_cli_connect_cb(): 2-cli Appending msg of type IPAC_MSGT_PONG into buffer -{20.000020} OK Client's test_segm_ipa_stream_srv_cli_connect_cb(): (msg dump: 00 01 fe 01 ) -{20.000020} OK Client's test_segm_ipa_stream_srv_cli_connect_cb(): 3-cli Appending msg of type IPAC_MSGT_PING into buffer -{20.000020} OK Client's test_segm_ipa_stream_srv_cli_connect_cb(): (msg dump: 00 01 fe 00 ) -{20.000020} OK Client's test_segm_ipa_stream_srv_cli_connect_cb(): 4-cli Appending msg of type IPAC_MSGT_ID_RESP into buffer -{20.000020} OK Client's test_segm_ipa_stream_srv_cli_connect_cb(): (msg dump: 00 07 fe 05 01 01 de ad be ef ) -{20.000020} OK Client's test_segm_ipa_stream_srv_cli_connect_cb(): (04 + 1/3)-cli Appending 1st third of msg of type IPAC_MSGT_ID_GET into buffer -{20.000020} OK Client's test_segm_ipa_stream_srv_cli_connect_cb(): (dump: 00 03 ) -{20.000020} OK Client's test_segm_ipa_stream_srv_cli_connect_cb(): Sending 4 + 1/3 messages as one: -{20.000020} OK Client's test_segm_ipa_stream_srv_cli_connect_cb(): (msg dump: 00 01 fe 00 00 01 fe 01 00 01 fe 00 00 07 fe 05 01 01 de ad be ef 00 03 ) +{20.000020} NA Client's test_segm_ipa_stream_srv_cli_connect_cb(): 1-cli Appending msg of type IPAC_MSGT_PING into buffer +{20.000020} NA Client's test_segm_ipa_stream_srv_cli_connect_cb(): (msg dump: 00 01 fe 00 ) +{20.000020} NA Client's test_segm_ipa_stream_srv_cli_connect_cb(): 2-cli Appending msg of type IPAC_MSGT_PONG into buffer +{20.000020} NA Client's test_segm_ipa_stream_srv_cli_connect_cb(): (msg dump: 00 01 fe 01 ) +{20.000020} NA Client's test_segm_ipa_stream_srv_cli_connect_cb(): 3-cli Appending msg of type IPAC_MSGT_PING into buffer +{20.000020} NA Client's test_segm_ipa_stream_srv_cli_connect_cb(): (msg dump: 00 01 fe 00 ) +{20.000020} NA Client's test_segm_ipa_stream_srv_cli_connect_cb(): 4-cli Appending msg of type IPAC_MSGT_ID_RESP into buffer +{20.000020} NA Client's test_segm_ipa_stream_srv_cli_connect_cb(): (msg dump: 00 07 fe 05 01 01 de ad be ef ) +{20.000020} NA Client's test_segm_ipa_stream_srv_cli_connect_cb(): (04 + 1/3)-cli Appending 1st third of msg of type IPAC_MSGT_ID_GET into buffer +{20.000020} NA Client's test_segm_ipa_stream_srv_cli_connect_cb(): (dump: 00 03 ) +{20.000020} NA Client's test_segm_ipa_stream_srv_cli_connect_cb(): Sending 4 + 1/3 messages as one: +{20.000020} NA Client's test_segm_ipa_stream_srv_cli_connect_cb(): (msg dump: 00 01 fe 00 00 01 fe 01 00 01 fe 00 00 07 fe 05 01 01 de ad be ef 00 03 ) {20.000022} NA|OK Server's test_segm_ipa_stream_srv_srv_read_cb(): 1-srv Received IPA message from stream (payload len = 1) {20.000022} NA|OK Server's test_segm_ipa_stream_srv_srv_read_cb(): msg buff data (including stripped headers): 00 01 fe 00 @@ -84,21 +84,21 @@ {20.000022} NA|OK Server's test_segm_ipa_stream_srv_srv_read_cb(): (msg dump: 00 07 fe 05 01 01 de ad be ef ) {20.000022} NA|OK Server's test_segm_ipa_stream_srv_srv_read_cb(): Send IPAC_MSGT_ID_GET to trigger client to send next third -{20.000024} OK Client's test_segm_ipa_stream_srv_cli_read_cb(): Received message from stream (total len = 6) -{20.000024} OK Client's test_segm_ipa_stream_srv_cli_read_cb(): Type: IPAC_MSGT_ID_GET -{20.000024} OK Client's test_segm_ipa_stream_srv_cli_read_cb(): Got IPAC_MSGT_ID_GET from server -{20.000024} OK Client's test_segm_ipa_stream_srv_cli_read_cb(): (4 + 2/3) -cli Appending: Second third of IPAC_MSGT_ID_GET -{20.000024} OK Client's test_segm_ipa_stream_srv_cli_read_cb(): Sending: Second third of IPAC_MSGT_ID_GET -{20.000024} OK Client's test_segm_ipa_stream_srv_cli_read_cb(): (msg dump: fe 04 ) - -{20.500024} OK Client's send_last_third(): Delay for sending last third of message is over -{20.500024} OK Client's send_last_third(): 5-cli Appending: Last third of IPAC_MSGT_ID_GET -{20.500024} OK Client's send_last_third(): 6-cli Appending msg of type IPAC_MSGT_PONG into buffer -{20.500024} OK Client's send_last_third(): (msg dump: 00 01 fe 01 ) -{20.500024} OK Client's send_last_third(): 7-cli Appending msg of type IPAC_MSGT_PONG into buffer -{20.500024} OK Client's send_last_third(): (msg dump: 00 01 fe 01 ) -{20.500024} OK Client's send_last_third(): Sending: Last third of IPAC_MSGT_ID_GET | IPAC_MSGT_PONG | IPAC_MSGT_PONG -{20.500024} OK Client's send_last_third(): (msg dump: 01 01 00 01 fe 01 00 01 fe 01 ) +{20.000024} NA Client's test_segm_ipa_stream_srv_cli_read_cb(): Received message from stream (payload len = 3) +{20.000024} NA Client's test_segm_ipa_stream_srv_cli_read_cb(): Type: IPAC_MSGT_ID_GET +{20.000024} NA Client's test_segm_ipa_stream_srv_cli_read_cb(): Got IPAC_MSGT_ID_GET from server +{20.000024} NA Client's test_segm_ipa_stream_srv_cli_read_cb(): (4 + 2/3) -cli Appending: Second third of IPAC_MSGT_ID_GET +{20.000024} NA Client's test_segm_ipa_stream_srv_cli_read_cb(): Sending: Second third of IPAC_MSGT_ID_GET +{20.000024} NA Client's test_segm_ipa_stream_srv_cli_read_cb(): (msg dump: fe 04 ) + +{20.500024} NA Client's send_last_third(): Delay for sending last third of message is over +{20.500024} NA Client's send_last_third(): 5-cli Appending: Last third of IPAC_MSGT_ID_GET +{20.500024} NA Client's send_last_third(): 6-cli Appending msg of type IPAC_MSGT_PONG into buffer +{20.500024} NA Client's send_last_third(): (msg dump: 00 01 fe 01 ) +{20.500024} NA Client's send_last_third(): 7-cli Appending msg of type IPAC_MSGT_PONG into buffer +{20.500024} NA Client's send_last_third(): (msg dump: 00 01 fe 01 ) +{20.500024} NA Client's send_last_third(): Sending: Last third of IPAC_MSGT_ID_GET | IPAC_MSGT_PONG | IPAC_MSGT_PONG +{20.500024} NA Client's send_last_third(): (msg dump: 01 01 00 01 fe 01 00 01 fe 01 ) {20.500026} NA|OK Server's test_segm_ipa_stream_srv_srv_read_cb(): 5-srv Received IPA message from stream (payload len = 3) {20.500026} NA|OK Server's test_segm_ipa_stream_srv_srv_read_cb(): msg buff data (including stripped headers): 00 03 fe 04 01 01 @@ -117,4 +117,73 @@ {20.500026} NA|OK Server's test_segm_ipa_stream_srv_srv_read_cb(): (msg dump: 00 01 fe 01 ) ==================================Test test_segm_ipa_stream_srv complete======================================== +______________________________________Running test test_segm_ipa_stream_cli______________________________________ +{20.500027} NA|OK Server's test_segm_ipa_stream_cli_srv_accept_cb(): 1-srv Appending msg of type IPAC_MSGT_PING into buffer +{20.500027} NA|OK Server's test_segm_ipa_stream_cli_srv_accept_cb(): (msg dump: 00 01 fe 00 ) +{20.500027} NA|OK Server's test_segm_ipa_stream_cli_srv_accept_cb(): 2-srv Appending msg of type IPAC_MSGT_PONG into buffer +{20.500027} NA|OK Server's test_segm_ipa_stream_cli_srv_accept_cb(): (msg dump: 00 01 fe 01 ) +{20.500027} NA|OK Server's test_segm_ipa_stream_cli_srv_accept_cb(): 3-srv Appending msg of type IPAC_MSGT_PING into buffer +{20.500027} NA|OK Server's test_segm_ipa_stream_cli_srv_accept_cb(): (msg dump: 00 01 fe 00 ) +{20.500027} NA|OK Server's test_segm_ipa_stream_cli_srv_accept_cb(): 4-srv Appending msg of type IPAC_MSGT_ID_RESP into buffer +{20.500027} NA|OK Server's test_segm_ipa_stream_cli_srv_accept_cb(): (msg dump: 00 07 fe 05 01 01 de ad be ef ) +{20.500027} NA|OK Server's test_segm_ipa_stream_cli_srv_accept_cb(): (04 + 1/3)-srv Appending 1st third of msg of type IPAC_MSGT_ID_GET into buffer +{20.500027} NA|OK Server's test_segm_ipa_stream_cli_srv_accept_cb(): (dump: 00 03 ) +{20.500027} NA|OK Server's test_segm_ipa_stream_cli_srv_accept_cb(): Sending 4 + 1/3 messages as one: +{20.500027} NA|OK Server's test_segm_ipa_stream_cli_srv_accept_cb(): (msg dump: 00 01 fe 00 00 01 fe 01 00 01 fe 00 00 07 fe 05 01 01 de ad be ef 00 03 ) + +{20.500029} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): 1-cli Received message from stream (len = 1) +{20.500029} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): msg buff data: 00 +{20.500029} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): IPA payload: 00 +{20.500029} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): Type: IPAC_MSGT_PING +{20.500029} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): (msg dump (including stripped headers): 00 01 fe 00 ) +{20.500029} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): 2-cli Received message from stream (len = 1) +{20.500029} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): msg buff data: 01 +{20.500029} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): IPA payload: 01 +{20.500029} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): Type: IPAC_MSGT_PONG +{20.500029} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): (msg dump (including stripped headers): 00 01 fe 01 ) +{20.500029} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): 3-cli Received message from stream (len = 1) +{20.500029} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): msg buff data: 00 +{20.500029} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): IPA payload: 00 +{20.500029} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): Type: IPAC_MSGT_PING +{20.500029} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): (msg dump (including stripped headers): 00 01 fe 00 ) +{20.500029} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): 4-cli Received message from stream (len = 7) +{20.500029} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): msg buff data: 05 01 01 de ad be ef +{20.500029} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): IPA payload: 05 01 01 de ad be ef +{20.500029} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): Type: IPAC_MSGT_ID_RESP +{20.500029} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): (msg dump (including stripped headers): 00 07 fe 05 01 01 de ad be ef ) +{20.500029} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): Send IPAC_MSGT_ID_GET to trigger server to send next third + +{20.500031} NA|OK Server's test_segm_ipa_stream_cli_srv_read_cb(): Received message from stream (total len including stripped headers = 6) +{20.500031} NA|OK Server's test_segm_ipa_stream_cli_srv_read_cb(): Type: IPAC_MSGT_ID_GET +{20.500031} NA|OK Server's test_segm_ipa_stream_cli_srv_read_cb(): Got IPAC_MSGT_ID_GET from client +{20.500031} NA|OK Server's test_segm_ipa_stream_cli_srv_read_cb(): (4 + 2/3) -srv Appending: Second third of IPAC_MSGT_ID_GET +{20.500031} NA|OK Server's test_segm_ipa_stream_cli_srv_read_cb(): Sending: Second third of IPAC_MSGT_ID_GET +{20.500031} NA|OK Server's test_segm_ipa_stream_cli_srv_read_cb(): (msg dump: fe 04 ) + +{20.625031} NA|OK Server's send_last_third_srv(): Delay for sending last third of message is over +{20.625031} NA|OK Server's send_last_third_srv(): 5-srv Appending: Last third of IPAC_MSGT_ID_GET +{20.625031} NA|OK Server's send_last_third_srv(): 6-srv Appending msg of type IPAC_MSGT_PONG into buffer +{20.625031} NA|OK Server's send_last_third_srv(): (msg dump: 00 01 fe 01 ) +{20.625031} NA|OK Server's send_last_third_srv(): 7-srv Appending msg of type IPAC_MSGT_PONG into buffer +{20.625031} NA|OK Server's send_last_third_srv(): (msg dump: 00 01 fe 01 ) +{20.625031} NA|OK Server's send_last_third_srv(): Sending: Last third of IPAC_MSGT_ID_GET | IPAC_MSGT_PONG | IPAC_MSGT_PONG +{20.625031} NA|OK Server's send_last_third_srv(): (msg dump: 01 01 00 01 fe 01 00 01 fe 01 ) + +{20.625033} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): 5-cli Received message from stream (len = 3) +{20.625033} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): msg buff data: 04 01 01 +{20.625033} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): IPA payload: 04 01 01 +{20.625033} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): Type: IPAC_MSGT_ID_GET +{20.625033} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): (msg dump (including stripped headers): 00 03 fe 04 01 01 ) +{20.625033} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): 6-cli Received message from stream (len = 1) +{20.625033} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): msg buff data: 01 +{20.625033} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): IPA payload: 01 +{20.625033} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): Type: IPAC_MSGT_PONG +{20.625033} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): (msg dump (including stripped headers): 00 01 fe 01 ) +{20.625033} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): 7-cli Received message from stream (len = 1) +{20.625033} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): msg buff data: 01 +{20.625033} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): IPA payload: 01 +{20.625033} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): Type: IPAC_MSGT_PONG +{20.625033} NA Client's test_segm_ipa_stream_cli_cli_read_cb(): (msg dump (including stripped headers): 00 01 fe 01 ) +==================================Test test_segm_ipa_stream_cli complete======================================== + Stream tests completed
View file
rpmlintrc
Deleted
@@ -1,5 +0,0 @@ -# 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
.