Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/cxx11-ubuntu.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- name: configure
run: |
mkdir _build && cd _build
cmake ../ -DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DENABLE_STDCXX_SYNC=ON -DENABLE_ENCRYPTION=ON -DENABLE_UNITTESTS=ON -DENABLE_BONDING=ON -DENABLE_TESTING=ON -DENABLE_EXAMPLES=ON -DENABLE_CODE_COVERAGE=ON
cmake ../ -DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DENABLE_STDCXX_SYNC=ON -DENABLE_ENCRYPTION=ON -DENABLE_UNITTESTS=ON -DENABLE_BONDING=ON -DENABLE_TESTING=ON -DENABLE_EXAMPLES=ON -DENABLE_CODE_COVERAGE=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
- name: build
run: cd _build && build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build .
- name: test
Expand All @@ -35,4 +35,4 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
# Consult https://docs.sonarcloud.io/advanced-setup/ci-based-analysis/sonarscanner-cli/ for more information and options.
run: sonar-scanner --define sonar.cfamily.build-wrapper-output=_build/"${{ env.BUILD_WRAPPER_OUT_DIR }}"
run: sonar-scanner --define sonar.cfamily.compile-commands="_build/compile_commands.json"
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,4 @@ compile_commands.json
# ignore files generated by clion and cmake
.idea/
cmake-build-debug/
tags
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ matrix:
- BUILD_TYPE=Release
- BUILD_OPTS='-DENABLE_MONOTONIC_CLOCK=ON'
script:
- echo COMPILER $TRAVIS_COMPILER
- echo SYSTEM $TRAVIS_OS_NAME
- echo BUILD_TYPE $BUILD_TYPE
- echo BUILD_OPTS $BUILD_OPTS
- if [ "$TRAVIS_COMPILER" == "x86_64-w64-mingw32-g++" ]; then
export CC="x86_64-w64-mingw32-gcc";
export CXX="x86_64-w64-mingw32-g++";
Expand Down
45 changes: 36 additions & 9 deletions CMakeLists.txt
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,12 @@ set_if(DARWIN (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set_if(LINUX ${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set_if(BSD ${SYSNAME_LC} MATCHES "bsd$")
set_if(MICROSOFT WIN32 AND (NOT MINGW AND NOT CYGWIN))
set_if(GNU ${CMAKE_SYSTEM_NAME} MATCHES "GNU")
set_if(GNU_OS ${CMAKE_SYSTEM_NAME} MATCHES "GNU") # Use GNU_OS to not confuse with gcc
set_if(ANDROID ${SYSNAME_LC} MATCHES "android")
set_if(OHOS ${CMAKE_SYSTEM_NAME} MATCHES "OHOS")
set_if(SUNOS "${SYSNAME_LC}" MATCHES "sunos")
set_if(POSIX LINUX OR DARWIN OR BSD OR SUNOS OR ANDROID OR (CYGWIN AND CYGWIN_USE_POSIX))
set_if(SYMLINKABLE LINUX OR DARWIN OR BSD OR SUNOS OR CYGWIN OR GNU)
set_if(POSIX LINUX OR DARWIN OR BSD OR SUNOS OR ANDROID OR OHOS OR (CYGWIN AND CYGWIN_USE_POSIX) OR GNU_OS)
set_if(SYMLINKABLE LINUX OR DARWIN OR BSD OR SUNOS OR CYGWIN OR GNU_OS)
set_if(NEED_DESTINATION ${CMAKE_VERSION} VERSION_LESS "3.14.0")

include(GNUInstallDirs)
Expand Down Expand Up @@ -172,14 +173,20 @@ option(ENABLE_CODE_COVERAGE "Enable code coverage reporting" OFF)
option(ENABLE_MONOTONIC_CLOCK "Enforced clock_gettime with monotonic clock on GC CV" ${ENABLE_MONOTONIC_CLOCK_DEFAULT})
option(ENABLE_STDCXX_SYNC "Use C++11 chrono and threads for timing instead of pthreads" ${ENABLE_STDCXX_SYNC_DEFAULT})
option(USE_OPENSSL_PC "Use pkg-config to find OpenSSL libraries" ON)
option(OPENSSL_USE_STATIC_LIBS "Link OpenSSL libraries statically." OFF)
option(SRT_USE_OPENSSL_STATIC_LIBS "Link OpenSSL libraries statically." OFF)
option(USE_BUSY_WAITING "Enable more accurate sending times at a cost of potentially higher CPU load" OFF)
option(USE_GNUSTL "Get c++ library/headers from the gnustl.pc" OFF)
option(ENABLE_SOCK_CLOEXEC "Enable setting SOCK_CLOEXEC on a socket" ON)
option(ENABLE_SHOW_PROJECT_CONFIG "Enable show Project Configuration" OFF)

option(ENABLE_CLANG_TSA "Enable Clang Thread Safety Analysis" OFF)

if (DEFINED OPENSSL_USE_STATIC_LIBS AND "${OPENSSL_USE_STATIC_LIBS}" STREQUAL "ON")
message(WARNING "Use of OPENSSL_USE_STATIC_LIBS as SRT build option here is deprecated.
Please use SRT_USE_OPENSSL_STATIC_LIBS instead.")
set(SRT_USE_OPENSSL_STATIC_LIBS ${OPENSSL_USE_STATIC_LIBS})
endif()

# NOTE: Use ATOMIC_USE_SRT_SYNC_MUTEX and will override the auto-detection of the
# Atomic implemetation in srtcore/atomic.h.
option(ATOMIC_USE_SRT_SYNC_MUTEX "Use srt::sync::Mutex to Implement Atomics" OFF)
Expand Down Expand Up @@ -389,7 +396,7 @@ if (ENABLE_ENCRYPTION)
# fall back to find_package method otherwise
if (USE_OPENSSL_PC)
pkg_check_modules(SSL ${SSL_REQUIRED_MODULES})
if (OPENSSL_USE_STATIC_LIBS)
if (SRT_USE_OPENSSL_STATIC_LIBS)
# use `pkg-config --static xxx` found libs
set(SSL_LIBRARIES ${SSL_STATIC_LIBRARIES})
endif()
Expand All @@ -413,6 +420,11 @@ if (ENABLE_ENCRYPTION)
)
message(STATUS "SSL via pkg-config: -L ${SSL_LIBRARY_DIRS} -I ${SSL_INCLUDE_DIRS} -l;${SSL_LIBRARIES}")
else()
if (SRT_USE_OPENSSL_STATIC_LIBS)
# use `pkg-config --static xxx` found libs
set(OPENSSL_USE_STATIC_LIBS True)
set(OPENSSL_MSVC_STATIC_RT True)
endif()
find_package(OpenSSL REQUIRED)
set (SSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR})
set (SSL_LIBRARIES ${OPENSSL_LIBRARIES})
Expand Down Expand Up @@ -466,6 +478,10 @@ if (ENABLE_ENCRYPTION)
# fall back to find_package method otherwise
if (USE_OPENSSL_PC)
pkg_check_modules(SSL ${SSL_REQUIRED_MODULES})
if (SRT_USE_OPENSSL_STATIC_LIBS)
# use `pkg-config --static xxx` found libs
set(SSL_LIBRARIES ${SSL_STATIC_LIBRARIES})
endif()
endif()
if (SSL_FOUND)
# We have some cases when pkg-config is improperly configured
Expand All @@ -486,6 +502,11 @@ if (ENABLE_ENCRYPTION)
)
message(STATUS "SSL via pkg-config: -L ${SSL_LIBRARY_DIRS} -I ${SSL_INCLUDE_DIRS} -l;${SSL_LIBRARIES}")
else()
if (SRT_USE_OPENSSL_STATIC_LIBS)
# use `pkg-config --static xxx` found libs
set(OPENSSL_USE_STATIC_LIBS True)
set(OPENSSL_MSVC_STATIC_RT True)
endif()
find_package(OpenSSL REQUIRED)
set (SSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR})
set (SSL_LIBRARIES ${OPENSSL_LIBRARIES})
Expand Down Expand Up @@ -771,6 +792,9 @@ elseif(LINUX)
elseif(ANDROID)
add_definitions(-DLINUX=1)
message(STATUS "DETECTED SYSTEM: ANDROID; LINUX=1" )
elseif(OHOS)
add_definitions(-DLINUX=1)
message(STATUS "DETECTED SYSTEM: OHOS; LINUX=1" )
elseif(CYGWIN)
add_definitions(-DCYGWIN=1)
message(STATUS "DETECTED SYSTEM: CYGWIN (posix mode); CYGWIN=1")
Expand Down Expand Up @@ -881,6 +905,9 @@ elseif (PTHREAD_LIBRARY AND PTHREAD_INCLUDE_DIR)
message(STATUS "Pthread library: ${PTHREAD_LIBRARY}")
message(STATUS "Pthread include dir: ${PTHREAD_INCLUDE_DIR}")
elseif (MICROSOFT)

message(WARNING "DEPRECATION WARNING!\nUsing POSIX thread API with Windows is deprecated and will be removed")

find_package(pthreads QUIET)

if (NOT PTHREAD_INCLUDE_DIR OR NOT PTHREAD_LIBRARY)
Expand Down Expand Up @@ -1079,7 +1106,7 @@ if (srt_libspec_shared)
if (MICROSOFT)
target_link_libraries(${TARGET_srt}_shared PRIVATE ws2_32.lib)
if (NOT (ENABLE_ENCRYPTION AND "${USE_ENCLIB}" STREQUAL "botan"))
if (OPENSSL_USE_STATIC_LIBS)
if (SRT_USE_OPENSSL_STATIC_LIBS)
target_link_libraries(${TARGET_srt}_shared PRIVATE crypt32.lib)
else()
set_target_properties(${TARGET_srt}_shared PROPERTIES LINK_FLAGS "/DELAYLOAD:libeay32.dll")
Expand Down Expand Up @@ -1118,7 +1145,7 @@ if (srt_libspec_static)
endif()
if (MICROSOFT)
target_link_libraries(${TARGET_srt}_static PRIVATE ws2_32.lib)
if (OPENSSL_USE_STATIC_LIBS)
if (SRT_USE_OPENSSL_STATIC_LIBS)
target_link_libraries(${TARGET_srt}_static PRIVATE crypt32.lib)
endif()
elseif (MINGW)
Expand All @@ -1132,7 +1159,7 @@ endif()
target_include_directories(srt_virtual PRIVATE ${SSL_INCLUDE_DIRS})

if (MICROSOFT)
if (OPENSSL_USE_STATIC_LIBS)
if (SRT_USE_OPENSSL_STATIC_LIBS)
set (SRT_LIBS_PRIVATE ${SRT_LIBS_PRIVATE} ws2_32.lib crypt32.lib)
else()
set (SRT_LIBS_PRIVATE ${SRT_LIBS_PRIVATE} ws2_32.lib)
Expand Down Expand Up @@ -1174,7 +1201,7 @@ endif()
if (srt_libspec_shared)
if (MICROSOFT)
target_link_libraries(${TARGET_srt}_shared PUBLIC Ws2_32.lib)
if (OPENSSL_USE_STATIC_LIBS)
if (SRT_USE_OPENSSL_STATIC_LIBS)
target_link_libraries(${TARGET_srt}_shared PUBLIC crypt32.lib)
endif()
endif()
Expand Down
107 changes: 57 additions & 50 deletions apps/transmitmedia.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -805,8 +805,10 @@ class UdpCommon
{
protected:
int m_sock = -1;
sockaddr_any sadr;
string adapter;
sockaddr_any interface_addr;
sockaddr_any target_addr;
bool is_multicast = false;
map<string, string> m_options;

void Setup(string host, int port, map<string,string> attr)
Expand All @@ -821,57 +823,55 @@ class UdpCommon
// set non-blocking mode
#if defined(_WIN32)
unsigned long ulyes = 1;
if (ioctlsocket(m_sock, FIONBIO, &ulyes) == SOCKET_ERROR)
const bool ioctl_error = (ioctlsocket(m_sock, FIONBIO, &ulyes) == SOCKET_ERROR);
#else
if (ioctl(m_sock, FIONBIO, (const char *)&yes) < 0)
const bool ioctl_error = (ioctl(m_sock, FIONBIO, (const char *)&yes) == -1);
#endif
if (ioctl_error)
{
Error(SysError(), "UdpCommon::Setup: ioctl FIONBIO");
}

sadr = CreateAddr(host, port);
interface_addr = CreateAddr("", port, AF_INET);
target_addr = CreateAddr(host, port);

bool is_multicast = false;
is_multicast = false;

if (attr.count("multicast"))
{
// XXX: Here provide support for IPv6 multicast #1479
if (sadr.family() != AF_INET)
if (target_addr.family() != AF_INET)
{
throw std::runtime_error("UdpCommon: Multicast on IPv6 is not yet supported");
}

if (!IsMulticast(sadr.sin.sin_addr))
if (!IsMulticast(target_addr.sin.sin_addr))
{
throw std::runtime_error("UdpCommon: requested multicast for a non-multicast-type IP address");
}
is_multicast = true;
}
else if (sadr.family() == AF_INET && IsMulticast(sadr.sin.sin_addr))
else if (target_addr.family() == AF_INET && IsMulticast(target_addr.sin.sin_addr))
{
is_multicast = true;
}

if (is_multicast)
{
ip_mreq mreq;
sockaddr_any maddr (AF_INET);
int opt_name;
void* mreq_arg_ptr;
const char* mreq_arg_ptr;
socklen_t mreq_arg_size;

adapter = attr.count("adapter") ? attr.at("adapter") : string();
if ( adapter == "" )
if (adapter == "")
{
Verb() << "Multicast: home address: INADDR_ANY:" << port;
maddr.sin.sin_family = AF_INET;
maddr.sin.sin_addr.s_addr = htonl(INADDR_ANY);
maddr.sin.sin_port = htons(port); // necessary for temporary use
}
else
{
Verb() << "Multicast: home address: " << adapter << ":" << port;
maddr = CreateAddr(adapter, port);
interface_addr = CreateAddr(adapter, port);
}

if (attr.count("source"))
Expand All @@ -880,51 +880,32 @@ class UdpCommon
ip_mreq_source mreq_ssm;
/* this is an ssm. we need to use the right struct and opt */
opt_name = IP_ADD_SOURCE_MEMBERSHIP;
mreq_ssm.imr_multiaddr.s_addr = sadr.sin.sin_addr.s_addr;
mreq_ssm.imr_interface.s_addr = maddr.sin.sin_addr.s_addr;
mreq_ssm.imr_multiaddr.s_addr = target_addr.sin.sin_addr.s_addr;
mreq_ssm.imr_interface.s_addr = interface_addr.sin.sin_addr.s_addr;
inet_pton(AF_INET, attr.at("source").c_str(), &mreq_ssm.imr_sourceaddr);
mreq_arg_size = sizeof(mreq_ssm);
mreq_arg_ptr = &mreq_ssm;
mreq_arg_ptr = (const char*)&mreq_ssm;
#else
throw std::runtime_error("UdpCommon: source-filter multicast not supported by OS");
#endif
}
else
{
opt_name = IP_ADD_MEMBERSHIP;
mreq.imr_multiaddr.s_addr = sadr.sin.sin_addr.s_addr;
mreq.imr_interface.s_addr = maddr.sin.sin_addr.s_addr;
mreq.imr_multiaddr.s_addr = target_addr.sin.sin_addr.s_addr;
mreq.imr_interface.s_addr = interface_addr.sin.sin_addr.s_addr;
mreq_arg_size = sizeof(mreq);
mreq_arg_ptr = &mreq;
mreq_arg_ptr = (const char*)&mreq;
}

#ifdef _WIN32
const char* mreq_arg = (const char*)mreq_arg_ptr;
const auto status_error = SOCKET_ERROR;
#else
const void* mreq_arg = mreq_arg_ptr;
const auto status_error = -1;
#endif
auto res = setsockopt(m_sock, IPPROTO_IP, opt_name, mreq_arg_ptr, mreq_arg_size);

#if defined(_WIN32) || defined(__CYGWIN__)
// On Windows it somehow doesn't work when bind()
// is called with multicast address. Write the address
// that designates the network device here.
// Also, sets port sharing when working with multicast
sadr = maddr;
int reuse = 1;
int shareAddrRes = setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char*>(&reuse), sizeof(reuse));
if (shareAddrRes == status_error)
{
throw runtime_error("marking socket for shared use failed");
}
Verb() << "Multicast(Windows): will bind to home address";
#else
Verb() << "Multicast(POSIX): will bind to IGMP address: " << host;
#endif
int res = setsockopt(m_sock, IPPROTO_IP, opt_name, mreq_arg, mreq_arg_size);

if ( res == status_error )
if (res == status_error)
{
Error(errno, "adding to multicast membership failed");
}
Expand Down Expand Up @@ -998,8 +979,35 @@ class UdpSource: public Source, public UdpCommon
UdpSource(string host, int port, const map<string,string>& attr)
{
Setup(host, port, attr);
int stat = ::bind(m_sock, sadr.get(), sadr.size());
if ( stat == -1 )

// On Windows it somehow doesn't work when bind()
// is called with multicast address. Write the address
// that designates the network device here, always.

// Hance we have two fields holding the address:
// * target_addr: address from which reading will be done
// * unicast: local address of the interface
// * multicast: the IGMP address
// * interface_addr: address of the local interface
// (same as target_addr for unicast)

// In case of multicast, binding should be done:
// On most POSIX systems, to the multicast address (target_addr in this case)
// On Windows, to a local address (hence use interface_addr, as in this
// case it differs to target_addr).

#if defined(_WIN32) || defined(__CYGWIN__)
sockaddr_any baddr = is_multicast ? interface_addr : target_addr;
static const char* const sysname = "Windows";
#else
static const char* const sysname = "POSIX";
sockaddr_any baddr = target_addr;
#endif
Verb("UDP:", is_multicast ? "Multicast" : "Unicast", "(", sysname,
"): will bind to: ", baddr.str());
int stat = ::bind(m_sock, baddr.get(), baddr.size());

if (stat == -1)
Error(SysError(), "Binding address for UDP");
eof = false;
}
Expand All @@ -1009,7 +1017,7 @@ class UdpSource: public Source, public UdpCommon
if (pkt.payload.size() < chunk)
pkt.payload.resize(chunk);

sockaddr_any sa(sadr.family());
sockaddr_any sa(target_addr.family());
socklen_t si = sa.size();
int stat = recvfrom(m_sock, pkt.payload.data(), (int) chunk, 0, sa.get(), &si);
if (stat < 1)
Expand Down Expand Up @@ -1045,15 +1053,14 @@ class UdpTarget: public Target, public UdpCommon
cerr << "\nWARN Host for UDP target is not provided. Will send to localhost:" << port << ".\n";

Setup(host, port, attr);
if (adapter != "")
if (is_multicast && interface_addr.isany() == false)
{
sockaddr_any maddr = CreateAddr(adapter, 0);
if (maddr.family() != AF_INET)
if (interface_addr.family() != AF_INET)
{
Error(0, "UDP/target: IPv6 multicast not supported in the application");
}

in_addr addr = maddr.sin.sin_addr;
in_addr addr = interface_addr.sin.sin_addr;

int res = setsockopt(m_sock, IPPROTO_IP, IP_MULTICAST_IF, reinterpret_cast<const char*>(&addr), sizeof(addr));
if (res == -1)
Expand All @@ -1066,7 +1073,7 @@ class UdpTarget: public Target, public UdpCommon

int Write(const char* data, size_t len, int64_t src_time SRT_ATR_UNUSED, ostream & ignored SRT_ATR_UNUSED = cout) override
{
int stat = sendto(m_sock, data, (int) len, 0, sadr.get(), sadr.size());
int stat = sendto(m_sock, data, (int)len, 0, target_addr.get(), target_addr.size());
if ( stat == -1 )
{
if ((false))
Expand Down
Loading