diff --git a/CMakeLists.txt b/CMakeLists.txt index 3422b73d1..d69a8d991 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -122,19 +122,24 @@ endforeach() # SRT_MAVG_SAMPLING_RATE 40 /* Max sampling rate */ # SRT_ENABLE_FREQUENT_LOG_TRACE 0 : set to 1 to enable printing reason for suppressed freq logs -# CMake offers the OLD behavior, where names that are defined below with -# option() function, will be deleted if they are not in cache or do not have set -# type - so effectively options provided through LIBSRT_* prefix would be rejected. -# We do want these variables, obviously. -# NOTE: This is introduced in cmake 3.13, so the namespaced-option feature will not -# work properly in the old cmake. -if (CMAKE_VERSION VERSION_GREATER 3.12) - cmake_policy(SET CMP0077 NEW) -endif() - -# Import all options preceded with LIBSRT_ likely from a parent scope. -# Names are not being checked, at worst it will set an unused variable. -srt_import_parent_options() +# Blocked by a general enabler, LIBSRT_ENABLE_IMPORT_VARIABLES, to prevent accidental use. +if ( (DEFINED LIBSRT_ENABLE_IMPORT_VARIABLES) AND (LIBSRT_ENABLE_IMPORT_VARIABLES EQUAL 1)) + unset(LIBSRT_ENABLE_IMPORT_VARIABLES) + + # CMake offers sometimes OLD behavior, where names that are defined below with + # option() function, will be deleted if they are not in cache or do not have set + # type - so effectively options provided through LIBSRT_* prefix would be rejected. + # We do want these variables, obviously. + # NOTE: This is introduced in cmake 3.13, so the namespaced-option feature will not + # work properly in the old cmake. + if (CMAKE_VERSION VERSION_GREATER 3.12) + cmake_policy(SET CMP0077 NEW) + endif() + + # Import all options preceded with LIBSRT_ likely from a parent scope. + # Names are not being checked, at worst it will set an unused variable. + srt_import_parent_options() +endif() # option defaults set(ENABLE_HEAVY_LOGGING_DEFAULT OFF) diff --git a/README.md b/README.md index b0df582af..9d6a6bcc6 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,6 @@ [![License: MPLv2.0][license-badge]](./LICENSE) [![Latest release][release-badge]][github releases] [![codecov][codecov-badge]][codecov-project] -[![Build Status Linux and macOS][travis-badge]][travis] [![Build Status Windows][appveyor-badge]][appveyor] [![Ubuntu 24.04][Ubuntu-badge]][Ubuntu-package] @@ -216,8 +215,6 @@ By contributing code to the SRT project, you agree to license your contribution [appveyor-badge]: https://img.shields.io/appveyor/ci/Haivision/srt/master.svg?label=Windows [appveyor]: https://ci.appveyor.com/project/Haivision/srt -[travis-badge]: https://img.shields.io/travis/Haivision/srt/master.svg?label=Linux/macOS -[travis]: https://travis-ci.org/Haivision/srt [license-badge]: https://img.shields.io/badge/License-MPLv2.0-blue [Vcpkg-package]: https://repology.org/project/srt/versions @@ -236,10 +233,10 @@ By contributing code to the SRT project, you agree to license your contribution [debian-package]: https://packages.debian.org/testing/libs/libsrt1.5-gnutls [fedora-package]: https://repology.org/project/srt/versions -[fedora-badge]: https://repology.org/badge/version-for-repo/fedora_37/srt.svg +[fedora-badge]: https://repology.org/badge/version-for-repo/fedora_43/srt.svg [homebrew-package]: https://repology.org/project/srt/versions [homebrew-badge]: https://repology.org/badge/version-for-repo/homebrew/srt.svg [Ubuntu-package]: https://repology.org/project/srt/versions -[Ubuntu-badge]: https://repology.org/badge/version-for-repo/ubuntu_24_04/srt.svg +[Ubuntu-badge]: https://repology.org/badge/version-for-repo/ubuntu_26_04/srt.svg diff --git a/docs/API/API-functions.md b/docs/API/API-functions.md index 928fd6aaa..fc82776ab 100644 --- a/docs/API/API-functions.md +++ b/docs/API/API-functions.md @@ -612,9 +612,10 @@ the listener socket to accept group connections | [`SRT_EINVPARAM`](#srt_einvparam) | Value of `backlog` is 0 or negative. | | [`SRT_EINVSOCK`](#srt_einvsock) | Socket [`u`](#u) indicates no valid SRT socket. | | [`SRT_EUNBOUNDSOCK`](#srt_eunboundsock) | [`srt_bind`](#srt_bind) has not yet been called on that socket. | +| [`SRT_ESCLOSED`](#srt_esclosed) | The socket has been closed | | [`SRT_ERDVNOSERV`](#srt_erdvnoserv) | [`SRTO_RENDEZVOUS`](API-socket-options.md#SRTO_RENDEZVOUS) flag is set to true on specified socket. | | [`SRT_EINVOP`](#srt_einvop) | Internal error (should not happen when [`SRT_EUNBOUNDSOCK`](#srt_eunboundsock) is reported). | -| [`SRT_ECONNSOCK`](#srt_econnsock) | The socket is already connected. | +| [`SRT_ECONNSOCK`](#srt_econnsock) | The socket is currently being used to establish a connection (like by `srt_connect`) | | [`SRT_EDUPLISTEN`](#srt_eduplisten) | The address used in [`srt_bind`](#srt_bind) by this socket is already occupied by another listening socket.
Binding multiple sockets to one IP address and port is allowed, as long as
[`SRTO_REUSEADDR`](API-socket-options.md#SRTO_REUSEADDRS) is set to true, but only one of these sockets can be set up as a listener. | | | | diff --git a/docs/build/build-options.md b/docs/build/build-options.md index 05fcf8be4..2ec4d454a 100644 --- a/docs/build/build-options.md +++ b/docs/build/build-options.md @@ -20,12 +20,22 @@ document and in the [SRT CookBook](https://srtlab.github.io/srt-cookbook/getting ## Building as a subproject The CMake tool offers the ability to add a complete project as a subdirectory. -Variables used by the SRT project in this case remain in their own scope, but -all variables from the parent scope are reflected. In order to prevent name -clashes for option-designating variables, SRT provides a namespace-like -prefixing for the optional variables it uses. If you want to configure optional -variables from the level of `CMakeLists.txt` of the parent project, use the -`LIBSRT_` prefix for the option names. +If you do this with SRT, note that all variables that can be optionally set +will get values from the parent configuration file including the one from SRT. + +To allow isolation of these variables and setting them explicitly to desired +values in case when the parent project uses variables with the same names, +there's a special feature provided: set the desired variables for the SRT +project using `LIBSRT_` prefix - this way they will get the values to the +right variables, visible only in the scope of the SRT build configuration. + +NOTE: This feature needs to be generally enabled by: + +``` +set (LIBSRT_ENABLE_IMPORT_VARIABLES 1) +``` + +otherwise all other variables with `LIBSRT_` prefix will be ignored. This will not prevent the variables from being seen as derived in SRT project scope, but if you explicitly set a variable this way, it will be set to the @@ -34,9 +44,10 @@ parent project, and it will also override (locally in SRT project only) any value of a variable with the same name in the parent project. For example, if you want to set `ENABLE_SHARED=OFF` in the parent project, -simply do: +add this before importing the SRT project: ``` +set (LIBSRT_ENABLE_IMPORT_VARIABLES 1) set (LIBSRT_ENABLE_SHARED OFF) ``` diff --git a/scripts/codespell/codespell.cfg b/scripts/codespell/codespell.cfg index a33874609..44f2ec937 100644 --- a/scripts/codespell/codespell.cfg +++ b/scripts/codespell/codespell.cfg @@ -6,9 +6,11 @@ builtin = clear,rare,informal,code # Ignore words listed in this file. ignore-words = ./scripts/codespell/codespell_whitelist.txt +ignore-regex = TEST\(.*\) # Add custom dictionary file. dictionary = ./scripts/codespell/codespell_dictionary.txt,- # Skip checking files or directories. skip = ./build/*,./.git/* + diff --git a/srtcore/api.cpp b/srtcore/api.cpp index 80d41582b..cc3bd49b7 100644 --- a/srtcore/api.cpp +++ b/srtcore/api.cpp @@ -1144,27 +1144,34 @@ int srt::CUDTUnited::listen(const SRTSOCKET u, int backlog) // it could have changed the state. It could be also set listen in another // thread, so check it out. - // do nothing if the socket is already listening - if (s->m_Status == SRTS_LISTENING) - return 0; - - // a socket can listen only if is in OPENED status - if (s->m_Status != SRTS_OPENED) - throw CUDTException(MJ_NOTSUP, MN_ISUNBOUND, 0); - - // [[using assert(s->m_Status == OPENED)]]; - - // listen is not supported in rendezvous connection setup if (s->core().m_config.bRendezvous) throw CUDTException(MJ_NOTSUP, MN_ISRENDEZVOUS, 0); - s->m_uiBackLog = backlog; - - // [[using assert(s->m_Status == OPENED)]]; // (still, unchanged) + switch(s->m_Status) + { + case SRTS_INIT: + throw CUDTException(MJ_NOTSUP, MN_ISUNBOUND, 0); + break; + case SRTS_OPENED: + s->m_uiBackLog = backlog; + s->core().setListenState(); // propagates CUDTException, + s->m_Status = SRTS_LISTENING; + break; + case SRTS_LISTENING: + s->m_uiBackLog = backlog; + break; + case SRTS_CONNECTING: + case SRTS_CONNECTED: + throw CUDTException(MJ_NOTSUP, MN_ISCONNECTED, 0); + break; + case SRTS_BROKEN: + case SRTS_CLOSING: + case SRTS_CLOSED: + case SRTS_NONEXIST: + throw CUDTException(MJ_SETUP, MN_CLOSED, 0); + break; + } - s->core().setListenState(); // propagates CUDTException, - // if thrown, remains in OPENED state if so. - s->m_Status = SRTS_LISTENING; return 0; } diff --git a/srtcore/common.cpp b/srtcore/common.cpp index 23b341313..b301b80a9 100644 --- a/srtcore/common.cpp +++ b/srtcore/common.cpp @@ -93,7 +93,9 @@ m_iMinor(minor) m_iErrno = NET_ERROR; else m_iErrno = err; - HLOGC(aclog.Debug, log << "CREATED SRT EXCEPTION: " << (1000*major+minor) << " errno=" << m_iErrno); + // XXX No logging allowed because this constructor can be also used for + // initializing global object. That problem should be solved separately. + // HLOGC(aclog.Debug, log << "CREATED SRT EXCEPTION: " << (1000*major+minor) << " errno=" << m_iErrno); } const char* srt::CUDTException::getErrorMessage() const ATR_NOTHROW diff --git a/srtcore/logging.h b/srtcore/logging.h index 7782245a2..dd9be95a8 100644 --- a/srtcore/logging.h +++ b/srtcore/logging.h @@ -189,6 +189,7 @@ struct SRT_API LogDispatcher ~LogDispatcher() { + src_config = NULL; // Allow to call CheckEnabled after destruction } bool CheckEnabled(); @@ -390,6 +391,12 @@ struct LogDispatcher::Proxy #endif + +// IMPORTANT: +// 1. Logger objects are only allowed to be global. The CheckEnabled +// method RELIES ON THAT it may run before the Logger() constructor is run. +// 2. Destructor resets src_config to NULL to prevent any logging instruction +// to access the facility after destruction. class Logger { int m_fa; @@ -425,12 +432,16 @@ inline bool LogDispatcher::CheckEnabled() // when the enabler check is tested here. Worst case, the log // will be printed just a moment after it was turned off. const LogConfig* config = src_config; // to enforce using const operator[] - config->lock(); - int configured_enabled_fa = config->enabled_fa[fa]; - int configured_maxlevel = config->max_level; - config->unlock(); + if (config) + { + config->lock(); + int configured_enabled_fa = config->enabled_fa[fa]; + int configured_maxlevel = config->max_level; + config->unlock(); - return configured_enabled_fa && level <= configured_maxlevel; + return configured_enabled_fa && level <= configured_maxlevel; + } + return false; } diff --git a/test/test_connection_timeout.cpp b/test/test_connection_timeout.cpp index 281376ce1..2c44baaa4 100644 --- a/test/test_connection_timeout.cpp +++ b/test/test_connection_timeout.cpp @@ -390,4 +390,30 @@ TEST(TestConnectionAPI, Accept) srt_cleanup(); } +TEST(TestConnectionAPI, Listen) +{ + using namespace std::chrono; + using namespace srt; + srt_startup(); + + SRTSOCKET s = srt_create_socket(); + int listen_stat1, listen_stat2, listen_stat3; + + sockaddr_any sa = srt::CreateAddr("localhost", 5555, AF_INET); + + ASSERT_NE(srt_bind(s, sa.get(), sa.size()), -1); + listen_stat1 = srt_listen(s, 1); + listen_stat2 = srt_listen(s, 5); + srt_close(s); + listen_stat3 = srt_listen(s, 5); + + int err = srt_getlasterror(NULL); + std::cout << "Listen after close error: " << srt_strerror(err, 0) << std::endl; + + EXPECT_EQ(listen_stat1, 0); + EXPECT_EQ(listen_stat2, 0); + EXPECT_EQ(listen_stat3, -1); + + srt_cleanup(); +}